MaterialXLab API  0.0.1
APIs For MaterialXLab Libraries
Loading...
Searching...
No Matches
PhysicallyBasedMaterialX.js File Reference

Go to the source code of this file.

Functions

function updateViewer (parent=null, target)
 
function async fetchData ()
 
function clearSelection ()
 
function setShadingModel (option)
 
function selectReference (addToSelection, col, refname)
 
function displayReferences (filteredTags=null)
 
function convertToMaterialX (materialNames=[])
 
function setupXMLSyntax ()
 
function setupJSONSyntax ()
 
function setupJSONRemappingSyntax ()
 
function startup ()
 

Variables

const iframeModal = document.getElementById('iframeModal')
 
const closeIframeModal = document.getElementById('closeIframeModal')
 
let messenger = null
 
const loader = new JsPhysicallyBasedMaterialLoader()
 
let cmeditor = setupXMLSyntax()
 
let jsonRemapEditor = setupJSONRemappingSyntax()
 
let jsoneditor = setupJSONSyntax()
 
let selected_references = []
 
window onload = startup
 

Function Documentation

◆ clearSelection()

function clearSelection ( )

Definition at line 47 of file PhysicallyBasedMaterialX.js.

47 {
49 // Clear borders
50 const referencesContainer = document.getElementById('PBReferencesImages');
51 Array.from(referencesContainer.children).forEach(child => {
52 child.style.background = '';
53 });
54}
let selected_references

◆ convertToMaterialX()

function convertToMaterialX ( materialNames = [])

Definition at line 177 of file PhysicallyBasedMaterialX.js.

177 {
178 // Get the shading mode option
179 let shadingModel = 'standard_surface';
180 const shadingModelOption = document.getElementById('shadingModelButton').textContent;
181 if (shadingModelOption) {
182 if (shadingModelOption) {
183 shadingModel = shadingModelOption.toLowerCase().replace(/ /g, '_');
184 console.log('>>>>>>>>>>>>>>>>>>> Selected shading model:', shadingModel);
185 }
186 }
187
188 console.log('> Generate for shading Model:', shadingModel);
189 let references = [];
190 let addAllInputs = false; // Always false since the JS API is missing addInputsFromNodeDef()
191 let remapKeys = {};
192 let shaderPrefix = '';
193
194 if (loader.convertToMaterialX(shadingModel, references, addAllInputs,
195 materialNames, remapKeys, shaderPrefix)) {
196
197 let [validateDocument, errors] = loader.validateDocument();
198 console.log('> MaterialX validation:', validateDocument, errors);
199 let docString = loader.getMaterialXString();
200 if (docString.length > 0) {
201 //document.getElementById('MaterialXMaterials').textContent = docString;
202 cmeditor.setValue(docString);
203 }
204 }
205}

◆ displayReferences()

function displayReferences ( filteredTags = null)

Definition at line 82 of file PhysicallyBasedMaterialX.js.

82 {
83 let references = loader.getReferenceList();
84
85 // If filtering, filter references by partial match in tags or name
86 if (filteredTags && filteredTags.length > 0) {
87 const lowerTags = filteredTags.map(tag => tag.toLowerCase());
88 references = references.filter(ref => {
89 const name = (ref.name || '').toLowerCase();
90 const tagsArr = (ref.tags && Array.isArray(ref.tags)) ? ref.tags.map(t => t.toLowerCase()) : [];
91 // Match if any filter string is a substring of the name or any tag
92 return lowerTags.some(tag => name.includes(tag) || tagsArr.some(t => t.includes(tag)));
93 });
94 }
95
96 // If an item is selected add it to the list
97 display_references = []
98 for (let i = 0; i < selected_references.length; i++) {
99 const selName = selected_references[i];
100 if (!references.find(ref => ref.name === selName)) {
101 // Find in full list
102 const fullRef = loader.getReferenceList().find(ref => ref.name === selName);
103 if (fullRef) {
104 display_references.push(fullRef);
105 }
106 }
107 }
108 for (let i = 0; i < references.length; i++) {
109 display_references.push(references[i]);
110 }
111 // Sort
112 display_references.sort((a, b) => a.name.localeCompare(b.name));
113
114 if (display_references.length > 0) {
115 const referencesContainer = document.getElementById('PBReferencesImages');
116 referencesContainer.innerHTML = ''; // Clear previous references
117
118 display_references.forEach(ref => {
119 const col = document.createElement('div');
120 col.className = 'rounded col-sm mx-auto ml-4 mb-2'; // Optional bottom margin
121 col.id = ref.name;
122 // Add tags as data attribute for easier filtering
123 if (ref.tags && Array.isArray(ref.tags)) {
124 col.setAttribute('data-tags', ref.tags.join(','));
125 } else {
126 col.setAttribute('data-tags', '');
127 }
128 // Highlight if selected
129 if (selected_references.includes(ref.name)) {
130 col.style.background = '#0072B2';
131 } else {
132 col.style.background = '';
133 }
134 col.addEventListener('click', (event) => {
135 // Check for shift key for multi-selection
136 let isMultiSelect = event.shiftKey;
137 selectReference(isMultiSelect, col, ref.name);
138 });
139
140 // Create a paragraph for the name
141 const name = document.createElement('p');
142 name.textContent = ref.name || 'Reference Image';
143 name.style.marginBottom = '2px';
144 col.appendChild(name);
145
146 // Create the image
147 const img = document.createElement('img');
148 img.src = ref.reference;
149 //img.style.maxWidth = '256';
150 img.style.width = '100%';
151 img.style.minWidth = '128px';
152 img.style.display = 'block'; // Ensures image appears below text
153 img.style.marginBottom = '10px';
154
155 // Append image to the column
156 col.appendChild(img);
157
158 // Show tags as Bootstrap pills in a line under the name
159 if (ref.tags && Array.isArray(ref.tags) && ref.tags.length > 0) {
160 const tagLine = document.createElement('div');
161 tagLine.style.marginBottom = '0px';
162 ref.tags.forEach(tag => {
163 const pill = document.createElement('div');
164 pill.className = 'badge bg-white text-dark mt-1 me-1 mb-1';
165 pill.textContent = tag;
166 tagLine.appendChild(pill);
167 });
168 col.appendChild(tagLine);
169 }
170
171 // Append the column to the references container
172 referencesContainer.appendChild(col);
173 });
174 }
175}
function selectReference(addToSelection, col, refname)

