2Copyright (c) 2025 NanMu Consulting
3Author: Bernard Kwok (kwokcb@gmail.com)
5Licensed under the Apache License, Version 2.0 (the "License");
6you may not use this file except in compliance with the License.
7You may obtain a copy of the License at
9 http://www.apache.org/licenses/LICENSE-2.0
11Unless required by applicable law or agreed to in writing, software
12distributed under the License is distributed on an "AS IS" BASIS,
13WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14See the License for the specific language governing permissions and
15limitations under the License.
19@file materialxgltf_pt/plugin.py
20@brief MaterialX glTF Texture Procedurals plugin for QuiltiX
21@details This plugin provides serialization of MaterialX graphs and procedural texture extension for glTF.
29 from pygments
import highlight
30 from pygments.lexers
import JsonLexer
31 from pygments.formatters
import HtmlFormatter
33 have_highliting =
False
35from typing
import TYPE_CHECKING
38 global QtCore, QAction, QTextEdit
40 from qtpy
import QtCore
41 from qtpy.QtWidgets
import (
45 logger.info(
"qtpy modules loaded successfully")
47 except ImportError
as e:
48 logger.error(f
"Failed to import qtpy modules: {e}")
51from QuiltiX
import constants, qx_plugin
53logger = logging.getLogger(__name__)
57 from gltf_materialx_converter
import converter
as MxGLTFPT
58 from gltf_materialx_converter
import utilities
as MxGLTFPTUtil
61 logger.error(
"gltf_materialx_converter module not found")
64 from QuiltiX
import quiltix
70 self.
formatter = HtmlFormatter(linenos=
False, style=
'github-dark')
77 f
"{self.formatter.get_style_defs('.highlight')}"
78 f
"pre {{ line-height: 1.0; margin: 0; font-size: {self.font_size}; }}"
81 full_html = f
"<html><head>{styles}</head><body>{highlighted_html}</body></html>"
87 Initialize the JSON serializer.
93 stdlib, libFiles = MxGLTFPTUtil.load_standard_libraries()
98 editor.file_menu.addSeparator()
99 mymenu = editor.file_menu.addMenu(
"glTF Texture Procedurals")
102 export_json = QAction(
"Save procedurals...", editor)
104 mymenu.addAction(export_json)
107 import_json = QAction(
"Load procedurals...", editor)
109 mymenu.addAction(import_json)
112 show_json_text = QAction(
"Show procedurals...", editor)
114 mymenu.addAction(show_json_text)
118 Set the indent for the JSON output.
124 Get the JSON for the given MaterialX document.
126 doc = self.
editor.qx_node_graph.get_current_mx_graph_doc()
128 logger.debug(
"Convert graph to glTF procedural")
129 doc.importLibrary(self.
stdlib)
130 converter = MxGLTFPT.glTFMaterialXConverter()
131 json_result, status = converter.materialX_to_glTF(doc)
133 if (len(json_result) == 0):
134 logger.warning(
"Empty result for conversion to glTF")
141 Show the JSON for the current MaterialX document.
143 logger.debug(
"Show glTF triggered")
150 logger.error(f
"Failed to get glTF from graph")
154 Export the current graph to a JSON file.
156 start_path = self.
editor.mx_selection_path
158 start_path = self.
editor.geometry_selection_path
161 start_path = os.path.join(self.
root,
"resources",
"materials")
163 path = self.
editor.request_filepath(
164 title=
"Save procedural file",
165 start_path=start_path,
166 file_filter=
"glTF files (*.gltf)",
177 with open(path,
"w")
as f:
179 logger.info(f
"Wrote glTF file: {path}")
181 self.
editor.set_current_filepath(path)
184 if os.path.exists(inputFile):
185 json_string = MxGLTFPTUtil.load_json_file(inputFile)
190 Import a glTF procedural file into the current graph.
192 start_path = self.
editor.mx_selection_path
194 start_path = self.
editor.geometry_selection_path
197 start_path = os.path.join(self.
root,
"resources",
"materials")
199 path = self.
editor.request_filepath(
200 title=
"Load glTF file",
201 start_path=start_path,
202 file_filter=
"glTF files (*.gltf)",
208 if not os.path.exists(path):
209 logger.error(
"Cannot find input file: " + path)
212 converter = MxGLTFPT.glTFMaterialXConverter()
214 logger.info(
"Loaded glTF: " + json_string)
215 if (len(json_string) == 0):
216 logger.error(
"glTF file is empty: " + path)
219 doc = converter.gltf_string_to_materialX(json_string, self.
stdlib)
221 logger.info(
"Loaded glTF file: " + path)
222 self.
editor.mx_selection_path = path
223 self.
editor.qx_node_graph.load_graph_from_mx_doc(doc)
224 self.
editor.qx_node_graph.mx_file_loaded.emit(path)
229 Show a text box with the given text.
231 te_text = QTextEdit()
232 te_text.setReadOnly(
True)
233 te_text.setParent(self.
editor, QtCore.Qt.Window)
234 te_text.setWindowTitle(title)
235 te_text.resize(1000, 800)
239 highlighted_html = jsonHighlighter.highlight(text)
240 te_text.setHtml(highlighted_html)
242 te_text.setPlainText(text)
249 logger.debug(
"> Checking if glTF Procedurals plugin is valid" + str(have_module))
252 logger.debug(f
"> QuiltiX GLTFPT plugin loaded {editor.gltfPT_serializer != None}")
255 return "MaterialX GLTF Procedurals"
__init__(self, font_size="14px")
show_text_box(self, text, title="")
Show a text box with the given text.
__init__(self, editor, root)
Initialize the JSON serializer.
import_gltf_triggered(self, editor)
Import a glTF procedural file into the current graph.
get_gltf_from_graph(self)
Get the JSON for the given MaterialX document.
set_indent(self, indent)
Set the indent for the JSON output.
load_gltf_file(self, inputFile)
export_json_triggered(self, editor)
Export the current graph to a JSON file.
show_gltf_triggered(self)
Show the JSON for the current MaterialX document.
after_ui_init("quiltix.QuiltiXWindow" editor)
After UI initialization, add the MaterialX glTF serializer to the editor.
bool is_valid()
Check if the plugin is valid.
str plugin_name()
Get the name of the plugin.
load_qt_modules()
Function to delay loading of Qt modules until after the QuiltiX UI is initialized.