示例#1
0
        private static bool RectToRect(Collider a, Collider b, Point2 offset)
        {
            RectInt ar = a.rect + a.Entity.Position + offset;
            RectInt br = b.rect + b.Entity.Position;

            return(ar.Overlaps(br));
        }
示例#2
0
        private static RectInt GetNewRoomLocation(List <Data.Room> rooms, List <RectInt> placeholders)
        {
            for (int i = 0; i < 10; i++)
            {
                int2 randomMapPosition = Util.Map.GetRandomMapPosition();

                RectInt roomBounds = new RectInt(
                    new Vector2Int(randomMapPosition.x, randomMapPosition.y),
                    new Vector2Int(Info.Map.SeedRoomSize, Info.Map.SeedRoomSize)
                    );

                bool collision = false;

                if (Util.Map.OnMap(roomBounds) == false)
                {
                    collision = true;
                }
                else
                {
                    foreach (Data.Room room in rooms)
                    {
                        if (roomBounds.Overlaps(room.Bounds))
                        {
                            collision = true;
                        }
                    }

                    foreach (RectInt placeholder in placeholders)
                    {
                        if (roomBounds.Overlaps(placeholder))
                        {
                            collision = true;
                        }
                    }
                }

                if (collision == false)
                {
                    return(roomBounds);
                }
            }

            return(new RectInt(0, 0, 0, 0));
        }
示例#3
0
 public static float CollideArea(this RectInt a, RectInt b)
 {
     if (a.Overlaps(b))
     {
         float width  = Mathf.Min(a.xMax, b.xMax) - Mathf.Max(a.xMin, b.xMin);
         float height = Mathf.Min(a.yMax, b.yMax) - Mathf.Max(a.yMin, b.yMin);
         return(width * height);
     }
     return(0);
 }
示例#4
0
        public static bool RayRectIntersect(Vector2Int origin, Vector2Int delta, RectInt rect, out Vector2Int preContact, out Vector2Int contactNormal)
        {
            // # Bounding Box Check
            Vector2Int raySize        = Vector2Int.Max(Vector2Int.one, new Vector2Int(Mathf.Abs(delta.x), Mathf.Abs(delta.y)));
            Vector2Int rayDst         = origin + delta;
            Vector2Int rayCorner      = Vector2Int.Min(origin, origin + delta);
            RectInt    rayBoundingBox = new RectInt(rayCorner.x, rayCorner.y, raySize.x, raySize.y);

            if (rayBoundingBox.Overlaps(rect) == false)
            {
                contactNormal = Vector2Int.zero;
                preContact    = Vector2Int.zero;
                return(false);
            }

            // Wall Checks
            Vector2Int?southHit = RayOrthoLineIntersect(origin, delta, rect.position, true, rect.width);
            Vector2Int?northHit = RayOrthoLineIntersect(origin, delta, rect.max, true, -rect.width);
            Vector2Int?westHit  = RayOrthoLineIntersect(origin, delta, rect.position, false, rect.height);
            Vector2Int?eastHit  = RayOrthoLineIntersect(origin, delta, rect.max, false, -rect.height);

            Vector2Int?NSCloser = GetCloser(origin, southHit, northHit);
            Vector2Int?EWCloser = GetCloser(origin, westHit, eastHit);
            Vector2Int?closest  = GetCloser(origin, NSCloser, EWCloser);

            preContact = closest ?? Vector2Int.zero;
            if (closest.HasValue)
            {
                if (closest == southHit)
                {
                    contactNormal = Vector2Int.down;
                }
                else if (closest == northHit)
                {
                    contactNormal = Vector2Int.up;
                }
                else if (closest == westHit)
                {
                    contactNormal = Vector2Int.left;
                }
                else
                {
                    contactNormal = Vector2Int.right;
                }
            }
            else
            {
                contactNormal = Vector2Int.zero;
            }
            return(closest.HasValue);
        }
