Skip to content

Commit

Permalink
Improvements to the MaterialX Viewer (AcademySoftwareFoundation#2101)
Browse files Browse the repository at this point in the history
- Replace raw pointers with NanoGUI references to improve application robustness.
- Allow UI names to be displayed without a corresponding UI folder.
  • Loading branch information
jstone-lucasfilm authored Nov 1, 2024
1 parent 65862ed commit 4339aaa
Show file tree
Hide file tree
Showing 5 changed files with 179 additions and 186 deletions.
2 changes: 1 addition & 1 deletion source/MaterialXRender/Util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ void createUIPropertyGroups(DocumentPtr doc, const VariableBlock& block, UIPrope

// Prepend a parent label for unlabeled node inputs.
ElementPtr parent = pair.first->getParent();
if (item.ui.uiFolder.empty() && parent && parent->isA<Node>())
if (item.ui.uiName.empty() && parent && parent->isA<Node>())
{
item.label = parent->getName() + pathSeparator + item.label;
}
Expand Down
103 changes: 51 additions & 52 deletions source/MaterialXView/Editor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ namespace
class EditorColorPicker : public ng::ColorPicker
{
public:
EditorColorPicker(ng::Widget* parent, const ng::Color& color) :
EditorColorPicker(ng::ref<ng::Widget> parent, const ng::Color& color) :
ng::ColorPicker(parent, color)
{
ng::Popup* popup = this->popup();
ng::Widget* floatGroup = new ng::Widget(popup);
ng::ref<ng::Popup> popup = this->popup();
ng::ref<ng::Widget> floatGroup = new ng::Widget(popup);
auto layout = new ng::GridLayout(ng::Orientation::Horizontal, 2,
ng::Alignment::Middle, 2, 2);
layout->set_col_alignment({ ng::Alignment::Fill, ng::Alignment::Fill });
Expand Down Expand Up @@ -60,7 +60,7 @@ class EditorColorPicker : public ng::ColorPicker

protected:
// Additional numeric entry / feedback widgets
ng::FloatBox<float>* _colorWidgets[4];
ng::ref<ng::FloatBox<float>> _colorWidgets[4];
};

} // anonymous namespace
Expand All @@ -70,18 +70,14 @@ class EditorColorPicker : public ng::ColorPicker
//

PropertyEditor::PropertyEditor() :
_window(nullptr),
_container(nullptr),
_gridLayout2(nullptr),
_gridLayout3(nullptr),
_visible(false),
_fileDialogsForImages(true)
{
}

void PropertyEditor::create(Viewer& parent)
{
ng::Window* parentWindow = parent.getWindow();
ng::ref<ng::Window> parentWindow = parent.getWindow();

// Remove the window associated with the form.
// This is done by explicitly creating and owning the window
Expand Down Expand Up @@ -110,7 +106,7 @@ void PropertyEditor::create(Viewer& parent)
_window->set_position(previousPosition);
_window->set_visible(_visible);

ng::VScrollPanel* scroll_panel = new ng::VScrollPanel(_window);
ng::ref<ng::VScrollPanel> scroll_panel = new ng::VScrollPanel(_window);
scroll_panel->set_fixed_height(300);
_container = new ng::Widget(scroll_panel);
_container->set_layout(new ng::GroupLayout(1, 1, 1, 1));
Expand All @@ -127,7 +123,7 @@ void PropertyEditor::create(Viewer& parent)
}

void PropertyEditor::addItemToForm(const mx::UIPropertyItem& item, const std::string& group,
ng::Widget* container, Viewer* viewer, bool editable)
ng::ref<ng::Widget> container, Viewer* viewer, bool editable)
{
const mx::UIProperties& ui = item.ui;
mx::ValuePtr value = item.variable->getValue();
Expand All @@ -148,9 +144,9 @@ void PropertyEditor::addItemToForm(const mx::UIPropertyItem& item, const std::st

if (!group.empty())
{
ng::Widget* twoColumns = new ng::Widget(container);
ng::ref<ng::Widget> twoColumns = new ng::Widget(container);
twoColumns->set_layout(_gridLayout2);
ng::Label* groupLabel = new ng::Label(twoColumns, group);
ng::ref<ng::Label> groupLabel = new ng::Label(twoColumns, group);
groupLabel->set_font_size(20);
groupLabel->set_font("sans-bold");
new ng::Label(twoColumns, "");
Expand Down Expand Up @@ -187,11 +183,11 @@ void PropertyEditor::addItemToForm(const mx::UIPropertyItem& item, const std::st
const size_t valueIndex = indexInEnumeration();
if (INVALID_INDEX != valueIndex)
{
ng::Widget* twoColumns = new ng::Widget(container);
ng::ref<ng::Widget> twoColumns = new ng::Widget(container);
twoColumns->set_layout(_gridLayout2);

new ng::Label(twoColumns, label);
ng::ComboBox* comboBox = new ng::ComboBox(twoColumns, { "" });
ng::ref<ng::ComboBox> comboBox = new ng::ComboBox(twoColumns, { "" });
comboBox->set_enabled(editable);
comboBox->set_items(enumeration);
comboBox->set_selected_index(static_cast<int>(valueIndex));
Expand All @@ -215,7 +211,7 @@ void PropertyEditor::addItemToForm(const mx::UIPropertyItem& item, const std::st
}
else
{
ng::Widget* twoColumns = new ng::Widget(container);
ng::ref<ng::Widget> twoColumns = new ng::Widget(container);
twoColumns->set_layout(_gridLayout2);

new ng::Label(twoColumns, label);
Expand Down Expand Up @@ -252,9 +248,9 @@ void PropertyEditor::addItemToForm(const mx::UIPropertyItem& item, const std::st
// Float widget
else if (value->isA<float>())
{
ng::Widget* threeColumns = new ng::Widget(container);
ng::ref<ng::Widget> threeColumns = new ng::Widget(container);
threeColumns->set_layout(_gridLayout3);
ng::FloatBox<float>* floatBox = createFloatWidget(threeColumns, label, value->asA<float>(), &ui, [viewer, path](float value)
ng::ref<ng::FloatBox<float>> floatBox = createFloatWidget(threeColumns, label, value->asA<float>(), &ui, [viewer, path](float value)
{
mx::MaterialPtr material = viewer->getSelectedMaterial();
if (material)
Expand All @@ -269,12 +265,12 @@ void PropertyEditor::addItemToForm(const mx::UIPropertyItem& item, const std::st
// Boolean widget
else if (value->isA<bool>())
{
ng::Widget* twoColumns = new ng::Widget(container);
ng::ref<ng::Widget> twoColumns = new ng::Widget(container);
twoColumns->set_layout(_gridLayout2);

bool v = value->asA<bool>();
new ng::Label(twoColumns, label);
ng::CheckBox* boolVar = new ng::CheckBox(twoColumns, "");
ng::ref<ng::CheckBox> boolVar = new ng::CheckBox(twoColumns, "");
boolVar->set_checked(v);
boolVar->set_font_size(15);
boolVar->set_callback([path, viewer](bool v)
Expand All @@ -290,7 +286,7 @@ void PropertyEditor::addItemToForm(const mx::UIPropertyItem& item, const std::st
// Color3 input. Can map to a combo box if an enumeration
else if (value->isA<mx::Color3>())
{
ng::Widget* twoColumns = new ng::Widget(container);
ng::ref<ng::Widget> twoColumns = new ng::Widget(container);
twoColumns->set_layout(_gridLayout2);

// Determine if there is an enumeration for this
Expand All @@ -312,7 +308,7 @@ void PropertyEditor::addItemToForm(const mx::UIPropertyItem& item, const std::st
// Create a combo box. The items are the enumerations in order.
if (index >= 0)
{
ng::ComboBox* comboBox = new ng::ComboBox(twoColumns, { "" });
ng::ref<ng::ComboBox> comboBox = new ng::ComboBox(twoColumns, { "" });
comboBox->set_enabled(editable);
comboBox->set_items(enumeration);
comboBox->set_selected_index(index);
Expand Down Expand Up @@ -353,7 +349,7 @@ void PropertyEditor::addItemToForm(const mx::UIPropertyItem& item, const std::st
// Color4 input
else if (value->isA<mx::Color4>())
{
ng::Widget* twoColumns = new ng::Widget(container);
ng::ref<ng::Widget> twoColumns = new ng::Widget(container);
twoColumns->set_layout(_gridLayout2);

new ng::Label(twoColumns, label);
Expand All @@ -376,7 +372,7 @@ void PropertyEditor::addItemToForm(const mx::UIPropertyItem& item, const std::st
// Vec 2 widget
else if (value->isA<mx::Vector2>())
{
ng::Widget* twoColumns = new ng::Widget(container);
ng::ref<ng::Widget> twoColumns = new ng::Widget(container);
twoColumns->set_layout(_gridLayout2);

mx::Vector2 v = value->asA<mx::Vector2>();
Expand Down Expand Up @@ -415,7 +411,7 @@ void PropertyEditor::addItemToForm(const mx::UIPropertyItem& item, const std::st
// Vec 3 input
else if (value->isA<mx::Vector3>())
{
ng::Widget* twoColumns = new ng::Widget(container);
ng::ref<ng::Widget> twoColumns = new ng::Widget(container);
twoColumns->set_layout(_gridLayout2);

mx::Vector3 v = value->asA<mx::Vector3>();
Expand Down Expand Up @@ -470,7 +466,7 @@ void PropertyEditor::addItemToForm(const mx::UIPropertyItem& item, const std::st
// Vec 4 input
else if (value->isA<mx::Vector4>())
{
ng::Widget* twoColumns = new ng::Widget(container);
ng::ref<ng::Widget> twoColumns = new ng::Widget(container);
twoColumns->set_layout(_gridLayout2);

mx::Vector4 v = value->asA<mx::Vector4>();
Expand Down Expand Up @@ -542,16 +538,17 @@ void PropertyEditor::addItemToForm(const mx::UIPropertyItem& item, const std::st
std::string v = value->asA<std::string>();
if (!v.empty())
{
ng::Widget* twoColumns = new ng::Widget(container);
ng::ref<ng::Widget> twoColumns = new ng::Widget(container);
twoColumns->set_layout(_gridLayout2);

if (item.variable->getType() == mx::Type::FILENAME)
{
new ng::Label(twoColumns, label);
ng::Button* buttonVar = new ng::Button(twoColumns, mx::FilePath(v).getBaseName());
ng::ref<ng::Button> buttonVar = new ng::Button(twoColumns, mx::FilePath(v).getBaseName());
buttonVar->set_enabled(editable);
buttonVar->set_font_size(15);
buttonVar->set_callback([buttonVar, path, viewer]()
auto buttonVarPtr = buttonVar.get();
buttonVar->set_callback([buttonVarPtr, path, viewer]()
{
mx::MaterialPtr material = viewer->getSelectedMaterial();
mx::ShaderPort* uniform = material ? material->findUniform(path) : nullptr;
Expand All @@ -572,7 +569,7 @@ void PropertyEditor::addItemToForm(const mx::UIPropertyItem& item, const std::st
if (!filename.empty())
{
uniform->setValue(mx::Value::createValue<std::string>(filename));
buttonVar->set_caption(mx::FilePath(filename).getBaseName());
buttonVarPtr->set_caption(mx::FilePath(filename).getBaseName());
viewer->perform_layout();
}
}
Expand All @@ -583,7 +580,7 @@ void PropertyEditor::addItemToForm(const mx::UIPropertyItem& item, const std::st
else
{
new ng::Label(twoColumns, label);
ng::TextBox* stringVar = new ng::TextBox(twoColumns, v);
ng::ref<ng::TextBox> stringVar = new ng::TextBox(twoColumns, v);
stringVar->set_fixed_size({ 100, 20 });
stringVar->set_font_size(15);
stringVar->set_callback([path, viewer](const std::string& v)
Expand Down Expand Up @@ -629,14 +626,12 @@ void PropertyEditor::updateContents(Viewer* viewer)
}
if (!shaderName.empty() && shaderName != "surface")
{
ng::Widget* twoColumns = new ng::Widget(_container);
ng::ref<ng::Widget> twoColumns = new ng::Widget(_container);
twoColumns->set_layout(_gridLayout2);
ng::Widget* threeColumns = new ng::Widget(_container);
threeColumns->set_layout(_gridLayout3);
ng::Label* modelLabel = new ng::Label(twoColumns, "Shading Model");
ng::ref<ng::Label> modelLabel = new ng::Label(twoColumns, "Shading Model");
modelLabel->set_font_size(20);
modelLabel->set_font("sans-bold");
ng::Label* nameLabel = new ng::Label(twoColumns, shaderName);
ng::ref<ng::Label> nameLabel = new ng::Label(twoColumns, shaderName);
nameLabel->set_font_size(20);
}
}
Expand Down Expand Up @@ -688,15 +683,15 @@ void PropertyEditor::updateContents(Viewer* viewer)
viewer->perform_layout();
}

ng::FloatBox<float>* createFloatWidget(ng::Widget* parent, const std::string& label, float value,
const mx::UIProperties* ui, std::function<void(float)> callback)
ng::ref<ng::FloatBox<float>> createFloatWidget(ng::ref<ng::Widget> parent, const std::string& label, float value,
const mx::UIProperties* ui, std::function<void(float)> callback)
{
new ng::Label(parent, label);

ng::Slider* slider = new ng::Slider(parent);
ng::ref<ng::Slider> slider = new ng::Slider(parent);
slider->set_value(value);

ng::FloatBox<float>* box = new ng::FloatBox<float>(parent, value);
ng::ref<ng::FloatBox<float>> box = new ng::FloatBox<float>(parent, value);
box->set_fixed_width(60);
box->set_font_size(15);
box->set_alignment(ng::TextBox::Alignment::Right);
Expand Down Expand Up @@ -734,29 +729,31 @@ ng::FloatBox<float>* createFloatWidget(ng::Widget* parent, const std::string& la
}
}

slider->set_callback([box, callback](float value)
auto sliderPtr = slider.get();
auto boxPtr = box.get();
slider->set_callback([boxPtr, callback](float value)
{
box->set_value(value);
boxPtr->set_value(value);
callback(value);
});
box->set_callback([slider, callback](float value)
box->set_callback([sliderPtr, callback](float value)
{
slider->set_value(value);
sliderPtr->set_value(value);
callback(value);
});

return box;
}

ng::IntBox<int>* createIntWidget(ng::Widget* parent, const std::string& label, int value,
const mx::UIProperties* ui, std::function<void(int)> callback)
ng::ref<ng::IntBox<int>> createIntWidget(ng::ref<ng::Widget> parent, const std::string& label, int value,
const mx::UIProperties* ui, std::function<void(int)> callback)
{
new ng::Label(parent, label);

ng::Slider* slider = new ng::Slider(parent);
ng::ref<ng::Slider> slider = new ng::Slider(parent);
slider->set_value((float) value);

ng::IntBox<int>* box = new ng::IntBox<int>(parent, value);
ng::ref<ng::IntBox<int>> box = new ng::IntBox<int>(parent, value);
box->set_fixed_width(60);
box->set_font_size(15);
box->set_alignment(ng::TextBox::Alignment::Right);
Expand Down Expand Up @@ -794,14 +791,16 @@ ng::IntBox<int>* createIntWidget(ng::Widget* parent, const std::string& label, i
}
}

slider->set_callback([box, callback](float value)
auto sliderPtr = slider.get();
auto boxPtr = box.get();
slider->set_callback([boxPtr, callback](float value)
{
box->set_value((int) value);
boxPtr->set_value((int) value);
callback((int) value);
});
box->set_callback([slider, callback](int value)
box->set_callback([sliderPtr, callback](int value)
{
slider->set_value((float) value);
sliderPtr->set_value((float) value);
callback(value);
});

Expand Down
20 changes: 10 additions & 10 deletions source/MaterialXView/Editor.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,27 +39,27 @@ class PropertyEditor
}
}

ng::Window* getWindow()
ng::ref<ng::Window> getWindow()
{
return _window;
}

protected:
void create(Viewer& parent);
void addItemToForm(const mx::UIPropertyItem& item, const std::string& group,
ng::Widget* container, Viewer* viewer, bool editable);
ng::ref<ng::Widget> container, Viewer* viewer, bool editable);

ng::Window* _window;
ng::Widget* _container;
ng::GridLayout* _gridLayout2;
ng::GridLayout* _gridLayout3;
ng::ref<ng::Window> _window;
ng::ref<ng::Widget> _container;
ng::ref<ng::GridLayout> _gridLayout2;
ng::ref<ng::GridLayout> _gridLayout3;
bool _visible;
bool _fileDialogsForImages;
};

ng::FloatBox<float>* createFloatWidget(ng::Widget* parent, const std::string& label, float value,
const mx::UIProperties* ui, std::function<void(float)> callback = nullptr);
ng::IntBox<int>* createIntWidget(ng::Widget* parent, const std::string& label, int value,
const mx::UIProperties* ui, std::function<void(int)> callback);
ng::ref<ng::FloatBox<float>> createFloatWidget(ng::ref<ng::Widget> parent, const std::string& label, float value,
const mx::UIProperties* ui, std::function<void(float)> callback = nullptr);
ng::ref<ng::IntBox<int>> createIntWidget(ng::ref<ng::Widget> parent, const std::string& label, int value,
const mx::UIProperties* ui, std::function<void(int)> callback);

#endif // MATERIALXVIEW_EDITOR_H
Loading

0 comments on commit 4339aaa

Please sign in to comment.