+
    i2j                     @   R t ^ RIt^ RIHtHtHt ^ RIHtHt ^ RI	t	^ RI
t
^ RIt^ RIt^ RIHt ^ RIt^ RIt ! R R4      t]R8X  d    ]! 4       t]P'                  4        R# R#   ] d3   t]! R] 24       ]P.                  ! R	R
]! ]4       24        RtAR# RtAii ; i)u  
File Format Converter v2.1 (Optimized)
统一的文件格式转换工具（性能优化版）
支持：FBX → MB | 3DMAX → FBX | Maya → FBX

核心优化：
1) Maya 相关转换改为“单进程批处理”（避免每个文件重复启动 mayapy）
2) 3ds Max 转换支持并行（可控线程数）
3) 统一临时脚本与 JSON 参数通信，减少重复开销
4) 更稳健的日志与超时控制
N)ttk
filedialog
messagebox)	DND_FILES
TkinterDnD)datetimec                      a  ] tR t^t o R tR tR tR tR tR t	R t
R tR	 tR
 tR tR tR tR tR tR tR tR tR tR tR tR tRtV tR# )FileFormatConverterc                   \         P                  ! 4       V n        V P                  P                  R 4       V P                  P	                  R4       V P                  P                  RR4       . V n        RV n        \        P                  ! RR7      V n
        RV n        RV n        \        P                  ! 4       V n        V P!                  4        V P#                  4        V P%                  4        R# )u,   文件格式转换工具 v2.1（优化版）1020x880FT)value6C:\Program Files\Autodesk\3ds Max 2021\3dsmaxbatch.exe/C:\Program Files\Autodesk\Maya2024\bin\maya.exeN)r   Tkroottitlegeometry	resizablefiles_queueis_processingtk
BooleanVarclean_scenemax_exemaya_exequeueQueue	log_queue_find_software	_build_ui_update_log_displayselfs   &9   /Users/mibo/.openclaw/workspace/一键转换_优化版.py__init__FileFormatConverter.__init__   s    MMO			FG		:&		E5)"==t4PJ  "    c                    . ROpV F0  p\         P                  P                  V4      '       g   K*  W n         M	  . ROpV F1  p\         P                  P                  V4      '       g   K*  W n         R# 	  R# )6C:\Program Files\Autodesk\3ds Max 2024\3dsmaxbatch.exeN)	r(   z6C:\Program Files\Autodesk\3ds Max 2023\3dsmaxbatch.exez6C:\Program Files\Autodesk\3ds Max 2022\3dsmaxbatch.exer   z6C:\Program Files\Autodesk\3ds Max 2020\3dsmaxbatch.exez6C:\Program Files\Autodesk\3ds Max 2019\3dsmaxbatch.exez6C:\Program Files\Autodesk\3ds Max 2018\3dsmaxbatch.exez6C:\Program Files\Autodesk\3ds Max 2017\3dsmaxbatch.exez6C:\Program Files\Autodesk\3ds Max 2016\3dsmaxbatch.exe)z/C:\Program Files\Autodesk\Maya2025\bin\maya.exer   z/C:\Program Files\Autodesk\Maya2023\bin\maya.exez/C:\Program Files\Autodesk\Maya2022\bin\maya.exez/C:\Program Files\Autodesk\Maya2021\bin\maya.exez/C:\Program Files\Autodesk\Maya2020\bin\maya.exe)ospathexistsr   r   )r"   	max_pathsr*   
maya_pathss   &   r#   r   "FileFormatConverter._find_software.   s^    

	 Dww~~d### 


 Dww~~d## $ r&   c                    \         P                  ! V P                  R RR7      pVP                  \         P                  \         P
                  R7       VP                  R4       \         P                  ! VRR;RRR7      P                  R<R7       \         P                  ! VR	R=RR
R7      P                  R>R7       \         P                  ! VRR7      pVP                  \         P
                  ^R>R7       \         P                  ! VR\         P                  ^R^ R7      V n	        V P                  P                  \         P
                  R^<R7       \         P                  ! V P                  RR?RR7      P                  R@R7       \         P                  ! V P                  RRARRR7      P                  4        \         P                  ! V P                  RR=RR
