Index: binaries/data/mods/public/simulation/components/Foundation.js =================================================================== --- binaries/data/mods/public/simulation/components/Foundation.js +++ binaries/data/mods/public/simulation/components/Foundation.js @@ -196,7 +196,8 @@ var cmpObstruction = Engine.QueryInterface(this.entity, IID_Obstruction); if (cmpObstruction && cmpObstruction.GetBlockMovementFlag()) { - var collisions = cmpObstruction.GetUnitCollisions(); + var collisions = cmpObstruction.GetCollisions(false); + if (collisions.length) { var cmpFoundationOwnership = Engine.QueryInterface(this.entity, IID_Ownership); Index: binaries/data/mods/public/simulation/components/Gate.js =================================================================== --- binaries/data/mods/public/simulation/components/Gate.js +++ binaries/data/mods/public/simulation/components/Gate.js @@ -215,7 +215,7 @@ return; // The gate can't be closed if there are entities colliding with it. - var collisions = cmpObstruction.GetUnitCollisions(); + var collisions = cmpObstruction.GetCollisions(true); if (collisions.length) { if (!this.timer) Index: source/simulation2/components/CCmpObstruction.cpp =================================================================== --- source/simulation2/components/CCmpObstruction.cpp +++ source/simulation2/components/CCmpObstruction.cpp @@ -615,7 +615,7 @@ return !cmpObstructionManager->TestStaticShape(filter, pos.X, pos.Y, cmpPosition->GetRotation().Y, m_Size0, m_Size1, NULL ); } - virtual std::vector GetUnitCollisions() const + virtual std::vector GetCollisions(bool flagConstruction) const { std::vector ret; @@ -624,20 +624,20 @@ return ret; // error // There are four 'block' flags: construction, foundation, movement, - // and pathfinding. Structures have all of these flags, while units + // and pathfinding. Structures have all of these flags, while most units // block only movement and construction. - flags_t flags = ICmpObstructionManager::FLAG_BLOCK_CONSTRUCTION; + flags_t flags = flagConstruction ? ICmpObstructionManager::FLAG_BLOCK_CONSTRUCTION : 0; // Ignore collisions within the same control group, or with other shapes that don't match the filter. // Note that, since the control group for each entity defaults to the entity's ID, this is typically // equivalent to only ignoring the entity's own shape and other shapes that don't match the filter. - SkipControlGroupsRequireFlagObstructionFilter filter(false, m_ControlGroup, m_ControlGroup2, flags); + SkipControlGroupsRequireFlagObstructionFilter filter(!flagConstruction, m_ControlGroup, m_ControlGroup2, flags); ICmpObstructionManager::ObstructionSquare square; if (!GetObstructionSquare(square)) return ret; // error - cmpObstructionManager->GetUnitsOnObstruction(square, ret, filter); + cmpObstructionManager->GetAllOnObstruction(square, ret, filter); return ret; } Index: source/simulation2/components/CCmpObstructionManager.cpp =================================================================== --- source/simulation2/components/CCmpObstructionManager.cpp +++ source/simulation2/components/CCmpObstructionManager.cpp @@ -476,6 +476,8 @@ virtual void GetUnitObstructionsInRange(const IObstructionTestFilter& filter, entity_pos_t x0, entity_pos_t z0, entity_pos_t x1, entity_pos_t z1, std::vector& squares) const; virtual void GetStaticObstructionsInRange(const IObstructionTestFilter& filter, entity_pos_t x0, entity_pos_t z0, entity_pos_t x1, entity_pos_t z1, std::vector& squares) const; virtual void GetUnitsOnObstruction(const ObstructionSquare& square, std::vector& out, const IObstructionTestFilter& filter, bool strict = false) const; + virtual void GetStaticsOnObstruction(const ObstructionSquare& square, std::vector& out, const IObstructionTestFilter& filter) const; + virtual void GetAllOnObstruction(const ObstructionSquare& square, std::vector& out, const IObstructionTestFilter& filter, bool strict = false) const; virtual void SetPassabilityCircular(bool enabled) { @@ -890,7 +892,7 @@ { case PathfinderPassability::PATHFINDING: { - auto it = pathfindingMasks.find(passability.m_Clearance); + std::map::iterator it = pathfindingMasks.find(passability.m_Clearance); if (it == pathfindingMasks.end()) pathfindingMasks[passability.m_Clearance] = passability.m_Mask; else @@ -979,7 +981,7 @@ m_UnitSubdivision.GetInRange(unitShapes, CFixedVector2D(x0, z0), CFixedVector2D(x1, z1)); for (entity_id_t& unitShape : unitShapes) { - auto it = m_UnitShapes.find(unitShape); + std::map::const_iterator it = m_UnitShapes.find(unitShape); ENSURE(it != m_UnitShapes.end()); if (!filter.TestShape(UNIT_INDEX_TO_TAG(it->first), it->second.flags, it->second.group, INVALID_ENTITY)) @@ -1007,7 +1009,7 @@ m_StaticSubdivision.GetInRange(staticShapes, CFixedVector2D(x0, z0), CFixedVector2D(x1, z1)); for (entity_id_t& staticShape : staticShapes) { - auto it = m_StaticShapes.find(staticShape); + std::map::const_iterator it = m_StaticShapes.find(staticShape); ENSURE(it != m_StaticShapes.end()); if (!filter.TestShape(STATIC_INDEX_TO_TAG(it->first), it->second.flags, it->second.group, it->second.group2)) @@ -1044,7 +1046,7 @@ for (const u32& unitShape : unitShapes) { - auto it = m_UnitShapes.find(unitShape); + std::map::const_iterator it = m_UnitShapes.find(unitShape); ENSURE(it != m_UnitShapes.end()); const UnitShape& shape = it->second; @@ -1086,6 +1088,41 @@ } } +void CCmpObstructionManager::GetStaticsOnObstruction(const ObstructionSquare& square, std::vector& out, const IObstructionTestFilter& filter) const +{ + PROFILE("GetStaticOnObstruction"); + + std::vector staticShapes; + CFixedVector2D center(square.x, square.z); + CFixedVector2D expandedBox = + Geometry::GetHalfBoundingBox(square.u, square.v, CFixedVector2D(square.hw, square.hh)) + + CFixedVector2D(m_MaxClearance, m_MaxClearance); + m_StaticSubdivision.GetInRange(staticShapes, center - expandedBox, center + expandedBox); + + std::map rasterizedRects; + + for (const u32& staticShape : staticShapes) + { + std::map::const_iterator it = m_StaticShapes.find(staticShape); + ENSURE(it != m_StaticShapes.end()); + + const StaticShape& shape = it->second; + + if (!filter.TestShape(STATIC_INDEX_TO_TAG(staticShape), shape.flags, shape.group, shape.group2)) + continue; + + if (Geometry::TestSquareSquare(center, square.u, square.v, CFixedVector2D(square.hw, square.hh), CFixedVector2D(shape.x,shape.z), shape.u, shape.v, CFixedVector2D(shape.hw,shape.hh))) + out.push_back(shape.entity); + } +} + +void CCmpObstructionManager::GetAllOnObstruction(const ObstructionSquare& square, std::vector& out, const IObstructionTestFilter& filter, bool strict) const +{ + // fetch units on the obstruction square + GetUnitsOnObstruction(square, out, filter, strict); + GetStaticsOnObstruction(square, out, filter); +} + void CCmpObstructionManager::RenderSubmit(SceneCollector& collector) { if (!m_DebugOverlayEnabled) Index: source/simulation2/components/ICmpObstruction.h =================================================================== --- source/simulation2/components/ICmpObstruction.h +++ source/simulation2/components/ICmpObstruction.h @@ -92,7 +92,7 @@ * Returns a list of units that are colliding with this entity, * @return vector of blocking units */ - virtual std::vector GetUnitCollisions() const = 0; + virtual std::vector GetCollisions(bool flagConstruction) const = 0; /** * Detects collisions between foundation-blocking entities and Index: source/simulation2/components/ICmpObstruction.cpp =================================================================== --- source/simulation2/components/ICmpObstruction.cpp +++ source/simulation2/components/ICmpObstruction.cpp @@ -50,7 +50,7 @@ DEFINE_INTERFACE_METHOD_CONST_0("CheckShorePlacement", bool, ICmpObstruction, CheckShorePlacement) DEFINE_INTERFACE_METHOD_CONST_2("CheckFoundation", std::string, ICmpObstruction, CheckFoundation_wrapper, std::string, bool) DEFINE_INTERFACE_METHOD_CONST_0("CheckDuplicateFoundation", bool, ICmpObstruction, CheckDuplicateFoundation) -DEFINE_INTERFACE_METHOD_CONST_0("GetUnitCollisions", std::vector, ICmpObstruction, GetUnitCollisions) +DEFINE_INTERFACE_METHOD_CONST_1("GetCollisions", std::vector, ICmpObstruction, GetCollisions, bool) DEFINE_INTERFACE_METHOD_1("SetActive", void, ICmpObstruction, SetActive, bool) DEFINE_INTERFACE_METHOD_3("SetDisableBlockMovementPathfinding", void, ICmpObstruction, SetDisableBlockMovementPathfinding, bool, bool, int32_t) DEFINE_INTERFACE_METHOD_CONST_0("GetBlockMovementFlag", bool, ICmpObstruction, GetBlockMovementFlag) Index: source/simulation2/components/ICmpObstructionManager.h =================================================================== --- source/simulation2/components/ICmpObstructionManager.h +++ source/simulation2/components/ICmpObstructionManager.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2017 Wildfire Games. +/* Copyright (C) 2018 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -245,9 +245,10 @@ virtual void GetObstructionsInRange(const IObstructionTestFilter& filter, entity_pos_t x0, entity_pos_t z0, entity_pos_t x1, entity_pos_t z1, std::vector& squares) const = 0; virtual void GetStaticObstructionsInRange(const IObstructionTestFilter& filter, entity_pos_t x0, entity_pos_t z0, entity_pos_t x1, entity_pos_t z1, std::vector& squares) const = 0; virtual void GetUnitObstructionsInRange(const IObstructionTestFilter& filter, entity_pos_t x0, entity_pos_t z0, entity_pos_t x1, entity_pos_t z1, std::vector& squares) const = 0; - + virtual void GetStaticsOnObstruction(const ObstructionSquare& square, std::vector& out, const IObstructionTestFilter& filter) const = 0; + virtual void GetAllOnObstruction(const ObstructionSquare& square, std::vector& out, const IObstructionTestFilter& filter, bool strict = false) const = 0; /** - * Returns the entity IDs of all unit shapes that intersect the given + * Returns the entity IDs of all shapes that intersect the given * obstruction square, filtering out using the given filter. * @param square the Obstruction squre we want to compare with. * @param out output list of obstructions