From a274217da50faa77eea40d1e6dc4bbca7350487e Mon Sep 17 00:00:00 2001 From: Jeffreytsai1004 Date: Mon, 10 Feb 2025 03:57:53 +0800 Subject: [PATCH] Update behaviour.py --- scripts/ui/behaviour.py | 498 ++++++++++++++++++++++++++++++---------- 1 file changed, 377 insertions(+), 121 deletions(-) diff --git a/scripts/ui/behaviour.py b/scripts/ui/behaviour.py index 7877665..a2a789d 100644 --- a/scripts/ui/behaviour.py +++ b/scripts/ui/behaviour.py @@ -35,167 +35,423 @@ class BehaviourTab(QtWidgets.QWidget): def __init__(self, parent=None): super(BehaviourTab, self).__init__(parent) self._setup_ui() - self._create_connections() def _setup_ui(self): """设置UI布局""" - # 创建主布局 - self.main_layout = QtWidgets.QHBoxLayout(self) - self.main_layout.setContentsMargins(2, 2, 2, 2) - self.main_layout.setSpacing(2) + # === Main Layout === + self.main_layout = QtWidgets.QVBoxLayout(self) + self.main_layout.setContentsMargins(4, 4, 4, 4) + self.main_layout.setSpacing(4) - # 创建左右两个主面板 - self.raw_control_widget = self._create_raw_control() - self.blend_shapes_widget = self._create_blend_shapes() + # === 创建水平分割布局 === + self.splitter = QtWidgets.QSplitter(QtCore.Qt.Horizontal) - self.main_layout.addWidget(self.raw_control_widget) - self.main_layout.addWidget(self.blend_shapes_widget) + # === Raw Control 部分 === + raw_control = QtWidgets.QWidget() + raw_layout = QtWidgets.QVBoxLayout(raw_control) + raw_layout.setContentsMargins(4, 4, 4, 4) + raw_layout.setSpacing(4) - def _create_raw_control(self): - """创建Raw Control部分""" - # === Widget === - widget = QtWidgets.QWidget() + # 标题和按钮 + title_widget = QtWidgets.QWidget() + title_layout = QtWidgets.QHBoxLayout(title_widget) + title_layout.setContentsMargins(0, 0, 0, 0) + title_layout.setSpacing(4) - # === Layout === - layout = QtWidgets.QVBoxLayout(widget) - layout.setContentsMargins(5, 5, 5, 5) - layout.setSpacing(5) + title = QtWidgets.QLabel("Raw Control [814/814]") + title.setStyleSheet("color: #00A5FF;") + restore_btn = QtWidgets.QPushButton("恢复表情") + blend_btn = QtWidgets.QPushButton("混合筛选") - # 标题 - title_layout = QtWidgets.QHBoxLayout() - title_label = QtWidgets.QLabel("Raw Control [814/814]") - title_layout.addWidget(title_label) - layout.addLayout(title_layout) + title_layout.addWidget(title) + title_layout.addStretch() + title_layout.addWidget(restore_btn) + title_layout.addWidget(blend_btn) # 搜索框 - self.search_edit = QtWidgets.QLineEdit() - self.search_edit.setPlaceholderText("搜索...") - layout.addWidget(self.search_edit) + search_edit = QtWidgets.QLineEdit() + search_edit.setPlaceholderText("搜索...") # BlendShape列表 - self.blend_list = QtWidgets.QListWidget() - layout.addWidget(self.blend_list) + blend_list = QtWidgets.QListWidget() + blend_list.setStyleSheet(""" + QListWidget { + background: #232323; + border: 1px solid #555555; + } + QListWidget::item { + color: #CCCCCC; + height: 24px; + } + QListWidget::item:selected { + background: #3D3D3D; + } + """) - # 数值调节 - value_layout = QtWidgets.QHBoxLayout() - self.value_spin = QtWidgets.QDoubleSpinBox() - self.value_spin.setValue(0.010) - self.value_spin.setDecimals(3) - value_layout.addWidget(self.value_spin) - layout.addLayout(value_layout) + # 数值控制区域 + value_widget = QtWidgets.QWidget() + value_layout = QtWidgets.QHBoxLayout(value_widget) + value_layout.setContentsMargins(0, 0, 0, 0) + value_layout.setSpacing(4) + + self.raw_spin = QtWidgets.QDoubleSpinBox() + self.raw_spin.setValue(0.010) + self.raw_spin.setDecimals(3) + self.raw_spin.setFixedWidth(60) + + self.raw_slider = QtWidgets.QSlider(QtCore.Qt.Horizontal) + self.raw_slider.setRange(0, 100) + self.raw_slider.setValue(10) # 初始值0.010对应10 + + check = QtWidgets.QCheckBox() + label = QtWidgets.QLabel("全部") + + value_layout.addWidget(self.raw_spin) + value_layout.addWidget(self.raw_slider) + value_layout.addWidget(check) + value_layout.addWidget(label) # 过滤按钮组 - filter_layout = QtWidgets.QHBoxLayout() - self.filter_buttons = [] + filter_widget = QtWidgets.QWidget() + filter_layout = QtWidgets.QHBoxLayout(filter_widget) + filter_layout.setContentsMargins(0, 0, 0, 0) + filter_layout.setSpacing(4) + for text in ["全部", "2", "3", "4", "5", "6"]: btn = QtWidgets.QPushButton(text) btn.setCheckable(True) + btn.setFixedHeight(24) filter_layout.addWidget(btn) - self.filter_buttons.append(btn) - layout.addLayout(filter_layout) - return widget + # 范围控制按钮 + range_widget = QtWidgets.QWidget() + range_layout = QtWidgets.QHBoxLayout(range_widget) + range_layout.setContentsMargins(0, 0, 0, 0) + range_layout.setSpacing(4) - def _create_blend_shapes(self): - """创建Related Blend Shapes部分""" - # === Widget === - widget = QtWidgets.QWidget() + range_plus = QtWidgets.QPushButton("范围+") + range_minus = QtWidgets.QPushButton("范围-") + range_layout.addWidget(range_plus) + range_layout.addWidget(range_minus) - # === Layout === - layout = QtWidgets.QVBoxLayout(widget) - layout.setContentsMargins(5, 5, 5, 5) - layout.setSpacing(5) + # 添加到Raw Control布局 + raw_layout.addWidget(title_widget) + raw_layout.addWidget(search_edit) + raw_layout.addWidget(blend_list) + raw_layout.addWidget(value_widget) + raw_layout.addWidget(filter_widget) + raw_layout.addWidget(range_widget) + + # === Related Blend Shapes 部分 === + related_shapes = QtWidgets.QWidget() + related_layout = QtWidgets.QVBoxLayout(related_shapes) + related_layout.setContentsMargins(4, 4, 4, 4) + related_layout.setSpacing(4) # 标题 - title_layout = QtWidgets.QHBoxLayout() - title_label = QtWidgets.QLabel("Related Blend Shapes [858/858]") - title_layout.addWidget(title_label) - layout.addLayout(title_layout) + related_title = QtWidgets.QLabel("Related Blend Shapes [858/858]") + related_title.setStyleSheet("color: #00A5FF;") # BlendShape列表 - self.related_list = QtWidgets.QListWidget() - layout.addWidget(self.related_list) + related_list = QtWidgets.QListWidget() + related_list.setStyleSheet(""" + QListWidget { + background: #232323; + border: 1px solid #555555; + } + QListWidget::item { + color: #CCCCCC; + height: 24px; + } + QListWidget::item:selected { + background: #3D3D3D; + } + """) - # 数值调节 - value_layout = QtWidgets.QHBoxLayout() - self.related_value_spin = QtWidgets.QDoubleSpinBox() - self.related_value_spin.setValue(0.000) - self.related_value_spin.setDecimals(3) - value_layout.addWidget(self.related_value_spin) - layout.addLayout(value_layout) + # 数值控制区域 + related_value_widget = QtWidgets.QWidget() + related_value_layout = QtWidgets.QHBoxLayout(related_value_widget) + related_value_layout.setContentsMargins(0, 0, 0, 0) + related_value_layout.setSpacing(4) + + self.related_spin = QtWidgets.QDoubleSpinBox() + self.related_spin.setValue(0.000) + self.related_spin.setDecimals(3) + self.related_spin.setFixedWidth(60) + + self.related_slider = QtWidgets.QSlider(QtCore.Qt.Horizontal) + self.related_slider.setRange(0, 100) + self.related_slider.setValue(0) + + related_check = QtWidgets.QCheckBox() + related_label = QtWidgets.QLabel("全部") + + related_value_layout.addWidget(self.related_spin) + related_value_layout.addWidget(self.related_slider) + related_value_layout.addWidget(related_check) + related_value_layout.addWidget(related_label) # 操作按钮组 - 第一行 - op_layout1 = QtWidgets.QHBoxLayout() - op_buttons1 = [ - ("翻转目标", "flip.png"), - ("镜像目标", "mirror.png"), - ("查找翻转目标", "find_flip.png") - ] - for text, icon in op_buttons1: - btn = QtWidgets.QPushButton(text) - if icon: - btn.setIcon(QtGui.QIcon(f"{config.ICONS_PATH}/{icon}")) - op_layout1.addWidget(btn) - layout.addLayout(op_layout1) + op_widget1 = QtWidgets.QWidget() + op_layout1 = QtWidgets.QHBoxLayout(op_widget1) + op_layout1.setContentsMargins(0, 0, 0, 0) + op_layout1.setSpacing(4) + + flip_btn = QtWidgets.QPushButton("翻转目标") + mirror_btn = QtWidgets.QPushButton("镜像目标") + find_flip_btn = QtWidgets.QPushButton("查找翻转目标") + + op_layout1.addWidget(flip_btn) + op_layout1.addWidget(mirror_btn) + op_layout1.addWidget(find_flip_btn) # 操作按钮组 - 第二行 - op_layout2 = QtWidgets.QHBoxLayout() - op_buttons2 = [ - ("添加混合目标", "add.png"), - ("删除混合目标", "delete.png"), - ("批量混合目标", "batch.png") - ] - for text, icon in op_buttons2: - btn = QtWidgets.QPushButton(text) - if icon: - btn.setIcon(QtGui.QIcon(f"{config.ICONS_PATH}/{icon}")) - op_layout2.addWidget(btn) - layout.addLayout(op_layout2) + op_widget2 = QtWidgets.QWidget() + op_layout2 = QtWidgets.QHBoxLayout(op_widget2) + op_layout2.setContentsMargins(0, 0, 0, 0) + op_layout2.setSpacing(4) - # 功能按钮组 - func_layout = QtWidgets.QHBoxLayout() - func_buttons = ["PSD", "BSE", "KEY", "MIR", "ARK", "CTR"] - for text in func_buttons: + add_btn = QtWidgets.QPushButton("添加混合目标") + delete_btn = QtWidgets.QPushButton("删除混合目标") + batch_btn = QtWidgets.QPushButton("批量混合目标") + + op_layout2.addWidget(add_btn) + op_layout2.addWidget(delete_btn) + op_layout2.addWidget(batch_btn) + + # 操作按钮组 - 第三行 + op_widget3 = QtWidgets.QWidget() + op_layout3 = QtWidgets.QHBoxLayout(op_widget3) + op_layout3.setContentsMargins(0, 0, 0, 0) + op_layout3.setSpacing(4) + + rebuild_btn = QtWidgets.QPushButton("重建混合目标") + rebuild_all_btn = QtWidgets.QPushButton("重建所有混合目标") + + op_layout3.addWidget(rebuild_btn) + op_layout3.addWidget(rebuild_all_btn) + + # 添加到Related布局 + related_layout.addWidget(related_title) + related_layout.addWidget(related_list) + related_layout.addWidget(related_value_widget) + related_layout.addWidget(op_widget1) + related_layout.addWidget(op_widget2) + related_layout.addWidget(op_widget3) + + # === 底部功能区域 === + self.bottom_widget = QtWidgets.QWidget() + self.bottom_layout = QtWidgets.QVBoxLayout(self.bottom_widget) + self.bottom_layout.setContentsMargins(4, 0, 4, 0) + self.bottom_layout.setSpacing(0) + + # 设置底部功能区的固定高度 + self.bottom_widget.setFixedHeight(88) + + # 先创建所有控件 + # 创建SpinBox + self.bottom_spin = QtWidgets.QDoubleSpinBox() + self.bottom_spin.setValue(0.000) + self.bottom_spin.setDecimals(3) + self.bottom_spin.setFixedWidth(60) + self.bottom_spin.setFixedHeight(20) + + # 创建Slider + self.bottom_slider = QtWidgets.QSlider(QtCore.Qt.Horizontal) + self.bottom_slider.setRange(0, 100) + self.bottom_slider.setValue(0) + self.bottom_slider.setFixedHeight(16) + + # 设置滑块样式 + slider_style = """ + QSlider::groove:horizontal { + height: 3px; + margin: 0px; + } + QSlider::handle:horizontal { + width: 8px; + height: 8px; + margin: -3px 0; + } + """ + self.bottom_slider.setStyleSheet(slider_style) + + # 然后创建功能按钮区域 + for i in range(1, 5): + widget_name = f'func_widget{i}' + layout_name = f'func_layout{i}' + + widget = QtWidgets.QWidget() + widget.setFixedHeight(22) + + layout = QtWidgets.QHBoxLayout(widget) + layout.setContentsMargins(0, 0, 0, 0) + layout.setSpacing(2) + + setattr(self, widget_name, widget) + setattr(self, layout_name, layout) + + # 调整所有按钮的高度 + for btn in self.findChildren(QtWidgets.QPushButton): + btn.setFixedHeight(20) + + # 功能按钮 - 第一行 + for text in ["PSD", "BSE", "KEY", "MIR", "ARK", "CTR"]: btn = QtWidgets.QPushButton(text) btn.setFixedWidth(40) - func_layout.addWidget(btn) - layout.addLayout(func_layout) + self.func_layout1.addWidget(btn) + self.func_layout1.addStretch() - return widget + # 功能按钮 - 第二行(范围控制) + plus_btn = QtWidgets.QPushButton("+") + plus_btn.setFixedWidth(24) - def _create_connections(self): - """创建信号连接""" - # 搜索框 - self.search_edit.textChanged.connect(self._filter_blend_shapes) + bottom_check = QtWidgets.QCheckBox() + bottom_label = QtWidgets.QLabel("全部") - # 数值调节 - self.value_spin.valueChanged.connect(self._update_raw_value) - self.related_value_spin.valueChanged.connect(self._update_related_value) + self.func_layout2.addWidget(self.bottom_spin) + self.func_layout2.addWidget(self.bottom_slider) + self.func_layout2.addWidget(plus_btn) + self.func_layout2.addWidget(bottom_check) + self.func_layout2.addWidget(bottom_label) - # 过滤按钮组 - for btn in self.filter_buttons: - btn.clicked.connect(self._apply_filter) + # 功能按钮 - 第三行和第四行使用更紧凑的布局 + self.restore_default_btn = QtWidgets.QPushButton("还原默认表情") + self.find_select_btn = QtWidgets.QPushButton("查找选择表情") + self.write_current_btn = QtWidgets.QPushButton("写入当前表情") + + for btn in [self.restore_default_btn, self.find_select_btn, self.write_current_btn]: + btn.setFixedHeight(24) + self.func_layout3.addWidget(btn) + + self.find_panel_btn = QtWidgets.QPushButton("控制面板查找") + self.select_joint_btn = QtWidgets.QPushButton("选择关联关节") + self.write_mirror_btn = QtWidgets.QPushButton("写入镜像表情") + + for btn in [self.find_panel_btn, self.select_joint_btn, self.write_mirror_btn]: + btn.setFixedHeight(24) + self.func_layout4.addWidget(btn) + + # 添加到底部布局 + self.bottom_layout.addWidget(self.func_widget1) + self.bottom_layout.addWidget(self.func_widget2) + self.bottom_layout.addWidget(self.func_widget3) + self.bottom_layout.addWidget(self.func_widget4) + + # 添加到分割器和主布局 + self.splitter.addWidget(raw_control) + self.splitter.addWidget(related_shapes) + + self.main_layout.addWidget(self.splitter) + self.main_layout.addWidget(self.bottom_widget) + + # === 设置样式 === + self._setup_style() + + # 添加信号连接 + self.raw_slider.valueChanged.connect(lambda v: self._on_slider_changed(self.raw_spin, v)) + self.related_slider.valueChanged.connect(lambda v: self._on_slider_changed(self.related_spin, v)) + self.bottom_slider.valueChanged.connect(lambda v: self._on_slider_changed(self.bottom_spin, v)) + + def _setup_style(self): + """设置样式""" + self.setStyleSheet(""" + QWidget { + background: #2D2D2D; + color: #CCCCCC; + } + QLabel { + background: transparent; + } + QLineEdit, QDoubleSpinBox { + background: #3D3D3D; + border: 1px solid #555555; + border-radius: 2px; + padding: 2px 4px; + min-height: 20px; + } + QPushButton { + background: #3D3D3D; + border: 1px solid #555555; + border-radius: 2px; + padding: 2px 4px; + min-height: 22px; + } + QPushButton:hover { + background: #454545; + } + QPushButton:pressed { + background: #2A2A2A; + } + QCheckBox { + spacing: 4px; + background: transparent; + } + QCheckBox::indicator { + width: 14px; + height: 14px; + background: #3D3D3D; + border: 1px solid #555555; + border-radius: 2px; + } + QCheckBox::indicator:checked { + background: #3D3D3D; + image: url(:checkboxChecked.png); + } + QCheckBox::indicator:unchecked { + background: #3D3D3D; + image: url(:checkboxUnchecked.png); + } + QSlider::groove:horizontal { + border: 1px solid #555555; + height: 4px; + background: #3D3D3D; + margin: 0px; + border-radius: 2px; + } + QSlider::handle:horizontal { + background: #CCCCCC; + border: 1px solid #555555; + width: 10px; + height: 10px; + margin: -3px 0; + border-radius: 5px; + } + QSlider::handle:horizontal:hover { + background: #FFFFFF; + } + QListWidget { + background: #232323; + border: 1px solid #555555; + } + QListWidget::item { + height: 22px; + padding: 0px 4px; + border-bottom: 1px solid #383838; + } + QListWidget::item:selected { + background: #4D4D4D; + } + QListWidget::item:hover { + background: #454545; + } + """) + + # 调整分割器的初始大小比例 + self.splitter.setSizes([int(self.width() * 0.45), int(self.width() * 0.55)]) - # ================================ 事件函数 ================================ - def _filter_blend_shapes(self, text): - """过滤BlendShape列表""" - # TODO: 实现过滤逻辑 - pass + # 功能按钮 - 第一行到第四行的布局 + for layout in [self.func_layout1, self.func_layout2, self.func_layout3, self.func_layout4]: + layout.setContentsMargins(0, 0, 0, 0) + layout.setSpacing(2) # 统一按钮间距 - def _update_raw_value(self, value): - """更新Raw Control值""" - # TODO: 实现更新逻辑 - pass - - def _update_related_value(self, value): - """更新Related Blend Shapes值""" - # TODO: 实现更新逻辑 - pass - - def _apply_filter(self): - """应用过滤器""" - # TODO: 实现过滤逻辑 - pass + # 所有功能按钮widget的布局 + for widget in [self.func_widget1, self.func_widget2, self.func_widget3, self.func_widget4]: + widget.setContentsMargins(0, 0, 0, 0) + + def _on_slider_changed(self, spin_box, value): + """处理滑块值变化""" + spin_box.setValue(value / 1000.0) # 将0-100的值转换为0.000-0.100 if __name__ == "__main__": pass