public SectorBasedObjectInstance Clone(RectangleInt2 area) { var result = (SectorBasedObjectInstance)Clone(); result.Area = area; return(result); }
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); }
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))); }
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); }
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); }
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)); }
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))); }
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); } }
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); } }
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)); } }
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(); }
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); })); }
public TextureView(Texture texture, RectangleInt2 area) { Texture = texture; Area = area; }
} = 0x1f; // Only the lower 5 bits are used. public TriggerInstance(RectangleInt2 area) : base(area) { }
public override void Transform(RectTransformation transformation, VectorInt2 oldRoomSize) { base.Transform(transformation, oldRoomSize); _area = transformation.TransformRect(_area, oldRoomSize); }
public virtual RectangleInt2 GetValidArea(RectangleInt2 newLocalRoomArea) { return(newLocalRoomArea.Inflate(-1)); // Not on room walls }
public PortalInstance(RectangleInt2 area, PortalDirection direction, Room adjoiningRoom = null) : base(area) { AdjoiningRoom = adjoiningRoom; Direction = direction; }
public SectorBasedObjectInstance(RectangleInt2 area) { Area = area; }