Merge pull request #11426 from pchote/actorpreview-dynamic-facing

Support dynamic ActorPreview facings and creating previews from live actors.
This commit is contained in:
reaperrr
2016-06-20 14:38:11 +02:00
committed by GitHub
39 changed files with 382 additions and 150 deletions

View File

@@ -11,7 +11,6 @@
using System.Linq; using System.Linq;
using OpenRA.Primitives; using OpenRA.Primitives;
using OpenRA.Traits;
namespace OpenRA namespace OpenRA
{ {
@@ -48,14 +47,6 @@ namespace OpenRA
T Value(World world); T Value(World world);
} }
public class FacingInit : IActorInit<int>
{
[FieldFromYamlKey] readonly int value = 128;
public FacingInit() { }
public FacingInit(int init) { value = init; }
public int Value(World world) { return value; }
}
public class LocationInit : IActorInit<CPos> public class LocationInit : IActorInit<CPos>
{ {
[FieldFromYamlKey] readonly CPos value = CPos.Zero; [FieldFromYamlKey] readonly CPos value = CPos.Zero;
@@ -64,23 +55,6 @@ namespace OpenRA
public CPos Value(World world) { return value; } public CPos Value(World world) { return value; }
} }
public class SubCellInit : IActorInit<SubCell>
{
[FieldFromYamlKey] readonly int value = (int)SubCell.FullCell;
public SubCellInit() { }
public SubCellInit(int init) { value = init; }
public SubCellInit(SubCell init) { value = (int)init; }
public SubCell Value(World world) { return (SubCell)value; }
}
public class CenterPositionInit : IActorInit<WPos>
{
[FieldFromYamlKey] readonly WPos value = WPos.Zero;
public CenterPositionInit() { }
public CenterPositionInit(WPos init) { value = init; }
public WPos Value(World world) { return value; }
}
public class OwnerInit : IActorInit<Player> public class OwnerInit : IActorInit<Player>
{ {
[FieldFromYamlKey] public readonly string PlayerName = "Neutral"; [FieldFromYamlKey] public readonly string PlayerName = "Neutral";
@@ -103,14 +77,4 @@ namespace OpenRA
return world.Players.First(x => x.InternalName == PlayerName); return world.Players.First(x => x.InternalName == PlayerName);
} }
} }
// Allows maps / transformations to specify the faction variant of an actor.
public class FactionInit : IActorInit<string>
{
[FieldFromYamlKey] public readonly string Faction;
public FactionInit() { }
public FactionInit(string faction) { Faction = faction; }
public string Value(World world) { return Faction; }
}
} }

View File

@@ -11,6 +11,7 @@
using System.Linq; using System.Linq;
using OpenRA.Activities; using OpenRA.Activities;
using OpenRA.Mods.Common;
using OpenRA.Mods.Common.Activities; using OpenRA.Mods.Common.Activities;
using OpenRA.Mods.Common.Traits; using OpenRA.Mods.Common.Traits;
using OpenRA.Primitives; using OpenRA.Primitives;

View File

@@ -10,9 +10,13 @@
#endregion #endregion
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using OpenRA.Graphics; using OpenRA.Graphics;
using OpenRA.Mods.Common;
using OpenRA.Mods.Common.Graphics;
using OpenRA.Mods.Common.Traits; using OpenRA.Mods.Common.Traits;
using OpenRA.Mods.Common.Traits.Render; using OpenRA.Mods.Common.Traits.Render;
using OpenRA.Primitives;
using OpenRA.Traits; using OpenRA.Traits;
namespace OpenRA.Mods.Cnc.Traits.Render namespace OpenRA.Mods.Cnc.Traits.Render
@@ -29,55 +33,80 @@ namespace OpenRA.Mods.Cnc.Traits.Render
public object Create(ActorInitializer init) { return new WithCargo(init.Self, this); } public object Create(ActorInitializer init) { return new WithCargo(init.Self, this); }
} }
public class WithCargo : IRenderModifier, ITick public class WithCargo : ITick, IRender, INotifyPassengerEntered, INotifyPassengerExited
{ {
readonly WithCargoInfo info;
readonly Cargo cargo; readonly Cargo cargo;
readonly IFacing facing;
readonly WithCargoInfo cargoInfo;
readonly BodyOrientation body; readonly BodyOrientation body;
readonly IFacing facing;
Dictionary<Actor, IActorPreview[]> previews = new Dictionary<Actor, IActorPreview[]>();
public WithCargo(Actor self, WithCargoInfo info) public WithCargo(Actor self, WithCargoInfo info)
{ {
this.info = info;
cargo = self.Trait<Cargo>(); cargo = self.Trait<Cargo>();
facing = self.TraitOrDefault<IFacing>();
cargoInfo = info;
body = self.Trait<BodyOrientation>(); body = self.Trait<BodyOrientation>();
facing = self.TraitOrDefault<IFacing>();
} }
public void Tick(Actor self) void ITick.Tick(Actor self)
{ {
if (facing == null) foreach (var actorPreviews in previews.Values)
return; if (actorPreviews != null)
foreach (var preview in actorPreviews)
foreach (var c in cargo.Passengers) preview.Tick();
{
var cargoFacing = c.TraitOrDefault<IFacing>();
if (cargoFacing != null)
cargoFacing.Facing = facing.Facing;
}
} }
public IEnumerable<IRenderable> ModifyRender(Actor self, WorldRenderer wr, IEnumerable<IRenderable> r) IEnumerable<IRenderable> IRender.Render(Actor self, WorldRenderer wr)
{ {
foreach (var rr in r)
yield return rr;
var bodyOrientation = body.QuantizeOrientation(self, self.Orientation); var bodyOrientation = body.QuantizeOrientation(self, self.Orientation);
var pos = self.CenterPosition; var pos = self.CenterPosition;
var i = 0; var i = 0;
foreach (var c in cargo.Passengers)
// Generate missing previews
var missing = previews
.Where(kv => kv.Value == null)
.Select(kv => kv.Key)
.ToList();
foreach (var p in missing)
{ {
var cargoPassenger = c.Trait<Passenger>(); var passengerInits = new TypeDictionary()
if (cargoInfo.DisplayTypes.Contains(cargoPassenger.Info.CargoType))
{ {
var index = cargo.PassengerCount > 1 ? i++ % cargoInfo.LocalOffset.Length : cargoInfo.LocalOffset.Length / 2; new OwnerInit(p.Owner),
var localOffset = cargoInfo.LocalOffset[index]; new DynamicFacingInit(() => body.QuantizeFacing(facing.Facing)),
var offset = pos - c.CenterPosition + body.LocalToWorld(localOffset.Rotate(bodyOrientation)); };
foreach (var cr in c.Render(wr))
yield return cr.OffsetBy(offset).WithZOffset(1); foreach (var api in p.TraitsImplementing<IActorPreviewInitModifier>())
} api.ModifyActorPreviewInit(p, passengerInits);
}
var init = new ActorPreviewInitializer(p.Info, wr, passengerInits);
previews[p] = p.Info.TraitInfos<IRenderActorPreviewInfo>()
.SelectMany(rpi => rpi.RenderPreview(init))
.ToArray();
}
foreach (var p in previews.Values.SelectMany(p => p))
{
var index = cargo.PassengerCount > 1 ? i++ % info.LocalOffset.Length : info.LocalOffset.Length / 2;
var localOffset = info.LocalOffset[index];
foreach (var pp in p.Render(wr, pos + body.LocalToWorld(localOffset.Rotate(bodyOrientation))))
yield return pp.WithZOffset(1);
}
}
void INotifyPassengerEntered.OnPassengerEntered(Actor self, Actor passenger)
{
if (info.DisplayTypes.Contains(passenger.Trait<Passenger>().Info.CargoType))
previews.Add(passenger, null);
}
void INotifyPassengerExited.OnPassengerExited(Actor self, Actor passenger)
{
previews.Remove(passenger);
} }
} }
} }

