123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650 |
- #if UNITY_EDITOR
- using UnityEngine;
- using UnityEditor;
- using System.Collections.Generic;
- namespace O3DWB
- {
- public class ObjectPlacementPathManualConstructionSession
- {
- #region Private Variables
- private ObjectPlacementPath _path;
- private ObjectPlacementPathSettings _pathSettings;
- private ObjectPlacementPathTileConnectionSettings _tileConnectionSettings;
- private List<ObjectPlacementPathTileConnectionGridCell> _tileConnectionGridCells;
- private ObjectPlacementPathManualConstructionSettings _manualConstructionSettings;
- private ObjectPlacementPathHeightAdjustmentSettings _heightAdjustmentSettings;
- private ObjectPlacementPathPaddingSettings _paddingSettings;
- private ObjectPlacementPathBorderSettings _borderSettings;
- private List<ObjectPlacementBoxStackSegment> _pathSegments;
- private ObjectPlacementExtensionPlane _pathExtensionPlane;
- private GameObject _startObject;
- private OrientedBox _startObjectHierarchyWorldOrientedBox;
- private float _tileConnectionXZSize;
- private ObjectPlacementPathManualHeightAdjuster _manualHeightAdjuster = new ObjectPlacementPathManualHeightAdjuster();
- private int _currentManualPathHeight = 1;
- private ObjectPlacementPathAutomaticRandomHeightAdjuster _automaticRandomHeightAdjuster = new ObjectPlacementPathAutomaticRandomHeightAdjuster();
- private ObjectPlacementPathAutomaticPatternHeightAdjuster _automaticPatternHeightAdjuster = new ObjectPlacementPathAutomaticPatternHeightAdjuster();
- private ObjectPlacementPathBorderApplyOperation _borderApplyOperation = new ObjectPlacementPathBorderApplyOperation();
- private ObjectPlacementPathTileConnectionDetector _tileConnectionDetector = new ObjectPlacementPathTileConnectionDetector();
- private PathNoTileConnectionsObjectPlacementDataCaculator _pathNoTileConnectionsObjectPlacementDataCalculator = new PathNoTileConnectionsObjectPlacementDataCaculator();
- private PathWithTileConnectionsObjectPlacementDataCalculator _pathWithTileConnectionsObjectPlacementDataCalculator = new PathWithTileConnectionsObjectPlacementDataCalculator();
- private bool _isActive = false;
- #endregion
- #region Private Properties
- private ObjectPlacementBoxStackSegment LastSegment { get { return _pathSegments.Count != 0 ? _pathSegments[_pathSegments.Count - 1] : null; } }
- private ObjectPlacementBoxStackSegment PenultimateSegment { get { return _pathSegments.Count > 1 ? _pathSegments[_pathSegments.Count - 2] : null; } }
- #endregion
- #region Public Properties
- public bool IsActive { get { return _isActive; } }
- #endregion
- #region Public Methods
- public void SetData(ObjectPlacementPathManualConstructionSessionData sessionData)
- {
- if(!_isActive)
- {
- _path = sessionData.Path;
- _pathSegments = sessionData.PathSegments;
- _pathExtensionPlane = sessionData.PathExtensionPlane;
- _tileConnectionGridCells = sessionData.TileConnectionGridCells;
- _startObject = sessionData.StartObject;
- _startObjectHierarchyWorldOrientedBox = _startObject.GetHierarchyWorldOrientedBox();
- _pathSettings = _path.Settings;
- _tileConnectionSettings = _pathSettings.TileConnectionSettings;
- _manualConstructionSettings = _pathSettings.ManualConstructionSettings;
- _heightAdjustmentSettings = _manualConstructionSettings.HeightAdjustmentSettings;
- _paddingSettings = _manualConstructionSettings.PaddingSettings;
- _borderSettings = _manualConstructionSettings.BorderSettings;
- _pathNoTileConnectionsObjectPlacementDataCalculator.Path = _path;
- _pathWithTileConnectionsObjectPlacementDataCalculator.Path = _path;
- }
- }
- public void Begin()
- {
- if (CanBegin())
- {
- _isActive = true;
- _currentManualPathHeight = 1;
- _pathSegments.Clear();
- if (_tileConnectionSettings.UseTileConnections) EstablshTileConnectionXZSize();
- CreateFirst2Segments();
- }
- }
- public List<ObjectPlacementData> End()
- {
- if(_isActive)
- {
- _isActive = false;
- RemoveSegmentsWithNoStacks();
- if (_tileConnectionSettings.UseTileConnections) return _pathWithTileConnectionsObjectPlacementDataCalculator.Calculate();
- else return _pathNoTileConnectionsObjectPlacementDataCalculator.Calculate();
- }
- return new List<ObjectPlacementData>();
- }
- public void Cancel()
- {
- _isActive = false;
- }
- public void ManualRaisePath()
- {
- if (CanManualRaiseOrLowerPath())
- {
- _currentManualPathHeight = _manualHeightAdjuster.Raise(_path, _currentManualPathHeight);
- if (_borderSettings.UseBorders) _borderApplyOperation.ApplyBordersToAllPathSegments(_pathSegments, _borderSettings);
- }
- }
- public void ManualLowerPath()
- {
- if (CanManualRaiseOrLowerPath())
- {
- _currentManualPathHeight = _manualHeightAdjuster.Lower(_path, _currentManualPathHeight);
- if (_borderSettings.UseBorders) _borderApplyOperation.ApplyBordersToAllPathSegments(_pathSegments, _borderSettings);
- }
- }
- public void UpdateForMouseMoveEvent()
- {
- if (_isActive) ExtendOrShrinkPathAlongExtensionPlane();
- }
- public void Attach2NewSegments()
- {
- if(_isActive)
- {
- RemoveSegmentsWithNoStacks();
- // First create the 2 new segments which will replace the current penultimate and last segments
- ObjectPlacementBoxStackSegment oldLastSegment = LastSegment;
- ObjectPlacementBoxStackSegment newPenultimateSegment = CreateNewSegment();
- CreateNewSegment();
- // We will want the first stack in the new penultimate segment to replace the last stack in 'LastSegment'.
- // Otherwise, when this function is called, an additional box will suddenly appear in the scene apparently
- // out of nowhere and it doesn't look very good. Not to mention that it can be quite confusing :).
- oldLastSegment.Shrink(1);
- newPenultimateSegment.Extend(1);
- newPenultimateSegment.SetExtensionDirection(oldLastSegment.ExtensionDirection);
- if (CanRotateObjectsToFollowPath())
- {
- newPenultimateSegment.SetRotationForAllStacks(oldLastSegment.StackRotation);
- MakeSegmentFollowPath(LastSegment);
- }
- newPenultimateSegment.ConnectFirstStackToLastStackInSegment(oldLastSegment, CalculateSegmentConnectionOffset(newPenultimateSegment, oldLastSegment));
- AdjustHeightForEntireSegment(PenultimateSegment);
- UpdateStackOverlapDataForLast2Segments();
- if (_borderSettings.UseBorders) _borderApplyOperation.ApplyBordersToAllPathSegments(_pathSegments, _borderSettings);
- if (_tileConnectionSettings.UseTileConnections) UpdateTileConnectionInformation();
- }
- }
- public void RemoveLast2Segments()
- {
- if(_isActive)
- {
- _pathSegments.RemoveLast();
- _pathSegments.RemoveLast();
- if (_pathSegments.Count == 0) End();
- }
- }
- public void OnExcludeCornersSettingsChanged()
- {
- if (_isActive && !_tileConnectionSettings.UseTileConnections)
- {
- ReconnectAllSegments();
- HandleStackOverlapForAllStacksInAllSegments();
- if (_borderSettings.UseBorders) _borderApplyOperation.ApplyBordersToAllPathSegments(_pathSegments, _borderSettings);
- SceneView.RepaintAll();
- }
- }
- public void OnRotateObjectsToFollowPathSettingsChanged()
- {
- if (_isActive && !_tileConnectionSettings.UseTileConnections)
- {
- AdjustRotationForAllSegments();
- ReconnectAllSegments();
- HandleStackOverlapForAllStacksInAllSegments();
- if (_borderSettings.UseBorders) _borderApplyOperation.ApplyBordersToAllPathSegments(_pathSegments, _borderSettings);
- SceneView.RepaintAll();
- }
- }
- public void OnPaddingSettingsChanged()
- {
- if (_isActive && !_tileConnectionSettings.UseTileConnections)
- {
- ObjectPlacementBoxStackSegmentActions.SetPaddingForSegments(_pathSegments, _paddingSettings.PaddingAlongExtensionPlane, _paddingSettings.PaddingAlongGrowDirection);
- ReconnectAllSegments();
- HandleStackOverlapForAllStacksInAllSegments();
- if (_borderSettings.UseBorders) _borderApplyOperation.ApplyBordersToAllPathSegments(_pathSegments, _borderSettings);
- SceneView.RepaintAll();
- }
- }
- public void OnBorderSettingsChanged()
- {
- if (_isActive)
- {
- if (_borderSettings.UseBorders) _borderApplyOperation.ApplyBordersToAllPathSegments(_pathSegments, _borderSettings);
- else ObjectPlacementBoxStackSegmentActions.ClearHideFlagsForAllStacksInSegments(_pathSegments, ObjectPlacementBoxHideFlags.PathApplyBorders);
- SceneView.RepaintAll();
- }
- }
- public void OnHeightAdjustmentModeChanged()
- {
- if (_isActive)
- {
- AdjustHeightForAllStacksInPath();
- if (_borderSettings.UseBorders) _borderApplyOperation.ApplyBordersToAllPathSegments(_pathSegments, _borderSettings);
- SceneView.RepaintAll();
- }
- }
- public void OnAutomaticRandomHeightAdjustmentSettingsChanged()
- {
- if (_isActive)
- {
- AdjustHeightForAllStacksInPath();
- if (_borderSettings.UseBorders) _borderApplyOperation.ApplyBordersToAllPathSegments(_pathSegments, _borderSettings);
- SceneView.RepaintAll();
- }
- }
- public void OnAutomaticPatternHeightAdjustmentSettingsChanged()
- {
- if (_isActive)
- {
- AdjustHeightForAllStacksInPath();
- if (_borderSettings.UseBorders) _borderApplyOperation.ApplyBordersToAllPathSegments(_pathSegments, _borderSettings);
- SceneView.RepaintAll();
- }
- }
- public void OnHeightPatternRemoved()
- {
- if(_isActive && _heightAdjustmentSettings.HeightAdjustmentMode == ObjectPlacementPathHeightAdjustmentMode.AutomaticPattern)
- {
- ObjectPlacementPathHeightPattern activePattern = ObjectPlacementPathHeightPatternDatabase.Get().ActivePattern;
- if (activePattern != null)
- {
- AdjustHeightForAllStacksInPath();
- if (_borderSettings.UseBorders) _borderApplyOperation.ApplyBordersToAllPathSegments(_pathSegments, _borderSettings);
- }
- else
- {
- Debug.LogWarning("There is no height pattern currently available. Path construction was cancelled.");
- End();
- }
-
- SceneView.RepaintAll();
- }
- }
- public void OnNewHeightPatternWasActivated()
- {
- if (_isActive && _heightAdjustmentSettings.HeightAdjustmentMode == ObjectPlacementPathHeightAdjustmentMode.AutomaticPattern)
- {
- AdjustHeightForAllStacksInPath();
- if (_borderSettings.UseBorders) _borderApplyOperation.ApplyBordersToAllPathSegments(_pathSegments, _borderSettings);
- SceneView.RepaintAll();
- }
- }
- #endregion
- #region Private Methods
- private bool CanBegin()
- {
- return !_isActive && IsSessionDataReady();
- }
- private bool CanRotateObjectsToFollowPath()
- {
- return _manualConstructionSettings.RotateObjectsToFollowPath && !_tileConnectionSettings.UseTileConnections;
- }
- private bool CanUsePadding()
- {
- return !_tileConnectionSettings.UseTileConnections;
- }
- private bool CanExcludeCorners()
- {
- return _manualConstructionSettings.ExcludeCorners && !_tileConnectionSettings.UseTileConnections;
- }
- private bool CanManualRaiseOrLowerPath()
- {
- return _isActive && _heightAdjustmentSettings.HeightAdjustmentMode == ObjectPlacementPathHeightAdjustmentMode.Manual;
- }
- private void EstablshTileConnectionXZSize()
- {
- if(_pathSettings.TileConnectionSettings.UsesSprites())
- {
- Vector3 scaledSize = _startObjectHierarchyWorldOrientedBox.ScaledSize;
- _tileConnectionXZSize = (scaledSize.x + scaledSize.y) * 0.5f;
- _pathWithTileConnectionsObjectPlacementDataCalculator.TileConnectionXZSize = _tileConnectionXZSize;
- }
- else
- {
- Vector3 scaledSize = _startObjectHierarchyWorldOrientedBox.ScaledSize;
- _tileConnectionXZSize = (scaledSize.x + scaledSize.z) * 0.5f;
- _pathWithTileConnectionsObjectPlacementDataCalculator.TileConnectionXZSize = _tileConnectionXZSize;
- }
- }
- private bool IsSessionDataReady()
- {
- bool isReady = (_path != null && _pathSegments != null && _startObject != null && _pathExtensionPlane != null);
- if (!isReady) return false;
- if (_heightAdjustmentSettings.HeightAdjustmentMode == ObjectPlacementPathHeightAdjustmentMode.AutomaticPattern &&
- ObjectPlacementPathHeightPatternDatabase.Get().ActivePattern == null)
- {
- Debug.LogWarning("Can not begin path construction because the automatic pattern height adjustment mode is selected but there is no active pattern.");
- isReady = false;
- }
- if (_tileConnectionSettings.UseTileConnections && !_tileConnectionSettings.DoAllTileConnectionsHavePrefabAssociated(true))
- {
- Debug.LogWarning("You are using tile connections, but not all tiles have an associated prefab. Please associate a prefab with each tile in order to being path construction.");
- isReady = false;
- }
- OrientedBox hierarchyWorldOrientedBox = _startObject.GetHierarchyWorldOrientedBox();
- float absSizeRight = hierarchyWorldOrientedBox.GetRotatedAndScaledSizeAlongDirection(_pathExtensionPlane.RightAxis);
- float absSizeLook = hierarchyWorldOrientedBox.GetRotatedAndScaledSizeAlongDirection(_pathExtensionPlane.LookAxis);
- if(absSizeRight < 1e-4f || absSizeLook < 1e-4f)
- {
- Debug.LogWarning("Can not begin path construction because the object has a 0 size component along the extention plane axes.");
- isReady = false;
- }
- return isReady;
- }
- private void RemoveSegmentsWithNoStacks()
- {
- _pathSegments.RemoveAll(item => item.NumberOfStacks == 0);
- }
- private void CreateFirst2Segments()
- {
- CreateNewSegment();
- CreateNewSegment();
- Vector3 camLookAxis = SceneViewCamera.Camera.transform.forward;
- Vector3 penultimateSegmentDir = _pathExtensionPlane.LookAxis;
- if(Mathf.Abs(Vector3.Dot(camLookAxis, _pathExtensionPlane.LookAxis)) <
- Mathf.Abs(Vector3.Dot(camLookAxis, _pathExtensionPlane.RightAxis)))
- {
- penultimateSegmentDir = _pathExtensionPlane.RightAxis;
- }
- PenultimateSegment.SetFirstStackBasePosition(_startObjectHierarchyWorldOrientedBox.Center);
- PenultimateSegment.SetExtensionDirection(penultimateSegmentDir);
- PenultimateSegment.Extend(1);
- AdjustHeightForEntireSegment(PenultimateSegment);
- }
- private ObjectPlacementBoxStackSegment CreateNewSegment()
- {
- var newSegment = new ObjectPlacementBoxStackSegment();
- newSegment.SetRotationForAllStacks(_startObjectHierarchyWorldOrientedBox.Rotation);
- newSegment.SetBoxSizeForAllStacks(GetSegmentBoxSize());
- newSegment.SetExtensionDirection(_pathExtensionPlane.LookAxis);
- newSegment.SetGrowAxis(_pathExtensionPlane.UpAxis);
-
- if (CanUsePadding())
- {
- newSegment.SetPaddingAlongStackGrowDirection(_paddingSettings.PaddingAlongGrowDirection);
- newSegment.SetPaddingAlongExtensionDirection(_paddingSettings.PaddingAlongExtensionPlane);
- }
- _pathSegments.Add(newSegment);
- return newSegment;
- }
- private Vector3 GetSegmentBoxSize()
- {
- if (_tileConnectionSettings.UseTileConnections)
- {
- if (_pathSettings.TileConnectionSettings.UsesSprites()) return new Vector3(_tileConnectionXZSize, _tileConnectionXZSize, _startObjectHierarchyWorldOrientedBox.ScaledSize.z);
- return new Vector3(_tileConnectionXZSize, _startObjectHierarchyWorldOrientedBox.ScaledSize.y, _tileConnectionXZSize);
- }
- else return _startObjectHierarchyWorldOrientedBox.ScaledSize;
- }
- private void ExtendOrShrinkPathAlongExtensionPlane()
- {
- // Construct a new extension plane in order to take into account the block's Y offset. Otherwise,
- // it becomes harder to control the block extension.
- Plane extensionPlane = _pathExtensionPlane.Plane;
- Vector3 pointOnBlockExtensionPlane = _pathExtensionPlane.PlaneQuad.Center;
- pointOnBlockExtensionPlane += extensionPlane.normal * _manualConstructionSettings.OffsetAlongGrowDirection;
- extensionPlane = new Plane(extensionPlane.normal, pointOnBlockExtensionPlane);
-
- // We will need to adjust the last 2 segments using the intersection point between the mouse cursor
- // and the extension plane, so the first thing that we will do is find this intersection point. This
- // intersection point will essentially help us visualize a triangle whose adjacent sides represent the
- // extension directions of the 2 segments. The hypotenuse represents the vector which goes from the
- // first stack in the penultimate segment to the last stack in the last segment.
- Vector3 extensionPlaneIntersectionPoint;
- if (MouseCursor.Instance.IntersectsPlane(extensionPlane, out extensionPlaneIntersectionPoint))
- {
- // We will need to adjust the number of stacks in each segment based on the length of the triangle's
- // adjacent sides. We will start with the penultimate segment and construct a vector which goes from
- // the first stack in the penultimate segment to the intersection point with the plane. Projecting this
- // vector on the extension direction of the penultimate segment will give us the length of the adjacent
- // side. This length is then used to calculate the number of stacks in the penultimate segment.
- Vector3 toIntersectionPoint = extensionPlaneIntersectionPoint - _pathExtensionPlane.Plane.ProjectPoint(PenultimateSegment.FirstStackBasePosition);
-
- if (_pathSegments.Count == 2 && PenultimateSegment.NumberOfStacks == 1 && !_pathSettings.TileConnectionSettings.UseTileConnections)
- {
- var extensionPlaneAxes = new List<Vector3> { _pathExtensionPlane.RightAxis, -_pathExtensionPlane.RightAxis, _pathExtensionPlane.LookAxis, -_pathExtensionPlane.LookAxis };
- int mostAlignedVector = toIntersectionPoint.GetIndexOfMostAlignedVector(extensionPlaneAxes);
- if (mostAlignedVector >= 0)
- {
- PenultimateSegment.SetExtensionDirection(extensionPlaneAxes[mostAlignedVector]);
- }
- }
- else if (!PenultimateSegment.ExtensionDirection.IsPointingInSameGeneralDirection(toIntersectionPoint)) PenultimateSegment.ReverseExtensionDirection();
- // Calculate the number of stacks in the penultimate segment
- float adjacentSideLength = PenultimateSegment.ExtensionDirection.GetAbsDot(toIntersectionPoint);
- float numberOfStacks = adjacentSideLength / (PenultimateSegment.GetBoxSizeAlongNormalizedDirection(PenultimateSegment.ExtensionDirection) + _paddingSettings.PaddingAlongExtensionPlane);
- int integerNumberOfStacks = (int)numberOfStacks + 1;
- int currentNumberOfStacks = PenultimateSegment.NumberOfStacks;
- int deltaNumberOfStacks = integerNumberOfStacks - currentNumberOfStacks;
- if (deltaNumberOfStacks > 0 || (deltaNumberOfStacks == 0 && _heightAdjustmentSettings.HeightAdjustmentMode == ObjectPlacementPathHeightAdjustmentMode.AutomaticPattern))
- {
- PenultimateSegment.Extend(deltaNumberOfStacks);
- AdjustHeightForStackRangeInSegment(PenultimateSegment, currentNumberOfStacks);
- }
- else PenultimateSegment.Shrink(Mathf.Abs(deltaNumberOfStacks));
- // We will have to do the same thing for the last segment. However, this time we will first detect its extension direction. The extension direction
- // is one of the extension plane's axes (right or look). The one we choose has to be the one which is not aligned with the penultimate segment's
- // extension direction (i.e. it has to be perpendicular to it).
- toIntersectionPoint = extensionPlaneIntersectionPoint - _pathExtensionPlane.Plane.ProjectPoint(PenultimateSegment.LastStackBasePosition);
- Vector3 extensionPlaneRight = _pathExtensionPlane.RightAxis;
- Vector3 extensionPlaneLook = _pathExtensionPlane.LookAxis;
- Vector3 lastSegmentExtensionDirection = extensionPlaneRight;
- if (lastSegmentExtensionDirection.IsAlignedWith(PenultimateSegment.ExtensionDirection)) lastSegmentExtensionDirection = extensionPlaneLook;
- if (!lastSegmentExtensionDirection.IsPointingInSameGeneralDirection(toIntersectionPoint)) lastSegmentExtensionDirection *= -1.0f;
- LastSegment.SetExtensionDirection(lastSegmentExtensionDirection);
- // Calculate the number of stacks in the segment.
- // Note: We no longer add 1 to the integer number of stacks because that stack is actually the last stack in the penultimate segment
- numberOfStacks = toIntersectionPoint.magnitude / (LastSegment.GetBoxSizeAlongNormalizedDirection(LastSegment.ExtensionDirection) + _paddingSettings.PaddingAlongExtensionPlane);
- integerNumberOfStacks = (int)numberOfStacks;
- currentNumberOfStacks = LastSegment.NumberOfStacks;
- deltaNumberOfStacks = integerNumberOfStacks - currentNumberOfStacks;
- if (deltaNumberOfStacks > 0 || (deltaNumberOfStacks == 0 && _heightAdjustmentSettings.HeightAdjustmentMode == ObjectPlacementPathHeightAdjustmentMode.AutomaticPattern))
- {
- LastSegment.Extend(deltaNumberOfStacks);
- AdjustHeightForStackRangeInSegment(LastSegment, currentNumberOfStacks);
- }
- else LastSegment.Shrink(Mathf.Abs(deltaNumberOfStacks));
- if (CanRotateObjectsToFollowPath()) MakeSegmentFollowPath(LastSegment);
- LastSegment.ConnectFirstStackToLastStackInSegment(PenultimateSegment, CalculateSegmentConnectionOffset(LastSegment, PenultimateSegment));
- UpdateStackOverlapDataForLast2Segments();
- if (_borderSettings.UseBorders) _borderApplyOperation.ApplyBordersToAllPathSegments(_pathSegments, _borderSettings);
- if (_tileConnectionSettings.UseTileConnections) UpdateTileConnectionInformation();
- SceneView.RepaintAll();
- }
- }
- private void MakeSegmentFollowPath(ObjectPlacementBoxStackSegment segment)
- {
- float angleFromFirstSegment = Vector3.Angle(_pathSegments[0].ExtensionDirection, segment.ExtensionDirection);
- Quaternion rotation = Quaternion.AngleAxis(angleFromFirstSegment, _pathExtensionPlane.Plane.normal);
- segment.SetRotationForAllStacks(rotation * _startObjectHierarchyWorldOrientedBox.Rotation);
- }
- private Vector3 CalculateSegmentConnectionOffset(ObjectPlacementBoxStackSegment sourceSegment, ObjectPlacementBoxStackSegment destinationSegment)
- {
- if (!CanExcludeCorners()) return CalculateSegmentConnectionOffsetForNoCornerExclusion(sourceSegment, destinationSegment);
- else
- {
- // Note: Corner exclusion is applied only if the 2 segments are perpendicular.
- if (sourceSegment.ExtensionDirection.IsPerpendicularTo(destinationSegment.ExtensionDirection)) return CalculateSegmentConnectionOffsetForCornerExclusion(sourceSegment, destinationSegment);
- else return CalculateSegmentConnectionOffsetForNoCornerExclusion(sourceSegment, destinationSegment);
- }
- }
- private Vector3 CalculateSegmentConnectionOffsetForNoCornerExclusion(ObjectPlacementBoxStackSegment sourceSegment, ObjectPlacementBoxStackSegment destinationSegment)
- {
- // No offset if the destination segment doesn't have any stacks
- if (destinationSegment.NumberOfStacks == 0) return Vector3.zero;
- bool srcPointsInSameDirAsDestination;
- bool srcExtensionDirAlignedWithDestDir = sourceSegment.ExtensionDirection.IsAlignedWith(destinationSegment.ExtensionDirection, out srcPointsInSameDirAsDestination);
- float multiplicationSign = 1.0f;
- if(srcExtensionDirAlignedWithDestDir)
- {
- if (!srcPointsInSameDirAsDestination) multiplicationSign *= -1.0f;
- }
- float destBoxSizeAlongDestExtensionDir = destinationSegment.GetBoxSizeAlongNormalizedDirection(destinationSegment.ExtensionDirection);
- float srcBoxSizeAlongDestExtensionDir = sourceSegment.GetBoxSizeAlongNormalizedDirection(destinationSegment.ExtensionDirection);
- Vector3 offsetAlongDestExtensionDir = destinationSegment.ExtensionDirection * (destBoxSizeAlongDestExtensionDir - srcBoxSizeAlongDestExtensionDir) * 0.5f;
- float destBoxSizeAlongSrcExtensionDir = destinationSegment.GetBoxSizeAlongNormalizedDirection(sourceSegment.ExtensionDirection);
- float srcBoxSizeAlongSrcExtensionDir = sourceSegment.GetBoxSizeAlongNormalizedDirection(sourceSegment.ExtensionDirection);
- Vector3 offsetAlongSourceExtensionDir = multiplicationSign * sourceSegment.ExtensionDirection * ((srcBoxSizeAlongSrcExtensionDir + destBoxSizeAlongSrcExtensionDir) * 0.5f + _paddingSettings.PaddingAlongExtensionPlane);
-
- return offsetAlongDestExtensionDir + offsetAlongSourceExtensionDir;
- }
- private Vector3 CalculateSegmentConnectionOffsetForCornerExclusion(ObjectPlacementBoxStackSegment sourceSegment, ObjectPlacementBoxStackSegment destinationSegment)
- {
- bool srcPointsInSameDirAsDestination;
- bool srcExtensionDirAlignedWithDestDir = sourceSegment.ExtensionDirection.IsAlignedWith(destinationSegment.ExtensionDirection, out srcPointsInSameDirAsDestination);
- float multiplicationSign = 1.0f;
- if (srcExtensionDirAlignedWithDestDir)
- {
- if (!srcPointsInSameDirAsDestination) multiplicationSign *= -1.0f;
- }
- float destBoxSizeAlongDestExtensionDir = destinationSegment.GetBoxSizeAlongNormalizedDirection(destinationSegment.ExtensionDirection);
- float srcBoxSizeAlongDestExtensionDir = sourceSegment.GetBoxSizeAlongNormalizedDirection(destinationSegment.ExtensionDirection);
- Vector3 offsetAlongDestExtensionDir = destinationSegment.ExtensionDirection * Mathf.Abs((destBoxSizeAlongDestExtensionDir + srcBoxSizeAlongDestExtensionDir) * 0.5f);
- float destBoxSizeAlongSrcExtensionDir = destinationSegment.GetBoxSizeAlongNormalizedDirection(sourceSegment.ExtensionDirection);
- float srcBoxSizeAlongSrcExtensionDir = sourceSegment.GetBoxSizeAlongNormalizedDirection(sourceSegment.ExtensionDirection);
- Vector3 offsetAlongSourceExtensionDir = multiplicationSign * sourceSegment.ExtensionDirection * (srcBoxSizeAlongSrcExtensionDir + destBoxSizeAlongSrcExtensionDir) * 0.5f;
- return offsetAlongDestExtensionDir + offsetAlongSourceExtensionDir;
- }
- private void AdjustHeightForEntireSegment(ObjectPlacementBoxStackSegment segment)
- {
- ObjectPlacementPathHeightAdjustmentMode heightAdjustmentMode = _heightAdjustmentSettings.HeightAdjustmentMode;
- if (heightAdjustmentMode == ObjectPlacementPathHeightAdjustmentMode.Manual) _manualHeightAdjuster.AdjustSegmentHeight(segment, _currentManualPathHeight);
- else if (heightAdjustmentMode == ObjectPlacementPathHeightAdjustmentMode.AutomaticRandom) _automaticRandomHeightAdjuster.AdjustSegmentHeight(segment, _heightAdjustmentSettings.AutomaticRandomHeightAdjustmentSettings);
- else _automaticPatternHeightAdjuster.AdjustSegmentHeight(segment, _pathSegments, _heightAdjustmentSettings.AutomaticPatternHeightAdjustmentSettings, ObjectPlacementPathHeightPatternDatabase.Get().ActivePattern);
- }
- private void AdjustHeightForStackRangeInSegment(ObjectPlacementBoxStackSegment segment, int indexOfFirstStackToAdjust)
- {
- ObjectPlacementPathHeightAdjustmentMode heightAdjustmentMode = _heightAdjustmentSettings.HeightAdjustmentMode;
- if (heightAdjustmentMode == ObjectPlacementPathHeightAdjustmentMode.Manual) _manualHeightAdjuster.AdjustSegmentHeight(segment, indexOfFirstStackToAdjust, _currentManualPathHeight);
- else if (heightAdjustmentMode == ObjectPlacementPathHeightAdjustmentMode.AutomaticRandom) _automaticRandomHeightAdjuster.AdjustSegmentHeight(segment, indexOfFirstStackToAdjust, _heightAdjustmentSettings.AutomaticRandomHeightAdjustmentSettings);
- else _automaticPatternHeightAdjuster.AdjustSegmentHeight(segment, _pathSegments, _heightAdjustmentSettings.AutomaticPatternHeightAdjustmentSettings, ObjectPlacementPathHeightPatternDatabase.Get().ActivePattern);
- }
- private void ReconnectAllSegments()
- {
- for(int segmentIndex = 1; segmentIndex < _pathSegments.Count; ++segmentIndex)
- {
- ObjectPlacementBoxStackSegment currentSegment = _pathSegments[segmentIndex];
- ObjectPlacementBoxStackSegment previousSegment = _pathSegments[segmentIndex - 1];
- currentSegment.ConnectFirstStackToLastStackInSegment(previousSegment, CalculateSegmentConnectionOffset(currentSegment, previousSegment));
- }
- }
- private void HandleStackOverlapForAllStacksInAllSegments()
- {
- for (int segmentIndex = 0; segmentIndex < _pathSegments.Count; ++segmentIndex)
- {
- _pathSegments[segmentIndex].MarkAllStacksAsNotOverlapped();
- ObjectPlacementBoxStackActions.MarkStacksAsOverlapped(ObjectPlacementPathOverlappedStackDetection.GetOverlappedStacksInSegment(segmentIndex, _pathSegments));
- }
- }
- private void AdjustRotationForAllSegments()
- {
- foreach(ObjectPlacementBoxStackSegment segment in _pathSegments)
- {
- if (_manualConstructionSettings.RotateObjectsToFollowPath)
- {
- if (_pathSegments.Count >= 2 && segment == _pathSegments[0] && segment.NumberOfStacks == 1 && _pathSegments[1].NumberOfStacks >= 1)
- {
- segment.LookStacksAlongDirection(_pathSegments[1].ExtensionDirection);
- }
- else segment.LookStacksAlongExtensionDirection();
- }
- else segment.LookStacksAlongDirection(_pathSegments[0].ExtensionDirection);
- }
- }
- private void AdjustHeightForAllStacksInPath()
- {
- if (_heightAdjustmentSettings.HeightAdjustmentMode == ObjectPlacementPathHeightAdjustmentMode.Manual) _manualHeightAdjuster.AdjustHeightForSegments(_pathSegments, _currentManualPathHeight);
- else if (_heightAdjustmentSettings.HeightAdjustmentMode == ObjectPlacementPathHeightAdjustmentMode.AutomaticRandom) _automaticRandomHeightAdjuster.AdjustHeightForSegments(_pathSegments, _heightAdjustmentSettings.AutomaticRandomHeightAdjustmentSettings);
- else _automaticPatternHeightAdjuster.AdjustHeightForAllSegmentsInPath(_pathSegments, _heightAdjustmentSettings.AutomaticPatternHeightAdjustmentSettings, ObjectPlacementPathHeightPatternDatabase.Get().ActivePattern);
- }
- private void UpdateTileConnectionInformation()
- {
- List<ObjectPlacementPathTileConnectionGridCell> tileConnectionGridCells = _tileConnectionDetector.Detect(_path, _tileConnectionXZSize);
- if (tileConnectionGridCells.Count == 0) return;
- _tileConnectionGridCells.Clear();
- _tileConnectionGridCells.AddRange(tileConnectionGridCells);
- bool usingSprites = _pathSettings.TileConnectionSettings.UsesSprites();
- List<OrientedBox> tileConnectionPrefabWorldOrientedBoxesExceptAutofill = PrefabQueries.GetHierarchyWorldOrientedBoxesForAllPrefabs(_tileConnectionSettings.GetAllTileConnectionPrefabs(true));
- foreach (ObjectPlacementPathTileConnectionGridCell tileConnectionGridCell in _tileConnectionGridCells)
- {
- ObjectPlacementPathTileConnectionTypeSettings tileConnectionTypeSettings = _tileConnectionSettings.GetSettingsForTileConnectionType(tileConnectionGridCell.TileConnectionType);
- tileConnectionGridCell.TileConnectionStack.SetBoxSize(GetTileConnectionSize(tileConnectionPrefabWorldOrientedBoxesExceptAutofill[(int)tileConnectionTypeSettings.TileConnectionType], usingSprites));
- tileConnectionGridCell.TileConnectionStack.PlaceOnPlane(_pathExtensionPlane.Plane);
- }
- }
- private Vector3 GetTileConnectionSize(OrientedBox tilePrefabOOBB, bool usingSprites)
- {
- Vector3 boxSize = GetSegmentBoxSize();
- if (usingSprites) boxSize.z = 0.0f;
- else boxSize.y = tilePrefabOOBB.ScaledSize.y;
- return boxSize;
- }
- private void UpdateStackOverlapDataForLast2Segments()
- {
- PenultimateSegment.MarkAllStacksAsNotOverlapped();
- LastSegment.MarkAllStacksAsNotOverlapped();
- ObjectPlacementBoxStackActions.MarkStacksAsOverlapped(ObjectPlacementPathOverlappedStackDetection.GetOverlappedStacksInSegment(_pathSegments.Count - 2, _pathSegments));
- ObjectPlacementBoxStackActions.MarkStacksAsOverlapped(ObjectPlacementPathOverlappedStackDetection.GetOverlappedStacksInSegment(_pathSegments.Count - 1, _pathSegments));
- }
- #endregion
- }
- }
- #endif
|