◆ fetchData()

function async fetchData ( )

Definition at line 27 of file PhysicallyBasedMaterialX.js.

27 {
28 const data = await loader.getPhysicallyBasedMaterials();
29 if (data) {
30 console.log('PhysicallyBased material count:', loader.materials.length);
31
32 let result = JSON.stringify(data, null, 4);
33 //document.getElementById('jsonMaterials').textContent = result;
34 jsoneditor.setValue(result);
35
36 let remappingMap = loader.getInputRemappingMap();
37 let remapResult = JSON.stringify(remappingMap, null, 4);
38 //document.getElementById('jsonRemapping').textContent = remapResult;
39 jsonRemapEditor.setValue(remapResult);
40
42 }
43}
let jsonRemapEditor
function displayReferences(filteredTags=null)

◆ selectReference()

function selectReference ( addToSelection,
col,
refname )

Definition at line 65 of file PhysicallyBasedMaterialX.js.

65 {
66 if (!addToSelection) {
68 }
69
70 //console.log('Selected reference:', refname);
71 if (!selected_references.includes(refname)) {
72 selected_references.push(refname);
73 col.style.background = '#3a99d0';
74 col.style.color = '#FFFFFF';
75 } else {
76 // Deselect
77 selected_references = selected_references.filter(name => name !== refname);
78 col.style.background = '';
79 }
80}
function clearSelection()

◆ setShadingModel()

function setShadingModel ( option)

Definition at line 56 of file PhysicallyBasedMaterialX.js.

56 {
57 // Set name of menu shadingModelButton
58 const shadingModelButton = document.getElementById('shadingModelButton');
59 if (shadingModelButton) {
60 shadingModelButton.textContent = option;
61 console.log('Set shading model to:', option);
62 }
63}

◆ setupJSONRemappingSyntax()

function setupJSONRemappingSyntax ( )

Definition at line 256 of file PhysicallyBasedMaterialX.js.

256 {
257 const jsonTextArea3 = document.getElementById('jsonRemapping');
258 let cmeditor3 = null;
259 if (jsonTextArea3) {
260 cmeditor3 = CodeMirror.fromTextArea(jsonTextArea3, {
261 mode: 'application/json',
262 lineNumbers: true,
263 dragDrop: false,
264 theme: 'dracula',
265 lineWrapping: true, // This is key
266 viewportMargin: Infinity // Helps with rendering
267 });
268
269 // Optional: Set an initial value for the textarea
270 const initialjson3 = '';
271 jsonTextArea3.value = initialjson3;
272 cmeditor3.setValue(initialjson3);
273
274 // Update CodeMirror whenever the textarea content changes
275 cmeditor3.on('change', (e) => {
276 jsonTextArea3.value = cmeditor3.getValue();
277 });
278 }
279 return cmeditor3;
280}

◆ setupJSONSyntax()

function setupJSONSyntax ( )

Definition at line 231 of file PhysicallyBasedMaterialX.js.

231 {
232 const jsonTextArea = document.getElementById('jsonMaterials');
233 let cmeditor2 = null;
234 if (jsonTextArea) {
235 cmeditor2 = CodeMirror.fromTextArea(jsonTextArea, {
236 mode: 'application/json',
237 lineNumbers: true,
238 dragDrop: false,
239 theme: 'dracula'
240 });
241
242 // Optional: Set an initial value for the textarea
243 const initialjson = '';
244 jsonTextArea.value = initialjson;
245 cmeditor2.setValue(initialjson);
246
247 // Update CodeMirror whenever the textarea content changes
248 cmeditor2.on('change', (e) => {
249 jsonTextArea.value = cmeditor2.getValue();
250 });
251 }
252 return cmeditor2;
253}