View File

@@ -0,0 +1,47 @@
using System;
using OpenRA.Traits;
namespace OpenRA.Mods.Common
{
public class FacingInit : IActorInit<int>
{
[FieldFromYamlKey] readonly int value = 128;
public FacingInit() { }
public FacingInit(int init) { value = init; }
public int Value(World world) { return value; }
}
public class DynamicFacingInit : IActorInit<Func<int>>
{
readonly Func<int> func;
public DynamicFacingInit(Func<int> func) { this.func = func; }
public Func<int> Value(World world) { return func; }
}
public class SubCellInit : IActorInit<SubCell>
{
[FieldFromYamlKey] readonly int value = (int)SubCell.FullCell;
public SubCellInit() { }
public SubCellInit(int init) { value = init; }
public SubCellInit(SubCell init) { value = (int)init; }
public SubCell Value(World world) { return (SubCell)value; }
}
public class CenterPositionInit : IActorInit<WPos>
{
[FieldFromYamlKey] readonly WPos value = WPos.Zero;
public CenterPositionInit() { }
public CenterPositionInit(WPos init) { value = init; }
public WPos Value(World world) { return value; }
}
// Allows maps / transformations to specify the faction variant of an actor.
public class FactionInit : IActorInit<string>
{
[FieldFromYamlKey] public readonly string Faction;
public FactionInit() { }
public FactionInit(string faction) { Faction = faction; }
public string Value(World world) { return Faction; }
}
}

View File

@@ -9,6 +9,7 @@
*/ */
#endregion #endregion
using System;
using System.Collections.Generic; using System.Collections.Generic;
using OpenRA.Graphics; using OpenRA.Graphics;
using OpenRA.Mods.Common.Traits; using OpenRA.Mods.Common.Traits;
@@ -42,6 +43,45 @@ namespace OpenRA.Mods.Common.Graphics
public U Get<T, U>() where T : IActorInit<U> { return dict.Get<T>().Value(World); } public U Get<T, U>() where T : IActorInit<U> { return dict.Get<T>().Value(World); }
public bool Contains<T>() where T : IActorInit { return dict.Contains<T>(); } public bool Contains<T>() where T : IActorInit { return dict.Contains<T>(); }
public Func<WRot> GetOrientation()
{
var facingInfo = Actor.TraitInfoOrDefault<IFacingInfo>();
if (facingInfo == null)
return () => WRot.Zero;
// Dynamic facing takes priority
var dynamicInit = dict.GetOrDefault<DynamicFacingInit>();
if (dynamicInit != null)
{
// TODO: Account for terrain slope
var getFacing = dynamicInit.Value(null);
return () => WRot.FromFacing(getFacing());
}
// Fall back to initial actor facing if an Init isn't available
var facingInit = dict.GetOrDefault<FacingInit>();
var facing = facingInit != null ? facingInit.Value(null) : facingInfo.GetInitialFacing();
var orientation = WRot.FromFacing(facing);
return () => orientation;
}
public Func<int> GetFacing()
{
var facingInfo = Actor.TraitInfoOrDefault<IFacingInfo>();
if (facingInfo == null)
return () => 0;
// Dynamic facing takes priority
var dynamicInit = dict.GetOrDefault<DynamicFacingInit>();
if (dynamicInit != null)
return dynamicInit.Value(null);
// Fall back to initial actor facing if an Init isn't available
var facingInit = dict.GetOrDefault<FacingInit>();
var facing = facingInit != null ? facingInit.Value(null) : facingInfo.GetInitialFacing();
return () => facing;
}
public DamageState GetDamageState() public DamageState GetDamageState()
{ {
var health = dict.GetOrDefault<HealthInit>(); var health = dict.GetOrDefault<HealthInit>();

View File

@@ -9,6 +9,7 @@
*/ */
#endregion #endregion
using System;
using System.Collections.Generic; using System.Collections.Generic;
using OpenRA.Graphics; using OpenRA.Graphics;
@@ -17,12 +18,12 @@ namespace OpenRA.Mods.Common.Graphics
public class SpriteActorPreview : IActorPreview public class SpriteActorPreview : IActorPreview
{ {
readonly Animation animation; readonly Animation animation;
readonly WVec offset; readonly Func<WVec> offset;
readonly int zOffset; readonly Func<int> zOffset;
readonly PaletteReference pr; readonly PaletteReference pr;
readonly float scale; readonly float scale;
public SpriteActorPreview(Animation animation, WVec offset, int zOffset, PaletteReference pr, float scale) public SpriteActorPreview(Animation animation, Func<WVec> offset, Func<int> zOffset, PaletteReference pr, float scale)
{ {
this.animation = animation; this.animation = animation;
this.offset = offset; this.offset = offset;
@@ -35,7 +36,7 @@ namespace OpenRA.Mods.Common.Graphics
public IEnumerable<IRenderable> Render(WorldRenderer wr, WPos pos) public IEnumerable<IRenderable> Render(WorldRenderer wr, WPos pos)
{ {
return animation.Render(pos, offset, zOffset, pr, scale); return animation.Render(pos, offset(), zOffset(), pr, scale);
} }
} }
} }

View File

@@ -196,6 +196,7 @@
<Compile Include="Lint\LintBuildablePrerequisites.cs" /> <Compile Include="Lint\LintBuildablePrerequisites.cs" />
<Compile Include="Lint\LintExts.cs" /> <Compile Include="Lint\LintExts.cs" />
<Compile Include="LoadScreens\ModChooserLoadScreen.cs" /> <Compile Include="LoadScreens\ModChooserLoadScreen.cs" />
<Compile Include="ActorInitializer.cs" />
<Compile Include="ShroudExts.cs" /> <Compile Include="ShroudExts.cs" />
<Compile Include="Orders\BeaconOrderGenerator.cs" /> <Compile Include="Orders\BeaconOrderGenerator.cs" />
<Compile Include="Orders\DeployOrderTargeter.cs" /> <Compile Include="Orders\DeployOrderTargeter.cs" />

View File

@@ -88,7 +88,7 @@ namespace OpenRA.Mods.Common.Traits
} }
public class Aircraft : ITick, ISync, IFacing, IPositionable, IMove, IIssueOrder, IResolveOrder, IOrderVoice, IDeathActorInitModifier, public class Aircraft : ITick, ISync, IFacing, IPositionable, IMove, IIssueOrder, IResolveOrder, IOrderVoice, IDeathActorInitModifier,
INotifyCreated, INotifyAddedToWorld, INotifyRemovedFromWorld, INotifyActorDisposing INotifyCreated, INotifyAddedToWorld, INotifyRemovedFromWorld, INotifyActorDisposing, IActorPreviewInitModifier
{ {
static readonly Pair<CPos, SubCell>[] NoCells = { }; static readonly Pair<CPos, SubCell>[] NoCells = { };
@@ -660,5 +660,11 @@ namespace OpenRA.Mods.Common.Traits
{ {
UnReserve(); UnReserve();
} }
void IActorPreviewInitModifier.ModifyActorPreviewInit(Actor self, TypeDictionary inits)
{
if (!inits.Contains<DynamicFacingInit>() && !inits.Contains<FacingInit>())
inits.Add(new DynamicFacingInit(() => Facing));
}
} }
} }

