diff --git a/documents/Specification/MaterialX.Specification.md b/documents/Specification/MaterialX.Specification.md
index 895b4756c5..42b6cbbcaf 100644
--- a/documents/Specification/MaterialX.Specification.md
+++ b/documents/Specification/MaterialX.Specification.md
@@ -1084,6 +1084,12 @@ Math nodes have one or two spatially-varying inputs, and are used to perform a m
* `in1` (float or colorN or vectorN): the value or nodename for the primary input
* `in2` (same type as `in1` or float): the modulo value or nodename to divide by, cannot be 0 in any channel; default is 1.0 in all channels, which effectively returns the fractional part of a float value
+
+
+* **`invert`**: subtract the incoming float/color/vector from "amount" in all channels, outputting: `amount - in`.
+ * `in` (float or colorN or vectorN): the value or nodename for the primary input
+ * `amount` (same type as `in` or float): the value or nodename to subtract from; default is 1.0 in all channels
+
* **`absval`**: the per-channel absolute value of the incoming float/color/vector.
diff --git a/javascript/MaterialXTest/browser/esslShaderGenerator.spec.js b/javascript/MaterialXTest/browser/esslShaderGenerator.spec.js
index 657310aeeb..dceba112e0 100644
--- a/javascript/MaterialXTest/browser/esslShaderGenerator.spec.js
+++ b/javascript/MaterialXTest/browser/esslShaderGenerator.spec.js
@@ -1,6 +1,6 @@
// MaterialX is served through a script tag in the test setup.
-function createStandardSurfaceMaterial(mx)
+function createStandardSurfaceMaterial(mx)
{
const doc = mx.createDocument();
const ssName = 'SR_default';
@@ -15,19 +15,21 @@ function createStandardSurfaceMaterial(mx)
return doc;
}
-describe('Generate ESSL Shaders', function ()
+describe('Generate ESSL Shaders', function ()
{
let mx;
const canvas = document.createElement('canvas');
const gl = canvas.getContext('webgl2');
-
+
this.timeout(60000);
- before(async function () {
+ before(async function ()
+ {
mx = await MaterialX();
});
- it('Compile Shaders', () => {
+ it('Compile Shaders', () =>
+ {
const doc = createStandardSurfaceMaterial(mx);
const gen = new mx.EsslShaderGenerator();
@@ -37,7 +39,7 @@ describe('Generate ESSL Shaders', function ()
doc.importLibrary(stdlib);
const elem = mx.findRenderableElement(doc);
- try
+ try
{
const mxShader = gen.generate(elem.getNamePath(), elem, genContext);
@@ -47,7 +49,7 @@ describe('Generate ESSL Shaders', function ()
const glVertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(glVertexShader, vShader);
gl.compileShader(glVertexShader);
- if (!gl.getShaderParameter(glVertexShader, gl.COMPILE_STATUS))
+ if (!gl.getShaderParameter(glVertexShader, gl.COMPILE_STATUS))
{
console.error("-------- VERTEX SHADER FAILED TO COMPILE: ----------------");
console.error("--- VERTEX SHADER LOG ---");
@@ -61,7 +63,7 @@ describe('Generate ESSL Shaders', function ()
const glPixelShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(glPixelShader, fShader);
gl.compileShader(glPixelShader);
- if (!gl.getShaderParameter(glPixelShader, gl.COMPILE_STATUS))
+ if (!gl.getShaderParameter(glPixelShader, gl.COMPILE_STATUS))
{
console.error("-------- PIXEL SHADER FAILED TO COMPILE: ----------------");
console.error("--- PIXEL SHADER LOG ---");
@@ -75,7 +77,7 @@ describe('Generate ESSL Shaders', function ()
catch (errPtr)
{
console.error("-------- Failed code generation: ----------------");
- console.error(mx.getExceptionMessage(errPtr));
+ console.error(mx.getExceptionMessage(errPtr));
}
});
});
diff --git a/javascript/MaterialXTest/browser/karma.conf.js b/javascript/MaterialXTest/browser/karma.conf.js
index aec860e8b5..6dd8051319 100644
--- a/javascript/MaterialXTest/browser/karma.conf.js
+++ b/javascript/MaterialXTest/browser/karma.conf.js
@@ -1,10 +1,11 @@
-module.exports = function(config) {
+module.exports = function (config)
+{
config.set({
basePath: '../', // base is the javascript folder
files: [
{ pattern: '_build/JsMaterialXGenShader.js', watched: false, included: true, served: true },
{ pattern: '_build/JsMaterialXGenShader.wasm', watched: false, included: false, served: true },
- {pattern: '_build/JsMaterialXGenShader.data', watched: false, included: false, served: true, nocache: true },
+ { pattern: '_build/JsMaterialXGenShader.data', watched: false, included: false, served: true, nocache: true },
{ pattern: 'browser/*.spec.js', watched: true, included: true, served: true },
],
mime: {
diff --git a/javascript/MaterialXTest/codeExamples.spec.js b/javascript/MaterialXTest/codeExamples.spec.js
index 17f2559b49..8cff44c3fe 100644
--- a/javascript/MaterialXTest/codeExamples.spec.js
+++ b/javascript/MaterialXTest/codeExamples.spec.js
@@ -2,8 +2,10 @@ import { expect } from 'chai';
import Module from './_build/JsMaterialXCore.js';
import { getMtlxStrings } from './testHelpers';
-describe('Code Examples', () => {
- it('Building a MaterialX Document', async () => {
+describe('Code Examples', () =>
+{
+ it('Building a MaterialX Document', async () =>
+ {
const mx = await Module();
// Create a document.
const doc = mx.createDocument();
@@ -76,7 +78,8 @@ describe('Code Examples', () => {
// expect(roughness.getBoundValue(material).getValueString()).to.equal('0.5');
});
- it('Traversing a Document Tree', async () => {
+ it('Traversing a Document Tree', async () =>
+ {
const xmlStr = getMtlxStrings(
['standard_surface_greysphere_calibration.mtlx'],
'../../resources/Materials/Examples/StandardSurface'
@@ -92,13 +95,16 @@ describe('Code Examples', () => {
let elementCount = 0;
let nodeCount = 0;
let fileCount = 0;
- for(let elem of elements) {
+ for (let elem of elements)
+ {
elementCount++;
// Display the filename of each image node.
- if (elem.isANode('image')) {
+ if (elem.isANode('image'))
+ {
nodeCount++;
const input = elem.getInput('file');
- if (input) {
+ if (input)
+ {
fileCount++;
const filename = input.getValueString();
expect(elem.getName()).to.equal('image1');
@@ -111,7 +117,8 @@ describe('Code Examples', () => {
expect(fileCount).to.equal(1);
});
- it('Building a MaterialX Document', async () => {
+ it('Building a MaterialX Document', async () =>
+ {
const xmlStr = getMtlxStrings(['standard_surface_marble_solid.mtlx'], '../../resources/Materials/Examples/StandardSurface')[0];
const mx = await Module();
diff --git a/javascript/MaterialXTest/customBindings.spec.js b/javascript/MaterialXTest/customBindings.spec.js
index e44cc7e85e..740189f0ef 100644
--- a/javascript/MaterialXTest/customBindings.spec.js
+++ b/javascript/MaterialXTest/customBindings.spec.js
@@ -2,15 +2,18 @@ import { expect } from 'chai';
import Module from './_build/JsMaterialXCore.js';
import { getMtlxStrings } from './testHelpers';
-describe('Custom Bindings', () => {
+describe('Custom Bindings', () =>
+{
const examplesPath = '../../resources/Materials/Examples/StandardSurface';
- let mx;
- before(async () => {
+ let mx;
+ before(async () =>
+ {
mx = await Module();
});
- it('Optional parameters work as expected', () => {
+ it('Optional parameters work as expected', () =>
+ {
const doc = mx.createDocument();
// Call a method without optional argument
const nodeGraph = doc.addNodeGraph();
@@ -29,7 +32,8 @@ describe('Custom Bindings', () => {
expect(() => { nodeGraph.addNode(); }).to.throw;
});
- it('Vector <-> Array conversion', () => {
+ it('Vector <-> Array conversion', () =>
+ {
// Functions that return vectors in C++ should return an array in JS
const doc = mx.createDocument();
const nodeGraph = doc.addNodeGraph();
@@ -66,7 +70,8 @@ describe('Custom Bindings', () => {
expect(nodes[2].getName()).to.equal('anotherNode'); // Name set explicitly at creation time
});
- it('C++ exception handling', () => {
+ it('C++ exception handling', () =>
+ {
// Exceptions that are thrown and caught in C++ shouldn't bubble up to JS
const doc = mx.createDocument();
const nodeGraph1 = doc.addNodeGraph();
@@ -79,15 +84,18 @@ describe('Custom Bindings', () => {
// Exceptions that are not caught in C++ should throw with an exception pointer
nodeGraph1.addNode('node', 'node1');
expect(() => { nodeGraph1.addNode('node', 'node1'); }).to.throw;
- try {
+ try
+ {
nodeGraph1.addNode('node', 'node1');
- } catch (errPtr) {
+ } catch (errPtr)
+ {
expect(errPtr).to.be.a('number');
expect(mx.getExceptionMessage(errPtr)).to.be.a('string');
}
});
- it('getReferencedSourceUris', async () => {
+ it('getReferencedSourceUris', async () =>
+ {
const doc = mx.createDocument();
const filename = 'standard_surface_look_brass_tiled.mtlx';
await mx.readFromXmlFile(doc, filename, examplesPath);
@@ -98,7 +106,8 @@ describe('Custom Bindings', () => {
expect(sourceUris.includes('standard_surface_brass_tiled.mtlx')).to.be.true;
});
- it('Should invoke correct instance of \'validate\'', () => {
+ it('Should invoke correct instance of \'validate\'', () =>
+ {
// We check whether the correct function is called by provoking an error message that is specific to the
// function that we expect to be called.
const message = {};
@@ -126,7 +135,8 @@ describe('Custom Bindings', () => {
expect(message.message).to.include('Unit type definition does not exist in document')
});
- it('StringResolver name substitution getters', () => {
+ it('StringResolver name substitution getters', () =>
+ {
const fnTestData = {
fnKey: 'fnValue',
fnKey1: 'fnValue1'
@@ -156,7 +166,8 @@ describe('Custom Bindings', () => {
expect(gnSubs).to.deep.equal(gnTestData);
});
- it('getShaderNodes', async () => {
+ it('getShaderNodes', async () =>
+ {
const doc = mx.createDocument();
const fileNames = ['standard_surface_marble_solid.mtlx'];
const mtlxStrs = getMtlxStrings(fileNames, examplesPath);
@@ -175,14 +186,16 @@ describe('Custom Bindings', () => {
expect(shaderNodes.length).to.equal(0);
});
- it('createValidName', () => {
+ it('createValidName', () =>
+ {
const testString = '_Note_:Please,turn.this+-into*1#valid\nname for_me';
const replaceRegex = /[^a-zA-Z0-9_:]/g
expect(mx.createValidName(testString)).to.equal(testString.replace(replaceRegex, '_'));
expect(mx.createValidName(testString, '-')).to.equal(testString.replace(replaceRegex, '-'));
});
- it('getVersionIntegers', () => {
+ it('getVersionIntegers', () =>
+ {
const versionStringArr = mx.getVersionString().split('.').map((value) => parseInt(value, 10));
// Global getVersionIntegers
diff --git a/javascript/MaterialXTest/document.spec.js b/javascript/MaterialXTest/document.spec.js
index 01dc828f3f..ac2adba9ff 100644
--- a/javascript/MaterialXTest/document.spec.js
+++ b/javascript/MaterialXTest/document.spec.js
@@ -1,30 +1,37 @@
import { expect } from 'chai';
import Module from './_build/JsMaterialXCore.js';
-describe('Document', () => {
+describe('Document', () =>
+{
let mx, doc;
- before(async () => {
+ before(async () =>
+ {
mx = await Module();
// Create a document.
doc = mx.createDocument();
});
- function expectError(type, cb) {
- try {
+ function expectError(type, cb)
+ {
+ try
+ {
cb();
throw new Error('Expected function to throw!');
- } catch (exceptionPtr) {
+ } catch (exceptionPtr)
+ {
const message = mx.getExceptionMessage(exceptionPtr);
expect(message.indexOf(type) !== -1).to.be.true;
}
}
let nodeGraph;
- it('Build document', () => {
+ it('Build document', () =>
+ {
// Create a node graph with constant and image sources.
nodeGraph = doc.addNodeGraph();
expect(nodeGraph).to.exist;
- expectError('Child name is not unique: nodegraph1', () => {
+ expectError('Child name is not unique: nodegraph1', () =>
+ {
doc.addNodeGraph(nodeGraph.getName());
});
const constant = nodeGraph.addNode('constant');
diff --git a/javascript/MaterialXTest/element.spec.js b/javascript/MaterialXTest/element.spec.js
index e22c374851..cbb672c5c2 100644
--- a/javascript/MaterialXTest/element.spec.js
+++ b/javascript/MaterialXTest/element.spec.js
@@ -1,145 +1,166 @@
import { expect } from 'chai';
import Module from './_build/JsMaterialXCore.js';
-describe('Element', () => {
- let mx, doc, valueTypes;
+describe('Element', () =>
+{
+ let mx, doc, valueTypes;
- const primitiveValueTypes = {
- Integer: 10,
- Boolean: true,
- String: 'test',
- Float: 15,
- IntegerArray: [1,2,3,4,5],
- FloatArray: [12, 14], // Not using actual floats to avoid precision problems
- StringArray: ['first', 'second'],
- BooleanArray:[true, true, false],
- }
+ const primitiveValueTypes = {
+ Integer: 10,
+ Boolean: true,
+ String: 'test',
+ Float: 15,
+ IntegerArray: [1, 2, 3, 4, 5],
+ FloatArray: [12, 14], // Not using actual floats to avoid precision problems
+ StringArray: ['first', 'second'],
+ BooleanArray: [true, true, false],
+ }
- before(async () => {
- mx = await Module();
- doc = mx.createDocument();
- valueTypes = {
- Color3: new mx.Color3(1, 0, 0.5),
- Color4: new mx.Color4(0, 1, 0.5, 1),
- Vector2: new mx.Vector2(0, 1),
- Vector3: new mx.Vector3(0, 1, 2),
- Vector4: new mx.Vector4(0, 1, 2, 1),
- Matrix33: new mx.Matrix33(0, 1, 2, 3, 4, 5, 6, 7, 8),
- Matrix44: new mx.Matrix44(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15),
- };
- });
+ before(async () =>
+ {
+ mx = await Module();
+ doc = mx.createDocument();
+ valueTypes = {
+ Color3: new mx.Color3(1, 0, 0.5),
+ Color4: new mx.Color4(0, 1, 0.5, 1),
+ Vector2: new mx.Vector2(0, 1),
+ Vector3: new mx.Vector3(0, 1, 2),
+ Vector4: new mx.Vector4(0, 1, 2, 1),
+ Matrix33: new mx.Matrix33(0, 1, 2, 3, 4, 5, 6, 7, 8),
+ Matrix44: new mx.Matrix44(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15),
+ };
+ });
- describe('value setters', () => {
- const checkValue = (types, assertionCallback) => {
- const elem = doc.addChildOfCategory('geomprop');
- Object.keys(types).forEach((typeName) => {
- const setFn = `setValue${typeName}`;
- elem[setFn](types[typeName]);
- assertionCallback(elem.getValue().getData(), typeName);
- });
- };
+ describe('value setters', () =>
+ {
+ const checkValue = (types, assertionCallback) =>
+ {
+ const elem = doc.addChildOfCategory('geomprop');
+ Object.keys(types).forEach((typeName) =>
+ {
+ const setFn = `setValue${typeName}`;
+ elem[setFn](types[typeName]);
+ assertionCallback(elem.getValue().getData(), typeName);
+ });
+ };
- it('should work with expected type', () => {
- checkValue(valueTypes, (returnedValue, typeName) => {
- expect(returnedValue).to.be.an.instanceof(mx[`${typeName}`]);
- expect(returnedValue.equals(valueTypes[typeName])).to.equal(true);
- });
- });
+ it('should work with expected type', () =>
+ {
+ checkValue(valueTypes, (returnedValue, typeName) =>
+ {
+ expect(returnedValue).to.be.an.instanceof(mx[`${typeName}`]);
+ expect(returnedValue.equals(valueTypes[typeName])).to.equal(true);
+ });
+ });
- it('should work with expected primitive type', () => {
- checkValue(primitiveValueTypes, (returnedValue, typeName) => {
- expect(returnedValue).to.eql(primitiveValueTypes[typeName]);
- });
- });
+ it('should work with expected primitive type', () =>
+ {
+ checkValue(primitiveValueTypes, (returnedValue, typeName) =>
+ {
+ expect(returnedValue).to.eql(primitiveValueTypes[typeName]);
+ });
+ });
- it('should fail for incorrect type', () => {
- const elem = doc.addChildOfCategory('geomprop');
- expect(()=>elem.Matrix33(true)).to.throw();
+ it('should fail for incorrect type', () =>
+ {
+ const elem = doc.addChildOfCategory('geomprop');
+ expect(() => elem.Matrix33(true)).to.throw();
+ });
});
- });
- describe('typed value setters', () => {
- const checkTypes = (types, assertionCallback) => {
- const elem = doc.addChildOfCategory('geomprop');
- Object.keys(types).forEach((typeName) => {
- const setFn = `setTypedAttribute${typeName}`;
- const getFn = `getTypedAttribute${typeName}`;
- elem[setFn](typeName, types[typeName]);
- assertionCallback(elem[getFn](typeName), types[typeName]);
- });
- };
+ describe('typed value setters', () =>
+ {
+ const checkTypes = (types, assertionCallback) =>
+ {
+ const elem = doc.addChildOfCategory('geomprop');
+ Object.keys(types).forEach((typeName) =>
+ {
+ const setFn = `setTypedAttribute${typeName}`;
+ const getFn = `getTypedAttribute${typeName}`;
+ elem[setFn](typeName, types[typeName]);
+ assertionCallback(elem[getFn](typeName), types[typeName]);
+ });
+ };
- it('should work with expected custom type', () => {
- checkTypes(valueTypes, (returnedValue, originalValue) => {
- expect(returnedValue.equals(originalValue)).to.equal(true);
- });
- });
+ it('should work with expected custom type', () =>
+ {
+ checkTypes(valueTypes, (returnedValue, originalValue) =>
+ {
+ expect(returnedValue.equals(originalValue)).to.equal(true);
+ });
+ });
- it('should work with expected primitive type', () => {
- checkTypes(primitiveValueTypes, (returnedValue, originalValue) => {
- expect(returnedValue).to.eql(originalValue);
- });
- });
+ it('should work with expected primitive type', () =>
+ {
+ checkTypes(primitiveValueTypes, (returnedValue, originalValue) =>
+ {
+ expect(returnedValue).to.eql(originalValue);
+ });
+ });
- it('should fail for incorrect type', () => {
- const elem = doc.addChildOfCategory('geomprop');
- expect(()=>elem.setTypedAttributeColor3('wrongType', true)).to.throw();
+ it('should fail for incorrect type', () =>
+ {
+ const elem = doc.addChildOfCategory('geomprop');
+ expect(() => elem.setTypedAttributeColor3('wrongType', true)).to.throw();
+ });
});
- });
- it('factory invocation should match specialized functions', () => {
- // List based in source/MaterialXCore/Element.cpp
- const elemtypeArr = [
- 'Backdrop',
- 'Collection',
- 'GeomInfo',
- 'MaterialAssign',
- 'PropertySetAssign',
- 'Visibility',
- 'GeomPropDef',
- 'Look',
- 'LookGroup',
- 'PropertySet',
- 'TypeDef',
- 'AttributeDef',
- 'NodeGraph',
- 'Implementation',
- 'Node',
- 'NodeDef',
- 'Variant',
- 'Member',
- 'TargetDef',
- 'GeomProp',
- 'Input',
- 'Output',
- 'Property',
- 'PropertyAssign',
- 'Unit',
- 'UnitDef',
- 'UnitTypeDef',
- 'VariantAssign',
- 'VariantSet',
- ];
+ it('factory invocation should match specialized functions', () =>
+ {
+ // List based in source/MaterialXCore/Element.cpp
+ const elemtypeArr = [
+ 'Backdrop',
+ 'Collection',
+ 'GeomInfo',
+ 'MaterialAssign',
+ 'PropertySetAssign',
+ 'Visibility',
+ 'GeomPropDef',
+ 'Look',
+ 'LookGroup',
+ 'PropertySet',
+ 'TypeDef',
+ 'AttributeDef',
+ 'NodeGraph',
+ 'Implementation',
+ 'Node',
+ 'NodeDef',
+ 'Variant',
+ 'Member',
+ 'TargetDef',
+ 'GeomProp',
+ 'Input',
+ 'Output',
+ 'Property',
+ 'PropertyAssign',
+ 'Unit',
+ 'UnitDef',
+ 'UnitTypeDef',
+ 'VariantAssign',
+ 'VariantSet',
+ ];
- elemtypeArr.forEach((typeName) => {
- const specializedFn = `addChild${typeName}`;
- const factoryName = typeName.toLowerCase();
- const type = mx[typeName];
- expect(doc[specializedFn]()).to.be.an.instanceof(type);
- expect(doc.addChildOfCategory(factoryName)).to.be.an.instanceof(type);
- });
+ elemtypeArr.forEach((typeName) =>
+ {
+ const specializedFn = `addChild${typeName}`;
+ const factoryName = typeName.toLowerCase();
+ const type = mx[typeName];
+ expect(doc[specializedFn]()).to.be.an.instanceof(type);
+ expect(doc.addChildOfCategory(factoryName)).to.be.an.instanceof(type);
+ });
- const specialElemType = {
- 'MaterialX': mx.Document,
- 'Comment': mx.CommentElement,
- 'Generic': mx.GenericElement,
- };
+ const specialElemType = {
+ 'MaterialX': mx.Document,
+ 'Comment': mx.CommentElement,
+ 'Generic': mx.GenericElement,
+ };
- Object.keys(specialElemType).forEach((typeName) => {
- const specializedFn = `addChild${typeName}`;
- const factoryName = typeName.toLowerCase();
- expect(doc[specializedFn]()).to.be.an.instanceof(specialElemType[typeName]);
- expect(doc.addChildOfCategory(factoryName)).to.be.an.instanceof(specialElemType[typeName]);
+ Object.keys(specialElemType).forEach((typeName) =>
+ {
+ const specializedFn = `addChild${typeName}`;
+ const factoryName = typeName.toLowerCase();
+ expect(doc[specializedFn]()).to.be.an.instanceof(specialElemType[typeName]);
+ expect(doc.addChildOfCategory(factoryName)).to.be.an.instanceof(specialElemType[typeName]);
+ });
});
- });
});
diff --git a/javascript/MaterialXTest/environ.spec.js b/javascript/MaterialXTest/environ.spec.js
index 2ac71dc044..2277e0b259 100644
--- a/javascript/MaterialXTest/environ.spec.js
+++ b/javascript/MaterialXTest/environ.spec.js
@@ -1,13 +1,16 @@
import { expect } from 'chai';;
import Module from './_build/JsMaterialXCore.js';
-describe('Environ', () => {
+describe('Environ', () =>
+{
let mx;
- before(async () => {
+ before(async () =>
+ {
mx = await Module();
});
- it('Environment variables', () => {
+ it('Environment variables', () =>
+ {
expect(mx.getEnviron(mx.MATERIALX_SEARCH_PATH_ENV_VAR)).to.equal('');
mx.setEnviron(mx.MATERIALX_SEARCH_PATH_ENV_VAR, 'test');
expect(mx.getEnviron(mx.MATERIALX_SEARCH_PATH_ENV_VAR)).to.equal('test');
diff --git a/javascript/MaterialXTest/testHelpers.js b/javascript/MaterialXTest/testHelpers.js
index c434400c6a..a75c2e6144 100644
--- a/javascript/MaterialXTest/testHelpers.js
+++ b/javascript/MaterialXTest/testHelpers.js
@@ -1,9 +1,11 @@
var fs = require('fs');
var path = require('path');
-export function getMtlxStrings(fileNames, subPath) {
+export function getMtlxStrings(fileNames, subPath)
+{
const mtlxStrs = [];
- for (let i = 0; i < fileNames.length; i++) {
+ for (let i = 0; i < fileNames.length; i++)
+ {
const p = path.resolve(subPath, fileNames[parseInt(i, 10)]);
const t = fs.readFileSync(p, 'utf8');
mtlxStrs.push(t);
diff --git a/javascript/MaterialXTest/traversal.spec.js b/javascript/MaterialXTest/traversal.spec.js
index 4f422bb5cc..62a895f852 100644
--- a/javascript/MaterialXTest/traversal.spec.js
+++ b/javascript/MaterialXTest/traversal.spec.js
@@ -1,13 +1,16 @@
import { expect } from 'chai';
import Module from './_build/JsMaterialXCore.js';
-describe('Traversal', () => {
+describe('Traversal', () =>
+{
let mx;
- before(async () => {
+ before(async () =>
+ {
mx = await Module();
});
- it('Traverse Graph', () => {
+ it('Traverse Graph', () =>
+ {
// Create a document.
const doc = mx.createDocument();
// Create a node graph with the following structure:
@@ -36,67 +39,79 @@ describe('Traversal', () => {
mix.setConnectedNode('bg', contrast);
mix.setConnectedNode('mask', noise3d);
output.setConnectedNode(mix);
-
+
expect(doc.validate()).to.be.true;
-
+
// Traverse the document tree (implicit iterator).
let nodeCount = 0;
- for (let elem of doc.traverseTree()) {
- if (elem instanceof mx.Node) {
+ for (let elem of doc.traverseTree())
+ {
+ if (elem instanceof mx.Node)
+ {
nodeCount++;
}
}
expect(nodeCount).to.equal(7);
-
+
// Traverse the document tree (explicit iterator)
let treeIter = doc.traverseTree();
nodeCount = 0;
let maxElementDepth = 0;
- for (let elem of treeIter) {
- if (elem instanceof mx.Node) {
+ for (let elem of treeIter)
+ {
+ if (elem instanceof mx.Node)
+ {
nodeCount++;
}
maxElementDepth = Math.max(maxElementDepth, treeIter.getElementDepth());
}
expect(nodeCount).to.equal(7);
expect(maxElementDepth).to.equal(3);
-
+
// Traverse the document tree (prune subtree).
nodeCount = 0;
treeIter = doc.traverseTree();
- for (let elem of treeIter) {
- if (elem instanceof mx.Node) {
+ for (let elem of treeIter)
+ {
+ if (elem instanceof mx.Node)
+ {
nodeCount++;
}
- if (elem instanceof mx.NodeGraph) {
+ if (elem instanceof mx.NodeGraph)
+ {
treeIter.setPruneSubtree(true);
}
}
expect(nodeCount).to.equal(0);
-
+
// Traverse upstream from the graph output (implicit iterator)
nodeCount = 0;
- for (let edge of output.traverseGraph()) {
+ for (let edge of output.traverseGraph())
+ {
const upstreamElem = edge.getUpstreamElement();
const connectingElem = edge.getConnectingElement();
const downstreamElem = edge.getDownstreamElement();
- if (upstreamElem instanceof mx.Node) {
+ if (upstreamElem instanceof mx.Node)
+ {
nodeCount++;
- if (downstreamElem instanceof mx.Node) {
+ if (downstreamElem instanceof mx.Node)
+ {
expect(connectingElem instanceof mx.Input).to.be.true;
}
}
}
expect(nodeCount).to.equal(7);
-
+
// Traverse upstream from the graph output (explicit iterator)
nodeCount = 0;
maxElementDepth = 0;
let maxNodeDepth = 0;
let graphIter = output.traverseGraph();
- for (let edge of graphIter) {
+ for (let edge of graphIter)
+ {
const upstreamElem = edge.getUpstreamElement();
- if (upstreamElem instanceof mx.Node) {
+ if (upstreamElem instanceof mx.Node)
+ {
nodeCount++;
}
maxElementDepth = Math.max(maxElementDepth, graphIter.getElementDepth());
@@ -105,22 +120,25 @@ describe('Traversal', () => {
expect(nodeCount).to.equal(7);
expect(maxElementDepth).to.equal(3);
expect(maxNodeDepth).to.equal(3);
-
+
// Traverse upstream from the graph output (prune subgraph)
nodeCount = 0;
graphIter = output.traverseGraph();
- for (let edge of graphIter) {
+ for (let edge of graphIter)
+ {
const upstreamElem = edge.getUpstreamElement();
expect(upstreamElem.getSelf()).to.be.an.instanceof(mx.Element);
- if (upstreamElem instanceof mx.Node) {
+ if (upstreamElem instanceof mx.Node)
+ {
nodeCount++;
}
- if (upstreamElem.getCategory() === 'multiply') {
+ if (upstreamElem.getCategory() === 'multiply')
+ {
graphIter.setPruneSubgraph(true);
}
}
expect(nodeCount).to.equal(5);
-
+
// Create and detect a cycle
multiply.setConnectedNode('in2', mix);
expect(output.hasUpstreamCycle()).to.be.true;
@@ -128,7 +146,7 @@ describe('Traversal', () => {
multiply.setConnectedNode('in2', constant);
expect(output.hasUpstreamCycle()).to.be.false;
expect(doc.validate()).to.be.true;
-
+
// Create and detect a loop
contrast.setConnectedNode('in', contrast);
expect(output.hasUpstreamCycle()).to.be.true;
@@ -137,10 +155,12 @@ describe('Traversal', () => {
expect(output.hasUpstreamCycle()).to.be.false;
expect(doc.validate()).to.be.true;
});
-
- describe("Traverse inheritance", () => {
+
+ describe("Traverse inheritance", () =>
+ {
let nodeDefInheritanceLevel2, nodeDefInheritanceLevel1, nodeDefParent;
- beforeEach(() => {
+ beforeEach(() =>
+ {
const doc = mx.createDocument();
nodeDefParent = doc.addNodeDef();
nodeDefParent.setName('BaseClass');
@@ -152,23 +172,29 @@ describe('Traversal', () => {
nodeDefInheritanceLevel1.setInheritsFrom(nodeDefParent);
});
- it('for of loop', () => {
+ it('for of loop', () =>
+ {
const inheritanceIterator = nodeDefInheritanceLevel2.traverseInheritance();
let inheritanceChainLength = 0;
- for(const elem of inheritanceIterator) {
- if (elem instanceof mx.NodeDef) {
+ for (const elem of inheritanceIterator)
+ {
+ if (elem instanceof mx.NodeDef)
+ {
inheritanceChainLength++;
}
}
expect(inheritanceChainLength).to.equal(2);;
});
- it('while loop', () => {
+ it('while loop', () =>
+ {
const inheritanceIterator = nodeDefInheritanceLevel2.traverseInheritance();
let inheritanceChainLength = 0;
let elem = inheritanceIterator.next();
- while (!elem.done) {
- if (elem.value instanceof mx.NodeDef) {
+ while (!elem.done)
+ {
+ if (elem.value instanceof mx.NodeDef)
+ {
inheritanceChainLength++;
}
elem = inheritanceIterator.next();
diff --git a/javascript/MaterialXTest/types.spec.js b/javascript/MaterialXTest/types.spec.js
index 7fae8b30c7..fc909c8c94 100644
--- a/javascript/MaterialXTest/types.spec.js
+++ b/javascript/MaterialXTest/types.spec.js
@@ -1,13 +1,16 @@
import { expect } from 'chai';;
import Module from './_build/JsMaterialXCore.js';
-describe('Types', () => {
+describe('Types', () =>
+{
let mx;
- before(async () => {
+ before(async () =>
+ {
mx = await Module();
});
- it('Vectors', () => {
+ it('Vectors', () =>
+ {
const v1 = new mx.Vector3(1, 2, 3);
let v2 = new mx.Vector3(2, 4, 6);
@@ -59,10 +62,13 @@ describe('Types', () => {
expect(v4.notEquals(v2)).to.be.true;
});
- function multiplyMatrix(matrix, val) {
+ function multiplyMatrix(matrix, val)
+ {
const clonedMatrix = matrix.copy();
- for (let i = 0; i < clonedMatrix.numRows(); ++i) {
- for (let k = 0; k < clonedMatrix.numColumns(); ++k) {
+ for (let i = 0; i < clonedMatrix.numRows(); ++i)
+ {
+ for (let k = 0; k < clonedMatrix.numColumns(); ++k)
+ {
const v = clonedMatrix.getItem(i, k);
clonedMatrix.setItem(i, k, v * val);
}
@@ -70,10 +76,13 @@ describe('Types', () => {
return clonedMatrix;
}
- function divideMatrix(matrix, val) {
+ function divideMatrix(matrix, val)
+ {
const clonedMatrix = matrix.copy();
- for (let i = 0; i < clonedMatrix.numRows(); ++i) {
- for (let k = 0; k < clonedMatrix.numColumns(); ++k) {
+ for (let i = 0; i < clonedMatrix.numRows(); ++i)
+ {
+ for (let k = 0; k < clonedMatrix.numColumns(); ++k)
+ {
const v = clonedMatrix.getItem(i, k);
clonedMatrix.setItem(i, k, v / val);
}
@@ -81,18 +90,19 @@ describe('Types', () => {
return clonedMatrix;
}
- it('Matrices', () => {
+ it('Matrices', () =>
+ {
// Translation and scale
const trans = mx.Matrix44.createTranslation(new mx.Vector3(1, 2, 3));
const scale = mx.Matrix44.createScale(new mx.Vector3(2, 2, 2));
expect(trans.equals(new mx.Matrix44(1, 0, 0, 0,
- 0, 1, 0, 0,
- 0, 0, 1, 0,
- 1, 2, 3, 1)));
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ 1, 2, 3, 1)));
expect(scale.equals(new mx.Matrix44(2, 0, 0, 0,
- 0, 2, 0, 0,
- 0, 0, 2, 0,
- 0, 0, 0, 1)));
+ 0, 2, 0, 0,
+ 0, 0, 2, 0,
+ 0, 0, 0, 1)));
// Indexing operators
expect(trans.getItem(3, 2)).to.equal(3);
@@ -103,9 +113,9 @@ describe('Types', () => {
// Matrix methods
expect(trans.getTranspose().equals(
new mx.Matrix44(1, 0, 0, 1,
- 0, 1, 0, 2,
- 0, 0, 1, 3,
- 0, 0, 0, 1)
+ 0, 1, 0, 2,
+ 0, 0, 1, 3,
+ 0, 0, 0, 1)
)).to.be.true;
expect(scale.getTranspose().equals(scale)).to.be.true;
expect(trans.getDeterminant()).to.equal(1);
@@ -120,17 +130,17 @@ describe('Types', () => {
let prod4 = trans;
prod4 = prod4.multiply(scale);
expect(prod1.equals(new mx.Matrix44(2, 0, 0, 0,
- 0, 2, 0, 0,
- 0, 0, 2, 0,
- 2, 4, 6, 1)));
+ 0, 2, 0, 0,
+ 0, 0, 2, 0,
+ 2, 4, 6, 1)));
expect(prod2.equals(new mx.Matrix44(2, 0, 0, 0,
- 0, 2, 0, 0,
- 0, 0, 2, 0,
- 1, 2, 3, 1)));
+ 0, 2, 0, 0,
+ 0, 0, 2, 0,
+ 1, 2, 3, 1)));
expect(prod3.equals(new mx.Matrix44(2, 0, 0, 0,
- 0, 2, 0, 0,
- 0, 0, 2, 0,
- 2, 4, 6, 2)));
+ 0, 2, 0, 0,
+ 0, 0, 2, 0,
+ 2, 4, 6, 2)));
expect(prod4.equals(prod1));
// Matrix division
diff --git a/javascript/MaterialXTest/value.spec.js b/javascript/MaterialXTest/value.spec.js
index 1b06d3f59b..6a9091ce47 100644
--- a/javascript/MaterialXTest/value.spec.js
+++ b/javascript/MaterialXTest/value.spec.js
@@ -1,13 +1,16 @@
import { expect } from 'chai';;
import Module from './_build/JsMaterialXCore.js';
-describe('Value', () => {
+describe('Value', () =>
+{
let mx;
- before(async () => {
+ before(async () =>
+ {
mx = await Module();
});
- it('Create values of different types', () => {
+ it('Create values of different types', () =>
+ {
const testValues = {
integer: '1',
boolean: 'true',
@@ -26,7 +29,8 @@ describe('Value', () => {
stringarray: "'one', 'two', 'three'",
};
- for (let type in testValues) {
+ for (let type in testValues)
+ {
const value = testValues[String(type)];
const newValue = mx.Value.createValueFromStrings(value, type);
const typeString = newValue.getTypeString();
diff --git a/javascript/MaterialXTest/xmlIo.spec.js b/javascript/MaterialXTest/xmlIo.spec.js
index e569b9be76..670b0df43d 100644
--- a/javascript/MaterialXTest/xmlIo.spec.js
+++ b/javascript/MaterialXTest/xmlIo.spec.js
@@ -4,7 +4,8 @@ import { getMtlxStrings } from './testHelpers';
const TIMEOUT = 60000;
-describe('XmlIo', () => {
+describe('XmlIo', () =>
+{
let mx;
// These should be relative to cwd
@@ -24,18 +25,23 @@ describe('XmlIo', () => {
'UsdPreviewSurface/usd_preview_surface_plastic.mtlx',
];
- async function readStdLibrary(asString = false) {
+ async function readStdLibrary(asString = false)
+ {
const libs = [];
let iterable = libraryFilenames;
- if (asString) {
+ if (asString)
+ {
const libraryMtlxStrings = getMtlxStrings(libraryFilenames, libraryPath);
iterable = libraryMtlxStrings;
}
- for (let file of iterable) {
+ for (let file of iterable)
+ {
const lib = mx.createDocument();
- if (asString) {
+ if (asString)
+ {
await mx.readFromXmlString(lib, file, libraryPath);
- } else {
+ } else
+ {
await mx.readFromXmlFile(lib, file, libraryPath);
}
libs.push(lib);
@@ -43,12 +49,15 @@ describe('XmlIo', () => {
return libs;
}
- async function readAndValidateExamples(examples, libraries, readFunc, searchPath = undefined) {
- for (let file of examples) {
+ async function readAndValidateExamples(examples, libraries, readFunc, searchPath = undefined)
+ {
+ for (let file of examples)
+ {
const doc = mx.createDocument();
await readFunc(doc, file, searchPath);
// Import stdlib into the current document and validate it.
- for (let lib of libraries) {
+ for (let lib of libraries)
+ {
doc.importLibrary(lib);
}
expect(doc.validate()).to.be.true;
@@ -56,8 +65,10 @@ describe('XmlIo', () => {
// Make sure the document does actually contain something.
let valueElementCount = 0;
const treeIter = doc.traverseTree();
- for(const elem of treeIter) {
- if (elem instanceof mx.ValueElement) {
+ for (const elem of treeIter)
+ {
+ if (elem instanceof mx.ValueElement)
+ {
valueElementCount++;
}
}
@@ -65,17 +76,20 @@ describe('XmlIo', () => {
};
}
- before(async () => {
+ before(async () =>
+ {
mx = await Module();
});
- it('Read XML from file', async () => {
+ it('Read XML from file', async () =>
+ {
// Read the standard library
const libs = await readStdLibrary(false);
// Read and validate the example documents.
await readAndValidateExamples(exampleFilenames, libs,
- async (document, file, sp) => {
+ async (document, file, sp) =>
+ {
await mx.readFromXmlFile(document, file, sp);
}, examplesPath);
@@ -90,14 +104,16 @@ describe('XmlIo', () => {
expect(copy.equals(doc)).to.be.true;
}).timeout(TIMEOUT);
- it('Read XML from string', async () => {
+ it('Read XML from string', async () =>
+ {
// Read the standard library
const libs = await readStdLibrary(true);
// Read and validate each example document.
const examplesStrings = getMtlxStrings(exampleFilenames, examplesPath);
await readAndValidateExamples(examplesStrings, libs,
- async (document, file) => {
+ async (document, file) =>
+ {
await mx.readFromXmlString(document, file);
});
@@ -112,14 +128,16 @@ describe('XmlIo', () => {
expect(copy.equals(doc)).to.be.true;
}).timeout(TIMEOUT);
- it('Read XML with recursive includes', async () => {
+ it('Read XML with recursive includes', async () =>
+ {
const doc = mx.createDocument();
await mx.readFromXmlFile(doc, includeTestPath + '/root.mtlx');
expect(doc.getChild('paint_semigloss')).to.exist;
expect(doc.validate()).to.be.true;
});
- it('Locate XML includes via search path', async () => {
+ it('Locate XML includes via search path', async () =>
+ {
const searchPath = includeTestPath + ';' + includeTestPath + '/folder';
const filename = 'non_relative_includes.mtlx';
const doc = mx.createDocument();
@@ -137,7 +155,8 @@ describe('XmlIo', () => {
expect(doc2.equals(doc)).to.be.true;
});
- it('Locate XML includes via environment variable', async () => {
+ it('Locate XML includes via environment variable', async () =>
+ {
const searchPath = includeTestPath + ';' + includeTestPath + '/folder';
const filename = 'non_relative_includes.mtlx';
@@ -160,13 +179,16 @@ describe('XmlIo', () => {
expect(doc2.equals(doc)).to.be.true;
});
- it('Locate XML includes via absolute search paths', async () => {
+ it('Locate XML includes via absolute search paths', async () =>
+ {
let absolutePath;
- if (typeof window === 'object') {
+ if (typeof window === 'object')
+ {
// We're in the browser
const cwd = window.location.origin + window.location.pathname;
absolutePath = cwd + '/' + includeTestPath;
- } else if (typeof process === 'object') {
+ } else if (typeof process === 'object')
+ {
// We're in Node
const nodePath = require('path');
absolutePath = nodePath.resolve(includeTestPath);
@@ -175,22 +197,26 @@ describe('XmlIo', () => {
await mx.readFromXmlFile(doc, 'root.mtlx', absolutePath);
});
- it('Detect XML include cycles', async () => {
+ it('Detect XML include cycles', async () =>
+ {
const doc = mx.createDocument();
expect(async () => await mx.readFromXmlFile(doc, includeTestPath + '/cycle.mtlx')).to.throw;
});
- it('Disabling XML includes', async () => {
+ it('Disabling XML includes', async () =>
+ {
const doc = mx.createDocument();
const readOptions = new mx.XmlReadOptions();
readOptions.readXIncludes = false;
expect(async () => await mx.readFromXmlFile(doc, includeTestPath + '/cycle.mtlx', readOptions)).to.not.throw;
});
- it('Write to XML string', async () => {
+ it('Write to XML string', async () =>
+ {
// Read all example documents and write them to an XML string
const searchPath = libraryPath + ';' + examplesPath;
- for (let filename of exampleFilenames) {
+ for (let filename of exampleFilenames)
+ {
const doc = mx.createDocument();
await mx.readFromXmlFile(doc, filename, searchPath);
@@ -206,7 +232,8 @@ describe('XmlIo', () => {
};
});
- it('Prepend include tag', () => {
+ it('Prepend include tag', () =>
+ {
const doc = mx.createDocument();
const includePath = "SomePath";
const writeOptions = new mx.XmlWriteOptions();
@@ -216,7 +243,8 @@ describe('XmlIo', () => {
});
// Node only, because we cannot read from a downloaded file in the browser
- it('Write XML to file', async () => {
+ it('Write XML to file', async () =>
+ {
const filename = '_build/testFile.mtlx';
const includeRegex = //g;
const doc = mx.createDocument();
diff --git a/javascript/MaterialXView/source/dropHandling.js b/javascript/MaterialXView/source/dropHandling.js
index 8e4b674e0e..f54b77115c 100644
--- a/javascript/MaterialXView/source/dropHandling.js
+++ b/javascript/MaterialXView/source/dropHandling.js
@@ -5,7 +5,8 @@ const debugFileHandling = false;
let loadingCallback = null;
let sceneLoadingCallback = null;
-export function setLoadingCallback(cb) {
+export function setLoadingCallback(cb)
+{
loadingCallback = cb;
}
@@ -14,7 +15,8 @@ export function setSceneLoadingCallback(cb)
sceneLoadingCallback = cb;
}
-export function dropHandler(ev) {
+export function dropHandler(ev)
+{
if (debugFileHandling) console.log('File(s) dropped', ev.dataTransfer.items, ev.dataTransfer.files);
// Prevent default behavior (Prevent file from being opened)
@@ -26,14 +28,15 @@ export function dropHandler(ev) {
let haveGetAsEntry = false;
if (ev.dataTransfer.items.length > 0)
- haveGetAsEntry =
- ("getAsEntry" in ev.dataTransfer.items[0]) ||
- ("webkitGetAsEntry" in ev.dataTransfer.items[0]);
+ haveGetAsEntry =
+ ("getAsEntry" in ev.dataTransfer.items[0]) ||
+ ("webkitGetAsEntry" in ev.dataTransfer.items[0]);
// Useful for debugging file handling on platforms that don't support newer file system APIs
// haveGetAsEntry = false;
- if (haveGetAsEntry) {
+ if (haveGetAsEntry)
+ {
for (var i = 0; i < ev.dataTransfer.items.length; i++)
{
let item = ev.dataTransfer.items[i];
@@ -47,7 +50,7 @@ export function dropHandler(ev) {
for (var i = 0; i < ev.dataTransfer.items.length; i++)
{
let item = ev.dataTransfer.items[i];
-
+
// API when there's no "getAsEntry" support
console.log(item.kind, item);
if (item.kind === 'file')
@@ -59,32 +62,40 @@ export function dropHandler(ev) {
else if (item.kind === 'directory')
{
var dirReader = item.createReader();
- dirReader.readEntries(function(entries) {
- for (var i = 0; i < entries.length; i++) {
- console.log(entries[i].name);
- var entry = entries[i];
- if (entry.isFile) {
- entry.file(function(file) {
- testAndLoadFile(file);
- });
+ dirReader.readEntries(function (entries)
+ {
+ for (var i = 0; i < entries.length; i++)
+ {
+ console.log(entries[i].name);
+ var entry = entries[i];
+ if (entry.isFile)
+ {
+ entry.file(function (file)
+ {
+ testAndLoadFile(file);
+ });
+ }
}
- }
});
}
}
- } else {
- for (var i = 0; i < ev.dataTransfer.files.length; i++) {
+ } else
+ {
+ for (var i = 0; i < ev.dataTransfer.files.length; i++)
+ {
let file = ev.dataTransfer.files[i];
testAndLoadFile(file);
}
}
}
-export function dragOverHandler(ev) {
+export function dragOverHandler(ev)
+{
ev.preventDefault();
}
-async function getBufferFromFile(fileEntry) {
+async function getBufferFromFile(fileEntry)
+{
if (fileEntry instanceof ArrayBuffer) return fileEntry;
if (fileEntry instanceof String) return fileEntry;
@@ -96,98 +107,120 @@ async function getBufferFromFile(fileEntry) {
if (debugFileHandling) console.log("reading ", fileEntry, "as text?", readAsText);
if (debugFileHandling) console.log("getBufferFromFile", fileEntry);
- const buffer = await new Promise((resolve, reject) => {
- function readFile(file) {
+ const buffer = await new Promise((resolve, reject) =>
+ {
+ function readFile(file)
+ {
var reader = new FileReader();
- reader.onloadend = function(e) {
+ reader.onloadend = function (e)
+ {
if (debugFileHandling) console.log("loaded", "should be text?", readAsText, this.result);
resolve(this.result);
};
-
+
if (readAsText)
reader.readAsText(file);
else
reader.readAsArrayBuffer(file);
}
- if ("file" in fileEntry) {
- fileEntry.file(function(file) {
+ if ("file" in fileEntry)
+ {
+ fileEntry.file(function (file)
+ {
readFile(file);
- }, (e) => {
+ }, (e) =>
+ {
console.error("Error reading file ", e);
});
}
- else {
+ else
+ {
readFile(fileEntry);
}
});
return buffer;
}
-async function handleFilesystemEntries(entries) {
+async function handleFilesystemEntries(entries)
+{
const allFiles = [];
const fileIgnoreList = [
- '.gitignore',
- 'README.md',
- '.DS_Store',
+ '.gitignore',
+ 'README.md',
+ '.DS_Store',
]
const dirIgnoreList = [
- '.git',
- 'node_modules',
+ '.git',
+ 'node_modules',
]
let isGLB = false;
let haveMtlx = false;
- for (let entry of entries) {
- if (debugFileHandling) console.log("file entry", entry)
- if (entry.isFile) {
- if (debugFileHandling)
- console.log("single file", entry);
- if (fileIgnoreList.includes(entry.name)) {
- continue;
- }
- allFiles.push(entry);
-
- if (entry.name.endsWith('glb')) {
- isGLB = true;
- break;
- }
- }
- else if (entry.isDirectory) {
- if (dirIgnoreList.includes(entry.name)) {
- continue;
+ for (let entry of entries)
+ {
+ if (debugFileHandling) console.log("file entry", entry)
+ if (entry.isFile)
+ {
+ if (debugFileHandling)
+ console.log("single file", entry);
+ if (fileIgnoreList.includes(entry.name))
+ {
+ continue;
+ }
+ allFiles.push(entry);
+
+ if (entry.name.endsWith('glb'))
+ {
+ isGLB = true;
+ break;
+ }
}
- const files = await readDirectory(entry);
- if (debugFileHandling) console.log("all files", files);
- for (const file of files) {
- if (fileIgnoreList.includes(file.name)) {
- continue;
- }
- allFiles.push(file);
+ else if (entry.isDirectory)
+ {
+ if (dirIgnoreList.includes(entry.name))
+ {
+ continue;
+ }
+ const files = await readDirectory(entry);
+ if (debugFileHandling) console.log("all files", files);
+ for (const file of files)
+ {
+ if (fileIgnoreList.includes(file.name))
+ {
+ continue;
+ }
+ allFiles.push(file);
+ }
}
- }
}
const imageLoader = new THREE.ImageLoader();
// unpack zip files first
- for (const fileEntry of allFiles) {
+ for (const fileEntry of allFiles)
+ {
// special case: zip archives
- if (fileEntry.fullPath.toLowerCase().endsWith('.zip')) {
- await new Promise(async (resolve, reject) => {
+ if (fileEntry.fullPath.toLowerCase().endsWith('.zip'))
+ {
+ await new Promise(async (resolve, reject) =>
+ {
const arrayBuffer = await getBufferFromFile(fileEntry);
// use fflate to unpack them and add the files to the cache
- fflate.unzip(new Uint8Array(arrayBuffer), (error, unzipped) => {
+ fflate.unzip(new Uint8Array(arrayBuffer), (error, unzipped) =>
+ {
// push these files into allFiles
- for (const [filePath, buffer] of Object.entries(unzipped)) {
+ for (const [filePath, buffer] of Object.entries(unzipped))
+ {
// mock FileEntry for easier usage downstream
const blob = new Blob([buffer]);
const newFileEntry = {
fullPath: "/" + filePath,
name: filePath.split('/').pop(),
- file: (callback) => {
+ file: (callback) =>
+ {
callback(blob);
},
isFile: true,
@@ -202,11 +235,14 @@ async function handleFilesystemEntries(entries) {
}
// sort so mtlx files come first
- allFiles.sort((a, b) => {
- if (a.name.endsWith('.mtlx') && !b.name.endsWith('.mtlx')) {
+ allFiles.sort((a, b) =>
+ {
+ if (a.name.endsWith('.mtlx') && !b.name.endsWith('.mtlx'))
+ {
return -1;
}
- if (!a.name.endsWith('.mtlx') && b.name.endsWith('.mtlx')) {
+ if (!a.name.endsWith('.mtlx') && b.name.endsWith('.mtlx'))
+ {
return 1;
}
return 0;
@@ -231,19 +267,22 @@ async function handleFilesystemEntries(entries) {
return;
}
- if (debugFileHandling) {
+ if (debugFileHandling)
+ {
console.log("- All files", allFiles);
}
// put all files in three' Cache
- for (const fileEntry of allFiles) {
+ for (const fileEntry of allFiles)
+ {
const allowedFileTypes = [
'png', 'jpg', 'jpeg'
];
const ext = fileEntry.fullPath.split('.').pop();
- if (!allowedFileTypes.includes(ext)) {
+ if (!allowedFileTypes.includes(ext))
+ {
// console.log("skipping file", fileEntry.fullPath);
continue;
}
@@ -272,37 +311,49 @@ async function handleFilesystemEntries(entries) {
}
}
-async function readDirectory(directory) {
+async function readDirectory(directory)
+{
let entries = [];
- let getEntries = async (directory) => {
+ let getEntries = async (directory) =>
+ {
let dirReader = directory.createReader();
- await new Promise((resolve, reject) => {
- dirReader.readEntries(
- async (results) => {
- if (results.length) {
- // entries = entries.concat(results);
- for (let entry of results) {
- if (entry.isDirectory) {
- await getEntries(entry);
- }
- else {
- entries.push(entry);
- }
- }
- }
- resolve();
- },
- (error) => {
- /* handle error — error is a FileError object */
- },
- )}
- )};
+ await new Promise((resolve, reject) =>
+ {
+ dirReader.readEntries(
+ async (results) =>
+ {
+ if (results.length)
+ {
+ // entries = entries.concat(results);
+ for (let entry of results)
+ {
+ if (entry.isDirectory)
+ {
+ await getEntries(entry);
+ }
+ else
+ {
+ entries.push(entry);
+ }
+ }
+ }
+ resolve();
+ },
+ (error) =>
+ {
+ /* handle error — error is a FileError object */
+ },
+ )
+ }
+ )
+ };
await getEntries(directory);
return entries;
}
-async function testAndLoadFile(file) {
+async function testAndLoadFile(file)
+{
let ext = file.name.split('.').pop();
if (debugFileHandling) console.log(file.name + ", " + file.size + ", " + ext);
@@ -314,7 +365,8 @@ async function testAndLoadFile(file) {
fullPath: "/" + file.name,
name: file.name.split('/').pop(),
isFile: true,
- file: (callback) => {
+ file: (callback) =>
+ {
callback(file);
}
};
diff --git a/javascript/MaterialXView/source/helper.js b/javascript/MaterialXView/source/helper.js
index 98441a605f..2b7f0f7d5b 100644
--- a/javascript/MaterialXView/source/helper.js
+++ b/javascript/MaterialXView/source/helper.js
@@ -45,8 +45,8 @@ function fromVector(value, dimension)
}
else
{
- outValue = [];
- for(let i = 0; i < dimension; ++i)
+ outValue = [];
+ for (let i = 0; i < dimension; ++i)
outValue.push(0.0);
}
@@ -69,13 +69,13 @@ function fromMatrix(matrix, dimension)
{
vec.push(matrix.getItem(i, k));
}
- }
+ }
} else
{
for (let i = 0; i < dimension; ++i)
vec.push(0.0);
}
-
+
return vec;
}
@@ -89,7 +89,7 @@ function fromMatrix(matrix, dimension)
*/
function toThreeUniform(type, value, name, uniforms, textureLoader, searchPath, flipY)
{
- let outValue;
+ let outValue;
switch (type)
{
case 'float':
@@ -97,7 +97,7 @@ function toThreeUniform(type, value, name, uniforms, textureLoader, searchPath,
case 'boolean':
outValue = value;
break;
- case 'vector2':
+ case 'vector2':
outValue = fromVector(value, 2);
break;
case 'vector3':
@@ -123,11 +123,11 @@ function toThreeUniform(type, value, name, uniforms, textureLoader, searchPath,
if (texture)
setTextureParameters(texture, name, uniforms, flipY);
outValue = texture;
- }
+ }
break;
case 'samplerCube':
case 'string':
- break;
+ break;
default:
// struct
outValue = toThreeUniform(value);
@@ -184,33 +184,33 @@ function getMinFilter(type, generateMipmaps)
* @param {mx.Uniforms} uniforms
* @param {mx.TextureFilter.generateMipmaps} generateMipmaps
*/
- function setTextureParameters(texture, name, uniforms, flipY = true, generateMipmaps = true)
- {
- const idx = name.lastIndexOf(IMAGE_PROPERTY_SEPARATOR);
- const base = name.substring(0, idx) || name;
-
- texture.generateMipmaps = generateMipmaps;
- texture.wrapS = THREE.RepeatWrapping;
- texture.wrapT = THREE.RepeatWrapping;
- texture.magFilter = THREE.LinearFilter;
- texture.flipY = flipY;
-
- if (uniforms.find(base + UADDRESS_MODE_SUFFIX))
- {
- const uaddressmode = uniforms.find(base + UADDRESS_MODE_SUFFIX).getValue().getData();
- texture.wrapS = getWrapping(uaddressmode);
- }
-
- if (uniforms.find(base + VADDRESS_MODE_SUFFIX))
- {
- const vaddressmode = uniforms.find(base + VADDRESS_MODE_SUFFIX).getValue().getData();
- texture.wrapT = getWrapping(vaddressmode);
- }
-
- const filterType = uniforms.find(base + FILTER_TYPE_SUFFIX) ? uniforms.get(base + FILTER_TYPE_SUFFIX).value : -1;
- texture.minFilter = getMinFilter(filterType, generateMipmaps);
- }
-
+function setTextureParameters(texture, name, uniforms, flipY = true, generateMipmaps = true)
+{
+ const idx = name.lastIndexOf(IMAGE_PROPERTY_SEPARATOR);
+ const base = name.substring(0, idx) || name;
+
+ texture.generateMipmaps = generateMipmaps;
+ texture.wrapS = THREE.RepeatWrapping;
+ texture.wrapT = THREE.RepeatWrapping;
+ texture.magFilter = THREE.LinearFilter;
+ texture.flipY = flipY;
+
+ if (uniforms.find(base + UADDRESS_MODE_SUFFIX))
+ {
+ const uaddressmode = uniforms.find(base + UADDRESS_MODE_SUFFIX).getValue().getData();
+ texture.wrapS = getWrapping(uaddressmode);
+ }
+
+ if (uniforms.find(base + VADDRESS_MODE_SUFFIX))
+ {
+ const vaddressmode = uniforms.find(base + VADDRESS_MODE_SUFFIX).getValue().getData();
+ texture.wrapT = getWrapping(vaddressmode);
+ }
+
+ const filterType = uniforms.find(base + FILTER_TYPE_SUFFIX) ? uniforms.get(base + FILTER_TYPE_SUFFIX).value : -1;
+ texture.minFilter = getMinFilter(filterType, generateMipmaps);
+}
+
/**
* Return the global light rotation matrix
*/
@@ -269,7 +269,7 @@ export function registerLights(mx, lights, genContext)
lightData.push({
type: lightTypesBound[nodeName],
direction: rotatedLightDirection,
- color: new THREE.Vector3(...lightColor),
+ color: new THREE.Vector3(...lightColor),
intensity: lightIntensity
});
}
@@ -290,16 +290,17 @@ export function getUniformValues(shaderStage, textureLoader, searchPath, flipY)
let threeUniforms = {};
const uniformBlocks = Object.values(shaderStage.getUniformBlocks());
- uniformBlocks.forEach(uniforms => {
+ uniformBlocks.forEach(uniforms =>
+ {
if (!uniforms.empty())
{
for (let i = 0; i < uniforms.size(); ++i)
{
- const variable = uniforms.get(i);
+ const variable = uniforms.get(i);
const value = variable.getValue()?.getData();
const name = variable.getVariable();
- threeUniforms[name] = new THREE.Uniform(toThreeUniform(variable.getType().getName(), value, name, uniforms,
- textureLoader, searchPath, flipY));
+ threeUniforms[name] = new THREE.Uniform(toThreeUniform(variable.getType().getName(), value, name, uniforms,
+ textureLoader, searchPath, flipY));
}
}
});
diff --git a/javascript/MaterialXView/source/index.js b/javascript/MaterialXView/source/index.js
index bffae2db8d..026653ca60 100644
--- a/javascript/MaterialXView/source/index.js
+++ b/javascript/MaterialXView/source/index.js
@@ -25,7 +25,8 @@ let captureRequested = false;
// Get URL options. Fallback to defaults if not specified.
let materialFilename = new URLSearchParams(document.location.search).get("file");
-if (!materialFilename) {
+if (!materialFilename)
+{
materialFilename = 'Materials/Examples/StandardSurface/standard_surface_default.mtlx';
}
@@ -37,7 +38,7 @@ viewer.getEditor().updateProperties(0.9);
function captureFrame()
{
let canvas = document.getElementById('webglcanvas');
- var url = canvas.toDataURL();
+ var url = canvas.toDataURL();
var link = document.createElement('a');
link.setAttribute('href', url);
link.setAttribute('target', '_blank');
@@ -45,7 +46,7 @@ function captureFrame()
link.click();
}
-function init()
+function init()
{
let canvas = document.getElementById('webglcanvas');
let context = canvas.getContext('webgl2');
@@ -53,7 +54,8 @@ function init()
// Handle material selection changes
let materialsSelect = document.getElementById('materials');
materialsSelect.value = materialFilename;
- materialsSelect.addEventListener('change', (e) => {
+ materialsSelect.addEventListener('change', (e) =>
+ {
materialFilename = e.target.value;
viewer.getEditor().initialize();
viewer.getMaterial().loadMaterials(viewer, materialFilename);
@@ -65,7 +67,8 @@ function init()
const scene = viewer.getScene();
let geometrySelect = document.getElementById('geometry');
geometrySelect.value = scene.getGeometryURL();
- geometrySelect.addEventListener('change', (e) => {
+ geometrySelect.addEventListener('change', (e) =>
+ {
console.log('Change geometry to:', e.target.value);
scene.setGeometryURL(e.target.value);
scene.loadGeometry(viewer, orbitControls);
@@ -95,14 +98,17 @@ function init()
// Set up controls
orbitControls = new OrbitControls(scene.getCamera(), renderer.domElement);
- orbitControls.addEventListener('change', () => {
+ orbitControls.addEventListener('change', () =>
+ {
viewer.getScene().setUpdateTransforms();
})
// Add hotkey 'f' to capture the current frame and save an image file.
// See check inside the render loop when a capture can be performed.
- document.addEventListener('keydown', (event) => {
- if (event.key === 'f') {
+ document.addEventListener('keydown', (event) =>
+ {
+ if (event.key === 'f')
+ {
captureRequested = true;
}
});
@@ -116,12 +122,14 @@ function init()
new Promise(resolve => hdrLoader.load('Lights/san_giuseppe_bridge_split.hdr', resolve)),
new Promise(resolve => hdrLoader.load('Lights/irradiance/san_giuseppe_bridge_split.hdr', resolve)),
new Promise(resolve => fileLoader.load('Lights/san_giuseppe_bridge_split.mtlx', resolve)),
- new Promise(function (resolve) {
- MaterialX().then((module) => {
+ new Promise(function (resolve)
+ {
+ MaterialX().then((module) =>
+ {
resolve(module);
});
- })
- ]).then(async ([radianceTexture, irradianceTexture, lightRigXml, mxIn]) =>
+ })
+ ]).then(async ([radianceTexture, irradianceTexture, lightRigXml, mxIn]) =>
{
// Initialize viewer + lighting
await viewer.initialize(mxIn, renderer, radianceTexture, irradianceTexture, lightRigXml);
@@ -137,10 +145,12 @@ function init()
viewer.getMaterial().updateMaterialAssignments(viewer);
canvas.addEventListener("keydown", handleKeyEvents, true);
-
- }).then(() => {
+
+ }).then(() =>
+ {
animate();
- }).catch(err => {
+ }).catch(err =>
+ {
console.error(Number.isInteger(err) ? this.getMx().getExceptionMessage(err) : err);
})
@@ -148,7 +158,8 @@ function init()
document.addEventListener('drop', dropHandler, false);
document.addEventListener('dragover', dragOverHandler, false);
- setLoadingCallback(file => {
+ setLoadingCallback(file =>
+ {
materialFilename = file.fullPath || file.name;
viewer.getEditor().initialize();
viewer.getMaterial().loadMaterials(viewer, materialFilename);
@@ -156,25 +167,26 @@ function init()
viewer.getScene().setUpdateTransforms();
});
- setSceneLoadingCallback(file => {
+ setSceneLoadingCallback(file =>
+ {
let glbFileName = file.fullPath || file.name;
console.log('Drop geometry to:', glbFileName);
scene.setGeometryURL(glbFileName);
- scene.loadGeometry(viewer, orbitControls);
+ scene.loadGeometry(viewer, orbitControls);
});
// enable three.js Cache so that dropped files can reference each other
THREE.Cache.enabled = true;
}
-function onWindowResize()
+function onWindowResize()
{
viewer.getScene().updateCamera();
- viewer.getScene().setUpdateTransforms();
+ viewer.getScene().setUpdateTransforms();
renderer.setSize(window.innerWidth, window.innerHeight);
}
-function animate()
+function animate()
{
requestAnimationFrame(animate);
@@ -182,7 +194,7 @@ function animate()
{
turntableStep = (turntableStep + 1) % 360;
var turntableAngle = turntableStep * (360.0 / turntableSteps) / 180.0 * Math.PI;
- viewer.getScene()._scene.rotation.y = turntableAngle ;
+ viewer.getScene()._scene.rotation.y = turntableAngle;
viewer.getScene().setUpdateTransforms();
}
diff --git a/javascript/MaterialXView/source/viewer.js b/javascript/MaterialXView/source/viewer.js
index 9992dd6985..06236fdac9 100644
--- a/javascript/MaterialXView/source/viewer.js
+++ b/javascript/MaterialXView/source/viewer.js
@@ -9,7 +9,7 @@ import { RGBELoader } from 'three/examples/jsm/loaders/RGBELoader.js';
import { prepareEnvTexture, getLightRotation, findLights, registerLights, getUniformValues } from './helper.js'
import { Group } from 'three';
-import GUI from 'lil-gui';
+import GUI from 'lil-gui';
const ALL_GEOMETRY_SPECIFIER = "*";
const NO_GEOMETRY_SPECIFIER = "";
@@ -21,18 +21,18 @@ var logDetailedTime = false;
/*
Scene management
*/
-export class Scene
+export class Scene
{
- constructor()
+ constructor()
{
this._geometryURL = new URLSearchParams(document.location.search).get("geom");
if (!this._geometryURL)
{
- this._geometryURL = 'Geometry/shaderball.glb';
+ this._geometryURL = 'Geometry/shaderball.glb';
}
}
- initialize()
+ initialize()
{
this._scene = new THREE.Scene();
this._scene.background = new THREE.Color(this.#_backgroundColor);
@@ -64,9 +64,10 @@ export class Scene
}
// Utility to perform geometry file load
- loadGeometryFile(geometryFilename, loader)
+ loadGeometryFile(geometryFilename, loader)
{
- return new Promise((resolve, reject) => {
+ return new Promise((resolve, reject) =>
+ {
loader.load(geometryFilename, data => resolve(data), null, reject);
});
}
@@ -82,8 +83,9 @@ export class Scene
const gltfData = await this.loadGeometryFile(this.getGeometryURL(), this.#_gltfLoader);
- const scene = this.getScene();
- while (scene.children.length > 0) {
+ const scene = this.getScene();
+ while (scene.children.length > 0)
+ {
scene.remove(scene.children[0]);
}
@@ -100,7 +102,7 @@ export class Scene
else
{
this.#_rootNode = model;
- }
+ }
scene.add(model);
console.log("- Scene load time: ", performance.now() - geomLoadTime, "ms");
@@ -123,7 +125,7 @@ export class Scene
{
var startUpdateSceneTime = performance.now();
var uvTime = 0;
- var normalTime = 0 ;
+ var normalTime = 0;
var tangentTime = 0;
var streamTime = 0;
var bboxTime = 0;
@@ -136,41 +138,47 @@ export class Scene
let theScene = viewer.getScene();
let flipV = theScene.getFlipGeometryV();
-
- this._scene.traverse((child) => {
- if (child.isMesh) {
+
+ this._scene.traverse((child) =>
+ {
+ if (child.isMesh)
+ {
var startUVTime = performance.now();
- if (!child.geometry.attributes.uv) {
+ if (!child.geometry.attributes.uv)
+ {
const posCount = child.geometry.attributes.position.count;
const uvs = [];
const pos = child.geometry.attributes.position.array;
-
- for (let i = 0; i < posCount; i++) {
+
+ for (let i = 0; i < posCount; i++)
+ {
uvs.push((pos[i * 3] - bsphere.center.x) / bsphere.radius);
uvs.push((pos[i * 3 + 1] - bsphere.center.y) / bsphere.radius);
}
-
+
child.geometry.setAttribute('uv', new THREE.BufferAttribute(new Float32Array(uvs), 2));
}
else if (flipV)
{
const uvCount = child.geometry.attributes.position.count;
const uvs = child.geometry.attributes.uv.array;
- for (let i = 0; i < uvCount; i++) {
- let v = 1.0-(uvs[i*2 +1]);
- uvs[i*2+1] = v;
+ for (let i = 0; i < uvCount; i++)
+ {
+ let v = 1.0 - (uvs[i * 2 + 1]);
+ uvs[i * 2 + 1] = v;
}
}
uvTime += performance.now() - startUVTime;
-
- if (!child.geometry.attributes.normal) {
+
+ if (!child.geometry.attributes.normal)
+ {
var startNormalTime = performance.new();
child.geometry.computeVertexNormals();
normalTime += performance.now() - startNormalTime;
}
-
- if (child.geometry.getIndex())
+
+ if (child.geometry.getIndex())
{
if (!child.geometry.attributes.tangent)
{
@@ -179,7 +187,7 @@ export class Scene
tangentTime += performance.now() - startTangentTime;
}
}
-
+
// Use default MaterialX naming convention.
var startStreamTime = performance.now();
child.geometry.attributes.i_position = child.geometry.attributes.position;
@@ -199,7 +207,7 @@ export class Scene
console.log(' - Stream Update time: ', streamTime);
console.log(' - Bounds compute time: ', bboxTime);
}
-
+
// Update the background
this._scene.background = this.getBackground();
@@ -208,10 +216,10 @@ export class Scene
camera.position.y = bsphere.center.y;
camera.position.z = bsphere.radius * 2.0;
camera.updateProjectionMatrix();
-
+
orbitControls.target = bsphere.center;
orbitControls.update();
- }
+ }
setUpdateTransforms()
{
@@ -231,10 +239,13 @@ export class Scene
const scene = this.getScene();
const camera = this.getCamera();
- scene.traverse((child) => {
- if (child.isMesh) {
+ scene.traverse((child) =>
+ {
+ if (child.isMesh)
+ {
const uniforms = child.material.uniforms;
- if (uniforms) {
+ if (uniforms)
+ {
uniforms.u_worldMatrix.value = child.matrixWorld;
uniforms.u_viewProjectionMatrix.value = this.#_viewProjMat.multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse);
@@ -242,8 +253,8 @@ export class Scene
uniforms.u_viewPosition.value = camera.getWorldPosition(this.#_worldViewPos);
if (uniforms.u_worldInverseTransposeMatrix)
- uniforms.u_worldInverseTransposeMatrix.value =
- new THREE.Matrix4().setFromMatrix3(this.#_normalMat.getNormalMatrix(child.matrixWorld));
+ uniforms.u_worldInverseTransposeMatrix.value =
+ new THREE.Matrix4().setFromMatrix3(this.#_normalMat.getNormalMatrix(child.matrixWorld));
}
}
});
@@ -283,9 +294,9 @@ export class Scene
const scene = this.getScene();
const camera = this.getCamera();
- scene.traverse((child) =>
+ scene.traverse((child) =>
{
- if (child.isMesh)
+ if (child.isMesh)
{
const dagPath = this.getDagPath(child).join('/');
@@ -336,19 +347,23 @@ export class Scene
camera.updateProjectionMatrix();
}
- getScene() {
+ getScene()
+ {
return this._scene;
}
- getCamera() {
+ getCamera()
+ {
return this._camera;
}
- getGeometryURL() {
+ getGeometryURL()
+ {
return this._geometryURL;
}
- setGeometryURL(url) {
+ setGeometryURL(url)
+ {
this._geometryURL = url;
}
@@ -367,7 +382,7 @@ export class Scene
this.#_showBackgroundTexture = enable;
}
- getBackground()
+ getBackground()
{
if (this.#_backgroundTexture && this.#_showBackgroundTexture)
{
@@ -424,31 +439,34 @@ export class Editor
initialize()
{
Array.from(document.getElementsByClassName('lil-gui')).forEach(
- function (element, index, array) {
- if (element.className) {
+ function (element, index, array)
+ {
+ if (element.className)
+ {
element.remove();
}
}
);
- this._gui = new GUI( { title: "Property Editor" } );
+ this._gui = new GUI({ title: "Property Editor" });
this._gui.close();
}
// Update ui properties
// - Hide close button
// - Update transparency so scene shows through if overlapping
- updateProperties(targetOpacity = 1)
+ updateProperties(targetOpacity = 1)
{
// Set opacity
Array.from(document.getElementsByClassName('dg')).forEach(
- function (element, index, array) {
+ function (element, index, array)
+ {
element.style.opacity = targetOpacity;
}
);
}
- getGUI()
+ getGUI()
{
return this._gui;
}
@@ -491,7 +509,7 @@ class MaterialAssign
{
return this._material;
}
-
+
getGeometry()
{
return this._geometry;
@@ -547,13 +565,13 @@ export class Material
}
// If no material file is selected, we programmatically create a default material as a fallback
- static createFallbackMaterial(doc)
+ static createFallbackMaterial(doc)
{
let ssNode = doc.getChild('Generated_Default_Shader');
if (ssNode)
{
return ssNode;
- }
+ }
const ssName = 'Generated_Default_Shader';
ssNode = doc.addChildOfCategory('standard_surface', ssName);
ssNode.setType('surfaceshader');
@@ -568,7 +586,8 @@ export class Material
async loadMaterialFile(loader, materialFilename)
{
- return new Promise((resolve, reject) => {
+ return new Promise((resolve, reject) =>
+ {
loader.load(materialFilename, data => resolve(data), null, reject);
});
}
@@ -585,7 +604,7 @@ export class Material
doc.importLibrary(viewer.getLibrary());
viewer.setDocument(doc);
- const fileloader = viewer.getFileLoader();
+ const fileloader = viewer.getFileLoader();
let mtlxMaterial = await viewer.getMaterial().loadMaterialFile(fileloader, materialFilename);
@@ -598,7 +617,7 @@ export class Material
// location.
if (!materialFilename) materialFilename = "/";
const paths = materialFilename.split('/');
- paths.pop();
+ paths.pop();
const searchPath = paths.join('/');
// Load material
@@ -613,18 +632,18 @@ export class Material
// and assign to the associated geometry. If there are no looks
// then the first material is found and assignment to all the
// geometry.
- this.clearMaterials();
+ this.clearMaterials();
var looks = doc.getLooks();
if (looks.length)
{
for (let look of looks)
{
const materialAssigns = look.getMaterialAssigns();
- for (let materialAssign of materialAssigns)
+ for (let materialAssign of materialAssigns)
{
let matName = materialAssign.getMaterial();
if (matName)
- {
+ {
let mat = doc.getChild(matName);
var shader;
if (mat)
@@ -672,8 +691,8 @@ export class Material
// The identifier used is "*" to mean the entire scene.
const materialNodes = doc.getMaterialNodes();
let shaderList = [];
- let foundRenderable = false;
- for (let i=0; i 0)
{
continue
}
let outputs = nodeGraph.getOutputs();
- for (let j=0; j
+ uniformBlocks.forEach(uniforms =>
{
- if (!uniforms.empty())
+ if (!uniforms.empty())
{
- for (let i = 0; i < uniforms.size(); ++i)
+ for (let i = 0; i < uniforms.size(); ++i)
{
const variable = uniforms.get(i);
const value = variable.getValue()?.getData();
let name = variable.getVariable();
- if (ignoreList.includes(name)) {
+ if (ignoreList.includes(name))
+ {
continue;
}
let currentFolder = matUI;
let currentElemPath = variable.getPath();
- if (!currentElemPath || currentElemPath.length == 0) {
+ if (!currentElemPath || currentElemPath.length == 0)
+ {
continue;
}
let currentElem = elem.getDocument().getDescendant(currentElemPath);
- if (!currentElem) {
+ if (!currentElem)
+ {
continue;
}
let currentNode = null;
if (currentElem.getParent() && currentElem.getParent().getNamePath() != "")
- {
+ {
currentNode = currentElem.getParent();
}
let uiname = "";
let nodeDefInput = null;
- if (currentNode) {
+ if (currentNode)
+ {
let currentNodePath = currentNode.getNamePath();
var pathSplit = currentNodePath.split('/');
- if (pathSplit.length) {
+ if (pathSplit.length)
+ {
currentNodePath = pathSplit[0];
}
currentFolder = folderList[currentNodePath];
- if (!currentFolder) {
+ if (!currentFolder)
+ {
currentFolder = matUI.addFolder(currentNodePath);
folderList[currentNodePath] = currentFolder;
}
// Check for ui attributes
var nodeDef = currentNode.getNodeDef();
- if (nodeDef) {
+ if (nodeDef)
+ {
// Remove node name from shader uniform name for non root nodes
let lookup_name = name.replace(currentNode.getName() + '_', '');
nodeDefInput = nodeDef.getActiveInput(lookup_name);
- if (nodeDefInput)
+ if (nodeDefInput)
{
uiname = nodeDefInput.getAttribute('uiname');
let uifolderName = nodeDefInput.getAttribute('uifolder');
- if (uifolderName && uifolderName.length) {
+ if (uifolderName && uifolderName.length)
+ {
let newFolderName = currentNodePath + '/' + uifolderName;
currentFolder = folderList[newFolderName];
- if (!currentFolder)
+ if (!currentFolder)
{
currentFolder = matUI.addFolder(uifolderName);
- currentFolder.domElement.classList.add('peditorfolder');
+ currentFolder.domElement.classList.add('peditorfolder');
folderList[newFolderName] = currentFolder;
}
}
@@ -1106,17 +1135,21 @@ export class Material
// Determine UI name to use
let path = name;
let interfaceName = currentElem.getAttribute("interfacename");
- if (interfaceName && interfaceName.length) {
+ if (interfaceName && interfaceName.length)
+ {
const graph = currentNode.getParent();
if (graph)
{
const graphInput = graph.getInput(interfaceName);
- if (graphInput) {
+ if (graphInput)
+ {
let uiname = graphInput.getAttribute('uiname');
- if (uiname.length) {
+ if (uiname.length)
+ {
path = uiname;
}
- else {
+ else
+ {
path = graphInput.getName();
}
}
@@ -1126,11 +1159,14 @@ export class Material
path = interfaceName;
}
}
- else {
- if (!uiname) {
+ else
+ {
+ if (!uiname)
+ {
uiname = currentElem.getAttribute('uiname');
}
- if (uiname && uiname.length) {
+ if (uiname && uiname.length)
+ {
path = uiname;
}
}
@@ -1236,33 +1272,35 @@ export class Material
{
let w = currentFolder.add(material.uniforms[name], 'value', minValue, maxValue, step).name(path);
w.domElement.classList.add('peditoritem');
- }
+ }
else
{
// Map enumList strings to values
// Map to 0..N if no values are specified via enumvalues attribute
if (enumValues.length == 0)
- {
+ {
for (let i = 0; i < enumList.length; ++i)
{
enumValues.push(i);
}
}
const enumeration = {};
- enumList.forEach((str, index) => {
+ enumList.forEach((str, index) =>
+ {
enumeration[str] = enumValues[index];
});
-
+
// Function to handle enum drop-down
- function handleDropdownChange(value) {
+ function handleDropdownChange(value)
+ {
if (material.uniforms[name])
{
material.uniforms[name].value = value;
- }
- }
+ }
+ }
const defaultOption = enumList[value]; // Set the default selected option
const dropdownController = currentFolder.add(enumeration, defaultOption, enumeration).name(path);
- dropdownController.onChange(handleDropdownChange);
+ dropdownController.onChange(handleDropdownChange);
dropdownController.domElement.classList.add('peditoritem');
}
}
@@ -1273,7 +1311,7 @@ export class Material
if (uniformToUpdate && value != null)
{
let w = currentFolder.add(material.uniforms[name], 'value').name(path);
- w.domElement.classList.add('peditoritem');
+ w.domElement.classList.add('peditoritem');
}
break;
@@ -1287,7 +1325,7 @@ export class Material
var maxValue = [DEFAULT_MAX, DEFAULT_MAX, DEFAULT_MAX, DEFAULT_MAX];
var step = [0, 0, 0, 0];
- if (nodeDefInput)
+ if (nodeDefInput)
{
if (nodeDefInput.hasAttribute('uisoftmin'))
minValue = nodeDefInput.getAttribute('uisoftmin').split(',').map(Number);
@@ -1300,7 +1338,7 @@ export class Material
maxValue = nodeDefInput.getAttribute('uimax').split(',').map(Number);
if (nodeDefInput.hasAttribute('uistep'))
- step = nodeDefInput.getAttribute('uistep').split(',').map(Number);
+ step = nodeDefInput.getAttribute('uistep').split(',').map(Number);
}
for (let i = 0; i < 4; ++i)
{
@@ -1312,10 +1350,11 @@ export class Material
const keyString = ["x", "y", "z", "w"];
let vecFolder = currentFolder.addFolder(path);
- Object.keys(material.uniforms[name].value).forEach((key) => {
- let w = vecFolder.add(material.uniforms[name].value,
+ Object.keys(material.uniforms[name].value).forEach((key) =>
+ {
+ let w = vecFolder.add(material.uniforms[name].value,
key, minValue[key], maxValue[key], step[key]).name(keyString[key]);
- w.domElement.classList.add('peditoritem');
+ w.domElement.classList.add('peditoritem');
})
}
break;
@@ -1333,11 +1372,12 @@ export class Material
color3.fromArray(material.uniforms[name].value);
dummy.color = color3.getHex();
let w = currentFolder.addColor(dummy, 'color').name(path)
- .onChange(function (value) {
+ .onChange(function (value)
+ {
const color3 = new THREE.Color(value);
material.uniforms[name].value.set(color3.toArray());
});
- w.domElement.classList.add('peditoritem');
+ w.domElement.classList.add('peditoritem');
}
break;
@@ -1351,7 +1391,8 @@ export class Material
break;
case 'string':
console.log('String: ', name);
- if (value != null) {
+ if (value != null)
+ {
var dummy =
{
thevalue: value
@@ -1359,7 +1400,7 @@ export class Material
let item = currentFolder.add(dummy, 'thevalue');
item.name(path);
item.disable(true);
- item.domElement.classList.add('peditoritem');
+ item.domElement.classList.add('peditoritem');
}
break;
default:
@@ -1388,7 +1429,7 @@ export class Material
Keeps track of local scene, and property editor as well as current MaterialX document
and assocaited material, shader and lighting information.
*/
-export class Viewer
+export class Viewer
{
static create()
{
@@ -1402,7 +1443,7 @@ export class Viewer
this.materials.push(new Material());
this.fileLoader = new THREE.FileLoader();
- this.hdrLoader = new RGBELoader();
+ this.hdrLoader = new RGBELoader();
}
//
@@ -1447,15 +1488,18 @@ export class Viewer
this.irradianceTexture = prepareEnvTexture(irradianceTexture, renderer.capabilities);
}
- getEditor() {
+ getEditor()
+ {
return this.editor;
}
- getScene() {
+ getScene()
+ {
return this.scene;
}
- getMaterial() {
+ getMaterial()
+ {
return this.materials[0];
}
@@ -1469,46 +1513,57 @@ export class Viewer
return this.hdrLoader;
}
- setDocument(doc) {
+ setDocument(doc)
+ {
this.doc = doc;
}
- getDocument() {
+ getDocument()
+ {
return this.doc;
}
- getLibrary() {
+ getLibrary()
+ {
return this.stdlib;
}
- getLightRig() {
+ getLightRig()
+ {
return this.lightRigDoc;
}
- getMx() {
+ getMx()
+ {
return this.mx;
}
- getGenerator() {
+ getGenerator()
+ {
return this.generator;
}
- getGenContext() {
+ getGenContext()
+ {
return this.genContext;
}
- getLights() {
+ getLights()
+ {
return this.lights;
}
- getLightData() {
+ getLightData()
+ {
return this.lightData;
}
- getRadianceTexture() {
+ getRadianceTexture()
+ {
return this.radianceTexture;
}
- getIrradianceTexture() {
+ getIrradianceTexture()
+ {
return this.irradianceTexture;
}
diff --git a/javascript/MaterialXView/webpack.config.js b/javascript/MaterialXView/webpack.config.js
index bf6673284a..cd33a443f2 100644
--- a/javascript/MaterialXView/webpack.config.js
+++ b/javascript/MaterialXView/webpack.config.js
@@ -6,75 +6,75 @@ const HtmlWebpackPlugin = require('html-webpack-plugin')
const stdSurfaceMaterials = "../../resources/Materials/Examples/StandardSurface";
const stdSurfaceMaterialsBaseURL = "Materials/Examples/StandardSurface";
let dirent = fs.readdirSync(stdSurfaceMaterials).filter(
- function (file) { if (file.lastIndexOf(".mtlx") > -1) return file; }
+ function (file) { if (file.lastIndexOf(".mtlx") > -1) return file; }
)
let materials = dirent
- .map((fileName) => ({name: fileName, value: `${stdSurfaceMaterialsBaseURL}/${fileName}`}));
+ .map((fileName) => ({ name: fileName, value: `${stdSurfaceMaterialsBaseURL}/${fileName}` }));
const usdSurfaceMaterials = "../../resources/Materials/Examples/UsdPreviewSurface";
const usdSurfaceMaterialsBaseURL = "Materials/Examples/UsdPreviewSurface";
dirent = fs.readdirSync(usdSurfaceMaterials).filter(
- function (file) { if (file.lastIndexOf(".mtlx") > -1) return file; }
+ function (file) { if (file.lastIndexOf(".mtlx") > -1) return file; }
)
let usdMaterials = dirent
- .map((fileName) => ({name: fileName, value: `${usdSurfaceMaterialsBaseURL}/${fileName}`}));
+ .map((fileName) => ({ name: fileName, value: `${usdSurfaceMaterialsBaseURL}/${fileName}` }));
const gltfSurfaceMaterials = "../../resources/Materials/Examples/GltfPbr";
const gltfSurfaceMaterialsBaseURL = "Materials/Examples/GltfPbr";
dirent = fs.readdirSync(gltfSurfaceMaterials).filter(
- function (file) { if (file.lastIndexOf(".mtlx") > -1) return file; }
+ function (file) { if (file.lastIndexOf(".mtlx") > -1) return file; }
)
let gltfMaterials = dirent
- .map((fileName) => ({name: fileName, value: `${gltfSurfaceMaterialsBaseURL}/${fileName}`}));
+ .map((fileName) => ({ name: fileName, value: `${gltfSurfaceMaterialsBaseURL}/${fileName}` }));
-materials = materials.concat( usdMaterials );
-materials = materials.concat( gltfMaterials );
+materials = materials.concat(usdMaterials);
+materials = materials.concat(gltfMaterials);
const geometryFiles = "../../resources/Geometry";
const geometryFilesURL = "Geometry";
dirent = fs.readdirSync(geometryFiles).filter(
- function (file) { if (file.lastIndexOf(".glb") > -1) return file; }
+ function (file) { if (file.lastIndexOf(".glb") > -1) return file; }
)
let geometry = dirent
- .map((fileName) => ({name: fileName, value: `${geometryFilesURL}/${fileName}`}));
-
+ .map((fileName) => ({ name: fileName, value: `${geometryFilesURL}/${fileName}` }));
+
module.exports = {
- entry: './source/index.js',
- output: {
- filename: 'main.js',
- path: path.resolve(__dirname, 'dist')
- },
- mode: "development",
- plugins: [
- new HtmlWebpackPlugin({
- templateParameters: {
- materials,
- geometry
- },
- template: 'index.ejs'
- }),
- new CopyPlugin({
- patterns: [
- {
- context: "../../resources/Images",
- from: "*.*",
- to: "Images",
- },
- {
- context: "../../resources/Geometry/",
- from: "*.glb",
- to: "Geometry",
- },
- { from: "./public", to: 'public' },
- { context: "../../resources/Lights", from: "*.*", to: "Lights" },
- { context: "../../resources/Lights/irradiance", from: "*.*", to: "Lights/irradiance" },
- { from: stdSurfaceMaterials, to: stdSurfaceMaterialsBaseURL },
- { from: usdSurfaceMaterials, to: usdSurfaceMaterialsBaseURL },
- { from: gltfSurfaceMaterials, to: gltfSurfaceMaterialsBaseURL },
- { from: "../build/bin/JsMaterialXGenShader.wasm" },
- { from: "../build/bin/JsMaterialXGenShader.js" },
- { from: "../build/bin/JsMaterialXGenShader.data" },
- ],
- }),
- ]
+ entry: './source/index.js',
+ output: {
+ filename: 'main.js',
+ path: path.resolve(__dirname, 'dist')
+ },
+ mode: "development",
+ plugins: [
+ new HtmlWebpackPlugin({
+ templateParameters: {
+ materials,
+ geometry
+ },
+ template: 'index.ejs'
+ }),
+ new CopyPlugin({
+ patterns: [
+ {
+ context: "../../resources/Images",
+ from: "*.*",
+ to: "Images",
+ },
+ {
+ context: "../../resources/Geometry/",
+ from: "*.glb",
+ to: "Geometry",
+ },
+ { from: "./public", to: 'public' },
+ { context: "../../resources/Lights", from: "*.*", to: "Lights" },
+ { context: "../../resources/Lights/irradiance", from: "*.*", to: "Lights/irradiance" },
+ { from: stdSurfaceMaterials, to: stdSurfaceMaterialsBaseURL },
+ { from: usdSurfaceMaterials, to: usdSurfaceMaterialsBaseURL },
+ { from: gltfSurfaceMaterials, to: gltfSurfaceMaterialsBaseURL },
+ { from: "../build/bin/JsMaterialXGenShader.wasm" },
+ { from: "../build/bin/JsMaterialXGenShader.js" },
+ { from: "../build/bin/JsMaterialXGenShader.data" },
+ ],
+ }),
+ ]
};
diff --git a/libraries/nprlib/nprlib_defs.mtlx b/libraries/nprlib/nprlib_defs.mtlx
index a8d282d0c4..dfbaa5b5f6 100644
--- a/libraries/nprlib/nprlib_defs.mtlx
+++ b/libraries/nprlib/nprlib_defs.mtlx
@@ -34,8 +34,8 @@
-
-
+
+
diff --git a/libraries/nprlib/nprlib_ng.mtlx b/libraries/nprlib/nprlib_ng.mtlx
index c287c2ef79..0bd7e334e5 100644
--- a/libraries/nprlib/nprlib_ng.mtlx
+++ b/libraries/nprlib/nprlib_ng.mtlx
@@ -32,10 +32,9 @@
-
-
-
-
+
+
+
diff --git a/resources/Materials/TestSuite/nprlib/edge_brighten.mtlx b/resources/Materials/TestSuite/nprlib/edge_brighten.mtlx
index dc06b76d98..8ce3affd40 100644
--- a/resources/Materials/TestSuite/nprlib/edge_brighten.mtlx
+++ b/resources/Materials/TestSuite/nprlib/edge_brighten.mtlx
@@ -1,17 +1,16 @@
-
-
-
-
+
+
+
-
-
+
+
-
-
+
+
diff --git a/source/MaterialXGenShader/ShaderNode.cpp b/source/MaterialXGenShader/ShaderNode.cpp
index ff3c8fdb10..6e951b06e6 100644
--- a/source/MaterialXGenShader/ShaderNode.cpp
+++ b/source/MaterialXGenShader/ShaderNode.cpp
@@ -244,6 +244,10 @@ ShaderNodePtr ShaderNode::create(const ShaderGraph* parent, const string& name,
newNode->_classification = Classification::SHADER | Classification::SURFACE | Classification::CLOSURE;
}
}
+ else if (*primaryOutput->getType() == *Type::VOLUMESHADER)
+ {
+ newNode->_classification = Classification::SHADER | Classification::VOLUME | Classification::CLOSURE;
+ }
else if (*primaryOutput->getType() == *Type::LIGHTSHADER)
{
newNode->_classification = Classification::LIGHT | Classification::SHADER | Classification::CLOSURE;
diff --git a/source/MaterialXGraphEditor/CMakeLists.txt b/source/MaterialXGraphEditor/CMakeLists.txt
index f5f22be2c5..557b134cff 100644
--- a/source/MaterialXGraphEditor/CMakeLists.txt
+++ b/source/MaterialXGraphEditor/CMakeLists.txt
@@ -60,6 +60,9 @@ set(GLFW_BUILD_TESTS OFF)
set(GLFW_BUILD_DOCS OFF)
set(GLFW_INSTALL OFF)
+# Explicitly build GLFW with static libraries, independent of the broader build settings.
+set(BUILD_SHARED_LIBS OFF)
+
add_subdirectory(External/Glfw)
if(MSVC)