Example #1
0
        public SectorBasedObjectInstance Clone(RectangleInt2 area)
        {
            var result = (SectorBasedObjectInstance)Clone();

            result.Area = area;
            return(result);
        }
Example #2
0
        public void RenderText(IEnumerable <Text> texts)
        {
            // Collect actual glyphs to render
            var glyphRenderInfos  = new List <RenderingFont.GlyphRenderInfo>();
            var overlayRectangles = new List <RectangleInt2>();
            RenderingTextureAllocator textureAllocator = null;

            foreach (Text text in texts)
            {
                // Build glyphs using the right font
                Vector2 pixelPos = text.PixelPos + text.Pos * Size * 0.5f;
                pixelPos += (text.ScreenAlignment * 2 - new Vector2(1)) * Size * new Vector2(0.5f, -0.5f);
                RectangleInt2 rect = text.Font.ParseString(text.String, text.Overlay, glyphRenderInfos, VectorInt2.FromRounded(pixelPos), text.TextAlignment);
                if (rect != RectangleInt2.Zero)
                {
                    overlayRectangles.Add(rect);
                }

                // Check texture allocator
                if (textureAllocator == null)
                {
                    textureAllocator = text.Font.TextureAllocator;
                }
                else if (textureAllocator != text.Font.TextureAllocator)
                {
                    throw new ArgumentException("Texts are using different texture allocators. This is not allowed in a single 'RenderText' call.");
                }
            }
            if (glyphRenderInfos.Count == 0)
            {
                return;
            }
            RenderGlyphs(textureAllocator, glyphRenderInfos, overlayRectangles);
        }
Example #3
0
        public RectangleInt2 TransformRect(RectangleInt2 area, VectorInt2 oldSize)
        {
            VectorInt2 first  = Transform(area.Start, oldSize);
            VectorInt2 second = Transform(area.End, oldSize);

            return(new RectangleInt2(VectorInt2.Min(first, second), VectorInt2.Max(first, second)));
        }
Example #4
0
        public static List <RectangleInt2> SplitIntoRectangles(RectangleInt2 area, Func <VectorInt2, bool> sectorToBeCovered)
        {
            // Check were the map must be covered
            bool[,] toBeCoveredMap = new bool[area.Width + 1, area.Height + 1];
            for (int x = 0; x <= area.Width; ++x)
            {
                for (int z = 0; z <= area.Height; ++z)
                {
                    toBeCoveredMap[x, z] = sectorToBeCovered(new VectorInt2(x, z) + area.Start);
                }
            }

            // Add rectanges greedily to cover space
            List <RectangleInt2> result = new List <RectangleInt2>();

            for (int currentX = 0; currentX <= area.Width; ++currentX)
            {
                for (int currentZ = 0; currentZ <= area.Height; ++currentZ)
                {
                    if (toBeCoveredMap[currentX, currentZ])
                    { // Needs to be covered with a rectangles.
                        // Create a rectangle and cover as much space as possible
                        int endX = currentX;
                        while (endX < area.Width)
                        {
                            if (!toBeCoveredMap[endX + 1, currentZ])
                            {
                                break;
                            }
                            ++endX;
                        }
                        int endZ = currentZ;
                        while (endZ < area.Height)
                        {
                            for (int x = currentX; x <= endX; ++x)
                            {
                                if (!toBeCoveredMap[x, endZ + 1])
                                {
                                    goto ExitEndZSearch;
                                }
                            }
                            ++endZ;
                        }
ExitEndZSearch:

                        // Update map and create actual rectangle
                        for (int x = currentX; x <= endX; ++x)
                        {
                            for (int z = currentZ; z <= endZ; ++z)
                            {
                                toBeCoveredMap[x, z] = false;
                            }
                        }
                        result.Add(new RectangleInt2(currentX, currentZ, endX, endZ) + area.Start);
                    }
                }
            }
            return(result);
        }
