A game framework written with osu! in mind.
1// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
2// See the LICENCE file in the repository root for full licence text.
3
4using System;
5using System.Runtime.CompilerServices;
6using osu.Framework.Layout;
7
8namespace osu.Framework.Graphics
9{
10 /// <summary>
11 /// Contains the internal logic for the state management of <see cref="Drawable.Invalidate"/>.
12 /// </summary>
13 internal struct InvalidationList
14 {
15 private Invalidation selfInvalidation;
16 private Invalidation parentInvalidation;
17 private Invalidation childInvalidation;
18
19 /// <summary>
20 /// Creates a new <see cref="InvalidationList"/>.
21 /// </summary>
22 /// <param name="initialState">The initial invalidation state.</param>
23 public InvalidationList(Invalidation initialState)
24 {
25 this = default;
26
27 invalidate(ref selfInvalidation, initialState);
28 invalidate(ref parentInvalidation, initialState);
29 invalidate(ref childInvalidation, initialState);
30 }
31
32 /// <summary>
33 /// Invalidates a <see cref="InvalidationSource"/> with given <see cref="Invalidation"/> flags.
34 /// </summary>
35 /// <param name="source">The <see cref="InvalidationSource"/> to invalidate.</param>
36 /// <param name="flags">The <see cref="Invalidation"/> flags to invalidate with.</param>
37 /// <returns>Whether an invalidation was performed.</returns>
38 /// <exception cref="ArgumentException">If <see cref="InvalidationSource"/> was not a valid source.</exception>
39 [MethodImpl(MethodImplOptions.AggressiveInlining)]
40 public bool Invalidate(InvalidationSource source, Invalidation flags)
41 {
42 switch (source)
43 {
44 case InvalidationSource.Self:
45 return invalidate(ref selfInvalidation, flags);
46
47 case InvalidationSource.Parent:
48 return invalidate(ref parentInvalidation, flags);
49
50 case InvalidationSource.Child:
51 return invalidate(ref childInvalidation, flags);
52
53 default:
54 throw new ArgumentException("Unexpected invalidation source.", nameof(source));
55 }
56 }
57
58 /// <summary>
59 /// Validates all <see cref="InvalidationSource"/>s with given <see cref="Invalidation"/> flags.
60 /// </summary>
61 /// <param name="validation">The <see cref="Invalidation"/> flags to validate with.</param>
62 /// <returns>Whether any <see cref="InvalidationSource"/> was validated.</returns>
63 [MethodImpl(MethodImplOptions.AggressiveInlining)]
64 public bool Validate(Invalidation validation)
65 {
66 return validate(ref selfInvalidation, validation)
67 | validate(ref parentInvalidation, validation)
68 | validate(ref childInvalidation, validation);
69 }
70
71 [MethodImpl(MethodImplOptions.AggressiveInlining)]
72 private bool invalidate(ref Invalidation target, Invalidation flags)
73 {
74 if ((target & flags) == flags)
75 return false;
76
77 // Remove all non-layout flags, as they should always propagate and are thus not to be stored.
78 target |= flags & Invalidation.Layout;
79 return true;
80 }
81
82 [MethodImpl(MethodImplOptions.AggressiveInlining)]
83 private bool validate(ref Invalidation target, Invalidation flags)
84 {
85 if ((target & flags) == 0)
86 return false;
87
88 target &= ~flags;
89 return true;
90 }
91 }
92}