mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-19 19:54:07 +00:00
ifcviewer-full: volume tool with HUD + per-object labels
Mirrors the Area tool's display: HUD shows total volume + object count, each selected object gets a label at its world-AABB centroid showing its individual volume. Gated behind ToolMode::Volume (Ctrl+Shift+V) so it stays out of the way until invoked. Volume is a passive tool — selection works as in None (multi-select, modifier toggle, box-select all keep working). Area / Length still intercept clicks through surfacePickedInTool. Adds volumesPerObject() reusing the same mesh-cached readback path as volumeOfObjects, so the per-object split costs no extra GL readbacks. computeObjectAabb is promoted to public for the centroid lookup. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -3596,8 +3596,11 @@ void ViewportWindow::handleMousePress(QMouseEvent* e) {
|
||||
// drag that happens to start on an object still box-selects, which
|
||||
// matches user intuition: the start point shouldn't disqualify the
|
||||
// gesture. Tool-mode LMB defers pick handling to surfacePickedInTool
|
||||
// on release.
|
||||
if (e->button() == Qt::LeftButton && tool_mode_ == ToolMode::None) {
|
||||
// on release for tools that consume clicks (Area / Length); Volume is
|
||||
// passive and routes input through normal selection.
|
||||
const bool tool_consumes_clicks =
|
||||
(tool_mode_ == ToolMode::Area || tool_mode_ == ToolMode::Length);
|
||||
if (e->button() == Qt::LeftButton && !tool_consumes_clicks) {
|
||||
press_pick_id_ = pickObjectAt(e->pos().x(), e->pos().y());
|
||||
box_select_start_pos_ = e->pos();
|
||||
box_select_current_pos_ = e->pos();
|
||||
@@ -3637,8 +3640,11 @@ void ViewportWindow::handleMouseRelease(QMouseEvent* e) {
|
||||
selection_.setSelection(picks, selection_.activeObjectId());
|
||||
}
|
||||
} else if (!was_drag) {
|
||||
// Click — apply press-time pick + modifiers.
|
||||
if (tool_mode_ != ToolMode::None) {
|
||||
// Click — apply press-time pick + modifiers. Area / Length
|
||||
// intercept clicks; None and Volume drive normal selection.
|
||||
const bool tool_consumes_clicks =
|
||||
(tool_mode_ == ToolMode::Area || tool_mode_ == ToolMode::Length);
|
||||
if (tool_consumes_clicks) {
|
||||
emit surfacePickedInTool(e->pos().x(), e->pos().y(),
|
||||
int(e->modifiers()));
|
||||
} else {
|
||||
@@ -4225,6 +4231,10 @@ void ViewportWindow::toggleLengthTool() {
|
||||
setToolMode(tool_mode_ == ToolMode::Length ? ToolMode::None : ToolMode::Length);
|
||||
}
|
||||
|
||||
void ViewportWindow::toggleVolumeTool() {
|
||||
setToolMode(tool_mode_ == ToolMode::Volume ? ToolMode::None : ToolMode::Volume);
|
||||
}
|
||||
|
||||
void ViewportWindow::setHighlightTriangles(const std::vector<float>& world_xyz,
|
||||
float r, float g, float b, float a) {
|
||||
if (!gl_initialized_) return;
|
||||
|
||||
@@ -255,11 +255,15 @@ public:
|
||||
// object selection); the app interprets them per-tool. Esc exits the
|
||||
// active tool. Backspace/Delete in length mode emits
|
||||
// toolBackspacePressed for "remove last point" semantics.
|
||||
enum class ToolMode { None, Area, Length };
|
||||
// Area / Length consume LMB clicks via surfacePickedInTool; Volume
|
||||
// is passive — selection behaves as in None and the host just gates
|
||||
// its volume HUD/labels on this mode.
|
||||
enum class ToolMode { None, Area, Length, Volume };
|
||||
Q_ENUM(ToolMode)
|
||||
|
||||
void toggleAreaTool();
|
||||
void toggleLengthTool();
|
||||
void toggleVolumeTool();
|
||||
void setToolMode(ToolMode mode);
|
||||
ToolMode toolMode() const { return tool_mode_; }
|
||||
|
||||
@@ -379,6 +383,10 @@ public:
|
||||
// Frame the union of all finalized models. No-op if the scene is empty.
|
||||
void viewAll();
|
||||
|
||||
// World-space AABB query. Returns false when the object has no live
|
||||
// instance or no mesh AABB yet (caller should treat as "unknown").
|
||||
bool computeObjectAabb(uint32_t object_id, QVector3D& mn, QVector3D& mx) const;
|
||||
|
||||
struct CameraState {
|
||||
QVector3D target;
|
||||
float distance;
|
||||
@@ -466,10 +474,8 @@ private:
|
||||
void updateSectionDrag(int x, int y);
|
||||
void updateCamera();
|
||||
|
||||
// Geometry queries used by focusOnSelectedObject() / viewAll(). Both
|
||||
// return false when nothing matched (caller should leave the camera
|
||||
// alone). Bounds are world-space AABBs.
|
||||
bool computeObjectAabb(uint32_t object_id, QVector3D& mn, QVector3D& mx) const;
|
||||
// Scene-wide AABB used by viewAll(). Returns false when the scene
|
||||
// has no finalized geometry (caller should leave the camera alone).
|
||||
bool computeSceneAabb(QVector3D& mn, QVector3D& mx) const;
|
||||
// Re-aim the orbit camera so the bounding sphere of [mn, mx] just fits
|
||||
// vertically and horizontally within the current FOV, with `padding`
|
||||
|
||||
Reference in New Issue
Block a user