Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion application/F3DOptionsTools.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ static inline const std::map<std::string_view, std::string_view> LibOptionsNames
{ "fps", "ui.fps" },
{ "filename", "ui.filename" },
{ "metadata", "ui.metadata" },
{ "scene-hierarchy", "ui.scene_hierarchy" },
{ "scene-hierarchy", "ui.scene_hierarchy.enable" },
{ "notifications", "ui.notifications.enable" },
{ "hdri-filename", "ui.hdri_filename" },
{ "blur-background", "render.background.blur.enable" },
Expand Down
6 changes: 5 additions & 1 deletion doc/libf3d/03-OPTIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -576,13 +576,17 @@ Set the opacity of the backdrop behind the UI elements. Value is between 0.0 (fu

CLI: `--backdrop-opacity`.

### `ui.scene_hierarchy` (_bool_, default: `false`)
### `ui.scene_hierarchy.enable` (_bool_, default: `false`)

Display the _scene hierarchy_ as a tree representing the internal structure of the model, with checkboxes allowing to hide or show individual parts.
By default the tree is only expanded enough to show nodes that have meaningful names, but all nodes can be fully expanded manually.

CLI: `--scene-hierarchy`.

### `ui.scene_hierarchy.max_width` (_int_, default: `600`)

Maximum initial width of the _scene hierarchy_ widget.

### `ui.notifications.enable` (_bool_, default: `false`)

Show notifications at the bottom left of the viewport.
Expand Down
10 changes: 8 additions & 2 deletions library/options.json
Original file line number Diff line number Diff line change
Expand Up @@ -296,8 +296,14 @@
"default_value": "false"
},
"scene_hierarchy": {
"type": "bool",
"default_value": "false"
"enable": {
"type": "bool",
"default_value": "false"
},
"max_width": {
"type": "int",
"default_value": "600"
}
},
"notifications": {
"enable": {
Expand Down
2 changes: 1 addition & 1 deletion library/src/interactor_impl.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -1714,7 +1714,7 @@ interactor& interactor_impl::initBindings()
this->addBinding({mod_t::NONE, "N"}, "toggle ui.filename","Scene", std::bind(docTgl, "Filename", std::cref(opts.ui.filename)), f3d::interactor::BindingType::TOGGLE);
this->addBinding({mod_t::NONE, "M"}, "toggle ui.metadata","Scene", std::bind(docTgl, "Metadata", std::cref(opts.ui.metadata)), f3d::interactor::BindingType::TOGGLE);
this->addBinding({mod_t::SHIFT, "N"}, "toggle ui.hdri_filename","Scene", std::bind(docTgl, "HDRI filename", std::cref(opts.ui.hdri_filename)), f3d::interactor::BindingType::TOGGLE);
this->addBinding({mod_t::SHIFT, "H"}, "toggle ui.scene_hierarchy","Scene", std::bind(docTgl, "Scene hierarchy", std::cref(opts.ui.scene_hierarchy)), f3d::interactor::BindingType::TOGGLE);
this->addBinding({mod_t::SHIFT, "H"}, "toggle ui.scene_hierarchy.enable","Scene", std::bind(docTgl, "Scene hierarchy", std::cref(opts.ui.scene_hierarchy.enable)), f3d::interactor::BindingType::TOGGLE);
this->addBinding({mod_t::NONE, "Z"}, "toggle ui.fps","Scene", std::bind(docTgl, "FPS Counter", std::cref(opts.ui.fps)), f3d::interactor::BindingType::TOGGLE);
#endif
#if F3D_MODULE_RAYTRACING
Expand Down
3 changes: 2 additions & 1 deletion library/src/window_impl.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -459,7 +459,8 @@ void window_impl::UpdateDynamicOptions()
renderer->SetFilenameInfo(opt.ui.filename_info);
renderer->ShowMetaData(opt.ui.metadata);
renderer->ShowHDRIFilename(opt.ui.hdri_filename);
renderer->ShowSceneHierarchy(opt.ui.scene_hierarchy);
renderer->ShowSceneHierarchy(opt.ui.scene_hierarchy.enable);
renderer->SetSceneHierarchyMaxWidth(opt.ui.scene_hierarchy.max_width);
renderer->ShowCheatSheet(opt.ui.cheatsheet);
renderer->ShowConsole(opt.ui.console);
renderer->ShowMinimalConsole(opt.ui.minimal_console);
Expand Down
93 changes: 86 additions & 7 deletions vtkext/private/module/vtkF3DImguiActor.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,61 @@ class vtkF3DRenderDataAssemblyVisitor : public vtkDataAssemblyVisitor
};
vtkStandardNewMacro(vtkF3DRenderDataAssemblyVisitor);

/**
* Visitor used to traverse a full tree (one per importer).
* It will take care of estimate the maximum width of the tree nodes in order to set the width of
* the scene hierarchy UI widget.
*/
class vtkF3DMaxWidthAssemblyVisitor : public vtkDataAssemblyVisitor
{
public:
static vtkF3DMaxWidthAssemblyVisitor* New();
vtkTypeMacro(vtkF3DMaxWidthAssemblyVisitor, vtkDataAssemblyVisitor);

float GetMaxWidth() const
{
return this->MaxWidth;
}

protected:
bool GetTraverseSubtree(int nodeid) override
{
return this->GetAssembly()->GetAttributeOrDefault(nodeid, "f3d_collapsed", 0) == 0;
}

void Visit(int nodeid) override
{
const char* defaultLabel =
this->GetAssembly()->GetNumberOfChildren(nodeid) > 0 ? "<group>" : "<object>";

float width =
ImGui::CalcTextSize(this->GetAssembly()->GetAttributeOrDefault(nodeid, "label", defaultLabel))
.x;

// arrow or bullet
width += ImGui::GetFontSize();

// spacing between arrow/bullet and checkbox
width += ImGui::GetStyle().ItemSpacing.x;

// checkbox
width += ImGui::GetFontSize() + ImGui::GetStyle().ItemInnerSpacing.x;

// indentation for parent nodes
while (nodeid != vtkDataAssembly::GetRootNode())
{
width += ImGui::GetStyle().IndentSpacing;
nodeid = this->GetAssembly()->GetParent(nodeid);
}

this->MaxWidth = std::max(this->MaxWidth, width);
}

private:
float MaxWidth = 0.f;
};
vtkStandardNewMacro(vtkF3DMaxWidthAssemblyVisitor);

}

