public void Initialise(LBLighting lightingScript) { lighting = lightingScript; // Only add celestials camera if it doesn't already exist Transform celestialTrm = transform.Find("Celestials Camera"); if (celestialTrm == null) { GameObject celestialsCameraObject = new GameObject("Celestials Camera"); celestialsCameraObject.transform.parent = transform; celestialsCameraObject.transform.localPosition = Vector3.zero; celestialsCamera = celestialsCameraObject.AddComponent <Camera>(); } celestialsCamera.nearClipPlane = 0.1f; celestialsCamera.farClipPlane = 10f; celestialsCamera.depth = -100f; celestialsCamera.clearFlags = CameraClearFlags.Skybox; if (lighting.mainCamera != null) { celestialsCamera.fieldOfView = lighting.mainCamera.fieldOfView; } else { Debug.LogWarning("WARNING: Celestials Main Camera is null. Some celestials may not work correctly."); } }
public LBWaterParameters() { // Defaults landscape = null; landscapeGameObject = null; waterTransform = null; waterPosition = Vector3.zero; waterSize = Vector2.one * 100f; waterIsPrimary = false; waterHeight = 1000f; waterPrefab = null; keepPrefabAspectRatio = true; waterResizingMode = LBWater.WaterResizingMode.StandardAssets; waterMeshResizingMode = LBWater.WaterMeshResizingMode.StandardAssets; waterMaxMeshThreshold = 5000; waterMainCamera = null; waterCameraList = new List <Camera>(); waterCausticsPrefabList = null; isRiver = false; riverMaterial = null; waterMaterial = null; flowMapTexture = null; riverFlowSpeed = 1.5f; isUnderWaterFXEnabled = false; underWaterFXPrefab = null; underWaterFXPrefabName = "unknown"; underWaterFXPrefabPath = string.Empty; reflectionProbePosition = Vector3.zero; lbLighting = null; }
public void BuildCelestrials(LBLighting lightingScript) { if (lighting == null) { Initialise(lightingScript); } DestroyStarGameObject(); DestroyMoonGameObject(); CreateStars(lightingScript.numberOfStars, lightingScript.starSize); CreateMoon(lightingScript.moonSize); }
// Use this for initialization void Awake() { lbLighting = GameObject.FindObjectOfType <LBLighting>(); if (lbLighting == null) { Debug.LogWarning("ERROR: Cannot find LBLighting in the scene"); } if (isFadeOnWake) { lbLighting.fadeInDuration = fadeInDuration; lbLighting.StartScreenFade(true); isFadingInStarted = true; } }
/// <summary> /// Verify that the stars and moon have been created /// If camera and/or light script isn't linked correctly, /// rebuild everything. /// </summary> public void CheckCelestials(LBLighting lightingScript) { if (celestialsCamera == null && lighting == null) { BuildCelestrials(lightingScript); } else { if (transform.Find("Stars") == null) { CreateStars(lightingScript.numberOfStars, lightingScript.starSize); } if (transform.Find("Moon") == null) { CreateMoon(lightingScript.moonSize); } } }
/// <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); }
public override void OnInspectorGUI() { // If the base command is called, all public fields not hidden, will be displayed //base.OnInspectorGUI(); EditorGUIUtility.labelWidth = 150f; if (labelFieldRichText == null) { labelFieldRichText = new GUIStyle("Label"); labelFieldRichText.richText = true; } EditorGUILayout.BeginVertical(EditorStyles.helpBox); // Read in all the properties serializedObject.Update(); EditorGUILayout.BeginHorizontal(); labelText = "<color=" + txtColourName + "><b>Landscape Name</b></color>"; EditorGUILayout.LabelField(labelText, labelFieldRichText, GUILayout.Width(EditorGUIUtility.labelWidth)); EditorGUILayout.PropertyField(landscapeNameProp, GUIContent.none); EditorGUILayout.EndHorizontal(); // This is the installed version of LB when the template was created EditorGUILayout.BeginHorizontal(); labelText = "<color=" + txtColourName + "><b>Landscape Version</b></color>"; EditorGUILayout.LabelField(labelText, labelFieldRichText, GUILayout.Width(EditorGUIUtility.labelWidth)); labelText = "<color=" + txtColourName + ">" + lastUpdatedVersionProp.stringValue + "</color>"; EditorGUILayout.LabelField(labelText, labelFieldRichText); EditorGUILayout.EndHorizontal(); // This is the installed version of LB when the template was created EditorGUILayout.BeginHorizontal(); labelText = "<color=" + txtColourName + "><b>LB Version</b></color>"; EditorGUILayout.LabelField(labelText, labelFieldRichText, GUILayout.Width(EditorGUIUtility.labelWidth)); labelText = "<color=" + txtColourName + ">" + lbVersionProp.stringValue + "</color>"; EditorGUILayout.LabelField(labelText, labelFieldRichText); EditorGUILayout.EndHorizontal(); // This is the installed version of Unity when the template was created EditorGUILayout.BeginHorizontal(); labelText = "<color=" + txtColourName + "><b>Unity Version</b></color>"; EditorGUILayout.LabelField(labelText, labelFieldRichText, GUILayout.Width(EditorGUIUtility.labelWidth)); labelText = "<color=" + txtColourName + ">" + templateUnityVersionProp.stringValue + "</color>"; EditorGUILayout.LabelField(labelText, labelFieldRichText); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); labelText = "<color=" + txtColourName + "><b>Landscape Size</b></color>"; EditorGUILayout.LabelField(labelText, labelFieldRichText, GUILayout.Width(EditorGUIUtility.labelWidth)); labelText = "<color=" + txtColourName + ">" + sizeProp.vector2Value + "</color>"; EditorGUILayout.LabelField(labelText, labelFieldRichText); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); labelText = "<color=" + txtColourName + "><b>Start Position</b></color>"; EditorGUILayout.LabelField(labelText, labelFieldRichText, GUILayout.Width(EditorGUIUtility.labelWidth)); labelText = "<color=" + txtColourName + ">X: " + startProp.vector3Value.x + " Y: " + startProp.vector3Value.y + " Z: " + startProp.vector3Value.z + "</color>"; EditorGUILayout.LabelField(labelText, labelFieldRichText); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); labelText = "<color=" + txtColourName + "><b>Heightmap Resolution</b></color>"; EditorGUILayout.LabelField(labelText, labelFieldRichText, GUILayout.Width(EditorGUIUtility.labelWidth)); labelText = "<color=" + txtColourName + ">" + heightmapResolutionProp.intValue + "</color>"; EditorGUILayout.LabelField(labelText, labelFieldRichText); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); labelText = "<color=" + txtColourName + "><b>Terrain Width</b></color>"; EditorGUILayout.LabelField(labelText, labelFieldRichText, GUILayout.Width(EditorGUIUtility.labelWidth)); labelText = "<color=" + txtColourName + ">" + terrainWidthProp.floatValue + "</color>"; EditorGUILayout.LabelField(labelText, labelFieldRichText); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); labelText = "<color=" + txtColourName + "><b>Terrain Height</b></color>"; EditorGUILayout.LabelField(labelText, labelFieldRichText, GUILayout.Width(EditorGUIUtility.labelWidth)); labelText = "<color=" + txtColourName + ">" + terrainHeightProp.floatValue + "</color>"; EditorGUILayout.LabelField(labelText, labelFieldRichText); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); labelText = "<color=" + txtColourName + "><b>Alphamap Resolution</b></color>"; EditorGUILayout.LabelField(labelText, labelFieldRichText, GUILayout.Width(EditorGUIUtility.labelWidth)); labelText = "<color=" + txtColourName + ">" + alphaMapResolutionProp.intValue + "</color>"; EditorGUILayout.LabelField(labelText, labelFieldRichText); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); labelText = "<color=" + txtColourName + "><b>Terrain Material Type</b></color>"; EditorGUILayout.LabelField(labelText, labelFieldRichText, GUILayout.Width(EditorGUIUtility.labelWidth)); EditorGUILayout.PropertyField(terrainMaterialTypeProp, GUIContent.none); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); labelText = "<color=" + txtColourName + "><b>Legacy Noise Offset</b></color>"; EditorGUILayout.LabelField(labelText, labelFieldRichText, GUILayout.Width(EditorGUIUtility.labelWidth)); labelText = "<color=" + txtColourName + ">" + useLegacyNoiseOffsetProp.boolValue + "</color>"; EditorGUILayout.LabelField(labelText, labelFieldRichText); EditorGUILayout.EndHorizontal(); labelText = "<color=" + txtColourName + "><b>GPU Acceleration</b></color>"; EditorGUILayout.LabelField(labelText, labelFieldRichText, GUILayout.Width(EditorGUIUtility.labelWidth)); EditorGUILayout.BeginHorizontal(); labelText = "<color=" + txtColourName + "><b> Topography</b></color>"; EditorGUILayout.LabelField(labelText, labelFieldRichText, GUILayout.Width(EditorGUIUtility.labelWidth)); labelText = "<color=" + txtColourName + ">" + useGPUTopographyProp.boolValue + "</color>"; EditorGUILayout.LabelField(labelText, labelFieldRichText); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); labelText = "<color=" + txtColourName + "><b> Texturing</b></color>"; EditorGUILayout.LabelField(labelText, labelFieldRichText, GUILayout.Width(EditorGUIUtility.labelWidth)); labelText = "<color=" + txtColourName + ">" + useGPUTexturingProp.boolValue + "</color>"; EditorGUILayout.LabelField(labelText, labelFieldRichText); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); labelText = "<color=" + txtColourName + "><b> Grass</b></color>"; EditorGUILayout.LabelField(labelText, labelFieldRichText, GUILayout.Width(EditorGUIUtility.labelWidth)); labelText = "<color=" + txtColourName + ">" + useGPUGrassProp.boolValue + "</color>"; EditorGUILayout.LabelField(labelText, labelFieldRichText); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); labelText = "<color=" + txtColourName + "><b> Path</b></color>"; EditorGUILayout.LabelField(labelText, labelFieldRichText, GUILayout.Width(EditorGUIUtility.labelWidth)); labelText = "<color=" + txtColourName + ">" + useGPUPathProp.boolValue + "</color>"; EditorGUILayout.LabelField(labelText, labelFieldRichText); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); labelText = "<color=" + txtColourName + "><b>Populate Landscape</b></color>"; EditorGUILayout.LabelField(labelText, labelFieldRichText, GUILayout.Width(EditorGUIUtility.labelWidth)); EditorGUILayout.PropertyField(isPopulateLandscapeProp, new GUIContent(""), GUILayout.Width(30)); EditorGUILayout.EndHorizontal(); if (GUILayout.Button("Create New unpopulated Landscape from Template")) { if (lbTemplate == null) { Debug.LogWarning("LBTemplateEditor - create landscape - template not defined. Please Report"); } else if (string.IsNullOrEmpty(UnityEditor.SceneManagement.EditorSceneManager.GetActiveScene().name)) { EditorUtility.DisplayDialog("Generate Landscape", "Please save the scene before adding a landscape.", "Got it!"); } else { LBLandscape lbLandscape = lbTemplate.CreateLandscapeFromTemplate(lbTemplate.landscapeName); UnityEditor.SceneManagement.EditorSceneManager.MarkSceneDirty(UnityEditor.SceneManagement.EditorSceneManager.GetActiveScene()); if (lbLandscape != null) { lbTemplate.ApplyTemplateToLandscape(lbLandscape, false, true, null, true); if (isPopulateLandscapeProp.boolValue) { lbLandscape.ApplyTopography(false, true); lbLandscape.ApplyTextures(false, true); lbLandscape.ApplyTrees(false, true); lbLandscape.ApplyGrass(false, true); lbLandscape.ApplyGroups(false, true); lbLandscape.ApplyMeshes(false, true); } if (lbTemplate.isLBLightingIncluded) { LBLighting lbLighting = GameObject.FindObjectOfType <LBLighting>(); 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, Camera.main, true); } } LandscapeBuilderWindow.SetLandscape(lbLandscape, true); // Prevent errors in editor for U2017 //EditorGUILayout.EndVertical(); //return; } } } EditorGUILayout.BeginHorizontal(); labelText = "<color=" + txtColourName + "><b>Debug Mode</b></color>"; EditorGUILayout.LabelField(labelText, labelFieldRichText, GUILayout.Width(EditorGUIUtility.labelWidth)); EditorGUILayout.PropertyField(debugModeProp, new GUIContent(""), GUILayout.Width(30)); labelText = "<color=" + txtColourName + "><b>INTERNAL USE ONLY</b></color>"; EditorGUILayout.LabelField(labelText, labelFieldRichText); EditorGUILayout.EndHorizontal(); serializedObject.ApplyModifiedProperties(); if (debugModeProp.boolValue) { // Display unhidden public variables in LBTemplate.cs DrawDefaultInspector(); } EditorGUILayout.EndVertical(); }
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); }