selection_dialog.py 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. # -*- coding: utf-8 -*-
  2. # !/usr/bin/python
  3. #
  4. # Copyright (c) Contributors to the Open 3D Engine Project.
  5. # For complete copyright and license terms please see the LICENSE at the root of this distribution.
  6. #
  7. # SPDX-License-Identifier: Apache-2.0 OR MIT
  8. #
  9. #
  10. # -------------------------------------------------------------------------
  11. import sys, os
  12. from PySide2 import QtCore, QtWidgets
  13. from PySide2.QtCore import QTimer
  14. from PySide2.QtCore import QProcess, Signal, Slot, QTextCodec
  15. from PySide2.QtGui import QTextCursor
  16. from PySide2.QtWidgets import QApplication, QPlainTextEdit
  17. sys.path.insert(0, os.path.abspath('../..'))
  18. import builder
  19. # sys.path.insert(0, os.path.abspath('../ui/'))
  20. # import main_win
  21. sys.path.insert(0, os.path.abspath('../watchdog/'))
  22. import watchdog
  23. class Window(QtWidgets.QDialog):
  24. def __init__(self, parent=None):
  25. super(Window, self).__init__(parent)
  26. self.browseButton = self.create_button("&Browse...", self.browse)
  27. self.findButton = self.create_button("&Find", self.find)
  28. self.removeButton = self.create_button("&Remove", self.remove)
  29. self.startWatch = self.create_button("&Start Watch", self.watch)
  30. self.killButton = self.create_button("&Stop Watch", self.kill)
  31. self.fileComboBox = self.createComboBox("*")
  32. self.textComboBox = self.createComboBox()
  33. # self.directoryComboBox = self.createComboBox(QtCore.QDir.currentPath())
  34. self.sbsarDirectory = "C:/Users/chunghao/Documents/Allegorithmic/Substance Designer/sbsar"
  35. self.directoryComboBox = self.createComboBox(self.sbsarDirectory)
  36. self.extensionLabel = QtWidgets.QLabel("Watch extensions:")
  37. # textLabel = QtWidgets.QLabel("Containing text:")
  38. self.directoryLabel = QtWidgets.QLabel("Watch directory:")
  39. self.filesFoundLabel = QtWidgets.QLabel()
  40. self.wacherLogLabel = QtWidgets.QLabel("Watcher Log")
  41. self.fileListLabel = QtWidgets.QLabel("File List")
  42. self.sbsarPresetLabel = QtWidgets.QLabel("Sbsar Preset")
  43. self.OutputResLabel = QtWidgets.QLabel("Output Size")
  44. self.OutputsLabel = QtWidgets.QLabel("Outputs")
  45. self.watcher_log = QPlainTextEdit()
  46. self.watcher_log.setReadOnly(True)
  47. self.watcher_log.setMaximumBlockCount(10000) # limit console to 10000 lines
  48. self.watcher_log._cursor_output = self.watcher_log.textCursor()
  49. self.create_files_table()
  50. buttonsLayout = QtWidgets.QHBoxLayout()
  51. buttonsLayout.addStretch()
  52. buttonsLayout.addWidget(self.findButton)
  53. # buttonsLayout.addWidget(self.removeButton)
  54. buttonsLayout.addWidget(self.startWatch)
  55. buttonsLayout.addWidget(self.killButton)
  56. self.mainLayout = QtWidgets.QGridLayout()
  57. self.mainLayout.addWidget(self.extensionLabel, 0, 0)
  58. self.mainLayout.addWidget(self.fileComboBox, 0, 1, 1, 2)
  59. # self.mainLayout.addWidget(textLabel, 1, 0)
  60. # self.mainLayout.addWidget(self.textComboBox, 1, 1, 1, 2)
  61. self.mainLayout.addWidget(self.directoryLabel, 2, 0)
  62. self.mainLayout.addWidget(self.wacherLogLabel, 3, 0)
  63. self.mainLayout.addWidget(self.fileListLabel, 4, 0)
  64. self.mainLayout.addWidget(self.directoryComboBox, 2, 1)
  65. self.mainLayout.addWidget(self.browseButton, 2, 2)
  66. self.mainLayout.addWidget(self.watcher_log, 3, 1, 1, 3)
  67. self.mainLayout.addWidget(self.filesTable, 4, 1, 1, 3)
  68. self.mainLayout.addWidget(self.filesFoundLabel, 5, 1)
  69. self.mainLayout.addLayout(buttonsLayout, 6, 0, 1, 3)
  70. self.setLayout(self.mainLayout)
  71. self.setWindowTitle("Substance Builder")
  72. self.resize(800, 300)
  73. self.path = self.directoryComboBox.currentText()
  74. self.groupbox_outputs = QtWidgets.QGroupBox("Outputs")
  75. self.watcher_script = "C:/dccapi/dev/Gems/DccScriptingInterface/LyPy/si_substance/builder/watchdog/__init__.py"
  76. @Slot(str)
  77. def append_output(self, text):
  78. self.watcher_log._cursor_output.insertText(text)
  79. self.scroll_to_last_line()
  80. def scroll_to_last_line(self):
  81. cursor = self.watcher_log.textCursor()
  82. cursor.movePosition(QTextCursor.End)
  83. cursor.movePosition(QTextCursor.Up if cursor.atBlockStart() else
  84. QTextCursor.StartOfLine)
  85. self.watcher_log.setTextCursor(cursor)
  86. def output_text(self, text):
  87. self.watcher_log._cursor_output.insertText(text)
  88. self.watcher_log.scroll_to_last_line()
  89. def browse(self):
  90. # self.directory = QtWidgets.QFileDialog.getExistingDirectory(self, "Find Files",
  91. # QtCore.QDir.currentPath())
  92. self.directory = QtWidgets.QFileDialog.getExistingDirectory(self, "Find watcher folder",
  93. "C:/Users/chunghao/Documents/Allegorithmic/Substance Designer/sbsar")
  94. if self.directory:
  95. if self.directoryComboBox.findText(self.directory) == -1:
  96. self.directoryComboBox.addItem(self.directory)
  97. self.directoryComboBox.setCurrentIndex(self.directoryComboBox.findText(self.directory))
  98. self.path = self.directory
  99. self.find()
  100. return self.path
  101. @staticmethod
  102. def updateComboBox(comboBox):
  103. if comboBox.findText(comboBox.currentText()) == -1:
  104. comboBox.addItem(comboBox.currentText())
  105. def find(self):
  106. self.filesTable.setRowCount(0)
  107. fileName = self.fileComboBox.currentText()
  108. text = self.textComboBox.currentText()
  109. self.path = self.directoryComboBox.currentText()
  110. # self.path = "C:/Users/chunghao/Documents/Allegorithmic/Substance Designer/sbsar"
  111. self.updateComboBox(self.fileComboBox)
  112. self.updateComboBox(self.textComboBox)
  113. self.updateComboBox(self.directoryComboBox)
  114. self.currentDir = QtCore.QDir(self.path)
  115. if not fileName:
  116. fileName = "*"
  117. files = self.currentDir.entryList([fileName],
  118. QtCore.QDir.Files | QtCore.QDir.NoSymLinks)
  119. if text:
  120. files = self.find_files(files, text)
  121. self.show_files(files)
  122. return self.path
  123. def find_files(self, files, text):
  124. progressDialog = QtWidgets.QProgressDialog(self)
  125. progressDialog.setCancelButtonText("&Cancel")
  126. progressDialog.setRange(0, len(files))
  127. progressDialog.setWindowTitle("Find Files")
  128. foundFiles = []
  129. for i in range(len(files)):
  130. progressDialog.setValue(i)
  131. progressDialog.setLabelText("Searching file number %d of %d..." % (i, len(files)))
  132. QtCore.qApp.processEvents()
  133. if progressDialog.wasCanceled():
  134. break
  135. inFile = QtCore.QFile(self.currentDir.absoluteFilePath(files[i]))
  136. if inFile.open(QtCore.QIODevice.ReadOnly):
  137. stream = QtCore.QTextStream(inFile)
  138. while not stream.atEnd():
  139. if progressDialog.wasCanceled():
  140. break
  141. line = stream.readLine()
  142. if text in line:
  143. foundFiles.append(files[i])
  144. break
  145. progressDialog.close()
  146. return foundFiles
  147. def show_files(self, files):
  148. for fn in files:
  149. # file = QtCore.QFile(self.currentDir.absoluteFilePath(fn))
  150. # size = QtCore.QFileInfo(file).size()
  151. fileNameItem = QtWidgets.QTableWidgetItem(fn)
  152. fileNameItem.setFlags(fileNameItem.flags() ^ QtCore.Qt.ItemIsEditable)
  153. # sizeItem = QtWidgets.QTableWidgetItem("%d KB" % (int((size + 1023) / 1024)))
  154. # sizeItem.setTextAlignment(QtCore.Qt.AlignVCenter | QtCore.Qt.AlignRight)
  155. # sizeItem.setFlags(sizeItem.flags() ^ QtCore.Qt.ItemIsEditable)
  156. row = self.filesTable.rowCount()
  157. self.filesTable.insertRow(row)
  158. self.filesTable.setItem(row, 0, fileNameItem)
  159. # self.filesTable.setItem(row, 1, sizeItem)
  160. self.filesFoundLabel.setText("%d file(s) found (Double click on a file to open it)" % len(files))
  161. def create_button(self, text, member):
  162. button = QtWidgets.QPushButton(text)
  163. button.clicked.connect(member)
  164. return button
  165. def createComboBox(self, text=""):
  166. comboBox = QtWidgets.QComboBox()
  167. comboBox.setEditable(True)
  168. comboBox.addItem(text)
  169. comboBox.setSizePolicy(QtWidgets.QSizePolicy.Expanding,
  170. QtWidgets.QSizePolicy.Preferred)
  171. return comboBox
  172. def create_files_table(self):
  173. self.filesTable = QtWidgets.QTableWidget(0, 1)
  174. self.filesTable.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
  175. self.filesTable.setHorizontalHeaderLabels(("File Name", ""))
  176. self.filesTable.horizontalHeader().setSectionResizeMode(0, QtWidgets.QHeaderView.Stretch)
  177. # self.filesTable.verticalHeader().hide()
  178. self.filesTable.verticalHeader().show()
  179. self.filesTable.setShowGrid(True)
  180. self.filesTable.cellActivated.connect(self.open_fileOfitem)
  181. def create_sbsar_params(self):
  182. self.mainLayout.addWidget(self.OutputsLabel, 9, 0)
  183. self.sbsarName = self.item.text().replace(".sbsar", "")
  184. self.groupbox_outputs = QtWidgets.QGroupBox("Outputs")
  185. self.horizontalLayoutOuputs = QtWidgets.QHBoxLayout(self.groupbox_outputs)
  186. self.horizontalLayoutOuputs.setObjectName(("horizontalLayoutOuputs"))
  187. # self.vertical_layout_outputs = QtWidgets.QVBoxLayout(self.groupbox_outputs)
  188. # self.vertical_layout_outputs.setObjectName("vertical_layout_outputs")
  189. self.sbsar_tex_outputs = builder.output_info(self.path, self.sbsarName)['_outputs']
  190. for index, tex in enumerate(self.sbsar_tex_outputs):
  191. print(tex, end=" ")
  192. self.sbsar_tex_outputs[index] = QtWidgets.QCheckBox(self.groupbox_outputs)
  193. self.sbsar_tex_outputs[index].setEnabled(True)
  194. self.sbsar_tex_outputs[index].setChecked(True)
  195. self.sbsar_tex_outputs[index].setObjectName(self.sbsarName+"_"+tex)
  196. self.sbsar_tex_outputs[index].setText(tex)
  197. self.horizontalLayoutOuputs.addWidget(self.sbsar_tex_outputs[index])
  198. self.mainLayout.addWidget(self.groupbox_outputs, 9, 1, 1, 3)
  199. print("\n")
  200. def create_sbsar_presets(self):
  201. self.mainLayout.addWidget(self.sbsarPresetLabel, 7, 0)
  202. self.sbsar_presets = builder.output_info(self.path, self.item.text().replace(".sbsar", ""))['_presets']
  203. self.comboBox_SbsarPreset = QtWidgets.QComboBox(self)
  204. for self.presetItem in self.sbsar_presets:
  205. print(self.presetItem, end=", ")
  206. preset_index = 0
  207. self.comboBox_SbsarPreset.addItem(self.presetItem)
  208. self.comboBox_SbsarPreset.setItemText(preset_index, self.presetItem)
  209. preset_index += 1
  210. self.mainLayout.addWidget(self.comboBox_SbsarPreset, 7, 1, 1, 3)
  211. print("\n")
  212. self.comboBox_SbsarPreset.activated[str].connect(self.preset_selected)
  213. def preset_selected(self, text):
  214. self.selected_text = text
  215. print(self.selected_text)
  216. def create_tex_res(self):
  217. self.mainLayout.addWidget(self.OutputResLabel, 8, 0)
  218. self.resSelector = QtWidgets.QComboBox(self)
  219. self.res = ["512x512", "1024x1024", "2048x2048"]
  220. self.resSelector.addItems(self.res)
  221. self.mainLayout.addWidget(self.resSelector, 8, 1, 1, 3)
  222. self.resSelector.activated[str].connect(self.res_selected)
  223. def res_selected(self):
  224. if self.resSelector.currentIndex() == 0: print("$outputsize@9,9")
  225. elif self.resSelector.currentIndex() == 1: print("$outputsize@10,10")
  226. elif self.resSelector.currentIndex() == 2: print("$outputsize@11,11")
  227. def remove(self):
  228. self.mainLayout.removeWidget(self.groupbox_outputs)
  229. self.groupbox_outputs.close()
  230. def kill(self):
  231. reader.kill()
  232. def watch(self):
  233. reader.start('python', ['-u', window.watcher_script, window.sbsarDirectory])
  234. def open_fileOfitem(self, row, column):
  235. self.item = self.filesTable.item(row, 0)
  236. print(self.path+"/"+self.item.text())
  237. if self.item.text().split(".")[-1] == "sbsar":
  238. self.create_sbsar_presets()
  239. self.create_tex_res()
  240. self.mainLayout.removeWidget(self.groupbox_outputs)
  241. self.groupbox_outputs.close()
  242. self.create_sbsar_params()
  243. elif self.item.text().split(".")[-1] == "sbs":
  244. print("This is a Substance File")
  245. builder.cook_sbsar(self.path+"/"+self.item.text(), builder._context, self.path, self.item.text().split(".")[0])
  246. # builder.output_info()
  247. class ProcessOutputReader(QProcess):
  248. produce_output = Signal(str)
  249. def __init__(self, parent=None):
  250. super().__init__(parent=parent)
  251. # merge stderr channel into stdout channel
  252. self.setProcessChannelMode(QProcess.MergedChannels)
  253. # prepare decoding process' output to Unicode
  254. self._codec = QTextCodec.codecForLocale()
  255. self._decoder_stdout = self._codec.makeDecoder()
  256. # only necessary when stderr channel isn't merged into stdout:
  257. # self._decoder_stderr = codec.makeDecoder()
  258. self.readyReadStandardOutput.connect(self._ready_read_standard_output)
  259. # only necessary when stderr channel isn't merged into stdout:
  260. # self.readyReadStandardError.connect(self._ready_read_standard_error)
  261. @Slot()
  262. def _ready_read_standard_output(self):
  263. raw_bytes = self.readAllStandardOutput()
  264. text = self._decoder_stdout.toUnicode(raw_bytes)
  265. self.produce_output.emit(text)
  266. # only necessary when stderr channel isn't merged into stdout:
  267. # @Slot()
  268. # def _ready_read_standard_error(self):
  269. # raw_bytes = self.readAllStandardError()
  270. # text = self._decoder_stderr.toUnicode(raw_bytes)
  271. # self.produce_output.emit(text)
  272. if __name__ == '__main__':
  273. app = QApplication(sys.argv)
  274. reader = ProcessOutputReader()
  275. window = Window()
  276. reader.produce_output.connect(window.append_output)
  277. reader.start('python', ['-u', window.watcher_script, window.sbsarDirectory])
  278. window.show()
  279. timer = QTimer()
  280. timer.timeout.connect(lambda: None)
  281. timer.start(10)
  282. # sys.exit(reader.kill())
  283. sys.exit(app.exec_())