Beispiel #1
0
        public static float playerPositionStep = 1f;         // meters

        static void CreatePlayer(Bounds sceneBounds)
        {
            var playerAsset = AssetDatabase.LoadAssetAtPath <GameObject>(playerPrefabPath);

            if (!playerAsset)
            {
                Debug.LogWarning($"Missing asset: {playerPrefabPath}");
                return;
            }
            var player = EP.Instantiate(playerAsset);

            // Place the player
            // NOTE: This could be managed by a configuration component
            var position = Vector3.zero;

            position.y = sceneBounds.max.y + playerPositionStep;
            for (position.x = sceneBounds.min.x + playerPositionStep; position.x < sceneBounds.max.x - playerPositionStep; position.x += playerPositionStep)
            {
                for (position.z = sceneBounds.min.z + playerPositionStep; position.z < sceneBounds.max.z - playerPositionStep; position.z += playerPositionStep)
                {
                    if (Physics.Raycast(position, Vector3.down, out var hitInfo, sceneBounds.size.y + playerPositionStep * 2f))
                    {
                        player.transform.position = hitInfo.point;
                        position = sceneBounds.max;                         // Break from both loops
                    }
                }
            }
        }
Beispiel #2
0
        // TODO: This, like a grid, is a standard layout
        // IDEA: When TransformData is included, provide utilities to generate layouts, and to replicate gameobjects over them
        static GameObject[] RotateCopies(GameObject original, Quaternion rotation, int count)
        {
            var copyList = new GameObject[count];

            copyList[0] = original;
            for (int c = 1; c < count; ++c)
            {
                var copy = EP.Instantiate(original);
                EP.SetParent(copy.transform, original.transform.parent);
                copy.transform.localPosition = rotation * copyList[c - 1].transform.localPosition;
                copy.transform.localRotation = rotation * copyList[c - 1].transform.localRotation;
                copyList[c] = copy;
            }
            return(copyList);
        }
Beispiel #3
0
        /// <summary>
        /// Make a copy of light source as area light, with equivalent illumination
        /// </summary>
        /// <remarks>
        /// Intensity is scaled relative to the area of the light
        /// </remarks>
        public static GameObject MakeAreaCopy(Light light, Vector2 areaSize)
        {
            var gameObject = EP.Instantiate();

            GameObjectUtility.SetStaticEditorFlags(gameObject, (StaticEditorFlags) ~0);
            EP.SetParent(gameObject.transform, light.transform.parent);
            gameObject.transform.localPosition = light.transform.localPosition;
            gameObject.transform.localRotation = light.transform.localRotation;
            var areaLight = EP.AddComponent <Light>(gameObject);

            areaLight.lightmapBakeType = LightmapBakeType.Baked;
            areaLight.type             = LightType.Rectangle;
            areaLight.areaSize         = areaSize;
            areaLight.intensity        = light.intensity / (areaSize.x * areaSize.y);
            areaLight.color            = light.color;
            areaLight.range            = light.range;
            return(gameObject);
        }
Beispiel #4
0
 // Find or make a prefab adjacent to the merged asset folder
 static void CreateMerged(string path, Dictionary <string, GameObject> mergedPrefabs)
 {
     if (!mergedPrefabs.ContainsKey(path))
     {
         // Find or make a merged prefab
         var mergedPath = path + ".prefab";
         var merged     = AssetDatabase.LoadAssetAtPath <GameObject>(mergedPath);
         if (!merged)
         {
             var empty = EP.Instantiate();
             empty.name = path.Substring((path.LastIndexOf('/') + 1));
             // WARNING: SaveAsPrefabAsset will return null while AssetDatabase.StartAssetEditing() pertains
             merged = PrefabUtility.SaveAsPrefabAsset(empty, mergedPath);
             EP.Destroy(empty);
             //Debug.Log($"Created empty merged object: {pathPart}.prefab");
         }
         mergedPrefabs.Add(path, merged);
     }
 }
Beispiel #5
0
        public static void ApplyTo(GameObject mergeTarget, params GameObject[] mergeSources)
        {
            using (var editScope = new EP.EditGameObject(mergeTarget)) {
                var targetEdit = editScope.editObject;
                foreach (var mergeSource in mergeSources)
                {
                    var sourceCopy = EP.Instantiate(mergeSource);

                    // Unpack only root model prefab, constituent prefab links will be retained
                    // NOTE: Applying UnpackPrefabInstance to a non-prefab object results in a crash
                    if (PrefabUtility.GetPrefabAssetType(sourceCopy) != PrefabAssetType.NotAPrefab)
                    {
                        PrefabUtility.UnpackPrefabInstance(sourceCopy, PrefabUnpackMode.OutermostRoot, InteractionMode.AutomatedAction);
                    }
                    Merge(sourceCopy.transform, targetEdit.transform);

                    EP.Destroy(sourceCopy);
                }
            }
        }
