@@ -219,6 +219,54 @@ public static void ShowWindow()
219219 window . minSize = new Vector2 ( 620f , 560f ) ;
220220 }
221221
222+ private const string ImportPatcherHubMenuPath = "!Pawlygon/Import Latest PatcherHub" ;
223+
224+ [ MenuItem ( ImportPatcherHubMenuPath , validate = true ) ]
225+ private static bool ValidateImportPatcherHub ( )
226+ {
227+ Menu . SetChecked ( ImportPatcherHubMenuPath , FTPatchConfigGenerator . IsPatcherHubAvailable ( ) ) ;
228+ return true ;
229+ }
230+
231+ [ MenuItem ( ImportPatcherHubMenuPath , priority = 200 ) ]
232+ private static void ImportPatcherHubMenuItem ( )
233+ {
234+ if ( FTPatchConfigGenerator . IsPatcherHubAvailable ( ) )
235+ {
236+ bool reimport = EditorUtility . DisplayDialog (
237+ "PatcherHub Already Installed" ,
238+ "PatcherHub is already installed in this project. Do you want to re-import the latest version?" ,
239+ "Re-import" , "Cancel" ) ;
240+ if ( ! reimport ) return ;
241+ }
242+
243+ try
244+ {
245+ GitHubReleaseInfo releaseInfo = FetchLatestPatcherHubReleaseInfo ( ) ;
246+ GitHubReleaseAsset unityPackageAsset = releaseInfo ? . assets ? . FirstOrDefault ( asset =>
247+ ! string . IsNullOrEmpty ( asset . name ) &&
248+ asset . name . EndsWith ( ".unitypackage" , StringComparison . OrdinalIgnoreCase ) &&
249+ ! string . IsNullOrEmpty ( asset . browser_download_url ) ) ;
250+
251+ if ( unityPackageAsset == null )
252+ {
253+ EditorUtility . DisplayDialog ( "Import Failed" ,
254+ "Could not find a .unitypackage asset in the latest PatcherHub release." , "OK" ) ;
255+ return ;
256+ }
257+
258+ string downloadPath = Path . Combine ( Path . GetTempPath ( ) , unityPackageAsset . name ) ;
259+ DownloadFile ( unityPackageAsset . browser_download_url , downloadPath ) ;
260+ AssetDatabase . ImportPackage ( downloadPath , false ) ;
261+ Debug . Log ( $ "[AvatarSetupWizard] Imported { unityPackageAsset . name } from { releaseInfo . tag_name } .") ;
262+ }
263+ catch ( Exception ex )
264+ {
265+ EditorUtility . DisplayDialog ( "Import Failed" ,
266+ $ "Failed to import PatcherHub: { ex . Message } ", "OK" ) ;
267+ }
268+ }
269+
222270 private void OnEnable ( )
223271 {
224272 FBXImportDetector . FbxReimported += HandleFbxReimported ;
@@ -587,14 +635,25 @@ private void DrawVrcftPrefabBlock(bool isVrcftAvailable, string vrcftPrefabPath)
587635
588636 private void DrawPatcherHubBlock ( )
589637 {
638+ bool isPatcherHubInstalled = FTPatchConfigGenerator . IsPatcherHubAvailable ( ) ;
639+
590640 using ( new EditorGUILayout . VerticalScope ( PawlygonEditorUI . SectionStyle ) )
591641 {
592642 EditorGUILayout . LabelField ( "PatcherHub" , new GUIStyle ( EditorStyles . boldLabel ) { fontSize = 13 } ) ;
593643 EditorGUILayout . Space ( 2f ) ;
594- EditorGUILayout . LabelField ( "Import the latest PatcherHub unitypackage so end users can patch the face-tracking changes onto the avatar FBX model." , PawlygonEditorUI . SubLabelStyle ) ;
644+
645+ if ( isPatcherHubInstalled )
646+ {
647+ EditorGUILayout . LabelField ( "PatcherHub detected. You can re-import to update to the latest version." , PawlygonEditorUI . SubLabelStyle ) ;
648+ }
649+ else
650+ {
651+ EditorGUILayout . LabelField ( "Import the latest PatcherHub unitypackage so end users can patch the face-tracking changes onto the avatar FBX model." , PawlygonEditorUI . SubLabelStyle ) ;
652+ }
653+
595654 EditorGUILayout . Space ( 8f ) ;
596655
597- if ( PawlygonEditorUI . DrawPrimaryButton ( "Import Latest PatcherHub" , 32f ) )
656+ if ( PawlygonEditorUI . DrawPrimaryButton ( isPatcherHubInstalled ? "Re-import Latest PatcherHub" : "Import Latest PatcherHub" , 32f ) )
598657 {
599658 ImportLatestPatcherHub ( ) ;
600659 }
0 commit comments