示例#5
0
    public static bool Intersects(this RectInt a, RectInt b, out RectInt area)
    {
        area = new RectInt();

        if (b.Overlaps(a))
        {
            int x1 = Mathf.Min(a.xMax, b.xMax);
            int x2 = Mathf.Max(a.xMin, b.xMin);
            int y1 = Mathf.Min(a.yMax, b.yMax);
            int y2 = Mathf.Max(a.yMin, b.yMin);
            area.x      = Mathf.Min(x1, x2);
            area.y      = Mathf.Min(y1, y2);
            area.width  = Mathf.Max(0, x1 - x2);
            area.height = Mathf.Max(0, y1 - y2);

            return(true);
        }

        return(false);
    }
示例#6
0
 // TODO: mimic logical & operation from Phil.Core.RectInt
 public static bool TryGetRectIntersection(RectInt a, RectInt b, out RectInt intersection)
 {
     if (!a.Overlaps(b))
     {
         intersection = new RectInt(0, 0, 0, 0);
         return(false);
     }
     else
     {
         var aMax     = a.TrueMax();
         var bMax     = b.TrueMax();
         int maxLeft  = Mathf.Max(a.xMin, b.xMin);
         int minRight = Mathf.Min(aMax.x, bMax.x);
         int minTop   = Mathf.Min(aMax.y, bMax.y);
         int maxBot   = Mathf.Max(a.yMin, b.yMin);
         int width    = minRight - maxLeft + 1;
         int height   = minTop - maxBot + 1;
         intersection = new RectInt(maxLeft, maxBot, width, height);
         return(true);
     }
 }
示例#7
0
        /// <summary>
        /// Checks if a given area in the container is free
        /// </summary>
        /// <param name="area">The area to check</param>
        /// <returns>If the given area is free</returns>
        public bool IsAreaFree(RectInt area)
        {
            if (area.xMin < 0 || area.xMax < 0)
            {
                return(false);
            }

            if (area.xMax > Size.x || area.yMax > Size.y)
            {
                return(false);
            }

            foreach (StoredItem storedItem in items)
            {
                var storedItemPlacement = new RectInt(storedItem.Position, storedItem.Item.Size);
                if (area.Overlaps(storedItemPlacement))
                {
                    return(false);
                }
            }

            return(true);
        }
