You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
138 lines
13 KiB
Python
138 lines
13 KiB
Python
import os
|
|
from pymxs import runtime as rt
|
|
try: from PySide6 import QtWidgets, QtCore, QtGui
|
|
except ImportError: from PySide2 import QtWidgets, QtCore, QtGui
|
|
|
|
import vr4life_engine as eng
|
|
import vr4life_cloud as cld
|
|
import importlib
|
|
importlib.reload(eng)
|
|
importlib.reload(cld)
|
|
|
|
def get_max_window_safe():
|
|
try:
|
|
if hasattr(rt, 'getMAXWindow'): return rt.getMAXWindow()
|
|
except: pass
|
|
for w in QtWidgets.QApplication.topLevelWidgets():
|
|
if w.inherits("QMainWindow") or w.windowTitle().startswith("Autodesk 3ds Max"): return w
|
|
return None
|
|
|
|
class AutoBakeManager(QtWidgets.QDialog):
|
|
def __init__(self):
|
|
super(AutoBakeManager, self).__init__(get_max_window_safe())
|
|
self.setWindowTitle("VR4LIFE AUTO-BAKE V167.0 - MODULAR ENTERPRISE")
|
|
self.resize(950, 1380); self.bake_items = []; self._is_cancelled = False
|
|
p = self.palette(); p.setColor(QtGui.QPalette.Window, QtGui.QColor(43, 43, 43)); self.setPalette(p); self.setAutoFillBackground(True)
|
|
self.init_ui()
|
|
rt.clearListener(); eng.load_bake_elements(self)
|
|
|
|
def init_ui(self):
|
|
layout = QtWidgets.QVBoxLayout(self)
|
|
lbl_t = QtWidgets.QLabel("VR4LIFE - V167.0 (Modular)"); lbl_t.setAlignment(QtCore.Qt.AlignCenter); lbl_t.setStyleSheet("font-size: 24px; font-weight: bold; color: #00FF00;")
|
|
layout.addWidget(lbl_t)
|
|
|
|
self.tabs = QtWidgets.QTabWidget()
|
|
self.tabs.setStyleSheet("QTabWidget::pane { border: 1px solid #777; background: #333; } QTabBar::tab { background: #444; color: #CCC; padding: 10px 15px; font-weight: bold; border: 1px solid #222; } QTabBar::tab:selected { background: #555; color: #00FF00; } QLabel { color: #FFF; font-weight: bold; }")
|
|
|
|
# ABA 1
|
|
t_gen = QtWidgets.QWidget(); l_gen = QtWidgets.QVBoxLayout(t_gen); f_gen = QtWidgets.QFormLayout()
|
|
self.btn_ref = QtWidgets.QPushButton("🔄 RECARREGAR MAPAS"); self.btn_ref.setStyleSheet("background: #555; color: white; height: 35px;"); self.btn_ref.clicked.connect(lambda: eng.load_bake_elements(self))
|
|
self.cmb_bake_elem = QtWidgets.QComboBox(); self.cmb_bake_elem.setStyleSheet("background: white; color: black; font-weight: bold;")
|
|
self.chk_denoise = QtWidgets.QCheckBox("✨ Ativar Denoiser IA"); self.chk_denoise.setStyleSheet("color: #00FFFF; font-weight: bold;"); self.chk_denoise.setChecked(True)
|
|
self.edt_p_bake = QtWidgets.QLineEdit(rt.maxFilePath + "_BAKE_JPG\\" if rt.maxFilePath else "C:\\VR4_BAKE\\"); self.edt_p_bake.setStyleSheet("background: white; color: black;")
|
|
self.edt_p_glb = QtWidgets.QLineEdit(rt.maxFilePath + "_EXPORT_GLB\\" if rt.maxFilePath else "C:\\VR4_GLB\\"); self.edt_p_glb.setStyleSheet("background: white; color: black;")
|
|
self.btn_brw_glb = QtWidgets.QPushButton("..."); self.btn_brw_glb.setStyleSheet("background: #777; color: white; font-weight: bold;"); self.btn_brw_glb.clicked.connect(self.browse_glb_folder)
|
|
h_glb = QtWidgets.QHBoxLayout(); h_glb.addWidget(self.edt_p_glb); h_glb.addWidget(self.btn_brw_glb)
|
|
f_gen.addRow("Mapa:", self.cmb_bake_elem); f_gen.addRow("", self.chk_denoise); f_gen.addRow("Pasta JPG:", self.edt_p_bake); f_gen.addRow("Pasta GLB/ZIP:", h_glb)
|
|
l_gen.addWidget(self.btn_ref); l_gen.addLayout(f_gen); l_gen.addStretch(); self.tabs.addTab(t_gen, "🗂️ 1. Geral")
|
|
|
|
# ABA 2
|
|
t_geo = QtWidgets.QWidget(); l_geo = QtWidgets.QVBoxLayout(t_geo); f_geo = QtWidgets.QFormLayout()
|
|
self.chk_a_weld = QtWidgets.QCheckBox("Fundir Grupos na opção 'AUTO'"); self.chk_a_weld.setStyleSheet("color: #00FF00; font-weight: bold;"); self.chk_a_weld.setChecked(True)
|
|
self.spn_pct = QtWidgets.QDoubleSpinBox(); self.spn_pct.setStyleSheet("background: white; color: black;"); self.spn_pct.setRange(0.1, 100.0); self.spn_pct.setValue(40.0)
|
|
self.spn_min_poly = QtWidgets.QSpinBox(); self.spn_min_poly.setStyleSheet("background: white; color: black;"); self.spn_min_poly.setRange(50, 10000000); self.spn_min_poly.setValue(3000)
|
|
self.spn_max_sz = QtWidgets.QDoubleSpinBox(); self.spn_max_sz.setStyleSheet("background: white; color: black;"); self.spn_max_sz.setRange(10.0, 100000.0); self.spn_max_sz.setValue(800.0)
|
|
self.chk_a_slice = QtWidgets.QCheckBox("Incluir Fatiador no 'AUTO'"); self.chk_a_slice.setStyleSheet("color: white; font-weight: bold;")
|
|
f_geo.addRow(QtWidgets.QLabel("🧩 SOLDADOR:")); f_geo.addRow("", self.chk_a_weld); f_geo.addRow(QtWidgets.QLabel("🛠️ OTIMIZADOR:")); f_geo.addRow("Vertex %:", self.spn_pct); f_geo.addRow("Meta Polys:", self.spn_min_poly); f_geo.addRow(QtWidgets.QLabel("✂️ FATIADOR:")); f_geo.addRow("Cortar se >:", self.spn_max_sz); f_geo.addRow("", self.chk_a_slice)
|
|
l_geo.addLayout(f_geo); l_geo.addStretch(); self.tabs.addTab(t_geo, "📐 2. Geometria")
|
|
|
|
# ABA 3
|
|
t_tex = QtWidgets.QWidget(); l_tex = QtWidgets.QVBoxLayout(t_tex); f_tex = QtWidgets.QFormLayout()
|
|
self.spn_res = QtWidgets.QSpinBox(); self.spn_res.setStyleSheet("background: white; color: black;"); self.spn_res.setRange(128, 8192); self.spn_res.setValue(2048)
|
|
self.chk_a_res = QtWidgets.QCheckBox("Auto-Size"); self.chk_a_res.setStyleSheet("color: #FFD700; font-weight: bold;"); self.chk_a_res.setChecked(True)
|
|
self.s256 = QtWidgets.QDoubleSpinBox(); self.s256.setStyleSheet("background: white; color: black;"); self.s256.setRange(0.1, 100000.0); self.s256.setValue(100.0); self.s256.setPrefix("< 256px: ")
|
|
self.s512 = QtWidgets.QDoubleSpinBox(); self.s512.setStyleSheet("background: white; color: black;"); self.s512.setRange(0.1, 100000.0); self.s512.setValue(300.0); self.s512.setPrefix("< 512px: ")
|
|
self.s1024 = QtWidgets.QDoubleSpinBox(); self.s1024.setStyleSheet("background: white; color: black;"); self.s1024.setRange(0.1, 100000.0); self.s1024.setValue(600.0); self.s1024.setPrefix("< 1024px: ")
|
|
h_sz = QtWidgets.QHBoxLayout(); h_sz.addWidget(self.chk_a_res); h_sz.addWidget(self.s256); h_sz.addWidget(self.s512); h_sz.addWidget(self.s1024)
|
|
for w in [self.chk_a_res, self.s256, self.s512, self.s1024, self.spn_res]: w.valueChanged.connect(self.upd_res_col) if hasattr(w, 'valueChanged') else w.toggled.connect(self.upd_res_col)
|
|
f_tex.addRow("Res Máx (>):", self.spn_res); f_tex.addRow("Escala:", h_sz)
|
|
l_tex.addLayout(f_tex); l_tex.addStretch(); self.tabs.addTab(t_tex, "🎨 3. Textura")
|
|
|
|
# ABA 4
|
|
t_cld = QtWidgets.QWidget(); l_cld = QtWidgets.QVBoxLayout(t_cld); f_cld = QtWidgets.QFormLayout()
|
|
self.e_hash = QtWidgets.QLineEdit(); self.e_hash.setStyleSheet("background: white; color: black; letter-spacing: 2px;"); self.e_hash.setEchoMode(QtWidgets.QLineEdit.Password)
|
|
self.b_conn = QtWidgets.QPushButton("🔄 Conectar CMS"); self.b_conn.setStyleSheet("background: #2E8B57; color: white; height: 30px;"); self.b_conn.clicked.connect(lambda: cld.mock_connect_api(self))
|
|
self.c_chn = QtWidgets.QComboBox(); self.c_chn.setStyleSheet("background: #CCC; color: black;"); self.c_chn.setEnabled(False)
|
|
self.c_pst = QtWidgets.QComboBox(); self.c_pst.setStyleSheet("background: #CCC; color: black;"); self.c_pst.setEnabled(False); self.c_pst.currentIndexChanged.connect(lambda idx: cld.on_post_changed(self, idx))
|
|
self.e_tit = QtWidgets.QLineEdit(); self.e_tit.setStyleSheet("background: #CCC; color: black;"); self.e_tit.setEnabled(False)
|
|
self.e_mp3 = QtWidgets.QLineEdit(); self.e_mp3.setStyleSheet("background: #CCC; color: black;"); self.e_mp3.setEnabled(False)
|
|
self.b_mp3 = QtWidgets.QPushButton("🎵 MP3"); self.b_mp3.setStyleSheet("background: #555; color: white;"); self.b_mp3.setEnabled(False); self.b_mp3.clicked.connect(self.browse_mp3)
|
|
h_mp3 = QtWidgets.QHBoxLayout(); h_mp3.addWidget(self.e_mp3); h_mp3.addWidget(self.b_mp3)
|
|
self.chk_tmb = QtWidgets.QCheckBox("📸 Thumbnail"); self.chk_tmb.setStyleSheet("color: gray; font-weight: bold;"); self.chk_tmb.setEnabled(False)
|
|
self.chk_up = QtWidgets.QCheckBox("🚀 Upload Multipart Automático"); self.chk_up.setStyleSheet("color: gray; font-weight: bold;"); self.chk_up.setEnabled(False)
|
|
f_cld.addRow("Chave:", self.e_hash); f_cld.addRow("", self.b_conn); f_cld.addRow("Canal:", self.c_chn); f_cld.addRow("Ação:", self.c_pst); f_cld.addRow("Título:", self.e_tit); f_cld.addRow("Som:", h_mp3)
|
|
f_cld.addRow("", self.chk_tmb); f_cld.addRow("", self.chk_up)
|
|
l_cld.addLayout(f_cld); l_cld.addStretch(); self.tabs.addTab(t_cld, "☁️ 4. API Cloud")
|
|
layout.addWidget(self.tabs)
|
|
|
|
self.btn_full = QtWidgets.QPushButton("🚀 EXECUTAR TUDO (AUTO)"); self.btn_full.setStyleSheet("background: #00A8FF; color: white; font-weight: bold; font-size: 15px; height: 50px; border-radius: 8px;")
|
|
self.btn_full.clicked.connect(self.run_full_auto); layout.addWidget(self.btn_full)
|
|
|
|
self.tree = QtWidgets.QTreeWidget(); self.tree.setStyleSheet("background: white; color: black;"); self.tree.setHeaderLabels(["Objeto", "Status", "Polys", "Res", "Eixo"])
|
|
self.tree.setColumnWidth(0, 260); self.tree.setColumnWidth(1, 140); self.tree.setColumnWidth(2, 70); self.tree.setColumnWidth(3, 70); self.tree.setColumnWidth(4, 70); self.tree.itemClicked.connect(self.on_item_click)
|
|
layout.addWidget(self.tree)
|
|
|
|
self.pb = QtWidgets.QProgressBar(); self.pb.setAlignment(QtCore.Qt.AlignCenter); self.pb.setStyleSheet("QProgressBar { font-weight: bold; color: black; background: white; } QProgressBar::chunk { background: #00FF00; }"); self.pb.setFormat("Pronto")
|
|
layout.addWidget(self.pb)
|
|
|
|
h_l = QtWidgets.QHBoxLayout()
|
|
self.b1 = QtWidgets.QPushButton("P1: Lista"); self.b1.setStyleSheet("background: #E0E0E0; color: black; font-weight: bold; height: 35px; border-radius: 4px;"); self.b1.clicked.connect(lambda: eng.load_selection(self))
|
|
self.b2 = QtWidgets.QPushButton("P2: Fundir"); self.b2.setStyleSheet("background: #32CD32; color: black; font-weight: bold; height: 35px; border-radius: 4px;"); self.b2.clicked.connect(lambda: eng.attach_grouped_objects(self, False))
|
|
self.b3 = QtWidgets.QPushButton("P3: Opt"); self.b3.setStyleSheet("background: #FF8C00; color: white; font-weight: bold; height: 35px; border-radius: 4px;"); self.b3.clicked.connect(lambda: eng.optimize_geometry(self))
|
|
self.b4 = QtWidgets.QPushButton("P4: Fatiar"); self.b4.setStyleSheet("background: #8B008B; color: white; font-weight: bold; height: 35px; border-radius: 4px;"); self.b4.clicked.connect(lambda: eng.slice_large_objects(self, False))
|
|
self.b5 = QtWidgets.QPushButton("P5: UV"); self.b5.setStyleSheet("background: #E0E0E0; color: black; font-weight: bold; height: 35px; border-radius: 4px;"); self.b5.clicked.connect(lambda: eng.prepare_mesh(self))
|
|
self.b6 = QtWidgets.QPushButton("P6: Bake"); self.b6.setStyleSheet("background: #E0E0E0; color: black; font-weight: bold; height: 35px; border-radius: 4px;"); self.b6.clicked.connect(lambda: eng.process_bake_logic(self, False))
|
|
self.b7 = QtWidgets.QPushButton("P7: Exportar"); self.b7.setStyleSheet("background: #FFD700; color: black; font-weight: bold; height: 35px; border-radius: 4px;"); self.b7.clicked.connect(lambda: cld.finalize_export(self, self.edt_p_bake.text(), self.edt_p_glb.text()))
|
|
for b in [self.b1, self.b2, self.b3, self.b4, self.b5, self.b6, self.b7]: h_l.addWidget(b)
|
|
layout.addLayout(h_l)
|
|
|
|
self.btn_cancel = QtWidgets.QPushButton("CANCELAR / FECHAR"); self.btn_cancel.setStyleSheet("background: #FF0000; color: white; font-weight: bold; height: 40px; border-radius: 8px;"); self.btn_cancel.clicked.connect(self.cancel_all)
|
|
layout.addWidget(self.btn_cancel)
|
|
|
|
def browse_glb_folder(self):
|
|
f = QtWidgets.QFileDialog.getExistingDirectory(self, "Selecione a Pasta GLB")
|
|
if f: self.edt_p_glb.setText(f + "\\")
|
|
|
|
def browse_mp3(self):
|
|
f, _ = QtWidgets.QFileDialog.getOpenFileName(self, "Selecione o Áudio", "", "MP3 (*.mp3)")
|
|
if f: self.e_mp3.setText(f); self.e_mp3.setStyleSheet("background: white; color: green; font-weight: bold;")
|
|
|
|
def upd_res_col(self): eng.upd_res_col(self)
|
|
def get_processable_items(self): return eng.get_processable_items(self)
|
|
|
|
def on_item_click(self, item, column):
|
|
o = rt.getNodeByName(item.text(0))
|
|
if o: rt.select(o); rt.redrawViews()
|
|
|
|
def run_full_auto(self):
|
|
self._is_cancelled = False
|
|
if not rt.execute("selection as array"): QtWidgets.QMessageBox.warning(self, "Aviso", "Selecione algo!"); return
|
|
if self.chk_a_weld.isChecked() and not self._is_cancelled: eng.attach_grouped_objects(self, True)
|
|
eng.load_selection(self)
|
|
if not self.get_processable_items(): return
|
|
if self.bake_items and not self._is_cancelled: eng.optimize_geometry(self)
|
|
if self.chk_a_slice.isChecked() and not self._is_cancelled: eng.slice_large_objects(self, True)
|
|
if not self._is_cancelled: eng.prepare_mesh(self)
|
|
if not self._is_cancelled: time.sleep(1.0); eng.process_bake_logic(self, True)
|
|
|
|
def cancel_all(self): self._is_cancelled = True; self.close() |