R7      P                  RBR7       V P                  P                  \        4       V P                  P                  RV P                  4       \         P                  ! VRRCR^^
R7      pVP                  \         P                  ^RDR7       \         P                   ! VRV P"                  R=RRR7      P                  \         P$                  R7       \         P                  ! VRRERRR7      P                  \         P$                  RFR7       \         P                  ! VRRCR^
^
R7      pVP                  \         P
                  R^RGR 7       \         P&                  ! V4      pVP                  \         P(                  \         P*                  R7       \         P,                  ! WEP.                  RH^R!7      V n        V P0                  P                  \         P
                  RR"7       VP3                  V P0                  P4                  R#7       \         P                  ! VRR7      pVP                  \         P                  ^RDR7       \         P6                  ! VR$V P8                  ^R=R%7      P                  \         P                  RIR&7       \         P6                  ! VR'V P:                  ^R=R%7      P                  \         P                  R(7       \         P6                  ! VR)V P<                  RJR*R^RR+7      V n        V P>                  P                  \         P                  ^R>R7       \         P                  ! V P                  R,R7      pVP                  \         P(                  \         P
                  RR-7       \         P                  ! VR^2R.7      pVP                  \         P                  R/7       VP                  R4       \         P                  ! VR0RJRRR7      P                  \         P                  ^^R17       \         P6                  ! VR'V P@                  R=\         PB                  RRR2R37      P                  \         P(                  ^R&7       \         P                  ! VR,^(R.7      p	V	P                  \         P                  ^RKR7       V	P                  R4       \D        PF                  ! V	R4R57      V n$        V PH                  P                  \         P                  ^R67       \         P                  ! VR,R7      p
V
P                  \         P
                  R^RLR 7       \         P&                  ! V
4      pVP                  \         P(                  \         P*                  R7       \         PJ                  ! V
\         PL                  VP.                  RHR\         PN                  R77      V n(        V PP                  P                  \         P
                  RR"7       VP3                  V PP                  P4                  R#7       V PS                  R8V PU                  4        R924       R:# )Mi  white)widthbg)sidefillFu   文件格式转换z#2c3e50)textfontr2   fg)padyu2   支持：FBX → MB | 3DMAX → FBX | Maya → FBXz#7f8c8d)r2   )r4   padxr8   z#ecf0f1z#3498db)r2   reliefborderwidthhighlightbackgroundhighlightthicknessT)r4   expandipadyu   📁)r5   r6   r2   u   拖拽文件到这里u    支持格式：.fbx .max .ma .mbz<<Drop>>Options)r5   r6   r2   r9   r8   u7   FBX→MB：清理场景（删除灯光/相机/空组）)r5   variabler6   r2   activebackground)anchoruK   提示：MAX 使用原始唤起方式；Maya 启用单进程批处理提速z#27ae60)rC   r8   u   待处理文件)r4   r>   r9   r8   )yscrollcommandr6   height)r4   r>   )commandu   添加文件)r5   rF   r1   r6   )r3   r9   u   清空)r3      开始转换#2ecc71)r5   rF   r6   r2   r7   rE   rB   z#f8f9fa)r3   r4   r>   )r2   rE   )r4   u   处理日志)r3   r9   r8   hand2)r5   rF   r6   r:   r2   r7   cursordeterminatemode)r4   r8   )wraprD   r6   r2   state[u-   ] ⚙️ 准备就绪，等待转换任务...N)Arial   bold)      )rQ   	   )    rR   )rQ   (   )rT   
   )rQ      rS   )rU   rT   )rQ   rY   rS   )rW      )rQ      )r\   rW   )rW      )ConsolasrV   )rW   rU   )rQ   r[   rS   )rY   rW   )rY   rR   )+r   Framer   packLEFTBOTHpack_propagateLabelSOLID	drop_areadrop_target_registerr   dnd_bind_on_drop