示例#8
0
        internal void ExecuteNonDrawMesh(DrawParams drawParams, float pixelsPerPoint, ref Exception immediateException)
        {
            switch (type)
            {
            case CommandType.ImmediateCull:
            {
                RectInt worldRect = RectPointsToPixelsAndFlipYAxis(owner.worldBound, pixelsPerPoint);
                if (!worldRect.Overlaps(Utility.GetActiveViewport()))
                {
                    break;
                }

                // Element isn't culled, follow through the normal immediate callback procedure
                goto case CommandType.Immediate;
            }

            case CommandType.Immediate:
            {
                if (immediateException != null)
                {
                    break;
                }

                s_ImmediateOverheadMarker.Begin();
                Matrix4x4     oldProjection = Utility.GetUnityProjectionMatrix();
                Camera        oldCamera     = Camera.current;
                RenderTexture oldRT         = RenderTexture.active;
                bool          hasScissor    = drawParams.scissor.Count > 1; // We always expect the "unbound" scissor rectangle to exists
                if (hasScissor)
                {
                    Utility.DisableScissor();     // Disable scissor since most IMGUI code assume it's inactive
                }
                using (new GUIClip.ParentClipScope(owner.worldTransform, owner.worldClip))
                {
                    s_ImmediateOverheadMarker.End();
                    try
                    {
                        callback();
                    }
                    catch (Exception e)
                    {
                        immediateException = e;
                    }
                    s_ImmediateOverheadMarker.Begin();
                }

                Camera.SetupCurrent(oldCamera);
                RenderTexture.active = oldRT;
                GL.modelview         = drawParams.view.Peek().transform;
                GL.LoadProjectionMatrix(oldProjection);

                if (hasScissor)
                {
                    Utility.SetScissorRect(RectPointsToPixelsAndFlipYAxis(drawParams.scissor.Peek(), pixelsPerPoint));
                }

                s_ImmediateOverheadMarker.End();
                break;
            }

            case CommandType.PushView:
                var     parent = owner.hierarchy.parent;
                Vector4 clipRect;
                if (parent != null)
                {
                    clipRect = RectToClipSpace(parent.worldClip);
                }
                else
                {
                    clipRect = UIRUtility.ToVector4(DrawParams.k_FullNormalizedRect);
                }
                var vt = new ViewTransform()
                {
                    transform = owner.worldTransform, clipRect = clipRect
                };
                drawParams.view.Push(vt);
                GL.modelview = vt.transform;
                break;

            case CommandType.PopView:
                drawParams.view.Pop();
                GL.modelview = drawParams.view.Peek().transform;
                break;

            case CommandType.PushScissor:
                Rect elemRect = CombineScissorRects(owner.worldClip, drawParams.scissor.Peek());
                drawParams.scissor.Push(elemRect);
                Utility.SetScissorRect(RectPointsToPixelsAndFlipYAxis(elemRect, pixelsPerPoint));
                break;

            case CommandType.PopScissor:
                drawParams.scissor.Pop();
                Rect prevRect = drawParams.scissor.Peek();
                if (prevRect.x == DrawParams.k_UnlimitedRect.x)
                {
                    Utility.DisableScissor();
                }
                else
                {
                    Utility.SetScissorRect(RectPointsToPixelsAndFlipYAxis(prevRect, pixelsPerPoint));
                }
                break;

            case CommandType.PushRenderTexture:
            {
                RectInt       viewport = Utility.GetActiveViewport();
                RenderTexture rt       = RenderTexture.GetTemporary(viewport.width, viewport.height, 24, RenderTextureFormat.ARGBHalf);
                RenderTexture.active = rt;
                GL.Clear(true, true, new Color(0, 0, 0, 0), UIRUtility.k_ClearZ);
                drawParams.renderTexture.Add(RenderTexture.active);
                break;
            }

            case CommandType.PopRenderTexture:
            {
                int index = drawParams.renderTexture.Count - 1;
                Debug.Assert(index > 0);        //Check that we have something to pop, We should never pop the last(original)one

                // Only supported use case for now is to do a blit befor the pop.
                // This should set the active RenderTexture to index-1 and we should not have this warning.
                Debug.Assert(drawParams.renderTexture[index - 1] == RenderTexture.active, "Content of previous render texture was probably not blitted");

                var rt = drawParams.renderTexture[index];
                if (rt != null)
                {
                    RenderTexture.ReleaseTemporary(rt);
                }
                drawParams.renderTexture.RemoveAt(index);
            }
            break;

            case CommandType.BlitToPreviousRT:
            {
                // Currently the command only blit to the previous RT, but this could be expanded if we use
                // indexCount and indexOffset to point to specific indices in the renderTextureBuffer.
                // The main difficulty is to memorize the current renderTexture depth to get the indices in the RenderChain
                // as we can edit the stack in the middle and that would requires rewriting previous/ subsequent commands

                //Also, there is currently no way to have a permanently assigned rt to be used as cache.

                var source      = drawParams.renderTexture[drawParams.renderTexture.Count - 1];
                var destination = drawParams.renderTexture[drawParams.renderTexture.Count - 2];


                // Note: Graphics.Blit set the arctive RT => RT is not restored and it is expected to be chaged before PopRenderTexture
                //TODO check blit code for other side effect
                Debug.Assert(source == RenderTexture.active, "Unexpected render target change: Current renderTarget is not the one on the top of the stack");

                //The following lines are equivalent to
                //Graphics.Blit(source, destination, state.material);
                //except the vertex are at the specified depth
                Blit(source, destination, UIRUtility.k_MeshPosZ);
            }
            break;

//Logic of both command is entirely in UIRenderDevice as it need access to the local variable defaultMat
            case CommandType.PushDefaultMaterial:
                break;

            case CommandType.PopDefaultMaterial:
                break;
            }
        }
