private void DebugPrototypeInformation(int prototypeID) { FoliagePrototype prototype = FoliageDB.sortedPrototypes[prototypeID]; GUILayout.Label(string.Format("{0} (ID: {1})", prototype.name, prototypeID), UNStandaloneUtility.boldLabel); GUILayout.Space(5); UNStandaloneUtility.BeginHorizontalOffset(25); GUILayout.Label("GPU Generated Density: " + prototype.maxGeneratedDensity); GUILayout.Label("Generation Radius: " + prototype.FoliageGenerationRadius.ToString().Replace("_", "")); //show radius and remove the "_" character. GUILayout.Label(string.Format("Width Noise: {0} ~ {1}", System.Math.Round(prototype.minimumWidth, 2), System.Math.Round(prototype.maximumWidth, 2))); GUILayout.Label(string.Format("Height Noise: {0} ~ {1}", System.Math.Round(prototype.minimumHeight, 2), System.Math.Round(prototype.maximumHeight, 2))); GUILayout.Space(5); GUILayout.Label("Wind:"); UNStandaloneUtility.BeginHorizontalOffset(25); GUILayout.Label("Individual Wind: " + prototype.useCustomWind); GUILayout.Label("Wind Bending: " + (prototype.useCustomWind == false ? FoliageDB.instance.globalWindSettings.windBending : prototype.customWindSettings.windBending)); GUILayout.Label("Wind Speed: " + (prototype.useCustomWind == false ? FoliageDB.instance.globalWindSettings.windSpeed : prototype.customWindSettings.windSpeed)); UNStandaloneUtility.EndHorizontalOffset(); UNStandaloneUtility.EndHorizontalOffset(); }
private void DebugGlobalSettings() { GUILayout.Space(10); GUILayout.Label(string.Format("Global Settings: (Frame: {0})", Time.frameCount), UNStandaloneUtility.boldLabel); GUILayout.Space(5); UNStandaloneUtility.BeginHorizontalOffset(25); GUILayout.Label(string.Format("Current Grided-Position : {0} ({1})", latestManagerChunk == null ? "Out Of Bounds" : latestManagerChunk.transform.position.ToString(), latestManagerChunk == null ? "NaN" : latestManagerChunk.isFoliageInstanceAttached ? latestManagerChunk.GetOrCreateFoliageManagerInstance().foliageAreaResolutionIntegral.ToString() : "Not Poppulated")); GUILayout.Label("Foliage Shadow Distance: " + (FoliageCore_MainManager.instance.useQualitySettingsShadowDistance ? QualitySettings.shadowDistance : FoliageCore_MainManager.instance.foliageShadowDistance)); GUILayout.Label("Foliage Foliage Density: " + FoliageCore_MainManager.instance.density); UNStandaloneUtility.EndHorizontalOffset(); }
void GridsCategory() { UNEditorUtility.DrawHelpBox("Grids Management", "Here you can manage your grids.", false, false); GUILayout.BeginHorizontal(); GUILayout.Space(Screen.width / 5); int resolution = terrain.sectorResolution == 1 ? 300 : (300 / terrain.sectorResolution); UNEditorUtility.DrawGridPreview(terrain.sectorResolution, UNStandaloneUtility.GetUIIcon("Square"), resolution, resolution); GUILayout.EndHorizontal(); GUILayout.Space(15); terrain.sectorResolution = EditorGUILayout.IntSlider(new GUIContent("Sector Resolution", "The resolution of the sector of the terrain, grids count = (resolution)^2"), terrain.sectorResolution, 1, Sector.resolutionLimit); }
private void DebugVisualSettings() { GUILayout.BeginVertical(); GUILayout.Space(10); GUILayout.Label("Visual Settings:", UNStandaloneUtility.boldLabel); UNStandaloneUtility.BeginHorizontalOffset(25); GUILayout.Space(5); GUILayout.Label("Vertices: " + string.Format("{0:n0}", lastRenderedVertices)); GUILayout.Label("Draw Calls: " + string.Format("{0:n0}", lastRenderedDrawCalls)); GUILayout.Label("Prototypes Drawn: " + string.Format("{0:n0}", lastRenderedPrototypes)); UNStandaloneUtility.EndHorizontalOffset(); GUILayout.EndVertical(); }
void DrawTabs() { string[] tabNames = System.Enum.GetNames(typeof(TerrainTabs)); Texture2D tabImage; TerrainTabs currentTabIndex; GUILayout.BeginHorizontal(); GUILayout.Space(Screen.width / 2.5f); bool buttonPressed = false; for (int i = 0; i < tabNames.Length; i++) { currentTabIndex = (System.Enum.GetValues(typeof(TerrainTabs)) as TerrainTabs[])[i]; GUI.color = currentTab == currentTabIndex ? chosenColor : Color.white; if (currentTabIndex == TerrainTabs.Vegetation) { tabImage = UNStandaloneUtility.GetUIIcon(tabNames[i] + (terrain.manageGrass ? "_On" : "_Off")); } else if (currentTabIndex == TerrainTabs.Trees) { tabImage = UNStandaloneUtility.GetUIIcon(tabNames[i] + (terrain.manageTrees ? "_On" : "_Off")); } else { tabImage = UNStandaloneUtility.GetUIIcon(tabNames[i]); } buttonPressed = GUILayout.Button(tabImage, tabsKeysStyle, GUILayout.MaxWidth(30), GUILayout.MaxHeight(30)); if (buttonPressed) { currentTab = currentTabIndex; } GUI.color = Color.white; } GUILayout.EndHorizontal(); }
protected override void Update() { if (!Application.isPlaying) { return; } base.Update(); FoliageCore_Chunk midChunk = middleFoliageChunkFromNeighbors; // middle chunk FoliageManagerInstance mInstance; if ((!wasPositionChecked || Vector3.Distance(lastCheckedPosition, transform.position) >= checkDistance) && isGrassReceiver && midChunk != null && midChunk.isFoliageInstanceAttached) { //latestChunk = FoliageManager.instance.sector.getChunk(new Vector3(transform.position.x - FoliageManager.instance.transform.position.x, 0, transform.position.z - FoliageManager.instance.transform.position.z), 0) as FoliageChunk; mInstance = midChunk.GetOrCreateFoliageManagerInstance(); latestChunk = mInstance.sector.getChunk(new Vector3(transform.position.x - mInstance.transform.position.x, 0, transform.position.z - mInstance.transform.position.z), 0) as FoliageChunk; _neighbors = UNStandaloneUtility.GetFoliageChunksNeighbors(transform.position - FoliageCore_MainManager.instance.transform.position, _neighbors); wasPositionChecked = true; lastCheckedPosition = transform.position; } }
/// <summary> /// Copy the terrain's details and use it with the custom Foliage system. /// </summary> /// <param name="terrain"></param> public void InsertFoliageFromTerrain(Terrain terrain) { UNStandaloneUtility.AddPrototypesIfDontExist(terrain.terrainData.detailPrototypes); List <int[, ]> detailData = UNStandaloneUtility.GetTerrainDetails(terrain.terrainData); int terrainDetailWidth = terrain.terrainData.detailWidth; int terrainDetailHeight = terrain.terrainData.detailHeight; var detailPrototypes = terrain.terrainData.detailPrototypes; var uNaturePrototypes = FoliageDB.sortedPrototypes; float posX; float posZ; int chunkIndex; FoliageCore_Chunk chunk; FoliageManagerInstance managerInstance; int prototype; float interpolatedX; float interpolatedZ; float worldPosX; float worldPosZ; FoliageGrassMap grassMap; for (int x = 0; x < terrainDetailWidth; x++) { for (int z = 0; z < terrainDetailHeight; z++) { worldPosX = ((x * terrain.terrainData.size.x) / terrainDetailWidth) + terrain.transform.position.x; worldPosZ = ((z * terrain.terrainData.size.z) / terrainDetailHeight) + terrain.transform.position.z; posX = worldPosX - transform.position.x; posZ = worldPosZ - transform.position.z; chunkIndex = GetChunkID(posX, posZ); if (CheckChunkInBounds(chunkIndex)) // If isn't out of bounds { chunk = sector.foliageChunks[chunkIndex]; managerInstance = chunk.GetOrCreateFoliageManagerInstance(); interpolatedX = managerInstance.TransformCord(worldPosX, managerInstance.transform.position.x); interpolatedZ = managerInstance.TransformCord(worldPosZ, managerInstance.transform.position.z); for (int prototypeIndex = 0; prototypeIndex < detailData.Count; prototypeIndex++) { prototype = UNStandaloneUtility.TryGetPrototypeIndex(detailPrototypes[prototypeIndex]); grassMap = managerInstance.grassMaps[uNaturePrototypes[prototype]]; grassMap.mapPixels[(int)interpolatedX + (int)interpolatedZ * grassMap.mapWidth].b = (byte)detailData[prototypeIndex][z, x]; // reset details on the terrain. detailData[prototypeIndex][z, x] = 0; grassMap.SetPixels32Delayed(); grassMap.dirty = true; } } } } for (int i = 0; i < detailData.Count; i++) { terrain.terrainData.SetDetailLayer(0, 0, i, detailData[i]); } SaveDelayedMaps(); //apply delayed maps. FoliageGrassMap.SaveAllMaps(); CallInstancesChunksUpdate(); #if UNITY_EDITOR UnityEditor.AssetDatabase.Refresh(); #endif }
void DrawPaintWindow() { GUILayout.BeginVertical("Box", GUILayout.Width(450)); GUILayout.BeginHorizontal(); GUILayout.Label("Paint Tools:", EditorStyles.boldLabel); GUILayout.FlexibleSpace(); if (GUILayout.Button("Reload Brushes")) { FoliageDB.instance.brushes = null; } GUILayout.EndHorizontal(); GUILayout.Space(5); GUILayout.BeginHorizontal(); GUILayout.BeginVertical("Box"); string[] paintMethodsNames = Enum.GetNames(typeof(CurrentPaintMethod)); CurrentPaintMethod currentType; for (int i = 0; i < paintMethodsNames.Length; i++) { currentType = (Enum.GetValues(typeof(CurrentPaintMethod)) as CurrentPaintMethod[])[i]; if (UNEditorUtility.DrawHighlitableButton(UNStandaloneUtility.GetUIIcon(paintMethodsNames[i]), paintMethod == currentType, GUILayout.Width(40), GUILayout.Height(40))) { paintMethod = currentType; // select the paint method. } } GUILayout.EndVertical(); GUILayout.Space(3); GUILayout.BeginVertical("Box", GUILayout.Height(100)); GUILayout.Label("Paint Settings:", EditorStyles.boldLabel); GUILayout.Space(5); switch (paintMethod) { case CurrentPaintMethod.Normal_Paint: DrawNormalBrush(); break; case CurrentPaintMethod.Spline_Paint: DrawSplineBrush(); break; } GUILayout.Space(5); paintBrushSize = EditorGUILayout.IntSlider(new GUIContent("Paint Brush Size:", "The percentage from the brush that will be drawn"), paintBrushSize, 1, 30); paintDensity = (byte)EditorGUILayout.IntSlider(new GUIContent("Paint Brush Density:", "The percentage from the brush that will be drawn"), paintDensity, 0, 15); instaRemove = EditorGUILayout.Toggle(new GUIContent("Instant Remove On Shift:", "Instantely remove the grass when shift is pressed (instead of needing to put density to 0"), instaRemove); GUILayout.EndVertical(); GUILayout.EndHorizontal(); if (FoliageGrassMap.globalDirty) { GUILayout.Space(10); EditorGUILayout.HelpBox("Foliage hasn't been saved after painting on terrain. \nPlease save the data by clicking the save button.", MessageType.Warning); if (GUILayout.Button("Save Grass Maps")) { FoliageGrassMap.SaveAllMaps(); EditorUtility.SetDirty(FoliageCore_MainManager.instance); if (!Application.isPlaying) { #if UNITY_5_3_OR_NEWER UnityEditor.SceneManagement.EditorSceneManager.SaveScene(UnityEngine.SceneManagement.SceneManager.GetActiveScene()); #else EditorApplication.SaveScene(); #endif } AssetDatabase.SaveAssets(); } } if (FoliageWorldMap.globalDirty) { GUILayout.Space(10); EditorGUILayout.HelpBox("World information isn't been saved. \nPlease save the data by clicking the save button or changes wont be applied.", MessageType.Warning); if (GUILayout.Button("Save World Map")) { FoliageWorldMap.SaveAllMaps(); EditorUtility.SetDirty(FoliageCore_MainManager.instance); if (!Application.isPlaying) { #if UNITY_5_3_OR_NEWER UnityEditor.SceneManagement.EditorSceneManager.SaveScene(UnityEngine.SceneManagement.SceneManager.GetActiveScene()); #else EditorApplication.SaveScene(); #endif } AssetDatabase.SaveAssets(); } } GUILayout.EndVertical(); }
public void DEBUG_DrawUI() { #if UNITY_EDITOR || DEVELOPMENT_BUILD if (Settings.UNSettings.instance.UN_Console_Debugging_Enabled) { #if UNITY_EDITOR Handles.BeginGUI(); #endif ClampDebugWindow(); if (DEBUG_Window_Open) { debugWindowRect = GUILayout.Window(3, debugWindowRect, (id) => { if (GUI.Button(new Rect(580, 0.75f, 15, 15), closeIcon, "Label")) { DEBUG_Window_Open = false; } if (FoliageCore_MainManager.instance.enabled) { if (GUI.Button(new Rect(565, -1f, 15, 15), DEBUG_Window_Minimized ? "+" : "-", "Label")) { DEBUG_Window_Minimized = !DEBUG_Window_Minimized; } if (!DEBUG_Window_Minimized) { GUILayout.BeginHorizontal(); GUILayout.BeginVertical(); #region Global Settings DebugGlobalSettings(); #endregion #region Prototypes GUILayout.Space(10); GUILayout.Label("Prototypes Settings:", UNStandaloneUtility.boldLabel); UNStandaloneUtility.BeginHorizontalOffset(25); for (int i = 0; i < FoliageDB.unSortedPrototypes.Count; i++) { GUILayout.Space(5); DebugPrototypeInformation(FoliageDB.unSortedPrototypes[i].id); } UNStandaloneUtility.EndHorizontalOffset(); #endregion GUILayout.EndVertical(); GUILayout.Space(10); DebugVisualSettings(); GUILayout.EndHorizontal(); } else { GUILayout.Label("", GUILayout.Height(15)); } } else { GUILayout.Label("Foliage disabled. Enable it on the FoliageManager component in your scene."); } GUI.DragWindow(); }, "uNature Debug", "Window", GUILayout.Width(600), GUILayout.Height((DEBUG_Window_Minimized || !FoliageCore_MainManager.instance.enabled) ? 2 : 400)); } #if UNITY_EDITOR Handles.EndGUI(); #endif } #endif }
public void OnDrawCamera(Camera camera) { if (!FoliageCore_MainManager.instance.enabled || prototypeMeshInstances == null) { return; } bool runCameraCheck = true; FoliageReceiver receiver = null; #if UNITY_EDITOR runCameraCheck = !UnityEditor.SceneView.GetAllSceneCameras().Contains(camera); #endif if (runCameraCheck) { if (FoliageReceiver.FReceivers.Count == 0) { return; } for (int i = 0; i < FoliageReceiver.FReceivers.Count; i++) { if (camera == FoliageReceiver.FReceivers[i].playerCamera) { receiver = FoliageReceiver.FReceivers[i]; break; } if (i == FoliageReceiver.FReceivers.Count - 1) { return; } } } if (receiver != null && !receiver.isGrassReceiver) { return; } int areaSizeIntegral = FoliageCore_MainManager.FOLIAGE_INSTANCE_AREA_SIZE; FoliageCore_Chunk[] targetedChunks = null; FoliageCore_Chunk currentMChunk; if (receiver == null) { targetedChunks = UNStandaloneUtility.GetFoliageChunksNeighbors(camera.transform.position - transform.position, targetedChunks); latestManagerChunk = targetedChunks[4]; } else { targetedChunks = receiver.neighbors; latestManagerChunk = receiver.middleFoliageChunkFromNeighbors; } Vector3 normalizedCameraPosition; FoliageManagerInstance mInstance; FoliageSector sector; FoliageChunk chunk; float density = FoliageCore_MainManager.instance.density; int instancesResolution = FoliageCore_MainManager.instance.instancesSectorResolution; #region PER_INSTANCE GPUMesh gpuInstance = null; FoliageChunk currentInstanceChunk; Vector3 pos; Material mat; int chunkIndex; FoliageMeshInstancesGroup meshGroup; FoliagePrototype prototype; int maxDensity; FoliageMeshInstance meshInstance; Vector3 chunkPos; int gpuMeshIndex = -1; Camera renderCamera = Application.isPlaying ? camera : null; List <FoliageChunk> chunks; Mesh targetMesh; Dictionary <int, GPUMesh> prototypeInstances; bool useQualitySettingsShadows = FoliageCore_MainManager.instance.useQualitySettingsShadowDistance; float shadowsDistance = FoliageCore_MainManager.instance.foliageShadowDistance; #endregion propertyBlock.SetVector("_StreamingAdjuster", UNStandaloneUtility.GetStreamingAdjuster()); if (receiver != null) { propertyBlock.SetFloat("_InteractionResolution", receiver.interactionMapResolutionIntegral); } for (int i = 0; i < targetedChunks.Length; i++) { currentMChunk = targetedChunks[i]; if (currentMChunk == null) { continue; } normalizedCameraPosition = camera.transform.position; if (!currentMChunk.InBounds(normalizedCameraPosition, 100) || !currentMChunk.isFoliageInstanceAttached) { continue; } mInstance = currentMChunk.GetOrCreateFoliageManagerInstance(); normalizedCameraPosition -= mInstance.transform.position; normalizedCameraPosition.x = Mathf.Clamp(normalizedCameraPosition.x, 0, areaSizeIntegral - 1); normalizedCameraPosition.z = Mathf.Clamp(normalizedCameraPosition.z, 0, areaSizeIntegral - 1); sector = mInstance.sector; chunks = sector.FoliageChunks; prototypeInstances = mInstance.meshInstances; chunk = sector.getChunk(normalizedCameraPosition) as FoliageChunk; if (chunk == null) { continue; } if (receiver != null) { propertyBlock.SetVector(PROPERTY_ID_FOLIAGE_INTERACTION_POSITION, chunk.position3D); } DEBUG_ResetValues(); mInstance.UpdateMaterialBlock(propertyBlock); for (int prototypeIndex = 0; prototypeIndex < FoliageDB.unSortedPrototypes.Count; prototypeIndex++) { prototype = FoliageDB.unSortedPrototypes[prototypeIndex]; if (!prototype.enabled) { continue; } int chunkOffset = FoliageMeshInstance.GENERATION_RANGE_OFFSET(prototype); int prototypeRadius = (int)prototype.FoliageGenerationRadius; propertyBlock.SetTexture(PROPERTY_ID_GRASSMAP, mInstance.grassMaps[prototype].map); //DEBUG _lastRenderedPrototypes++; try { gpuInstance = prototypeInstances[prototype.id]; } catch (System.Exception ex) { Debug.LogError(ex.ToString()); return; } try { mat = prototype.FoliageInstancedMeshData.mat; } catch { // if Foliage db was deleted/ a detail was removed... FoliageCore_MainManager.DestroyMeshInstance(prototype.id); OnDrawCamera(camera); return; } int xIndex; int zIndex; for (int x = 0; x < prototypeRadius; x++) { for (int z = 0; z < prototypeRadius; z++) { xIndex = chunk.x + (x - chunkOffset); zIndex = chunk.z + (z - chunkOffset); if (xIndex < 0 || zIndex < 0) { continue; } chunkIndex = xIndex + (zIndex * instancesResolution); if (chunkIndex >= chunks.Count) { continue; } currentInstanceChunk = chunks[chunkIndex]; if (currentInstanceChunk != null) { chunkPos = currentInstanceChunk.position3D; maxDensity = (int)(currentInstanceChunk.GetMaxDensityOnArea(prototype.id) * density); gpuMeshIndex = gpuInstance.GetMesh(maxDensity); if (gpuMeshIndex != -1) { //meshGroup = gpuInstance.LODMeshInstances[x, z, gpuMeshIndex]; meshGroup = gpuInstance.LODMeshInstances[gpuMeshIndex]; targetMesh = gpuInstance.meshes[gpuMeshIndex].mesh; for (int j = 0; j < meshGroup.Count; j++) { meshInstance = meshGroup[j]; pos = meshInstance.GetPosition(chunkPos); if (pos.x < 0 || pos.z < 0 || pos.x >= areaSizeIntegral || pos.z >= areaSizeIntegral) { continue; } propertyBlock.SetVector(PROPERTY_ID_WORLDPOSITION, pos); //DEBUG _lastRenderedVertices += targetMesh.vertexCount; //DEBUG _lastRenderedDrawCalls++; meshInstance.DrawAndUpdate(pos, targetMesh, mat, renderCamera, normalizedCameraPosition, prototype, propertyBlock, useQualitySettingsShadows, shadowsDistance); } } } } } } } }