1
0
mirror of https://github.com/SirusDoma/VoxCharger.git synced 2025-02-26 22:29:21 +01:00
VoxCharger/Sources/Ksh/Exporter.cs
CXO2 b8f49e3e2d Update 0.9.12c
- Fix naming and other code style issues
- Fix `float` and `double` parsing issue when current System Culture comma separator is not `.` - This fixes issue when parsing BPM and other floating numbers.
- Fix song selection when the program doesn't support the latest datecode in the future - It will disable Game Version and Infinite Version selection.
- Replaced ancient `FolderBrowserDialog` with `CommonFileDialog`
- Update default GameVersion and BackgroundId to latest version
- Implement Radar information in `LevelEditorForm`
- Implement built-in 2DX Encoder
- Start Offset / TimeStamp and Fader effect for audio preview is now supported
- Audio preview files is no longer divided into multiple files by default when audio files are unique. It still possible to specify unique preview via `LevelEditorForm`
- Implement advanced configuration when importing .ksh chart
- Add draft codes for Effect Mapping configurations and S3V support
- Other Bugfixes and QoL improvements
2023-01-06 20:59:21 +07:00

185 lines
6.8 KiB
C#

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace VoxCharger
{
public class ChartInfo
{
public Ksh Source { get; set; }
public VoxLevelHeader Header { get; set; }
public string FileName { get; set; }
public string MusicFileName { get; set; }
public ChartInfo(Ksh source, VoxLevelHeader header, string fileName)
{
Source = source;
Header = header;
FileName = fileName;
}
}
public partial class Ksh
{
public class Exporter
{
public Ksh Source { get; private set; } = null;
public Action Action { get; private set; } = null;
public Exporter(Ksh src)
{
Source = src;
}
public void Export(VoxHeader header, ParseOption options = null)
{
Export(header, null, options);
}
public void Export(VoxHeader header, Dictionary<Difficulty, ChartInfo> charts, ParseOption options = null, AudioImportOptions importOptions = null)
{
// Assign level info and charts
foreach (var chart in charts)
{
var info = chart.Value;
if (!File.Exists(info.FileName))
throw new IOException($"Chart file was moved or deleted\n{info.FileName}");
// If you happen to read the source, this is probably what you're looking for
var ksh = new Ksh();
ksh.Parse(info.FileName, options);
// Conversion is actually boring because its already "pre-converted"
var vox = new VoxChart();
vox.Import(ksh);
var level = ksh.ToLevelHeader();
level.Chart = vox;
info.Source = ksh;
header.Levels[chart.Key] = charts[chart.Key].Header = level;
}
// Prevent resource files being moved or deleted, copy them into temporary storage
string musicFile = string.Empty;
string tmpFile = string.Empty;
foreach (var chart in charts)
{
var info = chart.Value;
// Make sure to reuse 2dx / s3v file for music that share same file
if (string.IsNullOrEmpty(musicFile) || chart.Value.MusicFileName != musicFile)
{
string music = Path.Combine(Path.GetDirectoryName(info.FileName) ?? "", info.Source.MusicFileName);
if (File.Exists(music))
{
string tmp = Path.Combine(
Path.GetTempPath(),
$"{Path.GetRandomFileName()}{new FileInfo(info.Source.MusicFileName).Extension}"
);
musicFile = music;
info.MusicFileName = tmpFile = tmp;
File.Copy(music, tmp);
}
else
info.MusicFileName = string.Empty;
}
else
info.MusicFileName = tmpFile;
string jacket = Path.Combine(Path.GetDirectoryName(info.FileName), info.Source.JacketFileName);
if (File.Exists(jacket))
{
try
{
using (var image = Image.FromFile(jacket))
info.Header.Jacket = new Bitmap(image);
}
catch (Exception)
{
info.Header.Jacket = null;
}
}
}
Action = () =>
{
bool unique = false;
musicFile = charts.Values.First().MusicFileName;
foreach (var chart in charts)
{
if (chart.Value.MusicFileName != musicFile)
{
unique = true;
break;
}
}
// Import all music assets
AssetManager.ImportVox(header);
// Make sure to use single asset for music for shared music file
if (!unique)
{
AssetManager.ImportAudio(musicFile, header, importOptions);
AssetManager.ImportAudio(musicFile, header, (importOptions ?? AudioImportOptions.Default).AsPreview());
}
var highest = charts.Max(e => e.Key);
foreach (var entry in charts)
{
var chart = entry.Value;
if (unique && File.Exists(chart.MusicFileName))
{
AssetManager.ImportAudio(chart.MusicFileName, header, chart.Header.Difficulty, importOptions);
// Use shared preview using highest level music file
if (entry.Key == highest)
AssetManager.ImportAudio(chart.MusicFileName, header, (importOptions ?? AudioImportOptions.Default).AsPreview());
}
if (chart.Header.Jacket != null)
AssetManager.ImportJacket(header, chart.Header.Difficulty, chart.Header.Jacket);
}
};
}
public static Dictionary<Difficulty, ChartInfo> GetCharts(string dir, string title)
{
// Try to locate another difficulty
var charts = new Dictionary<Difficulty, ChartInfo>();
foreach (string fn in Directory.GetFiles(dir, "*.ksh"))
{
try
{
var chart = new Ksh();
chart.Parse(fn);
// Different chart
if (chart.Title != title)
continue;
charts[chart.Difficulty] = new ChartInfo(chart, chart.ToLevelHeader(), fn);
}
catch (Exception ex)
{
Debug.WriteLine("Failed attempt to parse ksh file: {0} ({1})", fn, ex.Message);
}
}
return charts;
}
}
}
}