View File

@@ -61,7 +61,7 @@ namespace OpenRA.Mods.Common.Traits
// Z-order is one set to the top of the footprint // Z-order is one set to the top of the footprint
var offset = map.CenterOfCell(cell) - map.CenterOfCell(location) - centerOffset; var offset = map.CenterOfCell(cell) - map.CenterOfCell(location) - centerOffset;
yield return new SpriteActorPreview(anim, offset, -(offset.Y + centerOffset.Y + 512), p, rs.Scale); yield return new SpriteActorPreview(anim, () => offset, () => -(offset.Y + centerOffset.Y + 512), p, rs.Scale);
} }
} }
} }

View File

@@ -309,6 +309,8 @@ namespace OpenRA.Mods.Common.Traits
upgradeManager.RevokeUpgrade(self, u, this); upgradeManager.RevokeUpgrade(self, u, this);
} }
// If not initialized then this will be notified in the first tick
if (initialized)
foreach (var npe in self.TraitsImplementing<INotifyPassengerEntered>()) foreach (var npe in self.TraitsImplementing<INotifyPassengerEntered>())
npe.OnPassengerEntered(self, a); npe.OnPassengerEntered(self, a);

View File

@@ -319,7 +319,7 @@ namespace OpenRA.Mods.Common.Traits
} }
public class Mobile : UpgradableTrait<MobileInfo>, IIssueOrder, IResolveOrder, IOrderVoice, IPositionable, IMove, IFacing, ISync, public class Mobile : UpgradableTrait<MobileInfo>, IIssueOrder, IResolveOrder, IOrderVoice, IPositionable, IMove, IFacing, ISync,
IDeathActorInitModifier, INotifyAddedToWorld, INotifyRemovedFromWorld, INotifyBlockingMove IDeathActorInitModifier, INotifyAddedToWorld, INotifyRemovedFromWorld, INotifyBlockingMove, IActorPreviewInitModifier
{ {
const int AverageTicksBeforePathing = 5; const int AverageTicksBeforePathing = 5;
const int SpreadTicksBeforePathing = 5; const int SpreadTicksBeforePathing = 5;
@@ -716,6 +716,12 @@ namespace OpenRA.Mods.Common.Traits
} }
} }
void IActorPreviewInitModifier.ModifyActorPreviewInit(Actor self, TypeDictionary inits)
{
if (!inits.Contains<DynamicFacingInit>() && !inits.Contains<FacingInit>())
inits.Add(new DynamicFacingInit(() => facing));
}
class MoveOrderTargeter : IOrderTargeter class MoveOrderTargeter : IOrderTargeter
{ {
readonly Mobile mobile; readonly Mobile mobile;

View File

@@ -83,7 +83,7 @@ namespace OpenRA.Mods.Common.Traits.Render
} }
} }
public class RenderSprites : IRender, ITick, INotifyOwnerChanged, INotifyEffectiveOwnerChanged public class RenderSprites : IRender, ITick, INotifyOwnerChanged, INotifyEffectiveOwnerChanged, IActorPreviewInitModifier
{ {
class AnimationWrapper class AnimationWrapper
{ {
@@ -231,5 +231,11 @@ namespace OpenRA.Mods.Common.Traits.Render
.Select(a => (a.Animation.Animation.Image.Size.XY * info.Scale).ToInt2()) .Select(a => (a.Animation.Animation.Image.Size.XY * info.Scale).ToInt2())
.FirstOrDefault(); .FirstOrDefault();
} }
void IActorPreviewInitModifier.ModifyActorPreviewInit(Actor self, TypeDictionary inits)
{
if (!inits.Contains<FactionInit>())
inits.Add(new FactionInit(faction));
}
} }
} }

View File

@@ -9,6 +9,7 @@
*/ */
#endregion #endregion
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using OpenRA.Graphics; using OpenRA.Graphics;
@@ -20,7 +21,7 @@ namespace OpenRA.Mods.Common.Traits.Render
public interface IRenderActorPreviewVoxelsInfo : ITraitInfo public interface IRenderActorPreviewVoxelsInfo : ITraitInfo
{ {
IEnumerable<VoxelAnimation> RenderPreviewVoxels( IEnumerable<VoxelAnimation> RenderPreviewVoxels(
ActorPreviewInitializer init, RenderVoxelsInfo rv, string image, WRot orientation, int facings, PaletteReference p); ActorPreviewInitializer init, RenderVoxelsInfo rv, string image, Func<WRot> orientation, int facings, PaletteReference p);
} }
public class RenderVoxelsInfo : ITraitInfo, IRenderActorPreviewInfo, Requires<BodyOrientationInfo> public class RenderVoxelsInfo : ITraitInfo, IRenderActorPreviewInfo, Requires<BodyOrientationInfo>
@@ -58,11 +59,8 @@ namespace OpenRA.Mods.Common.Traits.Render
body.QuantizedFacings; body.QuantizedFacings;
var palette = init.WorldRenderer.Palette(Palette ?? PlayerPalette + ownerName); var palette = init.WorldRenderer.Palette(Palette ?? PlayerPalette + ownerName);
var ifacing = init.Actor.TraitInfoOrDefault<IFacingInfo>();
var facing = ifacing != null ? init.Contains<FacingInit>() ? init.Get<FacingInit, int>() : ifacing.GetInitialFacing() : 0;
var orientation = WRot.FromFacing(facing);
var components = init.Actor.TraitInfos<IRenderActorPreviewVoxelsInfo>() var components = init.Actor.TraitInfos<IRenderActorPreviewVoxelsInfo>()
.SelectMany(rvpi => rvpi.RenderPreviewVoxels(init, this, image, orientation, facings, palette)) .SelectMany(rvpi => rvpi.RenderPreviewVoxels(init, this, image, init.GetOrientation(), facings, palette))
.ToArray(); .ToArray();
yield return new VoxelPreview(components, WVec.Zero, 0, Scale, LightPitch, yield return new VoxelPreview(components, WVec.Zero, 0, Scale, LightPitch,

View File

@@ -34,7 +34,7 @@ namespace OpenRA.Mods.Common.Traits.Render
{ {
var anim = new Animation(init.World, rs.Image, () => 0); var anim = new Animation(init.World, rs.Image, () => 0);
anim.PlayRepeating(RenderSprites.NormalizeSequence(anim, init.GetDamageState(), IdleSequence)); anim.PlayRepeating(RenderSprites.NormalizeSequence(anim, init.GetDamageState(), IdleSequence));
yield return new SpriteActorPreview(anim, WVec.Zero, 0, p, rs.Scale); yield return new SpriteActorPreview(anim, () => WVec.Zero, () => 0, p, rs.Scale);
} }
} }

