1using System.Collections;
2using System.Runtime.Serialization;
22 private List<Frame> frameList;
25 private List<double?>? frameDurations;
31 frameDurations is not
null && index < frameDurations.Count ? frameDurations[index] :
null;
38 if (index < 0 || index >=
FrameCount)
throw new ArgumentOutOfRangeException(nameof(index));
39 if (seconds is { } duration && (!
double.IsFinite(duration) || duration <= 0))
40 throw new ArgumentOutOfRangeException(nameof(seconds));
42 frameDurations = frameDurations is
null ?
new List<double?>() :
new(frameDurations);
43 while (frameDurations.Count <
FrameCount) frameDurations.Add(
null);
44 frameDurations[index] = seconds;
47 internal void SetDurations(IEnumerable<double?> durations)
49 var values = durations.ToList();
50 if (values.Count !=
FrameCount || values.Any(v => v is { } d && (!
double.IsFinite(d) || d <= 0)))
51 throw new ArgumentException(
"Durations must match the sequence and be positive finite values or null.", nameof(durations));
52 frameDurations = values.Any(v => v.HasValue) ? values :
null;
55 private int currentFrameIdx;
56 private int curFrameIncrement;
57 private bool cycleFinished;
61 #region constructors / finalizer
69 frameList =
new List<Frame>();
73 curFrameIncrement = 1;
86 curFrameIncrement = 1;
91 private void OnDeserialized(StreamingContext context)
94 curFrameIncrement = 1;
98 #endregion constructors / finalizer
108 get {
return cycleFinished; }
119 if (frameList ==
null)
122 return frameList.Count;
134 if (frameList ==
null)
137 return frameList[currentFrameIdx];
147 get {
return currentFrameIdx; }
156 get {
return frameList.AsReadOnly(); }
159 #endregion properties
161 #region public methods
195 if (frameList ==
null)
198 frameList.Add(frame);
208 if (idx < frameList.Count)
210 frameList.RemoveAt(idx);
211 if (frameDurations is not
null && idx < frameDurations.Count)
213 frameDurations =
new(frameDurations);
214 frameDurations.RemoveAt(idx);
225 curFrameIncrement = 1;
228 #endregion public methods
230 #region internal methods
232 internal void StopCycle()
234 cycleFinished =
true;
237 internal Frame AdvanceFrame()
242 currentFrameIdx += curFrameIncrement;
243 if ((currentFrameIdx <= 0) || (currentFrameIdx >= frameList.Count - 1))
244 curFrameIncrement *= -1;
246 if (currentFrameIdx < 0)
249 if (currentFrameIdx > frameList.Count - 1)
250 currentFrameIdx = frameList.Count - 1;
252 cycleFinished =
false;
256 if (++currentFrameIdx >= frameList.Count)
259 cycleFinished =
false;
263 if (++currentFrameIdx > frameList.Count - 1)
265 currentFrameIdx = frameList.Count - 1;
266 cycleFinished =
true;
269 cycleFinished =
false;
273 throw new InvalidOperationException(
"Invalid CycleType: " +
SequenceCycleType.ToString());
276 return frameList[currentFrameIdx];
279 #endregion internal methods
281 #region private methods
283 private void SetDefaults()
285 frameList =
new List<Frame>();
288 curFrameIncrement = 1;
289 cycleFinished =
true;
292 #endregion private methods
303 get {
return frameList[frameIdx]; }
308 #region IEnumerable Members
316 for (
int i = 0; i < frameList.Count; i++)
317 yield
return frameList[i];
324 IEnumerator<Frame> IEnumerable<Frame>.GetEnumerator()
326 return frameList.GetEnumerator();
329 #endregion IEnumerable Members
Represents a rectangular region within a tilesheet that contains a grid of frames.
static readonly string DefaultRegionName
The default name assigned to tilesheet regions when no name is specified.
Represents a tilesheet image and metadata for rendering tiles.
CycleType
Simple is self-terminating; the other two are repeating.
double? GetDurationSeconds(int index)
Gets the optional display duration for a frame occurrence.
void RemoveFrame(int idx)
Removes the frame at the specified index from the sequence.
Frame AddFrame(Frame frame)
Adds an existing frame to the sequence.
Frame AddFrame(Tilesheet bmp, int xTile, int yTile)
Creates and adds a new frame to the sequence using tilesheet coordinates.
void Reset()
Resets the sequence to its initial state, starting from the first frame.
IList< Frame > FrameList
Gets a read-only view of the list of frames in the sequence.
Frame CurrentFrame
Gets the frame currently active in the animation sequence.
FrameSequence(Frame frame)
Initializes a new instance of the FrameSequence struct with a single frame.
int FrameCount
Gets the total number of frames in the sequence.
CycleType SequenceCycleType
The type of cycle pattern used when animating through the frame sequence.
void SetDurationSeconds(int index, double? seconds)
Sets a positive display duration, or null to use the cycle default.
Frame AddFrame(Tilesheet bmp, string regionName, int xTile, int yTile)
Creates and adds a new frame to the sequence using tilesheet coordinates.
FrameSequence(List< Frame > frames)
Initializes a new instance of the FrameSequence struct with a collection of frames.
int CurrentFrameIdx
Gets the zero-based index of the current frame in the sequence.
IEnumerator GetEnumerator()
Returns an enumerator that iterates through the frame sequence.
bool CycleFinished
Gets a value indicating whether the animation cycle has finished playing through the sequence.
Represents the source Tilesheet and its coordinates to render on a destination.