Example #5
0
        private static bool LoadSprites(ChunkReader chunkIO, ChunkId idOuter, Wad2 wad, ref Dictionary <long, WadSprite> outSprites)
        {
            if (idOuter != Wad2Chunks.Sprites)
            {
                return(false);
            }

            var  sprites       = new Dictionary <long, WadSprite>();
            long obsoleteIndex = 0; // Move this into each chunk once we got rid of old style *.wad2 files.

            chunkIO.ReadChunks((id, chunkSize) =>
            {
                if (id != Wad2Chunks.Sprite)
                {
                    return(false);
                }

                int width          = LEB128.ReadInt(chunkIO.Raw);
                int height         = LEB128.ReadInt(chunkIO.Raw);
                byte[] imageData   = null;
                RectangleInt2 rect = new RectangleInt2();

                chunkIO.ReadChunks((id2, chunkSize2) =>
                {
                    if (id2 == Wad2Chunks.SpriteIndex)
                    {
                        obsoleteIndex = chunkIO.ReadChunkLong(chunkSize2);
                    }
                    else if (id2 == Wad2Chunks.SpriteData)
                    {
                        imageData = chunkIO.ReadChunkArrayOfBytes(chunkSize2);
                    }
                    else if (id2 == Wad2Chunks.SpriteSides)
                    {
                        rect.X0 = chunkIO.Raw.ReadInt32();
                        rect.Y0 = chunkIO.Raw.ReadInt32();
                        rect.X1 = chunkIO.Raw.ReadInt32();
                        rect.Y1 = chunkIO.Raw.ReadInt32();
                    }
                    else
                    {
                        return(false);
                    }
                    return(true);
                });

                sprites.Add(obsoleteIndex++, new WadSprite {
                    Texture   = new WadTexture(ImageC.FromByteArray(imageData, width, height)),
                    Alignment = rect
                })
                ;
                return(true);
            });

            outSprites = sprites;
            return(true);
        }
Example #6
0
        protected RectangleF ToVisualCoord(RectangleInt2 sectorArea)
        {
            PointF convertedPoint0 = ToVisualCoord(sectorArea.Start);
            PointF convertedPoint1 = ToVisualCoord(sectorArea.End);
            float  gridStep        = GetGridStep();

            return(RectangleF.FromLTRB(
                       Math.Min(convertedPoint0.X, convertedPoint1.X), Math.Min(convertedPoint0.Y, convertedPoint1.Y),
                       Math.Max(convertedPoint0.X, convertedPoint1.X) + gridStep, Math.Max(convertedPoint0.Y, convertedPoint1.Y) + gridStep));
        }
Example #7
0
        public IReadOnlyList <Room> TransformRooms(IEnumerable <Room> roomsToRotate, RectTransformation transformation)
        {
            IReadOnlyList <Room> rooms       = roomsToRotate as IReadOnlyList <Room> ?? roomsToRotate.ToList();
            RectangleInt2        coveredArea = new RectangleInt2(int.MaxValue, int.MaxValue, int.MinValue, int.MinValue);

            foreach (Room room in rooms)
            {
                coveredArea = coveredArea.Union(room.WorldArea);
            }
            return(TransformRooms(rooms, transformation, new VectorInt2((coveredArea.X0 + coveredArea.X1) / 2, (coveredArea.Y0 + coveredArea.Y1) / 2)));
        }
