yelby

VRChat Avatar Importer

Nov 29th, 2020 (edited)
133
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 13.43 KB | None | 0 0
  1. using UnityEngine;
  2. using UnityEditor;
  3. using UnityEngine.SceneManagement;
  4. using UnityEditor.SceneManagement;
  5. using UnityEditor.Presets;
  6. using System.Collections.Generic;
  7. using System.Linq;
  8.  
  9. public class Avatar_Importer_Main : EditorWindow
  10. {
  11.     //Attributes
  12.     string myString = "";
  13.     public Object source;
  14.     GameObject avatar;
  15.     Scene scene;
  16.     bool showBtn = true;
  17.     bool av3 = true;
  18.  
  19.     [MenuItem("Yelby/Avatar Setup")]
  20.     public static void ShowWindow()
  21.     {
  22.         GetWindow<Avatar_Importer_Main>("Avatar Setup");
  23.     }
  24.  
  25.     void OnGUI()
  26.     {
  27.         //Starting Instruction
  28.         GUILayout.Label("How to Use", EditorStyles.boldLabel);
  29.         GUILayout.Label("1. Import your avatar\n" +
  30.                         "2. Name the avatar below\n" +
  31.                         "3. Drag the avatar into box\n" +
  32.                         "4. Click Generate");
  33.  
  34.         //Text Field
  35.         myString = EditorGUILayout.TextField("Name of Avatar", myString);
  36.  
  37.         //Object Field
  38.         EditorGUILayout.BeginHorizontal();
  39.         GUILayout.Label("Drag Avatar Here: ");
  40.         source = EditorGUILayout.ObjectField(source, typeof(GameObject), false);
  41.         EditorGUILayout.EndHorizontal();
  42.  
  43.         //Floor Button
  44.         showBtn = EditorGUILayout.Toggle("Floor Plane", showBtn);
  45.         av3 = EditorGUILayout.Toggle("Is Avatar 3.0", av3);
  46.  
  47.         //Button
  48.         if (GUILayout.Button("Generate"))
  49.         {
  50.             if (source != null)
  51.             {
  52.                 if (myString == "")
  53.                 {
  54.                     Debug.LogWarning("No Name");
  55.                     EditorUtility.DisplayDialog("Avatar Failed", "Name Field is empty!", "Ok");
  56.                     return;
  57.                 }
  58.                 if (!AssetDatabase.IsValidFolder("Assets/Avatars/" + myString))
  59.                 {
  60.                     //General Stuff
  61.                     CreateFolders();
  62.                     Debug.Log("Folders Finished");
  63.                     inspectorOptions();
  64.                     Debug.Log("Properties Finished");
  65.                     moveAvatar();
  66.                     Debug.Log("Moving Avatar Finished");
  67.                     createScene();
  68.                     Debug.Log("Scene Creation Finished");
  69.                     addDescriptor();
  70.                     Debug.Log("Descriptor Finished");
  71.                     grabAnimations();
  72.                     Debug.Log("Animations Grabbed");
  73.  
  74.                     Selection.activeGameObject = null;
  75.                     //Floor
  76.                     if (showBtn)
  77.                     {
  78.                         generateFloor();
  79.                         Debug.Log("Floor Generated");
  80.                     }
  81.  
  82.                     Debug.Log("Avatar Generated");
  83.                     EditorUtility.DisplayDialog("Avatar Success", "Avatar has finished generating!", "Ok");
  84.                     source = null;
  85.                 }
  86.                 else
  87.                 {
  88.                     Debug.LogWarning("Name Taken");
  89.                     EditorUtility.DisplayDialog("Avatar Failed", "Name already taken!\nTry another name.", "Ok");
  90.                 }
  91.             }
  92.             else
  93.             {
  94.                 EditorUtility.DisplayDialog("Avatar Failed", "Avatar import field empty!", "ok");
  95.                 Debug.LogWarning("No Avatar in Field");
  96.             }
  97.  
  98.         }
  99.  
  100.         //Other Items
  101.         GUILayout.Label("Everything can't be automated.\nPlease follow these instructions", EditorStyles.boldLabel);
  102.         GUILayout.Label("1. Configure Your avatar\n" +
  103.                         "2. Now add your VRC_Avatar_Descriptor and make your avatar");
  104.  
  105.     }
  106.     //~~~~Methods~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  107.     void CreateFolders()
  108.     {
  109.         string guid = "";
  110.         string newFolderPath = "";
  111.  
  112.         //Make avatar folder if avatar folder doesn't exist
  113.         if (!AssetDatabase.IsValidFolder("Assets/Avatars"))
  114.         {
  115.             guid = AssetDatabase.CreateFolder("Assets", "Avatars");
  116.             newFolderPath = AssetDatabase.GUIDToAssetPath(guid);
  117.             Debug.Log("Avatars Folder Created");
  118.         }
  119.         //Make the <Character File> if it doesn't exist
  120.         if (!AssetDatabase.IsValidFolder("Assets/Avatars/" + myString))
  121.         {
  122.             guid = AssetDatabase.CreateFolder("Assets/Avatars", myString);
  123.             newFolderPath = AssetDatabase.GUIDToAssetPath(guid);
  124.             Debug.Log(myString + " Folder Created");
  125.         }
  126.  
  127.         //Creates Subfolder Names
  128.         string[] subfoldernames = { "Animations", "FBX", "Prefabs", "Textures", "UMats" };
  129.         string[] subfolders = new string[subfoldernames.Length];
  130.  
  131.         //Genterat subfolders
  132.         for (int i = 0; i < subfoldernames.Length; i++)
  133.         {
  134.             if (!AssetDatabase.IsValidFolder("Assets/Avatars/" + myString + "/" + subfoldernames[i]))
  135.             {
  136.                 subfolders[i] = AssetDatabase.CreateFolder("Assets/Avatars/" + myString, subfoldernames[i]);
  137.                 newFolderPath = AssetDatabase.GUIDToAssetPath(subfolders[i]);
  138.                 Debug.Log("Subfolder " + subfoldernames[i] + " generated");
  139.             }
  140.         }
  141.     }
  142.  
  143.     void moveAvatar()
  144.     {
  145.         //string oldpath = "Assets/" + source.name + ".fbx";
  146.         string oldpath = AssetDatabase.GetAssetPath(source);
  147.         string newpath = ("Assets/Avatars/" + myString + "/" + "FBX/" + myString + ".fbx");
  148.         AssetDatabase.MoveAsset(oldpath, newpath);
  149.         AssetDatabase.Refresh();
  150.         Debug.Log("Avatar moved from " + oldpath + " to " + newpath);
  151.     }
  152.  
  153.     void inspectorOptions()
  154.     {
  155.         //Load premade preset to avatar in "Assets/Yelby/Programs/Avatar Importer/ImportPreset.preset"
  156.         string presetloc = ("Assets/Yelby/Programs/Avatar Importer/ImportPreset.preset");
  157.         string humloc = ("Assets/Yelby/Programs/Avatar Importer/MMD Model Template.ht");
  158.         string pSource = AssetDatabase.GetAssetPath(source);
  159.         Object nSource = AssetImporter.GetAtPath(pSource);
  160.         var preset = AssetDatabase.LoadAssetAtPath<Preset>(presetloc);
  161.         var hum = AssetDatabase.LoadAssetAtPath<Avatar>(humloc);
  162.         if (preset.CanBeAppliedTo(nSource))
  163.         {
  164.             preset.ApplyTo(nSource);
  165.             Debug.Log("Preset Applied to " + source.name);
  166.         }
  167.  
  168.         //Scan through Avatar options to [Remove Toe Bones; Check if Chest is chest, spine is spine, hip is hip; Remove jaw bone]
  169.         /*Can't Automate*/
  170.  
  171.         //Export Materials to "Assets/Avatars/ <avatar name> / UMats"
  172.         string destinationPath = ("Assets/Avatars/" + myString + "/" + "UMats/");
  173.         ExtractMaterials(pSource, destinationPath);
  174.  
  175.         preset.UpdateProperties(nSource);
  176.     }
  177.  
  178.     void createScene()
  179.     {
  180.         scene = SceneManager.GetActiveScene();
  181.         string destinationPath = ("Assets/Avatars/" + myString + "/" + myString + ".unity");
  182.  
  183.         if (scene.name == "" || scene.name == "SampleScene")
  184.         {
  185.             //Place avatar into scene at 0,0,0
  186.             string nSource = ("Assets/Avatars/" + myString + "/FBX/" + myString + ".fbx");
  187.             Object oSource = AssetDatabase.LoadAssetAtPath<Object>(nSource);
  188.             var clone = Instantiate(oSource);
  189.             clone.name = myString;
  190.             fromPrefab();
  191.             //Save scene
  192.             EditorSceneManager.SaveScene(scene, destinationPath, false);
  193.         }
  194.         else
  195.         {
  196.             //Create scene with name of avatar and saved to "Assets/Avatars/ <Avatar Name>
  197.             var newScene = EditorSceneManager.NewScene(NewSceneSetup.DefaultGameObjects, NewSceneMode.Additive);
  198.             scene = newScene;
  199.             //Place avatar into scene at 0,0,0
  200.             string nSource = ("Assets/Avatars/" + myString + "/FBX/" + myString + ".fbx");
  201.             Object oSource = AssetDatabase.LoadAssetAtPath<Object>(nSource);
  202.             var clone = Instantiate(oSource);
  203.             clone.name = myString;
  204.  
  205.             //Add Prefab to Scene
  206.             fromPrefab();
  207.  
  208.             //Save scene
  209.             EditorSceneManager.SaveScene(newScene, destinationPath, false);
  210.         }
  211.         Debug.LogError("Scene Done");
  212.     }
  213.  
  214.     void addDescriptor()
  215.     {
  216.         //Add avatar Descriptor to avatar
  217.         /*Don't know how to do*/
  218.  
  219.         //Change eye position to be between assigned eyebones in humanoid/avatar
  220.         /*Not Exactly - Finds eye position if it exists*/
  221.         avatar = GameObject.Find(myString + "/Armature/Hips/Spine/Chest/Neck/Head/Eye_L");
  222.         if (avatar == true)
  223.         {
  224.             GameObject eyeloc = GameObject.CreatePrimitive(PrimitiveType.Sphere);
  225.             eyeloc.name = "Suggested Eye Location";
  226.             eyeloc.transform.localScale = new Vector3(0.05f, 0.05f, 0.05f);
  227.             Vector3 eyeloc2 = new Vector3(0, avatar.transform.position.y, avatar.transform.position.z);
  228.             eyeloc.transform.position = eyeloc2;
  229.             Debug.Log(eyeloc.name + " has been generated");
  230.         }
  231.         else
  232.         {
  233.             Debug.Log("Eye Bone Doesn't Exist [/Armature/Hips/Spine/Chest/Neck/Head/Eye_L]");
  234.         }
  235.  
  236.         //Delete Trash
  237.         avatar = GameObject.Find(myString);
  238.         DestroyImmediate(avatar);
  239.         Debug.Log("Avatar removed from Scene");
  240.  
  241.         EditorSceneManager.SaveScene(scene);
  242.  
  243.         //Auto select "auto visemes" from descriptor
  244.         /*Can't do because can't add componenet*/
  245.     }
  246.  
  247.     void generateFloor()
  248.     {
  249.         GameObject floor = GameObject.CreatePrimitive(PrimitiveType.Plane);
  250.         floor.name = "Floor";
  251.         EditorSceneManager.SaveScene(scene);
  252.     }
  253.  
  254.     void grabAnimations()
  255.     {
  256.         if (av3)
  257.         {
  258.             string folder = "Assets/VRCSDK/Examples3/Animation/Controllers";
  259.             if (AssetDatabase.IsValidFolder(folder))
  260.             {
  261.                 string[] original = { "vrc_AvatarV3LocomotionLayer" ,   //1
  262.                                   "vrc_AvatarV3IdleLayer" ,         //2
  263.                                   "vrc_AvatarV3HandsLayer2",        //3
  264.                                   "vrc_AvatarV3ActionLayer",        //4
  265.                                   "vrc_AvatarV3HandsLayer2",        //5
  266.                                   "vrc_AvatarV3SittingLayer"        //6
  267.                                 };
  268.                 string[] moved = {  "Base (Locomotion)" ,               //1
  269.                                 "Additive (Not Active)" ,           //2
  270.                                 "Gesture (Specific Movements",      //3
  271.                                 "Action (Dances)",                  //4
  272.                                 "FX (Everything that isn't bone)",  //5
  273.                                 "Sitting"                           //6
  274.                              };
  275.                 for (int i = 0; i < original.Length; i++)
  276.                 {
  277.                     AssetDatabase.CopyAsset("Assets/VRCSDK/Examples3/Animation/Controllers/" + original[i] + ".controller",
  278.                                             "Assets/Avatars/" + myString + "/Animations/" + moved[i] + ".controller");
  279.                 }
  280.                 Debug.Log("SDK3 Animations Pulled");
  281.             }
  282.             else
  283.             {
  284.                 Debug.LogWarning("Folder Does Not Exist SDK3");
  285.                 return;
  286.             }
  287.  
  288.         }
  289.         else
  290.         {
  291.             string folder = "Assets/VRChat Examples/Examples2/Animation/SDK2";
  292.             if (AssetDatabase.IsValidFolder(folder))
  293.             {
  294.                 AssetDatabase.CopyAsset(folder + "/CustomOverrideEmpty.overrideController",
  295.                                         "Assets/Avatars/" + myString + "/Animations/" + myString + ".overrideController");
  296.                 Debug.Log("SDK2 Animations Pulled");
  297.             }
  298.             else
  299.             {
  300.                 Debug.LogWarning("Folder Does Not Exist SDK2");
  301.                 return;
  302.             }
  303.         }
  304.  
  305.     }
  306.  
  307.     void fromPrefab()
  308.     {
  309.         //Add Prefab to Scene
  310.         avatar = GameObject.Find(myString);
  311.         PrefabUtility.SaveAsPrefabAssetAndConnect(avatar, "Assets/Avatars/" + myString + "/Prefabs/" + myString + ".prefab", InteractionMode.AutomatedAction);
  312.         Object temp = AssetDatabase.LoadAssetAtPath<Object>("Assets/Avatars/" + myString + "/Prefabs/" + myString + ".prefab");
  313.         PrefabUtility.InstantiatePrefab(temp);
  314.         Debug.LogWarning("Prefab Added");
  315.     }
  316.  
  317.     //~~~~Online Helpers~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  318.     public static void ExtractMaterials(string assetPath, string destinationPath)
  319.     {
  320.         HashSet<string> hashSet = new HashSet<string>();
  321.         IEnumerable<Object> enumerable = from x in AssetDatabase.LoadAllAssetsAtPath(assetPath)
  322.                                          where x.GetType() == typeof(Material)
  323.                                          select x;
  324.         foreach (Object item in enumerable)
  325.         {
  326.             string path = System.IO.Path.Combine(destinationPath, item.name) + ".mat";
  327.             path = AssetDatabase.GenerateUniqueAssetPath(path);
  328.             string value = AssetDatabase.ExtractAsset(item, path);
  329.             if (string.IsNullOrEmpty(value))
  330.             {
  331.                 hashSet.Add(assetPath);
  332.             }
  333.         }
  334.  
  335.         foreach (string item2 in hashSet)
  336.         {
  337.             AssetDatabase.WriteImportSettingsIfDirty(item2);
  338.             AssetDatabase.ImportAsset(item2, ImportAssetOptions.ForceUpdate);
  339.         }
  340.     }
  341. }
Add Comment
Please, Sign In to add comment