Skip to content

Commit 1efb70f

Browse files
HackLinjiuyuexushengj
authored andcommitted
[UI] Add ImagePack help text display in ImagePack viewer
1 parent 7da2069 commit 1efb70f

1 file changed

Lines changed: 162 additions & 2 deletions

File tree

src/preppipe_gui_pyside6/toolwidgets/imagepack.py

Lines changed: 162 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from PySide6.QtCore import *
77
from preppipe.assets.assetmanager import *
88
from preppipe.util.imagepack import *
9+
from preppipe.frontend.vnmodel import vnutil,vnparser
910
from ..forms.generated.ui_imagepackwidget import Ui_ImagePackWidget
1011
from ..componentwidgets.imageviewerwidget import ImageViewerWidget
1112
from ..componentwidgets.maskinputwidget import MaskInputWidget
@@ -142,6 +143,11 @@ def __init__(self, parent: QWidget):
142143
zh_cn="该图片包没有差分组合。",
143144
zh_hk="該圖片包沒有差分組合。",
144145
)
146+
_tr_no_description = TR_gui_tool_imagepack.tr("no_description",
147+
en="This image pack contains no description.",
148+
zh_cn="该图片包没有描述。",
149+
zh_hk="該圖片包沒有描述。",
150+
)
145151
_tr_preset_label = TR_gui_tool_imagepack.tr("preset_label",
146152
en="Preset",
147153
zh_cn="预设",
@@ -157,6 +163,155 @@ def __init__(self, parent: QWidget):
157163
zh_cn="应用",
158164
zh_hk="應用",
159165
)
166+
_tr_bracket_round = TR_gui_tool_imagepack.tr("bracket_round",
167+
en="({value})",
168+
zh_cn="({value})",
169+
zh_hk="({value})",
170+
)
171+
_tr_bracket_square = TR_gui_tool_imagepack.tr("bracket_square",
172+
en="[{value}]",
173+
zh_cn="【{value}】",
174+
zh_hk="【{value}】",
175+
)
176+
_tr_using_in_script = TR_gui_tool_imagepack.tr("using_in_script",
177+
en="Using in Script:",
178+
zh_cn="在剧本中使用:",
179+
zh_hk="在剧本中使用:",
180+
)
181+
_tr_colon = TR_gui_tool_imagepack.tr("colon",
182+
en=": ",
183+
zh_cn=":",
184+
zh_hk=":",
185+
)
186+
_tr_comma = TR_gui_tool_imagepack.tr("comma",
187+
en=", ",
188+
zh_cn=",",
189+
zh_hk=",",
190+
)
191+
_tr_place_1 = TR_gui_tool_imagepack.tr("place_1",
192+
en="Place1",
193+
zh_cn="地点1",
194+
zh_hk="地點1",
195+
)
196+
_tr_character_1 = TR_gui_tool_imagepack.tr("character_1",
197+
en="Character1",
198+
zh_cn="角色1",
199+
zh_hk="角色1",
200+
)
201+
202+
def _get_current_composite_name(self) -> str:
203+
ref=self.descriptor.composites_references
204+
if isinstance(self.current_index, list):
205+
layers=self.pack.layers
206+
layer_codes = []
207+
for layer_index in self.current_index:
208+
layer = layers[layer_index]
209+
layer_codes.append(ImagePackDescriptor.get_layer_code(layer.basename))
210+
211+
# 检查是否有预定义的基底组合缩写(如 B0=L1L2...)
212+
if charactersprite_gen := self.pack.opaque_metadata.get("charactersprite_gen", None):
213+
base_options = charactersprite_gen["bases"]
214+
# 尝试匹配基底组合,选择最完全匹配的(包含最多图层的)
215+
best_base_abbr = None
216+
best_base_codes = []
217+
for base_abbr, base_layer_codes in base_options.items():
218+
if set(base_layer_codes).issubset(set(layer_codes)):
219+
# 如果当前基底组合比之前找到的更完全(包含更多图层),则更新最佳匹配
220+
if len(base_layer_codes) > len(best_base_codes):
221+
best_base_abbr = base_abbr
222+
best_base_codes = base_layer_codes
223+
224+
if best_base_abbr:
225+
# 使用最完全匹配的基底组合
226+
remaining_codes = [code for code in layer_codes if code not in best_base_codes]
227+
return best_base_abbr + ''.join(remaining_codes)
228+
229+
# 如果没有匹配的基底组合,直接返回所有图层代码的拼接
230+
return ''.join(layer_codes)
231+
composite_code = self.descriptor.composites_code[self.current_index]
232+
if composite_code in ref:
233+
return ref[composite_code].get()
234+
return composite_code
235+
236+
def _get_place_1_composition(self,composition_text:str) -> str:
237+
return f"{self._tr_place_1.get()}{self._tr_bracket_round.get().format(value=composition_text)}"
238+
239+
def _build_modify_string(self, base_name: str) -> str:
240+
preset_params = [base_name]
241+
if self.current_mask_params:
242+
for mask_type, mask_value in zip(self.descriptor.get_masks(), self.current_mask_params):
243+
mask_name = mask_type.trname.get().lower()
244+
if isinstance(mask_value, Color):
245+
color_hex = mask_value.get_string()
246+
preset_params.append(f"{mask_name}={color_hex}")
247+
return f"{vnutil._tr_imagepreset.get()}{self._tr_bracket_round.get().format(value=self._tr_comma.get().join(preset_params))}"
248+
249+
def _update_description(self):
250+
desc=self.descriptor.description
251+
desc_list:list[str]=[]
252+
match self.descriptor.packtype:
253+
case ImagePackDescriptor.ImagePackType.CHARACTER:
254+
'''角色描述格式(无差分不显示composite):
255+
name(composite_name) (#composite_index)
256+
257+
description
258+
259+
using_in_script
260+
【decl:ch1】
261+
* character:preset(name)
262+
【character_enter:ch1】
263+
'''
264+
base_name=self.descriptor.topref.get()
265+
name,ch1=base_name,self._tr_character_1.get()
266+
if len(self.descriptor.composites_code):
267+
name=f"{base_name}{self._tr_bracket_round.get().format(value=self._get_current_composite_name())}"
268+
# 只有当current_index是预设组合时才显示索引
269+
if isinstance(self.current_index, int):
270+
name=f"{name} {self._tr_bracket_round.get().format(value=f'#{self.current_index}')}"
271+
decl=f"{vnparser.cmd_character_decl.CMD_INFO.name_tr.get()}{self._tr_colon.get()}{ch1}"
272+
preset=f"{vnparser._tr_chdecl_sprite.get()}{self._tr_colon.get()}{self._build_modify_string(base_name)}"
273+
action=f"{vnparser.cmd_character_entry.CMD_INFO.name_tr.get()}{self._tr_colon.get()}{ch1}"
274+
275+
desc_list.append(name)
276+
desc_list.append('')
277+
desc_list.append(desc.get() if desc else self._tr_no_description.get())
278+
desc_list.append('')
279+
desc_list.append(self._tr_using_in_script.get())
280+
desc_list.append(self._tr_bracket_square.get().format(value=decl))
281+
desc_list.append(f" * {preset}")
282+
desc_list.append(self._tr_bracket_square.get().format(value=action))
283+
case ImagePackDescriptor.ImagePackType.BACKGROUND:
284+
'''背景描述格式(无差分不显示composite):
285+
name(composite_name) (#composite_index)
286+
287+
description
288+
289+
using_in_script
290+
【decl:scene1】
291+
* background:preset(name)
292+
【switch_scene:scene1(composite_name)】
293+
'''
294+
name=self.descriptor.topref.get()
295+
base_name=name
296+
composition=''
297+
if len(self.descriptor.composites_code):
298+
composition=self._get_current_composite_name()
299+
name=f"{base_name}{self._tr_bracket_round.get().format(value=composition)}"
300+
name=f"{name} {self._tr_bracket_round.get().format(value=f'#{self.current_index}')}"
301+
decl=f"{vnparser.cmd_scene_decl.CMD_INFO.name_tr.get()}{self._tr_colon.get()}{self._tr_place_1.get()}"
302+
preset=f"{vnparser._tr_scenedecl_background.get()}{self._tr_colon.get()}{self._build_modify_string(base_name)}"
303+
action=f"{vnparser.cmd_switch_scene.CMD_INFO.name_tr.get()}{self._tr_colon.get()}{self._get_place_1_composition(composition)}"
304+
305+
desc_list.append(name)
306+
desc_list.append('')
307+
desc_list.append(desc.get() if desc else self._tr_no_description.get())
308+
desc_list.append('')
309+
desc_list.append(self._tr_using_in_script.get())
310+
desc_list.append(self._tr_bracket_square.get().format(value=decl))
311+
desc_list.append(f" * {preset}")
312+
desc_list.append(self._tr_bracket_square.get().format(value=action))
313+
314+
self.ui.infoLabel.setText('\n'.join(desc_list))
160315

