| 124 | /** |
| 125 | * Used by EntitySelection::PickEntitiesInRect. |
| 126 | */ |
| 127 | static bool CheckEntityVisibleAndInRect(CEntityHandle handle, CmpPtr<ICmpRangeManager> cmpRangeManager, const CCamera& camera, int sx0, int sy0, int sx1, int sy1, player_id_t owner, bool allowEditorSelectables) |
| 128 | { |
| 129 | // Check if this entity is only selectable in Atlas |
| 130 | CmpPtr<ICmpSelectable> cmpSelectable(handle); |
| 131 | if (!cmpSelectable || (!allowEditorSelectables && cmpSelectable->IsEditorOnly())) |
| 132 | return false; |
| 133 | |
| 134 | // Ignore entities hidden by LOS (or otherwise hidden, e.g. when not IsInWorld) |
| 135 | if (cmpRangeManager->GetLosVisibility(handle, owner) == ICmpRangeManager::VIS_HIDDEN) |
| 136 | return false; |
| 137 | |
| 138 | // Find the current interpolated model position. |
| 139 | // (We just use the centre position and not the whole bounding box, because maybe |
| 140 | // that's better for users trying to select objects in busy areas) |
| 141 | |
| 142 | CmpPtr<ICmpVisual> cmpVisual(handle); |
| 143 | if (!cmpVisual) |
| 144 | return false; |
| 145 | |
| 146 | CVector3D position = cmpVisual->GetPosition(); |
| 147 | |
| 148 | // Reject if it's not on-screen (e.g. it's behind the camera) |
| 149 | if (!camera.GetFrustum().IsPointVisible(position)) |
| 150 | return false; |
| 151 | |
| 152 | // Compare screen-space coordinates |
| 153 | float x, y; |
| 154 | camera.GetScreenCoordinates(position, x, y); |
| 155 | int ix = (int)x; |
| 156 | int iy = (int)y; |
| 157 | return sx0 <= ix && ix <= sx1 && sy0 <= iy && iy <= sy1; |
| 158 | } |
| 159 | |
141 | | entity_id_t ent = it->first; |
142 | | CEntityHandle handle = it->second->GetEntityHandle(); |
143 | | |
144 | | // Check if this entity is only selectable in Atlas |
145 | | if (static_cast<ICmpSelectable*>(it->second)->IsEditorOnly() && !allowEditorSelectables) |
146 | | continue; |
147 | | |
148 | | // Ignore entities hidden by LOS (or otherwise hidden, e.g. when not IsInWorld) |
149 | | if (cmpRangeManager->GetLosVisibility(handle, owner) == ICmpRangeManager::VIS_HIDDEN) |
150 | | continue; |
151 | | |
152 | | // Ignore entities not owned by 'owner' |
153 | | CmpPtr<ICmpOwnership> cmpOwnership(handle); |
154 | | if (owner != INVALID_PLAYER && (!cmpOwnership || cmpOwnership->GetOwner() != owner)) |
155 | | continue; |
156 | | |
157 | | // Find the current interpolated model position. |
158 | | // (We just use the centre position and not the whole bounding box, because maybe |
159 | | // that's better for users trying to select objects in busy areas) |
160 | | |
161 | | CmpPtr<ICmpVisual> cmpVisual(handle); |
162 | | if (!cmpVisual) |
163 | | continue; |
164 | | |
165 | | CVector3D position = cmpVisual->GetPosition(); |
166 | | |
167 | | // Reject if it's not on-screen (e.g. it's behind the camera) |
168 | | if (!camera.GetFrustum().IsPointVisible(position)) |
169 | | continue; |
170 | | |
171 | | // Compare screen-space coordinates |
172 | | float x, y; |
173 | | camera.GetScreenCoordinates(position, x, y); |
174 | | int ix = (int)x; |
175 | | int iy = (int)y; |
176 | | if (sx0 <= ix && ix <= sx1 && sy0 <= iy && iy <= sy1) |
177 | | hitEnts.push_back(ent); |
| 176 | CComponentManager& componentManager = simulation.GetSimContext().GetComponentManager(); |
| 177 | std::vector<entity_id_t> ents = cmpRangeManager->GetEntitiesByPlayer(owner); |
| 178 | for (std::vector<entity_id_t>::iterator it = ents.begin(); it != ents.end(); ++it) |
| 179 | { |
| 180 | if (CheckEntityVisibleAndInRect(componentManager.LookupEntityHandle(*it), cmpRangeManager, camera, sx0, sy0, sx1, sy1, owner, allowEditorSelectables)) |
| 181 | hitEnts.push_back(*it); |
| 182 | } |
| 183 | } |
| 184 | else // owner == INVALID_PLAYER; Used when selecting units in Atlas or other mods that allow all kinds of selectables to be selected. |
| 185 | { |
| 186 | const CSimulation2::InterfaceListUnordered& selectableEnts = simulation.GetEntitiesWithInterfaceUnordered(IID_Selectable); |
| 187 | for (CSimulation2::InterfaceListUnordered::const_iterator it = selectableEnts.begin(); it != selectableEnts.end(); ++it) |
| 188 | { |
| 189 | if (CheckEntityVisibleAndInRect(it->second->GetEntityHandle(), cmpRangeManager, camera, sx0, sy0, sx1, sy1, owner, allowEditorSelectables)) |
| 190 | hitEnts.push_back(it->first); |
| 191 | } |