123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322 |
- #if UNITY_EDITOR
- using UnityEngine;
- using System.Collections.Generic;
- namespace O3DWB
- {
- public class ObjectPlacementBoxStack
- {
- #region Private Variables
- private Vector3 _growDirection;
- private bool _isGrowingDownwards = false;
- private Vector3 _basePosition = Vector3.zero;
- private Quaternion _rotation = Quaternion.identity;
- private TransformMatrix _rotationMatrix = TransformMatrix.GetIdentity();
- private float _paddingAlongGrowDirection = 0.0f;
- private ObjectPlacementBoxStackOverlapData _overlapData = new ObjectPlacementBoxStackOverlapData();
- private Vector3 _boxSize = Vector3.one;
- private List<ObjectPlacementBox> _boxes = new List<ObjectPlacementBox>();
- #endregion
- #region Public Properties
- public int NumberOfBoxes { get { return _boxes.Count; } }
- public Vector3 BasePosition { get { return _basePosition; } }
- public Quaternion Rotation { get { return _rotation; } }
- public bool IsOverlappedByAnotherStack { get { return _overlapData.IsOverlappedByAnotherStack; ; } set { _overlapData.IsOverlappedByAnotherStack = value; } }
- public TransformMatrix RotationMatrix { get { return _rotationMatrix; } }
- public Vector3 UpAxis { get { return _rotationMatrix.GetNormalizedUpAxis(); } }
- public Vector3 GrowDirection { get { return IsGrowingUpwards ? _growDirection : -_growDirection; } }
- public float PaddingAlongGrowDirection { get { return _paddingAlongGrowDirection; } }
- public bool IsGrowingUpwards { get { return !_isGrowingDownwards; } }
- public bool IsGrowingDownwards { get { return _isGrowingDownwards; } }
- public int Height { get { return NumberOfBoxes * (IsGrowingUpwards ? 1 : -1); } }
- public Vector3 BoxSize { get { return _boxSize; } }
- #endregion
- #region Constructors
- public ObjectPlacementBoxStack()
- {
- _growDirection = UpAxis;
- }
- #endregion
- #region Public Methods
- public List<OrientedBox> GetAllOrientedBoxes()
- {
- var allOrientedBoxes = new List<OrientedBox>();
- foreach (var box in _boxes) allOrientedBoxes.Add(box.OrientedBox);
- return allOrientedBoxes;
- }
- public ObjectPlacementBox GetBoxByIndex(int boxIndex)
- {
- return _boxes[boxIndex];
- }
- public Plane GetBasePlane()
- {
- Vector3 growDirection = GrowDirection;
- Vector3 pointOnPlane = BasePosition - growDirection * GetBoxSizeAlongNormalizedDirection(growDirection) * 0.5f;
- return new Plane(growDirection, pointOnPlane);
- }
- public float GetBoxSizeAlongNormalizedDirection(Vector3 direction)
- {
- Vector3 transformedBoxSizeVector = RotationMatrix.MultiplyVector(_boxSize);
- return direction.GetAbsDot(transformedBoxSizeVector);
- }
- public void PlaceOnPlane(Plane plane)
- {
- Vector3 upAxis = UpAxis;
- if (plane.normal.IsAlignedWith(upAxis))
- {
- Vector3 projectedBasePosition = plane.ProjectPoint(BasePosition);
- Vector3 desiredBasePosition = projectedBasePosition + upAxis * GetBoxSizeAlongNormalizedDirection(upAxis) * 0.5f;
- SetBasePosition(desiredBasePosition);
- }
- }
- // Note: This method will reset any hide flags assigned to the placement boxes.
- public void SetGrowDirection(Vector3 growDirection)
- {
- _growDirection = growDirection;
- int numberOfBoxes = NumberOfBoxes;
- RemoveAllBoxes();
- if (_isGrowingDownwards) GrowDownwards(numberOfBoxes);
- else GrowUpwards(numberOfBoxes);
- }
- public void SetBoxSize(Vector3 boxSize)
- {
- _boxSize = boxSize;
- if(NumberOfBoxes != 0)
- {
- for (int boxIndex = 0; boxIndex < NumberOfBoxes; ++boxIndex)
- {
- ObjectPlacementBox box = _boxes[boxIndex];
- box.ModelSpaceSize = boxSize;
-
- if(boxIndex > 0) box.Center = CalculateBoxCenterToSitRightAfterBox(_boxes[boxIndex - 1]);
- }
- }
- }
- public void SetRotation(Quaternion rotation)
- {
- Quaternion relativeRotation = _rotation.GetRelativeRotation(rotation);
- _growDirection = relativeRotation * _growDirection;
- _rotation = rotation;
- _rotationMatrix = new TransformMatrix(Vector3.zero, _rotation, Vector3.one);
- foreach (ObjectPlacementBox box in _boxes)
- {
- Vector3 newBoxCenter = box.Center - _basePosition;
- newBoxCenter = relativeRotation * newBoxCenter;
- newBoxCenter += _basePosition;
- box.Center = newBoxCenter;
- box.Rotation = _rotation;
- }
- }
- // Note: This method will reset any hide flags assigned to the placement boxes.
- public void SetHeight(int height)
- {
- RemoveAllBoxes();
- if (height == 0) return;
- float boxSizeAlongGrow = GetBoxSizeAlongNormalizedDirection(GrowDirection);
- if (boxSizeAlongGrow < GetMinAllowedBoxSizeForGrow())
- {
- float sign = Mathf.Sign(height);
- height = (int)(1.0f * sign);
- }
- _isGrowingDownwards = height < 0;
- if (IsGrowingUpwards) GrowUpwards(height);
- else GrowDownwards(Mathf.Abs(height));
- }
- public void SetBasePosition(Vector3 basePosition)
- {
- Vector3 boxMoveOffset = basePosition - _basePosition;
- _basePosition = basePosition;
- OffsetBoxes(boxMoveOffset);
- }
- public void SetPaddingAlongGrowDirection(float paddingAlongGrowDirection)
- {
- if (paddingAlongGrowDirection == _paddingAlongGrowDirection) return;
- _paddingAlongGrowDirection = paddingAlongGrowDirection;
- for (int boxIndex = 1; boxIndex < NumberOfBoxes; ++boxIndex)
- {
- _boxes[boxIndex].Center = CalculateBoxCenterToSitRightAfterBox(_boxes[boxIndex - 1]);
- }
- }
- public void MoveBasePosition(Vector3 moveVector)
- {
- SetBasePosition(_basePosition + moveVector);
- }
- public void RemoveAllBoxes()
- {
- _boxes.Clear();
- }
- public void GrowUpwards(int amount)
- {
- if (amount <= 0) return;
- if (IsHeightRestrictedToOne() && Height == 1) return;
-
- if (!IsGrowingUpwards)
- {
- int numberOfRemovedBoxes = RemoveBoxesFromTopOfStack(amount);
- if (numberOfRemovedBoxes < amount)
- {
- _isGrowingDownwards = false;
- int remainingBoxes = amount - numberOfRemovedBoxes;
- CreateNewBoxesOnTopOfStack(remainingBoxes);
- }
- }
- else CreateNewBoxesOnTopOfStack(amount);
- }
- public void GrowDownwards(int amount)
- {
- if (amount <= 0) return;
- if (IsHeightRestrictedToOne() && Height == 1) return;
-
- if (!IsGrowingDownwards)
- {
- int numberOfRemovedBoxes = RemoveBoxesFromTopOfStack(amount);
- if (numberOfRemovedBoxes < amount)
- {
- _isGrowingDownwards = true;
- int remainingBoxes = amount - numberOfRemovedBoxes;
- CreateNewBoxesOnTopOfStack(remainingBoxes);
- }
- }
- else CreateNewBoxesOnTopOfStack(amount);
- }
- public Vector3 GetBasePositionConnectionVectorTo(ObjectPlacementBoxStack stack)
- {
- Plane basePlane = GetBasePlane();
- Vector3 projectedThisBasePos = basePlane.ProjectPoint(BasePosition);
- Vector3 projectedStackBasePos = basePlane.ProjectPoint(stack.BasePosition);
- return projectedStackBasePos - projectedThisBasePos;
- }
- public Vector3 GetNormalizedBasePositionConnectionVectorTo(ObjectPlacementBoxStack stack)
- {
- Vector3 connectionVector = GetBasePositionConnectionVectorTo(stack);
- connectionVector.Normalize();
- return connectionVector;
- }
- public void ClearHideFlagForAllBoxes(ObjectPlacementBoxHideFlags hideFlag)
- {
- foreach(ObjectPlacementBox box in _boxes)
- {
- box.ClearHideFlag(hideFlag);
- }
- }
- public void SetHideFlagForAllBoxes(ObjectPlacementBoxHideFlags hideFlag)
- {
- foreach (ObjectPlacementBox box in _boxes)
- {
- box.SetHideFlag(hideFlag);
- }
- }
- #endregion
- #region Private Methods
- private void OffsetBoxes(Vector3 offset)
- {
- foreach(ObjectPlacementBox box in _boxes)
- {
- box.Center = box.Center + offset;
- }
- }
- private void CreateNewBoxesOnTopOfStack(int numberOfBoxes)
- {
- for (int boxIndex = 0; boxIndex < numberOfBoxes; ++boxIndex)
- {
- CreateNewBoxOnTopOfStack();
- }
- }
- private void CreateNewBoxOnTopOfStack()
- {
- var newBox = new ObjectPlacementBox();
- newBox.Rotation = _rotation;
- newBox.ModelSpaceSize = _boxSize;
- newBox.Center = CalculateNewBoxCenterToSitOnTopOfStack();
- _boxes.Add(newBox);
- }
- private Vector3 CalculateNewBoxCenterToSitOnTopOfStack()
- {
- if (NumberOfBoxes == 0) return _basePosition;
- return CalculateBoxCenterToSitRightAfterBox(_boxes[NumberOfBoxes - 1]);
- }
- private Vector3 CalculateBoxCenterToSitRightAfterBox(ObjectPlacementBox afterBox)
- {
- return afterBox.Center + GrowDirection * (GetBoxSizeAlongNormalizedDirection(GrowDirection) + _paddingAlongGrowDirection);
- }
- private int RemoveBoxesFromTopOfStack(int numberOfBoxes)
- {
- int numberOfRemovedBoxes = 0;
- for (int boxIndex = 0; boxIndex < numberOfBoxes; ++boxIndex)
- {
- if (RemoveBoxFromTopOfStack()) ++numberOfRemovedBoxes;
- }
- return numberOfRemovedBoxes;
- }
- private bool RemoveBoxFromTopOfStack()
- {
- if (NumberOfBoxes > 0)
- {
- _boxes.RemoveAt(NumberOfBoxes - 1);
- return true;
- }
- return false;
- }
- private bool IsHeightRestrictedToOne()
- {
- return GetBoxSizeAlongNormalizedDirection(GrowDirection) >= GetMinAllowedBoxSizeForGrow();
- }
- private float GetMinAllowedBoxSizeForGrow()
- {
- return 1e-4f;
- }
- #endregion
- }
- }
- #endif
|