Пример #1
0
    private static void UpdateMetaDataRecursively(GameObject root, string suffix, PrefabLabData rootPLD, bool firstExecution)
    {
        PrefabLabData metadata = root.GetComponent <PrefabLabData>();

        metadata.Data = suffix;

        if (firstExecution)
        {
            rootPLD.SkinnedMeshes = false;
        }

        if (metadata.Type == PrefabLabObjectType.Old)
        {
            metadata.Type = PrefabLabObjectType.NotSpecified;
        }

        if (root.GetComponent <SkinnedMeshRenderer>() != null)
        {
            metadata.Type         = PrefabLabObjectType.SkinnedMesh;
            rootPLD.SkinnedMeshes = true;
        }

        for (int i = 0; i < root.transform.childCount; i++)
        {
            GameObject child = root.transform.GetChild(i).gameObject;
            UpdateMetaDataRecursively(child, suffix, rootPLD, false);
        }
    }
    public override void OnInspectorGUI()
    {
        PrefabLabData PLD = target as PrefabLabData;

        if (PLD.Type == PrefabLabObjectType.Old)
        {
            EditorGUILayout.Space();
            EditorGUILayout.HelpBox("This is an old prefab. Please update the prefab to see new features", MessageType.Info, true);
        }
        else if (PLD.Type == PrefabLabObjectType.Root)
        {
            EditorGUILayout.Space();

            PLD.ImportAnimationsAutomatically = EditorGUILayout.Toggle("Import Animations", PLD.ImportAnimationsAutomatically, EditorStyles.toggle);

            EditorGUILayout.Space();

            if (PLD.SkinnedMeshes)
            {
                EditorGUILayout.HelpBox("SkinnedMeshRenderers are not supported yet. To update a skinned mesh correctly select the skinned GameObject and follow instructions. TIP: Try to avoid adding components and GameObjects to the skinned object and it's bones.", MessageType.Warning, true);
            }
        }
        else if (PLD.Type == PrefabLabObjectType.SkinnedMesh)
        {
            EditorGUILayout.Space();
            EditorGUILayout.HelpBox("SkinnedMeshRenderers are not supported yet. To update a skinned mesh correctly you have to delete this gameObject, and all the bones used by this component. Apply the Prefab and update the prefab", MessageType.Warning, true);
        }

        EditorGUILayout.Space();

        if (GUILayout.Button("Update Prefab"))
        {
            string path = AssetDatabase.GetAssetPath(PrefabUpdater.GetInstanceIDOfSceneAndProjectObject(PLD.gameObject));

            PrefabLabSettings settings = PrefabUpdater.GetPrefabLabSettings();

            PrefabUpdater.UpdatePrefab(settings, path);
        }

        if (GUILayout.Button("Select Model"))
        {
            PrefabLabSettings settings = PrefabUpdater.GetPrefabLabSettings();

            Object[] newSelection = PrefabUpdater.GetModelsOrPrefabs(
                new Object[] { AssetDatabase.LoadAssetAtPath(AssetDatabase.GetAssetPath(PrefabUpdater.GetInstanceIDOfSceneAndProjectObject(PLD.gameObject)), typeof(Object)) }, settings);

            if (newSelection != null)
            {
                Selection.objects = newSelection;
            }
            else
            {
                Debug.Log("There was no prefab lab object found");
            }
        }

        EditorGUILayout.Space();
    }
Пример #3
0
    private static void CopyMetaData(GameObject source, GameObject destination)
    {
        PrefabLabData destPLD   = destination.GetComponent <PrefabLabData>();
        PrefabLabData sourcePLD = source.GetComponent <PrefabLabData>();

        if (destPLD != null)
        {
            destPLD.Type = sourcePLD.Type;
        }
        else
        {
            destPLD      = destination.AddComponent <PrefabLabData>();
            destPLD.Type = PrefabLabObjectType.NotSpecified;
        }
    }
Пример #4
0
    //Rename MetaData.Data from NewModelNameSuffix to CurrentModelNameSuffix
    //(New and Current exist so we can detect whether an gameobject has just been imported or its an older part of the prefab)
    private static void RenameNewToCurrent(GameObject root, PrefabLabSettings settings)
    {
        PrefabLabData metadata = root.GetComponent <PrefabLabData>();

        if (metadata != null)
        {
            if (metadata.Data == NewModelNameSuffix)
            {
                metadata.Data = settings.ModelMetadata;
            }
        }

        for (int i = 0; i < root.transform.childCount; i++)
        {
            RenameNewToCurrent(root.transform.GetChild(i).gameObject, settings);
        }
    }
