/// <summary> /// Get the MicroSplatData folder in the project folder, given a terrain material. /// trimAsset = true will remove the "Assets/" from the beginning of the folder /// </summary> /// <param name="terrainMat"></param> /// <param name="trimAssets"></param> /// <returns></returns> public static string GetMicroSplatDataFolder(Material terrainMat, bool trimAssets) { string path = LBEditorHelper.GetAssetFolder(terrainMat); if (string.IsNullOrEmpty(path)) { path = UnityEditor.SceneManagement.EditorSceneManager.GetActiveScene().path; } if (string.IsNullOrEmpty(path)) { path = "Assets"; } path = path.Replace("\\", "/"); if (path.Contains("/")) { path = path.Substring(0, path.LastIndexOf("/")); } path += "/MicroSplatData"; if (trimAssets) { path = path.Replace("Assets/", ""); } //Debug.Log("[DEBUG] path: " + path); return(path); }
private void ResetScale() { if (lbGroupMember != null && lbGroupDesignerItem != null) { if (lbGroupMember.isGroupOverride) { if (lbGroupMember.isKeepPrefabConnection) { // Find the original source prefab in the project folder #if UNITY_2018_2_OR_NEWER GameObject prefabSource = (GameObject)UnityEditor.PrefabUtility.GetCorrespondingObjectFromSource(lbGroupDesignerItem.gameObject); #else GameObject prefabSource = (GameObject)UnityEditor.PrefabUtility.GetPrefabParent(lbGroupDesignerItem.gameObject); #endif if (prefabSource != null) { lbGroupMember.minScale = prefabSource.transform.localScale.x; lbGroupMember.maxScale = lbGroupMember.minScale; } else { lbGroupMember.minScale = 1f; lbGroupMember.maxScale = 1f; } } else { lbGroupMember.minScale = 1f; lbGroupMember.maxScale = 1f; } lbGroupDesignerItem.lbGroupDesigner.UpdateGroupMember(lbGroupMember); LBEditorHelper.RepaintEditorWindow(typeof(LandscapeBuilderWindow)); } } }
/// <summary> /// Snap the prefab to ground (y-axis). Sets the prefab position to 0 on y-axis. /// If isConsiderPrefabExtents is true, set ground to be the bottom of the prefab /// rather than its pivot point. /// NOTE: Currently doesn't consider scaling. /// </summary> /// <param name="isConsiderPrefabExtents"></param> private void SnapToGround(bool isConsiderPrefabExtents = false) { if (lbGroupMember != null && lbGroupDesignerItem != null) { // Default lbGroupMember.minOffsetY = 0f; lbGroupMember.maxOffsetY = 0f; if (isConsiderPrefabExtents && lbGroupMember.prefab != null && lbGroupMember.lbMemberType == LBGroupMember.LBMemberType.Prefab) { // Need to reset y value for GetBounds to work correctly Vector3 tempPos = lbGroupMember.prefab.transform.position; tempPos.y = 0f; lbGroupMember.prefab.transform.position = tempPos; Bounds bounds = LBMeshOperations.GetBounds(lbGroupMember.prefab.transform, false, true); if (bounds.extents.y != 0f) { // bounds.extents.y is half the height of the prefab. lbGroupMember.minOffsetY = bounds.extents.y - bounds.center.y; lbGroupMember.maxOffsetY = lbGroupMember.minOffsetY; } } lbGroupDesignerItem.lbGroupDesigner.UpdateGroupMember(lbGroupMember); LBEditorHelper.RepaintEditorWindow(typeof(LandscapeBuilderWindow)); } }
// Upgrade project folders and move anything to correct location static void UpgradeProject() { // Move materials into a resources folders so that they are found in runtime generation LBEditorHelper.MoveAsset("LBSetup.UpgradeProject", materialsFolder, materialsFolder + "/Resources", "LBMoon.mat"); LBEditorHelper.MoveAsset("LBSetup.UpgradeProject", materialsFolder, materialsFolder + "/Resources", "LBTerrain.mat"); #if SCSM_SSC // If Sci-Fi Ship Controller is installed first, LBStar.mat exists in a non-resource folder in SSC. LBEditorHelper.MoveAsset("LBSetup.UpgradeProject", "Assets/SCSM/SciFiShipController/Demos/Materials/Environment", materialsFolder + "/Resources", "LBStar.mat"); // Move stars into resources folder so that celestials get built at runtime correctly LBEditorHelper.CheckFolder(modelsFolder); LBEditorHelper.MoveAsset("LBSetup.UpgradeProject", "Assets/SCSM/SciFiShipController/Demos/Models/Environment", modelsFolder + "/Resources", "StarLowPolyFBX.fbx"); #else LBEditorHelper.MoveAsset("LBSetup.UpgradeProject", materialsFolder, materialsFolder + "/Resources", "LBStar.mat"); // Move stars into resources folder so that celestials get built at runtime correctly LBEditorHelper.MoveAsset("LBSetup.UpgradeProject", modelsFolder, modelsFolder + "/Resources", "StarLowPolyFBX.fbx"); #endif // Move the shaders into a resources folder LBEditorHelper.MoveAsset("LBSetup.UpgradeProject", shadersFolder, shadersFolder + "/Resources", "LBTerrain-Base.shader"); LBEditorHelper.MoveAsset("LBSetup.UpgradeProject", shadersFolder, shadersFolder + "/Resources", "LBTerrain-AddPass.shader"); LBEditorHelper.MoveAsset("LBSetup.UpgradeProject", shadersFolder, shadersFolder + "/Resources", "LBTerrain-FirstPass.shader"); // v1.3.5 if (File.Exists(shadersFolder + "/" + "LBWeatherFX.shader") || File.Exists(shadersFolder + "/Resources/" + "LBWeatherFX.shader")) { Debug.LogWarning("WARNING: Landscape Builder - LBWeatherFX was replaced in v1.3.5 with LBImageFX - please consult the manual or contact support"); } if (File.Exists(shadersFolder + "/" + "LBSimpleSSRR.shader")) { Debug.LogWarning("WARNING: Landscape Builder - LBSimpleSSRR was replaced in v1.3.5 with LBImageFX - please consult the manual or contact support"); } // If the Designers are in the wrong folder, move them #if LB_EDITOR LBEditorHelper.MoveAsset("LBSetup.UpgradeProject", scriptsBehavioursFolder, scriptsDesignersFolder, "LBGroupDesigner.cs"); #endif LBEditorHelper.MoveAsset("LBSetup.UpgradeProject", scriptsBehavioursFolder, scriptsDesignersFolder, "LBStencilBrushPainter.cs"); // LB 2.0.4 may have incorrectly created a Material folder in Demo Scene\Models if (Directory.Exists(demosceneFolder + "/Models/Materials")) { if (AssetDatabase.DeleteAsset(demosceneFolder + "/Models/Materials")) { Debug.Log("INFO: Landscape Builder - Removed legacy " + demosceneFolder + "/Models/Materials folder"); } } // LB 2.2.0 Support for multiple SRP versions LBEditorHelper.RenameAsset("LBSetup.UpgradeProject", lbFolder + "/SRP", "LB_LWRP.unitypackage", "LB_LWRP_4.0.1.unitypackage"); LBEditorHelper.RenameAsset("LBSetup.UpgradeProject", lbFolder + "/SRP", "LB_HDRP.unitypackage", "LB_HDRP_4.9.0.unitypackage"); // LB 2.2.1 If the SRP version-based packages where imported, the rename above would not have updated original packages LBEditorHelper.DeleteAsset("LBSetup.UpgradeProject", lbFolder + "/SRP", "LB_HDRP.unitypackage"); LBEditorHelper.DeleteAsset("LBSetup.UpgradeProject", lbFolder + "/SRP", "LB_LWRP.unitypackage"); }
/// <summary> /// Add a zone at the same location as an object/prefab using its extents. /// NOTE: Rectangular zones cannot be rotated, so only width and length can be switched /// </summary> private void AddZoneToObject() { if (lbGroup != null && lbGroupMember != null && lbGroupDesignerItem != null && lbGroupMember.prefab != null && lbGroupMember.lbMemberType == LBGroupMember.LBMemberType.Prefab) { // Need to reset postion for GetBounds to work correctly Vector3 tempPos = lbGroupMember.prefab.transform.position; lbGroupMember.prefab.transform.position = Vector3.zero; Bounds bounds = LBMeshOperations.GetBounds(lbGroupMember.prefab.transform, false, true); lbGroupMember.prefab.transform.position = tempPos; if (bounds.extents.x != 0f && bounds.extents.z != 0f && lbGroup.maxClearingRadius > 0f) { LBGroupZone lbGroupZone = new LBGroupZone(); if (lbGroupZone != null) { if (bounds.extents.x == bounds.extents.z) { lbGroupZone.zoneType = LBGroupZone.LBGroupZoneType.circle; lbGroupZone.centrePointX = lbGroupMember.minOffsetX / lbGroup.maxClearingRadius; lbGroupZone.centrePointZ = lbGroupMember.minOffsetZ / lbGroup.maxClearingRadius; lbGroupZone.width = (bounds.extents.x - bounds.center.x) / lbGroup.maxClearingRadius; lbGroupZone.length = lbGroupZone.width; } else { lbGroupZone.zoneType = LBGroupZone.LBGroupZoneType.rectangle; lbGroupZone.centrePointX = lbGroupMember.minOffsetX / lbGroup.maxClearingRadius; lbGroupZone.centrePointZ = lbGroupMember.minOffsetZ / lbGroup.maxClearingRadius; lbGroupZone.width = (bounds.extents.x - bounds.center.x) * 2f / lbGroup.maxClearingRadius; lbGroupZone.length = (bounds.extents.z - bounds.center.z) * 2f / lbGroup.maxClearingRadius; float rotationY = lbGroupDesignerItem.transform.rotation.eulerAngles.y; // Get the absolute rotation on y-axis if (rotationY < 0) { rotationY = -rotationY; } // cater for rotation by switching width and length if ((rotationY > 45f && rotationY < 135f) || (rotationY > 225f && rotationY < 315f)) { float width = lbGroupZone.width; lbGroupZone.width = lbGroupZone.length; lbGroupZone.length = width; } } lbGroupZone.zoneName = lbGroupMember.prefab.name + " zone"; lbGroup.zoneList.Add(lbGroupZone); } } LBEditorHelper.RepaintEditorWindow(typeof(LandscapeBuilderWindow)); } }
/// <summary> /// Find the TextureArrayConfig for a given MicroSplat terrain material. /// This assumes it is always in the same project folder /// </summary> /// <param name="terrainMat"></param> /// <returns></returns> public static JBooth.MicroSplat.TextureArrayConfig GetTextureArrayConfig(Material terrainMat) { JBooth.MicroSplat.TextureArrayConfig textureArrayConfig = null; if (terrainMat != null) { string folder = GetMicroSplatDataFolder(terrainMat, true); textureArrayConfig = LBEditorHelper.GetAsset <JBooth.MicroSplat.TextureArrayConfig>(folder, terrainMat.name.Replace("MicroSplat", "MicroSplatConfig") + ".asset"); } return(textureArrayConfig); }
private void ResetRotation() { if (lbGroupMember != null && lbGroupDesignerItem != null) { lbGroupMember.rotationX = 0f; lbGroupMember.rotationZ = 0f; lbGroupMember.startRotationY = 0f; lbGroupMember.endRotationY = 359.9f; lbGroupDesignerItem.lbGroupDesigner.UpdateGroupMember(lbGroupMember); LBEditorHelper.RepaintEditorWindow(typeof(LandscapeBuilderWindow)); } }
private void OnEnable() { lbGroupLocationItem = (LBGroupLocationItem)target; landscape = lbGroupLocationItem.transform.GetComponentInParent <LBLandscape>(); landscapeBounds = landscape.GetLandscapeWorldBoundsFast(); prevPosition = lbGroupLocationItem.transform.position; if (lbGroupLocationItem.lbGroup != null && lbGroupLocationItem.lbGroup.isFixedRotation) { lbGroupLocationItem.rotationY = lbGroupLocationItem.transform.rotation.eulerAngles.y; // When first selected, update the rotation in the LB editor LBEditorHelper.RepaintEditorWindow(typeof(LandscapeBuilderWindow)); } //Debug.Log("WorldBounds: " + landscapeBounds.xMin + "," + landscapeBounds.yMin + " - " + landscapeBounds.xMax + "," + landscapeBounds.yMax); }
/// <summary> /// Add a new Location object and script to the scene. Append the location /// </summary> /// <param name="landscape"></param> /// <param name="lbGroupLocation"></param> /// <param name="showErrors"></param> /// <returns></returns> public static LBGroupLocationItem AddNewLocationToScene(LBLandscape landscape, LBGroup lbGroupLocation, Vector2 mousePosition, Camera svCamera, bool showErrors) { LBGroupLocationItem lbGroupLocationItem = null; string methodName = "LBGroupLocationItem.AddNewLocationToScene"; // Basic validation if (landscape == null) { if (showErrors) { Debug.LogWarning("ERROR: " + methodName + " landscape is null"); } } else if (lbGroupLocation == null) { if (showErrors) { Debug.LogWarning("ERROR: " + methodName + " lbGroupLocation is null"); } } else { Vector3 locationPoint = Vector3.zero; locationPoint = LBEditorHelper.GetLandscapePositionFromMouse(landscape, mousePosition, false, true); if (locationPoint.x != 0 && locationPoint.z != 0) { //Debug.Log("[DEBUG] locationPoint " + locationPoint + " mousePos: " + mousePosition); Material locationMaterial = null; locationMaterial = LBEditorHelper.GetMaterialFromAssets(LBSetup.materialsFolder, "LBLocation.mat"); lbGroupLocationItem = CreateLocationItemInScene(landscape, lbGroupLocation, locationMaterial, locationPoint, 0f, lbGroupLocation.positionList.Count + 1, showErrors); if (lbGroupLocationItem != null) { lbGroupLocationItem.lbGroup.positionList.Add(locationPoint - landscape.start); if (lbGroupLocationItem.lbGroup.isFixedRotation) { lbGroupLocationItem.lbGroup.rotationYList.Add(0f); } LBEditorHelper.RepaintLBW(); } } } return(lbGroupLocationItem); }
private void ResetPosition() { if (lbGroupMember != null && lbGroupDesignerItem != null) { lbGroupMember.minOffsetX = 0f; lbGroupMember.minOffsetZ = 0f; if (!lbGroupMember.randomiseOffsetY) { lbGroupMember.minOffsetY = 0f; } lbGroupDesignerItem.lbGroupDesigner.UpdateGroupMember(lbGroupMember); LBEditorHelper.RepaintEditorWindow(typeof(LandscapeBuilderWindow)); } }
private void DeleteAll() { if (lbGroup != null && lbGroupLocationItem != null) { if (lbGroup.positionList != null) { lbGroup.positionList.Clear(); if (lbGroup.isFixedRotation && lbGroup.rotationYList != null) { lbGroup.rotationYList.Clear(); } LBGroupLocationItem.RemoveLocationsFromScene(landscape, true); LBEditorHelper.RepaintEditorWindow(typeof(LandscapeBuilderWindow)); } } }
private void DeleteMember() { if (lbGroupMember != null && lbGroupDesignerItem != null) { int groupMemberPos = lbGroup.groupMemberList.FindIndex(gmbr => gmbr == lbGroupMember); if (LBEditorHelper.PromptForDelete("Group Member", "", groupMemberPos, false)) { lbGroup.groupMemberList.Remove(lbGroupMember); lbGroupMember = null; if (lbGroupDesignerItem.lbGroupDesigner) { lbGroupDesignerItem.lbGroupDesigner.RefreshWorkspace(); } } } }
private void SetRotationType(object obj) { if (lbGroupMember != null && lbGroupDesignerItem != null) { // Find the matching RotationType, and update the instances of the member in the Group Designer. foreach (LBGroupMember.LBRotationType rotationType in System.Enum.GetValues(typeof(LBGroupMember.LBRotationType))) { if (rotationType.ToString() == obj.ToString()) { lbGroupMember.rotationType = rotationType; lbGroupDesignerItem.lbGroupDesigner.UpdateGroupMember(lbGroupMember); LBEditorHelper.RepaintEditorWindow(typeof(LandscapeBuilderWindow)); break; } } } }
private void ToggleOverrideGroupDefaults() { if (lbGroupMember != null && lbGroupDesignerItem != null) { lbGroupMember.isGroupOverride = !lbGroupMember.isGroupOverride; if (lbGroupMember.isGroupOverride) { // Copy Group defaults to the member lbGroupMember.minScale = lbGroup.minScale; lbGroupMember.maxScale = lbGroup.maxScale; lbGroupMember.minHeight = lbGroup.minHeight; lbGroupMember.maxHeight = lbGroup.maxHeight; lbGroupMember.minInclination = lbGroup.minInclination; lbGroupMember.maxInclination = lbGroup.maxInclination; } LBEditorHelper.RepaintEditorWindow(typeof(LandscapeBuilderWindow)); lbGroupDesignerItem.lbGroupDesigner.UpdateGroupMember(lbGroupMember); } }
/// <summary> /// Find the TextureArrayConfig for a given MicroSplat terrain material. /// This assumes it is in the same project folder. If it is not in the /// default folder, it also checks the terrainData folder which can /// happen for imported terrains. /// </summary> /// <param name="landscape"></param> /// <param name="terrainMat"></param> /// <returns></returns> public static JBooth.MicroSplat.TextureArrayConfig GetTextureArrayConfig(LBLandscape landscape, Material terrainMat) { JBooth.MicroSplat.TextureArrayConfig textureArrayConfig = null; if (terrainMat != null) { string folder = GetMicroSplatDataFolder(terrainMat, true); textureArrayConfig = LBEditorHelper.GetAsset <JBooth.MicroSplat.TextureArrayConfig>(folder, terrainMat.name.Replace("MicroSplat", "MicroSplatConfig") + ".asset"); // Check the terrain data folder if 1) The material is stored in the scene AND 2) it is not in the default location if (textureArrayConfig == null && landscape != null && landscape.useProjectForTerrainData) { //Debug.Log("[DEBUG] GetTextureArrayConfig checking: " + landscape.terrainDataFolder + " rather than " + folder); folder = landscape.terrainDataFolder + "/MicroSplatData"; textureArrayConfig = LBEditorHelper.GetAsset <JBooth.MicroSplat.TextureArrayConfig>(folder, terrainMat.name.Replace("MicroSplat", "MicroSplatConfig") + ".asset"); } } return(textureArrayConfig); }
void Update() { if (EditorApplication.isPlayingOrWillChangePlaymode) { return; } if (Selection.activeTransform != null) { // Has the user selected this prefabinstance or a child of the prefab? // NOTE: This could be a little slow if user selects the "wrong" object in hierarchy if (Selection.activeTransform.IsChildOf(this.transform)) { // If user selected a child of the prefab, select the root of the prefab. if (Selection.activeTransform != this.transform) { Selection.activeTransform = this.transform; } // Was this previously unselected in the last frame? if (!isSelected) { isSelected = true; // Auto shrink all other members if (lbGroupDesigner != null && lbGroupMember != null) { if (lbGroupDesigner.lbGroup != null) { lbGroupDesigner.lbGroup.GroupMemberListExpand(false); lbGroupMember.showInEditor = true; LBEditorHelper.RepaintLBW(); } } } } else { isSelected = false; } } }
private void TogglePlaceInCentre() { lbGroupMember.isPlacedInCentre = !lbGroupMember.isPlacedInCentre; if (lbGroupMember.isPlacedInCentre) { // When turning on isPlacedInCentre, take the location of the current instance of the member. lbGroupMember.minOffsetX = lbGroupDesignerItem.position.x; lbGroupMember.minOffsetZ = lbGroupDesignerItem.position.z; } else { // Reset when turning off isPlacedInCentre lbGroupMember.minOffsetX = 0f; lbGroupMember.minOffsetZ = 0f; } lbGroupMember.showtabInEditor = (int)LBGroupMember.LBMemberEditorTab.General; // Turning off/on isPlacedInCentre for a member could significantly change the layout, so refresh the entire workspace RefreshDesigner(false); LBEditorHelper.RepaintEditorWindow(typeof(LandscapeBuilderWindow)); }
// Use this for initialization void Start() { if (!Application.isPlaying && PlayerSettings.colorSpace != ColorSpace.Linear) { string msg = "Your project is using the older Gamma Colour Space. These demo's are designed for Linear colour space. Change Color Space to Linear in the Project Player settings. Then run the scene. If you don't change it, the sky will appear grey."; EditorUtility.DisplayDialog("Change Player Project Settings Color Space", msg, "Got it!"); // NOTE: In 2018.3 betas, Edit/Settings was used. In 2018.3.0f2, it was changed to Edit/Project Settings #if UNITY_2018_3_OR_NEWER LBEditorHelper.CallMenu("Edit/Project Settings..."); #else LBEditorHelper.CallMenu("Edit/Project Settings/Player"); #endif // The following doesn't work because you'd need to start, stop and restart playing the scene //if (EditorUtility.DisplayDialog("Change Project Color Space", msg, "Yes", "No")) //{ // PlayerSettings.colorSpace = ColorSpace.Linear; //} } }
private void DeleteLocation() { if (lbGroup != null && landscape != null) { if (lbGroup.positionList != null) { // Find the location in the list and remove it int idx = lbGroup.positionList.FindIndex(pos => pos == lbGroupLocationItem.transform.position - landscape.start); if (idx > -1) { //Debug.Log("Delete location at " + lbGroupLocationItem.transform.position); lbGroup.positionList.RemoveAt(idx); if (lbGroup.isFixedRotation && lbGroup.rotationYList != null) { lbGroup.rotationYList.RemoveAt(idx); } DestroyImmediate(lbGroupLocationItem.gameObject); LBEditorHelper.RepaintEditorWindow(typeof(LandscapeBuilderWindow)); } } } }
/// <summary> /// Load a template but delay short period of time after updating /// the infoPanel text to force it to be displayed /// For URP/LWRP/HDRP all trees will be forced to be billboarded /// as currently we are only using built-in SRP trees. /// </summary> /// <param name="templateNumber"></param> /// <returns></returns> IEnumerator LoadTemplateWithUIDelay(int templateNumber) { bool showSRPWarning = false; if (lbTemplates != null) { int numTemplates = lbTemplates.Length; if (templateNumber < numTemplates) { LBTemplate lbTemplate = lbTemplates[templateNumber]; if (lbTemplate != null) { // Disable buttons EnableButton(quality1Button, false); EnableButton(quality2Button, false); EnableButton(quality3Button, false); EnableButton(quality4Button, false); EnableButton(infoButton, false); EnableButton(gpuButton, false); DisplayBackgroundPanel(true); currentTemplateName = lbTemplate.name; SetInfoTitle("Loading Template... PLEASE WAIT"); string infoText = "Applying template... "; SetInfoText(infoText); DisplayInfoPanel(true); yield return(new WaitForSeconds(0.1f)); // Remove any camera animators LBCameraAnimator.RemoveCameraAnimatorsFromScene(lbLandscape, false); yield return(new WaitForSeconds(0.1f)); // if LBLighting is in the scene, remove all references to terrains to // prevent errors when the current landscape is deleted. LBLighting lbLighting = GameObject.FindObjectOfType <LBLighting>(); if (lbLighting != null) { lbLighting.ClearAllTerrains(); } if (lbLandscape != null) { DestroyImmediate(lbLandscape.gameObject); } lbLandscape = lbTemplate.CreateLandscapeFromTemplate("DemoLandscape"); Camera mainCamera = Camera.main; if (mainCamera != null) { mainCamera.transform.position = new Vector3(2000f, 2000f, 0f); mainCamera.transform.LookAt(lbLandscape.transform); } // Currently, when applying template ignore water if LWRP, URP or HDRP are enabled // This could be updated if we had a LWRP/HDRP-compatible water asset if (lbTemplate.ApplyTemplateToLandscape(lbLandscape, ignoreStartPosition, true, (isURP || isLWRP || isHDRP) ? null : waterPrefab, true)) { infoText += "DONE\n\n"; SetInfoText(infoText); yield return(new WaitForSeconds(0.1f)); lbLandscape.showTiming = false; lbLandscape.SetLandscapeTerrains(true); // Build the landscape int numTerrains = (lbLandscape.landscapeTerrains == null ? 0 : lbLandscape.landscapeTerrains.Length); if (numTerrains > 0) { // Our older templates don't use GPU for Topography and Path. If it is fully capable // of using the GPU, list it here. bool isModernTemplate = lbTemplate.name.StartsWith("DemoStoneCottage"); // Override the template GPU settings lbLandscape.useGPUTopography = isModernTemplate ? enableGPU : false; lbLandscape.useGPUTexturing = enableGPU; lbLandscape.useGPUGrass = enableGPU; lbLandscape.useGPUPath = isModernTemplate ? enableGPU : false; // Check for URP/LWRP/HDRP or do we need to create a default material for U2019.2.0 or newer if (isURP || isLWRP || isHDRP || is201920Plus) { float pixelError = 0f; Terrain terrain = null; LBLandscape.TerrainMaterialType terrainMaterialType = isURP ? LBLandscape.TerrainMaterialType.URP : (isLWRP ? LBLandscape.TerrainMaterialType.LWRP : (terrainMaterialType = isHDRP ? LBLandscape.TerrainMaterialType.HDRP : LBLandscape.TerrainMaterialType.BuiltInStandard)); for (int tIdx = 0; tIdx < numTerrains; tIdx++) { terrain = lbLandscape.landscapeTerrains[tIdx]; lbLandscape.SetTerrainMaterial(terrain, tIdx, (tIdx == numTerrains - 1), terrain.terrainData.size.x, ref pixelError, terrainMaterialType); // For URP/LWRP/HDRP all trees will be forced to be billboarded // as currently we are only using built-in SRP trees. if (isURP || isLWRP || isHDRP) { // Force all trees to be billboards terrain.treeBillboardDistance = 0f; terrain.treeMaximumFullLODCount = 0; showSRPWarning = true; } } } // These are the cut-down versions without progress bars and minimal validation infoText += "Building Topography" + (lbLandscape.useGPUTopography ? " (GPU)..." : "..."); SetInfoText(infoText); yield return(new WaitForSeconds(0.1f)); lbLandscape.ApplyTopography(true, true); infoText += "DONE\n\n"; infoText += "Adding Textures" + (lbLandscape.useGPUTexturing ? " (GPU)..." : "..."); SetInfoText(infoText); yield return(new WaitForSeconds(0.1f)); lbLandscape.ApplyTextures(true, true); infoText += "DONE\n\n"; infoText += "Placing Trees... "; SetInfoText(infoText); yield return(new WaitForSeconds(0.1f)); lbLandscape.ApplyTrees(true, true); infoText += "DONE\n\n"; infoText += "Placing Grass" + (lbLandscape.useGPUGrass ? " (GPU)..." : "..."); SetInfoText(infoText); yield return(new WaitForSeconds(0.1f)); lbLandscape.ApplyGrass(true, true); infoText += "DONE\n\n"; SetInfoText(infoText); yield return(new WaitForSeconds(0.1f)); if (lbLandscape.lbGroupList != null && lbLandscape.lbGroupList.Count > 0) { infoText += "Placing Groups" + (lbLandscape.useGPUTopography ? " (GPU)..." : "..."); SetInfoText(infoText); yield return(new WaitForSeconds(0.1f)); lbLandscape.ApplyGroups(false, false); } // Apply lighting last as it needs the Camera Paths (and Animator camera to set up WeatherFX) if (lbTemplate.isLBLightingIncluded) { infoText += "Applying lighting... "; SetInfoText(infoText); yield return(new WaitForSeconds(0.1f)); //if (lbLighting != null) { DestroyImmediate(lbLighting.gameObject); } if (lbLighting == null) { // If LBLighting isn't already in the scene, add it. lbLighting = LBLighting.AddLightingToScene(true); } if (lbLighting != null) { // Restore the lighting settings from the template lbTemplate.ApplyLBLightingSettings(lbLandscape, ref lbLighting, mainCamera, true); } infoText += "DONE\n\n"; SetInfoText(infoText); yield return(new WaitForSeconds(0.1f)); // Prior to Unity 5.4, ImageFX and/or camera clear flags are not updated correctly // when the WeatherFX with celestials is added to the scene after a configuration without // celestials. The workaround, is to force the GameView to repaint or be re-initalised. // To be effective, a "reasonable" delay is required between switching away from Game view // and back. The exact cause of the issue is unknown... #if !UNITY_5_4_OR_NEWER && UNITY_EDITOR if (lbLighting.useCelestials) { bool wasMaximized = LBEditorHelper.GameViewMaximize(this.GetType(), false); LBEditorHelper.ShowSceneView(this.GetType(), true); yield return(new WaitForSeconds(0.5f)); LBEditorHelper.GameViewMaximize(this.GetType(), wasMaximized); } #endif } // Find the first animation and start it (there should be only one in a demo template) LBCameraAnimator lbCameraAnimator = LBCameraAnimator.GetFirstCameraAnimatorInLandscape(lbLandscape); if (lbCameraAnimator != null) { if (lbTemplate.name.StartsWith("FPS Forest Demo")) { // This uses the old Unity 4 trees which don't work so well with anti-aliasing QualitySettings.antiAliasing = 0; if (lbCameraAnimator.animatorCamera != null) { lbCameraAnimator.SetMoveSpeed(2f); lbCameraAnimator.animatorCamera.renderingPath = RenderingPath.Forward; lbCameraAnimator.animateSpeed = false; } } else if (lbTemplate.name.StartsWith("DemoStoneCottage")) { lbCameraAnimator.minMoveSpeed = 1f; lbCameraAnimator.maxMoveSpeed = 3f; lbCameraAnimator.animateSpeed = true; } else { lbCameraAnimator.animateSpeed = true; } // Reset LBImageFX timing so clouds always appear the same if (lbCameraAnimator.animatorCamera != null) { LBImageFX lbImageFX = lbCameraAnimator.animatorCamera.GetComponent <LBImageFX>(); if (lbImageFX != null) { //Debug.Log("LBDemoLoader.LoadTemplateWithUIDelay - Resetting LBImageFX cloud positions"); lbImageFX.ResetCloudPosition(); } } //Debug.Log("LBDemoLoader " + lbTemplate.name + " renderpath: " + lbCameraAnimator.animatorCamera.renderingPath); lbCameraAnimator.pauseAtEndDuration = 999f; lbCameraAnimator.BeginAnimation(true, 0f); } else { Debug.LogWarning("LBDemoLoader.LoadTemplateWithUIDelay - Couldn't find a camera animator in the demo template"); } } } // Re-enable buttons EnableButton(quality1Button, true); EnableButton(quality2Button, true); EnableButton(quality3Button, true); EnableButton(quality4Button, true); EnableButton(infoButton, true); EnableButton(gpuButton, true); UpdateInfoButtonText("Show Info"); } } } if (showSRPWarning) { SetInfoTitle("SRP WARNING"); SetInfoText("This demo scene is designed for the built-in RP.\n\nSee SRP folder for into on URP and HDRP"); } else { DisplayInfoPanel(false); } DisplayBackgroundPanel(false); }
private void OnDisable() { LBEditorHelper.RepaintEditorWindow(typeof(LandscapeBuilderWindow)); }
private void OnSceneGUI() { if (EditorApplication.isPlayingOrWillChangePlaymode) { return; } Event current = Event.current; if (current != null) { if (lbGroupLocationItem == null) { return; } else if (lbGroup == null) { lbGroup = lbGroupLocationItem.lbGroup; if (lbGroup == null) { return; } } bool isLeftButton = (current.button == 0); bool isRightButton = (current.button == 1); tryPosition = lbGroupLocationItem.transform.position; // Clamp position of clearing if (tryPosition.x < landscapeBounds.xMin || tryPosition.x > landscapeBounds.xMax || tryPosition.z < landscapeBounds.yMin || tryPosition.z > landscapeBounds.yMax) { lbGroupLocationItem.transform.position = prevPosition; } // Update prevPostion with the current position prevPosition = lbGroupLocationItem.transform.position; prevPosition.y = LBLandscapeTerrain.GetHeight(landscape, new Vector2(prevPosition.x, prevPosition.z), false) + landscape.start.y; // Snap the clearing location to the terrain height at this point lbGroupLocationItem.transform.position = prevPosition; if (current.type == EventType.MouseDown && isRightButton) { #region Display the Context-sensitive menu // NOTE: The Context Menu that is display when a location is NOT selected, can be found // in LandscapeBuilderWindow.SceneGUI(SceneView sv) GenericMenu menu = new GenericMenu(); menu.AddItem(new GUIContent("Delete Postion"), false, DeleteLocation); menu.AddSeparator(""); menu.AddItem(new GUIContent("Delete ALL"), false, DeleteAll); menu.AddSeparator(""); menu.AddItem(new GUIContent("Unselect"), false, () => { Selection.activeObject = null; }); // The Cancel option is not really necessary as use can just click anywhere else. However, it may help some users. menu.AddItem(new GUIContent("Cancel"), false, () => { }); menu.ShowAsContext(); current.Use(); #endregion } // Record the starting positions else if (current.type == EventType.MouseDown && isLeftButton && landscape != null) { lbGroupLocationItem.position = lbGroupLocationItem.transform.position - landscape.start; lbGroupLocationItem.rotationY = lbGroupLocationItem.transform.rotation.eulerAngles.y; } else if (current.type == EventType.MouseUp && isLeftButton) { if (lbGroup.isFixedRotation) { #if UNITY_2017_3_OR_NEWER if (Tools.current == Tool.Rotate || Tools.current == Tool.Transform) #else if (Tools.current == Tool.Rotate) #endif { // Locate the first matching clearing position // Only check x,z axis as the y-axis may be slightly wrong int idx = lbGroup.positionList.FindIndex(pos => pos.x == lbGroupLocationItem.position.x && pos.z == lbGroupLocationItem.position.z); if (idx > -1) { // update with the new rotation lbGroupLocationItem.rotationY = lbGroupLocationItem.transform.rotation.eulerAngles.y; lbGroup.rotationYList[idx] = lbGroupLocationItem.rotationY; lbGroupLocationItem.transform.rotation = Quaternion.Euler(0f, lbGroupLocationItem.rotationY, 0f); // Update the LB Editor Windows LBEditorHelper.RepaintEditorWindow(typeof(LandscapeBuilderWindow)); } } } #if UNITY_2017_3_OR_NEWER if ((Tools.current == Tool.Move || Tools.current == Tool.Transform) && landscape != null) #else if (Tools.current == Tool.Move && landscape != null) #endif { // Locate the first matching clearing position // Only check x,z axis as the y-axis may be slightly wrong int idx = lbGroup.positionList.FindIndex(pos => pos.x == lbGroupLocationItem.position.x && pos.z == lbGroupLocationItem.position.z); if (idx > -1) { // update it with the new position lbGroup.positionList[idx] = lbGroupLocationItem.transform.position - landscape.start; } } #if UNITY_2017_3_OR_NEWER if (Tools.current == Tool.Scale || Tools.current == Tool.Transform) #else if (Tools.current == Tool.Scale) #endif { lbGroup.minClearingRadius = lbGroupLocationItem.transform.localScale.x / 2f; lbGroup.maxClearingRadius = lbGroup.minClearingRadius; // Update the LB Editor Windows LBEditorHelper.RepaintEditorWindow(typeof(LandscapeBuilderWindow)); // Resize all the locations in the scene LBGroupLocationItem.RefreshLocationSizesInScene(landscape, lbGroup, true); } } #region Changed Rotation // Clamp rotation if (!lbGroup.isFixedRotation) { lbGroupLocationItem.transform.rotation = Quaternion.identity; } //else //{ // Vector3 eulerAngles = lbGroupLocationItem.transform.rotation.eulerAngles; // if (eulerAngles.x != 0f || eulerAngles.z != 0f) // { // //lbGroupLocationItem.transform.rotation = Quaternion.Euler(0f, lbGroupLocationItem.rotationY, 0f); // } //} #endregion #region Changed Radius #if UNITY_2017_3_OR_NEWER if (Tools.current == Tool.Scale || Tools.current == Tool.Transform) #else if (Tools.current == Tool.Scale) #endif { // Equally scale x-z axis float currentScale = lbGroup.minClearingRadius * 2f; float maxScale = -currentScale; Vector3 localScale = lbGroupLocationItem.transform.localScale; // Delta = Abs(localScale.) - currentScale float deltaX = (localScale.x < 0f ? -localScale.x : localScale.x); float deltaY = (localScale.y < 0f ? -localScale.y : localScale.y); float deltaZ = (localScale.z < 0f ? -localScale.z : localScale.z); // Get the max scale amount of any of the axis if (deltaX != currentScale && deltaX > maxScale) { maxScale = localScale.x; } if (deltaZ != currentScale && deltaZ > maxScale) { maxScale = localScale.z; } // Did the user change the scale? if (maxScale != -currentScale) { // Clamp scaling to 0.2 if (maxScale < 0.2f) { maxScale = 0.2f; } localScale.x = maxScale; // Make x-z axis the same localScale.z = localScale.x; // Don't change y-axis localScale.y = 0.1f; lbGroupLocationItem.transform.localScale = localScale; } else if (deltaY > 0f) { // Local Y axis scaling localScale.y = 0.1f; lbGroupLocationItem.transform.localScale = localScale; } } #endregion } }
public static bool SaveTemplate ( LBLandscape landscape, string LBEditorVersion, string landscapeTemplateName, ref bool isSceneSaveRequired, bool createTemplatePackage, bool addMapTexturesToTemplatePackage, bool addLayerHeightmapTexturesToTemplatePackage, bool addLBLightingToTemplate, bool addPathsToTemplate, bool addStencilsToTemplate, bool addPathMeshMaterialsToTemplate ) { bool isSuccessful = false; string landscapeName = landscape.name; // Create a new gameobject in the scene hierarchy that we can turn into a prefab GameObject newTemplateObj = new GameObject(landscapeName + " template"); if (newTemplateObj == null) { Debug.LogWarning("Landscape Builder - could not create temporary gameobject for " + landscapeName + " template"); } else { LBTemplate lbTemplate = newTemplateObj.AddComponent <LBTemplate>(); if (lbTemplate == null) { Debug.LogWarning("Landscape Builder - could not add LBTemplate component " + landscapeName + " template"); GameObject.DestroyImmediate(newTemplateObj); } else { // This is the installed version of LB when the template was created lbTemplate.LBVersion = LBEditorVersion; // This is the version of the landscape when the template was created lbTemplate.LastUpdatedVersion = landscape.LastUpdatedVersion; // The version of Unity that created this template lbTemplate.templateUnityVersion = Application.unityVersion; lbTemplate.useLegacyNoiseOffset = landscape.useLegacyNoiseOffset; // Name of the landscape game object lbTemplate.landscapeName = landscapeName; lbTemplate.size = landscape.size; lbTemplate.start = landscape.start; // Landscape terrain settings Vector3 terrainSize3D = landscape.GetLandscapeTerrainSize(); lbTemplate.heightmapResolution = landscape.GetLandscapeTerrainHeightmapResolution(); lbTemplate.terrainWidth = terrainSize3D.x; lbTemplate.terrainHeight = terrainSize3D.y; lbTemplate.pixelError = landscape.GetLandscapeTerrainPixelError(); lbTemplate.baseMapDistance = landscape.GetLandscapeTerrainBaseMapDist(); lbTemplate.alphaMapResolution = landscape.GetLandscapeTerrainAlphaMapResolution(); lbTemplate.baseTextureResolution = landscape.GetLandscapeTerrainBaseTextureResolution(); lbTemplate.treeDistance = landscape.GetLandscapeTerrainTreeDistance(); lbTemplate.treeBillboardDistance = landscape.GetLandscapeTerrainTreeBillboardStart(); lbTemplate.detailDistance = landscape.GetLandscapeTerrainDetailDistance(); lbTemplate.detailDensity = landscape.GetLandscapeTerrainDetailDensity(); lbTemplate.detailResolution = landscape.GetLandscapeTerrainDetailResolution(); lbTemplate.treeFadeDistance = landscape.GetLandscapeTerrainTreeFadeLength(); lbTemplate.grassWindSpeed = landscape.GetLandscapeTerrainGrassWindSpeed(); lbTemplate.grassWindRippleSize = landscape.GetLandscapeTerrainGrassWindRippleSize(); lbTemplate.grassWindBending = landscape.GetLandscapeTerrainGrassWindBending(); lbTemplate.grassWindTint = landscape.GetLandscapeTerrainGrassWindTint(); lbTemplate.terrainLegacySpecular = landscape.GetLandscapeTerrainLegacySpecular(); lbTemplate.terrainLegacyShininess = landscape.GetLandscapeTerrainLegacyShininess(); lbTemplate.useTerrainDrawInstanced = landscape.GetLandscapeTerrainDrawInstanced(); lbTemplate.useTerrainPerPixelNormals = GetTerrainPerPixelNormals(landscape); lbTemplate.terrainGroupingID = landscape.GetLandscapeTerrainGroupingID(); lbTemplate.terrainAutoConnect = landscape.GetLandscapeTerrainAutoConnect(); // Synchronize with a duplicate enum in lbTemplate lbTemplate.terrainMaterialType = (LBTemplate.TerrainMaterialType)landscape.GetTerrainMaterialType(); // Check if any lists are null if (landscape.topographyLayersList == null) { landscape.topographyLayersList = new List <LBLayer>(); } if (landscape.terrainTexturesList == null) { landscape.terrainTexturesList = new List <LBTerrainTexture>(); } if (landscape.terrainTreesList == null) { landscape.terrainTreesList = new List <LBTerrainTree>(); } if (landscape.terrainGrassList == null) { landscape.terrainGrassList = new List <LBTerrainGrass>(); } if (landscape.lbGroupList == null) { landscape.lbGroupList = new List <LBGroup>(); } if (landscape.landscapeMeshList == null) { landscape.landscapeMeshList = new List <LBLandscapeMesh>(); } if (landscape.landscapeWaterList == null) { landscape.landscapeWaterList = new List <LBWater>(); } // Update texture names to help detect missing textures when importing templates into another project for (int txIdx = 0; txIdx < landscape.terrainTexturesList.Count; txIdx++) { // Only attempt to update the textureName if it is null or an empty string. // This avoids loosing details about an already missing texture if (string.IsNullOrEmpty(landscape.terrainTexturesList[txIdx].textureName)) { if (landscape.terrainTexturesList[txIdx].texture != null) { landscape.terrainTexturesList[txIdx].textureName = landscape.terrainTexturesList[txIdx].texture.name; isSceneSaveRequired = true; } } // Only attempt to update the normalMapName if it is null or an empty string. // This avoids loosing details about an already missing normalMap if (string.IsNullOrEmpty(landscape.terrainTexturesList[txIdx].normalMapName)) { if (landscape.terrainTexturesList[txIdx].normalMap != null) { landscape.terrainTexturesList[txIdx].normalMapName = landscape.terrainTexturesList[txIdx].normalMap.name; isSceneSaveRequired = true; } } } // Update Grass texture names to help detect missing textures when importing templates into another project for (int grIdx = 0; grIdx < landscape.terrainGrassList.Count; grIdx++) { // Only attempt to update the grass textureName if it is null or an empty string. // This avoids loosing details about an already missing grass texture if (string.IsNullOrEmpty(landscape.terrainGrassList[grIdx].textureName)) { if (landscape.terrainGrassList[grIdx].texture != null) { landscape.terrainGrassList[grIdx].textureName = landscape.terrainGrassList[grIdx].texture.name; isSceneSaveRequired = true; } } // Only attempt to update the grass meshPrefName if it is null or an empty string. // This avoids loosing details about an already missing grass mesh prefab if (string.IsNullOrEmpty(landscape.terrainGrassList[grIdx].meshPrefabName)) { if (landscape.terrainGrassList[grIdx].meshPrefab != null) { landscape.terrainGrassList[grIdx].meshPrefabName = landscape.terrainGrassList[grIdx].meshPrefab.name; isSceneSaveRequired = true; } } } // Update Tree prefab names to help detect missing prefabs when importing templates into another project for (int trIdx = 0; trIdx < landscape.terrainTreesList.Count; trIdx++) { // Only attempt to update the tree prefabName if it is null or an empty string. // This avoids loosing details about an already missing tree prefab if (string.IsNullOrEmpty(landscape.terrainTreesList[trIdx].prefabName)) { if (landscape.terrainTreesList[trIdx].prefab != null) { landscape.terrainTreesList[trIdx].prefabName = landscape.terrainTreesList[trIdx].prefab.name; isSceneSaveRequired = true; } } } // Update Mesh prefab names to help detect missing prefabs when importing templates into another project for (int meshIdx = 0; meshIdx < landscape.landscapeMeshList.Count; meshIdx++) { // Only attempt to update the mesh prefabName if it is null or an empty string. // This avoids loosing details about an already missing mesh prefab if (string.IsNullOrEmpty(landscape.landscapeMeshList[meshIdx].prefabName)) { if (landscape.landscapeMeshList[meshIdx].prefab != null) { landscape.landscapeMeshList[meshIdx].prefabName = landscape.landscapeMeshList[meshIdx].prefab.name; isSceneSaveRequired = true; } } } int numGroups = landscape.lbGroupList == null ? 0 : landscape.lbGroupList.Count; // Update Group Member prefab names to help detect missing prefabs when importing templates into another project for (int grpIdx = 0; grpIdx < numGroups; grpIdx++) { if (landscape.lbGroupList[grpIdx].groupMemberList != null) { List <LBGroupMember> groupMemberList = landscape.lbGroupList[grpIdx].groupMemberList; for (int grpMbrIdx = 0; grpMbrIdx < groupMemberList.Count; grpMbrIdx++) { // Only attempt to update the prefab prefabName if it is null or an empty string. // This avoids loosing details about an already missing prefab if (string.IsNullOrEmpty(groupMemberList[grpMbrIdx].prefabName)) { if (groupMemberList[grpMbrIdx].prefab != null) { groupMemberList[grpMbrIdx].prefabName = groupMemberList[grpMbrIdx].prefab.name; isSceneSaveRequired = true; } } } } } // Landscape class lists - perform deep copy (#SMS 2.0.6 Beta 6f) // Attempts to avoid issue where a template prefab is created (and later deleted) which could delete data // from the landscape meta-data in the scene. lbTemplate.topographyLayersList = landscape.topographyLayersList.ConvertAll(lyr => new LBLayer(lyr)); lbTemplate.terrainTexturesList = landscape.terrainTexturesList.ConvertAll(tt => new LBTerrainTexture(tt)); lbTemplate.terrainTreesList = landscape.terrainTreesList.ConvertAll(tt => new LBTerrainTree(tt)); lbTemplate.terrainGrassList = landscape.terrainGrassList.ConvertAll(tg => new LBTerrainGrass(tg)); lbTemplate.lbGroupList = landscape.lbGroupList.ConvertAll(grp => new LBGroup(grp)); lbTemplate.landscapeMeshList = landscape.landscapeMeshList.ConvertAll(msh => new LBLandscapeMesh(msh)); lbTemplate.landscapeWaterList = landscape.landscapeWaterList.ConvertAll(wtr => new LBWater(wtr, false)); // Check for surface and/or base mesh materials in Group Object Paths for (int grpIdx = 0; grpIdx < numGroups; grpIdx++) { int numGrpMembers = landscape.lbGroupList[grpIdx].groupMemberList == null ? 0 : landscape.lbGroupList[grpIdx].groupMemberList.Count; for (int grpMbrIdx = 0; grpMbrIdx < numGrpMembers; grpMbrIdx++) { LBGroupMember _lbGroupMember = landscape.lbGroupList[grpIdx].groupMemberList[grpMbrIdx]; // A deep copy will attempt create a new instance of the material using our LBGroupMember clone constructor // In this case we need to reference the actual material in the project folder. // If the Object Path was a duplicate of an existing Object Path, then this may also fail. if (_lbGroupMember != null && _lbGroupMember.lbMemberType == LBGroupMember.LBMemberType.ObjPath && _lbGroupMember.lbObjPath != null) { lbTemplate.lbGroupList[grpIdx].groupMemberList[grpMbrIdx].lbObjPath.surfaceMeshMaterial = _lbGroupMember.lbObjPath.surfaceMeshMaterial; lbTemplate.lbGroupList[grpIdx].groupMemberList[grpMbrIdx].lbObjPath.baseMeshMaterial = _lbGroupMember.lbObjPath.baseMeshMaterial; } } } // Final Pass varibles lbTemplate.useFinalPassSmoothing = landscape.useFinalPassSmoothing; lbTemplate.finalPassSmoothingIterations = landscape.finalPassSmoothingIterations; lbTemplate.finalPassPixelRange = landscape.finalPassPixelRange; lbTemplate.fPassSmoothStencilGUID = landscape.fPassSmoothStencilGUID; lbTemplate.fPassSmoothStencilLayerGUID = landscape.fPassSmoothStencilLayerGUID; lbTemplate.fPassSmoothFilterMode = landscape.fPassSmoothFilterMode; lbTemplate.thermalErosionPreset = landscape.thermalErosionPreset; lbTemplate.useThermalErosion = landscape.useThermalErosion; lbTemplate.thermalErosionIterations = landscape.thermalErosionIterations; lbTemplate.thermalErosionTalusAngle = landscape.thermalErosionTalusAngle; lbTemplate.thermalErosionStrength = landscape.thermalErosionStrength; lbTemplate.fPassThErosionStencilGUID = landscape.fPassThErosionStencilGUID; lbTemplate.fPassThErosionStencilLayerGUID = landscape.fPassThErosionStencilLayerGUID; lbTemplate.fPassThErosionFilterMode = landscape.fPassThErosionFilterMode; // Group Settings lbTemplate.autoRefreshGroupDesigner = landscape.autoRefreshGroupDesigner; // Vegetation Integration variables lbTemplate.useVegetationSystem = landscape.useVegetationSystem; lbTemplate.useVegetationSystemTextures = landscape.useVegetationSystemTextures; // Landscape Extension lbTemplate.useLandscapeExtension = landscape.useLandscapeExtension; if (landscape.lbLandscapeExtension != null) { lbTemplate.lbLandscapeExtension = new LBLandscapeExtension(landscape.lbLandscapeExtension); } else { lbTemplate.lbLandscapeExtension = new LBLandscapeExtension(); } // GPU acceleration lbTemplate.useGPUTexturing = landscape.useGPUTexturing; lbTemplate.useGPUTopography = landscape.useGPUTopography; lbTemplate.useGPUGrass = landscape.useGPUGrass; lbTemplate.useGPUPath = landscape.useGPUPath; // Undo override lbTemplate.isUndoTopographyDisabled = landscape.isUndoTopographyDisabled; // Topography Mask - there is one per landscape lbTemplate.topographyMaskMode = (LBTemplate.MaskMode)landscape.topographyMaskMode; lbTemplate.distanceToCentreMask = landscape.distanceToCentreMask; lbTemplate.maskWarpAmount = landscape.maskWarpAmount; lbTemplate.maskNoiseTileSize = landscape.maskNoiseTileSize; lbTemplate.maskNoiseOffsetX = landscape.maskNoiseOffsetX; lbTemplate.maskNoiseOffsetY = landscape.maskNoiseOffsetY; lbTemplate.maskNoiseCurveModifier = landscape.maskNoiseCurveModifier; // Does user wish to include LBLighting? if (addLBLightingToTemplate) { // Only include LBLighting if it is in the scene LBLighting lbLighting = GameObject.FindObjectOfType <LBLighting>(); if (lbLighting == null) { lbTemplate.isLBLightingIncluded = false; Debug.LogWarning("Landscape Builder - Export Template - No LBLighting found in the scene"); } else { lbTemplate.isLBLightingIncluded = true; lbTemplate.AddLBLightingSettings(lbLighting); } } else { lbTemplate.isLBLightingIncluded = false; } // Create an empty list of Asset Paths for the mesh materials List <string> lbMapPathMaterialAssetPathList = new List <string>(); if (addPathsToTemplate) { // Find any Camera Paths in this landscape (changed from all in scene in 1.3.2 Beta 9b) List <LBCameraPath> lbCameraPathList = LBCameraPath.GetCameraPathsInLandscape(landscape); if (lbCameraPathList != null) { // Get the LBPath from each LBCameraPath and add it to the LBTemplate instance foreach (LBCameraPath lbCameraPath in lbCameraPathList) { if (lbCameraPath.lbPath != null) { // Update the path name before adding to the template if (lbCameraPath.gameObject != null) { lbCameraPath.lbPath.pathName = lbCameraPath.gameObject.name; isSceneSaveRequired = true; } lbTemplate.lbPathList.Add(lbCameraPath.lbPath); } } } // Find all MapPaths in the this landscape List <LBMapPath> lbMapPathList = LBMapPath.GetMapPathsInLandscape(landscape); if (lbMapPathList != null) { // Get the LBPath from each LBMapPath and add it to the LBTemplate instance foreach (LBMapPath lbMapPath in lbMapPathList) { if (lbMapPath.lbPath != null) { // Update the path name before adding to the template if (lbMapPath.gameObject != null) { lbMapPath.lbPath.pathName = lbMapPath.gameObject.name; // Check for a mesh if (lbMapPath.lbPath.lbMesh != null && addPathMeshMaterialsToTemplate) { lbMapPath.lbPath.meshTempMaterial = lbMapPath.meshMaterial; // If also creating a package, remember the asset path for this mesh material if (createTemplatePackage) { string mapPathMatAssetPath = UnityEditor.AssetDatabase.GetAssetPath(lbMapPath.meshMaterial); if (!string.IsNullOrEmpty(mapPathMatAssetPath)) { lbMapPathMaterialAssetPathList.Add(mapPathMatAssetPath); } } } else { lbMapPath.lbPath.meshTempMaterial = null; } isSceneSaveRequired = true; } lbTemplate.lbPathList.Add(lbMapPath.lbPath); } } } } if (addStencilsToTemplate) { List <LBStencil> lbStencilList = LBStencil.GetStencilsInLandscape(landscape, true); if (lbTemplate.lbTemplateStencilList == null) { lbTemplate.lbTemplateStencilList = new List <LBTemplateStencil>(); } if (lbTemplate.lbTemplateStencilList != null && lbStencilList != null) { // Create a LBTemplateStencil for each Stencil in the landscape, and add it to the Template. // NOTE Does not copy the USHORT layerArray or render textures in the Stencil Layers as we want to keep // the Template as small as possible. foreach (LBStencil lbStencil in lbStencilList) { if (lbStencil != null) { LBTemplateStencil lbTemplateStencil = new LBTemplateStencil(lbStencil); if (lbTemplateStencil != null) { lbTemplate.lbTemplateStencilList.Add(lbTemplateStencil); } } } } } // Create template folders if they don't already exist LBEditorHelper.CheckFolder("Assets/LandscapeBuilder/Templates"); if (!Directory.Exists("LandscapeBuilder/TemplatePackages")) { Directory.CreateDirectory("LandscapeBuilder/TemplatePackages"); } // Create a prefab bool continueToSave = false; string templateFullPath = Application.dataPath + "/LandscapeBuilder/Templates/" + landscapeTemplateName + ".prefab"; string templateAssetPath = "Assets/LandscapeBuilder/Templates/" + landscapeTemplateName + ".prefab"; if (File.Exists(templateFullPath)) { if (EditorUtility.DisplayDialog("Template Already Exists", "Are you sure you want to save the template? The currently existing" + " template will be lost.", "Overwrite", "Cancel")) { if (!AssetDatabase.DeleteAsset(templateAssetPath)) { Debug.LogWarning("Landscape Builder - could not overwrite Assets/LandscapeBuilder/Templates/" + landscapeTemplateName + " for " + landscapeName + " template"); } else { continueToSave = true; } } } else { continueToSave = true; } if (continueToSave) { #if UNITY_2018_3_OR_NEWER GameObject templatePrefabGO = PrefabUtility.SaveAsPrefabAsset(newTemplateObj, templateAssetPath); #else GameObject templatePrefabGO = PrefabUtility.CreatePrefab(templateAssetPath, newTemplateObj); #endif if (templatePrefabGO != null && createTemplatePackage) { // Always include the template prefab (this is meta-data only) List <string> templateAssetPaths = new List <string>(); templateAssetPaths.Add(templateAssetPath); // Although technically users could include 3rd party textures in a LBMap texture, they are MUCH more likely to use // map textures generated from within Landscape Builder. if (addMapTexturesToTemplatePackage) { List <string> uniqueMapTexPaths = LBLandscapeOperations.GetMapTextureAssetPathsFromLandscape(landscape, true); if (uniqueMapTexPaths != null) { if (uniqueMapTexPaths.Count > 0) { templateAssetPaths.AddRange(uniqueMapTexPaths); } } } if (addLayerHeightmapTexturesToTemplatePackage) { // Get a list of the image-based topography layers with a heightmap texture List <LBLayer> layerList = landscape.topographyLayersList.FindAll(lyr => lyr.heightmapImage != null && (lyr.type == LBLayer.LayerType.ImageBase || lyr.type == LBLayer.LayerType.ImageAdditive || lyr.type == LBLayer.LayerType.ImageSubtractive || lyr.type == LBLayer.LayerType.ImageDetail)); if (layerList != null) { //Debug.Log("Save Template found " + layerList.Count + " image layers with a heightmap"); for (int lyrIdx = 0; lyrIdx < layerList.Count; lyrIdx++) { // Get the path in the asset db to the image-based layer heightmap texture string heightmapPath = UnityEditor.AssetDatabase.GetAssetPath(layerList[lyrIdx].heightmapImage); if (!string.IsNullOrEmpty(heightmapPath)) { templateAssetPaths.Add(heightmapPath); } } } } // Add the list of map path mesh materials we add earlier. if (addPathMeshMaterialsToTemplate && lbMapPathMaterialAssetPathList.Count > 0) { templateAssetPaths.AddRange(lbMapPathMaterialAssetPathList); } AssetDatabase.ExportPackage(templateAssetPaths.ToArray(), "LandscapeBuilder/TemplatePackages/" + landscapeTemplateName + ".unitypackage", ExportPackageOptions.Interactive); } LBEditorHelper.HighlightItemInProjectWindow(templateAssetPath); } // Cleanup scene hierarchy GameObject.DestroyImmediate(newTemplateObj); } } return(isSuccessful); }
private void OnGUI() { //if (labelFieldRichText == null) { labelFieldRichText = new GUIStyle("Label"); labelFieldRichText.richText = true; } GUILayout.BeginVertical("HelpBox"); EditorGUILayout.HelpBox("The LB Manager will help you optimise your landscapes prior to shipping your game. It will remove all unneeded LB components. [Technical Preview]", MessageType.Info, true); EditorGUI.BeginChangeCheck(); landscape = (LBLandscape)EditorGUILayout.ObjectField(landscapeGUIContent, landscape, typeof(LBLandscape), true); if (EditorGUI.EndChangeCheck() && landscape != null) { landscapeTemplateName = "LB_Backup_" + landscape.name + "_Template"; } scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition); EditorGUIUtility.labelWidth += labelWidthOffset; #region Start of Phase 1 currentBgndColor = GUI.backgroundColor; GUI.backgroundColor = GUI.backgroundColor * (EditorGUIUtility.isProSkin ? 0.7f : 1.3f); GUILayout.BeginVertical(EditorStyles.helpBox); GUI.backgroundColor = currentBgndColor; EditorGUILayout.LabelField("<color=" + txtColourName + "><b>Phase 1 - Backup</b></color>", labelFieldRichText); EditorGUILayout.HelpBox("You need to: Backup each landscape in each scene to a template.", MessageType.Info, true); EditorGUIUtility.labelWidth -= labelWidthOffset; landscapeTemplateName = EditorGUILayout.TextField(saveTemplateNameContent, landscapeTemplateName); EditorGUIUtility.labelWidth += labelWidthOffset; if (GUILayout.Button("Backup Template", GUILayout.MaxWidth(130f))) { bool isSceneSaveRequired = false; if (landscape != null) { LBEditorCommon.SaveTemplate(landscape, LBEditorCommon.LBVersion, landscapeTemplateName, ref isSceneSaveRequired, createTemplatePackage, addMapTexturesToTemplatePackage, addLayerHeightmapTexturesToTemplatePackage, addLBLightingToTemplate, addPathsToTemplate, addStencilsToTemplate, addPathMeshMaterialsToTemplate); } else { EditorUtility.DisplayDialog("Backup Template", "Select a landscape above so that you can back it up to a template", "Got it!"); } } GUILayout.EndVertical(); // End of Phase 1 #endregion End Phase 1 EditorGUILayout.Space(); #region Start of Phase 2 currentBgndColor = GUI.backgroundColor; GUI.backgroundColor = GUI.backgroundColor * (EditorGUIUtility.isProSkin ? 0.7f : 1.3f); GUILayout.BeginVertical(EditorStyles.helpBox); GUI.backgroundColor = currentBgndColor; EditorGUILayout.LabelField("<color=" + txtColourName + "><b>Phase 2 - Optimise</b></color>", labelFieldRichText); EditorGUILayout.HelpBox("You need to: Optimise each landscape in EACH scene by removing unnecessary scripts. You will need to open each scene one at a time.", MessageType.Info, true); isRemovePrefabItems = EditorGUILayout.Toggle(removePrefabItemContent, isRemovePrefabItems); isRemoveMapPaths = EditorGUILayout.Toggle(removeMapPathContent, isRemoveMapPaths); isRemoveStencils = EditorGUILayout.Toggle(removeStencilContent, isRemoveStencils); isRemoveLBLandscape = EditorGUILayout.Toggle(removeLBLandscapeContent, isRemoveLBLandscape); if (GUILayout.Button(finaliseBtnContent, GUILayout.MaxWidth(130f))) { if (landscape != null) { if (EditorUtility.DisplayDialog("Finalise Landscape", "This action will clear all LB Editor data based on your preferences above.\n\nWARNING: There is NO UNDO.", "FINALISE", "Cancel")) { if (isRemovePrefabItems) { RemovePrefabItems(); } if (isRemoveMapPaths) { RemoveMapPaths(); } if (isRemoveStencils) { RemoveStencils(); } if (isRemoveLBLandscape) { RemoveLBLandscape(); } } } else { EditorUtility.DisplayDialog("Finalise Landscape", "Select a landscape above so that you can finalise it", "Got it!"); } } GUILayout.EndVertical(); // End of Phase 2 #endregion End Phase 2 EditorGUILayout.Space(); #region Start of Phase 3 currentBgndColor = GUI.backgroundColor; GUI.backgroundColor = GUI.backgroundColor * (EditorGUIUtility.isProSkin ? 0.7f : 1.3f); GUILayout.BeginVertical(EditorStyles.helpBox); GUI.backgroundColor = currentBgndColor; EditorGUILayout.LabelField("<color=" + txtColourName + "><b>Phase 3 - Uninstall</b></color>", labelFieldRichText); EditorGUILayout.HelpBox("You need to: Selectively remove unnecessary Landscape Builder scripts in the project. Re-import LB package to re-install them.", MessageType.Info, true); isRemoveDemoScene = EditorGUILayout.Toggle(removeDemoSceneContent, isRemoveDemoScene); isRemoveDemoAssets = EditorGUILayout.Toggle(removeDemoAssetsContent, isRemoveDemoAssets); isRemoveUnityWater = EditorGUILayout.Toggle(removeUnityWaterContent, isRemoveUnityWater); isRemoveRuntimeSamples = EditorGUILayout.Toggle(removeRuntimeSamplesContent, isRemoveRuntimeSamples); isRemoveEditorScripts = EditorGUILayout.Toggle(removeEditorScriptsContent, isRemoveEditorScripts); isRemoveSRP = EditorGUILayout.Toggle(removeSRPContent, isRemoveSRP); if (GUILayout.Button(uninstallBtnContent, GUILayout.MaxWidth(130f))) { if (EditorUtility.DisplayDialog("Uninstall components", "This action will uninstall all selected components. Make sure you have Finalised all landscape in all scenes before proceeding. If you are unsure Cancel.\n\nWARNING: There is NO UNDO.", "DO IT!", "Cancel")) { // Close the LB Editor if it is open var lbW = LBEditorHelper.GetLBW(); if (lbW != null) { lbW.Close(); } if (isRemoveDemoAssets) { UninstallDemoAssets(); } else if (isRemoveDemoScene) { UninstallDemoScene(); } if (isRemoveUnityWater) { UninstallUnityWater(); } if (isRemoveRuntimeSamples) { UinstallRuntimeSamples(); } if (isRemoveEditorScripts) { UninstallEditorScripts(); } if (isRemoveSRP) { UninstallSRP(); } } } GUILayout.EndVertical(); // End of Phase 3 #endregion End Phase 3 EditorGUIUtility.labelWidth -= 10f; EditorGUILayout.EndScrollView(); GUILayout.EndVertical(); }
private void OnSceneGUI() { if (EditorApplication.isPlayingOrWillChangePlaymode) { return; } // Don't process scene requests for Group Designer items when the ObjPathDesigner is enabled else if (lbGroupDesignerItem.lbGroupDesigner != null && lbGroupDesignerItem.lbGroupDesigner.isObjDesignerEnabled) { lbGroupDesignerItem.transform.position = prevPosition; lbGroupDesignerItem.transform.rotation = lbGroupDesignerItem.rotation; lbGroupDesignerItem.transform.localScale = lbGroupDesignerItem.scale; Selection.activeGameObject = null; return; } Event current = Event.current; //Debug.Log("DesignerItemEditor " + lbGroupDesignerItem.name); if (current != null) { // Get the group member. If we can't, and this isn't a SubGroup item, get out. if (lbGroupMember == null) { lbGroupMember = lbGroupDesignerItem.lbGroupMember; if (lbGroupMember == null && !lbGroupDesignerItem.isSubGroup) { return; } } bool isInSubGroup = !string.IsNullOrEmpty(lbGroupDesignerItem.SubGroupGUID); if (lbGroupDesignerItem.isObjPathMember || isInSubGroup) { // If user attempts to move/rotate or scale an ObjPath member, SubGroup member, or a SubGroup, reset it lbGroupDesignerItem.transform.position = prevPosition; lbGroupDesignerItem.transform.rotation = lbGroupDesignerItem.rotation; lbGroupDesignerItem.transform.localScale = lbGroupDesignerItem.scale; } else { #region Check if Scale is overridden // If Override is off, scaling is at the group level, not the member level, so don't allow scaling. if (!lbGroupMember.isGroupOverride && Tools.current == Tool.Scale) { Tools.current = Tool.None; } #if UNITY_2017_3_OR_NEWER else if (Tools.current == Tool.Scale || Tools.current == Tool.Transform) #else else if (Tools.current == Tool.Scale) #endif { // If using Transform tool in U2017.3+, may need to reset scaling back to pre-scaled value. if (!lbGroupMember.isGroupOverride) { lbGroupDesignerItem.transform.localScale = lbGroupDesignerItem.scale; } else { // Equally scale all axis float maxScale = 0f; Vector3 localScale = lbGroupDesignerItem.transform.localScale; // Get the max scale amount of any of the axis if (Mathf.Abs(localScale.x) > maxScale) { maxScale = localScale.x; } if (Mathf.Abs(localScale.y) > maxScale) { maxScale = localScale.y; } if (Mathf.Abs(localScale.z) > maxScale) { maxScale = localScale.z; } // Make each axis the same localScale = maxScale * Vector3.one; // Clamp scaling to between 0.1 and 10 if (localScale.x < 0.1f) { localScale = Vector3.one * 0.1f; } if (localScale.x > 10f) { localScale = Vector3.one * 10f; } lbGroupDesignerItem.transform.localScale = localScale; } } #endregion #region Lock Y rotation if randomise is enabled #if UNITY_2017_3_OR_NEWER if ((Tools.current == Tool.Rotate || Tools.current == Tool.Transform) && lbGroupMember.randomiseRotationY) #else if (Tools.current == Tool.Rotate && lbGroupMember.randomiseRotationY) #endif { // Pivotmode of center can cause issues with some prefabs that aren't centred correctly. // Prevent x,z movement of prefab when only y rotation change is attempted if (Tools.pivotMode == PivotMode.Center) { Tools.pivotMode = PivotMode.Pivot; } lbGroupDesignerItem.transform.eulerAngles = new Vector3(lbGroupDesignerItem.transform.eulerAngles.x, lbGroupDesignerItem.rotation.eulerAngles.y, lbGroupDesignerItem.transform.eulerAngles.z); } #endregion #region Clamp MinOffsetX,Z #if UNITY_2017_3_OR_NEWER if (Tools.current == Tool.Move || Tools.current == Tool.Transform) #else if (Tools.current == Tool.Move) #endif { if (lbGroupMember.isPlacedInCentre) { if (lbGroup != null && lbGroupDesignerItem.lbGroupDesigner != null) { // If the user attempts to move it outside the clearing radius, lock the position to the last known position Vector3 newPos = lbGroupDesignerItem.transform.position; float distanceToCentre = Vector2.Distance(lbGroupDesignerItem.lbGroupDesigner.grpBasePlaneCentre2D, new Vector2(newPos.x, newPos.z)); if (distanceToCentre > lbGroup.maxClearingRadius) { lbGroupDesignerItem.transform.position = prevPosition; } } } else if (!lbGroupMember.randomiseOffsetY) { // Don't allow movement on x,z axis for items that aren't offset from the Centre of the clearing AND don't use randomiseOffsetY. lbGroupDesignerItem.transform.position = new Vector3(lbGroupDesignerItem.position.x, lbGroupDesignerItem.transform.position.y, lbGroupDesignerItem.position.z); } else { // Don't allow movement on any axis for items that aren't offset from the Centre of the clearing. lbGroupDesignerItem.transform.position = lbGroupDesignerItem.position; } // Update last known position prevPosition = lbGroupDesignerItem.transform.position; } #endregion } bool isLeftButton = (current.button == 0); bool isRightButton = (current.button == 1); // ISSUE (ignore if vertex snapping is not enabled [v key held down]) current.keyCode != KeyCode.V // Record the starting positions if (!lbGroupDesignerItem.isObjPathMember && current.type == EventType.MouseDown && isLeftButton) { Tools.hidden = false; //Debug.Log("Left Btn Down"); lbGroupDesignerItem.position = lbGroupDesignerItem.transform.position; lbGroupDesignerItem.rotation = lbGroupDesignerItem.transform.rotation; lbGroupDesignerItem.scale = lbGroupDesignerItem.transform.localScale; } else if (!lbGroupDesignerItem.isObjPathMember && !isInSubGroup && current.type == EventType.MouseUp && lbGroupMember != null && isLeftButton) { #region Move #if UNITY_2017_3_OR_NEWER if (Tools.current == Tool.Move || Tools.current == Tool.Transform) #else if (Tools.current == Tool.Move) #endif { if (lbGroupMember.isPlacedInCentre) { lbGroupMember.minOffsetX = lbGroupDesignerItem.transform.position.x; lbGroupMember.minOffsetZ = lbGroupDesignerItem.transform.position.z; if (!lbGroupMember.randomiseOffsetY) { lbGroupMember.minOffsetY = lbGroupDesignerItem.transform.position.y - lbGroupDesignerItem.lbGroupDesigner.BasePlaneOffsetY; } } else if (!lbGroupMember.randomiseOffsetY) { lbGroupMember.minOffsetY = lbGroupDesignerItem.transform.position.y - lbGroupDesignerItem.lbGroupDesigner.BasePlaneOffsetY; lbGroupMember.maxOffsetY = lbGroupMember.minOffsetY; // Update all the instances of this member in the Designer if (lbGroupDesignerItem.lbGroupDesigner != null) { lbGroupDesignerItem.lbGroupDesigner.UpdateGroupMember(lbGroupMember); } } } #endregion #region Rotate #if UNITY_2017_3_OR_NEWER if (Tools.current == Tool.Rotate || Tools.current == Tool.Transform) #else if (Tools.current == Tool.Rotate) #endif { Vector3 newRotation = lbGroupDesignerItem.transform.rotation.eulerAngles; lbGroupMember.rotationX = newRotation.x; lbGroupMember.rotationZ = newRotation.z; if (!lbGroupMember.randomiseRotationY) { lbGroupMember.startRotationY = newRotation.y; lbGroupMember.endRotationY = newRotation.y; if (!lbGroupMember.isPlacedInCentre && lbGroupDesignerItem.lbGroupDesigner != null) { // Update all the instances of this member in the Designer lbGroupDesignerItem.lbGroupDesigner.UpdateGroupMember(lbGroupMember); } } } #endregion #region Scale #if UNITY_2017_3_OR_NEWER if ((Tools.current == Tool.Scale || Tools.current == Tool.Transform) && lbGroupMember.isGroupOverride) #else if (Tools.current == Tool.Scale && lbGroupMember.isGroupOverride) #endif { //Debug.Log("Scale start:" + lbGroupDesignerItem.scale + " mouseup:" + lbGroupDesignerItem.transform.localScale); lbGroupMember.minScale = lbGroupDesignerItem.transform.localScale.x; lbGroupMember.maxScale = lbGroupMember.minScale; if (!lbGroupMember.isPlacedInCentre && lbGroupDesignerItem.lbGroupDesigner != null) { // Update all the instances of this member in the Designer lbGroupDesignerItem.lbGroupDesigner.UpdateGroupMember(lbGroupMember); } } #endregion // Update the LB Editor Windows LBEditorHelper.RepaintEditorWindow(typeof(LandscapeBuilderWindow)); //Debug.Log("Prefab: " + this.name + " start pos:" + lbGroupDesignerItem.position + " end pos:" + lbGroupDesignerItem.transform.position); } //if (current.keyCode == KeyCode.V && current.type == EventType.KeyUp) //if (current.keyCode != KeyCode.V) //{ // //LBIntegration.ReflectionOutputFields(typeof(Tools), true, true); // bool isVertexDragging = false; // try // { // isVertexDragging = LBIntegration.ReflectionGetValue<bool>(typeof(Tools), "vertexDragging", null, true, true); // } // catch (System.Exception ex) // { // Debug.LogWarning("LBGroupDesignerItemEditor could not find VertexDragging - PLEASE REPORT " + ex.Message); // } // Debug.Log("Vertex Snapping enabled..." + Time.realtimeSinceStartup + " vertexDragging: " + isVertexDragging); //} #region Display the Context-sensitive menu else if (current.type == EventType.MouseDown && isRightButton) { bool isCheckProximity = (lbGroupDesignerItem.lbGroupDesigner == null ? true : lbGroupDesignerItem.lbGroupDesigner.isCheckProximity); GenericMenu menu = new GenericMenu(); menu.AddItem(new GUIContent("Close Designer"), false, CloseGroupDesigner); menu.AddItem(new GUIContent("Refresh Designer"), false, () => RefreshDesigner(true)); menu.AddItem(new GUIContent("Check Proximity"), isCheckProximity, CheckProximity, !isCheckProximity); menu.AddItem(new GUIContent("Auto Refresh"), lbGroupDesignerItem.lbGroupDesigner.GetAutoRefresh, () => { lbGroupDesignerItem.lbGroupDesigner.SetAutoRefresh(!lbGroupDesignerItem.lbGroupDesigner.GetAutoRefresh); }); // The following context menu items only apply to GroupMembers. // Also exclude members in a subgroup within the Clearing Group if (!lbGroupDesignerItem.isSubGroup && !isInSubGroup) { menu.AddSeparator(""); if (lbGroupDesignerItem.lbGroupDesigner.showZones) { menu.AddItem(new GUIContent("Add/"), false, () => { }); menu.AddItem(new GUIContent("Add/Zone under Object"), false, AddZoneToObject); } menu.AddItem(new GUIContent("Reset/"), false, () => { }); menu.AddItem(new GUIContent("Reset/Reset Rotation"), false, ResetRotation); menu.AddItem(new GUIContent("Reset/Reset Position"), false, ResetPosition); if (lbGroupMember.isGroupOverride) { menu.AddItem(new GUIContent("Reset/Reset Scale"), false, ResetScale); } menu.AddItem(new GUIContent("Snap/"), false, () => { }); menu.AddItem(new GUIContent("Snap/Pivot to Ground"), false, () => SnapToGround(false)); menu.AddItem(new GUIContent("Snap/Model to Ground"), false, () => SnapToGround(true)); if (!lbGroupDesignerItem.isObjPathMember) { menu.AddItem(new GUIContent("Place In Centre +offset"), lbGroupMember.isPlacedInCentre, TogglePlaceInCentre); } menu.AddItem(new GUIContent("Override Group"), lbGroupMember.isGroupOverride, ToggleOverrideGroupDefaults); menu.AddItem(new GUIContent("Rotation/Face 2 Group Centre"), lbGroupMember.rotationType == LBGroupMember.LBRotationType.Face2GroupCentre, SetRotationType, LBGroupMember.LBRotationType.Face2GroupCentre); menu.AddItem(new GUIContent("Rotation/Face 2 Zone Centre"), lbGroupMember.rotationType == LBGroupMember.LBRotationType.Face2ZoneCentre, SetRotationType, LBGroupMember.LBRotationType.Face2ZoneCentre); menu.AddItem(new GUIContent("Rotation/Group Space"), lbGroupMember.rotationType == LBGroupMember.LBRotationType.GroupSpace, SetRotationType, "GroupSpace"); menu.AddItem(new GUIContent("Rotation/World Space"), lbGroupMember.rotationType == LBGroupMember.LBRotationType.WorldSpace, SetRotationType, "WorldSpace"); menu.AddItem(new GUIContent("Rotation/"), false, () => { }); menu.AddItem(new GUIContent("Rotation/Randomise Y"), lbGroupMember.randomiseRotationY, () => { lbGroupMember.randomiseRotationY = !lbGroupMember.randomiseRotationY; lbGroupMember.showtabInEditor = (int)LBGroupMember.LBMemberEditorTab.XYZ; LBEditorHelper.RepaintEditorWindow(typeof(LandscapeBuilderWindow)); lbGroupDesignerItem.lbGroupDesigner.UpdateGroupMember(lbGroupMember); }); } menu.AddSeparator(""); if (lbGroupDesignerItem.isObjPathMember && !isInSubGroup) { menu.AddItem(new GUIContent("Show Object Path"), false, () => { if (!string.IsNullOrEmpty(lbGroupDesignerItem.objPathGroupMemberGUID) && lbGroupDesignerItem.lbGroupDesigner.lbGroup != null) { LBGroupMember objPathGroupMember = lbGroupDesignerItem.lbGroupDesigner.lbGroup.GetMemberByGUID(lbGroupDesignerItem.objPathGroupMemberGUID, false); if (objPathGroupMember != null) { lbGroupDesignerItem.lbGroupDesigner.lbGroup.GroupMemberListExpand(false); lbGroupDesignerItem.lbGroupDesigner.lbGroup.showGroupMembersInEditor = true; objPathGroupMember.showInEditor = true; LBEditorHelper.RepaintLBW(); } ; } ; }); } menu.AddItem(new GUIContent("Zoom Out"), false, () => { lbGroupDesignerItem.lbGroupDesigner.ZoomExtent(SceneView.lastActiveSceneView); }); menu.AddItem(new GUIContent("Zoom In"), false, () => { lbGroupDesignerItem.lbGroupDesigner.ZoomIn(SceneView.lastActiveSceneView); }); menu.AddItem(new GUIContent("Display/Group Extent"), lbGroupDesignerItem.lbGroupDesigner.showGroupExtent, () => { lbGroupDesignerItem.lbGroupDesigner.showGroupExtent = !lbGroupDesignerItem.lbGroupDesigner.showGroupExtent; }); menu.AddItem(new GUIContent("Display/SubGroup Extents"), lbGroupDesignerItem.lbGroupDesigner.showSubGroupExtent, () => { lbGroupDesignerItem.lbGroupDesigner.showSubGroupExtent = !lbGroupDesignerItem.lbGroupDesigner.showSubGroupExtent; }); menu.AddItem(new GUIContent("Display/Member Extent Proximity"), lbGroupDesignerItem.lbGroupDesigner.showProximity, () => { lbGroupDesignerItem.lbGroupDesigner.showProximity = !lbGroupDesignerItem.lbGroupDesigner.showProximity; if (lbGroupDesignerItem.lbGroupDesigner.showProximity) { lbGroupMember.showtabInEditor = (int)LBGroupMember.LBMemberEditorTab.Proximity; } LBEditorHelper.RepaintEditorWindow(typeof(LandscapeBuilderWindow)); }); menu.AddItem(new GUIContent("Display/Member Tree Proximity"), lbGroupDesignerItem.lbGroupDesigner.showTreeProximity, () => { lbGroupDesignerItem.lbGroupDesigner.showTreeProximity = !lbGroupDesignerItem.lbGroupDesigner.showTreeProximity; if (lbGroupDesignerItem.lbGroupDesigner.showTreeProximity) { lbGroupMember.showtabInEditor = (int)LBGroupMember.LBMemberEditorTab.Proximity; } LBEditorHelper.RepaintEditorWindow(typeof(LandscapeBuilderWindow)); }); menu.AddItem(new GUIContent("Display/Member Flatten Area"), lbGroupDesignerItem.lbGroupDesigner.showFlattenArea, () => { lbGroupDesignerItem.lbGroupDesigner.showFlattenArea = !lbGroupDesignerItem.lbGroupDesigner.showFlattenArea; if (lbGroupDesignerItem.lbGroupDesigner.showFlattenArea) { lbGroupMember.showtabInEditor = (int)LBGroupMember.LBMemberEditorTab.General; } LBEditorHelper.RepaintEditorWindow(typeof(LandscapeBuilderWindow)); }); menu.AddItem(new GUIContent("Display/Zones"), lbGroupDesignerItem.lbGroupDesigner.showZones, () => { lbGroupDesignerItem.lbGroupDesigner.showZones = !lbGroupDesignerItem.lbGroupDesigner.showZones; if (lbGroupDesignerItem.lbGroupDesigner.showZones) { lbGroupMember.showtabInEditor = (int)LBGroupMember.LBMemberEditorTab.Zone; } LBEditorHelper.RepaintEditorWindow(typeof(LandscapeBuilderWindow)); }); // Cannot directly delete items: // 1. in an Object Path // 2. in a subgroup within the current Group // 3. a whole subgroup within the current Group if (!lbGroupDesignerItem.isObjPathMember && !isInSubGroup && !lbGroupDesignerItem.isSubGroup) { menu.AddSeparator(""); menu.AddItem(new GUIContent("Delete"), false, DeleteMember); } menu.AddSeparator(""); menu.AddItem(new GUIContent("Unselect"), false, () => { Selection.activeObject = null; }); // The Cancel option is not really necessary as use can just click anywhere else. However, it may help some users. menu.AddItem(new GUIContent("Cancel"), false, () => { }); menu.ShowAsContext(); current.Use(); } #endregion } }