支持EV图像合成
This commit is contained in:
parent
f38fc2c4cc
commit
a6f10be546
@ -1,243 +1,30 @@
|
||||
using ImageMagick;
|
||||
using System.Text;
|
||||
using static System.Runtime.InteropServices.JavaScript.JSType;
|
||||
|
||||
namespace EscudeTools
|
||||
{
|
||||
public class Image
|
||||
{
|
||||
//public byte[] file = new byte[64]; // Image file name
|
||||
//public int page; // Image memory
|
||||
//public int back_page; // Back image memory
|
||||
public uint width; // Width
|
||||
public uint height; // Height
|
||||
public uint depth; // Color depth
|
||||
//public int id; // ID
|
||||
public int reff; // Reference counter
|
||||
//public bool cache; // Cache flag
|
||||
public bool isFile; // Is it an image file
|
||||
//public uint[] extra = new uint[8]; // Reserved
|
||||
|
||||
public string fileStr; // 自己加的,用于保存文件名
|
||||
}
|
||||
public class GInfo
|
||||
{
|
||||
public int width; // Width
|
||||
public int height; // Height
|
||||
public int depth; // Color depth
|
||||
public string pixel; // address of the pixel data
|
||||
public uint pitch;
|
||||
public string palette;
|
||||
}
|
||||
public class LsfImage
|
||||
{
|
||||
//public bool cache; // Cache flag
|
||||
public Image img; // Layer image
|
||||
}
|
||||
public class LsfData
|
||||
{
|
||||
//public byte[] path = new byte[64]; // LSF folder
|
||||
public LsfFileHeader lfh; // LSF file header
|
||||
public LsfLayerInfo[] lli; // LSF layer information
|
||||
public LsfImage[] layer; // LSF layer image
|
||||
|
||||
public string pathStr;
|
||||
public string lsfName;
|
||||
}
|
||||
public class LsfFileHeader
|
||||
{
|
||||
//public uint signature; // Header signature (LSF) 0x46534C
|
||||
public ushort revision; // Revision number
|
||||
public ushort bg; // Background flag
|
||||
public ushort id; // ID
|
||||
public ushort layer_count; // Number of layers
|
||||
public int width; // Width in pixels
|
||||
public int height; // Height in pixels
|
||||
public int bx; // Base coordinates
|
||||
public int by; // Base coordinates
|
||||
}
|
||||
public class LsfLayerInfo
|
||||
{
|
||||
public byte[] name = new byte[64]; // File name
|
||||
public byte[] text = new byte[64]; // Generic string
|
||||
public Rect rect; // Layer position
|
||||
public int cx; // Center coordinates
|
||||
public int cy; // Center coordinates
|
||||
public byte index; // Position
|
||||
public byte state; // State
|
||||
public byte mode; // Drawing mode
|
||||
public byte opacity; // Opacity
|
||||
public uint fill; // Fill color
|
||||
public uint value; // Generic value
|
||||
|
||||
public string nameStr; // 自己加的,用于保存文件名
|
||||
public string textStr; // 自己加的,用于保存通用名
|
||||
public string indexStr; // Position str
|
||||
public string stateStr; // State str
|
||||
public string modeStr; // Drawing mode str
|
||||
public string opacityStr; // Opacity str
|
||||
|
||||
public bool skip = false; // 是否跳过
|
||||
|
||||
}
|
||||
public class Rect
|
||||
{
|
||||
public int left; // Top-left corner X coordinate of the rectangle
|
||||
public int top; // Top-left corner Y coordinate of the rectangle
|
||||
public int right; // Bottom-right corner X coordinate of the rectangle
|
||||
public int bottom; // Bottom-right corner Y coordinate of the rectangle
|
||||
}
|
||||
public class CgInfo
|
||||
{
|
||||
public int kind; // Image category
|
||||
public int index; // Image index
|
||||
public int x; // Coordinates
|
||||
public int y; // Coordinates
|
||||
public int scale; // Scale factor
|
||||
public bool loop; // Loop flag
|
||||
public byte[] name = new byte[64]; // Registered name
|
||||
public byte[] file = new byte[64]; // File name
|
||||
public byte[] option = new byte[128]; // Options
|
||||
public uint coverd; // White-out ID
|
||||
public uint filter; // Filter
|
||||
public uint color; // Color
|
||||
public uint id; // Image identification ID
|
||||
public uint loc; // Coordinate list
|
||||
public uint spot; // Coordinate index
|
||||
public int order; // CG viewing display order
|
||||
public uint link; // Related CG
|
||||
|
||||
public string nameStr;
|
||||
public string fileStr;
|
||||
public string optionStr;
|
||||
}
|
||||
|
||||
public class ImageManager
|
||||
{
|
||||
static readonly byte[] lsfFileSignature = [0x4C, 0x53, 0x46, 0x00];
|
||||
static readonly byte[] lsfLayerSkipSignature = [0x00, 0x75, 0x6C, 0x00]; //flowchat部分的lsf块
|
||||
static readonly byte[] motV1Signature = [0x6D, 0x6F, 0x74, 0x00]; // mot v1 file signature
|
||||
static readonly byte[] motV2Signature = [0x4D, 0x4F, 0x54, 0x00]; // MOT v2 file signature
|
||||
private static string WorkPath = string.Empty;
|
||||
private LsfData lsfData = new();
|
||||
private List<LsfData> lsfDatas = [];
|
||||
|
||||
private bool preFetchInfo;
|
||||
|
||||
public bool LoadLsf(string path, bool preFI = false)
|
||||
public static bool EvProcess(LsfData ld, int[] n, string target)
|
||||
{
|
||||
if (!File.Exists(path))
|
||||
return false;
|
||||
preFetchInfo = preFI;
|
||||
lsfData.pathStr = Path.GetDirectoryName(path);
|
||||
lsfData.lsfName = Path.GetFileNameWithoutExtension(path);
|
||||
lsfData.lfh = LoadLsfHeader(path);
|
||||
lsfData.lli = LoadLsfLayerInfo(path);
|
||||
lsfData.layer = new LsfImage[lsfData.lfh.layer_count];
|
||||
for (int i = 0; i < lsfData.lfh.layer_count; i++)
|
||||
//get base size
|
||||
int height = ld.lfh.height, width = ld.lfh.width;
|
||||
using var baseImage = new MagickImage(MagickColors.Transparent, (uint)width, (uint)height);
|
||||
for (int i = 0; i < n.Length; i++)
|
||||
{
|
||||
string imgPath = Path.Combine(lsfData.pathStr, lsfData.lli[i].nameStr + ".png");
|
||||
LsfImage li = new();
|
||||
if (!lsfData.lli[i].skip)
|
||||
{
|
||||
li.img = LoadLsfImage(imgPath);
|
||||
lsfData.layer[i] = li;
|
||||
}
|
||||
string imgPath = ld.layer[n[i]].img.fileStr;
|
||||
using var overlayImage = new MagickImage(imgPath);
|
||||
int offsetX = ld.lli[n[i]].rect.left;
|
||||
int offsetY = ld.lli[n[i]].rect.top;
|
||||
int mode = ld.lli[n[i]].mode;
|
||||
baseImage.Composite(overlayImage, offsetX, offsetY, (mode == 3) ? CompositeOperator.Multiply : ((mode == 10) ? CompositeOperator.Plus : CompositeOperator.Over));
|
||||
}
|
||||
lsfDatas.Add(lsfData);
|
||||
lsfData = new();
|
||||
baseImage.Write(target);
|
||||
return true;
|
||||
}
|
||||
|
||||
private LsfFileHeader LoadLsfHeader(string path)
|
||||
public static bool STProcess()
|
||||
{
|
||||
using var fs = new FileStream(path, FileMode.Open, FileAccess.Read);
|
||||
if (fs.Length < 0x1C)
|
||||
throw new Exception("Invalid LSF Header");
|
||||
using var br = new BinaryReader(fs);
|
||||
byte[] head = br.ReadBytes(4);
|
||||
if (!head.SequenceEqual(lsfFileSignature))
|
||||
throw new Exception("Invalid LSF file");
|
||||
LsfFileHeader lfh = new()
|
||||
{
|
||||
//lfh.signature = br.ReadUInt32(); //无用
|
||||
revision = br.ReadUInt16(),
|
||||
bg = br.ReadUInt16(),
|
||||
id = br.ReadUInt16(),
|
||||
layer_count = br.ReadUInt16(),
|
||||
width = br.ReadInt32(),
|
||||
height = br.ReadInt32(),
|
||||
bx = br.ReadInt32(),
|
||||
by = br.ReadInt32()
|
||||
};
|
||||
return lfh;
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private LsfLayerInfo[] LoadLsfLayerInfo(string path)
|
||||
{
|
||||
EncodingProvider provider = CodePagesEncodingProvider.Instance;
|
||||
Encoding? shiftJis = provider.GetEncoding("shift-jis");
|
||||
using var fs = new FileStream(path, FileMode.Open, FileAccess.Read);
|
||||
using var br = new BinaryReader(fs);
|
||||
br.ReadBytes(0x1C); // Skip the header
|
||||
long remainingBytes = br.BaseStream.Length - br.BaseStream.Position;
|
||||
if (remainingBytes != lsfData.lfh.layer_count * 0xA4)
|
||||
throw new Exception("Invalid LSF Layer Info");
|
||||
LsfLayerInfo[] llis = new LsfLayerInfo[lsfData.lfh.layer_count];
|
||||
for (int i = 0; i < lsfData.lfh.layer_count; i++)
|
||||
{
|
||||
LsfLayerInfo l = new()
|
||||
{
|
||||
name = br.ReadBytes(64),
|
||||
text = br.ReadBytes(64),
|
||||
rect = new Rect
|
||||
{
|
||||
left = br.ReadInt32(),
|
||||
top = br.ReadInt32(),
|
||||
right = br.ReadInt32(),
|
||||
bottom = br.ReadInt32()
|
||||
},
|
||||
cx = br.ReadInt32(),
|
||||
cy = br.ReadInt32(),
|
||||
index = br.ReadByte(),
|
||||
state = br.ReadByte(),
|
||||
mode = br.ReadByte(),
|
||||
opacity = br.ReadByte(),
|
||||
fill = br.ReadUInt32(),
|
||||
value = br.ReadUInt32()
|
||||
};
|
||||
if (l.name.Take(4).SequenceEqual(lsfLayerSkipSignature))//临时处理
|
||||
l.skip = true;
|
||||
l.nameStr = shiftJis.GetString(l.name).TrimEnd('\0');
|
||||
l.textStr = shiftJis.GetString(l.text).TrimEnd('\0');
|
||||
l.indexStr = l.index.ToString().TrimEnd('\0');
|
||||
l.stateStr = l.state.ToString().TrimEnd('\0');
|
||||
l.modeStr = l.mode.ToString().TrimEnd('\0');
|
||||
l.opacityStr = l.opacity.ToString().TrimEnd('\0');
|
||||
llis[i] = l;
|
||||
}
|
||||
return llis;
|
||||
}
|
||||
|
||||
private Image LoadLsfImage(string imgPath)
|
||||
{
|
||||
if (!File.Exists(imgPath))
|
||||
throw new Exception("Image file not found");//一般文件都是存在的,不存在是因为这是特殊lsf
|
||||
Image i = new()
|
||||
{
|
||||
fileStr = imgPath,
|
||||
isFile = true,
|
||||
reff = 1
|
||||
};
|
||||
if (preFetchInfo)
|
||||
{
|
||||
using var image = new MagickImage(imgPath);
|
||||
i.width = image.Width;
|
||||
i.height = image.Height;
|
||||
i.depth = image.Depth;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
244
EscudeTools/LsfManager.cs
Normal file
244
EscudeTools/LsfManager.cs
Normal file
@ -0,0 +1,244 @@
|
||||
using ImageMagick;
|
||||
using System.Text;
|
||||
|
||||
namespace EscudeTools
|
||||
{
|
||||
public class Image
|
||||
{
|
||||
//public byte[] file = new byte[64]; // Image file name
|
||||
//public int page; // Image memory
|
||||
//public int back_page; // Back image memory
|
||||
public uint width; // Width
|
||||
public uint height; // Height
|
||||
public uint depth; // Color depth
|
||||
//public int id; // ID
|
||||
public int reff; // Reference counter
|
||||
//public bool cache; // Cache flag
|
||||
public bool isFile; // Is it an image file
|
||||
//public uint[] extra = new uint[8]; // Reserved
|
||||
|
||||
public string fileStr; // 自己加的,用于保存文件名
|
||||
}
|
||||
public class GInfo
|
||||
{
|
||||
public int width; // Width
|
||||
public int height; // Height
|
||||
public int depth; // Color depth
|
||||
public string pixel; // address of the pixel data
|
||||
public uint pitch;
|
||||
public string palette;
|
||||
}
|
||||
public class LsfImage
|
||||
{
|
||||
//public bool cache; // Cache flag
|
||||
public Image img; // Layer image
|
||||
}
|
||||
public class LsfData
|
||||
{
|
||||
//public byte[] path = new byte[64]; // LSF folder
|
||||
public LsfFileHeader lfh; // LSF file header
|
||||
public LsfLayerInfo[] lli; // LSF layer information
|
||||
public LsfImage[] layer; // LSF layer image
|
||||
|
||||
public string pathStr;
|
||||
public string lsfName;
|
||||
}
|
||||
public class LsfFileHeader
|
||||
{
|
||||
//public uint signature; // Header signature (LSF) 0x46534C
|
||||
public ushort revision; // Revision number
|
||||
public ushort bg; // Background flag
|
||||
public ushort id; // ID
|
||||
public ushort layer_count; // Number of layers
|
||||
public int width; // Width in pixels
|
||||
public int height; // Height in pixels
|
||||
public int bx; // Base coordinates
|
||||
public int by; // Base coordinates
|
||||
}
|
||||
public class LsfLayerInfo
|
||||
{
|
||||
public byte[] name = new byte[64]; // File name
|
||||
public byte[] text = new byte[64]; // Generic string
|
||||
public Rect rect; // Layer position
|
||||
public int cx; // Center coordinates
|
||||
public int cy; // Center coordinates
|
||||
public byte index; // Position
|
||||
public byte state; // State
|
||||
public byte mode; // Drawing mode
|
||||
public byte opacity; // Opacity
|
||||
public uint fill; // Fill color
|
||||
public uint value; // Generic value
|
||||
|
||||
public string nameStr; // 自己加的,用于保存文件名
|
||||
public string textStr; // 自己加的,用于保存通用名
|
||||
public string indexStr; // Position str
|
||||
public string stateStr; // State str
|
||||
public string modeStr; // Drawing mode str
|
||||
public string opacityStr; // Opacity str
|
||||
|
||||
public bool skip = false; // 是否跳过
|
||||
|
||||
}
|
||||
public class Rect
|
||||
{
|
||||
public int left; // Top-left corner X coordinate of the rectangle
|
||||
public int top; // Top-left corner Y coordinate of the rectangle
|
||||
public int right; // Bottom-right corner X coordinate of the rectangle
|
||||
public int bottom; // Bottom-right corner Y coordinate of the rectangle
|
||||
}
|
||||
public class CgInfo
|
||||
{
|
||||
public int kind; // Image category
|
||||
public int index; // Image index
|
||||
public int x; // Coordinates
|
||||
public int y; // Coordinates
|
||||
public int scale; // Scale factor
|
||||
public bool loop; // Loop flag
|
||||
public byte[] name = new byte[64]; // Registered name
|
||||
public byte[] file = new byte[64]; // File name
|
||||
public byte[] option = new byte[128]; // Options
|
||||
public uint coverd; // White-out ID
|
||||
public uint filter; // Filter
|
||||
public uint color; // Color
|
||||
public uint id; // Image identification ID
|
||||
public uint loc; // Coordinate list
|
||||
public uint spot; // Coordinate index
|
||||
public int order; // CG viewing display order
|
||||
public uint link; // Related CG
|
||||
|
||||
public string nameStr;
|
||||
public string fileStr;
|
||||
public string optionStr;
|
||||
}
|
||||
public class LsfManager
|
||||
{
|
||||
static readonly byte[] lsfFileSignature = [0x4C, 0x53, 0x46, 0x00];
|
||||
static readonly byte[] lsfLayerSkipSignature = [0x00, 0x75, 0x6C, 0x00]; //flowchat部分的lsf块
|
||||
private static string WorkPath = string.Empty;
|
||||
private LsfData lsfData = new();
|
||||
private Dictionary<string, LsfData> lsfDataLookup = new();
|
||||
|
||||
private bool preFetchInfo;
|
||||
|
||||
public bool LoadLsf(string path, bool preFI = false)
|
||||
{
|
||||
if (!File.Exists(path))
|
||||
return false;
|
||||
preFetchInfo = preFI;
|
||||
lsfData.pathStr = Path.GetDirectoryName(path);
|
||||
lsfData.lsfName = Path.GetFileNameWithoutExtension(path).ToLower();
|
||||
lsfData.lfh = LoadLsfHeader(path);
|
||||
lsfData.lli = LoadLsfLayerInfo(path);
|
||||
lsfData.layer = new LsfImage[lsfData.lfh.layer_count];
|
||||
for (int i = 0; i < lsfData.lfh.layer_count; i++)
|
||||
{
|
||||
string imgPath = Path.Combine(lsfData.pathStr, lsfData.lli[i].nameStr + ".png");
|
||||
LsfImage li = new();
|
||||
if (!lsfData.lli[i].skip)
|
||||
{
|
||||
li.img = LoadLsfImage(imgPath);
|
||||
lsfData.layer[i] = li;
|
||||
}
|
||||
}
|
||||
lsfDataLookup[lsfData.lsfName] = lsfData;
|
||||
lsfData = new();
|
||||
return true;
|
||||
}
|
||||
|
||||
public LsfData? FindLsfDataByName(string name)
|
||||
{
|
||||
lsfDataLookup.TryGetValue(name.ToLower(), out var lsfData);
|
||||
return lsfData; // 如果未找到,则返回 null
|
||||
}
|
||||
|
||||
private LsfFileHeader LoadLsfHeader(string path)
|
||||
{
|
||||
using var fs = new FileStream(path, FileMode.Open, FileAccess.Read);
|
||||
if (fs.Length < 0x1C)
|
||||
throw new Exception("Invalid LSF Header");
|
||||
using var br = new BinaryReader(fs);
|
||||
byte[] head = br.ReadBytes(4);
|
||||
if (!head.SequenceEqual(lsfFileSignature))
|
||||
throw new Exception("Invalid LSF file");
|
||||
LsfFileHeader lfh = new()
|
||||
{
|
||||
//lfh.signature = br.ReadUInt32(); //无用
|
||||
revision = br.ReadUInt16(),
|
||||
bg = br.ReadUInt16(),
|
||||
id = br.ReadUInt16(),
|
||||
layer_count = br.ReadUInt16(),
|
||||
width = br.ReadInt32(),
|
||||
height = br.ReadInt32(),
|
||||
bx = br.ReadInt32(),
|
||||
by = br.ReadInt32()
|
||||
};
|
||||
return lfh;
|
||||
}
|
||||
|
||||
private LsfLayerInfo[] LoadLsfLayerInfo(string path)
|
||||
{
|
||||
EncodingProvider provider = CodePagesEncodingProvider.Instance;
|
||||
Encoding? shiftJis = provider.GetEncoding("shift-jis");
|
||||
using var fs = new FileStream(path, FileMode.Open, FileAccess.Read);
|
||||
using var br = new BinaryReader(fs);
|
||||
br.ReadBytes(0x1C); // Skip the header
|
||||
long remainingBytes = br.BaseStream.Length - br.BaseStream.Position;
|
||||
if (remainingBytes != lsfData.lfh.layer_count * 0xA4)
|
||||
throw new Exception("Invalid LSF Layer Info");
|
||||
LsfLayerInfo[] llis = new LsfLayerInfo[lsfData.lfh.layer_count];
|
||||
for (int i = 0; i < lsfData.lfh.layer_count; i++)
|
||||
{
|
||||
LsfLayerInfo l = new()
|
||||
{
|
||||
name = br.ReadBytes(64),
|
||||
text = br.ReadBytes(64),
|
||||
rect = new Rect
|
||||
{
|
||||
left = br.ReadInt32(),
|
||||
top = br.ReadInt32(),
|
||||
right = br.ReadInt32(),
|
||||
bottom = br.ReadInt32()
|
||||
},
|
||||
cx = br.ReadInt32(),
|
||||
cy = br.ReadInt32(),
|
||||
index = br.ReadByte(),
|
||||
state = br.ReadByte(),
|
||||
mode = br.ReadByte(),
|
||||
opacity = br.ReadByte(),
|
||||
fill = br.ReadUInt32(),
|
||||
value = br.ReadUInt32()
|
||||
};
|
||||
if (l.name.Take(4).SequenceEqual(lsfLayerSkipSignature))//临时处理
|
||||
l.skip = true;
|
||||
l.nameStr = shiftJis.GetString(l.name).TrimEnd('\0');
|
||||
l.textStr = shiftJis.GetString(l.text).TrimEnd('\0');
|
||||
l.indexStr = l.index.ToString().TrimEnd('\0');
|
||||
l.stateStr = l.state.ToString().TrimEnd('\0');
|
||||
l.modeStr = l.mode.ToString().TrimEnd('\0');
|
||||
l.opacityStr = l.opacity.ToString().TrimEnd('\0');
|
||||
llis[i] = l;
|
||||
}
|
||||
return llis;
|
||||
}
|
||||
|
||||
private Image LoadLsfImage(string imgPath)
|
||||
{
|
||||
if (!File.Exists(imgPath))
|
||||
throw new Exception("Image file not found");//一般文件都是存在的,不存在是因为这是特殊lsf
|
||||
Image i = new()
|
||||
{
|
||||
fileStr = imgPath,
|
||||
isFile = true,
|
||||
reff = 1
|
||||
};
|
||||
if (preFetchInfo)
|
||||
{
|
||||
using var image = new MagickImage(imgPath);
|
||||
i.width = image.Width;
|
||||
i.height = image.Height;
|
||||
i.depth = image.Depth;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,226 +1,408 @@
|
||||
namespace EscudeTools
|
||||
using Microsoft.Data.Sqlite;
|
||||
|
||||
namespace EscudeTools
|
||||
{
|
||||
internal class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
if (Directory.Exists(args[0]))
|
||||
if (Directory.Exists(args[0]) && File.Exists(args[1]))
|
||||
//if (File.Exists(args[0]))
|
||||
{
|
||||
string graphicsDBPath = args[1];
|
||||
using SqliteConnection connection = new($"Data Source={graphicsDBPath};");
|
||||
connection.Open();
|
||||
List<string> tableNames = [];
|
||||
string[] foundTN = new string[2];
|
||||
List<int> tableIds = [];
|
||||
bool found1 = false, found2 = false;
|
||||
using (var command = new SqliteCommand("SELECT name FROM sqlite_master WHERE type='table';", connection))
|
||||
using (var reader = command.ExecuteReader())
|
||||
{
|
||||
int id = 0;
|
||||
while (reader.Read())
|
||||
{
|
||||
string tableName = reader.GetString(0);
|
||||
if (tableName.StartsWith("イベント"))
|
||||
{
|
||||
foundTN[0] = tableName;
|
||||
found1 = true;
|
||||
}
|
||||
else if (tableName.StartsWith("立ち"))
|
||||
{
|
||||
foundTN[1] = tableName;
|
||||
found2 = true;
|
||||
}
|
||||
tableNames.Add(tableName);
|
||||
tableIds.Add(id++);
|
||||
}
|
||||
}
|
||||
if (!(found1 && found2))
|
||||
{
|
||||
for (int i = 0; i < tableNames.Count; i++)
|
||||
Console.WriteLine($"{tableIds[i]}: {tableNames[i]}");
|
||||
if (!found1)
|
||||
{
|
||||
Console.WriteLine("自动识别失败,请选择存放CG信息的数据表ID: ");
|
||||
string? input = Console.ReadLine();
|
||||
if (int.TryParse(input, out int userInputId))
|
||||
{
|
||||
if (userInputId >= 0 && userInputId < tableIds.Count)
|
||||
{
|
||||
foundTN[0] = tableNames[userInputId];
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Invalid ID.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Invalid input. Please enter a valid number.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!found2)
|
||||
{
|
||||
Console.WriteLine("自动识别失败,请选择存放立绘信息的数据表ID: ");
|
||||
string? input = Console.ReadLine();
|
||||
if (int.TryParse(input, out int userInputId))
|
||||
{
|
||||
if (userInputId >= 0 && userInputId < tableIds.Count)
|
||||
{
|
||||
foundTN[1] = tableNames[userInputId];
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Invalid ID.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Invalid input. Please enter a valid number.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
List<EvTable> evts = [];
|
||||
List<StTable> stts = [];
|
||||
using (var command = new SqliteCommand($"SELECT * FROM {foundTN[0]};", connection))
|
||||
{
|
||||
using var reader = command.ExecuteReader();
|
||||
while (reader.Read())
|
||||
{
|
||||
if (reader.IsDBNull(0) || string.IsNullOrEmpty(reader.GetString(0)))
|
||||
continue;
|
||||
evts.Add(new EvTable
|
||||
{
|
||||
name = reader.GetString(0),
|
||||
file = reader.GetString(1),
|
||||
option = reader.GetString(2).Split(' '),
|
||||
coverd = (uint)reader.GetInt32(3),
|
||||
filter = (uint)reader.GetInt32(4),
|
||||
color = (uint)reader.GetInt32(5),
|
||||
id = (uint)reader.GetInt32(6),
|
||||
loc = (uint)reader.GetInt32(7),
|
||||
order = reader.GetInt32(8),
|
||||
link = (uint)reader.GetInt32(9)
|
||||
});
|
||||
}
|
||||
}
|
||||
using (var command = new SqliteCommand($"SELECT * FROM {foundTN[1]};", connection))
|
||||
{
|
||||
using var reader = command.ExecuteReader();
|
||||
while (reader.Read())
|
||||
{
|
||||
if (reader.IsDBNull(0) || string.IsNullOrEmpty(reader.GetString(0)))
|
||||
continue;
|
||||
stts.Add(new StTable
|
||||
{
|
||||
name = reader.GetString(0),
|
||||
file = reader.GetString(1),
|
||||
option = reader.GetString(2).Split(' '),
|
||||
coverd = (uint)reader.GetInt32(3),
|
||||
filter = (uint)reader.GetInt32(4),
|
||||
color = (uint)reader.GetInt32(5),
|
||||
id = (uint)reader.GetInt32(6),
|
||||
loc = (uint)reader.GetInt32(7),
|
||||
order = reader.GetInt32(8),
|
||||
link = (uint)reader.GetInt32(9)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
string[] files = Directory.GetFiles(args[0], "*.lsf", SearchOption.AllDirectories);
|
||||
ImageManager im = new();
|
||||
LsfManager lm = new();
|
||||
foreach (string file in files)
|
||||
{
|
||||
if (im.LoadLsf(file))
|
||||
if (lm.LoadLsf(file, true))
|
||||
Console.WriteLine($"Load {file} Success");
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"Load {file} Failed");
|
||||
}
|
||||
}
|
||||
Console.WriteLine("OK");
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// NOTE
|
||||
// 推荐使用DB Browser for SQLite (https://sqlitebrowser.org/) 查看、编辑导出的数据库文件
|
||||
// 这不是广告,这只是我在开发期间使用的工具
|
||||
|
||||
////Batch Unpack ESC-ARC Package
|
||||
//if (Directory.Exists(args[0]))
|
||||
//{
|
||||
// string[] files = Directory.GetFiles(args[0], "*.bin");
|
||||
// PackManager pm = new();
|
||||
// foreach (string file in files)
|
||||
// {
|
||||
// if (pm.Load(file))
|
||||
// {
|
||||
// Console.WriteLine($"Load {file} Success");
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// Console.WriteLine($"Load {file} Failed");
|
||||
// }
|
||||
|
||||
// if (pm.Extract())
|
||||
// Console.WriteLine("Extract Package Success");
|
||||
// else
|
||||
// {
|
||||
// Console.WriteLine("Extract Package Failed");
|
||||
// }
|
||||
// }
|
||||
connection.Close();
|
||||
string outputDir = Path.Combine(Path.GetDirectoryName(args[0]), "Output");
|
||||
if (!Directory.Exists(outputDir))
|
||||
Directory.CreateDirectory(outputDir);
|
||||
var parallelOptions = new ParallelOptions
|
||||
{
|
||||
MaxDegreeOfParallelism = 6 // 设置最大并行线程数
|
||||
};
|
||||
Parallel.ForEach(evts, parallelOptions, evt =>
|
||||
//foreach (EvTable evt in evts)
|
||||
{
|
||||
if (evt.order == 0) //仅提取鉴赏中有的CG
|
||||
return;
|
||||
//continue;
|
||||
string targetFilename = Path.Combine(outputDir, evt.name + ".png"); //最后保存可用的文件名(这里还没有后缀)
|
||||
LsfData lsfData = lm.FindLsfDataByName(evt.file) ?? throw new Exception("Something Wrong");
|
||||
List<int> pendingList = [];
|
||||
foreach (string o in evt.option)
|
||||
{
|
||||
int t = TableManagercs.ParseOptions(lsfData, o);
|
||||
if (t == -1)
|
||||
continue;
|
||||
pendingList.Add(t);
|
||||
}
|
||||
if (pendingList[0] != 0)
|
||||
pendingList.Insert(0, 0);
|
||||
if (!ImageManager.EvProcess(lsfData, [.. pendingList], targetFilename))
|
||||
throw new Exception("Process Fail");
|
||||
else
|
||||
Console.WriteLine($"Export {evt.name} Success");
|
||||
});
|
||||
//}
|
||||
|
||||
////Batch Repack ESC-ARC Package
|
||||
//if (Directory.Exists(args[0]) && Directory.Exists(args[1]))
|
||||
//{
|
||||
// string[] directories = Directory.GetDirectories(args[0]);
|
||||
// foreach (string directory in directories)
|
||||
// {
|
||||
// PackManager pm = new();
|
||||
// string providerFilePath = Path.Combine(args[1], Path.GetFileName(directory) + ".bin");
|
||||
// if (pm.Repack(directory, 2,true, providerFilePath))
|
||||
// Console.WriteLine("Repack Package Success");
|
||||
// else
|
||||
// {
|
||||
// Console.WriteLine("Repack Package Failed");
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
|
||||
////Batch Unpack Script(Full, Text, Mess)
|
||||
//if (Directory.Exists(args[0]))
|
||||
//{
|
||||
// string[] files = Directory.GetFiles(args[0], "*.bin");
|
||||
// foreach (string file in files)
|
||||
// {
|
||||
// ScriptManager smr = new();
|
||||
// if (smr.LoadScriptFile(file))
|
||||
// {
|
||||
// Console.WriteLine($"Load {file} Success");
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// Console.WriteLine($"Load {file} Failed");
|
||||
// return;
|
||||
// }
|
||||
// if (smr.ExportDatabase(Path.GetDirectoryName(args[0])))
|
||||
// Console.WriteLine("Export Script Success");
|
||||
// else
|
||||
// {
|
||||
// Console.WriteLine("Export Script Failed");
|
||||
// return;
|
||||
// }
|
||||
// if (smr.ExportTextDatabase(Path.GetDirectoryName(args[0])))
|
||||
// Console.WriteLine("Export Text Success");
|
||||
// else
|
||||
// {
|
||||
// Console.WriteLine("Export Text Failed");
|
||||
// return;
|
||||
// }
|
||||
// if (smr.ExportMessDatabase(Path.GetDirectoryName(args[0])))
|
||||
// Console.WriteLine("Export Mess Success");
|
||||
// else
|
||||
// {
|
||||
// Console.WriteLine("Export Mess Failed");
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
////Export Full Script
|
||||
//if (File.Exists(args[0])) //fail //lost 1 //something diff
|
||||
//{
|
||||
// ScriptManager.Repackv1(args[0], true);
|
||||
//}
|
||||
|
||||
////Export ScriptMessage
|
||||
//if (File.Exists(args[1])) //pass
|
||||
//{
|
||||
// ScriptManager.Repackv2(args[1], true);
|
||||
//}
|
||||
|
||||
//////Export ScriptFile
|
||||
//if (File.Exists(args[2])) //pass
|
||||
//{
|
||||
// ScriptManager.Repackv3(args[2]);
|
||||
//}
|
||||
|
||||
|
||||
|
||||
//ScriptManager smr = new();
|
||||
//smr.LoadScriptFile(args[0]); //加载.bin文件
|
||||
//smr.ExportDatabase(Path.GetDirectoryName(args[0]));
|
||||
//smr.ExportMessDatabase(Path.GetDirectoryName(args[0]));
|
||||
//return;
|
||||
|
||||
|
||||
//if (Directory.Exists(args[0]))
|
||||
//{
|
||||
// string[] files = Directory.GetFiles(args[0], "*.db");
|
||||
|
||||
// foreach (string file in files)
|
||||
// {
|
||||
// DatabaseManager.ExportMDB(file);
|
||||
|
||||
// }
|
||||
//}
|
||||
|
||||
//if (Directory.Exists(args[0]))
|
||||
//{
|
||||
// string[] files = Directory.GetFiles(args[0], "*.bin");
|
||||
// DatabaseManager dm = new();
|
||||
// foreach (string file in files)
|
||||
// {
|
||||
// dm.LoadDatabase(file);
|
||||
// if (dm.ExportDatabase(Path.GetDirectoryName(args[0])))
|
||||
// Console.WriteLine("Export Database Success");
|
||||
// }
|
||||
|
||||
//}
|
||||
|
||||
|
||||
//if (Directory.Exists(args[0]))
|
||||
//{
|
||||
// string[] files = Directory.GetFiles(args[0], "db_*.bin");
|
||||
// DatabaseManager dm = new();
|
||||
// foreach (string file in files)
|
||||
// {
|
||||
// if (dm.LoadDatabase(file))
|
||||
// {
|
||||
// Console.WriteLine($"Load {file} Success");
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// Console.WriteLine($"Load {file} Failed");
|
||||
// return;
|
||||
// }
|
||||
|
||||
// if (dm.ExportDatabase(Path.GetDirectoryName(args[0])))
|
||||
// Console.WriteLine("Export Database Success");
|
||||
// else
|
||||
// {
|
||||
// Console.WriteLine("Export Database Failed");
|
||||
// return;
|
||||
// }
|
||||
|
||||
// }
|
||||
|
||||
//}
|
||||
|
||||
|
||||
// if (args.Length == 0 || args.Length > 2)
|
||||
// {
|
||||
// Console.WriteLine("Invalid arguments. Use -h for help.");
|
||||
// return;
|
||||
// }
|
||||
|
||||
// switch (args[0])
|
||||
// {
|
||||
// case "-h":
|
||||
// case "-r":
|
||||
// case "-d":
|
||||
// case "-s":
|
||||
// default:
|
||||
// break;
|
||||
// }
|
||||
//}
|
||||
//static void DisplayHelp()
|
||||
//{
|
||||
// Console.WriteLine("Usage: EscudeTools.exe [-r <filepath>] [-d <directory>] [-s <filepath>] [-h]");
|
||||
// Console.WriteLine("Options:");
|
||||
// Console.WriteLine(" <filepath> Single lsf process");
|
||||
// Console.WriteLine(" -r <filepath> Read single lsf file");
|
||||
// Console.WriteLine(" -d <directory> Process all lsf files in directory");
|
||||
// Console.WriteLine(" -s <filepath> Same as <filepath>");
|
||||
// Console.WriteLine(" -h Display help info");
|
||||
//}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//// 批量读取lsf文件
|
||||
//if (Directory.Exists(args[0]))
|
||||
//{
|
||||
// string[] files = Directory.GetFiles(args[0], "*.lsf", SearchOption.AllDirectories);
|
||||
// LsfManager lm = new();
|
||||
// foreach (string file in files)
|
||||
// {
|
||||
// if (lm.LoadLsf(file, true))
|
||||
// Console.WriteLine($"Load {file} Success");
|
||||
// else
|
||||
// {
|
||||
// Console.WriteLine($"Load {file} Failed");
|
||||
// }
|
||||
// }
|
||||
// Console.WriteLine("OK");
|
||||
|
||||
//}
|
||||
|
||||
|
||||
|
||||
|
||||
// NOTE
|
||||
// 推荐使用DB Browser for SQLite (https://sqlitebrowser.org/) 查看、编辑导出的数据库文件
|
||||
// 这不是广告,这只是我在开发期间使用的工具
|
||||
|
||||
////Batch Unpack ESC-ARC Package
|
||||
//if (Directory.Exists(args[0]))
|
||||
//{
|
||||
// string[] files = Directory.GetFiles(args[0], "*.bin");
|
||||
// PackManager pm = new();
|
||||
// foreach (string file in files)
|
||||
// {
|
||||
// if (pm.Load(file))
|
||||
// {
|
||||
// Console.WriteLine($"Load {file} Success");
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// Console.WriteLine($"Load {file} Failed");
|
||||
// }
|
||||
|
||||
// if (pm.Extract())
|
||||
// Console.WriteLine("Extract Package Success");
|
||||
// else
|
||||
// {
|
||||
// Console.WriteLine("Extract Package Failed");
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
////Batch Repack ESC-ARC Package
|
||||
//if (Directory.Exists(args[0]) && Directory.Exists(args[1]))
|
||||
//{
|
||||
// string[] directories = Directory.GetDirectories(args[0]);
|
||||
// foreach (string directory in directories)
|
||||
// {
|
||||
// PackManager pm = new();
|
||||
// string providerFilePath = Path.Combine(args[1], Path.GetFileName(directory) + ".bin");
|
||||
// if (pm.Repack(directory, 2,true, providerFilePath))
|
||||
// Console.WriteLine("Repack Package Success");
|
||||
// else
|
||||
// {
|
||||
// Console.WriteLine("Repack Package Failed");
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
|
||||
////Batch Unpack Script(Full, Text, Mess)
|
||||
//if (Directory.Exists(args[0]))
|
||||
//{
|
||||
// string[] files = Directory.GetFiles(args[0], "*.bin");
|
||||
// foreach (string file in files)
|
||||
// {
|
||||
// ScriptManager smr = new();
|
||||
// if (smr.LoadScriptFile(file))
|
||||
// {
|
||||
// Console.WriteLine($"Load {file} Success");
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// Console.WriteLine($"Load {file} Failed");
|
||||
// return;
|
||||
// }
|
||||
// if (smr.ExportDatabase(Path.GetDirectoryName(args[0])))
|
||||
// Console.WriteLine("Export Script Success");
|
||||
// else
|
||||
// {
|
||||
// Console.WriteLine("Export Script Failed");
|
||||
// return;
|
||||
// }
|
||||
// if (smr.ExportTextDatabase(Path.GetDirectoryName(args[0])))
|
||||
// Console.WriteLine("Export Text Success");
|
||||
// else
|
||||
// {
|
||||
// Console.WriteLine("Export Text Failed");
|
||||
// return;
|
||||
// }
|
||||
// if (smr.ExportMessDatabase(Path.GetDirectoryName(args[0])))
|
||||
// Console.WriteLine("Export Mess Success");
|
||||
// else
|
||||
// {
|
||||
// Console.WriteLine("Export Mess Failed");
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
////Export Full Script
|
||||
//if (File.Exists(args[0])) //fail //lost 1 //something diff
|
||||
//{
|
||||
// ScriptManager.Repackv1(args[0], true);
|
||||
//}
|
||||
|
||||
////Export ScriptMessage
|
||||
//if (File.Exists(args[1])) //pass
|
||||
//{
|
||||
// ScriptManager.Repackv2(args[1], true);
|
||||
//}
|
||||
|
||||
//////Export ScriptFile
|
||||
//if (File.Exists(args[2])) //pass
|
||||
//{
|
||||
// ScriptManager.Repackv3(args[2]);
|
||||
//}
|
||||
|
||||
|
||||
|
||||
//ScriptManager smr = new();
|
||||
//smr.LoadScriptFile(args[0]); //加载.bin文件
|
||||
//smr.ExportDatabase(Path.GetDirectoryName(args[0]));
|
||||
//smr.ExportMessDatabase(Path.GetDirectoryName(args[0]));
|
||||
//return;
|
||||
|
||||
|
||||
//if (Directory.Exists(args[0]))
|
||||
//{
|
||||
// string[] files = Directory.GetFiles(args[0], "*.db");
|
||||
|
||||
// foreach (string file in files)
|
||||
// {
|
||||
// DatabaseManager.ExportMDB(file);
|
||||
|
||||
// }
|
||||
//}
|
||||
|
||||
//if (Directory.Exists(args[0]))
|
||||
//{
|
||||
// string[] files = Directory.GetFiles(args[0], "*.bin");
|
||||
// DatabaseManager dm = new();
|
||||
// foreach (string file in files)
|
||||
// {
|
||||
// dm.LoadDatabase(file);
|
||||
// if (dm.ExportDatabase(Path.GetDirectoryName(args[0])))
|
||||
// Console.WriteLine("Export Database Success");
|
||||
// }
|
||||
|
||||
//}
|
||||
|
||||
|
||||
//if (Directory.Exists(args[0]))
|
||||
//{
|
||||
// string[] files = Directory.GetFiles(args[0], "db_*.bin");
|
||||
// DatabaseManager dm = new();
|
||||
// foreach (string file in files)
|
||||
// {
|
||||
// if (dm.LoadDatabase(file))
|
||||
// {
|
||||
// Console.WriteLine($"Load {file} Success");
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// Console.WriteLine($"Load {file} Failed");
|
||||
// return;
|
||||
// }
|
||||
|
||||
// if (dm.ExportDatabase(Path.GetDirectoryName(args[0])))
|
||||
// Console.WriteLine("Export Database Success");
|
||||
// else
|
||||
// {
|
||||
// Console.WriteLine("Export Database Failed");
|
||||
// return;
|
||||
// }
|
||||
|
||||
// }
|
||||
|
||||
//}
|
||||
|
||||
|
||||
// if (args.Length == 0 || args.Length > 2)
|
||||
// {
|
||||
// Console.WriteLine("Invalid arguments. Use -h for help.");
|
||||
// return;
|
||||
// }
|
||||
|
||||
// switch (args[0])
|
||||
// {
|
||||
// case "-h":
|
||||
// case "-r":
|
||||
// case "-d":
|
||||
// case "-s":
|
||||
// default:
|
||||
// break;
|
||||
// }
|
||||
//}
|
||||
//static void DisplayHelp()
|
||||
//{
|
||||
// Console.WriteLine("Usage: EscudeTools.exe [-r <filepath>] [-d <directory>] [-s <filepath>] [-h]");
|
||||
// Console.WriteLine("Options:");
|
||||
// Console.WriteLine(" <filepath> Single lsf process");
|
||||
// Console.WriteLine(" -r <filepath> Read single lsf file");
|
||||
// Console.WriteLine(" -d <directory> Process all lsf files in directory");
|
||||
// Console.WriteLine(" -s <filepath> Same as <filepath>");
|
||||
// Console.WriteLine(" -h Display help info");
|
||||
//}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
"profiles": {
|
||||
"EscudeTools": {
|
||||
"commandName": "Project",
|
||||
"commandLineArgs": "G:\\x221.local\\lab2"
|
||||
"commandLineArgs": "G:\\x221.local\\lab2\\ev\\1\r\n\"G:\\x221.local\\lab2\\db_graphics.db\""
|
||||
}
|
||||
}
|
||||
}
|
84
EscudeTools/TableManagercs.cs
Normal file
84
EscudeTools/TableManagercs.cs
Normal file
@ -0,0 +1,84 @@
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace EscudeTools
|
||||
{
|
||||
public class EvTable
|
||||
{
|
||||
public string name;
|
||||
public string file;
|
||||
public string[] option;
|
||||
public uint coverd;
|
||||
public uint filter;
|
||||
public uint color;
|
||||
public uint id;
|
||||
public uint loc;
|
||||
public int order;
|
||||
public uint link;
|
||||
}
|
||||
public class StTable
|
||||
{
|
||||
public string name;
|
||||
public string file;
|
||||
public string[] option;
|
||||
public uint coverd;
|
||||
public uint filter;
|
||||
public uint color;
|
||||
public uint id;
|
||||
public uint loc;
|
||||
public int order;
|
||||
public uint link;
|
||||
}
|
||||
public class TableManagercs
|
||||
{
|
||||
public static int ParseOptions(LsfData ld, string input)
|
||||
{
|
||||
// 正则表达式匹配 p*:* 格式
|
||||
Regex regex = new(@"p(\d+):(\d+)");
|
||||
MatchCollection matches = regex.Matches(input);
|
||||
|
||||
List<int> results = [];
|
||||
|
||||
foreach (Match match in matches)
|
||||
{
|
||||
if (match.Groups.Count == 3)
|
||||
{
|
||||
if (int.TryParse(match.Groups[1].Value, out int firstNumber) &&
|
||||
int.TryParse(match.Groups[2].Value, out int secondNumber))
|
||||
{
|
||||
results.Add(firstNumber);//index
|
||||
results.Add(secondNumber);//state //可能要+1
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < ld.lli.Length; i++)
|
||||
{
|
||||
if (ld.lli[i].index == 0 && ld.lli[i].state == 0)
|
||||
{
|
||||
if (ld.lli[i].index == results[0] && ld.lli[i].state + 1 == results[1])
|
||||
return i;
|
||||
}
|
||||
if (ld.lli[i].index == results[0] && ld.lli[i].state == results[1])
|
||||
return i;
|
||||
}
|
||||
//一般可以忽略这个警告
|
||||
Console.WriteLine($"[WARN] Found invalid index:state data {results[0]}:{results[1]} in {ld.lsfName}, may be a bug?");
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static int ParseCharactor(string input)
|
||||
{
|
||||
// 使用正则表达式匹配格式 * _ *
|
||||
Regex regex = new(@"^(\d+)_.*$");
|
||||
var match = regex.Match(input);
|
||||
|
||||
if (match.Success && match.Groups.Count > 1)
|
||||
{
|
||||
if (int.TryParse(match.Groups[1].Value, out int result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
BIN
example/2024-10-22_174116.png
Normal file
BIN
example/2024-10-22_174116.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 504 KiB |
Loading…
x
Reference in New Issue
Block a user