Fixes, mem management, ui refactors

This commit is contained in:
Nahuel Rocchetti 2023-06-01 00:47:49 -03:00
parent 9f2933bcea
commit 7c7e5cbd70
22 changed files with 293 additions and 66 deletions

View file

@ -535,7 +535,7 @@ MonoBehaviour:
InitialLoadScreenBackgroundImage: {fileID: 19247262}
InitialLoadScreenLogoImage: {fileID: 1334026411}
InitialLoadScreenReiaPlayer: {fileID: 1690878381}
EnableReia: 1
EnableReia: 0
StreamReia: 0
--- !u!1 &1690878377
GameObject:
@ -635,6 +635,7 @@ GameObject:
- component: {fileID: 1755469746}
- component: {fileID: 1755469745}
- component: {fileID: 1755469744}
- component: {fileID: 1755469748}
m_Layer: 5
m_Name: Canvas
m_TagString: Untagged
@ -694,7 +695,7 @@ Canvas:
m_RenderMode: 0
m_Camera: {fileID: 0}
m_PlaneDistance: 100
m_PixelPerfect: 0
m_PixelPerfect: 1
m_ReceivesEvents: 1
m_OverrideSorting: 0
m_OverridePixelPerfect: 0
@ -725,6 +726,18 @@ RectTransform:
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0, y: 0}
--- !u!114 &1755469748
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1755469743}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: db3b6e6445c9df84bb2e95b9365382be, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!1 &1836641136
GameObject:
m_ObjectHideFlags: 0

View file

@ -154,7 +154,7 @@ MonoBehaviour:
m_EditorClassIdentifier:
Language: 1
Canvas: {fileID: 272227683}
Key: 0x49001000
Key: 0x0C7FE4BF
Reload: 0
LoadPackagesFromAllEPs: 1
--- !u!4 &28655043
@ -183,6 +183,7 @@ GameObject:
- component: {fileID: 272227682}
- component: {fileID: 272227681}
- component: {fileID: 272227680}
- component: {fileID: 272227684}
m_Layer: 5
m_Name: Canvas
m_TagString: Untagged
@ -242,7 +243,7 @@ Canvas:
m_RenderMode: 0
m_Camera: {fileID: 0}
m_PlaneDistance: 100
m_PixelPerfect: 0
m_PixelPerfect: 1
m_ReceivesEvents: 1
m_OverrideSorting: 0
m_OverridePixelPerfect: 0
@ -270,6 +271,18 @@ RectTransform:
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0, y: 0}
--- !u!114 &272227684
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 272227679}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: db3b6e6445c9df84bb2e95b9365382be, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!1 &1095143543
GameObject:
m_ObjectHideFlags: 0

View file

@ -6,6 +6,7 @@
using OpenTS2.Common;
using OpenTS2.Common.Utils;
using OpenTS2.Engine;
using OpenTS2.Files.Formats.DBPF;
using System;
using System.Collections.Generic;
@ -13,13 +14,14 @@ using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
namespace OpenTS2.Content
{
/// <summary>
/// Represents a saveable DBPF asset.
/// </summary>
public abstract class AbstractAsset : ICloneable
public abstract class AbstractAsset : ICloneable, IDisposable
{
/// <summary>
/// Global TGI.
@ -60,6 +62,7 @@ namespace OpenTS2.Content
}
}
bool _compressed = false;
public bool Disposed = false;
/// <summary>
/// Save changes to this asset in memory.
@ -102,5 +105,30 @@ namespace OpenTS2.Content
{
return new UnityEngine.Object[] { };
}
public Action OnCollection;
protected virtual void Dispose(bool disposing)
{
if (!Disposed)
{
var key = new CacheKey(TGI, Package);
MemoryController.MarkForRemoval(new MemoryController.RemovalInfo(key, GetUnmanagedResources()));
Disposed = true;
}
}
~AbstractAsset()
{
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
Dispose(disposing: false);
}
public void Dispose()
{
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
}
}