View File

@@ -9,6 +9,7 @@
*/ */
#endregion #endregion
using System;
using System.Collections.Generic; using System.Collections.Generic;
using OpenRA.Graphics; using OpenRA.Graphics;
using OpenRA.Mods.Common.Graphics; using OpenRA.Mods.Common.Graphics;
@@ -22,13 +23,10 @@ namespace OpenRA.Mods.Common.Traits.Render
public override IEnumerable<IActorPreview> RenderPreviewSprites(ActorPreviewInitializer init, RenderSpritesInfo rs, string image, int facings, PaletteReference p) public override IEnumerable<IActorPreview> RenderPreviewSprites(ActorPreviewInitializer init, RenderSpritesInfo rs, string image, int facings, PaletteReference p)
{ {
var ifacing = init.Actor.TraitInfoOrDefault<IFacingInfo>(); var anim = new Animation(init.World, image, init.GetFacing());
var facing = ifacing != null ? init.Contains<FacingInit>() ? init.Get<FacingInit, int>() : ifacing.GetInitialFacing() : 0;
var anim = new Animation(init.World, image, () => facing);
anim.PlayRepeating(RenderSprites.NormalizeSequence(anim, init.GetDamageState(), Sequence)); anim.PlayRepeating(RenderSprites.NormalizeSequence(anim, init.GetDamageState(), Sequence));
yield return new SpriteActorPreview(anim, WVec.Zero, 0, p, rs.Scale); yield return new SpriteActorPreview(anim, () => WVec.Zero, () => 0, p, rs.Scale);
} }
} }

View File

@@ -33,7 +33,7 @@ namespace OpenRA.Mods.Common.Traits.Render
var anim = new Animation(init.World, image); var anim = new Animation(init.World, image);
anim.PlayFetchIndex(RenderSprites.NormalizeSequence(anim, init.GetDamageState(), Sequence), () => 0); anim.PlayFetchIndex(RenderSprites.NormalizeSequence(anim, init.GetDamageState(), Sequence), () => 0);
yield return new SpriteActorPreview(anim, WVec.Zero, 0, p, rs.Scale); yield return new SpriteActorPreview(anim, () => WVec.Zero, () => 0, p, rs.Scale);
} }
string IWallConnectorInfo.GetWallConnectionType() string IWallConnectorInfo.GetWallConnectionType()

View File

@@ -9,6 +9,7 @@
*/ */
#endregion #endregion
using System;
using System.Collections.Generic; using System.Collections.Generic;
using OpenRA.Graphics; using OpenRA.Graphics;
using OpenRA.Mods.Common.Graphics; using OpenRA.Mods.Common.Graphics;
@@ -46,14 +47,28 @@ namespace OpenRA.Mods.Common.Traits.Render
if (Palette != null) if (Palette != null)
p = init.WorldRenderer.Palette(Palette); p = init.WorldRenderer.Palette(Palette);
var body = init.Actor.TraitInfo<BodyOrientationInfo>(); Func<int> facing;
var facing = init.Contains<FacingInit>() ? init.Get<FacingInit, int>() : 0; if (init.Contains<DynamicFacingInit>())
var anim = new Animation(init.World, image, () => facing); facing = init.Get<DynamicFacingInit, Func<int>>();
else
{
var f = init.Contains<FacingInit>() ? init.Get<FacingInit, int>() : 0;
facing = () => f;
}
var anim = new Animation(init.World, image, facing);
anim.PlayRepeating(RenderSprites.NormalizeSequence(anim, init.GetDamageState(), Sequence)); anim.PlayRepeating(RenderSprites.NormalizeSequence(anim, init.GetDamageState(), Sequence));
var orientation = body.QuantizeOrientation(new WRot(WAngle.Zero, WAngle.Zero, WAngle.FromFacing(facing)), facings); var body = init.Actor.TraitInfo<BodyOrientationInfo>();
var offset = body.LocalToWorld(Offset.Rotate(orientation)); Func<WRot> orientation = () => body.QuantizeOrientation(WRot.FromFacing(facing()), facings);
yield return new SpriteActorPreview(anim, offset, offset.Y + offset.Z + 1, p, rs.Scale); Func<WVec> offset = () => body.LocalToWorld(Offset.Rotate(orientation()));
Func<int> zOffset = () =>
{
var tmpOffset = offset();
return tmpOffset.Y + tmpOffset.Z + 1;
};
yield return new SpriteActorPreview(anim, offset, zOffset, p, rs.Scale);
} }
} }

View File

@@ -9,6 +9,7 @@
*/ */
#endregion #endregion
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using OpenRA.Graphics; using OpenRA.Graphics;
@@ -31,14 +32,9 @@ namespace OpenRA.Mods.Common.Traits.Render
public IEnumerable<IActorPreview> RenderPreviewSprites(ActorPreviewInitializer init, RenderSpritesInfo rs, string image, int facings, PaletteReference p) public IEnumerable<IActorPreview> RenderPreviewSprites(ActorPreviewInitializer init, RenderSpritesInfo rs, string image, int facings, PaletteReference p)
{ {
var facing = 0; var anim = new Animation(init.World, image, init.GetFacing());
var ifacing = init.Actor.TraitInfoOrDefault<IFacingInfo>();
if (ifacing != null)
facing = init.Contains<FacingInit>() ? init.Get<FacingInit, int>() : ifacing.GetInitialFacing();
var anim = new Animation(init.World, image, () => facing);
anim.PlayRepeating(RenderSprites.NormalizeSequence(anim, init.GetDamageState(), StandSequences.First())); anim.PlayRepeating(RenderSprites.NormalizeSequence(anim, init.GetDamageState(), StandSequences.First()));
yield return new SpriteActorPreview(anim, WVec.Zero, 0, p, rs.Scale); yield return new SpriteActorPreview(anim, () => WVec.Zero, () => 0, p, rs.Scale);
} }
} }

View File

