public static void SnapshotObjects(this MMTerrainLayer layer, Terrain terrain) { #if UNITY_EDITOR var terrainSize = terrain.terrainData.size; var terrainPos = terrain.GetPosition(); var terrainBounds = new Bounds(terrainPos, Vector3.zero); terrainBounds.Encapsulate(terrainPos + terrainSize); terrainBounds.Expand(Vector3.up * 5000); var allTransforms = UnityEngine.Object.FindObjectsOfType <Transform>(); var done = new HashSet <Transform>(); allTransforms = allTransforms.OrderBy(transform => TransformExtensions.GetHierarchyDepth(transform)).ToArray(); HashSet <Transform> ignores = new HashSet <Transform>(); layer.Objects.Clear(); for (var i = 0; i < allTransforms.Length; i++) { var transform = allTransforms[i]; if (done.Contains(transform) || ignores.Contains(transform)) { continue; } var ws = transform.GetComponentInAncestors <LayerComponentBase>(); if (ws) { //Debug.Log(string.Format("WorldStamp Object Capture : Ignored {0} as it contained a WorldStamp. Recursive WorldStamps are currently not supported.", transform), transform); ignores.Add(transform); var children = ws.transform.GetComponentsInChildren <Transform>(true); foreach (var ignore in children) { ignores.Add(ignore); } continue; } var rn = transform.GetComponentInAncestors <RoadNetwork>(); if (rn) { ignores.Add(rn.transform); var children = rn.transform.GetComponentsInChildren <Transform>(true); foreach (var ignore in children) { ignores.Add(ignore); } continue; } var template = transform.GetComponentInAncestors <WorldStampTemplate>(); if (template) { ignores.Add(template.transform); var children = template.transform.GetComponentsInChildren <Transform>(true); foreach (var ignore in children) { ignores.Add(ignore); } continue; } var go = transform.gameObject; var prefabRoot = PrefabUtility.GetPrefabObject(go); if (prefabRoot == null) { //Debug.LogError("Unable to collect non-prefab object: " + go.name, go); continue; } #if UNITY_2018_2_OR_NEWER var prefabAsset = PrefabUtility.FindPrefabRoot(PrefabUtility.GetCorrespondingObjectFromSource(go) as GameObject); #else var prefabAsset = PrefabUtility.FindPrefabRoot(PrefabUtility.GetPrefabParent(go) as GameObject); #endif var rootInScene = PrefabUtility.FindPrefabRoot(go); var relativePos = rootInScene.transform.position - terrainPos; relativePos = new Vector3(relativePos.x / terrainSize.x, (rootInScene.transform.position.y - terrain.SampleHeight(rootInScene.transform.position)) - terrainPos.y, relativePos.z / terrainSize.z); layer.Objects.Add(new PrefabObjectData { Guid = Guid.NewGuid().ToString(), Prefab = prefabAsset, Position = relativePos, Rotation = rootInScene.transform.localRotation.eulerAngles, Scale = rootInScene.transform.localScale, ContainerMetadata = layer.name, }); done.Add(rootInScene.transform); var doneChildren = rootInScene.transform.GetComponentsInChildren <Transform>(true); foreach (var item in doneChildren) { done.Add(item); } } #endif }
protected override void CaptureInternal(Terrain terrain, Bounds bounds) { #if UNITY_EDITOR BoundsMapping.Clear(); Objects.Clear(); var expandedBounds = bounds; expandedBounds.Expand(Vector3.up * 5000); var terrainPos = terrain.GetPosition(); var allTransforms = Object.FindObjectsOfType <Transform>(); var done = new HashSet <Transform>(); allTransforms = allTransforms.OrderBy(transform => TransformExtensions.GetHierarchyDepth(transform)).ToArray(); HashSet <Transform> ignores = new HashSet <Transform>(); for (int i = 0; i < allTransforms.Length; i++) { var transform = allTransforms[i]; if (done.Contains(transform) || ignores.Contains(transform)) { continue; } if (transform.GetComponent <TerrainCollider>()) { continue; } if (!expandedBounds.Contains(transform.position)) { continue; } var ws = transform.GetComponentInAncestors <WorldStamp>(); if (ws) { //Debug.Log(string.Format("WorldStamp Object Capture : Ignored {0} as it contained a WorldStamp. Recursive WorldStamps are currently not supported.", transform), transform); ignores.Add(transform); var children = ws.transform.GetComponentsInChildren <Transform>(true); foreach (var ignore in children) { ignores.Add(ignore); } continue; } var rn = transform.GetComponentInAncestors <RoadNetwork>(); if (rn) { ignores.Add(rn.transform); var children = rn.transform.GetComponentsInChildren <Transform>(true); foreach (var ignore in children) { ignores.Add(ignore); } continue; } var template = transform.GetComponentInAncestors <WorldStampTemplate>(); if (template) { ignores.Add(template.transform); var children = template.transform.GetComponentsInChildren <Transform>(true); foreach (var ignore in children) { ignores.Add(ignore); } continue; } var go = transform.gameObject; if (Mask != (Mask | (1 << go.layer))) { continue; } var prefabRoot = PrefabUtility.GetPrefabObject(go); if (prefabRoot == null) { //DebugHelper.DrawCube(collider.bounds.center, collider.bounds.extents, Quaternion.identity, Color.red, 30); continue; } done.Add(transform); var subTransforms = transform.GetComponentsInChildren <Transform>(); foreach (var childTransform in subTransforms) { done.Add(childTransform); } #if UNITY_2018_2_OR_NEWER var prefabAsset = PrefabUtility.FindPrefabRoot(PrefabUtility.GetCorrespondingObjectFromSource(go) as GameObject); #else var prefabAsset = PrefabUtility.FindPrefabRoot(PrefabUtility.GetPrefabParent(go) as GameObject); #endif var root = PrefabUtility.FindPrefabRoot(go); var relativePos = root.transform.position - bounds.min; relativePos = new Vector3(relativePos.x / bounds.size.x, 0, relativePos.z / bounds.size.z); if (RelativeMode == WorldStamp.EObjectRelativeMode.RelativeToTerrain) { var terrainHeightAtPoint = terrain.SampleHeight(root.transform.position); relativePos.y = (root.transform.position.y - terrainHeightAtPoint); } else { relativePos.y = root.transform.position.y; } relativePos.y -= terrainPos.y; var newData = new PrefabObjectData() { AbsoluteHeight = RelativeMode == WorldStamp.EObjectRelativeMode.RelativeToStamp, Prefab = prefabAsset, Position = relativePos, Rotation = root.transform.rotation.eulerAngles, Scale = root.transform.lossyScale, Guid = GUID.Generate().ToString(), }; var c = transform.GetComponentInChildren <Collider>(); if (c) { BoundsMapping[newData] = c.bounds; } else { var r = transform.GetComponentInChildren <Renderer>(); if (r) { BoundsMapping[newData] = r.bounds; } } done.Add(root.transform); var doneChildren = root.transform.GetComponentsInChildren <Transform>(true); foreach (var item in doneChildren) { done.Add(item); } Objects.Add(newData); } #endif }