Refactor FTL time tracking code to fix a UI bug (#26538)
The FTL UI on the shuttle console would reset the FTL progress bar every time you open it. This is because the server only sends "time until completion", not a start/end time. The FTL code now uses a separate start/end time so the exact same progress bar can be preserved. For convenience, I made a StartEndTime record struct that stores the actual tuple. This is now used by the code and has some helpers.
This commit is contained in:
committed by
GitHub
parent
72c6a14d59
commit
3b791459c7
@@ -5,6 +5,7 @@ using Content.Shared.Shuttles.BUIStates;
|
|||||||
using Content.Shared.Shuttles.Components;
|
using Content.Shared.Shuttles.Components;
|
||||||
using Content.Shared.Shuttles.Systems;
|
using Content.Shared.Shuttles.Systems;
|
||||||
using Content.Shared.Shuttles.UI.MapObjects;
|
using Content.Shared.Shuttles.UI.MapObjects;
|
||||||
|
using Content.Shared.Timing;
|
||||||
using Robust.Client.AutoGenerated;
|
using Robust.Client.AutoGenerated;
|
||||||
using Robust.Client.Graphics;
|
using Robust.Client.Graphics;
|
||||||
using Robust.Client.UserInterface;
|
using Robust.Client.UserInterface;
|
||||||
@@ -38,16 +39,11 @@ public sealed partial class MapScreen : BoxContainer
|
|||||||
private EntityUid? _shuttleEntity;
|
private EntityUid? _shuttleEntity;
|
||||||
|
|
||||||
private FTLState _state;
|
private FTLState _state;
|
||||||
private float _ftlDuration;
|
private StartEndTime _ftlTime;
|
||||||
|
|
||||||
private List<ShuttleBeaconObject> _beacons = new();
|
private List<ShuttleBeaconObject> _beacons = new();
|
||||||
private List<ShuttleExclusionObject> _exclusions = new();
|
private List<ShuttleExclusionObject> _exclusions = new();
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// When the next FTL state change happens.
|
|
||||||
/// </summary>
|
|
||||||
private TimeSpan _nextFtlTime;
|
|
||||||
|
|
||||||
private TimeSpan _nextPing;
|
private TimeSpan _nextPing;
|
||||||
private TimeSpan _pingCooldown = TimeSpan.FromSeconds(3);
|
private TimeSpan _pingCooldown = TimeSpan.FromSeconds(3);
|
||||||
private TimeSpan _nextMapDequeue;
|
private TimeSpan _nextMapDequeue;
|
||||||
@@ -114,8 +110,7 @@ public sealed partial class MapScreen : BoxContainer
|
|||||||
_beacons = state.Destinations;
|
_beacons = state.Destinations;
|
||||||
_exclusions = state.Exclusions;
|
_exclusions = state.Exclusions;
|
||||||
_state = state.FTLState;
|
_state = state.FTLState;
|
||||||
_ftlDuration = state.FTLDuration;
|
_ftlTime = state.FTLTime;
|
||||||
_nextFtlTime = _timing.CurTime + TimeSpan.FromSeconds(_ftlDuration);
|
|
||||||
MapRadar.InFtl = true;
|
MapRadar.InFtl = true;
|
||||||
MapFTLState.Text = Loc.GetString($"shuttle-console-ftl-state-{_state.ToString()}");
|
MapFTLState.Text = Loc.GetString($"shuttle-console-ftl-state-{_state.ToString()}");
|
||||||
|
|
||||||
@@ -511,20 +506,8 @@ public sealed partial class MapScreen : BoxContainer
|
|||||||
MapRebuildButton.Disabled = false;
|
MapRebuildButton.Disabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var ftlDiff = (float) (_nextFtlTime - _timing.CurTime).TotalSeconds;
|
var progress = _ftlTime.ProgressAt(curTime);
|
||||||
|
FTLBar.Value = float.IsFinite(progress) ? progress : 1;
|
||||||
float ftlRatio;
|
|
||||||
|
|
||||||
if (_ftlDuration.Equals(0f))
|
|
||||||
{
|
|
||||||
ftlRatio = 1f;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ftlRatio = Math.Clamp(1f - (ftlDiff / _ftlDuration), 0f, 1f);
|
|
||||||
}
|
|
||||||
|
|
||||||
FTLBar.Value = ftlRatio;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Draw(DrawingHandleScreen handle)
|
protected override void Draw(DrawingHandleScreen handle)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using Content.Shared.Shuttles.Systems;
|
using Content.Shared.Shuttles.Systems;
|
||||||
using Content.Shared.Tag;
|
using Content.Shared.Tag;
|
||||||
|
using Content.Shared.Timing;
|
||||||
using Robust.Shared.Audio;
|
using Robust.Shared.Audio;
|
||||||
using Robust.Shared.Map;
|
using Robust.Shared.Map;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
@@ -16,15 +17,15 @@ public sealed partial class FTLComponent : Component
|
|||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
public FTLState State = FTLState.Available;
|
public FTLState State = FTLState.Available;
|
||||||
|
|
||||||
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public StartEndTime StateTime;
|
||||||
|
|
||||||
[ViewVariables(VVAccess.ReadWrite)]
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
public float StartupTime = 0f;
|
public float StartupTime = 0f;
|
||||||
|
|
||||||
[ViewVariables(VVAccess.ReadWrite)]
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
public float TravelTime = 0f;
|
public float TravelTime = 0f;
|
||||||
|
|
||||||
[ViewVariables(VVAccess.ReadWrite)]
|
|
||||||
public float Accumulator = 0f;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Coordinates to arrive it: May be relative to another grid (for docking) or map coordinates.
|
/// Coordinates to arrive it: May be relative to another grid (for docking) or map coordinates.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ using Content.Shared.Shuttles.Systems;
|
|||||||
using Content.Shared.Tag;
|
using Content.Shared.Tag;
|
||||||
using Content.Shared.Movement.Systems;
|
using Content.Shared.Movement.Systems;
|
||||||
using Content.Shared.Shuttles.UI.MapObjects;
|
using Content.Shared.Shuttles.UI.MapObjects;
|
||||||
|
using Content.Shared.Timing;
|
||||||
using Robust.Server.GameObjects;
|
using Robust.Server.GameObjects;
|
||||||
using Robust.Shared.Collections;
|
using Robust.Shared.Collections;
|
||||||
using Robust.Shared.GameStates;
|
using Robust.Shared.GameStates;
|
||||||
@@ -257,7 +258,11 @@ public sealed partial class ShuttleConsoleSystem : SharedShuttleConsoleSystem
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
navState = new NavInterfaceState(0f, null, null, new Dictionary<NetEntity, List<DockingPortState>>());
|
navState = new NavInterfaceState(0f, null, null, new Dictionary<NetEntity, List<DockingPortState>>());
|
||||||
mapState = new ShuttleMapInterfaceState(FTLState.Invalid, 0f, new List<ShuttleBeaconObject>(), new List<ShuttleExclusionObject>());
|
mapState = new ShuttleMapInterfaceState(
|
||||||
|
FTLState.Invalid,
|
||||||
|
default,
|
||||||
|
new List<ShuttleBeaconObject>(),
|
||||||
|
new List<ShuttleExclusionObject>());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_ui.TryGetUi(consoleUid, ShuttleConsoleUiKey.Key, out var bui))
|
if (_ui.TryGetUi(consoleUid, ShuttleConsoleUiKey.Key, out var bui))
|
||||||
@@ -408,12 +413,12 @@ public sealed partial class ShuttleConsoleSystem : SharedShuttleConsoleSystem
|
|||||||
public ShuttleMapInterfaceState GetMapState(Entity<FTLComponent?> shuttle)
|
public ShuttleMapInterfaceState GetMapState(Entity<FTLComponent?> shuttle)
|
||||||
{
|
{
|
||||||
FTLState ftlState = FTLState.Available;
|
FTLState ftlState = FTLState.Available;
|
||||||
float stateDuration = 0f;
|
StartEndTime stateDuration = default;
|
||||||
|
|
||||||
if (Resolve(shuttle, ref shuttle.Comp, false) && shuttle.Comp.LifeStage < ComponentLifeStage.Stopped)
|
if (Resolve(shuttle, ref shuttle.Comp, false) && shuttle.Comp.LifeStage < ComponentLifeStage.Stopped)
|
||||||
{
|
{
|
||||||
ftlState = shuttle.Comp.State;
|
ftlState = shuttle.Comp.State;
|
||||||
stateDuration = _shuttle.GetStateDuration(shuttle.Comp);
|
stateDuration = _shuttle.GetStateTime(shuttle.Comp);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<ShuttleBeaconObject>? beacons = null;
|
List<ShuttleBeaconObject>? beacons = null;
|
||||||
@@ -422,7 +427,8 @@ public sealed partial class ShuttleConsoleSystem : SharedShuttleConsoleSystem
|
|||||||
GetExclusions(ref exclusions);
|
GetExclusions(ref exclusions);
|
||||||
|
|
||||||
return new ShuttleMapInterfaceState(
|
return new ShuttleMapInterfaceState(
|
||||||
ftlState, stateDuration,
|
ftlState,
|
||||||
|
stateDuration,
|
||||||
beacons ?? new List<ShuttleBeaconObject>(),
|
beacons ?? new List<ShuttleBeaconObject>(),
|
||||||
exclusions ?? new List<ShuttleExclusionObject>());
|
exclusions ?? new List<ShuttleExclusionObject>());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ using Content.Shared.Parallax;
|
|||||||
using Content.Shared.Shuttles.Components;
|
using Content.Shared.Shuttles.Components;
|
||||||
using Content.Shared.Shuttles.Systems;
|
using Content.Shared.Shuttles.Systems;
|
||||||
using Content.Shared.StatusEffect;
|
using Content.Shared.StatusEffect;
|
||||||
|
using Content.Shared.Timing;
|
||||||
using Content.Shared.Whitelist;
|
using Content.Shared.Whitelist;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Robust.Shared.Audio;
|
using Robust.Shared.Audio;
|
||||||
@@ -131,7 +132,7 @@ public sealed partial class ShuttleSystem
|
|||||||
return mapUid;
|
return mapUid;
|
||||||
}
|
}
|
||||||
|
|
||||||
public float GetStateDuration(FTLComponent component)
|
public StartEndTime GetStateTime(FTLComponent component)
|
||||||
{
|
{
|
||||||
var state = component.State;
|
var state = component.State;
|
||||||
|
|
||||||
@@ -141,9 +142,9 @@ public sealed partial class ShuttleSystem
|
|||||||
case FTLState.Travelling:
|
case FTLState.Travelling:
|
||||||
case FTLState.Arriving:
|
case FTLState.Arriving:
|
||||||
case FTLState.Cooldown:
|
case FTLState.Cooldown:
|
||||||
return component.Accumulator;
|
return component.StateTime;
|
||||||
case FTLState.Available:
|
case FTLState.Available:
|
||||||
return 0f;
|
return default;
|
||||||
default:
|
default:
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
@@ -251,7 +252,9 @@ public sealed partial class ShuttleSystem
|
|||||||
|
|
||||||
hyperspace.StartupTime = startupTime;
|
hyperspace.StartupTime = startupTime;
|
||||||
hyperspace.TravelTime = hyperspaceTime;
|
hyperspace.TravelTime = hyperspaceTime;
|
||||||
hyperspace.Accumulator = hyperspace.StartupTime;
|
hyperspace.StateTime = StartEndTime.FromStartDuration(
|
||||||
|
_gameTiming.CurTime,
|
||||||
|
TimeSpan.FromSeconds(hyperspace.StartupTime));
|
||||||
hyperspace.TargetCoordinates = coordinates;
|
hyperspace.TargetCoordinates = coordinates;
|
||||||
hyperspace.TargetAngle = angle;
|
hyperspace.TargetAngle = angle;
|
||||||
hyperspace.PriorityTag = priorityTag;
|
hyperspace.PriorityTag = priorityTag;
|
||||||
@@ -282,7 +285,9 @@ public sealed partial class ShuttleSystem
|
|||||||
var config = _dockSystem.GetDockingConfig(shuttleUid, target, priorityTag);
|
var config = _dockSystem.GetDockingConfig(shuttleUid, target, priorityTag);
|
||||||
hyperspace.StartupTime = startupTime;
|
hyperspace.StartupTime = startupTime;
|
||||||
hyperspace.TravelTime = hyperspaceTime;
|
hyperspace.TravelTime = hyperspaceTime;
|
||||||
hyperspace.Accumulator = hyperspace.StartupTime;
|
hyperspace.StateTime = StartEndTime.FromStartDuration(
|
||||||
|
_gameTiming.CurTime,
|
||||||
|
TimeSpan.FromSeconds(hyperspace.StartupTime));
|
||||||
hyperspace.PriorityTag = priorityTag;
|
hyperspace.PriorityTag = priorityTag;
|
||||||
|
|
||||||
_console.RefreshShuttleConsoles(shuttleUid);
|
_console.RefreshShuttleConsoles(shuttleUid);
|
||||||
@@ -366,7 +371,7 @@ public sealed partial class ShuttleSystem
|
|||||||
// Reset rotation so they always face the same direction.
|
// Reset rotation so they always face the same direction.
|
||||||
xform.LocalRotation = Angle.Zero;
|
xform.LocalRotation = Angle.Zero;
|
||||||
_index += width + Buffer;
|
_index += width + Buffer;
|
||||||
comp.Accumulator += comp.TravelTime - DefaultArrivalTime;
|
comp.StateTime = StartEndTime.FromCurTime(_gameTiming, comp.TravelTime - DefaultArrivalTime);
|
||||||
|
|
||||||
Enable(uid, component: body);
|
Enable(uid, component: body);
|
||||||
_physics.SetLinearVelocity(uid, new Vector2(0f, 20f), body: body);
|
_physics.SetLinearVelocity(uid, new Vector2(0f, 20f), body: body);
|
||||||
@@ -401,7 +406,7 @@ public sealed partial class ShuttleSystem
|
|||||||
{
|
{
|
||||||
var shuttle = entity.Comp2;
|
var shuttle = entity.Comp2;
|
||||||
var comp = entity.Comp1;
|
var comp = entity.Comp1;
|
||||||
comp.Accumulator += DefaultArrivalTime;
|
comp.StateTime = StartEndTime.FromCurTime(_gameTiming, DefaultArrivalTime);
|
||||||
comp.State = FTLState.Arriving;
|
comp.State = FTLState.Arriving;
|
||||||
// TODO: Arrival effects
|
// TODO: Arrival effects
|
||||||
// For now we'll just use the ss13 bubbles but we can do fancier.
|
// For now we'll just use the ss13 bubbles but we can do fancier.
|
||||||
@@ -504,7 +509,7 @@ public sealed partial class ShuttleSystem
|
|||||||
}
|
}
|
||||||
|
|
||||||
comp.State = FTLState.Cooldown;
|
comp.State = FTLState.Cooldown;
|
||||||
comp.Accumulator += FTLCooldown;
|
comp.StateTime = StartEndTime.FromCurTime(_gameTiming, FTLCooldown);
|
||||||
_console.RefreshShuttleConsoles(uid);
|
_console.RefreshShuttleConsoles(uid);
|
||||||
_mapManager.SetMapPaused(mapId, false);
|
_mapManager.SetMapPaused(mapId, false);
|
||||||
Smimsh(uid, xform: xform);
|
Smimsh(uid, xform: xform);
|
||||||
@@ -519,15 +524,14 @@ public sealed partial class ShuttleSystem
|
|||||||
_console.RefreshShuttleConsoles(entity);
|
_console.RefreshShuttleConsoles(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateHyperspace(float frameTime)
|
private void UpdateHyperspace()
|
||||||
{
|
{
|
||||||
|
var curTime = _gameTiming.CurTime;
|
||||||
var query = EntityQueryEnumerator<FTLComponent, ShuttleComponent>();
|
var query = EntityQueryEnumerator<FTLComponent, ShuttleComponent>();
|
||||||
|
|
||||||
while (query.MoveNext(out var uid, out var comp, out var shuttle))
|
while (query.MoveNext(out var uid, out var comp, out var shuttle))
|
||||||
{
|
{
|
||||||
comp.Accumulator -= frameTime;
|
if (curTime < comp.StateTime.End)
|
||||||
|
|
||||||
if (comp.Accumulator > 0f)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var entity = (uid, comp, shuttle);
|
var entity = (uid, comp, shuttle);
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ using Robust.Shared.Physics;
|
|||||||
using Robust.Shared.Physics.Components;
|
using Robust.Shared.Physics.Components;
|
||||||
using Robust.Shared.Physics.Systems;
|
using Robust.Shared.Physics.Systems;
|
||||||
using Robust.Shared.Random;
|
using Robust.Shared.Random;
|
||||||
|
using Robust.Shared.Timing;
|
||||||
|
|
||||||
namespace Content.Server.Shuttles.Systems;
|
namespace Content.Server.Shuttles.Systems;
|
||||||
|
|
||||||
@@ -30,6 +31,7 @@ public sealed partial class ShuttleSystem : SharedShuttleSystem
|
|||||||
[Dependency] private readonly IMapManager _mapManager = default!;
|
[Dependency] private readonly IMapManager _mapManager = default!;
|
||||||
[Dependency] private readonly IRobustRandom _random = default!;
|
[Dependency] private readonly IRobustRandom _random = default!;
|
||||||
[Dependency] private readonly ITileDefinitionManager _tileDefManager = default!;
|
[Dependency] private readonly ITileDefinitionManager _tileDefManager = default!;
|
||||||
|
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||||
[Dependency] private readonly BiomeSystem _biomes = default!;
|
[Dependency] private readonly BiomeSystem _biomes = default!;
|
||||||
[Dependency] private readonly BodySystem _bobby = default!;
|
[Dependency] private readonly BodySystem _bobby = default!;
|
||||||
[Dependency] private readonly DockingSystem _dockSystem = default!;
|
[Dependency] private readonly DockingSystem _dockSystem = default!;
|
||||||
@@ -68,7 +70,7 @@ public sealed partial class ShuttleSystem : SharedShuttleSystem
|
|||||||
public override void Update(float frameTime)
|
public override void Update(float frameTime)
|
||||||
{
|
{
|
||||||
base.Update(frameTime);
|
base.Update(frameTime);
|
||||||
UpdateHyperspace(frameTime);
|
UpdateHyperspace();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnGridFixtureChange(EntityUid uid, FixturesComponent manager, GridFixtureChangeEvent args)
|
private void OnGridFixtureChange(EntityUid uid, FixturesComponent manager, GridFixtureChangeEvent args)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using Content.Shared.Shuttles.Systems;
|
using Content.Shared.Shuttles.Systems;
|
||||||
using Content.Shared.Shuttles.UI.MapObjects;
|
using Content.Shared.Shuttles.UI.MapObjects;
|
||||||
|
using Content.Shared.Timing;
|
||||||
using Robust.Shared.Serialization;
|
using Robust.Shared.Serialization;
|
||||||
|
|
||||||
namespace Content.Shared.Shuttles.BUIStates;
|
namespace Content.Shared.Shuttles.BUIStates;
|
||||||
@@ -16,9 +17,9 @@ public sealed class ShuttleMapInterfaceState
|
|||||||
public readonly FTLState FTLState;
|
public readonly FTLState FTLState;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// How long the FTL state takes.
|
/// When the current FTL state starts and ends.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public float FTLDuration;
|
public StartEndTime FTLTime;
|
||||||
|
|
||||||
public List<ShuttleBeaconObject> Destinations;
|
public List<ShuttleBeaconObject> Destinations;
|
||||||
|
|
||||||
@@ -26,12 +27,12 @@ public sealed class ShuttleMapInterfaceState
|
|||||||
|
|
||||||
public ShuttleMapInterfaceState(
|
public ShuttleMapInterfaceState(
|
||||||
FTLState ftlState,
|
FTLState ftlState,
|
||||||
float ftlDuration,
|
StartEndTime ftlTime,
|
||||||
List<ShuttleBeaconObject> destinations,
|
List<ShuttleBeaconObject> destinations,
|
||||||
List<ShuttleExclusionObject> exclusions)
|
List<ShuttleExclusionObject> exclusions)
|
||||||
{
|
{
|
||||||
FTLState = ftlState;
|
FTLState = ftlState;
|
||||||
FTLDuration = ftlDuration;
|
FTLTime = ftlTime;
|
||||||
Destinations = destinations;
|
Destinations = destinations;
|
||||||
Exclusions = exclusions;
|
Exclusions = exclusions;
|
||||||
}
|
}
|
||||||
|
|||||||
68
Content.Shared/Timing/StartEndTime.cs
Normal file
68
Content.Shared/Timing/StartEndTime.cs
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
using Robust.Shared.Timing;
|
||||||
|
|
||||||
|
namespace Content.Shared.Timing;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a range of an "action" in time, as start/end times.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Positions in time are represented as <see cref="TimeSpan"/>s, usually from <see cref="IGameTiming.CurTime"/>
|
||||||
|
/// or <see cref="IGameTiming.RealTime"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="Start">The time the action starts.</param>
|
||||||
|
/// <param name="End">The time action ends.</param>
|
||||||
|
[Serializable]
|
||||||
|
public record struct StartEndTime(TimeSpan Start, TimeSpan End)
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// How long the action takes.
|
||||||
|
/// </summary>
|
||||||
|
public TimeSpan Length => End - Start;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get how far the action has progressed relative to a time value.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="time">The time to get the current progress value for.</param>
|
||||||
|
/// <param name="clamp">If true, clamp values outside the time range to 0 through 1.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// <para>
|
||||||
|
/// A progress value. Zero means <paramref name="time"/> is at <see cref="Start"/>,
|
||||||
|
/// one means <paramref name="time"/> is at <see cref="End"/>.
|
||||||
|
/// </para>
|
||||||
|
/// <para>
|
||||||
|
/// This function returns <see cref="float.NaN"/> if <see cref="Start"/> and <see cref="End"/> are identical.
|
||||||
|
/// </para>
|
||||||
|
/// </returns>
|
||||||
|
public float ProgressAt(TimeSpan time, bool clamp = true)
|
||||||
|
{
|
||||||
|
var length = Length;
|
||||||
|
if (length == default)
|
||||||
|
return float.NaN;
|
||||||
|
|
||||||
|
var progress = (float) ((time - Start) / length);
|
||||||
|
if (clamp)
|
||||||
|
progress = MathHelper.Clamp01(progress);
|
||||||
|
|
||||||
|
return progress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static StartEndTime FromStartDuration(TimeSpan start, TimeSpan duration)
|
||||||
|
{
|
||||||
|
return new StartEndTime(start, start + duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static StartEndTime FromStartDuration(TimeSpan start, float durationSeconds)
|
||||||
|
{
|
||||||
|
return new StartEndTime(start, start + TimeSpan.FromSeconds(durationSeconds));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static StartEndTime FromCurTime(IGameTiming gameTiming, TimeSpan duration)
|
||||||
|
{
|
||||||
|
return FromStartDuration(gameTiming.CurTime, duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static StartEndTime FromCurTime(IGameTiming gameTiming, float durationSeconds)
|
||||||
|
{
|
||||||
|
return FromStartDuration(gameTiming.CurTime, durationSeconds);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user