diff --git a/source/MaterialXView/Viewer.cpp b/source/MaterialXView/Viewer.cpp index 71cccf36c8..c0d90d30a7 100644 --- a/source/MaterialXView/Viewer.cpp +++ b/source/MaterialXView/Viewer.cpp @@ -566,6 +566,7 @@ void Viewer::createLoadMeshInterface(Widget* parent, const std::string& label) { ng::Button* meshButton = new ng::Button(parent, label); meshButton->set_icon(FA_FOLDER); + meshButton->set_tooltip("Load a new geometry in the OBJ or glTF format."); meshButton->set_callback([this]() { m_process_events = false; @@ -593,6 +594,7 @@ void Viewer::createLoadMaterialsInterface(Widget* parent, const std::string& lab { ng::Button* materialButton = new ng::Button(parent, label); materialButton->set_icon(FA_FOLDER); + materialButton->set_tooltip("Load a material document in the MTLX format."); materialButton->set_callback([this]() { m_process_events = false; @@ -610,6 +612,7 @@ void Viewer::createLoadEnvironmentInterface(Widget* parent, const std::string& l { ng::Button* envButton = new ng::Button(parent, label); envButton->set_icon(FA_FOLDER); + envButton->set_tooltip("Load a lat-long environment light in the HDR format."); envButton->set_callback([this]() { m_process_events = false; @@ -635,6 +638,7 @@ void Viewer::createSaveMaterialsInterface(Widget* parent, const std::string& lab { ng::Button* materialButton = new ng::Button(parent, label); materialButton->set_icon(FA_SAVE); + materialButton->set_tooltip("Save a material document in the MTLX format."); materialButton->set_callback([this]() { m_process_events = false; @@ -664,6 +668,7 @@ void Viewer::createPropertyEditorInterface(Widget* parent, const std::string& la { ng::Button* editorButton = new ng::Button(parent, label); editorButton->set_flags(ng::Button::ToggleButton); + editorButton->set_tooltip("View or edit properties of the current material."); editorButton->set_change_callback([this](bool state) { _propertyEditor.setVisible(state); @@ -671,56 +676,138 @@ void Viewer::createPropertyEditorInterface(Widget* parent, const std::string& la }); } +void Viewer::createDocumentationInterface(Widget* parent, ng::VScrollPanel* scrollPanel) +{ + ng::GridLayout* documentationLayout = new ng::GridLayout(ng::Orientation::Vertical, 3, + ng::Alignment::Minimum, 13, 5); + documentationLayout->set_row_alignment({ ng::Alignment::Minimum, ng::Alignment::Maximum }); + + ng::Widget* documentationGroup = new ng::Widget(parent); + documentationGroup->set_layout(documentationLayout); + ng::Label* documentationLabel = new ng::Label(documentationGroup, "Documentation"); + documentationLabel->set_font_size(20); + documentationLabel->set_font("sans-bold"); + + ng::Button* shortcutsButton = new ng::Button(documentationGroup, "Keyboard Shortcuts"); + shortcutsButton->set_flags(ng::Button::ToggleButton); + shortcutsButton->set_icon(FA_CARET_RIGHT); + shortcutsButton->set_fixed_width(230); + + ng::Widget* shortcutsTable = new ng::Widget(documentationGroup); + shortcutsTable->set_layout(new ng::GroupLayout(13)); + shortcutsTable->set_visible(false); + + // recompute layout when showing/hiding shortcuts. + shortcutsButton->set_change_callback([this, scrollPanel, shortcutsButton, + shortcutsTable](bool state) + { + shortcutsTable->set_visible(state); + shortcutsButton->set_icon(state ? FA_CARET_DOWN : FA_CARET_RIGHT); + scrollPanel->set_scroll(state ? 0.73f : 1.0f); + perform_layout(); + }); + + // 2 cell layout for (key, description) pair. + ng::GridLayout* gridLayout2 = new ng::GridLayout(ng::Orientation::Horizontal, 2, + ng::Alignment::Minimum, 2, 2); + gridLayout2->set_col_alignment({ ng::Alignment::Minimum, ng::Alignment::Maximum }); + + const std::vector> KEYBOARD_SHORTCUTS = + { + std::make_pair("R", "Reload the current material from file. " + "Hold SHIFT to reload all standard libraries as well."), + std::make_pair("G", "Save the current GLSL shader source to file."), + std::make_pair("O", "Save the current OSL shader source to file."), + std::make_pair("M", "Save the current MDL shader source to file."), + std::make_pair("L", "Load GLSL shader source from file. " + "Editing the source files before loading provides a way " + "to debug and experiment with shader source code."), + std::make_pair("D", "Save each node graph in the current material as a DOT file. " + "See www.graphviz.org for more details on this format."), + std::make_pair("F", "Capture the current frame and save to file."), + std::make_pair("W", "Create a wedge rendering and save to file. " + "See Advanced Settings for additional controls."), + std::make_pair("T", "Translate the current material to a different shading model. " + "See Advanced Settings for additional controls."), + std::make_pair("B", "Bake the current material to textures. " + "See Advanced Settings for additional controls."), + std::make_pair("UP","Select the previous geometry."), + std::make_pair("DOWN","Select the next geometry."), + std::make_pair("RIGHT", "Switch to the next material."), + std::make_pair("LEFT", "Switch to the previous material."), + std::make_pair("+", "Zoom in with the camera."), + std::make_pair("-", "Zoom out with the camera.") + }; + + for (const auto& shortcut : KEYBOARD_SHORTCUTS) + { + ng::Widget* twoColumns = new ng::Widget(shortcutsTable); + twoColumns->set_layout(gridLayout2); + + ng::Label* keyLabel = new ng::Label(twoColumns, shortcut.first); + keyLabel->set_font("sans-bold"); + keyLabel->set_font_size(16); + keyLabel->set_fixed_width(40); + + ng::Label* descriptionLabel = new ng::Label(twoColumns, shortcut.second); + descriptionLabel->set_font_size(16); + descriptionLabel->set_fixed_width(160); + } +} + void Viewer::createAdvancedSettings(Widget* parent) { ng::PopupButton* advancedButton = new ng::PopupButton(parent, "Advanced Settings"); advancedButton->set_icon(FA_TOOLS); advancedButton->set_chevron_icon(-1); + advancedButton->set_tooltip("Asset and rendering options."); ng::Popup* advancedPopupParent = advancedButton->popup(); advancedPopupParent->set_layout(new ng::GroupLayout()); ng::VScrollPanel* scrollPanel = new ng::VScrollPanel(advancedPopupParent); scrollPanel->set_fixed_height(500); ng::Widget* advancedPopup = new ng::Widget(scrollPanel); - advancedPopup->set_layout(new ng::GroupLayout(13)); + advancedPopup->set_layout(new ng::BoxLayout(ng::Orientation::Vertical)); - ng::Label* viewLabel = new ng::Label(advancedPopup, "Viewing Options"); + ng::Widget* settingsGroup = new ng::Widget(advancedPopup); + settingsGroup->set_layout(new ng::GroupLayout(13)); + ng::Label* viewLabel = new ng::Label(settingsGroup, "Viewing Options"); viewLabel->set_font_size(20); viewLabel->set_font("sans-bold"); - ng::CheckBox* drawEnvironmentBox = new ng::CheckBox(advancedPopup, "Draw Environment"); + ng::CheckBox* drawEnvironmentBox = new ng::CheckBox(settingsGroup, "Draw Environment"); drawEnvironmentBox->set_checked(_drawEnvironment); drawEnvironmentBox->set_callback([this](bool enable) { _drawEnvironment = enable; }); - ng::CheckBox* outlineSelectedGeometryBox = new ng::CheckBox(advancedPopup, "Outline Selected Geometry"); + ng::CheckBox* outlineSelectedGeometryBox = new ng::CheckBox(settingsGroup, "Outline Selected Geometry"); outlineSelectedGeometryBox->set_checked(_outlineSelection); outlineSelectedGeometryBox->set_callback([this](bool enable) { _outlineSelection = enable; }); - ng::Label* renderLabel = new ng::Label(advancedPopup, "Render Options"); + ng::Label* renderLabel = new ng::Label(settingsGroup, "Render Options"); renderLabel->set_font_size(20); renderLabel->set_font("sans-bold"); - ng::CheckBox* transparencyBox = new ng::CheckBox(advancedPopup, "Render Transparency"); + ng::CheckBox* transparencyBox = new ng::CheckBox(settingsGroup, "Render Transparency"); transparencyBox->set_checked(_renderTransparency); transparencyBox->set_callback([this](bool enable) { _renderTransparency = enable; }); - ng::CheckBox* doubleSidedBox = new ng::CheckBox(advancedPopup, "Render Double-Sided"); + ng::CheckBox* doubleSidedBox = new ng::CheckBox(settingsGroup, "Render Double-Sided"); doubleSidedBox->set_checked(_renderDoubleSided); doubleSidedBox->set_callback([this](bool enable) { _renderDoubleSided = enable; }); - ng::CheckBox* importanceSampleBox = new ng::CheckBox(advancedPopup, "Environment FIS"); + ng::CheckBox* importanceSampleBox = new ng::CheckBox(settingsGroup, "Environment FIS"); importanceSampleBox->set_checked(_genContext.getOptions().hwSpecularEnvironmentMethod == mx::SPECULAR_ENVIRONMENT_FIS); _lightHandler->setUsePrefilteredMap(_genContext.getOptions().hwSpecularEnvironmentMethod != mx::SPECULAR_ENVIRONMENT_FIS); importanceSampleBox->set_callback([this](bool enable) @@ -733,7 +820,7 @@ void Viewer::createAdvancedSettings(Widget* parent) reloadShaders(); }); - ng::CheckBox* refractionBox = new ng::CheckBox(advancedPopup, "Transmission Refraction"); + ng::CheckBox* refractionBox = new ng::CheckBox(settingsGroup, "Transmission Refraction"); refractionBox->set_checked(_genContext.getOptions().hwTransmissionRenderMethod == mx::TRANSMISSION_REFRACTION); refractionBox->set_callback([this](bool enable) { @@ -744,14 +831,14 @@ void Viewer::createAdvancedSettings(Widget* parent) reloadShaders(); }); - ng::CheckBox* refractionSidedBox = new ng::CheckBox(advancedPopup, "Refraction Two-Sided"); + ng::CheckBox* refractionSidedBox = new ng::CheckBox(settingsGroup, "Refraction Two-Sided"); refractionSidedBox->set_checked(_lightHandler->getRefractionTwoSided()); refractionSidedBox->set_callback([this](bool enable) { _lightHandler->setRefractionTwoSided(enable); }); - ng::CheckBox* shaderInterfaceBox = new ng::CheckBox(advancedPopup, "Reduce Shader Interface"); + ng::CheckBox* shaderInterfaceBox = new ng::CheckBox(settingsGroup, "Reduce Shader Interface"); shaderInterfaceBox->set_checked(_genContext.getOptions().shaderInterfaceType == mx::SHADER_INTERFACE_REDUCED); shaderInterfaceBox->set_callback([this](bool enable) { @@ -759,7 +846,7 @@ void Viewer::createAdvancedSettings(Widget* parent) setShaderInterfaceType(interfaceType); }); - Widget* albedoGroup = new Widget(advancedPopup); + Widget* albedoGroup = new Widget(settingsGroup); albedoGroup->set_layout(new ng::BoxLayout(ng::Orientation::Horizontal)); new ng::Label(albedoGroup, "Albedo Method:"); mx::StringVec albedoOptions = { "Analytic", "Table", "MC" }; @@ -790,7 +877,7 @@ void Viewer::createAdvancedSettings(Widget* parent) } }); - Widget* sampleGroup = new Widget(advancedPopup); + Widget* sampleGroup = new Widget(settingsGroup); sampleGroup->set_layout(new ng::BoxLayout(ng::Orientation::Horizontal)); new ng::Label(sampleGroup, "Environment Samples:"); mx::StringVec sampleOptions; @@ -808,25 +895,25 @@ void Viewer::createAdvancedSettings(Widget* parent) _lightHandler->setEnvSampleCount(MIN_ENV_SAMPLE_COUNT * (int) std::pow(4, index)); }); - ng::Label* lightingLabel = new ng::Label(advancedPopup, "Lighting Options"); + ng::Label* lightingLabel = new ng::Label(settingsGroup, "Lighting Options"); lightingLabel->set_font_size(20); lightingLabel->set_font("sans-bold"); - ng::CheckBox* directLightingBox = new ng::CheckBox(advancedPopup, "Direct Lighting"); + ng::CheckBox* directLightingBox = new ng::CheckBox(settingsGroup, "Direct Lighting"); directLightingBox->set_checked(_lightHandler->getDirectLighting()); directLightingBox->set_callback([this](bool enable) { _lightHandler->setDirectLighting(enable); }); - ng::CheckBox* indirectLightingBox = new ng::CheckBox(advancedPopup, "Indirect Lighting"); + ng::CheckBox* indirectLightingBox = new ng::CheckBox(settingsGroup, "Indirect Lighting"); indirectLightingBox->set_checked(_lightHandler->getIndirectLighting()); indirectLightingBox->set_callback([this](bool enable) { _lightHandler->setIndirectLighting(enable); }); - ng::Widget* lightRotationRow = new ng::Widget(advancedPopup); + ng::Widget* lightRotationRow = new ng::Widget(settingsGroup); lightRotationRow->set_layout(new ng::BoxLayout(ng::Orientation::Horizontal)); mx::UIProperties ui; ui.uiMin = mx::Value::createValue(0.0f); @@ -839,11 +926,11 @@ void Viewer::createAdvancedSettings(Widget* parent) }); lightRotationBox->set_editable(true); - ng::Label* shadowingLabel = new ng::Label(advancedPopup, "Shadowing Options"); + ng::Label* shadowingLabel = new ng::Label(settingsGroup, "Shadowing Options"); shadowingLabel->set_font_size(20); shadowingLabel->set_font("sans-bold"); - ng::CheckBox* shadowMapBox = new ng::CheckBox(advancedPopup, "Shadow Map"); + ng::CheckBox* shadowMapBox = new ng::CheckBox(settingsGroup, "Shadow Map"); shadowMapBox->set_checked(_genContext.getOptions().hwShadowMap); shadowMapBox->set_callback([this](bool enable) { @@ -851,7 +938,7 @@ void Viewer::createAdvancedSettings(Widget* parent) reloadShaders(); }); - ng::CheckBox* ambientOcclusionBox = new ng::CheckBox(advancedPopup, "Ambient Occlusion"); + ng::CheckBox* ambientOcclusionBox = new ng::CheckBox(settingsGroup, "Ambient Occlusion"); ambientOcclusionBox->set_checked(_genContext.getOptions().hwAmbientOcclusion); ambientOcclusionBox->set_callback([this](bool enable) { @@ -859,7 +946,7 @@ void Viewer::createAdvancedSettings(Widget* parent) reloadShaders(); }); - ng::Widget* ambientOcclusionGainRow = new ng::Widget(advancedPopup); + ng::Widget* ambientOcclusionGainRow = new ng::Widget(settingsGroup); ambientOcclusionGainRow->set_layout(new ng::BoxLayout(ng::Orientation::Horizontal)); ng::FloatBox* ambientOcclusionGainBox = createFloatWidget(ambientOcclusionGainRow, "AO Gain:", _ambientOcclusionGain, nullptr, [this](float value) @@ -868,11 +955,11 @@ void Viewer::createAdvancedSettings(Widget* parent) }); ambientOcclusionGainBox->set_editable(true); - ng::Label* sceneLabel = new ng::Label(advancedPopup, "Scene Options"); + ng::Label* sceneLabel = new ng::Label(settingsGroup, "Scene Options"); sceneLabel->set_font_size(20); sceneLabel->set_font("sans-bold"); - Widget* unitGroup = new Widget(advancedPopup); + Widget* unitGroup = new Widget(settingsGroup); unitGroup->set_layout(new ng::BoxLayout(ng::Orientation::Horizontal)); new ng::Label(unitGroup, "Distance Unit:"); ng::ComboBox* distanceUnitBox = new ng::ComboBox(unitGroup, _distanceUnitOptions); @@ -899,65 +986,65 @@ void Viewer::createAdvancedSettings(Widget* parent) m_process_events = true; }); - ng::Label* meshLoading = new ng::Label(advancedPopup, "Mesh Loading Options"); + ng::Label* meshLoading = new ng::Label(settingsGroup, "Mesh Loading Options"); meshLoading->set_font_size(20); meshLoading->set_font("sans-bold"); - ng::CheckBox* splitUdimsBox = new ng::CheckBox(advancedPopup, "Split By UDIMs"); + ng::CheckBox* splitUdimsBox = new ng::CheckBox(settingsGroup, "Split By UDIMs"); splitUdimsBox->set_checked(_splitByUdims); splitUdimsBox->set_callback([this](bool enable) { _splitByUdims = enable; }); - ng::Label* materialLoading = new ng::Label(advancedPopup, "Material Loading Options"); + ng::Label* materialLoading = new ng::Label(settingsGroup, "Material Loading Options"); materialLoading->set_font_size(20); materialLoading->set_font("sans-bold"); - ng::CheckBox* mergeMaterialsBox = new ng::CheckBox(advancedPopup, "Merge Materials"); + ng::CheckBox* mergeMaterialsBox = new ng::CheckBox(settingsGroup, "Merge Materials"); mergeMaterialsBox->set_checked(_mergeMaterials); mergeMaterialsBox->set_callback([this](bool enable) { _mergeMaterials = enable; }); - ng::CheckBox* showInputsBox = new ng::CheckBox(advancedPopup, "Show All Inputs"); + ng::CheckBox* showInputsBox = new ng::CheckBox(settingsGroup, "Show All Inputs"); showInputsBox->set_checked(_showAllInputs); showInputsBox->set_callback([this](bool enable) { _showAllInputs = enable; }); - ng::CheckBox* flattenBox = new ng::CheckBox(advancedPopup, "Flatten Subgraphs"); + ng::CheckBox* flattenBox = new ng::CheckBox(settingsGroup, "Flatten Subgraphs"); flattenBox->set_checked(_flattenSubgraphs); flattenBox->set_callback([this](bool enable) { _flattenSubgraphs = enable; }); - ng::Label* envLoading = new ng::Label(advancedPopup, "Environment Loading Options"); + ng::Label* envLoading = new ng::Label(settingsGroup, "Environment Loading Options"); envLoading->set_font_size(20); envLoading->set_font("sans-bold"); - ng::CheckBox* normalizeEnvBox = new ng::CheckBox(advancedPopup, "Normalize Environment"); + ng::CheckBox* normalizeEnvBox = new ng::CheckBox(settingsGroup, "Normalize Environment"); normalizeEnvBox->set_checked(_normalizeEnvironment); normalizeEnvBox->set_callback([this](bool enable) { _normalizeEnvironment = enable; }); - ng::CheckBox* splitDirectLightBox = new ng::CheckBox(advancedPopup, "Split Direct Light"); + ng::CheckBox* splitDirectLightBox = new ng::CheckBox(settingsGroup, "Split Direct Light"); splitDirectLightBox->set_checked(_splitDirectLight); splitDirectLightBox->set_callback([this](bool enable) { _splitDirectLight = enable; }); - ng::Label* translationLabel = new ng::Label(advancedPopup, "Translation Options (T)"); + ng::Label* translationLabel = new ng::Label(settingsGroup, "Translation Options (T)"); translationLabel->set_font_size(20); translationLabel->set_font("sans-bold"); - ng::Widget* targetShaderGroup = new ng::Widget(advancedPopup); + ng::Widget* targetShaderGroup = new ng::Widget(settingsGroup); targetShaderGroup->set_layout(new ng::BoxLayout(ng::Orientation::Horizontal)); new ng::Label(targetShaderGroup, "Target Shader"); ng::TextBox* targetShaderBox = new ng::TextBox(targetShaderGroup, _targetShader); @@ -969,43 +1056,43 @@ void Viewer::createAdvancedSettings(Widget* parent) targetShaderBox->set_font_size(16); targetShaderBox->set_editable(true); - ng::Label* textureLabel = new ng::Label(advancedPopup, "Texture Baking Options (B)"); + ng::Label* textureLabel = new ng::Label(settingsGroup, "Texture Baking Options (B)"); textureLabel->set_font_size(20); textureLabel->set_font("sans-bold"); - ng::CheckBox* bakeHdrBox = new ng::CheckBox(advancedPopup, "Bake HDR Textures"); + ng::CheckBox* bakeHdrBox = new ng::CheckBox(settingsGroup, "Bake HDR Textures"); bakeHdrBox->set_checked(_bakeHdr); bakeHdrBox->set_callback([this](bool enable) { _bakeHdr = enable; }); - ng::CheckBox* bakeAverageBox = new ng::CheckBox(advancedPopup, "Bake Averaged Textures"); + ng::CheckBox* bakeAverageBox = new ng::CheckBox(settingsGroup, "Bake Averaged Textures"); bakeAverageBox->set_checked(_bakeAverage); bakeAverageBox->set_callback([this](bool enable) { _bakeAverage = enable; }); - ng::CheckBox* bakeOptimized = new ng::CheckBox(advancedPopup, "Optimize Baked Constants"); + ng::CheckBox* bakeOptimized = new ng::CheckBox(settingsGroup, "Optimize Baked Constants"); bakeOptimized->set_checked(_bakeOptimize); bakeOptimized->set_callback([this](bool enable) { _bakeOptimize = enable; }); - ng::CheckBox* bakeDocumentPerMaterial= new ng::CheckBox(advancedPopup, "Bake Document Per Material"); + ng::CheckBox* bakeDocumentPerMaterial= new ng::CheckBox(settingsGroup, "Bake Document Per Material"); bakeDocumentPerMaterial->set_checked(_bakeDocumentPerMaterial); bakeDocumentPerMaterial->set_callback([this](bool enable) { _bakeDocumentPerMaterial = enable; }); - ng::Label* wedgeLabel = new ng::Label(advancedPopup, "Wedge Render Options (W)"); + ng::Label* wedgeLabel = new ng::Label(settingsGroup, "Wedge Render Options (W)"); wedgeLabel->set_font_size(20); wedgeLabel->set_font("sans-bold"); - ng::Widget* wedgeNameGroup = new ng::Widget(advancedPopup); + ng::Widget* wedgeNameGroup = new ng::Widget(settingsGroup); wedgeNameGroup->set_layout(new ng::BoxLayout(ng::Orientation::Horizontal)); new ng::Label(wedgeNameGroup, "Property Name"); ng::TextBox* wedgeNameBox = new ng::TextBox(wedgeNameGroup, _wedgePropertyName); @@ -1017,7 +1104,7 @@ void Viewer::createAdvancedSettings(Widget* parent) wedgeNameBox->set_font_size(16); wedgeNameBox->set_editable(true); - ng::Widget* wedgeMinGroup = new ng::Widget(advancedPopup); + ng::Widget* wedgeMinGroup = new ng::Widget(settingsGroup); wedgeMinGroup->set_layout(new ng::BoxLayout(ng::Orientation::Horizontal)); mx::UIProperties wedgeProp; wedgeProp.uiSoftMin = mx::Value::createValue(0.0f); @@ -1030,7 +1117,7 @@ void Viewer::createAdvancedSettings(Widget* parent) wedgeMinBox->set_value(0.0); wedgeMinBox->set_editable(true); - ng::Widget* wedgeMaxGroup = new ng::Widget(advancedPopup); + ng::Widget* wedgeMaxGroup = new ng::Widget(settingsGroup); wedgeMaxGroup->set_layout(new ng::BoxLayout(ng::Orientation::Horizontal)); ng::FloatBox* wedgeMaxBox = createFloatWidget(wedgeMaxGroup, "Property Max:", _wedgePropertyMax, &wedgeProp, [this](float value) @@ -1040,7 +1127,7 @@ void Viewer::createAdvancedSettings(Widget* parent) wedgeMaxBox->set_value(1.0); wedgeMaxBox->set_editable(true); - ng::Widget* wedgeCountGroup = new ng::Widget(advancedPopup); + ng::Widget* wedgeCountGroup = new ng::Widget(settingsGroup); wedgeCountGroup->set_layout(new ng::BoxLayout(ng::Orientation::Horizontal)); mx::UIProperties wedgeCountProp; wedgeCountProp.uiMin = mx::Value::createValue(1); @@ -1053,6 +1140,8 @@ void Viewer::createAdvancedSettings(Widget* parent) }); wedgeCountBox->set_value(8); wedgeCountBox->set_editable(true); + + createDocumentationInterface(advancedPopup, scrollPanel); } void Viewer::updateGeometrySelections() diff --git a/source/MaterialXView/Viewer.h b/source/MaterialXView/Viewer.h index c3f4bb48da..08712f3c78 100644 --- a/source/MaterialXView/Viewer.h +++ b/source/MaterialXView/Viewer.h @@ -16,7 +16,6 @@ #include #include - #include namespace mx = MaterialX; @@ -290,6 +289,7 @@ class Viewer : public ng::Screen void createSaveMaterialsInterface(Widget* parent, const std::string& label); void createPropertyEditorInterface(Widget* parent, const std::string& label); void createAdvancedSettings(Widget* parent); + void createDocumentationInterface(Widget* parent, ng::VScrollPanel* scrollPanel); // Return the ambient occlusion image, if any, associated with the given material. mx::ImagePtr getAmbientOcclusionImage(mx::MaterialPtr material);