Пример #5
0
    //Recursive remove old prefab parts and move the userdata on it to lostObjects
    private static void RescueAndRemove(GameObject importedModel, GameObject prefab, GameObject lostObjects)
    {
        //Check prefab for removed parts
        for (int oldPrefabIndex = prefab.transform.childCount - 1; oldPrefabIndex >= 0; oldPrefabIndex--)
        {
            bool hasMatch = false;

            for (int newModelIndex = importedModel.transform.childCount - 1; newModelIndex >= 0; newModelIndex--)
            {
                GameObject newModelChild  = importedModel.transform.GetChild(newModelIndex).gameObject;
                GameObject oldPrefabChild = prefab.transform.GetChild(oldPrefabIndex).gameObject;

                if (newModelChild.name == oldPrefabChild.name)
                {
                    hasMatch = true;

                    RescueAndRemove(newModelChild, oldPrefabChild, lostObjects);
                    break;
                }
            }

            //Removed gameobject in the prefab detected. Gather userdata and add it to lost gameobjects
            if (!hasMatch)
            {
                PrefabLabData metadata = prefab.transform.GetChild(oldPrefabIndex).gameObject.GetComponent <PrefabLabData>();
                if (metadata != null)
                {
                    if (metadata.Data != NewModelNameSuffix)    //Check whether the modelpart has just been added to the prefab by Rebuild() or not
                    {
                        //Gather userdata before removing
                        FindAndSaveLostObjects(prefab.transform.GetChild(oldPrefabIndex).gameObject, lostObjects);

                        GameObject.DestroyImmediate(prefab.transform.GetChild(oldPrefabIndex).gameObject);
                    }
                }
            }
        }
    }
Пример #6
0
 //Recursively find all gameobjects in root and add suffix to name
 private static void UpdateMetaDataRecursively(GameObject root, string suffix, PrefabLabData rootPLD)
 {
     UpdateMetaDataRecursively(root, suffix, rootPLD, true);
 }
Пример #7
0
    private static void CopyComponents(GameObject source, GameObject destination, string assetPath, PrefabLabData PLD)
    {
        CopyTransform(source, destination);

        CopyMetaData(source, destination);

        if (GetModelImporter(assetPath).importMaterials)
        {
            CopyMaterials(source, destination);
        }

        if (GetModelImporter(assetPath).generateAnimations != ModelImporterGenerateAnimations.None && PLD.ImportAnimationsAutomatically)
        {
            CopyAnimations(source, destination);
        }

        if (GetModelImporter(assetPath).addCollider)
        {
            CopyColliders(source, destination);
        }
    }
Пример #8
0
    //Recursive copy newly found modelparts to the prefab
    //and synch Transform, Materials etc. with current parts
    private static void RebuildPrefab(GameObject importedModel, GameObject prefab, string assetPath, PrefabLabData PLD)
    {
        for (int newModelIndex = importedModel.transform.childCount - 1; newModelIndex >= 0; newModelIndex--)
        {
            bool hasMatch = false;

            for (int oldPrefabIndex = prefab.transform.childCount - 1; oldPrefabIndex >= 0; oldPrefabIndex--)
            {
                GameObject importedModelChild = importedModel.transform.GetChild(newModelIndex).gameObject;
                GameObject prefabChild        = prefab.transform.GetChild(oldPrefabIndex).gameObject;

                if (importedModelChild.name == prefabChild.name)
                {
                    CopyComponents(importedModelChild, prefabChild, assetPath, PLD);

                    hasMatch = true;

                    RebuildPrefab(importedModelChild, prefabChild, assetPath, PLD);
                    break;
                }
            }

            //New gameobject in importedModel detected, copy it to the prefab
            if (!hasMatch)
            {
                ParentGOWithoutTransformChanges(prefab, importedModel.transform.GetChild(newModelIndex).gameObject);
            }
        }
    }