LabelFrameXCheckbuttonr   W	ScrollbarRIGHTYListboxsetfile_listboxconfigyviewButton
_add_files_clear_files_start_conversionconvert_btn
_clear_logFLATr   Progressbarprogress_barTextWORDDISABLEDlog_text_log	_get_time)r"   
left_panel
drop_frameoptions_frame
list_framelist_scroll	btn_frameright_panel
log_headerprogress_frame	log_frame
log_scrolls   &           r#   r   FileFormatConverter._build_uiL   s   XXdiisw?
RWW2773!!%(
"6=RW^clmrrxr  	A
"V"w9	>>Bdd>PXXjW5
RWW2G<*288YZ6?TUWR@
f=YOTTZbTc
&=DY)	--1TV
&H"yY	@@D'@R++I6
DMM:jyG\)0rD2G<
}U $ 0 0(Ww	P QUPT\^\`\`PTPa
c"w9	>>Bd"$$U[d>\]]:4ELa&-BRA
RWWTIll:.bhhRTT2JJz//XgpqrBGGD94#4#4#:#:;HHZG4	BDDr8
		).$//QSZfgllrtryry  AGl  	H
		)(D4E4ERVbchhnpnunuhv99ZndNdNd*?IRY,-	K 	244bw?hhtyyY7bhhRWWTBXXkgbA
RTT"!!%(
.7L		++/4RWW2B4+O
		*8T__<`b`g`g7	<<@DbhhUWD<X+)BGBW=%%e,OONOBDDq1HH[Y7	BGGDrI\\),
RXXBDD1	
%4U5$--"5"56		Adnn&''TUVr&   c                J    \         P                  ! 4       P                  R 4      # )z%H:%M:%S)r   nowstrftimer!   s   &r#   r   FileFormatConverter._get_time   s    ||~&&z22r&   c                <    V P                   P                  V4       R # N)r   put)r"   messages   &&r#   r   FileFormatConverter._log   s    7#r&   c                      V P                   P                  4       pV P                  P                  \        P
                  R7       V P                  P                  \        P                  VR,           4       V P                  P                  \        P                  4       V P                  P                  \        P                  R7       K    \        P                   d     Mi ; iT P                  P                  ^dT P                  4       R# )TrO   
N)r   
get_nowaitr   rt   r   NORMALinsertENDseer   r   Emptyr   afterr    )r"   msgs   & r#   r    'FileFormatConverter._update_log_display   s    	nn//1$$299$5$$RVVS4Z8!!"&&)$$2;;$7{{ 				T556s   CC C%$C%c                H   V P                   P                  \        P                  R 7       V P                   P	                  R\        P
                  4       V P                   P                  \        P                  R 7       V P                  RV P                  4        R24       R# )r   g      ?rP   u   ] 🔄 日志已清空N)	r   rt   r   r   deleter   r   r   r   r!   s   &r#   r{   FileFormatConverter._clear_log   sj    299-S"&&)2;;/		Adnn&''=>?r&   c           	        V P                   P                  P                  VP                  4      pV EF/  pVP	                  R 4      p\
        P                  P                  V4      '       g   K<  \
        P                  P                  V4      ^,          P                  4       pVR9   g   Ky  W0P                  9  g   K  V P                  P                  V4       V P                  P                  \        P                  \
        P                  P                  V4      4       V P!                  RV P#                  4        R\
        P                  P                  V4       24       EK2  	  R# )z{}rP      ] ➕ Added: N).fbx.max.ma.mb)r   r   	splitlistdatastripr)   r*   isfilesplitextlowerr   appendrs   r   r   basenamer   r   )r"   eventfiles	file_pathexts   &&   r#   ri   FileFormatConverter._on_drop   s    		&&uzz2I!-Iww~~i((gg&&y1!4::<88YN^N^=^$$++I6%%,,RVVRWW5E5Ei5PQII$.."2!3=AQAQR[A\@]^_ r&   c           	        \         P                  ! R . ROR7      pV F  pW P                  9  g   K  V P                  P                  V4       V P                  P                  \        P                  \        P                  P                  V4      4       V P                  RV P                  4        R\        P                  P                  V4       24       K  	  R# )u   选择文件)r   	filetypesrP   r   N))u   全部支持格式z*.fbx *.max *.ma *.mb)u
   FBX 文件z*.fbx)u   3ds Max 文件z*.max)u   Maya 文件z	*.ma *.mb)u   所有文件z*.*)r   askopenfilenamesr   r   rs   r   r   r   r)   r*   r   r   r   )r"   r   r   s   &  r#   rw   FileFormatConverter._add_files   s    ++ 	
 I 0 00  ''	2!!((1A1A)1LM		Adnn./}RWW=M=Mi=X<YZ[	 r&   c                    V P                   P                  4        V P                  P                  ^ \        P
                  4       V P                  RV P                  4        R24       R# )rW   rP   u   ] 🗑️ 文件队列已清空N)r   clearrs   r   r   r   r   r   r!   s   &r#   rx    FileFormatConverter._clear_files   sL       BFF+		Adnn&''FGHr&   c                   V P                   '       g   \        P                  ! R R4       R# V P                  '       d   \        P                  ! R R4       R# RV n        V P                  P                  \        P                  RRR7       ^ V P                  R&   \        P                  ! V P                  RR	7      pVP                  4        R# )
u   提示u   队列里还没有文件Nu   正在处理中，请稍候Tu   处理中...z#95a5a6rO   r5   r2   r   )targetdaemon)r   r   showwarningr   rz   rt   r   r   r~   	threadingThread_process_filesstart)r"   ts   & r#   ry   %FileFormatConverter._start_conversion   s    ""8-GH""8-JK!bkk9U%&'"D$7$7E		r&   c           	     
   \        V P                  4      p^ p^ p^ pV P                   Uu. uF+  qUP                  4       P                  R4      '       g   K)  VNK-  	  ppV P                   Uu. uF+  qUP                  4       P                  R4      '       g   K)  VNK-  	  ppV P                   Uu. uF+  qUP                  4       P                  R4      '       g   K)  VNK-  	  ppV P	                  RV P                  4        RV R24       V P	                  R4       V'       Ed.   V P	                  RV P                  4        R\        V4       24       V P                  V4      p	V	 F  w  rpV^,          pV'       dP   V^,          pV P	                  RV P                  4        R\        P                  P                  V
