284 lines
9.4 KiB
C#
284 lines
9.4 KiB
C#
using Cryville.Common;
|
|
using Cryville.Common.Unity;
|
|
using Cryville.Crtr.Extension;
|
|
using Cryville.Crtr.Extensions;
|
|
using Cryville.Crtr.Extensions.Umg;
|
|
using Cryville.Crtr.UI;
|
|
using Newtonsoft.Json;
|
|
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using UnityEngine;
|
|
using Logger = Cryville.Common.Logging.Logger;
|
|
|
|
namespace Cryville.Crtr.Browsing {
|
|
internal class LegacyResourceManager : IPathedResourceManager<ChartDetail> {
|
|
private readonly string _rootPath;
|
|
private DirectoryInfo cd;
|
|
private DirectoryInfo[] items = new DirectoryInfo[0];
|
|
public string[] CurrentDirectory { get; private set; }
|
|
public int Count { get { return items.Length; } }
|
|
|
|
static bool _init;
|
|
|
|
public event Action ItemChanged;
|
|
|
|
public LegacyResourceManager(string rootPath) {
|
|
_rootPath = rootPath;
|
|
if (!_init) {
|
|
_init = true;
|
|
ExtensionManager.Init(rootPath);
|
|
}
|
|
}
|
|
|
|
public void ChangeDirectory(string[] dir) {
|
|
CurrentDirectory = dir;
|
|
cd = new DirectoryInfo(_rootPath + "/charts/" + string.Join("/", dir));
|
|
items = cd.GetDirectories();
|
|
ItemChanged?.Invoke();
|
|
}
|
|
|
|
public void OpenDirectory(int id) {
|
|
string[] nd = new string[CurrentDirectory.Length + 1];
|
|
Array.Copy(CurrentDirectory, nd, CurrentDirectory.Length);
|
|
nd[CurrentDirectory.Length] = items[id].Name;
|
|
ChangeDirectory(nd);
|
|
}
|
|
|
|
public void ReturnToDirectory(int index) {
|
|
string[] nd = new string[index + 1];
|
|
Array.Copy(CurrentDirectory, nd, index + 1);
|
|
ChangeDirectory(nd);
|
|
}
|
|
|
|
public ChartDetail this[int index] {
|
|
get {
|
|
var item = items[index];
|
|
ChartMeta meta = null;
|
|
var metaFile = new FileInfo(Path.Combine(item.FullName, ".umgc"));
|
|
if (metaFile.Exists) {
|
|
using (var reader = new StreamReader(metaFile.FullName)) {
|
|
meta = JsonConvert.DeserializeObject<ChartMeta>(reader.ReadToEnd());
|
|
}
|
|
}
|
|
AsyncDelivery<Texture2D> cover = null;
|
|
if (meta.cover != null && meta.cover != "") {
|
|
var coverFile = item.GetFiles(meta.cover);
|
|
if (coverFile.Length > 0) {
|
|
cover = new AsyncDelivery<Texture2D>();
|
|
var task = new LoadTextureTask(PlatformConfig.FileProtocolPrefix + coverFile[0].FullName, cover.Deliver);
|
|
cover.CancelSource = task.Cancel;
|
|
Game.NetworkTaskWorker.SubmitNetworkTask(task);
|
|
}
|
|
}
|
|
return new ChartDetail {
|
|
Cover = cover,
|
|
Meta = meta,
|
|
};
|
|
}
|
|
}
|
|
|
|
public Uri GetItemUri(int id) {
|
|
var item = items[id];
|
|
var meta = new ChartMeta();
|
|
var metaFile = new FileInfo(Path.Combine(item.FullName, ".umgc"));
|
|
using (var reader = new StreamReader(metaFile.FullName)) {
|
|
meta = JsonConvert.DeserializeObject<ChartMeta>(reader.ReadToEnd());
|
|
}
|
|
return new Uri(Path.Combine(items[id].Name, string.Format("{0}.json", meta.data)));
|
|
}
|
|
|
|
public bool ImportItemFrom(Uri uri) {
|
|
if (!uri.IsFile) throw new NotSupportedException();
|
|
var file = new FileInfo(uri.LocalPath);
|
|
IEnumerable<ResourceConverter> converters;
|
|
if (!ExtensionManager.TryGetConverters(file.Extension, out converters)) return false;
|
|
foreach (var converter in converters) {
|
|
var resources = new List<Resource>();
|
|
var ses = new ConversionSession {
|
|
OnResourceAdd = res => resources.Add(res)
|
|
};
|
|
try {
|
|
converter.Convert(file, ses);
|
|
}
|
|
catch (Exception ex) {
|
|
LogAndPopupExtra(4, ex, "Failed to import resource: {0}", ex.Message);
|
|
return false;
|
|
}
|
|
foreach (var res in resources) {
|
|
if (!res.Valid) {
|
|
LogAndPopup(3, "Attempt to import invalid resource: {0}", res);
|
|
}
|
|
else if (res is RawChartResource) {
|
|
var tres = (RawChartResource)res;
|
|
var dir = new DirectoryInfo(_rootPath + "/charts/" + res.Name);
|
|
if (!dir.Exists) dir.Create();
|
|
using (var writer = new StreamWriter(dir.FullName + "/.json")) {
|
|
writer.Write(JsonConvert.SerializeObject(ConvertChartData(tres.Main), Game.GlobalJsonSerializerSettings));
|
|
}
|
|
using (var writer = new StreamWriter(dir.FullName + "/.umgc")) {
|
|
tres.Meta.data = "";
|
|
writer.Write(JsonConvert.SerializeObject(tres.Meta, Game.GlobalJsonSerializerSettings));
|
|
}
|
|
if (tres.Meta.cover != null) {
|
|
var coverFile = new FileInfo(Path.Combine(file.Directory.FullName, tres.Meta.cover));
|
|
if (coverFile.Exists)
|
|
coverFile.CopyTo(Path.Combine(dir.FullName, tres.Meta.cover), true);
|
|
}
|
|
}
|
|
else if (res is FileResource) {
|
|
var tres = (FileResource)res;
|
|
DirectoryInfo dest;
|
|
bool singleFileFlag = false;
|
|
if (res is ChartResource)
|
|
dest = new DirectoryInfo(_rootPath + "/charts/" + res.Name);
|
|
else if (res is ExtensionResource) {
|
|
dest = new DirectoryInfo(_rootPath + "/extensions");
|
|
singleFileFlag = true;
|
|
Popup.Create("Please restart the game to reload the extensions");
|
|
}
|
|
else if (res is RulesetResource)
|
|
dest = new DirectoryInfo(_rootPath + "/rulesets/" + res.Name);
|
|
else if (res is SkinResource)
|
|
dest = new DirectoryInfo(_rootPath + "/skins/" + (res as SkinResource).RulesetName + "/" + res.Name);
|
|
else if (res is SongResource)
|
|
dest = new DirectoryInfo(_rootPath + "/songs/" + res.Name);
|
|
else {
|
|
LogAndPopup(3, "Attempt to import unsupported file resource: {0}", res);
|
|
continue;
|
|
}
|
|
if (singleFileFlag || !dest.Exists) {
|
|
dest.Create();
|
|
tres.Master.CopyTo(Path.Combine(dest.FullName, singleFileFlag ? tres.Master.Name : tres.Master.Extension));
|
|
foreach (var attachment in tres.Attachments) {
|
|
if (singleFileFlag) throw new InvalidOperationException("Internal error");
|
|
attachment.CopyTo(Path.Combine(dest.FullName, attachment.Name));
|
|
}
|
|
}
|
|
else LogAndPopup(1, "Resource already exists: {0}", res);
|
|
}
|
|
else {
|
|
LogAndPopup(3, "Attempt to import unsupported resource: {0}", res);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
Enumerator GetEnumerator() { return new Enumerator(this); }
|
|
IEnumerator<ChartDetail> IEnumerable<ChartDetail>.GetEnumerator() { return GetEnumerator(); }
|
|
IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
|
|
|
|
public struct Enumerator : IEnumerator<ChartDetail> {
|
|
readonly LegacyResourceManager _list;
|
|
public ChartDetail Current => throw new NotImplementedException();
|
|
object IEnumerator.Current => Current;
|
|
|
|
public Enumerator(LegacyResourceManager list) { _list = list; }
|
|
public void Dispose() { }
|
|
|
|
public bool MoveNext() {
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public void Reset() {
|
|
throw new NotImplementedException();
|
|
}
|
|
}
|
|
|
|
void LogAndPopup(int level, string format, params object[] args) {
|
|
var msg = string.Format(format, args);
|
|
Logger.Log("main", level, "Resource", msg);
|
|
Popup.Create(msg);
|
|
}
|
|
|
|
void LogAndPopupExtra(int level, object extraLog, string format, params object[] args) {
|
|
var msg = string.Format(format, args);
|
|
Logger.Log("main", level, "Resource", "{0}\n{1}", msg, extraLog);
|
|
Popup.Create(msg);
|
|
}
|
|
|
|
public string[] GetSupportedFormats() {
|
|
return ExtensionManager.GetSupportedFormats().ToArray();
|
|
}
|
|
|
|
public IReadOnlyDictionary<string, string> GetPresetPaths() {
|
|
return ExtensionManager.GetLocalResourcePaths();
|
|
}
|
|
|
|
static Chart ConvertChartData(ChartData i) {
|
|
return new Chart {
|
|
endtime = ConvertBeatTime(i.endtime),
|
|
format = i.format,
|
|
groups = ConvertGroups(i.groups),
|
|
motions = ConvertMotions(i.motions),
|
|
ruleset = i.ruleset,
|
|
sigs = ConvertSignatures(i.sigs),
|
|
sounds = ConvertSounds(i.sounds),
|
|
time = ConvertBeatTime(i.time),
|
|
};
|
|
}
|
|
static BeatTime? ConvertBeatTime(Extension.BeatTime? value) {
|
|
if (value == null) return null;
|
|
return new BeatTime(value.Value.b, value.Value.n, value.Value.d);
|
|
}
|
|
static List<Chart.Group> ConvertGroups(List<ChartData.Group> l) {
|
|
return l.Select(i => new Chart.Group {
|
|
endtime = ConvertBeatTime(i.endtime),
|
|
motions = ConvertMotions(i.motions),
|
|
notes = ConvertNotes(i.notes),
|
|
time = ConvertBeatTime(i.time),
|
|
tracks = ConvertTracks(i.tracks),
|
|
}).ToList();
|
|
}
|
|
static List<Chart.Judge> ConvertJudges(List<ChartData.Judge> l) {
|
|
return l.Select(i => new Chart.Judge {
|
|
endtime = ConvertBeatTime(i.endtime),
|
|
name = i.name,
|
|
time = ConvertBeatTime(i.time),
|
|
}).ToList();
|
|
}
|
|
static List<Chart.Motion> ConvertMotions(List<ChartData.Motion> l) {
|
|
return l.Select(i => new Chart.Motion {
|
|
endtime = ConvertBeatTime(i.endtime),
|
|
motion = i.motion,
|
|
sumfix = i.sumfix,
|
|
time = ConvertBeatTime(i.time),
|
|
}).ToList();
|
|
}
|
|
static List<Chart.Note> ConvertNotes(List<ChartData.Note> l) {
|
|
return l.Select(i => new Chart.Note {
|
|
endtime = ConvertBeatTime(i.endtime),
|
|
judges = ConvertJudges(i.judges),
|
|
motions = ConvertMotions(i.motions),
|
|
time = ConvertBeatTime(i.time),
|
|
}).ToList();
|
|
}
|
|
static List<Chart.Signature> ConvertSignatures(List<ChartData.Signature> l) {
|
|
return l.Select(i => new Chart.Signature {
|
|
endtime = ConvertBeatTime(i.endtime),
|
|
tempo = i.tempo,
|
|
time = ConvertBeatTime(i.time),
|
|
}).ToList();
|
|
}
|
|
static List<Chart.Sound> ConvertSounds(List<ChartData.Sound> l) {
|
|
return l.Select(i => new Chart.Sound {
|
|
endtime = ConvertBeatTime(i.endtime),
|
|
id = i.id,
|
|
offset = i.offset,
|
|
time = ConvertBeatTime(i.time),
|
|
}).ToList();
|
|
}
|
|
static List<Chart.Track> ConvertTracks(List<ChartData.Track> l) {
|
|
return l.Select(i => new Chart.Track {
|
|
endtime = ConvertBeatTime(i.endtime),
|
|
motions = ConvertMotions(i.motions),
|
|
time = ConvertBeatTime(i.time),
|
|
}).ToList();
|
|
}
|
|
}
|
|
}
|