Example #8
0
        private static void ConvertTrLevelSprites(Wad2 wad, TrLevel oldLevel)
        {
            ImageC tiles = ImageC.FromByteArray(oldLevel.TextureMap32, 256, oldLevel.TextureMap32.Length / 1024);

            foreach (var oldSequence in oldLevel.SpriteSequences)
            {
                int lengthOfSequence = -oldSequence.NegativeLength;
                int startIndex       = oldSequence.Offset;

                var newSequence = new WadSpriteSequence(new WadSpriteSequenceId((uint)oldSequence.ObjectID));
                for (int i = startIndex; i < startIndex + lengthOfSequence; i++)
                {
                    tr_sprite_texture oldSpriteTexture = oldLevel.SpriteTextures[i];

                    int spriteX, spriteY, spriteWidth, spriteHeight;

                    int x1 = oldSpriteTexture.LeftSide;
                    int x2 = oldSpriteTexture.RightSide;
                    int y1 = oldSpriteTexture.TopSide;
                    int y2 = oldSpriteTexture.BottomSide;

                    if (oldLevel.Version == TRVersion.Game.TR1 ||
                        oldLevel.Version == TRVersion.Game.TR2 ||
                        oldLevel.Version == TRVersion.Game.TR3)
                    {
                        spriteX      = oldSpriteTexture.X;
                        spriteY      = oldSpriteTexture.Y;
                        spriteWidth  = ((oldSpriteTexture.Width - 255) / 256 + 1);
                        spriteHeight = ((oldSpriteTexture.Height - 255) / 256 + 1);
                    }
                    else
                    {
                        spriteX      = oldSpriteTexture.LeftSide;
                        spriteY      = oldSpriteTexture.TopSide;
                        spriteWidth  = ((oldSpriteTexture.Width / 256) + 1);
                        spriteHeight = ((oldSpriteTexture.Height / 256) + 1);
                    }

                    // Add current sprite to the sequence
                    var spriteImage = ImageC.CreateNew(spriteWidth, spriteHeight);
                    spriteImage.CopyFrom(0, 0, tiles, spriteX, spriteY + oldSpriteTexture.Tile * 256, spriteWidth, spriteHeight);
                    RectangleInt2 rect = new RectangleInt2(x1, y1, x2, y2);
                    newSequence.Sprites.Add(new WadSprite {
                        Texture   = new WadTexture(spriteImage),
                        Alignment = rect
                    });
                }

                wad.SpriteSequences.Add(newSequence.Id, newSequence);
            }
        }
Example #9
0
        public static RectangleInt2 GetOppositePortalArea(PortalDirection direction, RectangleInt2 area)
        {
            switch (direction)
            {
            case PortalDirection.WallPositiveX:
                return(area + new VectorInt2(-1, 0));

            case PortalDirection.WallPositiveZ:
                return(area + new VectorInt2(0, -1));

            case PortalDirection.WallNegativeZ:
                return(area + new VectorInt2(0, 1));

            case PortalDirection.WallNegativeX:
                return(area + new VectorInt2(1, 0));

            default:
                return(area);
            }
        }
Example #10
0
        public override RectangleInt2 GetValidArea(RectangleInt2 newLocalRoomArea)
        {
            switch (Direction) // Special constraints for portals on walls
            {
            case PortalDirection.WallPositiveZ:
                return(newLocalRoomArea.Inflate(-1, 0));

            case PortalDirection.WallNegativeZ:
                return(newLocalRoomArea.Inflate(-1, 0));

            case PortalDirection.WallPositiveX:
                return(newLocalRoomArea.Inflate(0, -1));

            case PortalDirection.WallNegativeX:
                return(newLocalRoomArea.Inflate(0, -1));

            default:
                return(newLocalRoomArea.Inflate(-1, -1));
            }
        }
