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

Go to the source code of this file.

Classes

class  MxMaterialXMonitor
 Custom monitor class for MaterialX graph. More...
 

Functions

function toggleRequireUpdateUI ()
 
function export initializeNodeEditor (materialFilename, geometryId, customRenderer, user_icon_map=null, sampleFiles=null, readOnly=false)
 Function to initialize the MaterialX node editor.
 

Function Documentation

◆ initializeNodeEditor()

function export initializeNodeEditor ( materialFilename,
geometryId,
customRenderer,
user_icon_map = null,
sampleFiles = null,
readOnly = false )

Function to initialize the MaterialX node editor.

Parameters
materialFilename- The filename of the MaterialX document to load
geometryId- The id of the geometry to load
customRenderer- The custom renderer object to use for rendering
user_icon_map- The object containing the user icon map. Optional.
sampleFiles- The object containing the sample files. Optional.
readOnly- Flag to indicate if the editor is read-only. Optional.
Returns
{void}

Create a menu item for the library dropdown

Parameters
text- The text to display for the menu item
filename- The filename to load when the menu item is clicked
Returns
{HTMLElement} - The menu item element

Create a submenu for the library dropdown

Parameters
title- The title of the submenu
auto_close- Make the submenu appear if not top level
Returns
{HTMLElement} - The submenu element

Create the library menu structure

Parameters
sampleFiles- The object containing the library structure
libraryDropdown- The dropdown menu element
Returns
{void}

Display the node types in the UI

Parameters
nodeTypes- The object containing the node types
Returns
{void}

Update xml document text display

Parameters
contents- The contents of the document
Returns
{void}

Update gltf document text display

Parameters
contents- The contents of the document
Returns
{void}

Update javascript definitions display

Parameters
contents- The contents of the document
Returns
{void}

Add event handlers for UI elements

Returns
{void}

Definition at line 137 of file node_editor.js.

