public static void SnapshotSplats(this MMTerrainLayer layer, Terrain terrain) { var rawSplats = terrain.terrainData.GetAlphamaps(0, 0, terrain.terrainData.alphamapWidth, terrain.terrainData.alphamapHeight); layer.SplatData.Clear(); var splatWrapperLookup = ResolvePrototypes(terrain.terrainData.splatPrototypes); for (var k = 0; k < rawSplats.GetLength(2); ++k) { var prototype = terrain.terrainData.splatPrototypes[k]; SplatPrototypeWrapper wrapper; if (!splatWrapperLookup.TryGetValue(prototype, out wrapper)) { continue; } var data = new Serializable2DByteArray(terrain.terrainData.alphamapResolution, terrain.terrainData.alphamapResolution); float sum = 0; for (var u = 0; u < rawSplats.GetLength(0); ++u) { for (var v = 0; v < rawSplats.GetLength(1); ++v) { var sample = (byte)Mathf.Clamp(rawSplats[u, v, k] * 255f, 0, 255); data[v, u] = sample; sum += sample; } } if (sum > 0) { layer.SplatData[wrapper] = data; } } }
private void DrawLayerElementCallback(Rect rect, int index, bool isActive, bool isFocused) { rect.y += 2; rect.height -= 2; float headerHeight = 18; float previewTexSize = 57; float objFieldWidth = rect.width - previewTexSize - previewTexSize / 2; var layerNumberRect = new Rect(rect.x, rect.y, 10, headerHeight); EditorGUI.LabelField(layerNumberRect, index.ToString()); var nameRect = new Rect(layerNumberRect.xMax + 4, rect.y, objFieldWidth, headerHeight); var newKey = (DetailPrototypeWrapper)EditorGUI.ObjectField(nameRect, _wrapper.DetailPrototypes[index], typeof(DetailPrototypeWrapper), false); if (newKey != _wrapper.DetailPrototypes[index]) { _wrapper.DetailPrototypes[index] = newKey; _wrapper.RefreshDetails(); } if (_wrapper.DetailPrototypes[index] == null) { return; } var previewRect = new Rect(layerNumberRect.xMax + 4 + objFieldWidth + 4, rect.y, previewTexSize, previewTexSize); var tex = _wrapper.DetailPrototypes[index] != null ? _wrapper.DetailPrototypes[index].PrototypeTexture : null; GUI.DrawTexture(previewRect, tex); var infoRect = new Rect(layerNumberRect.xMax + 4, rect.y + headerHeight, objFieldWidth, rect.height - headerHeight); bool any = false; StringBuilder sb = new StringBuilder("Written to by: "); foreach (var MMTerrainLayer in _wrapper.Layers) { var wrappers = MMTerrainLayer.GetDetailPrototypeWrappers(); if (wrappers != null && wrappers.Contains(_wrapper.DetailPrototypes[index])) { sb.Append(MMTerrainLayer.name); sb.Append(" "); any = true; } } if (any) { var style = EditorStyles.label; style.wordWrap = true; EditorGUI.LabelField(infoRect, sb.ToString(), style); } }
public static void SnapshotVegetationStudioData(this MMTerrainLayer layer, Terrain terrain) { layer.VSRemovals.Clear(); layer.VSInstances.Clear(); var vegStorages = UnityEngine.Object.FindObjectsOfType <PersistentVegetationStorage>(); foreach (var vegStorage in vegStorages) { var vegSys = vegStorage.GetComponent <VegetationSystem>(); if (vegSys.GetTerrain() != terrain) { continue; } if (vegSys.CurrentVegetationPackage == null) { Debug.LogWarning(string.Format("Couldn't capture from system {0} as it doesn't have a Vegetation Package assigned.", vegSys), vegSys); continue; } if (vegStorage == null) { Debug.LogError(string.Format("Unable to find Vegetation Storage from system {0}!", vegSys), vegSys); continue; } if (vegStorage.PersistentVegetationStoragePackage == null) { Debug.LogError(string.Format("Unable to find PersistentVegetation Storage from system {0}!", vegStorage), vegStorage); continue; } foreach (var cell in vegStorage.PersistentVegetationStoragePackage.PersistentVegetationCellList) { foreach (var info in cell.PersistentVegetationInfoList) { foreach (var item in info.VegetationItemList) { var wPos = terrain.GetPosition() + item.Position; var pos = terrain.WorldToTreePos(wPos); pos.y = wPos.y - terrain.SampleHeight(wPos) - terrain.GetPosition().y; layer.VSInstances.Add(new VegetationStudioInstance() { Guid = System.Guid.NewGuid().ToString(), Position = pos, Rotation = item.Rotation.eulerAngles, Scale = item.Scale, VSID = info.VegetationItemID, Package = vegSys.CurrentVegetationPackage, }); } } } } }
public static void SnapshotTrees(this MMTerrainLayer layer, Terrain terrain) { layer.Trees.Clear(); var tSize = terrain.terrainData.size; var trees = terrain.terrainData.treeInstances; var prototypes = new List <TreePrototype>(terrain.terrainData.treePrototypes); for (var i = 0; i < trees.Length; i++) { var wPos = terrain.TreeToWorldPos(trees[i].position); var h = terrain.SampleHeight(wPos); var newInstance = new MadMapsTreeInstance(trees[i], prototypes); newInstance.Position.y = (newInstance.Position.y * tSize.y) - h; layer.Trees.Add(newInstance); } }
public static void SnapshotDetails(this MMTerrainLayer layer, Terrain terrain) { layer.DetailData.Clear(); var prototypes = terrain.terrainData.detailPrototypes; var dRes = terrain.terrainData.detailResolution; var wrapperLookup = ResolvePrototypes(prototypes); for (var i = 0; i < prototypes.Length; i++) { DetailPrototypeWrapper wrapper; var prototype = prototypes[i]; if (!wrapperLookup.TryGetValue(prototype, out wrapper)) { continue; } var data = new Serializable2DByteArray(dRes, dRes); var detailMap = terrain.terrainData.GetDetailLayer(0, 0, terrain.terrainData.detailWidth, terrain.terrainData.detailHeight, i); int sum = 0; for (var u = 0; u < detailMap.GetLength(0); u++) { for (var v = 0; v < detailMap.GetLength(1); v++) { var sample = (byte)detailMap[u, v]; data[v, u] = sample; sum += sample; } } if (sum > 0) { layer.DetailData.Add(wrapper, data); } } }
public static void SnapshotHeights(this MMTerrainLayer layer, Terrain terrain) { layer.Heights = new Serializable2DFloatArray(terrain.terrainData.GetHeights(0, 0, terrain.terrainData.heightmapWidth, terrain.terrainData.heightmapHeight).Flip()); }
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 }
public static MMTerrainLayer DrawExpandedGUI(TerrainWrapper wrapper, MMTerrainLayer layer) { bool isInScene = layer != null && string.IsNullOrEmpty(AssetDatabase.GetAssetPath(layer)); EditorGUILayout.BeginHorizontal(); layer = (MMTerrainLayer)EditorGUILayout.ObjectField(isInScene ? "Asset (In-Scene)" : "Asset", layer, typeof(MMTerrainLayer), true); if (layer != null && isInScene && GUILayout.Button(_saveContent, EditorStyles.label, GUILayout.Width(20), GUILayout.Height(16))) { var path = EditorUtility.SaveFilePanel("Save Terrain Layer", "Assets", layer.name, "asset"); if (!string.IsNullOrEmpty(path)) { path = path.Substring(path.LastIndexOf("Assets/", StringComparison.Ordinal)); AssetDatabase.CreateAsset(layer, path); } } EditorGUILayout.EndHorizontal(); if (layer == null) { EditorGUILayout.HelpBox("Snapshot is Null!", MessageType.Error); if (GUILayout.Button("Create Snapshot", EditorStyles.toolbarButton)) { layer = ScriptableObject.CreateInstance <MMTerrainLayer>(); GUIUtility.ExitGUI(); return(layer); } EditorGUILayout.EndVertical(); return(layer); } EditorGUILayout.BeginHorizontal(); var previewContent = new GUIContent(GUIResources.EyeOpenIcon, "Preview"); EditorGUILayout.LabelField("Height:", layer.Heights != null ? string.Format("{0}x{1}", layer.Heights.Width, layer.Heights.Height) : "null"); if (layer.Heights != null && GUILayout.Button(previewContent, EditorStyles.label, GUILayout.Width(20), GUILayout.Height(16))) { DataInspector.SetData(layer.Heights); } if (GUILayout.Button(GenericEditor.DeleteContent, EditorStyles.label, GUILayout.Width(20)) && EditorUtility.DisplayDialog("Really Clear?", "", "Yes", "No")) { layer.Heights.Clear(); EditorUtility.SetDirty(layer); EditorGUIUtility.ExitGUI(); return(layer); } EditorGUILayout.EndHorizontal(); EditorExtensions.Seperator(); EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("Splats", layer.SplatData != null ? string.Format("{0}", layer.SplatData.Count) : "null"); if (layer.SplatData != null && GUILayout.Button(previewContent, EditorStyles.label, GUILayout.Width(20), GUILayout.Height(16))) { List <IDataInspectorProvider> data = new List <IDataInspectorProvider>(); List <object> context = new List <object>(); foreach (var keyValuePair in layer.SplatData) { data.Add(keyValuePair.Value); context.Add(keyValuePair.Key); } DataInspector.SetData(data, context); } if (GUILayout.Button(GenericEditor.DeleteContent, EditorStyles.label, GUILayout.Width(20)) && EditorUtility.DisplayDialog("Really Clear?", "", "Yes", "No")) { layer.SplatData.Clear(); EditorUtility.SetDirty(layer); EditorGUIUtility.ExitGUI(); return(layer); } EditorGUILayout.EndHorizontal(); EditorExtensions.Seperator(); EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("Details", layer.DetailData != null ? string.Format("{0}", layer.DetailData.Count) : "null"); if (layer.DetailData != null && GUILayout.Button(previewContent, EditorStyles.label, GUILayout.Width(20), GUILayout.Height(16))) { List <IDataInspectorProvider> data = new List <IDataInspectorProvider>(); List <object> context = new List <object>(); foreach (var keyValuePair in layer.DetailData) { data.Add(keyValuePair.Value); context.Add(keyValuePair.Key); } DataInspector.SetData(data, context, true); } if (GUILayout.Button(GenericEditor.DeleteContent, EditorStyles.label, GUILayout.Width(20)) && EditorUtility.DisplayDialog("Really Clear?", "", "Yes", "No")) { layer.DetailData.Clear(); EditorUtility.SetDirty(layer); EditorGUIUtility.ExitGUI(); return(layer); } EditorGUILayout.EndHorizontal(); EditorExtensions.Seperator(); EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("Trees", layer.Trees != null ? string.Format("{0}", layer.Trees.Count) : "null"); if (layer.Trees != null && GUILayout.Button(previewContent, EditorStyles.label, GUILayout.Width(20), GUILayout.Height(16))) { Dictionary <object, IDataInspectorProvider> data = new Dictionary <object, IDataInspectorProvider>(); foreach (var tree in layer.Trees) { if (!data.ContainsKey(tree.Prototype)) { data[tree.Prototype] = new PositionList(); } (data[tree.Prototype] as PositionList).Add(tree.Position); } DataInspector.SetData(data.Values.ToList(), data.Keys.ToList(), true); } if (GUILayout.Button(GenericEditor.DeleteContent, EditorStyles.label, GUILayout.Width(20)) && EditorUtility.DisplayDialog("Really Clear?", "", "Yes", "No")) { layer.Trees.Clear(); EditorUtility.SetDirty(layer); EditorGUIUtility.ExitGUI(); return(layer); } EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("➥Removals", layer.TreeRemovals != null ? string.Format("{0}", layer.TreeRemovals.Count) : "null"); if (layer.TreeRemovals != null && GUILayout.Button(previewContent, EditorStyles.label, GUILayout.Width(20), GUILayout.Height(16))) { Dictionary <object, IDataInspectorProvider> data = new Dictionary <object, IDataInspectorProvider>(); var compoundTrees = wrapper.GetCompoundTrees(layer, false); compoundTrees.AddRange(layer.Trees); foreach (var guid in layer.TreeRemovals) { MadMapsTreeInstance tree = null; foreach (var t in compoundTrees) { if (t.Guid == guid) { tree = t; break; } } if (tree == null) { Debug.LogError("Couldn't find tree removal " + guid, layer); continue; } if (!data.ContainsKey(tree.Prototype)) { data[tree.Prototype] = new PositionList(); } (data[tree.Prototype] as PositionList).Add(tree.Position); } DataInspector.SetData(data.Values.ToList(), data.Keys.ToList(), true); } if (GUILayout.Button(GenericEditor.DeleteContent, EditorStyles.label, GUILayout.Width(20)) && EditorUtility.DisplayDialog("Really Clear?", "", "Yes", "No")) { layer.TreeRemovals.Clear(); EditorUtility.SetDirty(layer); EditorGUIUtility.ExitGUI(); return(layer); } EditorGUILayout.EndHorizontal(); EditorExtensions.Seperator(); #if VEGETATION_STUDIO EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("Vegetation Studio", layer.VSInstances != null ? string.Format("{0}", layer.VSInstances.Count) : "null"); if (layer.VSInstances != null && GUILayout.Button(previewContent, EditorStyles.label, GUILayout.Width(20), GUILayout.Height(16))) { Dictionary <object, IDataInspectorProvider> data = new Dictionary <object, IDataInspectorProvider>(); foreach (var tree in layer.VSInstances) { if (!data.ContainsKey(tree.VSID)) { data[tree.VSID] = new PositionList(); } (data[tree.VSID] as PositionList).Add(tree.Position); } DataInspector.SetData(data.Values.ToList(), data.Keys.ToList(), true); } if (GUILayout.Button(GenericEditor.DeleteContent, EditorStyles.label, GUILayout.Width(20)) && EditorUtility.DisplayDialog("Really Clear?", "", "Yes", "No")) { layer.VSInstances.Clear(); EditorUtility.SetDirty(layer); EditorGUIUtility.ExitGUI(); return(layer); } EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("➥Removals", layer.VSRemovals != null ? string.Format("{0}", layer.VSRemovals.Count) : "null"); if (layer.VSRemovals != null && GUILayout.Button(previewContent, EditorStyles.label, GUILayout.Width(20), GUILayout.Height(16))) { Dictionary <object, IDataInspectorProvider> data = new Dictionary <object, IDataInspectorProvider>(); var compoundVS = wrapper.GetCompoundVegetationStudioData(layer, false); compoundVS.AddRange(layer.VSInstances); foreach (var guid in layer.VSRemovals) { VegetationStudioInstance vsInstance = null; foreach (var t in compoundVS) { if (t.Guid == guid) { vsInstance = t; break; } } if (vsInstance == null) { Debug.LogError("Couldn't find VS removal " + guid, layer); continue; } if (!data.ContainsKey(vsInstance.VSID)) { data[vsInstance.VSID] = new PositionList(); } (data[vsInstance.VSID] as PositionList).Add(vsInstance.Position); } DataInspector.SetData(data.Values.ToList(), data.Keys.ToList(), true); } if (GUILayout.Button(GenericEditor.DeleteContent, EditorStyles.label, GUILayout.Width(20)) && EditorUtility.DisplayDialog("Really Clear?", "", "Yes", "No")) { layer.VSRemovals.Clear(); EditorUtility.SetDirty(layer); EditorGUIUtility.ExitGUI(); return(layer); } EditorGUILayout.EndHorizontal(); EditorExtensions.Seperator(); #endif EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("Objects", layer.Objects != null ? string.Format("{0}", layer.Objects.Count) : "null"); if (layer.Objects != null && GUILayout.Button(previewContent, EditorStyles.label, GUILayout.Width(20), GUILayout.Height(16))) { Dictionary <object, IDataInspectorProvider> data = new Dictionary <object, IDataInspectorProvider>(); foreach (var obj in layer.Objects) { if (!data.ContainsKey(obj.Prefab)) { data[obj.Prefab] = new PositionList(); } (data[obj.Prefab] as PositionList).Add(obj.Position); } DataInspector.SetData(data.Values.ToList(), data.Keys.ToList(), true); } if (GUILayout.Button(GenericEditor.DeleteContent, EditorStyles.label, GUILayout.Width(20)) && EditorUtility.DisplayDialog("Really Clear?", "", "Yes", "No")) { layer.Objects.Clear(); EditorUtility.SetDirty(layer); EditorGUIUtility.ExitGUI(); return(layer); } EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("➥Removals", layer.ObjectRemovals != null ? string.Format("{0}", layer.ObjectRemovals.Count) : "null"); if (layer.ObjectRemovals != null && GUILayout.Button(previewContent, EditorStyles.label, GUILayout.Width(20), GUILayout.Height(16))) { Dictionary <object, IDataInspectorProvider> data = new Dictionary <object, IDataInspectorProvider>(); var compoundObjs = wrapper.GetCompoundObjects(layer, false); compoundObjs.AddRange(layer.Objects); foreach (var guid in layer.ObjectRemovals) { WorldStamps.PrefabObjectData?obj = null; foreach (var t in compoundObjs) { if (t.Guid == guid) { obj = t; break; } } if (obj == null) { Debug.LogError("Couldn't find object removal " + guid, layer); continue; } if (!data.ContainsKey(obj.Value.Prefab)) { data[obj.Value.Prefab] = new PositionList(); } (data[obj.Value.Prefab] as PositionList).Add(obj.Value.Position); } DataInspector.SetData(data.Values.ToList(), data.Keys.ToList(), true); } if (GUILayout.Button(GenericEditor.DeleteContent, EditorStyles.label, GUILayout.Width(20)) && EditorUtility.DisplayDialog("Really Clear?", "", "Yes", "No")) { layer.ObjectRemovals.Clear(); EditorUtility.SetDirty(layer); EditorGUIUtility.ExitGUI(); return(layer); } EditorGUILayout.EndHorizontal(); EditorExtensions.Seperator(); EditorGUILayout.BeginHorizontal(); bool hasStencil = layer.Stencil != null && layer.Stencil.Width > 0 && layer.Stencil.Height > 0;; EditorGUILayout.LabelField("Stencil" + (hasStencil ? "" : " (null)"), layer.Stencil != null ? string.Format("{0}", string.Format("{0}x{1}", layer.Stencil.Width, layer.Stencil.Height)) : "null"); GUI.enabled = hasStencil; if (GUILayout.Button(EditorGUIUtility.IconContent("Terrain Icon"), EditorStyles.label, GUILayout.Width(20), GUILayout.Height(16))) { TerrainWrapperGUI.StencilLayerDisplay = layer; } if (GUILayout.Button(previewContent, EditorStyles.label, GUILayout.Width(20), GUILayout.Height(16))) { DataInspector.SetData(layer.Stencil); } GUI.enabled = true; if (GUILayout.Button(GenericEditor.DeleteContent, EditorStyles.label, GUILayout.Width(20)) && EditorUtility.DisplayDialog("Really Clear?", "", "Yes", "No")) { layer.Stencil.Clear(); EditorUtility.SetDirty(layer); EditorGUIUtility.ExitGUI(); return(layer); } EditorGUILayout.EndHorizontal(); EditorExtensions.Seperator(); EditorGUILayout.LabelField("Layer Commands", EditorStyles.boldLabel); EditorGUILayout.BeginHorizontal(); if (GUILayout.Button("Capture From Terrain")) { if (EditorUtility.DisplayDialog(string.Format("Capture Layer {0} from current Terrain?", layer.name), "This will clear any existing data!", "Yes", "No")) { layer.SnapshotTerrain(wrapper.Terrain); EditorUtility.SetDirty(layer); EditorUtility.SetDirty(wrapper.Terrain); EditorSceneManager.MarkAllScenesDirty(); AssetDatabase.SaveAssets(); EditorUtility.SetDirty(layer); EditorGUIUtility.ExitGUI(); return(layer); } } EditorGUILayout.Space(); if (GUILayout.Button("Apply To Terrain")) { if (wrapper.PrepareApply()) { layer.WriteToTerrain(wrapper); wrapper.FinaliseApply(); EditorUtility.SetDirty(layer); EditorSceneManager.MarkAllScenesDirty(); EditorGUIUtility.ExitGUI(); return(layer); } } EditorGUILayout.Space(); if (GUILayout.Button("Clear Layer")) { if (EditorUtility.DisplayDialog(string.Format("Clear Layer {0}?", layer.name), "This will clear any existing data!", "Yes", "No")) { layer.Clear(wrapper); EditorUtility.SetDirty(wrapper.Terrain); EditorUtility.SetDirty(layer); EditorSceneManager.MarkAllScenesDirty(); EditorGUIUtility.ExitGUI(); return(layer); } } EditorGUILayout.EndHorizontal(); EditorGUILayout.Space(); return(layer); }
void OnDisable() { StencilLayerDisplay = null; }