Example #11
0
        private static int GetTextureAreaPage(TextureArea textureArea1, TextureArea?textureArea2)
        {
            int width     = textureArea1.Texture.Image.Width;
            int height    = textureArea1.Texture.Image.Height;
            int numXPages = (int)Math.Ceiling((float)width / SplitPageSize);
            int numYPages = (int)Math.Ceiling((float)height / SplitPageSize);

            Rectangle2 textureRect = textureArea2 != null?textureArea1.GetRect().Union(textureArea2.Value.GetRect()) : textureArea1.GetRect();

            for (int yPage = 0; yPage < numYPages; yPage++)
            {
                for (int xPage = 0; xPage < numXPages; xPage++)
                {
                    Rectangle2 pageRect = new RectangleInt2(xPage * SplitPageSize, yPage * SplitPageSize, (xPage + 1) * SplitPageSize, (yPage + 1) * SplitPageSize);
                    if (pageRect.Contains(textureRect))
                    {
                        return(yPage * numXPages + xPage);
                    }
                }
            }
            return(-1);
        }
            protected override void PaintSectorTile(PaintEventArgs e, RectangleF sectorArea, int x, int z)
            {
                Room          room    = Parent._roomToResize;
                RectangleInt2 newArea = Parent.NewArea;
                VectorInt2    old     = new VectorInt2(x, z) + newArea.Start;

                // Draw new border wall
                if ((x == 0) || (z == 0) || (x == newArea.Width) || (z == newArea.Height))
                {
                    // Draw border wall using old room if possible
                    if ((newArea.X0 == 0 && x == 0 && room.LocalArea.Inflate(0, -1).Contains(old) && 0 < z && z < newArea.Height) ||
                        (newArea.Y0 == 0 && z == 0 && room.LocalArea.Inflate(-1, 0).Contains(old) && 0 < x && x < newArea.Width) ||
                        (newArea.X1 == room.NumXSectors - 1 && x == newArea.Width && room.LocalArea.Inflate(0, -1).Contains(old) && 0 < z && z < newArea.Height) ||
                        (newArea.Y1 == room.NumZSectors - 1 && z == newArea.Height && room.LocalArea.Inflate(-1, 0).Contains(old) && 0 < x && x < newArea.Width))
                    {
                        base.PaintSectorTile(e, sectorArea, old.X, old.Y);
                    }
                    else
                    {
                        using (var b = new SolidBrush(Parent._editor.Configuration.UI_ColorScheme.ColorBorderWall.ToWinFormsColor()))
                            e.Graphics.FillRectangle(b, sectorArea);
                    }
                    return;
                }

                // Draw inner parts of the old room
                if (old.X > 0 && old.Y > 0 && old.X < (room.NumXSectors - 1) && old.Y < (room.NumZSectors - 1))
                {
                    base.PaintSectorTile(e, sectorArea, old.X, old.Y);
                    return;
                }

                // Draw new floor
                using (var b = new SolidBrush(Parent.UseFloor ?
                                              Parent._editor.Configuration.UI_ColorScheme.ColorFloor.ToWinFormsColor() :
                                              Parent._editor.Configuration.UI_ColorScheme.ColorWall.ToWinFormsColor()))
                    e.Graphics.FillRectangle(b, sectorArea);
            }
        public FormResizeRoom(Editor editor, Room roomToResize, RectangleInt2 newArea)
        {
            InitializeComponent();
            gridControl.Parent = this;
            gridControl.Room   = roomToResize;
            _editor            = editor;
            _roomToResize      = roomToResize;

            roomIcon.Image = Properties.Resources.misc_North;

            try
            {
                _alreadyUpdatingGui = true;
                numericXn.Value     = -newArea.X0;
                numericZn.Value     = -newArea.Y0;
                numericXp.Value     = newArea.X1 + 1 - _roomToResize.NumXSectors;
                numericZp.Value     = newArea.Y1 + 1 - _roomToResize.NumZSectors;
            }
            finally
            {
                _alreadyUpdatingGui = false;
            }
            UpdateGui();
        }