@@ -9,6 +9,7 @@
*/ */
#endregion #endregion
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using OpenRA.Graphics; using OpenRA.Graphics;
@@ -68,14 +69,28 @@ namespace OpenRA.Mods.Common.Traits.Render
if (Palette != null) if (Palette != null)
p = init.WorldRenderer.Palette(Palette); p = init.WorldRenderer.Palette(Palette);
Func<int> facing;
if (init.Contains<DynamicFacingInit>())
facing = init.Get<DynamicFacingInit, Func<int>>();
else
{
var f = init.Contains<FacingInit>() ? init.Get<FacingInit, int>() : 0;
facing = () => f;
}
var anim = new Animation(init.World, image); var anim = new Animation(init.World, image);
anim.PlayThen(OpeningSequence, () => anim.PlayRepeating(Sequence)); anim.PlayThen(OpeningSequence, () => anim.PlayRepeating(Sequence));
var body = init.Actor.TraitInfo<BodyOrientationInfo>(); var body = init.Actor.TraitInfo<BodyOrientationInfo>();
var facing = init.Contains<FacingInit>() ? init.Get<FacingInit, int>() : 0; Func<WRot> orientation = () => body.QuantizeOrientation(WRot.FromFacing(facing()), facings);
var orientation = body.QuantizeOrientation(new WRot(WAngle.Zero, WAngle.Zero, WAngle.FromFacing(facing)), facings); Func<WVec> offset = () => body.LocalToWorld(Offset.Rotate(orientation()));
var offset = body.LocalToWorld(Offset.Rotate(orientation)); Func<int> zOffset = () =>
yield return new SpriteActorPreview(anim, offset, offset.Y + offset.Z + 1, p, rs.Scale); {
var tmpOffset = offset();
return tmpOffset.Y + tmpOffset.Z + 1;
};
yield return new SpriteActorPreview(anim, offset, zOffset, p, rs.Scale);
} }
} }

View File

@@ -31,7 +31,7 @@ namespace OpenRA.Mods.Common.Traits.Render
var bi = init.Actor.TraitInfo<BuildingInfo>(); var bi = init.Actor.TraitInfo<BuildingInfo>();
var offset = FootprintUtils.CenterOffset(init.World, bi).Y + 512; // Additional 512 units move from center -> top of cell var offset = FootprintUtils.CenterOffset(init.World, bi).Y + 512; // Additional 512 units move from center -> top of cell
yield return new SpriteActorPreview(anim, WVec.Zero, offset, p, rs.Scale); yield return new SpriteActorPreview(anim, () => WVec.Zero, () => offset, p, rs.Scale);
} }
} }

View File

@@ -9,6 +9,7 @@
*/ */
#endregion #endregion
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using OpenRA.Graphics; using OpenRA.Graphics;
@@ -46,10 +47,15 @@ namespace OpenRA.Mods.Common.Traits.Render
var anim = new Animation(init.World, image, () => t.InitialFacing); var anim = new Animation(init.World, image, () => t.InitialFacing);
anim.Play(RenderSprites.NormalizeSequence(anim, init.GetDamageState(), Sequence)); anim.Play(RenderSprites.NormalizeSequence(anim, init.GetDamageState(), Sequence));
var turretOrientation = body.QuantizeOrientation(new WRot(WAngle.Zero, WAngle.Zero, WAngle.FromFacing(t.InitialFacing)), facings); var turretOrientation = body.QuantizeOrientation(WRot.FromFacing(t.InitialFacing), facings);
var turretOffset = body.LocalToWorld(t.Offset.Rotate(turretOrientation)); Func<WVec> turretOffset = () => body.LocalToWorld(t.Offset.Rotate(turretOrientation));
Func<int> zOffset = () =>
{
var tmpOffset = turretOffset();
return tmpOffset.Y + tmpOffset.Z;
};
yield return new SpriteActorPreview(anim, turretOffset, turretOffset.Y + turretOffset.Z, p, rs.Scale); yield return new SpriteActorPreview(anim, turretOffset, zOffset, p, rs.Scale);
} }
} }

View File

@@ -39,7 +39,7 @@ namespace OpenRA.Mods.Common.Traits.Render
var anim = new Animation(init.World, image); var anim = new Animation(init.World, image);
anim.PlayRepeating(RenderSprites.NormalizeSequence(anim, init.GetDamageState(), Sequence)); anim.PlayRepeating(RenderSprites.NormalizeSequence(anim, init.GetDamageState(), Sequence));
yield return new SpriteActorPreview(anim, WVec.Zero, 0, p, rs.Scale); yield return new SpriteActorPreview(anim, () => WVec.Zero, () => 0, p, rs.Scale);
} }
} }

View File

@@ -9,6 +9,7 @@
*/ */
#endregion #endregion
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using OpenRA.Graphics; using OpenRA.Graphics;
@@ -44,16 +45,20 @@ namespace OpenRA.Mods.Common.Traits.Render
var t = init.Actor.TraitInfos<TurretedInfo>() var t = init.Actor.TraitInfos<TurretedInfo>()
.First(tt => tt.Turret == Turret); .First(tt => tt.Turret == Turret);
var ifacing = init.Actor.TraitInfoOrDefault<IFacingInfo>(); var turretFacing = Turreted.TurretFacingFromInit(init, t.InitialFacing, Turret);
var bodyFacing = ifacing != null ? init.Contains<FacingInit>() ? init.Get<FacingInit, int>() : ifacing.GetInitialFacing() : 0; var anim = new Animation(init.World, image, turretFacing);
var turretFacing = Turreted.GetInitialTurretFacing(init, t.InitialFacing, Turret);
var anim = new Animation(init.World, image, () => turretFacing);
anim.Play(RenderSprites.NormalizeSequence(anim, init.GetDamageState(), Sequence)); anim.Play(RenderSprites.NormalizeSequence(anim, init.GetDamageState(), Sequence));
var orientation = body.QuantizeOrientation(new WRot(WAngle.Zero, WAngle.Zero, WAngle.FromFacing(bodyFacing)), facings); Func<int> facing = init.GetFacing();
var offset = body.LocalToWorld(t.Offset.Rotate(orientation)); Func<WRot> orientation = () => body.QuantizeOrientation(WRot.FromFacing(facing()), facings);
yield return new SpriteActorPreview(anim, offset, -(offset.Y + offset.Z) + 1, p, rs.Scale); Func<WVec> offset = () => body.LocalToWorld(t.Offset.Rotate(orientation()));
Func<int> zOffset = () =>
{
var tmpOffset = offset();
return -(tmpOffset.Y + tmpOffset.Z) + 1;
};
yield return new SpriteActorPreview(anim, offset, zOffset, p, rs.Scale);
} }
} }

View File

@@ -32,7 +32,7 @@ namespace OpenRA.Mods.Common.Traits.Render
var anim = new Animation(init.World, image, () => t.InitialFacing); var anim = new Animation(init.World, image, () => t.InitialFacing);
anim.PlayRepeating(RenderSprites.NormalizeSequence(anim, init.GetDamageState(), wsb.Sequence)); anim.PlayRepeating(RenderSprites.NormalizeSequence(anim, init.GetDamageState(), wsb.Sequence));
yield return new SpriteActorPreview(anim, WVec.Zero, 0, p, rs.Scale); yield return new SpriteActorPreview(anim, () => WVec.Zero, () => 0, p, rs.Scale);
} }
} }

View File