Пример #9
0
    public static void UpdatePrefab(string modelPath, PrefabLabSettings settings)
    {
        //Substract subdirs from imported asset
        string relativeSubdir = modelPath.Remove(0, ("Assets/" + settings.SourceFolder).Length + 1);

        relativeSubdir = relativeSubdir.Remove(relativeSubdir.LastIndexOf("/") + 1);
        string relativeSourceFolder = settings.DestinationFolder + "/" + relativeSubdir;
        string absoluteSubdir       = Application.dataPath + "/" + relativeSourceFolder;

        //Prepare the imported model for modification
        GameObject importedModel = (GameObject)PrefabUtility.InstantiatePrefab(AssetDatabase.LoadAssetAtPath(modelPath, typeof(GameObject)));

        AddMetaData(importedModel);

        GameObject lostObjects = null;

        Object originalPrefab;

        if (!FindExistingPrefab(importedModel.name, relativeSourceFolder, settings.PrefabSuffix, out originalPrefab))
        {
            //Create subdirs
            Directory.CreateDirectory(absoluteSubdir);

            AssetDatabase.Refresh();

            //Prefab not found, create one for me please!
            string prefabFilepath = "Assets/" + relativeSourceFolder + importedModel.name + settings.PrefabSuffix + ".prefab";
            Object emptyPrefab    = PrefabUtility.CreateEmptyPrefab(prefabFilepath);
            AssetDatabase.ImportAsset(prefabFilepath);

            //Creating an empty prefab is really empty so we need a gameobject to start with, called parent
            GameObject    parent = new GameObject(importedModel.name + settings.PrefabSuffix);
            PrefabLabData PLD    = parent.AddComponent <PrefabLabData>();
            PLD.Type = PrefabLabObjectType.Root;

            //Mark as max model
            UpdateMetaDataRecursively(importedModel, settings.ModelMetadata, PLD);
            //Copy newModel to prefab
            importedModel.transform.parent = parent.transform;

            originalPrefab = PrefabUtility.ReplacePrefab(parent, emptyPrefab, ReplacePrefabOptions.ReplaceNameBased);

            //Clean up
            GameObject.DestroyImmediate(parent);
        }
        else
        {
            GameObject prefab = (GameObject)GameObject.Instantiate(originalPrefab);
            prefab.name = originalPrefab.name;

            PrefabLabData PLD = prefab.GetComponent <PrefabLabData>();
            if (PLD == null)
            {
                PLD      = prefab.AddComponent <PrefabLabData>();
                PLD.Type = PrefabLabObjectType.Root;
            }

            //Find LostObjects root or create it
            lostObjects = GetChildByName(lostObjectsName, prefab);

            if (lostObjects == null)
            {
                lostObjects = new GameObject(lostObjectsName);
                lostObjects.transform.parent = prefab.transform;
            }

            //Find newModel root in merlin's prefab and do magic
            GameObject prefabModelRoot = GetChildByName(importedModel.name, prefab);

            if (prefabModelRoot != null)
            {
                //Check if object changed from one object to multiple
                if ((prefabModelRoot.transform.GetChildCount() == 0 && importedModel.transform.GetChildCount() != 0) || (prefabModelRoot.transform.GetChildCount() != 0 && importedModel.transform.GetChildCount() == 0))
                {
                    prefabModelRoot.transform.parent = lostObjects.transform;

#if UNITY_3_0 || UNITY_3_1 || UNITY_3_2 || UNITY_3_3 || UNITY_3_4 || UNITY_3_5 || UNITY_3_6
                    prefabModelRoot.SetActiveRecursively(false);
#else
                    prefabModelRoot.SetActive(false);
#endif
                    prefabModelRoot = null;

                    Debug.LogWarning("Unity treats model files with one object differently than files with multiple objects. You changed in the number of objects in " + importedModel.name + ". We recovered the old gameobjects in LostObjects.");
                }
            }

            if (prefabModelRoot == null)
            {
                UpdateMetaDataRecursively(importedModel, settings.ModelMetadata, PLD);

                importedModel.transform.parent        = prefab.transform;
                importedModel.transform.localPosition = Vector3.zero;
            }
            else
            {
                //Mark the newly imported as new to know later on if a modelpart has just been imported or its an old prefabpart
                UpdateMetaDataRecursively(importedModel, NewModelNameSuffix, PLD);

                //Does all the magic to childs
                RebuildPrefab(importedModel, prefabModelRoot, modelPath, PLD);
                RescueAndRemove(importedModel, prefabModelRoot, lostObjects);
                RenameNewToCurrent(prefabModelRoot.gameObject, settings);

                //Don't forget the parent
                CopyComponents(importedModel, prefabModelRoot, modelPath, PLD);
            }

            //Clean up if no lostobjects have been found
            if (lostObjects.transform.childCount > 0)
            {
#if UNITY_3_0 || UNITY_3_1 || UNITY_3_2 || UNITY_3_3 || UNITY_3_4 || UNITY_3_5 || UNITY_3_6
                lostObjects.SetActiveRecursively(false);
#else
                lostObjects.SetActive(false);
#endif

                Debug.Log("Prefab Lab Warning: There are " + lostObjects.transform.childCount + " objects found which don't have a parent anymore because it has been deleted in the model." +
                          System.Environment.NewLine +
                          "To recover these objects, browse to the gameobject \"" + lostObjectsName + "\" in the prefab " + prefab.name + ".", originalPrefab);
            }
            else
            {
                GameObject.DestroyImmediate(lostObjects);
            }

            //Save created or modified prefab
            PrefabUtility.ReplacePrefab(prefab, originalPrefab, ReplacePrefabOptions.ReplaceNameBased);

            //Clean up
            GameObject.DestroyImmediate(importedModel);
            GameObject.DestroyImmediate(prefab);
        }
    }