4       RV 24       MNV^,          pV P	                  RV P                  4        R	\        P                  P                  V
4       RV 24       V P                  P                  ^ V P                  WA,          ^d,          4       K  	  V'       Ed-   V P	                  RV P                  4        R
\        V4       24       V F  p
V P                  V
4      w  rV^,          pV'       dP   V^,          pV P	                  RV P                  4        R\        P                  P                  V
4       RV 24       MNV^,          pV P	                  RV P                  4        R	\        P                  P                  V
4       RV 24       V P                  P                  ^ V P                  WA,          ^d,          4       K  	  V'       Ed.   V P	                  RV P                  4        R\        V4       24       V P                  V4      p	V	 F  w  rpV^,          pV'       dP   V^,          pV P	                  RV P                  4        R\        P                  P                  V
4       RV 24       MNV^,          pV P	                  RV P                  4        R	\        P                  P                  V
4       RV 24       V P                  P                  ^ V P                  WA,          ^d,          4       K  	  V P	                  R4       V P	                  RV P                  4        R24       V P	                  RV P                  4        RV RV 24       V P                  P                  ^ V P                  W#4       R# u upi u upi u upi )rW   r   r   rP   u    ] 🚀 开始批量转换（共 u    个文件）u#   ] 🧠 Maya batch mode: FBX→MB x u   ] ✅ z -> u   ] ❌ u-   ] 🛡️ 3ds Max 原始模式：MAX→FBX x u%   ] 🧠 Maya batch mode: Maya→FBX x u   ] 🏁 转换完成u   ] ✅ 成功: u    | ❌ 失败: N)r   r   zF======================================================================)lenr   r   endswithr   r   _convert_fbx_to_mb_batchr)   r*   r   r   r   _update_progress_convert_max_to_fbx_single_convert_maya_to_fbx_batch_conversion_complete)r"   totalsuccessfaildonef	fbx_files	max_files
maya_filesresultsr   okinfos   &            r#   r   "FileFormatConverter._process_files   s\   D$$% $ 0 0O 01GGI4F4Fv4NQQ 0	O $ 0 0O 01GGI4F4Fv4NQQ 0	O!%!1!1X!1AWWY5G5G5Waa!1
X		Adnn&''Gwm\]		( 9II$..*++NsS\~N^_`33I>G'.#	t	qLGII$.."2!36"'':J:J9:U9VVZ[_Z`abAIDII$.."2!36"'':J:J9:U9VVZ[_Z`ab		4#8#8$,:LM (/ 9II$..*++XY\]fYgXhij&	::9E	qLGII$.."2!36"'':J:J9:U9VVZ[_Z`abAIDII$.."2!36"'':J:J9:U9VVZ[_Z`ab		4#8#8$,:LM ' :II$..*++PQTU_Q`Pabc55jAG'.#	t	qLGII$.."2!36"'':J:J9:U9VVZ[_Z`abAIDII$.."2!36"'':J:J9:U9VVZ[_Z`ab		4#8#8$,:LM (/ 			(		Adnn&'':;<		Adnn&'~gYodVTU		444gDi POXs#   &T<T<+&UU,&UUc                "    WP                   R &   R# )r   N)r~   )r"   r   s   &&r#   r   $FileFormatConverter._update_progress)  s    %*'"r&   c                    R V n         V P                  P                  \        P                  RRR7       \
        P                  ! RRV RV 24       R# )FrG   rH   r   u   完成u#   批量转换完成！

✅ 成功: u   
❌ 失败: N)r   rz   rt   r   r   r   showinfo)r"   r   r   s   &&&r#   r   (FileFormatConverter._conversion_complete,  sJ    "biinSH(MgYVdeidj&klr&   c                    \         P                  P                  V P                  4      p\         P                  P	                  VR 4      p\         P                  P                  V4      '       d   V# R# )z
mayapy.exeN)r)   r*   dirnamer   joinr+   )r"   maya_dir
mayapy_exes   &  r#   _get_mayapy_exe#FileFormatConverter._get_mayapy_exe2  sI    77??4==1WW\\(L9
WW^^J77zATAr&   c           
        \         P                  P                  V P                  4      '       g#   VR ,           Uu. uF  q3R,          RR3NK  	  up# V P	                  4       pV'       g#   VR ,           Uu. uF  q3R,          RR3NK  	  up# V P                  V4      p\        P                  ! RRRRR7      ;_uu_ 4       p\        P                  ! WR^R	7       VP                  pR