@@ -9,6 +9,7 @@
*/ */
#endregion #endregion
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using OpenRA.Graphics; using OpenRA.Graphics;
@@ -30,7 +31,8 @@ namespace OpenRA.Mods.Common.Traits.Render
public override object Create(ActorInitializer init) { return new WithVoxelBarrel(init.Self, this); } public override object Create(ActorInitializer init) { return new WithVoxelBarrel(init.Self, this); }
public IEnumerable<VoxelAnimation> RenderPreviewVoxels(ActorPreviewInitializer init, RenderVoxelsInfo rv, string image, WRot orientation, int facings, PaletteReference p) public IEnumerable<VoxelAnimation> RenderPreviewVoxels(
ActorPreviewInitializer init, RenderVoxelsInfo rv, string image, Func<WRot> orientation, int facings, PaletteReference p)
{ {
if (UpgradeMinEnabledLevel > 0) if (UpgradeMinEnabledLevel > 0)
yield break; yield break;
@@ -43,14 +45,14 @@ namespace OpenRA.Mods.Common.Traits.Render
var voxel = VoxelProvider.GetVoxel(image, Sequence); var voxel = VoxelProvider.GetVoxel(image, Sequence);
var turretFacing = Turreted.GetInitialTurretFacing(init, t.InitialFacing, t.Turret); var turretFacing = Turreted.TurretFacingFromInit(init, t.InitialFacing, t.Turret);
var turretOrientation = body.QuantizeOrientation(new WRot(WAngle.Zero, WAngle.Zero, WAngle.FromFacing(turretFacing) - orientation.Yaw), facings); Func<WRot> turretOrientation = () => body.QuantizeOrientation(WRot.FromYaw(WAngle.FromFacing(turretFacing()) - orientation().Yaw), facings);
var quantizedTurret = body.QuantizeOrientation(turretOrientation, facings); Func<WRot> quantizedTurret = () => body.QuantizeOrientation(turretOrientation(), facings);
var quantizedBody = body.QuantizeOrientation(orientation, facings); Func<WRot> quantizedBody = () => body.QuantizeOrientation(orientation(), facings);
var barrelOffset = body.LocalToWorld((t.Offset + LocalOffset.Rotate(quantizedTurret)).Rotate(quantizedBody)); Func<WVec> barrelOffset = () => body.LocalToWorld((t.Offset + LocalOffset.Rotate(quantizedTurret())).Rotate(quantizedBody()));
yield return new VoxelAnimation(voxel, () => barrelOffset, () => new[] { turretOrientation, orientation }, yield return new VoxelAnimation(voxel, barrelOffset, () => new[] { turretOrientation(), orientation() },
() => false, () => 0); () => false, () => 0);
} }
} }

View File

@@ -25,13 +25,13 @@ namespace OpenRA.Mods.Common.Traits.Render
public override object Create(ActorInitializer init) { return new WithVoxelBody(init.Self, this); } public override object Create(ActorInitializer init) { return new WithVoxelBody(init.Self, this); }
public IEnumerable<VoxelAnimation> RenderPreviewVoxels(ActorPreviewInitializer init, RenderVoxelsInfo rv, string image, WRot orientation, int facings, PaletteReference p) public IEnumerable<VoxelAnimation> RenderPreviewVoxels(
ActorPreviewInitializer init, RenderVoxelsInfo rv, string image, Func<WRot> orientation, int facings, PaletteReference p)
{ {
var body = init.Actor.TraitInfo<BodyOrientationInfo>(); var body = init.Actor.TraitInfo<BodyOrientationInfo>();
var voxel = VoxelProvider.GetVoxel(image, "idle"); var voxel = VoxelProvider.GetVoxel(image, "idle");
var bodyOrientation = new[] { body.QuantizeOrientation(orientation, facings) };
yield return new VoxelAnimation(voxel, () => WVec.Zero, yield return new VoxelAnimation(voxel, () => WVec.Zero,
() => bodyOrientation, () => new[] { body.QuantizeOrientation(orientation(), facings) },
() => false, () => 0); () => false, () => 0);
} }
} }

View File

@@ -9,6 +9,7 @@
*/ */
#endregion #endregion
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using OpenRA.Graphics; using OpenRA.Graphics;
@@ -27,7 +28,8 @@ namespace OpenRA.Mods.Common.Traits.Render
public override object Create(ActorInitializer init) { return new WithVoxelTurret(init.Self, this); } public override object Create(ActorInitializer init) { return new WithVoxelTurret(init.Self, this); }
public IEnumerable<VoxelAnimation> RenderPreviewVoxels(ActorPreviewInitializer init, RenderVoxelsInfo rv, string image, WRot orientation, int facings, PaletteReference p) public IEnumerable<VoxelAnimation> RenderPreviewVoxels(
ActorPreviewInitializer init, RenderVoxelsInfo rv, string image, Func<WRot> orientation, int facings, PaletteReference p)
{ {
if (UpgradeMinEnabledLevel > 0) if (UpgradeMinEnabledLevel > 0)
yield break; yield break;
@@ -37,12 +39,12 @@ namespace OpenRA.Mods.Common.Traits.Render
.First(tt => tt.Turret == Turret); .First(tt => tt.Turret == Turret);
var voxel = VoxelProvider.GetVoxel(image, Sequence); var voxel = VoxelProvider.GetVoxel(image, Sequence);
var turretOffset = body.LocalToWorld(t.Offset.Rotate(orientation)); Func<WVec> turretOffset = () => body.LocalToWorld(t.Offset.Rotate(orientation()));
var turretFacing = Turreted.GetInitialTurretFacing(init, t.InitialFacing, Turret); var turretFacing = Turreted.TurretFacingFromInit(init, t.InitialFacing, Turret);
var turretBodyOrientation = new WRot(WAngle.Zero, WAngle.Zero, WAngle.FromFacing(turretFacing) - orientation.Yaw); Func<WRot> turretBodyOrientation = () => WRot.FromYaw(WAngle.FromFacing(turretFacing()) - orientation().Yaw);
var turretOrientation = new[] { turretBodyOrientation, body.QuantizeOrientation(orientation, facings) }; yield return new VoxelAnimation(voxel, turretOffset,
yield return new VoxelAnimation(voxel, () => turretOffset, () => turretOrientation, () => false, () => 0); () => new[] { turretBodyOrientation(), body.QuantizeOrientation(orientation(), facings) }, () => false, () => 0);
} }
} }

View File

@@ -72,7 +72,7 @@ namespace OpenRA.Mods.Common.Traits.Render
var anim = new Animation(init.World, image, () => 0); var anim = new Animation(init.World, image, () => 0);
anim.PlayFetchIndex(RenderSprites.NormalizeSequence(anim, init.GetDamageState(), Sequence), () => adjacent); anim.PlayFetchIndex(RenderSprites.NormalizeSequence(anim, init.GetDamageState(), Sequence), () => adjacent);
yield return new SpriteActorPreview(anim, WVec.Zero, 0, p, rs.Scale); yield return new SpriteActorPreview(anim, () => WVec.Zero, () => 0, p, rs.Scale);
} }
string IWallConnectorInfo.GetWallConnectionType() string IWallConnectorInfo.GetWallConnectionType()

View File

