66from PySide6 .QtCore import *
77from preppipe .assets .assetmanager import *
88from preppipe .util .imagepack import *
9+ from preppipe .frontend .vnmodel import vnutil ,vnparser
910from ..forms .generated .ui_imagepackwidget import Ui_ImagePackWidget
1011from ..componentwidgets .imageviewerwidget import ImageViewerWidget
1112from ..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