Merge pull request #8065 from pchote/ingame-map-editor
Add the new map editor.
This commit is contained in:
@@ -375,6 +375,11 @@ namespace OpenRA
|
|||||||
ModData.LoadScreen.StartGame(args);
|
ModData.LoadScreen.StartGame(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void LoadEditor(string mapUid)
|
||||||
|
{
|
||||||
|
StartGame(mapUid, WorldType.Editor);
|
||||||
|
}
|
||||||
|
|
||||||
public static void LoadShellMap()
|
public static void LoadShellMap()
|
||||||
{
|
{
|
||||||
var shellmap = ChooseShellmap();
|
var shellmap = ChooseShellmap();
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ namespace OpenRA.Graphics
|
|||||||
Sheet.ReleaseBuffer();
|
Sheet.ReleaseBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Sprite TileSprite(TerrainTile r)
|
public Sprite TileSprite(TerrainTile r, int? variant = null)
|
||||||
{
|
{
|
||||||
TheaterTemplate template;
|
TheaterTemplate template;
|
||||||
if (!templates.TryGetValue(r.Type, out template))
|
if (!templates.TryGetValue(r.Type, out template))
|
||||||
@@ -91,7 +91,7 @@ namespace OpenRA.Graphics
|
|||||||
if (r.Index >= template.Stride)
|
if (r.Index >= template.Stride)
|
||||||
return missingTile;
|
return missingTile;
|
||||||
|
|
||||||
var start = template.Variants > 1 ? random.Next(template.Variants) : 0;
|
var start = template.Variants > 1 ? variant.HasValue ? variant.Value : random.Next(template.Variants) : 0;
|
||||||
return template.Sprites[start * template.Stride + r.Index];
|
return template.Sprites[start * template.Stride + r.Index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ namespace OpenRA
|
|||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MiniYaml Save()
|
public MiniYaml Save(Func<object, bool> initFilter = null)
|
||||||
{
|
{
|
||||||
var ret = new MiniYaml(Type);
|
var ret = new MiniYaml(Type);
|
||||||
foreach (var init in InitDict)
|
foreach (var init in InitDict)
|
||||||
@@ -56,6 +56,9 @@ namespace OpenRA
|
|||||||
if (init is ISuppressInitExport)
|
if (init is ISuppressInitExport)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (initFilter != null && !initFilter(init))
|
||||||
|
continue;
|
||||||
|
|
||||||
var initName = init.GetType().Name;
|
var initName = init.GetType().Name;
|
||||||
ret.Nodes.Add(new MiniYamlNode(initName.Substring(0, initName.Length - 4), FieldSaver.Save(init)));
|
ret.Nodes.Add(new MiniYamlNode(initName.Substring(0, initName.Length - 4), FieldSaver.Save(init)));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -91,6 +91,27 @@ namespace OpenRA.Primitives
|
|||||||
return new T[0];
|
return new T[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Remove<T>(T val)
|
||||||
|
{
|
||||||
|
var t = val.GetType();
|
||||||
|
|
||||||
|
foreach (var i in t.GetInterfaces())
|
||||||
|
InnerRemove(i, val);
|
||||||
|
foreach (var tt in t.BaseTypes())
|
||||||
|
InnerRemove(tt, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InnerRemove(Type t, object val)
|
||||||
|
{
|
||||||
|
List<object> objs;
|
||||||
|
object obj;
|
||||||
|
|
||||||
|
if (dataMultiple.TryGetValue(t, out objs))
|
||||||
|
objs.Remove(val);
|
||||||
|
else if (dataSingular.TryGetValue(t, out obj))
|
||||||
|
dataSingular.Remove(t);
|
||||||
|
}
|
||||||
|
|
||||||
public IEnumerator GetEnumerator()
|
public IEnumerator GetEnumerator()
|
||||||
{
|
{
|
||||||
return WithInterface<object>().GetEnumerator();
|
return WithInterface<object>().GetEnumerator();
|
||||||
|
|||||||
@@ -158,7 +158,12 @@ namespace OpenRA.Traits
|
|||||||
|
|
||||||
public interface IRadarColorModifier { Color RadarColorOverride(Actor self); }
|
public interface IRadarColorModifier { Color RadarColorOverride(Actor self); }
|
||||||
|
|
||||||
public interface IOccupySpaceInfo : ITraitInfo { }
|
public interface IOccupySpaceInfo : ITraitInfo
|
||||||
|
{
|
||||||
|
IReadOnlyDictionary<CPos, SubCell> OccupiedCells(ActorInfo info, CPos location, SubCell subCell = SubCell.Any);
|
||||||
|
bool SharesCell { get; }
|
||||||
|
}
|
||||||
|
|
||||||
public interface IOccupySpace
|
public interface IOccupySpace
|
||||||
{
|
{
|
||||||
WPos CenterPosition { get; }
|
WPos CenterPosition { get; }
|
||||||
|
|||||||
@@ -493,6 +493,8 @@ namespace OpenRA.Widgets
|
|||||||
|
|
||||||
public class ContainerWidget : Widget
|
public class ContainerWidget : Widget
|
||||||
{
|
{
|
||||||
|
public readonly bool ClickThrough = true;
|
||||||
|
|
||||||
public ContainerWidget() { IgnoreMouseOver = true; }
|
public ContainerWidget() { IgnoreMouseOver = true; }
|
||||||
public ContainerWidget(ContainerWidget other)
|
public ContainerWidget(ContainerWidget other)
|
||||||
: base(other) { IgnoreMouseOver = true; }
|
: base(other) { IgnoreMouseOver = true; }
|
||||||
@@ -501,6 +503,11 @@ namespace OpenRA.Widgets
|
|||||||
public override Widget Clone() { return new ContainerWidget(this); }
|
public override Widget Clone() { return new ContainerWidget(this); }
|
||||||
public Func<KeyInput, bool> OnKeyPress = _ => false;
|
public Func<KeyInput, bool> OnKeyPress = _ => false;
|
||||||
public override bool HandleKeyPress(KeyInput e) { return OnKeyPress(e); }
|
public override bool HandleKeyPress(KeyInput e) { return OnKeyPress(e); }
|
||||||
|
|
||||||
|
public override bool HandleMouseInput(MouseInput mi)
|
||||||
|
{
|
||||||
|
return !ClickThrough && EventBounds.Contains(mi.Location);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class WidgetArgs : Dictionary<string, object>
|
public class WidgetArgs : Dictionary<string, object>
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ using OpenRA.Traits;
|
|||||||
|
|
||||||
namespace OpenRA
|
namespace OpenRA
|
||||||
{
|
{
|
||||||
public enum WorldType { Regular, Shellmap }
|
public enum WorldType { Regular, Shellmap, Editor }
|
||||||
|
|
||||||
public class World
|
public class World
|
||||||
{
|
{
|
||||||
@@ -170,7 +170,8 @@ namespace OpenRA
|
|||||||
TileSet = map.Rules.TileSets[Map.Tileset];
|
TileSet = map.Rules.TileSets[Map.Tileset];
|
||||||
SharedRandom = new MersenneTwister(orderManager.LobbyInfo.GlobalSettings.RandomSeed);
|
SharedRandom = new MersenneTwister(orderManager.LobbyInfo.GlobalSettings.RandomSeed);
|
||||||
|
|
||||||
WorldActor = CreateActor("World", new TypeDictionary());
|
var worldActorType = type == WorldType.Editor ? "EditorWorld" : "World";
|
||||||
|
WorldActor = CreateActor(worldActorType, new TypeDictionary());
|
||||||
ActorMap = WorldActor.Trait<ActorMap>();
|
ActorMap = WorldActor.Trait<ActorMap>();
|
||||||
ScreenMap = WorldActor.Trait<ScreenMap>();
|
ScreenMap = WorldActor.Trait<ScreenMap>();
|
||||||
|
|
||||||
@@ -198,8 +199,16 @@ namespace OpenRA
|
|||||||
|
|
||||||
public void LoadComplete(WorldRenderer wr)
|
public void LoadComplete(WorldRenderer wr)
|
||||||
{
|
{
|
||||||
|
// ScreenMap must be initialized before anything else
|
||||||
|
using (new Support.PerfTimer("ScreenMap.WorldLoaded"))
|
||||||
|
ScreenMap.WorldLoaded(this, wr);
|
||||||
|
|
||||||
foreach (var wlh in WorldActor.TraitsImplementing<IWorldLoaded>())
|
foreach (var wlh in WorldActor.TraitsImplementing<IWorldLoaded>())
|
||||||
{
|
{
|
||||||
|
// These have already been initialized
|
||||||
|
if (wlh == ScreenMap)
|
||||||
|
continue;
|
||||||
|
|
||||||
using (new Support.PerfTimer(wlh.GetType().Name + ".WorldLoaded"))
|
using (new Support.PerfTimer(wlh.GetType().Name + ".WorldLoaded"))
|
||||||
wlh.WorldLoaded(this, wr);
|
wlh.WorldLoaded(this, wr);
|
||||||
}
|
}
|
||||||
|
|||||||
134
OpenRA.Mods.Common/EditorBrushes/EditorActorBrush.cs
Normal file
134
OpenRA.Mods.Common/EditorBrushes/EditorActorBrush.cs
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007-2015 The OpenRA Developers (see AUTHORS)
|
||||||
|
* This file is part of OpenRA, which is free software. It is made
|
||||||
|
* available to you under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation. For more information,
|
||||||
|
* see COPYING.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Linq;
|
||||||
|
using OpenRA.FileFormats;
|
||||||
|
using OpenRA.Graphics;
|
||||||
|
using OpenRA.Mods.Common;
|
||||||
|
using OpenRA.Mods.Common.Graphics;
|
||||||
|
using OpenRA.Mods.Common.Traits;
|
||||||
|
using OpenRA.Orders;
|
||||||
|
using OpenRA.Primitives;
|
||||||
|
using OpenRA.Traits;
|
||||||
|
using OpenRA.Widgets;
|
||||||
|
|
||||||
|
namespace OpenRA.Mods.Common.Widgets
|
||||||
|
{
|
||||||
|
public class EditorActorBrush : IEditorBrush
|
||||||
|
{
|
||||||
|
public readonly ActorInfo Actor;
|
||||||
|
|
||||||
|
readonly WorldRenderer worldRenderer;
|
||||||
|
readonly World world;
|
||||||
|
readonly EditorActorLayer editorLayer;
|
||||||
|
readonly EditorViewportControllerWidget editorWidget;
|
||||||
|
readonly ActorPreviewWidget preview;
|
||||||
|
readonly CVec locationOffset;
|
||||||
|
readonly WVec previewOffset;
|
||||||
|
readonly PlayerReference owner;
|
||||||
|
|
||||||
|
int facing = 92;
|
||||||
|
|
||||||
|
public EditorActorBrush(EditorViewportControllerWidget editorWidget, ActorInfo actor, PlayerReference owner, WorldRenderer wr)
|
||||||
|
{
|
||||||
|
this.editorWidget = editorWidget;
|
||||||
|
worldRenderer = wr;
|
||||||
|
world = wr.World;
|
||||||
|
editorLayer = world.WorldActor.Trait<EditorActorLayer>();
|
||||||
|
|
||||||
|
Actor = actor;
|
||||||
|
this.owner = owner;
|
||||||
|
|
||||||
|
preview = editorWidget.Get<ActorPreviewWidget>("DRAG_ACTOR_PREVIEW");
|
||||||
|
preview.GetScale = () => worldRenderer.Viewport.Zoom;
|
||||||
|
preview.IsVisible = () => editorWidget.CurrentBrush == this;
|
||||||
|
|
||||||
|
var buildingInfo = actor.Traits.GetOrDefault<BuildingInfo>();
|
||||||
|
if (buildingInfo != null)
|
||||||
|
{
|
||||||
|
locationOffset = -FootprintUtils.AdjustForBuildingSize(buildingInfo);
|
||||||
|
previewOffset = FootprintUtils.CenterOffset(world, buildingInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
var td = new TypeDictionary();
|
||||||
|
td.Add(new FacingInit(facing));
|
||||||
|
td.Add(new TurretFacingInit(facing));
|
||||||
|
td.Add(new OwnerInit(owner.Name));
|
||||||
|
td.Add(new RaceInit(owner.Race));
|
||||||
|
preview.SetPreview(actor, td);
|
||||||
|
|
||||||
|
// The preview widget may be rendered by the higher-level code before it is ticked.
|
||||||
|
// Force a manual tick to ensure the bounds are set correctly for this first draw.
|
||||||
|
Tick();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool HandleMouseInput(MouseInput mi)
|
||||||
|
{
|
||||||
|
// Exclusively uses left and right mouse buttons, but nothing else
|
||||||
|
if (mi.Button != MouseButton.Left && mi.Button != MouseButton.Right)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (mi.Button == MouseButton.Right)
|
||||||
|
{
|
||||||
|
editorWidget.ClearBrush();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var cell = worldRenderer.Viewport.ViewToWorld(mi.Location);
|
||||||
|
if (mi.Button == MouseButton.Left && mi.Event == MouseInputEvent.Down && world.Map.Contains(cell))
|
||||||
|
{
|
||||||
|
var newActorReference = new ActorReference(Actor.Name);
|
||||||
|
newActorReference.Add(new OwnerInit(owner.Name));
|
||||||
|
|
||||||
|
cell += locationOffset;
|
||||||
|
newActorReference.Add(new LocationInit(cell));
|
||||||
|
|
||||||
|
var ios = Actor.Traits.GetOrDefault<IOccupySpaceInfo>();
|
||||||
|
if (ios != null && ios.SharesCell)
|
||||||
|
{
|
||||||
|
var subcell = editorLayer.FreeSubCellAt(cell);
|
||||||
|
if (subcell != SubCell.Invalid)
|
||||||
|
newActorReference.Add(new SubCellInit(subcell));
|
||||||
|
}
|
||||||
|
|
||||||
|
var initDict = newActorReference.InitDict;
|
||||||
|
|
||||||
|
if (Actor.Traits.Contains<IFacingInfo>())
|
||||||
|
initDict.Add(new FacingInit(facing));
|
||||||
|
|
||||||
|
if (Actor.Traits.Contains<TurretedInfo>())
|
||||||
|
initDict.Add(new TurretFacingInit(facing));
|
||||||
|
|
||||||
|
editorLayer.Add(newActorReference);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Tick()
|
||||||
|
{
|
||||||
|
var cell = worldRenderer.Viewport.ViewToWorld(Viewport.LastMousePos);
|
||||||
|
var pos = world.Map.CenterOfCell(cell + locationOffset) + previewOffset;
|
||||||
|
|
||||||
|
var origin = worldRenderer.Viewport.WorldToViewPx(worldRenderer.ScreenPxPosition(pos));
|
||||||
|
|
||||||
|
var zoom = worldRenderer.Viewport.Zoom;
|
||||||
|
var s = preview.IdealPreviewSize;
|
||||||
|
var o = preview.PreviewOffset;
|
||||||
|
preview.Bounds.X = origin.X - (int)(zoom * (o.X + s.X / 2));
|
||||||
|
preview.Bounds.Y = origin.Y - (int)(zoom * (o.Y + s.Y / 2));
|
||||||
|
preview.Bounds.Width = (int)(zoom * s.X);
|
||||||
|
preview.Bounds.Height = (int)(zoom * s.Y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
114
OpenRA.Mods.Common/EditorBrushes/EditorDefaultBrush.cs
Normal file
114
OpenRA.Mods.Common/EditorBrushes/EditorDefaultBrush.cs
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007-2015 The OpenRA Developers (see AUTHORS)
|
||||||
|
* This file is part of OpenRA, which is free software. It is made
|
||||||
|
* available to you under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation. For more information,
|
||||||
|
* see COPYING.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Linq;
|
||||||
|
using OpenRA.FileFormats;
|
||||||
|
using OpenRA.Graphics;
|
||||||
|
using OpenRA.Mods.Common;
|
||||||
|
using OpenRA.Mods.Common.Graphics;
|
||||||
|
using OpenRA.Mods.Common.Traits;
|
||||||
|
using OpenRA.Orders;
|
||||||
|
using OpenRA.Primitives;
|
||||||
|
using OpenRA.Traits;
|
||||||
|
using OpenRA.Widgets;
|
||||||
|
|
||||||
|
namespace OpenRA.Mods.Common.Widgets
|
||||||
|
{
|
||||||
|
public interface IEditorBrush
|
||||||
|
{
|
||||||
|
bool HandleMouseInput(MouseInput mi);
|
||||||
|
void Tick();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class EditorDefaultBrush : IEditorBrush
|
||||||
|
{
|
||||||
|
public readonly ActorInfo Actor;
|
||||||
|
|
||||||
|
readonly WorldRenderer worldRenderer;
|
||||||
|
readonly World world;
|
||||||
|
readonly EditorViewportControllerWidget editorWidget;
|
||||||
|
readonly EditorActorLayer editorLayer;
|
||||||
|
readonly Dictionary<int, ResourceType> resources;
|
||||||
|
|
||||||
|
public EditorDefaultBrush(EditorViewportControllerWidget editorWidget, WorldRenderer wr)
|
||||||
|
{
|
||||||
|
this.editorWidget = editorWidget;
|
||||||
|
worldRenderer = wr;
|
||||||
|
world = wr.World;
|
||||||
|
|
||||||
|
editorLayer = world.WorldActor.Trait<EditorActorLayer>();
|
||||||
|
resources = world.WorldActor.TraitsImplementing<ResourceType>()
|
||||||
|
.ToDictionary(r => r.Info.ResourceType, r => r);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool HandleMouseInput(MouseInput mi)
|
||||||
|
{
|
||||||
|
// Exclusively uses left and right mouse buttons, but nothing else
|
||||||
|
// Mouse move events are important for tooltips, so we always allow these through
|
||||||
|
if (mi.Button != MouseButton.Left && mi.Button != MouseButton.Right && mi.Event != MouseInputEvent.Move)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var cell = worldRenderer.Viewport.ViewToWorld(mi.Location);
|
||||||
|
if (mi.Event == MouseInputEvent.Up)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
var underCursor = editorLayer.PreviewsAt(worldRenderer.Viewport.ViewToWorldPx(mi.Location))
|
||||||
|
.FirstOrDefault();
|
||||||
|
|
||||||
|
ResourceType type;
|
||||||
|
if (underCursor != null)
|
||||||
|
editorWidget.SetTooltip(underCursor.Tooltip);
|
||||||
|
else if (world.Map.Contains(cell) && resources.TryGetValue(world.Map.MapResources.Value[cell].Type, out type))
|
||||||
|
editorWidget.SetTooltip(type.Info.Name);
|
||||||
|
else
|
||||||
|
editorWidget.SetTooltip(null);
|
||||||
|
|
||||||
|
// Finished with mouse move events, so let them bubble up the widget tree
|
||||||
|
if (mi.Event == MouseInputEvent.Move)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (mi.Button == MouseButton.Right)
|
||||||
|
{
|
||||||
|
editorWidget.SetTooltip(null);
|
||||||
|
|
||||||
|
if (underCursor != null)
|
||||||
|
editorLayer.Remove(underCursor);
|
||||||
|
|
||||||
|
if (world.Map.MapResources.Value[cell].Type != 0)
|
||||||
|
world.Map.MapResources.Value[cell] = new ResourceTile();
|
||||||
|
}
|
||||||
|
else if (mi.Button == MouseButton.Left && mi.Event == MouseInputEvent.Down)
|
||||||
|
{
|
||||||
|
if (underCursor != null)
|
||||||
|
{
|
||||||
|
// Test case / demonstration of how to edit an existing actor
|
||||||
|
var facing = underCursor.Init<FacingInit>();
|
||||||
|
if (facing != null)
|
||||||
|
underCursor.ReplaceInit(new FacingInit((facing.Value(world) + 32) % 256));
|
||||||
|
else if (underCursor.Info.Traits.WithInterface<UsesInit<FacingInit>>().Any())
|
||||||
|
underCursor.ReplaceInit(new FacingInit(32));
|
||||||
|
|
||||||
|
var turret = underCursor.Init<TurretFacingInit>();
|
||||||
|
if (turret != null)
|
||||||
|
underCursor.ReplaceInit(new TurretFacingInit((turret.Value(world) + 32) % 256));
|
||||||
|
else if (underCursor.Info.Traits.WithInterface<UsesInit<TurretFacingInit>>().Any())
|
||||||
|
underCursor.ReplaceInit(new TurretFacingInit(32));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Tick() { }
|
||||||
|
}
|
||||||
|
}
|
||||||
115
OpenRA.Mods.Common/EditorBrushes/EditorResourceBrush.cs
Normal file
115
OpenRA.Mods.Common/EditorBrushes/EditorResourceBrush.cs
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007-2015 The OpenRA Developers (see AUTHORS)
|
||||||
|
* This file is part of OpenRA, which is free software. It is made
|
||||||
|
* available to you under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation. For more information,
|
||||||
|
* see COPYING.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Linq;
|
||||||
|
using OpenRA.FileFormats;
|
||||||
|
using OpenRA.Graphics;
|
||||||
|
using OpenRA.Mods.Common;
|
||||||
|
using OpenRA.Mods.Common.Graphics;
|
||||||
|
using OpenRA.Mods.Common.Traits;
|
||||||
|
using OpenRA.Orders;
|
||||||
|
using OpenRA.Primitives;
|
||||||
|
using OpenRA.Traits;
|
||||||
|
using OpenRA.Widgets;
|
||||||
|
|
||||||
|
namespace OpenRA.Mods.Common.Widgets
|
||||||
|
{
|
||||||
|
public class EditorResourceBrush : IEditorBrush
|
||||||
|
{
|
||||||
|
public readonly ResourceTypeInfo ResourceType;
|
||||||
|
|
||||||
|
readonly WorldRenderer worldRenderer;
|
||||||
|
readonly World world;
|
||||||
|
readonly EditorViewportControllerWidget editorWidget;
|
||||||
|
readonly SpriteWidget preview;
|
||||||
|
|
||||||
|
public EditorResourceBrush(EditorViewportControllerWidget editorWidget, ResourceTypeInfo resource, WorldRenderer wr)
|
||||||
|
{
|
||||||
|
this.editorWidget = editorWidget;
|
||||||
|
ResourceType = resource;
|
||||||
|
worldRenderer = wr;
|
||||||
|
world = wr.World;
|
||||||
|
|
||||||
|
preview = editorWidget.Get<SpriteWidget>("DRAG_LAYER_PREVIEW");
|
||||||
|
preview.Palette = resource.Palette;
|
||||||
|
preview.GetScale = () => worldRenderer.Viewport.Zoom;
|
||||||
|
preview.IsVisible = () => editorWidget.CurrentBrush == this;
|
||||||
|
|
||||||
|
var variant = resource.Variants.FirstOrDefault();
|
||||||
|
var sequenceProvider = wr.World.Map.Rules.Sequences[world.TileSet.Id];
|
||||||
|
var sequence = sequenceProvider.GetSequence("resources", variant);
|
||||||
|
var sprite = sequence.GetSprite(resource.MaxDensity - 1);
|
||||||
|
preview.GetSprite = () => sprite;
|
||||||
|
|
||||||
|
// The preview widget may be rendered by the higher-level code before it is ticked.
|
||||||
|
// Force a manual tick to ensure the bounds are set correctly for this first draw.
|
||||||
|
Tick();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool HandleMouseInput(MouseInput mi)
|
||||||
|
{
|
||||||
|
// Exclusively uses left and right mouse buttons, but nothing else
|
||||||
|
if (mi.Button != MouseButton.Left && mi.Button != MouseButton.Right)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (mi.Button == MouseButton.Right)
|
||||||
|
{
|
||||||
|
editorWidget.ClearBrush();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var cell = worldRenderer.Viewport.ViewToWorld(mi.Location);
|
||||||
|
|
||||||
|
if (mi.Button == MouseButton.Left && AllowResourceAt(cell))
|
||||||
|
{
|
||||||
|
var type = (byte)ResourceType.ResourceType;
|
||||||
|
var index = (byte)ResourceType.MaxDensity;
|
||||||
|
world.Map.MapResources.Value[cell] = new ResourceTile(type, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AllowResourceAt(CPos cell)
|
||||||
|
{
|
||||||
|
if (!world.Map.Contains(cell))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var tile = world.Map.MapTiles.Value[cell];
|
||||||
|
var tileInfo = world.TileSet.GetTileInfo(tile);
|
||||||
|
var terrainType = world.TileSet.TerrainInfo[tileInfo.TerrainType];
|
||||||
|
|
||||||
|
if (world.Map.MapResources.Value[cell].Type == ResourceType.ResourceType)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!ResourceType.AllowedTerrainTypes.Contains(terrainType.Type))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return ResourceType.AllowOnRamps || tileInfo == null || tileInfo.RampType == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Tick()
|
||||||
|
{
|
||||||
|
var cell = worldRenderer.Viewport.ViewToWorld(Viewport.LastMousePos);
|
||||||
|
var offset = WVec.Zero;
|
||||||
|
var location = world.Map.CenterOfCell(cell) + offset;
|
||||||
|
|
||||||
|
var cellScreenPosition = worldRenderer.ScreenPxPosition(location);
|
||||||
|
var cellScreenPixel = worldRenderer.Viewport.WorldToViewPx(cellScreenPosition);
|
||||||
|
var zoom = worldRenderer.Viewport.Zoom;
|
||||||
|
|
||||||
|
preview.Bounds.X = cellScreenPixel.X;
|
||||||
|
preview.Bounds.Y = cellScreenPixel.Y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
151
OpenRA.Mods.Common/EditorBrushes/EditorTileBrush.cs
Normal file
151
OpenRA.Mods.Common/EditorBrushes/EditorTileBrush.cs
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007-2015 The OpenRA Developers (see AUTHORS)
|
||||||
|
* This file is part of OpenRA, which is free software. It is made
|
||||||
|
* available to you under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation. For more information,
|
||||||
|
* see COPYING.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Linq;
|
||||||
|
using OpenRA.FileFormats;
|
||||||
|
using OpenRA.Graphics;
|
||||||
|
using OpenRA.Mods.Common;
|
||||||
|
using OpenRA.Mods.Common.Graphics;
|
||||||
|
using OpenRA.Mods.Common.Traits;
|
||||||
|
using OpenRA.Orders;
|
||||||
|
using OpenRA.Primitives;
|
||||||
|
using OpenRA.Traits;
|
||||||
|
using OpenRA.Widgets;
|
||||||
|
|
||||||
|
namespace OpenRA.Mods.Common.Widgets
|
||||||
|
{
|
||||||
|
public class EditorTileBrush : IEditorBrush
|
||||||
|
{
|
||||||
|
public readonly ushort Template;
|
||||||
|
|
||||||
|
readonly WorldRenderer worldRenderer;
|
||||||
|
readonly World world;
|
||||||
|
readonly EditorViewportControllerWidget editorWidget;
|
||||||
|
readonly TerrainTemplatePreviewWidget preview;
|
||||||
|
readonly Rectangle bounds;
|
||||||
|
|
||||||
|
bool painting;
|
||||||
|
|
||||||
|
public EditorTileBrush(EditorViewportControllerWidget editorWidget, ushort template, WorldRenderer wr)
|
||||||
|
{
|
||||||
|
this.editorWidget = editorWidget;
|
||||||
|
Template = template;
|
||||||
|
worldRenderer = wr;
|
||||||
|
world = wr.World;
|
||||||
|
|
||||||
|
preview = editorWidget.Get<TerrainTemplatePreviewWidget>("DRAG_TILE_PREVIEW");
|
||||||
|
preview.GetScale = () => worldRenderer.Viewport.Zoom;
|
||||||
|
preview.IsVisible = () => editorWidget.CurrentBrush == this;
|
||||||
|
|
||||||
|
preview.Template = world.TileSet.Templates.First(t => t.Value.Id == template).Value;
|
||||||
|
bounds = worldRenderer.Theater.TemplateBounds(preview.Template, Game.ModData.Manifest.TileSize, world.Map.TileShape);
|
||||||
|
|
||||||
|
// The preview widget may be rendered by the higher-level code before it is ticked.
|
||||||
|
// Force a manual tick to ensure the bounds are set correctly for this first draw.
|
||||||
|
Tick();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool HandleMouseInput(MouseInput mi)
|
||||||
|
{
|
||||||
|
// Exclusively uses left and right mouse buttons, but nothing else
|
||||||
|
if (mi.Button != MouseButton.Left && mi.Button != MouseButton.Right)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (mi.Button == MouseButton.Right)
|
||||||
|
{
|
||||||
|
editorWidget.ClearBrush();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mi.Button == MouseButton.Left)
|
||||||
|
{
|
||||||
|
if (mi.Event == MouseInputEvent.Down)
|
||||||
|
painting = true;
|
||||||
|
else if (mi.Event == MouseInputEvent.Up)
|
||||||
|
painting = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!painting)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
var map = world.Map;
|
||||||
|
var cell = worldRenderer.Viewport.ViewToWorld(mi.Location);
|
||||||
|
|
||||||
|
if (mi.Event != MouseInputEvent.Down && mi.Event != MouseInputEvent.Move)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
var rules = map.Rules;
|
||||||
|
var tileset = rules.TileSets[map.Tileset];
|
||||||
|
var template = tileset.Templates[Template];
|
||||||
|
var baseHeight = map.Contains(cell) ? map.MapHeight.Value[cell] : 0;
|
||||||
|
if (mi.Event == MouseInputEvent.Move && PlacementOverlapsSameTemplate(template, cell))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
var i = 0;
|
||||||
|
for (var y = 0; y < template.Size.Y; y++)
|
||||||
|
{
|
||||||
|
for (var x = 0; x < template.Size.X; x++, i++)
|
||||||
|
{
|
||||||
|
if (template.Contains(i) && template[i] != null)
|
||||||
|
{
|
||||||
|
var index = template.PickAny ? (byte)Game.CosmeticRandom.Next(0, template.TilesCount) : (byte)i;
|
||||||
|
var c = cell + new CVec(x, y);
|
||||||
|
if (!map.Contains(c))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
map.MapTiles.Value[c] = new TerrainTile(Template, index);
|
||||||
|
map.MapHeight.Value[c] = (byte)(baseHeight + template[index].Height).Clamp(0, world.TileSet.MaxGroundHeight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PlacementOverlapsSameTemplate(TerrainTemplateInfo template, CPos cell)
|
||||||
|
{
|
||||||
|
var map = world.Map;
|
||||||
|
var i = 0;
|
||||||
|
for (var y = 0; y < template.Size.Y; y++)
|
||||||
|
{
|
||||||
|
for (var x = 0; x < template.Size.X; x++, i++)
|
||||||
|
{
|
||||||
|
if (template.Contains(i) && template[i] != null)
|
||||||
|
{
|
||||||
|
var c = cell + new CVec(x, y);
|
||||||
|
if (map.Contains(c) && map.MapTiles.Value[c].Type == template.Id)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Tick()
|
||||||
|
{
|
||||||
|
var cell = worldRenderer.Viewport.ViewToWorld(Viewport.LastMousePos);
|
||||||
|
var offset = WVec.Zero;
|
||||||
|
var location = world.Map.CenterOfCell(cell) + offset;
|
||||||
|
|
||||||
|
var cellScreenPosition = worldRenderer.ScreenPxPosition(location);
|
||||||
|
var cellScreenPixel = worldRenderer.Viewport.WorldToViewPx(cellScreenPosition);
|
||||||
|
var zoom = worldRenderer.Viewport.Zoom;
|
||||||
|
|
||||||
|
preview.Bounds.X = cellScreenPixel.X + (int)(zoom * bounds.X);
|
||||||
|
preview.Bounds.Y = cellScreenPixel.Y + (int)(zoom * bounds.Y);
|
||||||
|
preview.Bounds.Width = (int)(zoom * bounds.Width);
|
||||||
|
preview.Bounds.Height = (int)(zoom * bounds.Height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -539,6 +539,7 @@
|
|||||||
<Compile Include="Widgets\Logic\Ingame\IngameRadarDisplayLogic.cs" />
|
<Compile Include="Widgets\Logic\Ingame\IngameRadarDisplayLogic.cs" />
|
||||||
<Compile Include="Widgets\Logic\Ingame\LeaveMapLogic.cs" />
|
<Compile Include="Widgets\Logic\Ingame\LeaveMapLogic.cs" />
|
||||||
<Compile Include="Widgets\Logic\Ingame\LoadIngamePlayerOrObserverUILogic.cs" />
|
<Compile Include="Widgets\Logic\Ingame\LoadIngamePlayerOrObserverUILogic.cs" />
|
||||||
|
<Compile Include="Widgets\Logic\Ingame\LoadMapEditorLogic.cs" />
|
||||||
<Compile Include="Widgets\Logic\Ingame\ObserverShroudSelectorLogic.cs" />
|
<Compile Include="Widgets\Logic\Ingame\ObserverShroudSelectorLogic.cs" />
|
||||||
<Compile Include="Widgets\Logic\Ingame\ObserverStatsLogic.cs" />
|
<Compile Include="Widgets\Logic\Ingame\ObserverStatsLogic.cs" />
|
||||||
<Compile Include="Widgets\Logic\Ingame\OrderButtonsChromeLogic.cs" />
|
<Compile Include="Widgets\Logic\Ingame\OrderButtonsChromeLogic.cs" />
|
||||||
@@ -559,6 +560,13 @@
|
|||||||
<Compile Include="Widgets\Logic\Lobby\LobbyUtils.cs" />
|
<Compile Include="Widgets\Logic\Lobby\LobbyUtils.cs" />
|
||||||
<Compile Include="Widgets\Logic\Lobby\SpawnSelectorTooltipLogic.cs" />
|
<Compile Include="Widgets\Logic\Lobby\SpawnSelectorTooltipLogic.cs" />
|
||||||
<Compile Include="Widgets\Logic\MainMenuLogic.cs" />
|
<Compile Include="Widgets\Logic\MainMenuLogic.cs" />
|
||||||
|
<Compile Include="Widgets\Logic\Editor\ActorSelectorLogic.cs" />
|
||||||
|
<Compile Include="Widgets\Logic\Editor\LayerSelectorLogic.cs" />
|
||||||
|
<Compile Include="Widgets\Logic\Editor\MapEditorLogic.cs" />
|
||||||
|
<Compile Include="Widgets\Logic\Editor\MapEditorTabsLogic.cs" />
|
||||||
|
<Compile Include="Widgets\Logic\Editor\NewMapLogic.cs" />
|
||||||
|
<Compile Include="Widgets\Logic\Editor\SaveMapLogic.cs" />
|
||||||
|
<Compile Include="Widgets\Logic\Editor\TileSelectorLogic.cs" />
|
||||||
<Compile Include="Widgets\Logic\MapChooserLogic.cs" />
|
<Compile Include="Widgets\Logic\MapChooserLogic.cs" />
|
||||||
<Compile Include="Widgets\Logic\MissionBrowserLogic.cs" />
|
<Compile Include="Widgets\Logic\MissionBrowserLogic.cs" />
|
||||||
<Compile Include="Widgets\Logic\ModBrowserLogic.cs" />
|
<Compile Include="Widgets\Logic\ModBrowserLogic.cs" />
|
||||||
@@ -627,6 +635,14 @@
|
|||||||
<Compile Include="Traits\Plug.cs" />
|
<Compile Include="Traits\Plug.cs" />
|
||||||
<Compile Include="Widgets\Logic\Ingame\MenuButtonsChromeLogic.cs" />
|
<Compile Include="Widgets\Logic\Ingame\MenuButtonsChromeLogic.cs" />
|
||||||
<Compile Include="Widgets\Logic\Ingame\LoadIngamePerfLogic.cs" />
|
<Compile Include="Widgets\Logic\Ingame\LoadIngamePerfLogic.cs" />
|
||||||
|
<Compile Include="Traits\World\EditorActorLayer.cs" />
|
||||||
|
<Compile Include="EditorBrushes\EditorActorBrush.cs" />
|
||||||
|
<Compile Include="EditorBrushes\EditorTileBrush.cs" />
|
||||||
|
<Compile Include="EditorBrushes\EditorResourceBrush.cs" />
|
||||||
|
<Compile Include="EditorBrushes\EditorDefaultBrush.cs" />
|
||||||
|
<Compile Include="Traits\World\EditorActorPreview.cs" />
|
||||||
|
<Compile Include="Traits\World\EditorResourceLayer.cs" />
|
||||||
|
<Compile Include="Widgets\EditorViewportControllerWidget.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
@@ -641,4 +657,7 @@ cd "$(SolutionDir)"</PostBuildEvent>
|
|||||||
<Target Name="AfterBuild">
|
<Target Name="AfterBuild">
|
||||||
</Target>
|
</Target>
|
||||||
-->
|
-->
|
||||||
|
<ItemGroup>
|
||||||
|
<Folder Include="EditorBrushes\" />
|
||||||
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
@@ -43,6 +43,9 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
public virtual object Create(ActorInitializer init) { return new Aircraft(init, this); }
|
public virtual object Create(ActorInitializer init) { return new Aircraft(init, this); }
|
||||||
public int GetInitialFacing() { return InitialFacing; }
|
public int GetInitialFacing() { return InitialFacing; }
|
||||||
public WRange GetCruiseAltitude() { return CruiseAltitude; }
|
public WRange GetCruiseAltitude() { return CruiseAltitude; }
|
||||||
|
|
||||||
|
public IReadOnlyDictionary<CPos, SubCell> OccupiedCells(ActorInfo info, CPos location, SubCell subCell = SubCell.Any) { return new ReadOnlyDictionary<CPos, SubCell>(); }
|
||||||
|
bool IOccupySpaceInfo.SharesCell { get { return false; } }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Aircraft : IFacing, IPositionable, ISync, INotifyKilled, IIssueOrder, IOrderVoice, INotifyAddedToWorld, INotifyRemovedFromWorld
|
public class Aircraft : IFacing, IPositionable, ISync, INotifyKilled, IIssueOrder, IOrderVoice, INotifyAddedToWorld, INotifyRemovedFromWorld
|
||||||
|
|||||||
@@ -104,6 +104,16 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
.Any(b => Math.Abs(a.X - b.X) <= Adjacent
|
.Any(b => Math.Abs(a.X - b.X) <= Adjacent
|
||||||
&& Math.Abs(a.Y - b.Y) <= Adjacent));
|
&& Math.Abs(a.Y - b.Y) <= Adjacent));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IReadOnlyDictionary<CPos, SubCell> OccupiedCells(ActorInfo info, CPos topLeft, SubCell subCell = SubCell.Any)
|
||||||
|
{
|
||||||
|
var occupied = FootprintUtils.UnpathableTiles(info.Name, this, topLeft)
|
||||||
|
.ToDictionary(c => c, c => SubCell.FullCell);
|
||||||
|
|
||||||
|
return new ReadOnlyDictionary<CPos, SubCell>(occupied);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IOccupySpaceInfo.SharesCell { get { return false; } }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Building : IOccupySpace, INotifySold, INotifyTransform, ISync, INotifyCreated, INotifyAddedToWorld, INotifyRemovedFromWorld
|
public class Building : IOccupySpace, INotifySold, INotifyTransform, ISync, INotifyCreated, INotifyAddedToWorld, INotifyRemovedFromWorld
|
||||||
|
|||||||
@@ -28,6 +28,14 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
public readonly string CrushClass = "crate";
|
public readonly string CrushClass = "crate";
|
||||||
|
|
||||||
public object Create(ActorInitializer init) { return new Crate(init, this); }
|
public object Create(ActorInitializer init) { return new Crate(init, this); }
|
||||||
|
|
||||||
|
public IReadOnlyDictionary<CPos, SubCell> OccupiedCells(ActorInfo info, CPos location, SubCell subCell = SubCell.Any)
|
||||||
|
{
|
||||||
|
var occupied = new Dictionary<CPos, SubCell>() { { location, SubCell.FullCell } };
|
||||||
|
return new ReadOnlyDictionary<CPos, SubCell>(occupied);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IOccupySpaceInfo.SharesCell { get { return false; } }
|
||||||
}
|
}
|
||||||
|
|
||||||
class Crate : ITick, IPositionable, ICrushable, ISync, INotifyParachuteLanded, INotifyAddedToWorld, INotifyRemovedFromWorld
|
class Crate : ITick, IPositionable, ICrushable, ISync, INotifyParachuteLanded, INotifyAddedToWorld, INotifyRemovedFromWorld
|
||||||
|
|||||||
@@ -24,6 +24,14 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
public object Create(ActorInitializer init) { return new Husk(init, this); }
|
public object Create(ActorInitializer init) { return new Husk(init, this); }
|
||||||
|
|
||||||
public int GetInitialFacing() { return 128; }
|
public int GetInitialFacing() { return 128; }
|
||||||
|
|
||||||
|
public IReadOnlyDictionary<CPos, SubCell> OccupiedCells(ActorInfo info, CPos location, SubCell subCell = SubCell.Any)
|
||||||
|
{
|
||||||
|
var occupied = new Dictionary<CPos, SubCell>() { { location, SubCell.FullCell } };
|
||||||
|
return new ReadOnlyDictionary<CPos, SubCell>(occupied);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IOccupySpaceInfo.SharesCell { get { return false; } }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Husk : IPositionable, IFacing, ISync, INotifyCreated, INotifyAddedToWorld, INotifyRemovedFromWorld, IDisable
|
public class Husk : IPositionable, IFacing, ISync, INotifyCreated, INotifyAddedToWorld, INotifyRemovedFromWorld, IDisable
|
||||||
|
|||||||
@@ -18,6 +18,16 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
{
|
{
|
||||||
public readonly bool OccupiesSpace = true;
|
public readonly bool OccupiesSpace = true;
|
||||||
public object Create(ActorInitializer init) { return new Immobile(init, this); }
|
public object Create(ActorInitializer init) { return new Immobile(init, this); }
|
||||||
|
|
||||||
|
public IReadOnlyDictionary<CPos, SubCell> OccupiedCells(ActorInfo info, CPos location, SubCell subCell = SubCell.Any)
|
||||||
|
{
|
||||||
|
var occupied = OccupiesSpace ? new Dictionary<CPos, SubCell>() { { location, SubCell.FullCell } } :
|
||||||
|
new Dictionary<CPos, SubCell>();
|
||||||
|
|
||||||
|
return new ReadOnlyDictionary<CPos, SubCell>(occupied);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IOccupySpaceInfo.SharesCell { get { return false; } }
|
||||||
}
|
}
|
||||||
|
|
||||||
class Immobile : IOccupySpace, ISync, INotifyAddedToWorld, INotifyRemovedFromWorld
|
class Immobile : IOccupySpace, ISync, INotifyAddedToWorld, INotifyRemovedFromWorld
|
||||||
|
|||||||
@@ -295,6 +295,13 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
}
|
}
|
||||||
|
|
||||||
public int GetInitialFacing() { return InitialFacing; }
|
public int GetInitialFacing() { return InitialFacing; }
|
||||||
|
|
||||||
|
public IReadOnlyDictionary<CPos, SubCell> OccupiedCells(ActorInfo info, CPos location, SubCell subCell = SubCell.Any)
|
||||||
|
{
|
||||||
|
return new ReadOnlyDictionary<CPos, SubCell>(new Dictionary<CPos, SubCell>() { { location, subCell } });
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IOccupySpaceInfo.SharesCell { get { return SharesCell; } }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Mobile : IIssueOrder, IResolveOrder, IOrderVoice, IPositionable, IMove, IFacing, ISync, INotifyAddedToWorld, INotifyRemovedFromWorld, INotifyBlockingMove
|
public class Mobile : IIssueOrder, IResolveOrder, IOrderVoice, IPositionable, IMove, IFacing, ISync, INotifyAddedToWorld, INotifyRemovedFromWorld, INotifyBlockingMove
|
||||||
|
|||||||
@@ -64,9 +64,15 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
var facings = 0;
|
var facings = 0;
|
||||||
var body = init.Actor.Traits.GetOrDefault<BodyOrientationInfo>();
|
var body = init.Actor.Traits.GetOrDefault<BodyOrientationInfo>();
|
||||||
if (body != null)
|
if (body != null)
|
||||||
facings = body.QuantizedFacings == -1 ?
|
{
|
||||||
init.Actor.Traits.Get<IQuantizeBodyOrientationInfo>().QuantizedBodyFacings(init.Actor, sequenceProvider, race) :
|
facings = body.QuantizedFacings;
|
||||||
body.QuantizedFacings;
|
|
||||||
|
if (facings == -1)
|
||||||
|
{
|
||||||
|
var qbo = init.Actor.Traits.GetOrDefault<IQuantizeBodyOrientationInfo>();
|
||||||
|
facings = qbo != null ? qbo.QuantizedBodyFacings(init.Actor, sequenceProvider, race) : 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
foreach (var spi in init.Actor.Traits.WithInterface<IRenderActorPreviewSpritesInfo>())
|
foreach (var spi in init.Actor.Traits.WithInterface<IRenderActorPreviewSpritesInfo>())
|
||||||
foreach (var preview in spi.RenderPreviewSprites(init, this, image, facings, palette))
|
foreach (var preview in spi.RenderPreviewSprites(init, this, image, facings, palette))
|
||||||
|
|||||||
268
OpenRA.Mods.Common/Traits/World/EditorActorLayer.cs
Normal file
268
OpenRA.Mods.Common/Traits/World/EditorActorLayer.cs
Normal file
@@ -0,0 +1,268 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007-2015 The OpenRA Developers (see AUTHORS)
|
||||||
|
* This file is part of OpenRA, which is free software. It is made
|
||||||
|
* available to you under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation. For more information,
|
||||||
|
* see COPYING.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using OpenRA.Graphics;
|
||||||
|
using OpenRA.Mods.Common.Graphics;
|
||||||
|
using OpenRA.Primitives;
|
||||||
|
using OpenRA.Traits;
|
||||||
|
|
||||||
|
namespace OpenRA.Mods.Common.Traits
|
||||||
|
{
|
||||||
|
[Desc("Required for the map editor to work. Attach this to the world actor.")]
|
||||||
|
public class EditorActorLayerInfo : ITraitInfo
|
||||||
|
{
|
||||||
|
[Desc("Size of partition bins (world pixels)")]
|
||||||
|
public readonly int BinSize = 250;
|
||||||
|
|
||||||
|
public object Create(ActorInitializer init) { return new EditorActorLayer(init.Self, this); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class EditorActorLayer : IWorldLoaded, ITickRender, IRender, IRadarSignature, ICreatePlayers
|
||||||
|
{
|
||||||
|
readonly EditorActorLayerInfo info;
|
||||||
|
readonly Dictionary<string, EditorActorPreview> previews = new Dictionary<string, EditorActorPreview>();
|
||||||
|
readonly Dictionary<CPos, List<EditorActorPreview>> cellMap = new Dictionary<CPos, List<EditorActorPreview>>();
|
||||||
|
|
||||||
|
SpatiallyPartitioned<EditorActorPreview> screenMap;
|
||||||
|
WorldRenderer worldRenderer;
|
||||||
|
|
||||||
|
public MapPlayers Players { get; private set; }
|
||||||
|
|
||||||
|
public EditorActorLayer(Actor self, EditorActorLayerInfo info)
|
||||||
|
{
|
||||||
|
this.info = info;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CreatePlayers(World w)
|
||||||
|
{
|
||||||
|
if (w.Type != WorldType.Editor)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Players = new MapPlayers(w.Map.PlayerDefinitions);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WorldLoaded(World world, WorldRenderer wr)
|
||||||
|
{
|
||||||
|
if (world.Type != WorldType.Editor)
|
||||||
|
return;
|
||||||
|
|
||||||
|
worldRenderer = wr;
|
||||||
|
|
||||||
|
foreach (var pr in Players.Players.Values)
|
||||||
|
wr.UpdatePalettesForPlayer(pr.Name, pr.Color, false);
|
||||||
|
|
||||||
|
var ts = Game.ModData.Manifest.TileSize;
|
||||||
|
var width = world.Map.MapSize.X * ts.Width;
|
||||||
|
var height = world.Map.MapSize.Y * ts.Height;
|
||||||
|
screenMap = new SpatiallyPartitioned<EditorActorPreview>(width, height, info.BinSize);
|
||||||
|
|
||||||
|
foreach (var kv in world.Map.ActorDefinitions)
|
||||||
|
Add(kv.Key, new ActorReference(kv.Value.Value, kv.Value.ToDictionary()), true);
|
||||||
|
|
||||||
|
// Update neighbours in one pass
|
||||||
|
foreach (var p in previews.Values)
|
||||||
|
UpdateNeighbours(p.Footprint);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void TickRender(WorldRenderer wr, Actor self)
|
||||||
|
{
|
||||||
|
if (wr.World.Type != WorldType.Editor)
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (var kv in previews.Values)
|
||||||
|
kv.Tick();
|
||||||
|
}
|
||||||
|
|
||||||
|
static readonly IEnumerable<IRenderable> NoRenderables = Enumerable.Empty<IRenderable>();
|
||||||
|
public virtual IEnumerable<IRenderable> Render(Actor self, WorldRenderer wr)
|
||||||
|
{
|
||||||
|
if (wr.World.Type != WorldType.Editor)
|
||||||
|
return NoRenderables;
|
||||||
|
|
||||||
|
return PreviewsInBox(wr.Viewport.TopLeft, wr.Viewport.BottomRight)
|
||||||
|
.SelectMany(p => p.Render());
|
||||||
|
}
|
||||||
|
|
||||||
|
public EditorActorPreview Add(ActorReference reference) { return Add(NextActorName(), reference); }
|
||||||
|
|
||||||
|
EditorActorPreview Add(string id, ActorReference reference, bool initialSetup = false)
|
||||||
|
{
|
||||||
|
var owner = Players.Players[reference.InitDict.Get<OwnerInit>().PlayerName];
|
||||||
|
|
||||||
|
var preview = new EditorActorPreview(worldRenderer, id, reference, owner);
|
||||||
|
previews.Add(id, preview);
|
||||||
|
screenMap.Add(preview, preview.Bounds);
|
||||||
|
|
||||||
|
foreach (var kv in preview.Footprint)
|
||||||
|
{
|
||||||
|
List<EditorActorPreview> list;
|
||||||
|
if (!cellMap.TryGetValue(kv.Key, out list))
|
||||||
|
{
|
||||||
|
list = new List<EditorActorPreview>();
|
||||||
|
cellMap.Add(kv.Key, list);
|
||||||
|
}
|
||||||
|
|
||||||
|
list.Add(preview);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!initialSetup)
|
||||||
|
{
|
||||||
|
UpdateNeighbours(preview.Footprint);
|
||||||
|
|
||||||
|
if (reference.Type == "mpspawn")
|
||||||
|
SyncMultiplayerCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
return preview;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Remove(EditorActorPreview preview)
|
||||||
|
{
|
||||||
|
previews.Remove(preview.ID);
|
||||||
|
screenMap.Remove(preview);
|
||||||
|
|
||||||
|
foreach (var kv in preview.Footprint)
|
||||||
|
{
|
||||||
|
List<EditorActorPreview> list;
|
||||||
|
if (!cellMap.TryGetValue(kv.Key, out list))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
list.Remove(preview);
|
||||||
|
|
||||||
|
if (!list.Any())
|
||||||
|
cellMap.Remove(kv.Key);
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateNeighbours(preview.Footprint);
|
||||||
|
|
||||||
|
if (preview.Info.Name == "mpspawn")
|
||||||
|
SyncMultiplayerCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SyncMultiplayerCount()
|
||||||
|
{
|
||||||
|
var newCount = previews.Count(p => p.Value.Info.Name == "mpspawn");
|
||||||
|
var mp = Players.Players.Where(p => p.Key.StartsWith("Multi")).ToList();
|
||||||
|
foreach (var kv in mp)
|
||||||
|
{
|
||||||
|
var name = kv.Key;
|
||||||
|
var index = int.Parse(name.Substring(5));
|
||||||
|
|
||||||
|
if (index >= newCount)
|
||||||
|
{
|
||||||
|
Players.Players.Remove(name);
|
||||||
|
worldRenderer.World.Players.RemoveAll(pp => pp.InternalName == name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var index = 0; index < newCount; index++)
|
||||||
|
{
|
||||||
|
if (Players.Players.ContainsKey("Multi{0}".F(index)))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var pr = new PlayerReference
|
||||||
|
{
|
||||||
|
Name = "Multi{0}".F(index),
|
||||||
|
Race = "Random",
|
||||||
|
Playable = true,
|
||||||
|
Enemies = new[] { "Creeps" }
|
||||||
|
};
|
||||||
|
|
||||||
|
Players.Players.Add(pr.Name, pr);
|
||||||
|
worldRenderer.UpdatePalettesForPlayer(pr.Name, pr.Color, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateNeighbours(IReadOnlyDictionary<CPos, SubCell> footprint)
|
||||||
|
{
|
||||||
|
// Include actors inside the footprint too
|
||||||
|
var cells = OpenRA.Traits.Util.ExpandFootprint(footprint.Keys, true);
|
||||||
|
foreach (var p in cells.SelectMany(c => PreviewsAt(c)))
|
||||||
|
p.ReplaceInit(new RuntimeNeighbourInit(NeighbouringPreviews(p.Footprint)));
|
||||||
|
}
|
||||||
|
|
||||||
|
Dictionary<CPos, string[]> NeighbouringPreviews(IReadOnlyDictionary<CPos, SubCell> footprint)
|
||||||
|
{
|
||||||
|
var cells = OpenRA.Traits.Util.ExpandFootprint(footprint.Keys, true).Except(footprint.Keys);
|
||||||
|
return cells.ToDictionary(c => c, c => PreviewsAt(c).Select(p => p.Info.Name).ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<EditorActorPreview> PreviewsInBox(int2 a, int2 b)
|
||||||
|
{
|
||||||
|
return screenMap.InBox(Rectangle.FromLTRB(Math.Min(a.X, b.X), Math.Min(a.Y, b.Y), Math.Max(a.X, b.X), Math.Max(a.Y, b.Y)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<EditorActorPreview> PreviewsInBox(Rectangle r)
|
||||||
|
{
|
||||||
|
return screenMap.InBox(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<EditorActorPreview> PreviewsAt(CPos cell)
|
||||||
|
{
|
||||||
|
List<EditorActorPreview> list;
|
||||||
|
if (cellMap.TryGetValue(cell, out list))
|
||||||
|
return list;
|
||||||
|
|
||||||
|
return Enumerable.Empty<EditorActorPreview>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public SubCell FreeSubCellAt(CPos cell)
|
||||||
|
{
|
||||||
|
var map = worldRenderer.World.Map;
|
||||||
|
var previews = PreviewsAt(cell).ToList();
|
||||||
|
if (!previews.Any())
|
||||||
|
return map.DefaultSubCell;
|
||||||
|
|
||||||
|
for (var i = (int)SubCell.First; i < map.SubCellOffsets.Length; i++)
|
||||||
|
if (!previews.Any(p => p.Footprint[cell] == (SubCell)i))
|
||||||
|
return (SubCell)i;
|
||||||
|
|
||||||
|
return SubCell.Invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<EditorActorPreview> PreviewsAt(int2 worldPx)
|
||||||
|
{
|
||||||
|
return screenMap.At(worldPx);
|
||||||
|
}
|
||||||
|
|
||||||
|
string NextActorName()
|
||||||
|
{
|
||||||
|
var id = previews.Count();
|
||||||
|
var possibleName = "Actor" + id.ToString();
|
||||||
|
|
||||||
|
while (previews.ContainsKey(possibleName))
|
||||||
|
{
|
||||||
|
id++;
|
||||||
|
possibleName = "Actor" + id.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
return possibleName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<MiniYamlNode> Save()
|
||||||
|
{
|
||||||
|
var nodes = new List<MiniYamlNode>();
|
||||||
|
foreach (var a in previews)
|
||||||
|
nodes.Add(new MiniYamlNode(a.Key, a.Value.Save()));
|
||||||
|
|
||||||
|
return nodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<Pair<CPos, Color>> RadarSignatureCells(Actor self)
|
||||||
|
{
|
||||||
|
return cellMap.SelectMany(c => c.Value.Select(p => Pair.New(c.Key, p.Owner.Color.RGB)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
164
OpenRA.Mods.Common/Traits/World/EditorActorPreview.cs
Normal file
164
OpenRA.Mods.Common/Traits/World/EditorActorPreview.cs
Normal file
@@ -0,0 +1,164 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007-2015 The OpenRA Developers (see AUTHORS)
|
||||||
|
* This file is part of OpenRA, which is free software. It is made
|
||||||
|
* available to you under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation. For more information,
|
||||||
|
* see COPYING.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using OpenRA.Graphics;
|
||||||
|
using OpenRA.Mods.Common.Graphics;
|
||||||
|
using OpenRA.Primitives;
|
||||||
|
using OpenRA.Traits;
|
||||||
|
|
||||||
|
namespace OpenRA.Mods.Common.Traits
|
||||||
|
{
|
||||||
|
public class EditorActorPreview
|
||||||
|
{
|
||||||
|
public readonly string Tooltip;
|
||||||
|
public readonly string ID;
|
||||||
|
public readonly ActorInfo Info;
|
||||||
|
public readonly PlayerReference Owner;
|
||||||
|
public readonly WPos CenterPosition;
|
||||||
|
public readonly IReadOnlyDictionary<CPos, SubCell> Footprint;
|
||||||
|
public readonly Rectangle Bounds;
|
||||||
|
|
||||||
|
public SubCell SubCell { get; private set; }
|
||||||
|
|
||||||
|
readonly ActorReference actor;
|
||||||
|
readonly WorldRenderer worldRenderer;
|
||||||
|
IActorPreview[] previews;
|
||||||
|
|
||||||
|
public EditorActorPreview(WorldRenderer worldRenderer, string id, ActorReference actor, PlayerReference owner)
|
||||||
|
{
|
||||||
|
ID = id;
|
||||||
|
this.actor = actor;
|
||||||
|
this.Owner = owner;
|
||||||
|
this.worldRenderer = worldRenderer;
|
||||||
|
|
||||||
|
if (!actor.InitDict.Contains<RaceInit>())
|
||||||
|
actor.InitDict.Add(new RaceInit(owner.Race));
|
||||||
|
|
||||||
|
if (!actor.InitDict.Contains<OwnerInit>())
|
||||||
|
actor.InitDict.Add(new OwnerInit(owner.Name));
|
||||||
|
|
||||||
|
var world = worldRenderer.World;
|
||||||
|
if (!world.Map.Rules.Actors.TryGetValue(actor.Type.ToLowerInvariant(), out Info))
|
||||||
|
throw new InvalidDataException("Actor {0} of unknown type {1}".F(id, actor.Type.ToLowerInvariant()));
|
||||||
|
|
||||||
|
CenterPosition = PreviewPosition(world, actor.InitDict);
|
||||||
|
|
||||||
|
var location = actor.InitDict.Get<LocationInit>().Value(worldRenderer.World);
|
||||||
|
var ios = Info.Traits.GetOrDefault<IOccupySpaceInfo>();
|
||||||
|
|
||||||
|
var subCellInit = actor.InitDict.GetOrDefault<SubCellInit>();
|
||||||
|
var subCell = subCellInit != null ? subCellInit.Value(worldRenderer.World) : SubCell.Any;
|
||||||
|
|
||||||
|
if (ios != null)
|
||||||
|
Footprint = ios.OccupiedCells(Info, location, subCell);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var footprint = new Dictionary<CPos, SubCell>() { { location, SubCell.FullCell } };
|
||||||
|
Footprint = new ReadOnlyDictionary<CPos, SubCell>(footprint);
|
||||||
|
}
|
||||||
|
|
||||||
|
var tooltipInfo = Info.Traits.GetOrDefault<ITooltipInfo>();
|
||||||
|
Tooltip = "{0} ({1})".F(tooltipInfo != null ? tooltipInfo.TooltipForPlayerStance(Stance.None) : Info.Name, ID);
|
||||||
|
|
||||||
|
GeneratePreviews();
|
||||||
|
|
||||||
|
// Bounds are fixed from the initial render.
|
||||||
|
// If this is a problem, then we may need to fetch the area from somewhere else
|
||||||
|
var r = previews
|
||||||
|
.SelectMany(p => p.Render(worldRenderer, CenterPosition))
|
||||||
|
.Select(rr => rr.PrepareRender(worldRenderer));
|
||||||
|
|
||||||
|
if (r.Any())
|
||||||
|
{
|
||||||
|
Bounds = r.First().ScreenBounds(worldRenderer);
|
||||||
|
foreach (var rr in r.Skip(1))
|
||||||
|
Bounds = Rectangle.Union(Bounds, rr.ScreenBounds(worldRenderer));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Tick()
|
||||||
|
{
|
||||||
|
foreach (var p in previews)
|
||||||
|
p.Tick();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<IRenderable> Render()
|
||||||
|
{
|
||||||
|
return previews.SelectMany(p => p.Render(worldRenderer, CenterPosition));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ReplaceInit<T>(T init)
|
||||||
|
{
|
||||||
|
var original = actor.InitDict.GetOrDefault<T>();
|
||||||
|
if (original != null)
|
||||||
|
actor.InitDict.Remove(original);
|
||||||
|
|
||||||
|
actor.InitDict.Add(init);
|
||||||
|
GeneratePreviews();
|
||||||
|
}
|
||||||
|
|
||||||
|
public T Init<T>()
|
||||||
|
{
|
||||||
|
return actor.InitDict.GetOrDefault<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public MiniYaml Save()
|
||||||
|
{
|
||||||
|
Func<object, bool> saveInit = init =>
|
||||||
|
{
|
||||||
|
var race = init as RaceInit;
|
||||||
|
if (race != null && race.Race == Owner.Race)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// TODO: Other default values will need to be filtered
|
||||||
|
// here after we have built a properties panel
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
return actor.Save(saveInit);
|
||||||
|
}
|
||||||
|
|
||||||
|
WPos PreviewPosition(World world, TypeDictionary init)
|
||||||
|
{
|
||||||
|
if (init.Contains<CenterPositionInit>())
|
||||||
|
return init.Get<CenterPositionInit>().Value(world);
|
||||||
|
|
||||||
|
if (init.Contains<LocationInit>())
|
||||||
|
{
|
||||||
|
var cell = init.Get<LocationInit>().Value(world);
|
||||||
|
var offset = WVec.Zero;
|
||||||
|
|
||||||
|
var subCellInit = actor.InitDict.GetOrDefault<SubCellInit>();
|
||||||
|
var subCell = subCellInit != null ? subCellInit.Value(worldRenderer.World) : SubCell.Any;
|
||||||
|
|
||||||
|
var buildingInfo = Info.Traits.GetOrDefault<BuildingInfo>();
|
||||||
|
if (buildingInfo != null)
|
||||||
|
offset = FootprintUtils.CenterOffset(world, buildingInfo);
|
||||||
|
|
||||||
|
return world.Map.CenterOfSubCell(cell, subCell) + offset;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw new InvalidDataException("Actor {0} must define Location or CenterPosition".F(ID));
|
||||||
|
}
|
||||||
|
|
||||||
|
void GeneratePreviews()
|
||||||
|
{
|
||||||
|
var init = new ActorPreviewInitializer(Info, worldRenderer, actor.InitDict);
|
||||||
|
previews = Info.Traits.WithInterface<IRenderActorPreviewInfo>()
|
||||||
|
.SelectMany(rpi => rpi.RenderPreview(init))
|
||||||
|
.ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
155
OpenRA.Mods.Common/Traits/World/EditorResourceLayer.cs
Normal file
155
OpenRA.Mods.Common/Traits/World/EditorResourceLayer.cs
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007-2015 The OpenRA Developers (see AUTHORS)
|
||||||
|
* This file is part of OpenRA, which is free software. It is made
|
||||||
|
* available to you under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation. For more information,
|
||||||
|
* see COPYING.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using OpenRA.Graphics;
|
||||||
|
using OpenRA.Mods.Common.Graphics;
|
||||||
|
using OpenRA.Primitives;
|
||||||
|
using OpenRA.Traits;
|
||||||
|
|
||||||
|
namespace OpenRA.Mods.Common.Traits
|
||||||
|
{
|
||||||
|
using CellContents = ResourceLayer.CellContents;
|
||||||
|
|
||||||
|
[Desc("Required for the map editor to work. Attach this to the world actor.")]
|
||||||
|
public class EditorResourceLayerInfo : ITraitInfo, Requires<ResourceTypeInfo>
|
||||||
|
{
|
||||||
|
public virtual object Create(ActorInitializer init) { return new EditorResourceLayer(init.Self); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class EditorResourceLayer : IWorldLoaded, IRenderOverlay
|
||||||
|
{
|
||||||
|
protected readonly Map Map;
|
||||||
|
protected readonly TileSet Tileset;
|
||||||
|
protected readonly Dictionary<int, ResourceType> Resources;
|
||||||
|
protected readonly CellLayer<CellContents> Tiles;
|
||||||
|
protected readonly HashSet<CPos> Dirty = new HashSet<CPos>();
|
||||||
|
|
||||||
|
public EditorResourceLayer(Actor self)
|
||||||
|
{
|
||||||
|
if (self.World.Type != WorldType.Editor)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Map = self.World.Map;
|
||||||
|
Tileset = self.World.TileSet;
|
||||||
|
|
||||||
|
Tiles = new CellLayer<CellContents>(Map);
|
||||||
|
Resources = self.TraitsImplementing<ResourceType>()
|
||||||
|
.ToDictionary(r => r.Info.ResourceType, r => r);
|
||||||
|
|
||||||
|
Map.MapResources.Value.CellEntryChanged += UpdateCell;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WorldLoaded(World w, WorldRenderer wr)
|
||||||
|
{
|
||||||
|
if (w.Type != WorldType.Editor)
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (var cell in Map.Cells)
|
||||||
|
UpdateCell(cell);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateCell(CPos cell)
|
||||||
|
{
|
||||||
|
var uv = cell.ToMPos(Map);
|
||||||
|
var tile = Map.MapResources.Value[uv];
|
||||||
|
|
||||||
|
ResourceType type;
|
||||||
|
if (Resources.TryGetValue(tile.Type, out type))
|
||||||
|
{
|
||||||
|
Tiles[uv] = new CellContents
|
||||||
|
{
|
||||||
|
Type = type,
|
||||||
|
Variant = ChooseRandomVariant(type),
|
||||||
|
};
|
||||||
|
|
||||||
|
Map.CustomTerrain[uv] = Tileset.GetTerrainIndex(type.Info.TerrainType);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Tiles[uv] = CellContents.Empty;
|
||||||
|
Map.CustomTerrain[uv] = byte.MaxValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ingame resource rendering is a giant hack (#6395),
|
||||||
|
// so we must also touch all the neighbouring tiles
|
||||||
|
Dirty.Add(cell);
|
||||||
|
foreach (var d in CVec.Directions)
|
||||||
|
{
|
||||||
|
var c = cell + d;
|
||||||
|
if (Map.Contains(c))
|
||||||
|
Dirty.Add(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual string ChooseRandomVariant(ResourceType t)
|
||||||
|
{
|
||||||
|
return t.Variants.Keys.Random(Game.CosmeticRandom);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int ResourceDensityAt(CPos c)
|
||||||
|
{
|
||||||
|
// Set density based on the number of neighboring resources
|
||||||
|
var adjacent = 0;
|
||||||
|
var type = Tiles[c].Type;
|
||||||
|
for (var u = -1; u < 2; u++)
|
||||||
|
for (var v = -1; v < 2; v++)
|
||||||
|
if (Map.MapResources.Value[c + new CVec(u, v)].Type == type.Info.ResourceType)
|
||||||
|
adjacent++;
|
||||||
|
|
||||||
|
return Math.Max(int2.Lerp(0, type.Info.MaxDensity, adjacent, 9), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual CellContents UpdateDirtyTile(CPos c)
|
||||||
|
{
|
||||||
|
var t = Tiles[c];
|
||||||
|
var type = t.Type;
|
||||||
|
|
||||||
|
// Empty tile
|
||||||
|
if (type == null)
|
||||||
|
{
|
||||||
|
t.Sprite = null;
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set density based on the number of neighboring resources
|
||||||
|
t.Density = ResourceDensityAt(c);
|
||||||
|
|
||||||
|
var sprites = type.Variants[t.Variant];
|
||||||
|
var frame = int2.Lerp(0, sprites.Length - 1, t.Density - 1, type.Info.MaxDensity);
|
||||||
|
t.Sprite = sprites[frame];
|
||||||
|
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Render(WorldRenderer wr)
|
||||||
|
{
|
||||||
|
if (wr.World.Type != WorldType.Editor)
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (var c in Dirty)
|
||||||
|
Tiles[c] = UpdateDirtyTile(c);
|
||||||
|
|
||||||
|
Dirty.Clear();
|
||||||
|
|
||||||
|
foreach (var uv in wr.Viewport.VisibleCells.MapCoords)
|
||||||
|
{
|
||||||
|
var t = Tiles[uv];
|
||||||
|
if (t.Sprite != null)
|
||||||
|
new SpriteRenderable(t.Sprite, wr.World.Map.CenterOfCell(uv.ToCPos(Map)),
|
||||||
|
WVec.Zero, -511, t.Type.Palette, 1f, true).Render(wr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -23,6 +23,9 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
[Desc("The widget tree to open when a regular map is loaded (i.e. the ingame UI).")]
|
[Desc("The widget tree to open when a regular map is loaded (i.e. the ingame UI).")]
|
||||||
public readonly string IngameRoot = "INGAME_ROOT";
|
public readonly string IngameRoot = "INGAME_ROOT";
|
||||||
|
|
||||||
|
[Desc("The widget tree to open when the map editor is loaded.")]
|
||||||
|
public readonly string EditorRoot = "EDITOR_ROOT";
|
||||||
|
|
||||||
[Desc("Remove any existing UI when a map is loaded.")]
|
[Desc("Remove any existing UI when a map is loaded.")]
|
||||||
public readonly bool ClearRoot = true;
|
public readonly bool ClearRoot = true;
|
||||||
|
|
||||||
@@ -44,7 +47,9 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
if (info.ClearRoot)
|
if (info.ClearRoot)
|
||||||
Ui.ResetAll();
|
Ui.ResetAll();
|
||||||
|
|
||||||
var widget = world.Type == WorldType.Shellmap ? info.ShellmapRoot : info.IngameRoot;
|
var widget = world.Type == WorldType.Shellmap ? info.ShellmapRoot :
|
||||||
|
world.Type == WorldType.Editor ? info.EditorRoot : info.IngameRoot;
|
||||||
|
|
||||||
Game.LoadWidget(world, widget, Ui.Root, new WidgetArgs());
|
Game.LoadWidget(world, widget, Ui.Root, new WidgetArgs());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -248,6 +248,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
|
|
||||||
public struct CellContents
|
public struct CellContents
|
||||||
{
|
{
|
||||||
|
public static readonly CellContents Empty = new CellContents();
|
||||||
public ResourceType Type;
|
public ResourceType Type;
|
||||||
public int Density;
|
public int Density;
|
||||||
public string Variant;
|
public string Variant;
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
[Desc("Renders a debug overlay showing the terrain cells. Attach this to the world actor.")]
|
[Desc("Renders a debug overlay showing the terrain cells. Attach this to the world actor.")]
|
||||||
public class TerrainGeometryOverlayInfo : TraitInfo<TerrainGeometryOverlay> { }
|
public class TerrainGeometryOverlayInfo : TraitInfo<TerrainGeometryOverlay> { }
|
||||||
|
|
||||||
public class TerrainGeometryOverlay : IRenderOverlay, IWorldLoaded, IChatCommand
|
public class TerrainGeometryOverlay : IPostRender, IWorldLoaded, IChatCommand
|
||||||
{
|
{
|
||||||
const string CommandName = "terrainoverlay";
|
const string CommandName = "terrainoverlay";
|
||||||
const string CommandDesc = "Toggles the terrain geometry overlay";
|
const string CommandDesc = "Toggles the terrain geometry overlay";
|
||||||
@@ -46,7 +46,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
Enabled ^= true;
|
Enabled ^= true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Render(WorldRenderer wr)
|
public void RenderAfterWorld(WorldRenderer wr, Actor self)
|
||||||
{
|
{
|
||||||
if (!Enabled)
|
if (!Enabled)
|
||||||
return;
|
return;
|
||||||
|
|||||||
98
OpenRA.Mods.Common/Widgets/EditorViewportControllerWidget.cs
Normal file
98
OpenRA.Mods.Common/Widgets/EditorViewportControllerWidget.cs
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007-2015 The OpenRA Developers (see AUTHORS)
|
||||||
|
* This file is part of OpenRA, which is free software. It is made
|
||||||
|
* available to you under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation. For more information,
|
||||||
|
* see COPYING.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Linq;
|
||||||
|
using OpenRA.FileFormats;
|
||||||
|
using OpenRA.Graphics;
|
||||||
|
using OpenRA.Mods.Common;
|
||||||
|
using OpenRA.Mods.Common.Graphics;
|
||||||
|
using OpenRA.Mods.Common.Traits;
|
||||||
|
using OpenRA.Orders;
|
||||||
|
using OpenRA.Primitives;
|
||||||
|
using OpenRA.Traits;
|
||||||
|
using OpenRA.Widgets;
|
||||||
|
|
||||||
|
namespace OpenRA.Mods.Common.Widgets
|
||||||
|
{
|
||||||
|
public class EditorViewportControllerWidget : Widget
|
||||||
|
{
|
||||||
|
public IEditorBrush CurrentBrush { get; private set; }
|
||||||
|
|
||||||
|
public readonly string TooltipContainer;
|
||||||
|
public readonly string TooltipTemplate;
|
||||||
|
|
||||||
|
readonly Lazy<TooltipContainerWidget> tooltipContainer;
|
||||||
|
readonly EditorDefaultBrush defaultBrush;
|
||||||
|
readonly WorldRenderer worldRenderer;
|
||||||
|
|
||||||
|
bool enableTooltips;
|
||||||
|
|
||||||
|
[ObjectCreator.UseCtor]
|
||||||
|
public EditorViewportControllerWidget(World world, WorldRenderer worldRenderer)
|
||||||
|
{
|
||||||
|
this.worldRenderer = worldRenderer;
|
||||||
|
tooltipContainer = Exts.Lazy(() => Ui.Root.Get<TooltipContainerWidget>(TooltipContainer));
|
||||||
|
CurrentBrush = defaultBrush = new EditorDefaultBrush(this, worldRenderer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ClearBrush() { SetBrush(null); }
|
||||||
|
public void SetBrush(IEditorBrush brush)
|
||||||
|
{
|
||||||
|
CurrentBrush = brush ?? defaultBrush;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void MouseEntered()
|
||||||
|
{
|
||||||
|
enableTooltips = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void MouseExited()
|
||||||
|
{
|
||||||
|
tooltipContainer.Value.RemoveTooltip();
|
||||||
|
enableTooltips = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetTooltip(string tooltip)
|
||||||
|
{
|
||||||
|
if (!enableTooltips)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (tooltip != null)
|
||||||
|
{
|
||||||
|
Func<string> getTooltip = () => tooltip;
|
||||||
|
tooltipContainer.Value.SetTooltip(TooltipTemplate, new WidgetArgs() { { "getText", getTooltip } });
|
||||||
|
}
|
||||||
|
else
|
||||||
|
tooltipContainer.Value.RemoveTooltip();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool HandleMouseInput(MouseInput mi)
|
||||||
|
{
|
||||||
|
if (CurrentBrush.HandleMouseInput(mi))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return base.HandleMouseInput(mi);
|
||||||
|
}
|
||||||
|
|
||||||
|
WPos cachedViewportPosition;
|
||||||
|
public override void Tick()
|
||||||
|
{
|
||||||
|
// Clear any tooltips when the viewport is scrolled using the keyboard
|
||||||
|
if (worldRenderer.Viewport.CenterPosition != cachedViewportPosition)
|
||||||
|
SetTooltip(null);
|
||||||
|
|
||||||
|
cachedViewportPosition = worldRenderer.Viewport.CenterPosition;
|
||||||
|
CurrentBrush.Tick();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
150
OpenRA.Mods.Common/Widgets/Logic/Editor/ActorSelectorLogic.cs
Normal file
150
OpenRA.Mods.Common/Widgets/Logic/Editor/ActorSelectorLogic.cs
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007-2015 The OpenRA Developers (see AUTHORS)
|
||||||
|
* This file is part of OpenRA, which is free software. It is made
|
||||||
|
* available to you under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation. For more information,
|
||||||
|
* see COPYING.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Linq;
|
||||||
|
using OpenRA.FileFormats;
|
||||||
|
using OpenRA.Graphics;
|
||||||
|
using OpenRA.Mods.Common;
|
||||||
|
using OpenRA.Mods.Common.Graphics;
|
||||||
|
using OpenRA.Mods.Common.Traits;
|
||||||
|
using OpenRA.Mods.Common.Widgets;
|
||||||
|
using OpenRA.Primitives;
|
||||||
|
using OpenRA.Traits;
|
||||||
|
using OpenRA.Widgets;
|
||||||
|
|
||||||
|
namespace OpenRA.Mods.Common.Widgets.Logic
|
||||||
|
{
|
||||||
|
public class ActorSelectorLogic
|
||||||
|
{
|
||||||
|
readonly EditorViewportControllerWidget editor;
|
||||||
|
readonly DropDownButtonWidget ownersDropDown;
|
||||||
|
readonly ScrollPanelWidget panel;
|
||||||
|
readonly ScrollItemWidget itemTemplate;
|
||||||
|
readonly Ruleset modRules;
|
||||||
|
readonly World world;
|
||||||
|
readonly WorldRenderer worldRenderer;
|
||||||
|
|
||||||
|
PlayerReference selectedOwner;
|
||||||
|
|
||||||
|
[ObjectCreator.UseCtor]
|
||||||
|
public ActorSelectorLogic(Widget widget, World world, WorldRenderer worldRenderer, Ruleset modRules)
|
||||||
|
{
|
||||||
|
this.modRules = modRules;
|
||||||
|
this.world = world;
|
||||||
|
this.worldRenderer = worldRenderer;
|
||||||
|
|
||||||
|
editor = widget.Parent.Get<EditorViewportControllerWidget>("MAP_EDITOR");
|
||||||
|
ownersDropDown = widget.Get<DropDownButtonWidget>("OWNERS_DROPDOWN");
|
||||||
|
|
||||||
|
panel = widget.Get<ScrollPanelWidget>("ACTORTEMPLATE_LIST");
|
||||||
|
itemTemplate = panel.Get<ScrollItemWidget>("ACTORPREVIEW_TEMPLATE");
|
||||||
|
panel.Layout = new GridLayout(panel);
|
||||||
|
|
||||||
|
var editorLayer = world.WorldActor.Trait<EditorActorLayer>();
|
||||||
|
|
||||||
|
selectedOwner = editorLayer.Players.Players.Values.First();
|
||||||
|
Func<PlayerReference, ScrollItemWidget, ScrollItemWidget> setupItem = (option, template) =>
|
||||||
|
{
|
||||||
|
var item = ScrollItemWidget.Setup(template, () => selectedOwner == option, () =>
|
||||||
|
{
|
||||||
|
selectedOwner = option;
|
||||||
|
|
||||||
|
ownersDropDown.Text = selectedOwner.Name;
|
||||||
|
ownersDropDown.TextColor = selectedOwner.Color.RGB;
|
||||||
|
|
||||||
|
IntializeActorPreviews();
|
||||||
|
});
|
||||||
|
|
||||||
|
item.Get<LabelWidget>("LABEL").GetText = () => option.Name;
|
||||||
|
item.GetColor = () => option.Color.RGB;
|
||||||
|
|
||||||
|
return item;
|
||||||
|
};
|
||||||
|
|
||||||
|
ownersDropDown.OnClick = () =>
|
||||||
|
{
|
||||||
|
var owners = editorLayer.Players.Players.Values.OrderBy(p => p.Name);
|
||||||
|
ownersDropDown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 270, owners, setupItem);
|
||||||
|
};
|
||||||
|
|
||||||
|
ownersDropDown.Text = selectedOwner.Name;
|
||||||
|
ownersDropDown.TextColor = selectedOwner.Color.RGB;
|
||||||
|
|
||||||
|
IntializeActorPreviews();
|
||||||
|
}
|
||||||
|
|
||||||
|
void IntializeActorPreviews()
|
||||||
|
{
|
||||||
|
panel.RemoveChildren();
|
||||||
|
|
||||||
|
var actors = modRules.Actors.Where(a => !a.Value.Name.Contains('^'))
|
||||||
|
.Select(a => a.Value);
|
||||||
|
|
||||||
|
foreach (var a in actors)
|
||||||
|
{
|
||||||
|
var actor = a;
|
||||||
|
if (actor.Traits.Contains<BridgeInfo>()) // bridge layer takes care about that automatically
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!actor.Traits.Contains<IRenderActorPreviewInfo>())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var filter = actor.Traits.GetOrDefault<EditorTilesetFilterInfo>();
|
||||||
|
if (filter != null)
|
||||||
|
{
|
||||||
|
if (filter.ExcludeTilesets != null && filter.ExcludeTilesets.Contains(world.TileSet.Id))
|
||||||
|
continue;
|
||||||
|
if (filter.RequireTilesets != null && !filter.RequireTilesets.Contains(world.TileSet.Id))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var td = new TypeDictionary();
|
||||||
|
td.Add(new FacingInit(92));
|
||||||
|
td.Add(new TurretFacingInit(92));
|
||||||
|
td.Add(new HideBibPreviewInit());
|
||||||
|
td.Add(new OwnerInit(selectedOwner.Name));
|
||||||
|
td.Add(new RaceInit(selectedOwner.Race));
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var item = ScrollItemWidget.Setup(itemTemplate,
|
||||||
|
() => { var brush = editor.CurrentBrush as EditorActorBrush; return brush != null && brush.Actor == actor; },
|
||||||
|
() => editor.SetBrush(new EditorActorBrush(editor, actor, selectedOwner, worldRenderer)));
|
||||||
|
|
||||||
|
var preview = item.Get<ActorPreviewWidget>("ACTOR_PREVIEW");
|
||||||
|
preview.SetPreview(actor, td);
|
||||||
|
|
||||||
|
// Scale templates to fit within the panel
|
||||||
|
var scale = 1f;
|
||||||
|
if (scale * preview.IdealPreviewSize.X > itemTemplate.Bounds.Width)
|
||||||
|
scale = (float)(itemTemplate.Bounds.Width - panel.ItemSpacing) / (float)preview.IdealPreviewSize.X;
|
||||||
|
|
||||||
|
preview.GetScale = () => scale;
|
||||||
|
preview.Bounds.Width = (int)(scale * preview.IdealPreviewSize.X);
|
||||||
|
preview.Bounds.Height = (int)(scale * preview.IdealPreviewSize.Y);
|
||||||
|
|
||||||
|
item.Bounds.Width = preview.Bounds.Width + 2 * preview.Bounds.X;
|
||||||
|
item.Bounds.Height = preview.Bounds.Height + 2 * preview.Bounds.Y;
|
||||||
|
item.IsVisible = () => true;
|
||||||
|
item.GetTooltipText = () => actor.Name;
|
||||||
|
panel.AddChild(item);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
Log.Write("debug", "Map editor ignoring actor {0}, because of missing sprites for tileset {1}.",
|
||||||
|
actor.Name, world.TileSet.Id);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007-2015 The OpenRA Developers (see AUTHORS)
|
||||||
|
* This file is part of OpenRA, which is free software. It is made
|
||||||
|
* available to you under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation. For more information,
|
||||||
|
* see COPYING.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using OpenRA.FileFormats;
|
||||||
|
using OpenRA.Graphics;
|
||||||
|
using OpenRA.Traits;
|
||||||
|
using OpenRA.Widgets;
|
||||||
|
|
||||||
|
namespace OpenRA.Mods.Common.Widgets.Logic
|
||||||
|
{
|
||||||
|
public class LayerSelectorLogic
|
||||||
|
{
|
||||||
|
readonly EditorViewportControllerWidget editor;
|
||||||
|
readonly Ruleset modRules;
|
||||||
|
readonly World world;
|
||||||
|
readonly WorldRenderer worldRenderer;
|
||||||
|
|
||||||
|
readonly ScrollPanelWidget layerTemplateList;
|
||||||
|
readonly ScrollItemWidget layerPreviewTemplate;
|
||||||
|
|
||||||
|
[ObjectCreator.UseCtor]
|
||||||
|
public LayerSelectorLogic(Widget widget, WorldRenderer worldRenderer, Ruleset modRules)
|
||||||
|
{
|
||||||
|
this.modRules = modRules;
|
||||||
|
this.worldRenderer = worldRenderer;
|
||||||
|
this.world = worldRenderer.World;
|
||||||
|
|
||||||
|
editor = widget.Parent.Get<EditorViewportControllerWidget>("MAP_EDITOR");
|
||||||
|
|
||||||
|
layerTemplateList = widget.Get<ScrollPanelWidget>("LAYERTEMPLATE_LIST");
|
||||||
|
layerTemplateList.Layout = new GridLayout(layerTemplateList);
|
||||||
|
layerPreviewTemplate = layerTemplateList.Get<ScrollItemWidget>("LAYERPREVIEW_TEMPLATE");
|
||||||
|
|
||||||
|
IntializeLayerPreview(widget);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IntializeLayerPreview(Widget widget)
|
||||||
|
{
|
||||||
|
layerTemplateList.RemoveChildren();
|
||||||
|
|
||||||
|
var resources = modRules.Actors["world"].Traits.WithInterface<ResourceTypeInfo>();
|
||||||
|
foreach (var resource in resources)
|
||||||
|
{
|
||||||
|
var newResourcePreviewTemplate = ScrollItemWidget.Setup(layerPreviewTemplate,
|
||||||
|
() => { var brush = editor.CurrentBrush as EditorResourceBrush; return brush != null && brush.ResourceType == resource; },
|
||||||
|
() => editor.SetBrush(new EditorResourceBrush(editor, resource, worldRenderer)));
|
||||||
|
|
||||||
|
newResourcePreviewTemplate.Bounds.X = 0;
|
||||||
|
newResourcePreviewTemplate.Bounds.Y = 0;
|
||||||
|
|
||||||
|
var layerPreview = newResourcePreviewTemplate.Get<SpriteWidget>("LAYER_PREVIEW");
|
||||||
|
layerPreview.IsVisible = () => true;
|
||||||
|
layerPreview.GetPalette = () => resource.Palette;
|
||||||
|
|
||||||
|
var variant = resource.Variants.FirstOrDefault();
|
||||||
|
var sequenceProvier = modRules.Sequences[world.TileSet.Id];
|
||||||
|
var sequence = sequenceProvier.GetSequence("resources", variant);
|
||||||
|
var frame = sequence.Frames != null ? sequence.Frames.Last() : resource.MaxDensity - 1;
|
||||||
|
layerPreview.GetSprite = () => sequence.GetSprite(frame);
|
||||||
|
|
||||||
|
var tileWidth = Game.ModData.Manifest.TileSize.Width;
|
||||||
|
var tileHeight = Game.ModData.Manifest.TileSize.Height;
|
||||||
|
layerPreview.Bounds.Width = tileWidth;
|
||||||
|
layerPreview.Bounds.Height = tileHeight;
|
||||||
|
newResourcePreviewTemplate.Bounds.Width = tileWidth + (layerPreview.Bounds.X * 2);
|
||||||
|
newResourcePreviewTemplate.Bounds.Height = tileHeight + (layerPreview.Bounds.Y * 2);
|
||||||
|
|
||||||
|
newResourcePreviewTemplate.IsVisible = () => true;
|
||||||
|
newResourcePreviewTemplate.GetTooltipText = () => resource.Name;
|
||||||
|
|
||||||
|
layerTemplateList.AddChild(newResourcePreviewTemplate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
70
OpenRA.Mods.Common/Widgets/Logic/Editor/MapEditorLogic.cs
Normal file
70
OpenRA.Mods.Common/Widgets/Logic/Editor/MapEditorLogic.cs
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007-2015 The OpenRA Developers (see AUTHORS)
|
||||||
|
* This file is part of OpenRA, which is free software. It is made
|
||||||
|
* available to you under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation. For more information,
|
||||||
|
* see COPYING.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Linq;
|
||||||
|
using OpenRA.Graphics;
|
||||||
|
using OpenRA.Mods.Common.Traits;
|
||||||
|
using OpenRA.Primitives;
|
||||||
|
using OpenRA.Traits;
|
||||||
|
using OpenRA.Widgets;
|
||||||
|
|
||||||
|
namespace OpenRA.Mods.Common.Widgets.Logic
|
||||||
|
{
|
||||||
|
public class MapEditorLogic
|
||||||
|
{
|
||||||
|
[ObjectCreator.UseCtor]
|
||||||
|
public MapEditorLogic(Widget widget, World world, WorldRenderer worldRenderer)
|
||||||
|
{
|
||||||
|
var gridButton = widget.GetOrNull<ButtonWidget>("GRID_BUTTON");
|
||||||
|
var terrainGeometryTrait = world.WorldActor.Trait<TerrainGeometryOverlay>();
|
||||||
|
|
||||||
|
if (gridButton != null && terrainGeometryTrait != null)
|
||||||
|
{
|
||||||
|
gridButton.OnClick = () => terrainGeometryTrait.Enabled ^= true;
|
||||||
|
gridButton.IsHighlighted = () => terrainGeometryTrait.Enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
var zoomDropdown = widget.Get<DropDownButtonWidget>("ZOOM_BUTTON");
|
||||||
|
if (zoomDropdown != null)
|
||||||
|
{
|
||||||
|
var selectedZoom = Game.Settings.Graphics.PixelDouble ? 2f : 1f;
|
||||||
|
var selectedLabel = selectedZoom.ToString();
|
||||||
|
Func<float, ScrollItemWidget, ScrollItemWidget> setupItem = (zoom, itemTemplate) =>
|
||||||
|
{
|
||||||
|
var item = ScrollItemWidget.Setup(itemTemplate,
|
||||||
|
() => selectedZoom == zoom,
|
||||||
|
() => { worldRenderer.Viewport.Zoom = selectedZoom = zoom; selectedLabel = zoom.ToString(); });
|
||||||
|
|
||||||
|
var label = zoom.ToString();
|
||||||
|
item.Get<LabelWidget>("LABEL").GetText = () => label;
|
||||||
|
|
||||||
|
return item;
|
||||||
|
};
|
||||||
|
|
||||||
|
var options = new[] { 2f, 1f, 0.5f, 0.25f };
|
||||||
|
zoomDropdown.OnMouseDown = _ => zoomDropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 150, options, setupItem);
|
||||||
|
zoomDropdown.GetText = () => selectedLabel;
|
||||||
|
zoomDropdown.GetKey = _ => Game.Settings.Keys.TogglePixelDoubleKey;
|
||||||
|
zoomDropdown.OnKeyPress = e =>
|
||||||
|
{
|
||||||
|
var key = Hotkey.FromKeyInput(e);
|
||||||
|
if (key != Game.Settings.Keys.TogglePixelDoubleKey)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var selected = (options.IndexOf(selectedZoom) + 1) % options.Length;
|
||||||
|
worldRenderer.Viewport.Zoom = selectedZoom = options[selected];
|
||||||
|
selectedLabel = selectedZoom.ToString();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007-2015 The OpenRA Developers (see AUTHORS)
|
||||||
|
* This file is part of OpenRA, which is free software. It is made
|
||||||
|
* available to you under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation. For more information,
|
||||||
|
* see COPYING.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using OpenRA.GameRules;
|
||||||
|
using OpenRA.Graphics;
|
||||||
|
using OpenRA.Widgets;
|
||||||
|
|
||||||
|
namespace OpenRA.Mods.Common.Widgets.Logic
|
||||||
|
{
|
||||||
|
public class MapEditorTabsLogic
|
||||||
|
{
|
||||||
|
protected enum MenuType { Tiles, Layers, Actors }
|
||||||
|
protected MenuType menuType = MenuType.Tiles;
|
||||||
|
|
||||||
|
[ObjectCreator.UseCtor]
|
||||||
|
public MapEditorTabsLogic(Widget widget, WorldRenderer worldRenderer)
|
||||||
|
{
|
||||||
|
var tabContainer = widget.Get("MAP_EDITOR_TAB_CONTAINER");
|
||||||
|
|
||||||
|
var tilesTab = tabContainer.Get<ButtonWidget>("TILES_TAB");
|
||||||
|
tilesTab.IsHighlighted = () => menuType == MenuType.Tiles;
|
||||||
|
tilesTab.OnClick = () => { menuType = MenuType.Tiles; };
|
||||||
|
|
||||||
|
var overlaysTab = tabContainer.Get<ButtonWidget>("OVERLAYS_TAB");
|
||||||
|
overlaysTab.IsHighlighted = () => menuType == MenuType.Layers;
|
||||||
|
overlaysTab.OnClick = () => { menuType = MenuType.Layers; };
|
||||||
|
|
||||||
|
var actorsTab = tabContainer.Get<ButtonWidget>("ACTORS_TAB");
|
||||||
|
actorsTab.IsHighlighted = () => menuType == MenuType.Actors;
|
||||||
|
actorsTab.OnClick = () => { menuType = MenuType.Actors; };
|
||||||
|
|
||||||
|
var tileContainer = widget.Parent.Get<ContainerWidget>("TILE_WIDGETS");
|
||||||
|
tileContainer.IsVisible = () => menuType == MenuType.Tiles;
|
||||||
|
|
||||||
|
var layerContainer = widget.Parent.Get<ContainerWidget>("LAYER_WIDGETS");
|
||||||
|
layerContainer.IsVisible = () => menuType == MenuType.Layers;
|
||||||
|
|
||||||
|
var actorContainer = widget.Parent.Get<ContainerWidget>("ACTOR_WIDGETS");
|
||||||
|
actorContainer.IsVisible = () => menuType == MenuType.Actors;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
94
OpenRA.Mods.Common/Widgets/Logic/Editor/NewMapLogic.cs
Normal file
94
OpenRA.Mods.Common/Widgets/Logic/Editor/NewMapLogic.cs
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007-2015 The OpenRA Developers (see AUTHORS)
|
||||||
|
* This file is part of OpenRA, which is free software. It is made
|
||||||
|
* available to you under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation. For more information,
|
||||||
|
* see COPYING.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using OpenRA;
|
||||||
|
using OpenRA.FileFormats;
|
||||||
|
using OpenRA.Mods.Common.Widgets;
|
||||||
|
using OpenRA.Traits;
|
||||||
|
using OpenRA.Widgets;
|
||||||
|
|
||||||
|
namespace OpenRA.Mods.Common.Widgets.Logic
|
||||||
|
{
|
||||||
|
public class NewMapLogic
|
||||||
|
{
|
||||||
|
Widget panel;
|
||||||
|
|
||||||
|
[ObjectCreator.UseCtor]
|
||||||
|
public NewMapLogic(Action onExit, Action<string> onSelect, Ruleset modRules, Widget widget, World world)
|
||||||
|
{
|
||||||
|
panel = widget;
|
||||||
|
|
||||||
|
panel.Get<ButtonWidget>("CANCEL_BUTTON").OnClick = () => { Ui.CloseWindow(); onExit(); };
|
||||||
|
|
||||||
|
var tilesetDropDown = panel.Get<DropDownButtonWidget>("TILESET");
|
||||||
|
var tilesets = modRules.TileSets.Select(t => t.Key).ToList();
|
||||||
|
Func<string, ScrollItemWidget, ScrollItemWidget> setupItem = (option, template) =>
|
||||||
|
{
|
||||||
|
var item = ScrollItemWidget.Setup(template,
|
||||||
|
() => tilesetDropDown.Text == option,
|
||||||
|
() => { tilesetDropDown.Text = option; });
|
||||||
|
item.Get<LabelWidget>("LABEL").GetText = () => option;
|
||||||
|
return item;
|
||||||
|
};
|
||||||
|
tilesetDropDown.Text = tilesets.First();
|
||||||
|
tilesetDropDown.OnClick = () =>
|
||||||
|
tilesetDropDown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 210, tilesets, setupItem);
|
||||||
|
|
||||||
|
var widthTextField = panel.Get<TextFieldWidget>("WIDTH");
|
||||||
|
var heightTextField = panel.Get<TextFieldWidget>("HEIGHT");
|
||||||
|
|
||||||
|
panel.Get<ButtonWidget>("CREATE_BUTTON").OnClick = () =>
|
||||||
|
{
|
||||||
|
var tileset = modRules.TileSets[tilesetDropDown.Text];
|
||||||
|
var map = Map.FromTileset(tileset);
|
||||||
|
|
||||||
|
int width, height;
|
||||||
|
int.TryParse(widthTextField.Text, out width);
|
||||||
|
int.TryParse(heightTextField.Text, out height);
|
||||||
|
|
||||||
|
// Require at least a 2x2 playable area so that the
|
||||||
|
// ground is visible through the edge shroud
|
||||||
|
width = Math.Max(2, width);
|
||||||
|
height = Math.Max(2, height);
|
||||||
|
|
||||||
|
map.Resize(width + 2, height + tileset.MaxGroundHeight + 2);
|
||||||
|
map.ResizeCordon(1, 1, width + 1, height + tileset.MaxGroundHeight + 1);
|
||||||
|
map.PlayerDefinitions = new MapPlayers(map.Rules, map.SpawnPoints.Value.Length).ToMiniYaml();
|
||||||
|
map.FixOpenAreas(modRules);
|
||||||
|
|
||||||
|
var userMapFolder = Game.ModData.Manifest.MapFolders.First(f => f.Value == "User").Key;
|
||||||
|
|
||||||
|
// Ignore optional flag
|
||||||
|
if (userMapFolder.StartsWith("~"))
|
||||||
|
userMapFolder = userMapFolder.Substring(1);
|
||||||
|
|
||||||
|
var mapDir = Platform.ResolvePath(userMapFolder);
|
||||||
|
Directory.CreateDirectory(mapDir);
|
||||||
|
var tempLocation = Path.Combine(mapDir, "temp") + ".oramap";
|
||||||
|
map.Save(tempLocation); // TODO: load it right away and save later properly
|
||||||
|
|
||||||
|
var newMap = new Map(tempLocation);
|
||||||
|
Game.ModData.MapCache[newMap.Uid].UpdateFromMap(newMap, MapClassification.User);
|
||||||
|
|
||||||
|
ConnectionLogic.Connect(System.Net.IPAddress.Loopback.ToString(),
|
||||||
|
Game.CreateLocalServer(newMap.Uid),
|
||||||
|
"",
|
||||||
|
() => { Game.LoadEditor(newMap.Uid); },
|
||||||
|
() => { Game.CloseServer(); onExit(); });
|
||||||
|
onSelect(newMap.Uid);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
141
OpenRA.Mods.Common/Widgets/Logic/Editor/SaveMapLogic.cs
Normal file
141
OpenRA.Mods.Common/Widgets/Logic/Editor/SaveMapLogic.cs
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007-2015 The OpenRA Developers (see AUTHORS)
|
||||||
|
* This file is part of OpenRA, which is free software. It is made
|
||||||
|
* available to you under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation. For more information,
|
||||||
|
* see COPYING.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using OpenRA.Mods.Common.Traits;
|
||||||
|
using OpenRA.Widgets;
|
||||||
|
|
||||||
|
namespace OpenRA.Mods.Common.Widgets.Logic
|
||||||
|
{
|
||||||
|
public class SaveMapLogic
|
||||||
|
{
|
||||||
|
[ObjectCreator.UseCtor]
|
||||||
|
public SaveMapLogic(Widget widget, Action onExit, Map map, EditorActorLayer editorActorLayer)
|
||||||
|
{
|
||||||
|
var title = widget.Get<TextFieldWidget>("TITLE");
|
||||||
|
title.Text = map.Title;
|
||||||
|
|
||||||
|
var author = widget.Get<TextFieldWidget>("AUTHOR");
|
||||||
|
author.Text = map.Author;
|
||||||
|
|
||||||
|
// TODO: This should use a multi-line textfield once they exist
|
||||||
|
var description = widget.Get<TextFieldWidget>("DESCRIPTION");
|
||||||
|
description.Text = map.Description;
|
||||||
|
|
||||||
|
// TODO: This should use a multi-selection dropdown once they exist
|
||||||
|
var visibilityDropdown = widget.Get<DropDownButtonWidget>("VISIBILITY_DROPDOWN");
|
||||||
|
{
|
||||||
|
var mapVisibility = new List<string>(Enum.GetNames(typeof(MapVisibility)));
|
||||||
|
Func<string, ScrollItemWidget, ScrollItemWidget> setupItem = (option, template) =>
|
||||||
|
{
|
||||||
|
var item = ScrollItemWidget.Setup(template,
|
||||||
|
() => visibilityDropdown.Text == option,
|
||||||
|
() => { visibilityDropdown.Text = option; });
|
||||||
|
item.Get<LabelWidget>("LABEL").GetText = () => option;
|
||||||
|
return item;
|
||||||
|
};
|
||||||
|
|
||||||
|
visibilityDropdown.Text = Enum.GetName(typeof(MapVisibility), map.Visibility);
|
||||||
|
visibilityDropdown.OnClick = () =>
|
||||||
|
visibilityDropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 210, mapVisibility, setupItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
var directoryDropdown = widget.Get<DropDownButtonWidget>("DIRECTORY_DROPDOWN");
|
||||||
|
{
|
||||||
|
var mapDirectories = Game.ModData.Manifest.MapFolders.Keys.Select(ff =>
|
||||||
|
{
|
||||||
|
var f = Platform.UnresolvePath(ff);
|
||||||
|
if (f.StartsWith("~"))
|
||||||
|
f = f.Substring(1);
|
||||||
|
|
||||||
|
return f;
|
||||||
|
}).ToList();
|
||||||
|
|
||||||
|
Func<string, ScrollItemWidget, ScrollItemWidget> setupItem = (option, template) =>
|
||||||
|
{
|
||||||
|
var item = ScrollItemWidget.Setup(template,
|
||||||
|
() => directoryDropdown.Text == option,
|
||||||
|
() => directoryDropdown.Text = option);
|
||||||
|
item.Get<LabelWidget>("LABEL").GetText = () => option;
|
||||||
|
return item;
|
||||||
|
};
|
||||||
|
|
||||||
|
var mapDirectory = Platform.UnresolvePath(Path.GetDirectoryName(map.Path));
|
||||||
|
var initialDirectory = mapDirectories.FirstOrDefault(f => f == mapDirectory);
|
||||||
|
|
||||||
|
if (initialDirectory == null)
|
||||||
|
initialDirectory = mapDirectories.First();
|
||||||
|
|
||||||
|
directoryDropdown.Text = initialDirectory;
|
||||||
|
directoryDropdown.OnClick = () =>
|
||||||
|
directoryDropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 210, mapDirectories, setupItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
var filename = widget.Get<TextFieldWidget>("FILENAME");
|
||||||
|
filename.Text = Path.GetFileNameWithoutExtension(map.Path);
|
||||||
|
|
||||||
|
var fileTypes = new Dictionary<string, string>()
|
||||||
|
{
|
||||||
|
{ ".oramap", ".oramap" },
|
||||||
|
{ "(unpacked)", "" }
|
||||||
|
};
|
||||||
|
|
||||||
|
var typeDropdown = widget.Get<DropDownButtonWidget>("TYPE_DROPDOWN");
|
||||||
|
{
|
||||||
|
Func<string, ScrollItemWidget, ScrollItemWidget> setupItem = (option, template) =>
|
||||||
|
{
|
||||||
|
var item = ScrollItemWidget.Setup(template,
|
||||||
|
() => typeDropdown.Text == option,
|
||||||
|
() => typeDropdown.Text = option);
|
||||||
|
item.Get<LabelWidget>("LABEL").GetText = () => option;
|
||||||
|
return item;
|
||||||
|
};
|
||||||
|
|
||||||
|
typeDropdown.Text = Path.GetExtension(map.Path);
|
||||||
|
if (string.IsNullOrEmpty(typeDropdown.Text))
|
||||||
|
typeDropdown.Text = fileTypes.First(t => t.Value == "").Key;
|
||||||
|
|
||||||
|
typeDropdown.OnClick = () =>
|
||||||
|
typeDropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 210, fileTypes.Keys, setupItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
var close = widget.Get<ButtonWidget>("BACK_BUTTON");
|
||||||
|
close.OnClick = () => { Ui.CloseWindow(); onExit(); };
|
||||||
|
|
||||||
|
var save = widget.Get<ButtonWidget>("SAVE_BUTTON");
|
||||||
|
save.OnClick = () =>
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(filename.Text))
|
||||||
|
return;
|
||||||
|
|
||||||
|
map.Title = title.Text;
|
||||||
|
map.Description = description.Text;
|
||||||
|
map.Author = author.Text;
|
||||||
|
map.Visibility = (MapVisibility)Enum.Parse(typeof(MapVisibility), visibilityDropdown.Text);
|
||||||
|
map.ActorDefinitions = editorActorLayer.Save();
|
||||||
|
map.PlayerDefinitions = editorActorLayer.Players.ToMiniYaml();
|
||||||
|
map.RequiresMod = Game.ModData.Manifest.Mod.Id;
|
||||||
|
|
||||||
|
var combinedPath = Platform.ResolvePath(Path.Combine(directoryDropdown.Text, filename.Text + fileTypes[typeDropdown.Text]));
|
||||||
|
map.Save(combinedPath);
|
||||||
|
|
||||||
|
// Update the map cache so it can be loaded without restarting the game
|
||||||
|
Game.ModData.MapCache[map.Uid].UpdateFromMap(map, MapClassification.User);
|
||||||
|
|
||||||
|
Console.WriteLine("Saved current map at {0}", combinedPath);
|
||||||
|
Ui.CloseWindow();
|
||||||
|
onExit();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
92
OpenRA.Mods.Common/Widgets/Logic/Editor/TileSelectorLogic.cs
Normal file
92
OpenRA.Mods.Common/Widgets/Logic/Editor/TileSelectorLogic.cs
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007-2015 The OpenRA Developers (see AUTHORS)
|
||||||
|
* This file is part of OpenRA, which is free software. It is made
|
||||||
|
* available to you under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation. For more information,
|
||||||
|
* see COPYING.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using OpenRA.FileFormats;
|
||||||
|
using OpenRA.Graphics;
|
||||||
|
using OpenRA.Widgets;
|
||||||
|
|
||||||
|
namespace OpenRA.Mods.Common.Widgets.Logic
|
||||||
|
{
|
||||||
|
public class TileSelectorLogic
|
||||||
|
{
|
||||||
|
readonly EditorViewportControllerWidget editor;
|
||||||
|
readonly ScrollPanelWidget panel;
|
||||||
|
readonly ScrollItemWidget itemTemplate;
|
||||||
|
|
||||||
|
[ObjectCreator.UseCtor]
|
||||||
|
public TileSelectorLogic(Widget widget, WorldRenderer worldRenderer, Ruleset modRules)
|
||||||
|
{
|
||||||
|
var tileset = modRules.TileSets[worldRenderer.World.Map.Tileset];
|
||||||
|
|
||||||
|
editor = widget.Parent.Get<EditorViewportControllerWidget>("MAP_EDITOR");
|
||||||
|
panel = widget.Get<ScrollPanelWidget>("TILETEMPLATE_LIST");
|
||||||
|
itemTemplate = panel.Get<ScrollItemWidget>("TILEPREVIEW_TEMPLATE");
|
||||||
|
panel.Layout = new GridLayout(panel);
|
||||||
|
|
||||||
|
var tileCategorySelector = widget.Get<DropDownButtonWidget>("TILE_CATEGORY");
|
||||||
|
var categories = tileset.EditorTemplateOrder;
|
||||||
|
Func<string, ScrollItemWidget, ScrollItemWidget> setupItem = (option, template) =>
|
||||||
|
{
|
||||||
|
var item = ScrollItemWidget.Setup(template,
|
||||||
|
() => tileCategorySelector.Text == option,
|
||||||
|
() => { tileCategorySelector.Text = option; IntializeTilePreview(widget, worldRenderer, tileset, option); });
|
||||||
|
|
||||||
|
item.Get<LabelWidget>("LABEL").GetText = () => option;
|
||||||
|
return item;
|
||||||
|
};
|
||||||
|
|
||||||
|
tileCategorySelector.OnClick = () =>
|
||||||
|
tileCategorySelector.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 270, categories, setupItem);
|
||||||
|
|
||||||
|
tileCategorySelector.Text = categories.First();
|
||||||
|
IntializeTilePreview(widget, worldRenderer, tileset, categories.First());
|
||||||
|
}
|
||||||
|
|
||||||
|
void IntializeTilePreview(Widget widget, WorldRenderer worldRenderer, TileSet tileset, string category)
|
||||||
|
{
|
||||||
|
panel.RemoveChildren();
|
||||||
|
|
||||||
|
var tileIds = tileset.Templates
|
||||||
|
.Where(t => t.Value.Category == category)
|
||||||
|
.Select(t => t.Value.Id);
|
||||||
|
|
||||||
|
foreach (var t in tileIds)
|
||||||
|
{
|
||||||
|
var tileId = t;
|
||||||
|
var item = ScrollItemWidget.Setup(itemTemplate,
|
||||||
|
() => { var brush = editor.CurrentBrush as EditorTileBrush; return brush != null && brush.Template == tileId; },
|
||||||
|
() => editor.SetBrush(new EditorTileBrush(editor, tileId, worldRenderer)));
|
||||||
|
|
||||||
|
var preview = item.Get<TerrainTemplatePreviewWidget>("TILE_PREVIEW");
|
||||||
|
var template = tileset.Templates[tileId];
|
||||||
|
var bounds = worldRenderer.Theater.TemplateBounds(template, Game.ModData.Manifest.TileSize, worldRenderer.World.Map.TileShape);
|
||||||
|
|
||||||
|
// Scale templates to fit within the panel
|
||||||
|
var scale = 1f;
|
||||||
|
while (scale * bounds.Width > itemTemplate.Bounds.Width)
|
||||||
|
scale /= 2;
|
||||||
|
|
||||||
|
preview.Template = template;
|
||||||
|
preview.GetScale = () => scale;
|
||||||
|
preview.Bounds.Width = (int)(scale * bounds.Width);
|
||||||
|
preview.Bounds.Height = (int)(scale * bounds.Height);
|
||||||
|
|
||||||
|
item.Bounds.Width = preview.Bounds.Width + 2 * preview.Bounds.X;
|
||||||
|
item.Bounds.Height = preview.Bounds.Height + 2 * preview.Bounds.Y;
|
||||||
|
item.IsVisible = () => true;
|
||||||
|
item.GetTooltipText = () => tileId.ToString();
|
||||||
|
|
||||||
|
panel.AddChild(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -36,7 +36,9 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
// TODO: Create a mechanism to do things like this cleaner. Also needed for scripted missions
|
// TODO: Create a mechanism to do things like this cleaner. Also needed for scripted missions
|
||||||
Action onQuit = () =>
|
Action onQuit = () =>
|
||||||
{
|
{
|
||||||
Sound.PlayNotification(world.Map.Rules, null, "Speech", "Leave", world.LocalPlayer == null ? null : world.LocalPlayer.Country.Race);
|
if (world.Type == WorldType.Regular)
|
||||||
|
Sound.PlayNotification(world.Map.Rules, null, "Speech", "Leave", world.LocalPlayer == null ? null : world.LocalPlayer.Country.Race);
|
||||||
|
|
||||||
resumeDisabled = true;
|
resumeDisabled = true;
|
||||||
|
|
||||||
var exitDelay = 1200;
|
var exitDelay = 1200;
|
||||||
@@ -64,18 +66,29 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
|
|
||||||
Action showMenu = () => hideMenu = false;
|
Action showMenu = () => hideMenu = false;
|
||||||
|
|
||||||
menu.Get<ButtonWidget>("ABORT_MISSION").OnClick = () =>
|
var abortMissionButton = menu.Get<ButtonWidget>("ABORT_MISSION");
|
||||||
|
abortMissionButton.IsVisible = () => world.Type == WorldType.Regular;
|
||||||
|
abortMissionButton.OnClick = () =>
|
||||||
{
|
{
|
||||||
hideMenu = true;
|
hideMenu = true;
|
||||||
ConfirmationDialogs.PromptConfirmAction("Abort Mission", "Leave this game and return to the menu?", onQuit, showMenu);
|
ConfirmationDialogs.PromptConfirmAction("Abort Mission", "Leave this game and return to the menu?", onQuit, showMenu);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var exitEditorButton = menu.Get<ButtonWidget>("EXIT_EDITOR");
|
||||||
|
exitEditorButton.IsVisible = () => world.Type == WorldType.Editor;
|
||||||
|
exitEditorButton.OnClick = () =>
|
||||||
|
{
|
||||||
|
hideMenu = true;
|
||||||
|
ConfirmationDialogs.PromptConfirmAction("Exit Map Editor", "Exit and lose all unsaved changes?", onQuit, showMenu);
|
||||||
|
};
|
||||||
|
|
||||||
Action onSurrender = () =>
|
Action onSurrender = () =>
|
||||||
{
|
{
|
||||||
world.IssueOrder(new Order("Surrender", world.LocalPlayer.PlayerActor, false));
|
world.IssueOrder(new Order("Surrender", world.LocalPlayer.PlayerActor, false));
|
||||||
closeMenu();
|
closeMenu();
|
||||||
};
|
};
|
||||||
var surrenderButton = menu.Get<ButtonWidget>("SURRENDER");
|
var surrenderButton = menu.Get<ButtonWidget>("SURRENDER");
|
||||||
|
surrenderButton.IsVisible = () => world.Type == WorldType.Regular;
|
||||||
surrenderButton.IsDisabled = () => (world.LocalPlayer == null || world.LocalPlayer.WinState != WinState.Undefined);
|
surrenderButton.IsDisabled = () => (world.LocalPlayer == null || world.LocalPlayer.WinState != WinState.Undefined);
|
||||||
surrenderButton.OnClick = () =>
|
surrenderButton.OnClick = () =>
|
||||||
{
|
{
|
||||||
@@ -84,6 +97,19 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
};
|
};
|
||||||
surrenderButton.IsDisabled = () => world.LocalPlayer == null || world.LocalPlayer.WinState != WinState.Undefined;
|
surrenderButton.IsDisabled = () => world.LocalPlayer == null || world.LocalPlayer.WinState != WinState.Undefined;
|
||||||
|
|
||||||
|
var saveMapButton = menu.Get<ButtonWidget>("SAVE_MAP");
|
||||||
|
saveMapButton.IsVisible = () => world.Type == WorldType.Editor;
|
||||||
|
saveMapButton.OnClick = () =>
|
||||||
|
{
|
||||||
|
hideMenu = true;
|
||||||
|
Ui.OpenWindow("SAVE_MAP_PANEL", new WidgetArgs()
|
||||||
|
{
|
||||||
|
{ "onExit", () => hideMenu = false },
|
||||||
|
{ "map", world.Map },
|
||||||
|
{ "editorActorLayer", world.WorldActor.Trait<EditorActorLayer>() }
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
menu.Get<ButtonWidget>("MUSIC").OnClick = () =>
|
menu.Get<ButtonWidget>("MUSIC").OnClick = () =>
|
||||||
{
|
{
|
||||||
hideMenu = true;
|
hideMenu = true;
|
||||||
@@ -111,7 +137,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
resumeButton.OnClick = closeMenu;
|
resumeButton.OnClick = closeMenu;
|
||||||
|
|
||||||
var panelRoot = widget.GetOrNull("PANEL_ROOT");
|
var panelRoot = widget.GetOrNull("PANEL_ROOT");
|
||||||
if (panelRoot != null)
|
if (panelRoot != null && world.Type != WorldType.Editor)
|
||||||
{
|
{
|
||||||
var gameInfoPanel = Game.LoadWidget(world, "GAME_INFO_PANEL", panelRoot, new WidgetArgs()
|
var gameInfoPanel = Game.LoadWidget(world, "GAME_INFO_PANEL", panelRoot, new WidgetArgs()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -102,8 +102,9 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
{
|
{
|
||||||
leaveButton.Disabled = true;
|
leaveButton.Disabled = true;
|
||||||
|
|
||||||
Sound.PlayNotification(world.Map.Rules, null, "Speech", "Leave",
|
if (world.Type == WorldType.Regular)
|
||||||
world.LocalPlayer == null ? null : world.LocalPlayer.Country.Race);
|
Sound.PlayNotification(world.Map.Rules, null, "Speech", "Leave",
|
||||||
|
world.LocalPlayer == null ? null : world.LocalPlayer.Country.Race);
|
||||||
|
|
||||||
var exitDelay = 1200;
|
var exitDelay = 1200;
|
||||||
if (mpe != null)
|
if (mpe != null)
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007-2015 The OpenRA Developers (see AUTHORS)
|
||||||
|
* This file is part of OpenRA, which is free software. It is made
|
||||||
|
* available to you under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation. For more information,
|
||||||
|
* see COPYING.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using OpenRA.Widgets;
|
||||||
|
|
||||||
|
namespace OpenRA.Mods.Common.Widgets.Logic
|
||||||
|
{
|
||||||
|
public class LoadMapEditorLogic
|
||||||
|
{
|
||||||
|
[ObjectCreator.UseCtor]
|
||||||
|
public LoadMapEditorLogic(Widget widget, World world)
|
||||||
|
{
|
||||||
|
var editorRoot = widget.Get("WORLD_ROOT");
|
||||||
|
Game.LoadWidget(world, "EDITOR_WORLD_ROOT", editorRoot, new WidgetArgs());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -21,7 +21,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
{
|
{
|
||||||
public class MainMenuLogic
|
public class MainMenuLogic
|
||||||
{
|
{
|
||||||
protected enum MenuType { Main, Singleplayer, Extras, None }
|
protected enum MenuType { Main, Singleplayer, Extras, MapEditor, None }
|
||||||
|
|
||||||
protected MenuType menuType = MenuType.Main;
|
protected MenuType menuType = MenuType.Main;
|
||||||
readonly Widget rootMenu;
|
readonly Widget rootMenu;
|
||||||
@@ -122,6 +122,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extrasMenu.Get<ButtonWidget>("MAP_EDITOR_BUTTON").OnClick = () => menuType = MenuType.MapEditor;
|
||||||
|
|
||||||
var assetBrowserButton = extrasMenu.GetOrNull<ButtonWidget>("ASSETBROWSER_BUTTON");
|
var assetBrowserButton = extrasMenu.GetOrNull<ButtonWidget>("ASSETBROWSER_BUTTON");
|
||||||
if (assetBrowserButton != null)
|
if (assetBrowserButton != null)
|
||||||
assetBrowserButton.OnClick = () =>
|
assetBrowserButton.OnClick = () =>
|
||||||
@@ -144,6 +146,43 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
|
|
||||||
extrasMenu.Get<ButtonWidget>("BACK_BUTTON").OnClick = () => menuType = MenuType.Main;
|
extrasMenu.Get<ButtonWidget>("BACK_BUTTON").OnClick = () => menuType = MenuType.Main;
|
||||||
|
|
||||||
|
// Map editor menu
|
||||||
|
var mapEditorMenu = widget.Get("MAP_EDITOR_MENU");
|
||||||
|
mapEditorMenu.IsVisible = () => menuType == MenuType.MapEditor;
|
||||||
|
|
||||||
|
var onSelect = new Action<string>(uid =>
|
||||||
|
{
|
||||||
|
RemoveShellmapUI();
|
||||||
|
LoadMapIntoEditor(Game.ModData.MapCache[uid].Map);
|
||||||
|
});
|
||||||
|
|
||||||
|
var newMapButton = widget.Get<ButtonWidget>("NEW_MAP_BUTTON");
|
||||||
|
newMapButton.OnClick = () =>
|
||||||
|
{
|
||||||
|
menuType = MenuType.None;
|
||||||
|
Game.OpenWindow("NEW_MAP_BG", new WidgetArgs()
|
||||||
|
{
|
||||||
|
{ "onSelect", onSelect },
|
||||||
|
{ "onExit", () => menuType = MenuType.MapEditor }
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
var loadMapButton = widget.Get<ButtonWidget>("LOAD_MAP_BUTTON");
|
||||||
|
loadMapButton.OnClick = () =>
|
||||||
|
{
|
||||||
|
var initialMap = Game.ModData.MapCache.FirstOrDefault();
|
||||||
|
menuType = MenuType.None;
|
||||||
|
Game.OpenWindow("MAPCHOOSER_PANEL", new WidgetArgs()
|
||||||
|
{
|
||||||
|
{ "initialMap", initialMap != null ? initialMap.Uid : null },
|
||||||
|
{ "onExit", () => menuType = MenuType.MapEditor },
|
||||||
|
{ "onSelect", onSelect },
|
||||||
|
{ "filter", MapVisibility.Lobby | MapVisibility.Shellmap | MapVisibility.MissionSelector },
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
mapEditorMenu.Get<ButtonWidget>("BACK_BUTTON").OnClick = () => menuType = MenuType.Extras;
|
||||||
|
|
||||||
var newsBG = widget.GetOrNull("NEWS_BG");
|
var newsBG = widget.GetOrNull("NEWS_BG");
|
||||||
if (newsBG != null)
|
if (newsBG != null)
|
||||||
{
|
{
|
||||||
@@ -189,6 +228,15 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LoadMapIntoEditor(Map map)
|
||||||
|
{
|
||||||
|
ConnectionLogic.Connect(System.Net.IPAddress.Loopback.ToString(),
|
||||||
|
Game.CreateLocalServer(map.Uid),
|
||||||
|
"",
|
||||||
|
() => { Game.LoadEditor(map.Uid); },
|
||||||
|
() => { Game.CloseServer(); menuType = MenuType.MapEditor; });
|
||||||
|
}
|
||||||
|
|
||||||
void SetNewsStatus(string message)
|
void SetNewsStatus(string message)
|
||||||
{
|
{
|
||||||
message = WidgetUtils.WrapText(message, newsStatus.Bounds.Width, Game.Renderer.Fonts[newsStatus.Font]);
|
message = WidgetUtils.WrapText(message, newsStatus.Bounds.Width, Game.Renderer.Fonts[newsStatus.Font]);
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
{ "onExit", () => { } },
|
{ "onExit", () => { } },
|
||||||
{ "onSelect", (Action<string>)(uid => preview = Game.ModData.MapCache[uid]) },
|
{ "onSelect", (Action<string>)(uid => preview = Game.ModData.MapCache[uid]) },
|
||||||
{ "filter", MapVisibility.Lobby },
|
{ "filter", MapVisibility.Lobby },
|
||||||
|
{ "onStart", () => { } }
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
{
|
{
|
||||||
public class SpriteWidget : Widget
|
public class SpriteWidget : Widget
|
||||||
{
|
{
|
||||||
|
public Func<float> GetScale = () => 1f;
|
||||||
public string Palette = "chrome";
|
public string Palette = "chrome";
|
||||||
public Func<string> GetPalette;
|
public Func<string> GetPalette;
|
||||||
public Func<Sprite> GetSprite;
|
public Func<Sprite> GetSprite;
|
||||||
@@ -44,6 +45,7 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
|
|
||||||
Sprite cachedSprite = null;
|
Sprite cachedSprite = null;
|
||||||
string cachedPalette = null;
|
string cachedPalette = null;
|
||||||
|
float cachedScale;
|
||||||
PaletteReference pr;
|
PaletteReference pr;
|
||||||
float2 offset = float2.Zero;
|
float2 offset = float2.Zero;
|
||||||
|
|
||||||
@@ -51,6 +53,7 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
{
|
{
|
||||||
var sprite = GetSprite();
|
var sprite = GetSprite();
|
||||||
var palette = GetPalette();
|
var palette = GetPalette();
|
||||||
|
var scale = GetScale();
|
||||||
|
|
||||||
if (sprite == null || palette == null)
|
if (sprite == null || palette == null)
|
||||||
return;
|
return;
|
||||||
@@ -67,7 +70,14 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
cachedPalette = palette;
|
cachedPalette = palette;
|
||||||
}
|
}
|
||||||
|
|
||||||
Game.Renderer.SpriteRenderer.DrawSprite(sprite, RenderOrigin + offset, pr);
|
if (scale != cachedScale)
|
||||||
|
{
|
||||||
|
offset *= scale;
|
||||||
|
cachedScale = scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
var size = new float2(sprite.Size.X * scale, sprite.Size.Y * scale);
|
||||||
|
Game.Renderer.SpriteRenderer.DrawSprite(sprite, RenderOrigin + offset, pr, size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
if (tileInfo == null)
|
if (tileInfo == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var sprite = worldRenderer.Theater.TileSprite(tile);
|
var sprite = worldRenderer.Theater.TileSprite(tile, 0);
|
||||||
var size = new float2(sprite.Size.X * scale, sprite.Size.Y * scale);
|
var size = new float2(sprite.Size.X * scale, sprite.Size.Y * scale);
|
||||||
|
|
||||||
var u = shape == TileShape.Rectangle ? x : (x - y) / 2f;
|
var u = shape == TileShape.Rectangle ? x : (x - y) / 2f;
|
||||||
|
|||||||
@@ -90,6 +90,7 @@
|
|||||||
<Compile Include="UtilityCommands\ImportD2kMapCommand.cs" />
|
<Compile Include="UtilityCommands\ImportD2kMapCommand.cs" />
|
||||||
<Compile Include="Traits\Render\WithAttackOverlay.cs" />
|
<Compile Include="Traits\Render\WithAttackOverlay.cs" />
|
||||||
<Compile Include="Traits\Render\WithDecorationCarryable.cs" />
|
<Compile Include="Traits\Render\WithDecorationCarryable.cs" />
|
||||||
|
<Compile Include="Traits\World\D2kEditorResourceLayer.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
|
|||||||
98
OpenRA.Mods.D2k/Traits/World/D2kEditorResourceLayer.cs
Normal file
98
OpenRA.Mods.D2k/Traits/World/D2kEditorResourceLayer.cs
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007-2015 The OpenRA Developers (see AUTHORS)
|
||||||
|
* This file is part of OpenRA, which is free software. It is made
|
||||||
|
* available to you under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation. For more information,
|
||||||
|
* see COPYING.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using OpenRA.Graphics;
|
||||||
|
using OpenRA.Mods.Common.Traits;
|
||||||
|
using OpenRA.Traits;
|
||||||
|
|
||||||
|
namespace OpenRA.Mods.D2k.Traits
|
||||||
|
{
|
||||||
|
using CellContents = D2kResourceLayer.CellContents;
|
||||||
|
using ClearSides = D2kResourceLayer.ClearSides;
|
||||||
|
|
||||||
|
[Desc("Used to render spice with round borders.")]
|
||||||
|
public class D2kEditorResourceLayerInfo : EditorResourceLayerInfo
|
||||||
|
{
|
||||||
|
public override object Create(ActorInitializer init) { return new D2kEditorResourceLayer(init.Self); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class D2kEditorResourceLayer : EditorResourceLayer
|
||||||
|
{
|
||||||
|
public D2kEditorResourceLayer(Actor self)
|
||||||
|
: base(self) { }
|
||||||
|
|
||||||
|
public override CellContents UpdateDirtyTile(CPos c)
|
||||||
|
{
|
||||||
|
var t = Tiles[c];
|
||||||
|
|
||||||
|
// Empty tile
|
||||||
|
if (t.Type == null)
|
||||||
|
{
|
||||||
|
t.Sprite = null;
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Density = ResourceDensityAt(c);
|
||||||
|
|
||||||
|
int index;
|
||||||
|
var clear = FindClearSides(t.Type, c);
|
||||||
|
if (clear == ClearSides.None)
|
||||||
|
{
|
||||||
|
var sprites = D2kResourceLayer.Variants[t.Variant];
|
||||||
|
var frame = t.Density > t.Type.Info.MaxDensity / 2 ? 1 : 0;
|
||||||
|
t.Sprite = t.Type.Variants.First().Value[sprites[frame]];
|
||||||
|
}
|
||||||
|
else if (D2kResourceLayer.SpriteMap.TryGetValue(clear, out index))
|
||||||
|
t.Sprite = t.Type.Variants.First().Value[index];
|
||||||
|
else
|
||||||
|
t.Sprite = null;
|
||||||
|
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override string ChooseRandomVariant(ResourceType t)
|
||||||
|
{
|
||||||
|
return D2kResourceLayer.Variants.Keys.Random(Game.CosmeticRandom);
|
||||||
|
}
|
||||||
|
|
||||||
|
ClearSides FindClearSides(ResourceType t, CPos p)
|
||||||
|
{
|
||||||
|
var ret = ClearSides.None;
|
||||||
|
if (Tiles[p + new CVec(0, -1)].Type != t)
|
||||||
|
ret |= ClearSides.Top | ClearSides.TopLeft | ClearSides.TopRight;
|
||||||
|
|
||||||
|
if (Tiles[p + new CVec(-1, 0)].Type != t)
|
||||||
|
ret |= ClearSides.Left | ClearSides.TopLeft | ClearSides.BottomLeft;
|
||||||
|
|
||||||
|
if (Tiles[p + new CVec(1, 0)].Type != t)
|
||||||
|
ret |= ClearSides.Right | ClearSides.TopRight | ClearSides.BottomRight;
|
||||||
|
|
||||||
|
if (Tiles[p + new CVec(0, 1)].Type != t)
|
||||||
|
ret |= ClearSides.Bottom | ClearSides.BottomLeft | ClearSides.BottomRight;
|
||||||
|
|
||||||
|
if (Tiles[p + new CVec(-1, -1)].Type != t)
|
||||||
|
ret |= ClearSides.TopLeft;
|
||||||
|
|
||||||
|
if (Tiles[p + new CVec(1, -1)].Type != t)
|
||||||
|
ret |= ClearSides.TopRight;
|
||||||
|
|
||||||
|
if (Tiles[p + new CVec(-1, 1)].Type != t)
|
||||||
|
ret |= ClearSides.BottomLeft;
|
||||||
|
|
||||||
|
if (Tiles[p + new CVec(1, 1)].Type != t)
|
||||||
|
ret |= ClearSides.BottomRight;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -21,7 +21,7 @@ namespace OpenRA.Mods.D2k.Traits
|
|||||||
|
|
||||||
public class D2kResourceLayer : ResourceLayer
|
public class D2kResourceLayer : ResourceLayer
|
||||||
{
|
{
|
||||||
[Flags] enum ClearSides : byte
|
[Flags] public enum ClearSides : byte
|
||||||
{
|
{
|
||||||
None = 0x0,
|
None = 0x0,
|
||||||
Left = 0x1,
|
Left = 0x1,
|
||||||
@@ -37,7 +37,7 @@ namespace OpenRA.Mods.D2k.Traits
|
|||||||
All = 0xFF
|
All = 0xFF
|
||||||
}
|
}
|
||||||
|
|
||||||
static readonly Dictionary<string, int[]> Variants = new Dictionary<string, int[]>()
|
public static readonly Dictionary<string, int[]> Variants = new Dictionary<string, int[]>()
|
||||||
{
|
{
|
||||||
{ "cleara", new[] { 0, 50 } },
|
{ "cleara", new[] { 0, 50 } },
|
||||||
{ "clearb", new[] { 1, 51 } },
|
{ "clearb", new[] { 1, 51 } },
|
||||||
@@ -45,7 +45,7 @@ namespace OpenRA.Mods.D2k.Traits
|
|||||||
{ "cleard", new[] { 0, 53 } },
|
{ "cleard", new[] { 0, 53 } },
|
||||||
};
|
};
|
||||||
|
|
||||||
static readonly Dictionary<ClearSides, int> SpriteMap = new Dictionary<ClearSides, int>()
|
public static readonly Dictionary<ClearSides, int> SpriteMap = new Dictionary<ClearSides, int>()
|
||||||
{
|
{
|
||||||
{ ClearSides.None, 0 },
|
{ ClearSides.None, 0 },
|
||||||
{ ClearSides.Left | ClearSides.Top | ClearSides.TopLeft | ClearSides.TopRight | ClearSides.BottomLeft | ClearSides.BottomRight, 2 },
|
{ ClearSides.Left | ClearSides.Top | ClearSides.TopLeft | ClearSides.TopRight | ClearSides.BottomLeft | ClearSides.BottomRight, 2 },
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ using OpenRA.Traits;
|
|||||||
|
|
||||||
namespace OpenRA.Mods.RA.Traits
|
namespace OpenRA.Mods.RA.Traits
|
||||||
{
|
{
|
||||||
class MineInfo : ITraitInfo, IOccupySpaceInfo
|
class MineInfo : ITraitInfo
|
||||||
{
|
{
|
||||||
public readonly string[] CrushClasses = { };
|
public readonly string[] CrushClasses = { };
|
||||||
public readonly bool AvoidFriendly = true;
|
public readonly bool AvoidFriendly = true;
|
||||||
|
|||||||
385
mods/cnc/chrome/editor.yaml
Normal file
385
mods/cnc/chrome/editor.yaml
Normal file
@@ -0,0 +1,385 @@
|
|||||||
|
Container@NEW_MAP_BG:
|
||||||
|
Logic: NewMapLogic
|
||||||
|
X: (WINDOW_RIGHT - WIDTH)/2
|
||||||
|
Y: (WINDOW_BOTTOM - HEIGHT)/2
|
||||||
|
Width: 300
|
||||||
|
Height: 125
|
||||||
|
Children:
|
||||||
|
Label@TITLE:
|
||||||
|
Text:New Map
|
||||||
|
Width: PARENT_RIGHT
|
||||||
|
Y: 0-25
|
||||||
|
Font: BigBold
|
||||||
|
Contrast: true
|
||||||
|
Align: Center
|
||||||
|
Background@bg:
|
||||||
|
Width: PARENT_RIGHT
|
||||||
|
Height: 90
|
||||||
|
Background: panel-black
|
||||||
|
Children:
|
||||||
|
Label@TILESET_LABEL:
|
||||||
|
X: 25
|
||||||
|
Y: 14
|
||||||
|
Width: 95
|
||||||
|
Height: 25
|
||||||
|
Align: Right
|
||||||
|
Text: Tileset:
|
||||||
|
DropDownButton@TILESET:
|
||||||
|
X: 125
|
||||||
|
Y: 15
|
||||||
|
Width: 160
|
||||||
|
Height: 25
|
||||||
|
Label@WIDTH_LABEL:
|
||||||
|
X: 25
|
||||||
|
Y: 49
|
||||||
|
Width: 95
|
||||||
|
Height: 25
|
||||||
|
Align: Right
|
||||||
|
Text: Width:
|
||||||
|
TextField@WIDTH:
|
||||||
|
X: 125
|
||||||
|
Y: 50
|
||||||
|
Width: 50
|
||||||
|
MaxLength: 3
|
||||||
|
Height: 25
|
||||||
|
Text: 128
|
||||||
|
Label@HEIGHT_LABEL:
|
||||||
|
X: 135
|
||||||
|
Y: 49
|
||||||
|
Width: 95
|
||||||
|
Height: 25
|
||||||
|
Align: Right
|
||||||
|
Text: Height:
|
||||||
|
TextField@HEIGHT:
|
||||||
|
X: 235
|
||||||
|
Y: 50
|
||||||
|
Width: 50
|
||||||
|
MaxLength: 3
|
||||||
|
Height: 25
|
||||||
|
Text: 128
|
||||||
|
Button@CANCEL_BUTTON:
|
||||||
|
Y: 89
|
||||||
|
Width: 140
|
||||||
|
Height: 35
|
||||||
|
Text: Cancel
|
||||||
|
Font: Bold
|
||||||
|
Key: escape
|
||||||
|
Button@CREATE_BUTTON:
|
||||||
|
X: PARENT_RIGHT - WIDTH
|
||||||
|
Y: 89
|
||||||
|
Width: 140
|
||||||
|
Height: 35
|
||||||
|
Text: Create
|
||||||
|
Font: Bold
|
||||||
|
Key: return
|
||||||
|
|
||||||
|
|
||||||
|
Background@SAVE_MAP_PANEL:
|
||||||
|
Logic: SaveMapLogic
|
||||||
|
X: (WINDOW_RIGHT - WIDTH)/2
|
||||||
|
Y: (WINDOW_BOTTOM - HEIGHT)/2
|
||||||
|
Width: 345
|
||||||
|
Height: 264
|
||||||
|
Children:
|
||||||
|
Label@LABEL_TITLE:
|
||||||
|
Text: Save Map
|
||||||
|
Width: PARENT_RIGHT
|
||||||
|
Y: 0-25
|
||||||
|
Font: BigBold
|
||||||
|
Contrast: true
|
||||||
|
Align: Center
|
||||||
|
Background@SAVE_MAP_BACKGROUND:
|
||||||
|
Width: PARENT_RIGHT
|
||||||
|
Height: 230
|
||||||
|
Background: panel-black
|
||||||
|
Children:
|
||||||
|
Label@TITLE_LABEL:
|
||||||
|
X: 10
|
||||||
|
Y: 14
|
||||||
|
Width: 95
|
||||||
|
Height: 25
|
||||||
|
Align: Right
|
||||||
|
Text: Title:
|
||||||
|
TextField@TITLE:
|
||||||
|
X: 110
|
||||||
|
Y: 15
|
||||||
|
Width: 220
|
||||||
|
MaxLength: 50
|
||||||
|
Height: 25
|
||||||
|
Label@AUTHOR_LABEL:
|
||||||
|
X: 10
|
||||||
|
Y: 49
|
||||||
|
Width: 95
|
||||||
|
Height: 25
|
||||||
|
Align: Right
|
||||||
|
Text: Author:
|
||||||
|
TextField@AUTHOR:
|
||||||
|
X: 110
|
||||||
|
Y: 50
|
||||||
|
Width: 220
|
||||||
|
MaxLength: 50
|
||||||
|
Height: 25
|
||||||
|
Label@DESCRIPTION_LABEL:
|
||||||
|
X: 10
|
||||||
|
Y: 84
|
||||||
|
Width: 95
|
||||||
|
Height: 25
|
||||||
|
Align: Right
|
||||||
|
Text: Description:
|
||||||
|
TextField@DESCRIPTION:
|
||||||
|
X: 110
|
||||||
|
Y: 85
|
||||||
|
Width: 220
|
||||||
|
MaxLength: 50
|
||||||
|
Height: 25
|
||||||
|
Label@VISIBILITY_LABEL:
|
||||||
|
X: 10
|
||||||
|
Y: 119
|
||||||
|
Width: 95
|
||||||
|
Height: 25
|
||||||
|
Align: Right
|
||||||
|
Text: Visibility:
|
||||||
|
DropDownButton@VISIBILITY_DROPDOWN:
|
||||||
|
X: 110
|
||||||
|
Y: 120
|
||||||
|
Width: 220
|
||||||
|
Height: 25
|
||||||
|
Font: Regular
|
||||||
|
Label@DIRECTORY_LABEL:
|
||||||
|
X: 10
|
||||||
|
Y: 154
|
||||||
|
Width: 95
|
||||||
|
Height: 25
|
||||||
|
Align: Right
|
||||||
|
Text: Directory:
|
||||||
|
DropDownButton@DIRECTORY_DROPDOWN:
|
||||||
|
X: 110
|
||||||
|
Y: 155
|
||||||
|
Width: 220
|
||||||
|
Height: 25
|
||||||
|
Font: Regular
|
||||||
|
Label@FILENAME_LABEL:
|
||||||
|
X: 10
|
||||||
|
Y: 189
|
||||||
|
Width: 95
|
||||||
|
Height: 25
|
||||||
|
Align: Right
|
||||||
|
Text: Filename:
|
||||||
|
TextField@FILENAME:
|
||||||
|
X: 110
|
||||||
|
Y: 190
|
||||||
|
Width: 105
|
||||||
|
Height: 25
|
||||||
|
DropDownButton@TYPE_DROPDOWN:
|
||||||
|
X: 220
|
||||||
|
Y: 190
|
||||||
|
Width: 110
|
||||||
|
Height: 25
|
||||||
|
Font: Regular
|
||||||
|
Button@BACK_BUTTON:
|
||||||
|
Y: PARENT_BOTTOM - 35
|
||||||
|
Width: 140
|
||||||
|
Height: 35
|
||||||
|
Text: Cancel
|
||||||
|
Font: Bold
|
||||||
|
Key: escape
|
||||||
|
Button@SAVE_BUTTON:
|
||||||
|
X: PARENT_RIGHT - 140
|
||||||
|
Y: PARENT_BOTTOM - 35
|
||||||
|
Width: 140
|
||||||
|
Height: 35
|
||||||
|
Text: Save
|
||||||
|
Font: Bold
|
||||||
|
|
||||||
|
Container@EDITOR_ROOT:
|
||||||
|
Logic: LoadMapEditorLogic
|
||||||
|
Children:
|
||||||
|
Container@WORLD_ROOT:
|
||||||
|
Container@MENU_ROOT:
|
||||||
|
TooltipContainer@TOOLTIP_CONTAINER:
|
||||||
|
|
||||||
|
Container@EDITOR_WORLD_ROOT:
|
||||||
|
Logic: LoadIngamePerfLogic, MapEditorLogic
|
||||||
|
Children:
|
||||||
|
Container@PERF_ROOT:
|
||||||
|
ViewportController:
|
||||||
|
Width: WINDOW_RIGHT
|
||||||
|
Height: WINDOW_BOTTOM
|
||||||
|
EditorViewportController@MAP_EDITOR:
|
||||||
|
Width: WINDOW_RIGHT
|
||||||
|
Height: WINDOW_BOTTOM
|
||||||
|
TooltipContainer: TOOLTIP_CONTAINER
|
||||||
|
TooltipTemplate: SIMPLE_TOOLTIP
|
||||||
|
Children:
|
||||||
|
TerrainTemplatePreview@DRAG_TILE_PREVIEW:
|
||||||
|
Visible: false
|
||||||
|
Sprite@DRAG_LAYER_PREVIEW:
|
||||||
|
Visible: false
|
||||||
|
ActorPreview@DRAG_ACTOR_PREVIEW:
|
||||||
|
Visible: false
|
||||||
|
Background@RADAR_BG:
|
||||||
|
X: WINDOW_RIGHT-255
|
||||||
|
Y: 5
|
||||||
|
Width: 250
|
||||||
|
Height: 250
|
||||||
|
Background: panel-gray
|
||||||
|
Children:
|
||||||
|
Radar@INGAME_RADAR:
|
||||||
|
X: 1
|
||||||
|
Y: 1
|
||||||
|
Width: PARENT_RIGHT-2
|
||||||
|
Height: PARENT_BOTTOM-2
|
||||||
|
MenuButton@OPTIONS_BUTTON:
|
||||||
|
Logic: MenuButtonsChromeLogic
|
||||||
|
Key: escape
|
||||||
|
X: WINDOW_RIGHT-254-WIDTH
|
||||||
|
Y: 5
|
||||||
|
Width: 30
|
||||||
|
Height: 25
|
||||||
|
TooltipText: Menu
|
||||||
|
TooltipContainer: TOOLTIP_CONTAINER
|
||||||
|
Children:
|
||||||
|
Image:
|
||||||
|
X: 7
|
||||||
|
Y: 5
|
||||||
|
ImageCollection: order-icons
|
||||||
|
ImageName: options
|
||||||
|
Container@TILE_WIDGETS:
|
||||||
|
Logic: TileSelectorLogic
|
||||||
|
X: WINDOW_RIGHT-255
|
||||||
|
Y: 278
|
||||||
|
Width: 250
|
||||||
|
Height: 324
|
||||||
|
ClickThrough: false
|
||||||
|
Children:
|
||||||
|
Container@TILES_BG:
|
||||||
|
Width: PARENT_RIGHT
|
||||||
|
Height: PARENT_BOTTOM
|
||||||
|
Children:
|
||||||
|
DropDownButton@TILE_CATEGORY:
|
||||||
|
Width: PARENT_RIGHT
|
||||||
|
Height: 25
|
||||||
|
Font: Bold
|
||||||
|
ScrollPanel@TILETEMPLATE_LIST:
|
||||||
|
Y: 24
|
||||||
|
Width: PARENT_RIGHT
|
||||||
|
Height: PARENT_BOTTOM - 24
|
||||||
|
ItemSpacing: 4
|
||||||
|
Children:
|
||||||
|
ScrollItem@TILEPREVIEW_TEMPLATE:
|
||||||
|
Visible: false
|
||||||
|
Width: PARENT_RIGHT - 35
|
||||||
|
TooltipContainer: TOOLTIP_CONTAINER
|
||||||
|
Children:
|
||||||
|
TerrainTemplatePreview@TILE_PREVIEW:
|
||||||
|
X: 4
|
||||||
|
Y: 4
|
||||||
|
Container@LAYER_WIDGETS:
|
||||||
|
Logic: LayerSelectorLogic
|
||||||
|
X: WINDOW_RIGHT-255
|
||||||
|
Y: 278
|
||||||
|
Width: 250
|
||||||
|
Height: 324
|
||||||
|
ClickThrough: false
|
||||||
|
Children:
|
||||||
|
Container@LAYERS_BG:
|
||||||
|
Width: PARENT_RIGHT
|
||||||
|
Height: PARENT_BOTTOM
|
||||||
|
Children:
|
||||||
|
ScrollPanel@LAYERTEMPLATE_LIST:
|
||||||
|
Width: PARENT_RIGHT
|
||||||
|
Height: PARENT_BOTTOM
|
||||||
|
ItemSpacing: 4
|
||||||
|
Children:
|
||||||
|
ScrollItem@LAYERPREVIEW_TEMPLATE:
|
||||||
|
Visible: false
|
||||||
|
IgnoreChildMouseOver: true
|
||||||
|
TooltipContainer: TOOLTIP_CONTAINER
|
||||||
|
Children:
|
||||||
|
Sprite@LAYER_PREVIEW:
|
||||||
|
X: 4
|
||||||
|
Y: 4
|
||||||
|
Visible: false
|
||||||
|
Container@ACTOR_WIDGETS:
|
||||||
|
Logic: ActorSelectorLogic
|
||||||
|
X: WINDOW_RIGHT-255
|
||||||
|
Y: 278
|
||||||
|
Width: 250
|
||||||
|
Height: 324
|
||||||
|
ClickThrough: false
|
||||||
|
Children:
|
||||||
|
Container@ACTORS_BG:
|
||||||
|
Width: PARENT_RIGHT
|
||||||
|
Height: PARENT_BOTTOM
|
||||||
|
Children:
|
||||||
|
DropDownButton@OWNERS_DROPDOWN:
|
||||||
|
Width: PARENT_RIGHT
|
||||||
|
Height: 25
|
||||||
|
Font: Bold
|
||||||
|
ScrollPanel@ACTORTEMPLATE_LIST:
|
||||||
|
Y: 24
|
||||||
|
Width: PARENT_RIGHT
|
||||||
|
Height: PARENT_BOTTOM - 24
|
||||||
|
ItemSpacing: 4
|
||||||
|
Children:
|
||||||
|
ScrollItem@ACTORPREVIEW_TEMPLATE:
|
||||||
|
Visible: false
|
||||||
|
Width: PARENT_RIGHT - 35
|
||||||
|
TooltipContainer: TOOLTIP_CONTAINER
|
||||||
|
IgnoreChildMouseOver: true
|
||||||
|
Children:
|
||||||
|
ActorPreview@ACTOR_PREVIEW:
|
||||||
|
X: 4
|
||||||
|
Y: 4
|
||||||
|
Visible: true
|
||||||
|
Container@MAP_EDITOR_TAB_CONTAINER:
|
||||||
|
Logic: MapEditorTabsLogic
|
||||||
|
X: WINDOW_RIGHT-255
|
||||||
|
Y: 254
|
||||||
|
Width: 250
|
||||||
|
Height: 25
|
||||||
|
ClickThrough: false
|
||||||
|
Children:
|
||||||
|
Button@TILES_TAB:
|
||||||
|
Width: 81
|
||||||
|
Height: 25
|
||||||
|
Text: Tiles
|
||||||
|
Font: Bold
|
||||||
|
Button@OVERLAYS_TAB:
|
||||||
|
X: 80
|
||||||
|
Width: 90
|
||||||
|
Height: 25
|
||||||
|
Text: Overlays
|
||||||
|
Font: Bold
|
||||||
|
Button@ACTORS_TAB:
|
||||||
|
X: 169
|
||||||
|
Width: 81
|
||||||
|
Height: 25
|
||||||
|
Text: Actors
|
||||||
|
Font: Bold
|
||||||
|
Button@GRID_BUTTON:
|
||||||
|
X: WINDOW_RIGHT - 420
|
||||||
|
Y: 5
|
||||||
|
Width: 100
|
||||||
|
Height: 25
|
||||||
|
Text: Grid
|
||||||
|
Font: Bold
|
||||||
|
Key: f1
|
||||||
|
TooltipTemplate: BUTTON_TOOLTIP
|
||||||
|
TooltipText: Toggle the terrain grid
|
||||||
|
TooltipContainer: TOOLTIP_CONTAINER
|
||||||
|
Label@ZOOM_LABEL:
|
||||||
|
X: WINDOW_RIGHT - 500 - 55
|
||||||
|
Y: 5
|
||||||
|
Width: 50
|
||||||
|
Height: 25
|
||||||
|
Text: Zoom:
|
||||||
|
Align: Right
|
||||||
|
Font: Bold
|
||||||
|
Contrast: true
|
||||||
|
DropDownButton@ZOOM_BUTTON:
|
||||||
|
X: WINDOW_RIGHT - 500
|
||||||
|
Y: 5
|
||||||
|
Width: 70
|
||||||
|
Height: 25
|
||||||
|
Font: Bold
|
||||||
@@ -33,12 +33,24 @@ Container@INGAME_MENU:
|
|||||||
Width: 140
|
Width: 140
|
||||||
Height: 35
|
Height: 35
|
||||||
Text: Abort Mission
|
Text: Abort Mission
|
||||||
|
Button@EXIT_EDITOR:
|
||||||
|
X: 0
|
||||||
|
Y: 0
|
||||||
|
Width: 140
|
||||||
|
Height: 35
|
||||||
|
Text: Exit Map Editor
|
||||||
Button@SURRENDER:
|
Button@SURRENDER:
|
||||||
X: 150
|
X: 150
|
||||||
Y: 0
|
Y: 0
|
||||||
Width: 140
|
Width: 140
|
||||||
Height: 35
|
Height: 35
|
||||||
Text: Surrender
|
Text: Surrender
|
||||||
|
Button@SAVE_MAP:
|
||||||
|
X: 150
|
||||||
|
Y: 0
|
||||||
|
Width: 140
|
||||||
|
Height: 35
|
||||||
|
Text: Save Map
|
||||||
Button@MUSIC:
|
Button@MUSIC:
|
||||||
X: 300
|
X: 300
|
||||||
Y: 0
|
Y: 0
|
||||||
|
|||||||
@@ -165,14 +165,21 @@ Container@MENU_BACKGROUND:
|
|||||||
Width: 140
|
Width: 140
|
||||||
Height: 35
|
Height: 35
|
||||||
Text: Music
|
Text: Music
|
||||||
Button@ASSETBROWSER_BUTTON:
|
Button@MAP_EDITOR_BUTTON:
|
||||||
X: 300
|
X: 300
|
||||||
Y: 0
|
Y: 0
|
||||||
Width: 140
|
Width: 140
|
||||||
Height: 35
|
Height: 35
|
||||||
|
Text: Map Editor
|
||||||
|
Font: Bold
|
||||||
|
Button@ASSETBROWSER_BUTTON:
|
||||||
|
X: 450
|
||||||
|
Y: 0
|
||||||
|
Width: 140
|
||||||
|
Height: 35
|
||||||
Text: Asset Browser
|
Text: Asset Browser
|
||||||
Button@CREDITS_BUTTON:
|
Button@CREDITS_BUTTON:
|
||||||
X: 450
|
X: 600
|
||||||
Y: 0
|
Y: 0
|
||||||
Width: 140
|
Width: 140
|
||||||
Height: 35
|
Height: 35
|
||||||
@@ -184,6 +191,41 @@ Container@MENU_BACKGROUND:
|
|||||||
Width: 140
|
Width: 140
|
||||||
Height: 35
|
Height: 35
|
||||||
Text: Back
|
Text: Back
|
||||||
|
Background@MAP_EDITOR_MENU:
|
||||||
|
Width: PARENT_RIGHT
|
||||||
|
Visible: False
|
||||||
|
Children:
|
||||||
|
Label@MAP_EDITOR_MENU_TITLE:
|
||||||
|
X: 0
|
||||||
|
Y: 0-30
|
||||||
|
Width: PARENT_RIGHT
|
||||||
|
Height: 20
|
||||||
|
Text: Map Editor
|
||||||
|
Align: Center
|
||||||
|
Font: Bold
|
||||||
|
Contrast: True
|
||||||
|
Button@NEW_MAP_BUTTON:
|
||||||
|
X: 0
|
||||||
|
Y: 0
|
||||||
|
Width: 140
|
||||||
|
Height: 35
|
||||||
|
Text: New Map
|
||||||
|
Font: Bold
|
||||||
|
Button@LOAD_MAP_BUTTON:
|
||||||
|
X: 150
|
||||||
|
Y: 0
|
||||||
|
Width: 140
|
||||||
|
Height: 35
|
||||||
|
Text: Load Map
|
||||||
|
Font: Bold
|
||||||
|
Button@BACK_BUTTON:
|
||||||
|
X: 300
|
||||||
|
Y: 0
|
||||||
|
Width: 140
|
||||||
|
Height: 35
|
||||||
|
Text: Back
|
||||||
|
Font: Bold
|
||||||
|
Key: escape
|
||||||
Container@NEWS_BG:
|
Container@NEWS_BG:
|
||||||
Children:
|
Children:
|
||||||
DropDownButton@NEWS_BUTTON:
|
DropDownButton@NEWS_BUTTON:
|
||||||
|
|||||||
@@ -120,6 +120,7 @@ ChromeLayout:
|
|||||||
./mods/cnc/chrome/tooltips.yaml
|
./mods/cnc/chrome/tooltips.yaml
|
||||||
./mods/cnc/chrome/assetbrowser.yaml
|
./mods/cnc/chrome/assetbrowser.yaml
|
||||||
./mods/cnc/chrome/missionbrowser.yaml
|
./mods/cnc/chrome/missionbrowser.yaml
|
||||||
|
./mods/cnc/chrome/editor.yaml
|
||||||
|
|
||||||
Voices:
|
Voices:
|
||||||
./mods/cnc/audio/voices.yaml
|
./mods/cnc/audio/voices.yaml
|
||||||
|
|||||||
@@ -1,17 +1,8 @@
|
|||||||
World:
|
^BaseWorld:
|
||||||
Inherits: ^Palettes
|
Inherits: ^Palettes
|
||||||
ChatCommands:
|
|
||||||
DevCommands:
|
|
||||||
PlayerCommands:
|
|
||||||
HelpCommand:
|
|
||||||
ScreenMap:
|
ScreenMap:
|
||||||
ActorMap:
|
ActorMap:
|
||||||
LoadWidgetAtGameStart:
|
TerrainGeometryOverlay:
|
||||||
ShellmapRoot: MENU_BACKGROUND
|
|
||||||
ScreenShaker:
|
|
||||||
BuildingInfluence:
|
|
||||||
BridgeLayer:
|
|
||||||
Bridges: bridge1, bridge2, bridge3, bridge4
|
|
||||||
ShroudRenderer:
|
ShroudRenderer:
|
||||||
ShroudVariants: typea, typeb, typec, typed
|
ShroudVariants: typea, typeb, typec, typed
|
||||||
FogVariants: typea, typeb, typec, typed
|
FogVariants: typea, typeb, typec, typed
|
||||||
@@ -30,18 +21,6 @@ World:
|
|||||||
Name: Nod
|
Name: Nod
|
||||||
Race: nod
|
Race: nod
|
||||||
Description: Brotherhood of Nod\nThe Brotherhood is a religious cult centered around their leader Kane\nand the alien substance Tiberium. They utilize stealth technology\nand guerilla tactics to defeat those who oppose them.
|
Description: Brotherhood of Nod\nThe Brotherhood is a religious cult centered around their leader Kane\nand the alien substance Tiberium. They utilize stealth technology\nand guerilla tactics to defeat those who oppose them.
|
||||||
ProductionQueueFromSelection:
|
|
||||||
ProductionTabsWidget: PRODUCTION_TABS
|
|
||||||
DomainIndex:
|
|
||||||
SmudgeLayer@SCORCH:
|
|
||||||
Type: Scorch
|
|
||||||
Sequence: scorches
|
|
||||||
SmokePercentage: 50
|
|
||||||
SmudgeLayer@CRATER:
|
|
||||||
Type: Crater
|
|
||||||
Sequence: craters
|
|
||||||
ResourceLayer:
|
|
||||||
ResourceClaimLayer:
|
|
||||||
ResourceType@green-tib:
|
ResourceType@green-tib:
|
||||||
ResourceType: 1
|
ResourceType: 1
|
||||||
Palette: staticterrain
|
Palette: staticterrain
|
||||||
@@ -66,8 +45,33 @@ World:
|
|||||||
PipColor: Blue
|
PipColor: Blue
|
||||||
AllowedTerrainTypes: Clear,Road
|
AllowedTerrainTypes: Clear,Road
|
||||||
AllowUnderActors: true
|
AllowUnderActors: true
|
||||||
|
LoadWidgetAtGameStart:
|
||||||
|
ShellmapRoot: MENU_BACKGROUND
|
||||||
|
|
||||||
|
World:
|
||||||
|
Inherits: ^BaseWorld
|
||||||
|
ChatCommands:
|
||||||
|
DevCommands:
|
||||||
|
PlayerCommands:
|
||||||
|
HelpCommand:
|
||||||
|
ScreenShaker:
|
||||||
|
NukePaletteEffect:
|
||||||
|
BuildingInfluence:
|
||||||
|
BridgeLayer:
|
||||||
|
Bridges: bridge1, bridge2, bridge3, bridge4
|
||||||
|
ProductionQueueFromSelection:
|
||||||
|
ProductionTabsWidget: PRODUCTION_TABS
|
||||||
|
DomainIndex:
|
||||||
|
SmudgeLayer@SCORCH:
|
||||||
|
Type: Scorch
|
||||||
|
Sequence: scorches
|
||||||
|
SmokePercentage: 50
|
||||||
|
SmudgeLayer@CRATER:
|
||||||
|
Type: Crater
|
||||||
|
Sequence: craters
|
||||||
|
ResourceLayer:
|
||||||
|
ResourceClaimLayer:
|
||||||
PathfinderDebugOverlay:
|
PathfinderDebugOverlay:
|
||||||
TerrainGeometryOverlay:
|
|
||||||
SpawnMapActors:
|
SpawnMapActors:
|
||||||
MPStartLocations:
|
MPStartLocations:
|
||||||
CreateMPPlayers:
|
CreateMPPlayers:
|
||||||
@@ -143,3 +147,7 @@ World:
|
|||||||
PanelName: SKIRMISH_STATS
|
PanelName: SKIRMISH_STATS
|
||||||
RadarPings:
|
RadarPings:
|
||||||
|
|
||||||
|
EditorWorld:
|
||||||
|
Inherits: ^BaseWorld
|
||||||
|
EditorActorLayer:
|
||||||
|
EditorResourceLayer:
|
||||||
|
|||||||
@@ -53,6 +53,13 @@ Container@INGAME_MENU:
|
|||||||
Height: 30
|
Height: 30
|
||||||
Text: Surrender
|
Text: Surrender
|
||||||
Font: Bold
|
Font: Bold
|
||||||
|
Button@SAVE_MAP:
|
||||||
|
X: (PARENT_RIGHT - WIDTH)/2
|
||||||
|
Y: 180
|
||||||
|
Width: 140
|
||||||
|
Height: 30
|
||||||
|
Text: Save Map
|
||||||
|
Font: Bold
|
||||||
Button@ABORT_MISSION:
|
Button@ABORT_MISSION:
|
||||||
X: (PARENT_RIGHT - WIDTH)/2
|
X: (PARENT_RIGHT - WIDTH)/2
|
||||||
Y: 220
|
Y: 220
|
||||||
@@ -60,3 +67,10 @@ Container@INGAME_MENU:
|
|||||||
Height: 30
|
Height: 30
|
||||||
Text: Abort Mission
|
Text: Abort Mission
|
||||||
Font: Bold
|
Font: Bold
|
||||||
|
Button@EXIT_EDITOR:
|
||||||
|
X: (PARENT_RIGHT - WIDTH)/2
|
||||||
|
Y: 220
|
||||||
|
Width: 140
|
||||||
|
Height: 30
|
||||||
|
Text: Exit Map Editor
|
||||||
|
Font: Bold
|
||||||
|
|||||||
@@ -127,16 +127,23 @@ Container@MAINMENU:
|
|||||||
Height: 30
|
Height: 30
|
||||||
Text: Music
|
Text: Music
|
||||||
Font: Bold
|
Font: Bold
|
||||||
Button@ASSETBROWSER_BUTTON:
|
Button@MAP_EDITOR_BUTTON:
|
||||||
X: PARENT_RIGHT/2-WIDTH/2
|
X: PARENT_RIGHT/2-WIDTH/2
|
||||||
Y: 140
|
Y: 140
|
||||||
Width: 140
|
Width: 140
|
||||||
Height: 30
|
Height: 30
|
||||||
|
Text: Map Editor
|
||||||
|
Font: Bold
|
||||||
|
Button@ASSETBROWSER_BUTTON:
|
||||||
|
X: PARENT_RIGHT/2-WIDTH/2
|
||||||
|
Y: 180
|
||||||
|
Width: 140
|
||||||
|
Height: 30
|
||||||
Text: Asset Browser
|
Text: Asset Browser
|
||||||
Font: Bold
|
Font: Bold
|
||||||
Button@CREDITS_BUTTON:
|
Button@CREDITS_BUTTON:
|
||||||
X: PARENT_RIGHT/2-WIDTH/2
|
X: PARENT_RIGHT/2-WIDTH/2
|
||||||
Y: 180
|
Y: 220
|
||||||
Width: 140
|
Width: 140
|
||||||
Height: 30
|
Height: 30
|
||||||
Text: Credits
|
Text: Credits
|
||||||
@@ -149,6 +156,40 @@ Container@MAINMENU:
|
|||||||
Height: 30
|
Height: 30
|
||||||
Text: Back
|
Text: Back
|
||||||
Font: Bold
|
Font: Bold
|
||||||
|
Background@MAP_EDITOR_MENU:
|
||||||
|
Width: PARENT_RIGHT
|
||||||
|
Height: PARENT_BOTTOM
|
||||||
|
Children:
|
||||||
|
Label@MAP_EDITOR_MENU_TITLE:
|
||||||
|
X: 0
|
||||||
|
Y: 20
|
||||||
|
Width: 200
|
||||||
|
Height: 30
|
||||||
|
Text: Map Editor
|
||||||
|
Align: Center
|
||||||
|
Font: Bold
|
||||||
|
Button@NEW_MAP_BUTTON:
|
||||||
|
X: PARENT_RIGHT/2-WIDTH/2
|
||||||
|
Y: 60
|
||||||
|
Width: 140
|
||||||
|
Height: 30
|
||||||
|
Text: New Map
|
||||||
|
Font: Bold
|
||||||
|
Button@LOAD_MAP_BUTTON:
|
||||||
|
X: PARENT_RIGHT/2-WIDTH/2
|
||||||
|
Y: 100
|
||||||
|
Width: 140
|
||||||
|
Height: 30
|
||||||
|
Text: Load Map
|
||||||
|
Font: Bold
|
||||||
|
Button@BACK_BUTTON:
|
||||||
|
X: PARENT_RIGHT/2-WIDTH/2
|
||||||
|
Key: escape
|
||||||
|
Y: 260
|
||||||
|
Width: 140
|
||||||
|
Height: 30
|
||||||
|
Text: Back
|
||||||
|
Font: Bold
|
||||||
Background@NEWS_BG:
|
Background@NEWS_BG:
|
||||||
X: (WINDOW_RIGHT - WIDTH)/2
|
X: (WINDOW_RIGHT - WIDTH)/2
|
||||||
Y: 35
|
Y: 35
|
||||||
|
|||||||
@@ -100,6 +100,7 @@ ChromeLayout:
|
|||||||
./mods/ra/chrome/assetbrowser.yaml
|
./mods/ra/chrome/assetbrowser.yaml
|
||||||
./mods/ra/chrome/missionbrowser.yaml
|
./mods/ra/chrome/missionbrowser.yaml
|
||||||
./mods/ra/chrome/confirmation-dialogs.yaml
|
./mods/ra/chrome/confirmation-dialogs.yaml
|
||||||
|
./mods/ra/chrome/editor.yaml
|
||||||
|
|
||||||
Weapons:
|
Weapons:
|
||||||
./mods/d2k/weapons.yaml
|
./mods/d2k/weapons.yaml
|
||||||
|
|||||||
@@ -76,4 +76,5 @@ sietch:
|
|||||||
Power:
|
Power:
|
||||||
Amount: 0
|
Amount: 0
|
||||||
ProvidesPrerequisite@buildingname:
|
ProvidesPrerequisite@buildingname:
|
||||||
|
-WithCrumbleOverlay:
|
||||||
|
|
||||||
|
|||||||
@@ -1,23 +1,8 @@
|
|||||||
World:
|
^BaseWorld:
|
||||||
Inherits: ^Palettes
|
Inherits: ^Palettes
|
||||||
ChatCommands:
|
|
||||||
DevCommands:
|
|
||||||
PlayerCommands:
|
|
||||||
HelpCommand:
|
|
||||||
ScreenMap:
|
ScreenMap:
|
||||||
ActorMap:
|
ActorMap:
|
||||||
LoadWidgetAtGameStart:
|
TerrainGeometryOverlay:
|
||||||
ScreenShaker:
|
|
||||||
BuildingInfluence:
|
|
||||||
ProductionQueueFromSelection:
|
|
||||||
ProductionPaletteWidget: PRODUCTION_PALETTE
|
|
||||||
WormManager:
|
|
||||||
CrateSpawner:
|
|
||||||
Minimum: 0
|
|
||||||
Maximum: 2
|
|
||||||
SpawnInterval: 60
|
|
||||||
WaterChance: 0
|
|
||||||
ValidGround: Sand, Dune, Rock
|
|
||||||
ShroudRenderer:
|
ShroudRenderer:
|
||||||
ShroudVariants: typea, typeb, typec, typed
|
ShroudVariants: typea, typeb, typec, typed
|
||||||
FogVariants: typea, typeb, typec, typed
|
FogVariants: typea, typeb, typec, typed
|
||||||
@@ -46,12 +31,6 @@ World:
|
|||||||
Name: Corrino
|
Name: Corrino
|
||||||
Race: corrino
|
Race: corrino
|
||||||
Selectable: false
|
Selectable: false
|
||||||
DomainIndex:
|
|
||||||
PathfinderDebugOverlay:
|
|
||||||
BuildableTerrainLayer:
|
|
||||||
D2kResourceLayer:
|
|
||||||
TerrainGeometryOverlay:
|
|
||||||
ResourceClaimLayer:
|
|
||||||
ResourceType@Spice:
|
ResourceType@Spice:
|
||||||
ResourceType: 1
|
ResourceType: 1
|
||||||
Palette: d2k
|
Palette: d2k
|
||||||
@@ -64,6 +43,30 @@ World:
|
|||||||
PipColor: green
|
PipColor: green
|
||||||
AllowedTerrainTypes: Sand
|
AllowedTerrainTypes: Sand
|
||||||
AllowUnderActors: true
|
AllowUnderActors: true
|
||||||
|
LoadWidgetAtGameStart:
|
||||||
|
|
||||||
|
World:
|
||||||
|
Inherits: ^BaseWorld
|
||||||
|
ChatCommands:
|
||||||
|
DevCommands:
|
||||||
|
PlayerCommands:
|
||||||
|
HelpCommand:
|
||||||
|
ScreenShaker:
|
||||||
|
BuildingInfluence:
|
||||||
|
ProductionQueueFromSelection:
|
||||||
|
ProductionPaletteWidget: PRODUCTION_PALETTE
|
||||||
|
WormManager:
|
||||||
|
CrateSpawner:
|
||||||
|
Minimum: 0
|
||||||
|
Maximum: 2
|
||||||
|
SpawnInterval: 60
|
||||||
|
WaterChance: 0
|
||||||
|
ValidGround: Sand, Dune, Rock
|
||||||
|
DomainIndex:
|
||||||
|
PathfinderDebugOverlay:
|
||||||
|
BuildableTerrainLayer:
|
||||||
|
D2kResourceLayer:
|
||||||
|
ResourceClaimLayer:
|
||||||
SmudgeLayer@Rock:
|
SmudgeLayer@Rock:
|
||||||
Type: RockCrater
|
Type: RockCrater
|
||||||
Sequence: rockcraters
|
Sequence: rockcraters
|
||||||
@@ -135,3 +138,8 @@ World:
|
|||||||
RadarPings:
|
RadarPings:
|
||||||
ObjectivesPanel:
|
ObjectivesPanel:
|
||||||
PanelName: SKIRMISH_STATS
|
PanelName: SKIRMISH_STATS
|
||||||
|
|
||||||
|
EditorWorld:
|
||||||
|
Inherits: ^BaseWorld
|
||||||
|
EditorActorLayer:
|
||||||
|
D2kEditorResourceLayer:
|
||||||
|
|||||||
372
mods/ra/chrome/editor.yaml
Normal file
372
mods/ra/chrome/editor.yaml
Normal file
@@ -0,0 +1,372 @@
|
|||||||
|
Background@NEW_MAP_BG:
|
||||||
|
Logic: NewMapLogic
|
||||||
|
X: (WINDOW_RIGHT - WIDTH)/2
|
||||||
|
Y: (WINDOW_BOTTOM - HEIGHT)/2
|
||||||
|
Width: 300
|
||||||
|
Height: 185
|
||||||
|
Children:
|
||||||
|
Label@LABEL_TITLE:
|
||||||
|
X: 0
|
||||||
|
Y: 20
|
||||||
|
Width: 300
|
||||||
|
Height: 25
|
||||||
|
Text: New Map
|
||||||
|
Align: Center
|
||||||
|
Font: Bold
|
||||||
|
Label@TILESET_LABEL:
|
||||||
|
X: 20
|
||||||
|
Y: 59
|
||||||
|
Width: 95
|
||||||
|
Height: 25
|
||||||
|
Align: Right
|
||||||
|
Text: Tileset:
|
||||||
|
DropDownButton@TILESET:
|
||||||
|
X: 120
|
||||||
|
Y: 60
|
||||||
|
Width: 160
|
||||||
|
Height: 25
|
||||||
|
Label@WIDTH_LABEL:
|
||||||
|
X: 20
|
||||||
|
Y: 94
|
||||||
|
Width: 95
|
||||||
|
Height: 25
|
||||||
|
Align: Right
|
||||||
|
Text: Width:
|
||||||
|
TextField@WIDTH:
|
||||||
|
X: 120
|
||||||
|
Y: 95
|
||||||
|
Width: 50
|
||||||
|
MaxLength: 3
|
||||||
|
Height: 25
|
||||||
|
Text: 128
|
||||||
|
Label@HEIGHT_LABEL:
|
||||||
|
X: 130
|
||||||
|
Y: 94
|
||||||
|
Width: 95
|
||||||
|
Height: 25
|
||||||
|
Align: Right
|
||||||
|
Text: Height:
|
||||||
|
TextField@HEIGHT:
|
||||||
|
X: 230
|
||||||
|
Y: 95
|
||||||
|
Width: 50
|
||||||
|
MaxLength: 3
|
||||||
|
Height: 25
|
||||||
|
Text: 128
|
||||||
|
Button@CREATE_BUTTON:
|
||||||
|
X: 30
|
||||||
|
Y: PARENT_BOTTOM - 45
|
||||||
|
Width: 120
|
||||||
|
Height: 25
|
||||||
|
Text: Create
|
||||||
|
Font: Bold
|
||||||
|
Key: return
|
||||||
|
Button@CANCEL_BUTTON:
|
||||||
|
X: 160
|
||||||
|
Y: PARENT_BOTTOM - 45
|
||||||
|
Width: 120
|
||||||
|
Height: 25
|
||||||
|
Text: Cancel
|
||||||
|
Font: Bold
|
||||||
|
Key: escape
|
||||||
|
|
||||||
|
Background@SAVE_MAP_PANEL:
|
||||||
|
Logic: SaveMapLogic
|
||||||
|
X: (WINDOW_RIGHT - WIDTH)/2
|
||||||
|
Y: (WINDOW_BOTTOM - HEIGHT)/2
|
||||||
|
Width: 350
|
||||||
|
Height: 335
|
||||||
|
Children:
|
||||||
|
Label@LABEL_TITLE:
|
||||||
|
X: (PARENT_RIGHT - WIDTH)/2
|
||||||
|
Y: 20
|
||||||
|
Width: 250
|
||||||
|
Height: 25
|
||||||
|
Text: Save Map
|
||||||
|
Align: Center
|
||||||
|
Font: Bold
|
||||||
|
Label@TITLE_LABEL:
|
||||||
|
X: 10
|
||||||
|
Y: 59
|
||||||
|
Width: 95
|
||||||
|
Height: 25
|
||||||
|
Align: Right
|
||||||
|
Text: Title:
|
||||||
|
TextField@TITLE:
|
||||||
|
X: 110
|
||||||
|
Y: 60
|
||||||
|
Width: 220
|
||||||
|
MaxLength: 50
|
||||||
|
Height: 25
|
||||||
|
Label@AUTHOR_LABEL:
|
||||||
|
X: 10
|
||||||
|
Y: 94
|
||||||
|
Width: 95
|
||||||
|
Height: 25
|
||||||
|
Align: Right
|
||||||
|
Text: Author:
|
||||||
|
TextField@AUTHOR:
|
||||||
|
X: 110
|
||||||
|
Y: 95
|
||||||
|
Width: 220
|
||||||
|
MaxLength: 50
|
||||||
|
Height: 25
|
||||||
|
Label@DESCRIPTION_LABEL:
|
||||||
|
X: 10
|
||||||
|
Y: 129
|
||||||
|
Width: 95
|
||||||
|
Height: 25
|
||||||
|
Align: Right
|
||||||
|
Text: Description:
|
||||||
|
TextField@DESCRIPTION:
|
||||||
|
X: 110
|
||||||
|
Y: 130
|
||||||
|
Width: 220
|
||||||
|
MaxLength: 50
|
||||||
|
Height: 25
|
||||||
|
Label@VISIBILITY_LABEL:
|
||||||
|
X: 10
|
||||||
|
Y: 164
|
||||||
|
Width: 95
|
||||||
|
Height: 25
|
||||||
|
Align: Right
|
||||||
|
Text: Visibility:
|
||||||
|
DropDownButton@VISIBILITY_DROPDOWN:
|
||||||
|
X: 110
|
||||||
|
Y: 165
|
||||||
|
Width: 220
|
||||||
|
Height: 25
|
||||||
|
Label@DIRECTORY_LABEL:
|
||||||
|
X: 10
|
||||||
|
Y: 199
|
||||||
|
Width: 95
|
||||||
|
Height: 25
|
||||||
|
Align: Right
|
||||||
|
Text: Directory:
|
||||||
|
DropDownButton@DIRECTORY_DROPDOWN:
|
||||||
|
X: 110
|
||||||
|
Y: 200
|
||||||
|
Width: 220
|
||||||
|
Height: 25
|
||||||
|
Label@FILENAME_LABEL:
|
||||||
|
X: 10
|
||||||
|
Y: 234
|
||||||
|
Width: 95
|
||||||
|
Height: 25
|
||||||
|
Align: Right
|
||||||
|
Text: Filename:
|
||||||
|
TextField@FILENAME:
|
||||||
|
X: 110
|
||||||
|
Y: 235
|
||||||
|
Width: 105
|
||||||
|
Height: 25
|
||||||
|
DropDownButton@TYPE_DROPDOWN:
|
||||||
|
X: 220
|
||||||
|
Y: 235
|
||||||
|
Width: 110
|
||||||
|
Height: 25
|
||||||
|
Button@SAVE_BUTTON:
|
||||||
|
X: 80
|
||||||
|
Y: PARENT_BOTTOM - 45
|
||||||
|
Width: 120
|
||||||
|
Height: 25
|
||||||
|
Text: Save
|
||||||
|
Font: Bold
|
||||||
|
Button@BACK_BUTTON:
|
||||||
|
X: 210
|
||||||
|
Y: PARENT_BOTTOM - 45
|
||||||
|
Width: 120
|
||||||
|
Height: 25
|
||||||
|
Text: Cancel
|
||||||
|
Font: Bold
|
||||||
|
Key: escape
|
||||||
|
|
||||||
|
Container@EDITOR_ROOT:
|
||||||
|
Logic: LoadMapEditorLogic
|
||||||
|
Children:
|
||||||
|
Container@WORLD_ROOT:
|
||||||
|
Container@MENU_ROOT:
|
||||||
|
TooltipContainer@TOOLTIP_CONTAINER:
|
||||||
|
|
||||||
|
Container@EDITOR_WORLD_ROOT:
|
||||||
|
Logic: LoadIngamePerfLogic, MapEditorLogic
|
||||||
|
Children:
|
||||||
|
Container@PERF_ROOT:
|
||||||
|
ViewportController:
|
||||||
|
X: 0
|
||||||
|
Y: 0
|
||||||
|
Width: WINDOW_RIGHT
|
||||||
|
Height: WINDOW_BOTTOM
|
||||||
|
TooltipContainer: TOOLTIP_CONTAINER
|
||||||
|
EditorViewportController@MAP_EDITOR:
|
||||||
|
Width: WINDOW_RIGHT
|
||||||
|
Height: WINDOW_BOTTOM
|
||||||
|
TooltipContainer: TOOLTIP_CONTAINER
|
||||||
|
TooltipTemplate: SIMPLE_TOOLTIP
|
||||||
|
Children:
|
||||||
|
ActorPreview@DRAG_ACTOR_PREVIEW:
|
||||||
|
Visible: false
|
||||||
|
TerrainTemplatePreview@DRAG_TILE_PREVIEW:
|
||||||
|
Visible: false
|
||||||
|
Sprite@DRAG_LAYER_PREVIEW:
|
||||||
|
Visible: false
|
||||||
|
Background@RADAR_BG:
|
||||||
|
X: WINDOW_RIGHT-255
|
||||||
|
Y: 5
|
||||||
|
Width: 250
|
||||||
|
Height: 250
|
||||||
|
Children:
|
||||||
|
Radar@INGAME_RADAR:
|
||||||
|
X: 10
|
||||||
|
Y: 10
|
||||||
|
Width: PARENT_RIGHT-19
|
||||||
|
Height: PARENT_BOTTOM-19
|
||||||
|
Container@TILE_WIDGETS:
|
||||||
|
Logic: TileSelectorLogic
|
||||||
|
Children:
|
||||||
|
Background@TILES_BG:
|
||||||
|
X: WINDOW_RIGHT-250
|
||||||
|
Y: 290
|
||||||
|
Width: 240
|
||||||
|
Height: 360
|
||||||
|
Children:
|
||||||
|
DropDownButton@TILE_CATEGORY:
|
||||||
|
X: 10
|
||||||
|
Y: 10
|
||||||
|
Width: 220
|
||||||
|
Height: 25
|
||||||
|
Font: Bold
|
||||||
|
ScrollPanel@TILETEMPLATE_LIST:
|
||||||
|
X: 10
|
||||||
|
Y: 35
|
||||||
|
Width: PARENT_RIGHT-20
|
||||||
|
Height: PARENT_BOTTOM-45
|
||||||
|
ItemSpacing: 4
|
||||||
|
Children:
|
||||||
|
ScrollItem@TILEPREVIEW_TEMPLATE:
|
||||||
|
Visible: false
|
||||||
|
Width: PARENT_RIGHT - 35
|
||||||
|
TooltipContainer: TOOLTIP_CONTAINER
|
||||||
|
Children:
|
||||||
|
TerrainTemplatePreview@TILE_PREVIEW:
|
||||||
|
X: 4
|
||||||
|
Y: 4
|
||||||
|
Container@LAYER_WIDGETS:
|
||||||
|
Visible: false
|
||||||
|
Logic: LayerSelectorLogic
|
||||||
|
Children:
|
||||||
|
Background@LAYERS_BG:
|
||||||
|
X: WINDOW_RIGHT-250
|
||||||
|
Y: 290
|
||||||
|
Width: 240
|
||||||
|
Height: 360
|
||||||
|
Children:
|
||||||
|
ScrollPanel@LAYERTEMPLATE_LIST:
|
||||||
|
X: 10
|
||||||
|
Y: 10
|
||||||
|
Width: PARENT_RIGHT-20
|
||||||
|
Height: PARENT_BOTTOM-20
|
||||||
|
ItemSpacing: 4
|
||||||
|
Children:
|
||||||
|
ScrollItem@LAYERPREVIEW_TEMPLATE:
|
||||||
|
Visible: false
|
||||||
|
IgnoreChildMouseOver: true
|
||||||
|
TooltipContainer: TOOLTIP_CONTAINER
|
||||||
|
Children:
|
||||||
|
Sprite@LAYER_PREVIEW:
|
||||||
|
X: 4
|
||||||
|
Y: 4
|
||||||
|
Visible: false
|
||||||
|
Container@ACTOR_WIDGETS:
|
||||||
|
Visible: false
|
||||||
|
Logic: ActorSelectorLogic
|
||||||
|
Children:
|
||||||
|
Background@ACTORS_BG:
|
||||||
|
X: WINDOW_RIGHT-250
|
||||||
|
Y: 290
|
||||||
|
Width: 240
|
||||||
|
Height: 360
|
||||||
|
Children:
|
||||||
|
DropDownButton@OWNERS_DROPDOWN:
|
||||||
|
X: 10
|
||||||
|
Y: 10
|
||||||
|
Width: 220
|
||||||
|
Height: 25
|
||||||
|
Font: Bold
|
||||||
|
ScrollPanel@ACTORTEMPLATE_LIST:
|
||||||
|
X: 10
|
||||||
|
Y: 35
|
||||||
|
Width: PARENT_RIGHT-20
|
||||||
|
Height: PARENT_BOTTOM-45
|
||||||
|
ItemSpacing: 4
|
||||||
|
Children:
|
||||||
|
ScrollItem@ACTORPREVIEW_TEMPLATE:
|
||||||
|
Visible: false
|
||||||
|
Width: PARENT_RIGHT - 35
|
||||||
|
TooltipContainer: TOOLTIP_CONTAINER
|
||||||
|
IgnoreChildMouseOver: true
|
||||||
|
Children:
|
||||||
|
ActorPreview@ACTOR_PREVIEW:
|
||||||
|
X: 4
|
||||||
|
Y: 4
|
||||||
|
Visible: true
|
||||||
|
Container@MAP_EDITOR_TAB_CONTAINER:
|
||||||
|
Logic: MapEditorTabsLogic
|
||||||
|
X: WINDOW_RIGHT-245
|
||||||
|
Y: 260
|
||||||
|
Width: 240
|
||||||
|
Height: 25
|
||||||
|
Children:
|
||||||
|
Button@TILES_TAB:
|
||||||
|
X: 0
|
||||||
|
Width: 70
|
||||||
|
Height: 25
|
||||||
|
Text: Tiles
|
||||||
|
Font: Bold
|
||||||
|
Button@OVERLAYS_TAB:
|
||||||
|
X: 70
|
||||||
|
Width: 90
|
||||||
|
Height: 25
|
||||||
|
Text: Overlays
|
||||||
|
Font: Bold
|
||||||
|
Button@ACTORS_TAB:
|
||||||
|
X: 160
|
||||||
|
Width: 70
|
||||||
|
Height: 25
|
||||||
|
Text: Actors
|
||||||
|
Font: Bold
|
||||||
|
MenuButton@OPTIONS_BUTTON:
|
||||||
|
Logic: MenuButtonsChromeLogic
|
||||||
|
MenuContainer: INGAME_MENU
|
||||||
|
HideIngameUI: true
|
||||||
|
Pause: true
|
||||||
|
Width: 160
|
||||||
|
Height: 25
|
||||||
|
Text: Menu
|
||||||
|
TooltipText: Menu
|
||||||
|
TooltipContainer: TOOLTIP_CONTAINER
|
||||||
|
Font: Bold
|
||||||
|
Key: escape
|
||||||
|
Button@GRID_BUTTON:
|
||||||
|
X: 180
|
||||||
|
Width: 160
|
||||||
|
Height: 25
|
||||||
|
Text: Grid
|
||||||
|
TooltipTemplate: BUTTON_TOOLTIP
|
||||||
|
TooltipText: Toggle the terrain grid
|
||||||
|
TooltipContainer: TOOLTIP_CONTAINER
|
||||||
|
Font: Bold
|
||||||
|
Key: f1
|
||||||
|
Label@ZOOM_LABEL:
|
||||||
|
X: 345
|
||||||
|
Width: 50
|
||||||
|
Height: 25
|
||||||
|
Text: Zoom:
|
||||||
|
Align: Right
|
||||||
|
Font: Bold
|
||||||
|
Contrast: true
|
||||||
|
DropDownButton@ZOOM_BUTTON:
|
||||||
|
X: 400
|
||||||
|
Width: 70
|
||||||
|
Height: 25
|
||||||
|
Font: Bold
|
||||||
@@ -66,6 +66,13 @@ Container@INGAME_MENU:
|
|||||||
Height: 30
|
Height: 30
|
||||||
Text: Surrender
|
Text: Surrender
|
||||||
Font: Bold
|
Font: Bold
|
||||||
|
Button@SAVE_MAP:
|
||||||
|
X: (PARENT_RIGHT - WIDTH)/2
|
||||||
|
Y: 180
|
||||||
|
Width: 140
|
||||||
|
Height: 30
|
||||||
|
Text: Save Map
|
||||||
|
Font: Bold
|
||||||
Button@ABORT_MISSION:
|
Button@ABORT_MISSION:
|
||||||
X: (PARENT_RIGHT - WIDTH)/2
|
X: (PARENT_RIGHT - WIDTH)/2
|
||||||
Y: 220
|
Y: 220
|
||||||
@@ -73,3 +80,10 @@ Container@INGAME_MENU:
|
|||||||
Height: 30
|
Height: 30
|
||||||
Text: Abort Mission
|
Text: Abort Mission
|
||||||
Font: Bold
|
Font: Bold
|
||||||
|
Button@EXIT_EDITOR:
|
||||||
|
X: (PARENT_RIGHT - WIDTH)/2
|
||||||
|
Y: 220
|
||||||
|
Width: 140
|
||||||
|
Height: 30
|
||||||
|
Text: Exit Map Editor
|
||||||
|
Font: Bold
|
||||||
|
|||||||
@@ -140,16 +140,23 @@ Container@MAINMENU:
|
|||||||
Height: 30
|
Height: 30
|
||||||
Text: Music
|
Text: Music
|
||||||
Font: Bold
|
Font: Bold
|
||||||
Button@ASSETBROWSER_BUTTON:
|
Button@MAP_EDITOR_BUTTON:
|
||||||
X: PARENT_RIGHT/2-WIDTH/2
|
X: PARENT_RIGHT/2-WIDTH/2
|
||||||
Y: 140
|
Y: 140
|
||||||
Width: 140
|
Width: 140
|
||||||
Height: 30
|
Height: 30
|
||||||
|
Text: Map Editor
|
||||||
|
Font: Bold
|
||||||
|
Button@ASSETBROWSER_BUTTON:
|
||||||
|
X: PARENT_RIGHT/2-WIDTH/2
|
||||||
|
Y: 180
|
||||||
|
Width: 140
|
||||||
|
Height: 30
|
||||||
Text: Asset Browser
|
Text: Asset Browser
|
||||||
Font: Bold
|
Font: Bold
|
||||||
Button@CREDITS_BUTTON:
|
Button@CREDITS_BUTTON:
|
||||||
X: PARENT_RIGHT/2-WIDTH/2
|
X: PARENT_RIGHT/2-WIDTH/2
|
||||||
Y: 180
|
Y: 220
|
||||||
Width: 140
|
Width: 140
|
||||||
Height: 30
|
Height: 30
|
||||||
Text: Credits
|
Text: Credits
|
||||||
@@ -162,6 +169,40 @@ Container@MAINMENU:
|
|||||||
Height: 30
|
Height: 30
|
||||||
Text: Back
|
Text: Back
|
||||||
Font: Bold
|
Font: Bold
|
||||||
|
Background@MAP_EDITOR_MENU:
|
||||||
|
Width: PARENT_RIGHT
|
||||||
|
Height: PARENT_BOTTOM
|
||||||
|
Children:
|
||||||
|
Label@MAP_EDITOR_MENU_TITLE:
|
||||||
|
X: 0
|
||||||
|
Y: 20
|
||||||
|
Width: 200
|
||||||
|
Height: 30
|
||||||
|
Text: Map Editor
|
||||||
|
Align: Center
|
||||||
|
Font: Bold
|
||||||
|
Button@NEW_MAP_BUTTON:
|
||||||
|
X: PARENT_RIGHT/2-WIDTH/2
|
||||||
|
Y: 60
|
||||||
|
Width: 140
|
||||||
|
Height: 30
|
||||||
|
Text: New Map
|
||||||
|
Font: Bold
|
||||||
|
Button@LOAD_MAP_BUTTON:
|
||||||
|
X: PARENT_RIGHT/2-WIDTH/2
|
||||||
|
Y: 100
|
||||||
|
Width: 140
|
||||||
|
Height: 30
|
||||||
|
Text: Load Map
|
||||||
|
Font: Bold
|
||||||
|
Button@BACK_BUTTON:
|
||||||
|
X: PARENT_RIGHT/2-WIDTH/2
|
||||||
|
Key: escape
|
||||||
|
Y: 260
|
||||||
|
Width: 140
|
||||||
|
Height: 30
|
||||||
|
Text: Back
|
||||||
|
Font: Bold
|
||||||
Container@PERFORMANCE_INFO:
|
Container@PERFORMANCE_INFO:
|
||||||
Logic: PerfDebugLogic
|
Logic: PerfDebugLogic
|
||||||
Children:
|
Children:
|
||||||
|
|||||||
@@ -114,6 +114,7 @@ ChromeLayout:
|
|||||||
./mods/ra/chrome/assetbrowser.yaml
|
./mods/ra/chrome/assetbrowser.yaml
|
||||||
./mods/ra/chrome/missionbrowser.yaml
|
./mods/ra/chrome/missionbrowser.yaml
|
||||||
./mods/ra/chrome/confirmation-dialogs.yaml
|
./mods/ra/chrome/confirmation-dialogs.yaml
|
||||||
|
./mods/ra/chrome/editor.yaml
|
||||||
|
|
||||||
Weapons:
|
Weapons:
|
||||||
./mods/ra/weapons/explosions.yaml
|
./mods/ra/weapons/explosions.yaml
|
||||||
|
|||||||
@@ -1,25 +1,9 @@
|
|||||||
World:
|
^BaseWorld:
|
||||||
Inherits: ^Palettes
|
Inherits: ^Palettes
|
||||||
ChatCommands:
|
|
||||||
DevCommands:
|
|
||||||
PlayerCommands:
|
|
||||||
HelpCommand:
|
|
||||||
ScreenMap:
|
|
||||||
ActorMap:
|
ActorMap:
|
||||||
|
ScreenMap:
|
||||||
|
TerrainGeometryOverlay:
|
||||||
LoadWidgetAtGameStart:
|
LoadWidgetAtGameStart:
|
||||||
ScreenShaker:
|
|
||||||
BuildingInfluence:
|
|
||||||
ProductionQueueFromSelection:
|
|
||||||
ProductionPaletteWidget: PRODUCTION_PALETTE
|
|
||||||
BridgeLayer:
|
|
||||||
Bridges: bridge1, bridge2, br1, br2, br3, sbridge1, sbridge2, sbridge3, sbridge4
|
|
||||||
CrateSpawner:
|
|
||||||
DeliveryAircraft: badr
|
|
||||||
QuantizedFacings: 16
|
|
||||||
Minimum: 1
|
|
||||||
Maximum: 3
|
|
||||||
SpawnInterval: 120
|
|
||||||
WaterChance: .2
|
|
||||||
ShroudRenderer:
|
ShroudRenderer:
|
||||||
FogVariants: shroud
|
FogVariants: shroud
|
||||||
Index: 255, 16, 32, 48, 64, 80, 96, 112, 128, 144, 160, 176, 192, 208, 224, 240, 20, 40, 56, 65, 97, 130, 148, 194, 24, 33, 66, 132, 28, 41, 67, 134, 1, 2, 4, 8, 3, 6, 12, 9, 7, 14, 13, 11, 5, 10, 15, 255
|
Index: 255, 16, 32, 48, 64, 80, 96, 112, 128, 144, 160, 176, 192, 208, 224, 240, 20, 40, 56, 65, 97, 130, 148, 194, 24, 33, 66, 132, 28, 41, 67, 134, 1, 2, 4, 8, 3, 6, 12, 9, 7, 14, 13, 11, 5, 10, 15, 255
|
||||||
@@ -77,16 +61,6 @@ World:
|
|||||||
RandomRaceMembers: russia, ukraine
|
RandomRaceMembers: russia, ukraine
|
||||||
Side: Random
|
Side: Random
|
||||||
Description: A random Soviet country.
|
Description: A random Soviet country.
|
||||||
DomainIndex:
|
|
||||||
SmudgeLayer@SCORCH:
|
|
||||||
Type: Scorch
|
|
||||||
Sequence: scorches
|
|
||||||
SmokePercentage: 50
|
|
||||||
SmudgeLayer@CRATER:
|
|
||||||
Type: Crater
|
|
||||||
Sequence: craters
|
|
||||||
ResourceLayer:
|
|
||||||
ResourceClaimLayer:
|
|
||||||
ResourceType@ore:
|
ResourceType@ore:
|
||||||
ResourceType: 1
|
ResourceType: 1
|
||||||
Palette: player
|
Palette: player
|
||||||
@@ -111,8 +85,37 @@ World:
|
|||||||
AllowedTerrainTypes: Clear,Road
|
AllowedTerrainTypes: Clear,Road
|
||||||
AllowUnderActors: true
|
AllowUnderActors: true
|
||||||
TerrainType: Gems
|
TerrainType: Gems
|
||||||
|
|
||||||
|
World:
|
||||||
|
Inherits: ^BaseWorld
|
||||||
|
ChatCommands:
|
||||||
|
DevCommands:
|
||||||
|
PlayerCommands:
|
||||||
|
HelpCommand:
|
||||||
|
ScreenShaker:
|
||||||
|
BuildingInfluence:
|
||||||
|
ProductionQueueFromSelection:
|
||||||
|
ProductionPaletteWidget: PRODUCTION_PALETTE
|
||||||
|
BridgeLayer:
|
||||||
|
Bridges: bridge1, bridge2, br1, br2, br3, sbridge1, sbridge2, sbridge3, sbridge4
|
||||||
|
CrateSpawner:
|
||||||
|
DeliveryAircraft: badr
|
||||||
|
QuantizedFacings: 16
|
||||||
|
Minimum: 1
|
||||||
|
Maximum: 3
|
||||||
|
SpawnInterval: 120
|
||||||
|
WaterChance: .2
|
||||||
|
DomainIndex:
|
||||||
|
SmudgeLayer@SCORCH:
|
||||||
|
Type: Scorch
|
||||||
|
Sequence: scorches
|
||||||
|
SmokePercentage: 50
|
||||||
|
SmudgeLayer@CRATER:
|
||||||
|
Type: Crater
|
||||||
|
Sequence: craters
|
||||||
|
ResourceLayer:
|
||||||
|
ResourceClaimLayer:
|
||||||
PathfinderDebugOverlay:
|
PathfinderDebugOverlay:
|
||||||
TerrainGeometryOverlay:
|
|
||||||
SpawnMapActors:
|
SpawnMapActors:
|
||||||
CreateMPPlayers:
|
CreateMPPlayers:
|
||||||
MPStartUnits@mcvonly:
|
MPStartUnits@mcvonly:
|
||||||
@@ -162,3 +165,7 @@ World:
|
|||||||
ObjectivesPanel:
|
ObjectivesPanel:
|
||||||
PanelName: SKIRMISH_STATS
|
PanelName: SKIRMISH_STATS
|
||||||
|
|
||||||
|
EditorWorld:
|
||||||
|
Inherits: ^BaseWorld
|
||||||
|
EditorActorLayer:
|
||||||
|
EditorResourceLayer:
|
||||||
|
|||||||
@@ -168,6 +168,7 @@ ChromeLayout:
|
|||||||
./mods/ra/chrome/assetbrowser.yaml
|
./mods/ra/chrome/assetbrowser.yaml
|
||||||
./mods/ra/chrome/missionbrowser.yaml
|
./mods/ra/chrome/missionbrowser.yaml
|
||||||
./mods/ra/chrome/confirmation-dialogs.yaml
|
./mods/ra/chrome/confirmation-dialogs.yaml
|
||||||
|
./mods/ra/chrome/editor.yaml
|
||||||
|
|
||||||
Voices:
|
Voices:
|
||||||
./mods/ts/audio/voices.yaml
|
./mods/ts/audio/voices.yaml
|
||||||
|
|||||||
@@ -1,15 +1,8 @@
|
|||||||
World:
|
^BaseWorld:
|
||||||
Inherits: ^Palettes
|
Inherits: ^Palettes
|
||||||
ChatCommands:
|
|
||||||
DevCommands:
|
|
||||||
PlayerCommands:
|
|
||||||
HelpCommand:
|
|
||||||
ScreenMap:
|
ScreenMap:
|
||||||
ActorMap:
|
ActorMap:
|
||||||
LoadWidgetAtGameStart:
|
LoadWidgetAtGameStart:
|
||||||
BuildingInfluence:
|
|
||||||
ProductionQueueFromSelection:
|
|
||||||
ProductionPaletteWidget: PRODUCTION_PALETTE
|
|
||||||
ShroudRenderer:
|
ShroudRenderer:
|
||||||
Index: 255, 16, 32, 48, 64, 80, 96, 112, 128, 144, 160, 176, 192, 208, 224, 240, 20, 40, 56, 65, 97, 130, 148, 194, 24, 33, 66, 132, 28, 41, 67, 134, 1, 2, 4, 8, 3, 6, 12, 9, 7, 14, 13, 11, 5, 10, 15, 255
|
Index: 255, 16, 32, 48, 64, 80, 96, 112, 128, 144, 160, 176, 192, 208, 224, 240, 20, 40, 56, 65, 97, 130, 148, 194, 24, 33, 66, 132, 28, 41, 67, 134, 1, 2, 4, 8, 3, 6, 12, 9, 7, 14, 13, 11, 5, 10, 15, 255
|
||||||
UseExtendedIndex: true
|
UseExtendedIndex: true
|
||||||
@@ -25,6 +18,41 @@ World:
|
|||||||
Country@1:
|
Country@1:
|
||||||
Name: Nod
|
Name: Nod
|
||||||
Race: nod
|
Race: nod
|
||||||
|
ResourceType@Tiberium:
|
||||||
|
ResourceType: 1
|
||||||
|
Palette: greentiberium
|
||||||
|
EditorSprite: waypoint # TODO: editor can't handle the real ones
|
||||||
|
Variants: tib01, tib02, tib03, tib04, tib05, tib06, tib07, tib08, tib09, tib10, tib11, tib12, tib13, tib14, tib15, tib16, tib17, tib18, tib19, tib20
|
||||||
|
MaxDensity: 12
|
||||||
|
ValuePerUnit: 50
|
||||||
|
Name: Tiberium
|
||||||
|
PipColor: Green
|
||||||
|
AllowedTerrainTypes: Clear, Rough, DirtRoad
|
||||||
|
AllowUnderActors: true
|
||||||
|
TerrainType: Tiberium
|
||||||
|
ResourceType@BlueTiberium:
|
||||||
|
ResourceType: 2
|
||||||
|
Palette: bluetiberium
|
||||||
|
EditorSprite: waypoint # TODO: editor can't handle the real ones
|
||||||
|
Variants: tib01, tib02, tib03, tib04, tib05, tib06, tib07, tib08, tib09, tib10, tib11, tib12, tib13, tib14, tib15, tib16, tib17, tib18, tib19, tib20
|
||||||
|
MaxDensity: 12
|
||||||
|
ValuePerUnit: 100
|
||||||
|
Name: BlueTiberium
|
||||||
|
PipColor: Blue
|
||||||
|
AllowedTerrainTypes: Clear, Rough, DirtRoad
|
||||||
|
AllowUnderActors: true
|
||||||
|
TerrainType: BlueTiberium
|
||||||
|
TerrainGeometryOverlay:
|
||||||
|
|
||||||
|
World:
|
||||||
|
Inherits: ^BaseWorld
|
||||||
|
ChatCommands:
|
||||||
|
DevCommands:
|
||||||
|
PlayerCommands:
|
||||||
|
HelpCommand:
|
||||||
|
BuildingInfluence:
|
||||||
|
ProductionQueueFromSelection:
|
||||||
|
ProductionPaletteWidget: PRODUCTION_PALETTE
|
||||||
DomainIndex:
|
DomainIndex:
|
||||||
SmudgeLayer@SMALLSCORCH:
|
SmudgeLayer@SMALLSCORCH:
|
||||||
Type: SmallScorch
|
Type: SmallScorch
|
||||||
@@ -55,32 +83,7 @@ World:
|
|||||||
Sequence: largecraters
|
Sequence: largecraters
|
||||||
ResourceLayer:
|
ResourceLayer:
|
||||||
ResourceClaimLayer:
|
ResourceClaimLayer:
|
||||||
ResourceType@Tiberium:
|
|
||||||
ResourceType: 1
|
|
||||||
Palette: greentiberium
|
|
||||||
EditorSprite: waypoint # TODO: editor can't handle the real ones
|
|
||||||
Variants: tib01, tib02, tib03, tib04, tib05, tib06, tib07, tib08, tib09, tib10, tib11, tib12, tib13, tib14, tib15, tib16, tib17, tib18, tib19, tib20
|
|
||||||
MaxDensity: 12
|
|
||||||
ValuePerUnit: 50
|
|
||||||
Name: Tiberium
|
|
||||||
PipColor: Green
|
|
||||||
AllowedTerrainTypes: Clear, Rough, DirtRoad
|
|
||||||
AllowUnderActors: true
|
|
||||||
TerrainType: Tiberium
|
|
||||||
ResourceType@BlueTiberium:
|
|
||||||
ResourceType: 2
|
|
||||||
Palette: bluetiberium
|
|
||||||
EditorSprite: waypoint # TODO: editor can't handle the real ones
|
|
||||||
Variants: tib01, tib02, tib03, tib04, tib05, tib06, tib07, tib08, tib09, tib10, tib11, tib12, tib13, tib14, tib15, tib16, tib17, tib18, tib19, tib20
|
|
||||||
MaxDensity: 12
|
|
||||||
ValuePerUnit: 100
|
|
||||||
Name: BlueTiberium
|
|
||||||
PipColor: Blue
|
|
||||||
AllowedTerrainTypes: Clear, Rough, DirtRoad
|
|
||||||
AllowUnderActors: true
|
|
||||||
TerrainType: BlueTiberium
|
|
||||||
PathfinderDebugOverlay:
|
PathfinderDebugOverlay:
|
||||||
TerrainGeometryOverlay:
|
|
||||||
SpawnMapActors:
|
SpawnMapActors:
|
||||||
CreateMPPlayers:
|
CreateMPPlayers:
|
||||||
MPStartUnits@MCV:
|
MPStartUnits@MCV:
|
||||||
@@ -153,3 +156,7 @@ World:
|
|||||||
ObjectivesPanel:
|
ObjectivesPanel:
|
||||||
PanelName: SKIRMISH_STATS
|
PanelName: SKIRMISH_STATS
|
||||||
|
|
||||||
|
EditorWorld:
|
||||||
|
Inherits: ^BaseWorld
|
||||||
|
EditorActorLayer:
|
||||||
|
EditorResourceLayer:
|
||||||
|
|||||||
Reference in New Issue
Block a user