public static bool GetRectSpacesDoOverlap(RectSpace space, RectSpace container)
 {
     return(RectContainsPoint(space.lowerLeft, container) ||
            RectContainsPoint(space.upperLeft, container) ||
            RectContainsPoint(space.upperRight, container) ||
            RectContainsPoint(space.lowerRight, container));
 }
 public static RectSpace TransformWithOffset(this RectSpace space, Vector2 transformation)
 {
     space.lowerLeft  -= (Vector3)transformation;
     space.upperLeft  -= (Vector3)transformation;
     space.upperRight -= (Vector3)transformation;
     space.lowerRight -= (Vector3)transformation;
     return(space);
 }
Example #3
0
 public RectSpace(RectSpace s)
 {
     markedForRemoval = false;
     lowerLeft        = s.lowerLeft;
     upperLeft        = s.upperLeft;
     upperRight       = s.upperRight;
     lowerRight       = s.lowerRight;
 }
        public static Vector2 GetRectSpaceOverlap(
            RectSpace element,
            RectSpace container,
            RectContainerElement.DragElementContainerBoundary mode)
        {
            Vector2 overlap = Vector2.zero;

            if (mode == RectContainerElement.DragElementContainerBoundary.Edge)
            {
                // X overlap
                if (element.left < container.left)
                {
                    overlap = new Vector2(element.left - container.left, overlap.y);
                }

                if (element.right > container.right)
                {
                    overlap = new Vector2(element.right - container.right, overlap.y);
                }

                // Y overlap
                if (element.top > container.top)
                {
                    overlap = new Vector2(overlap.x, element.top - container.top);
                }

                if (element.bottom < container.bottom)
                {
                    overlap = new Vector2(overlap.x, element.bottom - container.bottom);
                }
            }
            else
            {
                // X overlap
                if (element.center.x < container.left)
                {
                    overlap = new Vector2(element.center.x - container.left, overlap.y);
                }

                if (element.center.x > container.right)
                {
                    overlap = new Vector2(element.center.x - container.right, overlap.y);
                }

                // Y overlap
                if (element.center.y > container.top)
                {
                    overlap = new Vector2(overlap.x, element.center.y - container.top);
                }

                if (element.center.y < container.bottom)
                {
                    overlap = new Vector2(overlap.x, element.center.y - container.bottom);
                }
            }

            return(overlap);
        }
 void IUIDynamicElementListener.OnDynamicElementUpdate(IUIDynamicElement d)
 {
     // If this update is not from the source, that means it's coming from our container
     if (d != _source)
     {
         _containerSpace = new RectSpace(_explicitContainer);
         _source.ForceUpdate();
     }
 }
        public static RectSpace[] GetSplitSpacesFromObstacle(RectSpace obstacle, RectSpace spaceToSplit)
        {
            // Left, top, right, bottom
            List <RectSpace> splitSpaces = new List <RectSpace>();

            // Left space
            splitSpaces.Add(new RectSpace
            {
                lowerLeft  = spaceToSplit.lowerLeft,
                upperLeft  = spaceToSplit.upperLeft,
                upperRight = new Vector3(obstacle.left, spaceToSplit.top, 0),
                lowerRight = new Vector3(obstacle.left, spaceToSplit.bottom, 0),
            });

            // Top space
            splitSpaces.Add(new RectSpace
            {
                lowerLeft  = new Vector3(spaceToSplit.left, obstacle.top, 0),
                upperLeft  = spaceToSplit.upperLeft,
                upperRight = spaceToSplit.upperRight,
                lowerRight = new Vector3(spaceToSplit.right, obstacle.top, 0),
            });

            // Right space
            splitSpaces.Add(new RectSpace
            {
                lowerLeft  = new Vector3(obstacle.right, spaceToSplit.bottom, 0),
                upperLeft  = new Vector3(obstacle.right, spaceToSplit.top, 0),
                upperRight = spaceToSplit.upperRight,
                lowerRight = spaceToSplit.lowerLeft,
            });

            // Bottom space
            splitSpaces.Add(new RectSpace
            {
                lowerLeft  = spaceToSplit.lowerLeft,
                upperLeft  = new Vector3(spaceToSplit.left, obstacle.bottom, 0),
                upperRight = new Vector3(spaceToSplit.right, obstacle.bottom, 0),
                lowerRight = spaceToSplit.lowerRight,
            });

            // Remove any created spaces that are too small
            // const float epsilon = 0.001f;
            // for (int i = splitSpaces.Count - 1; i >= 0; i--)
            // {
            //     if (Mathf.Abs(splitSpaces[i].top - splitSpaces[i].bottom) <= epsilon ||
            //         Mathf.Abs(splitSpaces[i].left - splitSpaces[i].right) <= epsilon)
            //     {
            //         splitSpaces.RemoveAt(i);
            //     }
            // }

            return(splitSpaces.ToArray());
        }
 private void RefreshGroupFreeSpaces()
 {
     // Get container from group
     _positionEvaluationSpace = _group.GetGroupedElementEvaluationBoundary(
         this,
         _boundaryMode,
         new RectSpace(_source.dynamicTransform),
         _containerSpace,
         _currentElementFreeSpaces,
         out _currentElementFreeSpaces);
 }
        private static bool RectContainsPoint(Vector3 point, RectSpace rect)
        {
            bool contains = true;

            if (point.x < rect.left || point.x > rect.right)
            {
                contains = false;
            }
            else if (point.y < rect.bottom || point.y > rect.top)
            {
                contains = false;
            }

            return(contains);
        }