Beispiel #6
0
        static void CreateSun(Bounds sceneBounds)
        {
            var sunAsset = AssetDatabase.LoadAssetAtPath <GameObject>(sunPrefabPath);

            if (!sunAsset)
            {
                Debug.LogWarning($"Missing asset: {sunPrefabPath}");
                return;
            }
            var sun = EP.Instantiate(sunAsset);

            var light = sun.GetComponentInChildren <Light>();

            RenderSettings.sun = light;

            // Position the sun source outside of the model
            // NOTE: This could be managed by a configuration component
            sun.transform.position        = sceneBounds.center;
            light.transform.localPosition = new Vector3(0f, 0f, -sceneBounds.extents.magnitude);
        }
Beispiel #7
0
        public static string CreateScene(string path, params GameObject[] gameObjects)
        {
            var scenePath = path + ".unity";

            // PROBLEM: When using NewSceneMode.Single during import assertion "GetApplication().MayUpdate()" fails
            // SOLUTION: During import, using Additive loading works.
            // PROBLEM: InvalidOperationException: Cannot create a new scene additively with an untitled scene unsaved.
            // NOTE: This can occur when the previously opened scene has ceased to exist, in particular when a project is opened.
            var scene  = EditorSceneManager.GetActiveScene();
            var addNew = scene.name.Length > 0 && scene.path.Length > 0 && scene.path != scenePath;             // scene.IsValid() will be true even when path and name are empty

            if (addNew)
            {
                scene = EditorSceneManager.NewScene(NewSceneSetup.EmptyScene, NewSceneMode.Additive);
            }
            else
            {
                // Remove all default scene objects
                foreach (var rootObject in scene.GetRootGameObjects())
                {
                    EP.Destroy(rootObject);
                }
            }
            EditorSceneManager.SetActiveScene(scene);

            // Add objects to scene
            foreach (var gameObject in gameObjects)
            {
                EP.Instantiate(gameObject);
            }
            // WARNING: If scene is created during asset import physics computations will not be initialized

            // PROBLEM: At end of import the open scene will have been modified, so a pop-up will appear.
            // SOLUTION: After loading the scene in additive mode, close it.
            EditorSceneManager.SaveScene(scene, scenePath);
            if (addNew)
            {
                EditorSceneManager.CloseScene(scene, true);
            }
            return(scenePath);
        }
Beispiel #8
0
        public static void ApplyTo(GameObject gameObject, string pathRoot)
        {
            var assetType = PrefabUtility.GetPrefabAssetType(gameObject);

            if (assetType == PrefabAssetType.MissingAsset)
            {
                return;
            }
            if (assetType == PrefabAssetType.Model)
            {
                // In the case of a model created an editable prefab
                var prefab = EP.Instantiate(gameObject);
                PrefabUtility.UnpackPrefabInstance(prefab, PrefabUnpackMode.OutermostRoot, InteractionMode.AutomatedAction);
                gameObject = PrefabUtility.SaveAsPrefabAsset(prefab, pathRoot + ".prefab");
                EP.Destroy(prefab);
            }

            // NOTE: Calling CopyAssets will be extremely slow if each asset is imported individually.
            // Instead, all of the copying will be done in one batch, after which assets will be imported.
            // Then, a new instance of AssetGatherer will find those copies and make replacements in
            // a second batch.
            try {
                AssetDatabase.StartAssetEditing();
                var assertGatherer = new AssetGatherer(pathRoot);
                assertGatherer.CopyAssets(gameObject);
            } finally {
                AssetDatabase.StopAssetEditing();
                AssetDatabase.Refresh(ImportAssetOptions.ForceSynchronousImport);
            }
            try {
                AssetDatabase.StartAssetEditing();
                var assertGatherer = new AssetGatherer(pathRoot);
                assertGatherer.SwapAssets(gameObject);
            } finally {
                AssetDatabase.StopAssetEditing();
                AssetDatabase.Refresh(ImportAssetOptions.ForceSynchronousImport);
            }
        }