161316
def setData(self, packid : str | None = None, category_kind : ImagePackDescriptor.ImagePackType | None = None):
162317
if category_kind is not None:
@@ -326,6 +481,7 @@ def add_row(kind_tr, parts_list):
326481
self.ui.sourceGroupBox.setLayout(layout)
327482
# setData() 需要尽快返回,让组件先显示出来,后续再更新内容
328483
QMetaObject.invokeMethod(self, "finalize_init", Qt.QueuedConnection)
484+
self._update_description()
329485

330486
@Slot()
331487
def finalize_init(self):
@@ -347,15 +503,16 @@ def charactersprite_update_layer_preset_combobox_text(self):
347503

348504
def update_text(self):
349505
super().update_text()
350-
if self.charactersprite_layer_preset_combobox:
351-
self.charactersprite_update_layer_preset_combobox_text()
506+
self._update_description()
507+
self.charactersprite_update_layer_preset_combobox_text()
352508

353509
@Slot(int)
354510
def handleMaskParamUpdate(self, index : int):
355511
if self.current_mask_params is None:
356512
raise RuntimeError("current_mask_params is None")
357513
widget = self.mask_param_widgets[index]
358514
self.current_mask_params[index] = widget.getValue()
515+
self._update_description()
359516
WaitDialog.long_running_operation_start()
360517
QMetaObject.invokeMethod(self, "updateCurrentPack", Qt.QueuedConnection)
361518

@@ -371,6 +528,7 @@ def handleBackgroundCompositionChange(self):
371528
if self.current_index == new_index:
372529
return
373530
self.current_index = new_index
531+
self._update_description()
374532
QMetaObject.invokeMethod(self, "updateCurrentImage", Qt.QueuedConnection)
375533

376534
def updateCharacterCompositionPanelFromCurrentIndex(self):
@@ -433,6 +591,7 @@ def handleCharacterCompositionChange_Preset(self):
433591
self.updateCharacterCompositionPanelFromCurrentIndex()
434592
if self.current_index != new_index:
435593
self.current_index = new_index
594+
self._update_description()
436595
QMetaObject.invokeMethod(self, "updateCurrentImage", Qt.QueuedConnection)
437596

438597
@Slot()
@@ -452,6 +611,7 @@ def handleCharacterCompositionChange_ByLayer(self):
452611
new_index = current_index if current_index is not None else current_layers
453612
if self.current_index != new_index:
454613
self.current_index = new_index
614+
self._update_description()
455615
QMetaObject.invokeMethod(self, "updateCurrentImage", Qt.QueuedConnection)
456616

457617
@Slot()

0 commit comments

Comments
 (0)