+
    ;iv                     X   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It^ RIHtHt  ! R R4      t]R8X  d    ]! 4       t]P/                  4        R# R#   ] d3   t]! R	] 24       ]P6                  ! 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)datetime)ThreadPoolExecutoras_completedc                      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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
        \        P                  ! ^R7      V n        RV n        RV n        RV n        \         P"                  ! 4       V n        V P'                  4        V P)                  4        V P+                  4        V P-                  4        V P/                  RV P1                  4        R	V P                   24       V P/                  RV P1                  4        R
V P                   24       R# )u,   文件格式转换工具 v2.1（优化版）1020x880FT)valueN6C:\Program Files\Autodesk\3ds Max 2021\3dsmaxbatch.exe/C:\Program Files\Autodesk\Maya2024\bin\maya.exe[z] 3ds Max path: z] Maya path: )r   Tkroottitlegeometry	resizablefiles_queueis_processingtk
BooleanVarclean_sceneIntVarmax_parallelstart_tsmax_exemaya_exequeueQueue	log_queue_find_software_apply_modern_style	_build_ui_update_log_display_log	_get_timeselfs   &D   /Users/mibo/.openclaw/workspace/一键转换_优化版_2021优先.py__init__FileFormatConverter.__init__   s   MMO			FG		:&		E5)"==t4IIA.PJ  "  " 			Adnn&''7~FG		Adnn&'}T]]ODE    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# )r   N)	r   z6C:\Program Files\Autodesk\3ds Max 2024\3dsmaxbatch.exez6C:\Program Files\Autodesk\3ds Max 2023\3dsmaxbatch.exez6C:\Program Files\Autodesk\3ds Max 2022\3dsmaxbatch.exez6C:\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_pathsr2   
maya_pathss   &   r,   r$   "FileFormatConverter._find_software7   s^    

	 Dww~~d### 


 Dww~~d## $ r/   c                    \         P                  ! 4       p VP                  R 4       VP	                  R^R7       VP	                  R^R7       R#   \         d     L5i ; i)clamTProgressbar)	thickness	TCombobox)paddingN)r   Style	theme_use	Exception	configure)r+   styles   & r,   r%   'FileFormatConverter._apply_modern_styleU   sT    			OOF# 	"5Q/  		s   A AAc                   \         P                  ! V P                  R RR7      pVP                  \         P                  \         P
                  R7       VP                  R4       \         P                  ! VRRBRRR7      P                  RCR7       \         P                  ! VR	RDRR
R7      P                  RER7       \         P                  ! VRR7      pVP                  \         P
                  ^RER7       \         P                  ! VR\         P                  ^R^ R7      V n	        V P                  P                  \         P
                  R^<R7       \         P                  ! V P                  RRFRR7      P                  RGR7       \         P                  ! V P                  RRHRRR7      P                  4        \         P                  ! V P                  RRDRR
R7      P                  RIR7       V P                  P                  \        4       V P                  P                  RV P                  4       \         P                  ! VRRJR^^
R7      pVP                  \         P                  ^RKR7       \         P                   ! VRV P"                  RDRRR7      P                  \         P$                  R7       \         P                  ! VRR7      pVP                  \         P$                  RLR7       \         P                  ! VRRDRR7      P                  \         P                  R7       \&        P(                  ! V^R. RMOV P*                  R 7      pVP                  \         P                  R7       \         P                  ! VR!RNRR"R7      P                  \         P$                  RLR7       \         P                  ! VR#RJR^
^
R7      pVP                  \         P
                  R^ROR$7       \         P,                  ! V4      pVP                  \         P.                  \         P0                  R7       \         P2                  ! WgP4                  RP^R%7      V n        V P6                  P                  \         P
                  RR&7       VP9                  V P6                  P:                  R'7       \         P                  ! VRR7      pVP                  \         P                  ^RKR7       \         P<                  ! VR(V P>                  ^RDR)7      P                  \         P                  RQR*7       \         P<                  ! VR+V P@                  ^RDR)7      P                  \         P                  R7       \         P<                  ! VR,V PB                  RRR-R^R"R.7      V n"        V PD                  P                  \         P                  ^RER7       \         P                  ! V P                  R/R7      p	V	P                  \         P.                  \         P
                  RR07       \         P                  ! V	R^2R17      p