Beispiel #9
0
        static void ReplacePlaceholders(string prefabPath, GameObject gameObject)
        {
            Dictionary <string, CachedPrefab> prefabs = GetPrefabs(prefabPath);
            var children = gameObject.Children(true);

            foreach (var child in children)
            {
                // Do not modify existing child prefabs
                var childPrefab = PrefabUtility.GetNearestPrefabInstanceRoot(child);
                if (childPrefab != null && childPrefab != gameObject)
                {
                    continue;
                }

                // Placeholder names are constructed as "prefab_name=object_name"
                var name_parts = child.name.Split('=');
                if (name_parts.Length == 1)
                {
                    continue;
                }

                // Create an placeholder prefab that can be modified after import
                if (!prefabs.ContainsKey(name_parts[0]))
                {
                    var placeholder = EP.Instantiate();
                    placeholder.name = name_parts[0];
                    var placeholderPath  = prefabPath + "/" + placeholder.name + ".prefab";
                    var placeholderAsset = PrefabUtility.SaveAsPrefabAsset(placeholder, placeholderPath);
                    prefabs[name_parts[0]] = new CachedPrefab(placeholderAsset);
                    EP.Destroy(placeholder);
                    //Debug.Log($"Missing prefab in {gameObject.name} for {child.Path()} -> created placeholder");
                }

                ConfigurePrefab(child.transform, prefabs[name_parts[0]]);
                EP.Destroy(child);
            }
        }
Beispiel #10
0
        static void MergeGroup(string pathName, List <GameObject> group)
        {
            // Gather LODGroup and Renderers
            LODGroup lodGroup  = null;
            var      renderers = new List <RendererSort>();

            foreach (var gameObject in group)
            {
                var renderer = gameObject.GetComponent <Renderer>();
                if (renderer)
                {
                    renderers.Add(new RendererSort(renderer));
                }
                var isGroup = gameObject.GetComponent <LODGroup>();
                if (isGroup)
                {
                    var lods = isGroup.GetLODs();
                    foreach (var lod in lods)
                    {
                        foreach (var lodRenderer in lod.renderers)
                        {
                            // Renderers must begin as siblings of LODGroup
                            EP.SetParent(lodRenderer.transform, isGroup.transform.parent);
                            renderers.Add(new RendererSort(lodRenderer));
                        }
                    }

                    if (!!lodGroup || !!renderer)
                    {
                        // LODGroup manager cannot be duplicated, and cannot have renderer component
                        Debug.LogWarning($"Removing LODGroup found on {gameObject.Path()}");
                        EP.Destroy(isGroup);
                        continue;
                    }
                    lodGroup = isGroup;
                }
            }
            if (!lodGroup)
            {
                lodGroup = EP.AddComponent <LODGroup>(EP.Instantiate());
            }

            // renderers[0] has the lowest vertex count
            renderers.Sort((l, m) => l.vertexCount - m.vertexCount);
            // Remove missing meshes and duplicate levels of detail
            var vertexCount     = 0;
            var removeRenderers = new List <RendererSort>();

            foreach (var renderer in renderers)
            {
                if (vertexCount == renderer.vertexCount)
                {
                    removeRenderers.Add(renderer);
                    continue;
                }
                vertexCount = renderer.vertexCount;
            }
            foreach (var renderer in removeRenderers)
            {
                renderers.Remove(renderer);
                EP.Destroy(renderer.renderer.gameObject);
                // NOTE: Duplicate mesh asset could be removed
            }
            if (renderers.Count == 0)
            {
                EP.Destroy(lodGroup.gameObject);
                return;
            }
            // renderers[0] has the highest vertrex count
            renderers.Reverse();

            // Configure manager in hierarchy
            lodGroup.gameObject.name = pathName.Substring(pathName.LastIndexOf('/') + 1);
            EP.SetParent(lodGroup.transform, renderers[0].renderer.transform.parent);
            lodGroup.transform.localPosition = renderers[0].renderer.transform.localPosition;
            lodGroup.transform.localRotation = renderers[0].renderer.transform.localRotation;
            lodGroup.transform.localScale    = renderers[0].renderer.transform.localScale;
            for (var r = 0; r < renderers.Count; ++r)
            {
                var renderer = renderers[r].renderer;
                // TODO: Used PathNameExtension for this!
                var lodIndex = renderer.gameObject.name.LastIndexOf(lodSuffix);
                if (lodIndex >= 0)
                {
                    renderer.gameObject.name = renderer.gameObject.name.Substring(0, lodIndex);
                }
                renderer.gameObject.name += lodSuffix + r.ToString();
                EP.SetParent(renderer.transform, lodGroup.transform);
            }

            // Configure the group
            var lodList = new LOD[renderers.Count];

            for (var r = 0; r < renderers.Count; ++r)
            {
                lodList[r].renderers = new[] { renderers[r].renderer }
            }
            ;
            ConfigureLODGroup(lodGroup, lodList);

            // Configure the renderers and materials
            foreach (var lod in lodGroup.GetLODs())
            {
                foreach (var renderer in lod.renderers)
                {
                    SetLightmapScale(renderer);
                    foreach (var material in renderer.sharedMaterials)
                    {
                        UseFadingShader(material);
                    }
                }
            }
        }