Example #9
0
        /// <summary>
        /// Calculates and returns the array of navigable RectSpaces formed in a group by all of the
        /// group elements, excluding the given active element.
        /// </summary>
        private static RectSpace[] CalculateFreeSpacesForGroupedElement(
            RectContainerElement activeElement,
            List <RectContainerElement> allGroupElements,
            RectSpace activeElementContainer)
        {
            // Gather list of obstacles
            List <RectSpace> obstacles = new List <RectSpace>();

            foreach (RectContainerElement e in allGroupElements)
            {
                if (e != activeElement)
                {
                    obstacles.Add(new RectSpace(e._source.dynamicTransform));
                }
            }

            List <RectSpace> freeSpaces = new List <RectSpace>();

            freeSpaces.Add(activeElementContainer);
            foreach (RectSpace obstacle in obstacles)
            {
                // Is this obstacle overlapping with any known freespaces?
                List <RectSpace> createdFreeSpaces = new List <RectSpace>();
                foreach (var space in freeSpaces)
                {
                    if (RectBoundariesUtility.GetRectSpacesDoOverlap(obstacle, space))
                    {
                        space.markedForRemoval = true;
                        createdFreeSpaces.AddRange(
                            RectBoundariesUtility.GetSplitSpacesFromObstacle(obstacle, space));
                    }
                }

                // Remove marked spaces
                for (int i = freeSpaces.Count - 1; i >= 0; i--)
                {
                    if (freeSpaces[i].markedForRemoval)
                    {
                        freeSpaces.Remove(freeSpaces[i]);
                    }
                }

                // Add created spaces
                freeSpaces.AddRange(createdFreeSpaces);
            }

            return(freeSpaces.ToArray());
        }
