private void RenderPathUnderManualConstructionWhenNotUsingTileConnections(ObjectPlacementPath path) { List <ObjectPlacementBoxStackSegment> allPathSegments = path.GetAllSegments(); ObjectPlacementPathManualConstructionRenderSettings renderSettings = path.RenderSettings.ManualConstructionRenderSettings; Vector3 boxYOffsetvector = path.Settings.ManualConstructionSettings.OffsetAlongGrowDirection * path.ExtensionPlane.normal; foreach (ObjectPlacementBoxStackSegment segment in allPathSegments) { for (int stackIndex = 0; stackIndex < segment.NumberOfStacks; ++stackIndex) { ObjectPlacementBoxStack stack = segment.GetStackByIndex(stackIndex); if (stack.IsOverlappedByAnotherStack) { continue; } for (int boxIndex = 0; boxIndex < stack.NumberOfBoxes; ++boxIndex) { ObjectPlacementBox placementBox = stack.GetBoxByIndex(boxIndex); if (placementBox.IsHidden) { continue; } OrientedBox orientedBox = placementBox.OrientedBox; orientedBox.Center += boxYOffsetvector; GizmosEx.RenderOrientedBoxEdges(orientedBox, renderSettings.BoxBorderLineColor); } } } }
public void ApplyBordersToAllPathSegments(List <ObjectPlacementBoxStackSegment> pathSegments, ObjectPlacementPathBorderSettings borderSettings) { int totalNumberOfStacksInSegments = ObjectPlacementBoxStackSegmentQueries.GetTotalNumberOfStacksInSegments(pathSegments); int numberOfTraversedStacks = 0; for (int segmentIndex = 0; segmentIndex < pathSegments.Count; ++segmentIndex) { ObjectPlacementBoxStackSegment segment = pathSegments[segmentIndex]; for (int stackIndex = 0; stackIndex < segment.NumberOfStacks; ++stackIndex) { ObjectPlacementBoxStack stack = segment.GetStackByIndex(stackIndex); for (int boxIndex = 0; boxIndex < stack.NumberOfBoxes; ++boxIndex) { ObjectPlacementBox box = stack.GetBoxByIndex(boxIndex); box.ClearHideFlag(ObjectPlacementBoxHideFlags.PathApplyBorders); // Not hidden by default. We have to check against the borders to see if the box needs to be hidden. // Check if the box is outside the bottom and top borders if (boxIndex >= borderSettings.BottomBorderWidth && boxIndex < (stack.NumberOfBoxes - borderSettings.TopBorderWidth)) { // Check special case in which the current segment has the same extension direction as the one which precedes it // but is aiming in the opposite direction. In that case, the first stack will never be masked because it looks // weird. if (stackIndex == 0 && segmentIndex != 0) { ObjectPlacementBoxStackSegment previousSegment = pathSegments[segmentIndex - 1]; bool extendingInSameDirection; if (previousSegment.ExtensionDirection.IsAlignedWith(segment.ExtensionDirection, out extendingInSameDirection)) { // If the segments are aligned but they are extending in opposite directions, it means that // we have to leave the boxes in this stack untouched. if (!extendingInSameDirection) { continue; } } } if (numberOfTraversedStacks >= borderSettings.BeginBorderWidth && numberOfTraversedStacks < totalNumberOfStacksInSegments - borderSettings.EndBorderWidth) { box.SetHideFlag(ObjectPlacementBoxHideFlags.PathApplyBorders); } } } ++numberOfTraversedStacks; } } }
private void RenderPathUnderManualConstructionWhenUsingTileConnections(ObjectPlacementPath path, ObjectPlacementPathTileConnectionSettings tileConnectionSettings) { List <ObjectPlacementPathTileConnectionGridCell> tileConnectionGridCells = path.TileConnectionGridCells; ObjectPlacementPathManualConstructionRenderSettings renderSettings = path.RenderSettings.ManualConstructionRenderSettings; var tileConnectionYOffsetVectorCalculator = new ObjectPlacementPathTileConnectionYOffsetVectorCalculator(); // Loop through all tile connection grid cells. Each cell will give us access to all the information // that we need to perform the rendering operation. foreach (ObjectPlacementPathTileConnectionGridCell tileConnectionGridCell in tileConnectionGridCells) { // Use the cell to access the tile connection stack. If the stack is overlapped by another stack // or if no boxes exist in the stack, we can move on to the next cell. ObjectPlacementBoxStack tileConnectionStack = tileConnectionGridCell.TileConnectionStack; if (tileConnectionStack.IsOverlappedByAnotherStack || tileConnectionStack.NumberOfBoxes == 0) { continue; } // Calculate the Y offset vector which applies to all tiles in the current stack and then render each // box which resides inside the stack. Vector3 tileConnectionYOffsetVector = tileConnectionYOffsetVectorCalculator.Calculate(tileConnectionSettings.GetSettingsForTileConnectionType(tileConnectionGridCell.TileConnectionType), path); for (int boxIndex = 0; boxIndex < tileConnectionStack.NumberOfBoxes; ++boxIndex) { // If the box is hidden, we can move on to the next box ObjectPlacementBox placementBox = tileConnectionStack.GetBoxByIndex(boxIndex); if (placementBox.IsHidden) { continue; } // Retrieve the box and apply the Y offset vector. The render the box. OrientedBox orientedBox = placementBox.OrientedBox; orientedBox.Center += tileConnectionYOffsetVector; GizmosEx.RenderOrientedBoxEdges(orientedBox, renderSettings.BoxBorderLineColor); } // We have to take tile connection extrusion into account, so we will need to retrieve the extrusion // boxes and render those too. List <OrientedBox> extrusionOrientedBoxes = ObjectPlacementPathTileConnectionExtrusion.GetTileConnectionExtrusionOrientedBoxes(tileConnectionGridCell); foreach (OrientedBox extrusionBox in extrusionOrientedBoxes) { GizmosEx.RenderOrientedBoxEdges(extrusionBox, renderSettings.BoxBorderLineColor); } } }
public static List <OrientedBox> GetTileConnectionExtrusionOrientedBoxes(ObjectPlacementPathTileConnectionGridCell tileConnectionGridCell) { ObjectPlacementBoxStack tileConnectionStack = tileConnectionGridCell.TileConnectionStack; ObjectPlacementPathTileConnectionTypeSettings tileConnectionTypeSettings = tileConnectionGridCell.TileConnectionPath.Settings.TileConnectionSettings.GetSettingsForTileConnectionType(tileConnectionGridCell.TileConnectionType); if (tileConnectionStack != null) { if (tileConnectionStack.NumberOfBoxes == 0) { return(new List <OrientedBox>()); } if (tileConnectionTypeSettings.IsAnyExtrusionNecessary()) { // Handle upwards extrusion Vector3 nextTilePositionForUpwardsExtrusion; Vector3 extrudeOffset; Vector3 pathExtensionPlaneNormal = tileConnectionGridCell.TileConnectionPath.ExtensionPlane.normal; var tileConnectionYOffsetVectorCalculator = new ObjectPlacementPathTileConnectionYOffsetVectorCalculator(); Vector3 yOffsetVector = tileConnectionYOffsetVectorCalculator.Calculate(tileConnectionTypeSettings, tileConnectionGridCell.TileConnectionPath); extrudeOffset = pathExtensionPlaneNormal * tileConnectionStack.GetBoxSizeAlongNormalizedDirection(pathExtensionPlaneNormal); if (tileConnectionStack.IsGrowingUpwards) { nextTilePositionForUpwardsExtrusion = tileConnectionStack.GetBoxByIndex(tileConnectionStack.NumberOfBoxes - 1).Center + extrudeOffset; } else { nextTilePositionForUpwardsExtrusion = tileConnectionStack.GetBoxByIndex(0).Center + extrudeOffset; } var extrudedBox = new OrientedBox(); extrudedBox.Rotation = tileConnectionStack.Rotation; extrudedBox.ModelSpaceSize = tileConnectionStack.BoxSize; var extrusionOrientedBoxes = new List <OrientedBox>(); for (int extrudeIndex = 0; extrudeIndex < tileConnectionTypeSettings.UpwardsExtrusionAmount; ++extrudeIndex) { extrudedBox.Center = nextTilePositionForUpwardsExtrusion + yOffsetVector; extrusionOrientedBoxes.Add(new OrientedBox(extrudedBox)); nextTilePositionForUpwardsExtrusion += extrudeOffset; } // Handle downwards extrusion extrudeOffset = -pathExtensionPlaneNormal *tileConnectionStack.GetBoxSizeAlongNormalizedDirection(pathExtensionPlaneNormal); if (tileConnectionStack.IsGrowingDownwards) { nextTilePositionForUpwardsExtrusion = tileConnectionStack.GetBoxByIndex(tileConnectionStack.NumberOfBoxes - 1).Center + extrudeOffset; } else { nextTilePositionForUpwardsExtrusion = tileConnectionStack.GetBoxByIndex(0).Center + extrudeOffset; } for (int extrudeIndex = 0; extrudeIndex < tileConnectionTypeSettings.DownwardsExtrusionAmount; ++extrudeIndex) { extrudedBox.Center = nextTilePositionForUpwardsExtrusion + yOffsetVector; extrusionOrientedBoxes.Add(new OrientedBox(extrudedBox)); nextTilePositionForUpwardsExtrusion += extrudeOffset; } return(extrusionOrientedBoxes); } else { return(new List <OrientedBox>()); } } else { return(new List <OrientedBox>()); } }
public void ApplySubdivisionToEntireBlock(List <ObjectPlacementBoxStackSegment> allBlockSegments, ObjectPlacementBlockSubdivisionSettings subdivisionSettings) { // No subdivision required? if (!subdivisionSettings.SubdivideAlongGrowDirection && !subdivisionSettings.SubdivideAlongExtensionRight && !subdivisionSettings.SubdivideAlongExtensionLook) { return; } // Note: The following code assumes the segments' stacks extend along the extension plane right axis // and the segments themselves are arranged along the plane's look axis. for (int segmentIndex = 0; segmentIndex < allBlockSegments.Count; ++segmentIndex) { int numberOfTraversedSegments = segmentIndex + 1; ObjectPlacementBoxStackSegment segment = allBlockSegments[segmentIndex]; segment.ClearHideFlagInAllStacks(ObjectPlacementBoxHideFlags.BlockApplySubdivisions); // If we must subdivide along the extension look axis, we may need to hide the entire segment based // on the number of segments we have traversed so far. if (subdivisionSettings.SubdivideAlongExtensionLook) { // First calculate the remainder of how many pairs of <subidvision, gap> we have traversed int subdivisionGapPairSize = subdivisionSettings.SubdivisionGapSizeAlongExtensionLook + subdivisionSettings.SubdivisionSizeAlongExtensionLook; int remainder = numberOfTraversedSegments % subdivisionGapPairSize; // If the remainder is 0 it means we are at the end of a pair and the end of a pair is always a gap. So we activate // the hide flags. We also activate the hide flags if the remainder is bigger than the subdivision size. In that case // it means we reside somewhere inside the gap. if (remainder == 0 || remainder > subdivisionSettings.SubdivisionSizeAlongExtensionLook) { segment.SetHideFlagInAllStacks(ObjectPlacementBoxHideFlags.BlockApplySubdivisions); } } for (int stackIndex = 0; stackIndex < segment.NumberOfStacks; ++stackIndex) { int numberOfTraversedStacks = stackIndex + 1; ObjectPlacementBoxStack stack = segment.GetStackByIndex(stackIndex); if (subdivisionSettings.SubdivideAlongExtensionRight) { int subdivisionGapPairSize = subdivisionSettings.SubdivisionGapSizeAlongExtensionRight + subdivisionSettings.SubdivisionSizeAlongExtensionRight; int remainder = numberOfTraversedStacks % subdivisionGapPairSize; if (remainder == 0 || remainder > subdivisionSettings.SubdivisionSizeAlongExtensionRight) { stack.SetHideFlagForAllBoxes(ObjectPlacementBoxHideFlags.BlockApplySubdivisions); } } for (int boxIndex = 0; boxIndex < stack.NumberOfBoxes; ++boxIndex) { int numberOfTraversedBoxes = boxIndex + 1; if (subdivisionSettings.SubdivideAlongGrowDirection) { int subdivisionGapPairSize = subdivisionSettings.SubdivisionGapSizeAlongGrowDirection + subdivisionSettings.SubdivisionSizeAlongGrowDirection; int remainder = numberOfTraversedBoxes % subdivisionGapPairSize; if (remainder == 0 || remainder > subdivisionSettings.SubdivisionSizeAlongGrowDirection) { stack.GetBoxByIndex(boxIndex).SetHideFlag(ObjectPlacementBoxHideFlags.BlockApplySubdivisions); } } } } } }
public List <ObjectPlacementData> Calculate() { if (_path == null || _path.NumberOfSegments == 0 || !ObjectPlacementGuide.ExistsInScene) { return(new List <ObjectPlacementData>()); } Prefab placementGuidePrefab = ObjectPlacementGuide.Instance.SourcePrefab; Vector3 placementGuideWorldScale = ObjectPlacementGuide.Instance.WorldScale; float objectMissChance = _path.Settings.ManualConstructionSettings.ObjectMissChance; Vector3 yOffsetVector = _path.ExtensionPlane.normal * _path.Settings.ManualConstructionSettings.OffsetAlongGrowDirection; bool allowObjectIntersection = ObjectPlacementSettings.Get().ObjectIntersectionSettings.AllowIntersectionForPathPlacement; Quaternion placementGuideRotation = ObjectPlacementGuide.Instance.WorldRotation; bool rotateObjectsToFollowPath = _path.Settings.ManualConstructionSettings.RotateObjectsToFollowPath; Vector3 pathExtensionPlaneNormal = _path.ExtensionPlane.normal; Vector3 firstSegmentExtensionDir = _path.GetSegmentByIndex(0).ExtensionDirection; Quaternion firstSegmentRotation = Quaternion.LookRotation(firstSegmentExtensionDir, pathExtensionPlaneNormal); bool randomizePrefabs = _path.Settings.ManualConstructionSettings.RandomizePrefabs; PrefabCategory activePrefabCategory = PrefabCategoryDatabase.Get().ActivePrefabCategory; var objectPlacementDataInstances = new List <ObjectPlacementData>(_path.NumberOfSegments * 10); for (int segmentIndex = 0; segmentIndex < _path.NumberOfSegments; ++segmentIndex) { ObjectPlacementBoxStackSegment segment = _path.GetSegmentByIndex(segmentIndex); Quaternion worldRotation = placementGuideRotation; if (rotateObjectsToFollowPath) { // Note: ObjectPlacementPathManualConstructionSession.cs line 451. The design is a wreck. AGAIN :) if ((segmentIndex == 0 && _path.NumberOfSegments > 1 && segment.NumberOfStacks == 1)) { Vector3 dirBetweenStacks = segment.GetStackByIndex(0).BasePosition - _path.GetSegmentByIndex(1).GetStackByIndex(0).BasePosition; dirBetweenStacks.Normalize(); Quaternion segmentRotation = Quaternion.LookRotation(dirBetweenStacks, pathExtensionPlaneNormal); Quaternion fromPlacementGuideRotationToThis = QuaternionExtensions.GetRelativeRotation(placementGuideRotation, segmentRotation); worldRotation = fromPlacementGuideRotationToThis * worldRotation; } else if (segmentIndex != 0) { Quaternion segmentRotation = Quaternion.LookRotation(segment.ExtensionDirection, pathExtensionPlaneNormal); Quaternion fromFirstToThis = QuaternionExtensions.GetRelativeRotation(firstSegmentRotation, segmentRotation); worldRotation = fromFirstToThis * worldRotation; } } for (int stackIndex = 0; stackIndex < segment.NumberOfStacks; ++stackIndex) { ObjectPlacementBoxStack stack = segment.GetStackByIndex(stackIndex); if (stack.IsOverlappedByAnotherStack) { continue; } for (int stackBoxIndex = 0; stackBoxIndex < stack.NumberOfBoxes; ++stackBoxIndex) { ObjectPlacementBox box = stack.GetBoxByIndex(stackBoxIndex); if (box.IsHidden) { continue; } if (ObjectPlacementMissChance.Missed(objectMissChance, ObjectPlacementPathManualConstructionSettings.MinObjectMissChance, ObjectPlacementPathManualConstructionSettings.MaxObjectMissChance)) { continue; } if (!allowObjectIntersection && ObjectQueries.IntersectsAnyObjectsInScene(box.OrientedBox, true)) { continue; } Vector3 worldScale = placementGuideWorldScale; Prefab prefab = placementGuidePrefab; if (randomizePrefabs && activePrefabCategory.NumberOfPrefabs != 0) { int randomPrefabIndex = UnityEngine.Random.Range(0, activePrefabCategory.NumberOfPrefabs); Prefab randomPrefab = activePrefabCategory.GetPrefabByIndex(randomPrefabIndex); if (randomPrefab != null && randomPrefab.UnityPrefab != null) { prefab = activePrefabCategory.GetPrefabByIndex(randomPrefabIndex); worldScale = prefab.UnityPrefab.transform.lossyScale; } } var objectPlacementData = new ObjectPlacementData(); objectPlacementData.WorldPosition = ObjectPositionCalculator.CalculateObjectHierarchyPosition(prefab, box.Center + yOffsetVector, worldScale, worldRotation); objectPlacementData.WorldScale = worldScale; objectPlacementData.WorldRotation = worldRotation; objectPlacementData.Prefab = prefab; objectPlacementDataInstances.Add(objectPlacementData); } } } return(objectPlacementDataInstances); }
public List <ObjectPlacementData> Calculate() { if (_block == null || _block.NumberOfSegments == 0 || !ObjectPlacementGuide.ExistsInScene) { return(new List <ObjectPlacementData>()); } Prefab placementGuidePrefab = ObjectPlacementGuide.Instance.SourcePrefab; Vector3 placementGuideWorldScale = ObjectPlacementGuide.Instance.WorldScale; Quaternion placementGuideWorldRotation = ObjectPlacementGuide.Instance.WorldRotation; float objectMissChance = _block.Settings.ManualConstructionSettings.ObjectMissChance; ObjectRotationRandomizationSettings blockObjectRotationRandomizationSettings = _block.Settings.ManualConstructionSettings.ObjectRotationRandomizationSettings; bool randomizeRotations = blockObjectRotationRandomizationSettings.RandomizeRotation; Vector3 objectOffsetAlongExtensionPlaneNormal = _block.Settings.ManualConstructionSettings.OffsetAlongGrowDirection * _block.ExtensionPlane.normal; bool allowObjectIntersection = ObjectPlacementSettings.Get().ObjectIntersectionSettings.AllowIntersectionForBlockPlacement; bool randomizePrefabs = _block.Settings.ManualConstructionSettings.RandomizePrefabs; PrefabCategory activePrefabCategory = PrefabCategoryDatabase.Get().ActivePrefabCategory; ObjectPlacementBlockProjectionSettings projectionSettings = _block.Settings.BlockProjectionSettings; bool canProject = projectionSettings.ProjectOnSurface && (projectionSettings.CanProjectOnMesh || projectionSettings.CanProjectOnTerrain); var objectPlacementDataInstances = new List <ObjectPlacementData>(_block.NumberOfSegments * 10); for (int segmentIndex = 0; segmentIndex < _block.NumberOfSegments; ++segmentIndex) { ObjectPlacementBoxStackSegment segment = _block.GetSegmentByIndex(segmentIndex); for (int stackIndex = 0; stackIndex < segment.NumberOfStacks; ++stackIndex) { ObjectPlacementBoxStack stack = segment.GetStackByIndex(stackIndex); if (stack.IsOverlappedByAnotherStack || stack.NumberOfBoxes == 0) { continue; } Vector3 projectionOffset = Vector3.zero; Vector3 projectionDirection = Vector3.zero; Quaternion prjAlignRotation = Quaternion.identity; GameObjectRayHit projectionSurfaceHit = null; if (canProject) { Vector3 rayOrigin = stack.GetBoxByIndex(0).Center; Vector3 rayDir = Vector3.zero; if (projectionSettings.ProjectionDirection == ObjectBlockProjectionDir.BlockUp) { rayDir = _block.ExtensionPlane.normal; } else { rayDir = -_block.ExtensionPlane.normal; } projectionDirection = rayDir; Ray ray = new Ray(rayOrigin, rayDir); GameObjectRayHit closestMeshHit = null; GameObjectRayHit closestTerrainHit = null; if (projectionSettings.CanProjectOnMesh) { closestMeshHit = Octave3DScene.Get().RaycastAllMeshClosest(ray); } if (projectionSettings.CanProjectOnTerrain) { closestTerrainHit = Octave3DScene.Get().RaycastAllTerainsClosest(ray); } // Ignore stack if no surface was found and non-projectables must be rejected if (closestMeshHit == null && closestTerrainHit == null) { if (projectionSettings.RejectNonProjectables) { continue; } } else { projectionSurfaceHit = closestMeshHit; if (closestMeshHit == null || (closestTerrainHit != null && closestMeshHit.HitEnter > closestTerrainHit.HitEnter)) { projectionSurfaceHit = closestTerrainHit; } } if (projectionSurfaceHit != null) { ObjectPlacementBox projectionBox = stack.GetBoxByIndex(0); projectionOffset = projectionSurfaceHit.HitPoint - stack.GetBoxByIndex(0).Center; if (projectionOffset.sqrMagnitude > (projectionSurfaceHit.HitPoint - stack.GetBoxByIndex(stack.NumberOfBoxes - 1).Center).sqrMagnitude) { projectionBox = stack.GetBoxByIndex(stack.NumberOfBoxes - 1); projectionOffset = projectionSurfaceHit.HitPoint - projectionBox.Center; } if (!projectionSettings.AlignToSurfaceNormal) { var oobb = projectionBox.OrientedBox; Vector3 oldCenter = oobb.Center; GameObjectExtensions.EmbedObjectBoxInSurface(oobb, projectionDirection, projectionSurfaceHit.HitObject); projectionOffset = oobb.Center - oldCenter; } } } for (int stackBoxIndex = 0; stackBoxIndex < stack.NumberOfBoxes; ++stackBoxIndex) { ObjectPlacementBox box = stack.GetBoxByIndex(stackBoxIndex); if (box.IsHidden) { continue; } if (ObjectPlacementMissChance.Missed(objectMissChance, ObjectPlacementBlockManualConstructionSettings.MinObjectMissChance, ObjectPlacementBlockManualConstructionSettings.MaxObjectMissChance)) { continue; } if (!allowObjectIntersection && ObjectQueries.IntersectsAnyObjectsInScene(box.OrientedBox, true)) { continue; } Quaternion worldRotation = placementGuideWorldRotation; if (randomizeRotations) { worldRotation = ObjectRotationRandomization.GenerateRandomRotationQuaternion(blockObjectRotationRandomizationSettings); } Vector3 worldScale = placementGuideWorldScale; Prefab prefab = placementGuidePrefab; if (randomizePrefabs && activePrefabCategory.NumberOfPrefabs != 0) { int randomPrefabIndex = UnityEngine.Random.Range(0, activePrefabCategory.NumberOfPrefabs); Prefab randomPrefab = activePrefabCategory.GetPrefabByIndex(randomPrefabIndex); if (randomPrefab != null && randomPrefab.UnityPrefab != null) { prefab = activePrefabCategory.GetPrefabByIndex(randomPrefabIndex); worldScale = prefab.UnityPrefab.transform.lossyScale; } } Vector3 boxCenter = box.Center + objectOffsetAlongExtensionPlaneNormal + projectionOffset; if (projectionSurfaceHit != null) { if (projectionSettings.AlignToSurfaceNormal) { worldRotation = AxisAlignment.CalculateRotationQuaternionForAxisAlignment(worldRotation, projectionSettings.AlignmentAxis, projectionSurfaceHit.HitNormal); OrientedBox prefabWorldOOBB = prefab.UnityPrefab.GetHierarchyWorldOrientedBox(); Vector3 oobbSize = prefabWorldOOBB.ScaledSize; int axisIndex = (int)((int)(projectionSettings.AlignmentAxis) * 0.5f); boxCenter = projectionSurfaceHit.HitPoint + projectionSurfaceHit.HitNormal * oobbSize[axisIndex] * 0.5f + (oobbSize[axisIndex] * stackBoxIndex * projectionSurfaceHit.HitNormal); } } var objectPlacementData = new ObjectPlacementData(); objectPlacementData.WorldPosition = ObjectPositionCalculator.CalculateObjectHierarchyPosition(prefab, boxCenter, worldScale, worldRotation); objectPlacementData.WorldScale = worldScale; objectPlacementData.WorldRotation = worldRotation; objectPlacementData.Prefab = prefab; objectPlacementDataInstances.Add(objectPlacementData); } } } return(objectPlacementDataInstances); }
public List <ObjectPlacementData> Calculate() { if (!ValidatePlacementDataCalculationConditions()) { return(new List <ObjectPlacementData>()); } _allowObjectIntersection = ObjectPlacementSettings.Get().ObjectIntersectionSettings.AllowIntersectionForPathPlacement; List <ObjectPlacementBoxStackSegment> allPathSegments = _path.GetAllSegments(); float objectMissChance = _path.Settings.ManualConstructionSettings.ObjectMissChance; bool usingSprites = _path.Settings.TileConnectionSettings.UsesSprites(); var tileConnectionDetector = new ObjectPlacementPathTileConnectionDetector(); var tileConnectionRotationCalculator = new ObjectPlacementPathTileConnectionRotationCalculator(); List <ObjectPlacementPathTileConnectionGridCell> tileConnectionGridCells = tileConnectionDetector.Detect(_path, _tileConnectionXZSize); if (tileConnectionGridCells.Count == 0) { return(new List <ObjectPlacementData>()); } List <Prefab> tileConnectionPrefabsExceptAutofill = PathObjectPlacement.Get().PathSettings.TileConnectionSettings.GetAllTileConnectionPrefabs(true); List <Vector3> tileConnectionWorldScaleValuesExceptAutofill = CalculateWorldScaleForAllTileConnectionPrefabsExceptAutofill(PrefabQueries.GetTransformsForAllPrefabs(tileConnectionPrefabsExceptAutofill), PrefabQueries.GetHierarchyWorldOrientedBoxesForAllPrefabs(tileConnectionPrefabsExceptAutofill)); List <Vector3> tileConnectionOffsetsExceptAutofill = CalculateOffsetsForAllTileConnectionsExceptAutofill(); var objectPlacementDataInstances = new List <ObjectPlacementData>(allPathSegments.Count * 10); foreach (ObjectPlacementPathTileConnectionGridCell tileConnectionGridCell in tileConnectionGridCells) { ObjectPlacementPathTileConnectionType tileConnectionType = tileConnectionGridCell.TileConnectionType; ObjectPlacementBoxStack tileConnectionStack = tileConnectionGridCell.TileConnectionStack; if (tileConnectionStack.IsOverlappedByAnotherStack) { continue; } Prefab tileConnectionPrefab = tileConnectionPrefabsExceptAutofill[(int)tileConnectionType]; Quaternion tileConnectionRotation = tileConnectionRotationCalculator.Calculate(tileConnectionGridCell); Vector3 tileConnectionWorldScale = tileConnectionWorldScaleValuesExceptAutofill[(int)tileConnectionType]; Vector3 tileConnectionOffset = tileConnectionOffsetsExceptAutofill[(int)tileConnectionType]; for (int stackBoxIndex = 0; stackBoxIndex < tileConnectionStack.NumberOfBoxes; ++stackBoxIndex) { ObjectPlacementBox box = tileConnectionStack.GetBoxByIndex(stackBoxIndex); if (box.IsHidden) { continue; } if (ObjectPlacementMissChance.Missed(objectMissChance, ObjectPlacementPathManualConstructionSettings.MinObjectMissChance, ObjectPlacementPathManualConstructionSettings.MaxObjectMissChance)) { continue; } if (!_allowObjectIntersection && ObjectQueries.IntersectsAnyObjectsInScene(box.OrientedBox, true)) { continue; } var objectPlacementData = new ObjectPlacementData(); objectPlacementData.WorldPosition = ObjectPositionCalculator.CalculateObjectHierarchyPosition(tileConnectionPrefab, box.Center, tileConnectionWorldScale, tileConnectionRotation); objectPlacementData.WorldPosition += tileConnectionOffset; objectPlacementData.WorldScale = tileConnectionWorldScale; objectPlacementData.WorldRotation = tileConnectionRotation; objectPlacementData.Prefab = tileConnectionPrefab; objectPlacementDataInstances.Add(objectPlacementData); } // Apply extrusion if necessary if (!usingSprites) { List <OrientedBox> extrusionOrientedBoxes = ObjectPlacementPathTileConnectionExtrusion.GetTileConnectionExtrusionOrientedBoxes(tileConnectionGridCell); foreach (OrientedBox extrusionBox in extrusionOrientedBoxes) { if (ObjectPlacementMissChance.Missed(objectMissChance, ObjectPlacementPathManualConstructionSettings.MinObjectMissChance, ObjectPlacementPathManualConstructionSettings.MaxObjectMissChance)) { continue; } if (!_allowObjectIntersection && ObjectQueries.IntersectsAnyObjectsInScene(extrusionBox, true)) { continue; } var objectPlacementData = new ObjectPlacementData(); objectPlacementData.WorldPosition = ObjectPositionCalculator.CalculateObjectHierarchyPosition(tileConnectionPrefab, extrusionBox.Center, tileConnectionWorldScale, tileConnectionRotation); objectPlacementData.WorldScale = tileConnectionWorldScale; objectPlacementData.WorldRotation = tileConnectionRotation; objectPlacementData.Prefab = tileConnectionPrefab; objectPlacementDataInstances.Add(objectPlacementData); } } } ObjectPlacementPathTileConnectionSettings tileConnectionSettings = _path.Settings.TileConnectionSettings; if (tileConnectionSettings.DoesAutofillTileConnectionHavePrefabAssociated()) { objectPlacementDataInstances.AddRange(GetPlacementDataForAutofillTiles(tileConnectionGridCells[0].ParentGrid)); } return(objectPlacementDataInstances); }
public List <ObjectPlacementData> Calculate() { if (_block == null || _block.NumberOfSegments == 0 || !ObjectPlacementGuide.ExistsInScene) { return(new List <ObjectPlacementData>()); } Prefab placementGuidePrefab = ObjectPlacementGuide.Instance.SourcePrefab; Vector3 placementGuideWorldScale = ObjectPlacementGuide.Instance.WorldScale; Quaternion placementGuideWorldRotation = ObjectPlacementGuide.Instance.WorldRotation; float objectMissChance = _block.Settings.ManualConstructionSettings.ObjectMissChance; ObjectRotationRandomizationSettings blockObjectRotationRandomizationSettings = _block.Settings.ManualConstructionSettings.ObjectRotationRandomizationSettings; bool randomizeRotations = blockObjectRotationRandomizationSettings.RandomizeRotation; Vector3 objectOffsetAlongExtensionPlaneNormal = _block.Settings.ManualConstructionSettings.OffsetAlongGrowDirection * _block.ExtensionPlane.normal; bool allowObjectIntersection = ObjectPlacementSettings.Get().ObjectIntersectionSettings.AllowIntersectionForBlockPlacement; bool randomizePrefabs = _block.Settings.ManualConstructionSettings.RandomizePrefabs; PrefabCategory activePrefabCategory = PrefabCategoryDatabase.Get().ActivePrefabCategory; var objectPlacementDataInstances = new List <ObjectPlacementData>(_block.NumberOfSegments * 10); for (int segmentIndex = 0; segmentIndex < _block.NumberOfSegments; ++segmentIndex) { ObjectPlacementBoxStackSegment segment = _block.GetSegmentByIndex(segmentIndex); for (int stackIndex = 0; stackIndex < segment.NumberOfStacks; ++stackIndex) { ObjectPlacementBoxStack stack = segment.GetStackByIndex(stackIndex); if (stack.IsOverlappedByAnotherStack) { continue; } for (int stackBoxIndex = 0; stackBoxIndex < stack.NumberOfBoxes; ++stackBoxIndex) { ObjectPlacementBox box = stack.GetBoxByIndex(stackBoxIndex); if (box.IsHidden) { continue; } if (ObjectPlacementMissChance.Missed(objectMissChance, ObjectPlacementBlockManualConstructionSettings.MinObjectMissChance, ObjectPlacementBlockManualConstructionSettings.MaxObjectMissChance)) { continue; } if (!allowObjectIntersection && ObjectQueries.IntersectsAnyObjectsInScene(box.OrientedBox, true)) { continue; } Quaternion worldRotation = placementGuideWorldRotation; if (randomizeRotations) { worldRotation = ObjectRotationRandomization.GenerateRandomRotationQuaternion(blockObjectRotationRandomizationSettings); } Vector3 worldScale = placementGuideWorldScale; Prefab prefab = placementGuidePrefab; if (randomizePrefabs && activePrefabCategory.NumberOfPrefabs != 0) { int randomPrefabIndex = UnityEngine.Random.Range(0, activePrefabCategory.NumberOfPrefabs); Prefab randomPrefab = activePrefabCategory.GetPrefabByIndex(randomPrefabIndex); if (randomPrefab != null && randomPrefab.UnityPrefab != null) { prefab = activePrefabCategory.GetPrefabByIndex(randomPrefabIndex); worldScale = prefab.UnityPrefab.transform.lossyScale; } } var objectPlacementData = new ObjectPlacementData(); objectPlacementData.WorldPosition = ObjectPositionCalculator.CalculateObjectHierarchyPosition(prefab, box.Center + objectOffsetAlongExtensionPlaneNormal, worldScale, placementGuideWorldRotation); objectPlacementData.WorldScale = worldScale; objectPlacementData.WorldRotation = worldRotation; objectPlacementData.Prefab = prefab; objectPlacementDataInstances.Add(objectPlacementData); } } } return(objectPlacementDataInstances); }