Example #14
0
        public unsafe RectangleInt2 ParseString(string str, bool buildOverlay, List <GlyphRenderInfo> outGlyphRenderInfos, VectorInt2 offsetedPos = new VectorInt2(), Vector2 alignment = new Vector2())
        {
            RectangleInt2?result = null;

            // Do line breaking
            List <string> lines     = new List <string>();
            int           lineStart = 0;

            for (int i = 0; i < str.Length; ++i)
            {
                if (str[i] == '\n')
                {
                    bool hadR    = i != 0 && str[i - 1] == '\r';
                    int  lineEnd = i - (hadR ? 1 : 0);
                    lines.Add(str.Substring(lineStart, lineEnd - lineStart));
                    lineStart = i + 1;
                }
            }
            if (lineStart < str.Length)
            {
                lines.Add(str.Substring(lineStart));
            }

            // Handle line by line
            int totalHeight      = (lines.Count - 1) * _lineSpaceing + _lineAscent;
            int alignmentOffsetY = (int)(totalHeight * alignment.Y + 0.5f);

            for (int i = 0; i < lines.Count; ++i)
            {
                // Figure out glyph placement
                GDI.GCP_RESULTS gcp;
                gcp.StructSize = Marshal.SizeOf(typeof(GDI.GCP_RESULTS));
                gcp.OutString  = IntPtr.Zero;
                gcp.Order      = _gdiGetCharacterPlacementOrder;
                gcp.Dx         = _gdiGetCharacterPlacementDx;
                gcp.CaretPos   = IntPtr.Zero;
                gcp.Class      = IntPtr.Zero;
                gcp.Glyphs     = _gdiGetCharacterPlacementGlpyhs;
                gcp.GlyphCount = _gdiGetCharacterPlacementGlyphCount;
                gcp.MaxFit     = int.MaxValue;
                uint dimensions = GDI.GetCharacterPlacementW(_gdiHdc, lines[i], lines[i].Length, int.MaxValue, ref gcp, GDI.GCPFlags.GCP_LIGATE | GDI.GCPFlags.GCP_REORDER | GDI.GCPFlags.GCP_DIACRITIC | GDI.GCPFlags.GCP_USEKERNING);
                if (dimensions == 0)
                {
                    throw new GDI.GDIException("GetCharacterPlacementW");
                }
                int width  = (int)(dimensions & 0xffff);
                int height = (int)(dimensions >> 16);

                // Make each glyph available
                uint *      orderPtr         = (uint *)gcp.Order;
                int *       dxPtr            = (int *)gcp.Dx;
                GlyphIndex *gylphPtr         = (GlyphIndex *)gcp.Glyphs;
                int         alignmentOffsetX = (int)(alignment.X * width + 0.5f);
                VectorInt2  pos = offsetedPos + new VectorInt2(-alignmentOffsetX, alignmentOffsetY - _lineAscent - i * _lineSpaceing);
                for (int j = 0; j < gcp.GlyphCount; ++j)
                {
                    ushort glyphIndex = gylphPtr[orderPtr[j]];
                    int    dx         = dxPtr[orderPtr[j]];

                    GlyphData  glyphData   = GetOrCreateGlyph(glyphIndex);
                    VectorInt3 texPosition = TextureAllocator.Get(new RenderingTexture(glyphData.Image)
                    {
                        Tag = glyphData
                    });                                                                                                       // Tag the glyph data to keep the weak reference alive

                    var posStart = pos + glyphData.Offset + new VectorInt2(0, -glyphData.Image.Size.Y);
                    var posEnd   = pos + glyphData.Offset + new VectorInt2(glyphData.Image.Size.X, 0);

                    // Generate rectangular font overlay
                    if (buildOverlay)
                    {
                        var rect = new RectangleInt2(posStart, posEnd);
                        if (!result.HasValue)
                        {
                            result = rect;
                        }
                        else
                        {
                            result = result.Value.Union(rect);
                        }
                    }

                    outGlyphRenderInfos.Add(new GlyphRenderInfo
                    {
                        PosStart = posStart,
                        PosEnd   = posEnd,
                        TexStart = texPosition,
                        TexSize  = glyphData.Image.Size
                    });

                    pos.X += dx;
                }
            }

            return(result.HasValue ? result.Value.Inflate(2) : RectangleInt2.Zero);
        }
        public SelectedGeometryContextMenu(Editor editor, IWin32Window owner, Room targetRoom, RectangleInt2 targetArea, VectorInt2 targetBlock)
            : base(editor, owner)
        {
            Items.Add(new ToolStripMenuItem("Paste object", Properties.Resources.general_clipboard_16, (o, e) =>
            {
                EditorActions.PasteObject(targetBlock, targetRoom);
            })
            {
                Enabled = Clipboard.ContainsData(typeof(ObjectClipboardData).FullName)
            });
            Items.Add(new ToolStripSeparator());

            Items.Add(new ToolStripMenuItem("Move Lara", null, (o, e) =>
            {
                EditorActions.MoveLara(this, targetRoom, targetBlock);
            }));
            Items.Add(new ToolStripSeparator());

            Items.Add(new ToolStripMenuItem("Add trigger", null, (o, e) =>
            {
                EditorActions.AddTrigger(targetRoom, targetArea, this);
            }));

            Items.Add(new ToolStripMenuItem("Add portal", null, (o, e) =>
            {
                EditorActions.AddPortal(targetRoom, targetArea, this);
            }));
            Items.Add(new ToolStripSeparator());

            Items.Add(new ToolStripMenuItem("Add camera", Properties.Resources.objects_Camera_16, (o, e) =>
            {
                EditorActions.PlaceObject(targetRoom, targetBlock, new CameraInstance());
            }));

            Items.Add(new ToolStripMenuItem("Add fly-by camera", Properties.Resources.objects_movie_projector_16, (o, e) =>
            {
                EditorActions.PlaceObject(targetRoom, targetBlock, new FlybyCameraInstance(editor.SelectedObject));
            }));

            Items.Add(new ToolStripMenuItem("Add sink", Properties.Resources.objects_tornado_16, (o, e) =>
            {
                EditorActions.PlaceObject(targetRoom, targetBlock, new SinkInstance());
            }));

            Items.Add(new ToolStripMenuItem("Add sound source", Properties.Resources.objects_speaker_16, (o, e) =>
            {
                EditorActions.PlaceObject(targetRoom, targetBlock, new SoundSourceInstance());
            }));

            Items.Add(new ToolStripMenuItem("Add imported geometry", Properties.Resources.objects_custom_geometry, (o, e) =>
            {
                EditorActions.PlaceObject(targetRoom, targetBlock, new ImportedGeometryInstance());
            }));

            Items.Add(new ToolStripSeparator());

            Items.Add(new ToolStripMenuItem("Crop room", Properties.Resources.general_crop_16, (o, e) =>
            {
                EditorActions.CropRoom(targetRoom, targetArea, this);
            }));

            Items.Add(new ToolStripMenuItem("Split room", Properties.Resources.actions_Split_16, (o, e) =>
            {
                EditorActions.SplitRoom(this);
            }));
        }
Example #16
0
 public TextureView(Texture texture, RectangleInt2 area)
 {
     Texture = texture;
     Area    = area;
 }
Example #17
0
        } = 0x1f;                                  // Only the lower 5 bits are used.

        public TriggerInstance(RectangleInt2 area)
            : base(area)
        {
        }
Example #18
0
 public override void Transform(RectTransformation transformation, VectorInt2 oldRoomSize)
 {
     base.Transform(transformation, oldRoomSize);
     _area = transformation.TransformRect(_area, oldRoomSize);
 }
Example #19
0
 public virtual RectangleInt2 GetValidArea(RectangleInt2 newLocalRoomArea)
 {
     return(newLocalRoomArea.Inflate(-1)); // Not on room walls
 }
Example #20
0
 public PortalInstance(RectangleInt2 area, PortalDirection direction, Room adjoiningRoom = null)
     : base(area)
 {
     AdjoiningRoom = adjoiningRoom;
     Direction     = direction;
 }
Example #21
0
 public SectorBasedObjectInstance(RectangleInt2 area)
 {
     Area = area;
 }