This commit is contained in:
2025-05-12 02:07:24 +08:00
parent 5e5aa4f670
commit ba01b8fc6d
2 changed files with 220 additions and 92 deletions

View File

@@ -132,6 +132,7 @@ class FlowLayout(QtWidgets.QLayout):
item_width = item.sizeHint().width()
item_height = item.sizeHint().height()
# 检查是否需要换行 - 当前项放不下时
next_x = x + item_width + spacing
if next_x - spacing > rect.right() and line_height > 0:
@@ -167,7 +168,7 @@ class RiggingUI(ui_utils.BaseUI):
# 初始化DNA文件列表和按钮尺寸
self.dna_files = []
self.dna_button_size = (140, 170) # 增加按钮尺寸,提供更好的视觉效果
self.dna_button_size = (90, 120) # 保持3:4的宽高比例
# 初始化UI
self.create_widgets()
@@ -229,48 +230,87 @@ class RiggingUI(ui_utils.BaseUI):
self.controls["presets_scroll_area"] = QtWidgets.QScrollArea()
self.controls["presets_scroll_area"].setWidgetResizable(True)
self.controls["presets_scroll_area"].setObjectName("presetsScrollArea")
self.controls["presets_scroll_area"].setMinimumHeight(400) # 大幅增加最小高度,确保能容纳多行按钮
self.controls["presets_scroll_area"].setMinimumWidth(600) # 设置最小宽度,确保有足够空间显示按钮
# 预设内容区域
self.controls["presets_content"] = QtWidgets.QWidget()
self.controls["presets_content"].setObjectName("presetsContent")
self.controls["presets_content"].setMinimumHeight(380) # 保持内容区域最小高度
self.controls["presets_content"].setStyleSheet("""
#presetsContent {
background-color: #252526;
}
""")
# 使用流式布局替代原来的网格布局
self.controls["presets_flow_layout"] = FlowLayout(self.controls["presets_content"])
self.controls["presets_flow_layout"].setObjectName("presetsFlowLayout")
self.controls["presets_flow_layout"].setContentsMargins(10, 10, 10, 10)
self.controls["presets_flow_layout"].setSpacing(15) # 固定间距
self.controls["presets_flow_layout"].setContentsMargins(10, 10, 10, 5) # 进一步减小底部边距
self.controls["presets_flow_layout"].setSpacing(10) # 保持按钮间距
# 设置滚动区域内容
self.controls["presets_scroll_area"].setWidget(self.controls["presets_content"])
# 创建布局分隔器,添加垂直空间和分隔线
self.controls["presets_separator"] = QtWidgets.QFrame()
self.controls["presets_separator"].setFrameShape(QtWidgets.QFrame.HLine)
self.controls["presets_separator"].setFrameShadow(QtWidgets.QFrame.Sunken)
self.controls["presets_separator"].setFixedHeight(1) # 减小分隔线高度
self.controls["presets_separator"].setStyleSheet("background-color: #444444;")
# 预设底部滑块和按钮
self.controls["presets_slider_layout"] = QtWidgets.QHBoxLayout()
self.controls["presets_slider_layout"].setContentsMargins(5, 5, 5, 5)
self.controls["presets_slider_layout"].setSpacing(5)
self.controls["presets_slider_layout"].setContentsMargins(3, 0, 3, 0) # 减小左右内边距
self.controls["presets_slider_layout"].setSpacing(4) # 减小间距
# 数量显示
self.controls["presets_count_label"] = QtWidgets.QLabel("0")
self.controls["presets_count_label"].setObjectName("presetsCountLabel")
self.controls["presets_count_label"].setAlignment(QtCore.Qt.AlignCenter)
self.controls["presets_count_label"].setStyleSheet("font-weight: bold;")
self.controls["presets_count_label"].setStyleSheet("font-weight: bold; font-size: 12px;")
self.controls["presets_count_label"].setFixedWidth(40) # 增加宽度
# 滑块 - 用于调整预览图大小
self.controls["presets_slider"] = QtWidgets.QSlider(QtCore.Qt.Horizontal)
self.controls["presets_slider"].setObjectName("presetsSlider")
self.controls["presets_slider"].setMinimum(20) # 最小值
self.controls["presets_slider"].setMaximum(100) # 最大值
self.controls["presets_slider"].setValue(60) # 默认值
self.controls["presets_slider"].setMinimum(70) # 最小值70对应缩放因子约0.8
self.controls["presets_slider"].setMaximum(130) # 最大值130对应缩放因子约1.2
self.controls["presets_slider"].setValue(100) # 中间值100对应缩放因子1.0
self.controls["presets_slider"].setToolTip("调整预览图大小")
self.controls["presets_slider"].setFixedHeight(22) # 设置固定高度使滑块更粗
self.controls["presets_slider"].setStyleSheet("""
QSlider::groove:horizontal {
border: 1px solid #999999;
height: 8px;
background: #3E3E42;
margin: 2px 0;
border-radius: 4px;
}
QSlider::handle:horizontal {
background: #007ACC;
border: 1px solid #5AB2F5;
width: 16px;
height: 16px;
margin: -5px 0;
border-radius: 8px;
}
QSlider::handle:horizontal:hover {
background: #1C97EA;
}
""")
# 导出预设按钮
self.buttons["export_presets"] = QtWidgets.QPushButton(TEXT("export_presets", "导出预设"))
self.buttons["export_presets"].setObjectName("exportPresetsButton")
self.buttons["export_presets"].setIcon(ui_utils.load_icon("export"))
self.buttons["export_presets"].setFixedHeight(28) # 设置固定高度
# 导入预设按钮
self.buttons["import_presets"] = QtWidgets.QPushButton(TEXT("import_presets", "导入预设"))
self.buttons["import_presets"].setObjectName("importPresetsButton")
self.buttons["import_presets"].setIcon(ui_utils.load_icon("import"))
self.buttons["import_presets"].setFixedHeight(28) # 设置固定高度
# 添加到滑块布局
self.controls["presets_slider_layout"].addWidget(self.controls["presets_count_label"])
@@ -440,14 +480,36 @@ class RiggingUI(ui_utils.BaseUI):
# Presets 组布局
presets_group_layout = QtWidgets.QVBoxLayout(self.controls["presets_group"])
presets_group_layout.setContentsMargins(5, 5, 5, 5)
presets_group_layout.setSpacing(5)
presets_group_layout.setContentsMargins(5, 5, 5, 0) # 移除底部内边距
presets_group_layout.setSpacing(0) # 移除内部间距
# 添加预设滚动区域
presets_group_layout.addWidget(self.controls["presets_scroll_area"])
# 添加预设底部滑块布局
presets_group_layout.addLayout(self.controls["presets_slider_layout"])
# 添加分隔线
self.controls["presets_separator"].setFixedHeight(1) # 减小分隔线高度
self.controls["presets_separator"].setStyleSheet("background-color: #444444;")
presets_group_layout.addWidget(self.controls["presets_separator"])
# 创建滑块容器,与上方内容无缝对接
slider_container = QtWidgets.QWidget()
slider_container.setObjectName("sliderContainer")
slider_container.setFixedHeight(34) # 高度更小
slider_container.setStyleSheet("""
#sliderContainer {
background-color: #222222;
border-top: 1px solid #444444;
margin: 0px;
padding: 0px;
}
""")
slider_container_layout = QtWidgets.QVBoxLayout(slider_container)
slider_container_layout.setContentsMargins(5, 2, 5, 2) # 上下边距更小
slider_container_layout.setSpacing(0)
slider_container_layout.addLayout(self.controls["presets_slider_layout"])
# 添加滑块容器到布局
presets_group_layout.addWidget(slider_container)
# 添加Presets组到Presets面板
presets_layout.addWidget(self.controls["presets_group"])
@@ -560,11 +622,12 @@ class RiggingUI(ui_utils.BaseUI):
main_layout.addWidget(self.controls["bottom_buttons_panel"])
# 设置分割器初始大小
self.splitters["main_splitter"].setSizes([400, 100, 200])
self.splitters["main_splitter"].setSizes([800, 100, 200]) # 进一步增加顶部预设面板的高度
# 设置分割器的伸缩因子
for i in range(self.splitters["main_splitter"].count()):
self.splitters["main_splitter"].setStretchFactor(i, 1)
# 设置分割器的伸缩因子 - 让预设面板获得更多空间
self.splitters["main_splitter"].setStretchFactor(0, 4) # 预设面板占4份
self.splitters["main_splitter"].setStretchFactor(1, 1) # Assets面板占1份
self.splitters["main_splitter"].setStretchFactor(2, 1) # Descriptor面板占1份
# 监听预设内容区域大小变化更新DNA网格布局
self.controls["presets_content"].resizeEvent = lambda event: utils_rigging.on_presets_content_resize(event, self)

