// Recursive implementation of the EPA loop. // Each recursion adds a point to the convex hull until it's known that we have the closest point on the surface. static struct ClosestPoints EPARecurse(const struct SupportContext *ctx, const int count, const struct MinkowskiPoint *hull, const int iteration) { int mini = 0; cpFloat minDist = INFINITY; // TODO: precalculate this when building the hull and save a step. // Find the closest segment hull[i] and hull[i + 1] to (0, 0) for(int j=0, i=count-1; j<count; i=j, j++) { cpFloat d = ClosestDist(hull[i].ab, hull[j].ab); if(d < minDist) { minDist = d; mini = i; } } struct MinkowskiPoint v0 = hull[mini]; struct MinkowskiPoint v1 = hull[(mini + 1)%count]; cpAssertSoft(!cpveql(v0.ab, v1.ab), "Internal Error: EPA vertexes are the same (%d and %d)", mini, (mini + 1)%count); // Check if there is a point on the minkowski difference beyond this edge. struct MinkowskiPoint p = Support(ctx, cpvperp(cpvsub(v1.ab, v0.ab))); #if DRAW_EPA cpVect verts[count]; for(int i=0; i<count; i++) verts[i] = hull[i].ab; ChipmunkDebugDrawPolygon(count, verts, 0.0, RGBAColor(1, 1, 0, 1), RGBAColor(1, 1, 0, 0.25)); ChipmunkDebugDrawSegment(v0.ab, v1.ab, RGBAColor(1, 0, 0, 1)); ChipmunkDebugDrawDot(5, p.ab, LAColor(1, 1)); #endif if(CheckArea(cpvsub(v1.ab, v0.ab), cpvadd(cpvsub(p.ab, v0.ab), cpvsub(p.ab, v1.ab))) && iteration < MAX_EPA_ITERATIONS) { // Rebuild the convex hull by inserting p. struct MinkowskiPoint *hull2 = (struct MinkowskiPoint *)alloca((count + 1)*sizeof(struct MinkowskiPoint)); int count2 = 1; hull2[0] = p; for(int i=0; i<count; i++) { int index = (mini + 1 + i)%count; cpVect h0 = hull2[count2 - 1].ab; cpVect h1 = hull[index].ab; cpVect h2 = (i + 1 < count ? hull[(index + 1)%count] : p).ab; if(CheckArea(cpvsub(h2, h0), cpvadd(cpvsub(h1, h0), cpvsub(h1, h2)))) { hull2[count2] = hull[index]; count2++; } } return EPARecurse(ctx, count2, hull2, iteration + 1); } else { // Could not find a new point to insert, so we have found the closest edge of the minkowski difference. cpAssertWarn(iteration < WARN_EPA_ITERATIONS, "High EPA iterations: %d", iteration); return ClosestPointsNew(v0, v1); } }
// Recursive implementatino of the GJK loop. static inline struct ClosestPoints GJKRecurse(const struct SupportContext *ctx, const struct MinkowskiPoint v0, const struct MinkowskiPoint v1, const int iteration) { if(iteration > MAX_GJK_ITERATIONS) { cpAssertWarn(iteration < WARN_GJK_ITERATIONS, "High GJK iterations: %d", iteration); return ClosestPointsNew(v0, v1); } cpVect delta = cpvsub(v1.ab, v0.ab); if(CheckArea(delta, cpvadd(v0.ab, v1.ab))) { // Origin is behind axis. Flip and try again. return GJKRecurse(ctx, v1, v0, iteration); } else { cpFloat t = ClosestT(v0.ab, v1.ab); cpVect n = (-1.0f < t && t < 1.0f ? cpvperp(delta) : cpvneg(LerpT(v0.ab, v1.ab, t))); struct MinkowskiPoint p = Support(ctx, n); #if DRAW_GJK ChipmunkDebugDrawSegment(v0.ab, v1.ab, RGBAColor(1, 1, 1, 1)); cpVect c = cpvlerp(v0.ab, v1.ab, 0.5); ChipmunkDebugDrawSegment(c, cpvadd(c, cpvmult(cpvnormalize(n), 5.0)), RGBAColor(1, 0, 0, 1)); ChipmunkDebugDrawDot(5.0, p.ab, LAColor(1, 1)); #endif if( CheckArea(cpvsub(v1.ab, p.ab), cpvadd(v1.ab, p.ab)) && CheckArea(cpvadd(v0.ab, p.ab), cpvsub(v0.ab, p.ab)) ) { // The triangle v0, p, v1 contains the origin. Use EPA to find the MSA. cpAssertWarn(iteration < WARN_GJK_ITERATIONS, "High GJK->EPA iterations: %d", iteration); return EPA(ctx, v0, p, v1); } else { if(cpvdot(p.ab, n) <= cpfmax(cpvdot(v0.ab, n), cpvdot(v1.ab, n))) { // The edge v0, v1 that we already have is the closest to (0, 0) since p was not closer. cpAssertWarn(iteration < WARN_GJK_ITERATIONS, "High GJK iterations: %d", iteration); return ClosestPointsNew(v0, v1); } else { // p was closer to the origin than our existing edge. // Need to figure out which existing point to drop. if(ClosestDist(v0.ab, p.ab) < ClosestDist(p.ab, v1.ab)) { return GJKRecurse(ctx, v0, p, iteration + 1); } else { return GJKRecurse(ctx, p, v1, iteration + 1); } } } } }
bool Label::onMouseButton(int button, int action) { if (CheckArea(mousePosX, mousePosY) && action == 1) { textColor = vmath::vec4(0.6f, 0.1f, 0.5f, 1.0f); return TRUE; } else { return FALSE; } }
bool CAreaManager::QueryAreas(EntityId const nEntityID, Vec3 const& rPos, SAreaManagerResult *pResults, int nMaxResults, int& rNumResults) { rNumResults = 0; if (pResults) { // Make sure the area grid is recompiled, if needed, before accessing it UpdateDirtyAreas(); uint32 numAreas = 0; TAreaPointers const& rAreasAtPos(m_areaGrid.GetAreas(rPos)); TAreaPointers::const_iterator IterAreas(rAreasAtPos.begin()); TAreaPointers::const_iterator const IterAreasEnd(rAreasAtPos.end()); for (; IterAreas != IterAreasEnd; ++IterAreas) { CArea* const pArea = *IterAreas; #if defined(DEBUG_AREAMANAGER) CheckArea(pArea); #endif // DEBUG_AREAMANAGER // check if Area is hidden IEntity const* const pAreaEntity = m_pEntitySystem->GetEntity(pArea->GetEntityID()); if (pAreaEntity && !pAreaEntity->IsHidden()) { Vec3 Closest3d(ZERO); float const fGreatestFadeDistance = pArea->GetGreatestFadeDistance(); // This is optimized internally and might not recalculate but rather retrieve the cached data. float const fDistanceSq = pArea->CalcPointNearDistSq(nEntityID, rPos, Closest3d, false); bool const bIsPointWithin = (pArea->CalcPosType(nEntityID, rPos, false) == AREA_POS_TYPE_2DINSIDE_ZINSIDE); bool const isNear = ((fDistanceSq > 0.0f) && (fDistanceSq < fGreatestFadeDistance*fGreatestFadeDistance)); if (isNear || bIsPointWithin) { // still have room to put it in? if (rNumResults == nMaxResults) return false; // found area that should go into the results pResults[rNumResults].pArea = pArea; pResults[rNumResults].fDistanceSq = fDistanceSq; pResults[rNumResults].vPosOnHull = Closest3d; pResults[rNumResults].bInside = bIsPointWithin; pResults[rNumResults].bNear = isNear; ++rNumResults; } } } return true; } return false; }
/* --------------------------------------------------------------------------- */ void cVideoOut::DrawStill_420pl(sPicBuffer *buf) { oldPictureMutex.Lock(); OsdRefreshCounter=0; Osd_changed=0; CheckArea(buf->width, buf->height); CheckAspect(buf->dtg_active_format,buf->aspect_ratio); // display picture YUV (buf); oldPictureMutex.Unlock(); ProcessEvents(); }
/* * ValidArea() * * This will validate an area choice the system operator has made. */ char ValidArea(char *area) { char drive, *work, c; MSDOSparse(area, &drive); c = fileType(area, drive); if (!CheckArea(NO_MENU, c, &drive, area)) return FALSE; work = GetDynamic(strlen(area) + 5); sprintf(work, "%c:%s", drive, area); strcpy(area, work); free(work); return TRUE; }
/* * goodArea() * * This will get a valid path from the sysop. Drive should be set already. */ static goodArea(MenuId id, char *prompt, char *dir, char *drive) { int c; char dir_x[150], *dft; while (TRUE) { if (roomBuf.rbflags.ISDIR) dft = FindDirName(thisRoom); else dft = ourHomeSpace; if (!getXInternal(id, prompt, dir_x, 149, dft, dft)) return FALSE; MSDOSparse(dir_x, drive); c = fileType(dir_x, *drive); if (CheckArea(id, c, drive, dir_x)) { strCpy(dir, dir_x); return TRUE; } } }
int main(int argc, char *argv[]) { int ntotal,external; NodeList hull, intern, boundary, given; HNN=MakeHashTable(); HEL=MakeHashTable(); HLI=MakeHashTable(); NEL=MakeListTable(); CM=MakeQueueTable(); SetOptions(argc,argv); ReadFiles(argc,argv); /* CheckBoundary(); */ ntotal = CheckInput(); hull = MakeNodeList(ntotal); intern = MakeNodeList(ntotal); printf("Making convex hull... %d\n",hull->count); ConvexHull(hull,intern); /* CheckConvex(hull,intern); PrintNodeList("hull",hull); PrintNodeList("intern",intern); */ printf("Making maxi elements...\n"); MakeMaxiTriang(hull); CheckNeibor(-1); printf("Inserting convex hull... %d\n",hull->count); InsertBoundaryNodes(hull); CheckCircumCircle(); CheckNeibor(-2); WriteAll("M_hull.grd",hull); CheckNeibor(-3); printf("Inserting internal boundary points... %d\n",intern->count); InsertBoundaryNodes(intern); CheckCircumCircle(); CheckNeibor(-4); WriteAll("M_orgbound.grd",NULL); SetResolution(hull); CopyBoundaryLine(); printf("Recovering boundary lines 1...\n"); RecoverBoundary(); CheckCircumCircle(); CheckNeibor(-43); WriteAll("M_bndrecover.grd",NULL); printf("Refining boundary points 1...\n"); boundary = RefineBoundary(); if( boundary ) { printf("Inserting new boundary points... %d\n",boundary->count); InsertBoundaryNodes(boundary); CheckCircumCircle(); CheckCircumCircleProperty(); CheckNeibor(-5); } TestVersion(); printf("Marking external elements..."); external=MarkExternalElements( hull ); printf(" %d / %d\n",external,NTotElems); WriteGrd("M_finebound.grd"); /* printf("Marking outer elements..."); external=MarkOuterElements(); printf(" %d / %d\n",external,NTotElems); WriteGrd("M_test.grd"); */ FreeNodeList(hull); FreeNodeList(intern); FreeNodeList(boundary); given = GivenNodes(); printf("Inserting internal given points... %d\n",given->count); InsertNodes(given); FreeNodeList(given); CheckCircumCircle(); CheckNeibor(-44); WriteAll("M_given.grd",NULL); printf("Recovering boundary lines 2...\n"); RecoverBoundary(); CheckCircumCircle(); CheckNeibor(-45); WriteAll("M_intrecover.grd",NULL); CheckArea(); printf("Inserting internal points...\n"); InsertInternalNodes(); CheckCircumCircle(); CheckCircumCircleProperty(); WriteGrd("M_insert.grd"); TestVersion(); CheckArea(); printf("Refining internal points... %f\n",OpAspect); RefineInternalNodes(); CheckArea(); CheckCircumCircle(); CheckCircumCircleProperty(); WriteGrd("M_refine.grd"); CheckArea(); printf("Recovering boundary lines 3...\n"); RecoverBoundary(); printf("Recovering fault lines...\n"); RecoverInternalFault(); CheckCircumCircle(); CheckNeibor(-48); WriteAll("M_intrecover2.grd",NULL); printf("Marking outer elements..."); external=MarkOuterElements(); printf(" %d / %d\n",external,NTotElems); printf("Marking outer nodes..."); external=MarkOuterNodes(); printf(" %d / %d\n",external,NTotNodes); WriteGrd("M_test.grd"); TestVersion(); CheckArea(); printf("Smoothing internal points... %f\n",OpSmoothOmega); SmoothInternalNodes(); CheckArea(); WriteGrd("final.grd"); return 0; }
void BorderResizer::Wrap() { auto& controller(widget.get().GetController()); yunseq( FetchEvent<TouchDown>(controller).Add([this](CursorEventArgs&& e){ yunseq(orig_loc = FetchGUIState().CursorLocation, locked_bounds = GetBoundsOf(widget), focused = CheckArea(e)); }, 0xE0), FetchEvent<TouchHeld>(controller).Add([this](CursorEventArgs&& e){ if(e.Strategy == RoutedEventArgs::Direct && focused != Area(BorderArea::Center, BorderArea::Center)) { auto& st(FetchGUIState()); if(st.CheckDraggingOffset()) { const auto offset(st.CursorLocation - orig_loc); auto bounds(locked_bounds); switch(focused.first) { case BorderArea::Left: bounds.Width = max<SPos>(MinSize.Width, locked_bounds.Width - offset.X); bounds.X += locked_bounds.Width - bounds.Width; break; case BorderArea::Right: bounds.Width = max<SPos>(MinSize.Width, locked_bounds.Width + offset.X); break; default: ; } switch(focused.second) { case BorderArea::Up: bounds.Height = max<SPos>(MinSize.Height, locked_bounds.Height - offset.Y); bounds.Y += locked_bounds.Height - bounds.Height; break; case BorderArea::Down: bounds.Height = max<SPos>(MinSize.Height, locked_bounds.Height + offset.Y); break; default: ; } YTraceDe(Notice, "BorderResizer: new bounds = %s.\n", to_string(bounds).c_str()); InvalidateParent(widget); if(HostMode) { const auto& off( bounds.GetPoint() - locked_bounds.GetPoint()); SetBoundsOf(widget, bounds); const auto& nloc(FetchGUIState().CursorLocation - off); if(bounds.Width != MinSize.Width) orig_loc.X = nloc.X; if(bounds.Height != MinSize.Height) orig_loc.Y = nloc.Y; locked_bounds = GetBoundsOf(widget); locked_bounds.GetPointRef() -= off; } else SetBoundsOf(widget, bounds); } e.Handled = true; // XXX: Paint context target invalidated. } }, 0xE0), FetchEvent<Click>(controller).Add([this](CursorEventArgs&& e){ CallEvent<ClickAcross>(widget, e); }, 0xE0), FetchEvent<ClickAcross>(controller).Add([this](CursorEventArgs&&){ yunseq(orig_loc = Point::Invalid, locked_bounds = Rect(), focused = {BorderArea::Center, BorderArea::Center}); }, 0xE0) ); }
void TeamFortress_Build( int objtobuild ) { float btime; // gedict_t *te; vec3_t tmp1; vec3_t tmp2; newmis = spawn( ); g_globalvars.newmis = EDICT_TO_PROG( newmis ); // get an origin makevectors( self->s.v.v_angle ); g_globalvars.v_forward[2] = 0; VectorNormalize( g_globalvars.v_forward ); VectorScale( g_globalvars.v_forward, 64, g_globalvars.v_forward ); VectorAdd( self->s.v.origin, g_globalvars.v_forward, newmis->s.v.origin ); if ( objtobuild == BUILD_DISPENSER ) { if( self->has_dispenser && !tg_data.tg_enabled) { G_sprint( self, 2, "You can only have one dispenser.\nTry dismantling your old one.\n" ); return; } SetVector( tmp1, -8, -8, 0 ); SetVector( tmp2, 8, 8, 24 ); // newmis->mdl = "progs/disp.mdl"; newmis->mdl = "progs/dispencr.mdl"; // megatf disp! newmis->s.v.netname = "dispenser"; btime = g_globalvars.time + BUILD_TIME_DISPENSER; if( tg_data.tg_enabled ) btime = g_globalvars.time; } else { if ( objtobuild == BUILD_SENTRYGUN ) { if( self->has_sentry && !tg_data.tg_enabled) { G_sprint( self, 2, "You can only have one sentry gun.\nTry dismantling your old one.\n" ); return; } SetVector( tmp1, -16, -16, 0 ); SetVector( tmp2, 16, 16, 48 ); newmis->mdl = "progs/turrbase.mdl"; newmis->s.v.netname = "sentrygun"; btime = g_globalvars.time + BUILD_TIME_SENTRYGUN; if( tg_data.tg_enabled ) btime = g_globalvars.time; }else { G_Error("Unknown objtobuild in TeamFortress_Build\n"); return; } } VectorCopy(tmp1,newmis->s.v.mins); VectorCopy(tmp2,newmis->s.v.maxs); // before we start building it, check it out // check for validity of point if ( !CheckArea( newmis, self ) ) { G_sprint( self, 2, "Not enough room to build here\n" ); dremove( newmis ); return; } if ( !( ( int ) self->s.v.flags & FL_ONGROUND ) ) { CenterPrint( self, "You can't build in the air!\n\n" ); return; } self->is_building = 1; self->tfstate = self->tfstate | TFSTATE_CANT_MOVE; // Save the current weapon and remove it self->s.v.weapon = self->current_weapon; self->current_weapon = 0; self->s.v.weaponmodel = ""; self->s.v.weaponframe = 0; TeamFortress_SetSpeed( self ); newmis->s.v.owner = EDICT_TO_PROG( self ); newmis->s.v.classname = "timer"; newmis->s.v.netname = "build_timer"; newmis->s.v.nextthink = btime; newmis->s.v.think = ( func_t ) TeamFortress_FinishedBuilding; newmis->s.v.colormap = self->s.v.colormap; newmis->s.v.weapon = objtobuild; newmis->s.v.angles[1] = anglemod( self->s.v.angles[1] + 180 ); SetVector( newmis->s.v.velocity, 0, 0, 8 ); newmis->s.v.movetype = MOVETYPE_TOSS; newmis->s.v.solid = SOLID_BBOX; setmodel( newmis, newmis->mdl ); setsize( newmis, PASSVEC3( tmp1 ), PASSVEC3( tmp2 ) ); setorigin( newmis, PASSVEC3( newmis->s.v.origin ) ); newmis->s.v.flags = ( int ) newmis->s.v.flags - ( ( int ) newmis->s.v.flags & FL_ONGROUND ); }
bool CAreaManager::QueryAudioAreas(Vec3 const& rPos, SAudioAreaInfo *pResults, size_t const nMaxResults, size_t& rNumResults) { rNumResults = 0; if (pResults != nullptr) { // Make sure the area grid is recompiled, if needed, before accessing it UpdateDirtyAreas(); uint32 numAreas = 0; TAreaPointers const& rAreasAtPos(m_areaGrid.GetAreas(rPos)); TAreaPointers::const_iterator IterAreas(rAreasAtPos.begin()); TAreaPointers::const_iterator const IterAreasEnd(rAreasAtPos.end()); for (; IterAreas != IterAreasEnd; ++IterAreas) { CArea* const pArea = *IterAreas; #if defined(DEBUG_AREAMANAGER) CheckArea(pArea); #endif // DEBUG_AREAMANAGER // check if Area is hidden IEntity const* const pAreaEntity = m_pEntitySystem->GetEntity(pArea->GetEntityID()); if (pAreaEntity && !pAreaEntity->IsHidden()) { size_t const nAttachedEntities = pArea->GetEntityAmount(); if (nAttachedEntities > 0) { for (size_t iEntity = 0; iEntity < nAttachedEntities; ++iEntity) { IEntity const* const pEntity = gEnv->pEntitySystem->GetEntity(pArea->GetEntityByIdx(iEntity)); if (pEntity != nullptr) { IEntityAudioProxy const* const pAudioProxy = (IEntityAudioProxy*)pEntity->GetProxy(ENTITY_PROXY_AUDIO); if (pAudioProxy != nullptr) { TAudioEnvironmentID const nEnvironmentID = pAudioProxy->GetEnvironmentID(); float const fEnvironmentFadeDistance = pAudioProxy->GetEnvironmentFadeDistance(); if (nEnvironmentID != INVALID_AUDIO_ENVIRONMENT_ID) { // This is optimized internally and might not recalculate but rather retrieve the cached data. bool const bIsPointWithin = (pArea->CalcPosType(INVALID_ENTITYID, rPos, false) == AREA_POS_TYPE_2DINSIDE_ZINSIDE); float fEnvironmentAmount = 0.0f; if (!bIsPointWithin && (fEnvironmentFadeDistance > 0.0f)) { Vec3 Closest3d(ZERO); float const fDistance = sqrt_tpl(pArea->CalcPointNearDistSq(INVALID_ENTITYID, rPos, Closest3d, false)); if (fDistance <= fEnvironmentFadeDistance) { fEnvironmentAmount = 1.0f - (fDistance/fEnvironmentFadeDistance); } } else { fEnvironmentAmount = 1.0f; } if (fEnvironmentAmount > 0.0f) { // still have room to put it in? if (rNumResults == nMaxResults) return false; // found area that should go into the results pResults[rNumResults].pArea = pArea; pResults[rNumResults].fEnvironmentAmount = fEnvironmentAmount; pResults[rNumResults].nEnvironmentID = nEnvironmentID; pResults[rNumResults].nEnvProvidingEntityID = pEntity->GetId(); ++rNumResults; } } } } } } } } return true; } return false; }
void CAreaManager::UpdateEntity(Vec3 const& rPos, IEntity const* const pEntity) { EntityId const nEntityID = pEntity->GetId(); SAreasCache* pAreaCache = GetAreaCache(nEntityID); // Create a new area cache if necessary. if (pAreaCache == nullptr) { pAreaCache = MakeAreaCache(nEntityID); } assert(pAreaCache != nullptr); // Audio listeners and moving entities affected by environment changes need to update more often // to ensure smooth fading. uint32 const nExtendedFlags = pEntity->GetFlagsExtended(); float const fPosDelta = ((nExtendedFlags & ENTITY_FLAG_EXTENDED_AUDIO_LISTENER) != 0) || ((nExtendedFlags & ENTITY_FLAG_EXTENDED_NEEDS_MOVEINSIDE) != 0) ? 0.01f : CVar::es_EntityUpdatePosDelta; if (pAreaCache != nullptr && !rPos.IsEquivalent(pAreaCache->vLastUpdatePos, fPosDelta)) { pAreaCache->vLastUpdatePos = rPos; // First mark all cache entries that as if they are not in the grid. TAreaCacheVector::iterator Iter(pAreaCache->aoAreas.begin()); TAreaCacheVector::const_iterator IterEnd(pAreaCache->aoAreas.end()); for (; Iter != IterEnd; ++Iter) { SAreaCacheEntry& rAreaCacheEntry = (*Iter); CArea* const pArea = rAreaCacheEntry.pArea; #if defined(DEBUG_AREAMANAGER) CheckArea(pArea); #endif // DEBUG_AREAMANAGER rAreaCacheEntry.bInGrid = false; // Now pre-calculate position data. pArea->InvalidateCachedAreaData(nEntityID); pArea->CalcPosType(nEntityID, rPos); } TAreaPointers const& rAreasAtPos(m_areaGrid.GetAreas(rPos)); TAreaPointers::const_iterator IterAreas(rAreasAtPos.begin()); TAreaPointers::const_iterator const IterAreasEnd(rAreasAtPos.end()); for (; IterAreas != IterAreasEnd; ++IterAreas) { // Mark cache entries as if they are in the grid. CArea* const pArea = *IterAreas; SAreaCacheEntry* pAreaCacheEntry = nullptr; if (pAreaCache->GetCacheEntry(pArea, &pAreaCacheEntry)) { // cppcheck-suppress nullPointer pAreaCacheEntry->bInGrid = true; } else { // if they are not yet in the cache, add them pAreaCache->aoAreas.push_back(SAreaCacheEntry(pArea, false, false)); pArea->OnAddedToAreaCache(pEntity); } #if defined(DEBUG_AREAMANAGER) CheckArea(pArea); #endif // DEBUG_AREAMANAGER } // Go through all cache entries and process the areas. Iter = pAreaCache->aoAreas.begin(); IterEnd = pAreaCache->aoAreas.end(); for (; Iter != IterEnd; ++Iter) { SAreaCacheEntry& rAreaCacheEntry = (*Iter); CArea* const pArea = rAreaCacheEntry.pArea; #if defined(DEBUG_AREAMANAGER) CheckArea(pArea); #endif // DEBUG_AREAMANAGER // check if Area is hidden IEntity const* const pAreaEntity = m_pEntitySystem->GetEntity(pArea->GetEntityID()); bool bIsHidden = (pAreaEntity && pAreaEntity->IsHidden()); // area was just hidden if (bIsHidden && pArea->IsActive()) { pArea->LeaveArea(pEntity); pArea->LeaveNearArea(pEntity); rAreaCacheEntry.bNear = false; rAreaCacheEntry.bInside = false; pArea->SetActive(false); continue; } // area was just unhidden if (!bIsHidden && !pArea->IsActive()) { // ProcessArea will take care of properly setting cache entry data. rAreaCacheEntry.bNear = false; rAreaCacheEntry.bInside = false; pArea->SetActive(true); } // We process only for active areas in which grid we are. // Areas in our cache in which grid we are not get removed down below anyhow. if (pArea->IsActive()) { ProcessArea(pArea, rAreaCacheEntry, pAreaCache, rPos, pEntity); } } // Go through all areas again and send accumulated events. (needs to be done in a separate step) Iter = pAreaCache->aoAreas.begin(); for (; Iter != IterEnd; ++Iter) { SAreaCacheEntry& rAreaCacheEntry = (*Iter); CArea* const pArea = rAreaCacheEntry.pArea; #if defined(DEBUG_AREAMANAGER) CheckArea(pArea); #endif // DEBUG_AREAMANAGER pArea->SendCachedEventsFor(nEntityID); } // Remove all entries in the cache which are no longer in the grid. if (!pAreaCache->aoAreas.empty()) { pAreaCache->aoAreas.erase(std::remove_if(pAreaCache->aoAreas.begin(), pAreaCache->aoAreas.end(), SIsNotInGrid(pEntity, m_apAreas, m_apAreas.size())), pAreaCache->aoAreas.end()); } if (pAreaCache->aoAreas.empty()) { DeleteAreaCache(nEntityID); } } }