From 944c99c190e3850a2913268215b10b4507df8509 Mon Sep 17 00:00:00 2001 From: Bernard Kwok Date: Mon, 20 Feb 2023 19:21:55 -0500 Subject: [PATCH] UI Enhancements for MaterialX Graph Editor (#1251) - Add in a file menu with hotkeys - Add in a help menu - Add in Viewer menu --- source/MaterialXGraphEditor/Graph.cpp | 319 ++++++++++++++++----- source/MaterialXGraphEditor/Graph.h | 18 +- source/MaterialXGraphEditor/RenderView.cpp | 16 +- source/MaterialXGraphEditor/RenderView.h | 3 +- 4 files changed, 272 insertions(+), 84 deletions(-) diff --git a/source/MaterialXGraphEditor/Graph.cpp b/source/MaterialXGraphEditor/Graph.cpp index 074bcb6e50..783071c7e2 100644 --- a/source/MaterialXGraphEditor/Graph.cpp +++ b/source/MaterialXGraphEditor/Graph.cpp @@ -58,15 +58,15 @@ Graph::Graph(const std::string& materialFilename, _frameCount(INT_MIN), _pinFilterType(mx::EMPTY_STRING) { - // Filter for MaterialX files for load and save - mx::StringVec mtlxFilter; - mtlxFilter.push_back(".mtlx"); - _fileDialog.SetTypeFilters(mtlxFilter); - _fileDialogSave.SetTypeFilters(mtlxFilter); - loadStandardLibraries(); setPinColor(); + // Set up filters load and save + _mtlxFilter.push_back(".mtlx"); + _geomFilter.push_back(".obj"); + _geomFilter.push_back(".glb"); + _geomFilter.push_back(".gltf"); + _graphDoc = loadDocument(materialFilename); _graphDoc->importLibrary(_stdLib); @@ -88,6 +88,11 @@ Graph::Graph(const std::string& materialFilename, _renderer = std::make_shared(_graphDoc, meshFilename, envRadianceFilename, _searchPath, 256, 256); _renderer->initialize(); + mx::StringSet supportedExtensions = _renderer ? _renderer->getImageHandler()->supportedExtensions() : mx::StringSet(); + for (const std::string& supportedExtension : supportedExtensions) + { + _imageFilter.push_back("." + supportedExtension); + } _renderer->updateMaterials(nullptr); for (const std::string& incl : _renderer->getXincludeFiles()) { @@ -820,10 +825,14 @@ void Graph::updateMaterials(mx::InputPtr input, mx::ValuePtr value) } } // set the value of the selected node constants in the node property editor -void Graph::setConstant(UiNodePtr node, mx::InputPtr& input) +void Graph::setConstant(UiNodePtr node, mx::InputPtr& input, const mx::UIProperties& uiProperties) { - std::string inName = input->getName(); + std::string inName = !uiProperties.uiName.empty()? uiProperties.uiName : input->getName(); float labelWidth = ImGui::CalcTextSize(inName.c_str()).x; + + mx::ValuePtr minVal = uiProperties.uiMin; + mx::ValuePtr maxVal = uiProperties.uiMax; + // if input is a float set the float slider Ui to the value if (input->getType() == "float") { @@ -835,7 +844,10 @@ void Graph::setConstant(UiNodePtr node, mx::InputPtr& input) float prev = val->asA(), temp = val->asA(); ImGui::SameLine(); ImGui::PushItemWidth(labelWidth + 20); - ImGui::DragFloat("##hidelabel", &temp, 0.01f, 0.f, 100.f); + float min = minVal ? minVal->asA() : 0.f; + float max = maxVal ? maxVal->asA() : 100.f; + float speed = (max - min) / 1000.0f; + ImGui::DragFloat("##hidelabel", &temp, speed, min, max); ImGui::PopItemWidth(); // set input value and update materials if different from previous value if (prev != temp) @@ -854,7 +866,10 @@ void Graph::setConstant(UiNodePtr node, mx::InputPtr& input) int prev = val->asA(), temp = val->asA(); ImGui::SameLine(); ImGui::PushItemWidth(labelWidth + 20); - ImGui::DragInt("##hidelabel", &temp, 1, 0, 100); + int min = minVal ? minVal->asA() : 0; + int max = maxVal ? maxVal->asA() : 100; + float speed = (max - min) / 100.0f; + ImGui::DragInt("##hidelabel", &temp, speed, min, max); ImGui::PopItemWidth(); // set input value and update materials if different from previous value if (prev != temp) @@ -873,7 +888,10 @@ void Graph::setConstant(UiNodePtr node, mx::InputPtr& input) mx::Color3 prev = val->asA(), temp = val->asA(); ImGui::SameLine(); ImGui::PushItemWidth(labelWidth + 100); - ImGui::DragFloat3("##hidelabel", &temp[0], 0.01f, 0.f, 100.f); + float min = minVal ? minVal->asA()[0] : 0.f; + float max = maxVal ? maxVal->asA()[0] : 100.f; + float speed = (max - min) / 1000.0f; + ImGui::DragFloat3("##hidelabel", &temp[0], speed, min, max); ImGui::SameLine(); ImGui::ColorEdit3("##color", &temp[0], ImGuiColorEditFlags_NoInputs); ImGui::PopItemWidth(); @@ -895,7 +913,10 @@ void Graph::setConstant(UiNodePtr node, mx::InputPtr& input) mx::Color4 prev = val->asA(), temp = val->asA(); ImGui::SameLine(); ImGui::PushItemWidth(labelWidth + 100); - ImGui::DragFloat4("##hidelabel", &temp[0], 0.01f, 0.f, 100.f); + float min = minVal ? minVal->asA()[0] : 0.f; + float max = maxVal ? maxVal->asA()[0] : 100.f; + float speed = (max - min) / 1000.0f; + ImGui::DragFloat4("##hidelabel", &temp[0], speed, min, max); ImGui::SameLine(); // color edit for the color picker to the right of the color floats ImGui::ColorEdit4("##color", &temp[0], ImGuiColorEditFlags_NoInputs); @@ -917,7 +938,10 @@ void Graph::setConstant(UiNodePtr node, mx::InputPtr& input) mx::Vector2 prev = val->asA(), temp = val->asA(); ImGui::SameLine(); ImGui::PushItemWidth(labelWidth + 100); - ImGui::DragFloat2("##hidelabel", &temp[0], 0.01f, 0.f, 100.f); + float min = minVal ? minVal->asA()[0] : 0.f; + float max = maxVal ? maxVal->asA()[0] : 100.f; + float speed = (max - min) / 1000.0f; + ImGui::DragFloat2("##hidelabel", &temp[0], speed, min, max); ImGui::PopItemWidth(); // set input value and update materials if different from previous value if (prev != temp) @@ -936,7 +960,10 @@ void Graph::setConstant(UiNodePtr node, mx::InputPtr& input) mx::Vector3 prev = val->asA(), temp = val->asA(); ImGui::SameLine(); ImGui::PushItemWidth(labelWidth + 100); - ImGui::DragFloat3("##hidelabel", &temp[0], 0.01f, 0.f, 100.f); + float min = minVal ? minVal->asA()[0] : 0.f; + float max = maxVal ? maxVal->asA()[0] : 100.f; + float speed = (max - min) / 1000.0f; + ImGui::DragFloat3("##hidelabel", &temp[0], speed, min, max); ImGui::PopItemWidth(); // set input value and update materials if different from previous value if (prev != temp) @@ -955,7 +982,10 @@ void Graph::setConstant(UiNodePtr node, mx::InputPtr& input) mx::Vector4 prev = val->asA(), temp = val->asA(); ImGui::SameLine(); ImGui::PushItemWidth(labelWidth + 90); - ImGui::DragFloat4("##hidelabel", &temp[0], 0.01f, 0.f, 100.f); + float min = minVal ? minVal->asA()[0] : 0.f; + float max = maxVal ? maxVal->asA()[0] : 100.f; + float speed = (max - min) / 1000.0f; + ImGui::DragFloat4("##hidelabel", &temp[0], speed, min, max); ImGui::PopItemWidth(); // set input value and update materials if different from previous value if (prev != temp) @@ -998,15 +1028,9 @@ void Graph::setConstant(UiNodePtr node, mx::InputPtr& input) // browser button to select new file if (ImGui::Button("Browse")) { - _fileDialogConstant.SetTitle("Node Input Dialog"); - _fileDialogConstant.Open(); - mx::StringSet supportedExtensions = _renderer ? _renderer->getImageHandler()->supportedExtensions() : mx::StringSet(); - std::vector filters; - for (const std::string& supportedExtension : supportedExtensions) - { - filters.push_back("." + supportedExtension); - } - _fileDialogConstant.SetTypeFilters(filters); + _fileDialogImage.SetTitle("Node Input Dialog"); + _fileDialogImage.Open(); + _fileDialogImage.SetTypeFilters(_imageFilter); } ImGui::SameLine(); ImGui::PushItemWidth(labelWidth); @@ -1016,15 +1040,15 @@ void Graph::setConstant(UiNodePtr node, mx::InputPtr& input) ImGui::PopStyleColor(); // create and load document from selected file - if (_fileDialogConstant.HasSelected()) + if (_fileDialogImage.HasSelected()) { // set the new filename to the complete file path - mx::FilePath fileName = mx::FilePath(_fileDialogConstant.GetSelected().string()); + mx::FilePath fileName = mx::FilePath(_fileDialogImage.GetSelected().string()); temp = fileName; // need to set the file prefix for the input to "" so that it can find the new file input->setAttribute(input->FILE_PREFIX_ATTRIBUTE, ""); - _fileDialogConstant.ClearSelected(); - _fileDialogConstant.SetTypeFilters(std::vector()); + _fileDialogImage.ClearSelected(); + _fileDialogImage.SetTypeFilters(std::vector()); } // set input value and update materials if different from previous value @@ -2832,59 +2856,132 @@ void Graph::upNodeGraph() } } +void Graph::clearGraph() +{ + _graphNodes.clear(); + _currLinks.clear(); + _currEdge.clear(); + _newLinks.clear(); + _currPins.clear(); + _graphDoc = mx::createDocument(); + _graphDoc->importLibrary(_stdLib); + _currGraphElem = _graphDoc; + + if (_currUiNode != nullptr) + { + ed::DeselectNode(_currUiNode->getId()); + _currUiNode = nullptr; + } + _prevUiNode = nullptr; + _currRenderNode = nullptr; + _isNodeGraph = false; + _currGraphName.clear(); + + _renderer->setDocument(_graphDoc); + _renderer->updateMaterials(nullptr); +} + +void Graph::loadGraphFromFile() +{ + // deselect node before loading new file + if (_currUiNode != nullptr) + { + ed::DeselectNode(_currUiNode->getId()); + _currUiNode = nullptr; + } + + _fileDialog.SetTitle("Open File"); + _fileDialog.SetTypeFilters(_mtlxFilter); + _fileDialog.Open(); +} + +void Graph::saveGraphToFile() +{ + _fileDialogSave.SetTypeFilters(_mtlxFilter); + _fileDialogSave.SetTitle("Save File As"); + _fileDialogSave.Open(); +} + +void Graph::loadGeometry() +{ + _fileDialogGeom.SetTitle("Load Geometry"); + _fileDialogGeom.SetTypeFilters(_geomFilter); + _fileDialogGeom.Open(); +} + void Graph::graphButtons() { ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(.15f, .15f, .15f, 1.0f)); + ImGui::SetWindowFontScale(_fontScale); - // buttons for loading and saving a .mtlx - // new Material button - if (ImGui::Button("New Material")) + if (ImGui::BeginMenuBar()) { - _graphNodes.clear(); - _currLinks.clear(); - _currEdge.clear(); - _newLinks.clear(); - _currPins.clear(); - _graphDoc = mx::createDocument(); - _graphDoc->importLibrary(_stdLib); - _currGraphElem = _graphDoc; - - if (_currUiNode != nullptr) + if (ImGui::BeginMenu("File")) { - ed::DeselectNode(_currUiNode->getId()); - _currUiNode = nullptr; + // buttons for loading and saving a .mtlx + // new Material button + if (ImGui::MenuItem("New", "Ctrl-N")) + { + clearGraph(); + } + else if (ImGui::MenuItem("Open", "Ctrl-O")) + { + loadGraphFromFile(); + } + else if (ImGui::MenuItem("Save", "Ctrl-S")) + { + saveGraphToFile(); + } + ImGui::EndMenu(); } - _prevUiNode = nullptr; - _currRenderNode = nullptr; - _isNodeGraph = false; - _currGraphName.clear(); + + if (ImGui::BeginMenu("Graph")) + { + if (ImGui::MenuItem("Auto Layout")) + { + _autoLayout = true; + } + ImGui::EndMenu(); + } + + if (ImGui::BeginMenu("Viewer")) + { + if (ImGui::MenuItem("Load Geometry")) + { + loadGeometry(); + } + ImGui::EndMenu(); + } - _renderer->setDocument(_graphDoc); - _renderer->updateMaterials(nullptr); - } - ImGui::SameLine(); - if (ImGui::Button("Load Material")) - { - // deselect node before loading new file - if (_currUiNode != nullptr) + if (ImGui::Button("Help")) { - ed::DeselectNode(_currUiNode->getId()); - _currUiNode = nullptr; + ImGui::OpenPopup("Help"); + } + if (ImGui::BeginPopup("Help")) + { + showHelp(); + ImGui::EndPopup(); } - _fileDialog.SetTitle("Open File Window"); - _fileDialog.Open(); - } - ImGui::SameLine(); - if (ImGui::Button("Save Material")) - { - _fileDialogSave.SetTitle("Save File Window"); - _fileDialogSave.Open(); + ImGui::EndMenuBar(); } - ImGui::SameLine(); - if (ImGui::Button("Auto Layout")) + + // Menu keys + ImGuiIO& guiIO = ImGui::GetIO(); + if (guiIO.KeyCtrl && !_fileDialogSave.IsOpened() && !_fileDialog.IsOpened() && !_fileDialogGeom.IsOpened()) { - _autoLayout = true; + if (ImGui::IsKeyReleased(ImGuiKey_O)) + { + loadGraphFromFile(); + } + else if (ImGui::IsKeyReleased(ImGuiKey_N)) + { + clearGraph(); + } + else if (ImGui::IsKeyReleased(ImGuiKey_S)) + { + saveGraphToFile(); + } } // split window into panes for NodeEditor @@ -3066,10 +3163,13 @@ void Graph::propertyEditor() { if (_currUiNode->_showAllInputs || (input->getConnected() || _currUiNode->getNode()->getInput(input->_name))) { + mx::UIProperties uiProperties; + mx::getUIProperties(input->_input, mx::EMPTY_STRING, uiProperties); + std::string inputLabel = !uiProperties.uiName.empty() ? uiProperties.uiName : input->_input->getName(); mx::OutputPtr out = input->_input->getConnectedOutput(); // setting comment help box ImGui::PushID(int(input->_pinId.Get())); - ImGui::Text("%s", input->_input->getName().c_str()); + ImGui::Text("%s", inputLabel.c_str()); mx::InputPtr tempInt = _currUiNode->getNode()->getNodeDef()->getActiveInput(input->_input->getName()); docString += input->_name; docString += ": "; @@ -3089,7 +3189,7 @@ void Graph::propertyEditor() // setting constant sliders for input values if (!input->getConnected()) { - setConstant(_currUiNode, input->_input); + setConstant(_currUiNode, input->_input, uiProperties); } ImGui::PopID(); @@ -3108,9 +3208,14 @@ void Graph::propertyEditor() ImGui::Indent(); for (size_t i = 0; i < inputs.size(); i++) { + mx::InputPtr mxinput = inputs[i]->_input; + mx::UIProperties uiProperties; + mx::getUIProperties(mxinput, mx::EMPTY_STRING, uiProperties); + std::string inputLabel = !uiProperties.uiName.empty() ? uiProperties.uiName : mxinput->getName(); + // setting comment help box ImGui::PushID(int(inputs[i]->_pinId.Get())); - ImGui::Text("%s", inputs[i]->_input->getName().c_str()); + ImGui::Text("%s", inputLabel.c_str()); ImGui::SameLine(); std::string typeText = " [" + inputs[i]->_input->getType() + "]"; @@ -3118,7 +3223,7 @@ void Graph::propertyEditor() // setting constant sliders for input values if (!inputs[i]->getConnected()) { - setConstant(_currUiNode, inputs[i]->_input); + setConstant(_currUiNode, inputs[i]->_input, uiProperties); } ImGui::PopID(); } @@ -3139,9 +3244,14 @@ void Graph::propertyEditor() { if (_currUiNode->_showAllInputs || (input->getConnected() || _currUiNode->getNodeGraph()->getInput(input->_name))) { + mx::InputPtr mxinput = input->_input; + mx::UIProperties uiProperties; + mx::getUIProperties(mxinput, mx::EMPTY_STRING, uiProperties); + std::string inputLabel = !uiProperties.uiName.empty() ? uiProperties.uiName : mxinput->getName(); + // setting comment help box ImGui::PushID(int(input->_pinId.Get())); - ImGui::Text("%s", input->_input->getName().c_str()); + ImGui::Text("%s", inputLabel.c_str()); docString += _currUiNode->getNodeGraph()->getActiveInput(input->_input->getName())->getDocString(); @@ -3150,7 +3260,7 @@ void Graph::propertyEditor() ImGui::Text("%s", typeText.c_str()); if (!input->_input->getConnectedNode() && _currUiNode->getNodeGraph()->getActiveInput(input->_input->getName())) { - setConstant(_currUiNode, input->_input); + setConstant(_currUiNode, input->_input, uiProperties); } ImGui::PopID(); @@ -3175,6 +3285,51 @@ void Graph::propertyEditor() } } } + +// Helper to display basic user controls. +void Graph::showHelp() const +{ + ImGui::Text("MATERIALX GRAPH EDITOR HELP"); + if (ImGui::CollapsingHeader("Graph")) + { + if (ImGui::TreeNode("Navigation")) + { + ImGui::BulletText("F : Frame selected nodes in graph."); + ImGui::BulletText("RIGHT MOUSE button to pan."); + ImGui::BulletText("SCROLL WHEEL to zoom."); + ImGui::BulletText("\"<\" BUTTON to view parent of current graph"); + ImGui::TreePop(); + } + if (ImGui::TreeNode("Editing")) + { + ImGui::BulletText("TAB : Show popup menu to add new nodes."); + ImGui::BulletText("CTRL-C : Copy selected nodes to clipboard."); + ImGui::BulletText("CTRL-V : Paste clipboard to graph."); + ImGui::BulletText("CTRL-F : Find a node by name."); + ImGui::BulletText("CTRL-X : Delete selected nodes and add to clipboard."); + ImGui::BulletText("DELETE : Delete selected nodes or connections."); + ImGui::TreePop(); + } + } + if (ImGui::CollapsingHeader("Viewer")) + { + ImGui::BulletText("LEFT MOUSE button to tumble."); + ImGui::BulletText("RIGHT MOUSE button to pan."); + ImGui::BulletText("SCROLL WHEEL to zoom."); + ImGui::BulletText("Keypad +/- to zoom in fixed increments"); + } + + if (ImGui::CollapsingHeader("Property Editor")) + { + ImGui::BulletText("UP/DOWN ARROW to move between inputs."); + ImGui::BulletText("LEFT-MOUSE DRAG to modify values while entry field is in focus."); + ImGui::BulletText("DBL_CLICK or CTRL+CLICK LEFT-MOUSE on entry field to input values."); + ImGui::Separator(); + ImGui::BulletText("\"Show all inputs\" Will toggle between showing all inputs and\n only those that have been modified."); + ImGui::BulletText("\"Node Info\" Will toggle showing node information."); + } +} + void Graph::addNodePopup(bool cursor) { bool open_AddPopup = ImGui::IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows) && ImGui::IsKeyReleased(ImGuiKey_Tab); @@ -3402,7 +3557,7 @@ void Graph::handleRenderViewInputs(ImVec2 minValue, float width, float height) _renderer->setKeyEvent(ImGuiKey_KeypadSubtract); } // scrolling not possible if open or save file dialog is open - if (scrollAmt != 0 && !_fileDialogSave.IsOpened() && !_fileDialog.IsOpened()) + if (scrollAmt != 0 && !_fileDialogSave.IsOpened() && !_fileDialog.IsOpened() && !_fileDialogGeom.IsOpened()) { _renderer->setScrollEvent(scrollAmt); } @@ -3423,7 +3578,7 @@ void Graph::drawGraph(ImVec2 mousePos) ImGuiIO& io2 = ImGui::GetIO(); ImGui::SetNextWindowSize(io2.DisplaySize); ImGui::SetNextWindowPos(ImVec2(io2.DisplaySize.x * 0.5f, io2.DisplaySize.y * 0.5f), ImGuiCond_Always, ImVec2(0.5f, 0.5f)); - ImGui::Begin("MaterialX", nullptr, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoSavedSettings); + ImGui::Begin("MaterialX", nullptr, ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoSavedSettings); io2.ConfigFlags = ImGuiConfigFlags_IsSRGB | ImGuiConfigFlags_NavEnableKeyboard; io2.MouseDoubleClickTime = .5; @@ -3806,6 +3961,7 @@ void Graph::drawGraph(ImVec2 mousePos) ed::End(); ImGui::End(); + _fileDialog.Display(); // create and load document from selected file if (_fileDialog.HasSelected()) @@ -3827,7 +3983,16 @@ void Graph::drawGraph(ImVec2 mousePos) _renderer->updateMaterials(nullptr); } - _fileDialogConstant.Display(); + _fileDialogGeom.Display(); + if (_fileDialogGeom.HasSelected()) + { + mx::FilePath fileName = mx::FilePath(_fileDialogGeom.GetSelected().string()); + _fileDialogGeom.ClearSelected(); + _renderer->loadMesh(fileName); + _renderer->updateMaterials(nullptr); + } + + _fileDialogImage.Display(); } // return node location in graphNodes vector based off of node id diff --git a/source/MaterialXGraphEditor/Graph.h b/source/MaterialXGraphEditor/Graph.h index e838e677d8..9044eb27a6 100644 --- a/source/MaterialXGraphEditor/Graph.h +++ b/source/MaterialXGraphEditor/Graph.h @@ -117,7 +117,7 @@ class Graph void upNodeGraph(); // property editor information - void setConstant(UiNodePtr node, mx::InputPtr& input); + void setConstant(UiNodePtr node, mx::InputPtr& input, const mx::UIProperties& uiProperties); void propertyEditor(); void setDefaults(mx::InputPtr input); @@ -146,6 +146,19 @@ class Graph void handleRenderViewInputs(ImVec2 minValue, float width, float height); void setRenderMaterial(UiNodePtr node); + // File I/O + void clearGraph(); + void loadGraphFromFile(); + void saveGraphToFile(); + void loadGeometry(); + + mx::StringVec _geomFilter; + mx::StringVec _mtlxFilter; + mx::StringVec _imageFilter; + + // Help + void showHelp() const; + RenderViewPtr _renderer; // document and intializing information @@ -199,7 +212,8 @@ class Graph // file dialog information ImGui::FileBrowser _fileDialog; ImGui::FileBrowser _fileDialogSave; - ImGui::FileBrowser _fileDialogConstant; + ImGui::FileBrowser _fileDialogImage; + ImGui::FileBrowser _fileDialogGeom; bool _isNodeGraph; diff --git a/source/MaterialXGraphEditor/RenderView.cpp b/source/MaterialXGraphEditor/RenderView.cpp index 32a2d1d6bf..5e57cf83e3 100644 --- a/source/MaterialXGraphEditor/RenderView.cpp +++ b/source/MaterialXGraphEditor/RenderView.cpp @@ -317,6 +317,18 @@ void RenderView::loadMesh(const mx::FilePath& filename) { _shadowMaterial->unbindGeometry(); } + + _meshRotation = mx::Vector3(); + _meshScale = 1.0f; + _cameraTarget = mx::Vector3(); + + initCamera(); + + if (_shadowMap) + { + _imageHandler->releaseRenderResources(_shadowMap); + _shadowMap = nullptr; + } } } @@ -885,10 +897,6 @@ void RenderView::initCamera() { _viewCamera->setViewportSize(mx::Vector2((float) _screenWidth, (float) _screenHeight)); - // Disable user camera controls when non-centered views are requested. - _userCameraEnabled = _cameraTarget == mx::Vector3(0.0) && - _meshScale == 1.0f; - if (!_userCameraEnabled || _geometryHandler->getMeshes().empty()) { return; diff --git a/source/MaterialXGraphEditor/RenderView.h b/source/MaterialXGraphEditor/RenderView.h index c6bfe9dca2..4f39f5be9e 100644 --- a/source/MaterialXGraphEditor/RenderView.h +++ b/source/MaterialXGraphEditor/RenderView.h @@ -192,9 +192,10 @@ class RenderView void setScrollEvent(float scrollY); void setMaterial(mx::TypedElementPtr elem); + void loadMesh(const mx::FilePath& filename); + private: void initContext(mx::GenContext& context); - void loadMesh(const mx::FilePath& filename); void loadEnvironmentLight(); void applyDirectLights(mx::DocumentPtr doc);