1
0
Fork 0
mirror of https://github.com/Ellpeck/MLEM.git synced 2024-11-22 20:58:34 +01:00

some element code cleanup

This commit is contained in:
Ellpeck 2020-05-17 00:59:15 +02:00
parent 85e63ac998
commit 5115bd8ca6
4 changed files with 80 additions and 77 deletions

View file

@ -10,6 +10,7 @@ namespace MLEM.Ui.Elements {
} }
public override void Draw(GameTime time, SpriteBatch batch, float alpha, BlendState blendState, SamplerState samplerState, Matrix matrix) { public override void Draw(GameTime time, SpriteBatch batch, float alpha, BlendState blendState, SamplerState samplerState, Matrix matrix) {
// since the group never accesses its own area when drawing, we have to update it manually
this.UpdateAreaIfDirty(); this.UpdateAreaIfDirty();
base.Draw(time, batch, alpha, blendState, samplerState, matrix); base.Draw(time, batch, alpha, blendState, samplerState, matrix);
} }

View file

@ -12,7 +12,11 @@ namespace MLEM.Ui.Elements {
private TextureRegion texture; private TextureRegion texture;
public TextureCallback GetTextureCallback; public TextureCallback GetTextureCallback;
public TextureRegion Texture { public TextureRegion Texture {
get => this.texture; get {
if (this.GetTextureCallback != null)
this.Texture = this.GetTextureCallback(this);
return this.texture;
}
set { set {
if (this.texture != value) { if (this.texture != value) {
this.texture = value; this.texture = value;
@ -53,33 +57,21 @@ namespace MLEM.Ui.Elements {
} }
protected override Vector2 CalcActualSize(RectangleF parentArea) { protected override Vector2 CalcActualSize(RectangleF parentArea) {
return this.texture != null && this.scaleToImage ? this.texture.Size.ToVector2() : base.CalcActualSize(parentArea); return this.Texture != null && this.scaleToImage ? this.Texture.Size.ToVector2() : base.CalcActualSize(parentArea);
}
public override void ForceUpdateArea() {
if (this.GetTextureCallback != null)
this.Texture = this.GetTextureCallback(this);
base.ForceUpdateArea();
}
public override void Update(GameTime time) {
base.Update(time);
if (this.GetTextureCallback != null)
this.Texture = this.GetTextureCallback(this);
} }
public override void Draw(GameTime time, SpriteBatch batch, float alpha, BlendState blendState, SamplerState samplerState, Matrix matrix) { public override void Draw(GameTime time, SpriteBatch batch, float alpha, BlendState blendState, SamplerState samplerState, Matrix matrix) {
if (this.texture == null) if (this.Texture == null)
return; return;
var center = new Vector2(this.texture.Width / 2F, this.texture.Height / 2F); var center = new Vector2(this.Texture.Width / 2F, this.Texture.Height / 2F);
var color = this.Color.OrDefault(Microsoft.Xna.Framework.Color.White) * alpha; var color = this.Color.OrDefault(Microsoft.Xna.Framework.Color.White) * alpha;
if (this.MaintainImageAspect) { if (this.MaintainImageAspect) {
var scale = Math.Min(this.DisplayArea.Width / this.texture.Width, this.DisplayArea.Height / this.texture.Height); var scale = Math.Min(this.DisplayArea.Width / this.Texture.Width, this.DisplayArea.Height / this.Texture.Height);
var imageOffset = new Vector2(this.DisplayArea.Width / 2F - this.texture.Width * scale / 2, this.DisplayArea.Height / 2F - this.texture.Height * scale / 2); var imageOffset = new Vector2(this.DisplayArea.Width / 2F - this.Texture.Width * scale / 2, this.DisplayArea.Height / 2F - this.Texture.Height * scale / 2);
batch.Draw(this.texture, this.DisplayArea.Location + center * scale + imageOffset, color, this.ImageRotation, center, scale * this.ImageScale, this.ImageEffects, 0); batch.Draw(this.Texture, this.DisplayArea.Location + center * scale + imageOffset, color, this.ImageRotation, center, scale * this.ImageScale, this.ImageEffects, 0);
} else { } else {
var scale = new Vector2(1F / this.texture.Width, 1F / this.texture.Height) * this.DisplayArea.Size; var scale = new Vector2(1F / this.Texture.Width, 1F / this.Texture.Height) * this.DisplayArea.Size;
batch.Draw(this.texture, this.DisplayArea.Location + center * scale, color, this.ImageRotation, center, scale * this.ImageScale, this.ImageEffects, 0); batch.Draw(this.Texture, this.DisplayArea.Location + center * scale, color, this.ImageRotation, center, scale * this.ImageScale, this.ImageEffects, 0);
} }
base.Draw(time, batch, alpha, blendState, samplerState, matrix); base.Draw(time, batch, alpha, blendState, samplerState, matrix);
} }

View file

@ -67,27 +67,9 @@ namespace MLEM.Ui.Elements {
} }
base.ForceUpdateArea(); base.ForceUpdateArea();
this.ScrollChildren(); this.ScrollChildren();
this.ScrollSetup();
if (this.scrollOverflow) {
// if there is only one child, then we have just the scroll bar
if (this.Children.Count == 1)
return;
// the "real" first child is the scroll bar, which we want to ignore
var firstChild = this.Children[1];
var lowestChild = this.GetLowestChild(e => !e.IsHidden);
// the max value of the scrollbar is the amount of non-scaled pixels taken up by overflowing components
var childrenHeight = lowestChild.Area.Bottom - firstChild.Area.Top;
this.ScrollBar.MaxValue = (childrenHeight - this.Area.Height) / this.Scale + this.ChildPadding.Height;
// update the render target
var targetArea = (Rectangle) this.GetRenderTargetArea();
if (this.renderTarget == null || targetArea.Width != this.renderTarget.Width || targetArea.Height != this.renderTarget.Height) {
if (this.renderTarget != null)
this.renderTarget.Dispose();
this.renderTarget = targetArea.IsEmpty ? null : new RenderTarget2D(this.System.GraphicsDevice, targetArea.Width, targetArea.Height);
}
}
} }
private void ScrollChildren() { private void ScrollChildren() {
@ -183,5 +165,27 @@ namespace MLEM.Ui.Elements {
this.Texture.SetFromStyle(style.PanelTexture); this.Texture.SetFromStyle(style.PanelTexture);
} }
protected virtual void ScrollSetup() {
if (!this.scrollOverflow)
return;
// if there is only one child, then we have just the scroll bar
if (this.Children.Count == 1)
return;
// the "real" first child is the scroll bar, which we want to ignore
var firstChild = this.Children[1];
var lowestChild = this.GetLowestChild(e => !e.IsHidden);
// the max value of the scrollbar is the amount of non-scaled pixels taken up by overflowing components
var childrenHeight = lowestChild.Area.Bottom - firstChild.Area.Top;
this.ScrollBar.MaxValue = (childrenHeight - this.Area.Height) / this.Scale + this.ChildPadding.Height;
// update the render target
var targetArea = (Rectangle) this.GetRenderTargetArea();
if (this.renderTarget == null || targetArea.Width != this.renderTarget.Width || targetArea.Height != this.renderTarget.Height) {
if (this.renderTarget != null)
this.renderTarget.Dispose();
this.renderTarget = targetArea.IsEmpty ? null : new RenderTarget2D(this.System.GraphicsDevice, targetArea.Width, targetArea.Height);
}
}
} }
} }