struct vtkF3DImguiActor::Internals
Expand Down Expand Up @@ -586,8 +641,14 @@ void vtkF3DImguiActor::RenderSceneHierarchy(vtkOpenGLRenderWindow* renWin)
const ImGuiViewport* viewport = ImGui::GetMainViewport();
assert(viewport);

vtkF3DRenderer* ren = vtkF3DRenderer::SafeDownCast(renWin->GetRenderers()->GetFirstRenderer());
assert(ren != nullptr);

vtkF3DMetaImporter* importer = ren->GetMetaImporter();
assert(importer != nullptr);

constexpr float margin = F3DStyle::GetDefaultMargin();
constexpr float defaultWidth = 200.f;
float defaultWidth = this->CalculateHierarchyWidth(importer);
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like there's an autofit feature in imgui if we specify 0?

Suggested change
float defaultWidth = this->CalculateHierarchyWidth(importer);
float defaultWidth = 0.f;

float winHeight = viewport->WorkSize.y - 2.0f * margin;

float posX = margin;
Expand All @@ -608,12 +669,6 @@ void vtkF3DImguiActor::RenderSceneHierarchy(vtkOpenGLRenderWindow* renWin)

ImGui::Begin("Scene Hierarchy", nullptr, flags);

vtkF3DRenderer* ren = vtkF3DRenderer::SafeDownCast(renWin->GetRenderers()->GetFirstRenderer());
assert(ren != nullptr);

vtkF3DMetaImporter* importer = ren->GetMetaImporter();
assert(importer != nullptr);

for (int i = 0; i < importer->GetImporterInfoCount(); i++)
{
vtkF3DMetaImporter::ImporterInfo info = importer->GetImporterInfo(i);
Expand All @@ -629,6 +684,30 @@ void vtkF3DImguiActor::RenderSceneHierarchy(vtkOpenGLRenderWindow* renWin)
ImGui::End();
}

