Editor marker tiles layer
56
OpenRA.Game/Graphics/MarkerTileRenderable.cs
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright (c) The OpenRA Developers and Contributors
|
||||||
|
* 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.Linq;
|
||||||
|
using OpenRA.Primitives;
|
||||||
|
|
||||||
|
namespace OpenRA.Graphics
|
||||||
|
{
|
||||||
|
public class MarkerTileRenderable : IRenderable, IFinalizedRenderable
|
||||||
|
{
|
||||||
|
readonly CPos pos;
|
||||||
|
readonly Color color;
|
||||||
|
|
||||||
|
public MarkerTileRenderable(CPos pos, Color color)
|
||||||
|
{
|
||||||
|
this.pos = pos;
|
||||||
|
this.color = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
public WPos Pos => WPos.Zero;
|
||||||
|
public int ZOffset => 0;
|
||||||
|
public bool IsDecoration => true;
|
||||||
|
|
||||||
|
public IRenderable WithZOffset(int newOffset) { return this; }
|
||||||
|
|
||||||
|
public IRenderable OffsetBy(in WVec vec)
|
||||||
|
{
|
||||||
|
return new MarkerTileRenderable(pos, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IRenderable AsDecoration() { return this; }
|
||||||
|
|
||||||
|
public IFinalizedRenderable PrepareRender(WorldRenderer wr) { return this; }
|
||||||
|
public void Render(WorldRenderer wr)
|
||||||
|
{
|
||||||
|
var map = wr.World.Map;
|
||||||
|
var r = map.Grid.Ramps[map.Ramp[pos]];
|
||||||
|
var wpos = map.CenterOfCell(pos) - new WVec(0, 0, r.CenterHeightOffset);
|
||||||
|
|
||||||
|
var corners = r.Corners.Select(corner => wr.Viewport.WorldToViewPx(wr.Screen3DPosition(wpos + corner))).ToList();
|
||||||
|
|
||||||
|
Game.Renderer.RgbaColorRenderer.FillRect(corners[0], corners[1], corners[2], corners[3], color);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RenderDebugGeometry(WorldRenderer wr) { }
|
||||||
|
public Rectangle ScreenBounds(WorldRenderer wr) { return Rectangle.Empty; }
|
||||||
|
}
|
||||||
|
}
|
||||||
234
OpenRA.Mods.Common/EditorBrushes/EditorMarkerLayerBrush.cs
Normal file
@@ -0,0 +1,234 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright (c) The OpenRA Developers and Contributors
|
||||||
|
* 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;
|
||||||
|
using System.Linq;
|
||||||
|
using OpenRA.Graphics;
|
||||||
|
using OpenRA.Mods.Common.Traits;
|
||||||
|
|
||||||
|
namespace OpenRA.Mods.Common.Widgets
|
||||||
|
{
|
||||||
|
public sealed class EditorMarkerLayerBrush : IEditorBrush
|
||||||
|
{
|
||||||
|
public int? Template;
|
||||||
|
|
||||||
|
readonly WorldRenderer worldRenderer;
|
||||||
|
readonly World world;
|
||||||
|
readonly EditorActionManager editorActionManager;
|
||||||
|
readonly MarkerLayerOverlay markerLayerOverlay;
|
||||||
|
readonly EditorViewportControllerWidget editorWidget;
|
||||||
|
|
||||||
|
PaintMarkerTileEditorAction action;
|
||||||
|
bool painting;
|
||||||
|
|
||||||
|
public EditorMarkerLayerBrush(EditorViewportControllerWidget editorWidget, int? id, WorldRenderer wr)
|
||||||
|
{
|
||||||
|
this.editorWidget = editorWidget;
|
||||||
|
worldRenderer = wr;
|
||||||
|
world = wr.World;
|
||||||
|
|
||||||
|
editorActionManager = world.WorldActor.Trait<EditorActionManager>();
|
||||||
|
markerLayerOverlay = world.WorldActor.Trait<MarkerLayerOverlay>();
|
||||||
|
|
||||||
|
Template = id;
|
||||||
|
worldRenderer = wr;
|
||||||
|
world = wr.World;
|
||||||
|
action = new PaintMarkerTileEditorAction(Template, markerLayerOverlay);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool HandleMouseInput(MouseInput mi)
|
||||||
|
{
|
||||||
|
if (mi.Button != MouseButton.Left && mi.Button != MouseButton.Right)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (mi.Button == MouseButton.Right)
|
||||||
|
{
|
||||||
|
if (mi.Event == MouseInputEvent.Up)
|
||||||
|
{
|
||||||
|
editorWidget.ClearBrush();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var cell = worldRenderer.Viewport.ViewToWorld(mi.Location);
|
||||||
|
|
||||||
|
if (mi.Button == MouseButton.Left && mi.Event != MouseInputEvent.Up)
|
||||||
|
{
|
||||||
|
action.Add(cell);
|
||||||
|
painting = true;
|
||||||
|
}
|
||||||
|
else if (painting && mi.Button == MouseButton.Left && mi.Event == MouseInputEvent.Up)
|
||||||
|
{
|
||||||
|
if (action.DidPaintTiles)
|
||||||
|
editorActionManager.Add(action);
|
||||||
|
|
||||||
|
action = new PaintMarkerTileEditorAction(Template, markerLayerOverlay);
|
||||||
|
painting = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Tick() { }
|
||||||
|
|
||||||
|
public void Dispose() { }
|
||||||
|
}
|
||||||
|
|
||||||
|
readonly struct PaintMarkerTile
|
||||||
|
{
|
||||||
|
public readonly CPos Cell;
|
||||||
|
public readonly int? Previous;
|
||||||
|
|
||||||
|
public PaintMarkerTile(CPos cell, int? previous)
|
||||||
|
{
|
||||||
|
Cell = cell;
|
||||||
|
Previous = previous;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PaintMarkerTileEditorAction : IEditorAction
|
||||||
|
{
|
||||||
|
[TranslationReference("amount", "type")]
|
||||||
|
const string AddedMarkerTiles = "notification-added-marker-tiles";
|
||||||
|
|
||||||
|
[TranslationReference("amount")]
|
||||||
|
const string RemovedMarkerTiles = "notification-removed-marker-tiles";
|
||||||
|
|
||||||
|
public string Text { get; private set; }
|
||||||
|
|
||||||
|
readonly int? type;
|
||||||
|
readonly MarkerLayerOverlay markerLayerOverlay;
|
||||||
|
|
||||||
|
readonly List<PaintMarkerTile> paintTiles = new();
|
||||||
|
|
||||||
|
public bool DidPaintTiles => paintTiles.Count > 0;
|
||||||
|
|
||||||
|
public PaintMarkerTileEditorAction(
|
||||||
|
int? type,
|
||||||
|
MarkerLayerOverlay markerLayerOverlay)
|
||||||
|
{
|
||||||
|
this.markerLayerOverlay = markerLayerOverlay;
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Execute()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Do()
|
||||||
|
{
|
||||||
|
foreach (var paintTile in paintTiles)
|
||||||
|
markerLayerOverlay.SetTile(paintTile.Cell, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Undo()
|
||||||
|
{
|
||||||
|
foreach (var paintTile in paintTiles)
|
||||||
|
markerLayerOverlay.SetTile(paintTile.Cell, paintTile.Previous);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Add(CPos target)
|
||||||
|
{
|
||||||
|
foreach (var cell in markerLayerOverlay.CalculateMirrorPositions(target))
|
||||||
|
{
|
||||||
|
var existing = markerLayerOverlay.CellLayer[cell];
|
||||||
|
if (existing == type)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
paintTiles.Add(new PaintMarkerTile(cell, existing));
|
||||||
|
markerLayerOverlay.SetTile(cell, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type != null)
|
||||||
|
Text = TranslationProvider.GetString(AddedMarkerTiles, Translation.Arguments("amount", paintTiles.Count, "type", type));
|
||||||
|
else
|
||||||
|
Text = TranslationProvider.GetString(RemovedMarkerTiles, Translation.Arguments("amount", paintTiles.Count));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ClearSelectedMarkerTilesEditorAction : IEditorAction
|
||||||
|
{
|
||||||
|
[TranslationReference("amount", "type")]
|
||||||
|
const string ClearedSelectedMarkerTiles = "notification-cleared-selected-marker-tiles";
|
||||||
|
|
||||||
|
public string Text { get; }
|
||||||
|
|
||||||
|
readonly MarkerLayerOverlay markerLayerOverlay;
|
||||||
|
readonly HashSet<CPos> tiles;
|
||||||
|
readonly int tile;
|
||||||
|
|
||||||
|
public ClearSelectedMarkerTilesEditorAction(
|
||||||
|
int tile,
|
||||||
|
MarkerLayerOverlay markerLayerOverlay)
|
||||||
|
{
|
||||||
|
this.tile = tile;
|
||||||
|
this.markerLayerOverlay = markerLayerOverlay;
|
||||||
|
|
||||||
|
tiles = new HashSet<CPos>(markerLayerOverlay.Tiles[tile]);
|
||||||
|
|
||||||
|
Text = TranslationProvider.GetString(ClearedSelectedMarkerTiles, Translation.Arguments("amount", tiles.Count, "type", tile));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Execute()
|
||||||
|
{
|
||||||
|
Do();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Do()
|
||||||
|
{
|
||||||
|
markerLayerOverlay.ClearSelected(tile);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Undo()
|
||||||
|
{
|
||||||
|
markerLayerOverlay.SetSelected(tile, tiles);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ClearAllMarkerTilesEditorAction : IEditorAction
|
||||||
|
{
|
||||||
|
[TranslationReference("amount")]
|
||||||
|
const string ClearedAllMarkerTiles = "notification-cleared-all-marker-tiles";
|
||||||
|
|
||||||
|
public string Text { get; }
|
||||||
|
|
||||||
|
readonly MarkerLayerOverlay markerLayerOverlay;
|
||||||
|
readonly Dictionary<int, HashSet<CPos>> tiles;
|
||||||
|
|
||||||
|
public ClearAllMarkerTilesEditorAction(
|
||||||
|
MarkerLayerOverlay markerLayerOverlay)
|
||||||
|
{
|
||||||
|
this.markerLayerOverlay = markerLayerOverlay;
|
||||||
|
tiles = new Dictionary<int, HashSet<CPos>>(markerLayerOverlay.Tiles);
|
||||||
|
|
||||||
|
var allTilesCount = tiles.Values.Select(x => x.Count).Sum();
|
||||||
|
|
||||||
|
Text = TranslationProvider.GetString(ClearedAllMarkerTiles, Translation.Arguments("amount", allTilesCount));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Execute()
|
||||||
|
{
|
||||||
|
Do();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Do()
|
||||||
|
{
|
||||||
|
markerLayerOverlay.ClearAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Undo()
|
||||||
|
{
|
||||||
|
markerLayerOverlay.SetAll(tiles);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
471
OpenRA.Mods.Common/Traits/World/MarkerLayerOverlay.cs
Normal file
@@ -0,0 +1,471 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright (c) The OpenRA Developers and Contributors
|
||||||
|
* 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;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using OpenRA.Graphics;
|
||||||
|
using OpenRA.Mods.Common.Graphics;
|
||||||
|
using OpenRA.Traits;
|
||||||
|
using Color = OpenRA.Primitives.Color;
|
||||||
|
|
||||||
|
namespace OpenRA.Mods.Common.Traits
|
||||||
|
{
|
||||||
|
[TraitLocation(SystemActors.EditorWorld)]
|
||||||
|
public class MarkerLayerOverlayInfo : TraitInfo
|
||||||
|
{
|
||||||
|
[Desc("A list of colors to be used for drawing.")]
|
||||||
|
public readonly Color[] Colors = new[]
|
||||||
|
{
|
||||||
|
Color.FromArgb(255, 0, 0),
|
||||||
|
Color.FromArgb(255, 127, 0),
|
||||||
|
Color.FromArgb(255, 238, 70),
|
||||||
|
Color.FromArgb(0, 255, 33),
|
||||||
|
Color.FromArgb(0, 255, 255),
|
||||||
|
Color.FromArgb(0, 42, 255),
|
||||||
|
Color.FromArgb(165, 0, 255),
|
||||||
|
Color.FromArgb(255, 0, 220),
|
||||||
|
};
|
||||||
|
|
||||||
|
[Desc("Default alpha blend.")]
|
||||||
|
public readonly int Alpha = 85;
|
||||||
|
|
||||||
|
[Desc("Color of the axis angle display.")]
|
||||||
|
public readonly Color AxisAngleColor = Color.Crimson;
|
||||||
|
|
||||||
|
public override object Create(ActorInitializer init)
|
||||||
|
{
|
||||||
|
return new MarkerLayerOverlay(init.Self, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class MarkerLayerOverlay : IRenderAnnotations, INotifyActorDisposing, IWorldLoaded
|
||||||
|
{
|
||||||
|
public class MarkerLayerFile
|
||||||
|
{
|
||||||
|
public Dictionary<int, List<int>> Tiles { get; set; }
|
||||||
|
public MarkerTileMirrorMode MirrorMode { get; set; }
|
||||||
|
public int NumSides { get; set; }
|
||||||
|
public int AxisAngle { get; set; }
|
||||||
|
public int TileAlpha { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
const double DegreesToRadians = Math.PI / 180;
|
||||||
|
|
||||||
|
readonly int[] validFlipModeSides = { 2, 4 };
|
||||||
|
|
||||||
|
public enum MarkerTileMirrorMode
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
Flip,
|
||||||
|
Rotate
|
||||||
|
}
|
||||||
|
|
||||||
|
readonly World world;
|
||||||
|
readonly WPos mapCenter;
|
||||||
|
readonly Color[] alphaBlendColors;
|
||||||
|
|
||||||
|
public readonly CellLayer<int?> CellLayer;
|
||||||
|
public readonly Dictionary<int, HashSet<CPos>> Tiles = new();
|
||||||
|
|
||||||
|
public bool Enabled = true;
|
||||||
|
public MarkerTileMirrorMode MirrorMode { get; private set; } = MarkerTileMirrorMode.None;
|
||||||
|
public MarkerLayerOverlayInfo Info { get; }
|
||||||
|
public int NumSides = 2;
|
||||||
|
public int AxisAngle;
|
||||||
|
public int TileAlpha
|
||||||
|
{
|
||||||
|
get => tileAlpha;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
tileAlpha = value;
|
||||||
|
UpdateTileAlpha();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int tileAlpha;
|
||||||
|
bool disposed;
|
||||||
|
|
||||||
|
public MarkerLayerOverlay(Actor self, MarkerLayerOverlayInfo info)
|
||||||
|
{
|
||||||
|
Info = info;
|
||||||
|
world = self.World;
|
||||||
|
var map = self.World.Map;
|
||||||
|
|
||||||
|
tileAlpha = info.Alpha;
|
||||||
|
alphaBlendColors = new Color[info.Colors.Length];
|
||||||
|
UpdateTileAlpha();
|
||||||
|
|
||||||
|
CellLayer = new CellLayer<int?>(map);
|
||||||
|
|
||||||
|
mapCenter = GetMapCenterWPos();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WorldLoaded(World w, WorldRenderer wr)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var modData = Game.ModData;
|
||||||
|
var mod = modData.Manifest.Metadata;
|
||||||
|
var directory = Path.Combine(Platform.SupportDir, "Editor", modData.Manifest.Id, mod.Version, "MarkerTiles");
|
||||||
|
if (!Directory.Exists(directory))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(world.Map.Package.Name))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var markerTileFilename = $"{Path.GetFileNameWithoutExtension(world.Map.Package.Name)}.json";
|
||||||
|
var markerTilePath = Path.Combine(directory, markerTileFilename);
|
||||||
|
if (!File.Exists(markerTilePath))
|
||||||
|
return;
|
||||||
|
|
||||||
|
using (var streamReader = new StreamReader(markerTilePath))
|
||||||
|
{
|
||||||
|
var content = streamReader.ReadToEnd();
|
||||||
|
var file = JsonConvert.DeserializeObject<MarkerLayerFile>(content);
|
||||||
|
|
||||||
|
TileAlpha = file.TileAlpha;
|
||||||
|
MirrorMode = file.MirrorMode;
|
||||||
|
NumSides = file.NumSides;
|
||||||
|
AxisAngle = file.AxisAngle;
|
||||||
|
|
||||||
|
var savedTilesHashSetDictionary = file.Tiles.ToDictionary(x => x.Key, x => x.Value.Select(bits => new CPos(bits)).ToHashSet());
|
||||||
|
SetAll(savedTilesHashSetDictionary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Log.Write("debug", "Failed to load map editor marker tiles.");
|
||||||
|
Log.Write("debug", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public MarkerLayerFile ToFile()
|
||||||
|
{
|
||||||
|
var tilesBitsDictionary = Tiles.ToDictionary(x => x.Key, x => x.Value.Select(cpos => cpos.Bits).ToList());
|
||||||
|
return new MarkerLayerFile
|
||||||
|
{
|
||||||
|
Tiles = tilesBitsDictionary,
|
||||||
|
TileAlpha = TileAlpha,
|
||||||
|
MirrorMode = MirrorMode,
|
||||||
|
NumSides = NumSides,
|
||||||
|
AxisAngle = AxisAngle,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateTileAlpha()
|
||||||
|
{
|
||||||
|
for (var i = 0; i < Info.Colors.Length; i++)
|
||||||
|
alphaBlendColors[i] = Color.FromArgb(tileAlpha, Info.Colors[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ClearSelected(int tileType)
|
||||||
|
{
|
||||||
|
if (Tiles.TryGetValue(tileType, out var set))
|
||||||
|
foreach (var pos in set)
|
||||||
|
SetTile(pos, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ClearAll()
|
||||||
|
{
|
||||||
|
foreach (var position in Tiles.SelectMany(x => x.Value))
|
||||||
|
CellLayer[position] = null;
|
||||||
|
|
||||||
|
Tiles.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetAll(Dictionary<int, HashSet<CPos>> newTiles)
|
||||||
|
{
|
||||||
|
ClearAll();
|
||||||
|
|
||||||
|
foreach (var type in newTiles)
|
||||||
|
{
|
||||||
|
var set = new HashSet<CPos>();
|
||||||
|
Tiles.Add(type.Key, set);
|
||||||
|
|
||||||
|
foreach (var position in type.Value)
|
||||||
|
{
|
||||||
|
if (!world.Map.Contains(position))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
set.Add(position);
|
||||||
|
CellLayer[position] = type.Key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetSelected(int tile, HashSet<CPos> newTiles)
|
||||||
|
{
|
||||||
|
var type = Tiles[tile];
|
||||||
|
foreach (var pos in type)
|
||||||
|
SetTile(pos, null);
|
||||||
|
|
||||||
|
type.Clear();
|
||||||
|
|
||||||
|
foreach (var pos in newTiles)
|
||||||
|
{
|
||||||
|
type.Add(pos);
|
||||||
|
CellLayer[pos] = tile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetMirrorMode(MarkerTileMirrorMode mirrorMode)
|
||||||
|
{
|
||||||
|
MirrorMode = mirrorMode;
|
||||||
|
|
||||||
|
if (mirrorMode == MarkerTileMirrorMode.Flip && !validFlipModeSides.Contains(NumSides))
|
||||||
|
NumSides = validFlipModeSides[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
WPos GetMapCenterWPos()
|
||||||
|
{
|
||||||
|
var map = world.Map;
|
||||||
|
|
||||||
|
var boundsWidth = map.AllCells.BottomRight.X - map.AllCells.TopLeft.X;
|
||||||
|
var boundsHeight = map.AllCells.BottomRight.Y - map.AllCells.TopLeft.Y;
|
||||||
|
|
||||||
|
var xIsOdd = boundsWidth % 2 != 0;
|
||||||
|
var yIsOdd = boundsHeight % 2 != 0;
|
||||||
|
|
||||||
|
var xCenter = boundsWidth / 2;
|
||||||
|
var yCenter = boundsHeight / 2;
|
||||||
|
|
||||||
|
var centerWpos = map.CenterOfCell(new CPos(xCenter, yCenter));
|
||||||
|
if (xIsOdd)
|
||||||
|
centerWpos += new WVec(512, 0, 0);
|
||||||
|
|
||||||
|
if (yIsOdd)
|
||||||
|
centerWpos += new WVec(0, 512, 0);
|
||||||
|
|
||||||
|
return centerWpos;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CPos[] CalculateMirrorPositions(CPos cell)
|
||||||
|
{
|
||||||
|
const int DegreesInCircle = 360;
|
||||||
|
|
||||||
|
var map = world.Map;
|
||||||
|
|
||||||
|
var wpos = map.CenterOfCell(cell);
|
||||||
|
var wposVec = wpos - mapCenter;
|
||||||
|
var angle = DegreesInCircle / NumSides;
|
||||||
|
|
||||||
|
var targets = new List<CPos>();
|
||||||
|
|
||||||
|
if (map.Contains(cell))
|
||||||
|
targets.Add(cell);
|
||||||
|
|
||||||
|
if (MirrorMode == MarkerTileMirrorMode.Flip)
|
||||||
|
{
|
||||||
|
var startAxis = new WVec(1024, 0, 0);
|
||||||
|
var axes = new List<WVec>();
|
||||||
|
for (var i = 0; i < NumSides / 2; i++)
|
||||||
|
{
|
||||||
|
var targetAngle = (i * angle + AxisAngle) * DegreesToRadians;
|
||||||
|
var point = new WVec((int)(startAxis.X * Math.Cos(targetAngle) - startAxis.Y * Math.Sin(targetAngle)),
|
||||||
|
(int)(startAxis.X * Math.Sin(targetAngle) + startAxis.Y * Math.Cos(targetAngle)),
|
||||||
|
wpos.Z);
|
||||||
|
|
||||||
|
axes.Add(point);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var axis in axes)
|
||||||
|
{
|
||||||
|
var point = GetAxisMirrorPoint(mapCenter, axis, wpos);
|
||||||
|
var cellPoint = map.CellContaining(point);
|
||||||
|
|
||||||
|
if (map.Contains(cellPoint))
|
||||||
|
targets.Add(cellPoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mirror twice for both
|
||||||
|
if (axes.Count == 2)
|
||||||
|
{
|
||||||
|
var point = GetAxisMirrorPoint(mapCenter, axes[0], wpos);
|
||||||
|
point = GetAxisMirrorPoint(mapCenter, axes[1], point);
|
||||||
|
var cellPoint = map.CellContaining(point);
|
||||||
|
|
||||||
|
if (map.Contains(cellPoint))
|
||||||
|
targets.Add(cellPoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////
|
||||||
|
|
||||||
|
static WPos GetAxisMirrorPoint(WPos center, WVec axis, WPos point)
|
||||||
|
{
|
||||||
|
var testPoint = center - new WVec(point.X, point.Y, 0);
|
||||||
|
var a = axis.Y;
|
||||||
|
var b = -axis.X;
|
||||||
|
var c = -a * 0 - b * 0;
|
||||||
|
|
||||||
|
var m = Math.Sqrt(a * a + b * b);
|
||||||
|
var aDash = a / m;
|
||||||
|
var bDash = b / m;
|
||||||
|
var cDash = c / m;
|
||||||
|
|
||||||
|
var d = aDash * testPoint.X + bDash * testPoint.Y + cDash;
|
||||||
|
var pxDash = testPoint.X - 2 * aDash * d;
|
||||||
|
var pyDash = testPoint.Y - 2 * bDash * d;
|
||||||
|
|
||||||
|
return new WPos((int)pxDash + center.X, (int)pyDash + center.Y, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (MirrorMode == MarkerTileMirrorMode.Rotate)
|
||||||
|
{
|
||||||
|
// Rotate
|
||||||
|
var flipAngleRadians = DegreesToRadians * angle;
|
||||||
|
|
||||||
|
var sidesAreEven = NumSides % 2 == 0;
|
||||||
|
var oddSideStartIndex = (int)Math.Floor((double)NumSides / 2);
|
||||||
|
var startIndex = sidesAreEven ? 0 : -oddSideStartIndex;
|
||||||
|
var count = sidesAreEven ? NumSides : oddSideStartIndex + 1;
|
||||||
|
|
||||||
|
for (var i = startIndex; i < count; i++)
|
||||||
|
{
|
||||||
|
var targetAngle = i * flipAngleRadians;
|
||||||
|
var point = new WPos((int)(wposVec.X * Math.Cos(targetAngle) - wposVec.Y * Math.Sin(targetAngle)),
|
||||||
|
(int)(wposVec.X * Math.Sin(targetAngle) + wposVec.Y * Math.Cos(targetAngle)),
|
||||||
|
wpos.Z);
|
||||||
|
|
||||||
|
var cellPoint = map.CellContaining(point + new WVec(mapCenter.X, mapCenter.Y, 0));
|
||||||
|
|
||||||
|
if (map.Contains(cellPoint))
|
||||||
|
targets.Add(cellPoint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return targets.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetTile(CPos target, int? tileType)
|
||||||
|
{
|
||||||
|
if (!world.Map.Contains(target))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Maintain map of tile types for selective clearing
|
||||||
|
var prevTile = CellLayer[target];
|
||||||
|
if (prevTile.HasValue && Tiles.TryGetValue(prevTile.Value, out var set))
|
||||||
|
set.Remove(target);
|
||||||
|
|
||||||
|
if (tileType.HasValue)
|
||||||
|
{
|
||||||
|
if (Tiles.TryGetValue(tileType.Value, out set))
|
||||||
|
set.Add(target);
|
||||||
|
else
|
||||||
|
Tiles.Add(tileType.Value, new HashSet<CPos> { target });
|
||||||
|
|
||||||
|
CellLayer[target] = tileType;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
CellLayer[target] = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
void INotifyActorDisposing.Disposing(Actor self)
|
||||||
|
{
|
||||||
|
if (disposed)
|
||||||
|
return;
|
||||||
|
|
||||||
|
disposed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
readonly struct MapLine
|
||||||
|
{
|
||||||
|
public readonly float2 Start;
|
||||||
|
public readonly float2 End;
|
||||||
|
|
||||||
|
public MapLine(float2 start, float2 end)
|
||||||
|
{
|
||||||
|
Start = start;
|
||||||
|
End = end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerable<IRenderable> IRenderAnnotations.RenderAnnotations(Actor self, WorldRenderer wr)
|
||||||
|
{
|
||||||
|
if (!Enabled)
|
||||||
|
yield break;
|
||||||
|
|
||||||
|
foreach (var cellPair in Tiles)
|
||||||
|
foreach (var cellPos in cellPair.Value)
|
||||||
|
yield return new MarkerTileRenderable(cellPos, alphaBlendColors[cellPair.Key]);
|
||||||
|
|
||||||
|
if (MirrorMode != MarkerTileMirrorMode.Flip)
|
||||||
|
yield break;
|
||||||
|
|
||||||
|
const int LineWidth = 1;
|
||||||
|
|
||||||
|
var color = Info.AxisAngleColor;
|
||||||
|
var targetAngle = AxisAngle * DegreesToRadians;
|
||||||
|
|
||||||
|
var mapCenterFloat = new float2(mapCenter.X, mapCenter.Y);
|
||||||
|
var mapBoundsWorldSize = mapCenterFloat * 2;
|
||||||
|
|
||||||
|
// Create our axis lines
|
||||||
|
var horizontalVec = new float2(1, 0);
|
||||||
|
var verticalVec = new float2(0, 1);
|
||||||
|
var edges = new[]
|
||||||
|
{
|
||||||
|
new MapLine(mapCenterFloat, mapCenterFloat + horizontalVec),
|
||||||
|
new MapLine(mapCenterFloat, mapCenterFloat + verticalVec),
|
||||||
|
};
|
||||||
|
|
||||||
|
var sourceAxes = new[] { verticalVec, -verticalVec, horizontalVec, -horizontalVec };
|
||||||
|
for (var i = 0; i < NumSides; i++)
|
||||||
|
{
|
||||||
|
var isOpposite = i % 2 != 0;
|
||||||
|
var sourceAxis = sourceAxes[i];
|
||||||
|
var rotatedAxis = new float2(
|
||||||
|
(float)(sourceAxis.X * Math.Cos(targetAngle) - sourceAxis.Y * Math.Sin(targetAngle)),
|
||||||
|
(float)(sourceAxis.X * Math.Sin(targetAngle) + sourceAxis.Y * Math.Cos(targetAngle)));
|
||||||
|
|
||||||
|
var axisLine = new MapLine(float2.Zero, rotatedAxis);
|
||||||
|
var collisionPoints = FindEdgeCollisionPoints(edges, axisLine);
|
||||||
|
|
||||||
|
var closestCollisionPoint = collisionPoints.OrderBy(x => x.LengthSquared).First();
|
||||||
|
if (isOpposite)
|
||||||
|
closestCollisionPoint *= -1;
|
||||||
|
|
||||||
|
var resultPos = new WVec((int)closestCollisionPoint.X, (int)closestCollisionPoint.Y, 0);
|
||||||
|
yield return new LineAnnotationRenderable(mapCenter, mapCenter + resultPos, LineWidth, color, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static float2[] FindEdgeCollisionPoints(MapLine[] mapEdges, MapLine axis)
|
||||||
|
{
|
||||||
|
var collisionResults = new List<float2>();
|
||||||
|
foreach (var mapEdge in mapEdges)
|
||||||
|
if (FindIntersection(axis.Start, axis.End, mapEdge.Start, mapEdge.End, out var collisionVec))
|
||||||
|
collisionResults.Add(collisionVec);
|
||||||
|
|
||||||
|
return collisionResults.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool FindIntersection(float2 a1, float2 a2, float2 b1, float2 b2, out float2 result)
|
||||||
|
{
|
||||||
|
result = float2.Zero;
|
||||||
|
var d = (a1.X - a2.X) * (b1.Y - b2.Y) - (a1.Y - a2.Y) * (b1.X - b2.X);
|
||||||
|
|
||||||
|
// check if lines are parallel
|
||||||
|
if (d == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var px = (a1.X * a2.Y - a1.Y * a2.X) * (b1.X - b2.X) - (a1.X - a2.X) * (b1.X * b2.Y - b1.Y * b2.X);
|
||||||
|
var py = (a1.X * a2.Y - a1.Y * a2.X) * (b1.Y - b2.Y) - (a1.Y - a2.Y) * (b1.X * b2.Y - b1.Y * b2.X);
|
||||||
|
|
||||||
|
result = new float2(px, py) / d;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IRenderAnnotations.SpatiallyPartitionable => false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright (c) The OpenRA Developers and Contributors
|
||||||
|
* 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.Mods.Common.UpdateRules.Rules
|
||||||
|
{
|
||||||
|
public class AddMarkerLayerOverlay : UpdateRule
|
||||||
|
{
|
||||||
|
public override string Name => "Add MarkerLayerOverlay.";
|
||||||
|
|
||||||
|
public override string Description =>
|
||||||
|
"Add MarkerLayerOverlay to editor.";
|
||||||
|
|
||||||
|
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
|
||||||
|
{
|
||||||
|
var editorWorldNode = actorNode.LastChildMatching("EditorWorld");
|
||||||
|
if (editorWorldNode == null)
|
||||||
|
yield break;
|
||||||
|
|
||||||
|
var markerLayerOverlayNode = new MiniYamlNodeBuilder("MarkerLayerOverlay", new MiniYamlBuilder(""));
|
||||||
|
editorWorldNode.AddNode(markerLayerOverlayNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -86,6 +86,7 @@ namespace OpenRA.Mods.Common.UpdateRules
|
|||||||
new ReplacePaletteModifiers(),
|
new ReplacePaletteModifiers(),
|
||||||
new RemoveConyardChronoReturnAnimation(),
|
new RemoveConyardChronoReturnAnimation(),
|
||||||
new RemoveEditorSelectionLayerProperties(),
|
new RemoveEditorSelectionLayerProperties(),
|
||||||
|
new AddMarkerLayerOverlay(),
|
||||||
|
|
||||||
// Execute these rules last to avoid premature yaml merge crashes.
|
// Execute these rules last to avoid premature yaml merge crashes.
|
||||||
new ReplaceCloakPalette(),
|
new ReplaceCloakPalette(),
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
public readonly string TooltipTemplate;
|
public readonly string TooltipTemplate;
|
||||||
public readonly EditorDefaultBrush DefaultBrush;
|
public readonly EditorDefaultBrush DefaultBrush;
|
||||||
|
|
||||||
|
public event Action BrushChanged;
|
||||||
|
|
||||||
readonly Lazy<TooltipContainerWidget> tooltipContainer;
|
readonly Lazy<TooltipContainerWidget> tooltipContainer;
|
||||||
readonly WorldRenderer worldRenderer;
|
readonly WorldRenderer worldRenderer;
|
||||||
|
|
||||||
@@ -46,6 +48,8 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
CurrentBrush?.Dispose();
|
CurrentBrush?.Dispose();
|
||||||
|
|
||||||
CurrentBrush = brush ?? DefaultBrush;
|
CurrentBrush = brush ?? DefaultBrush;
|
||||||
|
|
||||||
|
BrushChanged?.Invoke();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void MouseEntered()
|
public override void MouseEntered()
|
||||||
|
|||||||
259
OpenRA.Mods.Common/Widgets/Logic/Editor/MapMarkerTilesLogic.cs
Normal file
@@ -0,0 +1,259 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright (c) The OpenRA Developers and Contributors
|
||||||
|
* 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;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Linq;
|
||||||
|
using OpenRA.Graphics;
|
||||||
|
using OpenRA.Mods.Common.Traits;
|
||||||
|
using OpenRA.Widgets;
|
||||||
|
using static OpenRA.Mods.Common.Traits.MarkerLayerOverlay;
|
||||||
|
|
||||||
|
namespace OpenRA.Mods.Common.Widgets.Logic
|
||||||
|
{
|
||||||
|
public class MapMarkerTilesLogic : ChromeLogic
|
||||||
|
{
|
||||||
|
[TranslationReference]
|
||||||
|
const string MarkerMirrorModeNoneTranslation = "mirror-mode.none";
|
||||||
|
|
||||||
|
[TranslationReference]
|
||||||
|
const string MarkerMirrorModeFlipTranslation = "mirror-mode.flip";
|
||||||
|
|
||||||
|
[TranslationReference]
|
||||||
|
const string MarkerMirrorModeRotateTranslation = "mirror-mode.rotate";
|
||||||
|
|
||||||
|
readonly EditorActionManager editorActionManager;
|
||||||
|
readonly MarkerLayerOverlay markerLayerTrait;
|
||||||
|
readonly ScrollPanelWidget tileColorPanel;
|
||||||
|
readonly SliderWidget alphaSlider;
|
||||||
|
readonly LabelWidget alphaValueLabel;
|
||||||
|
readonly DropDownButtonWidget modeDropdown;
|
||||||
|
readonly SliderWidget rotateNumSidesSlider;
|
||||||
|
readonly DropDownButtonWidget flipNumSidesDropdown;
|
||||||
|
readonly LabelWidget numSidesLabel;
|
||||||
|
readonly LabelWidget rotateNumSidesValueLabel;
|
||||||
|
readonly LabelWidget axisAngleLabel;
|
||||||
|
readonly SliderWidget axisAngleSlider;
|
||||||
|
readonly LabelWidget axisAngleValueLabel;
|
||||||
|
readonly ButtonWidget clearSelectedButtonWidget;
|
||||||
|
readonly ButtonWidget clearAllButtonWidget;
|
||||||
|
readonly EditorViewportControllerWidget editor;
|
||||||
|
|
||||||
|
int? markerTile;
|
||||||
|
|
||||||
|
[ObjectCreator.UseCtor]
|
||||||
|
public MapMarkerTilesLogic(Widget widget, World world, ModData modData, WorldRenderer worldRenderer, Dictionary<string, MiniYaml> logicArgs)
|
||||||
|
{
|
||||||
|
markerLayerTrait = world.WorldActor.Trait<MarkerLayerOverlay>();
|
||||||
|
editorActionManager = world.WorldActor.Trait<EditorActionManager>();
|
||||||
|
|
||||||
|
editor = widget.Parent.Parent.Parent.Parent.Get<EditorViewportControllerWidget>("MAP_EDITOR");
|
||||||
|
editor.BrushChanged += HandleBrushChanged;
|
||||||
|
|
||||||
|
tileColorPanel = widget.Get<ScrollPanelWidget>("TILE_COLOR_PANEL");
|
||||||
|
{
|
||||||
|
tileColorPanel.Layout = new GridLayout(tileColorPanel);
|
||||||
|
var colorSwatchTemplate = tileColorPanel.Get<ScrollItemWidget>("TILE_COLOR_TEMPLATE");
|
||||||
|
var iconTemplate = tileColorPanel.Get<ScrollItemWidget>("TILE_ICON_TEMPLATE");
|
||||||
|
tileColorPanel.RemoveChildren();
|
||||||
|
|
||||||
|
var colors = markerLayerTrait.Info.Colors;
|
||||||
|
for (var colorIndex = 0; colorIndex < colors.Length; colorIndex++)
|
||||||
|
{
|
||||||
|
var scrollItem = SetupColorSwatchItem(colorIndex, colorSwatchTemplate);
|
||||||
|
tileColorPanel.AddChild(scrollItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
var eraseItem = SetupEraseItem(iconTemplate);
|
||||||
|
tileColorPanel.AddChild(eraseItem);
|
||||||
|
|
||||||
|
///////
|
||||||
|
|
||||||
|
ScrollItemWidget SetupColorSwatchItem(int index, ScrollItemWidget template)
|
||||||
|
{
|
||||||
|
var item = ScrollItemWidget.Setup(template,
|
||||||
|
() => markerTile == index,
|
||||||
|
() =>
|
||||||
|
{
|
||||||
|
markerTile = index;
|
||||||
|
editor.SetBrush(new EditorMarkerLayerBrush(editor, index, worldRenderer));
|
||||||
|
});
|
||||||
|
|
||||||
|
var colorWidget = item.Get<ColorBlockWidget>("TILE_PREVIEW");
|
||||||
|
colorWidget.GetColor = () => colors[index];
|
||||||
|
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
ScrollItemWidget SetupEraseItem(ScrollItemWidget template)
|
||||||
|
{
|
||||||
|
var item = ScrollItemWidget.Setup(template,
|
||||||
|
() => markerTile == null && editor.CurrentBrush != null && editor.CurrentBrush is EditorMarkerLayerBrush,
|
||||||
|
() =>
|
||||||
|
{
|
||||||
|
markerTile = null;
|
||||||
|
editor.SetBrush(new EditorMarkerLayerBrush(editor, null, worldRenderer));
|
||||||
|
});
|
||||||
|
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
clearSelectedButtonWidget = widget.Get<ButtonWidget>("CLEAR_CURRENT_BUTTON");
|
||||||
|
clearSelectedButtonWidget.IsDisabled = () => markerTile == null;
|
||||||
|
clearSelectedButtonWidget.OnClick = ClearSelected;
|
||||||
|
|
||||||
|
clearAllButtonWidget = widget.Get<ButtonWidget>("CLEAR_ALL_BUTTON");
|
||||||
|
clearAllButtonWidget.OnClick = ClearAll;
|
||||||
|
|
||||||
|
alphaSlider = widget.Get<SliderWidget>("ALPHA_SLIDER");
|
||||||
|
alphaSlider.MinimumValue = 1;
|
||||||
|
alphaSlider.MaximumValue = 255;
|
||||||
|
alphaSlider.Ticks = 12;
|
||||||
|
alphaSlider.OnChange += (val) => markerLayerTrait.TileAlpha = (int)val;
|
||||||
|
alphaSlider.GetValue = () => markerLayerTrait.TileAlpha;
|
||||||
|
|
||||||
|
alphaValueLabel = widget.Get<LabelWidget>("ALPHA_VALUE");
|
||||||
|
alphaValueLabel.GetText = () => markerLayerTrait.TileAlpha.ToString(NumberFormatInfo.InvariantInfo);
|
||||||
|
|
||||||
|
modeDropdown = widget.Get<DropDownButtonWidget>("MODE_DROPDOWN");
|
||||||
|
modeDropdown.OnMouseDown = _ => ShowMarkerModeDropDown(modeDropdown);
|
||||||
|
modeDropdown.GetText = () =>
|
||||||
|
{
|
||||||
|
switch (markerLayerTrait.MirrorMode)
|
||||||
|
{
|
||||||
|
case MarkerTileMirrorMode.None:
|
||||||
|
return TranslationProvider.GetString(MarkerMirrorModeNoneTranslation);
|
||||||
|
case MarkerTileMirrorMode.Flip:
|
||||||
|
return TranslationProvider.GetString(MarkerMirrorModeFlipTranslation);
|
||||||
|
case MarkerTileMirrorMode.Rotate:
|
||||||
|
return TranslationProvider.GetString(MarkerMirrorModeRotateTranslation);
|
||||||
|
default:
|
||||||
|
throw new ArgumentException($"Couldn't find translation for marker tile mirror mode '{markerLayerTrait.MirrorMode}'");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
bool IsFlipMode() => markerLayerTrait.MirrorMode == MarkerTileMirrorMode.Flip;
|
||||||
|
bool IsRotateMode() => markerLayerTrait.MirrorMode == MarkerTileMirrorMode.Rotate;
|
||||||
|
|
||||||
|
numSidesLabel = widget.Get<LabelWidget>("NUM_SIDES_LABEL");
|
||||||
|
numSidesLabel.IsVisible = () => IsFlipMode() || IsRotateMode();
|
||||||
|
|
||||||
|
rotateNumSidesSlider = widget.Get<SliderWidget>("ROTATE_NUM_SIDES_SLIDER");
|
||||||
|
rotateNumSidesSlider.MinimumValue = 2;
|
||||||
|
rotateNumSidesSlider.MaximumValue = 8;
|
||||||
|
rotateNumSidesSlider.Ticks = 7;
|
||||||
|
rotateNumSidesSlider.IsVisible = IsRotateMode;
|
||||||
|
rotateNumSidesSlider.OnChange += (val) => markerLayerTrait.NumSides = (int)val;
|
||||||
|
rotateNumSidesSlider.GetValue = () => markerLayerTrait.NumSides;
|
||||||
|
|
||||||
|
rotateNumSidesValueLabel = widget.Get<LabelWidget>("ROTATE_NUM_SIDES_VALUE");
|
||||||
|
rotateNumSidesValueLabel.IsVisible = IsRotateMode;
|
||||||
|
rotateNumSidesValueLabel.GetText = () => markerLayerTrait.NumSides.ToString(NumberFormatInfo.InvariantInfo);
|
||||||
|
|
||||||
|
flipNumSidesDropdown = widget.Get<DropDownButtonWidget>("FLIP_NUM_SIDES_DROPDOWN");
|
||||||
|
flipNumSidesDropdown.OnMouseDown = _ => ShowFlipNumSidesDropDown(flipNumSidesDropdown);
|
||||||
|
flipNumSidesDropdown.IsVisible = IsFlipMode;
|
||||||
|
flipNumSidesDropdown.GetText = () => markerLayerTrait.NumSides.ToString(NumberFormatInfo.InvariantInfo);
|
||||||
|
|
||||||
|
axisAngleLabel = widget.Get<LabelWidget>("AXIS_ANGLE_LABEL");
|
||||||
|
axisAngleLabel.IsVisible = IsFlipMode;
|
||||||
|
|
||||||
|
axisAngleSlider = widget.Get<SliderWidget>("AXIS_ANGLE_SLIDER");
|
||||||
|
axisAngleSlider.MinimumValue = 0;
|
||||||
|
axisAngleSlider.MaximumValue = 11;
|
||||||
|
axisAngleSlider.Ticks = 12;
|
||||||
|
axisAngleSlider.IsVisible = IsFlipMode;
|
||||||
|
axisAngleSlider.OnChange += (val) => markerLayerTrait.AxisAngle = (int)val * 15;
|
||||||
|
axisAngleSlider.GetValue = () => markerLayerTrait.AxisAngle / 15;
|
||||||
|
|
||||||
|
axisAngleValueLabel = widget.Get<LabelWidget>("AXIS_ANGLE_VALUE");
|
||||||
|
axisAngleValueLabel.IsVisible = IsFlipMode;
|
||||||
|
axisAngleValueLabel.GetText = () => markerLayerTrait.AxisAngle.ToString(NumberFormatInfo.InvariantInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
editor.BrushChanged -= HandleBrushChanged;
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleBrushChanged()
|
||||||
|
{
|
||||||
|
if (editor.CurrentBrush is not EditorMarkerLayerBrush)
|
||||||
|
{
|
||||||
|
markerTile = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClearSelected()
|
||||||
|
{
|
||||||
|
if (editor.CurrentBrush is EditorMarkerLayerBrush markerLayerBrush &&
|
||||||
|
markerLayerBrush.Template.HasValue &&
|
||||||
|
markerLayerTrait.Tiles.TryGetValue(markerLayerBrush.Template.Value, out var tiles) &&
|
||||||
|
tiles.Count > 0)
|
||||||
|
editorActionManager.Add(new ClearSelectedMarkerTilesEditorAction(markerLayerBrush.Template.Value, markerLayerTrait));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClearAll()
|
||||||
|
{
|
||||||
|
if (markerLayerTrait.Tiles.Count > 0 && markerLayerTrait.Tiles.Any(x => x.Value.Count > 0))
|
||||||
|
editorActionManager.Add(new ClearAllMarkerTilesEditorAction(markerLayerTrait));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShowMarkerModeDropDown(DropDownButtonWidget dropdown)
|
||||||
|
{
|
||||||
|
ScrollItemWidget SetupItem(MarkerTileMirrorMode mode, ScrollItemWidget itemTemplate)
|
||||||
|
{
|
||||||
|
var item = ScrollItemWidget.Setup(itemTemplate,
|
||||||
|
() => markerLayerTrait.MirrorMode == mode,
|
||||||
|
() => markerLayerTrait.SetMirrorMode(mode));
|
||||||
|
|
||||||
|
item.Get<LabelWidget>("LABEL").GetText = () =>
|
||||||
|
{
|
||||||
|
switch (mode)
|
||||||
|
{
|
||||||
|
case MarkerTileMirrorMode.None:
|
||||||
|
return TranslationProvider.GetString(MarkerMirrorModeNoneTranslation);
|
||||||
|
case MarkerTileMirrorMode.Flip:
|
||||||
|
return TranslationProvider.GetString(MarkerMirrorModeFlipTranslation);
|
||||||
|
case MarkerTileMirrorMode.Rotate:
|
||||||
|
return TranslationProvider.GetString(MarkerMirrorModeRotateTranslation);
|
||||||
|
default:
|
||||||
|
throw new ArgumentException($"Couldn't find translation for marker tile mirror mode '{mode}'");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
var options = new[] { MarkerTileMirrorMode.None, MarkerTileMirrorMode.Flip, MarkerTileMirrorMode.Rotate };
|
||||||
|
dropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 150, options, SetupItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShowFlipNumSidesDropDown(DropDownButtonWidget dropdown)
|
||||||
|
{
|
||||||
|
ScrollItemWidget SetupItem(int value, ScrollItemWidget itemTemplate)
|
||||||
|
{
|
||||||
|
var item = ScrollItemWidget.Setup(itemTemplate,
|
||||||
|
() => markerLayerTrait.NumSides == value,
|
||||||
|
() => markerLayerTrait.NumSides = value);
|
||||||
|
|
||||||
|
item.Get<LabelWidget>("LABEL").GetText = () => value.ToString(NumberFormatInfo.InvariantInfo);
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
var options = new[] { 2, 4 };
|
||||||
|
dropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 150, options, SetupItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,13 +11,14 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using OpenRA.Graphics;
|
||||||
using OpenRA.Mods.Common.Lint;
|
using OpenRA.Mods.Common.Lint;
|
||||||
using OpenRA.Mods.Common.Traits;
|
using OpenRA.Mods.Common.Traits;
|
||||||
using OpenRA.Widgets;
|
using OpenRA.Widgets;
|
||||||
|
|
||||||
namespace OpenRA.Mods.Common.Widgets.Logic
|
namespace OpenRA.Mods.Common.Widgets.Logic
|
||||||
{
|
{
|
||||||
[ChromeLogicArgsHotkeys("ToggleGridOverlayKey", "ToggleBuildableOverlayKey")]
|
[ChromeLogicArgsHotkeys("ToggleGridOverlayKey", "ToggleBuildableOverlayKey", "ToggleMarkerOverlayKey")]
|
||||||
public class MapOverlaysLogic : ChromeLogic
|
public class MapOverlaysLogic : ChromeLogic
|
||||||
{
|
{
|
||||||
[Flags]
|
[Flags]
|
||||||
@@ -26,19 +27,19 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
None = 0,
|
None = 0,
|
||||||
Grid = 1,
|
Grid = 1,
|
||||||
Buildable = 2,
|
Buildable = 2,
|
||||||
|
Marker = 4,
|
||||||
}
|
}
|
||||||
|
|
||||||
readonly TerrainGeometryOverlay terrainGeometryTrait;
|
readonly TerrainGeometryOverlay terrainGeometryTrait;
|
||||||
readonly BuildableTerrainOverlay buildableTerrainTrait;
|
readonly BuildableTerrainOverlay buildableTerrainTrait;
|
||||||
readonly Widget widget;
|
readonly MarkerLayerOverlay markerLayerTrait;
|
||||||
|
|
||||||
[ObjectCreator.UseCtor]
|
[ObjectCreator.UseCtor]
|
||||||
public MapOverlaysLogic(Widget widget, World world, ModData modData, Dictionary<string, MiniYaml> logicArgs)
|
public MapOverlaysLogic(Widget widget, World world, ModData modData, WorldRenderer worldRenderer, Dictionary<string, MiniYaml> logicArgs)
|
||||||
{
|
{
|
||||||
this.widget = widget;
|
|
||||||
|
|
||||||
terrainGeometryTrait = world.WorldActor.Trait<TerrainGeometryOverlay>();
|
terrainGeometryTrait = world.WorldActor.Trait<TerrainGeometryOverlay>();
|
||||||
buildableTerrainTrait = world.WorldActor.Trait<BuildableTerrainOverlay>();
|
buildableTerrainTrait = world.WorldActor.Trait<BuildableTerrainOverlay>();
|
||||||
|
markerLayerTrait = world.WorldActor.Trait<MarkerLayerOverlay>();
|
||||||
|
|
||||||
var toggleGridKey = new HotkeyReference();
|
var toggleGridKey = new HotkeyReference();
|
||||||
if (logicArgs.TryGetValue("ToggleGridOverlayKey", out var yaml))
|
if (logicArgs.TryGetValue("ToggleGridOverlayKey", out var yaml))
|
||||||
@@ -48,6 +49,10 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
if (logicArgs.TryGetValue("ToggleBuildableOverlayKey", out yaml))
|
if (logicArgs.TryGetValue("ToggleBuildableOverlayKey", out yaml))
|
||||||
toggleBuildableKey = modData.Hotkeys[yaml.Value];
|
toggleBuildableKey = modData.Hotkeys[yaml.Value];
|
||||||
|
|
||||||
|
var toggleMarkerKey = new HotkeyReference();
|
||||||
|
if (logicArgs.TryGetValue("ToggleMarkerOverlayKey", out yaml))
|
||||||
|
toggleMarkerKey = modData.Hotkeys[yaml.Value];
|
||||||
|
|
||||||
var keyhandler = widget.Get<LogicKeyListenerWidget>("OVERLAY_KEYHANDLER");
|
var keyhandler = widget.Get<LogicKeyListenerWidget>("OVERLAY_KEYHANDLER");
|
||||||
keyhandler.AddHandler(e =>
|
keyhandler.AddHandler(e =>
|
||||||
{
|
{
|
||||||
@@ -66,6 +71,12 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (toggleMarkerKey.IsActivatedBy(e))
|
||||||
|
{
|
||||||
|
markerLayerTrait.Enabled ^= true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -84,23 +95,33 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
|
|
||||||
Widget CreateOverlaysPanel()
|
Widget CreateOverlaysPanel()
|
||||||
{
|
{
|
||||||
var categoriesPanel = widget.Get<Widget>("TOOLS_WIDGETS");
|
var categoriesPanel = Ui.LoadWidget("OVERLAY_PANEL", null, new WidgetArgs());
|
||||||
var showGridCheckbox = categoriesPanel.Get<CheckboxWidget>("SHOW_TILE_GRID");
|
var categoryTemplate = categoriesPanel.Get<CheckboxWidget>("CATEGORY_TEMPLATE");
|
||||||
var showBuildableAreaCheckbox = categoriesPanel.Get<CheckboxWidget>("SHOW_BUILDABLE_AREA");
|
|
||||||
|
|
||||||
MapOverlays[] allCategories = { MapOverlays.Grid, MapOverlays.Buildable };
|
MapOverlays[] allCategories = { MapOverlays.Grid, MapOverlays.Buildable, MapOverlays.Marker };
|
||||||
foreach (var cat in allCategories)
|
foreach (var cat in allCategories)
|
||||||
{
|
{
|
||||||
|
var category = (CheckboxWidget)categoryTemplate.Clone();
|
||||||
|
category.GetText = () => cat.ToString();
|
||||||
|
category.IsVisible = () => true;
|
||||||
|
|
||||||
if (cat.HasFlag(MapOverlays.Grid))
|
if (cat.HasFlag(MapOverlays.Grid))
|
||||||
{
|
{
|
||||||
showGridCheckbox.IsChecked = () => terrainGeometryTrait.Enabled;
|
category.IsChecked = () => terrainGeometryTrait.Enabled;
|
||||||
showGridCheckbox.OnClick = () => terrainGeometryTrait.Enabled ^= true;
|
category.OnClick = () => terrainGeometryTrait.Enabled ^= true;
|
||||||
}
|
}
|
||||||
else if (cat.HasFlag(MapOverlays.Buildable))
|
else if (cat.HasFlag(MapOverlays.Buildable))
|
||||||
{
|
{
|
||||||
showBuildableAreaCheckbox.IsChecked = () => buildableTerrainTrait.Enabled;
|
category.IsChecked = () => buildableTerrainTrait.Enabled;
|
||||||
showBuildableAreaCheckbox.OnClick = () => buildableTerrainTrait.Enabled ^= true;
|
category.OnClick = () => buildableTerrainTrait.Enabled ^= true;
|
||||||
}
|
}
|
||||||
|
else if (cat.HasFlag(MapOverlays.Marker))
|
||||||
|
{
|
||||||
|
category.IsChecked = () => markerLayerTrait.Enabled;
|
||||||
|
category.OnClick = () => markerLayerTrait.Enabled ^= true;
|
||||||
|
}
|
||||||
|
|
||||||
|
categoriesPanel.AddChild(category);
|
||||||
}
|
}
|
||||||
|
|
||||||
return categoriesPanel;
|
return categoriesPanel;
|
||||||
|
|||||||
82
OpenRA.Mods.Common/Widgets/Logic/Editor/MapToolsLogic.cs
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright (c) The OpenRA Developers and Contributors
|
||||||
|
* 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;
|
||||||
|
using OpenRA.Graphics;
|
||||||
|
using OpenRA.Widgets;
|
||||||
|
|
||||||
|
namespace OpenRA.Mods.Common.Widgets.Logic
|
||||||
|
{
|
||||||
|
public class MapToolsLogic : ChromeLogic
|
||||||
|
{
|
||||||
|
[TranslationReference]
|
||||||
|
const string MarkerTiles = "label-tool-marker-tiles";
|
||||||
|
|
||||||
|
enum MapTool
|
||||||
|
{
|
||||||
|
MarkerTiles
|
||||||
|
}
|
||||||
|
|
||||||
|
readonly DropDownButtonWidget toolsDropdown;
|
||||||
|
readonly Dictionary<MapTool, string> toolNames = new()
|
||||||
|
{
|
||||||
|
{ MapTool.MarkerTiles, MarkerTiles }
|
||||||
|
};
|
||||||
|
|
||||||
|
readonly Dictionary<MapTool, Widget> toolPanels = new();
|
||||||
|
|
||||||
|
MapTool selectedTool = MapTool.MarkerTiles;
|
||||||
|
|
||||||
|
[ObjectCreator.UseCtor]
|
||||||
|
public MapToolsLogic(Widget widget, World world, ModData modData, WorldRenderer worldRenderer, Dictionary<string, MiniYaml> logicArgs)
|
||||||
|
{
|
||||||
|
toolsDropdown = widget.Get<DropDownButtonWidget>("TOOLS_DROPDOWN");
|
||||||
|
|
||||||
|
var markerToolPanel = widget.Get<ScrollPanelWidget>("MARKER_TOOL_PANEL");
|
||||||
|
toolPanels.Add(MapTool.MarkerTiles, markerToolPanel);
|
||||||
|
|
||||||
|
toolsDropdown.OnMouseDown = _ => ShowToolsDropDown(toolsDropdown);
|
||||||
|
toolsDropdown.GetText = () => TranslationProvider.GetString(toolNames[selectedTool]);
|
||||||
|
toolsDropdown.Disabled = true; // TODO: Enable if new tools are added
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShowToolsDropDown(DropDownButtonWidget dropdown)
|
||||||
|
{
|
||||||
|
ScrollItemWidget SetupItem(MapTool tool, ScrollItemWidget itemTemplate)
|
||||||
|
{
|
||||||
|
var item = ScrollItemWidget.Setup(itemTemplate,
|
||||||
|
() => selectedTool == tool,
|
||||||
|
() => SelectTool(tool));
|
||||||
|
|
||||||
|
item.Get<LabelWidget>("LABEL").GetText = () => TranslationProvider.GetString(toolNames[tool]);
|
||||||
|
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
var options = new[] { MapTool.MarkerTiles };
|
||||||
|
dropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 150, options, SetupItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SelectTool(MapTool tool)
|
||||||
|
{
|
||||||
|
if (tool != selectedTool)
|
||||||
|
{
|
||||||
|
var currentToolPanel = toolPanels[selectedTool];
|
||||||
|
currentToolPanel.Visible = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
selectedTool = tool;
|
||||||
|
|
||||||
|
var toolPanel = toolPanels[selectedTool];
|
||||||
|
toolPanel.Visible = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,6 +13,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using OpenRA.FileSystem;
|
using OpenRA.FileSystem;
|
||||||
using OpenRA.Mods.Common.Traits;
|
using OpenRA.Mods.Common.Traits;
|
||||||
using OpenRA.Widgets;
|
using OpenRA.Widgets;
|
||||||
@@ -300,6 +301,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
}
|
}
|
||||||
|
|
||||||
saveMap(combinedPath);
|
saveMap(combinedPath);
|
||||||
|
|
||||||
|
SaveMapMarkerTiles(map, modData, world);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void SaveMapInner(Map map, IReadWritePackage package, World world, ModData modData)
|
public static void SaveMapInner(Map map, IReadWritePackage package, World world, ModData modData)
|
||||||
@@ -344,5 +347,33 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
},
|
},
|
||||||
confirmText: SaveMapFailedConfirm);
|
confirmText: SaveMapFailedConfirm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void SaveMapMarkerTiles(Map map, ModData modData, World world)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var markerLayerOverlay = world.WorldActor.Trait<MarkerLayerOverlay>();
|
||||||
|
if (markerLayerOverlay.Tiles.Count == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var mod = modData.Manifest.Metadata;
|
||||||
|
var directory = Path.Combine(Platform.SupportDir, "Editor", modData.Manifest.Id, mod.Version, "MarkerTiles");
|
||||||
|
Directory.CreateDirectory(directory);
|
||||||
|
|
||||||
|
var markerTilesFile = markerLayerOverlay.ToFile();
|
||||||
|
var markerTilesContent = JsonConvert.SerializeObject(markerTilesFile);
|
||||||
|
|
||||||
|
var markerTileFilename = $"{Path.GetFileNameWithoutExtension(map.Package.Name)}.json";
|
||||||
|
using (var streamWriter = new StreamWriter(Path.Combine(directory, markerTileFilename), false))
|
||||||
|
{
|
||||||
|
streamWriter.Write(markerTilesContent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Log.Write("debug", "Failed to save map editor marker tiles.");
|
||||||
|
Log.Write("debug", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -759,3 +759,4 @@ editor:
|
|||||||
actors: 802, 68, 16, 16
|
actors: 802, 68, 16, 16
|
||||||
tools: 904, 68, 16, 16
|
tools: 904, 68, 16, 16
|
||||||
history: 904, 51, 16, 16
|
history: 904, 51, 16, 16
|
||||||
|
erase: 818, 170, 16, 16
|
||||||
|
|||||||
@@ -218,6 +218,7 @@ Container@EDITOR_WORLD_ROOT:
|
|||||||
Logic: LoadIngamePerfLogic, MapEditorLogic, ActorEditLogic, MapOverlaysLogic, MapEditorSelectionLogic
|
Logic: LoadIngamePerfLogic, MapEditorLogic, ActorEditLogic, MapOverlaysLogic, MapEditorSelectionLogic
|
||||||
ToggleGridOverlayKey: EditorToggleGridOverlay
|
ToggleGridOverlayKey: EditorToggleGridOverlay
|
||||||
ToggleBuildableOverlayKey: EditorToggleBuildableOverlay
|
ToggleBuildableOverlayKey: EditorToggleBuildableOverlay
|
||||||
|
ToggleMarkerOverlayKey: EditorToggleMarkerOverlay
|
||||||
Children:
|
Children:
|
||||||
LogicKeyListener@OVERLAY_KEYHANDLER:
|
LogicKeyListener@OVERLAY_KEYHANDLER:
|
||||||
Container@PERF_ROOT:
|
Container@PERF_ROOT:
|
||||||
@@ -431,25 +432,161 @@ Container@EDITOR_WORLD_ROOT:
|
|||||||
Width: 290
|
Width: 290
|
||||||
Height: WINDOW_BOTTOM - 410
|
Height: WINDOW_BOTTOM - 410
|
||||||
ClickThrough: false
|
ClickThrough: false
|
||||||
|
Logic: MapToolsLogic
|
||||||
Children:
|
Children:
|
||||||
Background@TOOLS_EDIT_PANEL:
|
Background@TOOLS_EDIT_PANEL:
|
||||||
X: 0
|
|
||||||
Y: 0
|
|
||||||
Width: PARENT_RIGHT
|
Width: PARENT_RIGHT
|
||||||
|
Height: 25
|
||||||
|
Background: panel-black
|
||||||
|
Label@TOOLS_LABEL:
|
||||||
|
Y: 1
|
||||||
|
Width: 55
|
||||||
|
Height: 25
|
||||||
|
Text: label-tools-bg-categories
|
||||||
|
Align: Right
|
||||||
|
Font: TinyBold
|
||||||
|
DropDownButton@TOOLS_DROPDOWN:
|
||||||
|
X: 60
|
||||||
|
Width: PARENT_RIGHT - 60
|
||||||
|
Height: 25
|
||||||
|
Font: Bold
|
||||||
|
ScrollPanel@MARKER_TOOL_PANEL:
|
||||||
|
Y: 24
|
||||||
|
Width: PARENT_RIGHT - 1
|
||||||
Height: PARENT_BOTTOM
|
Height: PARENT_BOTTOM
|
||||||
Background: scrollpanel-bg
|
Visible: true
|
||||||
Checkbox@SHOW_TILE_GRID:
|
ScrollBar: Hidden
|
||||||
X: 6
|
ScrollbarWidth: 0
|
||||||
Y: 7
|
Logic: MapMarkerTilesLogic
|
||||||
Width: PARENT_RIGHT - 29
|
Children:
|
||||||
Height: 20
|
ScrollPanel@TILE_COLOR_PANEL:
|
||||||
Text: label-show-tile-grid
|
X: 6
|
||||||
Checkbox@SHOW_BUILDABLE_AREA:
|
Y: 6
|
||||||
X: 6
|
Width: PARENT_RIGHT - 18
|
||||||
Y: 32
|
Height: 31
|
||||||
Width: PARENT_RIGHT - 29
|
TopBottomSpacing: 1
|
||||||
Height: 20
|
ItemSpacing: 1
|
||||||
Text: label-show-buildable-area
|
ScrollBar: Hidden
|
||||||
|
ScrollbarWidth: 0
|
||||||
|
ContentHeight: 31
|
||||||
|
Children:
|
||||||
|
ScrollItem@TILE_COLOR_TEMPLATE:
|
||||||
|
Visible: false
|
||||||
|
Height: 29
|
||||||
|
Width: 29
|
||||||
|
IgnoreChildMouseOver: true
|
||||||
|
Children:
|
||||||
|
ColorBlock@TILE_PREVIEW:
|
||||||
|
X: 2
|
||||||
|
Y: 2
|
||||||
|
Width: 26
|
||||||
|
Height: 26
|
||||||
|
ScrollItem@TILE_ICON_TEMPLATE:
|
||||||
|
Visible: false
|
||||||
|
Height: 29
|
||||||
|
Width: 29
|
||||||
|
IgnoreChildMouseOver: true
|
||||||
|
Children:
|
||||||
|
Image@TILE_ERASE:
|
||||||
|
X: 6
|
||||||
|
Y: 6
|
||||||
|
Width: 26
|
||||||
|
Height: 26
|
||||||
|
ImageCollection: editor
|
||||||
|
ImageName: erase
|
||||||
|
Button@CLEAR_CURRENT_BUTTON:
|
||||||
|
X: 6
|
||||||
|
Y: 42
|
||||||
|
Width: 100
|
||||||
|
Height: 25
|
||||||
|
Text: button-marker-tiles-clear-current
|
||||||
|
Font: Bold
|
||||||
|
Button@CLEAR_ALL_BUTTON:
|
||||||
|
X: 111
|
||||||
|
Y: 42
|
||||||
|
Width: 75
|
||||||
|
Height: 25
|
||||||
|
Text: button-marker-tiles-clear-all
|
||||||
|
Font: Bold
|
||||||
|
Label@ALPHA_LABEL:
|
||||||
|
X: 6
|
||||||
|
Y: 72
|
||||||
|
Width: 265
|
||||||
|
Height: 25
|
||||||
|
Align: Left
|
||||||
|
Text: label-marker-alpha
|
||||||
|
Slider@ALPHA_SLIDER:
|
||||||
|
X: 130
|
||||||
|
Y: 72
|
||||||
|
Width: 128
|
||||||
|
Height: 25
|
||||||
|
Label@ALPHA_VALUE:
|
||||||
|
X: 260
|
||||||
|
Y: 72
|
||||||
|
Width: 30
|
||||||
|
Height: 25
|
||||||
|
Align: Left
|
||||||
|
Text: 85
|
||||||
|
Label@MODE_LABEL:
|
||||||
|
X: 6
|
||||||
|
Y: 102
|
||||||
|
Width: 265
|
||||||
|
Height: 25
|
||||||
|
Align: Left
|
||||||
|
Text: label-marker-mirror-mode
|
||||||
|
DropDownButton@MODE_DROPDOWN:
|
||||||
|
X: 129
|
||||||
|
Y: 102
|
||||||
|
Width: 157
|
||||||
|
Height: 25
|
||||||
|
Label@NUM_SIDES_LABEL:
|
||||||
|
X: 6
|
||||||
|
Y: 132
|
||||||
|
Width: 256
|
||||||
|
Height: 25
|
||||||
|
Align: Left
|
||||||
|
Text: label-marker-layer-num-sides
|
||||||
|
Slider@ROTATE_NUM_SIDES_SLIDER:
|
||||||
|
X: 130
|
||||||
|
Y: 132
|
||||||
|
Width: 128
|
||||||
|
Height: 25
|
||||||
|
Visible: false
|
||||||
|
Label@ROTATE_NUM_SIDES_VALUE:
|
||||||
|
X: 260
|
||||||
|
Y: 132
|
||||||
|
Width: 30
|
||||||
|
Height: 25
|
||||||
|
Align: Left
|
||||||
|
Text: 2
|
||||||
|
Visible: false
|
||||||
|
DropDownButton@FLIP_NUM_SIDES_DROPDOWN:
|
||||||
|
X: 129
|
||||||
|
Y: 132
|
||||||
|
Width: 157
|
||||||
|
Height: 25
|
||||||
|
Label@AXIS_ANGLE_LABEL:
|
||||||
|
X: 6
|
||||||
|
Y: 162
|
||||||
|
Width: 256
|
||||||
|
Height: 25
|
||||||
|
Align: Left
|
||||||
|
Text: label-marker-axis-angle
|
||||||
|
Visible: false
|
||||||
|
Slider@AXIS_ANGLE_SLIDER:
|
||||||
|
X: 130
|
||||||
|
Y: 162
|
||||||
|
Width: 128
|
||||||
|
Height: 25
|
||||||
|
Visible: false
|
||||||
|
Label@AXIS_ANGLE_VALUE:
|
||||||
|
X: 260
|
||||||
|
Y: 162
|
||||||
|
Width: 30
|
||||||
|
Height: 25
|
||||||
|
Align: Left
|
||||||
|
Text: 0
|
||||||
|
Visible: false
|
||||||
Container@HISTORY_WIDGETS:
|
Container@HISTORY_WIDGETS:
|
||||||
Logic: HistoryLogLogic
|
Logic: HistoryLogLogic
|
||||||
X: WINDOW_RIGHT - 295
|
X: WINDOW_RIGHT - 295
|
||||||
@@ -819,6 +956,13 @@ Container@EDITOR_WORLD_ROOT:
|
|||||||
TooltipTemplate: BUTTON_TOOLTIP
|
TooltipTemplate: BUTTON_TOOLTIP
|
||||||
TooltipText: button-editor-world-root-paste.tooltip
|
TooltipText: button-editor-world-root-paste.tooltip
|
||||||
TooltipContainer: TOOLTIP_CONTAINER
|
TooltipContainer: TOOLTIP_CONTAINER
|
||||||
|
DropDownButton@OVERLAY_BUTTON:
|
||||||
|
X: WINDOW_RIGHT - 914
|
||||||
|
Y: 5
|
||||||
|
Width: 140
|
||||||
|
Height: 25
|
||||||
|
Text: dropdownbutton-editor-world-root-overlay-button
|
||||||
|
Font: Bold
|
||||||
Label@COORDINATE_LABEL:
|
Label@COORDINATE_LABEL:
|
||||||
X: 10
|
X: 10
|
||||||
Width: 50
|
Width: 50
|
||||||
@@ -863,7 +1007,7 @@ ScrollPanel@CATEGORY_FILTER_PANEL:
|
|||||||
|
|
||||||
ScrollPanel@OVERLAY_PANEL:
|
ScrollPanel@OVERLAY_PANEL:
|
||||||
Width: 140
|
Width: 140
|
||||||
Height: 55
|
Height: 80
|
||||||
ItemSpacing: 5
|
ItemSpacing: 5
|
||||||
TopBottomSpacing: 0
|
TopBottomSpacing: 0
|
||||||
Children:
|
Children:
|
||||||
@@ -873,4 +1017,3 @@ ScrollPanel@OVERLAY_PANEL:
|
|||||||
Width: PARENT_RIGHT - 29
|
Width: PARENT_RIGHT - 29
|
||||||
Height: 20
|
Height: 20
|
||||||
Visible: false
|
Visible: false
|
||||||
|
|
||||||
|
|||||||
@@ -70,8 +70,13 @@ label-copy-filters = Copy Filters
|
|||||||
label-filter-terrain = Terrain
|
label-filter-terrain = Terrain
|
||||||
label-filter-resources = Resources
|
label-filter-resources = Resources
|
||||||
label-filter-actors = Actors
|
label-filter-actors = Actors
|
||||||
label-show-tile-grid = Show Tile Grid
|
label-tools-bg-categories = Tool:
|
||||||
label-show-buildable-area = Show Buildable Area
|
button-marker-tiles-clear-current = Clear Current
|
||||||
|
button-marker-tiles-clear-all = Clear All
|
||||||
|
label-marker-layer-num-sides = Number of Sides
|
||||||
|
label-marker-alpha = Tile Alpha
|
||||||
|
label-marker-mirror-mode = Mirror Mode
|
||||||
|
label-marker-axis-angle = Axis Angle
|
||||||
|
|
||||||
button-map-editor-tab-container-select-tooltip = Select
|
button-map-editor-tab-container-select-tooltip = Select
|
||||||
button-map-editor-tab-container-tiles-tooltip = Tiles
|
button-map-editor-tab-container-tiles-tooltip = Tiles
|
||||||
@@ -96,9 +101,12 @@ button-editor-world-root-redo =
|
|||||||
.label = Redo
|
.label = Redo
|
||||||
.tooltip = Redo last step
|
.tooltip = Redo last step
|
||||||
|
|
||||||
|
dropdownbutton-editor-world-root-overlay-button = Overlays
|
||||||
button-select-categories-buttons-all = All
|
button-select-categories-buttons-all = All
|
||||||
button-select-categories-buttons-none = None
|
button-select-categories-buttons-none = None
|
||||||
|
|
||||||
|
label-tool-marker-tiles = Marker Tiles
|
||||||
|
|
||||||
## gamesave-browser.yaml
|
## gamesave-browser.yaml
|
||||||
label-gamesave-browser-panel-load-title = Load game
|
label-gamesave-browser-panel-load-title = Load game
|
||||||
label-gamesave-browser-panel-save-title = Save game
|
label-gamesave-browser-panel-save-title = Save game
|
||||||
|
|||||||
@@ -299,3 +299,4 @@ EditorWorld:
|
|||||||
EditorActionManager:
|
EditorActionManager:
|
||||||
BuildableTerrainOverlay:
|
BuildableTerrainOverlay:
|
||||||
AllowedTerrainTypes: Clear, Road
|
AllowedTerrainTypes: Clear, Road
|
||||||
|
MarkerLayerOverlay:
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 406 KiB After Width: | Height: | Size: 406 KiB |
|
Before Width: | Height: | Size: 1017 KiB After Width: | Height: | Size: 1019 KiB |
|
Before Width: | Height: | Size: 166 KiB After Width: | Height: | Size: 166 KiB |
@@ -84,7 +84,7 @@ Background@SAVE_MAP_PANEL:
|
|||||||
Y: 21
|
Y: 21
|
||||||
Width: 250
|
Width: 250
|
||||||
Height: 25
|
Height: 25
|
||||||
Text: label-save-map-panel-title.label
|
Text: label-save-map-panel-heading
|
||||||
Align: Center
|
Align: Center
|
||||||
Font: Bold
|
Font: Bold
|
||||||
Label@TITLE_LABEL:
|
Label@TITLE_LABEL:
|
||||||
@@ -93,7 +93,7 @@ Background@SAVE_MAP_PANEL:
|
|||||||
Width: 95
|
Width: 95
|
||||||
Height: 25
|
Height: 25
|
||||||
Align: Right
|
Align: Right
|
||||||
Text: label-save-map-panel-title.label
|
Text: label-save-map-panel-title
|
||||||
TextField@TITLE:
|
TextField@TITLE:
|
||||||
X: 110
|
X: 110
|
||||||
Y: 60
|
Y: 60
|
||||||
@@ -207,6 +207,7 @@ Container@EDITOR_WORLD_ROOT:
|
|||||||
Logic: LoadIngamePerfLogic, MapEditorLogic, ActorEditLogic, MapOverlaysLogic, MapEditorSelectionLogic
|
Logic: LoadIngamePerfLogic, MapEditorLogic, ActorEditLogic, MapOverlaysLogic, MapEditorSelectionLogic
|
||||||
ToggleGridOverlayKey: EditorToggleGridOverlay
|
ToggleGridOverlayKey: EditorToggleGridOverlay
|
||||||
ToggleBuildableOverlayKey: EditorToggleBuildableOverlay
|
ToggleBuildableOverlayKey: EditorToggleBuildableOverlay
|
||||||
|
ToggleMarkerOverlayKey: EditorToggleMarkerOverlay
|
||||||
Children:
|
Children:
|
||||||
LogicKeyListener@OVERLAY_KEYHANDLER:
|
LogicKeyListener@OVERLAY_KEYHANDLER:
|
||||||
Container@PERF_ROOT:
|
Container@PERF_ROOT:
|
||||||
@@ -392,19 +393,159 @@ Container@EDITOR_WORLD_ROOT:
|
|||||||
Width: 310
|
Width: 310
|
||||||
Height: WINDOW_BOTTOM - 458
|
Height: WINDOW_BOTTOM - 458
|
||||||
Visible: false
|
Visible: false
|
||||||
|
Logic: MapToolsLogic
|
||||||
Children:
|
Children:
|
||||||
Checkbox@SHOW_TILE_GRID:
|
Label@TOOLS_LABEL:
|
||||||
X: 15
|
Y: 12
|
||||||
Y: 15
|
Width: 55
|
||||||
Width: PARENT_RIGHT - 15
|
Height: 25
|
||||||
Height: 20
|
Text: label-tools-bg-categories
|
||||||
Text: label-show-tile-grid
|
Align: Right
|
||||||
Checkbox@SHOW_BUILDABLE_AREA:
|
Font: TinyBold
|
||||||
X: 15
|
DropDownButton@TOOLS_DROPDOWN:
|
||||||
Y: 40
|
X: 60
|
||||||
Width: PARENT_RIGHT - 15
|
Y: 10
|
||||||
Height: 20
|
Width: PARENT_RIGHT - 70
|
||||||
Text: label-show-buildable-area
|
Height: 25
|
||||||
|
Font: Bold
|
||||||
|
ScrollPanel@MARKER_TOOL_PANEL:
|
||||||
|
X: 9
|
||||||
|
Y: 35
|
||||||
|
Width: 290
|
||||||
|
Height: WINDOW_BOTTOM - 490
|
||||||
|
Visible: true
|
||||||
|
ScrollBar: Hidden
|
||||||
|
ScrollbarWidth: 0
|
||||||
|
Logic: MapMarkerTilesLogic
|
||||||
|
Children:
|
||||||
|
ScrollPanel@TILE_COLOR_PANEL:
|
||||||
|
X: 6
|
||||||
|
Y: 6
|
||||||
|
Width: PARENT_RIGHT - 19
|
||||||
|
Height: 31
|
||||||
|
TopBottomSpacing: 1
|
||||||
|
ItemSpacing: 1
|
||||||
|
ScrollBar: Hidden
|
||||||
|
ScrollbarWidth: 0
|
||||||
|
ContentHeight: 31
|
||||||
|
Children:
|
||||||
|
ScrollItem@TILE_COLOR_TEMPLATE:
|
||||||
|
Visible: false
|
||||||
|
Height: 29
|
||||||
|
Width: 29
|
||||||
|
IgnoreChildMouseOver: true
|
||||||
|
Children:
|
||||||
|
ColorBlock@TILE_PREVIEW:
|
||||||
|
X: 2
|
||||||
|
Y: 2
|
||||||
|
Width: 26
|
||||||
|
Height: 26
|
||||||
|
ScrollItem@TILE_ICON_TEMPLATE:
|
||||||
|
Visible: false
|
||||||
|
Height: 29
|
||||||
|
Width: 29
|
||||||
|
IgnoreChildMouseOver: true
|
||||||
|
Children:
|
||||||
|
Image@TILE_ERASE:
|
||||||
|
X: 6
|
||||||
|
Y: 6
|
||||||
|
Width: 26
|
||||||
|
Height: 26
|
||||||
|
ImageCollection: editor
|
||||||
|
ImageName: erase
|
||||||
|
Button@CLEAR_CURRENT_BUTTON:
|
||||||
|
X: 6
|
||||||
|
Y: 42
|
||||||
|
Width: 100
|
||||||
|
Height: 25
|
||||||
|
Text: button-marker-tiles-clear-current
|
||||||
|
Font: Bold
|
||||||
|
Button@CLEAR_ALL_BUTTON:
|
||||||
|
X: 111
|
||||||
|
Y: 42
|
||||||
|
Width: 75
|
||||||
|
Height: 25
|
||||||
|
Text: button-marker-tiles-clear-all
|
||||||
|
Font: Bold
|
||||||
|
Label@ALPHA_LABEL:
|
||||||
|
X: 6
|
||||||
|
Y: 72
|
||||||
|
Width: 265
|
||||||
|
Height: 25
|
||||||
|
Align: Left
|
||||||
|
Text: label-marker-alpha
|
||||||
|
Slider@ALPHA_SLIDER:
|
||||||
|
X: 130
|
||||||
|
Y: 72
|
||||||
|
Width: 128
|
||||||
|
Height: 25
|
||||||
|
Label@ALPHA_VALUE:
|
||||||
|
X: 260
|
||||||
|
Y: 72
|
||||||
|
Width: 30
|
||||||
|
Height: 25
|
||||||
|
Align: Left
|
||||||
|
Text: 85
|
||||||
|
Label@MODE_LABEL:
|
||||||
|
X: 6
|
||||||
|
Y: 102
|
||||||
|
Width: 265
|
||||||
|
Height: 25
|
||||||
|
Align: Left
|
||||||
|
Text: label-marker-mirror-mode
|
||||||
|
DropDownButton@MODE_DROPDOWN:
|
||||||
|
X: 129
|
||||||
|
Y: 102
|
||||||
|
Width: 157
|
||||||
|
Height: 25
|
||||||
|
Label@NUM_SIDES_LABEL:
|
||||||
|
X: 6
|
||||||
|
Y: 132
|
||||||
|
Width: 256
|
||||||
|
Height: 25
|
||||||
|
Align: Left
|
||||||
|
Text: label-marker-layer-num-sides
|
||||||
|
Slider@ROTATE_NUM_SIDES_SLIDER:
|
||||||
|
X: 130
|
||||||
|
Y: 132
|
||||||
|
Width: 128
|
||||||
|
Height: 25
|
||||||
|
Visible: false
|
||||||
|
Label@ROTATE_NUM_SIDES_VALUE:
|
||||||
|
X: 260
|
||||||
|
Y: 132
|
||||||
|
Width: 30
|
||||||
|
Height: 25
|
||||||
|
Align: Left
|
||||||
|
Text: 2
|
||||||
|
Visible: false
|
||||||
|
DropDownButton@FLIP_NUM_SIDES_DROPDOWN:
|
||||||
|
X: 129
|
||||||
|
Y: 132
|
||||||
|
Width: 157
|
||||||
|
Height: 25
|
||||||
|
Label@AXIS_ANGLE_LABEL:
|
||||||
|
X: 6
|
||||||
|
Y: 162
|
||||||
|
Width: 256
|
||||||
|
Height: 25
|
||||||
|
Align: Left
|
||||||
|
Text: label-marker-axis-angle
|
||||||
|
Visible: false
|
||||||
|
Slider@AXIS_ANGLE_SLIDER:
|
||||||
|
X: 130
|
||||||
|
Y: 162
|
||||||
|
Width: 128
|
||||||
|
Height: 25
|
||||||
|
Visible: false
|
||||||
|
Label@AXIS_ANGLE_VALUE:
|
||||||
|
X: 260
|
||||||
|
Y: 162
|
||||||
|
Width: 30
|
||||||
|
Height: 25
|
||||||
|
Align: Left
|
||||||
|
Text: 0
|
||||||
|
Visible: false
|
||||||
Container@HISTORY_WIDGETS:
|
Container@HISTORY_WIDGETS:
|
||||||
X: WINDOW_RIGHT - 320
|
X: WINDOW_RIGHT - 320
|
||||||
Y: 354
|
Y: 354
|
||||||
@@ -768,15 +909,21 @@ Container@EDITOR_WORLD_ROOT:
|
|||||||
TooltipTemplate: BUTTON_TOOLTIP
|
TooltipTemplate: BUTTON_TOOLTIP
|
||||||
TooltipText: button-editor-world-root-paste.tooltip
|
TooltipText: button-editor-world-root-paste.tooltip
|
||||||
TooltipContainer: TOOLTIP_CONTAINER
|
TooltipContainer: TOOLTIP_CONTAINER
|
||||||
|
DropDownButton@OVERLAY_BUTTON:
|
||||||
|
X: 390
|
||||||
|
Width: 140
|
||||||
|
Height: 25
|
||||||
|
Text: dropdownbutton-editor-world-root-overlay-button
|
||||||
|
Font: Bold
|
||||||
Label@COORDINATE_LABEL:
|
Label@COORDINATE_LABEL:
|
||||||
X: 470
|
X: 540
|
||||||
Width: 50
|
Width: 50
|
||||||
Height: 25
|
Height: 25
|
||||||
Align: Left
|
Align: Left
|
||||||
Font: Bold
|
Font: Bold
|
||||||
Contrast: true
|
Contrast: true
|
||||||
Label@CASH_LABEL:
|
Label@CASH_LABEL:
|
||||||
X: 595
|
X: 655
|
||||||
Width: 50
|
Width: 50
|
||||||
Height: 25
|
Height: 25
|
||||||
Align: Left
|
Align: Left
|
||||||
@@ -812,3 +959,15 @@ ScrollPanel@CATEGORY_FILTER_PANEL:
|
|||||||
Height: 20
|
Height: 20
|
||||||
Visible: false
|
Visible: false
|
||||||
|
|
||||||
|
ScrollPanel@OVERLAY_PANEL:
|
||||||
|
Width: 140
|
||||||
|
Height: 80
|
||||||
|
ItemSpacing: 5
|
||||||
|
TopBottomSpacing: 0
|
||||||
|
Children:
|
||||||
|
Checkbox@CATEGORY_TEMPLATE:
|
||||||
|
X: 5
|
||||||
|
Y: 5
|
||||||
|
Width: PARENT_RIGHT - 29
|
||||||
|
Height: 20
|
||||||
|
Visible: false
|
||||||
|
|||||||
@@ -78,3 +78,8 @@ EditorToggleBuildableOverlay: F2
|
|||||||
Description: Buildable Terrain Overlay
|
Description: Buildable Terrain Overlay
|
||||||
Types: Editor
|
Types: Editor
|
||||||
Contexts: Editor
|
Contexts: Editor
|
||||||
|
|
||||||
|
EditorToggleMarkerOverlay: F3
|
||||||
|
Description: Marker Layer Overlay
|
||||||
|
Types: Editor
|
||||||
|
Contexts: Editor
|
||||||
|
|||||||
@@ -43,10 +43,8 @@ label-new-map-bg-width = Width:
|
|||||||
label-new-map-bg-height = Height:
|
label-new-map-bg-height = Height:
|
||||||
button-new-map-bg-create = Create
|
button-new-map-bg-create = Create
|
||||||
|
|
||||||
label-save-map-panel-title =
|
label-save-map-panel-heading = Save Map
|
||||||
.label = Save Map
|
label-save-map-panel-title = Title:
|
||||||
.label = Title:
|
|
||||||
|
|
||||||
label-save-map-panel-author = Author:
|
label-save-map-panel-author = Author:
|
||||||
label-save-map-panel-visibility = Visibility:
|
label-save-map-panel-visibility = Visibility:
|
||||||
dropdownbutton-save-map-panel-visibility-dropdown = Map Visibility
|
dropdownbutton-save-map-panel-visibility-dropdown = Map Visibility
|
||||||
@@ -68,8 +66,13 @@ label-copy-filters = Copy Filters
|
|||||||
label-filter-terrain = Terrain
|
label-filter-terrain = Terrain
|
||||||
label-filter-resources = Resources
|
label-filter-resources = Resources
|
||||||
label-filter-actors = Actors
|
label-filter-actors = Actors
|
||||||
label-show-tile-grid = Show Tile Grid
|
label-tools-bg-categories = Tool:
|
||||||
label-show-buildable-area = Show Buildable Area
|
button-marker-tiles-clear-current = Clear Current
|
||||||
|
button-marker-tiles-clear-all = Clear All
|
||||||
|
label-marker-layer-num-sides = Number of Sides
|
||||||
|
label-marker-alpha = Tile Alpha
|
||||||
|
label-marker-mirror-mode = Mirror Mode
|
||||||
|
label-marker-axis-angle = Axis Angle
|
||||||
|
|
||||||
button-map-editor-tab-container-select-tooltip = Select
|
button-map-editor-tab-container-select-tooltip = Select
|
||||||
button-map-editor-tab-container-tiles-tooltip = Tiles
|
button-map-editor-tab-container-tiles-tooltip = Tiles
|
||||||
@@ -98,9 +101,12 @@ button-editor-world-root-redo =
|
|||||||
.label = Redo
|
.label = Redo
|
||||||
.tooltip = Redo last step
|
.tooltip = Redo last step
|
||||||
|
|
||||||
|
dropdownbutton-editor-world-root-overlay-button = Overlays
|
||||||
button-select-categories-buttons-all = All
|
button-select-categories-buttons-all = All
|
||||||
button-select-categories-buttons-none = None
|
button-select-categories-buttons-none = None
|
||||||
|
|
||||||
|
label-tool-marker-tiles = Marker Tiles
|
||||||
|
|
||||||
## gamesave-browser.yaml
|
## gamesave-browser.yaml
|
||||||
label-gamesave-browser-panel-load-title = Load game
|
label-gamesave-browser-panel-load-title = Load game
|
||||||
label-gamesave-browser-panel-save-title = Save game
|
label-gamesave-browser-panel-save-title = Save game
|
||||||
|
|||||||
@@ -823,9 +823,29 @@ notification-added-resource =
|
|||||||
notification-added-tile = Added tile { $id }
|
notification-added-tile = Added tile { $id }
|
||||||
notification-filled-tile = Filled with tile { $id }
|
notification-filled-tile = Filled with tile { $id }
|
||||||
|
|
||||||
|
## EditorMarkerLayerBrush
|
||||||
|
notification-added-marker-tiles =
|
||||||
|
{ $amount ->
|
||||||
|
[one] Added one marker tile of type { $type }
|
||||||
|
*[other] Added { $amount } marker tiles of type { $type }
|
||||||
|
}
|
||||||
|
notification-removed-marker-tiles =
|
||||||
|
{ $amount ->
|
||||||
|
[one] Removed one marker tile
|
||||||
|
*[other] Removed { $amount } marker tiles
|
||||||
|
}
|
||||||
|
notification-cleared-selected-marker-tiles = Cleared { $amount } marker tiles of type { $type }
|
||||||
|
notification-cleared-all-marker-tiles = Cleared { $amount } marker tiles
|
||||||
|
|
||||||
## EditorActionManager
|
## EditorActionManager
|
||||||
notification-opened = Opened
|
notification-opened = Opened
|
||||||
|
|
||||||
|
## MapOverlaysLogic
|
||||||
|
mirror-mode =
|
||||||
|
.none = None
|
||||||
|
.flip = Flip
|
||||||
|
.rotate = Rotate
|
||||||
|
|
||||||
## ActorEditLogic
|
## ActorEditLogic
|
||||||
notification-edited-actor = Edited { $name } ({ $id })
|
notification-edited-actor = Edited { $name } ({ $id })
|
||||||
|
|
||||||
|
|||||||
@@ -521,3 +521,4 @@ editor:
|
|||||||
actors: 34, 68, 16, 16
|
actors: 34, 68, 16, 16
|
||||||
tools: 34, 144, 16, 16
|
tools: 34, 144, 16, 16
|
||||||
history: 136, 51, 16, 16
|
history: 136, 51, 16, 16
|
||||||
|
erase: 67, 144, 16, 16
|
||||||
|
|||||||
@@ -265,3 +265,4 @@ EditorWorld:
|
|||||||
EditorActionManager:
|
EditorActionManager:
|
||||||
BuildableTerrainOverlay:
|
BuildableTerrainOverlay:
|
||||||
AllowedTerrainTypes: Rock, Concrete
|
AllowedTerrainTypes: Rock, Concrete
|
||||||
|
MarkerLayerOverlay:
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 48 KiB |
|
Before Width: | Height: | Size: 89 KiB After Width: | Height: | Size: 90 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 27 KiB |
@@ -665,3 +665,4 @@ editor:
|
|||||||
actors: 34, 68, 16, 16
|
actors: 34, 68, 16, 16
|
||||||
tools: 136, 68, 16, 16
|
tools: 136, 68, 16, 16
|
||||||
history: 136, 51, 16, 16
|
history: 136, 51, 16, 16
|
||||||
|
erase: 50, 187, 16, 16
|
||||||
|
|||||||
@@ -321,3 +321,4 @@ EditorWorld:
|
|||||||
EditorActionManager:
|
EditorActionManager:
|
||||||
BuildableTerrainOverlay:
|
BuildableTerrainOverlay:
|
||||||
AllowedTerrainTypes: Clear, Road
|
AllowedTerrainTypes: Clear, Road
|
||||||
|
MarkerLayerOverlay:
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 75 KiB |
|
Before Width: | Height: | Size: 154 KiB After Width: | Height: | Size: 155 KiB |
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 35 KiB |
@@ -796,3 +796,4 @@ editor:
|
|||||||
actors: 34, 68, 16, 16
|
actors: 34, 68, 16, 16
|
||||||
tools: 34, 144, 16, 16
|
tools: 34, 144, 16, 16
|
||||||
history: 136, 51, 16, 16
|
history: 136, 51, 16, 16
|
||||||
|
erase: 67, 144, 16, 16
|
||||||
|
|||||||
@@ -430,3 +430,4 @@ EditorWorld:
|
|||||||
AllowedTerrainTypes: Clear, Rough, Road, DirtRoad, Green, Sand, Pavement
|
AllowedTerrainTypes: Clear, Rough, Road, DirtRoad, Green, Sand, Pavement
|
||||||
Palette: ra
|
Palette: ra
|
||||||
Alpha: 0.35
|
Alpha: 0.35
|
||||||
|
MarkerLayerOverlay:
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 73 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |