···5353 });
5454 }
55555656+#pragma warning disable RS0030 // (banned API)
5657 /// <summary>
5758 /// A fast alternative functionally equivalent to <see cref="Enum.HasFlag"/>, eliminating boxing in all scenarios.
5859 /// </summary>
5960 /// <param name="enumValue">The enum to check.</param>
6061 /// <param name="flag">The flag to check for.</param>
6262+#pragma warning restore RS0030
6163 [MethodImpl(MethodImplOptions.AggressiveInlining)]
6264 public static unsafe bool HasFlagFast<T>(this T enumValue, T flag) where T : unmanaged, Enum
6365 {
···55using System.Collections.Generic;
66using osuTK;
77using System.Linq;
88+using osu.Framework.Extensions.EnumExtensions;
89using osu.Framework.Utils;
9101011namespace osu.Framework.Graphics.Containers
···8788 private Vector2 spacingFactor(Drawable c)
8889 {
8990 Vector2 result = c.RelativeOriginPosition;
9090- if (c.Anchor.HasFlag(Anchor.x2))
9191+ if (c.Anchor.HasFlagFast(Anchor.x2))
9192 result.X = 1 - result.X;
9292- if (c.Anchor.HasFlag(Anchor.y2))
9393+ if (c.Anchor.HasFlagFast(Anchor.y2))
9394 result.Y = 1 - result.Y;
9495 return result;
9596 }
···104105105106 // If we are autosize and haven't specified a maximum size, we should allow infinite expansion.
106107 // If we are inheriting then we need to use the parent size (our ActualSize).
107107- max.X = AutoSizeAxes.HasFlag(Axes.X) ? float.MaxValue : s.X;
108108- max.Y = AutoSizeAxes.HasFlag(Axes.Y) ? float.MaxValue : s.Y;
108108+ max.X = AutoSizeAxes.HasFlagFast(Axes.X) ? float.MaxValue : s.X;
109109+ max.Y = AutoSizeAxes.HasFlagFast(Axes.Y) ? float.MaxValue : s.Y;
109110 }
110111111112 var children = FlowingChildren.ToArray();
···262263 break;
263264 }
264265265265- if (c.Anchor.HasFlag(Anchor.x1))
266266+ if (c.Anchor.HasFlagFast(Anchor.x1))
266267 // Begin flow at centre of row
267268 result[i].X += rowOffsetsToMiddle[rowIndices[i]];
268268- else if (c.Anchor.HasFlag(Anchor.x2))
269269+ else if (c.Anchor.HasFlagFast(Anchor.x2))
269270 // Flow right-to-left
270271 result[i].X = -result[i].X;
271272272272- if (c.Anchor.HasFlag(Anchor.y1))
273273+ if (c.Anchor.HasFlagFast(Anchor.y1))
273274 // Begin flow at centre of total height
274275 result[i].Y -= height / 2;
275275- else if (c.Anchor.HasFlag(Anchor.y2))
276276+ else if (c.Anchor.HasFlagFast(Anchor.y2))
276277 // Flow bottom-to-top
277278 result[i].Y = -result[i].Y;
278279 }
···1010using Markdig.Syntax.Inlines;
1111using osu.Framework.Allocation;
1212using osu.Framework.Caching;
1313+using osu.Framework.Extensions.EnumExtensions;
1314using osu.Framework.Graphics.Sprites;
1415using osuTK;
1516···3738 get => base.AutoSizeAxes;
3839 set
3940 {
4040- if (value.HasFlag(Axes.X))
4141+ if (value.HasFlagFast(Axes.X))
4142 throw new ArgumentException($"{nameof(MarkdownContainer)} does not support an {nameof(AutoSizeAxes)} of {value}");
42434344 base.AutoSizeAxes = value;
···77using System.Collections.Generic;
88using System.Linq;
99using System.Text;
1010+using osu.Framework.Extensions.EnumExtensions;
10111112namespace osu.Framework.Graphics.Containers
1213{
···192193 {
193194 // FillFlowContainer will reverse the ordering of right-anchored words such that the (previously) first word would be
194195 // the right-most word, whereas it should still be flowed left-to-right. This is achieved by reversing the comparator.
195195- if (TextAnchor.HasFlag(Anchor.x2))
196196+ if (TextAnchor.HasFlagFast(Anchor.x2))
196197 return base.Compare(y, x);
197198198199 return base.Compare(x, y);
+19-18
osu.Framework/Graphics/Drawable.cs
···2525using JetBrains.Annotations;
2626using osu.Framework.Bindables;
2727using osu.Framework.Development;
2828+using osu.Framework.Extensions.EnumExtensions;
2829using osu.Framework.Graphics.Cursor;
2930using osu.Framework.Graphics.OpenGL;
3031using osu.Framework.Input.Bindings;
···661662 {
662663 offset = Parent.RelativeChildOffset;
663664664664- if (!RelativePositionAxes.HasFlag(Axes.X))
665665+ if (!RelativePositionAxes.HasFlagFast(Axes.X))
665666 offset.X = 0;
666667667667- if (!RelativePositionAxes.HasFlag(Axes.Y))
668668+ if (!RelativePositionAxes.HasFlagFast(Axes.Y))
668669 offset.Y = 0;
669670 }
670671···790791791792 relativeSizeAxes = value;
792793793793- if (relativeSizeAxes.HasFlag(Axes.X) && Width == 0) Width = 1;
794794- if (relativeSizeAxes.HasFlag(Axes.Y) && Height == 0) Height = 1;
794794+ if (relativeSizeAxes.HasFlagFast(Axes.X) && Width == 0) Width = 1;
795795+ if (relativeSizeAxes.HasFlagFast(Axes.Y) && Height == 0) Height = 1;
795796796797 updateBypassAutoSizeAxes();
797798···885886 {
886887 Vector2 conversion = relativeToAbsoluteFactor;
887888888888- if (relativeAxes.HasFlag(Axes.X))
889889+ if (relativeAxes.HasFlagFast(Axes.X))
889890 v.X *= conversion.X;
890890- if (relativeAxes.HasFlag(Axes.Y))
891891+ if (relativeAxes.HasFlagFast(Axes.Y))
891892 v.Y *= conversion.Y;
892893893894 // FillMode only makes sense if both axes are relatively sized as the general rule
···11221123 throw new InvalidOperationException(@"Can not obtain relative origin position for custom origins.");
1123112411241125 Vector2 result = Vector2.Zero;
11251125- if (origin.HasFlag(Anchor.x1))
11261126+ if (origin.HasFlagFast(Anchor.x1))
11261127 result.X = 0.5f;
11271127- else if (origin.HasFlag(Anchor.x2))
11281128+ else if (origin.HasFlagFast(Anchor.x2))
11281129 result.X = 1;
1129113011301130- if (origin.HasFlag(Anchor.y1))
11311131+ if (origin.HasFlagFast(Anchor.y1))
11311132 result.Y = 0.5f;
11321132- else if (origin.HasFlag(Anchor.y2))
11331133+ else if (origin.HasFlagFast(Anchor.y2))
11331134 result.Y = 1;
1134113511351136 return result;
···12111212 return customRelativeAnchorPosition;
1212121312131214 Vector2 result = Vector2.Zero;
12141214- if (anchor.HasFlag(Anchor.x1))
12151215+ if (anchor.HasFlagFast(Anchor.x1))
12151216 result.X = 0.5f;
12161216- else if (anchor.HasFlag(Anchor.x2))
12171217+ else if (anchor.HasFlagFast(Anchor.x2))
12171218 result.X = 1;
1218121912191219- if (anchor.HasFlag(Anchor.y1))
12201220+ if (anchor.HasFlagFast(Anchor.y1))
12201221 result.Y = 0.5f;
12211221- else if (anchor.HasFlag(Anchor.y2))
12221222+ else if (anchor.HasFlagFast(Anchor.y2))
12221223 result.Y = 1;
1223122412241225 return result;
···12561257 {
12571258 Vector2 result = Vector2.Zero;
1258125912591259- if (anchor.HasFlag(Anchor.x1))
12601260+ if (anchor.HasFlagFast(Anchor.x1))
12601261 result.X = size.X / 2f;
12611261- else if (anchor.HasFlag(Anchor.x2))
12621262+ else if (anchor.HasFlagFast(Anchor.x2))
12621263 result.X = size.X;
1263126412641264- if (anchor.HasFlag(Anchor.y1))
12651265+ if (anchor.HasFlagFast(Anchor.y1))
12651266 result.Y = size.Y / 2f;
12661266- else if (anchor.HasFlag(Anchor.y2))
12671267+ else if (anchor.HasFlagFast(Anchor.y2))
12671268 result.Y = size.Y;
1268126912691270 return result;
+3-2
osu.Framework/Graphics/Lines/Path.cs
···99using osu.Framework.Allocation;
1010using System.Collections.Generic;
1111using osu.Framework.Caching;
1212+using osu.Framework.Extensions.EnumExtensions;
1213using osuTK.Graphics;
1314using osuTK.Graphics.ES30;
1415···113114 {
114115 get
115116 {
116116- if (AutoSizeAxes.HasFlag(Axes.X))
117117+ if (AutoSizeAxes.HasFlagFast(Axes.X))
117118 return base.Width = vertexBounds.Width;
118119119120 return base.Width;
···131132 {
132133 get
133134 {
134134- if (AutoSizeAxes.HasFlag(Axes.Y))
135135+ if (AutoSizeAxes.HasFlagFast(Axes.Y))
135136 return base.Height = vertexBounds.Height;
136137137138 return base.Height;
···77using System.Linq;
88using JetBrains.Annotations;
99using osu.Framework.Bindables;
1010+using osu.Framework.Extensions.EnumExtensions;
1011using osu.Framework.Graphics.Containers;
1112using osu.Framework.Input;
1213using osu.Framework.Input.Bindings;
···168169169170 AddInternal(Dropdown);
170171171171- Trace.Assert(Dropdown.Header.Anchor.HasFlag(Anchor.x2), $@"The {nameof(Dropdown)} implementation should use a right-based anchor inside a TabControl.");
172172- Trace.Assert(!Dropdown.Header.RelativeSizeAxes.HasFlag(Axes.X), $@"The {nameof(Dropdown)} implementation's header should have a specific size.");
172172+ Trace.Assert(Dropdown.Header.Anchor.HasFlagFast(Anchor.x2), $@"The {nameof(Dropdown)} implementation should use a right-based anchor inside a TabControl.");
173173+ Trace.Assert(!Dropdown.Header.RelativeSizeAxes.HasFlagFast(Axes.X), $@"The {nameof(Dropdown)} implementation's header should have a specific size.");
173174 }
174175175176 AddInternal(TabContainer = CreateTabFlow());
···11// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
22// See the LICENCE file in the repository root for full licence text.
3344+using osu.Framework.Extensions.EnumExtensions;
45using osuTK;
56using osuTK.Input;
67···2930 }
30313132 Scroll = new Vector2(-tkState.Scroll.X, tkState.Scroll.Y);
3232- HasPreciseScroll = tkState.Flags.HasFlag(MouseStateFlags.HasPreciseScroll);
3333+ HasPreciseScroll = tkState.Flags.HasFlagFast(MouseStateFlags.HasPreciseScroll);
3334 Position = new Vector2(mappedPosition?.X ?? tkState.X, mappedPosition?.Y ?? tkState.Y);
3435 }
3536
···11// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
22// See the LICENCE file in the repository root for full licence text.
3344+using osu.Framework.Extensions.EnumExtensions;
45using osu.Framework.Input;
56using osuTK.Input;
67using SDL2;
···1314 {
1415 // Apple devices don't have the notion of NumLock (they have a Clear key instead).
1516 // treat them as if they always have NumLock on (the numpad always performs its primary actions).
1616- bool numLockOn = sdlKeysym.mod.HasFlag(SDL.SDL_Keymod.KMOD_NUM) || RuntimeInfo.IsApple;
1717+ bool numLockOn = sdlKeysym.mod.HasFlagFast(SDL.SDL_Keymod.KMOD_NUM) || RuntimeInfo.IsApple;
17181819 switch (sdlKeysym.scancode)
1920 {
···446447 public static WindowState ToWindowState(this SDL.SDL_WindowFlags windowFlags)
447448 {
448449 // NOTE: on macOS, SDL2 does not differentiate between "maximised" and "fullscreen desktop"
449449- if (windowFlags.HasFlag(SDL.SDL_WindowFlags.SDL_WINDOW_FULLSCREEN_DESKTOP) ||
450450- windowFlags.HasFlag(SDL.SDL_WindowFlags.SDL_WINDOW_BORDERLESS) ||
451451- windowFlags.HasFlag(SDL.SDL_WindowFlags.SDL_WINDOW_MAXIMIZED) && RuntimeInfo.OS == RuntimeInfo.Platform.MacOsx)
450450+ if (windowFlags.HasFlagFast(SDL.SDL_WindowFlags.SDL_WINDOW_FULLSCREEN_DESKTOP) ||
451451+ windowFlags.HasFlagFast(SDL.SDL_WindowFlags.SDL_WINDOW_BORDERLESS) ||
452452+ windowFlags.HasFlagFast(SDL.SDL_WindowFlags.SDL_WINDOW_MAXIMIZED) && RuntimeInfo.OS == RuntimeInfo.Platform.MacOsx)
452453 return WindowState.FullscreenBorderless;
453454454454- if (windowFlags.HasFlag(SDL.SDL_WindowFlags.SDL_WINDOW_MINIMIZED))
455455+ if (windowFlags.HasFlagFast(SDL.SDL_WindowFlags.SDL_WINDOW_MINIMIZED))
455456 return WindowState.Minimised;
456457457457- if (windowFlags.HasFlag(SDL.SDL_WindowFlags.SDL_WINDOW_FULLSCREEN))
458458+ if (windowFlags.HasFlagFast(SDL.SDL_WindowFlags.SDL_WINDOW_FULLSCREEN))
458459 return WindowState.Fullscreen;
459460460460- if (windowFlags.HasFlag(SDL.SDL_WindowFlags.SDL_WINDOW_MAXIMIZED))
461461+ if (windowFlags.HasFlagFast(SDL.SDL_WindowFlags.SDL_WINDOW_MAXIMIZED))
461462 return WindowState.Maximised;
462463463464 return WindowState.Normal;