V
P                  \         P                  R27       V
P                  R4       \         P                  ! V
R3RRRRR7      P                  \         P                  ^^R47       \         P<                  ! V
R+V PF                  RD\         PH                  RRR5R67      P                  \         P.                  ^R*7       \         P                  ! V	R/^(R17      pVP                  \         P                  ^RSR7       VP                  R4       \&        PJ                  ! VR7R87      V n&        V PL                  P                  \         P                  ^R97       \         P                  ! V	R:RDR/R;R7      V n'        V PN                  P                  \         P$                  ^RTR<7       \         P                  ! V	R=RDR/R;R7      V n(        V PP                  P                  \         P$                  ^RUR<7       \         P                  ! V	R/R7      pVP                  \         P
                  R^RVR$7       \         P,                  ! V4      pVP                  \         P.                  \         P0                  R7       \         PR                  ! V\         PT                  VP4                  RPR\         PV                  R>7      V n,        V PX                  P                  \         P
                  RR&7       VP9                  V PX                  P:                  R'7       V P[                  R?V P]                  4        R@24       RA# )Wi  white)widthbg)sidefillFu   文件格式转换z#2c3e50)textfontrF   fg)padyu2   支持：FBX → MB | 3DMAX → FBX | Maya → FBXz#7f8c8d)rF   )rH   padxrL   z#ecf0f1z#3498db)rF   reliefborderwidthhighlightbackgroundhighlightthicknessT)rH   expandipadyu   📁)rI   rJ   rF   u   拖拽文件到这里u    支持格式：.fbx .max .ma .mbz<<Drop>>Options)rI   rJ   rF   rM   rL   u7   FBX→MB：清理场景（删除灯光/相机/空组）)rI   variablerJ   rF   activebackground)anchor)rW   rL   u   MAX 并行数：)rG   readonly)rE   statevaluestextvariableu?   提示：MAX 支持并行；Maya 启用单进程批处理提速z#27ae60u   待处理文件)rH   rR   rM   rL   )yscrollcommandrJ   height)rH   rR   )commandu   添加文件)rI   r^   rE   rJ   )rG   rM   u   清空   开始转换#2ecc71)rI   r^   rJ   rF   rK   r]   rV   z#f8f9fa)rG   rH   rR   )rF   r]   )rH   u   处理日志)rG   rM   rL   hand2)rI   r^   rJ   rN   rF   rK   cursordeterminatemode)rH   rL   u   状态：待命z#34495e)rW   rM   rL   u   用时：00:00)wrapr\   rJ   rF   rY   r   u-   ] ⚙️ 准备就绪，等待转换任务...N)Arial   bold)      )rg   	   )    rh   )rg   (   )rj   
   )rg      ri   )rk   rj   )rg   ro   ri   )rm      )   rm   )            )rg   rr   )rm      )Consolasrl   )rm   rk   )rg   rq   ri   )ro   rm   )rt   rm   )rt   rr   )ro   rh   )/r   Framer   packLEFTBOTHpack_propagateLabelSOLID	drop_areadrop_target_registerr   dnd_bind_on_drop
LabelFrameXCheckbuttonr   Wr   Comboboxr   	ScrollbarRIGHTYListboxsetfile_listboxconfigyviewButton
_add_files_clear_files_start_conversionconvert_btn
_clear_logFLATProgressbarprogress_barstatus_label
time_labelTextWORDDISABLEDlog_textr(   r)   )r+   
left_panel
drop_frameoptions_framemax_parallel_framemax_parallel_combo
list_framelist_scroll	btn_frameright_panel
log_headerprogress_frame	log_frame
log_scrolls   &             r,   r&   FileFormatConverter._build_ui^   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XXm@rtt&9
#*<<T[\aagigngnao \\*<AZ1=DL]L]_RWW-
W"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[7H|(1iAbdd&A((;5EL&/I?BDDr?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rY   
N)r#   
get_nowaitr   r   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      ?r   u   ] 🔄 日志已清空N)	r   r   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{}r      ] ➕ Added: N).fbx.max.ma.mb)r   r   	splitlistdatastripr1   r2   isfilesplitextlowerr   appendr   r   r   basenamer(   r)   )r+   eventfiles	file_pathexts   &&   r,   r   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   	filetypesr   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   r   r   r   r   r1   r2   r   r(   r)   )r+   r   r   s   &  r,   r   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# )rm   r   u   ] 🗑️ 文件队列已清空N)r   clearr   r   r   r   r(   r)   r*   s   &r,   r    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        \        P                  ! 4       V n        V P                  P                  \        P                  RRR7       ^ V P                  R&   V P                  P                  R	R
7       V P                  4        \        P                  ! V P                  RR7      pVP!                  4        R# )u   提示u   队列里还没有文件Nu   正在处理中，请稍候Tu   处理中...z#95a5a6rY   rI   rF   r   u   状态：处理中rI   )targetdaemon)r   r   showwarningr   timer   r   r   r   r   r   r   _update_elapsed_time	threadingThread_process_filesstart)r+   ts   & r,   r   %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                   P#                  4       4      ^4      4      pV P	                  RV P                  4        R
\        V4       RV 24       \%        VR7      ;_uu_ 4       pV Uu/ uF  q^P'                  V P(                  V4      VbK!  	  pp\+        V4       EF  pVV,          p
 VP-                  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       EK  	  RRR4       V'       Ed.   V P	                  RV P                  4        R\        V4       24       V P3                  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 P4                  W#4       R# u upi u upi u upi u upi   \.         d   pR\1        T4      r Rp?ELRp?ii ; i  + '       g   i     EL; i)rm   r   r   r   u    ] 🚀 开始批量转换（共 u    个文件）u#   ] 🧠 Maya batch mode: FBX→MB x u   ] ✅ z -> u   ] ❌ u)   ] ⚡ 3ds Max 并行模式：MAX→FBX x z | workers=)max_workersFNu%   ] 🧠 Maya batch mode: Maya→FBX x u   ] 🏁 转换完成u   ] ✅ 成功: u    | ❌ 失败: )r   r   zF======================================================================)lenr   r   endswithr(   r)   _convert_fbx_to_mb_batchr1   r2   r   r   r   _update_progressmaxminintr   getr   submit_convert_max_to_fbx_singler	   resultr?   str_convert_maya_to_fbx_batch_conversion_complete)r+   totalsuccessfaildonef	fbx_files	max_files
