Implement new viewport size/zoom UI.

This commit is contained in:
Paul Chote
2019-12-11 18:48:43 +00:00
committed by tovl
parent 860117daf9
commit 1dcb903580
17 changed files with 319 additions and 253 deletions

View File

@@ -673,7 +673,10 @@ namespace OpenRA
// World rendering is disabled while the loading screen is displayed
if (worldRenderer != null && !worldRenderer.World.IsLoadingGameSave)
{
worldRenderer.Viewport.Tick();
worldRenderer.PrepareRenderables();
}
Ui.PrepareRenderables();
Renderer.WorldModelRenderer.EndFrame();

View File

@@ -36,6 +36,8 @@ namespace OpenRA.Graphics
public class Viewport
{
readonly WorldRenderer worldRenderer;
readonly WorldViewportSizes viewportSizes;
readonly GraphicSettings graphicSettings;
// Map bounds (world-px)
readonly Rectangle mapBounds;
@@ -55,14 +57,16 @@ namespace OpenRA.Graphics
ProjectedCellRegion allCells;
bool allCellsDirty = true;
readonly float[] availableZoomSteps = new[] { 2f, 1f, 0.5f, 0.25f };
WorldViewport lastViewportDistance;
float zoom = 1f;
float minZoom = 1f;
float maxZoom = 2f;
public float[] AvailableZoomSteps
{
get { return availableZoomSteps; }
}
bool unlockMinZoom;
float unlockedMinZoomScale;
float unlockedMinZoom = 1f;
public float Zoom
{
@@ -71,16 +75,37 @@ namespace OpenRA.Graphics
return zoom;
}
set
private set
{
var newValue = ClosestTo(AvailableZoomSteps, value);
zoom = newValue;
zoom = value;
viewportSize = (1f / zoom * new float2(Game.Renderer.Resolution)).ToInt2();
cellsDirty = true;
allCellsDirty = true;
}
}
public void AdjustZoom(float dz)
{
// Exponential ensures that equal positive and negative steps have the same effect
Zoom = (zoom * (float)Math.Exp(dz)).Clamp(unlockMinZoom ? unlockedMinZoom : minZoom, maxZoom);
}
public void ToggleZoom()
{
// Unlocked zooms always reset to the default zoom
if (zoom < minZoom)
Zoom = minZoom;
else
Zoom = zoom > minZoom ? minZoom : maxZoom;
}
public void UnlockMinimumZoom(float scale)
{
unlockMinZoom = true;
unlockedMinZoomScale = scale;
UpdateViewportZooms(false);
}
public static long LastMoveRunTime = 0;
public static int2 LastMousePos;
@@ -120,6 +145,8 @@ namespace OpenRA.Graphics
{
worldRenderer = wr;
var grid = Game.ModData.Manifest.Get<MapGrid>();
viewportSizes = Game.ModData.Manifest.Get<WorldViewportSizes>();
graphicSettings = Game.Settings.Graphics;
// Calculate map bounds in world-px
if (wr.World.Type == WorldType.Editor)
@@ -141,8 +168,75 @@ namespace OpenRA.Graphics
CenterLocation = (tl + br) / 2;
}
Zoom = Game.Settings.Graphics.PixelDouble ? 2 : 1;
tileSize = grid.TileSize;
UpdateViewportZooms();
}
public void Tick()
{
if (lastViewportDistance != graphicSettings.ViewportDistance)
UpdateViewportZooms();
}
float CalculateMinimumZoom(float minHeight, float maxHeight)
{
var h = Game.Renderer.Resolution.Height;
// Check the easy case: the native resolution is within the maximum limit
// Also catches the case where the user may force a resolution smaller than the minimum window size
if (h <= maxHeight)
return 1;
// Find a clean fraction that brings us within the desired range to reduce aliasing
var step = 1f;
while (true)
{
var testZoom = 1f;
while (true)
{
var nextZoom = testZoom + step;
if (h < minHeight * nextZoom)
break;
testZoom = nextZoom;
}
if (h < maxHeight * testZoom)
return testZoom;
step /= 2;
}
}
void UpdateViewportZooms(bool resetCurrentZoom = true)
{
lastViewportDistance = graphicSettings.ViewportDistance;
var vd = graphicSettings.ViewportDistance;
if (viewportSizes.AllowNativeZoom && vd == WorldViewport.Native)
minZoom = 1;
else
{
var range = viewportSizes.GetSizeRange(vd);
minZoom = CalculateMinimumZoom(range.X, range.Y);
}
maxZoom = Math.Min(minZoom * viewportSizes.MaxZoomScale, Game.Renderer.Resolution.Height * 1f / viewportSizes.MaxZoomWindowHeight);
if (unlockMinZoom)
{
// Specators and the map editor support zooming out by an extra factor of two.
// TODO: Allow zooming out until the full map is visible
// We need to improve our viewport scroll handling to center the map as we zoom out
// before this will work well enough to enable
unlockedMinZoom = minZoom * unlockedMinZoomScale;
}
if (resetCurrentZoom)
Zoom = minZoom;
else
Zoom = Zoom.Clamp(minZoom, maxZoom);
}
public CPos ViewToWorld(int2 view)

View File

@@ -13,7 +13,6 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using OpenRA.Graphics;
using OpenRA.Primitives;
using OpenRA.Traits;
@@ -34,6 +33,8 @@ namespace OpenRA
Incompatible = 16
}
public enum WorldViewport { Native, Close, Medium, Far }
public class ServerSettings
{
[Desc("Sets the server name.")]
@@ -145,8 +146,8 @@ namespace OpenRA
public bool HardwareCursors = true;
public bool PixelDouble = false;
public bool CursorDouble = false;
public WorldViewport ViewportDistance = WorldViewport.Medium;
[Desc("Add a frame rate limiter. It is recommended to not disable this.")]
public bool CapFramerate = true;
@@ -207,6 +208,7 @@ namespace OpenRA
public MouseButtonPreference MouseButtonPreference = new MouseButtonPreference();
public float ViewportEdgeScrollStep = 30f;
public float UIScrollSpeed = 50f;
public float ZoomSpeed = 0.04f;
public int SelectionDeadzone = 24;
public int MouseScrollDeadzone = 8;
@@ -220,8 +222,7 @@ namespace OpenRA
[Desc("Filename of the authentication profile to use.")]
public string AuthProfile = "player.oraid";
public bool AllowZoom = true;
public Modifiers ZoomModifier = Modifiers.Ctrl;
public Modifiers ZoomModifier = Modifiers.None;
public bool FetchNews = true;

View File

@@ -0,0 +1,33 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version. For more
* information, see COPYING.
*/
#endregion
using System.Collections.Generic;
namespace OpenRA
{
public class WorldViewportSizes : IGlobalModData
{
public readonly int2 CloseWindowHeights = new int2(480, 600);
public readonly int2 MediumWindowHeights = new int2(600, 900);
public readonly int2 FarWindowHeights = new int2(900, 1300);
public readonly float MaxZoomScale = 2.0f;
public readonly int MaxZoomWindowHeight = 240;
public readonly bool AllowNativeZoom = true;
public int2 GetSizeRange(WorldViewport distance)
{
return distance == WorldViewport.Close ? CloseWindowHeights
: distance == WorldViewport.Medium ? MediumWindowHeights
: FarWindowHeights;
}
}
}