◆ setupXMLSyntax()

function setupXMLSyntax ( )

Definition at line 208 of file PhysicallyBasedMaterialX.js.

208 {
209 // Initialize CodeMirror for XML syntax highlighting
210 const materialXTextArea = document.getElementById('MaterialXMaterials');
211 let cmeditor = CodeMirror.fromTextArea(materialXTextArea, {
212 mode: 'application/xml',
213 lineNumbers: true,
214 dragDrop: true,
215 theme: 'night',
216 });
217
218 // Optional: Set an initial value for the textarea
219 const initialXML = '';
220 materialXTextArea.value = initialXML;
221 cmeditor.setValue(initialXML);
222
223 // Update CodeMirror whenever the textarea content changes
224 cmeditor.on('change', (e) => {
225 materialXTextArea.value = cmeditor.getValue();
226 });
227
228 return cmeditor;
229}

◆ startup()

function startup ( )

Definition at line 282 of file PhysicallyBasedMaterialX.js.

283{
284 document.body.setAttribute('data-bs-theme', 'dark');
285
286 // Filter by tags or name
287 document.getElementById('materialFilter').addEventListener('input', function (e) {
288 const filterValue = e.target.value.trim();
289 let tags = [];
290 if (filterValue.length > 0) {
291 // Allow comma or space separated tags
292 tags = filterValue.split(/[, ]+/).filter(Boolean);
293 }
294 displayReferences(tags.length > 0 ? tags : null);
295 });
296
297
298 document.getElementById('shadingModelOption').addEventListener('click', async (e) => {
299 setShadingModel(e.target.textContent);
300 });
301
302 document.getElementById('clearSelection').addEventListener('click', async () => {
304 });
305
306 document.getElementById('fetchData').addEventListener('click', async () => {
307 await fetchData();
308 });
309 fetchData();
310
311 document.getElementById('genMaterialX').addEventListener('click', async () => {
313 });
314
315 let = viewer = document.getElementById("viewer");
316 let targetURL = "https://kwokcb.github.io/MaterialXLab/javascript/shader_utilities/dist/index.html?viewerOnly=1";
317 viewer.src = targetURL;
318
319 let modalDialog = null;
320
321 // Show the modal with iframe when the View button is clicked
322 // Remove Bootstrap modal triggers so modal cannot be opened by data attributes
323 viewerButton = document.getElementById('openViewer');
324 viewerButton.removeAttribute('data-bs-toggle');
325 viewerButton.removeAttribute('data-bs-target');
326
327 function showModal() {
328 if (!cmeditor.getValue().trim()) {
329 alert('No shaders to display.');
330 e.preventDefault();
331 e.stopPropagation();
332 return false;
333 }
334 // Open the modal programmatically using Bootstrap's JS API
335 var modalEl = document.getElementById('viewPopup');
336 if (window.bootstrap && modalEl) {
337 if (!modalDialog)
338 modalDialog = window.bootstrap.Modal.getOrCreateInstance(modalEl);
339 modalDialog.show();
340 }
341 // Update the viewer after modal is shown
342 viewer.style.display = 'block';
343 updateViewer(viewer, targetURL);
344 }
345
346 viewerButton.addEventListener('click', async (e) => {
347 showModal();
348 });
349}
function setShadingModel(option)
function async fetchData()
function convertToMaterialX(materialNames=[])
function updateViewer(parent=null, target)

◆ updateViewer()

function updateViewer ( parent = null,
target )

Definition at line 8 of file PhysicallyBasedMaterialX.js.

8 {
9 if (!messenger) {
10 messenger = new IframeMessenger(parent, target);
11 }
12 // Get text from editor
13 text = cmeditor.getValue();
14 message = JSON.stringify({ type: "document", value: text });
15 messenger.post(message);
16}

Variable Documentation

◆ closeIframeModal

const closeIframeModal = document.getElementById('closeIframeModal')

Definition at line 4 of file PhysicallyBasedMaterialX.js.

◆ cmeditor

let cmeditor = setupXMLSyntax()

Definition at line 22 of file PhysicallyBasedMaterialX.js.

◆ iframeModal

const iframeModal = document.getElementById('iframeModal')

Definition at line 3 of file PhysicallyBasedMaterialX.js.

◆ jsoneditor

let jsoneditor = setupJSONSyntax()

Definition at line 24 of file PhysicallyBasedMaterialX.js.

◆ jsonRemapEditor

let jsonRemapEditor = setupJSONRemappingSyntax()

Definition at line 23 of file PhysicallyBasedMaterialX.js.

◆ loader

const loader = new JsPhysicallyBasedMaterialLoader()

Definition at line 19 of file PhysicallyBasedMaterialX.js.

◆ messenger

let messenger = null

Definition at line 7 of file PhysicallyBasedMaterialX.js.

◆ onload

window onload = startup

Definition at line 352 of file PhysicallyBasedMaterialX.js.

◆ selected_references

let selected_references = []

Definition at line 25 of file PhysicallyBasedMaterialX.js.