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);
                    }
                }
            }
        }
示例#2
0
        public static List <ObjectPlacementBoxStack> GetOverlappedStacksInSegment(int segmentIndex, List <ObjectPlacementBoxStackSegment> pathSegments)
        {
            var overlappedStacks = new List <ObjectPlacementBoxStack>(pathSegments.Count * 10);

            ObjectPlacementBoxStackSegment possiblyOverlappedSegment = pathSegments[segmentIndex];

            for (int possiblyOverlappingSegmentIndex = segmentIndex - 1; possiblyOverlappingSegmentIndex >= 0; --possiblyOverlappingSegmentIndex)
            {
                ObjectPlacementBoxStackSegment possiblyOverlappingSegment = pathSegments[possiblyOverlappingSegmentIndex];

                if (possiblyOverlappingSegment.ExtensionVectorIntersects(possiblyOverlappedSegment) ||
                    possiblyOverlappingSegment.ExtensionVectorOverlaps(possiblyOverlappedSegment))
                {
                    for (int possiblyOverlappedStackIndex = 0; possiblyOverlappedStackIndex < possiblyOverlappedSegment.NumberOfStacks; ++possiblyOverlappedStackIndex)
                    {
                        ObjectPlacementBoxStack possiblyOverlappedStack = possiblyOverlappedSegment.GetStackByIndex(possiblyOverlappedStackIndex);
                        for (int possiblyOverlappingStackIndex = 0; possiblyOverlappingStackIndex < possiblyOverlappingSegment.NumberOfStacks; ++possiblyOverlappingStackIndex)
                        {
                            ObjectPlacementBoxStack possiblyOverlappingStack = possiblyOverlappingSegment.GetStackByIndex(possiblyOverlappingStackIndex);
                            if (IsStackOverlappedBy(possiblyOverlappedStack, possiblyOverlappingStack))
                            {
                                overlappedStacks.Add(possiblyOverlappedStack);
                            }
                        }
                    }
                }
            }

            return(overlappedStacks);
        }
        public Vector3 GetNormalizedBasePositionConnectionVectorTo(ObjectPlacementBoxStack stack)
        {
            Vector3 connectionVector = GetBasePositionConnectionVectorTo(stack);

            connectionVector.Normalize();

            return(connectionVector);
        }
        public Vector3 GetBasePositionConnectionVectorTo(ObjectPlacementBoxStack stack)
        {
            Plane   basePlane             = GetBasePlane();
            Vector3 projectedThisBasePos  = basePlane.ProjectPoint(BasePosition);
            Vector3 projectedStackBasePos = basePlane.ProjectPoint(stack.BasePosition);

            return(projectedStackBasePos - projectedThisBasePos);
        }
示例#5
0
        private void CreateNewStackAtEndOfSegment()
        {
            var newStack = new ObjectPlacementBoxStack();

            newStack.SetRotation(_stackRotation);
            newStack.SetBoxSize(_boxSize);
            newStack.SetGrowDirection(_growAxis);
            newStack.SetBasePosition(CalculateStackBasePositionToSitAtEndOfSegment());
            newStack.SetPaddingAlongGrowDirection(_paddingAlongStackGrowDirection);
            newStack.GrowUpwards(1);

            _stacks.Add(newStack);
        }
        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);
                }
            }
        }