示例#9
0
        /// <summary>
        /// Gets the first empty space in <paramref name="atlas"/> that has at least the size of <paramref name="pixelScale"/>.
        /// </summary>
        /// <param name="atlas">The <see cref="dfAtlas"/> to find the empty space in.</param>
        /// <param name="pixelScale">The required size of the empty space.</param>
        /// <returns>The rect of the empty space divided by the atlas texture's size.</returns>
        public static Rect FindFirstValidEmptySpace(this dfAtlas atlas, IntVector2 pixelScale)
        {
            if (atlas == null || atlas.Texture == null || !atlas.Texture.IsReadable())
            {
                return(new Rect(0f, 0f, 0f, 0f));
            }
            Vector2Int     point      = new Vector2Int(0, 0);
            int            pointIndex = -1;
            List <RectInt> rects      = atlas.GetPixelRegions();

            while (true)
            {
                bool shouldContinue = false;
                foreach (RectInt rint in rects)
                {
                    if (rint.Overlaps(new RectInt(point, pixelScale.ToVector2Int())))
                    {
                        shouldContinue = true;
                        pointIndex++;
                        if (pointIndex >= rects.Count)
                        {
                            return(new Rect(0f, 0f, 0f, 0f));
                        }
                        point = rects[pointIndex].max + Vector2Int.one;
                        if (point.x > atlas.Texture.width || point.y > atlas.Texture.height)
                        {
                            atlas.ResizeAtlas(new IntVector2(atlas.Texture.width * 2, atlas.Texture.height * 2));
                        }
                        break;
                    }
                    bool shouldBreak = false;
                    foreach (RectInt rint2 in rects)
                    {
                        RectInt currentRect = new RectInt(point, pixelScale.ToVector2Int());
                        if (rint2.x < currentRect.x || rint2.y < currentRect.y)
                        {
                            continue;
                        }
                        else
                        {
                            if (currentRect.Overlaps(rint2))
                            {
                                shouldContinue = true;
                                shouldBreak    = true;
                                pointIndex++;
                                if (pointIndex >= rects.Count)
                                {
                                    return(new Rect(0f, 0f, 0f, 0f));
                                }
                                point = rects[pointIndex].max + Vector2Int.one;
                                if (point.x > atlas.Texture.width || point.y > atlas.Texture.height)
                                {
                                    atlas.ResizeAtlas(new IntVector2(atlas.Texture.width * 2, atlas.Texture.height * 2));
                                }
                                break;
                            }
                        }
                    }
                    if (shouldBreak)
                    {
                        break;
                    }
                }
                if (shouldContinue)
                {
                    continue;
                }
                RectInt currentRect2 = new RectInt(point, pixelScale.ToVector2Int());
                if (currentRect2.xMax > atlas.Texture.width || currentRect2.yMax > atlas.Texture.height)
                {
                    atlas.ResizeAtlas(new IntVector2(atlas.Texture.width * 2, atlas.Texture.height * 2));
                }
                break;
            }
            RectInt currentRect3 = new RectInt(point, pixelScale.ToVector2Int());
            Rect    rect         = new Rect((float)currentRect3.x / atlas.Texture.width, (float)currentRect3.y / atlas.Texture.height, (float)currentRect3.width / atlas.Texture.width, (float)currentRect3.height / atlas.Texture.height);

            return(rect);
        }
