diff --git a/Gui/ViewModels/Graphics/ImageTableViewModel.cs b/Gui/ViewModels/Graphics/ImageTableViewModel.cs index b92cc625..f3bee884 100644 --- a/Gui/ViewModels/Graphics/ImageTableViewModel.cs +++ b/Gui/ViewModels/Graphics/ImageTableViewModel.cs @@ -5,6 +5,7 @@ using Common.Logging; using Definitions.ObjectModels; using Definitions.ObjectModels.Graphics; +using Definitions.ObjectModels.Objects.Building; using Definitions.ObjectModels.Objects.Common; using Gui.ViewModels.LocoTypes.Objects.Building; using ReactiveUI; @@ -94,7 +95,7 @@ public class ImageTableViewModel : ReactiveObject, IExtraContentViewModel ImageTable Model { get; init; } - public ImageTableViewModel(ImageTable imageTable, ILogger logger, BuildingComponents? buildingComponents = null) + public ImageTableViewModel(ImageTable imageTable, ILogger logger, BuildingComponents? buildingComponents = null, BuildingObjectFlags? buildingFlags = null) { ArgumentNullException.ThrowIfNull(imageTable); @@ -116,7 +117,7 @@ public ImageTableViewModel(ImageTable imageTable, ILogger logger, BuildingCompon // building components if (buildingComponents != null) { - BuildingComponents = new(buildingComponents, imageTable); + BuildingComponents = new(buildingComponents, imageTable, buildingFlags); } _ = this.WhenAnyValue(o => o.SelectedPrimarySwatch).Skip(1) diff --git a/Gui/ViewModels/LocoTypes/ObjectEditorViewModel.cs b/Gui/ViewModels/LocoTypes/ObjectEditorViewModel.cs index 4966b28d..7f5b0d21 100644 --- a/Gui/ViewModels/LocoTypes/ObjectEditorViewModel.cs +++ b/Gui/ViewModels/LocoTypes/ObjectEditorViewModel.cs @@ -6,6 +6,7 @@ using Dat.Data; using Dat.FileParsing; using Definitions.ObjectModels; +using Definitions.ObjectModels.Objects.Building; using Definitions.ObjectModels.Objects.Common; using Definitions.ObjectModels.Objects.Sound; using Definitions.ObjectModels.Types; @@ -264,7 +265,8 @@ public override void Load() else { var bc = CurrentObject.LocoObject.ObjectType == ObjectType.Building ? (CurrentObject.LocoObject.Object as IHasBuildingComponents)?.BuildingComponents : null; - ExtraContentViewModel = new ImageTableViewModel(CurrentObject.LocoObject.ImageTable, Model.Logger, bc); + var buildingFlags = CurrentObject.LocoObject.ObjectType == ObjectType.Building ? (CurrentObject.LocoObject.Object as BuildingObject)?.Flags : null; + ExtraContentViewModel = new ImageTableViewModel(CurrentObject.LocoObject.ImageTable, Model.Logger, bc, buildingFlags); } } } diff --git a/Gui/ViewModels/LocoTypes/Objects/Building/BuildingComponentsViewModel.cs b/Gui/ViewModels/LocoTypes/Objects/Building/BuildingComponentsViewModel.cs index fc3d75db..acc21134 100644 --- a/Gui/ViewModels/LocoTypes/Objects/Building/BuildingComponentsViewModel.cs +++ b/Gui/ViewModels/LocoTypes/Objects/Building/BuildingComponentsViewModel.cs @@ -42,6 +42,8 @@ public class BuildingComponentsViewModel : ReactiveObject protected ImageTable ImageTable { get; set; } + protected BuildingObjectFlags? BuildingFlags { get; set; } + public BuildingComponentsViewModel() { _ = this.WhenAnyValue(x => x.BuildingVariations) @@ -53,12 +55,13 @@ public BuildingComponentsViewModel() _ = MessageBus.Current.Listen().Subscribe(UpdateBuildingComponents); } - public BuildingComponentsViewModel(BuildingComponents buildingComponents, ImageTable imageTable) : this() + public BuildingComponentsViewModel(BuildingComponents buildingComponents, ImageTable imageTable, BuildingObjectFlags? buildingFlags = null) : this() { ArgumentNullException.ThrowIfNull(buildingComponents); ArgumentNullException.ThrowIfNull(imageTable); ImageTable = imageTable; + BuildingFlags = buildingFlags; UpdateBuildingComponents(buildingComponents); } @@ -78,6 +81,10 @@ void UpdateBuildingComponents(BuildingComponents buildingComponents) protected void RecomputeBuildingVariationViewModels(List> buildingVariations, List buildingHeights) { + const int minPartsForShadowReordering = 2; + const int shadowPartIndex = 1; + const int basePartIndex = 0; + var layers = ImageTable.Groups.ConvertAll(x => x.GraphicsElements); BuildingVariationViewModels.Clear(); @@ -85,6 +92,8 @@ protected void RecomputeBuildingVariationViewModels(List> building MaxWidth = layers.Max(x => x.Max(y => y.Width)) + 16; MaxHeight = (layers.Max(x => x.Max(y => y.Height)) * buildingHeights.Count) + buildingHeights.Sum(x => x) + buildingVariations.Max(x => x.Count) * (VerticalLayerSpacing * 2); + var hasShadows = BuildingFlags?.HasFlag(BuildingObjectFlags.HasShadows) ?? false; + var x = 0; foreach (var variation in buildingVariations) { @@ -102,7 +111,20 @@ protected void RecomputeBuildingVariationViewModels(List> building }; var cumulativeOffset = 0; - foreach (var variationItem in variation) + + // When HasShadows flag is set, the first 4 images (part 0) are the base layer + // and the second 4 images (part 1) are the shadows. + // Shadows should be rendered first (below/behind the base layer). + // Example: variation [0, 1, 2] becomes [1, 0, 2] - swap first two parts, keep rest + var reorderedVariation = variation; + if (hasShadows && variation.Count >= minPartsForShadowReordering) + { + // Reorder so shadows (part 1) come before base (part 0) + // Skip(2) skips the first 2 parts we're explicitly including, avoiding duplication + reorderedVariation = [variation[shadowPartIndex], variation[basePartIndex], .. variation.Skip(minPartsForShadowReordering)]; + } + + foreach (var variationItem in reorderedVariation) { if (layers.Count > variationItem) {