Example #10
0
        /// <summary>
        /// Calculates and returns a list of the freespaces within which the given element is
        /// completely contained (not overlapping any edges).
        /// </summary>
        private static List <RectSpace> CalculateEnclosingFreeSpacesForGroupedElement(
            RectContainerElement activeElement,
            RectContainerElement.DragElementContainerBoundary boundaryMode,
            RectSpace element,
            RectSpace[] freespaces)
        {
            List <RectSpace> containingSpaces = new List <RectSpace>();

            foreach (RectSpace space in freespaces)
            {
                if (RectBoundariesUtility.GetRectSpaceOverlap(element, space, boundaryMode) == Vector2.zero)
                {
                    containingSpaces.Add(space);
                }
            }

            return(containingSpaces);
        }
 public void SetContainerType(
     DragElementContainerType containerType, 
     RectTransform container,
     IUIDynamicElement dynamicContainer)
 {
     _explicitContainer = container;
     _dynamicContainer = dynamicContainer;
     _containerType = containerType;
     switch (_containerType)
     {
         case DragElementContainerType.Screen:
         case DragElementContainerType.SafeArea:
             _containerSpace = new RectSpace(RectBoundariesUtility.GetScreenCorners());
             GourdUI.Device.RegisterScreenUpdateListener(this);
             break;
         
         case DragElementContainerType.Parent:
             _containerSpace = new RectSpace(_explicitContainer);
             _dynamicContainer?.SubscribeDynamicElementListener(this);
             break;
     }
     _currentElementFreeSpaces.Add(_containerSpace);
 }
        Tuple<Vector2, bool, bool> IUIDynamicElementPositionFilter.GetFilteredPosition()
        {
            // Refersh container
            if (_group != null)
            {
                RefreshGroupFreeSpaces();
            }
            else
            {
                _positionEvaluationSpace = _containerSpace;
            }
            
            // Find the overlap with the current container
            Vector2 boundaryOverlap = RectBoundariesUtility.GetRectSpaceOverlap(
                new RectSpace(_source.dynamicTransform),
                _positionEvaluationSpace,
                _boundaryMode);

            return new Tuple<Vector2, bool, bool>(
                boundaryOverlap,
                boundaryOverlap.x != 0,
                boundaryOverlap.y != 0);
        }
 void IScreenRectUpdateListener.OnScreenRectUpdated(Rect rect)
 {
     _containerSpace = new RectSpace(RectBoundariesUtility.GetScreenCorners());
     _source.ForceUpdate();
 }
Example #14
0
        /// <summary>
        /// Returns the FreeSpaces within which the given element is completely contained, AFTER
        /// any overlap corrects have been applied.
        /// </summary>
        public RectSpace GetGroupedElementEvaluationBoundary(
            RectContainerElement activeElement,
            RectContainerElement.DragElementContainerBoundary boundaryMode,
            RectSpace activeSpace,
            RectSpace containerSpace,
            List <RectSpace> previousFreeSpaces,
            out List <RectSpace> newFreeSpaces)
        {
            // Get the free spaces
            RectSpace[] freespaces = CalculateFreeSpacesForGroupedElement(
                activeElement,
                _elements,
                containerSpace);

            // Is our element fully contained within any space?
            List <RectSpace> fs = CalculateEnclosingFreeSpacesForGroupedElement(
                activeElement,
                boundaryMode,
                activeSpace,
                freespaces);

            // If we didn't find a space, that means our element is overlapping
            // We want to apply the correction temporarily, re-check to find the correct space,
            // And then try again to find the new evaluation container space
            if (fs.Count == 0)
            {
                // Get overlap distances for each previous freespace
                Vector2[] overlapDistances = new Vector2[previousFreeSpaces.Count];
                for (int i = 0; i < previousFreeSpaces.Count; i++)
                {
                    overlapDistances [i] =
                        RectBoundariesUtility.GetRectSpaceOverlap(
                            activeSpace,
                            previousFreeSpaces[i],
                            boundaryMode);
                }

                // Which overlap distance was closest? That's the one we want!
                RectSpace evalSpace              = previousFreeSpaces[0];
                Vector2   evalDistance           = Vector2.zero;
                float     currentClosestDistance = float.MaxValue;
                for (int i = 0; i < previousFreeSpaces.Count; i++)
                {
                    if (overlapDistances[i].sqrMagnitude < currentClosestDistance)
                    {
                        currentClosestDistance = overlapDistances[i].sqrMagnitude;
                        evalDistance           = overlapDistances[i];
                        evalSpace = previousFreeSpaces[i];
                    }
                }

                // Now we can re-evaluate current spaces for transformed element
                RectSpace        corrected        = new RectSpace(activeSpace).TransformWithOffset(evalDistance);
                List <RectSpace> postCorrectionFS =
                    CalculateEnclosingFreeSpacesForGroupedElement(
                        activeElement,
                        boundaryMode,
                        corrected,
                        freespaces);
                newFreeSpaces = postCorrectionFS.Count > 0 ? postCorrectionFS : new List <RectSpace> {
                    containerSpace
                };

                //
                return(evalSpace);
            }

            newFreeSpaces = fs.Count > 0 ? fs : new List <RectSpace> {
                containerSpace
            };
            return(fs[0]);
        }