示例#10
0
        public static bool RectIntCast(RectInt origin, Vector2Int delta, RectInt obstruction,
                                       out RectInt dst, out Vector2Int contactNormal, out RectInt overlapIntersection, bool debug = false)
        {
            if (delta == Vector2Int.zero)
            {
                contactNormal = Vector2Int.zero;
                if (TryGetRectIntersection(origin, obstruction, out overlapIntersection))
                {
                    dst = origin;
                    return(true);
                }
                else
                {
                    dst = origin;
                    overlapIntersection = new RectInt(Vector2Int.zero, Vector2Int.zero);
                    return(false);
                }
            }

            float strideWidth  = (float)origin.width / 2;
            float strideHeight = (float)origin.height / 2;
            int   slices       = Mathf.Max(
                Mathf.CeilToInt((float)Mathf.Abs(delta.x) / strideWidth),
                Mathf.CeilToInt((float)Mathf.Abs(delta.y) / strideHeight)
                );

            Vector2 floatStride = new Vector2(delta.x, delta.y) / slices;
            // Debug.LogFormat("float stride: {0}", floatStride);
            RectInt?overlapRect = null;
            RectInt coarseRect  = new RectInt(0, 0, 0, 0);

            for (int i = 0; i < slices + 1; i++)
            {
                Vector2Int position = origin.position + Vector2Int.RoundToInt(i * floatStride);
                RectInt    iterRect = new RectInt(position, origin.size);

                if (iterRect.Overlaps(obstruction))
                {
                    TryGetRectIntersection(iterRect, obstruction, out RectInt ol);
                    overlapRect = ol;
                    coarseRect  = iterRect;
                    break;
                }
            }

            if (overlapRect.HasValue == false)
            {
                dst                 = new RectInt(origin.position + delta, origin.size);
                contactNormal       = Vector2Int.zero;
                overlapIntersection = new RectInt();
                return(false);
            }
            var overlap = overlapRect.Value;

            overlapIntersection = overlap;
            if (debug)
            {
                Debug.LogFormat("Coarse rect: {0}", coarseRect);
            }
            if (debug)
            {
                Debug.LogFormat("Overlap rect: {0}", overlap);
            }


            // At this point, one of our rects overlapped
            // Use our delta, coarse rect, and overlap rect to back-out of overlapping
            Vector2Int backTrack = Vector2Int.zero;

            // fine-tune contact normal? right now just returns a cardinal dir or zero.
            contactNormal = Vector2Int.zero;

            {
                Vector2Int backtrackFromHorz     = Vector2Int.zero;
                Vector2Int contactNormalFromHorz = Vector2Int.one;
                if (delta.x != 0)
                {
                    float slope = (float)delta.y / delta.x;
                    if (-delta.x > 0)
                    {
                        int rightResolve = 1 + overlap.TrueMax().x - coarseRect.x;
                        backtrackFromHorz.x = rightResolve;
                        backtrackFromHorz.y = Mathf.RoundToInt(rightResolve * slope);
                        if (debug)
                        {
                            Debug.LogFormat("Right resolve: {0}. backtrackFromHorz: {1}", rightResolve, backtrackFromHorz);
                        }
                        contactNormalFromHorz = Vector2Int.right;
                    }
                    else
                    {
                        int leftResolve = -Mathf.Abs(coarseRect.TrueMax().x - overlap.x + 1);
                        backtrackFromHorz.x = leftResolve;
                        backtrackFromHorz.y = Mathf.RoundToInt(leftResolve * slope);
                        if (debug)
                        {
                            Debug.LogFormat("Left resolve: {0}. backtrackFromHorz: {1}", leftResolve, backtrackFromHorz);
                        }
                        contactNormalFromHorz = Vector2Int.left;
                    }
                }
                Vector2Int backtrackFromVert     = Vector2Int.zero;
                Vector2Int contactNormalFromVert = Vector2Int.zero;
                if (delta.y != 0)
                {
                    // Pure vertical
                    float invSlope = (float)delta.x / delta.y;
                    if (delta.y > 0)
                    {
                        int downResolve = -Mathf.Abs(coarseRect.TrueMax().y - overlap.y + 1);
                        backtrackFromVert.y = downResolve;
                        backtrackFromVert.x = Mathf.RoundToInt(downResolve * invSlope);
                        if (debug)
                        {
                            Debug.LogFormat("Down resolve: {0}. backtrackFromVert: {1}.", downResolve, backtrackFromVert);
                        }
                        contactNormalFromVert = Vector2Int.down;
                    }
                    else
                    {
                        int upResolve = 1 + overlap.TrueMax().y - coarseRect.y;
                        backtrackFromVert.y = upResolve;
                        backtrackFromVert.x = Mathf.RoundToInt(upResolve * invSlope);
                        if (debug)
                        {
                            Debug.LogFormat("Up resolve: {0}. backtrackFromVert: {1}", upResolve, backtrackFromVert);
                        }
                        contactNormalFromVert = Vector2Int.up;
                    }
                }
                bool useVert = (Mathf.Abs(delta.y) > Mathf.Abs(delta.x));
                backTrack     = useVert ? backtrackFromVert : backtrackFromHorz;
                contactNormal = useVert ? contactNormalFromVert : contactNormalFromHorz;
            }
            // Note: we don't handle corner-to-corner collisions here^.

            if (debug)
            {
                Debug.LogFormat("backtrack: {0}", backTrack);
            }

            Vector2Int finalRectPos = coarseRect.position + backTrack;

            dst = new RectInt(finalRectPos, origin.size);

            if (debug)
            {
                Debug.LogFormat("Final rect: {0}", finalRectPos);
            }

            return(true);
        }