138 {
139 let my_icon_map = {
140 "_default_": "./Icons/materialx_logo.webp",
141 "_default_graph_": "./Icons/nodegraph_white.svg"
142 };
143
144 let geometryValues = ['teapot', 'shaderball', 'sphere', 'plane', 'cube', 'cylinder', 'twist', '_loadFromFile_']
145
146 if (user_icon_map) {
147 // add items in user icon map. Overwrite any existing items
148 for (var key in user_icon_map) {
149 my_icon_map[key] = user_icon_map[key];
150 }
151 }
152
153 // Check if URI exists
154 function uriExists(uri) {
155 return fetch(uri)
156 .then(response => {
157 if (response.ok) {
158 return Promise.resolve(true);
159 } else {
160 return Promise.resolve(false);
161 }
162 })
163 .catch(error => {
164 console.log('Error checking URI:', error);
165 return Promise.resolve(false);
166 });
167 }
168
169 // Renderable item UI updater
170 function renderableItemUpdater(renderableItems) {
171 let renderableItemSelect = document.getElementById('renderableItem');
172 if (renderableItemSelect) {
173
174 const TRUNCATION_LENGTH = 12;
175
176 while (renderableItemSelect.firstChild) {
177 renderableItemSelect.removeChild(renderableItemSelect.firstChild);
178 }
179 for (let i = 0; i < renderableItems.length; i++) {
180 let item = renderableItems[i];
181 let option = document.createElement('option');
182 option.value = item;
183 let uiItem = item;
184 // Truncate the name so it will fit into UI.
185 if (uiItem.length > 20)
186 uiItem = uiItem.substring(0, 20) + '...';
187 option.text = uiItem;
188 renderableItemSelect.appendChild(option);
189 }
190 }
191 }
192
193 // Logger
194 // TODO: Pass in a logger object instead of looking for a DOM element.
195 function consoleLog(text, severity, clear = null) {
196 if (severity === 2) {
197 text = '> Error: ' + text
198 }
199 else if (severity === 1) {
200 text = '> Warning: ' + text
201 }
202 else {
203 if (text.length)
204 text = '> ' + text;
205 }
206
207 let console_area = document.getElementById('console_area');
208 if (console_area) {
209 if (clear) {
210 console_area.value = text + '\n';
211 }
212 else {
213 console_area.value = console_area.value + text + '\n';
214 }
215 // Scroll to latest entry.
216 console_area.scrollTop = console_area.scrollHeight;
217 }
218 else {
219 console.log(text);
220 }
221 }
222
223 /* function createMenuStructure(obj) {
224 let items = [];
225 for (let key in obj) {
226 if (typeof obj[key] === 'object' && !Array.isArray(obj[key])) {
227 // It's a nested object, create a submenu
228 let subItems = createMenuStructure(obj[key]); // Recursively handle nested objects
229 items.push(createSubMenu(key, subItems));
230 } else {
231 items.push(createMenuItem(key, obj[key]));
232 }
233 console.log('<<< END SCAN');
234 }
235 return items;
236 } */
237
238
244
245 function createMenuItem(text, filename) {
246 let menuItem = document.createElement('li');
247 menuItem.className = 'dropdown-item';
248 menuItem.innerText = text;
249 menuItem.onclick = function () {
250 console.log('Load library file:', filename);
251 MxShadingGraphEditor.theEditor.handler.loadLibraryDocument(MxShadingGraphEditor.theEditor, filename);
252 // Collapse the dropdown menu
253 let dropdownMenu = document.getElementById('libraryDropdown');
254 dropdownMenu.classList.remove('show');
255 };
256 return menuItem;
257 }
258
264
265 function createSubMenu(title, auto_close = false) {
266
267 let li = document.createElement('li');
268 li.className = "dropend dropdown";
269 li.id = key;
270
271 let subMenu = document.createElement('a');
272 subMenu.className = "dropdown-item dropdown-toggle";
273 subMenu.setAttribute('data-bs-toggle', "dropdown");
274 if (auto_close) {
275 subMenu.setAttribute('data-bs-auto-close', 'outside');
276 }
277 subMenu.setAttribute('aria-expanded', 'false');
278 subMenu.setAttribute('aria-haspopup', 'true');
279 subMenu.innerHTML = title;
280 li.appendChild(subMenu);
281
282 return li;
283 }
284
290
291 function createLibraryMenu(sampleFiles, libraryDropdown) {
292 for (let key in sampleFiles) {
293 // Create top level menus
294 let li = createSubMenu(key, true);
295 libraryDropdown.appendChild(li);
296
297 let value = sampleFiles[key];
298
299 // Add items to the submenu
300 if (typeof value === 'string') {
301 let value = sampleFiles[key];
302 li.appendChild(createMenuItem(key, value));
303 }
304 else if (typeof value === 'object') {
305
306 let subMenuList = document.createElement('ul');
307 subMenuList.className = 'dropdown-menu';
308 subMenuList.id = key;
309
310 for (key in value) {
311
312 // Check if value is a string
313 if (typeof value[key] === 'string') {
314 subMenuList.appendChild(createMenuItem(key, value[key]));
315 }
316
317 else if (typeof value[key] === 'object') {
318
319 // Create sub level menus
320 let sli = createSubMenu(key, false);
321 subMenuList.appendChild(sli);
322
323 let ssubMenuList = document.createElement('ul');
324 ssubMenuList.className = 'dropdown-menu';
325 for (let skey in value[key]) {
326 ssubMenuList.appendChild(createMenuItem(skey, (value[key])[skey]));
327 }
328 sli.appendChild(ssubMenuList);
329 }
330 }
331
332 li.appendChild(subMenuList);
333 }
334
335 }
336 }
337
338 // Build material library menu UI
339 if (sampleFiles && libraryDropdown) {
340 createLibraryMenu(sampleFiles, libraryDropdown);
341 }
342
343 // Update selected geometry menu UI
344 let selectGeometryUI = false;
345 if (customRenderer) {
346
347 let geometryURL = geometryId;
348 if (geometryId.length > 0 && geometryValues.includes(geometryId)) {
349 geometryURL = 'Geometry/' + geometryId + '.glb';
350 selectGeometryUI = true;
351 }
352 var viewer = customRenderer.initialize(materialFilename, geometryURL, readOnly);
353 console.log('Setup renderer:', viewer);
354 }
355 else {
356 let preview_panel = document.getElementById("preview_panel");
357 // Hide preview_panel DOM element
358 if (preview_panel)
359 preview_panel.style.display = 'none';
360 }
361
362 // TODO: Pass in a ui function instead of looking for a DOM element.
367
368 function displayNodeTypes(nodeTypes) {
369 // Get the list container
370 var nodeList = document.getElementById('nodeTypesList');
371 if (!nodeList) {
372 return;
373 }
374
375 // Clear all children of nodeList
376 while (nodeList.firstChild) {
377 nodeList.removeChild(nodeList.firstChild);
378 }
379
380 // Iterate over the node types and add them to the list
381 for (var typeName in nodeTypes) {
382
383 var rowItem = document.createElement("tr");
384
385 var cellItem = document.createElement("td");
386 cellItem.textContent = typeName;
387 rowItem.appendChild(cellItem);
388
389 cellItem = document.createElement("td");
390 var nodeDefString = '<None>';
391 var nodeDefName = nodeTypes[typeName].nodedef_name;
392 var nodeDefNode = nodeTypes[typeName].nodedef_node
393 var nodeDefHref = nodeTypes[typeName].nodedef_href;
394 if (nodeDefName) {
395 if (nodeDefNode) {
396 var link = document.createElement("a");
397 link.target = "_blank";
398 link.href = nodeDefHref;
399 link.textContent = nodeDefNode + " ( " + nodeDefName + " )";
400 cellItem.appendChild(link);
401 }
402 else {
403 cellItem.textContent = nodeDefName;
404 }
405 }
406 else {
407 cellItem.textContent = nodeDefString;
408 }
409 rowItem.appendChild(cellItem);
410
411 nodeList.appendChild(rowItem);
412 }
413 }
414
415 // Set up syntax highlighting for text areas
416 var cmeditor = setupXMLSyntax();
417 var cmeditor2 = setupJavascriptSyntax();
418 var cmeditor3 = setupGLTFSyntax();
419
424
425 function docDisplayUpdater(contents) {
426 if (cmeditor)
427 cmeditor.setValue(contents);
428 }
429
434
435 function gltfDisplayUpdater(contents) {
436 if (!contents || contents.length == 0) {
437 contents = '{}';
438 }
439 if (cmeditor3)
440 cmeditor3.setValue(contents);
441 else
442 console.log(contents);
443 }
444
449
450 function jsDefinitionsDisplayUpdater(contents) {
451 if (cmeditor2)
452 cmeditor2.setValue(contents);
453 }
454
455 // Set up graphing UI
456 var canvas = document.getElementById('mygraphcanvas');
457 var ui = {
458 consoleLogger: consoleLog,
459 nodeTypesListUpdater: displayNodeTypes,
460 renderableItemUpdater: renderableItemUpdater,
461 documentDisplayUpdater: docDisplayUpdater,
462 gltfDocumentDisplayUpdater: gltfDisplayUpdater,
463 definitionsDisplayUpdater: jsDefinitionsDisplayUpdater,
464 propertypanel_content: document.getElementById('propertypanel_content'),
465 propertypanel_icon: document.getElementById('propertypanel_icon'),
466 icon_map: my_icon_map,
467 };
468 var editor = new MxShadingGraphEditor();
469
470 let monitor = new MxMaterialXMonitor('Custom MaterialX Graph Monitor');
471 monitor.setRenderer(customRenderer);
472 editor.initialize(canvas, ui, monitor, materialFilename, readOnly);
473
477
478 function addUIHandlers() {
479 // Add event listener to save canvas as image when button is clicked
480 var saveCanvasButton = document.getElementById('captureGraph');
481 if (saveCanvasButton) {
482 saveCanvasButton.addEventListener('click', function () {
483 var canvas = document.getElementById('mygraphcanvas');
484 var dataURL = canvas.toDataURL('image/png');
485 var link = document.createElement('a');
486 link.href = dataURL;
487 link.download = 'graph_capture.png';
488 link.click();
489 });
490 }
491
492 // TODO: Make this a user option
493 var auto_arrange_size = 80;
494
495 // Add load materialx graph event listener
496 var loadMaterialXDocumentFromFile = document.getElementById('loadMaterialXDocumentFromFile');
497 if (loadMaterialXDocumentFromFile) {
498 loadMaterialXDocumentFromFile.addEventListener('click', function () {
499 editor.loadGraphFromFile('mtlx', auto_arrange_size);
501 });
502 }
503
504 // Add load materialx zip event listener
505 var loadMaterialXDocumentFromZip = document.getElementById('loadMaterialXDocumentFromZip');
506 if (loadMaterialXDocumentFromZip) {
507 loadMaterialXDocumentFromZip.addEventListener('click', function () {
508 editor.loadGraphFromFile('zip', auto_arrange_size);
510 });
511 }
512
513 // Add load materialx graph from text event listener
514 var texAreaNumber = 0;
515 var loadMaterialXDocumentFromText = document.getElementById('loadMaterialXDocumentFromText');
516 if (loadMaterialXDocumentFromText) {
517 loadMaterialXDocumentFromText.addEventListener('click', function () {
518 var mtlxdoc = document.getElementById('mtlxdoc').value;
519 // Generate a name for the graph
520 if (mtlxdoc.length > 0) {
521 var name = 'MaterialXGraph' + texAreaNumber++;
522 editor.loadGraphFromString('mtlx', mtlxdoc, name, auto_arrange_size);
524 }
525 });
526 }
527
528 // Add load definitions event listener
529 var loadMaterialXDefinitions = document.getElementById('loadMaterialXDefinitions');
530 if (loadMaterialXDefinitions) {
531 loadMaterialXDefinitions.addEventListener('click', function () {
532 editor.loadDefinitionsFromFile('mtlx');
533 });
534 }
535
536 // Add clear graph event listener
537 var clearGraphButton = document.getElementById('clearGraph');
538 if (clearGraphButton) {
539 clearGraphButton.addEventListener('click', function () {
540 editor.clearGraph();
542 });
543 }
544
545 // Add save materialx graph event listener
546 var saveMaterialXGraph = document.getElementById('saveMaterialXGraph');
547 if (saveMaterialXGraph) {
548 saveMaterialXGraph.addEventListener('click', function () {
549 var sl = document.getElementById('writeCustomLibs').checked;
550 var sp = document.getElementById('saveNodePositions').checked;
551 var wo = true;
552 var graphWriteOptions = { writeCustomLibs: sl, saveNodePositions: sp, writeOutputs: wo };
553 editor.saveGraphToFile('mtlx', graphWriteOptions);
554 });
555 }
556
557 // Add save materialx graph text event listener
558 var saveMaterialXGraphText = document.getElementById('saveMaterialXGraphText');
559 if (saveMaterialXGraphText) {
560 saveMaterialXGraphText.addEventListener('click', function () {
561 saveToStringUI();
562 });
563 }
564
565 // Search graph
566 var searchGraph = document.getElementById('searchGraph');
567 if (searchGraph) {
568 searchGraph.addEventListener('click', function () {
569 var search = document.getElementById('searchGraphText').value;
570 editor.searchGraph(search);
571 });
572 }
573
574 // Add open subgraph event handler
575 var openSubgraph = document.getElementById('openSubgraph');
576 if (openSubgraph) {
577 openSubgraph.addEventListener('click', function () {
578 editor.openSubgraph();
579 });
580 }
581
582 // Add close subgraph event handler
583 var closeSubgraph = document.getElementById('closeSubgraph');
584 if (closeSubgraph) {
585 closeSubgraph.addEventListener('click', function () {
586 editor.closeSubgraph();
587 });
588 }
589
590 // Add reset view event handler
591 var resetView = document.getElementById('resetView');
592 if (resetView) {
593 resetView.addEventListener('click', function () {
594 editor.resetView();
595 });
596 }
597
598 // Add arrange graph event listener
599 var arrangeGraphButton = document.getElementById('arrangeGraph');
600 if (arrangeGraphButton) {
601 arrangeGraphButton.addEventListener('click', function () {
602 editor.arrangeGraph();
603 });
604 }
605
606 // Add center node event listener
607 var centerNodeButton = document.getElementById('centerNode');
608 if (centerNodeButton) {
609 centerNodeButton.addEventListener('click', function () {
610 editor.centerNode();
611 });
612 }
613
614 // Add collapse/expand nodes event listener
615 var collapseNodesButton = document.getElementById('collapseNodes');
616 if (collapseNodesButton) {
617 collapseNodesButton.addEventListener('click', function () {
618 editor.collapseExpandNodes(true);
619 });
620 }
621 var expandNodesButton = document.getElementById('expandNodes');
622 if (expandNodesButton) {
623 expandNodesButton.addEventListener('click', function () {
624 editor.collapseExpandNodes(false);
625 });
626 }
627
628 // Add select all event listener
629 var selectNodesButton = document.getElementById('selectNodes');
630 if (selectNodesButton) {
631 selectNodesButton.addEventListener('click', function () {
632 editor.selectNodes();
633 });
634 }
635
636 // Add copy selected event listener
637 var copySelectedButton = document.getElementById('copySelected');
638 if (copySelectedButton) {
639 copySelectedButton.addEventListener('click', function () {
640 editor.copyToClipboard();
641 });
642 }
643
644 // Add paste selected event listener
645 var pasteSelectedButton = document.getElementById('pasteSelected');
646 if (pasteSelectedButton) {
647 pasteSelectedButton.addEventListener('click', function () {
648 editor.pasteFromClipboard();
649 });
650 }
651
652 // Add create subgraph event listener
653 var createNodeGraphButton = document.getElementById('createNodeGraph');
654 if (createNodeGraphButton) {
655 createNodeGraphButton.addEventListener('click', function () {
656 editor.createNodeGraph();
657 });
658 }
659
660 // Add extract subgraph event listener
661 var extractNodeGraphButton = document.getElementById('extractNodeGraph');
662 if (extractNodeGraphButton) {
663 extractNodeGraphButton.addEventListener('click', function () {
664 editor.extractNodeGraph();
665 });
666 }
667
668 /*
669 // Add load serialization event listener
670 var loadSerialization = document.getElementById('loadSerialization');
671 loadSerialization.addEventListener('click', function () {
672 editor.loadSerialization();
673 });
674
675 // Add download graph event listener
676 var downloadGraph = document.getElementById('downloadGraph');
677 downloadGraph.addEventListener('click', function () {
678 editor.saveSerialization();
679 }); */
680
681 // Add xml to graph event listener
682 var xmlToGraph = document.getElementById('xmltograph');
683 if (xmlToGraph) {
684 xmlToGraph.addEventListener('click', function () {
685 var name = 'MaterialXGraph' + texAreaNumber++;
686 var mtlxdoc = document.getElementById('mtlxdoc').value;
687 editor.loadGraphFromString('mtlx', mtlxdoc, 'MaterialXGraph', auto_arrange_size);
689 });
690 }
691
692 function updateRenderableItemUI() {
693 let renderableItems = editor.findRenderableItems();
694 renderableItemUpdater(renderableItems);
695 }
696
697 function saveToStringUI() {
698 var cl = document.getElementById('writeCustomLibs').checked;
699 var sp = document.getElementById('saveNodePositions').checked;
700 var wo = true;
701 var graphWriteOptions = { writeCustomLibs: cl, saveNodePositions: sp, writeOutputs: wo };
702 console.log('Save with options: ', graphWriteOptions);
703 var result = editor.saveGraphToString('mtlx', graphWriteOptions);
704
705 cmeditor.setValue(result[0]);
706
707 if (customRenderer) {
708 customRenderer.setSourceColorSpace(editor.getSourceColorSpace());
709 customRenderer.setTargetDistanceUnit(editor.getTargetDistanceUnit());
710 customRenderer.updateMaterialFromText(result[0]);
711 updateRenderableItemUI();
712 }
713 }
714
715 // Add graph to xml event listener
716 var graphtoxml = document.getElementById('graphtoxml');
717 if (graphtoxml) {
718 graphtoxml.addEventListener('click', function () {
719 saveToStringUI();
720 });
721 }
722
723 let graphtoxml2 = document.getElementById('graphtoxml2');
724 if (graphtoxml2) {
725 graphtoxml2.addEventListener('click', function () {
726 saveToStringUI();
727 graphtoxml2.classList.remove('btn-outline-warning');
728 graphtoxml2.classList.add('btn-outline-secondary');
729 });
730 }
731
732 // Add graph to gltf event listener
733 var graphtogltf = document.getElementById('graphtogltf');
734 if (graphtogltf) {
735 graphtogltf.addEventListener('click', function () {
736 var graphWriteOptions = { writeCustomLibs: false, saveNodePositions: false, writeOutputs: true };
737 var result = editor.saveGraphToString('gltf', graphWriteOptions);
738 gltfDisplayUpdater(result[0]);
739 if (result[1]) {
740 consoleLog(result[1], 1, false);
741 }
742 });
743 }
744
745 // Add gltf to graph listener
746 var gltftograph = document.getElementById('gltftograph');
747 if (gltftograph) {
748 gltftograph.addEventListener('click', function () {
749 var gltfdoc = document.getElementById('gltfgraph').value;
750 if (gltfdoc.length > 0) {
751 editor.loadGraphFromString('gltf', gltfdoc, 'GLTFGraph', auto_arrange_size);
753 }
754 });
755 }
756
757 // Handle turntable option
758 let turntableEnabledUI = document.getElementById('turntableEnabled');
759 if (turntableEnabledUI) {
760 turntableEnabledUI.addEventListener('click', (e) => {
761 // Toggle inverting the button colors no toggling danger
762 turntableEnabledUI.classList.toggle('btn-secondary');
763 if (customRenderer)
764 customRenderer.toggleTurntable();
765 });
766 }
767
768 // Handle render disabled option
769 let disableRenderingUI = document.getElementById('disableRendering');
770 if (disableRenderingUI) {
771 disableRenderingUI.addEventListener('click', (e) => {
772 // Toggle inverting the button colors
773 disableRenderingUI.classList.toggle('btn-danger');
774 if (customRenderer)
775 customRenderer.toggleRendering();
776 });
777 }
778
779 // Handle background display option
780 let toggleBackgroundTextureUI = document.getElementById('toggleBackgroundTexture');
781 if (toggleBackgroundTextureUI) {
782 toggleBackgroundTextureUI.addEventListener('click', (e) => {
783 toggleBackgroundTextureUI.classList.toggle('btn-primary');
784 if (customRenderer)
785 customRenderer.toggleBackgroundTexture();
786 });
787 }
788
789 // Handle reset camera option
790 let resetCameraUI = document.getElementById('resetCamera');
791 if (resetCameraUI) {
792 resetCameraUI.addEventListener('click', (e) => {
793 if (customRenderer) {
794 customRenderer.resetCamera();
795 }
796 });
797 }
798
799 // Handle renderable geometry option
800 function loadFromMenu(e) {
801 var uiItem = e.target.value;
802 if (uiItem == '_loadFromFile_') {
803 // Create a file dialog to get the filename
804 var fileInput = document.createElement('input');
805 fileInput.type = 'file';
806 fileInput.accept = '.glb';
807
808 fileInput.onchange = function(event) {
809 var file = event.target.files[0];
810 if (file) {
811 var fileURL = URL.createObjectURL(file);
812 if (customRenderer)
813 customRenderer.setRenderGeometry(fileURL);
814 console.log('Change geometry to:', fileURL, 'from file:', file.name);
815 }
816 }
817 fileInput.click();
818 }
819 else {
820 // Convert to lowercase and remove spaces
821 var geometryURL = uiItem.toLowerCase().replace(/\s/g, '');
822 var geometryPath = 'Geometry/' + geometryURL + '.glb';
823 console.log('Change geometry to:', geometryPath);
824 if (customRenderer)
825 customRenderer.setRenderGeometry(geometryPath);
826 }
827 }
828
829 // Handle geometry item changed
830 let geometryItemSelect = document.getElementById('loadGeometry');
831 if (geometryItemSelect) {
832
833 // Add built-in geometry options
834 var geometryItems = ['Teapot', 'Shader Ball', 'Sphere', 'Plane', 'Cube', 'Cylinder', 'Twist', 'Custom...'];
835 for (var i = 0; i < geometryItems.length; i++) {
836 var option = document.createElement('option');
837 option.value = geometryValues[i];
838 option.text = geometryItems[i];
839 geometryItemSelect.appendChild(option);
840 }
841
842 // Add event handler for selection
843 geometryItemSelect.addEventListener('change', (e) => {
844 loadFromMenu(e);
845 if (e.target.value == '_loadFromFile_')
846 e.target.value = 'Custom Geometry'
847 });
848
849 // Set initial geometry.
850 if (selectGeometryUI) {
851 // Set the default geometry
852 geometryItemSelect.value = geometryId;
853 }
854 }
855
856 // Handle material selection change
857 let renderableItemSelect = document.getElementById('renderableItem');
858 if (renderableItemSelect) {
859 renderableItemSelect.addEventListener('change', (e) => {
860 let index = e.target.value;
861 if (customRenderer)
862 {
863 customRenderer.setRenderMaterial(index);
864 editor.searchGraph(index);
865 }
866 });
867 }
868
869 // Get the canvas element and its container
870 var canvas = document.getElementById('mygraphcanvas');
871 var canvasContainer = document.getElementById('canvasContainer');
872 var colContainer = document.getElementById('colContainer');
873
874 // Create a new ResizeObserver
875 var observer = new ResizeObserver(function (entries) {
876 //for (var entry of entries) {
877 // Get the new width and height of the column
878 //let newWidth = entry.contentRect.right;
879 //let newHeight = entry.contentRect.height;
880
881 var parent = canvas.parentNode;
882 let newWidth = parent.offsetWidth;
883 let newHeight = parent.offsetHeight;
884
885 // Set the canvas size to match the column
886 //canvas.width = newWidth;
887 //canvas.height = newHeight;
888
889 // Mark the editor as dirty to redraw the graph.
890 console.log('Resize node graph canvas to:', newWidth, newHeight);
891 editor.setDirty(newWidth, newHeight);
892 //console.log('Resized node graph canvas to:', canvas.width, canvas.height);
893 //}
894 });
895
896 // Start observing the canvas container
897 observer.observe(canvasContainer);
898
899 }
900
901 function setupGLTFSyntax() {
902 // Initialize CodeMirror for GLTF syntax highlighting
903 let cmeditor = null;
904 const gltfTextArea = document.getElementById('gltfgraph');
905 if (gltfTextArea) {
906 cmeditor = CodeMirror.fromTextArea(gltfTextArea, {
907 mode: 'application/json',
908 lineNumbers: true,
909 dragDrop: false,
910 theme: 'dracula'
911 });
912
913 // Optional: Set an initial value for the textarea
914 const initialGLTF = '';
915 gltfTextArea.value = initialGLTF;
916 cmeditor.setValue(initialGLTF);
917
918 // Update CodeMirror whenever the textarea content changes
919 cmeditor.on('change', (e) => {
920 gltfTextArea.value = cmeditor.getValue();
921 });
922
923 var pasteButton = document.getElementById('gltfgraph_paste');
924 if (pasteButton)
925 addPasteHandler(pasteButton, cmeditor);
926
927 }
928 return cmeditor;
929 }
930
931 function setupJavascriptSyntax() {
932 // Initialize CodeMirror for JS syntax highlighting
933 const elem = document.getElementById('mtlxlib');
934 if (!elem) {
935 return;
936 }
937 let cmeditor = CodeMirror.fromTextArea(elem, {
938 mode: 'application/javascript',
939 lineNumbers: true,
940 dragDrop: false,
941 theme: 'dracula',
942 readOnly: true
943 });
944
945 elem.value = '';
946 cmeditor.setValue('');
947
948 // Update CodeMirror whenever the textarea content changes
949 cmeditor.on('change', () => {
950 elem.value = cmeditor.getValue();
951 });
952
953 return cmeditor;
954 }
955
956
957 function setupXMLSyntax() {
958 // Initialize CodeMirror for XML syntax highlighting
959 const materialXTextArea = document.getElementById('mtlxdoc');
960 let cmeditor = CodeMirror.fromTextArea(materialXTextArea, {
961 mode: 'application/xml',
962 lineNumbers: true,
963 dragDrop: true,
964 theme: 'night'
965 });
966
967 // Optional: Set an initial value for the textarea
968 const initialXML = '';
969 materialXTextArea.value = initialXML;
970 cmeditor.setValue(initialXML);
971
972 // Update CodeMirror whenever the textarea content changes
973 cmeditor.on('change', (e) => {
974 materialXTextArea.value = cmeditor.getValue();
975 });
976
977 var pasteButton = document.getElementById('mtlxdoc_paste');
978 if (pasteButton)
979 addPasteHandler(pasteButton, cmeditor);
980
981 return cmeditor;
982 }
983
984 addUIHandlers();
985 addCopyHandlers();
986}
Custom monitor class for MaterialX graph.
This class is a wrapper around the LiteGraph library to provide a MaterialX node editor.
function toggleRequireUpdateUI()

◆ toggleRequireUpdateUI()

function toggleRequireUpdateUI ( )

Definition at line 10 of file node_editor.js.

10 {
11 let graphtoxml2 = document.getElementById('graphtoxml2');
12 if (graphtoxml2) {
13 graphtoxml2.classList.remove('btn-outline-secondary');
14 graphtoxml2.classList.add('btn-outline-warning');
15 }
16}