/// <summary> /// Build a list of the Group names in the landscape /// </summary> private void GetGroupNameList() { if (groupNameList == null) { groupNameList = new List <string>(20); } else { groupNameList.Clear(); } LBGroup lbGroup = null; if (landscape != null) { int numGroups = landscape.lbGroupList == null ? 0 : landscape.lbGroupList.Count; for (int gIdx = 0; gIdx < numGroups; gIdx++) { lbGroup = landscape.lbGroupList[gIdx]; if (lbGroup.lbGroupType == LBGroup.LBGroupType.Uniform) { groupNameList.Add("Group " + (gIdx + 1) + " " + lbGroup.groupName); } } } // Refresh the number of names in the list for faster lookup numGroupNames = groupNameList == null ? 0 : groupNameList.Count; }
/// <summary> /// Remove any existing Location objects from the landscape. Only add back in ones from the selected group. /// This assumes only one group can be displayed for the current landscape. /// </summary> /// <param name="landscape"></param> /// <param name="lbGroupLocation"></param> /// <param name="showErrors"></param> public static void RefreshLocationsInScene(LBLandscape landscape, LBGroup lbGroupLocation, Material locationMaterial, bool showErrors) { string methodName = "LBGroupLocationItem.RefreshLocationsInScene"; // Basic validation if (landscape == null) { if (showErrors) { Debug.LogWarning("ERROR: " + methodName + " landscape is null"); } } else { RemoveLocationsFromScene(landscape, showErrors); if (lbGroupLocation == null) { if (showErrors) { Debug.LogWarning("ERROR: " + methodName + " lbGroupLocation is null"); } } else { int numLocations = (lbGroupLocation.positionList == null ? 0 : lbGroupLocation.positionList.Count); for (int i = 0; i < numLocations; i++) { CreateLocationItemInScene(landscape, lbGroupLocation, locationMaterial, lbGroupLocation.positionList[i] + landscape.start, lbGroupLocation.isFixedRotation ? lbGroupLocation.rotationYList[i] : 0f, i + 1, showErrors); } } } }
public void InitialiseMemberProximity() { proximityMemberCellsListWidth = 1; if (isGroupDesignerEnabled) { // Set proximityMemberCellsListWidth dynamically based on group radius and 2x the maximum proximity proximityMemberCellsListWidth = (int)(activeGroupList[0].maxClearingRadius / LBGroup.GetMaxMemberProximityExtent(activeGroupList)); } else { // Set proximityMemberCellsListWidth dynamically based on landscape width and 2x the maximum proximity proximityMemberCellsListWidth = (int)(landscapeWidth * 0.5f / LBGroup.GetMaxMemberProximityExtent(activeGroupList)); } if (proximityMemberCellsListWidth > 100) { proximityMemberCellsListWidth = 100; } if (proximityMemberCellsListWidth < 1) { proximityMemberCellsListWidth = 1; } // Populate proximity lists totalProximityMemberCells = proximityMemberCellsListWidth * proximityMemberCellsListWidth; objectProximitiesList = new List <LBObjectProximity> [totalProximityMemberCells]; for (int i = 0; i < totalProximityMemberCells; i++) { objectProximitiesList[i] = new List <LBObjectProximity>(); } // Initialise proximity variables thisObjectProximityCellIndex = 0; proximityMemberCellXCoord = 0; proximityMemberCellZCoord = 0; thisObjectProximitiesList = new List <LBObjectProximity>(); }
public void InitialiseGrassArrays() { isRemoveGrassPresent = LBGroup.IsRemoveGrassPresent(activeGroupList); isGrassPopulationPresent = LBGroup.IsPopulateGrassPresent(activeGroupList); // A grass array needs to be size of the sum of all grass arrays in each terrain terrainDetailResolution = lbGroupParams.landscape.GetLandscapeTerrainDetailResolution(); grassArrayCellsListWidth = numTerrainsWide * terrainDetailResolution; totalGrassArrayCells = grassArrayCellsListWidth * grassArrayCellsListWidth; // Grass removal array: 255 = previous grass strengh, 0 = all grass removed initialGrassRemovalArray = new byte[totalGrassArrayCells]; finalGrassRemovalArray = new byte[totalGrassArrayCells]; // Find out how many grass addition arrays we need, then pack them all into a single array grassAdditionArraySize = lbGroupParams.landscape.GetNumTerrainGrassList * totalGrassArrayCells; grassAdditionArray = new byte[grassAdditionArraySize]; // Set defaults for each array for (int i = 0; i < totalGrassArrayCells; i++) { initialGrassRemovalArray[i] = 255; finalGrassRemovalArray[i] = 255; } for (int i = 0; i < grassAdditionArraySize; i++) { grassAdditionArray[i] = 0; } // Calculate the size in metres of each cell grassArrayCellSize = lbGroupParams.landscape.size.x / grassArrayCellsListWidth; // Initialise grass array variables thisGrassArrayCellIndex = 0; grassArrayCellXCoord = 0; grassArrayCellZCoord = 0; grassAreaRadius = 0; grassAreaNoBlendRadius = 0f; grassAreaCentreXIndex = 0; grassAreaCentreZIndex = 0; grassAreaMinXIndex = 0; grassAreaMaxXIndex = 0; grassAreaMinZIndex = 0; grassAreaMaxZIndex = 0; grassAdditionArrayIndexShift = 0; // Initialise grass removal variables grassRemovalBlendFactor = 0f; grassRemovalDist = 0f; // Initialise grass population variables grassPlacementDist = 0f; grassPopulationBlendFactor = 0f; grassNoiseValue = 0f; terrainGrassList = lbGroupParams.landscape.TerrainGrassList(); terrainGrassListSize = terrainGrassList == null ? 0 : terrainGrassList.Count; grsIdx = 0; // The Group-level Grass option tab contains GUIDs that reference LBTerrainGrass instances in the // landscape class terrainGrassList. These are LBTerrainGrass instances that have been applied // to the landscape. Some LBTerrainGrass instances may be disabled or don't have a valid grass texture. // This list contains the matching index of the Grass Tab's LBTerrainGrass in the // array of unique detailPrototypes for all terrains. terrainGrassArrayIndexList = new List <int>(new int[terrainGrassListSize]); }
/// <summary> /// Create a gameobject in the GroupDesigner that can be used to track location and size /// of SubGroups. Currently it assumes they are spawned from a Object Path in the parent /// Clearing Group. The LBPrefabItem component type may need to be changed for subgroups /// not created from an Object Path. /// </summary> /// <param name="parentTfrm"></param> /// <param name="parentGroup"></param> /// <param name="parentGroupMember"></param> /// <param name="subGroup"></param> /// <param name="subGroupPosition"></param> /// <param name="subGroupRotation"></param> /// <param name="subGroupRadius"></param> /// <param name="regionIdx"></param> /// <returns></returns> public static LBGroupDesignerItem CreateSubGroupItem(Transform parentTfrm, LBGroup parentGroup, LBGroupMember parentGroupMember, LBGroup subGroup, Vector3 subGroupPosition, Vector3 subGroupRotation, float subGroupRadius, int regionIdx) { LBGroupDesignerItem lbGroupDesignerItem = null; if (parentGroup != null && parentTfrm != null && subGroup != null) { // [DESIGNER] (parentGroupName.subgroup:subGroupName.regionnumber) GameObject subGroupGO = new GameObject("[DESIGNER] (" + (string.IsNullOrEmpty(parentGroup.groupName) ? "ParentGroup" : parentGroup.groupName) + ".subgroup:" + (string.IsNullOrEmpty(subGroup.groupName) ? "SubGroup" : subGroup.groupName) + "." + (regionIdx + 1) + ")"); if (subGroupGO != null) { Quaternion rotation = Quaternion.Euler(subGroupRotation); subGroupGO.transform.SetPositionAndRotation(subGroupPosition, rotation); subGroupGO.transform.SetParent(parentTfrm); lbGroupDesignerItem = subGroupGO.AddComponent <LBGroupDesignerItem>(); if (lbGroupDesignerItem != null) { lbGroupDesignerItem.isSubGroup = true; lbGroupDesignerItem.SubGroupGUID = subGroup == null ? string.Empty : subGroup.GUID; lbGroupDesignerItem.position = subGroupPosition; lbGroupDesignerItem.rotation = rotation; lbGroupDesignerItem.subGroupRadius = subGroupRadius; lbGroupDesignerItem.FindGroupDesigner(); if (parentGroupMember != null) { lbGroupDesignerItem.objPathGroupMemberGUID = parentGroupMember.GUID; lbGroupDesignerItem.isObjPathMember = parentGroupMember.lbMemberType == LBGroupMember.LBMemberType.ObjPath; } else { lbGroupDesignerItem.objPathGroupMemberGUID = string.Empty; lbGroupDesignerItem.isObjPathMember = false; } } LBPrefabItem lbPrefabItem = subGroupGO.AddComponent <LBPrefabItem>(); if (lbPrefabItem != null) { lbPrefabItem.prefabItemType = LBPrefabItem.PrefabItemType.ObjPathDesignerPrefab; // Add the GUID of the object path GroupMember so that we can track them in the scene // It lets us enable/disable existing prefabs when using the Object Path Designer // If this Group is being spawned from a parent group, assign the member GUID from that parent instead // of using the current member GUID. This ensures that the Designers can disable and enable the correct gameobject // for subgroups. lbPrefabItem.groupMemberGUID = parentGroupMember != null ? parentGroupMember.GUID : subGroup.GUID; } } } return(lbGroupDesignerItem); }
private void BClear_Click(object sender, EventArgs e) { T.Module(MethodBase.GetCurrentMethod().Name); filterText = string.Empty; TBFilter.Text = string.Empty; if (LBGroup.SelectedIndex > -1 && LBGroup.GetSelected(LBGroup.SelectedIndex)) { var result = GetLogItems(LBGroup.SelectedItem.ToString()); result = result.OrderByDescending(x => x.Stamp).ToList(); dgvLogs.DataSource = result; } T.Module(); }
private void Form1_Load(object sender, EventArgs e) { T.Module(MethodBase.GetCurrentMethod().Name); var folderGroups = config.Retrieve("folder.groups"); if (folderGroups.Length == 0) { Environment.Exit(0); } List <string> folderGroupList = folderGroups.Split(' ').ToList <string>(); folderGroupList.Sort(); T.Inform("folderGroups", folderGroups); LBGroup.DataSource = folderGroupList; LBGroup.SetSelected(0, false); T.Module(); }
private void OnEnable() { lbGroupDesignerItem = (LBGroupDesignerItem)target; if (lbGroupDesignerItem != null) { lbGroupDesignerItem.position = lbGroupDesignerItem.transform.position; lbGroupDesignerItem.rotation = lbGroupDesignerItem.transform.rotation; lbGroupDesignerItem.scale = lbGroupDesignerItem.transform.localScale; // Get a reference to the group from the designer. if (lbGroupDesignerItem.lbGroupDesigner != null) { lbGroup = lbGroupDesignerItem.lbGroupDesigner.lbGroup; } prevPosition = lbGroupDesignerItem.position; } }
/// <summary> /// Find all the manual clearing location objects in the scene, filter them by a group, and set their size. /// </summary> /// <param name="landscape"></param> /// <param name="lbGroupLocation"></param> /// <param name="showErrors"></param> public static void RefreshLocationSizesInScene(LBLandscape landscape, LBGroup lbGroupLocation, bool showErrors) { string methodName = "LBGroupLocationItem.RefreshLocationSizesInScene"; // 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 { List <LBGroupLocationItem> lbGroupLocationItemList = new List <LBGroupLocationItem>(); landscape.GetComponentsInChildren(lbGroupLocationItemList); // Update the size of all the current location items in the scene for this landscape if (lbGroupLocationItemList != null) { lbGroupLocationItemList.RemoveAll(locItem => locItem.lbGroup.groupName != lbGroupLocation.groupName); int numItems = lbGroupLocationItemList.Count; for (int i = 0; i < numItems; i++) { LBGroupLocationItem lbGroupLocationItem = lbGroupLocationItemList[i]; lbGroupLocationItem.transform.localScale = new Vector3(lbGroupLocation.maxClearingRadius * 2f, 0.1f, lbGroupLocation.maxClearingRadius * 2f); } } } } }
/// <summary> /// Refresh the number of zones in all location items in the scene for this a group. /// Typically called when manual clearing groups are being edited, and the number of zones is changed. /// </summary> /// <param name="landscape"></param> /// <param name="lbGroupLocation"></param> /// <param name="showErrors"></param> public static void RefreshLocationZonesInScene(LBLandscape landscape, LBGroup lbGroupLocation, bool showErrors) { string methodName = "LBGroupLocationItem.RefreshLocationZonesInScene"; // 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 { List <LBGroupLocationItem> lbGroupLocationItemList = new List <LBGroupLocationItem>(); landscape.GetComponentsInChildren(lbGroupLocationItemList); // Update the zone count for all the current location items in the scene for this group if (lbGroupLocationItemList != null) { lbGroupLocationItemList.RemoveAll(locItem => locItem.lbGroup.GUID != lbGroupLocation.GUID); int numItems = lbGroupLocationItemList.Count; for (int i = 0; i < numItems; i++) { LBGroupLocationItem lbGroupLocationItem = lbGroupLocationItemList[i]; lbGroupLocationItem.numZones = lbGroupLocation.zoneList == null ? 0 : lbGroupLocation.zoneList.Count; } } } } }
public LBObjPathParameters() { landscape = null; lbGroupOwner = null; lbGroupMemberOwner = null; prefabItemType = LBPrefabItem.PrefabItemType.ObjPathPrefab; showErrors = false; showProgress = false; showProgressDelegate = null; clearingRotationY = 0f; lbGroupMember = null; prefab = null; pathPoint = Vector3.zero; distanceAlongPath = 0f; parentTfm = null; terrainDataArray = new TerrainData[0]; terrainRectsArray = new Rect[0]; terrainHeight = 1000f; }
public void InitialiseTextureArrays() { isTexturingPresent = LBGroup.IsApplyTexturesPresent(activeGroupList); isObjPathTexturingPresent = LBGroup.IsApplyObjPathTexturesPresent(activeGroupList) && !isGroupDesignerEnabled; // A texture array needs to be size of the sum of all alphamap arrays in each terrain terrainAlphamapResolution = lbGroupParams.landscape.GetLandscapeTerrainAlphaMapResolution(); textureArrayCellsListWidth = numTerrainsWide * terrainAlphamapResolution; totalTextureArrayCells = textureArrayCellsListWidth * textureArrayCellsListWidth; // Texture array: 255 = add highest strength, 0 = add nothing // Find out how many texture arrays we need, then pack them all into a single array // NOTE: This may cause issues for Imported Terrains with different textures in each terrain. totalTextureAdditionArrays = lbGroupParams.landscape.GetNumActiveTerrainTextures(true); textureAdditionArraySize = totalTextureAdditionArrays * totalTextureArrayCells; textureAdditionArray = new byte[textureAdditionArraySize]; // Set defaults for each array for (int i = 0; i < textureAdditionArraySize; i++) { textureAdditionArray[i] = 0; } // Calculate the size in metres of each cell textureArrayCellSize = lbGroupParams.landscape.size.x / textureArrayCellsListWidth; // Initialise texture array variables thisTextureArrayCellIndex = 0; textureArrayCellXCoord = 0; textureArrayCellZCoord = 0; textureAreaRadius = 0; textureAreaNoBlendRadius = 0f; textureAreaCentreXIndex = 0; textureAreaCentreZIndex = 0; textureAreaMinXIndex = 0; textureAreaMaxXIndex = 0; textureAreaMinZIndex = 0; textureAreaMaxZIndex = 0; textureAdditionArrayIndexShift = 0; // Initialise texture placement variables texturePlacementDist = 0f; textureBlendFactor = 0f; terrainTextureList = lbGroupParams.landscape.TerrainTexturesList(); terrainTextureListSize = terrainTextureList == null ? 0 : terrainTextureList.Count; txIdx = 0; // The Group-level Tex option tab contains GUIDs that reference LBTerrainTexture instances in the // landscape class terrainTexturesList. These are LBTerrainTexture instances that have been applied // to the landscape. Some LBTerrainTexture instances may be disabled or don't have a valid Texture2D. // This list contains the matching index of the Texturing Tab's LBTerrainTexture in the // array of unique splatPrototypes for all terrains. terrainTextureArrayIndexList = new List <int>(new int[terrainTextureListSize]); // Fill the lookup array with -ve numbers to show there is no matching splatprototype to begin with for (int txArrayIdx = 0; txArrayIdx < terrainTextureListSize; txArrayIdx++) { terrainTextureArrayIndexList[txArrayIdx] = -1; } if ((isTexturingPresent || isObjPathTexturingPresent) && terrainTextureList != null) { // Get a list of unique textures from the terrain data for (int t = 0; t < numTerrains; t++) { #if UNITY_2018_3_OR_NEWER List <LBTerrainTexture> splatTextures = LBTerrainTexture.ToLBTerrainTextureList(terrainDataArray[t].terrainLayers); #else List <LBTerrainTexture> splatTextures = LBTerrainTexture.ToLBTerrainTextureList(terrainDataArray[t].splatPrototypes); #endif if (splatTextures != null) { for (txIdx = 0; txIdx < terrainTextureListSize; txIdx++) { // Skip textures that have already been matched if (terrainTextureArrayIndexList[txIdx] < 0) { LBTerrainTexture lbTerrainTexture = terrainTextureList[txIdx]; // Attempt to match this Texture with a splatPrototype // Check for tinted textures //int splatIdx = splatTextures.FindIndex(stx => stx.texture == (lbTerrainTexture.isTinted ? lbTerrainTexture.tintedTexture : lbTerrainTexture.texture) && int splatIdx = splatTextures.FindIndex(stx => lbTerrainTexture.CompareToTexture2D(stx.texture) && stx.normalMap == lbTerrainTexture.normalMap && stx.smoothness == lbTerrainTexture.smoothness && stx.metallic == lbTerrainTexture.metallic && stx.tileSize == lbTerrainTexture.tileSize); if (splatIdx >= 0) { // Add this splatPrototype index to the array of LBTerrainTexture indexes // This will enable us to tell which splatPrototype (if any) matches the current LBTerrainTexture terrainTextureArrayIndexList[txIdx] = splatIdx; } } } } } } }
private void OnGUI() { #region Initialise defaultEditorLabelWidth = EditorGUIUtility.labelWidth; defaultEditorFieldWidth = EditorGUIUtility.fieldWidth; //if (labelFieldRichText == null) { labelFieldRichText = new GUIStyle("Label"); labelFieldRichText.richText = true; } // Overide default styles EditorStyles.foldout.fontStyle = FontStyle.Bold; // When using a no-label foldout, don't forget to set the global // EditorGUIUtility.fieldWidth to a small value like 15, then back // to the original afterward. foldoutStyleNoLabel = new GUIStyle(EditorStyles.foldout); foldoutStyleNoLabel.fixedWidth = 0.01f; #endregion GUILayout.BeginVertical("HelpBox"); EditorGUILayout.HelpBox("The LB Path Importer will help you import Group Object Paths from an external source (e.g. EasyRoads3D) [EXPERIMENTAL]", MessageType.Info, true); EditorGUIUtility.labelWidth = 100f; landscape = (LBLandscape)EditorGUILayout.ObjectField(landscapeContent, landscape, typeof(LBLandscape), true); EditorGUIUtility.labelWidth = defaultEditorLabelWidth; EditorGUILayout.Space(); #region Import - EasyRoads 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>Import from EasyRoads3D</b></color>", labelFieldRichText); #if LB_EDITOR_ER3 GUILayout.BeginHorizontal(); if (GUILayout.Button(erGetRoadsBtnContent, GUILayout.MaxWidth(100f))) { GetRoadList(); GetFilteredRoadList(); } if (GUILayout.Button(erClearRoadsBtnContent, GUILayout.MaxWidth(100f))) { if (roadList != null) { roadList.Clear(); } if (filteredRoadList != null) { filteredRoadList.Clear(); } if (roadTypeList != null) { roadTypeList.Clear(); } numAllRoads = 0; numFilteredRoads = 0; numAllRoadTypes = 0; } GUILayout.EndHorizontal(); #else EditorGUILayout.HelpBox("EasyRoads3D v3.x does not appear to be installed", MessageType.Info, true); #endif #endregion EditorGUILayout.LabelField("Roads (all): " + numAllRoads.ToString("###0")); EditorGUILayout.LabelField("Roads (filtered): " + numFilteredRoads.ToString("###0")); EditorGUILayout.Space(); EditorGUILayout.LabelField("<color=" + txtColourName + "><b>Copy Filtered Roads to LB Group</b></color>", labelFieldRichText); if (landscape == null) { EditorGUILayout.HelpBox("Select a landscape to export roads to Group Object Paths", MessageType.Info, true); } else { List <LBGroup> groupList = landscape.lbGroupList.FindAll(grp => grp.lbGroupType == LBGroup.LBGroupType.Uniform); int numUniformGroups = groupList == null ? 0 : groupList.Count; GetGroupNameList(); if (numUniformGroups == 0) { EditorGUILayout.HelpBox("There are no Uniform Groups in the landscape", MessageType.Info, true); } else { EditorGUI.BeginChangeCheck(); GUILayout.BeginHorizontal(); EditorGUILayout.LabelField("Target Group", GUILayout.Width(90f)); if (groupLookupIndex > numGroupNames - 1) { groupLookupIndex = -1; lbGroupTarget = null; } ; groupLookupIndex = EditorGUILayout.Popup(groupLookupIndex, groupNameList.ToArray()); GUILayout.EndHorizontal(); if (EditorGUI.EndChangeCheck()) { // Attempt to get the actual LBGroup instance if (groupLookupIndex < 0 || groupLookupIndex > numGroupNames - 1) { lbGroupTarget = null; } else { string groupName = groupNameList[groupLookupIndex]; if (string.IsNullOrEmpty(groupName)) { lbGroupTarget = null; } else if (groupName.Length < 7) { lbGroupTarget = null; } else { // Extract the group number out of the group name string int nextSpace = groupName.IndexOf(" ", 6); if (nextSpace < 7) { lbGroupTarget = null; } else { int grpNumber = -1; int.TryParse(groupName.Substring(6, nextSpace - 6), out grpNumber); if (grpNumber >= 0) { lbGroupTarget = landscape.lbGroupList[grpNumber - 1]; //Debug.Log("[DEBUG: group " + lbGroupTarget == null ? "uknown" : lbGroupTarget.groupName); } } } } } // If user has deleted a Group which was previously selected in the Path Importer, remove this as the target if (groupLookupIndex < 0 && lbGroupTarget != null) { lbGroupTarget = null; } #if LB_EDITOR_ER3 splinePointFilterSize = EditorGUILayout.IntSlider(erSplinePointSizeContent, splinePointFilterSize, 1, 50); #endif GUILayout.BeginHorizontal(); if (GUILayout.Button(copyRoadsBtnContent, GUILayout.MaxWidth(100f))) { if (lbGroupTarget != null) { #if LB_EDITOR_ER3 GetERSplineForRoads(); #endif CopyRoads(false); } else { EditorUtility.DisplayDialog("Copy Roads to Group", "You need to select a Target (Uniform) Group first", "Got it!"); } } if (GUILayout.Button(updateRoadsBtnContent, GUILayout.MaxWidth(100f))) { if (lbGroupTarget != null) { #if LB_EDITOR_ER3 GetERSplineForRoads(); #endif CopyRoads(true); } else { EditorUtility.DisplayDialog("Update Roads in Group", "You need to select a Target (Uniform) Group first", "Got it!"); } } GUILayout.EndHorizontal(); } //landscape.lbGroupList.Exists(grp => grp.showGroupsInScene == true); } EditorGUILayout.Space(); scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition); #region Filtering GUILayout.BeginHorizontal(); // A Foldout with no label must have a style fixedWidth of low non-zero value, and have a small (global) fieldWidth. EditorGUIUtility.fieldWidth = 17f; isShowFilterList = EditorGUILayout.Foldout(isShowFilterList, "", foldoutStyleNoLabel); EditorGUIUtility.fieldWidth = defaultEditorFieldWidth; EditorGUI.BeginChangeCheck(); isFilterByRoadType = EditorGUILayout.Toggle(filterByRoadTypeContent, isFilterByRoadType); GUILayout.EndHorizontal(); if (EditorGUI.EndChangeCheck()) { GetFilteredRoadList(); } if (isFilterByRoadType) { if (roadTypeList == null) { roadTypeList = new List <LBRoadType>(20); } if (isShowFilterList) { for (int rt = 0; rt < numAllRoadTypes; rt++) { lbRoadType = roadTypeList[rt]; if (lbRoadType != null) { GUILayout.BeginHorizontal(); EditorGUI.BeginChangeCheck(); lbRoadType.isSelected = EditorGUILayout.Toggle(lbRoadType.isSelected, GUILayout.Width(colSelectorWidth)); GUILayout.Label(lbRoadType.roadTypeDesc); GUILayout.EndHorizontal(); if (EditorGUI.EndChangeCheck()) { GetFilteredRoadList(); } } } } } EditorGUILayout.Space(); #endregion #region Display Filtered Road List // Header GUILayout.BeginHorizontal(); EditorGUI.BeginChangeCheck(); isSelectAllFilteredRoads = EditorGUILayout.Toggle(isSelectAllFilteredRoads, GUILayout.Width(colSelectorWidth)); if (EditorGUI.EndChangeCheck()) { SelectFilteredRoads(isSelectAllFilteredRoads); } EditorGUILayout.LabelField("<color=" + txtColourName + "><b>Road Type</b></color>", labelFieldRichText, GUILayout.Width(colRoadTypeWidth)); EditorGUILayout.LabelField("<color=" + txtColourName + "><b>Road Name</b></color>", labelFieldRichText, GUILayout.Width(colRoadNameWidth)); GUILayout.EndHorizontal(); for (int i = 0; i < numFilteredRoads; i++) { if (i > 200) { if (i != numFilteredRoads - 1) { continue; } else { GUILayout.Label(".."); } } lbRoad = filteredRoadList[i]; if (lbRoad != null) { // Display the selectable road GUILayout.BeginHorizontal(); //if (GUILayout.Button(new GUIContent("v", "Move road down in the list"), buttonCompact, GUILayout.MaxWidth(20f))) //{ // lbRoadMoveDown = new LBRoad(lbRoad); // lbRoadMovePos = i; //} lbRoad.isSelected = EditorGUILayout.Toggle(lbRoad.isSelected, GUILayout.Width(colSelectorWidth)); //GUILayout.Label(new GUIContent("R", "Reverse direction of path for this road"), GUILayout.Width(12f)); //lbRoad.isReversed = EditorGUILayout.Toggle(lbRoad.isReversed, GUILayout.Width(20f)); GUILayout.Label(lbRoad.roadTypeDesc, GUILayout.Width(colRoadTypeWidth)); GUILayout.Label(lbRoad.roadName, GUILayout.Width(colRoadNameWidth)); GUILayout.EndHorizontal(); } } #endregion GUILayout.EndVertical(); EditorGUILayout.EndScrollView(); GUILayout.EndVertical(); }
/// <summary> /// Attempt to convert Mesh/Prefabs to Uniform Groups /// </summary> /// <param name="landscape"></param> public static void ConvertMeshesToGroups(LBLandscape landscape) { string methodName = "LBUpdate.ConvertMeshesToGroups"; if (landscape == null) { Debug.LogWarning("ERROR: " + methodName + " - landscape is null. Please Report."); } else if (landscape.landscapeMeshList != null && landscape.lbGroupList != null) { List <LBGroup> convertedGroupList = new List <LBGroup>(); int numMeshes = landscape.landscapeMeshList.Count; for (int mIdx = 0; mIdx < numMeshes; mIdx++) { LBLandscapeMesh lMesh = landscape.landscapeMeshList[mIdx]; if (lMesh.isDisabled) { Debug.Log("INFO: " + methodName + " skipping disabled Mesh " + (mIdx + 1)); } else if (lMesh.meshPlacingMode == LBLandscapeMesh.MeshPlacingMode.Map || lMesh.meshPlacingMode == LBLandscapeMesh.MeshPlacingMode.HeightInclinationMap) { Debug.Log("INFO: " + methodName + " cannot convert Mesh " + (mIdx + 1) + " as it contains a Map texture. Recommendation: use a Stencil Layer instead"); } else if (!lMesh.usePrefab) { Debug.Log("INFO: " + methodName + " cannot convert Mesh " + (mIdx + 1) + " as Groups only support prefabs."); } else if (lMesh.isClustered) { Debug.Log("INFO: " + methodName + " cannot convert Mesh " + (mIdx + 1) + " as source has Clusters enabled. Recommendation: Create a Procedural Clearing to replace this Mesh/Prefab."); } else { LBGroup lbGroup = null; LBGroupMember lbGroupMember = null; // If this is the first group always create a new one if (convertedGroupList.Count == 0) { lbGroup = new LBGroup(); if (lbGroup != null) { lbGroup.showInEditor = false; lbGroup.groupName = "converted group " + (convertedGroupList.Count + 1).ToString("000"); lbGroup.lbGroupType = LBGroup.LBGroupType.Uniform; lbGroup.filterList = GetSupportedMeshFilters(lMesh.filterList); convertedGroupList.Add(lbGroup); } } else { // Find a compatible group, else create a new one List <LBFilter> supportedMeshFilterList = GetSupportedMeshFilters(lMesh.filterList); int numThisMeshFilters = (supportedMeshFilterList == null ? 0 : supportedMeshFilterList.Count); // Find a group with the same filters for (int grpIdx = 0; grpIdx < convertedGroupList.Count; grpIdx++) { LBGroup searchGroup = convertedGroupList[grpIdx]; List <LBFilter> groupFilterList = searchGroup.filterList; int numThisGroupFilters = (groupFilterList == null ? 0 : groupFilterList.Count); if (numThisMeshFilters == 0 && numThisGroupFilters == 0) { lbGroup = searchGroup; break; } else if (numThisMeshFilters == numThisGroupFilters) { // Assume they match bool isMatch = true; for (int fIdx = 0; fIdx < numThisGroupFilters; fIdx++) { if (groupFilterList[fIdx].filterType != supportedMeshFilterList[fIdx].filterType) { isMatch = false; break; } else if (groupFilterList[fIdx].lbStencilGUID != supportedMeshFilterList[fIdx].lbStencilGUID) { isMatch = false; break; } else if (groupFilterList[fIdx].lbStencilLayerGUID != supportedMeshFilterList[fIdx].lbStencilLayerGUID) { isMatch = false; break; } } if (isMatch) { lbGroup = searchGroup; break; } } } // If no suitable group was found, add a new one if (lbGroup == null) { lbGroup = new LBGroup(); lbGroup.showInEditor = false; lbGroup.groupName = "converted group " + (convertedGroupList.Count + 1).ToString("000"); lbGroup.lbGroupType = LBGroup.LBGroupType.Uniform; lbGroup.filterList = GetSupportedMeshFilters(lMesh.filterList); convertedGroupList.Add(lbGroup); } } if (lbGroup == null) { Debug.Log("INFO: " + methodName + " could not create a new LBGroup. Please Report"); } else { lbGroupMember = new LBGroupMember(); if (lbGroupMember == null) { Debug.Log("INFO: " + methodName + " could not create a new LBGroupMember. Please Report"); } else { lbGroupMember.showInEditor = false; CopyMeshToGroupMember(lMesh, lbGroup, lbGroupMember); lbGroup.groupMemberList.Add(lbGroupMember); // Disable migrated mesh/prefab items lMesh.isDisabled = true; } } } } if (convertedGroupList.Count > 0) { landscape.lbGroupList.AddRange(convertedGroupList); } } }
private static void CopyMeshToGroupMember(LBLandscapeMesh lMesh, LBGroup lbGroup, LBGroupMember lbGroupMember) { if (lMesh != null && lbGroup != null && lbGroupMember != null) { if (lMesh.meshPlacingMode != LBLandscapeMesh.MeshPlacingMode.ConstantInfluence || lMesh.minScale != 1f || lMesh.maxScale != 1f) { // This may not the first member of the group so need to check if we need to override group defaults // The first member of a group sets the group-level default settings if (lbGroup.groupMemberList.Count < 1) { lbGroupMember.isGroupOverride = false; lbGroup.minScale = lMesh.minScale; lbGroup.maxScale = lMesh.maxScale; lbGroup.minHeight = lMesh.minHeight; lbGroup.maxHeight = lMesh.maxHeight; lbGroup.minInclination = lMesh.minInclination; lbGroup.maxInclination = lMesh.maxInclination; } // Does this member have the same rules as the group it will be placed into? else if (lMesh.minScale != lbGroup.minScale || lMesh.maxScale != lbGroup.maxScale || lMesh.minHeight != lbGroup.minHeight || lMesh.maxHeight != lbGroup.maxHeight || lMesh.minInclination != lbGroup.minInclination || lMesh.maxInclination != lbGroup.maxInclination) { lbGroupMember.isGroupOverride = true; lbGroupMember.minScale = lMesh.minScale; lbGroupMember.maxScale = lMesh.maxScale; lbGroupMember.minHeight = lMesh.minHeight; lbGroupMember.maxHeight = lMesh.maxHeight; lbGroupMember.minInclination = lMesh.minInclination; lbGroupMember.maxInclination = lMesh.maxInclination; } else { // Member rules are the same as the Group, so no need to override group-level defaults lbGroupMember.isGroupOverride = false; } } lbGroupMember.prefab = lMesh.prefab; lbGroupMember.prefabName = lMesh.prefabName; lbGroupMember.modelOffsetX = lMesh.offset.x; lbGroupMember.modelOffsetY = 0f; lbGroupMember.modelOffsetZ = lMesh.offset.z; lbGroupMember.randomiseOffsetY = false; lbGroupMember.minOffsetY = lMesh.offset.y; lbGroupMember.maxOffsetY = lbGroupMember.minOffsetY; lbGroupMember.randomiseRotationY = lMesh.randomiseYRotation; if (lMesh.randomiseYRotation) { lbGroupMember.startRotationY = 0f; lbGroupMember.endRotationY = 359.9f; } else { lbGroupMember.startRotationY = lMesh.fixedYRotation; lbGroupMember.endRotationY = lMesh.fixedYRotation; } lbGroupMember.randomiseRotationXZ = false; lbGroupMember.rotationX = lMesh.XRotation; lbGroupMember.endRotationX = lMesh.XRotation; lbGroupMember.rotationZ = lMesh.ZRotation; lbGroupMember.endRotationZ = lMesh.ZRotation; lbGroupMember.isCombineMesh = lMesh.isCombineMesh; lbGroupMember.isKeepPrefabConnection = lMesh.isKeepPrefabConnection; lbGroupMember.isCreateCollider = lMesh.isCreateCollider; lbGroupMember.isRemoveEmptyGameObjects = lMesh.isRemoveEmptyGameObjects; lbGroupMember.useNoise = lMesh.useNoise; lbGroupMember.noiseTileSize = lMesh.noiseTileSize; lbGroupMember.noisePlacementCutoff = lMesh.meshPlacementCutoff; lbGroupMember.maxPrefabSqrKm = lMesh.maxMeshes; lbGroupMember.maxPrefabPerGroup = 10000; // Slightly incompatible as old mesh is centre to centre distance // mesh.minProximity can be 0.0, while lbGroupMember.proximityExtent currently must be > 0.01. lbGroupMember.proximityExtent = lMesh.minProximity; lbGroupMember.isTerrainAligned = lMesh.isTerrainAligned; lbGroupMember.isTerrainFlattened = lMesh.isTerrainFlattened; lbGroupMember.flattenBlendRate = lMesh.flattenBlendRate; lbGroupMember.flattenDistance = lMesh.flattenDistance; lbGroupMember.flattenHeightOffset = lMesh.flattenHeightOffset; lbGroupMember.minGrassProximity = lMesh.minGrassProximity; lbGroupMember.isRemoveTree = true; lbGroupMember.minTreeProximity = lMesh.minTreeProximity; } }
/// <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); }
public void InitialiseTreeProximity(string methodName) { // Set proximityTreeCellsListWidth dynamically based on landscape width and 2x the maximum tree proximity // Populate proximity lists proximityTreeCellsListWidth = (int)(landscapeWidth * 0.5f / LBGroup.GetMaxMemberTreeProximity(activeGroupList)); if (proximityTreeCellsListWidth > 100) { proximityTreeCellsListWidth = 100; } if (proximityTreeCellsListWidth < 1) { proximityTreeCellsListWidth = 1; } totalProximityTreeCells = proximityTreeCellsListWidth * proximityTreeCellsListWidth; treeProximitiesList = new List <LBObjectProximity> [totalProximityTreeCells]; for (int i = 0; i < totalProximityTreeCells; i++) { treeProximitiesList[i] = new List <LBObjectProximity>(); } // Initialise proximity variables thisTreeProximityCellIndex = 0; proximityTreeCellXCoord = 0; proximityTreeCellZCoord = 0; // Calculate the size in metres of each cell proximityTreeCellSize = lbGroupParams.landscape.size.x / proximityTreeCellsListWidth; proximityTreeCellMinXCoord = 0; proximityTreeCellMaxXCoord = 0; proximityTreeCellMinZCoord = 0; proximityTreeCellMaxZCoord = 0; proximityTreeCellBlockHalfWidth = 0; thisTreeProximitiesList = new List <LBObjectProximity>(); // Populate tree positions for (int i = 0; i < numTerrains; i++) { // Get and initialise terrain info Terrain tTerrain = landscapeTerrains[i]; if (tTerrain == null) { Debug.LogWarning("ERROR " + methodName + " - terrain " + i.ToString() + " is invalid or could not be found. Please Report."); } else { TerrainData tTerrainData = tTerrain.terrainData; if (tTerrainData == null) { Debug.LogWarning("ERROR " + methodName + " - some terrain data is invalid or could not be found. Please Report."); } else { // Get the position of the terrain relative to the landscape Vector3 tTerrainPos = tTerrain.transform.position; // Get the trees array TreeInstance[] terrainTreesArray = tTerrainData.treeInstances; int terrainTreesArrayLength = terrainTreesArray.Length; // Initialise tree variables Vector3 tTreeWorldPos = Vector3.zero; Vector3 tTreeLandscapePos = Vector3.zero; Vector2 tTreeNormalisedPos = Vector2.zero; TreeInstance terrainTreeInstance; for (int t = 0; t < terrainTreesArrayLength; t++) { terrainTreeInstance = terrainTreesArray[t]; // Get landscape position of the tree tTreeWorldPos = Vector3.Scale(terrainTreeInstance.position, tTerrainData.size) + tTerrainPos; tTreeLandscapePos = tTreeWorldPos - landscapePosition; // Get normalised position of the tree tTreeNormalisedPos.x = tTreeLandscapePos.x / landscapeWidth; tTreeNormalisedPos.y = tTreeLandscapePos.z / landscapeLength; // Find which cell we are in proximityTreeCellXCoord = (int)(tTreeNormalisedPos.x * proximityTreeCellsListWidth); proximityTreeCellZCoord = (int)(tTreeNormalisedPos.y * proximityTreeCellsListWidth); if (proximityTreeCellXCoord >= proximityTreeCellsListWidth) { proximityTreeCellXCoord = proximityTreeCellsListWidth - 1; } if (proximityTreeCellZCoord >= proximityTreeCellsListWidth) { proximityTreeCellZCoord = proximityTreeCellsListWidth - 1; } thisTreeProximityCellIndex = proximityTreeCellXCoord + (proximityTreeCellZCoord * proximityTreeCellsListWidth); if (thisTreeProximityCellIndex < 0) { thisTreeProximityCellIndex = 0; } else if (thisTreeProximityCellIndex >= totalProximityTreeCells) { thisTreeProximityCellIndex = totalProximityTreeCells - 1; } // Add this tree position to the cell treeProximitiesList[thisTreeProximityCellIndex].Add(new LBObjectProximity(tTreeLandscapePos, 0f, (short)i, t)); } } } } // Initialise variables for removing trees treesToRemoveList = new List <LBObjectProximity>(); thisTreesToRemoveList = new List <LBObjectProximity>(); }
/// <summary> /// Create and initialise a location of a manual group in the scene. /// </summary> /// <param name="landscape"></param> /// <param name="lbGroupLocation"></param> /// <param name="locationMaterial"></param> /// <param name="locationPos"></param> /// <param name="locationYRotation"></param> /// <param name="locationNumber"></param> /// <param name="showErrors"></param> /// <returns></returns> private static LBGroupLocationItem CreateLocationItemInScene(LBLandscape landscape, LBGroup lbGroupLocation, Material locationMaterial, Vector3 locationPos, float locationYRotation, int locationNumber, bool showErrors) { LBGroupLocationItem lbGroupLocationItem = null; string methodName = "LBGroupLocationItem.CreateLocationItemInScene"; GameObject cylinder = GameObject.CreatePrimitive(PrimitiveType.Cylinder); if (cylinder != null) { lbGroupLocationItem = cylinder.AddComponent <LBGroupLocationItem>(); if (lbGroupLocationItem == null) { DestroyImmediate(cylinder); if (showErrors) { Debug.LogWarning("ERROR: " + methodName + " could not add LBGroupLocationItem to location gameobject. Please Report."); } } else { lbGroupLocationItem.lbGroup = lbGroupLocation; cylinder.name = lbGroupLocation.groupName + "_loc" + locationNumber.ToString("0000"); cylinder.transform.SetPositionAndRotation(locationPos, Quaternion.Euler(0f, locationYRotation, 0f)); cylinder.transform.localScale = new Vector3(lbGroupLocation.maxClearingRadius * 2f, 0.1f, lbGroupLocation.maxClearingRadius * 2f); MeshRenderer mRen = cylinder.GetComponent(typeof(MeshRenderer)) as MeshRenderer; if (mRen != null) { // Disable casting and receive shadows mRen.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; mRen.receiveShadows = false; if (locationMaterial != null) { mRen.sharedMaterial = locationMaterial; } } // Remove capsule collider Component collider = cylinder.GetComponent(typeof(Collider)); if (collider != null) { DestroyImmediate(collider); } cylinder.transform.SetParent(landscape.transform); lbGroupLocationItem.rotationY = locationYRotation; // Get the number of zones so that they can be shown in OnDrawGizmos lbGroupLocationItem.numZones = lbGroupLocation.zoneList == null ? 0 : lbGroupLocation.zoneList.Count; lbGroupLocationItem.isInitialised = true; } } return(lbGroupLocationItem); }
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 } }