diff --git a/libraries/bxdf/standard_surface.mtlx b/libraries/bxdf/standard_surface.mtlx index a85c790bc2..2e786257a9 100644 --- a/libraries/bxdf/standard_surface.mtlx +++ b/libraries/bxdf/standard_surface.mtlx @@ -19,7 +19,7 @@ doc="Color tint on the specular reflection." /> - @@ -29,15 +29,15 @@ doc="Transmission of light through the surface for materials such as glass or water. The greater the value the more transparent the material." /> - - - @@ -45,7 +45,7 @@ doc="The color of the subsurface scattering effect." /> - @@ -65,19 +65,19 @@ doc="The amount of directional bias, or anisotropy, of the clear-coat layer." /> - - - - - - - diff --git a/python/Scripts/mxdoc.py b/python/Scripts/mxdoc.py index 8569dc09ef..66a6c62880 100644 --- a/python/Scripts/mxdoc.py +++ b/python/Scripts/mxdoc.py @@ -11,6 +11,18 @@ def usage(): print 'Usage: mxdoc.py []' print '- Default output file name is "nodedef_documentation.md"' +HEADERS = ('Name', 'Type', 'Default Value', + 'UI min', 'UI max', + 'UI Soft Min', 'UI Soft Max', + 'UI step', 'UI group', + 'Description', 'UI Advanced', + 'Connectable') + +ATTR_NAMES = ('uimin', 'uimax', + 'uisoftmin', 'uisoftmax', + 'uistep', 'uifolder', + 'doc', 'uiadvanced') + def main(): if len(sys.argv) < 2: usage() @@ -18,7 +30,7 @@ def main(): outfilename = 'nodedef_documentation.md' if len(sys.argv) > 2: - outfilename = sys.argv[2] + outfilename = sys.argv[2] filename = sys.argv[1] @@ -43,30 +55,34 @@ def main(): for nd in nodedefs: file.write('- *Nodedef*: %s\n' % nd.getName()) file.write('- *Type*: %s\n' % nd.getType()) - file.write('- *Doc*: %s\n' % nd.getAttribute('doc')) - file.write('| Name | Type | Default Value | UI min | UI max | UI group | Description | UI Advanced | Connectable |\n') - file.write('| ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- |\n') + file.write('- *Doc*: %s\n\n' % nd.getAttribute('doc')) + file.write('| ' + ' | '.join(HEADERS) + ' |\n') + file.write('|' + ' ---- |' * len(HEADERS) + '\n') for inp in nd.getInputs(): - name = inp.getName() - type = inp.getType(); - value = inp.getValue() - uimin = inp.getAttribute('uimin') - uimax = inp.getAttribute('uimax') - uifolder = inp.getAttribute('uifolder') - docattr = inp.getAttribute('doc') - adv = inp.getAttribute('uiadvanced') - buf = '| %s | %s | %s | %s | %s | %s | %s | %s | %s |\n' % (name, type, value, uimin, uimax, uifolder, docattr, adv, "true") + infos = [] + infos.append(inp.getName()) + infos.append(inp.getType()) + val = inp.getValue() + if infos[1] == "float": + val = round(val, 6) + infos.append(str(val)) + for attrname in ATTR_NAMES: + infos.append(inp.getAttribute(attrname)) + infos.append("true") + buf = '| ' + " | ".join(infos) + ' |\n' file.write(buf) for p in nd.getParameters(): - name = p.getName() - type = p.getType(); - value = inp.getValue() - uimin = p.getAttribute('uimin') - uimax = p.getAttribute('uimax') - uifolder = p.getAttribute('uifolder') - docattr = p.getAttribute('doc') - adv = inp.getAttribute('uiadvanced') - buf = '| %s | %s | %s | %s | %s | %s | %s | %s | %s |\n' % (name, type, value, uimin, uimax, uifolder, docattr, adv, "false") + infos = [] + infos.append(p.getName()) + infos.append(p.getType()) + val = p.getValue() + if infos[1] == "float": + val = round(val, 6) + infos.append(str(val)) + for attrname in ATTR_NAMES: + infos.append(p.getAttribute(attrname)) + infos.append("false") + buf = '| ' + " | ".join(infos) + ' |\n' file.write(buf) file.close() diff --git a/python/Scripts/nodedef_documentation.md b/python/Scripts/nodedef_documentation.md deleted file mode 100644 index e597046fee..0000000000 --- a/python/Scripts/nodedef_documentation.md +++ /dev/null @@ -1,48 +0,0 @@ -- *Nodedef*: ND_standard_surface_surfaceshader -- *Type*: surfaceshader -- *Doc*: Autodesk standard surface shader - -| Name | Type | Default Value | UI min | UI max | UI group | Description | UI Advanced | Connectable | -| ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | -| base | float | 0.800000011921 | 0.0 | 1.0 | Base | Multiplier on the intensity of the diffuse reflection. | | true | -| base_color | color3 | 1, 1, 1 | 0,0,0 | 1,1,1 | Base | Color of the diffuse reflection. | | true | -| diffuse_roughness | float | 0.0 | 0.0 | 1.0 | Base | Roughness of the diffuse reflection. Higher values cause the surface to appear flatter and darker. | true | true | -| metalness | float | 0.0 | 0.0 | 1.0 | Base | Specifies how metallic the material appears. At its maximum, the surface behaves like a metal, using fully specular reflection and complex fresnel. | | true | -| specular | float | 1.0 | 0.0 | 1.0 | Specular | Multiplier on the intensity of the specular reflection. | | true | -| specular_color | color3 | 1, 1, 1 | 0,0,0 | 1,1,1 | Specular | Color tint on the specular reflection. | | true | -| specular_roughness | float | 0.20000000298 | 0.0 | 1.0 | Specular | The roughness of the specular reflection. Lower numbers produce sharper reflections, higher numbers produce blurrier reflections. | | true | -| specular_IOR | float | 1.5 | 0.0 | 3.0 | Specular | Index of refraction for specular reflection. | | true | -| specular_anisotropy | float | 0.0 | 0.0 | 1.0 | Specular | The directional bias of reflected and transmitted light resulting in materials appearing rougher or glossier in certain directions. | true | true | -| specular_rotation | float | 0.0 | 0.0 | 1.0 | Specular | Rotation of the axis of specular anisotropy around the surface normal. | true | true | -| transmission | float | 0.0 | 0.0 | 1.0 | Transmission | Transmission of light through the surface for materials such as glass or water. The greater the value the more transparent the material. | true | true | -| transmission_color | color3 | 1, 1, 1 | 0,0,0 | 1,1,1 | Transmission | Color tint on the transmitted light. | true | true | -| transmission_depth | float | 0.0 | 0.0 | 100.0 | Transmission | Specifies the distance light travels inside the material before its becomes exactly the transmission color according to Beer's law. | true | true | -| transmission_scatter | color3 | 0, 0, 0 | 0,0,0 | 1,1,1 | Transmission | Scattering coefficient of the interior medium. Suitable for a large body of liquid or one that is fairly thick, such as an ocean, honey, ice, or frosted glass. | true | true | -| transmission_scatter_anisotropy | float | 0.0 | 0.0 | 1.0 | Transmission | The amount of directional bias, or anisotropy, of the scattering. | true | true | -| transmission_dispersion | float | 0.0 | 0.0 | 100.0 | Transmission | Dispersion amount, describing how much the index of refraction varies across wavelengths. | true | true | -| transmission_extra_roughness | float | 0.0 | 0.0 | 1.0 | Transmission | Additional roughness on top of specular roughness. Positive values blur refractions more than reflections, and negative values blur refractions less. | true | true | -| subsurface | float | 0.0 | 0.0 | 1.0 | Subsurface | The blend between diffuse reflection and subsurface scattering. A value of 1.0 indicates full subsurface scattering and a value 0 for diffuse reflection only. | true | true | -| subsurface_color | color3 | 1, 1, 1 | 0,0,0 | 1,1,1 | Subsurface | The color of the subsurface scattering effect. | true | true | -| subsurface_radius | color3 | 1, 1, 1 | 0,0,0 | 1,1,1 | Subsurface | The mean free path. The distance which light can travel before being scattered inside the surface. | true | true | -| subsurface_scale | float | 1.0 | 0.0 | 10.0 | Subsurface | Scalar weight for the subsurface radius value. | true | true | -| subsurface_anisotropy | float | 0.0 | 0.0 | 1.0 | Subsurface | The direction of subsurface scattering. 0 scatters light evenly, positive values scatter forward and negative values scatter backward. | true | true | -| sheen | float | 0.0 | 0.0 | 1.0 | Sheen | The weight of a sheen layer that can be used to approximate microfibers or fabrics such as velvet and satin. | true | true | -| sheen_color | color3 | 1, 1, 1 | 0,0,0 | 1,1,1 | Sheen | The color of the sheen layer. | true | true | -| sheen_roughness | float | 0.300000011921 | 0.0 | 1.0 | Sheen | The roughness of the sheen layer. | true | true | -| coat | float | 0.0 | 0.0 | 1.0 | Coat | The weight of a reflective clear-coat layer on top of the material. Use for materials such as car paint or an oily layer. | | true | -| coat_color | color3 | 1, 1, 1 | 0,0,0 | 1,1,1 | Coat | The color of the clear-coat layer's transparency. | | true | -| coat_roughness | float | 0.10000000149 | 0.0 | 1.0 | Coat | The roughness of the clear-coat reflections. The lower the value, the sharper the reflection. | | true | -| coat_anisotropy | float | 0.0 | 0.0 | 1.0 | Coat | The amount of directional bias, or anisotropy, of the clear-coat layer. | true | true | -| coat_rotation | float | 0.0 | 0.0 | 1.0 | Coat | The rotation of the anisotropic effect of the clear-coat layer. | true | true | -| coat_IOR | float | 1.5 | 0.0 | 3.0 | Coat | The index of refraction of the clear-coat layer. | | true | -| coat_normal | vector3 | None | 0,0,0 | 1,1,1 | Coat | Input normal for clear-coat layer | | true | -| coat_affect_color | float | 0.0 | 0,0,0 | 1,1,1 | Coat | Controls the saturation of diffuse reflection and subsurface scattering below the clear-coat. | true | true | -| coat_affect_roughness | float | 0.0 | | | Coat | Controls the roughness of the specular reflection in the layers below the clear-coat. | true | true | -| thin_film_thickness | float | 0.0 | 0.0 | 2000.0 | Thin Film | The thickness of the thin film layer on a surface. Use for materials such as multitone car paint or soap bubbles. | true | true | -| thin_film_IOR | float | 1.5 | 0.0 | 3.0 | Thin Film | The index of refraction of the medium surrounding the material. | true | true | -| emission | float | 0.0 | 0.0 | 1.0 | Emission | The amount of emitted incandescent light. | | true | -| emission_color | color3 | 1, 1, 1 | 0,0,0 | 1,1,1 | Emission | The color of the emitted light. | | true | -| opacity | color3 | 1, 1, 1 | 0,0,0 | 1,1,1 | Geometry | The opacity of the entire material. | | true | -| thin_walled | boolean | False | | | Geometry | If tue the surface is double-sided and represents an infinitely thin shell. Suiteable for thin objects such as tree leafs or paper | true | true | -| normal | vector3 | None | | | Geometry | Input geometric normal | | true | -| tangent | vector3 | None | | | Geometry | Input geometric tangent | | true | diff --git a/resources/Materials/TestSuite/libraries/sd/floor.mtlx b/resources/Materials/TestSuite/libraries/sd/floor.mtlx index 0cd8dffab7..27d3a0c4b6 100644 --- a/resources/Materials/TestSuite/libraries/sd/floor.mtlx +++ b/resources/Materials/TestSuite/libraries/sd/floor.mtlx @@ -15,10 +15,11 @@ + - + @@ -117,7 +118,7 @@ - + @@ -290,6 +291,7 @@ + diff --git a/source/MaterialXCore/Element.cpp b/source/MaterialXCore/Element.cpp index 6b34130229..7653762f5b 100644 --- a/source/MaterialXCore/Element.cpp +++ b/source/MaterialXCore/Element.cpp @@ -32,6 +32,9 @@ const string ValueElement::UI_NAME_ATTRIBUTE = "uiname"; const string ValueElement::UI_FOLDER_ATTRIBUTE = "uifolder"; const string ValueElement::UI_MIN_ATTRIBUTE = "uimin"; const string ValueElement::UI_MAX_ATTRIBUTE = "uimax"; +const string ValueElement::UI_SOFT_MIN_ATTRIBUTE = "uisoftmin"; +const string ValueElement::UI_SOFT_MAX_ATTRIBUTE = "uisoftmax"; +const string ValueElement::UI_STEP_ATTRIBUTE = "uistep"; const string ValueElement::UI_ADVANCED_ATTRIBUTE = "uiadvanced"; const string ValueElement::UNIT_ATTRIBUTE = "unit"; const string ValueElement::UNITTYPE_ATTRIBUTE = "unittype"; diff --git a/source/MaterialXCore/Element.h b/source/MaterialXCore/Element.h index 9f56471cca..210b507598 100644 --- a/source/MaterialXCore/Element.h +++ b/source/MaterialXCore/Element.h @@ -1151,6 +1151,9 @@ class ValueElement : public TypedElement static const string UI_FOLDER_ATTRIBUTE; static const string UI_MIN_ATTRIBUTE; static const string UI_MAX_ATTRIBUTE; + static const string UI_SOFT_MIN_ATTRIBUTE; + static const string UI_SOFT_MAX_ATTRIBUTE; + static const string UI_STEP_ATTRIBUTE; static const string UI_ADVANCED_ATTRIBUTE; static const string UNIT_ATTRIBUTE; static const string UNITTYPE_ATTRIBUTE; diff --git a/source/MaterialXFormat/File.cpp b/source/MaterialXFormat/File.cpp index 42f861408f..f17ceb12f0 100644 --- a/source/MaterialXFormat/File.cpp +++ b/source/MaterialXFormat/File.cpp @@ -209,9 +209,20 @@ FilePathVec FilePath::getSubDirectories() const while (struct dirent* entry = readdir(dir)) { string path = entry->d_name; - if (entry->d_type == DT_DIR && (path != "." && path != "..")) + if (path == "." || path == "..") continue; + + auto d_type = entry->d_type; + FilePath newDir = *this / path; + + if (d_type == DT_UNKNOWN) + { + if (newDir.isDirectory()) + { + d_type = DT_DIR; + } + } + if (d_type == DT_DIR) { - FilePath newDir = *this / path; FilePathVec newDirs = newDir.getSubDirectories(); dirs.insert(dirs.end(), newDirs.begin(), newDirs.end()); } diff --git a/source/MaterialXRender/Util.cpp b/source/MaterialXRender/Util.cpp index c6a527aab8..50a9151f35 100644 --- a/source/MaterialXRender/Util.cpp +++ b/source/MaterialXRender/Util.cpp @@ -123,6 +123,39 @@ unsigned int getUIProperties(ConstValueElementPtr nodeDefElement, UIProperties& } } + const string& uiSoftMinString = nodeDefElement->getAttribute(ValueElement::UI_SOFT_MIN_ATTRIBUTE); + if (!uiSoftMinString.empty()) + { + ValuePtr value = Value::createValueFromStrings(uiSoftMinString, nodeDefElement->getType()); + if (value) + { + uiProperties.uiSoftMin = value; + propertyCount++; + } + } + + const string& uiSoftMaxString = nodeDefElement->getAttribute(ValueElement::UI_SOFT_MAX_ATTRIBUTE); + if (!uiSoftMaxString.empty()) + { + ValuePtr value = Value::createValueFromStrings(uiSoftMaxString, nodeDefElement->getType()); + if (value) + { + uiProperties.uiSoftMax = value; + propertyCount++; + } + } + + const string& uiStepString = nodeDefElement->getAttribute(ValueElement::UI_STEP_ATTRIBUTE); + if (!uiStepString.empty()) + { + ValuePtr value = Value::createValueFromStrings(uiStepString, nodeDefElement->getType()); + if (value) + { + uiProperties.uiStep = value; + propertyCount++; + } + } + const string& uiAdvancedString = nodeDefElement->getAttribute(ValueElement::UI_ADVANCED_ATTRIBUTE); uiProperties.uiAdvanced = (uiAdvancedString == "true"); if (!uiAdvancedString.empty()) diff --git a/source/MaterialXRender/Util.h b/source/MaterialXRender/Util.h index 26b5a2c805..d325a5633b 100644 --- a/source/MaterialXRender/Util.h +++ b/source/MaterialXRender/Util.h @@ -56,6 +56,15 @@ namespace MaterialX /// UI maximum value ValuePtr uiMax; + /// UI soft minimum value + ValuePtr uiSoftMin; + + /// UI soft maximum value + ValuePtr uiSoftMax; + + /// UI step value + ValuePtr uiStep; + /// UI advanced element bool uiAdvanced = false; }; diff --git a/source/MaterialXTest/RenderGLSL.cpp b/source/MaterialXTest/RenderGLSL.cpp index d2ea560235..49bc9ed3db 100644 --- a/source/MaterialXTest/RenderGLSL.cpp +++ b/source/MaterialXTest/RenderGLSL.cpp @@ -449,6 +449,12 @@ bool GlslShaderRenderTester::runRenderer(const std::string& shaderName, log << ". UI Min: " << uiProperties.uiMin->getValueString(); if (uiProperties.uiMax) log << ". UI Max: " << uiProperties.uiMax->getValueString(); + if (uiProperties.uiSoftMin) + log << ". UI Soft Min: " << uiProperties.uiSoftMin->getValueString(); + if (uiProperties.uiSoftMax) + log << ". UI Soft Max: " << uiProperties.uiSoftMax->getValueString(); + if (uiProperties.uiStep) + log << ". UI Step: " << uiProperties.uiStep->getValueString(); log << std::endl; } } diff --git a/source/MaterialXView/Editor.cpp b/source/MaterialXView/Editor.cpp index e6045660ab..9cfc122d17 100644 --- a/source/MaterialXView/Editor.cpp +++ b/source/MaterialXView/Editor.cpp @@ -138,7 +138,7 @@ void PropertyEditor::create(Viewer& parent) } ng::FloatBox* PropertyEditor::makeFloatWidget(ng::Widget* container, const std::string& label, mx::ValuePtr value, - bool editable, mx::ValuePtr min, mx::ValuePtr max, + bool editable, const mx::UIProperties& ui, Viewer* viewer, const std::string& path) { new ng::Label(container, label); @@ -147,19 +147,39 @@ ng::FloatBox* PropertyEditor::makeFloatWidget(ng::Widget* container, cons ng::Slider *slider = new ng::Slider(container); slider->setValue(v); + auto range = std::pair(0.0f, 0.0f); ng::FloatBox* floatVar = new ng::FloatBox(container, v); floatVar->setFixedSize(ng::Vector2i(100, 20)); floatVar->setEditable(editable); floatVar->setFontSize(15); floatVar->setAlignment(ng::TextBox::Alignment::Right); - if (min) + if (ui.uiMin) { - floatVar->setMinValue(min->asA()); + floatVar->setMinValue(ui.uiMin->asA()); + range.first = ui.uiMin->asA(); } - if (max) + if (ui.uiMax) { - floatVar->setMinValue(min->asA()); + floatVar->setMaxValue(ui.uiMax->asA()); + range.second = ui.uiMax->asA(); + } + if (ui.uiSoftMin) + { + range.first = ui.uiSoftMin->asA(); + } + if (ui.uiSoftMax) + { + range.second = ui.uiSoftMax->asA(); + } + if (range.first != range.second) + { + slider->setRange(range); + } + if (ui.uiStep) + { + floatVar->setValueIncrement(ui.uiStep->asA()); + floatVar->setSpinnable(true); } slider->setCallback([floatVar, path, viewer](float value) @@ -168,11 +188,13 @@ ng::FloatBox* PropertyEditor::makeFloatWidget(ng::Widget* container, cons MaterialPtr material = viewer->getSelectedMaterial(); if (material) { - material->setUniformFloat(path, value); + material->setUniformFloat(path, floatVar->value()); } }); - floatVar->setCallback([slider, path, viewer](float value) + floatVar->setCallback([floatVar, slider, path, viewer](float /*unclamped*/) { + // https://github.com/wjakob/nanogui/issues/205 + float value = floatVar->value(); slider->setValue(value); MaterialPtr material = viewer->getSelectedMaterial(); if (material) @@ -196,8 +218,6 @@ void PropertyEditor::addItemToForm(const mx::UIPropertyItem& item, const std::st label += std::string(" (") + unit + std::string(")"); } const std::string& path = item.variable->getPath(); - mx::ValuePtr min = ui.uiMin; - mx::ValuePtr max = ui.uiMax; const mx::StringVec& enumeration = ui.enumeration; const std::vector enumValues = ui.enumerationValues; @@ -279,15 +299,30 @@ void PropertyEditor::addItemToForm(const mx::UIPropertyItem& item, const std::st auto intVar = new ng::IntBox(twoColumns); intVar->setFixedSize(ng::Vector2i(100, 20)); intVar->setFontSize(15); + intVar->setEditable(editable); intVar->setSpinnable(editable); - intVar->setCallback([path, viewer](int v) + intVar->setCallback([intVar, path, viewer](int /*unclamped*/) { MaterialPtr material = viewer->getSelectedMaterial(); if (material) { - material->setUniformInt(path, v); + // https://github.com/wjakob/nanogui/issues/205 + material->setUniformInt(path, intVar->value()); } }); + if (ui.uiMin) + { + intVar->setMinValue(ui.uiMin->asA()); + } + if (ui.uiMax) + { + intVar->setMaxValue(ui.uiMax->asA()); + } + if (ui.uiStep) + { + intVar->setValueIncrement(ui.uiStep->asA()); + } + intVar->setValue(value->asA()); } } @@ -296,7 +331,7 @@ void PropertyEditor::addItemToForm(const mx::UIPropertyItem& item, const std::st { ng::Widget* threeColumns = new ng::Widget(container); threeColumns->setLayout(_gridLayout3); - makeFloatWidget(threeColumns, label, value, editable, min, max, viewer, path); + makeFloatWidget(threeColumns, label, value, editable, ui, viewer, path); } // Boolean widget diff --git a/source/MaterialXView/Editor.h b/source/MaterialXView/Editor.h index aff3db8909..e4d60fd6e3 100644 --- a/source/MaterialXView/Editor.h +++ b/source/MaterialXView/Editor.h @@ -39,7 +39,7 @@ class PropertyEditor void addItemToForm(const mx::UIPropertyItem& item, const std::string& group, ng::Widget* container, Viewer* viewer, bool editable); ng::FloatBox* makeFloatWidget(ng::Widget* container, const std::string& label, mx::ValuePtr value, - bool editable, mx::ValuePtr min, mx::ValuePtr max, Viewer* viewer, const std::string& path); + bool editable, const mx::UIProperties& ui, Viewer* viewer, const std::string& path); ng::Widget* _container; ng::Window* _formWindow; diff --git a/source/PyMaterialX/PyMaterialXCore/PyElement.cpp b/source/PyMaterialX/PyMaterialXCore/PyElement.cpp index 421254e3d9..be96dbf08d 100644 --- a/source/PyMaterialX/PyMaterialXCore/PyElement.cpp +++ b/source/PyMaterialX/PyMaterialXCore/PyElement.cpp @@ -178,6 +178,9 @@ void bindPyElement(py::module& mod) .def_readonly_static("UIFOLDER", &mx::ValueElement::UI_FOLDER_ATTRIBUTE) .def_readonly_static("UIMIN", &mx::ValueElement::UI_MIN_ATTRIBUTE) .def_readonly_static("UIMAX", &mx::ValueElement::UI_MAX_ATTRIBUTE) + .def_readonly_static("UISOFTMIN", &mx::ValueElement::UI_SOFT_MIN_ATTRIBUTE) + .def_readonly_static("UISOFTMAX", &mx::ValueElement::UI_SOFT_MAX_ATTRIBUTE) + .def_readonly_static("UISTEP", &mx::ValueElement::UI_STEP_ATTRIBUTE) .def_readonly_static("UIADVANCED", &mx::ValueElement::UI_ADVANCED_ATTRIBUTE) BIND_VALUE_ELEMENT_FUNC_INSTANCE(integer, int)