1
0
Fork 0
mirror of https://github.com/Ellpeck/MLEM.git synced 2024-05-18 23:21:22 +02:00

fixed some memory management issues in MLEM.Ui

This commit is contained in:
Ell 2022-11-24 18:38:51 +01:00
parent 9919ee4a97
commit e21729de67
5 changed files with 29 additions and 17 deletions

View file

@ -68,6 +68,10 @@ Fixes
- Fixed an exception when trying to force-update the area of an element without a ui system - Fixed an exception when trying to force-update the area of an element without a ui system
- Fixed the scroll bar of an empty panel being positioned incorrectly - Fixed the scroll bar of an empty panel being positioned incorrectly
- Fixed UiControls maintaining old input states when input types are toggled off - Fixed UiControls maintaining old input states when input types are toggled off
- Fixed an occasional deadlock when a game is disposed with a scrolling Panel present
Removals
- Marked Element.OnDisposed as obsolete in favor of the more predictable OnRemovedFromUi
### MLEM.Data ### MLEM.Data
Additions Additions

View file

@ -425,9 +425,10 @@ namespace MLEM.Ui.Elements {
/// </summary> /// </summary>
public GenericCallback OnRemovedFromUi; public GenericCallback OnRemovedFromUi;
/// <summary> /// <summary>
/// Event that is called when this element's <see cref="Dispose"/> method is called, which also happens in <see cref="Finalize"/>. /// Event that is called when this element's <see cref="Dispose"/> method is called.
/// This event is useful for unregistering global event handlers when this object should be destroyed. /// This event is useful for unregistering global event handlers when this object should be destroyed.
/// </summary> /// </summary>
[Obsolete("OnDisposed will be removed in a future update. To unregister custom event handlers, use OnRemovedFromUi instead.")]
public GenericCallback OnDisposed; public GenericCallback OnDisposed;
/// <summary> /// <summary>
@ -488,6 +489,7 @@ namespace MLEM.Ui.Elements {
} }
/// <inheritdoc /> /// <inheritdoc />
[Obsolete("Dispose will be removed in a future update. To unregister custom event handlers, use OnRemovedFromUi instead.")]
~Element() { ~Element() {
this.Dispose(); this.Dispose();
} }
@ -1098,6 +1100,7 @@ namespace MLEM.Ui.Elements {
} }
/// <summary>Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.</summary> /// <summary>Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.</summary>
[Obsolete("Dispose will be removed in a future update. To unregister custom event handlers, use OnRemovedFromUi instead.")]
public virtual void Dispose() { public virtual void Dispose() {
this.OnDisposed?.Invoke(this); this.OnDisposed?.Invoke(this);
GC.SuppressFinalize(this); GC.SuppressFinalize(this);

View file

@ -70,6 +70,13 @@ namespace MLEM.Ui.Elements {
this.scrollOverflow = scrollOverflow; this.scrollOverflow = scrollOverflow;
this.CanBeSelected = false; this.CanBeSelected = false;
// we dispose our render target when removing so that it doesn't cause a memory leak
// if we're added back afterwards, it'll be recreated in ScrollSetup anyway
this.OnRemovedFromUi += _ => {
this.renderTarget?.Dispose();
this.renderTarget = null;
};
if (scrollOverflow) { if (scrollOverflow) {
this.ScrollBar = new ScrollBar(Anchor.TopRight, Vector2.Zero, 0, 0) { this.ScrollBar = new ScrollBar(Anchor.TopRight, Vector2.Zero, 0, 0) {
OnValueChanged = (element, value) => this.ScrollChildren(), OnValueChanged = (element, value) => this.ScrollChildren(),
@ -177,15 +184,6 @@ namespace MLEM.Ui.Elements {
return base.GetElementUnderPos(position); return base.GetElementUnderPos(position);
} }
/// <inheritdoc />
public override void Dispose() {
if (this.renderTarget != null) {
this.renderTarget.Dispose();
this.renderTarget = null;
}
base.Dispose();
}
/// <summary> /// <summary>
/// Scrolls this panel's <see cref="ScrollBar"/> to the given <see cref="Element"/> in such a way that its center is positioned in the center of this panel. /// Scrolls this panel's <see cref="ScrollBar"/> to the given <see cref="Element"/> in such a way that its center is positioned in the center of this panel.
/// </summary> /// </summary>
@ -274,11 +272,13 @@ namespace MLEM.Ui.Elements {
// update the render target // update the render target
var targetArea = (Rectangle) this.GetRenderTargetArea(); var targetArea = (Rectangle) this.GetRenderTargetArea();
if (targetArea.Width <= 0 || targetArea.Height <= 0) if (targetArea.Width <= 0 || targetArea.Height <= 0) {
this.renderTarget?.Dispose();
this.renderTarget = null;
return; return;
}
if (this.renderTarget == null || targetArea.Width != this.renderTarget.Width || targetArea.Height != this.renderTarget.Height) { if (this.renderTarget == null || targetArea.Width != this.renderTarget.Width || targetArea.Height != this.renderTarget.Height) {
if (this.renderTarget != null) this.renderTarget?.Dispose();
this.renderTarget.Dispose();
this.renderTarget = targetArea.IsEmpty ? null : new RenderTarget2D(this.System.Game.GraphicsDevice, targetArea.Width, targetArea.Height); this.renderTarget = targetArea.IsEmpty ? null : new RenderTarget2D(this.System.Game.GraphicsDevice, targetArea.Width, targetArea.Height);
this.relevantChildrenDirty = true; this.relevantChildrenDirty = true;
} }

View file

@ -27,7 +27,7 @@ namespace MLEM.Ui.Parsers {
public static readonly ElementType[] ElementTypes = public static readonly ElementType[] ElementTypes =
#if NET6_0_OR_GREATER #if NET6_0_OR_GREATER
Enum.GetValues<ElementType>(); Enum.GetValues<ElementType>();
#else #else
(ElementType[]) Enum.GetValues(typeof(ElementType)); (ElementType[]) Enum.GetValues(typeof(ElementType));
#endif #endif
@ -145,9 +145,15 @@ namespace MLEM.Ui.Parsers {
throw new NullReferenceException("A UI parser requires a GraphicsDevice for parsing images"); throw new NullReferenceException("A UI parser requires a GraphicsDevice for parsing images");
TextureRegion image = null; TextureRegion image = null;
LoadImageAsync();
return new Image(Anchor.AutoLeft, new Vector2(1, -1), _ => image) { return new Image(Anchor.AutoLeft, new Vector2(1, -1), _ => image) {
OnDisposed = e => image?.Texture.Dispose() OnAddedToUi = e => {
if (image == null)
LoadImageAsync();
},
OnRemovedFromUi = e => {
image?.Texture.Dispose();
image = null;
}
}; };
async void LoadImageAsync() { async void LoadImageAsync() {

View file

@ -411,7 +411,6 @@ namespace MLEM.Graphics {
this.indices?.Dispose(); this.indices?.Dispose();
foreach (var buffer in this.vertexBuffers) foreach (var buffer in this.vertexBuffers)
buffer.Dispose(); buffer.Dispose();
GC.SuppressFinalize(this);
} }
private Item Add(Texture2D texture, Vector2 pos, Vector2 offset, Vector2 size, float sin, float cos, Color color, Vector2 texTl, Vector2 texBr, float depth) { private Item Add(Texture2D texture, Vector2 pos, Vector2 offset, Vector2 size, float sin, float cos, Color color, Vector2 texTl, Vector2 texBr, float depth) {