Pull down IPathedResourceManager. Reconstruct resource browser.

This commit is contained in:
2023-11-10 14:57:52 +08:00
parent bd834cff4a
commit ddf738ee27
11 changed files with 147 additions and 111 deletions

View File

@@ -1,11 +1,10 @@
using System;
using System.Collections.Generic; using System.Collections.Generic;
namespace Cryville.Crtr.Browsing { namespace Cryville.Crtr.Browsing {
public interface IResourceManager<T> { public interface IResourceManager<T> {
string[] CurrentDirectory { get; } int ItemCount { get; }
int ChangeDirectory(string[] dir);
int OpenDirectory(int id);
int ReturnToDirectory(int id);
ResourceItemMeta GetItemMeta(int id); ResourceItemMeta GetItemMeta(int id);
T GetItemDetail(int id); T GetItemDetail(int id);
string GetItemPath(int id); string GetItemPath(int id);
@@ -13,5 +12,13 @@ namespace Cryville.Crtr.Browsing {
bool ImportItemFrom(string path); bool ImportItemFrom(string path);
string[] GetSupportedFormats(); string[] GetSupportedFormats();
IReadOnlyDictionary<string, string> GetPresetPaths(); IReadOnlyDictionary<string, string> GetPresetPaths();
event Action ItemChanged;
}
public interface IPathedResourceManager<T> : IResourceManager<T> {
string[] CurrentDirectory { get; }
void ChangeDirectory(string[] dir);
void OpenDirectory(int id);
void ReturnToDirectory(int id);
} }
} }

View File

@@ -13,14 +13,17 @@ using UnityEngine;
using Logger = Cryville.Common.Logging.Logger; using Logger = Cryville.Common.Logging.Logger;
namespace Cryville.Crtr.Browsing { namespace Cryville.Crtr.Browsing {
internal class LegacyResourceManager : IResourceManager<ChartDetail> { internal class LegacyResourceManager : IPathedResourceManager<ChartDetail> {
private readonly string _rootPath; private readonly string _rootPath;
private DirectoryInfo cd; private DirectoryInfo cd;
private DirectoryInfo[] items = new DirectoryInfo[0]; private DirectoryInfo[] items = new DirectoryInfo[0];
public string[] CurrentDirectory { get; private set; } public string[] CurrentDirectory { get; private set; }
public int ItemCount { get { return items.Length; } }
static bool _init; static bool _init;
public event Action ItemChanged;
public LegacyResourceManager(string rootPath) { public LegacyResourceManager(string rootPath) {
_rootPath = rootPath; _rootPath = rootPath;
if (!_init) { if (!_init) {
@@ -29,24 +32,24 @@ namespace Cryville.Crtr.Browsing {
} }
} }
public int ChangeDirectory(string[] dir) { public void ChangeDirectory(string[] dir) {
CurrentDirectory = dir; CurrentDirectory = dir;
cd = new DirectoryInfo(_rootPath + "/charts/" + string.Join("/", dir)); cd = new DirectoryInfo(_rootPath + "/charts/" + string.Join("/", dir));
items = cd.GetDirectories(); items = cd.GetDirectories();
return items.Length; ItemChanged?.Invoke();
} }
public int OpenDirectory(int id) { public void OpenDirectory(int id) {
string[] nd = new string[CurrentDirectory.Length + 1]; string[] nd = new string[CurrentDirectory.Length + 1];
Array.Copy(CurrentDirectory, nd, CurrentDirectory.Length); Array.Copy(CurrentDirectory, nd, CurrentDirectory.Length);
nd[CurrentDirectory.Length] = items[id].Name; nd[CurrentDirectory.Length] = items[id].Name;
return ChangeDirectory(nd); ChangeDirectory(nd);
} }
public int ReturnToDirectory(int id) { public void ReturnToDirectory(int id) {
string[] nd = new string[id + 1]; string[] nd = new string[id + 1];
Array.Copy(CurrentDirectory, nd, id + 1); Array.Copy(CurrentDirectory, nd, id + 1);
return ChangeDirectory(nd); ChangeDirectory(nd);
} }
public ResourceItemMeta GetItemMeta(int id) { public ResourceItemMeta GetItemMeta(int id) {

View File

@@ -4,9 +4,15 @@ namespace Cryville.Crtr.Browsing.UI {
internal abstract class BrowserItem : MonoBehaviour { internal abstract class BrowserItem : MonoBehaviour {
public int? Id { get; private set; } public int? Id { get; private set; }
protected ResourceItemMeta meta; protected ResourceItemMeta meta;
internal virtual void Load(int id, ResourceItemMeta item) { internal void Load(int id, ResourceItemMeta item, bool selected) {
OnReset();
Id = id; Id = id;
meta = item; meta = item;
OnLoad(selected);
} }
protected abstract void OnReset();
protected abstract void OnLoad(bool selected);
internal virtual void OnSelect() { }
internal virtual void OnDeselect() { }
} }
} }

View File

@@ -1,3 +1,4 @@
using Cryville.Common.Unity;
using TMPro; using TMPro;
using UnityEngine; using UnityEngine;
using UnityEngine.UI; using UnityEngine.UI;
@@ -17,26 +18,31 @@ namespace Cryville.Crtr.Browsing.UI {
[SerializeField] [SerializeField]
TMP_Text m_desc; TMP_Text m_desc;
#pragma warning disable IDE0051 StateTweener _tweener;
void Awake() { void Awake() {
_tweener = GetComponent<StateTweener>();
} }
void OnDestroy() { void OnDestroy() {
OnReset();
}
protected override void OnReset() {
if (meta.Icon != null) meta.Icon.Cancel(); if (meta.Icon != null) meta.Icon.Cancel();
if (m_icon.sprite != null && m_icon.sprite != m_iconPlaceholder) { if (m_icon.sprite != null && m_icon.sprite != m_iconPlaceholder) {
Destroy(m_icon.sprite.texture); Destroy(m_icon.sprite.texture);
Destroy(m_icon.sprite); Destroy(m_icon.sprite);
} }
_tweener.ClearState();
} }
#pragma warning restore IDE0051
internal override void Load(int id, ResourceItemMeta item) { protected override void OnLoad(bool selected) {
OnDestroy();
base.Load(id, item);
_dir = meta.IsDirectory; _dir = meta.IsDirectory;
m_icon.sprite = m_iconPlaceholder; m_icon.sprite = m_iconPlaceholder;
if (meta.Icon != null) meta.Icon.Destination = DisplayCover; if (meta.Icon != null) meta.Icon.Destination = DisplayCover;
m_title.text = meta.Name; m_title.text = meta.Name;
m_desc.text = string.Format("{0}\n{1}", meta.DescriptionMain, meta.DescriptionSub); m_desc.text = string.Format("{0}\n{1}", meta.DescriptionMain, meta.DescriptionSub);
if (selected) _tweener.EnterState("Selected");
} }
private void DisplayCover(bool succeeded, Texture2D tex) { private void DisplayCover(bool succeeded, Texture2D tex) {
if (succeeded) { if (succeeded) {
@@ -45,9 +51,17 @@ namespace Cryville.Crtr.Browsing.UI {
} }
public void OnClick() { public void OnClick() {
if (Id == null) return; if (Id == null) return;
var resourceBrowser = GetComponentInParent<ResourceBrowser>(); var resourceBrowser = GetComponentInParent<PathedResourceBrowser>();
if (_dir) resourceBrowser.OnDirectoryItemClicked(Id.Value); if (_dir) resourceBrowser.OnDirectoryItemClicked(Id.Value);
else resourceBrowser.OnObjectItemClicked(Id.Value); else resourceBrowser.OnObjectItemClicked(Id.Value);
} }
internal override void OnSelect() {
base.OnSelect();
_tweener.EnterState("Selected", 0.1f);
}
internal override void OnDeselect() {
base.OnDeselect();
_tweener.ExitState("Selected", 0.1f);
}
} }
} }

View File

@@ -5,7 +5,7 @@ using UnityEngine;
using UnityEngine.UI; using UnityEngine.UI;
namespace Cryville.Crtr.Browsing.UI { namespace Cryville.Crtr.Browsing.UI {
public class DetailPanel : ResourceBrowserUnit { public class DetailPanel : MonoBehaviour {
[SerializeField] [SerializeField]
Sprite m_coverPlaceholder; Sprite m_coverPlaceholder;
[SerializeField] [SerializeField]
@@ -19,10 +19,13 @@ namespace Cryville.Crtr.Browsing.UI {
[SerializeField] [SerializeField]
TMP_Text m_desc; TMP_Text m_desc;
ResourceBrowserMaster _master;
int _id; int _id;
ChartDetail _data; ChartDetail _data;
protected override void Awake() { void Awake() {
_master = GetComponentInParent<ResourceBrowserMaster>();
} }
void OnDestroy() { void OnDestroy() {
if (_data.Cover != null) _data.Cover.Cancel(); if (_data.Cover != null) _data.Cover.Cancel();
@@ -53,10 +56,10 @@ namespace Cryville.Crtr.Browsing.UI {
} }
} }
public void OnPlay() { public void OnPlay() {
Master.Open(_id, _data); _master.Open(_id, _data);
} }
public void OnConfig() { public void OnConfig() {
Master.OpenConfig(_id, _data); _master.OpenConfig(_id, _data);
} }
} }
} }

View File

@@ -21,7 +21,7 @@ namespace Cryville.Crtr.Browsing.UI {
else return exp; else return exp;
} }
public void OnClick() { public void OnClick() {
GetComponentInParent<ResourceBrowser>().OnPathClicked(_id); GetComponentInParent<PathedResourceBrowser>().OnPathClicked(_id);
} }
} }
} }

View File

@@ -0,0 +1,83 @@
using Cryville.Common.Unity;
using Cryville.Common.Unity.UI;
using Cryville.Crtr.UI;
using System;
using System.Collections.Generic;
using UnityEngine;
namespace Cryville.Crtr.Browsing.UI {
public class PathedResourceBrowser : ResourceBrowser {
public IPathedResourceManager<ChartDetail> ResourceManager;
public ScrollableItemGrid ItemContainer;
readonly HashSet<int> _selectedItems = new HashSet<int>();
readonly Dictionary<int, BrowserItem> _items = new Dictionary<int, BrowserItem>();
FileDialog _dialog;
protected virtual void Start() {
ItemContainer.LoadItem = LoadItem;
ResourceManager.ItemChanged += OnItemChanged;
ResourceManager.ChangeDirectory(new string[] { "" });
InitDialog();
}
protected void InitDialog() {
_dialog = Instantiate(Resources.Load<GameObject>("Common/FileDialog")).GetComponent<FileDialog>();
_dialog.gameObject.SetActive(false);
_dialog.Filter = ResourceManager.GetSupportedFormats();
_dialog.PresetPaths = ResourceManager.GetPresetPaths();
_dialog.OnClose += OnAddDialogClosed;
}
void OnItemChanged() {
ItemContainer.ItemCount = ResourceManager.ItemCount;
_selectedItems.Clear();
_items.Clear();
}
private bool LoadItem(int id, GameObject obj) {
var bi = obj.GetComponent<BrowserItem>();
_items[id] = bi;
try {
var item = ResourceManager.GetItemMeta(id);
bi.Load(id, item, _selectedItems.Contains(id));
}
catch (Exception) {
bi.Load(id, new ResourceItemMeta { Name = "<color=#ff0000>Invalid resource</color>" }, _selectedItems.Contains(id));
}
return true;
}
public virtual void OnDirectoryItemClicked(int id) {
ResourceManager.OpenDirectory(id);
}
public void OnObjectItemClicked(int id) {
foreach (var item in _selectedItems) _items[item].OnDeselect();
_selectedItems.Clear();
_items[id].OnSelect();
_selectedItems.Add(id);
Master.ShowDetail(id, ResourceManager.GetItemDetail(id));
}
public void OnPathClicked(int id) {
ResourceManager.ReturnToDirectory(id);
}
public void OnAddButtonClicked() {
_dialog.Show();
}
private void OnAddDialogClosed() {
if (_dialog.FileName == null) return;
if (ResourceManager.ImportItemFrom(_dialog.FileName)) {
Popup.Create("Import succeeded");
OnPathClicked(ResourceManager.CurrentDirectory.Length - 1);
}
else {
Popup.Create("Import failed");
}
}
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: e8d98fa73d49ab94cb1a16c5ef09db6c guid: f3c17bb298cf2294dad4b675c7290b2a
MonoImporter: MonoImporter:
externalObjects: {} externalObjects: {}
serializedVersion: 2 serializedVersion: 2

View File

@@ -1,78 +1,10 @@
using Cryville.Common.Unity;
using Cryville.Common.Unity.UI;
using Cryville.Crtr.UI;
using System;
using UnityEngine; using UnityEngine;
using UnityEngine.UI;
namespace Cryville.Crtr.Browsing.UI { namespace Cryville.Crtr.Browsing.UI {
public class ResourceBrowser : ResourceBrowserUnit { public abstract class ResourceBrowser : MonoBehaviour {
public IResourceManager<ChartDetail> ResourceManager; protected ResourceBrowserMaster Master { get; private set; }
public ScrollableItemGrid PathContainer; protected virtual void Awake() {
public ScrollableItemGrid ItemContainer; Master = GetComponentInParent<ResourceBrowserMaster>();
FileDialog _dialog;
protected void Start() {
PathContainer.LoadItem = LoadPathPart;
ItemContainer.LoadItem = LoadItem;
ItemContainer.ItemCount = ResourceManager.ChangeDirectory(new string[] { "" });
PathContainer.ItemCount = ResourceManager.CurrentDirectory.Length;
_dialog = GameObject.Instantiate(Resources.Load<GameObject>("Common/FileDialog")).GetComponent<FileDialog>();
_dialog.gameObject.SetActive(false);
_dialog.Filter = ResourceManager.GetSupportedFormats();
_dialog.PresetPaths = ResourceManager.GetPresetPaths();
_dialog.OnClose += OnAddDialogClosed;
}
private bool LoadPathPart(int id, GameObject obj) {
var item = ResourceManager.CurrentDirectory[id];
obj.GetComponent<PathPart>().Load(id, item);
return true;
}
private bool LoadItem(int id, GameObject obj) {
var bi = obj.GetComponent<BrowserItem>();
try {
var item = ResourceManager.GetItemMeta(id);
bi.Load(id, item);
}
catch (Exception) {
bi.Load(id, new ResourceItemMeta { Name = "<color=#ff0000>Invalid resource</color>" });
}
return true;
}
public void OnDirectoryItemClicked(int id) {
ItemContainer.ItemCount = ResourceManager.OpenDirectory(id);
PathContainer.ItemCount = ResourceManager.CurrentDirectory.Length;
if (PathContainer.ItemCount >= PathContainer.VisibleLines - 1)
PathContainer.GetComponentInParent<ScrollRect>().velocity = new Vector2(-Screen.width, 0);
}
public void OnObjectItemClicked(int id) {
Master.ShowDetail(id, ResourceManager.GetItemDetail(id));
}
public void OnPathClicked(int id) {
ItemContainer.ItemCount = ResourceManager.ReturnToDirectory(id);
PathContainer.ItemCount = ResourceManager.CurrentDirectory.Length;
}
public void OnAddButtonClicked() {
_dialog.Show();
}
private void OnAddDialogClosed() {
if (_dialog.FileName == null) return;
if (ResourceManager.ImportItemFrom(_dialog.FileName)) {
Popup.Create("Import succeeded");
OnPathClicked(ResourceManager.CurrentDirectory.Length - 1);
}
else {
Popup.Create("Import failed");
}
} }
} }
} }

View File

@@ -18,12 +18,12 @@ namespace Cryville.Crtr.Browsing.UI {
[SerializeField] [SerializeField]
private DetailPanel m_detailPanel; private DetailPanel m_detailPanel;
readonly List<ResourceBrowserUnit> _units = new List<ResourceBrowserUnit>(); readonly List<ResourceBrowser> _units = new List<ResourceBrowser>();
void Awake() { void Awake() {
m_mainBrowser.ResourceManager = new LegacyResourceManager(Settings.Default.GameDataPath); m_mainBrowser.ResourceManager = new LegacyResourceManager(Settings.Default.GameDataPath);
_units.Add(MainBrowser); _units.Add(m_mainBrowser);
_units.Add(_detailPanel); // _units.Add(m_detailPanel);
} }
public void ShowDetail(int id, ChartDetail detail) { public void ShowDetail(int id, ChartDetail detail) {

View File

@@ -1,12 +0,0 @@
using UnityEngine;
namespace Cryville.Crtr.Browsing.UI {
public abstract class ResourceBrowserUnit : MonoBehaviour {
protected ResourceBrowserMaster Master { get; private set; }
protected virtual void Awake() {
Master = GetComponentInParent<ResourceBrowserMaster>();
}
public virtual void SlideToLeft() { }
public virtual void SlideToRight() { }
}
}