From 5ff7c9f269479f9e1fa1b31c2a9f3189def0e70e Mon Sep 17 00:00:00 2001 From: Gustas <37534529+PunkPun@users.noreply.github.com> Date: Fri, 26 Sep 2025 16:20:52 +0300 Subject: [PATCH] Fix scaling issues --- .../Widgets/ActorPreviewWidget.cs | 12 ++--- .../Logic/Editor/ActorSelectorLogic.cs | 15 +++++-- .../Logic/Editor/LayerSelectorLogic.cs | 38 ++++++++++------ .../Widgets/Logic/Editor/TileSelectorLogic.cs | 15 +++++-- .../Widgets/Logic/EncyclopediaLogic.cs | 2 +- .../Widgets/ResourcePreviewWidget.cs | 44 ++++++++++--------- .../Widgets/TerrainTemplatePreviewWidget.cs | 13 +++--- mods/cnc/chrome/editor.yaml | 8 +++- mods/common/chrome/editor.yaml | 8 +++- 9 files changed, 95 insertions(+), 60 deletions(-) diff --git a/OpenRA.Mods.Common/Widgets/ActorPreviewWidget.cs b/OpenRA.Mods.Common/Widgets/ActorPreviewWidget.cs index 719f17141b..0b18055d16 100644 --- a/OpenRA.Mods.Common/Widgets/ActorPreviewWidget.cs +++ b/OpenRA.Mods.Common/Widgets/ActorPreviewWidget.cs @@ -9,7 +9,6 @@ */ #endregion -using System; using System.Linq; using OpenRA.Graphics; using OpenRA.Mods.Common.Graphics; @@ -22,7 +21,7 @@ namespace OpenRA.Mods.Common.Widgets public class ActorPreviewWidget : Widget { public bool Animate = false; - public Func GetScale = () => 1f; + public float Scale = 1f; readonly WorldRenderer worldRenderer; readonly WorldViewportSizes viewportSizes; @@ -59,14 +58,17 @@ namespace OpenRA.Mods.Common.Widgets var r = preview.SelectMany(p => p.ScreenBounds(worldRenderer, WPos.Zero)); var b = r.Union(); IdealPreviewSize = new int2((int)(b.Width * viewportSizes.DefaultScale), (int)(b.Height * viewportSizes.DefaultScale)); - PreviewOffset = -new int2((int)(b.Left * viewportSizes.DefaultScale), (int)(b.Top * viewportSizes.DefaultScale)) - IdealPreviewSize / 2; + var previewTopLeft = new int2((int)(b.Left * viewportSizes.DefaultScale), (int)(b.Top * viewportSizes.DefaultScale)); + PreviewOffset = previewTopLeft + IdealPreviewSize / 2; } IFinalizedRenderable[] renderables; public override void PrepareRenderables() { - var scale = GetScale() * viewportSizes.DefaultScale; - var origin = RenderOrigin + PreviewOffset + new int2(RenderBounds.Size.Width / 2, RenderBounds.Size.Height / 2); + var scale = Scale * viewportSizes.DefaultScale; + var origin = RenderOrigin - new int2( + (int)(PreviewOffset.X * scale - RenderBounds.Size.Width / 2), + (int)(PreviewOffset.Y * scale - RenderBounds.Size.Height / 2)); renderables = preview .SelectMany(p => p.RenderUI(worldRenderer, origin, scale)) diff --git a/OpenRA.Mods.Common/Widgets/Logic/Editor/ActorSelectorLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Editor/ActorSelectorLogic.cs index cb48a4791e..4e1a9a5233 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Editor/ActorSelectorLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Editor/ActorSelectorLogic.cs @@ -198,11 +198,18 @@ namespace OpenRA.Mods.Common.Widgets.Logic preview.SetPreview(actor, td); // Scale templates to fit within the panel - var scale = 1f; - if (scale * preview.IdealPreviewSize.X > ItemTemplate.Bounds.Width) - scale = (ItemTemplate.Bounds.Width - Panel.ItemSpacing) / (float)preview.IdealPreviewSize.X; + // Preview position is assumed to be a margin + var maxPreviewWidth = item.Bounds.Width - 2 * preview.Bounds.X; + var maxPreviewHeight = item.Bounds.Height - 2 * preview.Bounds.Y; - preview.GetScale = () => scale; + var scale = 1f; + if (preview.IdealPreviewSize.X > maxPreviewWidth) + scale = maxPreviewWidth / (float)preview.IdealPreviewSize.X; + + if (preview.IdealPreviewSize.Y * scale > maxPreviewHeight) + scale = maxPreviewHeight / (float)preview.IdealPreviewSize.Y; + + preview.Scale = scale; preview.Bounds.Width = (int)(scale * preview.IdealPreviewSize.X); preview.Bounds.Height = (int)(scale * preview.IdealPreviewSize.Y); diff --git a/OpenRA.Mods.Common/Widgets/Logic/Editor/LayerSelectorLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Editor/LayerSelectorLogic.cs index 95aaa828e7..f8a139211c 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Editor/LayerSelectorLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Editor/LayerSelectorLogic.cs @@ -43,25 +43,35 @@ namespace OpenRA.Mods.Common.Widgets.Logic { foreach (var resourceType in resourceRenderer.ResourceTypes) { - var newResourcePreviewTemplate = ScrollItemWidget.Setup(layerPreviewTemplate, + var item = ScrollItemWidget.Setup(layerPreviewTemplate, () => editor.CurrentBrush is EditorResourceBrush brush && brush.ResourceType == resourceType, () => editor.SetBrush(new EditorResourceBrush(editor, resourceType, worldRenderer))); - newResourcePreviewTemplate.Bounds.X = 0; - newResourcePreviewTemplate.Bounds.Y = 0; + var preview = item.Get("LAYER_PREVIEW"); + preview.SetResourceType(resourceType); - var layerPreview = newResourcePreviewTemplate.Get("LAYER_PREVIEW"); - var size = layerPreview.IdealPreviewSize; - layerPreview.IsVisible = () => true; - layerPreview.ResourceType = resourceType; - layerPreview.Bounds.Width = size.Width; - layerPreview.Bounds.Height = size.Height; - newResourcePreviewTemplate.Bounds.Width = size.Width + layerPreview.Bounds.X * 2; - newResourcePreviewTemplate.Bounds.Height = size.Height + layerPreview.Bounds.Y * 2; - newResourcePreviewTemplate.IsVisible = () => true; - newResourcePreviewTemplate.GetTooltipText = () => resourceType; + // Scale templates to fit within the panel + // Preview position is assumed to be a margin + var maxPreviewWidth = item.Bounds.Width - 2 * preview.Bounds.X; + var maxPreviewHeight = item.Bounds.Height - 2 * preview.Bounds.Y; - layerTemplateList.AddChild(newResourcePreviewTemplate); + var scale = 1f; + if (preview.IdealPreviewSize.Width > maxPreviewWidth) + scale = maxPreviewWidth / (float)preview.IdealPreviewSize.Width; + + if (preview.IdealPreviewSize.Height * scale > maxPreviewHeight) + scale = maxPreviewHeight / (float)preview.IdealPreviewSize.Height; + + preview.Scale = scale; + preview.Bounds.Width = (int)(scale * preview.IdealPreviewSize.Width); + preview.Bounds.Height = (int)(scale * preview.IdealPreviewSize.Height); + + item.Bounds.Width = preview.Bounds.Width + 2 * preview.Bounds.X; + item.Bounds.Height = preview.Bounds.Height + 2 * preview.Bounds.Y; + item.IsVisible = () => true; + item.GetTooltipText = () => resourceType; + + layerTemplateList.AddChild(item); } } } diff --git a/OpenRA.Mods.Common/Widgets/Logic/Editor/TileSelectorLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Editor/TileSelectorLogic.cs index 5ed7ed699f..239810c9db 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Editor/TileSelectorLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Editor/TileSelectorLogic.cs @@ -116,11 +116,18 @@ namespace OpenRA.Mods.Common.Widgets.Logic preview.SetTemplate(terrainInfo.Templates[tileId]); // Scale templates to fit within the panel - var scale = 1f; - if (scale * preview.IdealPreviewSize.X > ItemTemplate.Bounds.Width) - scale = (ItemTemplate.Bounds.Width - Panel.ItemSpacing) / (float)preview.IdealPreviewSize.X; + // Preview position is assumed to be a margin + var maxPreviewWidth = item.Bounds.Width - 2 * preview.Bounds.X; + var maxPreviewHeight = item.Bounds.Height - 2 * preview.Bounds.Y; - preview.GetScale = () => scale; + var scale = 1f; + if (preview.IdealPreviewSize.X > maxPreviewWidth) + scale = maxPreviewWidth / (float)preview.IdealPreviewSize.X; + + if (preview.IdealPreviewSize.Y * scale > maxPreviewHeight) + scale = maxPreviewHeight / (float)preview.IdealPreviewSize.Y; + + preview.Scale = scale; preview.Bounds.Width = (int)(scale * preview.IdealPreviewSize.X); preview.Bounds.Height = (int)(scale * preview.IdealPreviewSize.Y); diff --git a/OpenRA.Mods.Common/Widgets/Logic/EncyclopediaLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/EncyclopediaLogic.cs index c728bb1d4d..20aab78fba 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/EncyclopediaLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/EncyclopediaLogic.cs @@ -179,7 +179,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic typeDictionary.Add(inits); previewWidget.SetPreview(actor, typeDictionary); - previewWidget.GetScale = () => selectedInfo.Scale; + previewWidget.Scale = selectedInfo.Scale; if (portraitWidget != null) { diff --git a/OpenRA.Mods.Common/Widgets/ResourcePreviewWidget.cs b/OpenRA.Mods.Common/Widgets/ResourcePreviewWidget.cs index 0d128c7ad0..b1b93d237d 100644 --- a/OpenRA.Mods.Common/Widgets/ResourcePreviewWidget.cs +++ b/OpenRA.Mods.Common/Widgets/ResourcePreviewWidget.cs @@ -20,7 +20,9 @@ namespace OpenRA.Mods.Common.Widgets { public class ResourcePreviewWidget : Widget { - public Func GetScale = () => 1f; + public float Scale = 1f; + + public Size IdealPreviewSize { get; private set; } readonly WorldRenderer worldRenderer; readonly WorldViewportSizes viewportSizes; @@ -29,23 +31,30 @@ namespace OpenRA.Mods.Common.Widgets string resourceType; IResourceRenderer resourceRenderer; + int2 spriteOffset; - public string ResourceType + public void SetResourceType(string value) { - get => resourceType; + resourceType = value; + if (resourceType != null) + resourceRenderer = resourceRenderers.FirstOrDefault(r => r.ResourceTypes.Contains(resourceType)); + else + resourceRenderer = null; - set + var bounds = resourceRenderer?.RenderUIPreview(worldRenderer, resourceType, int2.Zero, viewportSizes.DefaultScale) + .FirstOrDefault() + .PrepareRender(worldRenderer) + ?.ScreenBounds(worldRenderer); + + if (bounds != null) { - resourceType = value; - if (resourceType != null) - resourceRenderer = resourceRenderers.FirstOrDefault(r => r.ResourceTypes.Contains(resourceType)); - else - resourceRenderer = null; + spriteOffset = -bounds.Value.Location; + IdealPreviewSize = bounds.Value.Size; } + else + IdealPreviewSize = new Size((int)(tileSize.Width * viewportSizes.DefaultScale), (int)(tileSize.Height * viewportSizes.DefaultScale)); } - public Size IdealPreviewSize { get; } - [ObjectCreator.UseCtor] public ResourcePreviewWidget(ModData modData, WorldRenderer worldRenderer, World world) { @@ -53,15 +62,12 @@ namespace OpenRA.Mods.Common.Widgets viewportSizes = modData.Manifest.Get(); resourceRenderers = world.WorldActor.TraitsImplementing().ToArray(); tileSize = world.Map.Rules.TerrainInfo.TileSize; - IdealPreviewSize = new Size( - (int)(viewportSizes.DefaultScale * tileSize.Width), - (int)(viewportSizes.DefaultScale * tileSize.Height)); } protected ResourcePreviewWidget(ResourcePreviewWidget other) : base(other) { - GetScale = other.GetScale; + Scale = other.Scale; worldRenderer = other.worldRenderer; viewportSizes = other.viewportSizes; resourceRenderers = other.resourceRenderers; @@ -78,12 +84,8 @@ namespace OpenRA.Mods.Common.Widgets if (resourceRenderer == null) return; - var scale = GetScale() * viewportSizes.DefaultScale; - var origin = RenderOrigin + new int2( - (int)(0.5f * (RenderBounds.Size.Width - scale * tileSize.Width)), - (int)(0.5f * (RenderBounds.Size.Height - scale * tileSize.Height))); - - foreach (var r in resourceRenderer.RenderUIPreview(worldRenderer, resourceType, origin, scale)) + var scale = Scale * viewportSizes.DefaultScale; + foreach (var r in resourceRenderer.RenderUIPreview(worldRenderer, resourceType, RenderOrigin + spriteOffset, scale)) r.PrepareRender(worldRenderer).Render(worldRenderer); } } diff --git a/OpenRA.Mods.Common/Widgets/TerrainTemplatePreviewWidget.cs b/OpenRA.Mods.Common/Widgets/TerrainTemplatePreviewWidget.cs index b8a4f94dc8..d5dd6a7b36 100644 --- a/OpenRA.Mods.Common/Widgets/TerrainTemplatePreviewWidget.cs +++ b/OpenRA.Mods.Common/Widgets/TerrainTemplatePreviewWidget.cs @@ -9,7 +9,6 @@ */ #endregion -using System; using OpenRA.Graphics; using OpenRA.Mods.Common.Terrain; using OpenRA.Mods.Common.Traits; @@ -19,7 +18,7 @@ namespace OpenRA.Mods.Common.Widgets { public class TerrainTemplatePreviewWidget : Widget { - public Func GetScale = () => 1f; + public float Scale = 1f; readonly ITiledTerrainRenderer terrainRenderer; readonly WorldRenderer worldRenderer; @@ -27,7 +26,7 @@ namespace OpenRA.Mods.Common.Widgets TerrainTemplateInfo template; - public int2 PreviewOffset { get; private set; } + public int2 PreviewPos { get; private set; } public int2 IdealPreviewSize { get; private set; } [ObjectCreator.UseCtor] @@ -48,7 +47,7 @@ namespace OpenRA.Mods.Common.Widgets viewportSizes = other.viewportSizes; terrainRenderer = other.terrainRenderer; template = other.template; - GetScale = other.GetScale; + Scale = other.Scale; } public override TerrainTemplatePreviewWidget Clone() { return new TerrainTemplatePreviewWidget(this); } @@ -60,7 +59,7 @@ namespace OpenRA.Mods.Common.Widgets IdealPreviewSize = new int2((int)(b.Width * viewportSizes.DefaultScale), (int)(b.Height * viewportSizes.DefaultScale)); // Measured from the middle of the widget to the middle of the top-left cell of the template - PreviewOffset = -new int2((int)(b.Left * viewportSizes.DefaultScale), (int)(b.Top * viewportSizes.DefaultScale)) - IdealPreviewSize / 2; + PreviewPos = new int2((int)(b.Left * viewportSizes.DefaultScale), (int)(b.Top * viewportSizes.DefaultScale)); } public override void Draw() @@ -68,8 +67,8 @@ namespace OpenRA.Mods.Common.Widgets if (template == null) return; - var scale = GetScale() * viewportSizes.DefaultScale; - var origin = RenderOrigin + PreviewOffset + new int2(RenderBounds.Size.Width / 2, RenderBounds.Size.Height / 2); + var scale = Scale * viewportSizes.DefaultScale; + var origin = RenderOrigin - new int2((int)(PreviewPos.X * scale), (int)(PreviewPos.Y * scale)); foreach (var r in terrainRenderer.RenderUIPreview(worldRenderer, template, origin, scale)) r.PrepareRender(worldRenderer).Render(worldRenderer); diff --git a/mods/cnc/chrome/editor.yaml b/mods/cnc/chrome/editor.yaml index 488d6549c7..33e35015b5 100644 --- a/mods/cnc/chrome/editor.yaml +++ b/mods/cnc/chrome/editor.yaml @@ -325,7 +325,8 @@ Container@EDITOR_WORLD_ROOT: Children: ScrollItem@TILEPREVIEW_TEMPLATE: Visible: false - Width: PARENT_WIDTH - 35 + Width: (PARENT_WIDTH - 24) / 2 - 6 + Height: PARENT_WIDTH / 2 TooltipContainer: TOOLTIP_CONTAINER Children: TerrainTemplatePreview@TILE_PREVIEW: @@ -347,6 +348,8 @@ Container@EDITOR_WORLD_ROOT: Children: ScrollItem@LAYERPREVIEW_TEMPLATE: Visible: false + Width: (PARENT_WIDTH - 24) / 2 - 6 + Height: PARENT_WIDTH / 2 IgnoreChildMouseOver: true TooltipContainer: TOOLTIP_CONTAINER Children: @@ -412,7 +415,8 @@ Container@EDITOR_WORLD_ROOT: Children: ScrollItem@ACTORPREVIEW_TEMPLATE: Visible: false - Width: PARENT_WIDTH - 35 + Width: (PARENT_WIDTH - 24) / 2 - 6 + Height: PARENT_WIDTH / 2 TooltipContainer: TOOLTIP_CONTAINER TooltipTemplate: SIMPLE_TOOLTIP IgnoreChildMouseOver: true diff --git a/mods/common/chrome/editor.yaml b/mods/common/chrome/editor.yaml index 0af7b30ca0..1dfb233128 100644 --- a/mods/common/chrome/editor.yaml +++ b/mods/common/chrome/editor.yaml @@ -291,7 +291,8 @@ Container@EDITOR_WORLD_ROOT: Children: ScrollItem@TILEPREVIEW_TEMPLATE: Visible: false - Width: PARENT_WIDTH - 35 + Width: (PARENT_WIDTH - 24) / 2 - 6 + Height: PARENT_WIDTH / 2 TooltipContainer: TOOLTIP_CONTAINER Children: TerrainTemplatePreview@TILE_PREVIEW: @@ -315,6 +316,8 @@ Container@EDITOR_WORLD_ROOT: Children: ScrollItem@LAYERPREVIEW_TEMPLATE: Visible: false + Width: (PARENT_WIDTH - 24) / 2 - 6 + Height: PARENT_WIDTH / 2 IgnoreChildMouseOver: true TooltipContainer: TOOLTIP_CONTAINER Children: @@ -377,7 +380,8 @@ Container@EDITOR_WORLD_ROOT: Children: ScrollItem@ACTORPREVIEW_TEMPLATE: Visible: false - Width: PARENT_WIDTH - 35 + Width: (PARENT_WIDTH - 24) / 2 - 6 + Height: PARENT_WIDTH / 2 TooltipContainer: TOOLTIP_CONTAINER TooltipTemplate: SIMPLE_TOOLTIP IgnoreChildMouseOver: true