MetaFusion/scripts/DNA_Browser.py

238 lines
7.9 KiB
Python
Raw Normal View History

2025-01-11 16:53:48 +08:00
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from PySide2 import QtWidgets, QtCore, QtGui
import maya.cmds as cmds
import os
class DNABrowserWidget(QtWidgets.QWidget):
2025-01-11 18:26:42 +08:00
dna_selected = QtCore.Signal(str) # Signal: emitted when a DNA is selected
2025-01-11 16:53:48 +08:00
def __init__(self, dna_path, img_path, parent=None):
super().__init__(parent)
self.dna_path = dna_path
self.img_path = img_path
self.setup_ui()
self.scan_dna_files()
self.update_grid()
def setup_ui(self):
2025-01-11 18:26:42 +08:00
# Create main layout
2025-01-11 16:53:48 +08:00
self.main_layout = QtWidgets.QVBoxLayout(self)
self.main_layout.setContentsMargins(0, 0, 0, 0)
2025-01-11 18:26:42 +08:00
# Create flow layout container
2025-01-11 16:53:48 +08:00
self.flow_widget = QtWidgets.QWidget()
self.flow_layout = FlowLayout(self.flow_widget)
self.flow_layout.setSpacing(5)
2025-01-11 18:26:42 +08:00
# Create scroll area
2025-01-11 16:53:48 +08:00
self.scroll_area = QtWidgets.QScrollArea()
self.scroll_area.setWidgetResizable(True)
self.scroll_area.setWidget(self.flow_widget)
self.scroll_area.setStyleSheet("""
QScrollArea {
border: none;
background-color: transparent;
}
QScrollBar:vertical {
border: none;
background: #F0F0F0;
width: 8px;
margin: 0px;
}
QScrollBar::handle:vertical {
background: #CCCCCC;
border-radius: 4px;
min-height: 20px;
}
QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical {
height: 0px;
}
""")
self.main_layout.addWidget(self.scroll_area)
def scan_dna_files(self):
2025-01-11 18:26:42 +08:00
"""Scan DNA folder and build index"""
2025-01-11 16:53:48 +08:00
self.dna_files = {}
if not os.path.exists(self.dna_path):
cmds.warning(f"DNA path not found: {self.dna_path}")
return
if not os.path.exists(self.img_path):
cmds.warning(f"Image path not found: {self.img_path}")
return
for file in os.listdir(self.dna_path):
if file.endswith('.dna'):
name = os.path.splitext(file)[0]
dna_file = os.path.join(self.dna_path, file).replace("\\", "/")
2025-01-11 18:26:42 +08:00
# Search for images directly in the img directory
2025-01-11 16:53:48 +08:00
img_file = None
for ext in ['.jpg', '.png', '.jpeg']:
img_path = os.path.join(self.img_path, f"{name}{ext}").replace("\\", "/")
if os.path.exists(img_path):
img_file = img_path
break
self.dna_files[name] = {
'dna_path': dna_file,
'img_path': img_file
}
2025-01-11 18:26:42 +08:00
# Print debug information
2025-01-11 16:53:48 +08:00
print(f"DNA file: {name}")
print(f" DNA path: {dna_file}")
print(f" Image path: {img_file}")
print(f" Image exists: {bool(img_file and os.path.exists(img_file))}")
def update_grid(self):
2025-01-11 18:26:42 +08:00
"""Update DNA grid"""
# Clear existing buttons
2025-01-11 16:53:48 +08:00
for i in reversed(range(self.flow_layout.count())):
self.flow_layout.itemAt(i).widget().deleteLater()
2025-01-11 18:26:42 +08:00
# Calculate button size - reduced to about 1/4 of original
2025-01-11 16:53:48 +08:00
container_width = self.flow_widget.width() or 300
2025-01-11 18:26:42 +08:00
button_width = (container_width - 60) // 6 # 6 buttons per row
button_height = int(button_width * 1.2) # Maintain aspect ratio
2025-01-11 16:53:48 +08:00
2025-01-11 18:26:42 +08:00
# Create DNA sample buttons
2025-01-11 16:53:48 +08:00
for name, info in self.dna_files.items():
dna_btn = self.create_dna_button(name, info, button_width, button_height)
self.flow_layout.addWidget(dna_btn)
def create_dna_button(self, name, info, width, height):
2025-01-11 18:26:42 +08:00
"""Create DNA button"""
2025-01-11 16:53:48 +08:00
btn = QtWidgets.QPushButton()
btn.setFixedSize(width, height)
2025-01-11 18:26:42 +08:00
# Create button layout
2025-01-11 16:53:48 +08:00
layout = QtWidgets.QVBoxLayout(btn)
layout.setContentsMargins(2, 2, 2, 2)
layout.setSpacing(1)
2025-01-11 18:26:42 +08:00
# Create icon label
2025-01-11 16:53:48 +08:00
icon_label = QtWidgets.QLabel()
icon_label.setAlignment(QtCore.Qt.AlignCenter)
if info['img_path']:
pixmap = QtGui.QPixmap(info['img_path'])
scaled_pixmap = pixmap.scaled(
width - 4,
height - 16,
QtCore.Qt.KeepAspectRatio,
QtCore.Qt.SmoothTransformation
)
icon_label.setPixmap(scaled_pixmap)
else:
icon_label.setText("No Image")
2025-01-11 18:26:42 +08:00
icon_label.setStyleSheet("color: #FFFFFF; font-size: 8px;")
2025-01-11 16:53:48 +08:00
2025-01-11 18:26:42 +08:00
# Create text label
2025-01-11 16:53:48 +08:00
text_label = QtWidgets.QLabel(name)
text_label.setAlignment(QtCore.Qt.AlignCenter)
2025-01-11 18:26:42 +08:00
text_label.setStyleSheet("color: #FFFFFF; font-size: 8px;")
2025-01-11 16:53:48 +08:00
layout.addWidget(icon_label)
layout.addWidget(text_label)
2025-01-11 18:26:42 +08:00
# Set style - maintain black background with white text
2025-01-11 16:53:48 +08:00
btn.setStyleSheet("""
QPushButton {
background-color: #303030;
border: 1px solid #202020;
border-radius: 5px;
padding: 2px;
2025-01-11 18:26:42 +08:00
color: #FFFFFF;
2025-01-11 16:53:48 +08:00
}
QPushButton:hover {
background-color: #404040;
border: 1px solid #303030;
}
QPushButton:pressed {
background-color: #202020;
}
""")
btn.setProperty('dna_path', info['dna_path'])
btn.clicked.connect(lambda: self.on_dna_selected(info['dna_path']))
return btn
def on_dna_selected(self, dna_path):
2025-01-11 18:26:42 +08:00
"""Emit signal when DNA is selected"""
2025-01-11 16:53:48 +08:00
self.dna_selected.emit(dna_path)
class FlowLayout(QtWidgets.QLayout):
def __init__(self, parent=None):
super().__init__(parent)
self.itemList = []
self.spacing_x = 5
self.spacing_y = 5
def addItem(self, item):
self.itemList.append(item)
def count(self):
return len(self.itemList)
def itemAt(self, index):
if 0 <= index < len(self.itemList):
return self.itemList[index]
return None
def takeAt(self, index):
if 0 <= index < len(self.itemList):
return self.itemList.pop(index)
return None
def expandingDirections(self):
return QtCore.Qt.Orientations(QtCore.Qt.Orientation(0))
def hasHeightForWidth(self):
return True
def heightForWidth(self, width):
height = self.doLayout(QtCore.QRect(0, 0, width, 0), True)
return height
def setGeometry(self, rect):
super().setGeometry(rect)
self.doLayout(rect, False)
def sizeHint(self):
return self.minimumSize()
def minimumSize(self):
size = QtCore.QSize()
for item in self.itemList:
size = size.expandedTo(item.minimumSize())
return size
def doLayout(self, rect, testOnly):
x = rect.x()
y = rect.y()
lineHeight = 0
for item in self.itemList:
widget = item.widget()
spaceX = self.spacing_x
spaceY = self.spacing_y
nextX = x + item.sizeHint().width() + spaceX
if nextX - spaceX > rect.right() and lineHeight > 0:
x = rect.x()
y = y + lineHeight + spaceY
nextX = x + item.sizeHint().width() + spaceX
lineHeight = 0
if not testOnly:
item.setGeometry(QtCore.QRect(QtCore.QPoint(x, y), item.sizeHint()))
x = nextX
lineHeight = max(lineHeight, item.sizeHint().height())
return y + lineHeight - rect.y()
def create_browser(dna_path, img_path, parent=None):
2025-01-11 18:26:42 +08:00
"""Create and return DNA browser instance"""
2025-01-11 16:53:48 +08:00
return DNABrowserWidget(dna_path, img_path, parent)