View file

@ -6,6 +6,7 @@
using OpenTS2.Common;
using OpenTS2.Common.Utils;
using OpenTS2.Engine;
using OpenTS2.Files.Formats.DBPF;
using System;
using System.Collections;
@ -65,30 +66,19 @@ namespace OpenTS2.Content
}
}
public class CacheValue
{
public WeakReference WeakRef;
public UnityEngine.Object[] UnmanagedResources;
public CacheValue(WeakReference weakReference, UnityEngine.Object[] unmanagedResources)
{
WeakRef = weakReference;
UnmanagedResources = unmanagedResources;
}
}
/// <summary>
/// Manages caching for game content.
/// </summary>
public class ContentCache
{
// Dictionary to contain the temporary cache.
public Dictionary<CacheKey, CacheValue> Cache;
public Dictionary<CacheKey, WeakReference> Cache;
public ContentProvider Provider;
public ContentCache(ContentProvider provider)
{
Provider = provider;
Cache = new Dictionary<CacheKey, CacheValue>();
Cache = new Dictionary<CacheKey, WeakReference>();
}
public void Clear()
@ -114,20 +104,20 @@ namespace OpenTS2.Content
WeakReference GetOrAddInternal(CacheKey key, Func<CacheKey, AbstractAsset> objectFactory)
{
if (Cache.TryGetValue(key, out CacheValue result))
if (Cache.TryGetValue(key, out WeakReference result))
{
if (result.WeakRef.Target != null && result.WeakRef.IsAlive)
if (result.Target != null && result.IsAlive && !(result.Target as AbstractAsset).Disposed)
{
return result.WeakRef;
return result;
}
else
{
var asset = objectFactory(key);
if (asset == null)
return null;
result = new CacheValue(new WeakReference(asset), asset.GetUnmanagedResources());
result = new WeakReference(asset);
Cache[key] = result;
return result.WeakRef;
return result;
}
}
else
@ -135,9 +125,9 @@ namespace OpenTS2.Content
var asset = objectFactory(key);
if (asset == null)
return null;
result = new CacheValue(new WeakReference(asset), asset.GetUnmanagedResources());
result = new WeakReference(asset);
Cache[key] = result;
return result.WeakRef;
return result;
}
}
@ -191,7 +181,7 @@ namespace OpenTS2.Content
public WeakReference GetWeakReference(CacheKey key)
{
if (Cache.ContainsKey(key))
return Cache[key].WeakRef;
return Cache[key];
return null;
}

View file

@ -13,26 +13,53 @@ namespace OpenTS2.Engine
/// </summary>
public class MemoryController : MonoBehaviour
{
private ContentCache _cache;
public static MemoryController Singleton => s_singleton;
static MemoryController s_singleton = null;
public struct RemovalInfo
{
public UnityEngine.Object[] UnmanagedResources;
public CacheKey Key;
public RemovalInfo(CacheKey key, UnityEngine.Object[] unmanagedResources)
{
Key = key;
UnmanagedResources = unmanagedResources;
}
}
private static List<RemovalInfo> MarkedForRemoval = new List<RemovalInfo>();
private void Awake()
{
_cache = ContentProvider.Get().Cache;
if (s_singleton != null)
{
Destroy(gameObject);
return;
}
s_singleton = this;
DontDestroyOnLoad(gameObject);
}
public static void MarkForRemoval(RemovalInfo info)
{
lock(MarkedForRemoval)
MarkedForRemoval.Add(info);
}
private void Update()
{
var markedForRemoval = new List<CacheKey>();
foreach(var item in _cache.Cache)
lock (MarkedForRemoval)
{
if (!item.Value.WeakRef.IsAlive)
foreach (var removal in MarkedForRemoval)
{
foreach (var unmanagedObject in item.Value.UnmanagedResources)
unmanagedObject.Free();
markedForRemoval.Add(item.Key);
foreach (var unmanagedResource in removal.UnmanagedResources)
{
unmanagedResource.Free();
}
var cache = ContentProvider.Get().Cache;
if (cache.Cache.TryGetValue(removal.Key, out WeakReference _))
{
cache.Cache.Remove(removal.Key);
}
}
}
foreach(var removal in markedForRemoval)
{
_cache.Cache.Remove(removal);
MarkedForRemoval.Clear();
}
}
}

