From ddfbe7fb509f013c28c4b11c8d8517fb7608dea1 Mon Sep 17 00:00:00 2001 From: Kewin Kupilas Date: Sun, 24 Nov 2024 18:09:33 +0000 Subject: [PATCH] #957 - Relight rooms only when entering or in Lighting mode --- TombEditor/Editor.cs | 12 +++++ TombEditor/EditorActions.cs | 54 +++++++++++++--------- TombEditor/Forms/FormTextureRemap.cs | 2 +- TombEditor/Undo.cs | 8 ++-- TombLib/TombLib/LevelData/IO/Prj2Loader.cs | 2 +- TombLib/TombLib/LevelData/IO/PrjLoader.cs | 2 +- TombLib/TombLib/LevelData/Level.cs | 2 +- TombLib/TombLib/LevelData/Room.cs | 31 ++++++++++--- TombLib/TombLib/LevelData/RoomGeometry.cs | 5 +- 9 files changed, 76 insertions(+), 42 deletions(-) diff --git a/TombEditor/Editor.cs b/TombEditor/Editor.cs index f35d8eaa3..8026b5fc1 100644 --- a/TombEditor/Editor.cs +++ b/TombEditor/Editor.cs @@ -1076,6 +1076,16 @@ obj is RoomTextureChangedEvent || Tool = _lastGeometryTool; else Tool = _lastFaceEditTool; + + // If the mode switched to lighting mode, relight all rooms which have `PendingRelight` set to true + if (@event.Current == EditorMode.Lighting) + { + foreach (Room room in Level.Rooms) + { + if (room?.PendingRelight == true) + room.RebuildLighting(Configuration.Rendering3D_HighQualityLightPreview); + } + } } // Backup last used tool for next mode @@ -1449,5 +1459,7 @@ public bool IsPreciseGeometryAllowed => Level.Settings.GameVersion is TRVersion.Game.TombEngine || Configuration.Editor_EnableStepHeightControlsForUnsupportedEngines; public int IncrementReference => IsPreciseGeometryAllowed ? Configuration.Editor_StepHeight : Level.FullClickHeight; + + public bool ShouldRelight => Mode is EditorMode.Lighting; } } diff --git a/TombEditor/EditorActions.cs b/TombEditor/EditorActions.cs index 720427d90..d20716de5 100644 --- a/TombEditor/EditorActions.cs +++ b/TombEditor/EditorActions.cs @@ -64,7 +64,7 @@ public static void SmartBuildGeometry(Room room, RectangleInt2 area) var watch = new Stopwatch(); watch.Start(); - room.SmartBuildGeometry(area, _editor.Configuration.Rendering3D_HighQualityLightPreview); + room.SmartBuildGeometry(area, _editor.ShouldRelight, _editor.Configuration.Rendering3D_HighQualityLightPreview); watch.Stop(); logger.Debug("Edit geometry time: " + watch.ElapsedMilliseconds + " ms"); _editor.RoomGeometryChange(room); @@ -1252,27 +1252,31 @@ public static void DeleteObjectWithoutUpdate(ObjectInstance instance) if (instance is LightInstance) { - room.RebuildLighting(_editor.Configuration.Rendering3D_HighQualityLightPreview); + if (_editor.ShouldRelight) + room.RebuildLighting(_editor.Configuration.Rendering3D_HighQualityLightPreview); + _editor.RoomGeometryChange(room); } if (instance is PortalInstance) { - room.BuildGeometry(_editor.Configuration.Rendering3D_HighQualityLightPreview); + room.Rebuild(_editor.ShouldRelight, _editor.Configuration.Rendering3D_HighQualityLightPreview); + if (adjoiningRoom != null) { - adjoiningRoom.BuildGeometry(_editor.Configuration.Rendering3D_HighQualityLightPreview); + adjoiningRoom.Rebuild(_editor.ShouldRelight, _editor.Configuration.Rendering3D_HighQualityLightPreview); _editor.RoomSectorPropertiesChange(adjoiningRoom); if (adjoiningRoom.AlternateOpposite != null) { - adjoiningRoom.AlternateOpposite.BuildGeometry(_editor.Configuration.Rendering3D_HighQualityLightPreview); + adjoiningRoom.AlternateOpposite.Rebuild(_editor.ShouldRelight, _editor.Configuration.Rendering3D_HighQualityLightPreview); _editor.RoomSectorPropertiesChange(adjoiningRoom.AlternateOpposite); } } + if (room.AlternateOpposite != null) { - room.AlternateOpposite.BuildGeometry(_editor.Configuration.Rendering3D_HighQualityLightPreview); + room.AlternateOpposite.Rebuild(_editor.ShouldRelight, _editor.Configuration.Rendering3D_HighQualityLightPreview); _editor.RoomSectorPropertiesChange(room.AlternateOpposite); } } @@ -2484,8 +2488,8 @@ public static void DeleteRooms(IEnumerable rooms_, IWin32Window owner = nu // Update selection foreach (Room adjoiningRoom in adjoiningRooms) { - adjoiningRoom?.BuildGeometry(_editor.Configuration.Rendering3D_HighQualityLightPreview); - adjoiningRoom?.AlternateOpposite?.BuildGeometry(_editor.Configuration.Rendering3D_HighQualityLightPreview); + adjoiningRoom?.Rebuild(_editor.ShouldRelight, _editor.Configuration.Rendering3D_HighQualityLightPreview); + adjoiningRoom?.AlternateOpposite?.Rebuild(_editor.ShouldRelight, _editor.Configuration.Rendering3D_HighQualityLightPreview); } // Select last room, if available. Else select first existing room. @@ -2534,7 +2538,7 @@ public static void CropRoom(Room room, RectangleInt2 newArea, IWin32Window owner Room.FixupNeighborPortals(_editor.Level, new[] { room }, new[] { room }, ref relevantRooms); Parallel.ForEach(relevantRooms, relevantRoom => { - relevantRoom.BuildGeometry(_editor.Configuration.Rendering3D_HighQualityLightPreview); + relevantRoom.Rebuild(_editor.ShouldRelight, _editor.Configuration.Rendering3D_HighQualityLightPreview); }); // Cleanup @@ -3049,7 +3053,7 @@ public static void AddPortal(Room room, RectangleInt2 area, IWin32Window owner) // Update foreach (Room portalRoom in portals.Select(portal => portal.Room).Distinct()) { - portalRoom.BuildGeometry(_editor.Configuration.Rendering3D_HighQualityLightPreview); + portalRoom.Rebuild(_editor.ShouldRelight, _editor.Configuration.Rendering3D_HighQualityLightPreview); } foreach (PortalInstance portal in portals) @@ -3077,7 +3081,7 @@ public static void AlternateRoomEnable(Room room, short AlternateGroup) newRoom.Properties.Locked = false; newRoom.Name = room + " (Flipped)"; - newRoom.BuildGeometry(_editor.Configuration.Rendering3D_HighQualityLightPreview); + newRoom.Rebuild(_editor.ShouldRelight, _editor.Configuration.Rendering3D_HighQualityLightPreview); // Assign room _editor.Level.AssignRoomToFree(newRoom); @@ -3373,7 +3377,7 @@ public static void GridWallsSquares(Room room, RectangleInt2 area, bool fiveDivi if (fromUI) SmartBuildGeometry(room, area); else - room.BuildGeometry(); + room.Rebuild(_editor.ShouldRelight, _editor.Configuration.Rendering3D_HighQualityLightPreview); } public static Room CreateAdjoiningRoom(Room room, SectorSelection selection, PortalDirection direction, bool grid, int roomDepth, bool switchRoom = true, bool clearAdjoiningArea = false) @@ -3520,10 +3524,10 @@ public static Room CreateAdjoiningRoom(Room room, SectorSelection selection, Por // Build the geometry of the new room Parallel.Invoke(() => { - newRoom.BuildGeometry(_editor.Configuration.Rendering3D_HighQualityLightPreview); + newRoom.Rebuild(_editor.ShouldRelight, _editor.Configuration.Rendering3D_HighQualityLightPreview); }, () => { - room.BuildGeometry(_editor.Configuration.Rendering3D_HighQualityLightPreview); + room.Rebuild(_editor.ShouldRelight, _editor.Configuration.Rendering3D_HighQualityLightPreview); }); if (switchRoom && (_editor.SelectedRoom == room || _editor.SelectedRoom == room.AlternateOpposite)) @@ -3834,7 +3838,7 @@ public static void MergeRoomsHorizontally(IEnumerable rooms, IWin32Window Room.FixupNeighborPortals(_editor.Level, new[] { newRoom }, new[] { newRoom }.Concat(mergeRooms), ref relevantRooms); Parallel.ForEach(relevantRooms, relevantRoom => { - relevantRoom.BuildGeometry(_editor.Configuration.Rendering3D_HighQualityLightPreview); + relevantRoom.Rebuild(_editor.ShouldRelight, _editor.Configuration.Rendering3D_HighQualityLightPreview); }); // Add room and update the editor @@ -3885,7 +3889,7 @@ public static void SplitRoom(IWin32Window owner) Room.FixupNeighborPortals(_editor.Level, new[] { room, splitRoom }, new[] { room, splitRoom }, ref relevantRooms); Parallel.ForEach(relevantRooms, relevantRoom => { - relevantRoom.BuildGeometry(_editor.Configuration.Rendering3D_HighQualityLightPreview); + relevantRoom.Rebuild(_editor.ShouldRelight, _editor.Configuration.Rendering3D_HighQualityLightPreview); }); // Cleanup @@ -3932,7 +3936,7 @@ public static void DuplicateRoom(IWin32Window owner) var newRoom = _editor.SelectedRoom.Clone(_editor.Level); newRoom.Name = cutName + " (copy" + buffer + ")"; - newRoom.BuildGeometry(_editor.Configuration.Rendering3D_HighQualityLightPreview); + newRoom.Rebuild(_editor.ShouldRelight, _editor.Configuration.Rendering3D_HighQualityLightPreview); _editor.Level.AssignRoomToFree(newRoom); _editor.RoomListChange(); _editor.UndoManager.PushRoomCreated(newRoom); @@ -4608,7 +4612,7 @@ public static bool TransformRooms(RectTransformation transformation, IWin32Windo var newRooms = _editor.Level.TransformRooms(_editor.SelectedRooms, transformation); foreach (Room room in newRooms) { - room.BuildGeometry(_editor.Configuration.Rendering3D_HighQualityLightPreview); + room.Rebuild(_editor.ShouldRelight, _editor.Configuration.Rendering3D_HighQualityLightPreview); } _editor.SelectRoomsAndResetCamera(newRooms); @@ -4711,9 +4715,13 @@ public static void TryPasteSectors(SectorsClipboardData data, IWin32Window owner } // Redraw rooms in portals - portals.Select(p => p.AdjoiningRoom).ToList().ForEach(room => { room.BuildGeometry(); _editor.RoomGeometryChange(room); }); + portals.Select(p => p.AdjoiningRoom).ToList().ForEach(room => + { + room.Rebuild(_editor.ShouldRelight, _editor.Configuration.Rendering3D_HighQualityLightPreview); + _editor.RoomGeometryChange(room); + }); - _editor.SelectedRoom.BuildGeometry(_editor.Configuration.Rendering3D_HighQualityLightPreview); + _editor.SelectedRoom.Rebuild(_editor.ShouldRelight, _editor.Configuration.Rendering3D_HighQualityLightPreview); _editor.RoomSectorPropertiesChange(_editor.SelectedRoom); } @@ -4813,7 +4821,7 @@ public static void SetPortalOpacity(PortalOpacity opacity, IWin32Window owner) } portal.Opacity = opacity; - portal.Room.BuildGeometry(_editor.Configuration.Rendering3D_HighQualityLightPreview); + portal.Room.Rebuild(_editor.ShouldRelight, _editor.Configuration.Rendering3D_HighQualityLightPreview); _editor.RoomGeometryChange(portal.Room); _editor.ObjectChange(portal, ObjectChangeType.Change); } @@ -5326,7 +5334,7 @@ public static void MoveRooms(VectorInt3 positionDelta, IEnumerable rooms, // Update foreach (Room room in roomsToUpdate) { - room.BuildGeometry(_editor.Configuration.Rendering3D_HighQualityLightPreview); + room.Rebuild(_editor.ShouldRelight, _editor.Configuration.Rendering3D_HighQualityLightPreview); _editor.RoomSectorPropertiesChange(room); } @@ -5386,7 +5394,7 @@ public static void SplitSectorObjectOnSelection(SectorBasedObjectInstance @objec Room.FixupNeighborPortals(_editor.Level, new[] { room }, new[] { room }, ref relevantRooms); Parallel.ForEach(relevantRooms, relevantRoom => { - relevantRoom.BuildGeometry(_editor.Configuration.Rendering3D_HighQualityLightPreview); + relevantRoom.Rebuild(_editor.ShouldRelight, _editor.Configuration.Rendering3D_HighQualityLightPreview); }); foreach (Room relevantRoom in relevantRooms) _editor.RoomPropertiesChange(relevantRoom); diff --git a/TombEditor/Forms/FormTextureRemap.cs b/TombEditor/Forms/FormTextureRemap.cs index faf9a9664..b55686637 100644 --- a/TombEditor/Forms/FormTextureRemap.cs +++ b/TombEditor/Forms/FormTextureRemap.cs @@ -218,7 +218,7 @@ private void butOk_Click(object sender, EventArgs e) } // Send out updates - Parallel.ForEach(relevantRooms, room => room.BuildGeometry()); + Parallel.ForEach(relevantRooms, room => room.Rebuild(_editor.ShouldRelight, _editor.Configuration.Rendering3D_HighQualityLightPreview)); foreach (Room room in relevantRooms) _editor.RoomTextureChange(room); diff --git a/TombEditor/Undo.cs b/TombEditor/Undo.cs index 6fa8f2831..097f87c1e 100644 --- a/TombEditor/Undo.cs +++ b/TombEditor/Undo.cs @@ -187,7 +187,7 @@ public TransformObjectUndoInstance(EditorUndoManager parent, PositionBasedObject // Rebuild lighting! if (UndoObject is LightInstance) - Room.BuildGeometry(); + Room.RebuildLighting(parent.Editor.Configuration.Rendering3D_HighQualityLightPreview); // Move origin of object group, if it contains object if (Parent.Editor.SelectedObject is ObjectGroup) @@ -401,12 +401,12 @@ public GeometryUndoInstance(EditorUndoManager parent, Room room) : base(parent, for (int z = Area.Y0, j = 0; z < Area.Y1; z++, j++) Room.Sectors[x, z].ReplaceGeometry(Parent.Editor.Level, Sectors[i, j]); - Room.BuildGeometry(); + Room.Rebuild(parent.Editor.ShouldRelight, parent.Editor.Configuration.Rendering3D_HighQualityLightPreview); Parent.Editor.RoomGeometryChange(Room); Parent.Editor.RoomSectorPropertiesChange(Room); var relevantRooms = room.Portals.Select(p => p.AdjoiningRoom).Distinct(); - Parallel.ForEach(relevantRooms, r => r.BuildGeometry()); - + Parallel.ForEach(relevantRooms, r => r.Rebuild(parent.Editor.ShouldRelight, parent.Editor.Configuration.Rendering3D_HighQualityLightPreview)); + foreach (Room relevantRoom in relevantRooms) Parent.Editor.RoomGeometryChange(relevantRoom); diff --git a/TombLib/TombLib/LevelData/IO/Prj2Loader.cs b/TombLib/TombLib/LevelData/IO/Prj2Loader.cs index a246b041b..9496fa5a9 100644 --- a/TombLib/TombLib/LevelData/IO/Prj2Loader.cs +++ b/TombLib/TombLib/LevelData/IO/Prj2Loader.cs @@ -1170,7 +1170,7 @@ private static bool LoadRooms(ChunkReader chunkIO, ChunkId idOuter, Level level, CancellationToken = cancelToken, }; progressReporter?.ReportInfo("Building world geometry"); - Parallel.ForEach(level.ExistingRooms, parallelOptions, room => room.BuildGeometry()); + Parallel.ForEach(level.ExistingRooms, parallelOptions, room => room.Rebuild(relight: true, highQualityLighting: true)); return true; } diff --git a/TombLib/TombLib/LevelData/IO/PrjLoader.cs b/TombLib/TombLib/LevelData/IO/PrjLoader.cs index 95b5e391d..3b19f087b 100644 --- a/TombLib/TombLib/LevelData/IO/PrjLoader.cs +++ b/TombLib/TombLib/LevelData/IO/PrjLoader.cs @@ -1979,7 +1979,7 @@ public static Level LoadFromPrj(string filename, string soundsPath, { CancellationToken = cancelToken }; - Parallel.ForEach(level.ExistingRooms, options, room => room.BuildGeometry()); + Parallel.ForEach(level.ExistingRooms, options, room => room.Rebuild(relight: true, highQualityLighting: true)); progressReporter?.ReportProgress(100, "Level loaded correctly!"); return level; diff --git a/TombLib/TombLib/LevelData/Level.cs b/TombLib/TombLib/LevelData/Level.cs index 791981100..46e5d66c8 100644 --- a/TombLib/TombLib/LevelData/Level.cs +++ b/TombLib/TombLib/LevelData/Level.cs @@ -377,7 +377,7 @@ public void RemoveTextures(Predicate askIfTextureToRemove) sector.SetFaceTexture(face, TextureArea.None); } } - room.BuildGeometry(); + room.Rebuild(relight: true, highQualityLighting: true); }); foreach (AnimatedTextureSet set in Settings.AnimatedTextureSets) diff --git a/TombLib/TombLib/LevelData/Room.cs b/TombLib/TombLib/LevelData/Room.cs index 0e9ca9b5f..88613ca51 100644 --- a/TombLib/TombLib/LevelData/Room.cs +++ b/TombLib/TombLib/LevelData/Room.cs @@ -133,6 +133,7 @@ public class Room : ITriggerParameter // Internal data structures public RoomGeometry RoomGeometry { get; } = new RoomGeometry(); + public bool PendingRelight { get; private set; } = true; public Room(Level level, int numXSectors, int numZSectors, Vector3 ambientLight, string name = "Unnamed", int ceiling = DefaultHeight) { @@ -140,7 +141,7 @@ public Room(Level level, int numXSectors, int numZSectors, Vector3 ambientLight, Level = level; Properties = new RoomProperties() { AmbientLight = ambientLight }; Resize(null, new RectangleInt2(0, 0, numXSectors - 1, numZSectors - 1), 0, ceiling, true); - BuildGeometry(); + Rebuild(relight: true, highQualityLighting: true); } public Room(Level level, VectorInt2 sectorSize, Vector3 ambientLight, string name = "Unnamed", int ceiling = DefaultHeight) @@ -308,8 +309,8 @@ public Room Split(Level level, RectangleInt2 area, Room alternateOppositeSplitRo newRoom.MoveObjectFrom(level, this, instance); } - newRoom.BuildGeometry(); - BuildGeometry(); + newRoom.Rebuild(relight: true, highQualityLighting: true); + Rebuild(relight: true, highQualityLighting: true); return newRoom; } @@ -919,14 +920,30 @@ public FaceShape GetFaceShape(int x, int z, SectorFace face) } } - public void BuildGeometry(bool highQualityLighting = false, bool useLegacyCode = false) + public void Rebuild(bool relight, bool highQualityLighting) { - RoomGeometry.Build(this, highQualityLighting, useLegacyCode); + RoomGeometry.Build(this); + + if (relight) + { + RoomGeometry.Relight(this, highQualityLighting); + PendingRelight = false; + } + else + { + PendingRelight = true; + } + } + + public void BuildGeometry(bool useLegacyCode = false) + { + RoomGeometry.Build(this, useLegacyCode); } public void RebuildLighting(bool highQualityLighting) { RoomGeometry.Relight(this, highQualityLighting); + PendingRelight = false; } public Matrix4x4 Transform => Matrix4x4.CreateTranslation(WorldPos); @@ -1513,7 +1530,7 @@ public RoomConnectionInfo GetCeilingRoomConnectionInfo(VectorInt2 pos, bool incl return new RoomConnectionInfo(); } - public void SmartBuildGeometry(RectangleInt2 area, bool highQualityLighting = false) + public void SmartBuildGeometry(RectangleInt2 area, bool relight, bool highQualityLighting = false) { area = area.Inflate(1); // Add margin @@ -1557,7 +1574,7 @@ public void SmartBuildGeometry(RectangleInt2 area, bool highQualityLighting = fa // Update the collected stuff now Parallel.For(0, roomsToProcess.Count, index => { - roomsToProcess[index].BuildGeometry(highQualityLighting); + roomsToProcess[index].Rebuild(relight, highQualityLighting); }); } diff --git a/TombLib/TombLib/LevelData/RoomGeometry.cs b/TombLib/TombLib/LevelData/RoomGeometry.cs index e08b3e826..71825cc9b 100644 --- a/TombLib/TombLib/LevelData/RoomGeometry.cs +++ b/TombLib/TombLib/LevelData/RoomGeometry.cs @@ -44,7 +44,7 @@ public class RoomGeometry public SortedList VertexRangeLookup { get; } = new SortedList(); // useLegacyCode is used for converting legacy .PRJ files to .PRJ2 files - public void Build(Room room, bool highQualityLighting, bool useLegacyCode = false) + public void Build(Room room, bool useLegacyCode = false) { VertexPositions.Clear(); VertexEditorUVs.Clear(); @@ -321,9 +321,6 @@ public void Build(Room room, bool highQualityLighting, bool useLegacyCode = fals // Build color array VertexColors.Resize(VertexPositions.Count, room.Properties.AmbientLight); - - // Lighting - Relight(room, highQualityLighting); } public void UpdateFaceTexture(int x, int z, SectorFace face, TextureArea texture, bool wasDoubleSided)