R
R
4       \        P                  ! RRRRR7      ;_uu_ 4       pVP                  V4       VP                  p	R
R
R
4       \         P                  P                  4       p
RV
R&   RV
R&   RV
R&    VX	X.p\        P                  ! VRRRRV
RR7       \!        VRRR7      ;_uu_ 4       p\        P"                  ! V4      pR
R
R
4       . pXP%                  R. 4       FO  pVP'                  VP%                  RR4      \)        VP%                  R4      4      VP%                  RR4      34       KQ  	  TWy3 F  p \         P*                  ! V4       K  	  # u upi u upi   + '       g   i     ELr; i  + '       g   i     EL>; i  + '       g   i     L; i  \,         d     Kr  i ; i  \,         dj   pTR ,           Uu. uF  q3R,          RRT 23NK  	  Mu upi upu R
p?XX	3 F,  p \         P*                  ! T4       K    \,         d     K*  i ; i	  # R
p?ii ; i  XX	3 F,  p \         P*                  ! T4       K    \,         d     K*  i ; i	  i ; i)itemsinputFu   未找到 Mayau   未找到 mayapy.exewz.jsonutf-8rM   suffixr   encoding)ensure_asciiindentNz.pyPYTHONIOENCODING1MAYA_DISABLE_CIPMAYA_DISABLE_CLIC_IPMTignorei  )capture_outputr5   r   errorsenvtimeoutr)r   r    r   r   u   批处理异常: )r)   r*   r+   r   r   _generate_maya_batch_scripttempfileNamedTemporaryFilejsondumpnamewriteenvironcopy
subprocessrunopenloadgetr   boolunlink	Exception)r"   payloadrM   itemr   scriptjf	json_pathsfscript_pathr   cmdrfoutr   r  pes   &&&               r#   _run_mayapy_batch%FileFormatConverter._run_mayapy_batch7  s   ww~~dmm,,IPQXIYZIY']E+;<IYZZ))+
OVW^O_`O_t']E+ABO_``11$7((c'%ZabbfhIIga@I c ((c%X_``dfHHV''K a jjoo")"%'*#$	{I6CNN3t$Yagjtxyiw772iim 8 GWWY+gr 2Dt4EquuVUWGXYZ ,  -IIaL .G [ a cbb a`` 87 !   	bPWX_P`aP`']E->qc+BCP`aa-IIaL   .	b  -IIaL   .s   I5I	?&II"#8J I62A0J )J	I	"I3	6J	J 	JJL&L
1K	L
LL K55LL
LL ML31M3M	>MM	Mc                   R \        V P                  P                  4       4      R. /pV FL  p\        P                  P                  V4      ^ ,          R,           pVR,          P                  RVRV/4       KN  	  V P                  VRR7      # )r   r   r   r   output	fbx_to_mbrL   )r  r   r  r)   r*   r   r   r   )r"   r   r  fbxmbs   &&   r#   r   ,FileFormatConverter._convert_fbx_to_mb_batchb  s    4 0 0 4 4 67R
 C!!#&q)E1BG##Wc8R$@A  %%gK%@@r&   c                    R . /pV FL  p\         P                  P                  V4      ^ ,          R,           pVR ,          P                  RVRV/4       KN  	  V P	                  VRR7      # )r   z_static.fbxr   r#  maya_to_fbxrL   )r)   r*   r   r   r   )r"   r   r  mfr  s   &&   r#   r   .FileFormatConverter._convert_maya_to_fbx_batchl  sg    B-B''""2&q)M9CG##Wb(C$@A  %%gM%BBr&   c                >    R V RRR RRR RRR RRR R	RR
 RRR R2# )a  # -*- coding: utf-8 -*-