示例#8
0
        public void DetectTileConnectionTypesForAllOccupiedCells()
        {
            ObjectPlacementBoxStack firstStackInFirstPathSegment = _path.GetSegmentByIndex(0).GetStackByIndex(0);

            foreach (var pair in _occupiedCells)
            {
                ObjectPlacementPathTileConnectionGridCell tileConnectionGridCell = pair.Value;

                int numberOfNeighbours = tileConnectionGridCell.NumberOfNeighbours;
                if (numberOfNeighbours == 0)
                {
                    tileConnectionGridCell.TileConnectionType = ObjectPlacementPathTileConnectionType.Begin;
                }
                else if (numberOfNeighbours == 1)
                {
                    if (tileConnectionGridCell.TileConnectionStack == firstStackInFirstPathSegment)
                    {
                        tileConnectionGridCell.TileConnectionType = ObjectPlacementPathTileConnectionType.Begin;
                    }
                    else
                    {
                        tileConnectionGridCell.TileConnectionType = ObjectPlacementPathTileConnectionType.End;
                    }
                }
                else if (numberOfNeighbours == 2)
                {
                    if (tileConnectionGridCell.HasLeftAndRightNeighbours() || tileConnectionGridCell.HasForwardAndBackNeightbours())
                    {
                        tileConnectionGridCell.TileConnectionType = ObjectPlacementPathTileConnectionType.Forward;
                    }
                    else
                    {
                        tileConnectionGridCell.TileConnectionType = ObjectPlacementPathTileConnectionType.Turn;
                    }
                }
                else if (numberOfNeighbours == 3)
                {
                    tileConnectionGridCell.TileConnectionType = ObjectPlacementPathTileConnectionType.TJunction;
                }
                else
                {
                    tileConnectionGridCell.TileConnectionType = ObjectPlacementPathTileConnectionType.Cross;
                }
            }
        }
示例#9
0
        private static bool IsStackOverlappedBy(ObjectPlacementBoxStack possiblyOveralppedStack, ObjectPlacementBoxStack possiblyOverlappingStack)
        {
            bool stacksAreAligned = possiblyOveralppedStack.UpAxis.IsAlignedWith(possiblyOverlappingStack.UpAxis);

            if (!stacksAreAligned)
            {
                return(false);
            }

            Plane   stackBasePlane     = possiblyOveralppedStack.GetBasePlane();
            Vector3 basePositionVector = stackBasePlane.ProjectPoint(possiblyOverlappingStack.BasePosition) - stackBasePlane.ProjectPoint(possiblyOveralppedStack.BasePosition);

            if (basePositionVector.magnitude < 1e-3f)
            {
                return(true);
            }

            return(false);
        }
示例#10
0
        public List <ObjectPlacementPathTileConnectionGridCell> Detect(ObjectPlacementPath path, float tileXZSize)
        {
            _tileXZSize = tileXZSize;

            List <ObjectPlacementBoxStackSegment> allPathSegments = path.GetAllSegments();

            if (allPathSegments.Count == 0)
            {
                return(new List <ObjectPlacementPathTileConnectionGridCell>());
            }

            // Create the grid cell instances which are occupied by tiles
            Vector3 gridOrigin         = path.ExtensionPlane.ProjectPoint(allPathSegments[0].GetStackByIndex(0).BasePosition);
            var     tileConnectionGrid = new ObjectPlacementPathTileConnectionGrid(_tileXZSize, gridOrigin, path);

            foreach (ObjectPlacementBoxStackSegment segment in allPathSegments)
            {
                for (int stackIndex = 0; stackIndex < segment.NumberOfStacks; ++stackIndex)
                {
                    ObjectPlacementBoxStack stack = segment.GetStackByIndex(stackIndex);
                    if (stack.IsOverlappedByAnotherStack)
                    {
                        continue;
                    }

                    var tileConnectionGridCell = new ObjectPlacementPathTileConnectionGridCell(tileConnectionGrid.CalculateCellIndicesFromPosition(stack.BasePosition), tileConnectionGrid);
                    tileConnectionGridCell.TileConnectionSegment = segment;
                    tileConnectionGridCell.TileConnectionStack   = stack;
                    tileConnectionGridCell.TileConnectionPath    = path;

                    if (!tileConnectionGrid.IsCellOccupied(tileConnectionGridCell.CellIndices))
                    {
                        tileConnectionGrid.AddCell(tileConnectionGridCell);
                    }
                }
            }

            tileConnectionGrid.EstablishCellNeighbours();
            tileConnectionGrid.DetectTileConnectionTypesForAllOccupiedCells();

            return(tileConnectionGrid.OccupiedTileConnectionCells);
        }
示例#11
0
        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>());
            }
        }
示例#12
0
        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);
                            }
                        }
                    }
                }
            }
        }
示例#13
0
        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);
        }
示例#14
0
        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);
        }