maya_filesresultsr   okinfoworkersex
future_mapfuturees   &                 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!ST%6%6%:%:%<!=qABGII$..*++TUXYbUcTddopwoxyz#88BXabXaSTii(G(GKQNXa
b*:6F *6 2I1#)==? AID1		Adnn&6%7vbgg>N>Ny>Y=ZZ^_c^d"ef			Adnn&6%7vbgg>N>Ny>Y=ZZ^_c^d"efIIOOAt'<'<dlS>PQ 7 9& :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Dy POX0 c
 % 1#(#a&D1 988sr   &WW+&WW,&WWX%W!;XW&(X9CX!X&X	1X	=XX	XX	c                    \        ^ \        V4      4      p\        V^<4      w  r#\        V^<4      w  rBV'       d   VR RVR RVR 2# VR RVR 2# )rm   02d:)r   r   divmod)r+   secmshs   &&   r,   _format_duration$FileFormatConverter._format_durationU  s_    !SXc2a}-.!C!C!C)FqgQqg4FFr/   c                J   V P                   '       d   V P                  '       d}   \        P                  ! 4       V P                  ,
          pV P                  P	                  R V P                  V4       2R7       V P                  P                  RV P                  4       R# R# R# )u	   用时：r   i,  N)	r   r   r   r   r   r  r   r   r   )r+   elapseds   & r,   r   (FileFormatConverter._update_elapsed_time[  sr    $---iikDMM1GOO"")D4I4I'4R3S(T"UIIOOC!:!:; #0r/   c                "    WP                   R &   R# )r   N)r   )r+   r   s   &&r,   r   $FileFormatConverter._update_progressa  s    %*'"r/   c                   R V n         V P                  '       d'   \        P                  ! 4       V P                  ,
          M^ pV P                  P	                  \
        P                  RRR7       V P                  P	                  RR7       V P                  P	                  RV P                  V4       2R7       \        P                  ! RRV R	V R
V P                  V4       24       R# )Fr_   r`   r   u   状态：已完成r   u   总用时：u   完成u#   批量转换完成！

✅ 成功: u   
❌ 失败: u   
⏱️ 用时: N)r   r   r   r   r   r   r   r   r   r  r   showinfo)r+   r   r   total_elapseds   &&& r,   r   (FileFormatConverter._conversion_completed  s    "7;}}}		dmm3!biinS  &: ;l43H3H3W2X$YZH(MgYVdeidjj{  }A  }R  }R  S`  }a  |b  'c  	dr/   c                    \         P                  P                  V P                  4      p\         P                  P	                  VR 4      p\         P                  P                  V4      '       d   V# R# )z
mayapy.exeN)r1   r2   dirnamer    joinr3   )r+   maya_dir
mayapy_exes   &  r,   _get_mayapy_exe#FileFormatConverter._get_mayapy_exem  sI    77??4==1WW\\(L9
WW^^J77zATAr/   c                d   \         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&    \        P                  ! 4       p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  	  V P-                  RV P/                  4        RV RV P1                  \        P                  ! 4       V,
          4       24       TWy3 F  p \         P2                  ! V4       K  	  # u upi u upi   + '       g   i     EL; i  + '       g   i     EL; i  + '       g   i     EL; i  \4         d     Ks  i ; i  \4         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 \         P2                  ! T4       K    \4         d     K*  i ; i	  # R