@@ -9,6 +9,7 @@
*/ */
#endregion #endregion
using System;
using OpenRA.Graphics; using OpenRA.Graphics;
using OpenRA.Mods.Common.Traits.Render; using OpenRA.Mods.Common.Traits.Render;
using OpenRA.Traits; using OpenRA.Traits;
@@ -64,8 +65,9 @@ namespace OpenRA.Mods.Common.Traits
var body = self.Trait<BodyOrientation>(); var body = self.Trait<BodyOrientation>();
// TODO: Carry orientation over from the parent instead of just facing // TODO: Carry orientation over from the parent instead of just facing
var bodyFacing = init.Contains<FacingInit>() ? init.Get<FacingInit, int>() : 0; var bodyFacing = init.Contains<DynamicFacingInit>() ? init.Get<DynamicFacingInit, Func<int>>()()
facing = WAngle.FromFacing(Turreted.GetInitialTurretFacing(init, 0)); : init.Contains<FacingInit>() ? init.Get<FacingInit, int>() : 0;
facing = WAngle.FromFacing(Turreted.TurretFacingFromInit(init, 0)());
// Calculate final position // Calculate final position
var throwRotation = WRot.FromFacing(Game.CosmeticRandom.Next(1024)); var throwRotation = WRot.FromFacing(Game.CosmeticRandom.Next(1024));

View File

@@ -9,6 +9,7 @@
*/ */
#endregion #endregion
using System;
using System.Collections.Generic; using System.Collections.Generic;
using OpenRA.Primitives; using OpenRA.Primitives;
using OpenRA.Traits; using OpenRA.Traits;
@@ -31,7 +32,7 @@ namespace OpenRA.Mods.Common.Traits
public virtual object Create(ActorInitializer init) { return new Turreted(init, this); } public virtual object Create(ActorInitializer init) { return new Turreted(init, this); }
} }
public class Turreted : ITick, ISync, INotifyCreated, IDeathActorInitModifier public class Turreted : ITick, ISync, INotifyCreated, IDeathActorInitModifier, IActorPreviewInitModifier
{ {
readonly TurretedInfo info; readonly TurretedInfo info;
AttackTurreted attack; AttackTurreted attack;
@@ -49,28 +50,44 @@ namespace OpenRA.Mods.Common.Traits
public WVec Offset { get { return info.Offset + localOffset; } } public WVec Offset { get { return info.Offset + localOffset; } }
public string Name { get { return info.Turret; } } public string Name { get { return info.Turret; } }
public static int GetInitialTurretFacing(IActorInitializer init, int def, string turret = null) public static Func<int> TurretFacingFromInit(IActorInitializer init, int def, string turret = null)
{ {
if (turret != null && init.Contains<DynamicTurretFacingsInit>())
{
Func<int> facing;
if (init.Get<DynamicTurretFacingsInit, Dictionary<string, Func<int>>>().TryGetValue(turret, out facing))
return facing;
}
if (turret != null && init.Contains<TurretFacingsInit>()) if (turret != null && init.Contains<TurretFacingsInit>())
{ {
int facing; int facing;
if (init.Get<TurretFacingsInit, Dictionary<string, int>>().TryGetValue(turret, out facing)) if (init.Get<TurretFacingsInit, Dictionary<string, int>>().TryGetValue(turret, out facing))
return facing; return () => facing;
} }
if (init.Contains<TurretFacingInit>()) if (init.Contains<TurretFacingInit>())
return init.Get<TurretFacingInit, int>(); {
var facing = init.Get<TurretFacingInit, int>();
return () => facing;
}
if (init.Contains<DynamicFacingInit>())
return init.Get<DynamicFacingInit, Func<int>>();
if (init.Contains<FacingInit>()) if (init.Contains<FacingInit>())
return init.Get<FacingInit, int>(); {
var facing = init.Get<FacingInit, int>();
return () => facing;
}
return def; return () => def;
} }
public Turreted(ActorInitializer init, TurretedInfo info) public Turreted(ActorInitializer init, TurretedInfo info)
{ {
this.info = info; this.info = info;
TurretFacing = GetInitialTurretFacing(init, info.InitialFacing, info.Turret); TurretFacing = TurretFacingFromInit(init, info.InitialFacing, info.Turret)();
} }
public void Created(Actor self) public void Created(Actor self)
@@ -157,6 +174,28 @@ namespace OpenRA.Mods.Common.Traits
facings.Value(self.World).Add(Name, TurretFacing); facings.Value(self.World).Add(Name, TurretFacing);
} }
void IActorPreviewInitModifier.ModifyActorPreviewInit(Actor self, TypeDictionary inits)
{
var facings = inits.GetOrDefault<DynamicTurretFacingsInit>();
if (facings == null)
{
facings = new DynamicTurretFacingsInit();
inits.Add(facings);
}
Func<int> bodyFacing = () => facing.Facing;
var dynamicFacing = inits.GetOrDefault<DynamicFacingInit>();
var staticFacing = inits.GetOrDefault<FacingInit>();
if (dynamicFacing != null)
bodyFacing = dynamicFacing.Value(self.World);
else if (staticFacing != null)
bodyFacing = () => staticFacing.Value(self.World);
// Freeze the relative turret facing to its current value
var facingOffset = TurretFacing - bodyFacing();
facings.Value(self.World).Add(Name, () => bodyFacing() + facingOffset);
}
} }
public class TurretFacingInit : IActorInit<int> public class TurretFacingInit : IActorInit<int>
@@ -175,4 +214,12 @@ namespace OpenRA.Mods.Common.Traits
public TurretFacingsInit(Dictionary<string, int> init) { value = init; } public TurretFacingsInit(Dictionary<string, int> init) { value = init; }
public Dictionary<string, int> Value(World world) { return value; } public Dictionary<string, int> Value(World world) { return value; }
} }
public class DynamicTurretFacingsInit : IActorInit<Dictionary<string, Func<int>>>
{
readonly Dictionary<string, Func<int>> value = new Dictionary<string, Func<int>>();
public DynamicTurretFacingsInit() { }
public DynamicTurretFacingsInit(Dictionary<string, Func<int>> init) { value = init; }
public Dictionary<string, Func<int>> Value(World world) { return value; }
}
} }

View File

@@ -125,4 +125,10 @@ namespace OpenRA.Mods.Common.Traits
bool AdjacentWallCanConnect(Actor self, CPos wallLocation, string wallType, out CVec facing); bool AdjacentWallCanConnect(Actor self, CPos wallLocation, string wallType, out CVec facing);
void SetDirty(); void SetDirty();
} }
[RequireExplicitImplementation]
public interface IActorPreviewInitModifier
{
void ModifyActorPreviewInit(Actor self, TypeDictionary inits);
}
} }

View File

@@ -9,6 +9,7 @@
*/ */
#endregion #endregion
using OpenRA.Mods.Common;
using OpenRA.Mods.Common.Activities; using OpenRA.Mods.Common.Activities;
using OpenRA.Mods.Common.Traits; using OpenRA.Mods.Common.Traits;
using OpenRA.Mods.D2k.Activities; using OpenRA.Mods.D2k.Activities;

View File

