Ejemplo n.º 1
0
        private List <List <RelevantRoom> > groupBuildRoomSequences(Vector2 cursorPos, int groupIndex)
        {
            // Decide what bar is at the given index
            Vector2 probePos = groupIndex == DepthProbes.Count ? cursorPos : DepthProbes[groupIndex].Position;
            bool    shouldCheckRoomsToMove = groupIndex == DepthProbes.Count && _roomsToMove != null;

            // Iterate over all rooms under the cursor and add them to the room sequences
            IEnumerable <Room> sortedRoomList = _editor.Level.GetVerticallyAscendingRoomList(room =>
            {
                Vector2 roomLocal      = probePos - room.SectorPos;
                bool CollidesWithProbe = roomLocal.X >= 1 && roomLocal.Y >= 1 && roomLocal.X < room.NumXSectors - 1 && roomLocal.Y < room.NumZSectors - 1;
                return(shouldCheckRoomsToMove ? _roomsToMove.Contains(room) : CollidesWithProbe);
            });

            var roomSequences = new List <List <RelevantRoom> >();

            foreach (Room room in sortedRoomList)
            {
                Vector2 roomLocal         = probePos - room.SectorPos;
                bool    CollidesWithProbe = roomLocal.X >= 1 && roomLocal.Y >= 1 && roomLocal.X < room.NumXSectors - 1 && roomLocal.Y < room.NumZSectors - 1;

                Block        block        = CollidesWithProbe ? room.Blocks[(int)roomLocal.X, (int)roomLocal.Y] : null;
                RelevantRoom relevantRoom = new RelevantRoom
                {
                    Room     = room,
                    Block    = block,
                    MinDepth = room.Position.Y + room.GetLowestCorner(),
                    MaxDepth = room.Position.Y + room.GetHighestCorner()
                };

                // Search for a fit in the sequence for rooms it the current room is connected to on this sector
                if (block != null && block.FloorPortal != null)
                {
                    var portal    = block.FloorPortal;
                    var roomAbove = portal.AdjoiningRoom;
                    foreach (var roomSequence in roomSequences)
                    {
                        if (roomSequence.Last().Room == roomAbove)
                        {
                            roomSequence.Add(relevantRoom);
                            goto AddedRoomSucessfully;
                        }
                    }
                }
                roomSequences.Add(new List <RelevantRoom>());
                roomSequences.Last().Add(relevantRoom);
AddedRoomSucessfully:
                ;
            }

            // Also try moving rooms into the same sequence that are connected directly, just not on the square that is selected
            for (int i = 1; i < roomSequences.Count; ++i) // triangular iteration
            {
                var roomSequenceAbove = roomSequences[i];
                foreach (var portal in roomSequenceAbove[0].Room.Portals)
                {
                    var connectedRoom = portal.AdjoiningRoom;

                    for (int j = 0; j < i; ++j)
                    {
                        var roomSequenceBelow = roomSequences[j];
                        if (roomSequences[j].Last().Room != connectedRoom)
                        {
                            continue;
                        }

                        float distanceBetweenSequences = roomSequenceAbove[0].MinDepth - roomSequenceBelow.Last().MaxDepth;
                        if (!(distanceBetweenSequences >= 0.0))
                        {
                            continue;
                        }

                        roomSequences[j].AddRange(roomSequences[i]);
                        roomSequences.RemoveAt(i);
                        --i;
                        goto NextRoom;
                    }
                }
NextRoom:
                ;
            }

            // Try to merge independent sequences if they are sufficently far apart
            for (int i = 0; i < roomSequences.Count; ++i)
            {
                var roomSequenceAbove = roomSequences[i];
                for (int j = 0; j < roomSequences.Count; ++j)
                {
                    var   roomSequenceBelow        = roomSequences[j];
                    float distanceBetweenSequences = roomSequenceAbove[0].MinDepth - roomSequenceBelow.Last().MaxDepth;
                    if (distanceBetweenSequences >= _minDepthDifferenceBetweenIndependentlyMergedSequences)
                    {
                        roomSequenceBelow.AddRange(roomSequenceAbove);
                        roomSequences.RemoveAt(i);
                        --i;
                        goto NextRoom;
                    }
                }
NextRoom:
                ;
            }

            return(roomSequences);
        }
