place the selection panel beside what it describes
The panel was anchored to the right edge of the view, which is nowhere near whatever the player just clicked. It now stands beside the selection: right of it where it fits, otherwise left, otherwise the roomier side pushed inside the view -- the one case where it covers part of what it describes. Nothing told the panel where the selection was. The selection events carry ids only, and the mode that separates a fresh selection from an expanded one is consumed inside SelectionController before they are built, so the view now publishes the selection's screen bounds itself, immediately before selecting and only when the selection is starting. Freezing that rectangle is what holds the panel still: it does not chase a scrolling view, a ship flying off, or a selection being added to. Only the panel's own size still moves it, and even then it keeps its side and the edge facing the selection. The rectangles come from what the renderer was already computing for the selection outlines, now shared rather than duplicated. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JcReq7hVk4KUPhTDKWAG7K
This commit is contained in:
50
src/ui/SelectionBounds.h
Normal file
50
src/ui/SelectionBounds.h
Normal file
@@ -0,0 +1,50 @@
|
||||
#pragma once
|
||||
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
#include <QRect>
|
||||
|
||||
#include "entt/entity/entity.hpp"
|
||||
|
||||
#include "BuildingId.h"
|
||||
|
||||
class EntityAdmin;
|
||||
class Simulation;
|
||||
class WorldCoordinates;
|
||||
struct FactoryState;
|
||||
|
||||
// Where selectable objects are on the screen. The world renderer draws every selection
|
||||
// outline from these rectangles, and the selection panel is placed beside the one that
|
||||
// covers the whole selection (REQ-UI-SELECTION-PANEL).
|
||||
//
|
||||
// All of them are in the game world view's own widget coordinates, and all of them are
|
||||
// only true for the WorldCoordinates they were asked for: the transform is a value built
|
||||
// per frame or per event, so a rectangle does not survive a scroll or a resize.
|
||||
|
||||
// The footprint of a building or of a construction site (REQ-UI-SELECTION-CARD). Null
|
||||
// when the id names neither, which is what a deconstruction under the caller looks like.
|
||||
std::optional<QRectF> getBuildingWidgetRect(const FactoryState& state,
|
||||
const WorldCoordinates& coordinates,
|
||||
BuildingId id);
|
||||
|
||||
// The body of a ship or of a defence station (REQ-UI-ENTITY-CLICK-SELECT): a station's
|
||||
// footprint, or the square the ship's triangle is drawn in. The admin is taken by
|
||||
// non-const reference only because EntityAdmin::hasAll() is not const; nothing here
|
||||
// writes to it.
|
||||
std::optional<QRectF> getActorWidgetRect(EntityAdmin& admin,
|
||||
const WorldCoordinates& coordinates,
|
||||
entt::entity actor);
|
||||
|
||||
// The circle a piece of debris is drawn as (REQ-UI-DEBRIS-CLICK-SELECT).
|
||||
std::optional<QRectF> getDebrisWidgetRect(EntityAdmin& admin,
|
||||
const WorldCoordinates& coordinates,
|
||||
entt::entity debris);
|
||||
|
||||
// The rectangle covering a whole selection -- one object, or the bounding box of all of
|
||||
// them (REQ-UI-SELECTION-PANEL). Objects that no longer resolve are skipped; the result
|
||||
// is null when none of them does.
|
||||
QRect getSelectionWidgetRect(Simulation& sim, const WorldCoordinates& coordinates,
|
||||
const std::vector<BuildingId>& buildings,
|
||||
const std::vector<entt::entity>& actors,
|
||||
const std::vector<entt::entity>& debris);
|
||||
Reference in New Issue
Block a user