Merge branch 'master' of github.com:thatcosmonaut/encompass-cs
commit
1195f03fb2
|
@ -43,4 +43,4 @@ workflows:
|
|||
branches:
|
||||
ignore: /.*/
|
||||
tags:
|
||||
only: /^\d+\.\d+\.\d+(-rc\d+)?$/
|
||||
only: /^\d+\.\d+\.\d+(-preview\d+)?$/
|
||||
|
|
9
TODO
9
TODO
|
@ -1,4 +1,11 @@
|
|||
- implement IImmutableComponent and ITimedComponent
|
||||
- immutable component system?
|
||||
|
||||
- method to remove all components of a type without destroying Entities
|
||||
- method to remove a component of a type without destroying entity
|
||||
|
||||
- auto destroy entities that no longer have components
|
||||
|
||||
- fast lookup for messages that contain entity references instead of `Where` loop?
|
||||
|
||||
- look at test coverage
|
||||
- docs
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
using System;
|
||||
|
||||
namespace Encompass
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public class TimeDilationPriority : Attribute
|
||||
{
|
||||
public int timeDilationPriority;
|
||||
|
||||
public TimeDilationPriority(int timeDilationPriority)
|
||||
{
|
||||
this.timeDilationPriority = timeDilationPriority;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -27,7 +27,6 @@ namespace Encompass
|
|||
/// <summary>
|
||||
/// Used when activating time dilation. Lower priority overrides higher priority.
|
||||
/// </summary>
|
||||
internal int? timeDilationPriority = null;
|
||||
|
||||
private EntityManager entityManager;
|
||||
private MessageManager messageManager;
|
||||
|
@ -139,9 +138,9 @@ namespace Encompass
|
|||
/// <summary>
|
||||
/// Returns true if an Entity with the specified ID exists.
|
||||
/// </summary>
|
||||
internal bool EntityExists(Guid entityID)
|
||||
protected bool EntityExists(Entity entity)
|
||||
{
|
||||
return entityManager.EntityExists(entityID);
|
||||
return entityManager.EntityExists(entity.ID);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -689,15 +688,10 @@ namespace Encompass
|
|||
componentManager.MarkForRemoval(componentID);
|
||||
}
|
||||
|
||||
private void CheckTimeDilationPriorityExists()
|
||||
{
|
||||
if (!timeDilationPriority.HasValue) { throw new TimeDilationPriorityUndefinedException("Engines that activate time dilation must use the TimeDilationPriority attribute."); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Activates the Encompass time dilation system.
|
||||
/// If activating time dilation, make sure the TimeDilationPriority attribute is set or an exception will be thrown.
|
||||
/// Engines that have the IgnoresTimeDilation property will ignore all time dilation.
|
||||
/// If multiple time dilations are active they will be averaged.
|
||||
/// </summary>
|
||||
/// <param name="factor">The time dilation factor, which is multiplied by real delta time.</param>
|
||||
/// <param name="easeInTime">The time that will elapse before time is fully dilated, in real time.</param>
|
||||
|
@ -705,14 +699,13 @@ namespace Encompass
|
|||
/// <param name="easeOutTime">The time that will elapse before time is fully undilated.</param>
|
||||
public void ActivateTimeDilation(double factor, double easeInTime, double activeTime, double easeOutTime)
|
||||
{
|
||||
CheckTimeDilationPriorityExists();
|
||||
timeManager.ActivateTimeDilation(factor, easeInTime, activeTime, easeOutTime, timeDilationPriority.Value);
|
||||
timeManager.ActivateTimeDilation(factor, easeInTime, activeTime, easeOutTime);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Activates the Encompass time dilation system.
|
||||
/// If activating time dilation, make sure the TimeDilationPriority attribute is set or an exception will be thrown.
|
||||
/// Engines that have the IgnoresTimeDilation property will ignore all time dilation.
|
||||
/// If multiple time dilations are active they will be averaged.
|
||||
/// </summary>
|
||||
/// <param name="factor">The time dilation factor, which is multiplied by real delta time.</param>
|
||||
/// <param name="easeInTime">The time that will elapse before time is fully dilated, in real time.</param>
|
||||
|
@ -721,14 +714,13 @@ namespace Encompass
|
|||
/// <param name="easeOutTime">The time that will elapse before time is fully undilated.</param>
|
||||
public void ActivateTimeDilation(double factor, double easeInTime, System.Func<double, double, double, double, double> easeInFunction, double activeTime, double easeOutTime)
|
||||
{
|
||||
CheckTimeDilationPriorityExists();
|
||||
timeManager.ActivateTimeDilation(factor, easeInTime, easeInFunction, activeTime, easeOutTime, timeDilationPriority.Value);
|
||||
timeManager.ActivateTimeDilation(factor, easeInTime, easeInFunction, activeTime, easeOutTime);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Activates the Encompass time dilation system.
|
||||
/// If activating time dilation, make sure the TimeDilationPriority attribute is set or an exception will be thrown.
|
||||
/// Engines that have the IgnoresTimeDilation property will ignore all time dilation.
|
||||
/// If multiple time dilations are active they will be averaged.
|
||||
/// </summary>
|
||||
/// <param name="factor">The time dilation factor, which is multiplied by real delta time.</param>
|
||||
/// <param name="easeInTime">The time that will elapse before time is fully dilated, in real time.</param>
|
||||
|
@ -737,14 +729,13 @@ namespace Encompass
|
|||
/// <param name="easeOutFunction">An easing function for the easing out of time dilation.</param>
|
||||
public void ActivateTimeDilation(double factor, double easeInTime, double activeTime, double easeOutTime, System.Func<double, double, double, double, double> easeOutFunction)
|
||||
{
|
||||
CheckTimeDilationPriorityExists();
|
||||
timeManager.ActivateTimeDilation(factor, easeInTime, activeTime, easeOutTime, easeOutFunction, timeDilationPriority.Value);
|
||||
timeManager.ActivateTimeDilation(factor, easeInTime, activeTime, easeOutTime, easeOutFunction);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Activates the Encompass time dilation system.
|
||||
/// If activating time dilation, make sure the TimeDilationPriority attribute is set or an exception will be thrown.
|
||||
/// Engines that have the IgnoresTimeDilation property will ignore all time dilation.
|
||||
/// If multiple time dilations are active they will be averaged.
|
||||
/// </summary>
|
||||
/// <param name="factor">The time dilation factor, which is multiplied by real delta time.</param>
|
||||
/// <param name="easeInTime">The time that will elapse before time is fully dilated, in real time.</param>
|
||||
|
@ -754,8 +745,7 @@ namespace Encompass
|
|||
/// <param name="easeOutFunction">An easing function for the easing out of time dilation.</param>
|
||||
public void ActivateTimeDilation(double factor, double easeInTime, System.Func<double, double, double, double, double> easeInFunction, double activeTime, double easeOutTime, System.Func<double, double, double, double, double> easeOutFunction)
|
||||
{
|
||||
CheckTimeDilationPriorityExists();
|
||||
timeManager.ActivateTimeDilation(factor, easeInTime, easeInFunction, activeTime, easeOutTime, easeOutFunction, timeDilationPriority.Value);
|
||||
timeManager.ActivateTimeDilation(factor, easeInTime, easeInFunction, activeTime, easeOutTime, easeOutFunction);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
using System;
|
||||
|
||||
namespace Encompass.Exceptions
|
||||
{
|
||||
public class TimeDilationPriorityConflictException : Exception
|
||||
{
|
||||
public TimeDilationPriorityConflictException(
|
||||
string format,
|
||||
params object[] args
|
||||
) : base(string.Format(format, args)) { }
|
||||
}
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
using System;
|
||||
|
||||
namespace Encompass.Exceptions
|
||||
{
|
||||
public class TimeDilationPriorityUndefinedException : Exception
|
||||
{
|
||||
public TimeDilationPriorityUndefinedException(
|
||||
string format,
|
||||
params object[] args
|
||||
) : base(string.Format(format, args)) { }
|
||||
}
|
||||
}
|
|
@ -29,6 +29,16 @@ namespace Encompass
|
|||
return entityManager.GetEntity(entityID);
|
||||
}
|
||||
|
||||
protected IEnumerable<Entity> ReadEntities<TComponent>() where TComponent : struct, IComponent
|
||||
{
|
||||
return ReadComponentsIncludingEntity<TComponent>().Select(tuple => tuple.Item2);
|
||||
}
|
||||
|
||||
protected Entity ReadEntity<TComponent>() where TComponent : struct, IComponent
|
||||
{
|
||||
return ReadComponentIncludingEntity<TComponent>().Item2;
|
||||
}
|
||||
|
||||
protected IEnumerable<TComponent> ReadComponents<TComponent>() where TComponent : struct, IComponent
|
||||
{
|
||||
return componentManager.GetComponentsByType<TComponent>().Select(tuple => tuple.Item2);
|
||||
|
|
|
@ -1,73 +1,76 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Encompass
|
||||
{
|
||||
internal class TimeManager
|
||||
{
|
||||
private TimeDilationData timeDilationData = new TimeDilationData { factor = 1 };
|
||||
private bool newTimeDilationData = false;
|
||||
private TimeDilationData nextFrameTimeDilationData = new TimeDilationData { factor = 1 };
|
||||
private List<TimeDilationData> timeDilationDatas = new List<TimeDilationData>();
|
||||
|
||||
private double Linear(double t, double b, double c, double d)
|
||||
{
|
||||
return c * t / d + b;
|
||||
}
|
||||
private int minPriority = int.MaxValue;
|
||||
|
||||
public double TimeDilationFactor
|
||||
{
|
||||
get
|
||||
{
|
||||
return timeDilationData.Factor;
|
||||
return timeDilationDatas.Count == 0 ? 1 : timeDilationDatas.Select(data => data.Factor).Average();
|
||||
}
|
||||
}
|
||||
|
||||
public bool TimeDilationActive
|
||||
{
|
||||
get => TimeDilationFactor != 1;
|
||||
get => timeDilationDatas.Count != 0;
|
||||
}
|
||||
|
||||
public void Update(double dt)
|
||||
{
|
||||
if (newTimeDilationData)
|
||||
for (var i = timeDilationDatas.Count - 1; i >= 0; i--)
|
||||
{
|
||||
timeDilationData = nextFrameTimeDilationData;
|
||||
}
|
||||
var data = timeDilationDatas[i];
|
||||
|
||||
timeDilationData.elapsedTime += dt;
|
||||
newTimeDilationData = false;
|
||||
minPriority = int.MaxValue;
|
||||
}
|
||||
data.elapsedTime += dt;
|
||||
|
||||
public void ActivateTimeDilation(double factor, double easeInTime, double activeTime, double easeOutTime, int priority)
|
||||
{
|
||||
ActivateTimeDilation(factor, easeInTime, Linear, activeTime, easeOutTime, Linear, priority);
|
||||
}
|
||||
|
||||
public void ActivateTimeDilation(double factor, double easeInTime, System.Func<double, double, double, double, double> easeInFunction, double activeTime, double easeOutTime, int priority)
|
||||
{
|
||||
ActivateTimeDilation(factor, easeInTime, easeInFunction, activeTime, easeOutTime, Linear, priority);
|
||||
}
|
||||
|
||||
public void ActivateTimeDilation(double factor, double easeInTime, double activeTime, double easeOutTime, System.Func<double, double, double, double, double> easeOutFunction, int priority)
|
||||
{
|
||||
ActivateTimeDilation(factor, easeInTime, Linear, activeTime, easeOutTime, easeOutFunction, priority);
|
||||
}
|
||||
|
||||
public void ActivateTimeDilation(double factor, double easeInTime, System.Func<double, double, double, double, double> easeInFunction, double activeTime, double easeOutTime, System.Func<double, double, double, double, double> easeOutFunction, int priority)
|
||||
{
|
||||
if (priority <= minPriority)
|
||||
{
|
||||
newTimeDilationData = true;
|
||||
nextFrameTimeDilationData = new TimeDilationData
|
||||
if (data.elapsedTime > data.easeInTime + data.activeTime + data.easeOutTime)
|
||||
{
|
||||
elapsedTime = 0,
|
||||
easeInTime = easeInTime,
|
||||
easeInFunction = easeInFunction,
|
||||
activeTime = activeTime,
|
||||
easeOutTime = easeOutTime,
|
||||
easeOutFunction = easeOutFunction,
|
||||
factor = factor
|
||||
};
|
||||
timeDilationDatas.RemoveAt(i);
|
||||
}
|
||||
else
|
||||
{
|
||||
timeDilationDatas[i] = data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ActivateTimeDilation(double factor, double easeInTime, double activeTime, double easeOutTime)
|
||||
{
|
||||
ActivateTimeDilation(factor, easeInTime, Linear, activeTime, easeOutTime, Linear);
|
||||
}
|
||||
|
||||
public void ActivateTimeDilation(double factor, double easeInTime, System.Func<double, double, double, double, double> easeInFunction, double activeTime, double easeOutTime)
|
||||
{
|
||||
ActivateTimeDilation(factor, easeInTime, easeInFunction, activeTime, easeOutTime, Linear);
|
||||
}
|
||||
|
||||
public void ActivateTimeDilation(double factor, double easeInTime, double activeTime, double easeOutTime, System.Func<double, double, double, double, double> easeOutFunction)
|
||||
{
|
||||
ActivateTimeDilation(factor, easeInTime, Linear, activeTime, easeOutTime, easeOutFunction);
|
||||
}
|
||||
|
||||
public void ActivateTimeDilation(double factor, double easeInTime, System.Func<double, double, double, double, double> easeInFunction, double activeTime, double easeOutTime, System.Func<double, double, double, double, double> easeOutFunction)
|
||||
{
|
||||
timeDilationDatas.Add(new TimeDilationData
|
||||
{
|
||||
elapsedTime = 0,
|
||||
easeInTime = easeInTime,
|
||||
easeInFunction = easeInFunction,
|
||||
activeTime = activeTime,
|
||||
easeOutTime = easeOutTime,
|
||||
easeOutFunction = easeOutFunction,
|
||||
factor = factor
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -234,22 +234,8 @@ namespace Encompass
|
|||
var writePriorities = new Dictionary<Type, HashSet<int>>();
|
||||
var writeMessageToEngines = new Dictionary<Type, List<Engine>>();
|
||||
|
||||
var timeDilationPriorities = new Dictionary<int, HashSet<Engine>>();
|
||||
|
||||
foreach (var engine in engines)
|
||||
{
|
||||
var timeDilationPriorityAttribute = engine.GetType().GetCustomAttribute<TimeDilationPriority>();
|
||||
|
||||
if (timeDilationPriorityAttribute != null)
|
||||
{
|
||||
engine.timeDilationPriority = timeDilationPriorityAttribute.timeDilationPriority;
|
||||
if (!timeDilationPriorities.ContainsKey(timeDilationPriorityAttribute.timeDilationPriority))
|
||||
{
|
||||
timeDilationPriorities.Add(timeDilationPriorityAttribute.timeDilationPriority, new HashSet<Engine>());
|
||||
}
|
||||
timeDilationPriorities[timeDilationPriorityAttribute.timeDilationPriority].Add(engine);
|
||||
}
|
||||
|
||||
if (engine.GetType().GetCustomAttribute<IgnoresTimeDilation>() != null)
|
||||
{
|
||||
engine.usesTimeDilation = false;
|
||||
|
@ -344,18 +330,6 @@ namespace Encompass
|
|||
throw new EngineWriteConflictException(errorString);
|
||||
}
|
||||
|
||||
foreach (var timeDilationEngines in timeDilationPriorities)
|
||||
{
|
||||
var priority = timeDilationEngines.Key;
|
||||
var engines = timeDilationEngines.Value;
|
||||
if (engines.Count > 1)
|
||||
{
|
||||
var errorString = "Multiple Engines have the same Time Dilation Priority value: ";
|
||||
errorString += string.Join(", ", engines);
|
||||
throw new TimeDilationPriorityConflictException(errorString);
|
||||
}
|
||||
}
|
||||
|
||||
var engineOrder = new List<Engine>();
|
||||
foreach (var engine in engineGraph.TopologicalSort())
|
||||
{
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<RootNamespace>Encompass</RootNamespace>
|
||||
<PackageId>EncompassECS.Framework</PackageId>
|
||||
<Version>0.16.0</Version>
|
||||
<Version>0.17.0-preview2</Version>
|
||||
<Authors>Evan Hemsley</Authors>
|
||||
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
|
||||
<Company>Moonside Games</Company>
|
||||
|
|
|
@ -960,7 +960,6 @@ namespace Tests
|
|||
|
||||
static double dilatedDeltaTime;
|
||||
|
||||
[TimeDilationPriority(0)]
|
||||
class ActivateTimeDilationEngine : Engine
|
||||
{
|
||||
public override void Update(double dt)
|
||||
|
@ -1001,54 +1000,41 @@ namespace Tests
|
|||
dilatedDeltaTime.Should().BeApproximately(0.3, 0.01);
|
||||
}
|
||||
|
||||
class ActivateTimeDilationWithoutPriorityEngine : Engine
|
||||
class ActivateTimeDilationLowerFactorEngine : Engine
|
||||
{
|
||||
private bool activated = false;
|
||||
|
||||
public override void Update(double dt)
|
||||
{
|
||||
ActivateTimeDilation(0.2, 1, 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ActivateTimeDilationWithoutPriorityThrows()
|
||||
{
|
||||
var worldBuilder = new WorldBuilder();
|
||||
worldBuilder.AddEngine(new ActivateTimeDilationWithoutPriorityEngine());
|
||||
|
||||
var world = worldBuilder.Build();
|
||||
|
||||
Assert.Throws<TimeDilationPriorityUndefinedException>(() => world.Update(0.01));
|
||||
}
|
||||
|
||||
[TimeDilationPriority(0)]
|
||||
class ActivateTimeDilationLowerPriorityEngine : Engine
|
||||
{
|
||||
public override void Update(double dt)
|
||||
{
|
||||
if (!TimeDilationActive)
|
||||
if (!activated)
|
||||
{
|
||||
ActivateTimeDilation(0.2, 1, 1, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
dilatedDeltaTime = dt;
|
||||
activated = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[TimeDilationPriority(1)]
|
||||
class ActivateTimeDilationHigherPriorityEngine : Engine
|
||||
class ActivateTimeDilationHigherFactorEngine : Engine
|
||||
{
|
||||
private bool activated = false;
|
||||
|
||||
public override void Update(double dt)
|
||||
{
|
||||
if (!activated)
|
||||
{
|
||||
ActivateTimeDilation(0.5, 1, 1, 1);
|
||||
activated = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool timeDilationActive;
|
||||
class ReadDilatedDeltaTimeEngine : Engine
|
||||
{
|
||||
public override void Update(double dt)
|
||||
{
|
||||
if (!TimeDilationActive)
|
||||
{
|
||||
ActivateTimeDilation(0.5, 1, 1, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
dilatedDeltaTime = dt;
|
||||
}
|
||||
dilatedDeltaTime = dt;
|
||||
timeDilationActive = TimeDilationActive;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1056,26 +1042,23 @@ namespace Tests
|
|||
public void MultipleActivateTimeDilation()
|
||||
{
|
||||
var worldBuilder = new WorldBuilder();
|
||||
worldBuilder.AddEngine(new ActivateTimeDilationLowerPriorityEngine());
|
||||
worldBuilder.AddEngine(new ActivateTimeDilationHigherPriorityEngine());
|
||||
worldBuilder.AddEngine(new ReadDilatedDeltaTimeEngine());
|
||||
worldBuilder.AddEngine(new ActivateTimeDilationLowerFactorEngine());
|
||||
worldBuilder.AddEngine(new ActivateTimeDilationHigherFactorEngine());
|
||||
|
||||
var world = worldBuilder.Build();
|
||||
|
||||
world.Update(0.01); // activate time dilation
|
||||
|
||||
world.Update(0.5);
|
||||
world.Update(0.5); // 0.3 and 0.375
|
||||
|
||||
dilatedDeltaTime.Should().BeApproximately(0.3, 0.01);
|
||||
}
|
||||
dilatedDeltaTime.Should().BeApproximately(0.3375, 0.01);
|
||||
timeDilationActive.Should().BeTrue();
|
||||
|
||||
[Test]
|
||||
public void MultipleActivateTimeDilationWithDuplicatePriority()
|
||||
{
|
||||
var worldBuilder = new WorldBuilder();
|
||||
worldBuilder.AddEngine(new ActivateTimeDilationEngine());
|
||||
worldBuilder.AddEngine(new ActivateTimeDilationLowerPriorityEngine());
|
||||
world.Update(5);
|
||||
|
||||
Assert.Throws<TimeDilationPriorityConflictException>(() => worldBuilder.Build());
|
||||
dilatedDeltaTime.Should().BeApproximately(5, 0.01);
|
||||
timeDilationActive.Should().BeFalse();
|
||||
}
|
||||
|
||||
static double undilatedDeltaTime;
|
||||
|
|
Loading…
Reference in New Issue