@@ -14,6 +14,7 @@ using System.Linq;
using OpenRA.Effects; using OpenRA.Effects;
using OpenRA.GameRules; using OpenRA.GameRules;
using OpenRA.Graphics; using OpenRA.Graphics;
using OpenRA.Mods.Common;
using OpenRA.Mods.Common.Graphics; using OpenRA.Mods.Common.Graphics;
using OpenRA.Mods.Common.Traits; using OpenRA.Mods.Common.Traits;
using OpenRA.Mods.Common.Traits.Render; using OpenRA.Mods.Common.Traits.Render;
@@ -59,7 +60,7 @@ namespace OpenRA.Mods.D2k.Traits
var anim = new Animation(init.World, image); var anim = new Animation(init.World, image);
anim.PlayRepeating(RenderSprites.NormalizeSequence(anim, init.GetDamageState(), GrowthSequences[0])); anim.PlayRepeating(RenderSprites.NormalizeSequence(anim, init.GetDamageState(), GrowthSequences[0]));
yield return new SpriteActorPreview(anim, WVec.Zero, 0, p, rs.Scale); yield return new SpriteActorPreview(anim, () => WVec.Zero, () => 0, p, rs.Scale);
} }
} }

View File

@@ -10,6 +10,7 @@
#endregion #endregion
using System.Collections.Generic; using System.Collections.Generic;
using OpenRA.Mods.Common;
using OpenRA.Mods.Common.Traits; using OpenRA.Mods.Common.Traits;
using OpenRA.Traits; using OpenRA.Traits;

View File

@@ -12,6 +12,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using OpenRA.Mods.Common;
using OpenRA.Mods.Common.Activities; using OpenRA.Mods.Common.Activities;
using OpenRA.Mods.Common.Effects; using OpenRA.Mods.Common.Effects;
using OpenRA.Mods.Common.Traits; using OpenRA.Mods.Common.Traits;

View File

@@ -30,12 +30,13 @@ namespace OpenRA.Mods.TS.Traits.Render
public object Create(ActorInitializer init) { return new WithVoxelUnloadBody(init.Self, this); } public object Create(ActorInitializer init) { return new WithVoxelUnloadBody(init.Self, this); }
public IEnumerable<VoxelAnimation> RenderPreviewVoxels(ActorPreviewInitializer init, RenderVoxelsInfo rv, string image, WRot orientation, int facings, PaletteReference p) public IEnumerable<VoxelAnimation> RenderPreviewVoxels(
ActorPreviewInitializer init, RenderVoxelsInfo rv, string image, Func<WRot> orientation, int facings, PaletteReference p)
{ {
var body = init.Actor.TraitInfo<BodyOrientationInfo>(); var body = init.Actor.TraitInfo<BodyOrientationInfo>();
var voxel = VoxelProvider.GetVoxel(image, "idle"); var voxel = VoxelProvider.GetVoxel(image, "idle");
yield return new VoxelAnimation(voxel, () => WVec.Zero, yield return new VoxelAnimation(voxel, () => WVec.Zero,
() => new[] { body.QuantizeOrientation(orientation, facings) }, () => new[] { body.QuantizeOrientation(orientation(), facings) },
() => false, () => 0); () => false, () => 0);
} }
} }

View File

@@ -10,21 +10,37 @@
#endregion #endregion
using System; using System;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using OpenRA.Graphics; using OpenRA.Graphics;
using OpenRA.Mods.Common;
using OpenRA.Mods.Common.Graphics;
using OpenRA.Mods.Common.Traits; using OpenRA.Mods.Common.Traits;
using OpenRA.Mods.Common.Traits.Render; using OpenRA.Mods.Common.Traits.Render;
using OpenRA.Primitives;
using OpenRA.Traits; using OpenRA.Traits;
namespace OpenRA.Mods.TS.Traits.Render namespace OpenRA.Mods.TS.Traits.Render
{ {
public class WithVoxelWalkerBodyInfo : ITraitInfo, Requires<RenderVoxelsInfo>, Requires<IMoveInfo>, Requires<IFacingInfo> public class WithVoxelWalkerBodyInfo : ITraitInfo, IRenderActorPreviewVoxelsInfo, Requires<RenderVoxelsInfo>, Requires<IMoveInfo>, Requires<IFacingInfo>
{ {
public readonly int TickRate = 5; public readonly int TickRate = 5;
public object Create(ActorInitializer init) { return new WithVoxelWalkerBody(init.Self, this); } public object Create(ActorInitializer init) { return new WithVoxelWalkerBody(init.Self, this); }
public IEnumerable<VoxelAnimation> RenderPreviewVoxels(
ActorPreviewInitializer init, RenderVoxelsInfo rv, string image, Func<WRot> orientation, int facings, PaletteReference p)
{
var voxel = VoxelProvider.GetVoxel(image, "idle");
var body = init.Actor.TraitInfo<BodyOrientationInfo>();
var frame = init.Contains<BodyAnimationFrameInit>() ? init.Get<BodyAnimationFrameInit, uint>() : 0;
yield return new VoxelAnimation(voxel, () => WVec.Zero,
() => new[] { body.QuantizeOrientation(orientation(), facings) },
() => false, () => frame);
}
} }
public class WithVoxelWalkerBody : IAutoSelectionSize, ITick public class WithVoxelWalkerBody : IAutoSelectionSize, ITick, IActorPreviewInitModifier
{ {
WithVoxelWalkerBodyInfo info; WithVoxelWalkerBodyInfo info;
IMove movement; IMove movement;
@@ -69,5 +85,18 @@ namespace OpenRA.Mods.TS.Traits.Render
if (++frame == frames) if (++frame == frames)
frame = 0; frame = 0;
} }
void IActorPreviewInitModifier.ModifyActorPreviewInit(Actor self, TypeDictionary inits)
{
inits.Add(new BodyAnimationFrameInit(frame));
}
}
public class BodyAnimationFrameInit : IActorInit<uint>
{
[FieldFromYamlKey] readonly uint value = 0;
public BodyAnimationFrameInit() { }
public BodyAnimationFrameInit(uint init) { value = init; }
public uint Value(World world) { return value; }
} }
} }

View File

@@ -15,9 +15,9 @@ using System.Drawing;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using OpenRA.FileSystem; using OpenRA.FileSystem;
using OpenRA.Mods.Common;
using OpenRA.Mods.Common.FileFormats; using OpenRA.Mods.Common.FileFormats;
using OpenRA.Mods.Common.Traits; using OpenRA.Mods.Common.Traits;
using OpenRA.Traits;
namespace OpenRA.Mods.TS.UtilityCommands namespace OpenRA.Mods.TS.UtilityCommands
{ {

View File

@@ -1,9 +1,12 @@
lst: lst:
idle: lstnew idle: lstnew
UseClassicFacingFudge: True
Facings: 32 Facings: 32
unload: lstnew unload: lstnew
UseClassicFacingFudge: True
Facings: 32 Facings: 32
roof: lstnew2 roof: lstnew2
UseClassicFacingFudge: True
Facings: 32 Facings: 32
icon: lsticnh.tem icon: lsticnh.tem
AddExtension: False AddExtension: False