From 1a56f18e3a755316c430b1ecd80af35c418b0c17 Mon Sep 17 00:00:00 2001 From: Kewin Kupilas Date: Sat, 14 Dec 2024 12:47:41 +0000 Subject: [PATCH 01/19] Restored everything except RoomGeometry --- .../Panel3D/MouseHandler/Panel3DMouseDown.cs | 9 +- .../Panel3D/MouseHandler/Panel3DMouseMove.cs | 2 +- TombEditor/Controls/Panel3D/Panel3DDraw.cs | 173 +++++- TombEditor/Controls/ToolBox.Designer.cs | 570 +++++++++--------- TombEditor/Controls/ToolBox.cs | 14 + TombEditor/Controls/ToolBox.resx | 12 + TombEditor/Editor.cs | 3 + TombEditor/EditorActions.cs | 77 +-- TombEditor/Forms/FormTextureRemap.cs | 3 +- .../icons_general/general-sticker-16.png | Bin 0 -> 341 bytes .../DirectX11/Dx11RenderingDrawingRoom.cs | 4 +- .../GeometryIO/RoomGeometryExporter.cs | 8 +- TombLib/TombLib/LevelData/Compilers/Rooms.cs | 8 +- .../TombLib/LevelData/Compilers/Textures.cs | 4 +- .../LevelData/Compilers/TombEngine/Rooms.cs | 8 +- .../Compilers/TombEngine/Textures.cs | 4 +- TombLib/TombLib/LevelData/IO/LegacyRepair.cs | 64 +- TombLib/TombLib/LevelData/IO/Prj2Chunks.cs | 2 + TombLib/TombLib/LevelData/IO/Prj2Loader.cs | 19 +- TombLib/TombLib/LevelData/IO/Prj2Writer.cs | 13 +- TombLib/TombLib/LevelData/IO/PrjLoader.cs | 9 +- TombLib/TombLib/LevelData/Level.cs | 7 +- TombLib/TombLib/LevelData/Room.cs | 23 +- TombLib/TombLib/LevelData/Sector.cs | 107 ++-- .../LevelData/SectorEnums/FaceLayer.cs | 8 + .../SectorGeometry/SectorFaceData.cs | 14 +- .../LevelData/SectorStructs/FaceLayerInfo.cs | 17 + .../SectorStructs/SectorFaceIdentity.cs | 16 +- TombLib/TombLib/Utils/RectTransformation.cs | 36 +- 29 files changed, 733 insertions(+), 501 deletions(-) create mode 100644 TombEditor/Resources/icons_general/general-sticker-16.png create mode 100644 TombLib/TombLib/LevelData/SectorEnums/FaceLayer.cs create mode 100644 TombLib/TombLib/LevelData/SectorStructs/FaceLayerInfo.cs diff --git a/TombEditor/Controls/Panel3D/MouseHandler/Panel3DMouseDown.cs b/TombEditor/Controls/Panel3D/MouseHandler/Panel3DMouseDown.cs index 08b3b2226..bff51bba3 100644 --- a/TombEditor/Controls/Panel3D/MouseHandler/Panel3DMouseDown.cs +++ b/TombEditor/Controls/Panel3D/MouseHandler/Panel3DMouseDown.cs @@ -7,6 +7,7 @@ using TombLib; using TombLib.LevelData.SectorEnums; using TombLib.LevelData.SectorEnums.Extensions; +using TombLib.LevelData.SectorStructs; namespace TombEditor.Controls.Panel3D { @@ -161,19 +162,19 @@ private void OnMouseButtonDownLeft(Point location) { if (ModifierKeys.HasFlag(Keys.Shift)) { - EditorActions.RotateTexture(_editor.SelectedRoom, pos, newSectorPicking.Face); + EditorActions.RotateTexture(_editor.SelectedRoom, pos, new FaceLayerInfo(newSectorPicking.Face, _editor.ActiveTextureLayer)); break; } else if (ModifierKeys.HasFlag(Keys.Control)) { - EditorActions.MirrorTexture(_editor.SelectedRoom, pos, newSectorPicking.Face); + EditorActions.MirrorTexture(_editor.SelectedRoom, pos, new FaceLayerInfo(newSectorPicking.Face, _editor.ActiveTextureLayer)); break; } } if (ModifierKeys.HasFlag(Keys.Alt)) { - EditorActions.PickTexture(_editor.SelectedRoom, pos, newSectorPicking.Face); + EditorActions.PickTexture(_editor.SelectedRoom, pos, new FaceLayerInfo(newSectorPicking.Face, _editor.ActiveTextureLayer)); } else if (_editor.Tool.Tool == EditorToolType.GridPaint && !_editor.HighlightedSectors.Empty) { @@ -212,7 +213,7 @@ private void OnMouseButtonDownLeft(Point location) case EditorToolType.Brush: case EditorToolType.Pencil: - EditorActions.ApplyTexture(_editor.SelectedRoom, pos, newSectorPicking.Face, _editor.SelectedTexture); + EditorActions.ApplyTexture(_editor.SelectedRoom, pos, new FaceLayerInfo(newSectorPicking.Face, _editor.ActiveTextureLayer), _editor.SelectedTexture); _toolHandler.Engage(location.X, location.Y, newSectorPicking, false); break; diff --git a/TombEditor/Controls/Panel3D/MouseHandler/Panel3DMouseMove.cs b/TombEditor/Controls/Panel3D/MouseHandler/Panel3DMouseMove.cs index 091fa5cb8..ac5b3b8a7 100644 --- a/TombEditor/Controls/Panel3D/MouseHandler/Panel3DMouseMove.cs +++ b/TombEditor/Controls/Panel3D/MouseHandler/Panel3DMouseMove.cs @@ -296,7 +296,7 @@ private bool OnMouseMovedLeft(Point location) { if (_editor.SelectedSectors.Valid && _editor.SelectedSectors.Area.Contains(pos) || _editor.SelectedSectors.Empty) - return EditorActions.ApplyTexture(_editor.SelectedRoom, pos, newSectorPicking.Face, _editor.SelectedTexture, true); + return EditorActions.ApplyTexture(_editor.SelectedRoom, pos, new(newSectorPicking.Face, _editor.ActiveTextureLayer), _editor.SelectedTexture, true); } else if (_editor.Tool.Tool == EditorToolType.GridPaint && _toolHandler.Engaged) { diff --git a/TombEditor/Controls/Panel3D/Panel3DDraw.cs b/TombEditor/Controls/Panel3D/Panel3DDraw.cs index 53f2580b3..61515f614 100644 --- a/TombEditor/Controls/Panel3D/Panel3DDraw.cs +++ b/TombEditor/Controls/Panel3D/Panel3DDraw.cs @@ -4,7 +4,6 @@ using System.Drawing; using System.Linq; using System.Numerics; -using System.Windows.Forms; using TombLib; using TombLib.Controls; using TombLib.Graphics; @@ -332,38 +331,38 @@ void HandleDiagonal(int x, int z, SectorSurface surface, int yOffset) if (splitIndex is < 0 or > 7) // QA or WS { // PositiveZ Floor - if (currentRoom.RoomGeometry.VertexRangeLookup.ContainsKey(new SectorFaceIdentity(x, z, SectorFace.Wall_PositiveZ_QA))) + if (currentRoom.RoomGeometry.VertexRangeLookup.ContainsKey(new(x, z, new(SectorFace.Wall_PositiveZ_QA, FaceLayer.Base)))) HandlePositiveZ(x, z, targetSector.Floor, yOffset); // PositiveZ Ceiling - if (currentRoom.RoomGeometry.VertexRangeLookup.ContainsKey(new SectorFaceIdentity(x, z, SectorFace.Wall_PositiveZ_WS))) + if (currentRoom.RoomGeometry.VertexRangeLookup.ContainsKey(new(x, z, new(SectorFace.Wall_PositiveZ_WS, FaceLayer.Base)))) HandlePositiveZ(x, z, targetSector.Ceiling, yOffset); // PositiveX Floor - if (currentRoom.RoomGeometry.VertexRangeLookup.ContainsKey(new SectorFaceIdentity(x, z, SectorFace.Wall_PositiveX_QA))) + if (currentRoom.RoomGeometry.VertexRangeLookup.ContainsKey(new(x, z, new(SectorFace.Wall_PositiveX_QA, FaceLayer.Base)))) HandlePositiveX(x, z, targetSector.Floor, yOffset); // PositiveX Ceiling - if (currentRoom.RoomGeometry.VertexRangeLookup.ContainsKey(new SectorFaceIdentity(x, z, SectorFace.Wall_PositiveX_WS))) + if (currentRoom.RoomGeometry.VertexRangeLookup.ContainsKey(new(x, z, new(SectorFace.Wall_PositiveX_WS, FaceLayer.Base)))) HandlePositiveX(x, z, targetSector.Ceiling, yOffset); // NegativeZ Floor - if (currentRoom.RoomGeometry.VertexRangeLookup.ContainsKey(new SectorFaceIdentity(x, z, SectorFace.Wall_NegativeZ_QA))) + if (currentRoom.RoomGeometry.VertexRangeLookup.ContainsKey(new(x, z, new(SectorFace.Wall_NegativeZ_QA, FaceLayer.Base)))) HandleNegativeZ(x, z, targetSector.Floor, yOffset); // NegativeZ Ceiling - if (currentRoom.RoomGeometry.VertexRangeLookup.ContainsKey(new SectorFaceIdentity(x, z, SectorFace.Wall_NegativeZ_WS))) + if (currentRoom.RoomGeometry.VertexRangeLookup.ContainsKey(new(x, z, new(SectorFace.Wall_NegativeZ_WS, FaceLayer.Base)))) HandleNegativeZ(x, z, targetSector.Ceiling, yOffset); // NegativeX Floor - if (currentRoom.RoomGeometry.VertexRangeLookup.ContainsKey(new SectorFaceIdentity(x, z, SectorFace.Wall_NegativeX_QA))) + if (currentRoom.RoomGeometry.VertexRangeLookup.ContainsKey(new(x, z, new(SectorFace.Wall_NegativeX_QA, FaceLayer.Base)))) HandleNegativeX(x, z, targetSector.Floor, yOffset); // NegativeX Ceiling - if (currentRoom.RoomGeometry.VertexRangeLookup.ContainsKey(new SectorFaceIdentity(x, z, SectorFace.Wall_NegativeX_WS))) + if (currentRoom.RoomGeometry.VertexRangeLookup.ContainsKey(new(x, z, new(SectorFace.Wall_NegativeX_WS, FaceLayer.Base)))) HandleNegativeX(x, z, targetSector.Ceiling, yOffset); // Diagonal Floor - if (currentRoom.RoomGeometry.VertexRangeLookup.ContainsKey(new SectorFaceIdentity(x, z, SectorFace.Wall_Diagonal_QA))) + if (currentRoom.RoomGeometry.VertexRangeLookup.ContainsKey(new(x, z, new(SectorFace.Wall_Diagonal_QA, FaceLayer.Base)))) HandleDiagonal(x, z, targetSector.Floor, yOffset); // Diagonal Ceiling - if (currentRoom.RoomGeometry.VertexRangeLookup.ContainsKey(new SectorFaceIdentity(x, z, SectorFace.Wall_Diagonal_WS))) + if (currentRoom.RoomGeometry.VertexRangeLookup.ContainsKey(new(x, z, new(SectorFace.Wall_Diagonal_WS, FaceLayer.Base)))) HandleDiagonal(x, z, targetSector.Ceiling, yOffset); } else // Actual splits @@ -381,23 +380,23 @@ void HandleDiagonal(int x, int z, SectorSurface surface, int yOffset) }; // PositiveZ - if (currentRoom.RoomGeometry.VertexRangeLookup.ContainsKey(new SectorFaceIdentity(x, z, SectorFaceExtensions.GetExtraFloorSplitFace(Direction.PositiveZ, splitIndex)))) + if (currentRoom.RoomGeometry.VertexRangeLookup.ContainsKey(new(x, z, new(SectorFaceExtensions.GetExtraFloorSplitFace(Direction.PositiveZ, splitIndex), FaceLayer.Base)))) HandlePositiveZ(x, z, floorSurface, yOffset); // PositiveX - if (currentRoom.RoomGeometry.VertexRangeLookup.ContainsKey(new SectorFaceIdentity(x, z, SectorFaceExtensions.GetExtraFloorSplitFace(Direction.PositiveX, splitIndex)))) + if (currentRoom.RoomGeometry.VertexRangeLookup.ContainsKey(new(x, z, new(SectorFaceExtensions.GetExtraFloorSplitFace(Direction.PositiveX, splitIndex), FaceLayer.Base)))) HandlePositiveX(x, z, floorSurface, yOffset); // NegativeZ - if (currentRoom.RoomGeometry.VertexRangeLookup.ContainsKey(new SectorFaceIdentity(x, z, SectorFaceExtensions.GetExtraFloorSplitFace(Direction.NegativeZ, splitIndex)))) + if (currentRoom.RoomGeometry.VertexRangeLookup.ContainsKey(new(x, z, new(SectorFaceExtensions.GetExtraFloorSplitFace(Direction.NegativeZ, splitIndex), FaceLayer.Base)))) HandleNegativeZ(x, z, floorSurface, yOffset); // NegativeX - if (currentRoom.RoomGeometry.VertexRangeLookup.ContainsKey(new SectorFaceIdentity(x, z, SectorFaceExtensions.GetExtraFloorSplitFace(Direction.NegativeX, splitIndex)))) + if (currentRoom.RoomGeometry.VertexRangeLookup.ContainsKey(new(x, z, new(SectorFaceExtensions.GetExtraFloorSplitFace(Direction.NegativeX, splitIndex), FaceLayer.Base)))) HandleNegativeX(x, z, floorSurface, yOffset); // Diagonal - if (currentRoom.RoomGeometry.VertexRangeLookup.ContainsKey(new SectorFaceIdentity(x, z, SectorFaceExtensions.GetExtraFloorSplitFace(Direction.Diagonal, splitIndex)))) + if (currentRoom.RoomGeometry.VertexRangeLookup.ContainsKey(new(x, z, new(SectorFaceExtensions.GetExtraFloorSplitFace(Direction.Diagonal, splitIndex), FaceLayer.Base)))) HandleDiagonal(x, z, floorSurface, yOffset); } @@ -414,23 +413,23 @@ void HandleDiagonal(int x, int z, SectorSurface surface, int yOffset) }; // PositiveZ - if (currentRoom.RoomGeometry.VertexRangeLookup.ContainsKey(new SectorFaceIdentity(x, z, SectorFaceExtensions.GetExtraCeilingSplitFace(Direction.PositiveZ, splitIndex)))) + if (currentRoom.RoomGeometry.VertexRangeLookup.ContainsKey(new(x, z, new(SectorFaceExtensions.GetExtraCeilingSplitFace(Direction.PositiveZ, splitIndex), FaceLayer.Base)))) HandlePositiveZ(x, z, ceilingSurface, yOffset); // PositiveX - if (currentRoom.RoomGeometry.VertexRangeLookup.ContainsKey(new SectorFaceIdentity(x, z, SectorFaceExtensions.GetExtraCeilingSplitFace(Direction.PositiveX, splitIndex)))) + if (currentRoom.RoomGeometry.VertexRangeLookup.ContainsKey(new(x, z, new(SectorFaceExtensions.GetExtraCeilingSplitFace(Direction.PositiveX, splitIndex), FaceLayer.Base)))) HandlePositiveX(x, z, ceilingSurface, yOffset); // NegativeZ - if (currentRoom.RoomGeometry.VertexRangeLookup.ContainsKey(new SectorFaceIdentity(x, z, SectorFaceExtensions.GetExtraCeilingSplitFace(Direction.NegativeZ, splitIndex)))) + if (currentRoom.RoomGeometry.VertexRangeLookup.ContainsKey(new(x, z, new(SectorFaceExtensions.GetExtraCeilingSplitFace(Direction.NegativeZ, splitIndex), FaceLayer.Base)))) HandleNegativeZ(x, z, ceilingSurface, yOffset); // NegativeX - if (currentRoom.RoomGeometry.VertexRangeLookup.ContainsKey(new SectorFaceIdentity(x, z, SectorFaceExtensions.GetExtraCeilingSplitFace(Direction.NegativeX, splitIndex)))) + if (currentRoom.RoomGeometry.VertexRangeLookup.ContainsKey(new(x, z, new(SectorFaceExtensions.GetExtraCeilingSplitFace(Direction.NegativeX, splitIndex), FaceLayer.Base)))) HandleNegativeX(x, z, ceilingSurface, yOffset); // Diagonal - if (currentRoom.RoomGeometry.VertexRangeLookup.ContainsKey(new SectorFaceIdentity(x, z, SectorFaceExtensions.GetExtraCeilingSplitFace(Direction.Diagonal, splitIndex)))) + if (currentRoom.RoomGeometry.VertexRangeLookup.ContainsKey(new(x, z, new(SectorFaceExtensions.GetExtraCeilingSplitFace(Direction.Diagonal, splitIndex), FaceLayer.Base)))) HandleDiagonal(x, z, ceilingSurface, yOffset); } } @@ -450,6 +449,136 @@ void HandleDiagonal(int x, int z, SectorSurface surface, int yOffset) _legacyDevice.Draw(PrimitiveType.TriangleList, buffer.ElementCount); } + private static Vector3 ShiftVector3(Vector3 vector, SectorFace face, DiagonalSplit diagonalSplit, float shift) + { + switch (face.GetDirection()) + { + case Direction.PositiveX: + vector.X += shift; + break; + case Direction.NegativeX: + vector.X -= shift; + break; + case Direction.PositiveZ: + vector.Z += shift; + break; + case Direction.NegativeZ: + vector.Z -= shift; + break; + case Direction.Diagonal: + switch (diagonalSplit) + { + case DiagonalSplit.XpZn: + vector.X -= shift; + vector.Z += shift; + break; + case DiagonalSplit.XnZn: + vector.X += shift; + vector.Z += shift; + break; + case DiagonalSplit.XnZp: + vector.X += shift; + vector.Z -= shift; + break; + case DiagonalSplit.XpZp: + vector.X -= shift; + vector.Z -= shift; + break; + } + + break; + default: // Either Floor or Ceiling + if (face.IsFloor()) + vector.Y += shift; + else + vector.Y -= shift; + break; + } + + return vector; + } + + private void DrawDecalOutlines(Effect effect) + { + if (_editor.Mode is not EditorMode.FaceEdit) + return; + + Room currentRoom = _editor.SelectedRoom; + var vertices = new List(); + + for (int x = currentRoom.LocalArea.X0; x <= currentRoom.LocalArea.X1; x++) + for (int z = currentRoom.LocalArea.Y0; z <= currentRoom.LocalArea.Y1; z++) + { + for (SectorFace face = 0; face < SectorFace.Count; face++) + { + Sector sector = currentRoom.Sectors[x, z]; + var key = new SectorFaceIdentity(x, z, new FaceLayerInfo(face, FaceLayer.Decal)); + + if (currentRoom.RoomGeometry.VertexRangeLookup.ContainsKey(key)) + { + VertexRange range = currentRoom.RoomGeometry.VertexRangeLookup[key]; + DiagonalSplit diagonalSplit = face.IsFloorWall() ? sector.Floor.DiagonalSplit : sector.Ceiling.DiagonalSplit; + + if (range.Count == 3) + { + vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start] + currentRoom.WorldPos, face, diagonalSplit, Level.DecalOffset))); + vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 1] + currentRoom.WorldPos, face, diagonalSplit, Level.DecalOffset))); + + vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 1] + currentRoom.WorldPos, face, diagonalSplit, Level.DecalOffset))); + vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 2] + currentRoom.WorldPos, face, diagonalSplit, Level.DecalOffset))); + + vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 2] + currentRoom.WorldPos, face, diagonalSplit, Level.DecalOffset))); + vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start] + currentRoom.WorldPos, face, diagonalSplit, Level.DecalOffset))); + } + else if (range.Count == 6) + { + if (face.IsCeiling()) + { + vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start] + currentRoom.WorldPos, face, diagonalSplit, Level.DecalOffset))); + vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 2] + currentRoom.WorldPos, face, diagonalSplit, Level.DecalOffset))); + + vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 2] + currentRoom.WorldPos, face, diagonalSplit, Level.DecalOffset))); + vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 3] + currentRoom.WorldPos, face, diagonalSplit, Level.DecalOffset))); + + vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 3] + currentRoom.WorldPos, face, diagonalSplit, Level.DecalOffset))); + vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 5] + currentRoom.WorldPos, face, diagonalSplit, Level.DecalOffset))); + + vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 5] + currentRoom.WorldPos, face, diagonalSplit, Level.DecalOffset))); + vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start] + currentRoom.WorldPos, face, diagonalSplit, Level.DecalOffset))); + } + else + { + vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start] + currentRoom.WorldPos, face, diagonalSplit, Level.DecalOffset))); + vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 1] + currentRoom.WorldPos, face, diagonalSplit, Level.DecalOffset))); + + vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 1] + currentRoom.WorldPos, face, diagonalSplit, Level.DecalOffset))); + vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 3] + currentRoom.WorldPos, face, diagonalSplit, Level.DecalOffset))); + + vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 3] + currentRoom.WorldPos, face, diagonalSplit, Level.DecalOffset))); + vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 2] + currentRoom.WorldPos, face, diagonalSplit, Level.DecalOffset))); + + vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 2] + currentRoom.WorldPos, face, diagonalSplit, Level.DecalOffset))); + vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start] + currentRoom.WorldPos, face, diagonalSplit, Level.DecalOffset))); + } + } + } + } + } + + if (vertices.Count == 0) + return; + + using Buffer buffer = SharpDX.Toolkit.Graphics.Buffer.Vertex.New(_legacyDevice, vertices.ToArray(), SharpDX.Direct3D11.ResourceUsage.Dynamic); + + _legacyDevice.SetRasterizerState(_legacyDevice.RasterizerStates.Default); + _legacyDevice.SetVertexBuffer(buffer); + _legacyDevice.SetVertexInputLayout(VertexInputLayout.FromBuffer(0, buffer)); + effect.Parameters["ModelViewProjection"].SetValue(_viewProjection.ToSharpDX()); + effect.Parameters["Color"].SetValue(Vector4.One); + effect.CurrentTechnique.Passes[0].Apply(); + _legacyDevice.Draw(PrimitiveType.LineList, buffer.ElementCount); + } + private void DrawLights(Effect effect, Room[] roomsWhoseObjectsToDraw, List textToDraw, List sprites) { _legacyDevice.SetRasterizerState(_rasterizerWireframe); @@ -1954,6 +2083,8 @@ private void DrawScene() DrawFlybyPath(effect); // Draw sector split highlights DrawSectorSplitHighlights(effect); + // Draw decal outlines + DrawDecalOutlines(effect); } // Draw ghost block cubes diff --git a/TombEditor/Controls/ToolBox.Designer.cs b/TombEditor/Controls/ToolBox.Designer.cs index 96fb1e5e4..9c8a67049 100644 --- a/TombEditor/Controls/ToolBox.Designer.cs +++ b/TombEditor/Controls/ToolBox.Designer.cs @@ -28,362 +28,362 @@ protected override void Dispose(bool disposing) /// private void InitializeComponent() { - this.toolStrip = new DarkUI.Controls.DarkToolStrip(); - this.toolSelection = new System.Windows.Forms.ToolStripButton(); - this.toolBrush = new System.Windows.Forms.ToolStripButton(); - this.toolShovel = new System.Windows.Forms.ToolStripButton(); - this.toolPencil = new System.Windows.Forms.ToolStripButton(); - this.toolFlatten = new System.Windows.Forms.ToolStripButton(); - this.toolSmooth = new System.Windows.Forms.ToolStripButton(); - this.toolFill = new System.Windows.Forms.ToolStripButton(); - this.toolGridPaint = new System.Windows.Forms.ToolStripButton(); - this.toolGroup = new System.Windows.Forms.ToolStripButton(); - this.toolSeparator1 = new System.Windows.Forms.ToolStripSeparator(); - this.toolDrag = new System.Windows.Forms.ToolStripButton(); - this.toolRamp = new System.Windows.Forms.ToolStripButton(); - this.toolQuarterPipe = new System.Windows.Forms.ToolStripButton(); - this.toolHalfPipe = new System.Windows.Forms.ToolStripButton(); - this.toolBowl = new System.Windows.Forms.ToolStripButton(); - this.toolPyramid = new System.Windows.Forms.ToolStripButton(); - this.toolTerrain = new System.Windows.Forms.ToolStripButton(); - this.toolEraser = new System.Windows.Forms.ToolStripButton(); - this.toolInvisibility = new System.Windows.Forms.ToolStripButton(); - this.toolSeparator2 = new System.Windows.Forms.ToolStripSeparator(); - this.toolPortalDigger = new System.Windows.Forms.ToolStripButton(); - this.toolUVFixer = new System.Windows.Forms.ToolStripButton(); - this.toolStrip.SuspendLayout(); - this.SuspendLayout(); + var resources = new System.ComponentModel.ComponentResourceManager(typeof(ToolBox)); + toolStrip = new DarkUI.Controls.DarkToolStrip(); + toolSelection = new System.Windows.Forms.ToolStripButton(); + toolBrush = new System.Windows.Forms.ToolStripButton(); + toolShovel = new System.Windows.Forms.ToolStripButton(); + toolPencil = new System.Windows.Forms.ToolStripButton(); + toolFlatten = new System.Windows.Forms.ToolStripButton(); + toolSmooth = new System.Windows.Forms.ToolStripButton(); + toolFill = new System.Windows.Forms.ToolStripButton(); + toolGridPaint = new System.Windows.Forms.ToolStripButton(); + toolGroup = new System.Windows.Forms.ToolStripButton(); + toolSeparator1 = new System.Windows.Forms.ToolStripSeparator(); + toolDrag = new System.Windows.Forms.ToolStripButton(); + toolRamp = new System.Windows.Forms.ToolStripButton(); + toolQuarterPipe = new System.Windows.Forms.ToolStripButton(); + toolHalfPipe = new System.Windows.Forms.ToolStripButton(); + toolBowl = new System.Windows.Forms.ToolStripButton(); + toolPyramid = new System.Windows.Forms.ToolStripButton(); + toolTerrain = new System.Windows.Forms.ToolStripButton(); + toolEraser = new System.Windows.Forms.ToolStripButton(); + toolInvisibility = new System.Windows.Forms.ToolStripButton(); + toolSeparator2 = new System.Windows.Forms.ToolStripSeparator(); + toolPortalDigger = new System.Windows.Forms.ToolStripButton(); + toolUVFixer = new System.Windows.Forms.ToolStripButton(); + toolSeparator3 = new System.Windows.Forms.ToolStripSeparator(); + toolDecalsMode = new System.Windows.Forms.ToolStripButton(); + toolStrip.SuspendLayout(); + SuspendLayout(); // // toolStrip // - this.toolStrip.AutoSize = false; - this.toolStrip.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(60)))), ((int)(((byte)(63)))), ((int)(((byte)(65))))); - this.toolStrip.CanOverflow = false; - this.toolStrip.Dock = System.Windows.Forms.DockStyle.Fill; - this.toolStrip.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(220)))), ((int)(((byte)(220))))); - this.toolStrip.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden; - this.toolStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.toolSelection, - this.toolBrush, - this.toolShovel, - this.toolPencil, - this.toolFlatten, - this.toolSmooth, - this.toolFill, - this.toolGridPaint, - this.toolGroup, - this.toolSeparator1, - this.toolDrag, - this.toolRamp, - this.toolQuarterPipe, - this.toolHalfPipe, - this.toolBowl, - this.toolPyramid, - this.toolTerrain, - this.toolEraser, - this.toolInvisibility, - this.toolSeparator2, - this.toolPortalDigger, - this.toolUVFixer}); - this.toolStrip.LayoutStyle = System.Windows.Forms.ToolStripLayoutStyle.VerticalStackWithOverflow; - this.toolStrip.Location = new System.Drawing.Point(0, 0); - this.toolStrip.Name = "toolStrip"; - this.toolStrip.Padding = new System.Windows.Forms.Padding(1, 0, 1, 0); - this.toolStrip.Size = new System.Drawing.Size(28, 453); - this.toolStrip.TabIndex = 3; + toolStrip.AutoSize = false; + toolStrip.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + toolStrip.CanOverflow = false; + toolStrip.Dock = System.Windows.Forms.DockStyle.Fill; + toolStrip.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); + toolStrip.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden; + toolStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { toolSelection, toolBrush, toolShovel, toolPencil, toolFlatten, toolSmooth, toolFill, toolGridPaint, toolGroup, toolSeparator1, toolDrag, toolRamp, toolQuarterPipe, toolHalfPipe, toolBowl, toolPyramid, toolTerrain, toolEraser, toolInvisibility, toolSeparator2, toolPortalDigger, toolUVFixer, toolSeparator3, toolDecalsMode }); + toolStrip.LayoutStyle = System.Windows.Forms.ToolStripLayoutStyle.VerticalStackWithOverflow; + toolStrip.Location = new System.Drawing.Point(0, 0); + toolStrip.Name = "toolStrip"; + toolStrip.Padding = new System.Windows.Forms.Padding(1, 0, 1, 0); + toolStrip.Size = new System.Drawing.Size(33, 523); + toolStrip.TabIndex = 3; // // toolSelection // - this.toolSelection.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(60)))), ((int)(((byte)(63)))), ((int)(((byte)(65))))); - this.toolSelection.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.toolSelection.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(220)))), ((int)(((byte)(220))))); - this.toolSelection.Image = global::TombEditor.Properties.Resources.toolbox_Selection_16; - this.toolSelection.ImageTransparentColor = System.Drawing.Color.Magenta; - this.toolSelection.Margin = new System.Windows.Forms.Padding(1); - this.toolSelection.Name = "toolSelection"; - this.toolSelection.Size = new System.Drawing.Size(23, 20); - this.toolSelection.ToolTipText = "Selection"; - this.toolSelection.Click += new System.EventHandler(this.toolSelection_Click); + toolSelection.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + toolSelection.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + toolSelection.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); + toolSelection.Image = Properties.Resources.toolbox_Selection_16; + toolSelection.ImageTransparentColor = System.Drawing.Color.Magenta; + toolSelection.Margin = new System.Windows.Forms.Padding(1); + toolSelection.Name = "toolSelection"; + toolSelection.Size = new System.Drawing.Size(28, 20); + toolSelection.ToolTipText = "Selection"; + toolSelection.Click += toolSelection_Click; // // toolBrush // - this.toolBrush.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(60)))), ((int)(((byte)(63)))), ((int)(((byte)(65))))); - this.toolBrush.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.toolBrush.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(220)))), ((int)(((byte)(220))))); - this.toolBrush.Image = global::TombEditor.Properties.Resources.toolbox_Paint_16; - this.toolBrush.ImageTransparentColor = System.Drawing.Color.Magenta; - this.toolBrush.Margin = new System.Windows.Forms.Padding(1); - this.toolBrush.Name = "toolBrush"; - this.toolBrush.Size = new System.Drawing.Size(23, 20); - this.toolBrush.ToolTipText = "Brush"; - this.toolBrush.Click += new System.EventHandler(this.toolBrush_Click); + toolBrush.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + toolBrush.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + toolBrush.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); + toolBrush.Image = Properties.Resources.toolbox_Paint_16; + toolBrush.ImageTransparentColor = System.Drawing.Color.Magenta; + toolBrush.Margin = new System.Windows.Forms.Padding(1); + toolBrush.Name = "toolBrush"; + toolBrush.Size = new System.Drawing.Size(28, 20); + toolBrush.ToolTipText = "Brush"; + toolBrush.Click += toolBrush_Click; // // toolShovel // - this.toolShovel.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(60)))), ((int)(((byte)(63)))), ((int)(((byte)(65))))); - this.toolShovel.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.toolShovel.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(220)))), ((int)(((byte)(220))))); - this.toolShovel.Image = global::TombEditor.Properties.Resources.toolbox_Shovel_16; - this.toolShovel.ImageTransparentColor = System.Drawing.Color.Magenta; - this.toolShovel.Margin = new System.Windows.Forms.Padding(1); - this.toolShovel.Name = "toolShovel"; - this.toolShovel.Size = new System.Drawing.Size(23, 20); - this.toolShovel.ToolTipText = "Shovel"; - this.toolShovel.Click += new System.EventHandler(this.toolShovel_Click); + toolShovel.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + toolShovel.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + toolShovel.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); + toolShovel.Image = Properties.Resources.toolbox_Shovel_16; + toolShovel.ImageTransparentColor = System.Drawing.Color.Magenta; + toolShovel.Margin = new System.Windows.Forms.Padding(1); + toolShovel.Name = "toolShovel"; + toolShovel.Size = new System.Drawing.Size(28, 20); + toolShovel.ToolTipText = "Shovel"; + toolShovel.Click += toolShovel_Click; // // toolPencil // - this.toolPencil.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(60)))), ((int)(((byte)(63)))), ((int)(((byte)(65))))); - this.toolPencil.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.toolPencil.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(220)))), ((int)(((byte)(220))))); - this.toolPencil.Image = global::TombEditor.Properties.Resources.toolbox_Pencil_16; - this.toolPencil.ImageTransparentColor = System.Drawing.Color.Magenta; - this.toolPencil.Margin = new System.Windows.Forms.Padding(1); - this.toolPencil.Name = "toolPencil"; - this.toolPencil.Size = new System.Drawing.Size(23, 20); - this.toolPencil.ToolTipText = "Pencil"; - this.toolPencil.Click += new System.EventHandler(this.toolPencil_Click); + toolPencil.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + toolPencil.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + toolPencil.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); + toolPencil.Image = Properties.Resources.toolbox_Pencil_16; + toolPencil.ImageTransparentColor = System.Drawing.Color.Magenta; + toolPencil.Margin = new System.Windows.Forms.Padding(1); + toolPencil.Name = "toolPencil"; + toolPencil.Size = new System.Drawing.Size(28, 20); + toolPencil.ToolTipText = "Pencil"; + toolPencil.Click += toolPencil_Click; // // toolFlatten // - this.toolFlatten.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(60)))), ((int)(((byte)(63)))), ((int)(((byte)(65))))); - this.toolFlatten.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.toolFlatten.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(220)))), ((int)(((byte)(220))))); - this.toolFlatten.Image = global::TombEditor.Properties.Resources.toolbox_Bulldozer_1_16; - this.toolFlatten.ImageTransparentColor = System.Drawing.Color.Magenta; - this.toolFlatten.Margin = new System.Windows.Forms.Padding(1); - this.toolFlatten.Name = "toolFlatten"; - this.toolFlatten.Size = new System.Drawing.Size(23, 20); - this.toolFlatten.ToolTipText = "Bulldozer"; - this.toolFlatten.Click += new System.EventHandler(this.toolFlatten_Click); + toolFlatten.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + toolFlatten.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + toolFlatten.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); + toolFlatten.Image = Properties.Resources.toolbox_Bulldozer_1_16; + toolFlatten.ImageTransparentColor = System.Drawing.Color.Magenta; + toolFlatten.Margin = new System.Windows.Forms.Padding(1); + toolFlatten.Name = "toolFlatten"; + toolFlatten.Size = new System.Drawing.Size(28, 20); + toolFlatten.ToolTipText = "Bulldozer"; + toolFlatten.Click += toolFlatten_Click; // // toolSmooth // - this.toolSmooth.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(60)))), ((int)(((byte)(63)))), ((int)(((byte)(65))))); - this.toolSmooth.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.toolSmooth.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(220)))), ((int)(((byte)(220))))); - this.toolSmooth.Image = global::TombEditor.Properties.Resources.toolbox_Smooth_16; - this.toolSmooth.ImageTransparentColor = System.Drawing.Color.Magenta; - this.toolSmooth.Margin = new System.Windows.Forms.Padding(1); - this.toolSmooth.Name = "toolSmooth"; - this.toolSmooth.Size = new System.Drawing.Size(23, 20); - this.toolSmooth.ToolTipText = "Smooth"; - this.toolSmooth.Click += new System.EventHandler(this.toolSmooth_Click); + toolSmooth.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + toolSmooth.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + toolSmooth.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); + toolSmooth.Image = Properties.Resources.toolbox_Smooth_16; + toolSmooth.ImageTransparentColor = System.Drawing.Color.Magenta; + toolSmooth.Margin = new System.Windows.Forms.Padding(1); + toolSmooth.Name = "toolSmooth"; + toolSmooth.Size = new System.Drawing.Size(28, 20); + toolSmooth.ToolTipText = "Smooth"; + toolSmooth.Click += toolSmooth_Click; // // toolFill // - this.toolFill.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(60)))), ((int)(((byte)(63)))), ((int)(((byte)(65))))); - this.toolFill.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.toolFill.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(220)))), ((int)(((byte)(220))))); - this.toolFill.Image = global::TombEditor.Properties.Resources.toolbox_Fill_16; - this.toolFill.ImageTransparentColor = System.Drawing.Color.Magenta; - this.toolFill.Margin = new System.Windows.Forms.Padding(1); - this.toolFill.Name = "toolFill"; - this.toolFill.Size = new System.Drawing.Size(23, 20); - this.toolFill.ToolTipText = "Fill"; - this.toolFill.Click += new System.EventHandler(this.toolFill_Click); + toolFill.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + toolFill.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + toolFill.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); + toolFill.Image = Properties.Resources.toolbox_Fill_16; + toolFill.ImageTransparentColor = System.Drawing.Color.Magenta; + toolFill.Margin = new System.Windows.Forms.Padding(1); + toolFill.Name = "toolFill"; + toolFill.Size = new System.Drawing.Size(28, 20); + toolFill.ToolTipText = "Fill"; + toolFill.Click += toolFill_Click; // // toolGridPaint // - this.toolGridPaint.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(60)))), ((int)(((byte)(63)))), ((int)(((byte)(65))))); - this.toolGridPaint.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.toolGridPaint.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(220)))), ((int)(((byte)(220))))); - this.toolGridPaint.Image = global::TombEditor.Properties.Resources.toolbox_Paint2x2_16; - this.toolGridPaint.ImageTransparentColor = System.Drawing.Color.Magenta; - this.toolGridPaint.Margin = new System.Windows.Forms.Padding(1); - this.toolGridPaint.Name = "toolGridPaint"; - this.toolGridPaint.Size = new System.Drawing.Size(23, 20); - this.toolGridPaint.ToolTipText = "Grid Paint (2x2)"; - this.toolGridPaint.Click += new System.EventHandler(this.tooPaint2x2_Click); - this.toolGridPaint.MouseDown += new System.Windows.Forms.MouseEventHandler(this.toolGridPaint_MouseDown); - this.toolGridPaint.MouseUp += new System.Windows.Forms.MouseEventHandler(this.toolGridPaint_MouseUp); + toolGridPaint.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + toolGridPaint.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + toolGridPaint.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); + toolGridPaint.Image = Properties.Resources.toolbox_Paint2x2_16; + toolGridPaint.ImageTransparentColor = System.Drawing.Color.Magenta; + toolGridPaint.Margin = new System.Windows.Forms.Padding(1); + toolGridPaint.Name = "toolGridPaint"; + toolGridPaint.Size = new System.Drawing.Size(28, 20); + toolGridPaint.ToolTipText = "Grid Paint (2x2)"; + toolGridPaint.Click += tooPaint2x2_Click; + toolGridPaint.MouseDown += toolGridPaint_MouseDown; + toolGridPaint.MouseUp += toolGridPaint_MouseUp; // // toolGroup // - this.toolGroup.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(60)))), ((int)(((byte)(63)))), ((int)(((byte)(65))))); - this.toolGroup.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.toolGroup.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(220)))), ((int)(((byte)(220))))); - this.toolGroup.Image = global::TombEditor.Properties.Resources.toolbox_GroupTexture_16; - this.toolGroup.ImageTransparentColor = System.Drawing.Color.Magenta; - this.toolGroup.Margin = new System.Windows.Forms.Padding(1); - this.toolGroup.Name = "toolGroup"; - this.toolGroup.Size = new System.Drawing.Size(23, 20); - this.toolGroup.ToolTipText = "Group Texturing"; - this.toolGroup.Click += new System.EventHandler(this.toolGroup_Click); + toolGroup.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + toolGroup.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + toolGroup.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); + toolGroup.Image = Properties.Resources.toolbox_GroupTexture_16; + toolGroup.ImageTransparentColor = System.Drawing.Color.Magenta; + toolGroup.Margin = new System.Windows.Forms.Padding(1); + toolGroup.Name = "toolGroup"; + toolGroup.Size = new System.Drawing.Size(28, 20); + toolGroup.ToolTipText = "Group Texturing"; + toolGroup.Click += toolGroup_Click; // // toolSeparator1 // - this.toolSeparator1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(60)))), ((int)(((byte)(63)))), ((int)(((byte)(65))))); - this.toolSeparator1.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(220)))), ((int)(((byte)(220))))); - this.toolSeparator1.Margin = new System.Windows.Forms.Padding(0, 0, 2, 0); - this.toolSeparator1.Name = "toolSeparator1"; - this.toolSeparator1.Size = new System.Drawing.Size(23, 6); + toolSeparator1.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + toolSeparator1.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); + toolSeparator1.Margin = new System.Windows.Forms.Padding(0, 0, 2, 0); + toolSeparator1.Name = "toolSeparator1"; + toolSeparator1.Size = new System.Drawing.Size(28, 6); // // toolDrag // - this.toolDrag.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(60)))), ((int)(((byte)(63)))), ((int)(((byte)(65))))); - this.toolDrag.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.toolDrag.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(220)))), ((int)(((byte)(220))))); - this.toolDrag.Image = global::TombEditor.Properties.Resources.toolbox_Drag_16; - this.toolDrag.ImageTransparentColor = System.Drawing.Color.Magenta; - this.toolDrag.Margin = new System.Windows.Forms.Padding(1); - this.toolDrag.Name = "toolDrag"; - this.toolDrag.Size = new System.Drawing.Size(23, 20); - this.toolDrag.ToolTipText = "Drag"; - this.toolDrag.Click += new System.EventHandler(this.toolDrag_Click); + toolDrag.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + toolDrag.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + toolDrag.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); + toolDrag.Image = Properties.Resources.toolbox_Drag_16; + toolDrag.ImageTransparentColor = System.Drawing.Color.Magenta; + toolDrag.Margin = new System.Windows.Forms.Padding(1); + toolDrag.Name = "toolDrag"; + toolDrag.Size = new System.Drawing.Size(28, 20); + toolDrag.ToolTipText = "Drag"; + toolDrag.Click += toolDrag_Click; // // toolRamp // - this.toolRamp.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(60)))), ((int)(((byte)(63)))), ((int)(((byte)(65))))); - this.toolRamp.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.toolRamp.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(220)))), ((int)(((byte)(220))))); - this.toolRamp.Image = global::TombEditor.Properties.Resources.toolbox_GroupRamp_16; - this.toolRamp.ImageTransparentColor = System.Drawing.Color.Magenta; - this.toolRamp.Margin = new System.Windows.Forms.Padding(1); - this.toolRamp.Name = "toolRamp"; - this.toolRamp.Size = new System.Drawing.Size(23, 20); - this.toolRamp.ToolTipText = "Ramp"; - this.toolRamp.Click += new System.EventHandler(this.toolRamp_Click); + toolRamp.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + toolRamp.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + toolRamp.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); + toolRamp.Image = Properties.Resources.toolbox_GroupRamp_16; + toolRamp.ImageTransparentColor = System.Drawing.Color.Magenta; + toolRamp.Margin = new System.Windows.Forms.Padding(1); + toolRamp.Name = "toolRamp"; + toolRamp.Size = new System.Drawing.Size(28, 20); + toolRamp.ToolTipText = "Ramp"; + toolRamp.Click += toolRamp_Click; // // toolQuarterPipe // - this.toolQuarterPipe.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(60)))), ((int)(((byte)(63)))), ((int)(((byte)(65))))); - this.toolQuarterPipe.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.toolQuarterPipe.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(220)))), ((int)(((byte)(220))))); - this.toolQuarterPipe.Image = global::TombEditor.Properties.Resources.toolbox_GroupQuaterPipe_16; - this.toolQuarterPipe.ImageTransparentColor = System.Drawing.Color.Magenta; - this.toolQuarterPipe.Margin = new System.Windows.Forms.Padding(1); - this.toolQuarterPipe.Name = "toolQuarterPipe"; - this.toolQuarterPipe.Size = new System.Drawing.Size(23, 20); - this.toolQuarterPipe.ToolTipText = "Quarter Pipe"; - this.toolQuarterPipe.Click += new System.EventHandler(this.toolQuarterPipe_Click); + toolQuarterPipe.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + toolQuarterPipe.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + toolQuarterPipe.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); + toolQuarterPipe.Image = Properties.Resources.toolbox_GroupQuaterPipe_16; + toolQuarterPipe.ImageTransparentColor = System.Drawing.Color.Magenta; + toolQuarterPipe.Margin = new System.Windows.Forms.Padding(1); + toolQuarterPipe.Name = "toolQuarterPipe"; + toolQuarterPipe.Size = new System.Drawing.Size(28, 20); + toolQuarterPipe.ToolTipText = "Quarter Pipe"; + toolQuarterPipe.Click += toolQuarterPipe_Click; // // toolHalfPipe // - this.toolHalfPipe.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(60)))), ((int)(((byte)(63)))), ((int)(((byte)(65))))); - this.toolHalfPipe.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.toolHalfPipe.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(220)))), ((int)(((byte)(220))))); - this.toolHalfPipe.Image = global::TombEditor.Properties.Resources.toolbox_GroupHalfPipe_16; - this.toolHalfPipe.ImageTransparentColor = System.Drawing.Color.Magenta; - this.toolHalfPipe.Margin = new System.Windows.Forms.Padding(1); - this.toolHalfPipe.Name = "toolHalfPipe"; - this.toolHalfPipe.Size = new System.Drawing.Size(23, 20); - this.toolHalfPipe.ToolTipText = "Half Pipe"; - this.toolHalfPipe.Click += new System.EventHandler(this.toolHalfPipe_Click); + toolHalfPipe.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + toolHalfPipe.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + toolHalfPipe.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); + toolHalfPipe.Image = Properties.Resources.toolbox_GroupHalfPipe_16; + toolHalfPipe.ImageTransparentColor = System.Drawing.Color.Magenta; + toolHalfPipe.Margin = new System.Windows.Forms.Padding(1); + toolHalfPipe.Name = "toolHalfPipe"; + toolHalfPipe.Size = new System.Drawing.Size(28, 20); + toolHalfPipe.ToolTipText = "Half Pipe"; + toolHalfPipe.Click += toolHalfPipe_Click; // // toolBowl // - this.toolBowl.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(60)))), ((int)(((byte)(63)))), ((int)(((byte)(65))))); - this.toolBowl.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.toolBowl.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(220)))), ((int)(((byte)(220))))); - this.toolBowl.Image = global::TombEditor.Properties.Resources.toolbox_GroupBowl_16; - this.toolBowl.ImageTransparentColor = System.Drawing.Color.Magenta; - this.toolBowl.Margin = new System.Windows.Forms.Padding(1); - this.toolBowl.Name = "toolBowl"; - this.toolBowl.Size = new System.Drawing.Size(23, 20); - this.toolBowl.ToolTipText = "Bowl"; - this.toolBowl.Click += new System.EventHandler(this.toolBowl_Click); + toolBowl.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + toolBowl.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + toolBowl.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); + toolBowl.Image = Properties.Resources.toolbox_GroupBowl_16; + toolBowl.ImageTransparentColor = System.Drawing.Color.Magenta; + toolBowl.Margin = new System.Windows.Forms.Padding(1); + toolBowl.Name = "toolBowl"; + toolBowl.Size = new System.Drawing.Size(28, 20); + toolBowl.ToolTipText = "Bowl"; + toolBowl.Click += toolBowl_Click; // // toolPyramid // - this.toolPyramid.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(60)))), ((int)(((byte)(63)))), ((int)(((byte)(65))))); - this.toolPyramid.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.toolPyramid.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(220)))), ((int)(((byte)(220))))); - this.toolPyramid.Image = global::TombEditor.Properties.Resources.toolbox_GroupPyramid_16; - this.toolPyramid.ImageTransparentColor = System.Drawing.Color.Magenta; - this.toolPyramid.Margin = new System.Windows.Forms.Padding(1); - this.toolPyramid.Name = "toolPyramid"; - this.toolPyramid.Size = new System.Drawing.Size(23, 20); - this.toolPyramid.ToolTipText = "Pyramid"; - this.toolPyramid.Click += new System.EventHandler(this.toolPyramid_Click); + toolPyramid.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + toolPyramid.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + toolPyramid.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); + toolPyramid.Image = Properties.Resources.toolbox_GroupPyramid_16; + toolPyramid.ImageTransparentColor = System.Drawing.Color.Magenta; + toolPyramid.Margin = new System.Windows.Forms.Padding(1); + toolPyramid.Name = "toolPyramid"; + toolPyramid.Size = new System.Drawing.Size(28, 20); + toolPyramid.ToolTipText = "Pyramid"; + toolPyramid.Click += toolPyramid_Click; // // toolTerrain // - this.toolTerrain.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(60)))), ((int)(((byte)(63)))), ((int)(((byte)(65))))); - this.toolTerrain.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.toolTerrain.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(220)))), ((int)(((byte)(220))))); - this.toolTerrain.Image = global::TombEditor.Properties.Resources.toolbox_GroupTerrain_16; - this.toolTerrain.ImageTransparentColor = System.Drawing.Color.Magenta; - this.toolTerrain.Margin = new System.Windows.Forms.Padding(1); - this.toolTerrain.Name = "toolTerrain"; - this.toolTerrain.Size = new System.Drawing.Size(23, 20); - this.toolTerrain.ToolTipText = "Terrain"; - this.toolTerrain.Click += new System.EventHandler(this.toolTerrain_Click); + toolTerrain.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + toolTerrain.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + toolTerrain.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); + toolTerrain.Image = Properties.Resources.toolbox_GroupTerrain_16; + toolTerrain.ImageTransparentColor = System.Drawing.Color.Magenta; + toolTerrain.Margin = new System.Windows.Forms.Padding(1); + toolTerrain.Name = "toolTerrain"; + toolTerrain.Size = new System.Drawing.Size(28, 20); + toolTerrain.ToolTipText = "Terrain"; + toolTerrain.Click += toolTerrain_Click; // // toolEraser // - this.toolEraser.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(60)))), ((int)(((byte)(63)))), ((int)(((byte)(65))))); - this.toolEraser.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.toolEraser.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(220)))), ((int)(((byte)(220))))); - this.toolEraser.Image = global::TombEditor.Properties.Resources.toolbox_Eraser_16; - this.toolEraser.ImageTransparentColor = System.Drawing.Color.Magenta; - this.toolEraser.Margin = new System.Windows.Forms.Padding(1); - this.toolEraser.Name = "toolEraser"; - this.toolEraser.Size = new System.Drawing.Size(23, 20); - this.toolEraser.ToolTipText = "Eraser"; - this.toolEraser.Click += new System.EventHandler(this.toolEraser_Click); + toolEraser.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + toolEraser.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + toolEraser.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); + toolEraser.Image = Properties.Resources.toolbox_Eraser_16; + toolEraser.ImageTransparentColor = System.Drawing.Color.Magenta; + toolEraser.Margin = new System.Windows.Forms.Padding(1); + toolEraser.Name = "toolEraser"; + toolEraser.Size = new System.Drawing.Size(28, 20); + toolEraser.ToolTipText = "Eraser"; + toolEraser.Click += toolEraser_Click; // // toolInvisibility // - this.toolInvisibility.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(60)))), ((int)(((byte)(63)))), ((int)(((byte)(65))))); - this.toolInvisibility.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.toolInvisibility.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(220)))), ((int)(((byte)(220))))); - this.toolInvisibility.Image = global::TombEditor.Properties.Resources.toolbox_Invisible_16; - this.toolInvisibility.ImageTransparentColor = System.Drawing.Color.Magenta; - this.toolInvisibility.Margin = new System.Windows.Forms.Padding(1); - this.toolInvisibility.Name = "toolInvisibility"; - this.toolInvisibility.Size = new System.Drawing.Size(23, 20); - this.toolInvisibility.ToolTipText = "Invisibility"; - this.toolInvisibility.Click += new System.EventHandler(this.toolInvisibility_Click); + toolInvisibility.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + toolInvisibility.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + toolInvisibility.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); + toolInvisibility.Image = Properties.Resources.toolbox_Invisible_16; + toolInvisibility.ImageTransparentColor = System.Drawing.Color.Magenta; + toolInvisibility.Margin = new System.Windows.Forms.Padding(1); + toolInvisibility.Name = "toolInvisibility"; + toolInvisibility.Size = new System.Drawing.Size(28, 20); + toolInvisibility.ToolTipText = "Invisibility"; + toolInvisibility.Click += toolInvisibility_Click; // // toolSeparator2 // - this.toolSeparator2.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(60)))), ((int)(((byte)(63)))), ((int)(((byte)(65))))); - this.toolSeparator2.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(220)))), ((int)(((byte)(220))))); - this.toolSeparator2.Margin = new System.Windows.Forms.Padding(0, 0, 2, 0); - this.toolSeparator2.Name = "toolSeparator2"; - this.toolSeparator2.Size = new System.Drawing.Size(23, 6); + toolSeparator2.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + toolSeparator2.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); + toolSeparator2.Margin = new System.Windows.Forms.Padding(0, 0, 2, 0); + toolSeparator2.Name = "toolSeparator2"; + toolSeparator2.Size = new System.Drawing.Size(28, 6); // // toolPortalDigger // - this.toolPortalDigger.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(60)))), ((int)(((byte)(63)))), ((int)(((byte)(65))))); - this.toolPortalDigger.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.toolPortalDigger.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(220)))), ((int)(((byte)(220))))); - this.toolPortalDigger.Image = global::TombEditor.Properties.Resources.toolbox_PortalDigger_16; - this.toolPortalDigger.ImageTransparentColor = System.Drawing.Color.Magenta; - this.toolPortalDigger.Margin = new System.Windows.Forms.Padding(1); - this.toolPortalDigger.Name = "toolPortalDigger"; - this.toolPortalDigger.Size = new System.Drawing.Size(23, 20); - this.toolPortalDigger.ToolTipText = "Portal Digger"; - this.toolPortalDigger.Click += new System.EventHandler(this.toolPortalDigger_Click); + toolPortalDigger.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + toolPortalDigger.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + toolPortalDigger.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); + toolPortalDigger.Image = Properties.Resources.toolbox_PortalDigger_16; + toolPortalDigger.ImageTransparentColor = System.Drawing.Color.Magenta; + toolPortalDigger.Margin = new System.Windows.Forms.Padding(1); + toolPortalDigger.Name = "toolPortalDigger"; + toolPortalDigger.Size = new System.Drawing.Size(28, 20); + toolPortalDigger.ToolTipText = "Portal Digger"; + toolPortalDigger.Click += toolPortalDigger_Click; // // toolUVFixer // - this.toolUVFixer.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(60)))), ((int)(((byte)(63)))), ((int)(((byte)(65))))); - this.toolUVFixer.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.toolUVFixer.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(220)))), ((int)(((byte)(220))))); - this.toolUVFixer.Image = global::TombEditor.Properties.Resources.toolbox_UVFixer_16; - this.toolUVFixer.ImageTransparentColor = System.Drawing.Color.Magenta; - this.toolUVFixer.Margin = new System.Windows.Forms.Padding(1); - this.toolUVFixer.Name = "toolUVFixer"; - this.toolUVFixer.Size = new System.Drawing.Size(23, 20); - this.toolUVFixer.Text = "toolStripButton1"; - this.toolUVFixer.ToolTipText = "Fix texture coordinates"; - this.toolUVFixer.Click += new System.EventHandler(this.toolUVFixer_Click); + toolUVFixer.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + toolUVFixer.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + toolUVFixer.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); + toolUVFixer.Image = Properties.Resources.toolbox_UVFixer_16; + toolUVFixer.ImageTransparentColor = System.Drawing.Color.Magenta; + toolUVFixer.Margin = new System.Windows.Forms.Padding(1); + toolUVFixer.Name = "toolUVFixer"; + toolUVFixer.Size = new System.Drawing.Size(28, 20); + toolUVFixer.ToolTipText = "Fix texture coordinates"; + toolUVFixer.Click += toolUVFixer_Click; + // + // toolSeparator3 + // + toolSeparator3.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + toolSeparator3.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); + toolSeparator3.Margin = new System.Windows.Forms.Padding(0, 0, 2, 0); + toolSeparator3.Name = "toolSeparator3"; + toolSeparator3.Size = new System.Drawing.Size(28, 6); + // + // toolDecalsMode + // + toolDecalsMode.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + toolDecalsMode.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + toolDecalsMode.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); + toolDecalsMode.Image = (System.Drawing.Image)resources.GetObject("toolDecalsMode.Image"); + toolDecalsMode.ImageTransparentColor = System.Drawing.Color.Magenta; + toolDecalsMode.Margin = new System.Windows.Forms.Padding(1); + toolDecalsMode.Name = "toolDecalsMode"; + toolDecalsMode.Size = new System.Drawing.Size(28, 20); + toolDecalsMode.ToolTipText = "Toggle decals mode"; + toolDecalsMode.Click += toolDecalsMode_Click; // // ToolBox // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; - this.Controls.Add(this.toolStrip); - this.Margin = new System.Windows.Forms.Padding(0); - this.Name = "ToolBox"; - this.Size = new System.Drawing.Size(28, 453); - this.toolStrip.ResumeLayout(false); - this.toolStrip.PerformLayout(); - this.ResumeLayout(false); - + AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); + AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; + Controls.Add(toolStrip); + Margin = new System.Windows.Forms.Padding(0); + Name = "ToolBox"; + Size = new System.Drawing.Size(33, 523); + toolStrip.ResumeLayout(false); + toolStrip.PerformLayout(); + ResumeLayout(false); } #endregion @@ -411,5 +411,7 @@ private void InitializeComponent() private System.Windows.Forms.ToolStripButton toolUVFixer; private System.Windows.Forms.ToolStripButton toolGridPaint; private System.Windows.Forms.ToolStripButton toolPortalDigger; + private System.Windows.Forms.ToolStripSeparator toolSeparator3; + private System.Windows.Forms.ToolStripButton toolDecalsMode; } } diff --git a/TombEditor/Controls/ToolBox.cs b/TombEditor/Controls/ToolBox.cs index 149f2adad..ba6a3a7fe 100644 --- a/TombEditor/Controls/ToolBox.cs +++ b/TombEditor/Controls/ToolBox.cs @@ -2,6 +2,7 @@ using System.ComponentModel; using System.Windows.Forms; using TombEditor.Controls.ContextMenus; +using TombLib.LevelData.SectorEnums; using TombLib.Utils; namespace TombEditor.Controls @@ -108,6 +109,8 @@ private void EditorEventRaised(IEditorEvent obj) toolEraser.Visible = !geometryMode; toolInvisibility.Visible = !geometryMode; toolUVFixer.Visible = !geometryMode; + toolSeparator3.Visible = !geometryMode; + toolDecalsMode.Visible = !geometryMode; toolFlatten.Visible = geometryMode; toolShovel.Visible = geometryMode; toolSmooth.Visible = geometryMode; @@ -252,5 +255,16 @@ private void toolGridPaint_MouseDown(object sender, MouseEventArgs e) else ContextMenuTimer_Tick(sender, e); } + + private void toolDecalsMode_Click(object sender, EventArgs e) + { + _editor.ActiveTextureLayer = _editor.ActiveTextureLayer switch + { + FaceLayer.Base => FaceLayer.Decal, + _ => FaceLayer.Base + }; + + toolDecalsMode.Checked = _editor.ActiveTextureLayer == FaceLayer.Decal; + } } } diff --git a/TombEditor/Controls/ToolBox.resx b/TombEditor/Controls/ToolBox.resx index c42befb07..0c7f5f648 100644 --- a/TombEditor/Controls/ToolBox.resx +++ b/TombEditor/Controls/ToolBox.resx @@ -120,4 +120,16 @@ 17, 17 + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAE5SURBVDhPtZKxSsNgFIVjXBwtuDmIUAWhk86dxGAXQUER + dajgJBQ3hwzuFcTBF3BxqJ2Lk6uDYkVd7GZtXVR8Akn8bnqI1LTBwR74uNxzz3/zN6kzEIVhOBoEwQ4c + w7jsv4kDe/AJVfiCZ5jWOF0Ej+AWptS/wz60YCYK9ROBZXiy68syrwYrsAWvkNMoKYaPMK82EstW8a6o + LnUdbEnyJphZeFEbSwcvoWw9dRPa0P1OMApQU9sllowxu4YKTNIXqU2YUCRasAgXahPi0AjzA7CXegcf + UNc4/gktgkOyeor5MMyRtWU3sjvCeABPbapYckrWV9sRxhI0GMafsZfILECbXEbWjxgcQh2iP9Jv4a/B + G+RlJcVw10I84Zxagg3wwb7EPcwq2l92PYLbcAJnUAYP31Xkv+Q43wTrT7Q6A1OTAAAAAElFTkSuQmCC + + \ No newline at end of file diff --git a/TombEditor/Editor.cs b/TombEditor/Editor.cs index f35d8eaa3..a6983da15 100644 --- a/TombEditor/Editor.cs +++ b/TombEditor/Editor.cs @@ -9,6 +9,7 @@ using TombLib.Forms; using TombLib.LevelData; using TombLib.LevelData.IO; +using TombLib.LevelData.SectorEnums; using TombLib.Rendering; using TombLib.Utils; using TombLib.Wad.Catalog; @@ -1449,5 +1450,7 @@ public bool IsPreciseGeometryAllowed => Level.Settings.GameVersion is TRVersion.Game.TombEngine || Configuration.Editor_EnableStepHeightControlsForUnsupportedEngines; public int IncrementReference => IsPreciseGeometryAllowed ? Configuration.Editor_StepHeight : Level.FullClickHeight; + + public FaceLayer ActiveTextureLayer { get; set; } } } diff --git a/TombEditor/EditorActions.cs b/TombEditor/EditorActions.cs index 720427d90..8f4ad2ebb 100644 --- a/TombEditor/EditorActions.cs +++ b/TombEditor/EditorActions.cs @@ -1348,13 +1348,13 @@ public static void ReplaceEventSetNames(List list, string oldName, str } } - public static void RotateTexture(Room room, VectorInt2 pos, SectorFace face) + public static void RotateTexture(Room room, VectorInt2 pos, FaceLayerInfo face) { _editor.UndoManager.PushGeometryChanged(_editor.SelectedRoom); Sector sector = room.GetSector(pos); TextureArea newTexture = sector.GetFaceTexture(face); - bool isTriangle = room.GetFaceShape(pos.X, pos.Y, face) == FaceShape.Triangle; + bool isTriangle = room.GetFaceShape(pos.X, pos.Y, face.Face) == FaceShape.Triangle; newTexture.Rotate(1, isTriangle); sector.SetFaceTexture(face, newTexture); @@ -1364,14 +1364,14 @@ public static void RotateTexture(Room room, VectorInt2 pos, SectorFace face) _editor.RoomTextureChange(room); } - public static void MirrorTexture(Room room, VectorInt2 pos, SectorFace face) + public static void MirrorTexture(Room room, VectorInt2 pos, FaceLayerInfo face) { _editor.UndoManager.PushGeometryChanged(_editor.SelectedRoom); Sector sector = room.GetSector(pos); TextureArea newTexture = sector.GetFaceTexture(face); - newTexture.Mirror(room.GetFaceShape(pos.X, pos.Y, face) == FaceShape.Triangle); + newTexture.Mirror(room.GetFaceShape(pos.X, pos.Y, face.Face) == FaceShape.Triangle); sector.SetFaceTexture(face, newTexture); // Update state @@ -1379,7 +1379,7 @@ public static void MirrorTexture(Room room, VectorInt2 pos, SectorFace face) _editor.RoomTextureChange(room); } - public static void PickTexture(Room room, VectorInt2 pos, SectorFace face) + public static void PickTexture(Room room, VectorInt2 pos, FaceLayerInfo face) { var area = room.GetSector(pos).GetFaceTexture(face); @@ -1407,7 +1407,7 @@ public static void PickTexture(Room room, VectorInt2 pos, SectorFace face) area.DoubleSided = _editor.SelectedTexture.DoubleSided; } - if (face is SectorFace.Ceiling or SectorFace.Ceiling_Triangle2) + if (face.Face is SectorFace.Ceiling or SectorFace.Ceiling_Triangle2) area.Mirror(area.TextureIsTriangle); _editor.SelectTextureAndCenterView(area.RestoreQuad()); @@ -1428,7 +1428,8 @@ public static List> FindTextures(TextureSearchTyp var sector = room.GetSectorTry(x, z); if (sector == null) continue; - foreach (var face in Enum.GetValues(typeof(SectorFace)).Cast()) + for (SectorFace face = 0; face < SectorFace.Count; face++) + for (FaceLayer layer = 0; layer < FaceLayer.Count; layer++) { // Filter out impossible combinations right away if (face.IsNonWall() && sector.IsAnyWall) continue; @@ -1438,7 +1439,7 @@ public static List> FindTextures(TextureSearchTyp // Filter out undefined faces if (!room.IsFaceDefined(x, z, face)) continue; - var tex = sector.GetFaceTexture(face); + var tex = sector.GetFaceTexture(new FaceLayerInfo(face, layer)); var entry = new KeyValuePair(room, new VectorInt2(x, z)); switch (type) @@ -1545,7 +1546,7 @@ private static void CheckTextureAttributes(Room room, VectorInt2 pos, SectorFace private static bool _textureAtrributeMessageState = false; private static int _textureAttributeMessageCount = 0; - private static bool ApplyTextureToFace(Room room, VectorInt2 pos, SectorFace face, TextureArea texture, bool autocorrectCeiling = true) + private static bool ApplyTextureToFace(Room room, VectorInt2 pos, FaceLayerInfo face, TextureArea texture, bool autocorrectCeiling = true) { if (_editor.Configuration.UI_AutoSwitchRoomToOutsideOnAppliedInvisibleTexture && !room.Properties.FlagHorizon && texture.TextureIsInvisible) @@ -1555,7 +1556,7 @@ private static bool ApplyTextureToFace(Room room, VectorInt2 pos, SectorFace fac } Sector sector = room.GetSector(pos); - FaceShape shape = room.GetFaceShape(pos.X, pos.Y, face); + FaceShape shape = room.GetFaceShape(pos.X, pos.Y, face.Face); bool wasDoubleSided = sector.GetFaceTexture(face).DoubleSided; bool textureApplied = false; @@ -1563,14 +1564,14 @@ private static bool ApplyTextureToFace(Room room, VectorInt2 pos, SectorFace fac texture.ClampToBounds(); // HACK: Ceiling vertex order is hardly messed up, we need to do some transforms. - if (autocorrectCeiling && face.IsCeiling()) texture.Mirror(); + if (autocorrectCeiling && face.Face.IsCeiling()) texture.Mirror(); if (!_editor.Tool.TextureUVFixer || (shape == FaceShape.Triangle && texture.TextureIsTriangle)) { if (shape == FaceShape.Triangle) { - if (face.IsCeiling()) + if (face.Face.IsCeiling()) texture.Rotate(3); // WTF? But it works! texture.TexCoord3 = texture.TexCoord2; } @@ -1580,7 +1581,7 @@ private static bool ApplyTextureToFace(Room room, VectorInt2 pos, SectorFace fac if (textureApplied) { TextureArea currentTexture = sector.GetFaceTexture(face); - CheckTextureAttributes(room, pos, face, currentTexture); + CheckTextureAttributes(room, pos, face.Face, currentTexture); room.RoomGeometry.UpdateFaceTexture(pos.X, pos.Y, face, currentTexture, wasDoubleSided); } @@ -1588,11 +1589,11 @@ private static bool ApplyTextureToFace(Room room, VectorInt2 pos, SectorFace fac } TextureArea processedTexture = texture; - switch (face) + switch (face.Face) { case SectorFace.Floor: case SectorFace.Ceiling: - SectorSurface surface = face == SectorFace.Floor ? sector.Floor : sector.Ceiling; + SectorSurface surface = face.Face == SectorFace.Floor ? sector.Floor : sector.Ceiling; if (shape == FaceShape.Quad) break; if (surface.DiagonalSplit != DiagonalSplit.XnZn && @@ -1616,7 +1617,7 @@ private static bool ApplyTextureToFace(Room room, VectorInt2 pos, SectorFace fac case SectorFace.Floor_Triangle2: case SectorFace.Ceiling_Triangle2: - SectorSurface surface2 = face == SectorFace.Floor_Triangle2 ? sector.Floor : sector.Ceiling; + SectorSurface surface2 = face.Face == SectorFace.Floor_Triangle2 ? sector.Floor : sector.Ceiling; if (shape == FaceShape.Quad) break; if (surface2.DiagonalSplit == DiagonalSplit.XnZn || @@ -1761,14 +1762,14 @@ private static bool ApplyTextureToFace(Room room, VectorInt2 pos, SectorFace fac if (textureApplied) { TextureArea currentTexture = sector.GetFaceTexture(face); - CheckTextureAttributes(room, pos, face, currentTexture); + CheckTextureAttributes(room, pos, face.Face, currentTexture); room.RoomGeometry.UpdateFaceTexture(pos.X, pos.Y, face, currentTexture, wasDoubleSided); } return textureApplied; } - public static bool ApplyTexture(Room room, VectorInt2 pos, SectorFace face, TextureArea texture, bool disableUndo = false) + public static bool ApplyTexture(Room room, VectorInt2 pos, FaceLayerInfo face, TextureArea texture, bool disableUndo = false) { if(!disableUndo) _editor.UndoManager.PushGeometryChanged(_editor.SelectedRoom); @@ -2100,7 +2101,7 @@ public static void TexturizeWallSection(Room room, VectorInt2 pos, Direction dir } } - ApplyTextureToFace(room, pos, segment.Key, processedTexture); + ApplyTextureToFace(room, pos, new FaceLayerInfo(segment.Key, _editor.ActiveTextureLayer), processedTexture); } } @@ -2181,14 +2182,14 @@ public static void TexturizeGroup(Room room, SectorSelection selection, SectorSe { case SectorFace.Floor: case SectorFace.Floor_Triangle2: - ApplyTextureToFace(room, new VectorInt2(x, z), SectorFace.Floor, currentTexture); - ApplyTextureToFace(room, new VectorInt2(x, z), SectorFace.Floor_Triangle2, currentTexture); + ApplyTextureToFace(room, new VectorInt2(x, z), new FaceLayerInfo(SectorFace.Floor, _editor.ActiveTextureLayer), currentTexture); + ApplyTextureToFace(room, new VectorInt2(x, z), new FaceLayerInfo(SectorFace.Floor_Triangle2, _editor.ActiveTextureLayer), currentTexture); break; case SectorFace.Ceiling: case SectorFace.Ceiling_Triangle2: - ApplyTextureToFace(room, new VectorInt2(x, z), SectorFace.Ceiling, currentTexture, false); - ApplyTextureToFace(room, new VectorInt2(x, z), SectorFace.Ceiling_Triangle2, currentTexture, false); + ApplyTextureToFace(room, new VectorInt2(x, z), new FaceLayerInfo(SectorFace.Ceiling, _editor.ActiveTextureLayer), currentTexture, false); + ApplyTextureToFace(room, new VectorInt2(x, z), new FaceLayerInfo(SectorFace.Ceiling_Triangle2, _editor.ActiveTextureLayer), currentTexture, false); break; } } @@ -2215,23 +2216,23 @@ public static void TexturizeAll(Room room, SectorSelection selection, TextureAre case SectorFaceType.Floor: if (!room.Sectors[x, z].IsFullWall) { - ApplyTextureToFace(room, new VectorInt2(x, z), SectorFace.Floor, texture); - ApplyTextureToFace(room, new VectorInt2(x, z), SectorFace.Floor_Triangle2, texture); + ApplyTextureToFace(room, new VectorInt2(x, z), new FaceLayerInfo(SectorFace.Floor, _editor.ActiveTextureLayer), texture); + ApplyTextureToFace(room, new VectorInt2(x, z), new FaceLayerInfo(SectorFace.Floor_Triangle2, _editor.ActiveTextureLayer), texture); } break; case SectorFaceType.Ceiling: if (!room.Sectors[x, z].IsFullWall) { - ApplyTextureToFace(room, new VectorInt2(x, z), SectorFace.Ceiling, texture); - ApplyTextureToFace(room, new VectorInt2(x, z), SectorFace.Ceiling_Triangle2, texture); + ApplyTextureToFace(room, new VectorInt2(x, z), new FaceLayerInfo(SectorFace.Ceiling, _editor.ActiveTextureLayer), texture); + ApplyTextureToFace(room, new VectorInt2(x, z), new FaceLayerInfo(SectorFace.Ceiling_Triangle2, _editor.ActiveTextureLayer), texture); } break; case SectorFaceType.Wall: foreach (SectorFace face in SectorFaceExtensions.GetWalls()) if (room.IsFaceDefined(x, z, face)) - ApplyTextureToFace(room, new VectorInt2(x, z), face, texture); + ApplyTextureToFace(room, new VectorInt2(x, z), new FaceLayerInfo(face, _editor.ActiveTextureLayer), texture); break; } @@ -3659,9 +3660,9 @@ public static void MergeRoomsHorizontally(IEnumerable rooms, IWin32Window Sector newSector = sector.Value.GetSector(newSectorVec).Clone(); // Preserve outer wall textures - foreach (SectorFace face in oldSector.GetFaceTextures().Keys.Union(newSector.GetFaceTextures().Keys)) + foreach (FaceLayerInfo face in oldSector.GetFaceTexturesAll().Keys.Union(newSector.GetFaceTexturesAll().Keys)) { - var direction = face.GetDirection(); + var direction = face.Face.GetDirection(); if (direction == Direction.NegativeX || direction == Direction.PositiveX || direction == Direction.NegativeZ || direction == Direction.PositiveZ) newSector.SetFaceTexture(face, oldSector.GetFaceTexture(face)); } @@ -3690,22 +3691,24 @@ public static void MergeRoomsHorizontally(IEnumerable rooms, IWin32Window // Copy adjacent outer wall textures // Unfortunately they are always on the adjacent sector, so they need extra handling - for (SectorFace face = 0; face < SectorFace.Count; ++face) + for (SectorFace face = 0; face < SectorFace.Count; face++) + for (FaceLayer layer = 0; layer < FaceLayer.Count; layer++) { - var direction = face.GetDirection(); - switch (direction) + var faceLayer = new FaceLayerInfo(face, layer); + + switch (face.GetDirection()) { case Direction.NegativeX: - thisSectorPositiveX.SetFaceTexture(face, otherSectorPositiveX.GetFaceTexture(face)); + thisSectorPositiveX.SetFaceTexture(faceLayer, otherSectorPositiveX.GetFaceTexture(faceLayer)); break; case Direction.PositiveX: - thisSectorNegativeX.SetFaceTexture(face, otherSectorNegativeX.GetFaceTexture(face)); + thisSectorNegativeX.SetFaceTexture(faceLayer, otherSectorNegativeX.GetFaceTexture(faceLayer)); break; case Direction.NegativeZ: - thisSectorPositiveZ.SetFaceTexture(face, otherSectorPositiveZ.GetFaceTexture(face)); + thisSectorPositiveZ.SetFaceTexture(faceLayer, otherSectorPositiveZ.GetFaceTexture(faceLayer)); break; case Direction.PositiveZ: - thisSectorNegativeZ.SetFaceTexture(face, otherSectorNegativeZ.GetFaceTexture(face)); + thisSectorNegativeZ.SetFaceTexture(faceLayer, otherSectorNegativeZ.GetFaceTexture(faceLayer)); break; } } diff --git a/TombEditor/Forms/FormTextureRemap.cs b/TombEditor/Forms/FormTextureRemap.cs index b46774aac..833fe1ee3 100644 --- a/TombEditor/Forms/FormTextureRemap.cs +++ b/TombEditor/Forms/FormTextureRemap.cs @@ -9,6 +9,7 @@ using TombLib; using TombLib.LevelData; using TombLib.LevelData.SectorEnums; +using TombLib.LevelData.SectorStructs; using TombLib.Utils; namespace TombEditor.Forms @@ -153,7 +154,7 @@ private void butOk_Click(object sender, EventArgs e) int roomTextureCount = 0; foreach (Room room in relevantRooms) foreach (Sector sector in room.Sectors) - foreach (SectorFace face in sector.GetFaceTextures().Keys) + foreach (FaceLayerInfo face in sector.GetFaceTexturesAll().Keys) { var currentTextureArea = sector.GetFaceTexture(face); if (currentTextureArea.Texture == sourceTexture && diff --git a/TombEditor/Resources/icons_general/general-sticker-16.png b/TombEditor/Resources/icons_general/general-sticker-16.png new file mode 100644 index 0000000000000000000000000000000000000000..de3dff032176d0ebe774e603c54e93d5b02cfab4 GIT binary patch literal 341 zcmV-b0jmCqP) z`~wyPW|^!8LRi>vS&+X#ee~v4r*qFa_uj#?JwLwB`~803r&RinKpU2^i;hOYYxu%3 zzVU?KdcixmLQl*;u#O7)YJn&55a=grCz!$l-q2sP;2y)N+BDA5jM=!PnhCn`l2H%9 zGi=3t9;POO})VxqI00000NkvXXu0mjf2FQ-n literal 0 HcmV?d00001 diff --git a/TombLib/TombLib.Rendering/Rendering/DirectX11/Dx11RenderingDrawingRoom.cs b/TombLib/TombLib.Rendering/Rendering/DirectX11/Dx11RenderingDrawingRoom.cs index 765eed3bb..86deec728 100644 --- a/TombLib/TombLib.Rendering/Rendering/DirectX11/Dx11RenderingDrawingRoom.cs +++ b/TombLib/TombLib.Rendering/Rendering/DirectX11/Dx11RenderingDrawingRoom.cs @@ -61,7 +61,7 @@ public unsafe Dx11RenderingDrawingRoom(Dx11RenderingDevice device, Description d editorUVAndSectorTexture[i] = editorUv; } { - SectorFaceIdentity lastFaceIdentity = new SectorFaceIdentity(-1, -1, SectorFace.Floor); + SectorFaceIdentity lastFaceIdentity = new SectorFaceIdentity(-1, -1, new FaceLayerInfo(SectorFace.Floor, FaceLayer.Base)); uint lastSectorTexture = 0; uint overlay = 0; for (int i = 0, triangleCount = singleSidedVertexCount / 3; i < triangleCount; ++i) @@ -69,7 +69,7 @@ public unsafe Dx11RenderingDrawingRoom(Dx11RenderingDevice device, Description d SectorFaceIdentity currentFaceIdentity = roomGeometry.TriangleSectorInfo[i]; if (!lastFaceIdentity.Equals(currentFaceIdentity)) { - SectorTextureResult result = description.SectorTextureGet(description.Room, currentFaceIdentity.Position.X, currentFaceIdentity.Position.Y, currentFaceIdentity.Face); + SectorTextureResult result = description.SectorTextureGet(description.Room, currentFaceIdentity.Position.X, currentFaceIdentity.Position.Y, currentFaceIdentity.Face.Face); lastFaceIdentity = currentFaceIdentity; lastSectorTexture = 0; diff --git a/TombLib/TombLib/GeometryIO/RoomGeometryExporter.cs b/TombLib/TombLib/GeometryIO/RoomGeometryExporter.cs index 629430016..543c6b47c 100644 --- a/TombLib/TombLib/GeometryIO/RoomGeometryExporter.cs +++ b/TombLib/TombLib/GeometryIO/RoomGeometryExporter.cs @@ -105,7 +105,7 @@ public static RoomExportResult ExportRooms(IEnumerable roomsToExport, stri for (int z = 0; z < room.NumZSectors; z++) { var sector = room.GetSector(new VectorInt2(x, z)); - foreach (SectorFace face in sector.GetFaceTextures().Keys) + foreach (FaceLayerInfo face in sector.GetFaceTexturesAll().Keys) { var faceTexture = sector.GetFaceTexture(face); if (faceTexture.TextureIsInvisible || faceTexture.TextureIsUnavailable || faceTexture.Texture == null) @@ -179,7 +179,7 @@ public static RoomExportResult ExportRooms(IEnumerable roomsToExport, stri { var sector = room.GetSector(new VectorInt2(x, z)); - foreach (SectorFace face in sector.GetFaceTextures().Keys) + foreach (FaceLayerInfo face in sector.GetFaceTexturesAll().Keys) { var faceTexture = sector.GetFaceTexture(face); @@ -187,7 +187,7 @@ public static RoomExportResult ExportRooms(IEnumerable roomsToExport, stri continue; var range = room.RoomGeometry.VertexRangeLookup.TryGetOrDefault(new SectorFaceIdentity(x, z, face)); - var shape = room.GetFaceShape(x, z, face); + var shape = room.GetFaceShape(x, z, face.Face); if (shape == FaceShape.Quad) { @@ -218,7 +218,7 @@ public static RoomExportResult ExportRooms(IEnumerable roomsToExport, stri int textureWidth = textureArea1.Texture.Image.Width; int textureHeight = textureArea1.Texture.Image.Height; - if (face != SectorFace.Ceiling) + if (face.Face != SectorFace.Ceiling) { mesh.Positions.Add(room.RoomGeometry.VertexPositions[i + 3] + offset); mesh.Positions.Add(room.RoomGeometry.VertexPositions[i + 2] + offset); diff --git a/TombLib/TombLib/LevelData/Compilers/Rooms.cs b/TombLib/TombLib/LevelData/Compilers/Rooms.cs index acd7fea76..e12e6e7fe 100644 --- a/TombLib/TombLib/LevelData/Compilers/Rooms.cs +++ b/TombLib/TombLib/LevelData/Compilers/Rooms.cs @@ -347,10 +347,10 @@ private tr_room BuildRoom(Room room) if (!room.Properties.Hidden) for (int z = 0; z < room.NumZSectors; ++z) for (int x = 0; x < room.NumXSectors; ++x) - foreach (SectorFace face in room.Sectors[x, z].GetFaceTextures().Keys) + foreach (FaceLayerInfo face in room.Sectors[x, z].GetFaceTexturesAll().Keys) { var range = room.RoomGeometry.VertexRangeLookup.TryGetOrDefault(new SectorFaceIdentity(x, z, face)); - var shape = room.GetFaceShape(x, z, face); + var shape = room.GetFaceShape(x, z, face.Face); if (range.Count == 0) continue; @@ -383,7 +383,7 @@ private tr_room BuildRoom(Room room) { ushort vertex3Index; - if (face == SectorFace.Ceiling) + if (face.Face == SectorFace.Ceiling) { texture.Mirror(); vertex0Index = GetOrAddVertex(room, roomVerticesDictionary, roomVertices, vertexPositions[i + 1], vertexColors[i + 1]); @@ -434,7 +434,7 @@ private tr_room BuildRoom(Room room) } else { - if (face == SectorFace.Ceiling || face == SectorFace.Ceiling_Triangle2) + if (face.Face is SectorFace.Ceiling or SectorFace.Ceiling_Triangle2) texture.Mirror(true); vertex0Index = GetOrAddVertex(room, roomVerticesDictionary, roomVertices, vertexPositions[i + 0], vertexColors[i + 0]); diff --git a/TombLib/TombLib/LevelData/Compilers/Textures.cs b/TombLib/TombLib/LevelData/Compilers/Textures.cs index bab226ec7..3aaa202e2 100644 --- a/TombLib/TombLib/LevelData/Compilers/Textures.cs +++ b/TombLib/TombLib/LevelData/Compilers/Textures.cs @@ -72,11 +72,11 @@ private TextureFootStep.Type GetTextureSound(Room room, int x, int z) { Sector sector = room.Sectors[x, z]; - TextureFootStep.Type? result0 = GetTextureSound(!sector.Floor.IsQuad, sector.GetFaceTexture(SectorFace.Floor)); + TextureFootStep.Type? result0 = GetTextureSound(!sector.Floor.IsQuad, sector.GetFaceTexture(new(SectorFace.Floor, FaceLayer.Base))); if (result0.HasValue) return result0.Value; - TextureFootStep.Type? result1 = GetTextureSound(!sector.Floor.IsQuad, sector.GetFaceTexture(SectorFace.Floor_Triangle2)); + TextureFootStep.Type? result1 = GetTextureSound(!sector.Floor.IsQuad, sector.GetFaceTexture(new(SectorFace.Floor_Triangle2, FaceLayer.Base))); if (result1.HasValue) return result1.Value; diff --git a/TombLib/TombLib/LevelData/Compilers/TombEngine/Rooms.cs b/TombLib/TombLib/LevelData/Compilers/TombEngine/Rooms.cs index 785696252..8765f5b7e 100644 --- a/TombLib/TombLib/LevelData/Compilers/TombEngine/Rooms.cs +++ b/TombLib/TombLib/LevelData/Compilers/TombEngine/Rooms.cs @@ -298,10 +298,10 @@ private TombEngineRoom BuildRoom(Room room) if (!room.Properties.Hidden) for (int z = 0; z < room.NumZSectors; ++z) for (int x = 0; x < room.NumXSectors; ++x) - foreach (SectorFace face in room.Sectors[x, z].GetFaceTextures().Keys) + foreach (FaceLayerInfo face in room.Sectors[x, z].GetFaceTexturesAll().Keys) { var range = room.RoomGeometry.VertexRangeLookup.TryGetOrDefault(new SectorFaceIdentity(x, z, face)); - var shape = room.GetFaceShape(x, z, face); + var shape = room.GetFaceShape(x, z, face.Face); if (range.Count == 0) continue; @@ -335,7 +335,7 @@ private TombEngineRoom BuildRoom(Room room) { int vertex3Index; - if (face == SectorFace.Ceiling) + if (face.Face == SectorFace.Ceiling) { texture.Mirror(); vertex0Index = GetOrAddVertex(room, roomVerticesDictionary, roomVertices, vertexPositions[i + 1], vertexColors[i + 1], 0); @@ -375,7 +375,7 @@ private TombEngineRoom BuildRoom(Room room) } else { - if (face == SectorFace.Ceiling || face == SectorFace.Ceiling_Triangle2) + if (face.Face is SectorFace.Ceiling or SectorFace.Ceiling_Triangle2) texture.Mirror(true); vertex0Index = GetOrAddVertex(room, roomVerticesDictionary, roomVertices, vertexPositions[i + 0], vertexColors[i + 0], 0); diff --git a/TombLib/TombLib/LevelData/Compilers/TombEngine/Textures.cs b/TombLib/TombLib/LevelData/Compilers/TombEngine/Textures.cs index 0bb475cad..3684d3281 100644 --- a/TombLib/TombLib/LevelData/Compilers/TombEngine/Textures.cs +++ b/TombLib/TombLib/LevelData/Compilers/TombEngine/Textures.cs @@ -35,11 +35,11 @@ private TextureFootStep.Type GetTextureSound(Room room, int x, int z) { Sector sector = room.Sectors[x, z]; - TextureFootStep.Type? result0 = GetTextureSound(!sector.Floor.IsQuad, sector.GetFaceTexture(SectorFace.Floor)); + TextureFootStep.Type? result0 = GetTextureSound(!sector.Floor.IsQuad, sector.GetFaceTexture(new(SectorFace.Floor, FaceLayer.Base))); if (result0.HasValue) return result0.Value; - TextureFootStep.Type? result1 = GetTextureSound(!sector.Floor.IsQuad, sector.GetFaceTexture(SectorFace.Floor_Triangle2)); + TextureFootStep.Type? result1 = GetTextureSound(!sector.Floor.IsQuad, sector.GetFaceTexture(new(SectorFace.Floor_Triangle2, FaceLayer.Base))); if (result1.HasValue) return result1.Value; diff --git a/TombLib/TombLib/LevelData/IO/LegacyRepair.cs b/TombLib/TombLib/LevelData/IO/LegacyRepair.cs index 3d6d90a8e..991fd865c 100644 --- a/TombLib/TombLib/LevelData/IO/LegacyRepair.cs +++ b/TombLib/TombLib/LevelData/IO/LegacyRepair.cs @@ -52,25 +52,25 @@ private static void SwapFloor2FacesWhereApplicable(Room room, int x, int z) if (xn.Sector is not null) { if (split.XnZn > xn.Sector.Ceiling.XpZn || split.XnZp > xn.Sector.Ceiling.XpZp) - sector.SetFaceTexture(SectorFace.Wall_NegativeX_Floor2, sector.GetFaceTexture(SectorFace.Wall_NegativeX_QA)); + sector.SetFaceTexture(new(SectorFace.Wall_NegativeX_Floor2, FaceLayer.Base), sector.GetFaceTexture(new(SectorFace.Wall_NegativeX_QA, FaceLayer.Base))); } if (xp.Sector is not null) { if (split.XpZn > xp.Sector.Ceiling.XnZn || split.XpZp > xp.Sector.Ceiling.XnZp) - sector.SetFaceTexture(SectorFace.Wall_PositiveX_Floor2, sector.GetFaceTexture(SectorFace.Wall_PositiveX_QA)); + sector.SetFaceTexture(new(SectorFace.Wall_PositiveX_Floor2, FaceLayer.Base), sector.GetFaceTexture(new(SectorFace.Wall_PositiveX_QA, FaceLayer.Base))); } if (zn.Sector is not null) { if (split.XnZn > zn.Sector.Ceiling.XnZp || split.XpZn > zn.Sector.Ceiling.XpZp) - sector.SetFaceTexture(SectorFace.Wall_NegativeZ_Floor2, sector.GetFaceTexture(SectorFace.Wall_NegativeZ_QA)); + sector.SetFaceTexture(new(SectorFace.Wall_NegativeZ_Floor2, FaceLayer.Base), sector.GetFaceTexture(new(SectorFace.Wall_NegativeZ_QA, FaceLayer.Base))); } if (zp.Sector is not null) { if (split.XnZp > zp.Sector.Ceiling.XnZn || split.XpZp > zp.Sector.Ceiling.XpZn) - sector.SetFaceTexture(SectorFace.Wall_PositiveZ_Floor2, sector.GetFaceTexture(SectorFace.Wall_PositiveZ_QA)); + sector.SetFaceTexture(new(SectorFace.Wall_PositiveZ_Floor2, FaceLayer.Base), sector.GetFaceTexture(new(SectorFace.Wall_PositiveZ_QA, FaceLayer.Base))); } } @@ -98,25 +98,25 @@ private static void SwapCeiling2FacesWhereApplicable(Room room, int x, int z) if (xn.Sector is not null) { if (split.XnZn < xn.Sector.Floor.XpZn || split.XnZp < xn.Sector.Floor.XpZp) - sector.SetFaceTexture(SectorFace.Wall_NegativeX_Ceiling2, sector.GetFaceTexture(SectorFace.Wall_NegativeX_WS)); + sector.SetFaceTexture(new(SectorFace.Wall_NegativeX_Ceiling2, FaceLayer.Base), sector.GetFaceTexture(new(SectorFace.Wall_NegativeX_WS, FaceLayer.Base))); } if (xp.Sector is not null) { if (split.XpZn < xp.Sector.Floor.XnZn || split.XpZp < xp.Sector.Floor.XnZp) - sector.SetFaceTexture(SectorFace.Wall_PositiveX_Ceiling2, sector.GetFaceTexture(SectorFace.Wall_PositiveX_WS)); + sector.SetFaceTexture(new(SectorFace.Wall_PositiveX_Ceiling2, FaceLayer.Base), sector.GetFaceTexture(new(SectorFace.Wall_PositiveX_WS, FaceLayer.Base))); } if (zn.Sector is not null) { if (split.XnZn < zn.Sector.Floor.XnZp || split.XpZn < zn.Sector.Floor.XpZp) - sector.SetFaceTexture(SectorFace.Wall_NegativeZ_Ceiling2, sector.GetFaceTexture(SectorFace.Wall_NegativeZ_WS)); + sector.SetFaceTexture(new(SectorFace.Wall_NegativeZ_Ceiling2, FaceLayer.Base), sector.GetFaceTexture(new(SectorFace.Wall_NegativeZ_WS, FaceLayer.Base))); } if (zp.Sector is not null) { if (split.XnZp < zp.Sector.Floor.XnZn || split.XpZp < zp.Sector.Floor.XpZn) - sector.SetFaceTexture(SectorFace.Wall_PositiveZ_Ceiling2, sector.GetFaceTexture(SectorFace.Wall_PositiveZ_WS)); + sector.SetFaceTexture(new(SectorFace.Wall_PositiveZ_Ceiling2, FaceLayer.Base), sector.GetFaceTexture(new(SectorFace.Wall_PositiveZ_WS, FaceLayer.Base))); } } @@ -145,43 +145,43 @@ private static void SwapDiagonalFloor2FacesWhereApplicable(Room room, int x, int return; TextureArea - qaPositiveZ = localSector.GetFaceTexture(SectorFace.Wall_PositiveZ_QA), - qaNegativeZ = localSector.GetFaceTexture(SectorFace.Wall_NegativeZ_QA), - qaNegativeX = localSector.GetFaceTexture(SectorFace.Wall_NegativeX_QA), - qaPositiveX = localSector.GetFaceTexture(SectorFace.Wall_PositiveX_QA); + qaPositiveZ = localSector.GetFaceTexture(new(SectorFace.Wall_PositiveZ_QA, FaceLayer.Base)), + qaNegativeZ = localSector.GetFaceTexture(new(SectorFace.Wall_NegativeZ_QA, FaceLayer.Base)), + qaNegativeX = localSector.GetFaceTexture(new(SectorFace.Wall_NegativeX_QA, FaceLayer.Base)), + qaPositiveX = localSector.GetFaceTexture(new(SectorFace.Wall_PositiveX_QA, FaceLayer.Base)); switch (probingSector.Floor.DiagonalSplit) { case DiagonalSplit.XnZp: if (split.XnZn > localSector.Floor.XpZn) - localSector.SetFaceTexture(SectorFace.Wall_NegativeZ_Floor2, qaNegativeZ); + localSector.SetFaceTexture(new(SectorFace.Wall_NegativeZ_Floor2, FaceLayer.Base), qaNegativeZ); if (split.XpZp > localSector.Floor.XpZn) - localSector.SetFaceTexture(SectorFace.Wall_PositiveX_Floor2, qaPositiveX); + localSector.SetFaceTexture(new(SectorFace.Wall_PositiveX_Floor2, FaceLayer.Base), qaPositiveX); break; case DiagonalSplit.XpZn: if (split.XnZn > localSector.Floor.XnZp) - localSector.SetFaceTexture(SectorFace.Wall_NegativeX_Floor2, qaNegativeX); + localSector.SetFaceTexture(new(SectorFace.Wall_NegativeX_Floor2, FaceLayer.Base), qaNegativeX); if (split.XpZp > localSector.Floor.XnZp) - localSector.SetFaceTexture(SectorFace.Wall_PositiveZ_Floor2, qaPositiveZ); + localSector.SetFaceTexture(new(SectorFace.Wall_PositiveZ_Floor2, FaceLayer.Base), qaPositiveZ); break; case DiagonalSplit.XpZp: if (split.XpZn > localSector.Floor.XnZn) - localSector.SetFaceTexture(SectorFace.Wall_NegativeZ_Floor2, qaNegativeZ); + localSector.SetFaceTexture(new(SectorFace.Wall_NegativeZ_Floor2, FaceLayer.Base), qaNegativeZ); if (split.XnZp > localSector.Floor.XnZn) - localSector.SetFaceTexture(SectorFace.Wall_NegativeX_Floor2, qaNegativeX); + localSector.SetFaceTexture(new(SectorFace.Wall_NegativeX_Floor2, FaceLayer.Base), qaNegativeX); break; case DiagonalSplit.XnZn: if (split.XnZp > localSector.Floor.XpZp) - localSector.SetFaceTexture(SectorFace.Wall_PositiveZ_Floor2, qaPositiveZ); + localSector.SetFaceTexture(new(SectorFace.Wall_PositiveZ_Floor2, FaceLayer.Base), qaPositiveZ); if (split.XpZn > localSector.Floor.XpZp) - localSector.SetFaceTexture(SectorFace.Wall_PositiveX_Floor2, qaPositiveX); + localSector.SetFaceTexture(new(SectorFace.Wall_PositiveX_Floor2, FaceLayer.Base), qaPositiveX); break; } } @@ -211,43 +211,43 @@ private static void SwapDiagonalCeiling2FacesWhereApplicable(Room room, int x, i return; TextureArea - wsPositiveZ = localSector.GetFaceTexture(SectorFace.Wall_PositiveZ_WS), - wsNegativeZ = localSector.GetFaceTexture(SectorFace.Wall_NegativeZ_WS), - wsNegativeX = localSector.GetFaceTexture(SectorFace.Wall_NegativeX_WS), - wsPositiveX = localSector.GetFaceTexture(SectorFace.Wall_PositiveX_WS); + wsPositiveZ = localSector.GetFaceTexture(new(SectorFace.Wall_PositiveZ_WS, FaceLayer.Base)), + wsNegativeZ = localSector.GetFaceTexture(new(SectorFace.Wall_NegativeZ_WS, FaceLayer.Base)), + wsNegativeX = localSector.GetFaceTexture(new(SectorFace.Wall_NegativeX_WS, FaceLayer.Base)), + wsPositiveX = localSector.GetFaceTexture(new(SectorFace.Wall_PositiveX_WS, FaceLayer.Base)); switch (probingSector.Ceiling.DiagonalSplit) { case DiagonalSplit.XnZp: if (split.XnZn < localSector.Ceiling.XpZn) - localSector.SetFaceTexture(SectorFace.Wall_NegativeZ_Ceiling2, wsNegativeZ); + localSector.SetFaceTexture(new(SectorFace.Wall_NegativeZ_Ceiling2, FaceLayer.Base), wsNegativeZ); if (split.XpZp < localSector.Ceiling.XpZn) - localSector.SetFaceTexture(SectorFace.Wall_PositiveX_Ceiling2, wsPositiveX); + localSector.SetFaceTexture(new(SectorFace.Wall_PositiveX_Ceiling2, FaceLayer.Base), wsPositiveX); break; case DiagonalSplit.XpZn: if (split.XnZn < localSector.Ceiling.XnZp) - localSector.SetFaceTexture(SectorFace.Wall_NegativeX_Ceiling2, wsNegativeX); + localSector.SetFaceTexture(new(SectorFace.Wall_NegativeX_Ceiling2, FaceLayer.Base), wsNegativeX); if (split.XpZp < localSector.Ceiling.XnZp) - localSector.SetFaceTexture(SectorFace.Wall_PositiveZ_Ceiling2, wsPositiveZ); + localSector.SetFaceTexture(new(SectorFace.Wall_PositiveZ_Ceiling2, FaceLayer.Base), wsPositiveZ); break; case DiagonalSplit.XpZp: if (split.XpZn < localSector.Ceiling.XnZn) - localSector.SetFaceTexture(SectorFace.Wall_NegativeZ_Ceiling2, wsNegativeZ); + localSector.SetFaceTexture(new(SectorFace.Wall_NegativeZ_Ceiling2, FaceLayer.Base), wsNegativeZ); if (split.XnZp < localSector.Ceiling.XnZn) - localSector.SetFaceTexture(SectorFace.Wall_NegativeX_Ceiling2, wsNegativeX); + localSector.SetFaceTexture(new(SectorFace.Wall_NegativeX_Ceiling2, FaceLayer.Base), wsNegativeX); break; case DiagonalSplit.XnZn: if (split.XnZp < localSector.Ceiling.XpZp) - localSector.SetFaceTexture(SectorFace.Wall_PositiveZ_Ceiling2, wsPositiveZ); + localSector.SetFaceTexture(new(SectorFace.Wall_PositiveZ_Ceiling2, FaceLayer.Base), wsPositiveZ); if (split.XpZn < localSector.Ceiling.XpZp) - localSector.SetFaceTexture(SectorFace.Wall_PositiveX_Ceiling2, wsPositiveX); + localSector.SetFaceTexture(new(SectorFace.Wall_PositiveX_Ceiling2, FaceLayer.Base), wsPositiveX); break; } } diff --git a/TombLib/TombLib/LevelData/IO/Prj2Chunks.cs b/TombLib/TombLib/LevelData/IO/Prj2Chunks.cs index 0778f0ffa..d3fb354fe 100644 --- a/TombLib/TombLib/LevelData/IO/Prj2Chunks.cs +++ b/TombLib/TombLib/LevelData/IO/Prj2Chunks.cs @@ -135,7 +135,9 @@ internal static class Prj2Chunks /**************/public static readonly ChunkId SectorCeilingSubdivisions2 = new ChunkId(new byte[] { 10 }); /**************/public static readonly ChunkId TextureLevelTexture = new ChunkId(new byte[] { 16 }); /**************/public static readonly ChunkId TextureLevelTexture2 = new ChunkId(new byte[] { 18 }); + /**************/public static readonly ChunkId TextureLevelTexture3 = new ChunkId(new byte[] { 19 }); /**************/public static readonly ChunkId TextureInvisible = new ChunkId(new byte[] { 17 }); + /**************/public static readonly ChunkId TextureInvisible2 = new ChunkId(new byte[] { 20 }); /******/public static readonly ChunkId RoomAmbientLight = ChunkId.FromString("TeAmbient"); /******/public static readonly ChunkId RoomAlternate = ChunkId.FromString("TeAlternate"); /**********/public static readonly ChunkId AlternateRoom = ChunkId.FromString("TeRoom"); diff --git a/TombLib/TombLib/LevelData/IO/Prj2Loader.cs b/TombLib/TombLib/LevelData/IO/Prj2Loader.cs index a246b041b..f1e75faec 100644 --- a/TombLib/TombLib/LevelData/IO/Prj2Loader.cs +++ b/TombLib/TombLib/LevelData/IO/Prj2Loader.cs @@ -933,9 +933,14 @@ private static bool LoadRooms(ChunkReader chunkIO, ChunkId idOuter, Level level, } } else if (id4 == Prj2Chunks.TextureLevelTexture || - id4 == Prj2Chunks.TextureLevelTexture2) + id4 == Prj2Chunks.TextureLevelTexture2 || + id4 == Prj2Chunks.TextureLevelTexture3) { SectorFace face = (SectorFace)LEB128.ReadLong(chunkIO.Raw); + FaceLayer layer = FaceLayer.Base; + + if (id4 == Prj2Chunks.TextureLevelTexture3) + layer = (FaceLayer)LEB128.ReadLong(chunkIO.Raw); var textureArea = new TextureArea(); textureArea.TexCoord0 = chunkIO.Raw.ReadVector2(); @@ -943,7 +948,7 @@ private static bool LoadRooms(ChunkReader chunkIO, ChunkId idOuter, Level level, textureArea.TexCoord2 = chunkIO.Raw.ReadVector2(); textureArea.TexCoord3 = chunkIO.Raw.ReadVector2(); - if(id4 == Prj2Chunks.TextureLevelTexture2) + if(id4 == Prj2Chunks.TextureLevelTexture2 || id4 == Prj2Chunks.TextureLevelTexture3) { textureArea.ParentArea.Start = chunkIO.Raw.ReadVector2(); textureArea.ParentArea.End = chunkIO.Raw.ReadVector2(); @@ -956,12 +961,18 @@ private static bool LoadRooms(ChunkReader chunkIO, ChunkId idOuter, Level level, textureArea.DoubleSided = (blendFlag & 1) != 0; textureArea.Texture = levelSettingsIds.LevelTextures.TryGetOrDefault(LEB128.ReadLong(chunkIO.Raw)); - sector.SetFaceTexture(face, textureArea); + sector.SetFaceTexture(new FaceLayerInfo(face, layer), textureArea); } else if (id4 == Prj2Chunks.TextureInvisible) { SectorFace face = (SectorFace)LEB128.ReadLong(chunkIO.Raw); - sector.SetFaceTexture(face, TextureArea.Invisible); + sector.SetFaceTexture(new FaceLayerInfo(face, FaceLayer.Base), TextureArea.Invisible); + } + else if (id4 == Prj2Chunks.TextureInvisible2) + { + SectorFace face = (SectorFace)LEB128.ReadLong(chunkIO.Raw); + FaceLayer layer = (FaceLayer)LEB128.ReadLong(chunkIO.Raw); + sector.SetFaceTexture(new FaceLayerInfo(face, layer), TextureArea.Invisible); } else return false; diff --git a/TombLib/TombLib/LevelData/IO/Prj2Writer.cs b/TombLib/TombLib/LevelData/IO/Prj2Writer.cs index 6e9b97536..13798f32f 100644 --- a/TombLib/TombLib/LevelData/IO/Prj2Writer.cs +++ b/TombLib/TombLib/LevelData/IO/Prj2Writer.cs @@ -463,7 +463,7 @@ private static void WriteRooms(ChunkWriter chunkIO, Dictionary rooms, for (SectorEdge edge = 0; edge < SectorEdge.Count; ++edge) LEB128.Write(chunkIO.Raw, b.GetHeight(splitVertical, edge)); } - foreach (SectorFace face in b.GetFaceTextures().Where(texture => room.RoomGeometry.VertexRangeLookup.ContainsKey(new SectorFaceIdentity(x, z, texture.Key))).Select(x => x.Key)) + foreach (FaceLayerInfo face in b.GetFaceTexturesAll().Where(texture => room.RoomGeometry.VertexRangeLookup.ContainsKey(new SectorFaceIdentity(x, z, texture.Key))).Select(x => x.Key)) { TextureArea texture = b.GetFaceTexture(face); @@ -473,11 +473,12 @@ private static void WriteRooms(ChunkWriter chunkIO, Dictionary rooms, if (texture.Texture is LevelTexture t) { if (t != null && levelSettingIds.LevelTextures.ContainsKey(t)) - using (var chunkTextureLevelTexture = chunkIO.WriteChunk(Prj2Chunks.TextureLevelTexture2, LEB128.MaximumSize1Byte)) + using (var chunkTextureLevelTexture = chunkIO.WriteChunk(Prj2Chunks.TextureLevelTexture3, LEB128.MaximumSize1Byte)) { int textureIndex = levelSettingIds.LevelTextures[t]; - LEB128.Write(chunkIO.Raw, (long)face); + LEB128.Write(chunkIO.Raw, (long)face.Face); + LEB128.Write(chunkIO.Raw, (long)face.Layer); chunkIO.Raw.Write(texture.TexCoord0); chunkIO.Raw.Write(texture.TexCoord1); chunkIO.Raw.Write(texture.TexCoord2); @@ -491,7 +492,11 @@ private static void WriteRooms(ChunkWriter chunkIO, Dictionary rooms, logger.Warn("Room " + room.Name + " has a texture referring to a texture file " + t.Path + " which is missing from project."); } else if (texture.Texture == TextureInvisible.Instance) - chunkIO.WriteChunkInt(Prj2Chunks.TextureInvisible, (long)face); + using (var chunkTextureInvisible = chunkIO.WriteChunk(Prj2Chunks.TextureInvisible2, LEB128.MaximumSize1Byte)) + { + LEB128.Write(chunkIO.Raw, (long)face.Face); + LEB128.Write(chunkIO.Raw, (long)face.Layer); + } else throw new NotSupportedException("Unsupported texture type " + texture.Texture.GetType().Name); } diff --git a/TombLib/TombLib/LevelData/IO/PrjLoader.cs b/TombLib/TombLib/LevelData/IO/PrjLoader.cs index 95b5e391d..4ef4677a9 100644 --- a/TombLib/TombLib/LevelData/IO/PrjLoader.cs +++ b/TombLib/TombLib/LevelData/IO/PrjLoader.cs @@ -9,6 +9,7 @@ using System.Threading.Tasks; using TombLib.IO; using TombLib.LevelData.SectorEnums; +using TombLib.LevelData.SectorStructs; using TombLib.Utils; using TombLib.Wad; using TombLib.Wad.Catalog; @@ -2075,10 +2076,10 @@ private static void LoadTextureArea(Room room, int x, int z, SectorFace face, Le { case 0x0000: // TYPE_TEXTURE_NONE default: - sector.SetFaceTexture(face, new TextureArea()); + sector.SetFaceTexture(new FaceLayerInfo(face, FaceLayer.Base), new TextureArea()); return; case 0x0003: // TYPE_TEXTURE_COLOR - sector.SetFaceTexture(face, TextureArea.Invisible); + sector.SetFaceTexture(new FaceLayerInfo(face, FaceLayer.Base), TextureArea.Invisible); return; case 0x0007: // TYPE_TEXTURE_TILE int texIndex = ((prjFace._txtFlags & 0x03) << 8) | prjFace._txtIndex; @@ -2151,7 +2152,7 @@ private static void LoadTextureArea(Room room, int x, int z, SectorFace face, Le break; default: logger.Warn("Unknown texture triangle selection " + prjFace._txtTriangle); - sector.SetFaceTexture(face, new TextureArea()); + sector.SetFaceTexture(new FaceLayerInfo(face, FaceLayer.Base), new TextureArea()); return; } @@ -2225,7 +2226,7 @@ private static void LoadTextureArea(Room room, int x, int z, SectorFace face, Le } } - sector.SetFaceTexture(face, texture); + sector.SetFaceTexture(new FaceLayerInfo(face, FaceLayer.Base), texture); return; } } diff --git a/TombLib/TombLib/LevelData/Level.cs b/TombLib/TombLib/LevelData/Level.cs index 791981100..e1c0ac167 100644 --- a/TombLib/TombLib/LevelData/Level.cs +++ b/TombLib/TombLib/LevelData/Level.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Threading.Tasks; using TombLib.LevelData.SectorEnums; +using TombLib.LevelData.SectorStructs; using TombLib.Utils; using TombLib.Wad.Catalog; @@ -19,6 +20,8 @@ public class Level public const short MaxNumberOfRooms = 1024; + public const float DecalOffset = 8.0f; + public Room[] Rooms { get; } = new Room[MaxNumberOfRooms]; // Rooms in level public LevelSettings Settings { get; private set; } = new LevelSettings(); public ScriptIdTable GlobalScriptingIdsTable { get; } = new ScriptIdTable(); @@ -274,7 +277,7 @@ public IReadOnlyList TransformRooms(IEnumerable roomsToRotate, RectT VectorInt2 newSectorPosition = transformation.Transform(new VectorInt2(x, z), oldRoom.SectorSize); newRoom.Sectors[newSectorPosition.X, newSectorPosition.Y] = oldRoom.Sectors[x, z].Clone(); newRoom.Sectors[newSectorPosition.X, newSectorPosition.Y].Transform(transformation, null, - oldFace => oldRoom.GetFaceShape(x, z, oldFace)); + oldFace => oldRoom.GetFaceShape(x, z, oldFace.Face)); } newRooms[i] = newRoom; } @@ -368,7 +371,7 @@ public void RemoveTextures(Predicate askIfTextureToRemove) Parallel.ForEach(ExistingRooms, room => { foreach (Sector sector in room.Sectors) - foreach (SectorFace face in sector.GetFaceTextures().Keys) + foreach (FaceLayerInfo face in sector.GetFaceTexturesAll().Keys) { TextureArea currentTextureArea = sector.GetFaceTexture(face); LevelTexture currentTexture = currentTextureArea.Texture as LevelTexture; diff --git a/TombLib/TombLib/LevelData/Room.cs b/TombLib/TombLib/LevelData/Room.cs index c0fcc8dc7..fa38cebd6 100644 --- a/TombLib/TombLib/LevelData/Room.cs +++ b/TombLib/TombLib/LevelData/Room.cs @@ -884,13 +884,14 @@ public bool CornerSelected(RectangleInt2 area) } public bool IsFaceDefined(int x, int z, SectorFace face) - { - return RoomGeometry.VertexRangeLookup.TryGetOrDefault(new SectorFaceIdentity(x, z, face)).Count != 0; - } + => RoomGeometry.VertexRangeLookup.TryGetOrDefault(new SectorFaceIdentity(x, z, new FaceLayerInfo(face, FaceLayer.Base))).Count != 0; + + public bool IsFaceDefined(int x, int z, FaceLayerInfo faceLayer) + => RoomGeometry.VertexRangeLookup.TryGetOrDefault(new SectorFaceIdentity(x, z, faceLayer)).Count != 0; public float GetFaceHighestPoint(int x, int z, SectorFace face) { - var range = RoomGeometry.VertexRangeLookup.TryGetOrDefault(new SectorFaceIdentity(x, z, face)); + var range = RoomGeometry.VertexRangeLookup.TryGetOrDefault(new SectorFaceIdentity(x, z, new FaceLayerInfo(face, FaceLayer.Base))); float max = float.NegativeInfinity; for (int i = 0; i < range.Count; ++i) max = Math.Max(RoomGeometry.VertexPositions[i + range.Start].Y, max); @@ -899,7 +900,7 @@ public float GetFaceHighestPoint(int x, int z, SectorFace face) public float GetFaceLowestPoint(int x, int z, SectorFace face) { - var range = RoomGeometry.VertexRangeLookup.TryGetOrDefault(new SectorFaceIdentity(x, z, face)); + var range = RoomGeometry.VertexRangeLookup.TryGetOrDefault(new SectorFaceIdentity(x, z, new FaceLayerInfo(face, FaceLayer.Base))); float max = float.PositiveInfinity; for (int i = 0; i < range.Count; ++i) max = Math.Min(RoomGeometry.VertexPositions[i + range.Start].Y, max); @@ -908,7 +909,7 @@ public float GetFaceLowestPoint(int x, int z, SectorFace face) public FaceShape GetFaceShape(int x, int z, SectorFace face) { - switch (RoomGeometry.VertexRangeLookup.TryGetOrDefault(new SectorFaceIdentity(x, z, face)).Count) + switch (RoomGeometry.VertexRangeLookup.TryGetOrDefault(new SectorFaceIdentity(x, z, new FaceLayerInfo(face, FaceLayer.Base))).Count) { case 3: return FaceShape.Triangle; @@ -1634,7 +1635,7 @@ public void CopyDependentLevelSettings(CopyDependentLevelSettingsArgs args) for (int x = 0; x < NumXSectors; ++x) { Sector sector = Sectors[x, z]; - foreach (SectorFace face in sector.GetFaceTextures().Keys) + foreach (FaceLayerInfo face in sector.GetFaceTexturesAll().Keys) { TextureArea textureArea = sector.GetFaceTexture(face); var sourceTexture = textureArea.Texture as LevelTexture; @@ -1668,7 +1669,7 @@ public HashSet GetTextures() for (int x = 0; x < NumXSectors; ++x) { Sector sector = Sectors[x, z]; - foreach (SectorFace face in sector.GetFaceTextures().Keys) + foreach (FaceLayerInfo face in sector.GetFaceTexturesAll().Keys) result.Add(sector.GetFaceTexture(face).Texture); } return result; @@ -1695,10 +1696,10 @@ public void GetGeometryStatistics(out int vertices, out int faces) if (!Properties.Hidden) for (int z = 0; z < NumZSectors; ++z) for (int x = 0; x < NumXSectors; ++x) - foreach (SectorFace face in Sectors[x, z].GetFaceTextures().Keys) + foreach (FaceLayerInfo face in Sectors[x, z].GetFaceTexturesAll().Keys) { var range = RoomGeometry.VertexRangeLookup.TryGetOrDefault(new SectorFaceIdentity(x, z, face)); - var shape = GetFaceShape(x, z, face); + var shape = GetFaceShape(x, z, face.Face); if (range.Count == 0) continue; @@ -1718,7 +1719,7 @@ public void GetGeometryStatistics(out int vertices, out int faces) if (shape == FaceShape.Quad) { - if (face == SectorFace.Ceiling) + if (face.Face == SectorFace.Ceiling) { LevelCompilerClassicTR.GetOrAddVertex(this, roomVerticesDictionary, roomVertices, vertexPositions[i + 1], vertexColors[i + 1]); LevelCompilerClassicTR.GetOrAddVertex(this, roomVerticesDictionary, roomVertices, vertexPositions[i + 2], vertexColors[i + 2]); diff --git a/TombLib/TombLib/LevelData/Sector.cs b/TombLib/TombLib/LevelData/Sector.cs index 60806dcd0..847bf9fae 100644 --- a/TombLib/TombLib/LevelData/Sector.cs +++ b/TombLib/TombLib/LevelData/Sector.cs @@ -27,7 +27,7 @@ public enum SlopeCalculationMode public bool ForceFloorSolid { get; set; } // If this is set to true, portals are overwritten for this sector. public List ExtraFloorSplits { get; } = new(); public List ExtraCeilingSplits { get; } = new(); - private Dictionary _faceTextures { get; } = new(); + private Dictionary _faceTextures { get; } = new(); public SectorSurface Floor; public SectorSurface Ceiling; @@ -59,7 +59,7 @@ public Sector Clone() Ceiling = Ceiling }; - foreach (KeyValuePair entry in _faceTextures) + foreach (KeyValuePair entry in _faceTextures) result._faceTextures[entry.Key] = entry.Value; foreach (SectorSplit split in ExtraFloorSplits) @@ -84,15 +84,10 @@ public bool HasFlag(SectorFlags flag) public bool IsAnyPortal => FloorPortal != null || CeilingPortal != null || WallPortal != null; public bool HasGhostBlock => GhostBlock != null; - public bool SetFaceTexture(SectorFace face, TextureArea texture) + public bool SetFaceTexture(FaceLayerInfo face, TextureArea texture) { if (texture == TextureArea.None) - { - if (_faceTextures.ContainsKey(face)) - _faceTextures.Remove(face); - - return true; - } + return _faceTextures.Remove(face); if (texture.TextureIsDegenerate) texture = TextureArea.Invisible; @@ -106,15 +101,14 @@ public bool SetFaceTexture(SectorFace face, TextureArea texture) return false; } - public TextureArea GetFaceTexture(SectorFace face) - { - return _faceTextures.GetValueOrDefault(face); - } + public TextureArea GetFaceTexture(FaceLayerInfo face) + => _faceTextures.GetValueOrDefault(face); - public Dictionary GetFaceTextures() - { - return _faceTextures; - } + public Dictionary GetFaceTextures(FaceLayer layer) + => _faceTextures.Where(kvp => kvp.Key.Layer == layer).ToDictionary(kvp => kvp.Key.Face, kvp => kvp.Value); + + public Dictionary GetFaceTexturesAll() + => _faceTextures; public IEnumerable GetVerticals() { @@ -148,7 +142,7 @@ public void ReplaceGeometry(Level level, Sector replacement) Flags = replacement.Flags; ForceFloorSolid = replacement.ForceFloorSolid; - foreach (SectorFace face in replacement.GetFaceTextures().Keys.Union(_faceTextures.Keys)) + foreach (FaceLayerInfo face in replacement.GetFaceTexturesAll().Keys.Union(_faceTextures.Keys)) { var texture = replacement.GetFaceTexture(face); if (texture.TextureIsInvisible || level.Settings.Textures.Contains(texture.Texture)) @@ -304,7 +298,7 @@ private static DiagonalSplit TransformDiagonalSplit(DiagonalSplit split, RectTra return split; } - private void MirrorWallTexture(SectorFace oldFace, Func oldFaceIsTriangle) + private void MirrorWallTexture(FaceLayerInfo oldFace, Func oldFaceIsTriangle) { if (!_faceTextures.TryGetValue(oldFace, out TextureArea area)) return; @@ -329,7 +323,7 @@ private void MirrorWallTexture(SectorFace oldFace, Func o // When mirroring is done, a oldFaceIsTriangle must be provided that can return the previous shape of texture faces. // Set "onlyFloor" to true, to only modify the floor. // Set "onlyFloor" to false, to only modify the ceiling. - public void Transform(RectTransformation transformation, bool? onlyFloor = null, Func oldFaceIsTriangle = null) + public void Transform(RectTransformation transformation, bool? onlyFloor = null, Func oldFaceIsTriangle = null) { // Rotate sector flags if (transformation.MirrorX) @@ -389,13 +383,15 @@ public void Transform(RectTransformation transformation, bool? onlyFloor = null, transformation.TransformValueDiagonalQuad(ref GhostBlock.Ceiling.XpZp, ref GhostBlock.Ceiling.XnZp, ref GhostBlock.Ceiling.XnZn, ref GhostBlock.Ceiling.XpZn); } + for (FaceLayer layer = 0; layer < FaceLayer.Count; layer++) + { // Rotate applied textures if (onlyFloor != false) { // Fix lower wall textures if (transformation.MirrorX) { - var faces = _faceTextures.Where(pair => pair.Key.IsFloorWall()).Select(pair => pair.Key).ToList(); + var faces = _faceTextures.Where(pair => pair.Key.Face.IsFloorWall()).Select(pair => pair.Key).ToList(); for (int i = 0; i < faces.Count; i++) MirrorWallTexture(faces[i], oldFaceIsTriangle); @@ -412,44 +408,48 @@ public void Transform(RectTransformation transformation, bool? onlyFloor = null, SectorFaceExtensions.GetExtraFloorSplitFace(Direction.NegativeZ, i)); } + FaceLayerInfo + floorKey = new(SectorFace.Floor, layer), + floorTriangle2Key = new(SectorFace.Floor_Triangle2, layer); + // Fix floor textures if (Floor.IsQuad) { - if (_faceTextures.ContainsKey(SectorFace.Floor)) - _faceTextures[SectorFace.Floor] = _faceTextures[SectorFace.Floor].Transform(transformation * new RectTransformation { QuadrantRotation = 2 }); + if (_faceTextures.ContainsKey(floorKey)) + _faceTextures[floorKey] = _faceTextures[floorKey].Transform(transformation * new RectTransformation { QuadrantRotation = 2 }); } else { // Mirror if (transformation.MirrorX) { - _faceTextures.TrySwap(SectorFace.Floor, SectorFace.Floor_Triangle2); + _faceTextures.TrySwap(floorKey, floorTriangle2Key); - if (_faceTextures.ContainsKey(SectorFace.Floor)) + if (_faceTextures.ContainsKey(floorKey)) { - TextureArea floor = _faceTextures[SectorFace.Floor]; + TextureArea floor = _faceTextures[floorKey]; Swap.Do(ref floor.TexCoord0, ref floor.TexCoord2); - _faceTextures[SectorFace.Floor] = floor; + _faceTextures[floorKey] = floor; } - if (_faceTextures.ContainsKey(SectorFace.Floor_Triangle2)) + if (_faceTextures.ContainsKey(floorTriangle2Key)) { - TextureArea floorTriangle2 = _faceTextures[SectorFace.Floor_Triangle2]; + TextureArea floorTriangle2 = _faceTextures[floorTriangle2Key]; Swap.Do(ref floorTriangle2.TexCoord0, ref floorTriangle2.TexCoord2); - _faceTextures[SectorFace.Floor_Triangle2] = floorTriangle2; + _faceTextures[floorTriangle2Key] = floorTriangle2; } if (Floor.DiagonalSplit != DiagonalSplit.None) // REMOVE this when we have better diaognal steps. - _faceTextures.TrySwap(SectorFace.Floor, SectorFace.Floor_Triangle2); + _faceTextures.TrySwap(floorKey, floorTriangle2Key); } // Rotation for (int i = 0; i < transformation.QuadrantRotation; ++i) { if (!oldFloorSplitDirectionIsXEqualsZReal) - _faceTextures.TrySwap(SectorFace.Floor, SectorFace.Floor_Triangle2); + _faceTextures.TrySwap(floorKey, floorTriangle2Key); if (Floor.DiagonalSplit != DiagonalSplit.None) // REMOVE this when we have better diaognal steps. - _faceTextures.TrySwap(SectorFace.Floor, SectorFace.Floor_Triangle2); + _faceTextures.TrySwap(floorKey, floorTriangle2Key); oldFloorSplitDirectionIsXEqualsZReal = !oldFloorSplitDirectionIsXEqualsZReal; } @@ -460,7 +460,7 @@ public void Transform(RectTransformation transformation, bool? onlyFloor = null, // Fix upper wall textures if (transformation.MirrorX) { - var faces = _faceTextures.Where(pair => pair.Key.IsCeilingWall()).Select(pair => pair.Key).ToList(); + var faces = _faceTextures.Where(pair => pair.Key.Face.IsCeilingWall()).Select(pair => pair.Key).ToList(); for (int i = 0; i < faces.Count; i++) MirrorWallTexture(faces[i], oldFaceIsTriangle); @@ -477,44 +477,48 @@ public void Transform(RectTransformation transformation, bool? onlyFloor = null, SectorFaceExtensions.GetExtraCeilingSplitFace(Direction.NegativeZ, i)); } + FaceLayerInfo + ceilingKey = new(SectorFace.Ceiling, layer), + ceilingTriangle2Key = new(SectorFace.Ceiling_Triangle2, layer); + // Fix ceiling textures if (Ceiling.IsQuad) { - if (_faceTextures.ContainsKey(SectorFace.Ceiling)) - _faceTextures[SectorFace.Ceiling] = _faceTextures[SectorFace.Ceiling].Transform(transformation * new RectTransformation { QuadrantRotation = 2 }); + if (_faceTextures.ContainsKey(ceilingKey)) + _faceTextures[ceilingKey] = _faceTextures[ceilingKey].Transform(transformation * new RectTransformation { QuadrantRotation = 2 }); } else { // Mirror if (transformation.MirrorX) { - _faceTextures.TrySwap(SectorFace.Ceiling, SectorFace.Ceiling_Triangle2); + _faceTextures.TrySwap(ceilingKey, ceilingTriangle2Key); - if (_faceTextures.ContainsKey(SectorFace.Ceiling)) + if (_faceTextures.ContainsKey(ceilingKey)) { - TextureArea ceiling = _faceTextures[SectorFace.Ceiling]; + TextureArea ceiling = _faceTextures[ceilingKey]; Swap.Do(ref ceiling.TexCoord0, ref ceiling.TexCoord2); - _faceTextures[SectorFace.Ceiling] = ceiling; + _faceTextures[ceilingKey] = ceiling; } - if (_faceTextures.ContainsKey(SectorFace.Ceiling_Triangle2)) + if (_faceTextures.ContainsKey(ceilingTriangle2Key)) { - TextureArea ceilingTriangle2 = _faceTextures[SectorFace.Ceiling_Triangle2]; + TextureArea ceilingTriangle2 = _faceTextures[ceilingTriangle2Key]; Swap.Do(ref ceilingTriangle2.TexCoord0, ref ceilingTriangle2.TexCoord2); - _faceTextures[SectorFace.Ceiling_Triangle2] = ceilingTriangle2; + _faceTextures[ceilingTriangle2Key] = ceilingTriangle2; } if (Ceiling.DiagonalSplit != DiagonalSplit.None) // REMOVE this when we have better diaognal steps. - _faceTextures.TrySwap(SectorFace.Ceiling, SectorFace.Ceiling_Triangle2); + _faceTextures.TrySwap(ceilingKey, ceilingTriangle2Key); } // Rotation for (int i = 0; i < transformation.QuadrantRotation; ++i) { if (!oldCeilingSplitDirectionIsXEqualsZReal) - _faceTextures.TrySwap(SectorFace.Ceiling, SectorFace.Ceiling_Triangle2); + _faceTextures.TrySwap(ceilingKey, ceilingTriangle2Key); if (Ceiling.DiagonalSplit != DiagonalSplit.None) // REMOVE this when we have better diaognal steps. - _faceTextures.TrySwap(SectorFace.Ceiling, SectorFace.Ceiling_Triangle2); + _faceTextures.TrySwap(ceilingKey, ceilingTriangle2Key); oldCeilingSplitDirectionIsXEqualsZReal = !oldCeilingSplitDirectionIsXEqualsZReal; } @@ -524,15 +528,16 @@ public void Transform(RectTransformation transformation, bool? onlyFloor = null, { if (transformation.MirrorX) { - MirrorWallTexture(SectorFace.Wall_PositiveX_Middle, oldFaceIsTriangle); - MirrorWallTexture(SectorFace.Wall_PositiveZ_Middle, oldFaceIsTriangle); - MirrorWallTexture(SectorFace.Wall_NegativeX_Middle, oldFaceIsTriangle); - MirrorWallTexture(SectorFace.Wall_NegativeZ_Middle, oldFaceIsTriangle); - MirrorWallTexture(SectorFace.Wall_Diagonal_Middle, oldFaceIsTriangle); + MirrorWallTexture(new(SectorFace.Wall_PositiveX_Middle, layer), oldFaceIsTriangle); + MirrorWallTexture(new(SectorFace.Wall_PositiveZ_Middle, layer), oldFaceIsTriangle); + MirrorWallTexture(new(SectorFace.Wall_NegativeX_Middle, layer), oldFaceIsTriangle); + MirrorWallTexture(new(SectorFace.Wall_NegativeZ_Middle, layer), oldFaceIsTriangle); + MirrorWallTexture(new(SectorFace.Wall_Diagonal_Middle, layer), oldFaceIsTriangle); } transformation.TransformValueQuad(_faceTextures, SectorFace.Wall_PositiveX_Middle, SectorFace.Wall_PositiveZ_Middle, SectorFace.Wall_NegativeX_Middle, SectorFace.Wall_NegativeZ_Middle); } + } } public void FixHeights(SectorVerticalPart? vertical = null) diff --git a/TombLib/TombLib/LevelData/SectorEnums/FaceLayer.cs b/TombLib/TombLib/LevelData/SectorEnums/FaceLayer.cs new file mode 100644 index 000000000..91087224c --- /dev/null +++ b/TombLib/TombLib/LevelData/SectorEnums/FaceLayer.cs @@ -0,0 +1,8 @@ +namespace TombLib.LevelData.SectorEnums; + +public enum FaceLayer : byte +{ + Base, + Decal, + Count +} diff --git a/TombLib/TombLib/LevelData/SectorGeometry/SectorFaceData.cs b/TombLib/TombLib/LevelData/SectorGeometry/SectorFaceData.cs index caa68c009..9febf0edd 100644 --- a/TombLib/TombLib/LevelData/SectorGeometry/SectorFaceData.cs +++ b/TombLib/TombLib/LevelData/SectorGeometry/SectorFaceData.cs @@ -1,5 +1,5 @@ using System.Numerics; -using TombLib.LevelData.SectorEnums; +using TombLib.LevelData.SectorStructs; namespace TombLib.LevelData.SectorGeometry; @@ -11,7 +11,7 @@ public readonly struct SectorFaceData /// /// The exact hard-coded face type. /// - public readonly SectorFace Face; + public readonly FaceLayerInfo Face; public readonly Vector3 P0; public readonly Vector3 P1; @@ -31,7 +31,7 @@ public readonly struct SectorFaceData /// /// Constructor for a triangle face. /// - public SectorFaceData(SectorFace face, Vector3 p0, Vector3 p1, Vector3 p2, Vector2 uv0, Vector2 uv1, Vector2 uv2, bool isXEqualYDiagonal) + public SectorFaceData(FaceLayerInfo face, Vector3 p0, Vector3 p1, Vector3 p2, Vector2 uv0, Vector2 uv1, Vector2 uv2, bool isXEqualYDiagonal) { Face = face; @@ -54,7 +54,7 @@ public SectorFaceData(SectorFace face, Vector3 p0, Vector3 p1, Vector3 p2, Vecto /// /// Constructor for a quad face. /// - public SectorFaceData(SectorFace face, Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, Vector2 uv0, Vector2 uv1, Vector2 uv2, Vector2 uv3) + public SectorFaceData(FaceLayerInfo face, Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, Vector2 uv0, Vector2 uv1, Vector2 uv2, Vector2 uv3) { Face = face; @@ -74,7 +74,7 @@ public SectorFaceData(SectorFace face, Vector3 p0, Vector3 p1, Vector3 p2, Vecto IsTriangle = false; } - public static SectorFaceData? CreateVerticalFloorFaceData(SectorFace sectorFace, (int X, int Z) wallStartPoint, (int X, int Z) wallEndPoint, WallSplitData faceStartSplit, WallSplitData faceEndSplit) + public static SectorFaceData? CreateVerticalFloorFaceData(FaceLayerInfo sectorFace, (int X, int Z) wallStartPoint, (int X, int Z) wallEndPoint, WallSplitData faceStartSplit, WallSplitData faceEndSplit) { if (faceStartSplit.StartY > faceEndSplit.StartY && faceStartSplit.EndY > faceEndSplit.EndY) // Is quad { @@ -107,7 +107,7 @@ public SectorFaceData(SectorFace face, Vector3 p0, Vector3 p1, Vector3 p2, Vecto } } - public static SectorFaceData? CreateVerticalCeilingFaceData(SectorFace sectorFace, (int X, int Z) wallStartPoint, (int X, int Z) wallEndPoint, WallSplitData faceStartSplit, WallSplitData faceEndSplit) + public static SectorFaceData? CreateVerticalCeilingFaceData(FaceLayerInfo sectorFace, (int X, int Z) wallStartPoint, (int X, int Z) wallEndPoint, WallSplitData faceStartSplit, WallSplitData faceEndSplit) { if (faceStartSplit.StartY < faceEndSplit.StartY && faceStartSplit.EndY < faceEndSplit.EndY) // Is quad { @@ -140,7 +140,7 @@ public SectorFaceData(SectorFace face, Vector3 p0, Vector3 p1, Vector3 p2, Vecto } } - public static SectorFaceData? CreateVerticalMiddleFaceData(SectorFace sectorFace, (int X, int Z) wallStartPoint, (int X, int Z) wallEndPoint, WallSplitData faceStartSplit, WallSplitData faceEndSplit) + public static SectorFaceData? CreateVerticalMiddleFaceData(FaceLayerInfo sectorFace, (int X, int Z) wallStartPoint, (int X, int Z) wallEndPoint, WallSplitData faceStartSplit, WallSplitData faceEndSplit) { if (faceStartSplit.StartY != faceEndSplit.StartY && faceStartSplit.EndY != faceEndSplit.EndY) // Is quad { diff --git a/TombLib/TombLib/LevelData/SectorStructs/FaceLayerInfo.cs b/TombLib/TombLib/LevelData/SectorStructs/FaceLayerInfo.cs new file mode 100644 index 000000000..a44af2695 --- /dev/null +++ b/TombLib/TombLib/LevelData/SectorStructs/FaceLayerInfo.cs @@ -0,0 +1,17 @@ +using TombLib.LevelData.SectorEnums; + +namespace TombLib.LevelData.SectorStructs; + +public struct FaceLayerInfo +{ + public SectorFace Face { get; set; } + public FaceLayer Layer { get; set; } + + public FaceLayerInfo(SectorFace face, FaceLayer layer) + { + Face = face; + Layer = layer; + } + + public override int GetHashCode() => Face.GetHashCode() ^ Layer.GetHashCode(); +} diff --git a/TombLib/TombLib/LevelData/SectorStructs/SectorFaceIdentity.cs b/TombLib/TombLib/LevelData/SectorStructs/SectorFaceIdentity.cs index f61b13730..16f6b3fab 100644 --- a/TombLib/TombLib/LevelData/SectorStructs/SectorFaceIdentity.cs +++ b/TombLib/TombLib/LevelData/SectorStructs/SectorFaceIdentity.cs @@ -1,5 +1,4 @@ using System; -using TombLib.LevelData.SectorEnums; namespace TombLib.LevelData.SectorStructs; @@ -9,17 +8,17 @@ namespace TombLib.LevelData.SectorStructs; public readonly struct SectorFaceIdentity : IEquatable, IComparable, IComparable { public readonly VectorInt2 Position; - public readonly SectorFace Face; + public readonly FaceLayerInfo Face; - public SectorFaceIdentity(int x, int z, SectorFace face) + public SectorFaceIdentity(int x, int z, FaceLayerInfo face) { Position = new VectorInt2(x, z); Face = face; } public override readonly bool Equals(object other) => other is SectorFaceIdentity identity && identity.Equals(other); - public readonly bool Equals(SectorFaceIdentity other) => Position == other.Position && Face == other.Face; - public override int GetHashCode() => Position.GetHashCode() ^ (1200049507 * (int)Face); // Random prime + public readonly bool Equals(SectorFaceIdentity other) => Position == other.Position && Face.Face == other.Face.Face && Face.Layer == other.Face.Layer; + public override int GetHashCode() => Position.GetHashCode() ^ Face.GetHashCode(); readonly int IComparable.CompareTo(object other) => CompareTo((SectorFaceIdentity)other); public readonly int CompareTo(SectorFaceIdentity other) @@ -30,8 +29,11 @@ public readonly int CompareTo(SectorFaceIdentity other) if (Position.Y != other.Position.Y) return Position.Y > other.Position.Y ? 1 : -1; - if (Face != other.Face) - return Face > other.Face ? 1 : -1; + if (Face.Face != other.Face.Face) + return Face.Face > other.Face.Face ? 1 : -1; + + if (Face.Layer != other.Face.Layer) + return Face.Layer > other.Face.Layer ? 1 : -1; return 0; } diff --git a/TombLib/TombLib/Utils/RectTransformation.cs b/TombLib/TombLib/Utils/RectTransformation.cs index 60b6ced5c..f827a3131 100644 --- a/TombLib/TombLib/Utils/RectTransformation.cs +++ b/TombLib/TombLib/Utils/RectTransformation.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Numerics; using TombLib.LevelData.SectorEnums; +using TombLib.LevelData.SectorStructs; namespace TombLib.Utils { @@ -25,24 +26,33 @@ public int QuadrantRotation } } - public void TransformValueQuad(Dictionary faceTextures, SectorFace rotation0, SectorFace rotation1, SectorFace rotation2, SectorFace rotation3) + public void TransformValueQuad(Dictionary faceTextures, SectorFace rotation0, SectorFace rotation1, SectorFace rotation2, SectorFace rotation3) { - if (MirrorX) - faceTextures.TrySwap(rotation0, rotation2); - - for (int i = 0; i < QuadrantRotation; ++i) + for (FaceLayer layer = 0; layer < FaceLayer.Count; layer++) { - TextureArea? temp = null; + FaceLayerInfo + key0 = new(rotation0, layer), + key1 = new(rotation1, layer), + key2 = new(rotation2, layer), + key3 = new(rotation3, layer); + + if (MirrorX) + faceTextures.TrySwap(key0, key2); + + for (int i = 0; i < QuadrantRotation; ++i) + { + TextureArea? temp = null; - if (faceTextures.ContainsKey(rotation0)) - temp = faceTextures[rotation0]; + if (faceTextures.ContainsKey(key0)) + temp = faceTextures[key0]; - faceTextures.TrySwap(rotation0, rotation3); - faceTextures.TrySwap(rotation3, rotation2); - faceTextures.TrySwap(rotation2, rotation1); + faceTextures.TrySwap(key0, key3); + faceTextures.TrySwap(key3, key2); + faceTextures.TrySwap(key2, key1); - if (temp.HasValue) - faceTextures[rotation1] = temp.Value; + if (temp.HasValue) + faceTextures[key1] = temp.Value; + } } } From 0457c4050a54b1fabc3e7391a4d7b2abd3e3c210 Mon Sep 17 00:00:00 2001 From: Kewin Kupilas Date: Sat, 14 Dec 2024 13:36:18 +0000 Subject: [PATCH 02/19] Restored all previous functionality --- TombEditor/Controls/ToolBox.Designer.cs | 52 ++--- TombEditor/EditorActions.cs | 50 ++++- TombEditor/SectorsClipboardData.cs | 14 +- TombLib/TombLib/LevelData/RoomGeometry.cs | 190 +++++++++++++----- .../SectorGeometry/SectorFaceData.cs | 14 +- 5 files changed, 225 insertions(+), 95 deletions(-) diff --git a/TombEditor/Controls/ToolBox.Designer.cs b/TombEditor/Controls/ToolBox.Designer.cs index 9c8a67049..64c8b7205 100644 --- a/TombEditor/Controls/ToolBox.Designer.cs +++ b/TombEditor/Controls/ToolBox.Designer.cs @@ -70,7 +70,7 @@ private void InitializeComponent() toolStrip.Location = new System.Drawing.Point(0, 0); toolStrip.Name = "toolStrip"; toolStrip.Padding = new System.Windows.Forms.Padding(1, 0, 1, 0); - toolStrip.Size = new System.Drawing.Size(33, 523); + toolStrip.Size = new System.Drawing.Size(28, 523); toolStrip.TabIndex = 3; // // toolSelection @@ -82,7 +82,7 @@ private void InitializeComponent() toolSelection.ImageTransparentColor = System.Drawing.Color.Magenta; toolSelection.Margin = new System.Windows.Forms.Padding(1); toolSelection.Name = "toolSelection"; - toolSelection.Size = new System.Drawing.Size(28, 20); + toolSelection.Size = new System.Drawing.Size(23, 20); toolSelection.ToolTipText = "Selection"; toolSelection.Click += toolSelection_Click; // @@ -95,7 +95,7 @@ private void InitializeComponent() toolBrush.ImageTransparentColor = System.Drawing.Color.Magenta; toolBrush.Margin = new System.Windows.Forms.Padding(1); toolBrush.Name = "toolBrush"; - toolBrush.Size = new System.Drawing.Size(28, 20); + toolBrush.Size = new System.Drawing.Size(23, 20); toolBrush.ToolTipText = "Brush"; toolBrush.Click += toolBrush_Click; // @@ -108,7 +108,7 @@ private void InitializeComponent() toolShovel.ImageTransparentColor = System.Drawing.Color.Magenta; toolShovel.Margin = new System.Windows.Forms.Padding(1); toolShovel.Name = "toolShovel"; - toolShovel.Size = new System.Drawing.Size(28, 20); + toolShovel.Size = new System.Drawing.Size(23, 20); toolShovel.ToolTipText = "Shovel"; toolShovel.Click += toolShovel_Click; // @@ -121,7 +121,7 @@ private void InitializeComponent() toolPencil.ImageTransparentColor = System.Drawing.Color.Magenta; toolPencil.Margin = new System.Windows.Forms.Padding(1); toolPencil.Name = "toolPencil"; - toolPencil.Size = new System.Drawing.Size(28, 20); + toolPencil.Size = new System.Drawing.Size(23, 20); toolPencil.ToolTipText = "Pencil"; toolPencil.Click += toolPencil_Click; // @@ -134,7 +134,7 @@ private void InitializeComponent() toolFlatten.ImageTransparentColor = System.Drawing.Color.Magenta; toolFlatten.Margin = new System.Windows.Forms.Padding(1); toolFlatten.Name = "toolFlatten"; - toolFlatten.Size = new System.Drawing.Size(28, 20); + toolFlatten.Size = new System.Drawing.Size(23, 20); toolFlatten.ToolTipText = "Bulldozer"; toolFlatten.Click += toolFlatten_Click; // @@ -147,7 +147,7 @@ private void InitializeComponent() toolSmooth.ImageTransparentColor = System.Drawing.Color.Magenta; toolSmooth.Margin = new System.Windows.Forms.Padding(1); toolSmooth.Name = "toolSmooth"; - toolSmooth.Size = new System.Drawing.Size(28, 20); + toolSmooth.Size = new System.Drawing.Size(23, 20); toolSmooth.ToolTipText = "Smooth"; toolSmooth.Click += toolSmooth_Click; // @@ -160,7 +160,7 @@ private void InitializeComponent() toolFill.ImageTransparentColor = System.Drawing.Color.Magenta; toolFill.Margin = new System.Windows.Forms.Padding(1); toolFill.Name = "toolFill"; - toolFill.Size = new System.Drawing.Size(28, 20); + toolFill.Size = new System.Drawing.Size(23, 20); toolFill.ToolTipText = "Fill"; toolFill.Click += toolFill_Click; // @@ -173,7 +173,7 @@ private void InitializeComponent() toolGridPaint.ImageTransparentColor = System.Drawing.Color.Magenta; toolGridPaint.Margin = new System.Windows.Forms.Padding(1); toolGridPaint.Name = "toolGridPaint"; - toolGridPaint.Size = new System.Drawing.Size(28, 20); + toolGridPaint.Size = new System.Drawing.Size(23, 20); toolGridPaint.ToolTipText = "Grid Paint (2x2)"; toolGridPaint.Click += tooPaint2x2_Click; toolGridPaint.MouseDown += toolGridPaint_MouseDown; @@ -188,7 +188,7 @@ private void InitializeComponent() toolGroup.ImageTransparentColor = System.Drawing.Color.Magenta; toolGroup.Margin = new System.Windows.Forms.Padding(1); toolGroup.Name = "toolGroup"; - toolGroup.Size = new System.Drawing.Size(28, 20); + toolGroup.Size = new System.Drawing.Size(23, 20); toolGroup.ToolTipText = "Group Texturing"; toolGroup.Click += toolGroup_Click; // @@ -198,7 +198,7 @@ private void InitializeComponent() toolSeparator1.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); toolSeparator1.Margin = new System.Windows.Forms.Padding(0, 0, 2, 0); toolSeparator1.Name = "toolSeparator1"; - toolSeparator1.Size = new System.Drawing.Size(28, 6); + toolSeparator1.Size = new System.Drawing.Size(23, 6); // // toolDrag // @@ -209,7 +209,7 @@ private void InitializeComponent() toolDrag.ImageTransparentColor = System.Drawing.Color.Magenta; toolDrag.Margin = new System.Windows.Forms.Padding(1); toolDrag.Name = "toolDrag"; - toolDrag.Size = new System.Drawing.Size(28, 20); + toolDrag.Size = new System.Drawing.Size(23, 20); toolDrag.ToolTipText = "Drag"; toolDrag.Click += toolDrag_Click; // @@ -222,7 +222,7 @@ private void InitializeComponent() toolRamp.ImageTransparentColor = System.Drawing.Color.Magenta; toolRamp.Margin = new System.Windows.Forms.Padding(1); toolRamp.Name = "toolRamp"; - toolRamp.Size = new System.Drawing.Size(28, 20); + toolRamp.Size = new System.Drawing.Size(23, 20); toolRamp.ToolTipText = "Ramp"; toolRamp.Click += toolRamp_Click; // @@ -235,7 +235,7 @@ private void InitializeComponent() toolQuarterPipe.ImageTransparentColor = System.Drawing.Color.Magenta; toolQuarterPipe.Margin = new System.Windows.Forms.Padding(1); toolQuarterPipe.Name = "toolQuarterPipe"; - toolQuarterPipe.Size = new System.Drawing.Size(28, 20); + toolQuarterPipe.Size = new System.Drawing.Size(23, 20); toolQuarterPipe.ToolTipText = "Quarter Pipe"; toolQuarterPipe.Click += toolQuarterPipe_Click; // @@ -248,7 +248,7 @@ private void InitializeComponent() toolHalfPipe.ImageTransparentColor = System.Drawing.Color.Magenta; toolHalfPipe.Margin = new System.Windows.Forms.Padding(1); toolHalfPipe.Name = "toolHalfPipe"; - toolHalfPipe.Size = new System.Drawing.Size(28, 20); + toolHalfPipe.Size = new System.Drawing.Size(23, 20); toolHalfPipe.ToolTipText = "Half Pipe"; toolHalfPipe.Click += toolHalfPipe_Click; // @@ -261,7 +261,7 @@ private void InitializeComponent() toolBowl.ImageTransparentColor = System.Drawing.Color.Magenta; toolBowl.Margin = new System.Windows.Forms.Padding(1); toolBowl.Name = "toolBowl"; - toolBowl.Size = new System.Drawing.Size(28, 20); + toolBowl.Size = new System.Drawing.Size(23, 20); toolBowl.ToolTipText = "Bowl"; toolBowl.Click += toolBowl_Click; // @@ -274,7 +274,7 @@ private void InitializeComponent() toolPyramid.ImageTransparentColor = System.Drawing.Color.Magenta; toolPyramid.Margin = new System.Windows.Forms.Padding(1); toolPyramid.Name = "toolPyramid"; - toolPyramid.Size = new System.Drawing.Size(28, 20); + toolPyramid.Size = new System.Drawing.Size(23, 20); toolPyramid.ToolTipText = "Pyramid"; toolPyramid.Click += toolPyramid_Click; // @@ -287,7 +287,7 @@ private void InitializeComponent() toolTerrain.ImageTransparentColor = System.Drawing.Color.Magenta; toolTerrain.Margin = new System.Windows.Forms.Padding(1); toolTerrain.Name = "toolTerrain"; - toolTerrain.Size = new System.Drawing.Size(28, 20); + toolTerrain.Size = new System.Drawing.Size(23, 20); toolTerrain.ToolTipText = "Terrain"; toolTerrain.Click += toolTerrain_Click; // @@ -300,7 +300,7 @@ private void InitializeComponent() toolEraser.ImageTransparentColor = System.Drawing.Color.Magenta; toolEraser.Margin = new System.Windows.Forms.Padding(1); toolEraser.Name = "toolEraser"; - toolEraser.Size = new System.Drawing.Size(28, 20); + toolEraser.Size = new System.Drawing.Size(23, 20); toolEraser.ToolTipText = "Eraser"; toolEraser.Click += toolEraser_Click; // @@ -313,7 +313,7 @@ private void InitializeComponent() toolInvisibility.ImageTransparentColor = System.Drawing.Color.Magenta; toolInvisibility.Margin = new System.Windows.Forms.Padding(1); toolInvisibility.Name = "toolInvisibility"; - toolInvisibility.Size = new System.Drawing.Size(28, 20); + toolInvisibility.Size = new System.Drawing.Size(23, 20); toolInvisibility.ToolTipText = "Invisibility"; toolInvisibility.Click += toolInvisibility_Click; // @@ -323,7 +323,7 @@ private void InitializeComponent() toolSeparator2.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); toolSeparator2.Margin = new System.Windows.Forms.Padding(0, 0, 2, 0); toolSeparator2.Name = "toolSeparator2"; - toolSeparator2.Size = new System.Drawing.Size(28, 6); + toolSeparator2.Size = new System.Drawing.Size(23, 6); // // toolPortalDigger // @@ -334,7 +334,7 @@ private void InitializeComponent() toolPortalDigger.ImageTransparentColor = System.Drawing.Color.Magenta; toolPortalDigger.Margin = new System.Windows.Forms.Padding(1); toolPortalDigger.Name = "toolPortalDigger"; - toolPortalDigger.Size = new System.Drawing.Size(28, 20); + toolPortalDigger.Size = new System.Drawing.Size(23, 20); toolPortalDigger.ToolTipText = "Portal Digger"; toolPortalDigger.Click += toolPortalDigger_Click; // @@ -347,7 +347,7 @@ private void InitializeComponent() toolUVFixer.ImageTransparentColor = System.Drawing.Color.Magenta; toolUVFixer.Margin = new System.Windows.Forms.Padding(1); toolUVFixer.Name = "toolUVFixer"; - toolUVFixer.Size = new System.Drawing.Size(28, 20); + toolUVFixer.Size = new System.Drawing.Size(23, 20); toolUVFixer.ToolTipText = "Fix texture coordinates"; toolUVFixer.Click += toolUVFixer_Click; // @@ -357,7 +357,7 @@ private void InitializeComponent() toolSeparator3.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); toolSeparator3.Margin = new System.Windows.Forms.Padding(0, 0, 2, 0); toolSeparator3.Name = "toolSeparator3"; - toolSeparator3.Size = new System.Drawing.Size(28, 6); + toolSeparator3.Size = new System.Drawing.Size(23, 6); // // toolDecalsMode // @@ -368,7 +368,7 @@ private void InitializeComponent() toolDecalsMode.ImageTransparentColor = System.Drawing.Color.Magenta; toolDecalsMode.Margin = new System.Windows.Forms.Padding(1); toolDecalsMode.Name = "toolDecalsMode"; - toolDecalsMode.Size = new System.Drawing.Size(28, 20); + toolDecalsMode.Size = new System.Drawing.Size(23, 20); toolDecalsMode.ToolTipText = "Toggle decals mode"; toolDecalsMode.Click += toolDecalsMode_Click; // @@ -380,7 +380,7 @@ private void InitializeComponent() Controls.Add(toolStrip); Margin = new System.Windows.Forms.Padding(0); Name = "ToolBox"; - Size = new System.Drawing.Size(33, 523); + Size = new System.Drawing.Size(28, 523); toolStrip.ResumeLayout(false); toolStrip.PerformLayout(); ResumeLayout(false); diff --git a/TombEditor/EditorActions.cs b/TombEditor/EditorActions.cs index 8f4ad2ebb..a752f4ea4 100644 --- a/TombEditor/EditorActions.cs +++ b/TombEditor/EditorActions.cs @@ -1360,8 +1360,16 @@ public static void RotateTexture(Room room, VectorInt2 pos, FaceLayerInfo face) sector.SetFaceTexture(face, newTexture); // Update state - room.RoomGeometry.UpdateFaceTexture(pos.X, pos.Y, face, newTexture, newTexture.DoubleSided); - _editor.RoomTextureChange(room); + bool updated = room.RoomGeometry.UpdateFaceTexture(pos.X, pos.Y, face, newTexture, newTexture.DoubleSided); + + if (!updated && face.Layer is FaceLayer.Decal) + { + room.RoomGeometry.Build(room, _editor.Configuration.Rendering3D_HighQualityLightPreview); + updated = true; + } + + if (updated) + _editor.RoomTextureChange(room); } public static void MirrorTexture(Room room, VectorInt2 pos, FaceLayerInfo face) @@ -1375,8 +1383,16 @@ public static void MirrorTexture(Room room, VectorInt2 pos, FaceLayerInfo face) sector.SetFaceTexture(face, newTexture); // Update state - room.RoomGeometry.UpdateFaceTexture(pos.X, pos.Y, face, newTexture, newTexture.DoubleSided); - _editor.RoomTextureChange(room); + bool updated = room.RoomGeometry.UpdateFaceTexture(pos.X, pos.Y, face, newTexture, newTexture.DoubleSided); + + if (!updated && face.Layer is FaceLayer.Decal) + { + room.RoomGeometry.Build(room, _editor.Configuration.Rendering3D_HighQualityLightPreview); + updated = true; + } + + if (updated) + _editor.RoomTextureChange(room); } public static void PickTexture(Room room, VectorInt2 pos, FaceLayerInfo face) @@ -1582,7 +1598,17 @@ private static bool ApplyTextureToFace(Room room, VectorInt2 pos, FaceLayerInfo { TextureArea currentTexture = sector.GetFaceTexture(face); CheckTextureAttributes(room, pos, face.Face, currentTexture); - room.RoomGeometry.UpdateFaceTexture(pos.X, pos.Y, face, currentTexture, wasDoubleSided); + + bool updated = room.RoomGeometry.UpdateFaceTexture(pos.X, pos.Y, face, currentTexture, wasDoubleSided); + + if (!updated && face.Layer is FaceLayer.Decal) + { + room.RoomGeometry.Build(room, _editor.Configuration.Rendering3D_HighQualityLightPreview); + updated = true; + } + + if (updated) + _editor.RoomTextureChange(room); } return textureApplied; @@ -1644,7 +1670,7 @@ private static bool ApplyTextureToFace(Room room, VectorInt2 pos, FaceLayerInfo { // Get current face VertexRange vertexRange = new VertexRange(0, 0); - if (!room.RoomGeometry.VertexRangeLookup.TryGetValue(new SectorFaceIdentity(pos.X, pos.Y, face), out vertexRange)) + if (!room.RoomGeometry.VertexRangeLookup.TryGetValue(new SectorFaceIdentity(pos.X, pos.Y, new(face.Face, FaceLayer.Base)), out vertexRange)) return false; if (vertexRange.Count == 6) @@ -1763,7 +1789,17 @@ private static bool ApplyTextureToFace(Room room, VectorInt2 pos, FaceLayerInfo { TextureArea currentTexture = sector.GetFaceTexture(face); CheckTextureAttributes(room, pos, face.Face, currentTexture); - room.RoomGeometry.UpdateFaceTexture(pos.X, pos.Y, face, currentTexture, wasDoubleSided); + + bool updated = room.RoomGeometry.UpdateFaceTexture(pos.X, pos.Y, face, currentTexture, wasDoubleSided); + + if (!updated && face.Layer is FaceLayer.Decal) + { + room.RoomGeometry.Build(room, _editor.Configuration.Rendering3D_HighQualityLightPreview); + updated = true; + } + + if (updated) + _editor.RoomTextureChange(room); } return textureApplied; diff --git a/TombEditor/SectorsClipboardData.cs b/TombEditor/SectorsClipboardData.cs index 63038ea1e..76a448080 100644 --- a/TombEditor/SectorsClipboardData.cs +++ b/TombEditor/SectorsClipboardData.cs @@ -6,6 +6,7 @@ using TombLib; using TombLib.LevelData; using TombLib.LevelData.SectorEnums; +using TombLib.LevelData.SectorStructs; using TombLib.Utils; namespace TombEditor @@ -58,12 +59,13 @@ public SectorsClipboardData(Editor editor) writer.Write((byte)b.Ceiling.DiagonalSplit); writer.Write((short)b.Flags); - Dictionary textures = b.GetFaceTextures(); + Dictionary textures = b.GetFaceTexturesAll(); writer.Write(textures.Count); - foreach (KeyValuePair texturePair in textures) + foreach (KeyValuePair texturePair in textures) { - writer.Write((byte)texturePair.Key); + writer.Write((byte)texturePair.Key.Face); + writer.Write((byte)texturePair.Key.Layer); writer.Write(texturePair.Value.Texture.Image.FileName); writer.Write(texturePair.Value.TextureIsInvisible); @@ -136,13 +138,15 @@ public SectorsClipboardData(Editor editor) for (int i = 0; i < texturesCount; i++) { var face = (SectorFace)reader.ReadByte(); + var layer = (FaceLayer)reader.ReadByte(); + var layerInfo = new FaceLayerInfo(face, layer); string textureFileName = reader.ReadString(); bool isInvisible = reader.ReadBoolean(); if (string.IsNullOrEmpty(textureFileName)) { - b.SetFaceTexture(face, isInvisible ? TextureArea.Invisible : TextureArea.None); + b.SetFaceTexture(layerInfo, isInvisible ? TextureArea.Invisible : TextureArea.None); continue; } @@ -165,7 +169,7 @@ public SectorsClipboardData(Editor editor) DoubleSided = reader.ReadBoolean() }; - b.SetFaceTexture(face, texture); + b.SetFaceTexture(layerInfo, texture); } sectors[x, z] = b; diff --git a/TombLib/TombLib/LevelData/RoomGeometry.cs b/TombLib/TombLib/LevelData/RoomGeometry.cs index e08b3e826..c85c4bca7 100644 --- a/TombLib/TombLib/LevelData/RoomGeometry.cs +++ b/TombLib/TombLib/LevelData/RoomGeometry.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Numerics; using TombLib.LevelData.SectorEnums; +using TombLib.LevelData.SectorEnums.Extensions; using TombLib.LevelData.SectorGeometry; using TombLib.LevelData.SectorStructs; using TombLib.Utils; @@ -326,8 +327,11 @@ public void Build(Room room, bool highQualityLighting, bool useLegacyCode = fals Relight(room, highQualityLighting); } - public void UpdateFaceTexture(int x, int z, SectorFace face, TextureArea texture, bool wasDoubleSided) + public bool UpdateFaceTexture(int x, int z, FaceLayerInfo face, TextureArea texture, bool wasDoubleSided) { + if (face.Layer is FaceLayer.Decal && texture.TextureIsInvisible) + return false; + VertexRange range = VertexRangeLookup.GetValueOrDefault(new SectorFaceIdentity(x, z, face)); if (range.Count == 3) // Triangle @@ -338,10 +342,11 @@ public void UpdateFaceTexture(int x, int z, SectorFace face, TextureArea texture if (texture.DoubleSided) DoubleSidedTriangleCount++; - if (face is SectorFace.Ceiling or SectorFace.Ceiling_Triangle2) + if (face.Face is SectorFace.Ceiling or SectorFace.Ceiling_Triangle2) Swap.Do(ref texture.TexCoord0, ref texture.TexCoord2); TriangleTextureAreas[range.Start / 3] = texture; + return true; } else if (range.Count == 6) // Quad { @@ -356,7 +361,7 @@ public void UpdateFaceTexture(int x, int z, SectorFace face, TextureArea texture texture0.TexCoord1 = texture.TexCoord3; texture0.TexCoord2 = texture.TexCoord1; - if (face is SectorFace.Ceiling or SectorFace.Ceiling_Triangle2) + if (face.Face is SectorFace.Ceiling or SectorFace.Ceiling_Triangle2) Swap.Do(ref texture0.TexCoord0, ref texture0.TexCoord2); TriangleTextureAreas[range.Start / 3] = texture0; @@ -366,11 +371,14 @@ public void UpdateFaceTexture(int x, int z, SectorFace face, TextureArea texture texture1.TexCoord1 = texture.TexCoord1; texture1.TexCoord2 = texture.TexCoord3; - if (face is SectorFace.Ceiling or SectorFace.Ceiling_Triangle2) + if (face.Face is SectorFace.Ceiling or SectorFace.Ceiling_Triangle2) Swap.Do(ref texture1.TexCoord0, ref texture1.TexCoord2); TriangleTextureAreas[(range.Start + 3) / 3] = texture1; + return true; } + + return false; } private enum FaceDirection @@ -381,7 +389,8 @@ private enum FaceDirection private void BuildFloorOrCeilingFace(Room room, int x, int z, int h0, int h1, int h2, int h3, DiagonalSplit splitType, bool diagonalSplitXEqualsY, SectorFace face1, SectorFace face2, Room.RoomConnectionType portalMode) { - SectorType sectorType = room.Sectors[x, z].Type; + Sector sector = room.Sectors[x, z]; + SectorType sectorType = sector.Type; // Exit function if the sector is a complete wall or portal if (portalMode == Room.RoomConnectionType.FullPortal) @@ -428,21 +437,15 @@ private void BuildFloorOrCeilingFace(Room room, int x, int z, int h0, int h1, in // 4----3 // - Sector sector = room.Sectors[x, z]; - TextureArea defaultTexture = room.Level.Settings.DefaultTexture; - bool shouldApplyDefaultTexture1 = sector.GetFaceTexture(face1) == TextureArea.None && defaultTexture != TextureArea.None, - shouldApplyDefaultTexture2 = sector.GetFaceTexture(face2) == TextureArea.None && defaultTexture != TextureArea.None; + bool shouldApplyDefaultTexture1 = sector.GetFaceTexture(new(face1, FaceLayer.Base)) == TextureArea.None && defaultTexture != TextureArea.None, + shouldApplyDefaultTexture2 = sector.GetFaceTexture(new(face2, FaceLayer.Base)) == TextureArea.None && defaultTexture != TextureArea.None; if (shouldApplyDefaultTexture1) - sector.SetFaceTexture(face1, defaultTexture); + sector.SetFaceTexture(new(face1, FaceLayer.Base), defaultTexture); if (shouldApplyDefaultTexture2) - sector.SetFaceTexture(face2, defaultTexture); - - TextureArea - face1Texture = sector.GetFaceTexture(face1), - face2Texture = sector.GetFaceTexture(face2); + sector.SetFaceTexture(new(face2, FaceLayer.Base), defaultTexture); // Build sector if (splitType != DiagonalSplit.None) @@ -452,20 +455,20 @@ private void BuildFloorOrCeilingFace(Room room, int x, int z, int h0, int h1, in case DiagonalSplit.XpZn: if (portalMode != Room.RoomConnectionType.TriangularPortalXnZp) { - AddTriangle(x, z, face1, + TryRenderTriangleFace(sector, x, z, face1, new Vector3(x * Level.SectorSizeUnit, h0, z * Level.SectorSizeUnit), new Vector3(x * Level.SectorSizeUnit, h0, (z + 1) * Level.SectorSizeUnit), new Vector3((x + 1) * Level.SectorSizeUnit, h0, (z + 1) * Level.SectorSizeUnit), - face1Texture, new Vector2(0, 1), new Vector2(0, 0), new Vector2(1, 0), true); + new Vector2(0, 1), new Vector2(0, 0), new Vector2(1, 0), true); } if (portalMode != Room.RoomConnectionType.TriangularPortalXpZn && sectorType != SectorType.Wall) { - AddTriangle(x, z, face2, + TryRenderTriangleFace(sector, x, z, face2, new Vector3((x + 1) * Level.SectorSizeUnit, h1, (z + 1) * Level.SectorSizeUnit), new Vector3((x + 1) * Level.SectorSizeUnit, h2, z * Level.SectorSizeUnit), new Vector3(x * Level.SectorSizeUnit, h3, z * Level.SectorSizeUnit), - face2Texture, new Vector2(1, 0), new Vector2(1, 1), new Vector2(0, 1), true); + new Vector2(1, 0), new Vector2(1, 1), new Vector2(0, 1), true); } break; @@ -473,20 +476,20 @@ private void BuildFloorOrCeilingFace(Room room, int x, int z, int h0, int h1, in case DiagonalSplit.XnZn: if (portalMode != Room.RoomConnectionType.TriangularPortalXpZp) { - AddTriangle(x, z, face1, + TryRenderTriangleFace(sector, x, z, face1, new Vector3(x * Level.SectorSizeUnit, h1, (z + 1) * Level.SectorSizeUnit), new Vector3((x + 1) * Level.SectorSizeUnit, h1, (z + 1) * Level.SectorSizeUnit), new Vector3((x + 1) * Level.SectorSizeUnit, h1, z * Level.SectorSizeUnit), - face1Texture, new Vector2(0, 0), new Vector2(1, 0), new Vector2(1, 1), false); + new Vector2(0, 0), new Vector2(1, 0), new Vector2(1, 1), false); } if (portalMode != Room.RoomConnectionType.TriangularPortalXnZn && sectorType != SectorType.Wall) { - AddTriangle(x, z, face2, + TryRenderTriangleFace(sector, x, z, face2, new Vector3((x + 1) * Level.SectorSizeUnit, h2, z * Level.SectorSizeUnit), new Vector3(x * Level.SectorSizeUnit, h3, z * Level.SectorSizeUnit), new Vector3(x * Level.SectorSizeUnit, h0, (z + 1) * Level.SectorSizeUnit), - face2Texture, new Vector2(1, 1), new Vector2(0, 1), new Vector2(0, 0), false); + new Vector2(1, 1), new Vector2(0, 1), new Vector2(0, 0), false); } break; @@ -494,20 +497,20 @@ private void BuildFloorOrCeilingFace(Room room, int x, int z, int h0, int h1, in case DiagonalSplit.XnZp: if (portalMode != Room.RoomConnectionType.TriangularPortalXpZn) { - AddTriangle(x, z, face2, + TryRenderTriangleFace(sector, x, z, face2, new Vector3((x + 1) * Level.SectorSizeUnit, h2, (z + 1) * Level.SectorSizeUnit), new Vector3((x + 1) * Level.SectorSizeUnit, h2, z * Level.SectorSizeUnit), new Vector3(x * Level.SectorSizeUnit, h2, z * Level.SectorSizeUnit), - face2Texture, new Vector2(1, 0), new Vector2(1, 1), new Vector2(0, 1), true); + new Vector2(1, 0), new Vector2(1, 1), new Vector2(0, 1), true); } if (portalMode != Room.RoomConnectionType.TriangularPortalXnZp && sectorType != SectorType.Wall) { - AddTriangle(x, z, face1, + TryRenderTriangleFace(sector, x, z, face1, new Vector3(x * Level.SectorSizeUnit, h3, z * Level.SectorSizeUnit), new Vector3(x * Level.SectorSizeUnit, h0, (z + 1) * Level.SectorSizeUnit), new Vector3((x + 1) * Level.SectorSizeUnit, h1, (z + 1) * Level.SectorSizeUnit), - face1Texture, new Vector2(0, 1), new Vector2(0, 0), new Vector2(1, 0), true); + new Vector2(0, 1), new Vector2(0, 0), new Vector2(1, 0), true); } break; @@ -515,21 +518,21 @@ private void BuildFloorOrCeilingFace(Room room, int x, int z, int h0, int h1, in case DiagonalSplit.XpZp: if (portalMode != Room.RoomConnectionType.TriangularPortalXnZn) { - AddTriangle(x, z, face2, + TryRenderTriangleFace(sector, x, z, face2, new Vector3((x + 1) * Level.SectorSizeUnit, h3, z * Level.SectorSizeUnit), new Vector3(x * Level.SectorSizeUnit, h3, z * Level.SectorSizeUnit), new Vector3(x * Level.SectorSizeUnit, h3, (z + 1) * Level.SectorSizeUnit), - face2Texture, new Vector2(1, 1), new Vector2(0, 1), new Vector2(0, 0), false); + new Vector2(1, 1), new Vector2(0, 1), new Vector2(0, 0), false); } if (portalMode != Room.RoomConnectionType.TriangularPortalXpZp && sectorType != SectorType.Wall) { - AddTriangle(x, z, face1, + TryRenderTriangleFace(sector, x, z, face1, new Vector3(x * Level.SectorSizeUnit, h0, (z + 1) * Level.SectorSizeUnit), new Vector3((x + 1) * Level.SectorSizeUnit, h1, (z + 1) * Level.SectorSizeUnit), new Vector3((x + 1) * Level.SectorSizeUnit, h2, z * Level.SectorSizeUnit), - face1Texture, new Vector2(0, 0), new Vector2(1, 0), new Vector2(1, 1), false); + new Vector2(0, 0), new Vector2(1, 0), new Vector2(1, 1), false); } break; @@ -540,51 +543,51 @@ private void BuildFloorOrCeilingFace(Room room, int x, int z, int h0, int h1, in } else if (SectorSurface.IsQuad2(h0, h1, h2, h3) && portalMode == Room.RoomConnectionType.NoPortal) { - AddQuad(x, z, face1, + TryRenderQuadFace(sector, x, z, face1, new Vector3(x * Level.SectorSizeUnit, h0, (z + 1) * Level.SectorSizeUnit), new Vector3((x + 1) * Level.SectorSizeUnit, h1, (z + 1) * Level.SectorSizeUnit), new Vector3((x + 1) * Level.SectorSizeUnit, h2, z * Level.SectorSizeUnit), new Vector3(x * Level.SectorSizeUnit, h3, z * Level.SectorSizeUnit), - face1Texture, new Vector2(0, 0), new Vector2(1, 0), new Vector2(1, 1), new Vector2(0, 1)); + new Vector2(0, 0), new Vector2(1, 0), new Vector2(1, 1), new Vector2(0, 1)); } else if (diagonalSplitXEqualsY || portalMode == Room.RoomConnectionType.TriangularPortalXnZp || portalMode == Room.RoomConnectionType.TriangularPortalXpZn) { if (portalMode != Room.RoomConnectionType.TriangularPortalXnZp) { - AddTriangle(x, z, face2, + TryRenderTriangleFace(sector, x, z, face2, new Vector3(x * Level.SectorSizeUnit, h3, z * Level.SectorSizeUnit), new Vector3(x * Level.SectorSizeUnit, h0, (z + 1) * Level.SectorSizeUnit), new Vector3((x + 1) * Level.SectorSizeUnit, h1, (z + 1) * Level.SectorSizeUnit), - face2Texture, new Vector2(0, 1), new Vector2(0, 0), new Vector2(1, 0), true); + new Vector2(0, 1), new Vector2(0, 0), new Vector2(1, 0), true); } if (portalMode != Room.RoomConnectionType.TriangularPortalXpZn) { - AddTriangle(x, z, face1, + TryRenderTriangleFace(sector, x, z, face1, new Vector3((x + 1) * Level.SectorSizeUnit, h1, (z + 1) * Level.SectorSizeUnit), new Vector3((x + 1) * Level.SectorSizeUnit, h2, z * Level.SectorSizeUnit), new Vector3(x * Level.SectorSizeUnit, h3, z * Level.SectorSizeUnit), - face1Texture, new Vector2(1, 0), new Vector2(1, 1), new Vector2(0, 1), true); + new Vector2(1, 0), new Vector2(1, 1), new Vector2(0, 1), true); } } else { if (portalMode != Room.RoomConnectionType.TriangularPortalXpZp) { - AddTriangle(x, z, face1, + TryRenderTriangleFace(sector, x, z, face1, new Vector3(x * Level.SectorSizeUnit, h0, (z + 1) * Level.SectorSizeUnit), new Vector3((x + 1) * Level.SectorSizeUnit, h1, (z + 1) * Level.SectorSizeUnit), new Vector3((x + 1) * Level.SectorSizeUnit, h2, z * Level.SectorSizeUnit), - face1Texture, new Vector2(0, 0), new Vector2(1, 0), new Vector2(1, 1), false); + new Vector2(0, 0), new Vector2(1, 0), new Vector2(1, 1), false); } if (portalMode != Room.RoomConnectionType.TriangularPortalXnZn) { - AddTriangle(x, z, face2, + TryRenderTriangleFace(sector, x, z, face2, new Vector3((x + 1) * Level.SectorSizeUnit, h2, z * Level.SectorSizeUnit), new Vector3(x * Level.SectorSizeUnit, h3, z * Level.SectorSizeUnit), new Vector3(x * Level.SectorSizeUnit, h0, (z + 1) * Level.SectorSizeUnit), - face2Texture, new Vector2(1, 1), new Vector2(0, 1), new Vector2(0, 0), false); + new Vector2(1, 1), new Vector2(0, 1), new Vector2(0, 0), false); } } } @@ -640,22 +643,109 @@ private void AddVerticalFaces(Room room, int x, int z, FaceDirection faceDirecti private void AddFace(Room room, int x, int z, SectorFaceData face) { Sector sector = room.Sectors[x, z]; + var baseLayer = new FaceLayerInfo(face.Face, FaceLayer.Base); - bool shouldApplyDefaultTexture = sector.GetFaceTexture(face.Face) == TextureArea.None + bool shouldApplyDefaultTexture = sector.GetFaceTexture(baseLayer) == TextureArea.None && room.Level.Settings.DefaultTexture != TextureArea.None; if (shouldApplyDefaultTexture) - sector.SetFaceTexture(face.Face, room.Level.Settings.DefaultTexture); - - TextureArea texture = sector.GetFaceTexture(face.Face); + sector.SetFaceTexture(baseLayer, room.Level.Settings.DefaultTexture); if (face.IsQuad) - AddQuad(x, z, face.Face, face.P0, face.P1, face.P2, face.P3.Value, texture, face.UV0, face.UV1, face.UV2, face.UV3.Value); + TryRenderQuadFace(sector, x, z, face.Face, face.P0, face.P1, face.P2, face.P3.Value, face.UV0, face.UV1, face.UV2, face.UV3.Value); else - AddTriangle(x, z, face.Face, face.P0, face.P1, face.P2, texture, face.UV0, face.UV1, face.UV2, face.IsXEqualYDiagonal.Value); + TryRenderTriangleFace(sector, x, z, face.Face, face.P0, face.P1, face.P2, face.UV0, face.UV1, face.UV2, face.IsXEqualYDiagonal.Value); + } + + private void TryRenderQuadFace(Sector sector, int x, int z, SectorFace face, Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, Vector2 uv0, Vector2 uv1, Vector2 uv2, Vector2 uv3) + { + TextureArea + texture = sector.GetFaceTexture(new FaceLayerInfo(face, FaceLayer.Base)), + decal = sector.GetFaceTexture(new FaceLayerInfo(face, FaceLayer.Decal)); + + AddQuad(x, z, new FaceLayerInfo(face, FaceLayer.Base), p0, p1, p2, p3, texture, uv0, uv1, uv2, uv3); + + if (decal != TextureArea.None) + { + DiagonalSplit diagonalSplit = face.IsFloorWall() ? sector.Floor.DiagonalSplit : sector.Ceiling.DiagonalSplit; + + ShiftVector3(ref p0, face, diagonalSplit, Level.DecalOffset); + ShiftVector3(ref p1, face, diagonalSplit, Level.DecalOffset); + ShiftVector3(ref p2, face, diagonalSplit, Level.DecalOffset); + ShiftVector3(ref p3, face, diagonalSplit, Level.DecalOffset); + + AddQuad(x, z, new FaceLayerInfo(face, FaceLayer.Decal), p0, p1, p2, p3, decal, uv0, uv1, uv2, uv3); + } + } + + private void TryRenderTriangleFace(Sector sector, int x, int z, SectorFace face, Vector3 p0, Vector3 p1, Vector3 p2, Vector2 uv0, Vector2 uv1, Vector2 uv2, bool isXEqualYDiagonal) + { + TextureArea + texture = sector.GetFaceTexture(new FaceLayerInfo(face, FaceLayer.Base)), + decal = sector.GetFaceTexture(new FaceLayerInfo(face, FaceLayer.Decal)); + + AddTriangle(x, z, new FaceLayerInfo(face, FaceLayer.Base), p0, p1, p2, texture, uv0, uv1, uv2, isXEqualYDiagonal); + + if (decal != TextureArea.None) + { + DiagonalSplit diagonalSplit = face.IsFloorWall() ? sector.Floor.DiagonalSplit : sector.Ceiling.DiagonalSplit; + + ShiftVector3(ref p0, face, diagonalSplit, Level.DecalOffset); + ShiftVector3(ref p1, face, diagonalSplit, Level.DecalOffset); + ShiftVector3(ref p2, face, diagonalSplit, Level.DecalOffset); + + AddTriangle(x, z, new FaceLayerInfo(face, FaceLayer.Decal), p0, p1, p2, decal, uv0, uv1, uv2, isXEqualYDiagonal); + } + } + + private static void ShiftVector3(ref Vector3 vector, SectorFace face, DiagonalSplit diagonalSplit, float shift) + { + switch (face.GetDirection()) + { + case Direction.PositiveX: + vector.X += shift; + break; + case Direction.NegativeX: + vector.X -= shift; + break; + case Direction.PositiveZ: + vector.Z += shift; + break; + case Direction.NegativeZ: + vector.Z -= shift; + break; + case Direction.Diagonal: + switch (diagonalSplit) + { + case DiagonalSplit.XpZn: + vector.X -= shift; + vector.Z += shift; + break; + case DiagonalSplit.XnZn: + vector.X += shift; + vector.Z += shift; + break; + case DiagonalSplit.XnZp: + vector.X += shift; + vector.Z -= shift; + break; + case DiagonalSplit.XpZp: + vector.X -= shift; + vector.Z -= shift; + break; + } + + break; + default: // Either Floor or Ceiling + if (face.IsFloor()) + vector.Y += shift; + else + vector.Y -= shift; + break; + } } - private void AddQuad(int x, int z, SectorFace face, Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, + private void AddQuad(int x, int z, FaceLayerInfo face, Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, TextureArea texture, Vector2 editorUV0, Vector2 editorUV1, Vector2 editorUV2, Vector2 editorUV3) { if (texture.DoubleSided) @@ -691,7 +781,7 @@ private void AddQuad(int x, int z, SectorFace face, Vector3 p0, Vector3 p1, Vect TriangleSectorInfo.Add(new SectorFaceIdentity(x, z, face)); } - private void AddTriangle(int x, int z, SectorFace face, Vector3 p0, Vector3 p1, Vector3 p2, TextureArea texture, Vector2 editorUV0, Vector2 editorUV1, Vector2 editorUV2, bool isXEqualYDiagonal) + private void AddTriangle(int x, int z, FaceLayerInfo face, Vector3 p0, Vector3 p1, Vector3 p2, TextureArea texture, Vector2 editorUV0, Vector2 editorUV1, Vector2 editorUV2, bool isXEqualYDiagonal) { if (texture.DoubleSided) DoubleSidedTriangleCount += 1; @@ -1255,7 +1345,7 @@ public struct IntersectionInfo var normal = Vector3.Cross(p1 - p0, p2 - p0); if (Vector3.Dot(ray.Direction, normal) <= 0) if (!(distance > result.Distance)) - result = new IntersectionInfo() { Distance = distance, Face = entry.Key.Face, Pos = entry.Key.Position, VerticalCoord = position.Y }; + result = new IntersectionInfo() { Distance = distance, Face = entry.Key.Face.Face, Pos = entry.Key.Position, VerticalCoord = position.Y }; } } diff --git a/TombLib/TombLib/LevelData/SectorGeometry/SectorFaceData.cs b/TombLib/TombLib/LevelData/SectorGeometry/SectorFaceData.cs index 9febf0edd..caa68c009 100644 --- a/TombLib/TombLib/LevelData/SectorGeometry/SectorFaceData.cs +++ b/TombLib/TombLib/LevelData/SectorGeometry/SectorFaceData.cs @@ -1,5 +1,5 @@ using System.Numerics; -using TombLib.LevelData.SectorStructs; +using TombLib.LevelData.SectorEnums; namespace TombLib.LevelData.SectorGeometry; @@ -11,7 +11,7 @@ public readonly struct SectorFaceData /// /// The exact hard-coded face type. /// - public readonly FaceLayerInfo Face; + public readonly SectorFace Face; public readonly Vector3 P0; public readonly Vector3 P1; @@ -31,7 +31,7 @@ public readonly struct SectorFaceData /// /// Constructor for a triangle face. /// - public SectorFaceData(FaceLayerInfo face, Vector3 p0, Vector3 p1, Vector3 p2, Vector2 uv0, Vector2 uv1, Vector2 uv2, bool isXEqualYDiagonal) + public SectorFaceData(SectorFace face, Vector3 p0, Vector3 p1, Vector3 p2, Vector2 uv0, Vector2 uv1, Vector2 uv2, bool isXEqualYDiagonal) { Face = face; @@ -54,7 +54,7 @@ public SectorFaceData(FaceLayerInfo face, Vector3 p0, Vector3 p1, Vector3 p2, Ve /// /// Constructor for a quad face. /// - public SectorFaceData(FaceLayerInfo face, Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, Vector2 uv0, Vector2 uv1, Vector2 uv2, Vector2 uv3) + public SectorFaceData(SectorFace face, Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, Vector2 uv0, Vector2 uv1, Vector2 uv2, Vector2 uv3) { Face = face; @@ -74,7 +74,7 @@ public SectorFaceData(FaceLayerInfo face, Vector3 p0, Vector3 p1, Vector3 p2, Ve IsTriangle = false; } - public static SectorFaceData? CreateVerticalFloorFaceData(FaceLayerInfo sectorFace, (int X, int Z) wallStartPoint, (int X, int Z) wallEndPoint, WallSplitData faceStartSplit, WallSplitData faceEndSplit) + public static SectorFaceData? CreateVerticalFloorFaceData(SectorFace sectorFace, (int X, int Z) wallStartPoint, (int X, int Z) wallEndPoint, WallSplitData faceStartSplit, WallSplitData faceEndSplit) { if (faceStartSplit.StartY > faceEndSplit.StartY && faceStartSplit.EndY > faceEndSplit.EndY) // Is quad { @@ -107,7 +107,7 @@ public SectorFaceData(FaceLayerInfo face, Vector3 p0, Vector3 p1, Vector3 p2, Ve } } - public static SectorFaceData? CreateVerticalCeilingFaceData(FaceLayerInfo sectorFace, (int X, int Z) wallStartPoint, (int X, int Z) wallEndPoint, WallSplitData faceStartSplit, WallSplitData faceEndSplit) + public static SectorFaceData? CreateVerticalCeilingFaceData(SectorFace sectorFace, (int X, int Z) wallStartPoint, (int X, int Z) wallEndPoint, WallSplitData faceStartSplit, WallSplitData faceEndSplit) { if (faceStartSplit.StartY < faceEndSplit.StartY && faceStartSplit.EndY < faceEndSplit.EndY) // Is quad { @@ -140,7 +140,7 @@ public SectorFaceData(FaceLayerInfo face, Vector3 p0, Vector3 p1, Vector3 p2, Ve } } - public static SectorFaceData? CreateVerticalMiddleFaceData(FaceLayerInfo sectorFace, (int X, int Z) wallStartPoint, (int X, int Z) wallEndPoint, WallSplitData faceStartSplit, WallSplitData faceEndSplit) + public static SectorFaceData? CreateVerticalMiddleFaceData(SectorFace sectorFace, (int X, int Z) wallStartPoint, (int X, int Z) wallEndPoint, WallSplitData faceStartSplit, WallSplitData faceEndSplit) { if (faceStartSplit.StartY != faceEndSplit.StartY && faceStartSplit.EndY != faceEndSplit.EndY) // Is quad { From 70363dc520f9cb9f073cec8f511d3fd461589235 Mon Sep 17 00:00:00 2001 From: Kewin Kupilas Date: Sun, 26 Jan 2025 14:10:03 +0000 Subject: [PATCH 03/19] 0.0f offset decals + Added bad decal indicator --- TombEditor/Controls/Panel3D/Panel3DDraw.cs | 162 +++++++++++++++++---- TombLib/TombLib/LevelData/Level.cs | 2 - TombLib/TombLib/LevelData/RoomGeometry.cs | 64 -------- 3 files changed, 130 insertions(+), 98 deletions(-) diff --git a/TombEditor/Controls/Panel3D/Panel3DDraw.cs b/TombEditor/Controls/Panel3D/Panel3DDraw.cs index 61515f614..cded57efb 100644 --- a/TombEditor/Controls/Panel3D/Panel3DDraw.cs +++ b/TombEditor/Controls/Panel3D/Panel3DDraw.cs @@ -498,13 +498,87 @@ private static Vector3 ShiftVector3(Vector3 vector, SectorFace face, DiagonalSpl return vector; } + private bool IsOddRotation(Vector2[] first, Vector2[] second) + { + // Check if first is going clockwise + float firstArea = 0.0f; + + for (int i = 0; i < 4; i++) + { + Vector2 p1 = first[i]; + Vector2 p2 = first[(i + 1) % 4]; + firstArea += (p2.X - p1.X) * (p2.Y + p1.Y); + } + + bool isFirstClockwise = firstArea < 0.0f; + bool isFirst0, isFirst90, isFirst180, isFirst270; + + if (isFirstClockwise) + { + isFirst0 = first[0].X < first[1].X && first[0].Y < first[3].Y; + isFirst90 = first[0].X > first[3].X && first[0].Y < first[1].Y; + isFirst180 = first[0].X > first[1].X && first[0].Y > first[3].Y; + isFirst270 = first[0].X < first[3].X && first[0].Y > first[1].Y; + } + else + { + isFirst0 = first[0].X < first[3].X && first[0].Y < first[1].Y; + isFirst90 = first[0].X < first[1].X && first[0].Y > first[3].Y; + isFirst180 = first[0].X > first[3].X && first[0].Y > first[1].Y; + isFirst270 = first[0].X > first[1].X && first[0].Y < first[3].Y; + } + + // Check if second is going clockwise + float secondArea = 0.0f; + + for (int i = 0; i < 4; i++) + { + Vector2 p1 = second[i]; + Vector2 p2 = second[(i + 1) % 4]; + secondArea += (p2.X - p1.X) * (p2.Y + p1.Y); + } + + bool isSecondClockwise = secondArea < 0.0f; + bool isSecond0, isSecond90, isSecond180, isSecond270; + + if (isSecondClockwise) + { + isSecond0 = second[0].X < second[1].X && second[0].Y < second[3].Y; + isSecond90 = second[0].X > second[3].X && second[0].Y < second[1].Y; + isSecond180 = second[0].X > second[1].X && second[0].Y > second[3].Y; + isSecond270 = second[0].X < second[3].X && second[0].Y > second[1].Y; + } + else + { + isSecond0 = second[0].X < second[3].X && second[0].Y < second[1].Y; + isSecond90 = second[0].X < second[1].X && second[0].Y > second[3].Y; + isSecond180 = second[0].X > second[3].X && second[0].Y > second[1].Y; + isSecond270 = second[0].X > second[1].X && second[0].Y < second[3].Y; + } + + int firstRotation = isFirst0 ? 0 : isFirst90 ? 1 : isFirst180 ? 2 : 3; + int secondRotation = isSecond0 ? 0 : isSecond90 ? 1 : isSecond180 ? 2 : 3; + + if (isFirstClockwise == isSecondClockwise) + { + return (secondRotation - firstRotation) % 2 != 0; + } + else + { + return (secondRotation - firstRotation) % 2 == 0; + } + } + private void DrawDecalOutlines(Effect effect) { + const float DecalOutlineOffset = 8.0f; + if (_editor.Mode is not EditorMode.FaceEdit) return; Room currentRoom = _editor.SelectedRoom; var vertices = new List(); + var badVertices = new List(); for (int x = currentRoom.LocalArea.X0; x <= currentRoom.LocalArea.X1; x++) for (int z = currentRoom.LocalArea.Y0; z <= currentRoom.LocalArea.Y1; z++) @@ -519,64 +593,88 @@ private void DrawDecalOutlines(Effect effect) VertexRange range = currentRoom.RoomGeometry.VertexRangeLookup[key]; DiagonalSplit diagonalSplit = face.IsFloorWall() ? sector.Floor.DiagonalSplit : sector.Ceiling.DiagonalSplit; + TextureArea baseTexture = sector.GetFaceTexture(new(face, FaceLayer.Base)); + TextureArea decalTexture = sector.GetFaceTexture(new(face, FaceLayer.Decal)); + + if (range.Count == 6 && IsOddRotation(baseTexture.TexCoords, decalTexture.TexCoords)) + { + // Add the entire face into badVertices + for (int i = range.Start; i < range.Start + range.Count; i++) + badVertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[i] + currentRoom.WorldPos, face, diagonalSplit, DecalOutlineOffset))); + } + if (range.Count == 3) { - vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start] + currentRoom.WorldPos, face, diagonalSplit, Level.DecalOffset))); - vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 1] + currentRoom.WorldPos, face, diagonalSplit, Level.DecalOffset))); + vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start] + currentRoom.WorldPos, face, diagonalSplit, DecalOutlineOffset))); + vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 1] + currentRoom.WorldPos, face, diagonalSplit, DecalOutlineOffset))); - vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 1] + currentRoom.WorldPos, face, diagonalSplit, Level.DecalOffset))); - vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 2] + currentRoom.WorldPos, face, diagonalSplit, Level.DecalOffset))); + vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 1] + currentRoom.WorldPos, face, diagonalSplit, DecalOutlineOffset))); + vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 2] + currentRoom.WorldPos, face, diagonalSplit, DecalOutlineOffset))); - vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 2] + currentRoom.WorldPos, face, diagonalSplit, Level.DecalOffset))); - vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start] + currentRoom.WorldPos, face, diagonalSplit, Level.DecalOffset))); + vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 2] + currentRoom.WorldPos, face, diagonalSplit, DecalOutlineOffset))); + vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start] + currentRoom.WorldPos, face, diagonalSplit, DecalOutlineOffset))); } else if (range.Count == 6) { if (face.IsCeiling()) { - vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start] + currentRoom.WorldPos, face, diagonalSplit, Level.DecalOffset))); - vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 2] + currentRoom.WorldPos, face, diagonalSplit, Level.DecalOffset))); + vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start] + currentRoom.WorldPos, face, diagonalSplit, DecalOutlineOffset))); + vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 2] + currentRoom.WorldPos, face, diagonalSplit, DecalOutlineOffset))); - vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 2] + currentRoom.WorldPos, face, diagonalSplit, Level.DecalOffset))); - vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 3] + currentRoom.WorldPos, face, diagonalSplit, Level.DecalOffset))); + vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 2] + currentRoom.WorldPos, face, diagonalSplit, DecalOutlineOffset))); + vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 3] + currentRoom.WorldPos, face, diagonalSplit, DecalOutlineOffset))); - vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 3] + currentRoom.WorldPos, face, diagonalSplit, Level.DecalOffset))); - vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 5] + currentRoom.WorldPos, face, diagonalSplit, Level.DecalOffset))); + vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 3] + currentRoom.WorldPos, face, diagonalSplit, DecalOutlineOffset))); + vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 5] + currentRoom.WorldPos, face, diagonalSplit, DecalOutlineOffset))); - vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 5] + currentRoom.WorldPos, face, diagonalSplit, Level.DecalOffset))); - vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start] + currentRoom.WorldPos, face, diagonalSplit, Level.DecalOffset))); + vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 5] + currentRoom.WorldPos, face, diagonalSplit, DecalOutlineOffset))); + vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start] + currentRoom.WorldPos, face, diagonalSplit, DecalOutlineOffset))); } else { - vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start] + currentRoom.WorldPos, face, diagonalSplit, Level.DecalOffset))); - vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 1] + currentRoom.WorldPos, face, diagonalSplit, Level.DecalOffset))); + vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start] + currentRoom.WorldPos, face, diagonalSplit, DecalOutlineOffset))); + vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 1] + currentRoom.WorldPos, face, diagonalSplit, DecalOutlineOffset))); - vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 1] + currentRoom.WorldPos, face, diagonalSplit, Level.DecalOffset))); - vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 3] + currentRoom.WorldPos, face, diagonalSplit, Level.DecalOffset))); + vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 1] + currentRoom.WorldPos, face, diagonalSplit, DecalOutlineOffset))); + vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 3] + currentRoom.WorldPos, face, diagonalSplit, DecalOutlineOffset))); - vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 3] + currentRoom.WorldPos, face, diagonalSplit, Level.DecalOffset))); - vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 2] + currentRoom.WorldPos, face, diagonalSplit, Level.DecalOffset))); + vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 3] + currentRoom.WorldPos, face, diagonalSplit, DecalOutlineOffset))); + vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 2] + currentRoom.WorldPos, face, diagonalSplit, DecalOutlineOffset))); - vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 2] + currentRoom.WorldPos, face, diagonalSplit, Level.DecalOffset))); - vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start] + currentRoom.WorldPos, face, diagonalSplit, Level.DecalOffset))); + vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 2] + currentRoom.WorldPos, face, diagonalSplit, DecalOutlineOffset))); + vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start] + currentRoom.WorldPos, face, diagonalSplit, DecalOutlineOffset))); } } } } } - if (vertices.Count == 0) - return; + if (vertices.Count > 0) + { + using Buffer buffer = SharpDX.Toolkit.Graphics.Buffer.Vertex.New(_legacyDevice, vertices.ToArray(), SharpDX.Direct3D11.ResourceUsage.Dynamic); - using Buffer buffer = SharpDX.Toolkit.Graphics.Buffer.Vertex.New(_legacyDevice, vertices.ToArray(), SharpDX.Direct3D11.ResourceUsage.Dynamic); + _legacyDevice.SetRasterizerState(_legacyDevice.RasterizerStates.Default); + _legacyDevice.SetVertexBuffer(buffer); + _legacyDevice.SetVertexInputLayout(VertexInputLayout.FromBuffer(0, buffer)); + effect.Parameters["ModelViewProjection"].SetValue(_viewProjection.ToSharpDX()); + effect.Parameters["Color"].SetValue(Vector4.One); + effect.CurrentTechnique.Passes[0].Apply(); + _legacyDevice.Draw(PrimitiveType.LineList, buffer.ElementCount); + } - _legacyDevice.SetRasterizerState(_legacyDevice.RasterizerStates.Default); - _legacyDevice.SetVertexBuffer(buffer); - _legacyDevice.SetVertexInputLayout(VertexInputLayout.FromBuffer(0, buffer)); - effect.Parameters["ModelViewProjection"].SetValue(_viewProjection.ToSharpDX()); - effect.Parameters["Color"].SetValue(Vector4.One); - effect.CurrentTechnique.Passes[0].Apply(); - _legacyDevice.Draw(PrimitiveType.LineList, buffer.ElementCount); + if (badVertices.Count > 0) + { + using Buffer buffer = SharpDX.Toolkit.Graphics.Buffer.Vertex.New(_legacyDevice, badVertices.ToArray(), SharpDX.Direct3D11.ResourceUsage.Dynamic); + + _legacyDevice.SetRasterizerState(_legacyDevice.RasterizerStates.Default); + _legacyDevice.SetVertexBuffer(buffer); + _legacyDevice.SetVertexInputLayout(VertexInputLayout.FromBuffer(0, buffer)); + _legacyDevice.SetBlendState(_legacyDevice.BlendStates.NonPremultiplied); + effect.Parameters["ModelViewProjection"].SetValue(_viewProjection.ToSharpDX()); + effect.Parameters["Color"].SetValue(new[] { 1.0f, 0.1f, 0.1f, 0.5f }); + effect.CurrentTechnique.Passes[0].Apply(); + _legacyDevice.Draw(PrimitiveType.TriangleList, buffer.ElementCount); + } } private void DrawLights(Effect effect, Room[] roomsWhoseObjectsToDraw, List textToDraw, List sprites) diff --git a/TombLib/TombLib/LevelData/Level.cs b/TombLib/TombLib/LevelData/Level.cs index e1c0ac167..3a1aa49ce 100644 --- a/TombLib/TombLib/LevelData/Level.cs +++ b/TombLib/TombLib/LevelData/Level.cs @@ -20,8 +20,6 @@ public class Level public const short MaxNumberOfRooms = 1024; - public const float DecalOffset = 8.0f; - public Room[] Rooms { get; } = new Room[MaxNumberOfRooms]; // Rooms in level public LevelSettings Settings { get; private set; } = new LevelSettings(); public ScriptIdTable GlobalScriptingIdsTable { get; } = new ScriptIdTable(); diff --git a/TombLib/TombLib/LevelData/RoomGeometry.cs b/TombLib/TombLib/LevelData/RoomGeometry.cs index c85c4bca7..144f6d036 100644 --- a/TombLib/TombLib/LevelData/RoomGeometry.cs +++ b/TombLib/TombLib/LevelData/RoomGeometry.cs @@ -666,16 +666,7 @@ private void TryRenderQuadFace(Sector sector, int x, int z, SectorFace face, Vec AddQuad(x, z, new FaceLayerInfo(face, FaceLayer.Base), p0, p1, p2, p3, texture, uv0, uv1, uv2, uv3); if (decal != TextureArea.None) - { - DiagonalSplit diagonalSplit = face.IsFloorWall() ? sector.Floor.DiagonalSplit : sector.Ceiling.DiagonalSplit; - - ShiftVector3(ref p0, face, diagonalSplit, Level.DecalOffset); - ShiftVector3(ref p1, face, diagonalSplit, Level.DecalOffset); - ShiftVector3(ref p2, face, diagonalSplit, Level.DecalOffset); - ShiftVector3(ref p3, face, diagonalSplit, Level.DecalOffset); - AddQuad(x, z, new FaceLayerInfo(face, FaceLayer.Decal), p0, p1, p2, p3, decal, uv0, uv1, uv2, uv3); - } } private void TryRenderTriangleFace(Sector sector, int x, int z, SectorFace face, Vector3 p0, Vector3 p1, Vector3 p2, Vector2 uv0, Vector2 uv1, Vector2 uv2, bool isXEqualYDiagonal) @@ -687,62 +678,7 @@ private void TryRenderTriangleFace(Sector sector, int x, int z, SectorFace face, AddTriangle(x, z, new FaceLayerInfo(face, FaceLayer.Base), p0, p1, p2, texture, uv0, uv1, uv2, isXEqualYDiagonal); if (decal != TextureArea.None) - { - DiagonalSplit diagonalSplit = face.IsFloorWall() ? sector.Floor.DiagonalSplit : sector.Ceiling.DiagonalSplit; - - ShiftVector3(ref p0, face, diagonalSplit, Level.DecalOffset); - ShiftVector3(ref p1, face, diagonalSplit, Level.DecalOffset); - ShiftVector3(ref p2, face, diagonalSplit, Level.DecalOffset); - AddTriangle(x, z, new FaceLayerInfo(face, FaceLayer.Decal), p0, p1, p2, decal, uv0, uv1, uv2, isXEqualYDiagonal); - } - } - - private static void ShiftVector3(ref Vector3 vector, SectorFace face, DiagonalSplit diagonalSplit, float shift) - { - switch (face.GetDirection()) - { - case Direction.PositiveX: - vector.X += shift; - break; - case Direction.NegativeX: - vector.X -= shift; - break; - case Direction.PositiveZ: - vector.Z += shift; - break; - case Direction.NegativeZ: - vector.Z -= shift; - break; - case Direction.Diagonal: - switch (diagonalSplit) - { - case DiagonalSplit.XpZn: - vector.X -= shift; - vector.Z += shift; - break; - case DiagonalSplit.XnZn: - vector.X += shift; - vector.Z += shift; - break; - case DiagonalSplit.XnZp: - vector.X += shift; - vector.Z -= shift; - break; - case DiagonalSplit.XpZp: - vector.X -= shift; - vector.Z -= shift; - break; - } - - break; - default: // Either Floor or Ceiling - if (face.IsFloor()) - vector.Y += shift; - else - vector.Y -= shift; - break; - } } private void AddQuad(int x, int z, FaceLayerInfo face, Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, From d06077f0f42e22407be75036041f194952eb4e34 Mon Sep 17 00:00:00 2001 From: Kewin Kupilas Date: Sat, 13 Sep 2025 18:13:08 +0100 Subject: [PATCH 04/19] Fix overlays for legacy engines --- TombLib/TombLib/LevelData/Compilers/Rooms.cs | 83 +++++++++++++++++-- .../Compilers/Util/TexInfoManager.cs | 80 +++++++++++++----- 2 files changed, 136 insertions(+), 27 deletions(-) diff --git a/TombLib/TombLib/LevelData/Compilers/Rooms.cs b/TombLib/TombLib/LevelData/Compilers/Rooms.cs index e12e6e7fe..eccdfd77a 100644 --- a/TombLib/TombLib/LevelData/Compilers/Rooms.cs +++ b/TombLib/TombLib/LevelData/Compilers/Rooms.cs @@ -342,6 +342,9 @@ private tr_room BuildRoom(Room room) var roomTriangles = new List(); var roomQuads = new List(); + // Track base polygon rotations for decal coordination + var baseRotations = new Dictionary<(int, int, SectorFace), int>(); + // Add room's own geometry if (!room.Properties.Hidden) @@ -420,16 +423,51 @@ private tr_room BuildRoom(Room room) roomVertices[vertex3Index] = trVertex; } - var result = _textureInfoManager.AddTexture(texture, true, false); + Util.TexInfoManager.Result result; + + // Coordinate texture rotations between base and decal layers + var faceKey = (x, z, face.Face); + + if (face.Layer == FaceLayer.Base) + { + // Base layer: use optimal rotation and remember it + result = _textureInfoManager.AddTexture(texture, true, false); + baseRotations[faceKey] = result.Rotation; + } + else if (face.Layer == FaceLayer.Decal && baseRotations.ContainsKey(faceKey)) + { + // Decal layer: force to use same rotation as base + var baseRotation = baseRotations[faceKey]; + result = _textureInfoManager.AddTexture(texture, true, false, false, baseRotation); + } + else + { + // Fallback: use optimal rotation + result = _textureInfoManager.AddTexture(texture, true, false); + } + roomQuads.Add(result.CreateFace4(new ushort[] { vertex0Index, vertex1Index, vertex2Index, vertex3Index }, doubleSided, 0)); if (copyFace) { texture.Mirror(); - result = _textureInfoManager.AddTexture(texture, true, false); - roomQuads.Add(result.CreateFace4(new ushort[] { vertex3Index, vertex2Index, vertex1Index, vertex0Index }, + + Util.TexInfoManager.Result mirrorResult; + + if (face.Layer == FaceLayer.Decal && baseRotations.ContainsKey(faceKey)) + { + var baseRotation = baseRotations[faceKey]; + mirrorResult = _textureInfoManager.AddTexture(texture, true, false, false, baseRotation); + } + else + { + mirrorResult = _textureInfoManager.AddTexture(texture, true, false); + } + + roomQuads.Add(mirrorResult.CreateFace4(new ushort[] { vertex3Index, vertex2Index, vertex1Index, vertex0Index }, doubleSided, 0)); } + i += 3; } else @@ -458,7 +496,28 @@ private tr_room BuildRoom(Room room) roomVertices[vertex2Index] = trVertex; } - var result = _textureInfoManager.AddTexture(texture, true, true); + Util.TexInfoManager.Result result; + + // Coordinate texture rotations between base and decal layers + var faceKey = (x, z, face.Face); + + if (face.Layer == FaceLayer.Base) + { + // Base layer: use optimal rotation and remember it + result = _textureInfoManager.AddTexture(texture, true, true); + baseRotations[faceKey] = result.Rotation; + } + else if (face.Layer == FaceLayer.Decal && baseRotations.ContainsKey(faceKey)) + { + // Decal layer: force to use same rotation as base + var baseRotation = baseRotations[faceKey]; + result = _textureInfoManager.AddTexture(texture, true, true, false, baseRotation); + } + else + { + // Fallback: use optimal rotation + result = _textureInfoManager.AddTexture(texture, true, true); + } if (result.ConvertToQuad) roomQuads.Add(result.CreateFace4(new ushort[] { vertex0Index, vertex1Index, vertex2Index, vertex2Index }, @@ -470,8 +529,20 @@ private tr_room BuildRoom(Room room) if (copyFace) { texture.Mirror(true); - result = _textureInfoManager.AddTexture(texture, true, true); - roomTriangles.Add(result.CreateFace3(new ushort[] { vertex2Index, vertex1Index, vertex0Index }, + + Util.TexInfoManager.Result mirrorResult; + + if (face.Layer == FaceLayer.Decal && baseRotations.ContainsKey(faceKey)) + { + var baseRotation = baseRotations[faceKey]; + mirrorResult = _textureInfoManager.AddTexture(texture, true, true, false, baseRotation); + } + else + { + mirrorResult = _textureInfoManager.AddTexture(texture, true, true); + } + + roomTriangles.Add(mirrorResult.CreateFace3(new ushort[] { vertex2Index, vertex1Index, vertex0Index }, doubleSided, 0)); } } diff --git a/TombLib/TombLib/LevelData/Compilers/Util/TexInfoManager.cs b/TombLib/TombLib/LevelData/Compilers/Util/TexInfoManager.cs index 53428e2d1..d43fbeebb 100644 --- a/TombLib/TombLib/LevelData/Compilers/Util/TexInfoManager.cs +++ b/TombLib/TombLib/LevelData/Compilers/Util/TexInfoManager.cs @@ -679,7 +679,7 @@ public tr_face4 CreateFace4(ushort[] indices, bool doubleSided, ushort lightingE private Result? GetTexInfo(TextureArea areaToLook, List parentList, bool isForRoom, bool isForTriangle, bool topmostAndUnpadded, - bool checkParameters = true, bool scanOtherSets = false, float lookupMargin = 0.0f) + bool checkParameters = true, bool scanOtherSets = false, float lookupMargin = 0.0f, int forceRotation = -1) { var lookupCoordinates = new Vector2[isForTriangle ? 3 : 4]; for (int i = 0; i < lookupCoordinates.Length; i++) @@ -713,6 +713,10 @@ public tr_face4 CreateFace4(ushort[] indices, bool doubleSided, ushort lightingE var result = TestUVSimilarity(child.AbsCoord, lookupCoordinates, lookupMargin); if (result != _noTexInfo) { + // If rotation is forced for decal coordination, reject this match if rotation doesn't match + if (forceRotation >= 0 && result != forceRotation) + continue; + // Refresh topmost flag, as same texture may be applied to faces with different topmost priority parent.TopmostAndUnpadded |= topmostAndUnpadded; @@ -769,23 +773,8 @@ private void AddParent(TextureArea texture, List parentList, public Result AddTexture(TextureArea texture, bool isForRoom, bool isForTriangle, bool topmostAndUnpadded = false) { - if (_dataHasBeenLaidOut) - throw new InvalidOperationException("Data has been already laid out for this TexInfoManager. Reinitialize it if you want to restart texture collection."); - - if ((isForTriangle && texture.TriangleCoordsOutOfBounds) || (!isForTriangle && texture.QuadCoordsOutOfBounds)) - { - _progressReporter.ReportWarn("Texture (" + texture.TexCoord0 + ", " + texture.TexCoord1 + ", " + - texture.TexCoord2 + ", " + texture.TexCoord3 + ") is out of bounds and will be ignored."); + if (!ValidateTexture(texture, isForTriangle)) return new Result(); - } - - if (texture.ParentArea.Width > MaxTileSize || texture.ParentArea.Height > MaxTileSize) - { - _progressReporter.ReportWarn("Texture (" + texture.TexCoord0 + ", " + texture.TexCoord1 + ", " + - texture.TexCoord2 + ", " + texture.TexCoord3 + ") has incorrect parent area which has been reset. " + - "Possibly UV-mapped mesh with texture bigger than " + MaxTileSize + " in size."); - texture.ParentArea = Rectangle2.Zero; - } // Only try to remap animated textures if fast mode is disabled bool remapAnimatedTextures = _level.Settings.RemapAnimatedTextures && !_level.Settings.FastMode; @@ -834,24 +823,73 @@ public Result AddTexture(TextureArea texture, bool isForRoom, bool isForTriangle return AddTexture(texture, _parentTextures, isForRoom, isForTriangle, topmostAndUnpadded); } + public Result AddTexture(TextureArea texture, bool isForRoom, bool isForTriangle, bool topmostAndUnpadded, int forceRotation) + { + if (!ValidateTexture(texture, isForTriangle)) + return new Result(); + + // Force specific rotation for decal coordination + return AddTexture(texture, _parentTextures, isForRoom, isForTriangle, topmostAndUnpadded, -1, true, forceRotation); + } + + public bool ValidateTexture(TextureArea texture, bool isForTriangle) + { + if (_dataHasBeenLaidOut) + throw new InvalidOperationException("Data has been already laid out for this TexInfoManager. Reinitialize it if you want to restart texture collection."); + + if ((isForTriangle && texture.TriangleCoordsOutOfBounds) || (!isForTriangle && texture.QuadCoordsOutOfBounds)) + { + _progressReporter.ReportWarn("Texture (" + texture.TexCoord0 + ", " + texture.TexCoord1 + ", " + + texture.TexCoord2 + ", " + texture.TexCoord3 + ") is out of bounds and will be ignored."); + + return false; + } + + if (texture.ParentArea.Width > MaxTileSize || texture.ParentArea.Height > MaxTileSize) + { + _progressReporter.ReportWarn("Texture (" + texture.TexCoord0 + ", " + texture.TexCoord1 + ", " + + texture.TexCoord2 + ", " + texture.TexCoord3 + ") has incorrect parent area which has been reset. " + + "Possibly UV-mapped mesh with texture bigger than " + MaxTileSize + " in size."); + + texture.ParentArea = Rectangle2.Zero; + } + + return true; + } + // Internal AddTexture variation which is capable of adding texture to various ParentTextureArea lists // with customizable parameters. // If animFrameIndex == -1, it means that ordinary texture is added, otherwise it indicates that specific anim // texture frame is being processed. If so, frame index is saved into TexInfoIndex field of resulting child. // Later on, on real anim texture creation, this index is used to sort frames in proper order. - private Result AddTexture(TextureArea texture, List parentList, bool isForRoom, bool isForTriangle, bool topmostAndUnpadded = false, int animFrameIndex = -1, bool makeCanonical = true) + private Result AddTexture(TextureArea texture, List parentList, bool isForRoom, bool isForTriangle, bool topmostAndUnpadded = false, int animFrameIndex = -1, bool makeCanonical = true, int forceRotation = -1) { // In case AddTexture is used with animated seq packing, we don't check frames for full similarity, because // frames can be duplicated with Repeat function or simply because of complex animator functions applied. - var result = animFrameIndex >= 0 ? null : GetTexInfo(texture, parentList, isForRoom, isForTriangle, topmostAndUnpadded); + var result = animFrameIndex >= 0 ? null : GetTexInfo(texture, parentList, isForRoom, isForTriangle, topmostAndUnpadded, forceRotation: forceRotation); if (!result.HasValue) { // Try to create new canonical (top-left-based) texture as child or parent. // makeCanonical parameter is necessary for animated textures, because animators may produce frames // with non-canonically rotated coordinates (e.g. spin animator). - var canonicalTexture = makeCanonical ? texture.GetCanonicalTexture(isForTriangle) : texture; + // If forceRotation is specified, apply that specific rotation instead of canonical optimization. + + TextureArea canonicalTexture; + + if (forceRotation >= 0) + { + // Force specific rotation for decal coordination + canonicalTexture = texture; + + if (forceRotation > 0) + canonicalTexture.Rotate(forceRotation, isForTriangle); + } + else + { + canonicalTexture = makeCanonical ? texture.GetCanonicalTexture(isForTriangle) : texture; + } // If no any potential parents or children, create as new parent if (!TryToAddToExisting(canonicalTexture, parentList, isForRoom, isForTriangle, topmostAndUnpadded, animFrameIndex)) @@ -861,7 +899,7 @@ private Result AddTexture(TextureArea texture, List parentLis if (animFrameIndex >= 0) result = new Result { TexInfoIndex = _dummyTexInfo, Rotation = 0 }; else - result = GetTexInfo(texture, parentList, isForRoom, isForTriangle, topmostAndUnpadded); + result = GetTexInfo(texture, parentList, isForRoom, isForTriangle, topmostAndUnpadded, forceRotation: forceRotation); } if (!result.HasValue) From 9f91a30245ffef3cf13c01ac08b5bc1581235bab Mon Sep 17 00:00:00 2001 From: Kewin Kupilas Date: Sat, 13 Sep 2025 23:17:11 +0100 Subject: [PATCH 05/19] Cleanup --- .../LevelData/SectorStructs/FaceLayerInfo.cs | 17 ++++++++++++----- .../SectorStructs/SectorFaceIdentity.cs | 17 +++++++++-------- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/TombLib/TombLib/LevelData/SectorStructs/FaceLayerInfo.cs b/TombLib/TombLib/LevelData/SectorStructs/FaceLayerInfo.cs index a44af2695..29d907f35 100644 --- a/TombLib/TombLib/LevelData/SectorStructs/FaceLayerInfo.cs +++ b/TombLib/TombLib/LevelData/SectorStructs/FaceLayerInfo.cs @@ -1,11 +1,12 @@ -using TombLib.LevelData.SectorEnums; +using System; +using TombLib.LevelData.SectorEnums; namespace TombLib.LevelData.SectorStructs; -public struct FaceLayerInfo +public readonly struct FaceLayerInfo : IEquatable { - public SectorFace Face { get; set; } - public FaceLayer Layer { get; set; } + public readonly SectorFace Face { get; } + public readonly FaceLayer Layer { get; } public FaceLayerInfo(SectorFace face, FaceLayer layer) { @@ -13,5 +14,11 @@ public FaceLayerInfo(SectorFace face, FaceLayer layer) Layer = layer; } - public override int GetHashCode() => Face.GetHashCode() ^ Layer.GetHashCode(); + public override int GetHashCode() => HashCode.Combine(Face, Layer); + + public bool Equals(FaceLayerInfo other) => Face == other.Face && Layer == other.Layer; + public override bool Equals(object obj) => obj is FaceLayerInfo other && Equals(other); + + public static bool operator ==(FaceLayerInfo first, FaceLayerInfo second) => first.Equals(second); + public static bool operator !=(FaceLayerInfo first, FaceLayerInfo second) => !first.Equals(second); } diff --git a/TombLib/TombLib/LevelData/SectorStructs/SectorFaceIdentity.cs b/TombLib/TombLib/LevelData/SectorStructs/SectorFaceIdentity.cs index 16f6b3fab..80aa5bd32 100644 --- a/TombLib/TombLib/LevelData/SectorStructs/SectorFaceIdentity.cs +++ b/TombLib/TombLib/LevelData/SectorStructs/SectorFaceIdentity.cs @@ -7,8 +7,8 @@ namespace TombLib.LevelData.SectorStructs; /// public readonly struct SectorFaceIdentity : IEquatable, IComparable, IComparable { - public readonly VectorInt2 Position; - public readonly FaceLayerInfo Face; + public readonly VectorInt2 Position { get; } + public readonly FaceLayerInfo Face { get; } public SectorFaceIdentity(int x, int z, FaceLayerInfo face) { @@ -16,12 +16,13 @@ public SectorFaceIdentity(int x, int z, FaceLayerInfo face) Face = face; } - public override readonly bool Equals(object other) => other is SectorFaceIdentity identity && identity.Equals(other); - public readonly bool Equals(SectorFaceIdentity other) => Position == other.Position && Face.Face == other.Face.Face && Face.Layer == other.Face.Layer; - public override int GetHashCode() => Position.GetHashCode() ^ Face.GetHashCode(); + public override int GetHashCode() => HashCode.Combine(Position, Face.Face, Face.Layer); - readonly int IComparable.CompareTo(object other) => CompareTo((SectorFaceIdentity)other); - public readonly int CompareTo(SectorFaceIdentity other) + public bool Equals(SectorFaceIdentity other) => Position == other.Position && Face == other.Face; + public override bool Equals(object other) => other is SectorFaceIdentity identity && identity.Equals(other); + + int IComparable.CompareTo(object other) => CompareTo((SectorFaceIdentity)other); + public int CompareTo(SectorFaceIdentity other) { if (Position.X != other.Position.X) return Position.X > other.Position.X ? 1 : -1; @@ -39,7 +40,7 @@ public readonly int CompareTo(SectorFaceIdentity other) } public static bool operator ==(SectorFaceIdentity left, SectorFaceIdentity right) => left.Equals(right); - public static bool operator !=(SectorFaceIdentity left, SectorFaceIdentity right) => !(left == right); + public static bool operator !=(SectorFaceIdentity left, SectorFaceIdentity right) => !left.Equals(right); public static bool operator <(SectorFaceIdentity left, SectorFaceIdentity right) => left.CompareTo(right) < 0; public static bool operator <=(SectorFaceIdentity left, SectorFaceIdentity right) => left.CompareTo(right) <= 0; public static bool operator >(SectorFaceIdentity left, SectorFaceIdentity right) => left.CompareTo(right) > 0; From 2d88715924839a85fa69a1aa5457f1176a1b8e8d Mon Sep 17 00:00:00 2001 From: Kewin Kupilas Date: Sat, 13 Sep 2025 23:38:10 +0100 Subject: [PATCH 06/19] Remove bad decals indicators --- TombEditor/Controls/Panel3D/Panel3DDraw.cs | 93 ---------------------- 1 file changed, 93 deletions(-) diff --git a/TombEditor/Controls/Panel3D/Panel3DDraw.cs b/TombEditor/Controls/Panel3D/Panel3DDraw.cs index 01b70be71..690a0316e 100644 --- a/TombEditor/Controls/Panel3D/Panel3DDraw.cs +++ b/TombEditor/Controls/Panel3D/Panel3DDraw.cs @@ -498,77 +498,6 @@ private static Vector3 ShiftVector3(Vector3 vector, SectorFace face, DiagonalSpl return vector; } - private bool IsOddRotation(Vector2[] first, Vector2[] second) - { - // Check if first is going clockwise - float firstArea = 0.0f; - - for (int i = 0; i < 4; i++) - { - Vector2 p1 = first[i]; - Vector2 p2 = first[(i + 1) % 4]; - firstArea += (p2.X - p1.X) * (p2.Y + p1.Y); - } - - bool isFirstClockwise = firstArea < 0.0f; - bool isFirst0, isFirst90, isFirst180, isFirst270; - - if (isFirstClockwise) - { - isFirst0 = first[0].X < first[1].X && first[0].Y < first[3].Y; - isFirst90 = first[0].X > first[3].X && first[0].Y < first[1].Y; - isFirst180 = first[0].X > first[1].X && first[0].Y > first[3].Y; - isFirst270 = first[0].X < first[3].X && first[0].Y > first[1].Y; - } - else - { - isFirst0 = first[0].X < first[3].X && first[0].Y < first[1].Y; - isFirst90 = first[0].X < first[1].X && first[0].Y > first[3].Y; - isFirst180 = first[0].X > first[3].X && first[0].Y > first[1].Y; - isFirst270 = first[0].X > first[1].X && first[0].Y < first[3].Y; - } - - // Check if second is going clockwise - float secondArea = 0.0f; - - for (int i = 0; i < 4; i++) - { - Vector2 p1 = second[i]; - Vector2 p2 = second[(i + 1) % 4]; - secondArea += (p2.X - p1.X) * (p2.Y + p1.Y); - } - - bool isSecondClockwise = secondArea < 0.0f; - bool isSecond0, isSecond90, isSecond180, isSecond270; - - if (isSecondClockwise) - { - isSecond0 = second[0].X < second[1].X && second[0].Y < second[3].Y; - isSecond90 = second[0].X > second[3].X && second[0].Y < second[1].Y; - isSecond180 = second[0].X > second[1].X && second[0].Y > second[3].Y; - isSecond270 = second[0].X < second[3].X && second[0].Y > second[1].Y; - } - else - { - isSecond0 = second[0].X < second[3].X && second[0].Y < second[1].Y; - isSecond90 = second[0].X < second[1].X && second[0].Y > second[3].Y; - isSecond180 = second[0].X > second[3].X && second[0].Y > second[1].Y; - isSecond270 = second[0].X > second[1].X && second[0].Y < second[3].Y; - } - - int firstRotation = isFirst0 ? 0 : isFirst90 ? 1 : isFirst180 ? 2 : 3; - int secondRotation = isSecond0 ? 0 : isSecond90 ? 1 : isSecond180 ? 2 : 3; - - if (isFirstClockwise == isSecondClockwise) - { - return (secondRotation - firstRotation) % 2 != 0; - } - else - { - return (secondRotation - firstRotation) % 2 == 0; - } - } - private void DrawDecalOutlines(Effect effect) { const float DecalOutlineOffset = 8.0f; @@ -578,7 +507,6 @@ private void DrawDecalOutlines(Effect effect) Room currentRoom = _editor.SelectedRoom; var vertices = new List(); - var badVertices = new List(); for (int x = currentRoom.LocalArea.X0; x <= currentRoom.LocalArea.X1; x++) for (int z = currentRoom.LocalArea.Y0; z <= currentRoom.LocalArea.Y1; z++) @@ -596,13 +524,6 @@ private void DrawDecalOutlines(Effect effect) TextureArea baseTexture = sector.GetFaceTexture(new(face, FaceLayer.Base)); TextureArea decalTexture = sector.GetFaceTexture(new(face, FaceLayer.Decal)); - if (range.Count == 6 && IsOddRotation(baseTexture.TexCoords, decalTexture.TexCoords)) - { - // Add the entire face into badVertices - for (int i = range.Start; i < range.Start + range.Count; i++) - badVertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[i] + currentRoom.WorldPos, face, diagonalSplit, DecalOutlineOffset))); - } - if (range.Count == 3) { vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start] + currentRoom.WorldPos, face, diagonalSplit, DecalOutlineOffset))); @@ -661,20 +582,6 @@ private void DrawDecalOutlines(Effect effect) effect.CurrentTechnique.Passes[0].Apply(); _legacyDevice.Draw(PrimitiveType.LineList, buffer.ElementCount); } - - if (badVertices.Count > 0) - { - using Buffer buffer = SharpDX.Toolkit.Graphics.Buffer.Vertex.New(_legacyDevice, badVertices.ToArray(), SharpDX.Direct3D11.ResourceUsage.Dynamic); - - _legacyDevice.SetRasterizerState(_legacyDevice.RasterizerStates.Default); - _legacyDevice.SetVertexBuffer(buffer); - _legacyDevice.SetVertexInputLayout(VertexInputLayout.FromBuffer(0, buffer)); - _legacyDevice.SetBlendState(_legacyDevice.BlendStates.NonPremultiplied); - effect.Parameters["ModelViewProjection"].SetValue(_viewProjection.ToSharpDX()); - effect.Parameters["Color"].SetValue(new[] { 1.0f, 0.1f, 0.1f, 0.5f }); - effect.CurrentTechnique.Passes[0].Apply(); - _legacyDevice.Draw(PrimitiveType.TriangleList, buffer.ElementCount); - } } private void DrawLights(Effect effect, Room[] roomsWhoseObjectsToDraw, List textToDraw, List sprites) From dcb623eeb1908323a19128186730f0a7795d39f0 Mon Sep 17 00:00:00 2001 From: Kewin Kupilas Date: Sun, 14 Sep 2025 14:36:03 +0100 Subject: [PATCH 07/19] Drastically improve decal texturing performance --- TombEditor/EditorActions.cs | 117 ++++++++++++++---- TombLib/TombLib/Results/ApplyTextureResult.cs | 28 +++++ 2 files changed, 119 insertions(+), 26 deletions(-) create mode 100644 TombLib/TombLib/Results/ApplyTextureResult.cs diff --git a/TombEditor/EditorActions.cs b/TombEditor/EditorActions.cs index b8f048d8a..a4f720af4 100644 --- a/TombEditor/EditorActions.cs +++ b/TombEditor/EditorActions.cs @@ -26,6 +26,7 @@ using TombLib.LevelData.SectorStructs; using TombLib.LevelData.VisualScripting; using TombLib.Rendering; +using TombLib.Results; using TombLib.Utils; using TombLib.Wad; using TombLib.Wad.Catalog; @@ -1633,7 +1634,7 @@ private static void CheckTextureAttributes(Room room, VectorInt2 pos, SectorFace private static bool _textureAtrributeMessageState = false; private static int _textureAttributeMessageCount = 0; - private static bool ApplyTextureToFace(Room room, VectorInt2 pos, FaceLayerInfo face, TextureArea texture, bool autocorrectCeiling = true) + private static ApplyTextureResult ApplyTextureToFace(Room room, VectorInt2 pos, FaceLayerInfo face, TextureArea texture, bool autocorrectCeiling = true) { if (_editor.Configuration.UI_AutoSwitchRoomToOutsideOnAppliedInvisibleTexture && !room.Properties.FlagHorizon && texture.TextureIsInvisible) @@ -1645,7 +1646,7 @@ private static bool ApplyTextureToFace(Room room, VectorInt2 pos, FaceLayerInfo Sector sector = room.GetSector(pos); FaceShape shape = room.GetFaceShape(pos.X, pos.Y, face.Face); bool wasDoubleSided = sector.GetFaceTexture(face).DoubleSided; - bool textureApplied = false; + bool textureApplied, needsGeometryRebuild = false; // FIXME: Do we really need that now, when TextureOutOfBounds function was fixed? texture.ClampToBounds(); @@ -1674,7 +1675,7 @@ private static bool ApplyTextureToFace(Room room, VectorInt2 pos, FaceLayerInfo if (!updated && face.Layer is FaceLayer.Decal) { - room.RoomGeometry.Build(room, _editor.Configuration.Rendering3D_HighQualityLightPreview); + needsGeometryRebuild = true; updated = true; } @@ -1682,7 +1683,7 @@ private static bool ApplyTextureToFace(Room room, VectorInt2 pos, FaceLayerInfo _editor.RoomTextureChange(room); } - return textureApplied; + return new(textureApplied, needsGeometryRebuild); } TextureArea processedTexture = texture; @@ -1742,7 +1743,7 @@ private static bool ApplyTextureToFace(Room room, VectorInt2 pos, FaceLayerInfo // Get current face VertexRange vertexRange = new VertexRange(0, 0); if (!room.RoomGeometry.VertexRangeLookup.TryGetValue(new SectorFaceIdentity(pos.X, pos.Y, new(face.Face, FaceLayer.Base)), out vertexRange)) - return false; + return ApplyTextureResult.NoChange; if (vertexRange.Count == 6) { @@ -1865,7 +1866,7 @@ private static bool ApplyTextureToFace(Room room, VectorInt2 pos, FaceLayerInfo if (!updated && face.Layer is FaceLayer.Decal) { - room.RoomGeometry.Build(room, _editor.Configuration.Rendering3D_HighQualityLightPreview); + needsGeometryRebuild = true; updated = true; } @@ -1873,7 +1874,7 @@ private static bool ApplyTextureToFace(Room room, VectorInt2 pos, FaceLayerInfo _editor.RoomTextureChange(room); } - return textureApplied; + return new(textureApplied, needsGeometryRebuild); } public static bool ApplyTexture(Room room, VectorInt2 pos, FaceLayerInfo face, TextureArea texture, bool disableUndo = false) @@ -1883,12 +1884,18 @@ public static bool ApplyTexture(Room room, VectorInt2 pos, FaceLayerInfo face, T texture.ParentArea = new Rectangle2(); - bool textureApplied = ApplyTextureToFace(room, pos, face, texture); + ApplyTextureResult result = ApplyTextureToFace(room, pos, face, texture); - if (textureApplied) + if (result.NeedsGeometryRebuild) + { + room.RoomGeometry.Build(room, _editor.Configuration.Rendering3D_HighQualityLightPreview); + _editor.RoomGeometryChange(room); + } + + if (result.Success) _editor.RoomTextureChange(room); - return textureApplied; + return result.Success; } public static Dictionary GetFaces(Room room, VectorInt2 pos, Direction direction, SectorFaceType section) @@ -2119,7 +2126,7 @@ private static float[] GetAreaExtremums(Room room, RectangleInt2 area, Direction return new float[2] { minHeight, maxHeight }; } - public static void TexturizeWallSection(Room room, VectorInt2 pos, Direction direction, SectorFaceType section, TextureArea texture, int subdivisions = 0, int iteration = 0, float[] overrideHeights = null) + public static ApplyTextureResult TexturizeWallSection(Room room, VectorInt2 pos, Direction direction, SectorFaceType section, TextureArea texture, int subdivisions = 0, int iteration = 0, float[] overrideHeights = null) { if (subdivisions < 0 || iteration < 0) subdivisions = 0; @@ -2151,6 +2158,10 @@ public static void TexturizeWallSection(Room room, VectorInt2 pos, Direction dir float sectionHeight = maxSectionHeight - minSectionHeight; bool inverted = false; + bool anyTextureApplied = false; + bool needsGeometryRebuild = false; + ApplyTextureResult result; + foreach (var segment in segments) { float currentHighestPoint = Math.Abs(segment.Value[0] - maxSectionHeight) / sectionHeight; @@ -2208,8 +2219,12 @@ public static void TexturizeWallSection(Room room, VectorInt2 pos, Direction dir } } - ApplyTextureToFace(room, pos, new FaceLayerInfo(segment.Key, _editor.ActiveTextureLayer), processedTexture); + result = ApplyTextureToFace(room, pos, new FaceLayerInfo(segment.Key, _editor.ActiveTextureLayer), processedTexture); + anyTextureApplied |= result.Success; + needsGeometryRebuild |= result.NeedsGeometryRebuild; } + + return new(anyTextureApplied, needsGeometryRebuild); } public static void TexturizeGroup(Room room, SectorSelection selection, SectorSelection workArea, TextureArea texture, SectorFace pickedFace, bool subdivideWalls, bool unifyHeight, bool disableUndo = false) @@ -2220,6 +2235,10 @@ public static void TexturizeGroup(Room room, SectorSelection selection, SectorSe if (pickedFace.IsCeiling()) texture.Mirror(); RectangleInt2 area = selection != SectorSelection.None ? selection.Area : _editor.SelectedRoom.LocalArea; + bool anyTextureApplied = false; + bool needsGeometryRebuild = false; + ApplyTextureResult result; + if (pickedFace.IsWall()) { int xSubs = subdivideWalls ? 0 : area.X1 - area.X0; @@ -2238,16 +2257,22 @@ public static void TexturizeGroup(Room room, SectorSelection selection, SectorSe { case Direction.PositiveZ: case Direction.NegativeZ: - TexturizeWallSection(room, new VectorInt2(x, z), direction, faceType, texture, xSubs, iterX, unifyHeight ? GetAreaExtremums(room, area, direction, faceType) : null); + result = TexturizeWallSection(room, new VectorInt2(x, z), direction, faceType, texture, xSubs, iterX, unifyHeight ? GetAreaExtremums(room, area, direction, faceType) : null); + anyTextureApplied |= result.Success; + needsGeometryRebuild |= result.NeedsGeometryRebuild; break; case Direction.PositiveX: case Direction.NegativeX: - TexturizeWallSection(room, new VectorInt2(x, z), direction, faceType, texture, zSubs, iterZ, unifyHeight ? GetAreaExtremums(room, area, direction, faceType) : null); + result = TexturizeWallSection(room, new VectorInt2(x, z), direction, faceType, texture, zSubs, iterZ, unifyHeight ? GetAreaExtremums(room, area, direction, faceType) : null); + anyTextureApplied |= result.Success; + needsGeometryRebuild |= result.NeedsGeometryRebuild; break; case Direction.Diagonal: - TexturizeWallSection(room, new VectorInt2(x, z), Direction.Diagonal, faceType, texture); + result = TexturizeWallSection(room, new VectorInt2(x, z), Direction.Diagonal, faceType, texture); + anyTextureApplied |= result.Success; + needsGeometryRebuild |= result.NeedsGeometryRebuild; break; } } @@ -2289,21 +2314,38 @@ public static void TexturizeGroup(Room room, SectorSelection selection, SectorSe { case SectorFace.Floor: case SectorFace.Floor_Triangle2: - ApplyTextureToFace(room, new VectorInt2(x, z), new FaceLayerInfo(SectorFace.Floor, _editor.ActiveTextureLayer), currentTexture); - ApplyTextureToFace(room, new VectorInt2(x, z), new FaceLayerInfo(SectorFace.Floor_Triangle2, _editor.ActiveTextureLayer), currentTexture); + result = ApplyTextureToFace(room, new VectorInt2(x, z), new FaceLayerInfo(SectorFace.Floor, _editor.ActiveTextureLayer), currentTexture); + anyTextureApplied |= result.Success; + needsGeometryRebuild |= result.NeedsGeometryRebuild; + + result = ApplyTextureToFace(room, new VectorInt2(x, z), new FaceLayerInfo(SectorFace.Floor_Triangle2, _editor.ActiveTextureLayer), currentTexture); + anyTextureApplied |= result.Success; + needsGeometryRebuild |= result.NeedsGeometryRebuild; break; case SectorFace.Ceiling: case SectorFace.Ceiling_Triangle2: - ApplyTextureToFace(room, new VectorInt2(x, z), new FaceLayerInfo(SectorFace.Ceiling, _editor.ActiveTextureLayer), currentTexture, false); - ApplyTextureToFace(room, new VectorInt2(x, z), new FaceLayerInfo(SectorFace.Ceiling_Triangle2, _editor.ActiveTextureLayer), currentTexture, false); + result = ApplyTextureToFace(room, new VectorInt2(x, z), new FaceLayerInfo(SectorFace.Ceiling, _editor.ActiveTextureLayer), currentTexture, false); + anyTextureApplied |= result.Success; + needsGeometryRebuild |= result.NeedsGeometryRebuild; + + result = ApplyTextureToFace(room, new VectorInt2(x, z), new FaceLayerInfo(SectorFace.Ceiling_Triangle2, _editor.ActiveTextureLayer), currentTexture, false); + anyTextureApplied |= result.Success; + needsGeometryRebuild |= result.NeedsGeometryRebuild; break; } } } } - _editor.RoomTextureChange(room); + if (needsGeometryRebuild) + { + room.RoomGeometry.Build(room, _editor.Configuration.Rendering3D_HighQualityLightPreview); + _editor.RoomGeometryChange(room); + } + + if (anyTextureApplied) + _editor.RoomTextureChange(room); } public static void TexturizeAll(Room room, SectorSelection selection, TextureArea texture, SectorFaceType type) @@ -2315,6 +2357,11 @@ public static void TexturizeAll(Room room, SectorSelection selection, TextureAre texture.ParentArea = new Rectangle2(); + // Track if we need to rebuild geometry for decals at the end + bool anyTextureApplied = false; + bool needsGeometryRebuild = false; + ApplyTextureResult result; + for (int x = area.X0; x <= area.X1; x++) for (int z = area.Y0; z <= area.Y1; z++) { @@ -2323,29 +2370,47 @@ public static void TexturizeAll(Room room, SectorSelection selection, TextureAre case SectorFaceType.Floor: if (!room.Sectors[x, z].IsFullWall) { - ApplyTextureToFace(room, new VectorInt2(x, z), new FaceLayerInfo(SectorFace.Floor, _editor.ActiveTextureLayer), texture); - ApplyTextureToFace(room, new VectorInt2(x, z), new FaceLayerInfo(SectorFace.Floor_Triangle2, _editor.ActiveTextureLayer), texture); + result = ApplyTextureToFace(room, new VectorInt2(x, z), new FaceLayerInfo(SectorFace.Floor, _editor.ActiveTextureLayer), texture); + anyTextureApplied |= result.Success; + needsGeometryRebuild |= result.NeedsGeometryRebuild; + + result = ApplyTextureToFace(room, new VectorInt2(x, z), new FaceLayerInfo(SectorFace.Floor_Triangle2, _editor.ActiveTextureLayer), texture); + anyTextureApplied |= result.Success; + needsGeometryRebuild |= result.NeedsGeometryRebuild; } break; case SectorFaceType.Ceiling: if (!room.Sectors[x, z].IsFullWall) { - ApplyTextureToFace(room, new VectorInt2(x, z), new FaceLayerInfo(SectorFace.Ceiling, _editor.ActiveTextureLayer), texture); - ApplyTextureToFace(room, new VectorInt2(x, z), new FaceLayerInfo(SectorFace.Ceiling_Triangle2, _editor.ActiveTextureLayer), texture); + result = ApplyTextureToFace(room, new VectorInt2(x, z), new FaceLayerInfo(SectorFace.Ceiling, _editor.ActiveTextureLayer), texture); + anyTextureApplied |= result.Success; + needsGeometryRebuild |= result.NeedsGeometryRebuild; + + result = ApplyTextureToFace(room, new VectorInt2(x, z), new FaceLayerInfo(SectorFace.Ceiling_Triangle2, _editor.ActiveTextureLayer), texture); + anyTextureApplied |= result.Success; + needsGeometryRebuild |= result.NeedsGeometryRebuild; } break; case SectorFaceType.Wall: foreach (SectorFace face in SectorFaceExtensions.GetWalls()) if (room.IsFaceDefined(x, z, face)) - ApplyTextureToFace(room, new VectorInt2(x, z), new FaceLayerInfo(face, _editor.ActiveTextureLayer), texture); + { + result = ApplyTextureToFace(room, new VectorInt2(x, z), new FaceLayerInfo(face, _editor.ActiveTextureLayer), texture); + anyTextureApplied |= result.Success; + needsGeometryRebuild |= result.NeedsGeometryRebuild; + } break; } } - _editor.RoomTextureChange(room); + if (needsGeometryRebuild) + room.RoomGeometry.Build(room, _editor.Configuration.Rendering3D_HighQualityLightPreview); + + if (anyTextureApplied) + _editor.RoomTextureChange(room); } private static void AllocateScriptIds(PositionBasedObjectInstance instance) diff --git a/TombLib/TombLib/Results/ApplyTextureResult.cs b/TombLib/TombLib/Results/ApplyTextureResult.cs new file mode 100644 index 000000000..cd5c5b7e4 --- /dev/null +++ b/TombLib/TombLib/Results/ApplyTextureResult.cs @@ -0,0 +1,28 @@ +namespace TombLib.Results; + +/// +/// Result of applying a texture to a face in a room. +/// +public readonly struct ApplyTextureResult +{ + /// + /// Whether the texture application was successful - changes were made. + /// + public bool Success { get; } + + /// + /// Whether the geometry needs to be rebuilt after applying the texture. + /// + public bool NeedsGeometryRebuild { get; } + + public ApplyTextureResult(bool success, bool needsGeometryRebuild) + { + Success = success; + NeedsGeometryRebuild = needsGeometryRebuild; + } + + /// + /// Result indicating that the texture application was not successful - no changes were made. + /// + public static ApplyTextureResult NoChange => new(false, false); +} From 0b0d4d066b36950553c4aabd5e18af62a15813d0 Mon Sep 17 00:00:00 2001 From: Kewin Kupilas Date: Sun, 14 Sep 2025 19:05:11 +0100 Subject: [PATCH 08/19] Decals -> Overlays + Speed up outline rendering --- TombEditor/Controls/Panel3D/Panel3D.cs | 38 ++++- TombEditor/Controls/Panel3D/Panel3DDraw.cs | 145 ++++++++++++------ TombEditor/Controls/Panel3D/Panel3DInit.cs | 5 + TombEditor/Controls/ToolBox.Designer.cs | 28 ++-- TombEditor/Controls/ToolBox.cs | 8 +- TombEditor/Controls/ToolBox.resx | 2 +- TombEditor/EditorActions.cs | 10 +- TombLib/TombLib/LevelData/Compilers/Rooms.cs | 22 +-- .../Compilers/Util/TexInfoManager.cs | 6 +- TombLib/TombLib/LevelData/RoomGeometry.cs | 14 +- TombLib/TombLib/LevelData/Sector.cs | 2 +- .../LevelData/SectorEnums/FaceLayer.cs | 2 +- 12 files changed, 183 insertions(+), 99 deletions(-) diff --git a/TombEditor/Controls/Panel3D/Panel3D.cs b/TombEditor/Controls/Panel3D/Panel3D.cs index 61eca6e9f..d5be2ce3f 100644 --- a/TombEditor/Controls/Panel3D/Panel3D.cs +++ b/TombEditor/Controls/Panel3D/Panel3D.cs @@ -136,6 +136,9 @@ public bool DisablePickingForHiddenRooms private Buffer _flybyPathVertexBuffer; private Buffer _ghostBlockVertexBuffer; private Buffer _boxVertexBuffer; + private Buffer _overlayOutlineVertexBuffer; + private List _overlayOutlineVertices; + private Room _lastOverlayOutlineRoom; // Flyby stuff private const float _flybyPathThickness = 32.0f; @@ -217,6 +220,7 @@ protected override void Dispose(bool disposing) _rasterizerWireframe?.Dispose(); _objectHeightLineVertexBuffer?.Dispose(); _flybyPathVertexBuffer?.Dispose(); + _overlayOutlineVertexBuffer?.Dispose(); _gizmo?.Dispose(); _sphere?.Dispose(); _cone?.Dispose(); @@ -234,6 +238,16 @@ protected override void Dispose(bool disposing) private IReadOnlyList _splitHighlightHotkeys; + private void InvalidateOverlayOutlineCache(Room room = null) + { + if (room is null || _lastOverlayOutlineRoom == room) + { + _lastOverlayOutlineRoom = null; + _overlayOutlineVertexBuffer?.Dispose(); + _overlayOutlineVertexBuffer = null; + } + } + private void EditorEventRaised(IEditorEvent obj) { if (obj is Editor.InitEvent) @@ -276,6 +290,15 @@ obj is Editor.ToolChangedEvent || var room = ((IEditorRoomChangedEvent)obj).Room; _renderingCachedRooms.Remove(room); + + // Invalidate overlay outline cache for geometry or face-related changes + if (obj is Editor.RoomGeometryChangedEvent || + obj is Editor.RoomPositionChangedEvent || + obj is Editor.RoomSectorPropertiesChangedEvent) + { + InvalidateOverlayOutlineCache(room); + } + if (obj is Editor.RoomGeometryChangedEvent || obj is Editor.RoomPositionChangedEvent) foreach (var portal in room.Portals) _renderingCachedRooms.Remove(portal.AdjoiningRoom); @@ -292,10 +315,23 @@ obj is Editor.ToolChangedEvent || if (obj is Editor.SelectedSectorsChangedEvent || obj is Editor.HighlightedSectorChangedEvent) _renderingCachedRooms.Remove(_editor.SelectedRoom); + if (obj is Editor.SelectedRoomChangedEvent) + { _renderingCachedRooms.Remove(((Editor.SelectedRoomChangedEvent)obj).Previous); + + // Overlay outlines are room-specific, so invalidate cache when switching rooms + InvalidateOverlayOutlineCache(); + } + if (obj is Editor.RoomSectorPropertiesChangedEvent) - _renderingCachedRooms.Remove(((Editor.RoomSectorPropertiesChangedEvent)obj).Room); + { + var room = ((Editor.RoomSectorPropertiesChangedEvent)obj).Room; + _renderingCachedRooms.Remove(room); + + InvalidateOverlayOutlineCache(room); + } + if (obj is Editor.LoadedTexturesChangedEvent || obj is Editor.LoadedImportedGeometriesChangedEvent || obj is Editor.LevelChangedEvent || diff --git a/TombEditor/Controls/Panel3D/Panel3DDraw.cs b/TombEditor/Controls/Panel3D/Panel3DDraw.cs index 690a0316e..50a7b1dad 100644 --- a/TombEditor/Controls/Panel3D/Panel3DDraw.cs +++ b/TombEditor/Controls/Panel3D/Panel3DDraw.cs @@ -498,89 +498,132 @@ private static Vector3 ShiftVector3(Vector3 vector, SectorFace face, DiagonalSpl return vector; } - private void DrawDecalOutlines(Effect effect) + private void DrawOverlayOutlines(Effect effect) { - const float DecalOutlineOffset = 8.0f; + const float OverlayOutlineOffset = 16.0f; if (_editor.Mode is not EditorMode.FaceEdit) return; Room currentRoom = _editor.SelectedRoom; - var vertices = new List(); - for (int x = currentRoom.LocalArea.X0; x <= currentRoom.LocalArea.X1; x++) - for (int z = currentRoom.LocalArea.Y0; z <= currentRoom.LocalArea.Y1; z++) + // Check if we need to regenerate the vertex buffer + bool needsUpdate = _lastOverlayOutlineRoom != currentRoom || _overlayOutlineVertexBuffer is null; + + if (needsUpdate) + { + _overlayOutlineVertices.Clear(); + + // Quick check: does this room have any overlays at all? + bool hasOverlays = false; + + for (int x = currentRoom.LocalArea.X0; x <= currentRoom.LocalArea.X1 && !hasOverlays; x++) { - for (SectorFace face = 0; face < SectorFace.Count; face++) + for (int z = currentRoom.LocalArea.Y0; z <= currentRoom.LocalArea.Y1 && !hasOverlays; z++) { - Sector sector = currentRoom.Sectors[x, z]; - var key = new SectorFaceIdentity(x, z, new FaceLayerInfo(face, FaceLayer.Decal)); - - if (currentRoom.RoomGeometry.VertexRangeLookup.ContainsKey(key)) + for (SectorFace face = 0; face < SectorFace.Count; face++) { - VertexRange range = currentRoom.RoomGeometry.VertexRangeLookup[key]; - DiagonalSplit diagonalSplit = face.IsFloorWall() ? sector.Floor.DiagonalSplit : sector.Ceiling.DiagonalSplit; - - TextureArea baseTexture = sector.GetFaceTexture(new(face, FaceLayer.Base)); - TextureArea decalTexture = sector.GetFaceTexture(new(face, FaceLayer.Decal)); + var key = new SectorFaceIdentity(x, z, new FaceLayerInfo(face, FaceLayer.Overlay)); - if (range.Count == 3) + if (currentRoom.RoomGeometry.VertexRangeLookup.ContainsKey(key)) { - vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start] + currentRoom.WorldPos, face, diagonalSplit, DecalOutlineOffset))); - vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 1] + currentRoom.WorldPos, face, diagonalSplit, DecalOutlineOffset))); + hasOverlays = true; + break; + } + } + } + } - vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 1] + currentRoom.WorldPos, face, diagonalSplit, DecalOutlineOffset))); - vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 2] + currentRoom.WorldPos, face, diagonalSplit, DecalOutlineOffset))); + if (!hasOverlays) + { + _lastOverlayOutlineRoom = currentRoom; + _overlayOutlineVertexBuffer?.Dispose(); + _overlayOutlineVertexBuffer = null; + return; + } - vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 2] + currentRoom.WorldPos, face, diagonalSplit, DecalOutlineOffset))); - vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start] + currentRoom.WorldPos, face, diagonalSplit, DecalOutlineOffset))); - } - else if (range.Count == 6) + // Generate vertices for all overlay outlines in this room + for (int x = currentRoom.LocalArea.X0; x <= currentRoom.LocalArea.X1; x++) + { + for (int z = currentRoom.LocalArea.Y0; z <= currentRoom.LocalArea.Y1; z++) + { + for (SectorFace face = 0; face < SectorFace.Count; face++) + { + Sector sector = currentRoom.Sectors[x, z]; + var key = new SectorFaceIdentity(x, z, new FaceLayerInfo(face, FaceLayer.Overlay)); + + if (currentRoom.RoomGeometry.VertexRangeLookup.ContainsKey(key)) { - if (face.IsCeiling()) - { - vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start] + currentRoom.WorldPos, face, diagonalSplit, DecalOutlineOffset))); - vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 2] + currentRoom.WorldPos, face, diagonalSplit, DecalOutlineOffset))); + VertexRange range = currentRoom.RoomGeometry.VertexRangeLookup[key]; + DiagonalSplit diagonalSplit = face.IsFloorWall() ? sector.Floor.DiagonalSplit : sector.Ceiling.DiagonalSplit; - vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 2] + currentRoom.WorldPos, face, diagonalSplit, DecalOutlineOffset))); - vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 3] + currentRoom.WorldPos, face, diagonalSplit, DecalOutlineOffset))); + if (range.Count == 3) + { + _overlayOutlineVertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start] + currentRoom.WorldPos, face, diagonalSplit, OverlayOutlineOffset))); + _overlayOutlineVertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 1] + currentRoom.WorldPos, face, diagonalSplit, OverlayOutlineOffset))); - vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 3] + currentRoom.WorldPos, face, diagonalSplit, DecalOutlineOffset))); - vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 5] + currentRoom.WorldPos, face, diagonalSplit, DecalOutlineOffset))); + _overlayOutlineVertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 1] + currentRoom.WorldPos, face, diagonalSplit, OverlayOutlineOffset))); + _overlayOutlineVertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 2] + currentRoom.WorldPos, face, diagonalSplit, OverlayOutlineOffset))); - vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 5] + currentRoom.WorldPos, face, diagonalSplit, DecalOutlineOffset))); - vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start] + currentRoom.WorldPos, face, diagonalSplit, DecalOutlineOffset))); + _overlayOutlineVertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 2] + currentRoom.WorldPos, face, diagonalSplit, OverlayOutlineOffset))); + _overlayOutlineVertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start] + currentRoom.WorldPos, face, diagonalSplit, OverlayOutlineOffset))); } - else + else if (range.Count == 6) { - vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start] + currentRoom.WorldPos, face, diagonalSplit, DecalOutlineOffset))); - vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 1] + currentRoom.WorldPos, face, diagonalSplit, DecalOutlineOffset))); + if (face.IsCeiling()) + { + _overlayOutlineVertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start] + currentRoom.WorldPos, face, diagonalSplit, OverlayOutlineOffset))); + _overlayOutlineVertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 2] + currentRoom.WorldPos, face, diagonalSplit, OverlayOutlineOffset))); + + _overlayOutlineVertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 2] + currentRoom.WorldPos, face, diagonalSplit, OverlayOutlineOffset))); + _overlayOutlineVertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 3] + currentRoom.WorldPos, face, diagonalSplit, OverlayOutlineOffset))); + + _overlayOutlineVertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 3] + currentRoom.WorldPos, face, diagonalSplit, OverlayOutlineOffset))); + _overlayOutlineVertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 5] + currentRoom.WorldPos, face, diagonalSplit, OverlayOutlineOffset))); + + _overlayOutlineVertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 5] + currentRoom.WorldPos, face, diagonalSplit, OverlayOutlineOffset))); + _overlayOutlineVertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start] + currentRoom.WorldPos, face, diagonalSplit, OverlayOutlineOffset))); + } + else + { + _overlayOutlineVertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start] + currentRoom.WorldPos, face, diagonalSplit, OverlayOutlineOffset))); + _overlayOutlineVertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 1] + currentRoom.WorldPos, face, diagonalSplit, OverlayOutlineOffset))); - vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 1] + currentRoom.WorldPos, face, diagonalSplit, DecalOutlineOffset))); - vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 3] + currentRoom.WorldPos, face, diagonalSplit, DecalOutlineOffset))); + _overlayOutlineVertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 1] + currentRoom.WorldPos, face, diagonalSplit, OverlayOutlineOffset))); + _overlayOutlineVertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 3] + currentRoom.WorldPos, face, diagonalSplit, OverlayOutlineOffset))); - vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 3] + currentRoom.WorldPos, face, diagonalSplit, DecalOutlineOffset))); - vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 2] + currentRoom.WorldPos, face, diagonalSplit, DecalOutlineOffset))); + _overlayOutlineVertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 3] + currentRoom.WorldPos, face, diagonalSplit, OverlayOutlineOffset))); + _overlayOutlineVertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 2] + currentRoom.WorldPos, face, diagonalSplit, OverlayOutlineOffset))); - vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 2] + currentRoom.WorldPos, face, diagonalSplit, DecalOutlineOffset))); - vertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start] + currentRoom.WorldPos, face, diagonalSplit, DecalOutlineOffset))); + _overlayOutlineVertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start + 2] + currentRoom.WorldPos, face, diagonalSplit, OverlayOutlineOffset))); + _overlayOutlineVertices.Add(new SolidVertex(ShiftVector3(currentRoom.RoomGeometry.VertexPositions[range.Start] + currentRoom.WorldPos, face, diagonalSplit, OverlayOutlineOffset))); + } } } } } } - if (vertices.Count > 0) - { - using Buffer buffer = SharpDX.Toolkit.Graphics.Buffer.Vertex.New(_legacyDevice, vertices.ToArray(), SharpDX.Direct3D11.ResourceUsage.Dynamic); + // Create/update the vertex buffer + _overlayOutlineVertexBuffer?.Dispose(); + _overlayOutlineVertexBuffer = _overlayOutlineVertices.Count > 0 + ? SharpDX.Toolkit.Graphics.Buffer.Vertex.New(_legacyDevice, _overlayOutlineVertices.ToArray(), SharpDX.Direct3D11.ResourceUsage.Immutable) + : null; + + _lastOverlayOutlineRoom = currentRoom; + } + + // Draw using the cached buffer + if (_overlayOutlineVertexBuffer is not null) + { _legacyDevice.SetRasterizerState(_legacyDevice.RasterizerStates.Default); - _legacyDevice.SetVertexBuffer(buffer); - _legacyDevice.SetVertexInputLayout(VertexInputLayout.FromBuffer(0, buffer)); + _legacyDevice.SetVertexBuffer(_overlayOutlineVertexBuffer); + _legacyDevice.SetVertexInputLayout(VertexInputLayout.FromBuffer(0, _overlayOutlineVertexBuffer)); effect.Parameters["ModelViewProjection"].SetValue(_viewProjection.ToSharpDX()); effect.Parameters["Color"].SetValue(Vector4.One); effect.CurrentTechnique.Passes[0].Apply(); - _legacyDevice.Draw(PrimitiveType.LineList, buffer.ElementCount); + _legacyDevice.Draw(PrimitiveType.LineList, _overlayOutlineVertexBuffer.ElementCount); } } @@ -2123,8 +2166,8 @@ private void DrawScene() DrawFlybyPath(effect); // Draw sector split highlights DrawSectorSplitHighlights(effect); - // Draw decal outlines - DrawDecalOutlines(effect); + // Draw overlay outlines + DrawOverlayOutlines(effect); } // Draw ghost block cubes diff --git a/TombEditor/Controls/Panel3D/Panel3DInit.cs b/TombEditor/Controls/Panel3D/Panel3DInit.cs index a94d59518..c9ecc6683 100644 --- a/TombEditor/Controls/Panel3D/Panel3DInit.cs +++ b/TombEditor/Controls/Panel3D/Panel3DInit.cs @@ -1,4 +1,5 @@ using SharpDX.Toolkit.Graphics; +using System.Collections.Generic; using System.Numerics; using TombLib.Graphics.Primitives; using TombLib.Graphics; @@ -58,6 +59,10 @@ public override void InitializeRendering(RenderingDevice device, bool antialias, _ghostBlockVertexBuffer = SharpDX.Toolkit.Graphics.Buffer.Vertex.New(_legacyDevice, 84); _boxVertexBuffer = new BoundingBox(new Vector3(-_littleCubeRadius), new Vector3(_littleCubeRadius)).GetVertexBuffer(_legacyDevice); + // Initialize overlay outline cache + _overlayOutlineVertices = new List(); + _lastOverlayOutlineRoom = null; + // Maybe I could use this as bounding box, scaling it properly before drawing _linesCube = GeometricPrimitive.LinesCube.New(_legacyDevice, 128, 128, 128); diff --git a/TombEditor/Controls/ToolBox.Designer.cs b/TombEditor/Controls/ToolBox.Designer.cs index 64c8b7205..181310ae1 100644 --- a/TombEditor/Controls/ToolBox.Designer.cs +++ b/TombEditor/Controls/ToolBox.Designer.cs @@ -53,7 +53,7 @@ private void InitializeComponent() toolPortalDigger = new System.Windows.Forms.ToolStripButton(); toolUVFixer = new System.Windows.Forms.ToolStripButton(); toolSeparator3 = new System.Windows.Forms.ToolStripSeparator(); - toolDecalsMode = new System.Windows.Forms.ToolStripButton(); + toolOverlayMode = new System.Windows.Forms.ToolStripButton(); toolStrip.SuspendLayout(); SuspendLayout(); // @@ -65,7 +65,7 @@ private void InitializeComponent() toolStrip.Dock = System.Windows.Forms.DockStyle.Fill; toolStrip.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); toolStrip.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden; - toolStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { toolSelection, toolBrush, toolShovel, toolPencil, toolFlatten, toolSmooth, toolFill, toolGridPaint, toolGroup, toolSeparator1, toolDrag, toolRamp, toolQuarterPipe, toolHalfPipe, toolBowl, toolPyramid, toolTerrain, toolEraser, toolInvisibility, toolSeparator2, toolPortalDigger, toolUVFixer, toolSeparator3, toolDecalsMode }); + toolStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { toolSelection, toolBrush, toolShovel, toolPencil, toolFlatten, toolSmooth, toolFill, toolGridPaint, toolGroup, toolSeparator1, toolDrag, toolRamp, toolQuarterPipe, toolHalfPipe, toolBowl, toolPyramid, toolTerrain, toolEraser, toolInvisibility, toolSeparator2, toolPortalDigger, toolUVFixer, toolSeparator3, toolOverlayMode }); toolStrip.LayoutStyle = System.Windows.Forms.ToolStripLayoutStyle.VerticalStackWithOverflow; toolStrip.Location = new System.Drawing.Point(0, 0); toolStrip.Name = "toolStrip"; @@ -359,18 +359,18 @@ private void InitializeComponent() toolSeparator3.Name = "toolSeparator3"; toolSeparator3.Size = new System.Drawing.Size(23, 6); // - // toolDecalsMode + // toolOverlayMode // - toolDecalsMode.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); - toolDecalsMode.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - toolDecalsMode.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); - toolDecalsMode.Image = (System.Drawing.Image)resources.GetObject("toolDecalsMode.Image"); - toolDecalsMode.ImageTransparentColor = System.Drawing.Color.Magenta; - toolDecalsMode.Margin = new System.Windows.Forms.Padding(1); - toolDecalsMode.Name = "toolDecalsMode"; - toolDecalsMode.Size = new System.Drawing.Size(23, 20); - toolDecalsMode.ToolTipText = "Toggle decals mode"; - toolDecalsMode.Click += toolDecalsMode_Click; + toolOverlayMode.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + toolOverlayMode.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + toolOverlayMode.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); + toolOverlayMode.Image = (System.Drawing.Image)resources.GetObject("toolOverlayMode.Image"); + toolOverlayMode.ImageTransparentColor = System.Drawing.Color.Magenta; + toolOverlayMode.Margin = new System.Windows.Forms.Padding(1); + toolOverlayMode.Name = "toolOverlayMode"; + toolOverlayMode.Size = new System.Drawing.Size(23, 20); + toolOverlayMode.ToolTipText = "Toggle overlay mode"; + toolOverlayMode.Click += toolOverlayMode_Click; // // ToolBox // @@ -412,6 +412,6 @@ private void InitializeComponent() private System.Windows.Forms.ToolStripButton toolGridPaint; private System.Windows.Forms.ToolStripButton toolPortalDigger; private System.Windows.Forms.ToolStripSeparator toolSeparator3; - private System.Windows.Forms.ToolStripButton toolDecalsMode; + private System.Windows.Forms.ToolStripButton toolOverlayMode; } } diff --git a/TombEditor/Controls/ToolBox.cs b/TombEditor/Controls/ToolBox.cs index ba6a3a7fe..1aab009bf 100644 --- a/TombEditor/Controls/ToolBox.cs +++ b/TombEditor/Controls/ToolBox.cs @@ -110,7 +110,7 @@ private void EditorEventRaised(IEditorEvent obj) toolInvisibility.Visible = !geometryMode; toolUVFixer.Visible = !geometryMode; toolSeparator3.Visible = !geometryMode; - toolDecalsMode.Visible = !geometryMode; + toolOverlayMode.Visible = !geometryMode; toolFlatten.Visible = geometryMode; toolShovel.Visible = geometryMode; toolSmooth.Visible = geometryMode; @@ -256,15 +256,15 @@ private void toolGridPaint_MouseDown(object sender, MouseEventArgs e) ContextMenuTimer_Tick(sender, e); } - private void toolDecalsMode_Click(object sender, EventArgs e) + private void toolOverlayMode_Click(object sender, EventArgs e) { _editor.ActiveTextureLayer = _editor.ActiveTextureLayer switch { - FaceLayer.Base => FaceLayer.Decal, + FaceLayer.Base => FaceLayer.Overlay, _ => FaceLayer.Base }; - toolDecalsMode.Checked = _editor.ActiveTextureLayer == FaceLayer.Decal; + toolOverlayMode.Checked = _editor.ActiveTextureLayer == FaceLayer.Overlay; } } } diff --git a/TombEditor/Controls/ToolBox.resx b/TombEditor/Controls/ToolBox.resx index 0c7f5f648..575ee9505 100644 --- a/TombEditor/Controls/ToolBox.resx +++ b/TombEditor/Controls/ToolBox.resx @@ -121,7 +121,7 @@ 17, 17 - + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAE5SURBVDhPtZKxSsNgFIVjXBwtuDmIUAWhk86dxGAXQUER diff --git a/TombEditor/EditorActions.cs b/TombEditor/EditorActions.cs index a4f720af4..cfd5cf3ba 100644 --- a/TombEditor/EditorActions.cs +++ b/TombEditor/EditorActions.cs @@ -1434,7 +1434,7 @@ public static void RotateTexture(Room room, VectorInt2 pos, FaceLayerInfo face) // Update state bool updated = room.RoomGeometry.UpdateFaceTexture(pos.X, pos.Y, face, newTexture, newTexture.DoubleSided); - if (!updated && face.Layer is FaceLayer.Decal) + if (!updated && face.Layer is FaceLayer.Overlay) { room.RoomGeometry.Build(room, _editor.Configuration.Rendering3D_HighQualityLightPreview); updated = true; @@ -1457,7 +1457,7 @@ public static void MirrorTexture(Room room, VectorInt2 pos, FaceLayerInfo face) // Update state bool updated = room.RoomGeometry.UpdateFaceTexture(pos.X, pos.Y, face, newTexture, newTexture.DoubleSided); - if (!updated && face.Layer is FaceLayer.Decal) + if (!updated && face.Layer is FaceLayer.Overlay) { room.RoomGeometry.Build(room, _editor.Configuration.Rendering3D_HighQualityLightPreview); updated = true; @@ -1673,7 +1673,7 @@ private static ApplyTextureResult ApplyTextureToFace(Room room, VectorInt2 pos, bool updated = room.RoomGeometry.UpdateFaceTexture(pos.X, pos.Y, face, currentTexture, wasDoubleSided); - if (!updated && face.Layer is FaceLayer.Decal) + if (!updated && face.Layer is FaceLayer.Overlay) { needsGeometryRebuild = true; updated = true; @@ -1864,7 +1864,7 @@ private static ApplyTextureResult ApplyTextureToFace(Room room, VectorInt2 pos, bool updated = room.RoomGeometry.UpdateFaceTexture(pos.X, pos.Y, face, currentTexture, wasDoubleSided); - if (!updated && face.Layer is FaceLayer.Decal) + if (!updated && face.Layer is FaceLayer.Overlay) { needsGeometryRebuild = true; updated = true; @@ -2357,7 +2357,7 @@ public static void TexturizeAll(Room room, SectorSelection selection, TextureAre texture.ParentArea = new Rectangle2(); - // Track if we need to rebuild geometry for decals at the end + // Track if we need to rebuild geometry for overlays at the end bool anyTextureApplied = false; bool needsGeometryRebuild = false; ApplyTextureResult result; diff --git a/TombLib/TombLib/LevelData/Compilers/Rooms.cs b/TombLib/TombLib/LevelData/Compilers/Rooms.cs index eccdfd77a..fb2a8fd65 100644 --- a/TombLib/TombLib/LevelData/Compilers/Rooms.cs +++ b/TombLib/TombLib/LevelData/Compilers/Rooms.cs @@ -342,7 +342,7 @@ private tr_room BuildRoom(Room room) var roomTriangles = new List(); var roomQuads = new List(); - // Track base polygon rotations for decal coordination + // Track base polygon rotations for overlay coordination var baseRotations = new Dictionary<(int, int, SectorFace), int>(); // Add room's own geometry @@ -424,8 +424,8 @@ private tr_room BuildRoom(Room room) } Util.TexInfoManager.Result result; - - // Coordinate texture rotations between base and decal layers + + // Coordinate texture rotations between base and overlay layers var faceKey = (x, z, face.Face); if (face.Layer == FaceLayer.Base) @@ -434,9 +434,9 @@ private tr_room BuildRoom(Room room) result = _textureInfoManager.AddTexture(texture, true, false); baseRotations[faceKey] = result.Rotation; } - else if (face.Layer == FaceLayer.Decal && baseRotations.ContainsKey(faceKey)) + else if (face.Layer == FaceLayer.Overlay && baseRotations.ContainsKey(faceKey)) { - // Decal layer: force to use same rotation as base + // Overlay layer: force to use same rotation as base var baseRotation = baseRotations[faceKey]; result = _textureInfoManager.AddTexture(texture, true, false, false, baseRotation); } @@ -454,7 +454,7 @@ private tr_room BuildRoom(Room room) Util.TexInfoManager.Result mirrorResult; - if (face.Layer == FaceLayer.Decal && baseRotations.ContainsKey(faceKey)) + if (face.Layer == FaceLayer.Overlay && baseRotations.ContainsKey(faceKey)) { var baseRotation = baseRotations[faceKey]; mirrorResult = _textureInfoManager.AddTexture(texture, true, false, false, baseRotation); @@ -497,8 +497,8 @@ private tr_room BuildRoom(Room room) } Util.TexInfoManager.Result result; - - // Coordinate texture rotations between base and decal layers + + // Coordinate texture rotations between base and overlay layers var faceKey = (x, z, face.Face); if (face.Layer == FaceLayer.Base) @@ -507,9 +507,9 @@ private tr_room BuildRoom(Room room) result = _textureInfoManager.AddTexture(texture, true, true); baseRotations[faceKey] = result.Rotation; } - else if (face.Layer == FaceLayer.Decal && baseRotations.ContainsKey(faceKey)) + else if (face.Layer == FaceLayer.Overlay && baseRotations.ContainsKey(faceKey)) { - // Decal layer: force to use same rotation as base + // Overlay layer: force to use same rotation as base var baseRotation = baseRotations[faceKey]; result = _textureInfoManager.AddTexture(texture, true, true, false, baseRotation); } @@ -532,7 +532,7 @@ private tr_room BuildRoom(Room room) Util.TexInfoManager.Result mirrorResult; - if (face.Layer == FaceLayer.Decal && baseRotations.ContainsKey(faceKey)) + if (face.Layer == FaceLayer.Overlay && baseRotations.ContainsKey(faceKey)) { var baseRotation = baseRotations[faceKey]; mirrorResult = _textureInfoManager.AddTexture(texture, true, true, false, baseRotation); diff --git a/TombLib/TombLib/LevelData/Compilers/Util/TexInfoManager.cs b/TombLib/TombLib/LevelData/Compilers/Util/TexInfoManager.cs index d43fbeebb..22ba6bd56 100644 --- a/TombLib/TombLib/LevelData/Compilers/Util/TexInfoManager.cs +++ b/TombLib/TombLib/LevelData/Compilers/Util/TexInfoManager.cs @@ -713,7 +713,7 @@ public tr_face4 CreateFace4(ushort[] indices, bool doubleSided, ushort lightingE var result = TestUVSimilarity(child.AbsCoord, lookupCoordinates, lookupMargin); if (result != _noTexInfo) { - // If rotation is forced for decal coordination, reject this match if rotation doesn't match + // If rotation is forced for overlay coordination, reject this match if rotation doesn't match if (forceRotation >= 0 && result != forceRotation) continue; @@ -828,7 +828,7 @@ public Result AddTexture(TextureArea texture, bool isForRoom, bool isForTriangle if (!ValidateTexture(texture, isForTriangle)) return new Result(); - // Force specific rotation for decal coordination + // Force specific rotation for overlay coordination return AddTexture(texture, _parentTextures, isForRoom, isForTriangle, topmostAndUnpadded, -1, true, forceRotation); } @@ -880,7 +880,7 @@ private Result AddTexture(TextureArea texture, List parentLis if (forceRotation >= 0) { - // Force specific rotation for decal coordination + // Force specific rotation for overlay coordination canonicalTexture = texture; if (forceRotation > 0) diff --git a/TombLib/TombLib/LevelData/RoomGeometry.cs b/TombLib/TombLib/LevelData/RoomGeometry.cs index d9ebd0144..98a60fb37 100644 --- a/TombLib/TombLib/LevelData/RoomGeometry.cs +++ b/TombLib/TombLib/LevelData/RoomGeometry.cs @@ -329,7 +329,7 @@ public void Build(Room room, bool highQualityLighting, bool useLegacyCode = fals public bool UpdateFaceTexture(int x, int z, FaceLayerInfo face, TextureArea texture, bool wasDoubleSided) { - if (face.Layer is FaceLayer.Decal && texture.TextureIsInvisible) + if (face.Layer is FaceLayer.Overlay && texture.TextureIsInvisible) return false; VertexRange range = VertexRangeLookup.GetValueOrDefault(new SectorFaceIdentity(x, z, face)); @@ -661,24 +661,24 @@ private void TryRenderQuadFace(Sector sector, int x, int z, SectorFace face, Vec { TextureArea texture = sector.GetFaceTexture(new FaceLayerInfo(face, FaceLayer.Base)), - decal = sector.GetFaceTexture(new FaceLayerInfo(face, FaceLayer.Decal)); + overlay = sector.GetFaceTexture(new FaceLayerInfo(face, FaceLayer.Overlay)); AddQuad(x, z, new FaceLayerInfo(face, FaceLayer.Base), p0, p1, p2, p3, texture, uv0, uv1, uv2, uv3); - if (decal != TextureArea.None) - AddQuad(x, z, new FaceLayerInfo(face, FaceLayer.Decal), p0, p1, p2, p3, decal, uv0, uv1, uv2, uv3); + if (overlay != TextureArea.None) + AddQuad(x, z, new FaceLayerInfo(face, FaceLayer.Overlay), p0, p1, p2, p3, overlay, uv0, uv1, uv2, uv3); } private void TryRenderTriangleFace(Sector sector, int x, int z, SectorFace face, Vector3 p0, Vector3 p1, Vector3 p2, Vector2 uv0, Vector2 uv1, Vector2 uv2, bool isXEqualYDiagonal) { TextureArea texture = sector.GetFaceTexture(new FaceLayerInfo(face, FaceLayer.Base)), - decal = sector.GetFaceTexture(new FaceLayerInfo(face, FaceLayer.Decal)); + overlay = sector.GetFaceTexture(new FaceLayerInfo(face, FaceLayer.Overlay)); AddTriangle(x, z, new FaceLayerInfo(face, FaceLayer.Base), p0, p1, p2, texture, uv0, uv1, uv2, isXEqualYDiagonal); - if (decal != TextureArea.None) - AddTriangle(x, z, new FaceLayerInfo(face, FaceLayer.Decal), p0, p1, p2, decal, uv0, uv1, uv2, isXEqualYDiagonal); + if (overlay != TextureArea.None) + AddTriangle(x, z, new FaceLayerInfo(face, FaceLayer.Overlay), p0, p1, p2, overlay, uv0, uv1, uv2, isXEqualYDiagonal); } private void AddQuad(int x, int z, FaceLayerInfo face, Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, diff --git a/TombLib/TombLib/LevelData/Sector.cs b/TombLib/TombLib/LevelData/Sector.cs index f3aef0b52..3488563f0 100644 --- a/TombLib/TombLib/LevelData/Sector.cs +++ b/TombLib/TombLib/LevelData/Sector.cs @@ -86,7 +86,7 @@ public bool HasFlag(SectorFlags flag) public bool SetFaceTexture(FaceLayerInfo face, TextureArea texture) { - if (texture == TextureArea.None) + if (texture == TextureArea.None || (face.Layer is FaceLayer.Overlay && texture.TextureIsInvisible)) return _faceTextures.Remove(face); if (texture.TextureIsDegenerate) diff --git a/TombLib/TombLib/LevelData/SectorEnums/FaceLayer.cs b/TombLib/TombLib/LevelData/SectorEnums/FaceLayer.cs index 91087224c..c10e5648e 100644 --- a/TombLib/TombLib/LevelData/SectorEnums/FaceLayer.cs +++ b/TombLib/TombLib/LevelData/SectorEnums/FaceLayer.cs @@ -3,6 +3,6 @@ public enum FaceLayer : byte { Base, - Decal, + Overlay, Count } From 7c4e7c79311de16edc5d16a8e3125a01e4a53749 Mon Sep 17 00:00:00 2001 From: Kewin Kupilas Date: Sun, 14 Sep 2025 19:23:51 +0100 Subject: [PATCH 09/19] Fix infinite loop --- TombLib/TombLib/LevelData/SectorStructs/SectorFaceIdentity.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TombLib/TombLib/LevelData/SectorStructs/SectorFaceIdentity.cs b/TombLib/TombLib/LevelData/SectorStructs/SectorFaceIdentity.cs index 80aa5bd32..edf9f5d06 100644 --- a/TombLib/TombLib/LevelData/SectorStructs/SectorFaceIdentity.cs +++ b/TombLib/TombLib/LevelData/SectorStructs/SectorFaceIdentity.cs @@ -19,7 +19,7 @@ public SectorFaceIdentity(int x, int z, FaceLayerInfo face) public override int GetHashCode() => HashCode.Combine(Position, Face.Face, Face.Layer); public bool Equals(SectorFaceIdentity other) => Position == other.Position && Face == other.Face; - public override bool Equals(object other) => other is SectorFaceIdentity identity && identity.Equals(other); + public override bool Equals(object other) => other is SectorFaceIdentity identity && Equals(identity); int IComparable.CompareTo(object other) => CompareTo((SectorFaceIdentity)other); public int CompareTo(SectorFaceIdentity other) From c5ebb9f8f4f0dca7031ea711111b944643d4f73e Mon Sep 17 00:00:00 2001 From: Kewin Kupilas Date: Sun, 14 Sep 2025 19:26:04 +0100 Subject: [PATCH 10/19] Remove unnecassary `readonly` --- TombLib/TombLib/LevelData/SectorStructs/FaceLayerInfo.cs | 4 ++-- TombLib/TombLib/LevelData/SectorStructs/SectorFaceIdentity.cs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/TombLib/TombLib/LevelData/SectorStructs/FaceLayerInfo.cs b/TombLib/TombLib/LevelData/SectorStructs/FaceLayerInfo.cs index 29d907f35..b4d4e9ca6 100644 --- a/TombLib/TombLib/LevelData/SectorStructs/FaceLayerInfo.cs +++ b/TombLib/TombLib/LevelData/SectorStructs/FaceLayerInfo.cs @@ -5,8 +5,8 @@ namespace TombLib.LevelData.SectorStructs; public readonly struct FaceLayerInfo : IEquatable { - public readonly SectorFace Face { get; } - public readonly FaceLayer Layer { get; } + public SectorFace Face { get; } + public FaceLayer Layer { get; } public FaceLayerInfo(SectorFace face, FaceLayer layer) { diff --git a/TombLib/TombLib/LevelData/SectorStructs/SectorFaceIdentity.cs b/TombLib/TombLib/LevelData/SectorStructs/SectorFaceIdentity.cs index edf9f5d06..b9c19fa38 100644 --- a/TombLib/TombLib/LevelData/SectorStructs/SectorFaceIdentity.cs +++ b/TombLib/TombLib/LevelData/SectorStructs/SectorFaceIdentity.cs @@ -7,8 +7,8 @@ namespace TombLib.LevelData.SectorStructs; /// public readonly struct SectorFaceIdentity : IEquatable, IComparable, IComparable { - public readonly VectorInt2 Position { get; } - public readonly FaceLayerInfo Face { get; } + public VectorInt2 Position { get; } + public FaceLayerInfo Face { get; } public SectorFaceIdentity(int x, int z, FaceLayerInfo face) { From 2bb3dc5d9ebc8e1bdf13c68a9ef06bfe48fc45e3 Mon Sep 17 00:00:00 2001 From: Kewin Kupilas Date: Sun, 14 Sep 2025 19:28:52 +0100 Subject: [PATCH 11/19] Fix inconsistent spaces --- TombLib/TombLib/Utils/RectTransformation.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/TombLib/TombLib/Utils/RectTransformation.cs b/TombLib/TombLib/Utils/RectTransformation.cs index f827a3131..c64772286 100644 --- a/TombLib/TombLib/Utils/RectTransformation.cs +++ b/TombLib/TombLib/Utils/RectTransformation.cs @@ -31,10 +31,10 @@ public void TransformValueQuad(Dictionary faceTextur for (FaceLayer layer = 0; layer < FaceLayer.Count; layer++) { FaceLayerInfo - key0 = new(rotation0, layer), - key1 = new(rotation1, layer), - key2 = new(rotation2, layer), - key3 = new(rotation3, layer); + key0 = new(rotation0, layer), + key1 = new(rotation1, layer), + key2 = new(rotation2, layer), + key3 = new(rotation3, layer); if (MirrorX) faceTextures.TrySwap(key0, key2); From 9659656cc9d07f09aed933a4310fd3645f1a5d7f Mon Sep 17 00:00:00 2001 From: Kewin Kupilas Date: Sun, 14 Sep 2025 19:50:05 +0100 Subject: [PATCH 12/19] Replace Overlays Mode icon (Sticker -> Layers) --- TombEditor/Controls/ToolBox.Designer.cs | 3 +-- TombEditor/Controls/ToolBox.resx | 12 ------------ TombEditor/Properties/Resources.Designer.cs | 10 ++++++++++ TombEditor/Properties/Resources.resx | 3 +++ .../Resources/icons_general/general_layers-16.png | Bin 0 -> 244 bytes 5 files changed, 14 insertions(+), 14 deletions(-) create mode 100644 TombEditor/Resources/icons_general/general_layers-16.png diff --git a/TombEditor/Controls/ToolBox.Designer.cs b/TombEditor/Controls/ToolBox.Designer.cs index 181310ae1..ef41d2472 100644 --- a/TombEditor/Controls/ToolBox.Designer.cs +++ b/TombEditor/Controls/ToolBox.Designer.cs @@ -28,7 +28,6 @@ protected override void Dispose(bool disposing) /// private void InitializeComponent() { - var resources = new System.ComponentModel.ComponentResourceManager(typeof(ToolBox)); toolStrip = new DarkUI.Controls.DarkToolStrip(); toolSelection = new System.Windows.Forms.ToolStripButton(); toolBrush = new System.Windows.Forms.ToolStripButton(); @@ -364,7 +363,7 @@ private void InitializeComponent() toolOverlayMode.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); toolOverlayMode.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; toolOverlayMode.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); - toolOverlayMode.Image = (System.Drawing.Image)resources.GetObject("toolOverlayMode.Image"); + toolOverlayMode.Image = Properties.Resources.general_layers_16; toolOverlayMode.ImageTransparentColor = System.Drawing.Color.Magenta; toolOverlayMode.Margin = new System.Windows.Forms.Padding(1); toolOverlayMode.Name = "toolOverlayMode"; diff --git a/TombEditor/Controls/ToolBox.resx b/TombEditor/Controls/ToolBox.resx index 575ee9505..c42befb07 100644 --- a/TombEditor/Controls/ToolBox.resx +++ b/TombEditor/Controls/ToolBox.resx @@ -120,16 +120,4 @@ 17, 17 - - - - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAE5SURBVDhPtZKxSsNgFIVjXBwtuDmIUAWhk86dxGAXQUER - dajgJBQ3hwzuFcTBF3BxqJ2Lk6uDYkVd7GZtXVR8Akn8bnqI1LTBwR74uNxzz3/zN6kzEIVhOBoEwQ4c - w7jsv4kDe/AJVfiCZ5jWOF0Ej+AWptS/wz60YCYK9ROBZXiy68syrwYrsAWvkNMoKYaPMK82EstW8a6o - LnUdbEnyJphZeFEbSwcvoWw9dRPa0P1OMApQU9sllowxu4YKTNIXqU2YUCRasAgXahPi0AjzA7CXegcf - UNc4/gktgkOyeor5MMyRtWU3sjvCeABPbapYckrWV9sRxhI0GMafsZfILECbXEbWjxgcQh2iP9Jv4a/B - G+RlJcVw10I84Zxagg3wwb7EPcwq2l92PYLbcAJnUAYP31Xkv+Q43wTrT7Q6A1OTAAAAAElFTkSuQmCC - - \ No newline at end of file diff --git a/TombEditor/Properties/Resources.Designer.cs b/TombEditor/Properties/Resources.Designer.cs index f53d05977..19d7a6bbe 100644 --- a/TombEditor/Properties/Resources.Designer.cs +++ b/TombEditor/Properties/Resources.Designer.cs @@ -530,6 +530,16 @@ internal static System.Drawing.Bitmap general_Import_16 { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap general_layers_16 { + get { + object obj = ResourceManager.GetObject("general_layers_16", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// diff --git a/TombEditor/Properties/Resources.resx b/TombEditor/Properties/Resources.resx index a2a35232f..3bc505d81 100644 --- a/TombEditor/Properties/Resources.resx +++ b/TombEditor/Properties/Resources.resx @@ -562,4 +562,7 @@ ..\Resources\icons_texture\texture_MirrorPortal-16.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Resources\icons_general\general_layers-16.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + \ No newline at end of file diff --git a/TombEditor/Resources/icons_general/general_layers-16.png b/TombEditor/Resources/icons_general/general_layers-16.png new file mode 100644 index 0000000000000000000000000000000000000000..82aabb5596d1ef2827b4aa4f91fa9ca863731f4e GIT binary patch literal 244 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkP;i;2 zi(^Q|oU4~M@*Xk}VYy(!Qr6+{#lU4-0<)LK%+@B>6`7ZtZYa2BXbAXx3{X*yVVS_K z^5c@}zW?X{zd5}rU(`#6`P7tyoMjmX+!=>%ez}{_Xqp$XP`=RiOyNPX$9j!Y={)yi zjCgFnuI4q{k<@APs7QzD`ZtmJEUWs=SJ-i0N!%Owg}c4M=<1zopr08>j@p#T5? literal 0 HcmV?d00001 From f9815144e37349cb989f619dc2f46ec640477a62 Mon Sep 17 00:00:00 2001 From: Kewin Kupilas Date: Sun, 14 Sep 2025 19:52:07 +0100 Subject: [PATCH 13/19] Remove import --- .../Controls/Panel3D/MouseHandler/Panel3DMouseDown.cs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/TombEditor/Controls/Panel3D/MouseHandler/Panel3DMouseDown.cs b/TombEditor/Controls/Panel3D/MouseHandler/Panel3DMouseDown.cs index afdbe33ef..3cf9270ad 100644 --- a/TombEditor/Controls/Panel3D/MouseHandler/Panel3DMouseDown.cs +++ b/TombEditor/Controls/Panel3D/MouseHandler/Panel3DMouseDown.cs @@ -7,7 +7,6 @@ using TombLib; using TombLib.LevelData.SectorEnums; using TombLib.LevelData.SectorEnums.Extensions; -using TombLib.LevelData.SectorStructs; namespace TombEditor.Controls.Panel3D { @@ -162,19 +161,19 @@ private void OnMouseButtonDownLeft(Point location) { if (ModifierKeys.HasFlag(Keys.Shift)) { - EditorActions.RotateTexture(_editor.SelectedRoom, pos, new FaceLayerInfo(newSectorPicking.Face, _editor.ActiveTextureLayer)); + EditorActions.RotateTexture(_editor.SelectedRoom, pos, new(newSectorPicking.Face, _editor.ActiveTextureLayer)); break; } else if (ModifierKeys.HasFlag(Keys.Control)) { - EditorActions.MirrorTexture(_editor.SelectedRoom, pos, new FaceLayerInfo(newSectorPicking.Face, _editor.ActiveTextureLayer)); + EditorActions.MirrorTexture(_editor.SelectedRoom, pos, new(newSectorPicking.Face, _editor.ActiveTextureLayer)); break; } } if (ModifierKeys.HasFlag(Keys.Alt)) { - EditorActions.PickTexture(_editor.SelectedRoom, pos, new FaceLayerInfo(newSectorPicking.Face, _editor.ActiveTextureLayer)); + EditorActions.PickTexture(_editor.SelectedRoom, pos, new(newSectorPicking.Face, _editor.ActiveTextureLayer)); } else if (_editor.Tool.Tool == EditorToolType.GridPaint && !_editor.HighlightedSectors.Empty) { @@ -213,7 +212,7 @@ private void OnMouseButtonDownLeft(Point location) case EditorToolType.Brush: case EditorToolType.Pencil: - EditorActions.ApplyTexture(_editor.SelectedRoom, pos, new FaceLayerInfo(newSectorPicking.Face, _editor.ActiveTextureLayer), _editor.SelectedTexture); + EditorActions.ApplyTexture(_editor.SelectedRoom, pos, new(newSectorPicking.Face, _editor.ActiveTextureLayer), _editor.SelectedTexture); _toolHandler.Engage(location.X, location.Y, newSectorPicking, false); break; From 49aaf199876d53530389bbbc29d71f1fc2c26151 Mon Sep 17 00:00:00 2001 From: Kewin Kupilas Date: Sun, 14 Sep 2025 20:02:00 +0100 Subject: [PATCH 14/19] Reduce deltas --- TombEditor/Controls/Panel3D/Panel3DDraw.cs | 2 +- TombEditor/Controls/ToolBox.Designer.cs | 578 +++++++++++---------- 2 files changed, 302 insertions(+), 278 deletions(-) diff --git a/TombEditor/Controls/Panel3D/Panel3DDraw.cs b/TombEditor/Controls/Panel3D/Panel3DDraw.cs index 50a7b1dad..8a89025d3 100644 --- a/TombEditor/Controls/Panel3D/Panel3DDraw.cs +++ b/TombEditor/Controls/Panel3D/Panel3DDraw.cs @@ -514,7 +514,7 @@ private void DrawOverlayOutlines(Effect effect) { _overlayOutlineVertices.Clear(); - // Quick check: does this room have any overlays at all? + // Quick check: Does this room have any overlays at all? bool hasOverlays = false; for (int x = currentRoom.LocalArea.X0; x <= currentRoom.LocalArea.X1 && !hasOverlays; x++) diff --git a/TombEditor/Controls/ToolBox.Designer.cs b/TombEditor/Controls/ToolBox.Designer.cs index ef41d2472..f2eae0b5f 100644 --- a/TombEditor/Controls/ToolBox.Designer.cs +++ b/TombEditor/Controls/ToolBox.Designer.cs @@ -28,361 +28,385 @@ protected override void Dispose(bool disposing) /// private void InitializeComponent() { - toolStrip = new DarkUI.Controls.DarkToolStrip(); - toolSelection = new System.Windows.Forms.ToolStripButton(); - toolBrush = new System.Windows.Forms.ToolStripButton(); - toolShovel = new System.Windows.Forms.ToolStripButton(); - toolPencil = new System.Windows.Forms.ToolStripButton(); - toolFlatten = new System.Windows.Forms.ToolStripButton(); - toolSmooth = new System.Windows.Forms.ToolStripButton(); - toolFill = new System.Windows.Forms.ToolStripButton(); - toolGridPaint = new System.Windows.Forms.ToolStripButton(); - toolGroup = new System.Windows.Forms.ToolStripButton(); - toolSeparator1 = new System.Windows.Forms.ToolStripSeparator(); - toolDrag = new System.Windows.Forms.ToolStripButton(); - toolRamp = new System.Windows.Forms.ToolStripButton(); - toolQuarterPipe = new System.Windows.Forms.ToolStripButton(); - toolHalfPipe = new System.Windows.Forms.ToolStripButton(); - toolBowl = new System.Windows.Forms.ToolStripButton(); - toolPyramid = new System.Windows.Forms.ToolStripButton(); - toolTerrain = new System.Windows.Forms.ToolStripButton(); - toolEraser = new System.Windows.Forms.ToolStripButton(); - toolInvisibility = new System.Windows.Forms.ToolStripButton(); - toolSeparator2 = new System.Windows.Forms.ToolStripSeparator(); - toolPortalDigger = new System.Windows.Forms.ToolStripButton(); - toolUVFixer = new System.Windows.Forms.ToolStripButton(); - toolSeparator3 = new System.Windows.Forms.ToolStripSeparator(); - toolOverlayMode = new System.Windows.Forms.ToolStripButton(); - toolStrip.SuspendLayout(); - SuspendLayout(); + this.toolStrip = new DarkUI.Controls.DarkToolStrip(); + this.toolSelection = new System.Windows.Forms.ToolStripButton(); + this.toolBrush = new System.Windows.Forms.ToolStripButton(); + this.toolShovel = new System.Windows.Forms.ToolStripButton(); + this.toolPencil = new System.Windows.Forms.ToolStripButton(); + this.toolFlatten = new System.Windows.Forms.ToolStripButton(); + this.toolSmooth = new System.Windows.Forms.ToolStripButton(); + this.toolFill = new System.Windows.Forms.ToolStripButton(); + this.toolGridPaint = new System.Windows.Forms.ToolStripButton(); + this.toolGroup = new System.Windows.Forms.ToolStripButton(); + this.toolSeparator1 = new System.Windows.Forms.ToolStripSeparator(); + this.toolDrag = new System.Windows.Forms.ToolStripButton(); + this.toolRamp = new System.Windows.Forms.ToolStripButton(); + this.toolQuarterPipe = new System.Windows.Forms.ToolStripButton(); + this.toolHalfPipe = new System.Windows.Forms.ToolStripButton(); + this.toolBowl = new System.Windows.Forms.ToolStripButton(); + this.toolPyramid = new System.Windows.Forms.ToolStripButton(); + this.toolTerrain = new System.Windows.Forms.ToolStripButton(); + this.toolEraser = new System.Windows.Forms.ToolStripButton(); + this.toolInvisibility = new System.Windows.Forms.ToolStripButton(); + this.toolSeparator2 = new System.Windows.Forms.ToolStripSeparator(); + this.toolPortalDigger = new System.Windows.Forms.ToolStripButton(); + this.toolUVFixer = new System.Windows.Forms.ToolStripButton(); + this.toolSeparator3 = new System.Windows.Forms.ToolStripSeparator(); + this.toolOverlayMode = new System.Windows.Forms.ToolStripButton(); + this.toolStrip.SuspendLayout(); + this.SuspendLayout(); // // toolStrip // - toolStrip.AutoSize = false; - toolStrip.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); - toolStrip.CanOverflow = false; - toolStrip.Dock = System.Windows.Forms.DockStyle.Fill; - toolStrip.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); - toolStrip.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden; - toolStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { toolSelection, toolBrush, toolShovel, toolPencil, toolFlatten, toolSmooth, toolFill, toolGridPaint, toolGroup, toolSeparator1, toolDrag, toolRamp, toolQuarterPipe, toolHalfPipe, toolBowl, toolPyramid, toolTerrain, toolEraser, toolInvisibility, toolSeparator2, toolPortalDigger, toolUVFixer, toolSeparator3, toolOverlayMode }); - toolStrip.LayoutStyle = System.Windows.Forms.ToolStripLayoutStyle.VerticalStackWithOverflow; - toolStrip.Location = new System.Drawing.Point(0, 0); - toolStrip.Name = "toolStrip"; - toolStrip.Padding = new System.Windows.Forms.Padding(1, 0, 1, 0); - toolStrip.Size = new System.Drawing.Size(28, 523); - toolStrip.TabIndex = 3; + this.toolStrip.AutoSize = false; + this.toolStrip.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + this.toolStrip.CanOverflow = false; + this.toolStrip.Dock = System.Windows.Forms.DockStyle.Fill; + this.toolStrip.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); + this.toolStrip.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden; + this.toolStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + toolSelection, + toolBrush, + toolShovel, + toolPencil, + toolFlatten, + toolSmooth, + toolFill, + toolGridPaint, + toolGroup, + toolSeparator1, + toolDrag, + toolRamp, + toolQuarterPipe, + toolHalfPipe, + toolBowl, + toolPyramid, + toolTerrain, + toolEraser, + toolInvisibility, + toolSeparator2, + toolPortalDigger, + toolUVFixer, + toolSeparator3, + toolOverlayMode}); + this.toolStrip.LayoutStyle = System.Windows.Forms.ToolStripLayoutStyle.VerticalStackWithOverflow; + this.toolStrip.Location = new System.Drawing.Point(0, 0); + this.toolStrip.Name = "toolStrip"; + this.toolStrip.Padding = new System.Windows.Forms.Padding(1, 0, 1, 0); + this.toolStrip.Size = new System.Drawing.Size(28, 523); + this.toolStrip.TabIndex = 3; // // toolSelection // - toolSelection.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); - toolSelection.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - toolSelection.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); - toolSelection.Image = Properties.Resources.toolbox_Selection_16; - toolSelection.ImageTransparentColor = System.Drawing.Color.Magenta; - toolSelection.Margin = new System.Windows.Forms.Padding(1); - toolSelection.Name = "toolSelection"; - toolSelection.Size = new System.Drawing.Size(23, 20); - toolSelection.ToolTipText = "Selection"; - toolSelection.Click += toolSelection_Click; + this.toolSelection.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + this.toolSelection.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.toolSelection.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); + this.toolSelection.Image = Properties.Resources.toolbox_Selection_16; + this.toolSelection.ImageTransparentColor = System.Drawing.Color.Magenta; + this.toolSelection.Margin = new System.Windows.Forms.Padding(1); + this.toolSelection.Name = "toolSelection"; + this.toolSelection.Size = new System.Drawing.Size(23, 20); + this.toolSelection.ToolTipText = "Selection"; + this.toolSelection.Click += toolSelection_Click; // // toolBrush // - toolBrush.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); - toolBrush.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - toolBrush.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); - toolBrush.Image = Properties.Resources.toolbox_Paint_16; - toolBrush.ImageTransparentColor = System.Drawing.Color.Magenta; - toolBrush.Margin = new System.Windows.Forms.Padding(1); - toolBrush.Name = "toolBrush"; - toolBrush.Size = new System.Drawing.Size(23, 20); - toolBrush.ToolTipText = "Brush"; - toolBrush.Click += toolBrush_Click; + this.toolBrush.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + this.toolBrush.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.toolBrush.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); + this.toolBrush.Image = Properties.Resources.toolbox_Paint_16; + this.toolBrush.ImageTransparentColor = System.Drawing.Color.Magenta; + this.toolBrush.Margin = new System.Windows.Forms.Padding(1); + this.toolBrush.Name = "toolBrush"; + this.toolBrush.Size = new System.Drawing.Size(23, 20); + this.toolBrush.ToolTipText = "Brush"; + this.toolBrush.Click += toolBrush_Click; // // toolShovel // - toolShovel.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); - toolShovel.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - toolShovel.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); - toolShovel.Image = Properties.Resources.toolbox_Shovel_16; - toolShovel.ImageTransparentColor = System.Drawing.Color.Magenta; - toolShovel.Margin = new System.Windows.Forms.Padding(1); - toolShovel.Name = "toolShovel"; - toolShovel.Size = new System.Drawing.Size(23, 20); - toolShovel.ToolTipText = "Shovel"; - toolShovel.Click += toolShovel_Click; + this.toolShovel.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + this.toolShovel.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.toolShovel.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); + this.toolShovel.Image = Properties.Resources.toolbox_Shovel_16; + this.toolShovel.ImageTransparentColor = System.Drawing.Color.Magenta; + this.toolShovel.Margin = new System.Windows.Forms.Padding(1); + this.toolShovel.Name = "toolShovel"; + this.toolShovel.Size = new System.Drawing.Size(23, 20); + this.toolShovel.ToolTipText = "Shovel"; + this.toolShovel.Click += toolShovel_Click; // // toolPencil // - toolPencil.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); - toolPencil.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - toolPencil.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); - toolPencil.Image = Properties.Resources.toolbox_Pencil_16; - toolPencil.ImageTransparentColor = System.Drawing.Color.Magenta; - toolPencil.Margin = new System.Windows.Forms.Padding(1); - toolPencil.Name = "toolPencil"; - toolPencil.Size = new System.Drawing.Size(23, 20); - toolPencil.ToolTipText = "Pencil"; - toolPencil.Click += toolPencil_Click; + this.toolPencil.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + this.toolPencil.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.toolPencil.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); + this.toolPencil.Image = Properties.Resources.toolbox_Pencil_16; + this.toolPencil.ImageTransparentColor = System.Drawing.Color.Magenta; + this.toolPencil.Margin = new System.Windows.Forms.Padding(1); + this.toolPencil.Name = "toolPencil"; + this.toolPencil.Size = new System.Drawing.Size(23, 20); + this.toolPencil.ToolTipText = "Pencil"; + this.toolPencil.Click += toolPencil_Click; // // toolFlatten // - toolFlatten.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); - toolFlatten.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - toolFlatten.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); - toolFlatten.Image = Properties.Resources.toolbox_Bulldozer_1_16; - toolFlatten.ImageTransparentColor = System.Drawing.Color.Magenta; - toolFlatten.Margin = new System.Windows.Forms.Padding(1); - toolFlatten.Name = "toolFlatten"; - toolFlatten.Size = new System.Drawing.Size(23, 20); - toolFlatten.ToolTipText = "Bulldozer"; - toolFlatten.Click += toolFlatten_Click; + this.toolFlatten.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + this.toolFlatten.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.toolFlatten.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); + this.toolFlatten.Image = Properties.Resources.toolbox_Bulldozer_1_16; + this.toolFlatten.ImageTransparentColor = System.Drawing.Color.Magenta; + this.toolFlatten.Margin = new System.Windows.Forms.Padding(1); + this.toolFlatten.Name = "toolFlatten"; + this.toolFlatten.Size = new System.Drawing.Size(23, 20); + this.toolFlatten.ToolTipText = "Bulldozer"; + this.toolFlatten.Click += toolFlatten_Click; // // toolSmooth // - toolSmooth.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); - toolSmooth.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - toolSmooth.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); - toolSmooth.Image = Properties.Resources.toolbox_Smooth_16; - toolSmooth.ImageTransparentColor = System.Drawing.Color.Magenta; - toolSmooth.Margin = new System.Windows.Forms.Padding(1); - toolSmooth.Name = "toolSmooth"; - toolSmooth.Size = new System.Drawing.Size(23, 20); - toolSmooth.ToolTipText = "Smooth"; - toolSmooth.Click += toolSmooth_Click; + this.toolSmooth.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + this.toolSmooth.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.toolSmooth.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); + this.toolSmooth.Image = Properties.Resources.toolbox_Smooth_16; + this.toolSmooth.ImageTransparentColor = System.Drawing.Color.Magenta; + this.toolSmooth.Margin = new System.Windows.Forms.Padding(1); + this.toolSmooth.Name = "toolSmooth"; + this.toolSmooth.Size = new System.Drawing.Size(23, 20); + this.toolSmooth.ToolTipText = "Smooth"; + this.toolSmooth.Click += toolSmooth_Click; // // toolFill // - toolFill.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); - toolFill.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - toolFill.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); - toolFill.Image = Properties.Resources.toolbox_Fill_16; - toolFill.ImageTransparentColor = System.Drawing.Color.Magenta; - toolFill.Margin = new System.Windows.Forms.Padding(1); - toolFill.Name = "toolFill"; - toolFill.Size = new System.Drawing.Size(23, 20); - toolFill.ToolTipText = "Fill"; - toolFill.Click += toolFill_Click; + this.toolFill.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + this.toolFill.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.toolFill.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); + this.toolFill.Image = Properties.Resources.toolbox_Fill_16; + this.toolFill.ImageTransparentColor = System.Drawing.Color.Magenta; + this.toolFill.Margin = new System.Windows.Forms.Padding(1); + this.toolFill.Name = "toolFill"; + this.toolFill.Size = new System.Drawing.Size(23, 20); + this.toolFill.ToolTipText = "Fill"; + this.toolFill.Click += toolFill_Click; // // toolGridPaint // - toolGridPaint.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); - toolGridPaint.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - toolGridPaint.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); - toolGridPaint.Image = Properties.Resources.toolbox_Paint2x2_16; - toolGridPaint.ImageTransparentColor = System.Drawing.Color.Magenta; - toolGridPaint.Margin = new System.Windows.Forms.Padding(1); - toolGridPaint.Name = "toolGridPaint"; - toolGridPaint.Size = new System.Drawing.Size(23, 20); - toolGridPaint.ToolTipText = "Grid Paint (2x2)"; - toolGridPaint.Click += tooPaint2x2_Click; - toolGridPaint.MouseDown += toolGridPaint_MouseDown; - toolGridPaint.MouseUp += toolGridPaint_MouseUp; + this.toolGridPaint.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + this.toolGridPaint.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.toolGridPaint.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); + this.toolGridPaint.Image = Properties.Resources.toolbox_Paint2x2_16; + this.toolGridPaint.ImageTransparentColor = System.Drawing.Color.Magenta; + this.toolGridPaint.Margin = new System.Windows.Forms.Padding(1); + this.toolGridPaint.Name = "toolGridPaint"; + this.toolGridPaint.Size = new System.Drawing.Size(23, 20); + this.toolGridPaint.ToolTipText = "Grid Paint (2x2)"; + this.toolGridPaint.Click += tooPaint2x2_Click; + this.toolGridPaint.MouseDown += toolGridPaint_MouseDown; + this.toolGridPaint.MouseUp += toolGridPaint_MouseUp; // // toolGroup // - toolGroup.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); - toolGroup.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - toolGroup.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); - toolGroup.Image = Properties.Resources.toolbox_GroupTexture_16; - toolGroup.ImageTransparentColor = System.Drawing.Color.Magenta; - toolGroup.Margin = new System.Windows.Forms.Padding(1); - toolGroup.Name = "toolGroup"; - toolGroup.Size = new System.Drawing.Size(23, 20); - toolGroup.ToolTipText = "Group Texturing"; - toolGroup.Click += toolGroup_Click; + this.toolGroup.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + this.toolGroup.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.toolGroup.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); + this.toolGroup.Image = Properties.Resources.toolbox_GroupTexture_16; + this.toolGroup.ImageTransparentColor = System.Drawing.Color.Magenta; + this.toolGroup.Margin = new System.Windows.Forms.Padding(1); + this.toolGroup.Name = "toolGroup"; + this.toolGroup.Size = new System.Drawing.Size(23, 20); + this.toolGroup.ToolTipText = "Group Texturing"; + this.toolGroup.Click += toolGroup_Click; // // toolSeparator1 // - toolSeparator1.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); - toolSeparator1.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); - toolSeparator1.Margin = new System.Windows.Forms.Padding(0, 0, 2, 0); - toolSeparator1.Name = "toolSeparator1"; - toolSeparator1.Size = new System.Drawing.Size(23, 6); + this.toolSeparator1.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + this.toolSeparator1.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); + this.toolSeparator1.Margin = new System.Windows.Forms.Padding(0, 0, 2, 0); + this.toolSeparator1.Name = "toolSeparator1"; + this.toolSeparator1.Size = new System.Drawing.Size(23, 6); // // toolDrag // - toolDrag.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); - toolDrag.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - toolDrag.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); - toolDrag.Image = Properties.Resources.toolbox_Drag_16; - toolDrag.ImageTransparentColor = System.Drawing.Color.Magenta; - toolDrag.Margin = new System.Windows.Forms.Padding(1); - toolDrag.Name = "toolDrag"; - toolDrag.Size = new System.Drawing.Size(23, 20); - toolDrag.ToolTipText = "Drag"; - toolDrag.Click += toolDrag_Click; + this.toolDrag.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + this.toolDrag.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.toolDrag.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); + this.toolDrag.Image = Properties.Resources.toolbox_Drag_16; + this.toolDrag.ImageTransparentColor = System.Drawing.Color.Magenta; + this.toolDrag.Margin = new System.Windows.Forms.Padding(1); + this.toolDrag.Name = "toolDrag"; + this.toolDrag.Size = new System.Drawing.Size(23, 20); + this.toolDrag.ToolTipText = "Drag"; + this.toolDrag.Click += toolDrag_Click; // // toolRamp // - toolRamp.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); - toolRamp.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - toolRamp.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); - toolRamp.Image = Properties.Resources.toolbox_GroupRamp_16; - toolRamp.ImageTransparentColor = System.Drawing.Color.Magenta; - toolRamp.Margin = new System.Windows.Forms.Padding(1); - toolRamp.Name = "toolRamp"; - toolRamp.Size = new System.Drawing.Size(23, 20); - toolRamp.ToolTipText = "Ramp"; - toolRamp.Click += toolRamp_Click; + this.toolRamp.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + this.toolRamp.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.toolRamp.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); + this.toolRamp.Image = Properties.Resources.toolbox_GroupRamp_16; + this.toolRamp.ImageTransparentColor = System.Drawing.Color.Magenta; + this.toolRamp.Margin = new System.Windows.Forms.Padding(1); + this.toolRamp.Name = "toolRamp"; + this.toolRamp.Size = new System.Drawing.Size(23, 20); + this.toolRamp.ToolTipText = "Ramp"; + this.toolRamp.Click += toolRamp_Click; // // toolQuarterPipe // - toolQuarterPipe.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); - toolQuarterPipe.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - toolQuarterPipe.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); - toolQuarterPipe.Image = Properties.Resources.toolbox_GroupQuaterPipe_16; - toolQuarterPipe.ImageTransparentColor = System.Drawing.Color.Magenta; - toolQuarterPipe.Margin = new System.Windows.Forms.Padding(1); - toolQuarterPipe.Name = "toolQuarterPipe"; - toolQuarterPipe.Size = new System.Drawing.Size(23, 20); - toolQuarterPipe.ToolTipText = "Quarter Pipe"; - toolQuarterPipe.Click += toolQuarterPipe_Click; + this.toolQuarterPipe.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + this.toolQuarterPipe.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.toolQuarterPipe.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); + this.toolQuarterPipe.Image = Properties.Resources.toolbox_GroupQuaterPipe_16; + this.toolQuarterPipe.ImageTransparentColor = System.Drawing.Color.Magenta; + this.toolQuarterPipe.Margin = new System.Windows.Forms.Padding(1); + this.toolQuarterPipe.Name = "toolQuarterPipe"; + this.toolQuarterPipe.Size = new System.Drawing.Size(23, 20); + this.toolQuarterPipe.ToolTipText = "Quarter Pipe"; + this.toolQuarterPipe.Click += toolQuarterPipe_Click; // // toolHalfPipe // - toolHalfPipe.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); - toolHalfPipe.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - toolHalfPipe.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); - toolHalfPipe.Image = Properties.Resources.toolbox_GroupHalfPipe_16; - toolHalfPipe.ImageTransparentColor = System.Drawing.Color.Magenta; - toolHalfPipe.Margin = new System.Windows.Forms.Padding(1); - toolHalfPipe.Name = "toolHalfPipe"; - toolHalfPipe.Size = new System.Drawing.Size(23, 20); - toolHalfPipe.ToolTipText = "Half Pipe"; - toolHalfPipe.Click += toolHalfPipe_Click; + this.toolHalfPipe.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + this.toolHalfPipe.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.toolHalfPipe.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); + this.toolHalfPipe.Image = Properties.Resources.toolbox_GroupHalfPipe_16; + this.toolHalfPipe.ImageTransparentColor = System.Drawing.Color.Magenta; + this.toolHalfPipe.Margin = new System.Windows.Forms.Padding(1); + this.toolHalfPipe.Name = "toolHalfPipe"; + this.toolHalfPipe.Size = new System.Drawing.Size(23, 20); + this.toolHalfPipe.ToolTipText = "Half Pipe"; + this.toolHalfPipe.Click += toolHalfPipe_Click; // // toolBowl // - toolBowl.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); - toolBowl.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - toolBowl.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); - toolBowl.Image = Properties.Resources.toolbox_GroupBowl_16; - toolBowl.ImageTransparentColor = System.Drawing.Color.Magenta; - toolBowl.Margin = new System.Windows.Forms.Padding(1); - toolBowl.Name = "toolBowl"; - toolBowl.Size = new System.Drawing.Size(23, 20); - toolBowl.ToolTipText = "Bowl"; - toolBowl.Click += toolBowl_Click; + this.toolBowl.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + this.toolBowl.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.toolBowl.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); + this.toolBowl.Image = Properties.Resources.toolbox_GroupBowl_16; + this.toolBowl.ImageTransparentColor = System.Drawing.Color.Magenta; + this.toolBowl.Margin = new System.Windows.Forms.Padding(1); + this.toolBowl.Name = "toolBowl"; + this.toolBowl.Size = new System.Drawing.Size(23, 20); + this.toolBowl.ToolTipText = "Bowl"; + this.toolBowl.Click += toolBowl_Click; // // toolPyramid // - toolPyramid.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); - toolPyramid.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - toolPyramid.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); - toolPyramid.Image = Properties.Resources.toolbox_GroupPyramid_16; - toolPyramid.ImageTransparentColor = System.Drawing.Color.Magenta; - toolPyramid.Margin = new System.Windows.Forms.Padding(1); - toolPyramid.Name = "toolPyramid"; - toolPyramid.Size = new System.Drawing.Size(23, 20); - toolPyramid.ToolTipText = "Pyramid"; - toolPyramid.Click += toolPyramid_Click; + this.toolPyramid.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + this.toolPyramid.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.toolPyramid.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); + this.toolPyramid.Image = Properties.Resources.toolbox_GroupPyramid_16; + this.toolPyramid.ImageTransparentColor = System.Drawing.Color.Magenta; + this.toolPyramid.Margin = new System.Windows.Forms.Padding(1); + this.toolPyramid.Name = "toolPyramid"; + this.toolPyramid.Size = new System.Drawing.Size(23, 20); + this.toolPyramid.ToolTipText = "Pyramid"; + this.toolPyramid.Click += toolPyramid_Click; // // toolTerrain // - toolTerrain.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); - toolTerrain.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - toolTerrain.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); - toolTerrain.Image = Properties.Resources.toolbox_GroupTerrain_16; - toolTerrain.ImageTransparentColor = System.Drawing.Color.Magenta; - toolTerrain.Margin = new System.Windows.Forms.Padding(1); - toolTerrain.Name = "toolTerrain"; - toolTerrain.Size = new System.Drawing.Size(23, 20); - toolTerrain.ToolTipText = "Terrain"; - toolTerrain.Click += toolTerrain_Click; + this.toolTerrain.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + this.toolTerrain.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.toolTerrain.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); + this.toolTerrain.Image = Properties.Resources.toolbox_GroupTerrain_16; + this.toolTerrain.ImageTransparentColor = System.Drawing.Color.Magenta; + this.toolTerrain.Margin = new System.Windows.Forms.Padding(1); + this.toolTerrain.Name = "toolTerrain"; + this.toolTerrain.Size = new System.Drawing.Size(23, 20); + this.toolTerrain.ToolTipText = "Terrain"; + this.toolTerrain.Click += toolTerrain_Click; // // toolEraser // - toolEraser.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); - toolEraser.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - toolEraser.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); - toolEraser.Image = Properties.Resources.toolbox_Eraser_16; - toolEraser.ImageTransparentColor = System.Drawing.Color.Magenta; - toolEraser.Margin = new System.Windows.Forms.Padding(1); - toolEraser.Name = "toolEraser"; - toolEraser.Size = new System.Drawing.Size(23, 20); - toolEraser.ToolTipText = "Eraser"; - toolEraser.Click += toolEraser_Click; + this.toolEraser.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + this.toolEraser.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.toolEraser.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); + this.toolEraser.Image = Properties.Resources.toolbox_Eraser_16; + this.toolEraser.ImageTransparentColor = System.Drawing.Color.Magenta; + this.toolEraser.Margin = new System.Windows.Forms.Padding(1); + this.toolEraser.Name = "toolEraser"; + this.toolEraser.Size = new System.Drawing.Size(23, 20); + this.toolEraser.ToolTipText = "Eraser"; + this.toolEraser.Click += toolEraser_Click; // // toolInvisibility // - toolInvisibility.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); - toolInvisibility.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - toolInvisibility.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); - toolInvisibility.Image = Properties.Resources.toolbox_Invisible_16; - toolInvisibility.ImageTransparentColor = System.Drawing.Color.Magenta; - toolInvisibility.Margin = new System.Windows.Forms.Padding(1); - toolInvisibility.Name = "toolInvisibility"; - toolInvisibility.Size = new System.Drawing.Size(23, 20); - toolInvisibility.ToolTipText = "Invisibility"; - toolInvisibility.Click += toolInvisibility_Click; + this.toolInvisibility.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + this.toolInvisibility.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.toolInvisibility.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); + this.toolInvisibility.Image = Properties.Resources.toolbox_Invisible_16; + this.toolInvisibility.ImageTransparentColor = System.Drawing.Color.Magenta; + this.toolInvisibility.Margin = new System.Windows.Forms.Padding(1); + this.toolInvisibility.Name = "toolInvisibility"; + this.toolInvisibility.Size = new System.Drawing.Size(23, 20); + this.toolInvisibility.ToolTipText = "Invisibility"; + this.toolInvisibility.Click += toolInvisibility_Click; // // toolSeparator2 // - toolSeparator2.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); - toolSeparator2.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); - toolSeparator2.Margin = new System.Windows.Forms.Padding(0, 0, 2, 0); - toolSeparator2.Name = "toolSeparator2"; - toolSeparator2.Size = new System.Drawing.Size(23, 6); + this.toolSeparator2.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + this.toolSeparator2.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); + this.toolSeparator2.Margin = new System.Windows.Forms.Padding(0, 0, 2, 0); + this.toolSeparator2.Name = "toolSeparator2"; + this.toolSeparator2.Size = new System.Drawing.Size(23, 6); // // toolPortalDigger // - toolPortalDigger.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); - toolPortalDigger.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - toolPortalDigger.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); - toolPortalDigger.Image = Properties.Resources.toolbox_PortalDigger_16; - toolPortalDigger.ImageTransparentColor = System.Drawing.Color.Magenta; - toolPortalDigger.Margin = new System.Windows.Forms.Padding(1); - toolPortalDigger.Name = "toolPortalDigger"; - toolPortalDigger.Size = new System.Drawing.Size(23, 20); - toolPortalDigger.ToolTipText = "Portal Digger"; - toolPortalDigger.Click += toolPortalDigger_Click; + this.toolPortalDigger.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + this.toolPortalDigger.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.toolPortalDigger.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); + this.toolPortalDigger.Image = Properties.Resources.toolbox_PortalDigger_16; + this.toolPortalDigger.ImageTransparentColor = System.Drawing.Color.Magenta; + this.toolPortalDigger.Margin = new System.Windows.Forms.Padding(1); + this.toolPortalDigger.Name = "toolPortalDigger"; + this.toolPortalDigger.Size = new System.Drawing.Size(23, 20); + this.toolPortalDigger.ToolTipText = "Portal Digger"; + this.toolPortalDigger.Click += toolPortalDigger_Click; // // toolUVFixer // - toolUVFixer.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); - toolUVFixer.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - toolUVFixer.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); - toolUVFixer.Image = Properties.Resources.toolbox_UVFixer_16; - toolUVFixer.ImageTransparentColor = System.Drawing.Color.Magenta; - toolUVFixer.Margin = new System.Windows.Forms.Padding(1); - toolUVFixer.Name = "toolUVFixer"; - toolUVFixer.Size = new System.Drawing.Size(23, 20); - toolUVFixer.ToolTipText = "Fix texture coordinates"; - toolUVFixer.Click += toolUVFixer_Click; + this.toolUVFixer.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + this.toolUVFixer.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.toolUVFixer.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); + this.toolUVFixer.Image = Properties.Resources.toolbox_UVFixer_16; + this.toolUVFixer.ImageTransparentColor = System.Drawing.Color.Magenta; + this.toolUVFixer.Margin = new System.Windows.Forms.Padding(1); + this.toolUVFixer.Name = "toolUVFixer"; + this.toolUVFixer.Size = new System.Drawing.Size(23, 20); + this.toolUVFixer.ToolTipText = "Fix texture coordinates"; + this.toolUVFixer.Click += toolUVFixer_Click; // // toolSeparator3 // - toolSeparator3.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); - toolSeparator3.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); - toolSeparator3.Margin = new System.Windows.Forms.Padding(0, 0, 2, 0); - toolSeparator3.Name = "toolSeparator3"; - toolSeparator3.Size = new System.Drawing.Size(23, 6); + this.toolSeparator3.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + this.toolSeparator3.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); + this.toolSeparator3.Margin = new System.Windows.Forms.Padding(0, 0, 2, 0); + this.toolSeparator3.Name = "toolSeparator3"; + this.toolSeparator3.Size = new System.Drawing.Size(23, 6); // // toolOverlayMode // - toolOverlayMode.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); - toolOverlayMode.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - toolOverlayMode.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); - toolOverlayMode.Image = Properties.Resources.general_layers_16; - toolOverlayMode.ImageTransparentColor = System.Drawing.Color.Magenta; - toolOverlayMode.Margin = new System.Windows.Forms.Padding(1); - toolOverlayMode.Name = "toolOverlayMode"; - toolOverlayMode.Size = new System.Drawing.Size(23, 20); - toolOverlayMode.ToolTipText = "Toggle overlay mode"; - toolOverlayMode.Click += toolOverlayMode_Click; + this.toolOverlayMode.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + this.toolOverlayMode.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.toolOverlayMode.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); + this.toolOverlayMode.Image = Properties.Resources.general_layers_16; + this.toolOverlayMode.ImageTransparentColor = System.Drawing.Color.Magenta; + this.toolOverlayMode.Margin = new System.Windows.Forms.Padding(1); + this.toolOverlayMode.Name = "toolOverlayMode"; + this.toolOverlayMode.Size = new System.Drawing.Size(23, 20); + this.toolOverlayMode.ToolTipText = "Toggle overlay mode"; + this.toolOverlayMode.Click += toolOverlayMode_Click; // // ToolBox // - AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); - AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; - Controls.Add(toolStrip); - Margin = new System.Windows.Forms.Padding(0); - Name = "ToolBox"; - Size = new System.Drawing.Size(28, 523); - toolStrip.ResumeLayout(false); - toolStrip.PerformLayout(); - ResumeLayout(false); + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; + this.Controls.Add(toolStrip); + this.Margin = new System.Windows.Forms.Padding(0); + this.Name = "ToolBox"; + this.Size = new System.Drawing.Size(28, 523); + this.toolStrip.ResumeLayout(false); + this.toolStrip.PerformLayout(); + this.ResumeLayout(false); } #endregion From a4c11b0aee429f9bad24406ebe23bb02f30ae290 Mon Sep 17 00:00:00 2001 From: Kewin Kupilas Date: Sun, 14 Sep 2025 20:08:45 +0100 Subject: [PATCH 15/19] Reduce deltas even more --- TombEditor/Controls/ToolBox.Designer.cs | 238 ++++++++++++------------ 1 file changed, 119 insertions(+), 119 deletions(-) diff --git a/TombEditor/Controls/ToolBox.Designer.cs b/TombEditor/Controls/ToolBox.Designer.cs index f2eae0b5f..8dbb13b7a 100644 --- a/TombEditor/Controls/ToolBox.Designer.cs +++ b/TombEditor/Controls/ToolBox.Designer.cs @@ -59,36 +59,36 @@ private void InitializeComponent() // toolStrip // this.toolStrip.AutoSize = false; - this.toolStrip.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + this.toolStrip.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(60)))), ((int)(((byte)(63)))), ((int)(((byte)(65))))); this.toolStrip.CanOverflow = false; this.toolStrip.Dock = System.Windows.Forms.DockStyle.Fill; - this.toolStrip.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); + this.toolStrip.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(220)))), ((int)(((byte)(220))))); this.toolStrip.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden; this.toolStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { - toolSelection, - toolBrush, - toolShovel, - toolPencil, - toolFlatten, - toolSmooth, - toolFill, - toolGridPaint, - toolGroup, - toolSeparator1, - toolDrag, - toolRamp, - toolQuarterPipe, - toolHalfPipe, - toolBowl, - toolPyramid, - toolTerrain, - toolEraser, - toolInvisibility, - toolSeparator2, - toolPortalDigger, - toolUVFixer, - toolSeparator3, - toolOverlayMode}); + this.toolSelection, + this.toolBrush, + this.toolShovel, + this.toolPencil, + this.toolFlatten, + this.toolSmooth, + this.toolFill, + this.toolGridPaint, + this.toolGroup, + this.toolSeparator1, + this.toolDrag, + this.toolRamp, + this.toolQuarterPipe, + this.toolHalfPipe, + this.toolBowl, + this.toolPyramid, + this.toolTerrain, + this.toolEraser, + this.toolInvisibility, + this.toolSeparator2, + this.toolPortalDigger, + this.toolUVFixer, + this.toolSeparator3, + this.toolOverlayMode}); this.toolStrip.LayoutStyle = System.Windows.Forms.ToolStripLayoutStyle.VerticalStackWithOverflow; this.toolStrip.Location = new System.Drawing.Point(0, 0); this.toolStrip.Name = "toolStrip"; @@ -98,309 +98,309 @@ private void InitializeComponent() // // toolSelection // - this.toolSelection.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + this.toolSelection.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(60)))), ((int)(((byte)(63)))), ((int)(((byte)(65))))); this.toolSelection.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.toolSelection.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); - this.toolSelection.Image = Properties.Resources.toolbox_Selection_16; + this.toolSelection.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(220)))), ((int)(((byte)(220))))); + this.toolSelection.Image = global::TombEditor.Properties.Resources.toolbox_Selection_16; this.toolSelection.ImageTransparentColor = System.Drawing.Color.Magenta; this.toolSelection.Margin = new System.Windows.Forms.Padding(1); this.toolSelection.Name = "toolSelection"; this.toolSelection.Size = new System.Drawing.Size(23, 20); this.toolSelection.ToolTipText = "Selection"; - this.toolSelection.Click += toolSelection_Click; + this.toolSelection.Click += new System.EventHandler(this.toolSelection_Click); // // toolBrush // - this.toolBrush.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + this.toolBrush.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(60)))), ((int)(((byte)(63)))), ((int)(((byte)(65))))); this.toolBrush.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.toolBrush.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); - this.toolBrush.Image = Properties.Resources.toolbox_Paint_16; + this.toolBrush.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(220)))), ((int)(((byte)(220))))); + this.toolBrush.Image = global::TombEditor.Properties.Resources.toolbox_Paint_16; this.toolBrush.ImageTransparentColor = System.Drawing.Color.Magenta; this.toolBrush.Margin = new System.Windows.Forms.Padding(1); this.toolBrush.Name = "toolBrush"; this.toolBrush.Size = new System.Drawing.Size(23, 20); this.toolBrush.ToolTipText = "Brush"; - this.toolBrush.Click += toolBrush_Click; + this.toolBrush.Click += new System.EventHandler(this.toolBrush_Click); // // toolShovel // - this.toolShovel.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + this.toolShovel.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(60)))), ((int)(((byte)(63)))), ((int)(((byte)(65))))); this.toolShovel.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.toolShovel.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); - this.toolShovel.Image = Properties.Resources.toolbox_Shovel_16; + this.toolShovel.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(220)))), ((int)(((byte)(220))))); + this.toolShovel.Image = global::TombEditor.Properties.Resources.toolbox_Shovel_16; this.toolShovel.ImageTransparentColor = System.Drawing.Color.Magenta; this.toolShovel.Margin = new System.Windows.Forms.Padding(1); this.toolShovel.Name = "toolShovel"; this.toolShovel.Size = new System.Drawing.Size(23, 20); this.toolShovel.ToolTipText = "Shovel"; - this.toolShovel.Click += toolShovel_Click; + this.toolShovel.Click += new System.EventHandler(this.toolShovel_Click); // // toolPencil // - this.toolPencil.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + this.toolPencil.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(60)))), ((int)(((byte)(63)))), ((int)(((byte)(65))))); this.toolPencil.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.toolPencil.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); - this.toolPencil.Image = Properties.Resources.toolbox_Pencil_16; + this.toolPencil.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(220)))), ((int)(((byte)(220))))); + this.toolPencil.Image = global::TombEditor.Properties.Resources.toolbox_Pencil_16; this.toolPencil.ImageTransparentColor = System.Drawing.Color.Magenta; this.toolPencil.Margin = new System.Windows.Forms.Padding(1); this.toolPencil.Name = "toolPencil"; this.toolPencil.Size = new System.Drawing.Size(23, 20); this.toolPencil.ToolTipText = "Pencil"; - this.toolPencil.Click += toolPencil_Click; + this.toolPencil.Click += new System.EventHandler(this.toolPencil_Click); // // toolFlatten // - this.toolFlatten.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + this.toolFlatten.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(60)))), ((int)(((byte)(63)))), ((int)(((byte)(65))))); this.toolFlatten.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.toolFlatten.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); - this.toolFlatten.Image = Properties.Resources.toolbox_Bulldozer_1_16; + this.toolFlatten.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(220)))), ((int)(((byte)(220))))); + this.toolFlatten.Image = global::TombEditor.Properties.Resources.toolbox_Bulldozer_1_16; this.toolFlatten.ImageTransparentColor = System.Drawing.Color.Magenta; this.toolFlatten.Margin = new System.Windows.Forms.Padding(1); this.toolFlatten.Name = "toolFlatten"; this.toolFlatten.Size = new System.Drawing.Size(23, 20); this.toolFlatten.ToolTipText = "Bulldozer"; - this.toolFlatten.Click += toolFlatten_Click; + this.toolFlatten.Click += new System.EventHandler(this.toolFlatten_Click); // // toolSmooth // - this.toolSmooth.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + this.toolSmooth.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(60)))), ((int)(((byte)(63)))), ((int)(((byte)(65))))); this.toolSmooth.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.toolSmooth.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); - this.toolSmooth.Image = Properties.Resources.toolbox_Smooth_16; + this.toolSmooth.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(220)))), ((int)(((byte)(220))))); + this.toolSmooth.Image = global::TombEditor.Properties.Resources.toolbox_Smooth_16; this.toolSmooth.ImageTransparentColor = System.Drawing.Color.Magenta; this.toolSmooth.Margin = new System.Windows.Forms.Padding(1); this.toolSmooth.Name = "toolSmooth"; this.toolSmooth.Size = new System.Drawing.Size(23, 20); this.toolSmooth.ToolTipText = "Smooth"; - this.toolSmooth.Click += toolSmooth_Click; + this.toolSmooth.Click += new System.EventHandler(this.toolSmooth_Click); // // toolFill // - this.toolFill.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + this.toolFill.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(60)))), ((int)(((byte)(63)))), ((int)(((byte)(65))))); this.toolFill.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.toolFill.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); - this.toolFill.Image = Properties.Resources.toolbox_Fill_16; + this.toolFill.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(220)))), ((int)(((byte)(220))))); + this.toolFill.Image = global::TombEditor.Properties.Resources.toolbox_Fill_16; this.toolFill.ImageTransparentColor = System.Drawing.Color.Magenta; this.toolFill.Margin = new System.Windows.Forms.Padding(1); this.toolFill.Name = "toolFill"; this.toolFill.Size = new System.Drawing.Size(23, 20); this.toolFill.ToolTipText = "Fill"; - this.toolFill.Click += toolFill_Click; + this.toolFill.Click += new System.EventHandler(this.toolFill_Click); // // toolGridPaint // - this.toolGridPaint.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + this.toolGridPaint.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(60)))), ((int)(((byte)(63)))), ((int)(((byte)(65))))); this.toolGridPaint.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.toolGridPaint.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); - this.toolGridPaint.Image = Properties.Resources.toolbox_Paint2x2_16; + this.toolGridPaint.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(220)))), ((int)(((byte)(220))))); + this.toolGridPaint.Image = global::TombEditor.Properties.Resources.toolbox_Paint2x2_16; this.toolGridPaint.ImageTransparentColor = System.Drawing.Color.Magenta; this.toolGridPaint.Margin = new System.Windows.Forms.Padding(1); this.toolGridPaint.Name = "toolGridPaint"; this.toolGridPaint.Size = new System.Drawing.Size(23, 20); this.toolGridPaint.ToolTipText = "Grid Paint (2x2)"; - this.toolGridPaint.Click += tooPaint2x2_Click; - this.toolGridPaint.MouseDown += toolGridPaint_MouseDown; - this.toolGridPaint.MouseUp += toolGridPaint_MouseUp; + this.toolGridPaint.Click += new System.EventHandler(this.tooPaint2x2_Click); + this.toolGridPaint.MouseDown += new System.Windows.Forms.MouseEventHandler(this.toolGridPaint_MouseDown); + this.toolGridPaint.MouseUp += new System.Windows.Forms.MouseEventHandler(this.toolGridPaint_MouseUp); // // toolGroup // - this.toolGroup.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + this.toolGroup.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(60)))), ((int)(((byte)(63)))), ((int)(((byte)(65))))); this.toolGroup.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.toolGroup.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); - this.toolGroup.Image = Properties.Resources.toolbox_GroupTexture_16; + this.toolGroup.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(220)))), ((int)(((byte)(220))))); + this.toolGroup.Image = global::TombEditor.Properties.Resources.toolbox_GroupTexture_16; this.toolGroup.ImageTransparentColor = System.Drawing.Color.Magenta; this.toolGroup.Margin = new System.Windows.Forms.Padding(1); this.toolGroup.Name = "toolGroup"; this.toolGroup.Size = new System.Drawing.Size(23, 20); this.toolGroup.ToolTipText = "Group Texturing"; - this.toolGroup.Click += toolGroup_Click; + this.toolGroup.Click += new System.EventHandler(this.toolGroup_Click); // // toolSeparator1 // - this.toolSeparator1.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); - this.toolSeparator1.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); + this.toolSeparator1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(60)))), ((int)(((byte)(63)))), ((int)(((byte)(65))))); + this.toolSeparator1.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(220)))), ((int)(((byte)(220))))); this.toolSeparator1.Margin = new System.Windows.Forms.Padding(0, 0, 2, 0); this.toolSeparator1.Name = "toolSeparator1"; this.toolSeparator1.Size = new System.Drawing.Size(23, 6); // // toolDrag // - this.toolDrag.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + this.toolDrag.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(60)))), ((int)(((byte)(63)))), ((int)(((byte)(65))))); this.toolDrag.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.toolDrag.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); - this.toolDrag.Image = Properties.Resources.toolbox_Drag_16; + this.toolDrag.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(220)))), ((int)(((byte)(220))))); + this.toolDrag.Image = global::TombEditor.Properties.Resources.toolbox_Drag_16; this.toolDrag.ImageTransparentColor = System.Drawing.Color.Magenta; this.toolDrag.Margin = new System.Windows.Forms.Padding(1); this.toolDrag.Name = "toolDrag"; this.toolDrag.Size = new System.Drawing.Size(23, 20); this.toolDrag.ToolTipText = "Drag"; - this.toolDrag.Click += toolDrag_Click; + this.toolDrag.Click += new System.EventHandler(this.toolDrag_Click); // // toolRamp // - this.toolRamp.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + this.toolRamp.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(60)))), ((int)(((byte)(63)))), ((int)(((byte)(65))))); this.toolRamp.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.toolRamp.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); - this.toolRamp.Image = Properties.Resources.toolbox_GroupRamp_16; + this.toolRamp.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(220)))), ((int)(((byte)(220))))); + this.toolRamp.Image = global::TombEditor.Properties.Resources.toolbox_GroupRamp_16; this.toolRamp.ImageTransparentColor = System.Drawing.Color.Magenta; this.toolRamp.Margin = new System.Windows.Forms.Padding(1); this.toolRamp.Name = "toolRamp"; this.toolRamp.Size = new System.Drawing.Size(23, 20); this.toolRamp.ToolTipText = "Ramp"; - this.toolRamp.Click += toolRamp_Click; + this.toolRamp.Click += new System.EventHandler(this.toolRamp_Click); // // toolQuarterPipe // - this.toolQuarterPipe.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + this.toolQuarterPipe.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(60)))), ((int)(((byte)(63)))), ((int)(((byte)(65))))); this.toolQuarterPipe.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.toolQuarterPipe.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); - this.toolQuarterPipe.Image = Properties.Resources.toolbox_GroupQuaterPipe_16; + this.toolQuarterPipe.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(220)))), ((int)(((byte)(220))))); + this.toolQuarterPipe.Image = global::TombEditor.Properties.Resources.toolbox_GroupQuaterPipe_16; this.toolQuarterPipe.ImageTransparentColor = System.Drawing.Color.Magenta; this.toolQuarterPipe.Margin = new System.Windows.Forms.Padding(1); this.toolQuarterPipe.Name = "toolQuarterPipe"; this.toolQuarterPipe.Size = new System.Drawing.Size(23, 20); this.toolQuarterPipe.ToolTipText = "Quarter Pipe"; - this.toolQuarterPipe.Click += toolQuarterPipe_Click; + this.toolQuarterPipe.Click += new System.EventHandler(this.toolQuarterPipe_Click); // // toolHalfPipe // - this.toolHalfPipe.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + this.toolHalfPipe.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(60)))), ((int)(((byte)(63)))), ((int)(((byte)(65))))); this.toolHalfPipe.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.toolHalfPipe.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); - this.toolHalfPipe.Image = Properties.Resources.toolbox_GroupHalfPipe_16; + this.toolHalfPipe.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(220)))), ((int)(((byte)(220))))); + this.toolHalfPipe.Image = global::TombEditor.Properties.Resources.toolbox_GroupHalfPipe_16; this.toolHalfPipe.ImageTransparentColor = System.Drawing.Color.Magenta; this.toolHalfPipe.Margin = new System.Windows.Forms.Padding(1); this.toolHalfPipe.Name = "toolHalfPipe"; this.toolHalfPipe.Size = new System.Drawing.Size(23, 20); this.toolHalfPipe.ToolTipText = "Half Pipe"; - this.toolHalfPipe.Click += toolHalfPipe_Click; + this.toolHalfPipe.Click += new System.EventHandler(this.toolHalfPipe_Click); // // toolBowl // - this.toolBowl.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + this.toolBowl.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(60)))), ((int)(((byte)(63)))), ((int)(((byte)(65))))); this.toolBowl.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.toolBowl.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); - this.toolBowl.Image = Properties.Resources.toolbox_GroupBowl_16; + this.toolBowl.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(220)))), ((int)(((byte)(220))))); + this.toolBowl.Image = global::TombEditor.Properties.Resources.toolbox_GroupBowl_16; this.toolBowl.ImageTransparentColor = System.Drawing.Color.Magenta; this.toolBowl.Margin = new System.Windows.Forms.Padding(1); this.toolBowl.Name = "toolBowl"; this.toolBowl.Size = new System.Drawing.Size(23, 20); this.toolBowl.ToolTipText = "Bowl"; - this.toolBowl.Click += toolBowl_Click; + this.toolBowl.Click += new System.EventHandler(this.toolBowl_Click); // // toolPyramid // - this.toolPyramid.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + this.toolPyramid.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(60)))), ((int)(((byte)(63)))), ((int)(((byte)(65))))); this.toolPyramid.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.toolPyramid.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); - this.toolPyramid.Image = Properties.Resources.toolbox_GroupPyramid_16; + this.toolPyramid.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(220)))), ((int)(((byte)(220))))); + this.toolPyramid.Image = global::TombEditor.Properties.Resources.toolbox_GroupPyramid_16; this.toolPyramid.ImageTransparentColor = System.Drawing.Color.Magenta; this.toolPyramid.Margin = new System.Windows.Forms.Padding(1); this.toolPyramid.Name = "toolPyramid"; this.toolPyramid.Size = new System.Drawing.Size(23, 20); this.toolPyramid.ToolTipText = "Pyramid"; - this.toolPyramid.Click += toolPyramid_Click; + this.toolPyramid.Click += new System.EventHandler(this.toolPyramid_Click); // // toolTerrain // - this.toolTerrain.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + this.toolTerrain.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(60)))), ((int)(((byte)(63)))), ((int)(((byte)(65))))); this.toolTerrain.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.toolTerrain.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); - this.toolTerrain.Image = Properties.Resources.toolbox_GroupTerrain_16; + this.toolTerrain.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(220)))), ((int)(((byte)(220))))); + this.toolTerrain.Image = global::TombEditor.Properties.Resources.toolbox_GroupTerrain_16; this.toolTerrain.ImageTransparentColor = System.Drawing.Color.Magenta; this.toolTerrain.Margin = new System.Windows.Forms.Padding(1); this.toolTerrain.Name = "toolTerrain"; this.toolTerrain.Size = new System.Drawing.Size(23, 20); this.toolTerrain.ToolTipText = "Terrain"; - this.toolTerrain.Click += toolTerrain_Click; + this.toolTerrain.Click += new System.EventHandler(this.toolTerrain_Click); // // toolEraser // - this.toolEraser.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + this.toolEraser.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(60)))), ((int)(((byte)(63)))), ((int)(((byte)(65))))); this.toolEraser.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.toolEraser.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); - this.toolEraser.Image = Properties.Resources.toolbox_Eraser_16; + this.toolEraser.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(220)))), ((int)(((byte)(220))))); + this.toolEraser.Image = global::TombEditor.Properties.Resources.toolbox_Eraser_16; this.toolEraser.ImageTransparentColor = System.Drawing.Color.Magenta; this.toolEraser.Margin = new System.Windows.Forms.Padding(1); this.toolEraser.Name = "toolEraser"; this.toolEraser.Size = new System.Drawing.Size(23, 20); this.toolEraser.ToolTipText = "Eraser"; - this.toolEraser.Click += toolEraser_Click; + this.toolEraser.Click += new System.EventHandler(this.toolEraser_Click); // // toolInvisibility // - this.toolInvisibility.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + this.toolInvisibility.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(60)))), ((int)(((byte)(63)))), ((int)(((byte)(65))))); this.toolInvisibility.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.toolInvisibility.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); - this.toolInvisibility.Image = Properties.Resources.toolbox_Invisible_16; + this.toolInvisibility.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(220)))), ((int)(((byte)(220))))); + this.toolInvisibility.Image = global::TombEditor.Properties.Resources.toolbox_Invisible_16; this.toolInvisibility.ImageTransparentColor = System.Drawing.Color.Magenta; this.toolInvisibility.Margin = new System.Windows.Forms.Padding(1); this.toolInvisibility.Name = "toolInvisibility"; this.toolInvisibility.Size = new System.Drawing.Size(23, 20); this.toolInvisibility.ToolTipText = "Invisibility"; - this.toolInvisibility.Click += toolInvisibility_Click; + this.toolInvisibility.Click += new System.EventHandler(this.toolInvisibility_Click); // // toolSeparator2 // - this.toolSeparator2.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); - this.toolSeparator2.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); + this.toolSeparator2.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(60)))), ((int)(((byte)(63)))), ((int)(((byte)(65))))); + this.toolSeparator2.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(220)))), ((int)(((byte)(220))))); this.toolSeparator2.Margin = new System.Windows.Forms.Padding(0, 0, 2, 0); this.toolSeparator2.Name = "toolSeparator2"; this.toolSeparator2.Size = new System.Drawing.Size(23, 6); // // toolPortalDigger // - this.toolPortalDigger.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + this.toolPortalDigger.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(60)))), ((int)(((byte)(63)))), ((int)(((byte)(65))))); this.toolPortalDigger.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.toolPortalDigger.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); - this.toolPortalDigger.Image = Properties.Resources.toolbox_PortalDigger_16; + this.toolPortalDigger.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(220)))), ((int)(((byte)(220))))); + this.toolPortalDigger.Image = global::TombEditor.Properties.Resources.toolbox_PortalDigger_16; this.toolPortalDigger.ImageTransparentColor = System.Drawing.Color.Magenta; this.toolPortalDigger.Margin = new System.Windows.Forms.Padding(1); this.toolPortalDigger.Name = "toolPortalDigger"; this.toolPortalDigger.Size = new System.Drawing.Size(23, 20); this.toolPortalDigger.ToolTipText = "Portal Digger"; - this.toolPortalDigger.Click += toolPortalDigger_Click; + this.toolPortalDigger.Click += new System.EventHandler(this.toolPortalDigger_Click); // // toolUVFixer // - this.toolUVFixer.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + this.toolUVFixer.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(60)))), ((int)(((byte)(63)))), ((int)(((byte)(65))))); this.toolUVFixer.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.toolUVFixer.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); - this.toolUVFixer.Image = Properties.Resources.toolbox_UVFixer_16; + this.toolUVFixer.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(220)))), ((int)(((byte)(220))))); + this.toolUVFixer.Image = global::TombEditor.Properties.Resources.toolbox_UVFixer_16; this.toolUVFixer.ImageTransparentColor = System.Drawing.Color.Magenta; this.toolUVFixer.Margin = new System.Windows.Forms.Padding(1); this.toolUVFixer.Name = "toolUVFixer"; this.toolUVFixer.Size = new System.Drawing.Size(23, 20); this.toolUVFixer.ToolTipText = "Fix texture coordinates"; - this.toolUVFixer.Click += toolUVFixer_Click; + this.toolUVFixer.Click += new System.EventHandler(this.toolUVFixer_Click); // // toolSeparator3 // - this.toolSeparator3.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); - this.toolSeparator3.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); + this.toolSeparator3.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(60)))), ((int)(((byte)(63)))), ((int)(((byte)(65))))); + this.toolSeparator3.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(220)))), ((int)(((byte)(220))))); this.toolSeparator3.Margin = new System.Windows.Forms.Padding(0, 0, 2, 0); this.toolSeparator3.Name = "toolSeparator3"; this.toolSeparator3.Size = new System.Drawing.Size(23, 6); // // toolOverlayMode // - this.toolOverlayMode.BackColor = System.Drawing.Color.FromArgb(60, 63, 65); + this.toolOverlayMode.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(60)))), ((int)(((byte)(63)))), ((int)(((byte)(65))))); this.toolOverlayMode.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.toolOverlayMode.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); - this.toolOverlayMode.Image = Properties.Resources.general_layers_16; + this.toolOverlayMode.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(220)))), ((int)(((byte)(220))))); + this.toolOverlayMode.Image = global::TombEditor.Properties.Resources.general_layers_16; this.toolOverlayMode.ImageTransparentColor = System.Drawing.Color.Magenta; this.toolOverlayMode.Margin = new System.Windows.Forms.Padding(1); this.toolOverlayMode.Name = "toolOverlayMode"; this.toolOverlayMode.Size = new System.Drawing.Size(23, 20); this.toolOverlayMode.ToolTipText = "Toggle overlay mode"; - this.toolOverlayMode.Click += toolOverlayMode_Click; + this.toolOverlayMode.Click += new System.EventHandler(this.toolOverlayMode_Click); // // ToolBox // this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; - this.Controls.Add(toolStrip); + this.Controls.Add(this.toolStrip); this.Margin = new System.Windows.Forms.Padding(0); this.Name = "ToolBox"; this.Size = new System.Drawing.Size(28, 523); From e1f169c46ddbd5b6ce865f9e69f2b6472f0167c9 Mon Sep 17 00:00:00 2001 From: Kewin Kupilas Date: Sun, 14 Sep 2025 20:10:52 +0100 Subject: [PATCH 16/19] Restore whitespace --- TombEditor/Controls/ToolBox.Designer.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/TombEditor/Controls/ToolBox.Designer.cs b/TombEditor/Controls/ToolBox.Designer.cs index 8dbb13b7a..5e07095de 100644 --- a/TombEditor/Controls/ToolBox.Designer.cs +++ b/TombEditor/Controls/ToolBox.Designer.cs @@ -407,6 +407,7 @@ private void InitializeComponent() this.toolStrip.ResumeLayout(false); this.toolStrip.PerformLayout(); this.ResumeLayout(false); + } #endregion From 268753d20684c63ee65579d2bba41e932b225db9 Mon Sep 17 00:00:00 2001 From: Kewin Kupilas Date: Sun, 14 Sep 2025 20:12:56 +0100 Subject: [PATCH 17/19] Rename method --- TombEditor/EditorActions.cs | 2 +- TombEditor/Forms/FormTextureRemap.cs | 2 +- TombEditor/SectorsClipboardData.cs | 2 +- TombLib/TombLib/GeometryIO/RoomGeometryExporter.cs | 4 ++-- TombLib/TombLib/LevelData/Compilers/Rooms.cs | 2 +- TombLib/TombLib/LevelData/Compilers/TombEngine/Rooms.cs | 2 +- TombLib/TombLib/LevelData/IO/Prj2Writer.cs | 2 +- TombLib/TombLib/LevelData/Level.cs | 2 +- TombLib/TombLib/LevelData/Room.cs | 6 +++--- TombLib/TombLib/LevelData/Sector.cs | 4 ++-- 10 files changed, 14 insertions(+), 14 deletions(-) diff --git a/TombEditor/EditorActions.cs b/TombEditor/EditorActions.cs index cfd5cf3ba..bb4c9b89e 100644 --- a/TombEditor/EditorActions.cs +++ b/TombEditor/EditorActions.cs @@ -3832,7 +3832,7 @@ public static void MergeRoomsHorizontally(IEnumerable rooms, IWin32Window Sector newSector = sector.Value.GetSector(newSectorVec).Clone(); // Preserve outer wall textures - foreach (FaceLayerInfo face in oldSector.GetFaceTexturesAll().Keys.Union(newSector.GetFaceTexturesAll().Keys)) + foreach (FaceLayerInfo face in oldSector.GetAllFaceTextures().Keys.Union(newSector.GetAllFaceTextures().Keys)) { var direction = face.Face.GetDirection(); if (direction == Direction.NegativeX || direction == Direction.PositiveX || direction == Direction.NegativeZ || direction == Direction.PositiveZ) diff --git a/TombEditor/Forms/FormTextureRemap.cs b/TombEditor/Forms/FormTextureRemap.cs index 833fe1ee3..88414607f 100644 --- a/TombEditor/Forms/FormTextureRemap.cs +++ b/TombEditor/Forms/FormTextureRemap.cs @@ -154,7 +154,7 @@ private void butOk_Click(object sender, EventArgs e) int roomTextureCount = 0; foreach (Room room in relevantRooms) foreach (Sector sector in room.Sectors) - foreach (FaceLayerInfo face in sector.GetFaceTexturesAll().Keys) + foreach (FaceLayerInfo face in sector.GetAllFaceTextures().Keys) { var currentTextureArea = sector.GetFaceTexture(face); if (currentTextureArea.Texture == sourceTexture && diff --git a/TombEditor/SectorsClipboardData.cs b/TombEditor/SectorsClipboardData.cs index 76a448080..e3464e87f 100644 --- a/TombEditor/SectorsClipboardData.cs +++ b/TombEditor/SectorsClipboardData.cs @@ -59,7 +59,7 @@ public SectorsClipboardData(Editor editor) writer.Write((byte)b.Ceiling.DiagonalSplit); writer.Write((short)b.Flags); - Dictionary textures = b.GetFaceTexturesAll(); + Dictionary textures = b.GetAllFaceTextures(); writer.Write(textures.Count); foreach (KeyValuePair texturePair in textures) diff --git a/TombLib/TombLib/GeometryIO/RoomGeometryExporter.cs b/TombLib/TombLib/GeometryIO/RoomGeometryExporter.cs index 2e1ba56ec..ebc6c9053 100644 --- a/TombLib/TombLib/GeometryIO/RoomGeometryExporter.cs +++ b/TombLib/TombLib/GeometryIO/RoomGeometryExporter.cs @@ -105,7 +105,7 @@ public static RoomExportResult ExportRooms(IEnumerable roomsToExport, stri for (int z = 0; z < room.NumZSectors; z++) { var sector = room.GetSector(new VectorInt2(x, z)); - foreach (FaceLayerInfo face in sector.GetFaceTexturesAll().Keys) + foreach (FaceLayerInfo face in sector.GetAllFaceTextures().Keys) { var faceTexture = sector.GetFaceTexture(face); if (faceTexture.TextureIsInvisible || faceTexture.TextureIsUnavailable || faceTexture.Texture == null) @@ -179,7 +179,7 @@ public static RoomExportResult ExportRooms(IEnumerable roomsToExport, stri { var sector = room.GetSector(new VectorInt2(x, z)); - foreach (FaceLayerInfo face in sector.GetFaceTexturesAll().Keys) + foreach (FaceLayerInfo face in sector.GetAllFaceTextures().Keys) { var faceTexture = sector.GetFaceTexture(face); diff --git a/TombLib/TombLib/LevelData/Compilers/Rooms.cs b/TombLib/TombLib/LevelData/Compilers/Rooms.cs index fb2a8fd65..769d1be63 100644 --- a/TombLib/TombLib/LevelData/Compilers/Rooms.cs +++ b/TombLib/TombLib/LevelData/Compilers/Rooms.cs @@ -350,7 +350,7 @@ private tr_room BuildRoom(Room room) if (!room.Properties.Hidden) for (int z = 0; z < room.NumZSectors; ++z) for (int x = 0; x < room.NumXSectors; ++x) - foreach (FaceLayerInfo face in room.Sectors[x, z].GetFaceTexturesAll().Keys) + foreach (FaceLayerInfo face in room.Sectors[x, z].GetAllFaceTextures().Keys) { var range = room.RoomGeometry.VertexRangeLookup.TryGetOrDefault(new SectorFaceIdentity(x, z, face)); var shape = room.GetFaceShape(x, z, face.Face); diff --git a/TombLib/TombLib/LevelData/Compilers/TombEngine/Rooms.cs b/TombLib/TombLib/LevelData/Compilers/TombEngine/Rooms.cs index 0f40c6cd4..9f0b67e2f 100644 --- a/TombLib/TombLib/LevelData/Compilers/TombEngine/Rooms.cs +++ b/TombLib/TombLib/LevelData/Compilers/TombEngine/Rooms.cs @@ -292,7 +292,7 @@ private TombEngineRoom BuildRoom(Room room) if (!room.Properties.Hidden) for (int z = 0; z < room.NumZSectors; ++z) for (int x = 0; x < room.NumXSectors; ++x) - foreach (FaceLayerInfo face in room.Sectors[x, z].GetFaceTexturesAll().Keys) + foreach (FaceLayerInfo face in room.Sectors[x, z].GetAllFaceTextures().Keys) { var range = room.RoomGeometry.VertexRangeLookup.TryGetOrDefault(new SectorFaceIdentity(x, z, face)); var shape = room.GetFaceShape(x, z, face.Face); diff --git a/TombLib/TombLib/LevelData/IO/Prj2Writer.cs b/TombLib/TombLib/LevelData/IO/Prj2Writer.cs index 198a38097..aa70ffe77 100644 --- a/TombLib/TombLib/LevelData/IO/Prj2Writer.cs +++ b/TombLib/TombLib/LevelData/IO/Prj2Writer.cs @@ -466,7 +466,7 @@ private static void WriteRooms(ChunkWriter chunkIO, Dictionary rooms, for (SectorEdge edge = 0; edge < SectorEdge.Count; ++edge) LEB128.Write(chunkIO.Raw, b.GetHeight(splitVertical, edge)); } - foreach (FaceLayerInfo face in b.GetFaceTexturesAll().Where(texture => room.RoomGeometry.VertexRangeLookup.ContainsKey(new SectorFaceIdentity(x, z, texture.Key))).Select(x => x.Key)) + foreach (FaceLayerInfo face in b.GetAllFaceTextures().Where(texture => room.RoomGeometry.VertexRangeLookup.ContainsKey(new SectorFaceIdentity(x, z, texture.Key))).Select(x => x.Key)) { TextureArea texture = b.GetFaceTexture(face); diff --git a/TombLib/TombLib/LevelData/Level.cs b/TombLib/TombLib/LevelData/Level.cs index 8bf291ddb..5c54063ac 100644 --- a/TombLib/TombLib/LevelData/Level.cs +++ b/TombLib/TombLib/LevelData/Level.cs @@ -369,7 +369,7 @@ public void RemoveTextures(Predicate askIfTextureToRemove) Parallel.ForEach(ExistingRooms, room => { foreach (Sector sector in room.Sectors) - foreach (FaceLayerInfo face in sector.GetFaceTexturesAll().Keys) + foreach (FaceLayerInfo face in sector.GetAllFaceTextures().Keys) { TextureArea currentTextureArea = sector.GetFaceTexture(face); LevelTexture currentTexture = currentTextureArea.Texture as LevelTexture; diff --git a/TombLib/TombLib/LevelData/Room.cs b/TombLib/TombLib/LevelData/Room.cs index a32b78461..038be998c 100644 --- a/TombLib/TombLib/LevelData/Room.cs +++ b/TombLib/TombLib/LevelData/Room.cs @@ -1671,7 +1671,7 @@ public void CopyDependentLevelSettings(CopyDependentLevelSettingsArgs args) for (int x = 0; x < NumXSectors; ++x) { Sector sector = Sectors[x, z]; - foreach (FaceLayerInfo face in sector.GetFaceTexturesAll().Keys) + foreach (FaceLayerInfo face in sector.GetAllFaceTextures().Keys) { TextureArea textureArea = sector.GetFaceTexture(face); var sourceTexture = textureArea.Texture as LevelTexture; @@ -1705,7 +1705,7 @@ public HashSet GetTextures() for (int x = 0; x < NumXSectors; ++x) { Sector sector = Sectors[x, z]; - foreach (FaceLayerInfo face in sector.GetFaceTexturesAll().Keys) + foreach (FaceLayerInfo face in sector.GetAllFaceTextures().Keys) result.Add(sector.GetFaceTexture(face).Texture); } return result; @@ -1732,7 +1732,7 @@ public void GetGeometryStatistics(out int vertices, out int faces) if (!Properties.Hidden) for (int z = 0; z < NumZSectors; ++z) for (int x = 0; x < NumXSectors; ++x) - foreach (FaceLayerInfo face in Sectors[x, z].GetFaceTexturesAll().Keys) + foreach (FaceLayerInfo face in Sectors[x, z].GetAllFaceTextures().Keys) { var range = RoomGeometry.VertexRangeLookup.TryGetOrDefault(new SectorFaceIdentity(x, z, face)); var shape = GetFaceShape(x, z, face.Face); diff --git a/TombLib/TombLib/LevelData/Sector.cs b/TombLib/TombLib/LevelData/Sector.cs index 3488563f0..da6debfb1 100644 --- a/TombLib/TombLib/LevelData/Sector.cs +++ b/TombLib/TombLib/LevelData/Sector.cs @@ -107,7 +107,7 @@ public TextureArea GetFaceTexture(FaceLayerInfo face) public Dictionary GetFaceTextures(FaceLayer layer) => _faceTextures.Where(kvp => kvp.Key.Layer == layer).ToDictionary(kvp => kvp.Key.Face, kvp => kvp.Value); - public Dictionary GetFaceTexturesAll() + public Dictionary GetAllFaceTextures() => _faceTextures; public IEnumerable GetVerticals() @@ -142,7 +142,7 @@ public void ReplaceGeometry(Level level, Sector replacement) Flags = replacement.Flags; ForceFloorSolid = replacement.ForceFloorSolid; - foreach (FaceLayerInfo face in replacement.GetFaceTexturesAll().Keys.Union(_faceTextures.Keys)) + foreach (FaceLayerInfo face in replacement.GetAllFaceTextures().Keys.Union(_faceTextures.Keys)) { var texture = replacement.GetFaceTexture(face); if (texture.TextureIsInvisible || level.Settings.Textures.Contains(texture.Texture)) From 9dfa353a41c6f986c706aa0aa35e84e42683839e Mon Sep 17 00:00:00 2001 From: Kewin Kupilas Date: Sun, 14 Sep 2025 20:14:42 +0100 Subject: [PATCH 18/19] Remove unused icon --- .../icons_general/general-sticker-16.png | Bin 341 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 TombEditor/Resources/icons_general/general-sticker-16.png diff --git a/TombEditor/Resources/icons_general/general-sticker-16.png b/TombEditor/Resources/icons_general/general-sticker-16.png deleted file mode 100644 index de3dff032176d0ebe774e603c54e93d5b02cfab4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 341 zcmV-b0jmCqP) z`~wyPW|^!8LRi>vS&+X#ee~v4r*qFa_uj#?JwLwB`~803r&RinKpU2^i;hOYYxu%3 zzVU?KdcixmLQl*;u#O7)YJn&55a=grCz!$l-q2sP;2y)N+BDA5jM=!PnhCn`l2H%9 zGi=3t9;POO})VxqI00000NkvXXu0mjf2FQ-n From 00417f5d471621c98e6866945c1973e818015abb Mon Sep 17 00:00:00 2001 From: Kewin Kupilas Date: Sun, 14 Sep 2025 20:45:00 +0100 Subject: [PATCH 19/19] Mid-review adjustments --- TombEditor/EditorActions.cs | 15 +++------------ TombLib/TombLib/LevelData/Compilers/Rooms.cs | 12 ++++++------ TombLib/TombLib/LevelData/IO/PrjLoader.cs | 9 ++++----- TombLib/TombLib/LevelData/RoomGeometry.cs | 2 +- 4 files changed, 14 insertions(+), 24 deletions(-) diff --git a/TombEditor/EditorActions.cs b/TombEditor/EditorActions.cs index bb4c9b89e..9d5d5d1b4 100644 --- a/TombEditor/EditorActions.cs +++ b/TombEditor/EditorActions.cs @@ -1674,13 +1674,7 @@ private static ApplyTextureResult ApplyTextureToFace(Room room, VectorInt2 pos, bool updated = room.RoomGeometry.UpdateFaceTexture(pos.X, pos.Y, face, currentTexture, wasDoubleSided); if (!updated && face.Layer is FaceLayer.Overlay) - { needsGeometryRebuild = true; - updated = true; - } - - if (updated) - _editor.RoomTextureChange(room); } return new(textureApplied, needsGeometryRebuild); @@ -1865,13 +1859,7 @@ private static ApplyTextureResult ApplyTextureToFace(Room room, VectorInt2 pos, bool updated = room.RoomGeometry.UpdateFaceTexture(pos.X, pos.Y, face, currentTexture, wasDoubleSided); if (!updated && face.Layer is FaceLayer.Overlay) - { needsGeometryRebuild = true; - updated = true; - } - - if (updated) - _editor.RoomTextureChange(room); } return new(textureApplied, needsGeometryRebuild); @@ -2407,7 +2395,10 @@ public static void TexturizeAll(Room room, SectorSelection selection, TextureAre } if (needsGeometryRebuild) + { room.RoomGeometry.Build(room, _editor.Configuration.Rendering3D_HighQualityLightPreview); + _editor.RoomGeometryChange(room); + } if (anyTextureApplied) _editor.RoomTextureChange(room); diff --git a/TombLib/TombLib/LevelData/Compilers/Rooms.cs b/TombLib/TombLib/LevelData/Compilers/Rooms.cs index 769d1be63..d162b2f15 100644 --- a/TombLib/TombLib/LevelData/Compilers/Rooms.cs +++ b/TombLib/TombLib/LevelData/Compilers/Rooms.cs @@ -430,19 +430,19 @@ private tr_room BuildRoom(Room room) if (face.Layer == FaceLayer.Base) { - // Base layer: use optimal rotation and remember it + // Base layer: Use optimal rotation and remember it result = _textureInfoManager.AddTexture(texture, true, false); baseRotations[faceKey] = result.Rotation; } else if (face.Layer == FaceLayer.Overlay && baseRotations.ContainsKey(faceKey)) { - // Overlay layer: force to use same rotation as base + // Overlay layer: Force to use same rotation as base var baseRotation = baseRotations[faceKey]; result = _textureInfoManager.AddTexture(texture, true, false, false, baseRotation); } else { - // Fallback: use optimal rotation + // Fallback: Use optimal rotation result = _textureInfoManager.AddTexture(texture, true, false); } @@ -503,19 +503,19 @@ private tr_room BuildRoom(Room room) if (face.Layer == FaceLayer.Base) { - // Base layer: use optimal rotation and remember it + // Base layer: Use optimal rotation and remember it result = _textureInfoManager.AddTexture(texture, true, true); baseRotations[faceKey] = result.Rotation; } else if (face.Layer == FaceLayer.Overlay && baseRotations.ContainsKey(faceKey)) { - // Overlay layer: force to use same rotation as base + // Overlay layer: Force to use same rotation as base var baseRotation = baseRotations[faceKey]; result = _textureInfoManager.AddTexture(texture, true, true, false, baseRotation); } else { - // Fallback: use optimal rotation + // Fallback: Use optimal rotation result = _textureInfoManager.AddTexture(texture, true, true); } diff --git a/TombLib/TombLib/LevelData/IO/PrjLoader.cs b/TombLib/TombLib/LevelData/IO/PrjLoader.cs index 4e4876558..319a2fe85 100644 --- a/TombLib/TombLib/LevelData/IO/PrjLoader.cs +++ b/TombLib/TombLib/LevelData/IO/PrjLoader.cs @@ -9,7 +9,6 @@ using System.Threading.Tasks; using TombLib.IO; using TombLib.LevelData.SectorEnums; -using TombLib.LevelData.SectorStructs; using TombLib.Utils; using TombLib.Wad; using TombLib.Wad.Catalog; @@ -2082,10 +2081,10 @@ private static void LoadTextureArea(Room room, int x, int z, SectorFace face, Le { case 0x0000: // TYPE_TEXTURE_NONE default: - sector.SetFaceTexture(new FaceLayerInfo(face, FaceLayer.Base), new TextureArea()); + sector.SetFaceTexture(new(face, FaceLayer.Base), new TextureArea()); return; case 0x0003: // TYPE_TEXTURE_COLOR - sector.SetFaceTexture(new FaceLayerInfo(face, FaceLayer.Base), TextureArea.Invisible); + sector.SetFaceTexture(new(face, FaceLayer.Base), TextureArea.Invisible); return; case 0x0007: // TYPE_TEXTURE_TILE int texIndex = ((prjFace._txtFlags & 0x03) << 8) | prjFace._txtIndex; @@ -2158,7 +2157,7 @@ private static void LoadTextureArea(Room room, int x, int z, SectorFace face, Le break; default: logger.Warn("Unknown texture triangle selection " + prjFace._txtTriangle); - sector.SetFaceTexture(new FaceLayerInfo(face, FaceLayer.Base), new TextureArea()); + sector.SetFaceTexture(new(face, FaceLayer.Base), new TextureArea()); return; } @@ -2232,7 +2231,7 @@ private static void LoadTextureArea(Room room, int x, int z, SectorFace face, Le } } - sector.SetFaceTexture(new FaceLayerInfo(face, FaceLayer.Base), texture); + sector.SetFaceTexture(new(face, FaceLayer.Base), texture); return; } } diff --git a/TombLib/TombLib/LevelData/RoomGeometry.cs b/TombLib/TombLib/LevelData/RoomGeometry.cs index 98a60fb37..35a1dfa9d 100644 --- a/TombLib/TombLib/LevelData/RoomGeometry.cs +++ b/TombLib/TombLib/LevelData/RoomGeometry.cs @@ -330,7 +330,7 @@ public void Build(Room room, bool highQualityLighting, bool useLegacyCode = fals public bool UpdateFaceTexture(int x, int z, FaceLayerInfo face, TextureArea texture, bool wasDoubleSided) { if (face.Layer is FaceLayer.Overlay && texture.TextureIsInvisible) - return false; + return false; // Setting invisible texture on overlay should remove the overlay - prevent texture update VertexRange range = VertexRangeLookup.GetValueOrDefault(new SectorFaceIdentity(x, z, face));