Ejemplo n.º 2
0
        public void Draw(PaintEventArgs e, Size parentControlSize, Vector2 cursorPos, Func <Room, Brush, ConditionallyOwned <Brush> > getRoomBrush)
        {
            RectangleF barArea            = getBarArea(parentControlSize);
            float      selectedLimit0PosY = ToVisualY(barArea, _selectedLimit0);
            float      selectedLimit1PosY = ToVisualY(barArea, _selectedLimit1);

            // Draw box
            e.Graphics.FillRectangle(_backgroundBrush, barArea);

            // Draw height lines
            if (barArea.IntersectsWith(e.ClipRectangle))
            {
                e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
                for (int depth = (int)MinDepth; depth <= (int)MaxDepth; ++depth)
                {
                    float posY = ToVisualY(barArea, depth);
                    e.Graphics.DrawLine(_heightLinesPen, barArea.Left, posY, barArea.Right, posY);
                }
                e.Graphics.SmoothingMode = SmoothingMode.Default;
            }

            // Draw height strings
            for (int i = 0; i <= _heightStringCount; ++i)
            {
                float depth = MaxDepth - (MaxDepth - MinDepth) / _heightStringCount * i;
                float posY  = ToVisualY(barArea, depth);

                // Hide height string when close to selection limits
                float distanceToSelectionLimit0 = Math.Abs(posY - selectedLimit0PosY);
                float distanceToSelectionLimit1 = Math.Abs(posY - selectedLimit1PosY);
                float distance = Math.Min(distanceToSelectionLimit0, distanceToSelectionLimit1) - _heightStringFont.Height * 0.85f;

                if (distance > _heightStringFadeDistance)
                {
                    DrawHeightString(e, barArea, _outlinePen, (float)Math.Round(depth));

                    if (i > 0 && i < _heightStringCount)
                    {
                        e.Graphics.DrawLine(_heightLinesBigPen, barArea.Left, posY, barArea.Right, posY);
                    }
                }
                else if (distance > 0.0f)
                {
                    using (var alphaOutlinePen = (Pen)_outlinePen.Clone())
                    {
                        alphaOutlinePen.Color = Color.FromArgb((int)(alphaOutlinePen.Color.A * (distance / _heightStringFadeDistance)),
                                                               alphaOutlinePen.Color.R, alphaOutlinePen.Color.G, alphaOutlinePen.Color.B);
                        DrawHeightString(e, barArea, alphaOutlinePen, (float)Math.Round(depth));
                    }
                    if (i > 0 && i < _heightStringCount)
                    {
                        using (var alphaPen = (Pen)_heightLinesBigPen.Clone())
                        {
                            alphaPen.Color = Color.FromArgb((int)(alphaPen.Color.A * (distance / _heightStringFadeDistance)),
                                                            alphaPen.Color.R, alphaPen.Color.G, alphaPen.Color.B);
                            e.Graphics.DrawLine(alphaPen, barArea.Left, posY, barArea.Right, posY);
                        }
                    }
                }
            }

            // Draw common selection range
            DrawHeightString(e, barArea, _selectionPen, _selectedLimit0, true);
            DrawHeightString(e, barArea, _selectionPen, _selectedLimit1, true);

            RectangleF selectionRect = new RectangleF(new PointF(barArea.Left, Math.Min(selectedLimit1PosY, selectedLimit0PosY)),
                                                      new SizeF(_barWidth, Math.Abs(selectedLimit0PosY - selectedLimit1PosY)));

            e.Graphics.FillRectangle(_selectionBrush, selectionRect);

            // Draw probe selection ranges
            if (!barArea.Contains(e.ClipRectangle))
            {
                for (int groupIndex = 0; groupIndex < DepthProbes.Count; ++groupIndex)
                {
                    RectangleF groupArea = groupGetArea(barArea, groupIndex);
                    selectionRect = new RectangleF(new PointF(groupArea.Left, Math.Min(selectedLimit1PosY, selectedLimit0PosY)),
                                                   new SizeF(groupArea.Width, Math.Abs(selectedLimit0PosY - selectedLimit1PosY)));

                    using (var b = new SolidBrush(Color.FromArgb(60, DepthProbes[groupIndex].Color.R, DepthProbes[groupIndex].Color.G, DepthProbes[groupIndex].Color.B)))
                        e.Graphics.FillRectangle(b, selectionRect);
                }
            }

            // Draw depth bar content
            if (barArea.IntersectsWith(e.ClipRectangle))
            {
                // Draw group
                for (int groupIndex = 0; groupIndex < GroupCount; ++groupIndex)
                {
                    RectangleF groupArea = groupGetArea(barArea, groupIndex);
                    if (!groupArea.IntersectsWith(e.ClipRectangle))
                    {
                        continue;
                    }

                    // Draw sequences
                    List <List <RelevantRoom> > roomSequences = groupBuildRoomSequences(cursorPos, groupIndex);
                    float sequenceWidth = groupArea.Width / roomSequences.Count;
                    for (int roomSequenceIndex = 0; roomSequenceIndex < roomSequences.Count; ++roomSequenceIndex)
                    {
                        var   roomSequence = roomSequences[roomSequenceIndex];
                        float posX0        = groupArea.X + sequenceWidth * roomSequenceIndex;
                        float posX1        = groupArea.X + sequenceWidth * (roomSequenceIndex + 1);
                        for (int i = 0; i < roomSequence.Count; ++i)
                        {
                            RelevantRoom room  = roomSequence[i];
                            float        posY0 = ToVisualY(groupArea, room.MaxDepth);
                            float        posY1 = ToVisualY(groupArea, room.MinDepth);

                            // HACK: if a rooms is full of walls (but why a designer should do this???) then
                            // MaxDepth or MinDepth can be int.MinValue or int.MaxValue and posY0 or posY1 get f****d...
                            // However I'm solving the issue elsewhere, this hack is here as a really last chance for
                            // the 0.0000000001% of the cases that could be wrong
                            if (Math.Abs(posY0) >= short.MaxValue || Math.Abs(posY1) >= short.MaxValue)
                            {
                                continue;
                            }

                            // Draw fill color for room
                            Brush      colorBrush = _roomsNormalBrush;
                            RectangleF roomRect   = new RectangleF(posX0, posY0, posX1 - posX0, posY1 - posY0);
                            if (room.Block != null && room.Block.Type != BlockType.Floor)
                            {
                                colorBrush = _roomsWallBrush;
                            }
                            using (var colorBrush2 = getRoomBrush(room.Room, colorBrush))
                                e.Graphics.FillRectangle(colorBrush2, roomRect);
                            if (!CheckRoom(room.MinDepth, room.MaxDepth))
                            {
                                e.Graphics.FillRectangle(_roomsOutsideOverdraw, roomRect);
                            }
                            if (room.Room.Locked)
                            {
                                e.Graphics.FillRectangle(_roomsLockedBrush, roomRect);
                            }

                            // Find portals on the selected sector
                            Pen belowPen = _roomBoundsPen;
                            if (room.Block != null && room.Block.FloorPortal != null)
                            {
                                Room portalRoom = room.Block.FloorPortal.AdjoiningRoom;
                                if (i - 1 >= 0 && roomSequence[i - 1].Room == portalRoom)
                                {
                                    belowPen = _portalPen;
                                }
                            }
                            Pen abovePen = _roomBoundsPen;
                            if (room.Block != null && room.Block.CeilingPortal != null)
                            {
                                Room portalRoom = room.Block.CeilingPortal.AdjoiningRoom;
                                if (i + 1 < roomSequence.Count && roomSequence[i + 1].Room == portalRoom)
                                {
                                    abovePen = _portalPen;
                                }
                            }

                            //Draw room borders
                            e.Graphics.DrawLine(belowPen, posX0, posY1, posX1, posY1);
                            e.Graphics.DrawLine(abovePen, posX0, posY0, posX1, posY0);
                            e.Graphics.DrawLine(_sequenceSeperatorPen, posX0, posY0, posX0, posY1);
                            e.Graphics.DrawLine(_sequenceSeperatorPen, posX1, posY0, posX1, posY1);
                        }
                    }
                }
            }

            // Draw outline around the groups
            for (int groupIndex = 0; groupIndex < GroupCount; ++groupIndex)
            {
                RectangleF groupArea = groupGetArea(barArea, groupIndex);
                e.Graphics.DrawRectangle(_outlinePen, groupArea);
            }
        }