Make brush rendering self-contained
This commit is contained in:
@@ -9,30 +9,65 @@
|
|||||||
*/
|
*/
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using OpenRA.Graphics;
|
using OpenRA.Graphics;
|
||||||
using OpenRA.Mods.Common.Traits;
|
using OpenRA.Mods.Common.Traits;
|
||||||
|
using OpenRA.Traits;
|
||||||
|
|
||||||
namespace OpenRA.Mods.Common.Widgets
|
namespace OpenRA.Mods.Common.Widgets
|
||||||
{
|
{
|
||||||
public sealed class EditorActorBrush : IEditorBrush
|
public sealed class EditorActorBrush : IEditorBrush
|
||||||
{
|
{
|
||||||
|
public EditorActorPreview Preview;
|
||||||
|
|
||||||
readonly World world;
|
readonly World world;
|
||||||
readonly EditorActorLayer editorLayer;
|
readonly EditorActorLayer editorLayer;
|
||||||
readonly EditorCursorLayer editorCursor;
|
|
||||||
readonly EditorActionManager editorActionManager;
|
readonly EditorActionManager editorActionManager;
|
||||||
readonly EditorViewportControllerWidget editorWidget;
|
readonly EditorViewportControllerWidget editorWidget;
|
||||||
readonly int cursorToken;
|
readonly WVec centerOffset;
|
||||||
|
readonly bool sharesCell;
|
||||||
|
|
||||||
|
CPos cell;
|
||||||
|
SubCell subcell = SubCell.Invalid;
|
||||||
|
|
||||||
public EditorActorBrush(EditorViewportControllerWidget editorWidget, ActorInfo actor, PlayerReference owner, WorldRenderer wr)
|
public EditorActorBrush(EditorViewportControllerWidget editorWidget, ActorInfo actor, PlayerReference owner, WorldRenderer wr)
|
||||||
{
|
{
|
||||||
this.editorWidget = editorWidget;
|
this.editorWidget = editorWidget;
|
||||||
world = wr.World;
|
world = wr.World;
|
||||||
editorLayer = world.WorldActor.Trait<EditorActorLayer>();
|
editorLayer = world.WorldActor.Trait<EditorActorLayer>();
|
||||||
editorCursor = world.WorldActor.Trait<EditorCursorLayer>();
|
|
||||||
editorActionManager = world.WorldActor.Trait<EditorActionManager>();
|
editorActionManager = world.WorldActor.Trait<EditorActionManager>();
|
||||||
|
|
||||||
cursorToken = editorCursor.SetActor(wr, actor, owner);
|
var ios = actor.TraitInfoOrDefault<IOccupySpaceInfo>();
|
||||||
|
centerOffset = (ios as BuildingInfo)?.CenterOffset(world) ?? WVec.Zero;
|
||||||
|
sharesCell = ios != null && ios.SharesCell;
|
||||||
|
|
||||||
|
// Enforce first entry of ValidOwnerNames as owner if the actor has RequiresSpecificOwners.
|
||||||
|
var ownerName = owner.Name;
|
||||||
|
var specificOwnerInfo = actor.TraitInfoOrDefault<RequiresSpecificOwnersInfo>();
|
||||||
|
if (specificOwnerInfo != null && !specificOwnerInfo.ValidOwnerNames.Contains(ownerName))
|
||||||
|
ownerName = specificOwnerInfo.ValidOwnerNames.First();
|
||||||
|
|
||||||
|
var reference = new ActorReference(actor.Name)
|
||||||
|
{
|
||||||
|
new OwnerInit(ownerName),
|
||||||
|
new FactionInit(owner.Faction)
|
||||||
|
};
|
||||||
|
|
||||||
|
var worldPx = wr.Viewport.ViewToWorldPx(Viewport.LastMousePos) - wr.ScreenPxOffset(centerOffset);
|
||||||
|
cell = wr.Viewport.ViewToWorld(wr.Viewport.WorldToViewPx(worldPx));
|
||||||
|
reference.Add(new LocationInit(cell));
|
||||||
|
if (sharesCell)
|
||||||
|
{
|
||||||
|
subcell = editorLayer.FreeSubCellAt(cell);
|
||||||
|
if (subcell != SubCell.Invalid)
|
||||||
|
reference.Add(new SubCellInit(subcell));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (actor.HasTraitInfo<IFacingInfo>())
|
||||||
|
reference.Add(new FacingInit(editorLayer.Info.DefaultActorFacing));
|
||||||
|
|
||||||
|
Preview = new EditorActorPreview(wr, null, reference, owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool HandleMouseInput(MouseInput mi)
|
public bool HandleMouseInput(MouseInput mi)
|
||||||
@@ -52,29 +87,56 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (editorCursor.CurrentToken != cursorToken)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (mi.Button == MouseButton.Left && mi.Event == MouseInputEvent.Down)
|
if (mi.Button == MouseButton.Left && mi.Event == MouseInputEvent.Down)
|
||||||
{
|
{
|
||||||
// Check the actor is inside the map
|
// Check the actor is inside the map
|
||||||
var actor = editorCursor.Actor;
|
if (!Preview.Footprint.All(c => world.Map.Tiles.Contains(c.Key)))
|
||||||
if (!actor.Footprint.All(c => world.Map.Tiles.Contains(c.Key)))
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
var action = new AddActorAction(editorLayer, actor.Export());
|
var action = new AddActorAction(editorLayer, Preview.Export());
|
||||||
editorActionManager.Add(action);
|
editorActionManager.Add(action);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IEditorBrush.TickRender(WorldRenderer wr, Actor self)
|
||||||
|
{
|
||||||
|
// Offset mouse position by the center offset (in world pixels)
|
||||||
|
var worldPx = wr.Viewport.ViewToWorldPx(Viewport.LastMousePos) - wr.ScreenPxOffset(centerOffset);
|
||||||
|
var currentCell = wr.Viewport.ViewToWorld(wr.Viewport.WorldToViewPx(worldPx));
|
||||||
|
var currentSubcell = sharesCell ? editorLayer.FreeSubCellAt(currentCell) : SubCell.Invalid;
|
||||||
|
if (cell != currentCell || subcell != currentSubcell)
|
||||||
|
{
|
||||||
|
cell = currentCell;
|
||||||
|
Preview.ReplaceInit(new LocationInit(cell));
|
||||||
|
|
||||||
|
if (sharesCell)
|
||||||
|
{
|
||||||
|
subcell = editorLayer.FreeSubCellAt(cell);
|
||||||
|
if (subcell == SubCell.Invalid)
|
||||||
|
Preview.RemoveInit<SubCellInit>();
|
||||||
|
else
|
||||||
|
Preview.ReplaceInit(new SubCellInit(subcell));
|
||||||
|
}
|
||||||
|
|
||||||
|
Preview.UpdateFromMove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerable<IRenderable> IEditorBrush.RenderAboveShroud(Actor self, WorldRenderer wr)
|
||||||
|
{
|
||||||
|
return Preview.Render().OrderBy(WorldRenderer.RenderableZPositionComparisonKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerable<IRenderable> IEditorBrush.RenderAnnotations(Actor self, WorldRenderer wr)
|
||||||
|
{
|
||||||
|
return Preview.RenderAnnotations();
|
||||||
|
}
|
||||||
|
|
||||||
public void Tick() { }
|
public void Tick() { }
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose() { }
|
||||||
{
|
|
||||||
editorCursor.Clear(cursorToken);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class AddActorAction : IEditorAction
|
sealed class AddActorAction : IEditorAction
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using OpenRA.Graphics;
|
using OpenRA.Graphics;
|
||||||
using OpenRA.Mods.Common.EditorBrushes;
|
using OpenRA.Mods.Common.EditorBrushes;
|
||||||
|
using OpenRA.Mods.Common.Graphics;
|
||||||
using OpenRA.Mods.Common.Traits;
|
using OpenRA.Mods.Common.Traits;
|
||||||
|
|
||||||
namespace OpenRA.Mods.Common.Widgets
|
namespace OpenRA.Mods.Common.Widgets
|
||||||
@@ -94,14 +95,23 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IEditorBrush.TickRender(WorldRenderer wr, Actor self) { }
|
||||||
|
IEnumerable<IRenderable> IEditorBrush.RenderAboveShroud(Actor self, WorldRenderer wr) { yield break; }
|
||||||
|
IEnumerable<IRenderable> IEditorBrush.RenderAnnotations(Actor self, WorldRenderer wr)
|
||||||
|
{
|
||||||
|
if (PastePreviewPosition != null)
|
||||||
|
{
|
||||||
|
yield return new EditorSelectionAnnotationRenderable(Region, editorWidget.SelectionAltColor, editorWidget.SelectionAltOffset, PastePreviewPosition);
|
||||||
|
yield return new EditorSelectionAnnotationRenderable(Region, editorWidget.PasteColor, int2.Zero, PastePreviewPosition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void Tick()
|
public void Tick()
|
||||||
{
|
{
|
||||||
PastePreviewPosition = worldRenderer.Viewport.ViewToWorld(Viewport.LastMousePos);
|
PastePreviewPosition = worldRenderer.Viewport.ViewToWorld(Viewport.LastMousePos);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose() { }
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class CopyPasteEditorAction : IEditorAction
|
sealed class CopyPasteEditorAction : IEditorAction
|
||||||
|
|||||||
@@ -10,7 +10,9 @@
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using OpenRA.Graphics;
|
using OpenRA.Graphics;
|
||||||
|
using OpenRA.Mods.Common.Graphics;
|
||||||
using OpenRA.Mods.Common.Traits;
|
using OpenRA.Mods.Common.Traits;
|
||||||
using OpenRA.Widgets;
|
using OpenRA.Widgets;
|
||||||
|
|
||||||
@@ -20,6 +22,10 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
{
|
{
|
||||||
bool HandleMouseInput(MouseInput mi);
|
bool HandleMouseInput(MouseInput mi);
|
||||||
void Tick();
|
void Tick();
|
||||||
|
|
||||||
|
void TickRender(WorldRenderer wr, Actor self);
|
||||||
|
IEnumerable<IRenderable> RenderAboveShroud(Actor self, WorldRenderer wr);
|
||||||
|
IEnumerable<IRenderable> RenderAnnotations(Actor self, WorldRenderer wr);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class EditorSelection
|
public class EditorSelection
|
||||||
@@ -255,6 +261,17 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IEditorBrush.TickRender(WorldRenderer wr, Actor self) { }
|
||||||
|
IEnumerable<IRenderable> IEditorBrush.RenderAboveShroud(Actor self, WorldRenderer wr) { yield break; }
|
||||||
|
IEnumerable<IRenderable> IEditorBrush.RenderAnnotations(Actor self, WorldRenderer wr)
|
||||||
|
{
|
||||||
|
if (CurrentDragBounds != null)
|
||||||
|
{
|
||||||
|
yield return new EditorSelectionAnnotationRenderable(CurrentDragBounds, editorWidget.SelectionAltColor, editorWidget.SelectionAltOffset, null);
|
||||||
|
yield return new EditorSelectionAnnotationRenderable(CurrentDragBounds, editorWidget.SelectionMainColor, int2.Zero, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void Tick() { }
|
public void Tick() { }
|
||||||
|
|
||||||
public void Dispose() { }
|
public void Dispose() { }
|
||||||
|
|||||||
@@ -75,6 +75,10 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IEditorBrush.TickRender(WorldRenderer wr, Actor self) { }
|
||||||
|
IEnumerable<IRenderable> IEditorBrush.RenderAboveShroud(Actor self, WorldRenderer wr) { yield break; }
|
||||||
|
IEnumerable<IRenderable> IEditorBrush.RenderAnnotations(Actor self, WorldRenderer wr) { yield break; }
|
||||||
|
|
||||||
public void Tick() { }
|
public void Tick() { }
|
||||||
|
|
||||||
public void Dispose() { }
|
public void Dispose() { }
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using OpenRA.Graphics;
|
using OpenRA.Graphics;
|
||||||
using OpenRA.Mods.Common.Traits;
|
using OpenRA.Mods.Common.Traits;
|
||||||
|
|
||||||
@@ -23,13 +24,15 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
readonly World world;
|
readonly World world;
|
||||||
readonly EditorViewportControllerWidget editorWidget;
|
readonly EditorViewportControllerWidget editorWidget;
|
||||||
readonly EditorActionManager editorActionManager;
|
readonly EditorActionManager editorActionManager;
|
||||||
readonly EditorCursorLayer editorCursor;
|
|
||||||
readonly IResourceLayer resourceLayer;
|
readonly IResourceLayer resourceLayer;
|
||||||
readonly int cursorToken;
|
|
||||||
|
|
||||||
AddResourcesEditorAction action;
|
AddResourcesEditorAction action;
|
||||||
bool resourceAdded;
|
bool resourceAdded;
|
||||||
|
|
||||||
|
CPos cell;
|
||||||
|
readonly List<IRenderable> preview = new();
|
||||||
|
readonly IResourceRenderer[] resourceRenderers;
|
||||||
|
|
||||||
public EditorResourceBrush(EditorViewportControllerWidget editorWidget, string resourceType, WorldRenderer wr)
|
public EditorResourceBrush(EditorViewportControllerWidget editorWidget, string resourceType, WorldRenderer wr)
|
||||||
{
|
{
|
||||||
this.editorWidget = editorWidget;
|
this.editorWidget = editorWidget;
|
||||||
@@ -37,11 +40,13 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
worldRenderer = wr;
|
worldRenderer = wr;
|
||||||
world = wr.World;
|
world = wr.World;
|
||||||
editorActionManager = world.WorldActor.Trait<EditorActionManager>();
|
editorActionManager = world.WorldActor.Trait<EditorActionManager>();
|
||||||
editorCursor = world.WorldActor.Trait<EditorCursorLayer>();
|
|
||||||
resourceLayer = world.WorldActor.Trait<IResourceLayer>();
|
resourceLayer = world.WorldActor.Trait<IResourceLayer>();
|
||||||
action = new AddResourcesEditorAction(resourceType, resourceLayer);
|
|
||||||
|
|
||||||
cursorToken = editorCursor.SetResource(wr, resourceType);
|
resourceRenderers = world.WorldActor.TraitsImplementing<IResourceRenderer>().ToArray();
|
||||||
|
cell = wr.Viewport.ViewToWorld(wr.Viewport.WorldToViewPx(Viewport.LastMousePos));
|
||||||
|
UpdatePreview();
|
||||||
|
|
||||||
|
action = new AddResourcesEditorAction(resourceType, resourceLayer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool HandleMouseInput(MouseInput mi)
|
public bool HandleMouseInput(MouseInput mi)
|
||||||
@@ -61,9 +66,6 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (editorCursor.CurrentToken != cursorToken)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
var cell = worldRenderer.Viewport.ViewToWorld(mi.Location);
|
var cell = worldRenderer.Viewport.ViewToWorld(mi.Location);
|
||||||
|
|
||||||
if (mi.Button == MouseButton.Left && mi.Event != MouseInputEvent.Up && resourceLayer.CanAddResource(ResourceType, cell))
|
if (mi.Button == MouseButton.Left && mi.Event != MouseInputEvent.Up && resourceLayer.CanAddResource(ResourceType, cell))
|
||||||
@@ -81,12 +83,30 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UpdatePreview()
|
||||||
|
{
|
||||||
|
var pos = world.Map.CenterOfCell(cell);
|
||||||
|
|
||||||
|
preview.Clear();
|
||||||
|
preview.AddRange(resourceRenderers.SelectMany(r => r.RenderPreview(worldRenderer, ResourceType, pos)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void IEditorBrush.TickRender(WorldRenderer wr, Actor self)
|
||||||
|
{
|
||||||
|
var currentCell = wr.Viewport.ViewToWorld(Viewport.LastMousePos);
|
||||||
|
if (cell != currentCell)
|
||||||
|
{
|
||||||
|
cell = currentCell;
|
||||||
|
UpdatePreview();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerable<IRenderable> IEditorBrush.RenderAboveShroud(Actor self, WorldRenderer wr) { return preview; }
|
||||||
|
IEnumerable<IRenderable> IEditorBrush.RenderAnnotations(Actor self, WorldRenderer wr) { yield break; }
|
||||||
|
|
||||||
public void Tick() { }
|
public void Tick() { }
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose() { }
|
||||||
{
|
|
||||||
editorCursor.Clear(cursorToken);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
readonly struct CellResource
|
readonly struct CellResource
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
{
|
{
|
||||||
public sealed class EditorTileBrush : IEditorBrush
|
public sealed class EditorTileBrush : IEditorBrush
|
||||||
{
|
{
|
||||||
|
public readonly TerrainTemplateInfo TerrainTemplate;
|
||||||
public readonly ushort Template;
|
public readonly ushort Template;
|
||||||
|
|
||||||
readonly WorldRenderer worldRenderer;
|
readonly WorldRenderer worldRenderer;
|
||||||
@@ -27,11 +28,14 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
readonly ITemplatedTerrainInfo terrainInfo;
|
readonly ITemplatedTerrainInfo terrainInfo;
|
||||||
readonly EditorViewportControllerWidget editorWidget;
|
readonly EditorViewportControllerWidget editorWidget;
|
||||||
readonly EditorActionManager editorActionManager;
|
readonly EditorActionManager editorActionManager;
|
||||||
readonly EditorCursorLayer editorCursor;
|
|
||||||
readonly int cursorToken;
|
|
||||||
|
|
||||||
bool painting;
|
bool painting;
|
||||||
|
|
||||||
|
readonly ITiledTerrainRenderer terrainRenderer;
|
||||||
|
|
||||||
|
CPos cell;
|
||||||
|
readonly List<IRenderable> preview = new();
|
||||||
|
|
||||||
public EditorTileBrush(EditorViewportControllerWidget editorWidget, ushort id, WorldRenderer wr)
|
public EditorTileBrush(EditorViewportControllerWidget editorWidget, ushort id, WorldRenderer wr)
|
||||||
{
|
{
|
||||||
this.editorWidget = editorWidget;
|
this.editorWidget = editorWidget;
|
||||||
@@ -42,12 +46,12 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
throw new InvalidDataException("EditorTileBrush can only be used with template-based tilesets");
|
throw new InvalidDataException("EditorTileBrush can only be used with template-based tilesets");
|
||||||
|
|
||||||
editorActionManager = world.WorldActor.Trait<EditorActionManager>();
|
editorActionManager = world.WorldActor.Trait<EditorActionManager>();
|
||||||
editorCursor = world.WorldActor.Trait<EditorCursorLayer>();
|
terrainRenderer = world.WorldActor.Trait<ITiledTerrainRenderer>();
|
||||||
|
|
||||||
Template = id;
|
Template = id;
|
||||||
|
TerrainTemplate = terrainInfo.Templates.First(t => t.Value.Id == id).Value;
|
||||||
var template = terrainInfo.Templates.First(t => t.Value.Id == id).Value;
|
cell = wr.Viewport.ViewToWorld(wr.Viewport.WorldToViewPx(Viewport.LastMousePos));
|
||||||
cursorToken = editorCursor.SetTerrainTemplate(wr, template);
|
UpdatePreview();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool HandleMouseInput(MouseInput mi)
|
public bool HandleMouseInput(MouseInput mi)
|
||||||
@@ -81,9 +85,6 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
if (mi.Event != MouseInputEvent.Down && mi.Event != MouseInputEvent.Move)
|
if (mi.Event != MouseInputEvent.Down && mi.Event != MouseInputEvent.Move)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (editorCursor.CurrentToken != cursorToken)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
var cell = worldRenderer.Viewport.ViewToWorld(mi.Location);
|
var cell = worldRenderer.Viewport.ViewToWorld(mi.Location);
|
||||||
var isMoving = mi.Event == MouseInputEvent.Move;
|
var isMoving = mi.Event == MouseInputEvent.Move;
|
||||||
|
|
||||||
@@ -143,12 +144,30 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UpdatePreview()
|
||||||
|
{
|
||||||
|
var pos = world.Map.CenterOfCell(cell);
|
||||||
|
|
||||||
|
preview.Clear();
|
||||||
|
preview.AddRange(terrainRenderer.RenderPreview(worldRenderer, TerrainTemplate, pos));
|
||||||
|
}
|
||||||
|
|
||||||
|
void IEditorBrush.TickRender(WorldRenderer wr, Actor self)
|
||||||
|
{
|
||||||
|
var currentCell = wr.Viewport.ViewToWorld(Viewport.LastMousePos);
|
||||||
|
if (cell != currentCell)
|
||||||
|
{
|
||||||
|
cell = currentCell;
|
||||||
|
UpdatePreview();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerable<IRenderable> IEditorBrush.RenderAboveShroud(Actor self, WorldRenderer wr) { return preview; }
|
||||||
|
IEnumerable<IRenderable> IEditorBrush.RenderAnnotations(Actor self, WorldRenderer wr) { yield break; }
|
||||||
|
|
||||||
public void Tick() { }
|
public void Tick() { }
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose() { }
|
||||||
{
|
|
||||||
editorCursor.Clear(cursorToken);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class PaintTileEditorAction : IEditorAction
|
sealed class PaintTileEditorAction : IEditorAction
|
||||||
|
|||||||
@@ -28,6 +28,9 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
[Desc("Size of partition bins (world pixels).")]
|
[Desc("Size of partition bins (world pixels).")]
|
||||||
public readonly int BinSize = 250;
|
public readonly int BinSize = 250;
|
||||||
|
|
||||||
|
[Desc("Facing of new actors.")]
|
||||||
|
public readonly WAngle DefaultActorFacing = new(384);
|
||||||
|
|
||||||
void ICreatePlayersInfo.CreateServerPlayers(MapPreview map, Session lobbyInfo, List<GameInformation.Player> players, MersenneTwister playerRandom)
|
void ICreatePlayersInfo.CreateServerPlayers(MapPreview map, Session lobbyInfo, List<GameInformation.Player> players, MersenneTwister playerRandom)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException("EditorActorLayer must not be defined on the world actor.");
|
throw new NotImplementedException("EditorActorLayer must not be defined on the world actor.");
|
||||||
|
|||||||
@@ -12,57 +12,24 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using OpenRA.Graphics;
|
using OpenRA.Graphics;
|
||||||
using OpenRA.Mods.Common.Terrain;
|
using OpenRA.Mods.Common.Widgets;
|
||||||
using OpenRA.Traits;
|
using OpenRA.Traits;
|
||||||
|
|
||||||
namespace OpenRA.Mods.Common.Traits
|
namespace OpenRA.Mods.Common.Traits
|
||||||
{
|
{
|
||||||
public enum EditorCursorType { None, Actor, TerrainTemplate, Resource }
|
|
||||||
|
|
||||||
[TraitLocation(SystemActors.EditorWorld)]
|
[TraitLocation(SystemActors.EditorWorld)]
|
||||||
[Desc("Required for the map editor to work. Attach this to the world actor.")]
|
[Desc("Required for the map editor to work. Attach this to the world actor.")]
|
||||||
public class EditorCursorLayerInfo : TraitInfo, Requires<EditorActorLayerInfo>, Requires<ITiledTerrainRendererInfo>
|
public class EditorCursorLayerInfo : TraitInfo<EditorCursorLayer>, Requires<EditorActorLayerInfo>, Requires<ITiledTerrainRendererInfo> { }
|
||||||
|
|
||||||
|
public class EditorCursorLayer : ITickRender, IRenderAboveShroud, IRenderAnnotations
|
||||||
{
|
{
|
||||||
public readonly WAngle PreviewFacing = new(384);
|
IEditorBrush brush;
|
||||||
|
|
||||||
public override object Create(ActorInitializer init) { return new EditorCursorLayer(init.Self, this); }
|
static readonly IEnumerable<IRenderable> NoRenderables = Enumerable.Empty<IRenderable>();
|
||||||
}
|
|
||||||
|
|
||||||
public class EditorCursorLayer : IWorldLoaded, ITickRender, IRenderAboveShroud, IRenderAnnotations
|
public void SetBrush(IEditorBrush brush)
|
||||||
{
|
|
||||||
readonly EditorCursorLayerInfo info;
|
|
||||||
readonly EditorActorLayer editorLayer;
|
|
||||||
readonly ITiledTerrainRenderer terrainRenderer;
|
|
||||||
readonly World world;
|
|
||||||
IResourceRenderer[] resourceRenderers;
|
|
||||||
|
|
||||||
public int CurrentToken { get; private set; }
|
|
||||||
public EditorCursorType Type { get; private set; }
|
|
||||||
public EditorActorPreview Actor { get; private set; }
|
|
||||||
CPos actorLocation;
|
|
||||||
SubCell actorSubCell;
|
|
||||||
WVec actorCenterOffset;
|
|
||||||
bool actorSharesCell;
|
|
||||||
|
|
||||||
public TerrainTemplateInfo TerrainTemplate { get; private set; }
|
|
||||||
public string ResourceType { get; private set; }
|
|
||||||
CPos terrainOrResourceCell;
|
|
||||||
bool terrainOrResourceDirty;
|
|
||||||
readonly List<IRenderable> terrainOrResourcePreview = new();
|
|
||||||
|
|
||||||
public EditorCursorLayer(Actor self, EditorCursorLayerInfo info)
|
|
||||||
{
|
{
|
||||||
this.info = info;
|
this.brush = brush;
|
||||||
world = self.World;
|
|
||||||
editorLayer = self.Trait<EditorActorLayer>();
|
|
||||||
terrainRenderer = self.Trait<ITiledTerrainRenderer>();
|
|
||||||
|
|
||||||
Type = EditorCursorType.None;
|
|
||||||
}
|
|
||||||
|
|
||||||
void IWorldLoaded.WorldLoaded(World w, WorldRenderer wr)
|
|
||||||
{
|
|
||||||
resourceRenderers = w.WorldActor.TraitsImplementing<IResourceRenderer>().ToArray();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ITickRender.TickRender(WorldRenderer wr, Actor self)
|
void ITickRender.TickRender(WorldRenderer wr, Actor self)
|
||||||
@@ -70,69 +37,15 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
if (wr.World.Type != WorldType.Editor)
|
if (wr.World.Type != WorldType.Editor)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (Type == EditorCursorType.TerrainTemplate || Type == EditorCursorType.Resource)
|
brush?.TickRender(wr, self);
|
||||||
{
|
|
||||||
var cell = wr.Viewport.ViewToWorld(Viewport.LastMousePos);
|
|
||||||
if (terrainOrResourceCell != cell || terrainOrResourceDirty)
|
|
||||||
{
|
|
||||||
terrainOrResourceCell = cell;
|
|
||||||
terrainOrResourceDirty = false;
|
|
||||||
terrainOrResourcePreview.Clear();
|
|
||||||
|
|
||||||
var pos = world.Map.CenterOfCell(cell);
|
|
||||||
if (Type == EditorCursorType.TerrainTemplate)
|
|
||||||
terrainOrResourcePreview.AddRange(terrainRenderer.RenderPreview(wr, TerrainTemplate, pos));
|
|
||||||
else
|
|
||||||
terrainOrResourcePreview.AddRange(resourceRenderers.SelectMany(r => r.RenderPreview(wr, ResourceType, pos)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (Type == EditorCursorType.Actor)
|
|
||||||
{
|
|
||||||
// Offset mouse position by the center offset (in world pixels)
|
|
||||||
var worldPx = wr.Viewport.ViewToWorldPx(Viewport.LastMousePos) - wr.ScreenPxOffset(actorCenterOffset);
|
|
||||||
var cell = wr.Viewport.ViewToWorld(wr.Viewport.WorldToViewPx(worldPx));
|
|
||||||
var subCell = actorSharesCell ? editorLayer.FreeSubCellAt(cell) : SubCell.Invalid;
|
|
||||||
var updated = false;
|
|
||||||
if (actorLocation != cell)
|
|
||||||
{
|
|
||||||
actorLocation = cell;
|
|
||||||
Actor.ReplaceInit(new LocationInit(cell));
|
|
||||||
updated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (actorSubCell != subCell)
|
|
||||||
{
|
|
||||||
actorSubCell = subCell;
|
|
||||||
|
|
||||||
if (Actor.RemoveInits<SubCellInit>() > 0)
|
|
||||||
updated = true;
|
|
||||||
|
|
||||||
var subcell = world.Map.Tiles.Contains(cell) ? editorLayer.FreeSubCellAt(cell) : SubCell.Invalid;
|
|
||||||
if (subcell != SubCell.Invalid)
|
|
||||||
{
|
|
||||||
Actor.AddInit(new SubCellInit(subcell));
|
|
||||||
updated = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (updated)
|
|
||||||
Actor = new EditorActorPreview(wr, null, Actor.Export(), Actor.Owner);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static readonly IEnumerable<IRenderable> NoRenderables = Enumerable.Empty<IRenderable>();
|
|
||||||
IEnumerable<IRenderable> IRenderAboveShroud.RenderAboveShroud(Actor self, WorldRenderer wr)
|
IEnumerable<IRenderable> IRenderAboveShroud.RenderAboveShroud(Actor self, WorldRenderer wr)
|
||||||
{
|
{
|
||||||
if (wr.World.Type != WorldType.Editor)
|
if (wr.World.Type != WorldType.Editor)
|
||||||
return NoRenderables;
|
return NoRenderables;
|
||||||
|
|
||||||
if (Type == EditorCursorType.TerrainTemplate || Type == EditorCursorType.Resource)
|
return brush?.RenderAboveShroud(self, wr) ?? NoRenderables;
|
||||||
return terrainOrResourcePreview;
|
|
||||||
|
|
||||||
if (Type == EditorCursorType.Actor)
|
|
||||||
return Actor.Render().OrderBy(WorldRenderer.RenderableZPositionComparisonKey);
|
|
||||||
|
|
||||||
return NoRenderables;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IRenderAboveShroud.SpatiallyPartitionable => false;
|
bool IRenderAboveShroud.SpatiallyPartitionable => false;
|
||||||
@@ -142,88 +55,9 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
if (wr.World.Type != WorldType.Editor)
|
if (wr.World.Type != WorldType.Editor)
|
||||||
return NoRenderables;
|
return NoRenderables;
|
||||||
|
|
||||||
return Type == EditorCursorType.Actor ? Actor.RenderAnnotations() : NoRenderables;
|
return brush?.RenderAnnotations(self, wr) ?? NoRenderables;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IRenderAnnotations.SpatiallyPartitionable => false;
|
bool IRenderAnnotations.SpatiallyPartitionable => false;
|
||||||
|
|
||||||
public int SetActor(WorldRenderer wr, ActorInfo actor, PlayerReference owner)
|
|
||||||
{
|
|
||||||
var ios = actor.TraitInfoOrDefault<IOccupySpaceInfo>();
|
|
||||||
var buildingInfo = ios as BuildingInfo;
|
|
||||||
actorCenterOffset = buildingInfo?.CenterOffset(world) ?? WVec.Zero;
|
|
||||||
actorSharesCell = ios != null && ios.SharesCell;
|
|
||||||
actorSubCell = SubCell.Invalid;
|
|
||||||
|
|
||||||
// Enforce first entry of ValidOwnerNames as owner if the actor has RequiresSpecificOwners
|
|
||||||
var ownerName = owner.Name;
|
|
||||||
var specificOwnerInfo = actor.TraitInfoOrDefault<RequiresSpecificOwnersInfo>();
|
|
||||||
if (specificOwnerInfo != null && !specificOwnerInfo.ValidOwnerNames.Contains(ownerName))
|
|
||||||
ownerName = specificOwnerInfo.ValidOwnerNames.First();
|
|
||||||
|
|
||||||
var reference = new ActorReference(actor.Name)
|
|
||||||
{
|
|
||||||
new OwnerInit(ownerName),
|
|
||||||
new FactionInit(owner.Faction)
|
|
||||||
};
|
|
||||||
|
|
||||||
var worldPx = wr.Viewport.ViewToWorldPx(Viewport.LastMousePos) - wr.ScreenPxOffset(actorCenterOffset);
|
|
||||||
var cell = wr.Viewport.ViewToWorld(wr.Viewport.WorldToViewPx(worldPx));
|
|
||||||
|
|
||||||
reference.Add(new LocationInit(cell));
|
|
||||||
if (ios != null && ios.SharesCell)
|
|
||||||
{
|
|
||||||
actorSubCell = editorLayer.FreeSubCellAt(cell);
|
|
||||||
if (actorSubCell != SubCell.Invalid)
|
|
||||||
reference.Add(new SubCellInit(actorSubCell));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (actor.HasTraitInfo<IFacingInfo>())
|
|
||||||
reference.Add(new FacingInit(info.PreviewFacing));
|
|
||||||
|
|
||||||
Type = EditorCursorType.Actor;
|
|
||||||
Actor = new EditorActorPreview(wr, null, reference, owner);
|
|
||||||
TerrainTemplate = null;
|
|
||||||
ResourceType = null;
|
|
||||||
|
|
||||||
return ++CurrentToken;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int SetTerrainTemplate(WorldRenderer wr, TerrainTemplateInfo template)
|
|
||||||
{
|
|
||||||
terrainOrResourceCell = wr.Viewport.ViewToWorld(wr.Viewport.WorldToViewPx(Viewport.LastMousePos));
|
|
||||||
|
|
||||||
Type = EditorCursorType.TerrainTemplate;
|
|
||||||
TerrainTemplate = template;
|
|
||||||
Actor = null;
|
|
||||||
ResourceType = null;
|
|
||||||
terrainOrResourceDirty = true;
|
|
||||||
|
|
||||||
return ++CurrentToken;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int SetResource(WorldRenderer wr, string resourceType)
|
|
||||||
{
|
|
||||||
terrainOrResourceCell = wr.Viewport.ViewToWorld(wr.Viewport.WorldToViewPx(Viewport.LastMousePos));
|
|
||||||
|
|
||||||
Type = EditorCursorType.Resource;
|
|
||||||
ResourceType = resourceType;
|
|
||||||
Actor = null;
|
|
||||||
TerrainTemplate = null;
|
|
||||||
terrainOrResourceDirty = true;
|
|
||||||
|
|
||||||
return ++CurrentToken;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Clear(int token)
|
|
||||||
{
|
|
||||||
if (token != CurrentToken)
|
|
||||||
return;
|
|
||||||
|
|
||||||
Type = EditorCursorType.None;
|
|
||||||
Actor = null;
|
|
||||||
TerrainTemplate = null;
|
|
||||||
ResourceType = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,77 +0,0 @@
|
|||||||
#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.Mods.Common.Graphics;
|
|
||||||
using OpenRA.Mods.Common.Widgets;
|
|
||||||
using OpenRA.Traits;
|
|
||||||
using OpenRA.Widgets;
|
|
||||||
using Color = OpenRA.Primitives.Color;
|
|
||||||
|
|
||||||
namespace OpenRA.Mods.Common.Traits
|
|
||||||
{
|
|
||||||
[TraitLocation(SystemActors.EditorWorld)]
|
|
||||||
[Desc("Renders the selection grid in the editor.")]
|
|
||||||
public class EditorSelectionLayerInfo : TraitInfo, Requires<LoadWidgetAtGameStartInfo>, IEditorSelectionLayer
|
|
||||||
{
|
|
||||||
[Desc("Main color of the selection grid.")]
|
|
||||||
public readonly Color MainColor = Color.White;
|
|
||||||
|
|
||||||
[Desc("Alternate color of the selection grid.")]
|
|
||||||
public readonly Color AltColor = Color.Black;
|
|
||||||
|
|
||||||
[Desc("Main color of the paste grid.")]
|
|
||||||
public readonly Color PasteColor = Color.FromArgb(0xFF4CFF00);
|
|
||||||
|
|
||||||
[Desc("Thickness of the selection grid lines.")]
|
|
||||||
public readonly int LineThickness = 1;
|
|
||||||
|
|
||||||
[Desc("Render offset of the secondary grid lines.")]
|
|
||||||
public readonly int2 AltPixelOffset = new(1, 1);
|
|
||||||
|
|
||||||
public override object Create(ActorInitializer init) { return new EditorSelectionLayer(this); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class EditorSelectionLayer : IRenderAnnotations, IWorldLoaded
|
|
||||||
{
|
|
||||||
readonly EditorSelectionLayerInfo info;
|
|
||||||
EditorViewportControllerWidget editor;
|
|
||||||
|
|
||||||
public EditorSelectionLayer(EditorSelectionLayerInfo info)
|
|
||||||
{
|
|
||||||
this.info = info;
|
|
||||||
}
|
|
||||||
|
|
||||||
void IWorldLoaded.WorldLoaded(World w, WorldRenderer wr)
|
|
||||||
{
|
|
||||||
var worldRoot = Ui.Root.Get<ContainerWidget>("EDITOR_WORLD_ROOT");
|
|
||||||
editor = worldRoot.Get<EditorViewportControllerWidget>("MAP_EDITOR");
|
|
||||||
}
|
|
||||||
|
|
||||||
IEnumerable<IRenderable> IRenderAnnotations.RenderAnnotations(Actor self, WorldRenderer wr)
|
|
||||||
{
|
|
||||||
if (editor.DefaultBrush.CurrentDragBounds != null)
|
|
||||||
{
|
|
||||||
yield return new EditorSelectionAnnotationRenderable(editor.DefaultBrush.CurrentDragBounds, info.AltColor, info.AltPixelOffset, null);
|
|
||||||
yield return new EditorSelectionAnnotationRenderable(editor.DefaultBrush.CurrentDragBounds, info.MainColor, int2.Zero, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (editor.CurrentBrush is EditorCopyPasteBrush pasteBrush && pasteBrush.PastePreviewPosition != null)
|
|
||||||
{
|
|
||||||
yield return new EditorSelectionAnnotationRenderable(pasteBrush.Region, info.AltColor, info.AltPixelOffset, pasteBrush.PastePreviewPosition);
|
|
||||||
yield return new EditorSelectionAnnotationRenderable(pasteBrush.Region, info.PasteColor, int2.Zero, pasteBrush.PastePreviewPosition);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IRenderAnnotations.SpatiallyPartitionable => false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
#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 MovePreviewFacing : UpdateRule
|
||||||
|
{
|
||||||
|
public override string Name => "Move map editor preview facing to EditorActorLayer";
|
||||||
|
|
||||||
|
public override string Description =>
|
||||||
|
"PreviewFacing property was moved from the EditorCursorLayer to the EditorActorLayer.";
|
||||||
|
|
||||||
|
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
|
||||||
|
{
|
||||||
|
var cursorLayer = actorNode.LastChildMatching("EditorCursorLayer");
|
||||||
|
if (cursorLayer == null || cursorLayer.IsRemoval())
|
||||||
|
yield break;
|
||||||
|
|
||||||
|
var node = cursorLayer.LastChildMatching("PreviewFacing");
|
||||||
|
cursorLayer.RemoveNodes("PreviewFacing");
|
||||||
|
if (node == null || node.IsRemoval())
|
||||||
|
yield break;
|
||||||
|
|
||||||
|
var actorLayer = actorNode.LastChildMatching("EditorActorLayer");
|
||||||
|
if (actorLayer != null && !actorLayer.IsRemoval())
|
||||||
|
{
|
||||||
|
node.RenameKey("DefaultActorFacing");
|
||||||
|
actorLayer.AddNode(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -88,6 +88,7 @@ namespace OpenRA.Mods.Common.UpdateRules
|
|||||||
new RemoveEditorSelectionLayerProperties(),
|
new RemoveEditorSelectionLayerProperties(),
|
||||||
new AddMarkerLayerOverlay(),
|
new AddMarkerLayerOverlay(),
|
||||||
new AddSupportPowerBlockedCursor(),
|
new AddSupportPowerBlockedCursor(),
|
||||||
|
new MovePreviewFacing(),
|
||||||
|
|
||||||
// Execute these rules last to avoid premature yaml merge crashes.
|
// Execute these rules last to avoid premature yaml merge crashes.
|
||||||
new ReplaceCloakPalette(),
|
new ReplaceCloakPalette(),
|
||||||
|
|||||||
@@ -11,12 +11,23 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using OpenRA.Graphics;
|
using OpenRA.Graphics;
|
||||||
|
using OpenRA.Mods.Common.Traits;
|
||||||
using OpenRA.Widgets;
|
using OpenRA.Widgets;
|
||||||
|
using Color = OpenRA.Primitives.Color;
|
||||||
|
|
||||||
namespace OpenRA.Mods.Common.Widgets
|
namespace OpenRA.Mods.Common.Widgets
|
||||||
{
|
{
|
||||||
public class EditorViewportControllerWidget : Widget
|
public class EditorViewportControllerWidget : Widget
|
||||||
{
|
{
|
||||||
|
[Desc("Main color of the selection grid.")]
|
||||||
|
public readonly Color SelectionMainColor = Color.White;
|
||||||
|
|
||||||
|
[Desc("Alternate color of the selection grid.")]
|
||||||
|
public readonly Color SelectionAltColor = Color.Black;
|
||||||
|
|
||||||
|
[Desc("Main color of the copy / paste grid.")]
|
||||||
|
public readonly Color PasteColor = Color.FromArgb(0xFF4CFF00);
|
||||||
|
|
||||||
public IEditorBrush CurrentBrush { get; private set; }
|
public IEditorBrush CurrentBrush { get; private set; }
|
||||||
|
|
||||||
public readonly string TooltipContainer;
|
public readonly string TooltipContainer;
|
||||||
@@ -27,6 +38,8 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
|
|
||||||
readonly Lazy<TooltipContainerWidget> tooltipContainer;
|
readonly Lazy<TooltipContainerWidget> tooltipContainer;
|
||||||
readonly WorldRenderer worldRenderer;
|
readonly WorldRenderer worldRenderer;
|
||||||
|
readonly EditorCursorLayer editorCursor;
|
||||||
|
public int2 SelectionAltOffset { get; }
|
||||||
|
|
||||||
bool enableTooltips;
|
bool enableTooltips;
|
||||||
|
|
||||||
@@ -37,8 +50,15 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
tooltipContainer = Exts.Lazy(() => Ui.Root.Get<TooltipContainerWidget>(TooltipContainer));
|
tooltipContainer = Exts.Lazy(() => Ui.Root.Get<TooltipContainerWidget>(TooltipContainer));
|
||||||
CurrentBrush = DefaultBrush = new EditorDefaultBrush(this, worldRenderer);
|
CurrentBrush = DefaultBrush = new EditorDefaultBrush(this, worldRenderer);
|
||||||
|
|
||||||
|
editorCursor = worldRenderer.World.WorldActor.Trait<EditorCursorLayer>();
|
||||||
|
editorCursor.SetBrush(CurrentBrush);
|
||||||
|
|
||||||
// Allow zooming out to full map size
|
// Allow zooming out to full map size
|
||||||
worldRenderer.Viewport.UnlockMinimumZoom(0.25f);
|
worldRenderer.Viewport.UnlockMinimumZoom(0.25f);
|
||||||
|
|
||||||
|
SelectionAltOffset = worldRenderer.World.Map.Grid.Type == MapGridType.Rectangular
|
||||||
|
? new int2(1, 1)
|
||||||
|
: new int2(0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClearBrush() { SetBrush(null); }
|
public void ClearBrush() { SetBrush(null); }
|
||||||
@@ -50,6 +70,7 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
CurrentBrush = brush ?? DefaultBrush;
|
CurrentBrush = brush ?? DefaultBrush;
|
||||||
|
|
||||||
BrushChanged?.Invoke();
|
BrushChanged?.Invoke();
|
||||||
|
editorCursor.SetBrush(CurrentBrush);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void MouseEntered()
|
public override void MouseEntered()
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
readonly DropDownButtonWidget ownersDropDown;
|
readonly DropDownButtonWidget ownersDropDown;
|
||||||
readonly Ruleset mapRules;
|
readonly Ruleset mapRules;
|
||||||
readonly ActorSelectorActor[] allActors;
|
readonly ActorSelectorActor[] allActors;
|
||||||
readonly EditorCursorLayer editorCursor;
|
readonly EditorViewportControllerWidget editor;
|
||||||
|
|
||||||
PlayerReference selectedOwner;
|
PlayerReference selectedOwner;
|
||||||
|
|
||||||
@@ -53,7 +53,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
{
|
{
|
||||||
mapRules = world.Map.Rules;
|
mapRules = world.Map.Rules;
|
||||||
ownersDropDown = widget.Get<DropDownButtonWidget>("OWNERS_DROPDOWN");
|
ownersDropDown = widget.Get<DropDownButtonWidget>("OWNERS_DROPDOWN");
|
||||||
editorCursor = world.WorldActor.Trait<EditorCursorLayer>();
|
editor = widget.Parent.Parent.Get<EditorViewportControllerWidget>("MAP_EDITOR");
|
||||||
var editorLayer = world.WorldActor.Trait<EditorActorLayer>();
|
var editorLayer = world.WorldActor.Trait<EditorActorLayer>();
|
||||||
|
|
||||||
selectedOwner = editorLayer.Players.Players.Values.First();
|
selectedOwner = editorLayer.Players.Players.Values.First();
|
||||||
@@ -167,9 +167,9 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
ownersDropDown.TextColor = option.Color;
|
ownersDropDown.TextColor = option.Color;
|
||||||
InitializePreviews();
|
InitializePreviews();
|
||||||
|
|
||||||
var actor = editorCursor.Actor;
|
if (editor.CurrentBrush is EditorActorBrush brush)
|
||||||
if (actor != null)
|
|
||||||
{
|
{
|
||||||
|
var actor = brush.Preview;
|
||||||
actor.Owner = option;
|
actor.Owner = option;
|
||||||
actor.ReplaceInit(new OwnerInit(option.Name));
|
actor.ReplaceInit(new OwnerInit(option.Name));
|
||||||
actor.ReplaceInit(new FactionInit(option.Faction));
|
actor.ReplaceInit(new FactionInit(option.Faction));
|
||||||
@@ -204,7 +204,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var item = ScrollItemWidget.Setup(ItemTemplate,
|
var item = ScrollItemWidget.Setup(ItemTemplate,
|
||||||
() => editorCursor.Type == EditorCursorType.Actor && editorCursor.Actor.Info == actor,
|
() => Editor.CurrentBrush is EditorActorBrush eab && eab.Preview.Info == actor,
|
||||||
() => Editor.SetBrush(new EditorActorBrush(Editor, actor, selectedOwner, WorldRenderer)));
|
() => Editor.SetBrush(new EditorActorBrush(Editor, actor, selectedOwner, WorldRenderer)));
|
||||||
|
|
||||||
var preview = item.Get<ActorPreviewWidget>("ACTOR_PREVIEW");
|
var preview = item.Get<ActorPreviewWidget>("ACTOR_PREVIEW");
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
{
|
{
|
||||||
readonly EditorViewportControllerWidget editor;
|
readonly EditorViewportControllerWidget editor;
|
||||||
readonly WorldRenderer worldRenderer;
|
readonly WorldRenderer worldRenderer;
|
||||||
readonly EditorCursorLayer editorCursor;
|
|
||||||
|
|
||||||
readonly ScrollPanelWidget layerTemplateList;
|
readonly ScrollPanelWidget layerTemplateList;
|
||||||
readonly ScrollItemWidget layerPreviewTemplate;
|
readonly ScrollItemWidget layerPreviewTemplate;
|
||||||
@@ -29,8 +28,6 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
{
|
{
|
||||||
this.worldRenderer = worldRenderer;
|
this.worldRenderer = worldRenderer;
|
||||||
editor = widget.Parent.Parent.Get<EditorViewportControllerWidget>("MAP_EDITOR");
|
editor = widget.Parent.Parent.Get<EditorViewportControllerWidget>("MAP_EDITOR");
|
||||||
editorCursor = worldRenderer.World.WorldActor.Trait<EditorCursorLayer>();
|
|
||||||
|
|
||||||
layerTemplateList = widget.Get<ScrollPanelWidget>("LAYERTEMPLATE_LIST");
|
layerTemplateList = widget.Get<ScrollPanelWidget>("LAYERTEMPLATE_LIST");
|
||||||
layerTemplateList.Layout = new GridLayout(layerTemplateList);
|
layerTemplateList.Layout = new GridLayout(layerTemplateList);
|
||||||
layerPreviewTemplate = layerTemplateList.Get<ScrollItemWidget>("LAYERPREVIEW_TEMPLATE");
|
layerPreviewTemplate = layerTemplateList.Get<ScrollItemWidget>("LAYERPREVIEW_TEMPLATE");
|
||||||
@@ -46,7 +43,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
foreach (var resourceType in resourceRenderer.ResourceTypes)
|
foreach (var resourceType in resourceRenderer.ResourceTypes)
|
||||||
{
|
{
|
||||||
var newResourcePreviewTemplate = ScrollItemWidget.Setup(layerPreviewTemplate,
|
var newResourcePreviewTemplate = ScrollItemWidget.Setup(layerPreviewTemplate,
|
||||||
() => editorCursor.Type == EditorCursorType.Resource && editorCursor.ResourceType == resourceType,
|
() => editor.CurrentBrush is EditorResourceBrush brush && brush.ResourceType == resourceType,
|
||||||
() => editor.SetBrush(new EditorResourceBrush(editor, resourceType, worldRenderer)));
|
() => editor.SetBrush(new EditorResourceBrush(editor, resourceType, worldRenderer)));
|
||||||
|
|
||||||
newResourcePreviewTemplate.Bounds.X = 0;
|
newResourcePreviewTemplate.Bounds.X = 0;
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ using System.IO;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using OpenRA.Graphics;
|
using OpenRA.Graphics;
|
||||||
using OpenRA.Mods.Common.Terrain;
|
using OpenRA.Mods.Common.Terrain;
|
||||||
using OpenRA.Mods.Common.Traits;
|
|
||||||
using OpenRA.Widgets;
|
using OpenRA.Widgets;
|
||||||
|
|
||||||
namespace OpenRA.Mods.Common.Widgets.Logic
|
namespace OpenRA.Mods.Common.Widgets.Logic
|
||||||
@@ -40,7 +39,6 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
|
|
||||||
readonly ITemplatedTerrainInfo terrainInfo;
|
readonly ITemplatedTerrainInfo terrainInfo;
|
||||||
readonly TileSelectorTemplate[] allTemplates;
|
readonly TileSelectorTemplate[] allTemplates;
|
||||||
readonly EditorCursorLayer editorCursor;
|
|
||||||
|
|
||||||
[ObjectCreator.UseCtor]
|
[ObjectCreator.UseCtor]
|
||||||
public TileSelectorLogic(Widget widget, ModData modData, World world, WorldRenderer worldRenderer)
|
public TileSelectorLogic(Widget widget, ModData modData, World world, WorldRenderer worldRenderer)
|
||||||
@@ -51,7 +49,6 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
throw new InvalidDataException("TileSelectorLogic requires a template-based tileset.");
|
throw new InvalidDataException("TileSelectorLogic requires a template-based tileset.");
|
||||||
|
|
||||||
allTemplates = terrainInfo.Templates.Values.Select(t => new TileSelectorTemplate(t)).ToArray();
|
allTemplates = terrainInfo.Templates.Values.Select(t => new TileSelectorTemplate(t)).ToArray();
|
||||||
editorCursor = world.WorldActor.Trait<EditorCursorLayer>();
|
|
||||||
|
|
||||||
allCategories = allTemplates.SelectMany(t => t.Categories)
|
allCategories = allTemplates.SelectMany(t => t.Categories)
|
||||||
.Distinct()
|
.Distinct()
|
||||||
@@ -108,7 +105,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
|
|
||||||
var tileId = t.Template.Id;
|
var tileId = t.Template.Id;
|
||||||
var item = ScrollItemWidget.Setup(ItemTemplate,
|
var item = ScrollItemWidget.Setup(ItemTemplate,
|
||||||
() => editorCursor.Type == EditorCursorType.TerrainTemplate && editorCursor.TerrainTemplate.Id == tileId,
|
() => Editor.CurrentBrush is EditorTileBrush editorCursor && editorCursor.TerrainTemplate.Id == tileId,
|
||||||
() => Editor.SetBrush(new EditorTileBrush(Editor, tileId, WorldRenderer)));
|
() => Editor.SetBrush(new EditorTileBrush(Editor, tileId, WorldRenderer)));
|
||||||
|
|
||||||
var preview = item.Get<TerrainTemplatePreviewWidget>("TILE_PREVIEW");
|
var preview = item.Get<TerrainTemplatePreviewWidget>("TILE_PREVIEW");
|
||||||
|
|||||||
@@ -294,7 +294,6 @@ EditorWorld:
|
|||||||
TerrainType: BlueTiberium
|
TerrainType: BlueTiberium
|
||||||
AllowedTerrainTypes: Clear, Road
|
AllowedTerrainTypes: Clear, Road
|
||||||
MaxDensity: 12
|
MaxDensity: 12
|
||||||
EditorSelectionLayer:
|
|
||||||
LoadWidgetAtGameStart:
|
LoadWidgetAtGameStart:
|
||||||
EditorActionManager:
|
EditorActionManager:
|
||||||
BuildableTerrainOverlay:
|
BuildableTerrainOverlay:
|
||||||
|
|||||||
@@ -260,7 +260,6 @@ EditorWorld:
|
|||||||
TerrainType: Spice
|
TerrainType: Spice
|
||||||
AllowedTerrainTypes: SpiceSand
|
AllowedTerrainTypes: SpiceSand
|
||||||
MaxDensity: 20
|
MaxDensity: 20
|
||||||
EditorSelectionLayer:
|
|
||||||
LoadWidgetAtGameStart:
|
LoadWidgetAtGameStart:
|
||||||
EditorActionManager:
|
EditorActionManager:
|
||||||
BuildableTerrainOverlay:
|
BuildableTerrainOverlay:
|
||||||
|
|||||||
@@ -316,7 +316,6 @@ EditorWorld:
|
|||||||
TerrainType: Gems
|
TerrainType: Gems
|
||||||
AllowedTerrainTypes: Clear, Road
|
AllowedTerrainTypes: Clear, Road
|
||||||
MaxDensity: 3
|
MaxDensity: 3
|
||||||
EditorSelectionLayer:
|
|
||||||
LoadWidgetAtGameStart:
|
LoadWidgetAtGameStart:
|
||||||
EditorActionManager:
|
EditorActionManager:
|
||||||
BuildableTerrainOverlay:
|
BuildableTerrainOverlay:
|
||||||
|
|||||||
@@ -422,8 +422,6 @@ EditorWorld:
|
|||||||
AllowedTerrainTypes: Clear, Rough, DirtRoad
|
AllowedTerrainTypes: Clear, Rough, DirtRoad
|
||||||
MaxDensity: 2
|
MaxDensity: 2
|
||||||
VeinholeActors: veinhole
|
VeinholeActors: veinhole
|
||||||
EditorSelectionLayer:
|
|
||||||
AltPixelOffset: 0,1
|
|
||||||
LoadWidgetAtGameStart:
|
LoadWidgetAtGameStart:
|
||||||
EditorActionManager:
|
EditorActionManager:
|
||||||
BuildableTerrainOverlay:
|
BuildableTerrainOverlay:
|
||||||
|
|||||||
Reference in New Issue
Block a user