import sys, os, json

json_path = sys.argv[1]
with open(json_path, 'r', encoding='utf-8') as f:
    data = json.load(f)

import maya.standalone
maya.standalone.initialize(name='python')
import maya.cmds as cmds
import maya.mel as mel

MODE = "uW  "


def ensure_fbx_plugin():
    if not cmds.pluginInfo('fbxmaya', query=True, loaded=True):
        cmds.loadPlugin('fbxmaya')


def group_all_models(group_name):
    all_meshes = cmds.ls(type='mesh', long=True) or []
    transforms = []
    for mesh in all_meshes:
        p = cmds.listRelatives(mesh, parent=True, fullPath=True) or []
        transforms.extend(p)
    transforms = list(set(transforms))
    top_level = []
    for obj in transforms:
        parents = cmds.listRelatives(obj, parent=True, fullPath=True)
        if not parents:
            top_level.append(obj)
    if top_level:
        cmds.select(top_level, replace=True)
        cmds.group(name=group_name)


def cleanup_scene(group_name):
    lights = cmds.ls(type=['light', 'ambientLight', 'directionalLight', 'pointLight', 'spotLight'], long=True) or []
    light_tf = []
    for l in lights:
        light_tf.extend(cmds.listRelatives(l, parent=True, fullPath=True) or [])
    if light_tf:
        cmds.delete(list(set(light_tf)))

    cams = cmds.ls(type='camera', long=True) or []
    cam_tf = []
    for cam in cams:
        try:
            if not cmds.camera(cam, query=True, startupCamera=True):
                cam_tf.extend(cmds.listRelatives(cam, parent=True, fullPath=True) or [])
        except Exception:
            pass
    if cam_tf:
        cmds.delete(list(set(cam_tf)))

    for loc in cmds.ls(type='locator', long=True) or []:
        t = cmds.listRelatives(loc, parent=True, fullPath=True) or []
        if t:
            try: cmds.delete(t[0])
            except: pass

    for node in cmds.ls(type='transform', long=True) or []:
        try:
            shapes = cmds.listRelatives(node, shapes=True, fullPath=True, noIntermediate=True) or []
            children = cmds.listRelatives(node, children=True, fullPath=True) or []
            if (not shapes) and (not children):
                cmds.delete(node)
        except Exception:
            pass

    group_all_models(group_name)
    try:
        mel.eval('MLdeleteUnused();')
    except Exception:
        pass


def export_fbx_selected(output_file):
    mel.eval('FBXResetExport')
    mel.eval('FBXExportSmoothingGroups -v true')
    mel.eval('FBXExportHardEdges -v false')
    mel.eval('FBXExportTangents -v true')
    mel.eval('FBXExportSmoothMesh -v true')
    mel.eval('FBXExportInstances -v false')
    mel.eval('FBXExportTriangulate -v false')
    mel.eval('FBXExportShapes -v true')
    mel.eval('FBXExportAnimationOnly -v false')
    mel.eval('FBXExportBakeComplexAnimation -v false')
    mel.eval('FBXExportCameras -v false')
    mel.eval('FBXExportLights -v false')
    mel.eval('FBXExportUpAxis y')
    mel.eval('FBXExportFileVersion -v FBX202000')
    mel.eval('FBXExportScaleFactor 1.0')

    out_dir = os.path.dirname(output_file)
    if out_dir and not os.path.exists(out_dir):
        os.makedirs(out_dir)
    mel.eval('FBXExport -f "%s" -s' % output_file.replace('\\', '/'))


