A game framework written with osu! in mind.
at master 138 lines 4.0 kB view raw
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 osu.Framework.Allocation; 6using osu.Framework.Graphics.Containers; 7using osu.Framework.IO.Stores; 8using osu.Framework.Layout; 9using osuTK; 10using osuTK.Graphics; 11 12namespace osu.Framework.Graphics.Sprites 13{ 14 /// <summary> 15 /// A sprite representing an icon. 16 /// Uses <see cref="FontStore"/> to perform character lookups. 17 /// </summary> 18 public class SpriteIcon : CompositeDrawable 19 { 20 private Sprite spriteShadow; 21 private Sprite spriteMain; 22 23 private readonly LayoutValue layout = new LayoutValue(Invalidation.Colour, conditions: (s, _) => ((SpriteIcon)s).Shadow); 24 private Container shadowVisibility; 25 26 private FontStore store; 27 28 public SpriteIcon() 29 { 30 AddLayout(layout); 31 } 32 33 [BackgroundDependencyLoader] 34 private void load(FontStore store) 35 { 36 this.store = store; 37 38 InternalChildren = new Drawable[] 39 { 40 shadowVisibility = new Container 41 { 42 Anchor = Anchor.Centre, 43 Origin = Anchor.Centre, 44 RelativeSizeAxes = Axes.Both, 45 Child = spriteShadow = new Sprite 46 { 47 Anchor = Anchor.Centre, 48 Origin = Anchor.Centre, 49 RelativeSizeAxes = Axes.Both, 50 FillMode = FillMode.Fit, 51 Y = 2, 52 Colour = new Color4(0f, 0f, 0f, 0.2f), 53 }, 54 Alpha = shadow ? 1 : 0, 55 }, 56 spriteMain = new Sprite 57 { 58 Anchor = Anchor.Centre, 59 Origin = Anchor.Centre, 60 RelativeSizeAxes = Axes.Both, 61 FillMode = FillMode.Fit 62 }, 63 }; 64 65 updateTexture(); 66 } 67 68 protected override void LoadComplete() 69 { 70 base.LoadComplete(); 71 updateTexture(); 72 } 73 74 private IconUsage loadedIcon; 75 76 private void updateTexture() 77 { 78 var loadableIcon = icon; 79 80 if (loadableIcon.Equals(loadedIcon)) return; 81 82 var glyph = store.Get(loadableIcon.FontName, Icon.Icon); 83 84 if (glyph != null) 85 { 86 spriteMain.Texture = glyph.Texture; 87 spriteShadow.Texture = glyph.Texture; 88 89 if (Size == Vector2.Zero) 90 Size = new Vector2(glyph.Width, glyph.Height); 91 } 92 93 loadedIcon = loadableIcon; 94 } 95 96 protected override void Update() 97 { 98 if (!layout.IsValid) 99 { 100 //adjust shadow alpha based on highest component intensity to avoid muddy display of darker text. 101 //squared result for quadratic fall-off seems to give the best result. 102 var avgColour = (Color4)DrawColourInfo.Colour.AverageColour; 103 104 spriteShadow.Alpha = MathF.Pow(Math.Max(Math.Max(avgColour.R, avgColour.G), avgColour.B), 2); 105 106 layout.Validate(); 107 } 108 } 109 110 private bool shadow; 111 112 public bool Shadow 113 { 114 get => shadow; 115 set 116 { 117 shadow = value; 118 if (shadowVisibility != null) 119 shadowVisibility.Alpha = value ? 1 : 0; 120 } 121 } 122 123 private IconUsage icon; 124 125 public IconUsage Icon 126 { 127 get => icon; 128 set 129 { 130 if (icon.Equals(value)) return; 131 132 icon = value; 133 if (LoadState == LoadState.Loaded) 134 updateTexture(); 135 } 136 } 137 } 138}