p?ii ; i  XX	3 F,  p \         P2                  ! T4       K    \4         d     K*  i ; i	  i ; i)itemsinputFu   未找到 Mayau   未找到 mayapy.exewz.jsonutf-8re   suffixr   encoding)ensure_asciiindentNz.pyPYTHONIOENCODING1MAYA_DISABLE_CIPMAYA_DISABLE_CLIC_IPMTignorei  )capture_outputrI   r0  errorsenvtimeoutr)r0  r   r  r  r   u   ] ⏱️ Maya batch u	    用时: u   批处理异常: )r1   r2   r3   r    r'  _generate_maya_batch_scripttempfileNamedTemporaryFilejsondumpnamewriteenvironcopyr   
subprocessrunopenloadr   r   boolr(   r)   r  unlinkr?   )r+   payloadre   itemr&  scriptjf	json_pathsfscript_pathr:  t0cmdrfoutr  r<  pr  s   &&&                r,   _run_mayapy_batch%FileFormatConverter._run_mayapy_batchr  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")"%'*#$	B{I6CNN3t$Yagjtxyiw772iim 8 GWWY+gr 2Dt4EquuVUWGXYZ ,II$..*++?vYtOdOdeienenepsueuOvNwxy  -IIaL .K [ a cbb a`` 877 !   	bPWX_P`aP`']E->qc+BCP`aa-IIaL   .	b  -IIaL   .s   J*5J/?&J4K#AL 0KCL K04K	K	K-	'	L 0K?>K?M6M1L0/M17M68M9 MM+*M+1M66M9 9N/NN/N)	%N/(N)	)N/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_mbrd   )rK  r   r   r1   r2   r   r   rY  )r+   r   rM  fbxmbs   &&   r,   r   ,FileFormatConverter._convert_fbx_to_mb_batch  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_fbxrd   )r1   r2   r   r   rY  )r+   r   rM  mfrW  s   &&   r,   r   .FileFormatConverter._convert_maya_to_fbx_batch  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+   re   s   &&r,   r>  /FileFormatConverter._generate_maya_batch_script  s    	 
 th $$@A B  !((TU V  !((XY Z $$@A B   AB C w^ ^	r/   c           	     J    \         P                   ! 4       p\        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      '       d   \        P                  P                  V4      R,          pV P                  \         P                   ! 4       V,
          4      p	R\        P                  P                  V4       RVR RV	 R23 \        P                   ! V4       # R \        P                   ! V4       #   + '       g   i     E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)rm   r   r,  z.msFr-  r.  Nz
-sceneFilez-v5Ti  r7  )r8  rI   r;  r0  r9  z (z.2fz MB, )g      0A)Fu   未生成输出文件)r   r1   r2   r   _generate_max_to_fbx_scriptr?  r@  rD  rC  r   rG  rH  r3   getsizer  r   rL  r?   r   )r+   max_pathrT  output_path
max_scriptr  rS  rU  r_  costr  s   &&         r,   r   .FileFormatConverter._convert_max_to_fbx_singleR  s   	!B''**84Q7&@K99+FJ,,#eE\cddhi
#ff e||\8[$PSTs4dD[bkst77>>+..5IB00r1ABDBGG$4$4[$A#B"RHERVQWWX!YYIIk* 6IIk* edd ! y IIk*   	!#a&= 	!s   A5H  7FH  AG 1A;G -F1G GF.	(	H  1F?<H  >F??H  GH  GH  G=G,+G=,G:7G=9G::G==H   H"HH"H"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+   rn  s   &&r,   rk  /FileFormatConverter._generate_max_to_fbx_scriptl  s4    !))$4eJ #m $Kq q	r/   c                :    V P                   P                  4        R # r   )r   mainloopr*   s   &r,   rH  FileFormatConverter.run  s    		r/   )r   r   r   r   r   r   r#   r   r   r   r    r   r   r   r   r   N)__name__
__module____qualname____firstlineno__r-   r$   r%   r&   r)   r(   r'   r   r   r   r   r   r   r  r   r   r   r'  rY  r   r   r>  r   rk  rH  __static_attributes____classdictcell__)__classdict__s   @r,   r   r      s     F4<0fWP3$
7@	`\"I
$BEHG<+dB
+ZAC_D!4sj r/   r   __main__u   错误: u   错误u   程序启动失败:
)__doc__tkinterr   r   r   r   tkinterdnd2r   r   r1   rG  r   r?  r   r!   rA  r   concurrent.futuresr   r	   r   rz  apprH  r?   r  print	showerrorr   rf  r/   r,   <module>r     s   
  / / - 	        ?F FR zI!#	   InX)>s1vh'GHHIs   A0 0B)7'B$$B)