View file

@ -4,7 +4,7 @@ MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
executionOrder: -80
icon: {instanceID: 0}
userData:
assetBundleName:

View file

@ -17,7 +17,6 @@ namespace OpenTS2.Engine.Tests
public class UILayoutTest : MonoBehaviour
{
public Languages Language = Languages.USEnglish;
public Transform Canvas;
public string Key = "0x49001017";
public bool Reload = false;
public bool LoadPackagesFromAllEPs = true;
@ -49,7 +48,7 @@ namespace OpenTS2.Engine.Tests
var contentProvider = ContentProvider.Get();
var key = new ResourceKey(Convert.ToUInt32(Key, 16), 0xA99D8A11, TypeIDs.UI);
var uiLayout = contentProvider.GetAsset<UILayout>(key);
_instances.AddRange(uiLayout.Instantiate(Canvas));
_instances.AddRange(uiLayout.Instantiate(UIManager.MainCanvas.transform));
}
catch(Exception e)
{

View file

@ -19,7 +19,6 @@ namespace OpenTS2.Scenes
{
public class StartupController : MonoBehaviour
{
public Transform Canvas;
public float FadeOutTime = 1f;
public AudioSource MusicSource;
public UIBMPComponent InitialLoadScreenBackgroundImage;
@ -104,7 +103,7 @@ namespace OpenTS2.Scenes
oMgr.Initialize();
CursorController.Cursor = CursorController.CursorType.Default;
Debug.Log("All loaded");
var mainMenu = new MainMenu(Canvas);
var mainMenu = new MainMenu();
FadeOutLoading();
}

View file

@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
namespace OpenTS2.UI
{
[RequireComponent(typeof(Canvas))]
public class CanvasController : MonoBehaviour
{
private void Awake()
{
UIManager.MainCanvas = GetComponent<Canvas>();
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: db3b6e6445c9df84bb2e95b9365382be
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: -90
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -102,7 +102,7 @@ namespace OpenTS2.UI {
if (!UIManager.HeldComponent.isActiveAndEnabled)
UIManager.HeldComponent = null;
}
if (Input.GetMouseButtonUp(0))
if (!Input.GetMouseButton(0))
{
UIManager.HeldComponent = null;
}

View file

@ -12,32 +12,31 @@ using UnityEngine;
namespace OpenTS2.UI.Layouts
{
public class MainMenu
public class MainMenu : UILayoutInstance
{
public UIComponent Root;
private static ResourceKey s_mainMenuKey = new ResourceKey(0x49001017, 0xA99D8A11, TypeIDs.UI);
public MainMenu(Transform canvas)
protected override ResourceKey UILayoutResourceKey => new ResourceKey(0x49001017, 0xA99D8A11, TypeIDs.UI);
public MainMenu() : this(MainCanvas)
{
var contentProvider = ContentProvider.Get();
var mainMenuLayout = contentProvider.GetAsset<UILayout>(s_mainMenuKey);
var components = mainMenuLayout.Instantiate(canvas);
}
Root = components[0];
Root.SetAnchor(UIComponent.AnchorType.Center);
Root.transform.SetAsFirstSibling();
public MainMenu(Transform canvas) : base(canvas)
{
var root = Components[0];
root.SetAnchor(UIComponent.AnchorType.Center);
root.transform.SetAsFirstSibling();
var background = Root.GetChildByID(0x0DA36C7D);
var background = root.GetChildByID(0x0DA36C7D);
background.gameObject.SetActive(true);
background.transform.SetParent(Root.transform.parent);
background.SetAnchor(UIComponent.AnchorType.Center);
background.transform.SetAsFirstSibling();
var upperLeftSim = Root.GetChildByID(0xE1) as UIBMPComponent;
var lowerRightSim = Root.GetChildByID(0xE3) as UIBMPComponent;
var upperLeftSim = root.GetChildByID(0xE1) as UIBMPComponent;
var lowerRightSim = root.GetChildByID(0xE3) as UIBMPComponent;
// IDs for the textures for the Sims are stored in a constants table UI element.
var constantsTable = Root.GetChildByID(0x4DC1DCE2);
var constantsTable = root.GetChildByID(0x4DC1DCE2);
var constantComponents = constantsTable.Children;
var upperLeftKeys = new List<ResourceKey>();
@ -75,6 +74,8 @@ namespace OpenTS2.UI.Layouts
}
}
var contentProvider = ContentProvider.Get();
// Assign random images to the Sims.
var upperLeftKey = RandomUtils.RandomFromList(upperLeftKeys);
var lowerRightKey = RandomUtils.RandomFromList(lowerRightKeys);

View file

@ -0,0 +1,30 @@
using OpenTS2.Common;
using OpenTS2.Content;
using OpenTS2.Files.Formats.DBPF;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
namespace OpenTS2.UI.Layouts
{
public class Neighborhood : UILayoutInstance
{
protected override ResourceKey UILayoutResourceKey => new ResourceKey(0x49000000, 0xA99D8A11, TypeIDs.UI);
public Neighborhood() : this(MainCanvas)
{
}
public Neighborhood(Transform canvas) : base(canvas)
{
var root = Components[0];
root.SetAnchor(UIComponent.AnchorType.Stretch);
var puck = root.GetChildByID(0x4BE6ED7D);
puck.SetAnchor(UIComponent.AnchorType.BottomLeft);
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f3cb9b72754c1e243b2398cd87759214
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,24 @@
using OpenTS2.Common;
using OpenTS2.Content;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
namespace OpenTS2.UI.Layouts
{
public abstract class UILayoutInstance
{
public UIComponent[] Components;
protected static Transform MainCanvas => UIManager.MainCanvas.transform;
protected abstract ResourceKey UILayoutResourceKey { get; }
public UILayoutInstance(Transform parent)
{
var contentProvider = ContentProvider.Get();
var layout = contentProvider.GetAsset<UILayout>(UILayoutResourceKey);
Components = layout.Instantiate(parent);
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c705a5a9942421248971d871809c8f67
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -32,6 +32,8 @@ namespace OpenTS2.UI
var contentProvider = ContentProvider.Get();
var imageAsset = contentProvider.GetAsset<TextureAsset>(Image);
var rawImage = uiComponent.gameObject.AddComponent<RawImage>();
if (IgnoreMouse)
rawImage.raycastTarget = false;
if (imageAsset != null)
{
if (EdgeImage)

View file

@ -22,6 +22,8 @@ namespace OpenTS2.UI
public RawImage RawImageComponent => GetComponent<RawImage>();
public void SetTexture(Texture2D texture)
{
if (texture == null)
return;
_textures = UIUtils.SplitTextureHorizontalSequence(texture, texture.width / 4);
UpdateTexture();
}
@ -35,6 +37,8 @@ namespace OpenTS2.UI
void UpdateTexture()
{
if (_textures == null || _textures.Length < 4)
return;
if (GreyedOut)
RawImageComponent.texture = _textures[0];
else
@ -58,9 +62,12 @@ namespace OpenTS2.UI
{
if (UIManager.HeldComponent == this)
UIManager.HeldComponent = null;
if (_textures == null)
return;
foreach (var texture in _textures)
{
texture.Free();
if (texture != null)
texture.Free();
}
}

View file

@ -25,11 +25,14 @@ namespace OpenTS2.UI
}
public override UIComponent Instantiate(Transform parent)
{
var contentProvider = ContentProvider.Get();
var imageAsset = contentProvider.GetAsset<TextureAsset>(Image);
var uiComponent = base.Instantiate(parent) as UIButtonComponent;
var rawImage = uiComponent.gameObject.AddComponent<RawImage>();
uiComponent.SetTexture(imageAsset.Texture);
if (IgnoreMouse)
rawImage.raycastTarget = false;
var contentProvider = ContentProvider.Get();
var imageAsset = contentProvider.GetAsset<TextureAsset>(Image);
if (imageAsset != null)
uiComponent.SetTexture(imageAsset.Texture);
return uiComponent;
}
}

View file

@ -15,7 +15,12 @@ namespace OpenTS2.UI
{
public enum AnchorType
{
Center
Stretch,
Center,
BottomLeft,
TopLeft,
BottomRight,
TopRight
}
public UIElement Element;
public RectTransform RectTransformComponent => GetComponent<RectTransform>();
@ -25,10 +30,41 @@ namespace OpenTS2.UI
{
switch(anchor)
{
case AnchorType.Stretch:
RectTransformComponent.anchorMin = new Vector2(0f, 0f);
RectTransformComponent.anchorMax = new Vector2(1f, 1f);
RectTransformComponent.anchoredPosition = Vector2.zero;
RectTransformComponent.sizeDelta = Vector2.zero;
return;
case AnchorType.Center:
RectTransformComponent.anchorMin = new Vector2(0.5f, 0.5f);
RectTransformComponent.anchorMax = new Vector2(0.5f, 0.5f);
transform.localPosition = new Vector3(-RectTransformComponent.sizeDelta.x / 2f, RectTransformComponent.sizeDelta.y / 2f, 0f);
RectTransformComponent.anchoredPosition = new Vector2(-RectTransformComponent.sizeDelta.x / 2f, RectTransformComponent.sizeDelta.y / 2f);
return;
case AnchorType.BottomLeft:
RectTransformComponent.anchorMin = new Vector2(0f, 0f);
RectTransformComponent.anchorMax = new Vector2(0f, 0f);
RectTransformComponent.anchoredPosition = new Vector2(0f, RectTransformComponent.sizeDelta.y);
return;
case AnchorType.TopLeft:
RectTransformComponent.anchorMin = new Vector2(0f, 1f);
RectTransformComponent.anchorMax = new Vector2(0f, 1f);
RectTransformComponent.anchoredPosition = Vector2.zero;
return;
case AnchorType.BottomRight:
RectTransformComponent.anchorMin = new Vector2(1f, 0f);
RectTransformComponent.anchorMax = new Vector2(1f, 0f);
RectTransformComponent.anchoredPosition = new Vector2(RectTransformComponent.sizeDelta.x, RectTransformComponent.sizeDelta.y);
return;
case AnchorType.TopRight:
RectTransformComponent.anchorMin = new Vector2(1f, 1f);
RectTransformComponent.anchorMax = new Vector2(1f, 1f);
RectTransformComponent.anchoredPosition = new Vector2(RectTransformComponent.sizeDelta.x, 0f);
return;
}
}

View file

@ -16,6 +16,7 @@ namespace OpenTS2.UI
/// </summary>
public class UIElement
{
public bool IgnoreMouse = false;
public bool Visible = true;
public uint ID = 0x0;
public Rect Area = Rect.zero;
@ -32,6 +33,7 @@ namespace OpenTS2.UI
FillColor = properties.GetColorProperty("fillcolor");
Caption = properties.GetProperty("caption");
Visible = properties.GetBoolProperty("winflag_visible");
IgnoreMouse = properties.GetBoolProperty("winflag_ignoremouse");
}
public virtual UIComponent Instantiate(Transform parent)

View file

@ -3,11 +3,13 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
namespace OpenTS2.UI
{
public static class UIManager
{
public static Canvas MainCanvas = null;
public static UIComponent HeldComponent = null;
}
}