示例#15
0
        public List <ObjectPlacementPathTileConnectionGridCell> CreateAndReturnAutofillTileConnectionCells()
        {
            ObjectPlacementPathTileConnectionSettings tileConnectionSettings = _path.Settings.TileConnectionSettings;

            if (!tileConnectionSettings.DoesAutofillTileConnectionHavePrefabAssociated())
            {
                return(new List <ObjectPlacementPathTileConnectionGridCell>());
            }

            Plane       pathExtensionPlane        = _path.ExtensionPlane;
            OrientedBox autofillPrefabOrientedBox = tileConnectionSettings.GetSettingsForTileConnectionType(ObjectPlacementPathTileConnectionType.Autofill).Prefab.UnityPrefab.GetHierarchyWorldOrientedBox();
            Vector3     autofillStackBoxSize      = new Vector3(_cellXZSize, autofillPrefabOrientedBox.ScaledSize.y, _cellXZSize);
            Quaternion  autofillStackRotation     = Quaternion.LookRotation(_path.ExtensionPlaneLookAxis, pathExtensionPlane.normal);

            bool[,] cellAutofillFlags = new bool[NumberOfCellsOnX, NumberOfCellsOnZ];

            // We will first set all occupied cells to true
            foreach (var pair in _occupiedCells)
            {
                cellAutofillFlags[pair.Key.XIndex - MinCellIndexX, pair.Key.ZIndex - MinCellIndexZ] = true;
            }

            var autofillGridCells = new List <ObjectPlacementPathTileConnectionGridCell>(NumberOfCellsOnX * NumberOfCellsOnZ);

            for (int z = MinCellIndexZ; z <= MaxCellIndexZ; ++z)
            {
                for (int x = MinCellIndexX; x <= MaxCellIndexX; ++x)
                {
                    if (cellAutofillFlags[x - MinCellIndexX, z - MinCellIndexZ])
                    {
                        continue;
                    }

                    var traversedIndices = new HashSet <ObjectPlacementPathTileConnectionGridCellIndices>();
                    if (DetectCellsWhichLeadOutsideOfGridRecurse(cellAutofillFlags, x, z, traversedIndices))
                    {
                        foreach (ObjectPlacementPathTileConnectionGridCellIndices indices in traversedIndices)
                        {
                            cellAutofillFlags[indices.XIndex - MinCellIndexX, indices.ZIndex - MinCellIndexZ] = true;
                        }
                    }

                    if (!cellAutofillFlags[x - MinCellIndexX, z - MinCellIndexZ])
                    {
                        var autofillGridCell = new ObjectPlacementPathTileConnectionGridCell(new ObjectPlacementPathTileConnectionGridCellIndices(x, z), this);
                        autofillGridCells.Add(autofillGridCell);

                        AddCell(autofillGridCell);

                        var tileConnectionStack = new ObjectPlacementBoxStack();
                        tileConnectionStack.SetBoxSize(autofillStackBoxSize);
                        tileConnectionStack.SetRotation(autofillStackRotation);
                        tileConnectionStack.SetBasePosition(CalculateCellPosition(x, z));
                        tileConnectionStack.PlaceOnPlane(pathExtensionPlane);
                        tileConnectionStack.GrowUpwards(1);

                        autofillGridCell.TileConnectionStack = tileConnectionStack;
                        autofillGridCell.TileConnectionPath  = _path;
                        autofillGridCell.TileConnectionType  = ObjectPlacementPathTileConnectionType.Autofill;
                    }
                }
            }

            return(autofillGridCells);
        }
        public Quaternion Calculate(ObjectPlacementPathTileConnectionGridCell tileConnectionGridCell)
        {
            ObjectPlacementPath path = tileConnectionGridCell.TileConnectionPath;
            ObjectPlacementPathTileConnectionSettings tileConnectionSettings = path.Settings.TileConnectionSettings;
            Plane extensionPlane = path.ExtensionPlane;
            ObjectPlacementBoxStackSegment tileConnectionSegment = tileConnectionGridCell.TileConnectionSegment;
            ObjectPlacementBoxStack        tileConnectionStack   = tileConnectionGridCell.TileConnectionStack;

            bool       usingSprites           = tileConnectionSettings.UsesSprites();
            float      yAxisRotationInDegrees = ObjectPlacementPathTileConnectionYAxisRotations.GetAngleInDegrees(tileConnectionSettings.GetSettingsForTileConnectionType(tileConnectionGridCell.TileConnectionType).YAxisRotation);
            Quaternion yAxisRotation          = Quaternion.AngleAxis(yAxisRotationInDegrees, extensionPlane.normal);

            Quaternion defaultRotation = Quaternion.LookRotation(path.ExtensionPlaneLookAxis, extensionPlane.normal);

            if (usingSprites)
            {
                defaultRotation = Quaternion.LookRotation(extensionPlane.normal, path.ExtensionPlaneLookAxis);
            }

            ObjectPlacementPathTileConnectionType tileConnectionType = tileConnectionGridCell.TileConnectionType;

            if (tileConnectionType == ObjectPlacementPathTileConnectionType.Autofill)
            {
                return(yAxisRotation * defaultRotation);
            }
            else
            if (tileConnectionType == ObjectPlacementPathTileConnectionType.Begin)
            {
                if (tileConnectionGridCell.NumberOfNeighbours == 0)
                {
                    return(yAxisRotation * defaultRotation);
                }
                else
                {
                    ObjectPlacementBoxStack neighbour = tileConnectionGridCell.GetFirstNeighbour().TileConnectionStack;
                    Vector3 toNeighbour = tileConnectionStack.GetNormalizedBasePositionConnectionVectorTo(neighbour);

                    if (usingSprites)
                    {
                        return(yAxisRotation * Quaternion.LookRotation(extensionPlane.normal, toNeighbour));
                    }
                    return(yAxisRotation * Quaternion.LookRotation(toNeighbour, extensionPlane.normal));
                }
            }
            else if (tileConnectionType == ObjectPlacementPathTileConnectionType.End)
            {
                ObjectPlacementBoxStack neighbour = tileConnectionGridCell.GetFirstNeighbour().TileConnectionStack;
                Vector3 toEndTile = neighbour.GetNormalizedBasePositionConnectionVectorTo(tileConnectionStack);

                if (usingSprites)
                {
                    return(yAxisRotation * Quaternion.LookRotation(extensionPlane.normal, toEndTile));
                }
                return(yAxisRotation * Quaternion.LookRotation(toEndTile, extensionPlane.normal));
            }
            else
            if (tileConnectionType == ObjectPlacementPathTileConnectionType.Cross)
            {
                return(yAxisRotation * defaultRotation);
            }
            else
            if (tileConnectionType == ObjectPlacementPathTileConnectionType.TJunction)
            {
                ObjectPlacementBoxStack baseOfTJunction = null;
                if (tileConnectionGridCell.RightNeighbour != null && tileConnectionGridCell.LeftNeighbour != null)
                {
                    baseOfTJunction = tileConnectionGridCell.ForwardNeighbour != null ? tileConnectionGridCell.ForwardNeighbour.TileConnectionStack : tileConnectionGridCell.BackNeighbour.TileConnectionStack;
                }
                else
                {
                    baseOfTJunction = tileConnectionGridCell.RightNeighbour != null ? tileConnectionGridCell.RightNeighbour.TileConnectionStack : tileConnectionGridCell.LeftNeighbour.TileConnectionStack;
                }

                Vector3 toTJunction = baseOfTJunction.GetNormalizedBasePositionConnectionVectorTo(tileConnectionStack);

                if (usingSprites)
                {
                    return(yAxisRotation * Quaternion.LookRotation(extensionPlane.normal, toTJunction));
                }
                return(yAxisRotation * Quaternion.LookRotation(toTJunction, extensionPlane.normal));
            }
            else
            if (tileConnectionType == ObjectPlacementPathTileConnectionType.Forward)
            {
                if (tileConnectionSegment.NumberOfStacks == 1)
                {
                    if (tileConnectionGridCell.HasForwardAndBackNeightbours())
                    {
                        ObjectPlacementBoxStack forwardNeighbour = tileConnectionGridCell.ForwardNeighbour.TileConnectionStack;
                        ObjectPlacementBoxStack backNeighbour    = tileConnectionGridCell.BackNeighbour.TileConnectionStack;
                        Vector3 toForwardNeighbour = backNeighbour.GetNormalizedBasePositionConnectionVectorTo(forwardNeighbour);

                        if (usingSprites)
                        {
                            return(yAxisRotation * Quaternion.LookRotation(extensionPlane.normal, toForwardNeighbour));
                        }
                        return(yAxisRotation * Quaternion.LookRotation(toForwardNeighbour, extensionPlane.normal));
                    }
                    else
                    {
                        ObjectPlacementBoxStack leftNeighbour  = tileConnectionGridCell.LeftNeighbour.TileConnectionStack;
                        ObjectPlacementBoxStack rightNeighbour = tileConnectionGridCell.RightNeighbour.TileConnectionStack;
                        Vector3 toRightNeighbour = leftNeighbour.GetNormalizedBasePositionConnectionVectorTo(rightNeighbour);

                        if (usingSprites)
                        {
                            return(yAxisRotation * Quaternion.LookRotation(extensionPlane.normal, toRightNeighbour));
                        }
                        return(yAxisRotation * Quaternion.LookRotation(toRightNeighbour, extensionPlane.normal));
                    }
                }
                else
                {
                    if (usingSprites)
                    {
                        return(yAxisRotation * Quaternion.LookRotation(extensionPlane.normal, tileConnectionSegment.ExtensionDirection));
                    }
                    return(yAxisRotation * Quaternion.LookRotation(tileConnectionSegment.ExtensionDirection, extensionPlane.normal));
                }
            }
            else
            {
                ObjectPlacementBoxStack firstNeighbour, secondNeighbour;
                if (tileConnectionGridCell.RightNeighbour != null)
                {
                    firstNeighbour  = tileConnectionGridCell.RightNeighbour.TileConnectionStack;
                    secondNeighbour = tileConnectionGridCell.ForwardNeighbour != null ? tileConnectionGridCell.ForwardNeighbour.TileConnectionStack : tileConnectionGridCell.BackNeighbour.TileConnectionStack;
                }
                else
                if (tileConnectionGridCell.LeftNeighbour != null)
                {
                    firstNeighbour  = tileConnectionGridCell.LeftNeighbour.TileConnectionStack;
                    secondNeighbour = tileConnectionGridCell.ForwardNeighbour != null ? tileConnectionGridCell.ForwardNeighbour.TileConnectionStack : tileConnectionGridCell.BackNeighbour.TileConnectionStack;
                }
                else
                if (tileConnectionGridCell.ForwardNeighbour != null)
                {
                    firstNeighbour  = tileConnectionGridCell.ForwardNeighbour.TileConnectionStack;
                    secondNeighbour = tileConnectionGridCell.RightNeighbour != null ? tileConnectionGridCell.RightNeighbour.TileConnectionStack : tileConnectionGridCell.LeftNeighbour.TileConnectionStack;
                }
                else
                {
                    firstNeighbour  = tileConnectionGridCell.BackNeighbour.TileConnectionStack;
                    secondNeighbour = tileConnectionGridCell.RightNeighbour != null ? tileConnectionGridCell.RightNeighbour.TileConnectionStack : tileConnectionGridCell.LeftNeighbour.TileConnectionStack;
                }

                Vector3 tileLook, tileRight;
                tileLook  = firstNeighbour.GetNormalizedBasePositionConnectionVectorTo(tileConnectionStack);
                tileRight = tileConnectionStack.GetNormalizedBasePositionConnectionVectorTo(secondNeighbour);

                Vector3 tileUp = Vector3.Cross(tileLook, tileRight);
                if (Vector3.Dot(tileUp, extensionPlane.normal) < 0.0f)
                {
                    tileLook = -tileRight;
                }

                if (usingSprites)
                {
                    return(yAxisRotation * Quaternion.LookRotation(extensionPlane.normal, tileLook));
                }
                return(yAxisRotation * Quaternion.LookRotation(tileLook, extensionPlane.normal));
            }
        }
示例#17
0
        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);
        }
示例#18
0
 private Vector3 CalculateStackBasePositionToSitRightAfterStack(ObjectPlacementBoxStack afterStack)
 {
     return(afterStack.BasePosition + _extensionDirection * (GetBoxSizeAlongNormalizedDirection(_extensionDirection) + _paddingAlongExtensionDirection));
 }
示例#19
0
        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);
        }