View file

@ -33,13 +33,16 @@ namespace MLEM.Ui.Elements {
public StyleProp<Color> TextColor; public StyleProp<Color> TextColor;
public StyleProp<float> TextScale; public StyleProp<float> TextScale;
public string Text { public string Text {
get => this.text; get {
this.QueryTextCallback();
return this.text;
}
set { set {
if (this.text != value) { if (this.text != value) {
this.text = value; this.text = value;
this.IsHidden = string.IsNullOrWhiteSpace(this.text); this.IsHidden = string.IsNullOrWhiteSpace(this.text);
this.SetAreaDirty(); this.SetAreaDirty();
// cause text to be re-tokenized // force text to be re-tokenized
this.TokenizedText = null; this.TokenizedText = null;
} }
} }
@ -70,51 +73,22 @@ namespace MLEM.Ui.Elements {
protected override Vector2 CalcActualSize(RectangleF parentArea) { protected override Vector2 CalcActualSize(RectangleF parentArea) {
var size = base.CalcActualSize(parentArea); var size = base.CalcActualSize(parentArea);
var sc = this.TextScale * this.Scale; this.ParseText(size);
// old formatting stuff // old formatting stuff
this.splitText = this.RegularFont.Value.SplitString(this.text.RemoveFormatting(this.RegularFont.Value), size.X - this.ScaledPadding.Width, sc);
this.Formatting = this.text.GetFormattingCodes(this.RegularFont.Value);
if (this.Formatting.Count > 0) { if (this.Formatting.Count > 0) {
var textDims = this.RegularFont.Value.MeasureString(this.splitText) * sc; var textDims = this.RegularFont.Value.MeasureString(this.splitText) * this.TextScale * this.Scale;
return new Vector2(this.AutoAdjustWidth ? textDims.X + this.ScaledPadding.Width : size.X, textDims.Y + this.ScaledPadding.Height); return new Vector2(this.AutoAdjustWidth ? textDims.X + this.ScaledPadding.Width : size.X, textDims.Y + this.ScaledPadding.Height);
} }
this.TokenizedText.Split(this.RegularFont, size.X - this.ScaledPadding.Width, sc); var dims = this.TokenizedText.Measure(this.RegularFont) * this.TextScale * this.Scale;
var linkTokens = this.TokenizedText.Tokens.Where(t => t.AppliedCodes.Any(c => c is LinkCode)).ToArray();
// this basically checks if there are any tokens that have an area that doesn't have a link element associated with it
if (linkTokens.Any(t => !t.GetArea(Vector2.Zero, this.TextScale).All(a => this.GetChildren<Link>(c => c.PositionOffset == a.Location && c.Size == a.Size).Any()))) {
this.RemoveChildren(c => c is Link);
foreach (var link in linkTokens) {
var areas = link.GetArea(Vector2.Zero, this.TextScale).ToArray();
for (var i = 0; i < areas.Length; i++) {
var area = areas[i];
this.AddChild(new Link(Anchor.TopLeft, link, area.Size) {
PositionOffset = area.Location,
// only allow selecting the first part of a link
CanBeSelected = i == 0
});
}
}
}
var dims = this.TokenizedText.Measure(this.RegularFont) * sc;
return new Vector2(this.AutoAdjustWidth ? dims.X + this.ScaledPadding.Width : size.X, dims.Y + this.ScaledPadding.Height); return new Vector2(this.AutoAdjustWidth ? dims.X + this.ScaledPadding.Width : size.X, dims.Y + this.ScaledPadding.Height);
} }
public override void ForceUpdateArea() {
if (this.GetTextCallback != null)
this.Text = this.GetTextCallback(this);
if (this.TokenizedText == null)
this.TokenizedText = this.System.TextFormatter.Tokenize(this.RegularFont, this.text);
base.ForceUpdateArea();
}
public override void Update(GameTime time) { public override void Update(GameTime time) {
this.QueryTextCallback();
base.Update(time); base.Update(time);
if (this.GetTextCallback != null)
this.Text = this.GetTextCallback(this);
this.TimeIntoAnimation += time.ElapsedGameTime; this.TimeIntoAnimation += time.ElapsedGameTime;
if (this.TokenizedText != null) if (this.TokenizedText != null)
@ -145,6 +119,38 @@ namespace MLEM.Ui.Elements {
this.FormatSettings.SetFromStyle(style.FormatSettings); this.FormatSettings.SetFromStyle(style.FormatSettings);
} }
protected virtual void ParseText(Vector2 size) {
// old formatting stuff
this.splitText = this.RegularFont.Value.SplitString(this.Text.RemoveFormatting(this.RegularFont.Value), size.X - this.ScaledPadding.Width, this.TextScale * this.Scale);
this.Formatting = this.Text.GetFormattingCodes(this.RegularFont.Value);
if (this.TokenizedText == null)
this.TokenizedText = this.System.TextFormatter.Tokenize(this.RegularFont, this.Text);
this.TokenizedText.Split(this.RegularFont, size.X - this.ScaledPadding.Width, this.TextScale * this.Scale);
var linkTokens = this.TokenizedText.Tokens.Where(t => t.AppliedCodes.Any(c => c is LinkCode)).ToArray();
// this basically checks if there are any tokens that have an area that doesn't have a link element associated with it
if (linkTokens.Any(t => !t.GetArea(Vector2.Zero, this.TextScale).All(a => this.GetChildren<Link>(c => c.PositionOffset == a.Location && c.Size == a.Size).Any()))) {
this.RemoveChildren(c => c is Link);
foreach (var link in linkTokens) {
var areas = link.GetArea(Vector2.Zero, this.TextScale).ToArray();
for (var i = 0; i < areas.Length; i++) {
var area = areas[i];
this.AddChild(new Link(Anchor.TopLeft, link, area.Size) {
PositionOffset = area.Location,
// only allow selecting the first part of a link
CanBeSelected = i == 0
});
}
}
}
}
private void QueryTextCallback() {
if (this.GetTextCallback != null)
this.Text = this.GetTextCallback(this);
}
public delegate string TextCallback(Paragraph paragraph); public delegate string TextCallback(Paragraph paragraph);
[Obsolete("Use the new text formatting system in MLEM.Formatting instead")] [Obsolete("Use the new text formatting system in MLEM.Formatting instead")]