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 > 10)
186 uiItem = uiItem.substring(0, 10) + '...';
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 graph from text event listener
505 var texAreaNumber = 0;
506 var loadMaterialXDocumentFromText = document.getElementById('loadMaterialXDocumentFromText');
507 if (loadMaterialXDocumentFromText) {
508 loadMaterialXDocumentFromText.addEventListener('click', function () {
509 var mtlxdoc = document.getElementById('mtlxdoc').value;
510 // Generate a name for the graph
511 if (mtlxdoc.length > 0) {
512 var name = 'MaterialXGraph' + texAreaNumber++;
513 editor.loadGraphFromString('mtlx', mtlxdoc, name, auto_arrange_size);
515 }
516 });
517 }
518
519 // Add load definitions event listener
520 var loadMaterialXDefinitions = document.getElementById('loadMaterialXDefinitions');
521 if (loadMaterialXDefinitions) {
522 loadMaterialXDefinitions.addEventListener('click', function () {
523 editor.loadDefinitionsFromFile('mtlx');
524 });
525 }
526
527 // Add clear graph event listener
528 var clearGraphButton = document.getElementById('clearGraph');
529 if (clearGraphButton) {
530 clearGraphButton.addEventListener('click', function () {
531 editor.clearGraph();
533 });
534 }
535
536 // Add save materialx graph event listener
537 var saveMaterialXGraph = document.getElementById('saveMaterialXGraph');
538 if (saveMaterialXGraph) {
539 saveMaterialXGraph.addEventListener('click', function () {
540 var sl = document.getElementById('writeCustomLibs').checked;
541 var sp = document.getElementById('saveNodePositions').checked;
542 var wo = true;
543 var graphWriteOptions = { writeCustomLibs: sl, saveNodePositions: sp, writeOutputs: wo };
544 editor.saveGraphToFile('mtlx', graphWriteOptions);
545 });
546 }
547
548 // Add save materialx graph text event listener
549 var saveMaterialXGraphText = document.getElementById('saveMaterialXGraphText');
550 if (saveMaterialXGraphText) {
551 saveMaterialXGraphText.addEventListener('click', function () {
552 saveToStringUI();
553 });
554 }
555
556 // Add open subgraph event handler
557 var openSubgraph = document.getElementById('openSubgraph');
558 if (openSubgraph) {
559 openSubgraph.addEventListener('click', function () {
560 editor.openSubgraph();
561 });
562 }
563
564 // Add close subgraph event handler
565 var closeSubgraph = document.getElementById('closeSubgraph');
566 if (closeSubgraph) {
567 closeSubgraph.addEventListener('click', function () {
568 editor.closeSubgraph();
569 });
570 }
571
572 // Add reset view event handler
573 var resetView = document.getElementById('resetView');
574 if (resetView) {
575 resetView.addEventListener('click', function () {
576 editor.resetView();
577 });
578 }
579
580 // Add arrange graph event listener
581 var arrangeGraphButton = document.getElementById('arrangeGraph');
582 if (arrangeGraphButton) {
583 arrangeGraphButton.addEventListener('click', function () {
584 editor.arrangeGraph();
585 });
586 }
587
588 // Add center node event listener
589 var centerNodeButton = document.getElementById('centerNode');
590 if (centerNodeButton) {
591 centerNodeButton.addEventListener('click', function () {
592 editor.centerNode();
593 });
594 }
595
596 // Add collapse/expand nodes event listener
597 var collapseNodesButton = document.getElementById('collapseNodes');
598 if (collapseNodesButton) {
599 collapseNodesButton.addEventListener('click', function () {
600 editor.collapseExpandNodes(true);
601 });
602 }
603 var expandNodesButton = document.getElementById('expandNodes');
604 if (expandNodesButton) {
605 expandNodesButton.addEventListener('click', function () {
606 editor.collapseExpandNodes(false);
607 });
608 }
609
610 // Add copy selected event listener
611 var copySelectedButton = document.getElementById('copySelected');
612 if (copySelectedButton) {
613 copySelectedButton.addEventListener('click', function () {
614 editor.copyToClipboard();
615 });
616 }
617
618 // Add paste selected event listener
619 var pasteSelectedButton = document.getElementById('pasteSelected');
620 if (pasteSelectedButton) {
621 pasteSelectedButton.addEventListener('click', function () {
622 editor.pasteFromClipboard();
623 });
624 }
625
626 // Add create subgraph event listener
627 var createNodeGraphButton = document.getElementById('createNodeGraph');
628 if (createNodeGraphButton) {
629 createNodeGraphButton.addEventListener('click', function () {
630 editor.createNodeGraph();
631 });
632 }
633
634 // Add extract subgraph event listener
635 var extractNodeGraphButton = document.getElementById('extractNodeGraph');
636 if (extractNodeGraphButton) {
637 extractNodeGraphButton.addEventListener('click', function () {
638 editor.extractNodeGraph();
639 });
640 }
641
642 /*
643 // Add load serialization event listener
644 var loadSerialization = document.getElementById('loadSerialization');
645 loadSerialization.addEventListener('click', function () {
646 editor.loadSerialization();
647 });
648
649 // Add download graph event listener
650 var downloadGraph = document.getElementById('downloadGraph');
651 downloadGraph.addEventListener('click', function () {
652 editor.saveSerialization();
653 }); */
654
655 // Add xml to graph event listener
656 var xmlToGraph = document.getElementById('xmltograph');
657 if (xmlToGraph) {
658 xmlToGraph.addEventListener('click', function () {
659 var name = 'MaterialXGraph' + texAreaNumber++;
660 var mtlxdoc = document.getElementById('mtlxdoc').value;
661 editor.loadGraphFromString('mtlx', mtlxdoc, 'MaterialXGraph', auto_arrange_size);
663 });
664 }
665
666 function updateRenderableItemUI() {
667 let renderableItems = editor.findRenderableItems();
668 renderableItemUpdater(renderableItems);
669 }
670
671 function saveToStringUI() {
672 var cl = document.getElementById('writeCustomLibs').checked;
673 var sp = document.getElementById('saveNodePositions').checked;
674 var wo = true;
675 var graphWriteOptions = { writeCustomLibs: cl, saveNodePositions: sp, writeOutputs: wo };
676 console.log('Save with options: ', graphWriteOptions);
677 var result = editor.saveGraphToString('mtlx', graphWriteOptions);
678
679 cmeditor.setValue(result[0]);
680
681 if (customRenderer) {
682 customRenderer.setSourceColorSpace(editor.getSourceColorSpace());
683 customRenderer.setTargetDistanceUnit(editor.getTargetDistanceUnit());
684 customRenderer.updateMaterialFromText(result[0]);
685 updateRenderableItemUI();
686 }
687 }
688
689 // Add graph to xml event listener
690 var graphtoxml = document.getElementById('graphtoxml');
691 if (graphtoxml) {
692 graphtoxml.addEventListener('click', function () {
693 saveToStringUI();
694 });
695 }
696
697 let graphtoxml2 = document.getElementById('graphtoxml2');
698 if (graphtoxml2) {
699 graphtoxml2.addEventListener('click', function () {
700 saveToStringUI();
701 graphtoxml2.classList.remove('btn-outline-warning');
702 graphtoxml2.classList.add('btn-outline-secondary');
703 });
704 }
705
706 // Add graph to gltf event listener
707 var graphtogltf = document.getElementById('graphtogltf');
708 if (graphtogltf) {
709 graphtogltf.addEventListener('click', function () {
710 var graphWriteOptions = { writeCustomLibs: false, saveNodePositions: false, writeOutputs: true };
711 var result = editor.saveGraphToString('gltf', graphWriteOptions);
712 gltfDisplayUpdater(result[0]);
713 if (result[1]) {
714 consoleLog(result[1], 1, false);
715 }
716 });
717 }
718
719 // Add gltf to graph listener
720 var gltftograph = document.getElementById('gltftograph');
721 if (gltftograph) {
722 gltftograph.addEventListener('click', function () {
723 var gltfdoc = document.getElementById('gltfgraph').value;
724 if (gltfdoc.length > 0) {
725 editor.loadGraphFromString('gltf', gltfdoc, 'GLTFGraph', auto_arrange_size);
727 }
728 });
729 }
730
731 // Handle turntable option
732 let turntableEnabledUI = document.getElementById('turntableEnabled');
733 if (turntableEnabledUI) {
734 turntableEnabledUI.addEventListener('click', (e) => {
735 // Toggle inverting the button colors no toggling danger
736 turntableEnabledUI.classList.toggle('btn-secondary');
737 if (customRenderer)
738 customRenderer.toggleTurntable();
739 });
740 }
741
742 // Handle render disabled option
743 let disableRenderingUI = document.getElementById('disableRendering');
744 if (disableRenderingUI) {
745 disableRenderingUI.addEventListener('click', (e) => {
746 // Toggle inverting the button colors
747 disableRenderingUI.classList.toggle('btn-danger');
748 if (customRenderer)
749 customRenderer.toggleRendering();
750 });
751 }
752
753 // Handle background display option
754 let toggleBackgroundTextureUI = document.getElementById('toggleBackgroundTexture');
755 if (toggleBackgroundTextureUI) {
756 toggleBackgroundTextureUI.addEventListener('click', (e) => {
757 toggleBackgroundTextureUI.classList.toggle('btn-primary');
758 if (customRenderer)
759 customRenderer.toggleBackgroundTexture();
760 });
761 }
762
763 // Handle reset camera option
764 let resetCameraUI = document.getElementById('resetCamera');
765 if (resetCameraUI) {
766 resetCameraUI.addEventListener('click', (e) => {
767 if (customRenderer) {
768 customRenderer.resetCamera();
769 }
770 });
771 }
772
773 // Handle renderable geometry option
774 function loadFromMenu(e) {
775 var uiItem = e.target.value;
776 if (uiItem == '_loadFromFile_') {
777 // Create a file dialog to get the filename
778 var fileInput = document.createElement('input');
779 fileInput.type = 'file';
780 fileInput.accept = '.glb';
781
782 fileInput.onchange = function(event) {
783 var file = event.target.files[0];
784 if (file) {
785 var fileURL = URL.createObjectURL(file);
786 if (customRenderer)
787 customRenderer.setRenderGeometry(fileURL);
788 console.log('Change geometry to:', fileURL, 'from file:', file.name);
789 }
790 }
791 fileInput.click();
792 }
793 else {
794 // Convert to lowercase and remove spaces
795 var geometryURL = uiItem.toLowerCase().replace(/\s/g, '');
796 var geometryPath = 'Geometry/' + geometryURL + '.glb';
797 console.log('Change geometry to:', geometryPath);
798 if (customRenderer)
799 customRenderer.setRenderGeometry(geometryPath);
800 }
801 }
802
803 // Handle geometry item changed
804 let geometryItemSelect = document.getElementById('loadGeometry');
805 if (geometryItemSelect) {
806
807 // Add built-in geometry options
808 var geometryItems = ['Teapot', 'Shader Ball', 'Sphere', 'Plane', 'Cube', 'Cylinder', 'Twist', 'Custom...'];
809 for (var i = 0; i < geometryItems.length; i++) {
810 var option = document.createElement('option');
811 option.value = geometryValues[i];
812 option.text = geometryItems[i];
813 geometryItemSelect.appendChild(option);
814 }
815
816 // Add event handler for selection
817 geometryItemSelect.addEventListener('change', (e) => {
818 loadFromMenu(e);
819 if (e.target.value == '_loadFromFile_')
820 e.target.value = 'Custom Geometry'
821 });
822
823 // Set initial geometry.
824 if (selectGeometryUI) {
825 // Set the default geometry
826 geometryItemSelect.value = geometryId;
827 }
828 }
829
830 // Handle material selection change
831 let renderableItemSelect = document.getElementById('renderableItem');
832 if (renderableItemSelect) {
833 renderableItemSelect.addEventListener('change', (e) => {
834 let index = e.target.value;
835 if (customRenderer)
836 customRenderer.setRenderMaterial(index);
837 });
838 }
839
840 // Get the canvas element and its container
841 var canvas = document.getElementById('mygraphcanvas');
842 var canvasContainer = document.getElementById('canvasContainer');
843 var colContainer = document.getElementById('colContainer');
844
845 // Create a new ResizeObserver
846 var observer = new ResizeObserver(function (entries) {
847 //for (var entry of entries) {
848 // Get the new width and height of the column
849 //let newWidth = entry.contentRect.right;
850 //let newHeight = entry.contentRect.height;
851
852 var parent = canvas.parentNode;
853 let newWidth = parent.offsetWidth;
854 let newHeight = parent.offsetHeight;
855
856 // Set the canvas size to match the column
857 //canvas.width = newWidth;
858 //canvas.height = newHeight;
859
860 // Mark the editor as dirty to redraw the graph.
861 console.log('Resize node graph canvas to:', newWidth, newHeight);
862 editor.setDirty(newWidth, newHeight);
863 //console.log('Resized node graph canvas to:', canvas.width, canvas.height);
864 //}
865 });
866
867 // Start observing the canvas container
868 observer.observe(canvasContainer);
869
870 }
871
872 function setupGLTFSyntax() {
873 // Initialize CodeMirror for GLTF syntax highlighting
874 let cmeditor = null;
875 const gltfTextArea = document.getElementById('gltfgraph');
876 if (gltfTextArea) {
877 cmeditor = CodeMirror.fromTextArea(gltfTextArea, {
878 mode: 'application/json',
879 lineNumbers: true,
880 dragDrop: false,
881 theme: 'dracula'
882 });
883
884 // Optional: Set an initial value for the textarea
885 const initialGLTF = '';
886 gltfTextArea.value = initialGLTF;
887 cmeditor.setValue(initialGLTF);
888
889 // Update CodeMirror whenever the textarea content changes
890 cmeditor.on('change', (e) => {
891 gltfTextArea.value = cmeditor.getValue();
892 });
893
894 var pasteButton = document.getElementById('gltfgraph_paste');
895 if (pasteButton)
896 addPasteHandler(pasteButton, cmeditor);
897
898 }
899 return cmeditor;
900 }
901
902 function setupJavascriptSyntax() {
903 // Initialize CodeMirror for JS syntax highlighting
904 const elem = document.getElementById('mtlxlib');
905 if (!elem) {
906 return;
907 }
908 let cmeditor = CodeMirror.fromTextArea(elem, {
909 mode: 'application/javascript',
910 lineNumbers: true,
911 dragDrop: false,
912 theme: 'dracula',
913 readOnly: true
914 });
915
916 elem.value = '';
917 cmeditor.setValue('');
918
919 // Update CodeMirror whenever the textarea content changes
920 cmeditor.on('change', () => {
921 elem.value = cmeditor.getValue();
922 });
923
924 return cmeditor;
925 }
926
927
928 function setupXMLSyntax() {
929 // Initialize CodeMirror for XML syntax highlighting
930 const materialXTextArea = document.getElementById('mtlxdoc');
931 let cmeditor = CodeMirror.fromTextArea(materialXTextArea, {
932 mode: 'application/xml',
933 lineNumbers: true,
934 dragDrop: true,
935 theme: 'night'
936 });
937
938 // Optional: Set an initial value for the textarea
939 const initialXML = '';
940 materialXTextArea.value = initialXML;
941 cmeditor.setValue(initialXML);
942
943 // Update CodeMirror whenever the textarea content changes
944 cmeditor.on('change', (e) => {
945 materialXTextArea.value = cmeditor.getValue();
946 });
947
948 var pasteButton = document.getElementById('mtlxdoc_paste');
949 if (pasteButton)
950 addPasteHandler(pasteButton, cmeditor);
951
952 return cmeditor;
953 }
954
955 addUIHandlers();
956 addCopyHandlers();
957}
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}