results = []
ensure_fbx_plugin()
cmds.undoInfo(state=False)
cmds.autoSave(enable=False)

for item in data.get('items', []):
    src = item.get('input', '')
    dst = item.get('output', '')
    try:
        if MODE == 'fbx_to_mb':
            cmds.file(f=True, new=True)
            cmds.file(src.replace('\\','/'), i=True, type='FBX', ignoreVersion=True, f=True)

            group_name = os.path.splitext(os.path.basename(src))[0]
            if data.get('clean_scene', True):
                cleanup_scene(group_name)
            else:
                group_all_models(group_name)

            out_dir = os.path.dirname(dst)
            if out_dir and not os.path.exists(out_dir):
                os.makedirs(out_dir)
            cmds.file(rename=dst.replace('\\','/'))
            cmds.file(save=True, type='mayaBinary', force=True)

            ok = os.path.exists(dst)
            info = os.path.basename(dst) if ok else '未生成输出文件'
            results.append(r   z src, 'ok': ok, 'info': infoz)

        else:
            cmds.file(src.replace('\\','/'), open=True, force=True)
            meshes = cmds.ls(type='mesh', long=True) or []
            if not meshes:
                results.append(z, src, 'ok': False, 'info': 'no meshes found'a#  )
                continue

            transforms = []
            for mesh in meshes:
                transforms.extend(cmds.listRelatives(mesh, parent=True, fullPath=True) or [])
            transforms = list(set(transforms))
            if not transforms:
                results.append(z0 src, 'ok': False, 'info': 'no transforms found'u   )
                continue

            cmds.select(transforms, replace=True)
            export_fbx_selected(dst)

            ok = os.path.exists(dst)
            info = os.path.basename(dst) if ok else '未生成输出文件'
            results.append(z5)

    except Exception as e:
        results.append(z! src, 'ok': False, 'info': str(e)z	)

out = r   z resultszg
with open(json_path, 'w', encoding='utf-8') as f:
    json.dump(out, f, ensure_ascii=False, indent=2)
 )r"   rM   s   &&r#   r  /FileFormatConverter._generate_maya_batch_scripts  s    	 
 th $$@A B  !((TU V  !((XY Z $$@A B   AB C w^ ^	r&   c           	         \         P                  P                  V4      ^ ,          R,           pV P                  V4      p\        P
                  ! RRRRR7      ;_uu_ 4       pVP                  V4       VP                  pRRR4        V P                  RVXR	R
.p\        P                  ! VRRRRRR7       \         P                  P                  V4      '       df   \         P                  P                  V4      R,          pR\         P                  P                  V4       RVR R23 \         P                  ! V4       # R \         P                  ! V4       #   + '       g   i     L; i  \         d     # i ; i  \         d     # i ; i   \         P                  ! X4       i   \         d     i i ; i; i  \         d   pR\!        T4      3u Rp?# Rp?ii ; i)rW   r   r   z.msFr   r   Nz
-sceneFilez-v5Ti  r   )r   r5   r   r   r   z (z.2fz MB)g      0A)Fu   未生成输出文件)r)   r*   r   _generate_max_to_fbx_scriptr  r  r	  r  r   r  r  r+   getsizer   r  r  str)	r"   max_pathoutput_path
max_scriptr   r  r  r&  r  s	   &&       r#   r   .FileFormatConverter._convert_max_to_fbx_single  s   	!''**84Q7&@K99+FJ,,#eE\cddhi
#ff e||\8[$PSTs4dD[bkst77>>+..5IBBGG$4$4[$A#B"RHD!QQIIk* 6IIk* ed ! y IIk*   	!#a&= 	!s   A F< "E F< 	AF AF *E-F E>E*	%F< -E;8F< :E;;F< >F	F< FF< F9F('F9(F63F95F66F99F< <GGGGc                2    VP                  R R4      pRV R2# )\/a=  
(
    try
    (
        if maxFileName == "" then
        (
            print "ERROR: No scene file"
            quitMAX #noPrompt
        )

        local matPairs = #()
        local allMaterials = #()

        for obj in geometry do
        (
            if obj != undefined and not isDeleted obj and obj.material != undefined then
            (
                local mat = obj.material
                if classof mat == Multimaterial then
                (
                    for i = 1 to mat.numsubs do
                    (
                        if mat[i] != undefined then appendIfUnique allMaterials mat[i]
                    )
                )
                else appendIfUnique allMaterials mat
            )
        )

        for currentMat in allMaterials do
        (
            local newMat = StandardMaterial()
            newMat.name = currentMat.name + "_MatID"
            newMat.diffuse = random (color 50 50 50) (color 255 255 255)
            newMat.ambient = newMat.diffuse
            newMat.selfIllumAmount = 0
            append matPairs #(currentMat, newMat)
        )

        for obj in geometry do
        (
            if obj != undefined and not isDeleted obj then
            (
                try
                (
                    if superclassof obj == GeometryClass then
                    (
                        convertTo obj Editable_Poly
                        local oldMat = obj.material
                        if oldMat != undefined then
                        (
                            if classof oldMat == Multimaterial then
                            (
                                local newMultiMat = Multimaterial()
                                newMultiMat.name = oldMat.name + "_MatID"
                                newMultiMat.numsubs = oldMat.numsubs
                                for i = 1 to oldMat.numsubs do
                                (
                                    for pair in matPairs do
                                    (
                                        if pair[1] == oldMat[i] then
                                        (
                                            newMultiMat[i] = pair[2]
                                            exit
                                        )
                                    )
                                )
                                obj.material = newMultiMat
                            )
                            else
                            (
                                for pair in matPairs do
                                (
                                    if pair[1] == oldMat then
                                    (
                                        obj.material = pair[2]
                                        exit
                                    )
                                )
                            )
                        )
                    )
                )
                catch()
            )
        )

        try(renderers.current = ART_Renderer())catch()

        FBXExporterSetParam "FileVersion" "FBX202000"
        FBXExporterSetParam "ConvertUnit" "cm"
        FBXExporterSetParam "ScaleFactor" 1.0
        FBXExporterSetParam "UpAxis" "Y"
        FBXExporterSetParam "SmoothingGroups" true
        FBXExporterSetParam "Triangulate" false
        FBXExporterSetParam "PreserveEdgeOrientation" false
        FBXExporterSetParam "EmbedTextures" true
        FBXExporterSetParam "Animation" false
        FBXExporterSetParam "Cameras" false
        FBXExporterSetParam "Lights" false

        outputPath = "a=  "
        makeDir (getFilenamePath outputPath) all:true
        exportFile outputPath #noPrompt selectedOnly:false using:FBXEXP

        if (doesFileExist outputPath) then print "SUCCESS"
        else print "ERROR: FBX not created"
    )
    catch ex
    (
        print ("ERROR: " + (getCurrentException()))
    )
)
)replace)r"   r5  s   &&r#   r1  /FileFormatConverter._generate_max_to_fbx_script-  s4    !))$4eJ #m $Kq q	r&   c                :    V P                   P                  4        R # r   )r   mainloopr!   s   &r#   r  FileFormatConverter.run  s    		r&   )r   rz   rf   rs   r   r   r   r   r   r   r~   r   N)__name__
__module____qualname____firstlineno__r$   r   r   r   r   r    r{   ri   rw   rx   ry   r   r   r   r   r   r   r   r  r   r1  r  __static_attributes____classdictcell__)__classdict__s   @r#   r	   r	      s     #&<WWr3$
7@	`\"I
:Ex+mB
)VAC_D!0sj r&   r	   __main__u   错误: u   错误u   程序启动失败:
)__doc__tkinterr   r   r   r   tkinterdnd2r   r   r)   r  r   r  r   r   r  r	   r@  appr  r  r  print	showerrorr3  r-  r&   r#   <module>rN     s   
  / / - 	      I
 I
X zI!#	   InX)>s1vh'GHHIs   	A$ $B+'BB