View File

@@ -55,6 +55,9 @@ selected_controller = None
original_joint_properties = {}
original_controller_properties = {}
# DNA预览按钮默认尺寸
DEFAULT_DNA_BUTTON_SIZE = (90, 120) # 保持3:4的宽高比例
#========================================== FUNCTIONS ========================================
#------------------------------------ DNA PREVIEW ------------------------------------
@@ -251,87 +254,119 @@ def create_dna_preview_button(dna_info, item_size, on_click_callback):
QPushButton: 创建的DNA预览按钮
"""
try:
# 创建按钮
button = QtWidgets.QPushButton()
button.setObjectName(f"dna_button_{dna_info['name']}")
button.setFixedSize(item_size[0], item_size[1])
button.setProperty("class", "dna-preview-button")
button.setCursor(QtCore.Qt.PointingHandCursor) # 鼠标悬停时显示手型光标
# 调试信息
print(f"创建DNA按钮: {dna_info['name']}, 路径: {dna_info['image_path']}, 尺寸: {item_size}")
# 创建带有图标和文字的垂直布局按钮
dna_button = QtWidgets.QWidget()
dna_button.setFixedSize(item_size[0], item_size[1])
dna_button.setObjectName(f"dna_button_{dna_info['name']}")
dna_button.setCursor(QtCore.Qt.PointingHandCursor)
# 创建垂直布局
layout = QtWidgets.QVBoxLayout(button)
layout.setContentsMargins(0, 0, 0, 0)
layout.setSpacing(2)
# 创建图像容器
image_container = QtWidgets.QWidget()
image_container.setObjectName(f"image_container_{dna_info['name']}")
image_container.setFixedSize(item_size[0], item_size[0] - 10) # 留出底部名称空间
image_container.setStyleSheet("background-color: #2A2A2A; border-radius: 4px;")
layout = QtWidgets.QVBoxLayout(dna_button)
layout.setContentsMargins(2, 2, 2, 2)
layout.setSpacing(1) # 更小的间距
# 创建图像标签
image_label = QtWidgets.QLabel(image_container)
image_label.setObjectName(f"image_{dna_info['name']}")
image_label.setAlignment(QtCore.Qt.AlignCenter)
img_label = QtWidgets.QLabel()
img_label.setAlignment(QtCore.Qt.AlignCenter)
# 使用预缓存加载图像
pixmap = get_pixmap(dna_info['image_path'], item_size[0] - 16, item_size[0] - 26)
image_label.setPixmap(pixmap)
# 加载并缩放图像
img_height = int(item_size[1] * 0.8) # 图像占80%高度
img_width = item_size[0] - 4 # 减去边距
# 创建图像标签布局
image_layout = QtWidgets.QVBoxLayout(image_container)
image_layout.setContentsMargins(8, 8, 8, 8)
image_layout.addWidget(image_label, 0, QtCore.Qt.AlignCenter)
pixmap = QtGui.QPixmap(dna_info['image_path'])
if pixmap.isNull():
print(f"错误: 无法加载图像 {dna_info['image_path']}")
# 创建一个默认的纯色图片
pixmap = QtGui.QPixmap(img_width, img_height)
pixmap.fill(QtGui.QColor(60, 60, 60))
else:
# 缩放图像以适应,但保持纵横比
pixmap = pixmap.scaled(
img_width,
img_height,
QtCore.Qt.KeepAspectRatio,
QtCore.Qt.SmoothTransformation
)
# 创建名称标签
name_label = QtWidgets.QLabel(dna_info['name'])
name_label.setObjectName(f"name_{dna_info['name']}")
name_label.setAlignment(QtCore.Qt.AlignCenter)
name_label.setStyleSheet("""
background-color: transparent;
color: #E0E0E0;
# 设置图像标签的图像
img_label.setPixmap(pixmap)
img_label.setFixedHeight(img_height)
# 创建文本标签
text_label = QtWidgets.QLabel(dna_info['name'])
text_label.setAlignment(QtCore.Qt.AlignCenter)
text_label.setStyleSheet("""
color: white;
font-size: 9px; /* 更小的字体 */
font-weight: bold;
padding: 4px;
margin-top: 0px;
padding-top: 0px;
""")
text_label.setWordWrap(True) # 允许文本换行
text_label.setFixedHeight(15) # 固定文本高度
# 添加控件到布局
layout.addWidget(img_label)
layout.addWidget(text_label)
# 设置整体样式
dna_button.setStyleSheet("""
background-color: #333333;
border: 1px solid #444444;
border-radius: 3px;
""")
# 添加到布局
layout.addWidget(image_container, 0, QtCore.Qt.AlignCenter)
layout.addWidget(name_label, 0, QtCore.Qt.AlignCenter)
# 设置按钮样式
button.setStyleSheet("""
QPushButton {
background-color: #333333;
# 创建透明按钮覆盖整个区域以处理点击
overlay_button = QtWidgets.QPushButton(dna_button)
overlay_button.setObjectName("overlayButton")
overlay_button.setStyleSheet("""
#overlayButton {
background-color: transparent;
border: none;
border-radius: 6px;
padding: 0px;
}
QPushButton:hover {
background-color: #444444;
#overlayButton:hover {
background-color: rgba(0, 122, 204, 0.2);
}
QPushButton:pressed {
background-color: #555555;
#overlayButton:pressed {
background-color: rgba(0, 122, 204, 0.3);
}
""")
overlay_button.resize(dna_button.size())
overlay_button.clicked.connect(lambda: on_click_callback(dna_info['dna_path']))
# 设置按钮数据
button.setProperty("dna_path", dna_info['dna_path'])
# 存储DNA路径属性
dna_button.setProperty("dna_path", dna_info['dna_path'])
# 连接点击信号
button.clicked.connect(lambda: on_click_callback(dna_info['dna_path']))
return button
return dna_button
except Exception as e:
print(f"创建DNA预览按钮失败 ({dna_info.get('name', 'unknown')}): {str(e)}")
import traceback
traceback.print_exc()
# 返回一个简单的替代按钮
fallback_button = QtWidgets.QPushButton(dna_info.get('name', 'DNA'))
fallback_button.setFixedSize(item_size[0], item_size[1])
fallback_widget = QtWidgets.QWidget()
fallback_widget.setFixedSize(item_size[0], item_size[1])
fallback_layout = QtWidgets.QVBoxLayout(fallback_widget)
fallback_layout.setContentsMargins(2, 2, 2, 2)
fallback_label = QtWidgets.QLabel(dna_info.get('name', 'DNA'))
fallback_label.setAlignment(QtCore.Qt.AlignCenter)
fallback_label.setStyleSheet("color: white; font-weight: bold;")
fallback_layout.addWidget(fallback_label)
# 添加点击功能
if on_click_callback:
fallback_button = QtWidgets.QPushButton(fallback_widget)
fallback_button.setStyleSheet("background: transparent; border: none;")
fallback_button.resize(fallback_widget.size())
fallback_button.clicked.connect(lambda: on_click_callback(dna_info.get('dna_path', '')))
return fallback_button
return fallback_widget
# 缓存上一次的布局信息,避免不必要的重新计算
_last_layout_info = {
@@ -353,6 +388,11 @@ def load_dna_preview_buttons(ui_instance):
if not ui_instance or not hasattr(ui_instance, 'controls'):
print("无效的UI实例无法加载DNA预览按钮")
return False
# 检查是否有dna_button_size属性没有则初始化
if not hasattr(ui_instance, 'dna_button_size'):
ui_instance.dna_button_size = DEFAULT_DNA_BUTTON_SIZE
print(f"警告: UI实例没有dna_button_size属性使用默认值{DEFAULT_DNA_BUTTON_SIZE}")
# 获取DNA文件列表
dna_files = ui_instance.dna_files
@@ -751,37 +791,62 @@ def on_presets_slider_changed(ui_instance, value):
print("警告: UI实例无效无法调整预览按钮大小")
return
# 计算新的按钮尺寸 (基于滑块值进行缩放)
# 范围从最小100x120到最大180x220
base_width = 140 # 基础宽度
base_height = 170 # 基础高度
# 检查是否有dna_button_size属性没有则初始化
if not hasattr(ui_instance, 'dna_button_size'):
ui_instance.dna_button_size = DEFAULT_DNA_BUTTON_SIZE
print(f"警告: UI实例没有dna_button_size属性使用默认值{DEFAULT_DNA_BUTTON_SIZE}")
# 调试尺寸信息
print(f"当前按钮基础尺寸: {DEFAULT_DNA_BUTTON_SIZE[0]}x{DEFAULT_DNA_BUTTON_SIZE[1]}")
# 获取滑块范围
min_val = ui_instance.controls["presets_slider"].minimum()
max_val = ui_instance.controls["presets_slider"].maximum()
mid_val = (min_val + max_val) / 2
# 避免除以零
scale_range = max(1, max_val - min_val)
# 确保滑块值在范围内
value = max(min_val, min(max_val, value))
# 计算缩放比例 (0.7 到 1.3)
scale_factor = 0.7 + 0.6 * ((value - min_val) / scale_range)
# 计算缩放比例 - 更平滑的缩放效果
# 以100为中心点低于100缩小高于100放大
if value <= mid_val:
# 从0.8到1.0
scale_factor = 0.8 + 0.2 * ((value - min_val) / (mid_val - min_val))
else:
# 从1.0到1.2
scale_factor = 1.0 + 0.2 * ((value - mid_val) / (max_val - mid_val))
# 应用缩放
new_width = int(base_width * scale_factor)
new_height = int(base_height * scale_factor)
# 确保在合理范围内
scale_factor = max(0.7, min(1.3, scale_factor))
# 确保尺寸在合理范围内
new_width = max(100, min(180, new_width))
new_height = max(120, min(220, new_height))
# 从基础尺寸计算缩放后的尺寸,保持宽高比
new_width = int(DEFAULT_DNA_BUTTON_SIZE[0] * scale_factor)
new_height = int(DEFAULT_DNA_BUTTON_SIZE[1] * scale_factor)
# 确保尺寸不会太小或太大
new_width = max(60, min(130, new_width))
new_height = max(80, min(170, new_height))
# 确保宽高比例正确 - 约为3:4
aspect_ratio = DEFAULT_DNA_BUTTON_SIZE[0] / DEFAULT_DNA_BUTTON_SIZE[1]
# 优先以高度为准,调整宽度
new_width = int(new_height * aspect_ratio)
# 确保宽高为偶数
if new_width % 2 != 0:
new_width += 1
if new_height % 2 != 0:
new_height += 1
# 输出调试信息
print(f"调整DNA按钮大小: {new_width}x{new_height}, 缩放因子: {scale_factor:.2f}")
# 更新按钮尺寸
old_size = ui_instance.dna_button_size
ui_instance.dna_button_size = (new_width, new_height)
# 如果尺寸有明显变化,重新加载DNA预览按钮
if abs(old_size[0] - new_width) > 10 or abs(old_size[1] - new_height) > 10:
# 重新加载预览按钮
load_dna_preview_buttons(ui_instance)
# 重新加载预览按钮
load_dna_preview_buttons(ui_instance)
except Exception as e:
import traceback