//----------------------------------------------------------------------------
float vtkF3DImguiActor::CalculateHierarchyWidth(vtkF3DMetaImporter* importer)
{
float maxWidth = 0.0f;
const float indentPerLevel = ImGui::GetStyle().IndentSpacing;
const float treeArrowWidth = ImGui::GetFontSize();
const float checkboxWidth = ImGui::GetFrameHeight() + ImGui::GetStyle().ItemInnerSpacing.x;

for (int i = 0; i < importer->GetImporterInfoCount(); i++)
{
vtkF3DMetaImporter::ImporterInfo info = importer->GetImporterInfo(i);

vtkNew<::vtkF3DMaxWidthAssemblyVisitor> visitor;
info.DataAssembly->Visit(vtkDataAssembly::GetRootNode(), visitor);

maxWidth = std::max(maxWidth, visitor->GetMaxWidth());
}

float totalWidth =
maxWidth + 2.0f * ImGui::GetStyle().WindowPadding.x + ImGui::GetStyle().ScrollbarSize;

return std::min(totalWidth, static_cast<float>(this->SceneHierarchyMaxWidth));
}

//----------------------------------------------------------------------------
void vtkF3DImguiActor::RenderDropZone()
{
Expand Down
6 changes: 6 additions & 0 deletions vtkext/private/module/vtkF3DImguiActor.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

#include <memory>

class vtkF3DMetaImporter;
class vtkOpenGLRenderWindow;
class vtkWindow;

Expand Down Expand Up @@ -120,6 +121,11 @@ class vtkF3DImguiActor : public vtkF3DUIActor
* Compute the width of a badge
*/
float CalcBadgeWidth(const std::string& text);

/**
* Calculate the default width of the scene hierarchy UI widget
*/
float CalculateHierarchyWidth(vtkF3DMetaImporter* importer);
};

#endif
6 changes: 6 additions & 0 deletions vtkext/private/module/vtkF3DRenderer.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -1885,6 +1885,12 @@ void vtkF3DRenderer::ConfigureMetaData()
this->MetaDataConfigured = true;
}

//----------------------------------------------------------------------------
void vtkF3DRenderer::SetSceneHierarchyMaxWidth(const int maxWidth)
{
this->UIActor->SetSceneHierarchyMaxWidth(maxWidth);
}

//----------------------------------------------------------------------------
void vtkF3DRenderer::ShowSceneHierarchy(bool show)
{
Expand Down
1 change: 1 addition & 0 deletions vtkext/private/module/vtkF3DRenderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ class vtkF3DRenderer : public vtkOpenGLRenderer
void SetGridColor(const std::vector<double>& color);
void SetAxesColor(const std::vector<double>& colorXAxis, const std::vector<double>& colorYAxis,
const std::vector<double>& colorZAxis);
void SetSceneHierarchyMaxWidth(const int width);
///@}

/**
Expand Down
10 changes: 10 additions & 0 deletions vtkext/private/module/vtkF3DUIActor.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,16 @@ void vtkF3DUIActor::SetBackdropOpacity(const double backdropOpacity)
}
}

//----------------------------------------------------------------------------
void vtkF3DUIActor::SetSceneHierarchyMaxWidth(const int width)
{
if (this->SceneHierarchyMaxWidth != width)
{
this->SceneHierarchyMaxWidth = width;
this->Initialized = false;
}
}

//----------------------------------------------------------------------------
int vtkF3DUIActor::RenderOverlay(vtkViewport* vp)
{
Expand Down
7 changes: 6 additions & 1 deletion vtkext/private/module/vtkF3DUIActor.h
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,11 @@ class vtkF3DUIActor : public vtkProp
{
}

/**
* Set the maximum scene hierarchy width to display
*/
void SetSceneHierarchyMaxWidth(const int width);

/**
* Add notification info to deque
*/
Expand Down Expand Up @@ -318,7 +323,7 @@ class vtkF3DUIActor : public vtkProp
std::string MetaData = "";

bool SceneHierarchyVisible = false;

int SceneHierarchyMaxWidth = 600;
bool CheatSheetVisible = false;
std::vector<CheatSheetGroup> CheatSheet;

Expand Down