示例#11
0
        internal void ExecuteNonDrawMesh(DrawParams drawParams, float pixelsPerPoint, ref Exception immediateException)
        {
            switch (type)
            {
            case CommandType.ImmediateCull:
            {
                RectInt worldRect = RectPointsToPixelsAndFlipYAxis(owner.worldBound, pixelsPerPoint);
                if (!worldRect.Overlaps(Utility.GetActiveViewport()))
                {
                    break;
                }

                // Element isn't culled, follow through the normal immediate callback procedure
                goto case CommandType.Immediate;
            }

            case CommandType.Immediate:
            {
                if (immediateException != null)
                {
                    break;
                }

                Matrix4x4 oldProjection = Utility.GetUnityProjectionMatrix();
                bool      hasScissor    = drawParams.scissor.Count > 1; // We always expect the "unbound" scissor rectangle to exists
                if (hasScissor)
                {
                    Utility.DisableScissor();     // Disable scissor since most IMGUI code assume it's inactive
                }
                Utility.ProfileImmediateRendererBegin();
                try
                {
                    using (new GUIClip.ParentClipScope(owner.worldTransform, owner.worldClip))
                        callback();
                }
                catch (Exception e)
                {
                    immediateException = e;
                }

                GL.modelview = drawParams.view.Peek().transform;
                GL.LoadProjectionMatrix(oldProjection);
                Utility.ProfileImmediateRendererEnd();

                if (hasScissor)
                {
                    Utility.SetScissorRect(RectPointsToPixelsAndFlipYAxis(drawParams.scissor.Peek(), pixelsPerPoint));
                }
                break;
            }

            case CommandType.PushView:
                var vt = new ViewTransform()
                {
                    transform = owner.worldTransform, clipRect = RectToClipSpace(owner.worldClip)
                };
                drawParams.view.Push(vt);
                GL.modelview = vt.transform;
                break;

            case CommandType.PopView:
                drawParams.view.Pop();
                GL.modelview = drawParams.view.Peek().transform;
                break;

            case CommandType.PushScissor:
                Rect elemRect = CombineScissorRects(owner.worldClip, drawParams.scissor.Peek());
                drawParams.scissor.Push(elemRect);
                Utility.SetScissorRect(RectPointsToPixelsAndFlipYAxis(elemRect, pixelsPerPoint));
                break;

            case CommandType.PopScissor:
                drawParams.scissor.Pop();
                Rect prevRect = drawParams.scissor.Peek();
                if (prevRect.x == DrawParams.k_UnlimitedRect.x)
                {
                    Utility.DisableScissor();
                }
                else
                {
                    Utility.SetScissorRect(RectPointsToPixelsAndFlipYAxis(prevRect, pixelsPerPoint));
                }
                break;
            }
        }