mirror of
https://github.com/KillzXGaming/Switch-Toolbox
synced 2024-11-22 12:33:12 +00:00
Add latest files
Start on base for BLO. These will probably not be usable for awhile and is wip.. Currently aiming to support more varied layouts so this can help improve the code base. Add BRFNT and BCFNT support. All merged as BXFNT class. Fix bflim 3ds with LA4 textures. Fix loading/saving part panes with property user data. Fix texture coordinates to default centered UVs for layout panes with no textures. Cleanup some files and directories.
This commit is contained in:
parent
ba43fa5633
commit
af8a8f17f6
55 changed files with 3667 additions and 1719 deletions
File diff suppressed because it is too large
Load diff
|
@ -1,26 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Drawing;
|
||||
using Toolbox.Library;
|
||||
using LibEveryFileExplorer.GFX;
|
||||
|
||||
namespace FirstPlugin
|
||||
{
|
||||
public class BXFNT
|
||||
{
|
||||
public virtual string Name { get; set; }
|
||||
|
||||
public virtual Bitmap GetBitmap(string text, bool reversewh, LayoutBXLYT.BasePane pane)
|
||||
{
|
||||
return new Bitmap(32,32);
|
||||
}
|
||||
|
||||
public virtual BitmapFont GetBitmapFont(bool UseChannelComp = false)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
501
File_Format_Library/FileFormats/Font/BXFNT/BXFNT.cs
Normal file
501
File_Format_Library/FileFormats/Font/BXFNT/BXFNT.cs
Normal file
|
@ -0,0 +1,501 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows.Forms;
|
||||
using Toolbox.Library;
|
||||
using System.IO;
|
||||
using Toolbox.Library.IO;
|
||||
using Toolbox.Library.Forms;
|
||||
using System.Drawing;
|
||||
using FirstPlugin.Forms;
|
||||
using LibEveryFileExplorer.GFX;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace FirstPlugin
|
||||
{
|
||||
public class BXFNT : IFileFormat, IEditor<BffntEditor>, IConvertableTextFormat
|
||||
{
|
||||
public FileType FileType { get; set; } = FileType.Font;
|
||||
|
||||
public bool CanSave { get; set; }
|
||||
public string[] Description { get; set; } = new string[] { "Cafe Font", "CTR Font", "Revolution Font" };
|
||||
public string[] Extension { get; set; } = new string[] { "*.bffnt", "*.bcfnt", "*.brfnt", };
|
||||
public string FileName { get; set; }
|
||||
public string FilePath { get; set; }
|
||||
public IFileInfo IFileInfo { get; set; }
|
||||
|
||||
public bool Identify(Stream stream)
|
||||
{
|
||||
using (var reader = new FileReader(stream, true))
|
||||
{
|
||||
return reader.CheckSignature(4, "FFNT") ||
|
||||
reader.CheckSignature(4, "CFNT") ||
|
||||
reader.CheckSignature(4, "RFNT");
|
||||
}
|
||||
}
|
||||
|
||||
public Type[] Types
|
||||
{
|
||||
get
|
||||
{
|
||||
List<Type> types = new List<Type>();
|
||||
return types.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
public FFNT bffnt;
|
||||
|
||||
public BffntEditor OpenForm()
|
||||
{
|
||||
BffntEditor form = new BffntEditor();
|
||||
form.Text = "Font Editor";
|
||||
form.Dock = DockStyle.Fill;
|
||||
return form;
|
||||
}
|
||||
|
||||
public void FillEditor(UserControl control)
|
||||
{
|
||||
((BffntEditor)control).LoadFontFile(this);
|
||||
}
|
||||
|
||||
|
||||
#region Text Converter Interface
|
||||
public TextFileType TextFileType => TextFileType.Yaml;
|
||||
public bool CanConvertBack => false;
|
||||
|
||||
public string ConvertToString()
|
||||
{
|
||||
return BxfntYamlConverter.ToYaml(bffnt);
|
||||
}
|
||||
|
||||
public void ConvertFromString(string text)
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public void Load(System.IO.Stream stream)
|
||||
{
|
||||
PluginRuntime.BxfntFiles.Add(this);
|
||||
|
||||
CanSave = true;
|
||||
|
||||
bffnt = new FFNT();
|
||||
bffnt.Read(new FileReader(stream));
|
||||
|
||||
TGLP tglp = bffnt.FontSection.TextureGlyph;
|
||||
|
||||
if (tglp.SheetDataList.Count > 0)
|
||||
{
|
||||
if (bffnt.Platform == FFNT.PlatformType.NX)
|
||||
{
|
||||
var bntx = STFileLoader.OpenFileFormat(
|
||||
new MemoryStream(Utils.CombineByteArray(tglp.SheetDataList.ToArray())), "Sheet_0");
|
||||
if (bntx != null)
|
||||
{
|
||||
tglp.BinaryTextureFile = (BNTX)bntx;
|
||||
}
|
||||
}
|
||||
else if (bffnt.Platform == FFNT.PlatformType.Cafe)
|
||||
{
|
||||
for (int s = 0; s < tglp.SheetDataList.Count; s++) {
|
||||
var surface = new Gx2ImageBlock();
|
||||
surface.Text = $"Sheet_{s}";
|
||||
surface.Load(tglp, s);
|
||||
tglp.Textures.Add(surface);
|
||||
}
|
||||
}
|
||||
else if (bffnt.Platform == FFNT.PlatformType.Ctr)
|
||||
{
|
||||
for (int s = 0; s < tglp.SheetDataList.Count; s++)
|
||||
{
|
||||
var surface = new CtrImageBlock();
|
||||
surface.Text = $"Sheet_{s}";
|
||||
surface.Load(tglp, s);
|
||||
surface.GetBitmap().Save($"Image{s}.png");
|
||||
tglp.Textures.Add(surface);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int s = 0; s < tglp.SheetDataList.Count; s++)
|
||||
{
|
||||
var surface = new RevImageBlock();
|
||||
surface.Text = $"Sheet_{s}";
|
||||
surface.Load(tglp, s);
|
||||
surface.GetBitmap().Save($"Image{s}.png");
|
||||
tglp.Textures.Add(surface);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
foreach (byte[] texture in tglp.SheetDataList)
|
||||
{
|
||||
// BNTX file = (BNTX)STFileLoader.OpenFileFormat("Sheet" + i++, texture);
|
||||
// Nodes.Add(file);
|
||||
}
|
||||
}
|
||||
|
||||
public string Name { get { return FileName; } }
|
||||
|
||||
public BitmapFont GetBitmapFont(bool UseChannelComp = false)
|
||||
{
|
||||
return bffnt.GetBitmapFont(UseChannelComp);
|
||||
}
|
||||
|
||||
public Bitmap GetBitmap(string text, bool reversewh, LayoutBXLYT.BasePane pane)
|
||||
{
|
||||
return bffnt.GetBitmap(text, reversewh, pane);
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
PluginRuntime.BxfntFiles.Remove(this);
|
||||
}
|
||||
|
||||
public void Save(System.IO.Stream stream)
|
||||
{
|
||||
bffnt.Write(new FileWriter(stream));
|
||||
}
|
||||
|
||||
|
||||
public class SheetEntry : TreeNodeCustom
|
||||
{
|
||||
public SheetEntry()
|
||||
{
|
||||
ImageKey = "fileBlank";
|
||||
SelectedImageKey = "fileBlank";
|
||||
|
||||
ContextMenu = new ContextMenu();
|
||||
MenuItem export = new MenuItem("Export");
|
||||
ContextMenu.MenuItems.Add(export);
|
||||
export.Click += Export;
|
||||
|
||||
}
|
||||
public byte[] data;
|
||||
|
||||
public override void OnClick(TreeView treeview)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private void Export(object sender, EventArgs args)
|
||||
{
|
||||
SaveFileDialog sfd = new SaveFileDialog();
|
||||
sfd.FileName = Text;
|
||||
sfd.DefaultExt = "bntx";
|
||||
sfd.Filter = "Supported Formats|*.bntx;|" +
|
||||
"All files(*.*)|*.*";
|
||||
|
||||
|
||||
if (sfd.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
File.WriteAllBytes(sfd.FileName, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class FFNT
|
||||
{
|
||||
public string Signature;
|
||||
|
||||
public ushort BOM;
|
||||
public ushort HeaderSize;
|
||||
public uint Version { get; set; }
|
||||
|
||||
public FINF FontSection { get; set; }
|
||||
public FontKerningTable KerningTable { get; set; }
|
||||
|
||||
public PlatformType Platform { get; set; } = PlatformType.Cafe;
|
||||
|
||||
public enum PlatformType
|
||||
{
|
||||
Wii,
|
||||
Ctr,
|
||||
Cafe,
|
||||
NX,
|
||||
}
|
||||
|
||||
public void Read(FileReader reader)
|
||||
{
|
||||
reader.ByteOrder = Syroot.BinaryData.ByteOrder.BigEndian;
|
||||
|
||||
Signature = reader.ReadString(4, Encoding.ASCII);
|
||||
if (Signature != "FFNT" && Signature != "CFNT" && Signature != "RFNT")
|
||||
throw new Exception($"Invalid signature {Signature}! Expected FFNT or CFNT or RFNT.");
|
||||
|
||||
BOM = reader.ReadUInt16();
|
||||
reader.CheckByteOrderMark(BOM);
|
||||
|
||||
//Parse header first and check the version
|
||||
//Brfnt uses a slightly different header structure
|
||||
if (Signature == "RFNT") {
|
||||
Version = reader.ReadUInt16();
|
||||
uint FileSize = reader.ReadUInt32();
|
||||
HeaderSize = reader.ReadUInt16();
|
||||
ushort BlockCount = reader.ReadUInt16();
|
||||
}
|
||||
else
|
||||
{
|
||||
HeaderSize = reader.ReadUInt16();
|
||||
Version = reader.ReadUInt32();
|
||||
uint FileSize = reader.ReadUInt16();
|
||||
ushort BlockCount = reader.ReadUInt16();
|
||||
ushort Padding = reader.ReadUInt16();
|
||||
}
|
||||
|
||||
//Check platform based on version, magic, and endianness
|
||||
if (reader.ByteOrder == Syroot.BinaryData.ByteOrder.LittleEndian)
|
||||
{
|
||||
if (Version >= 0x04010000)
|
||||
Platform = PlatformType.NX;
|
||||
else
|
||||
Platform = PlatformType.Ctr;
|
||||
}
|
||||
else
|
||||
Platform = PlatformType.Cafe;
|
||||
|
||||
if (Signature == "CFNT")
|
||||
Platform = PlatformType.Ctr;
|
||||
if (Signature == "RFNT")
|
||||
Platform = PlatformType.Wii;
|
||||
|
||||
Console.WriteLine($"Platform {Platform}");
|
||||
|
||||
reader.Seek(HeaderSize, SeekOrigin.Begin);
|
||||
FontSection = new FINF();
|
||||
FontSection.Read(reader, this);
|
||||
|
||||
//Check for any unread blocks
|
||||
reader.Seek(HeaderSize, SeekOrigin.Begin);
|
||||
while (!reader.EndOfStream)
|
||||
{
|
||||
long BlockStart = reader.Position;
|
||||
|
||||
string BlockSignature = reader.ReadString(4, Encoding.ASCII);
|
||||
uint BlockSize = reader.ReadUInt32();
|
||||
|
||||
switch (BlockSignature)
|
||||
{
|
||||
case "FFNT":
|
||||
case "FFNA":
|
||||
case "FCPX":
|
||||
case "CWDH":
|
||||
case "CGLP":
|
||||
case "CMAP":
|
||||
case "TGLP":
|
||||
case "FINF":
|
||||
break;
|
||||
case "KRNG":
|
||||
KerningTable = new FontKerningTable();
|
||||
KerningTable.Read(reader, this, BlockSize);
|
||||
break;
|
||||
case "GLGR":
|
||||
case "HTGL":
|
||||
break;
|
||||
default:
|
||||
throw new Exception("Unknown block found! " + BlockSignature);
|
||||
}
|
||||
|
||||
reader.SeekBegin(BlockStart + BlockSize);
|
||||
}
|
||||
}
|
||||
|
||||
internal int BlockCounter = 0;
|
||||
public void Write(FileWriter writer)
|
||||
{
|
||||
writer.ByteOrder = Syroot.BinaryData.ByteOrder.BigEndian;
|
||||
|
||||
BlockCounter = 1;
|
||||
|
||||
writer.WriteSignature(Signature);
|
||||
writer.Write(BOM);
|
||||
writer.CheckByteOrderMark(BOM);
|
||||
|
||||
long _ofsFileSize;
|
||||
long _ofsBlockNum;
|
||||
if (Platform == PlatformType.Wii)
|
||||
{
|
||||
writer.Write((ushort)Version);
|
||||
_ofsFileSize = writer.Position;
|
||||
writer.Write(uint.MaxValue);
|
||||
writer.Write(HeaderSize);
|
||||
_ofsBlockNum = writer.Position;
|
||||
writer.Write((ushort)0); //BlockCount
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.Write(HeaderSize);
|
||||
writer.Write(Version);
|
||||
_ofsFileSize = writer.Position;
|
||||
writer.Write(uint.MaxValue);
|
||||
_ofsBlockNum = writer.Position;
|
||||
writer.Write((ushort)0); //BlockCount
|
||||
writer.Write((ushort)0);
|
||||
}
|
||||
|
||||
writer.SeekBegin(HeaderSize);
|
||||
FontSection.Write(writer, this);
|
||||
if (KerningTable != null) {
|
||||
BlockCounter++;
|
||||
KerningTable.Write(writer, this);
|
||||
}
|
||||
|
||||
//Save Block Count
|
||||
using (writer.TemporarySeek(_ofsBlockNum, SeekOrigin.Begin))
|
||||
{
|
||||
writer.Write((ushort)(BlockCounter + 1));
|
||||
}
|
||||
|
||||
//Save File size
|
||||
using (writer.TemporarySeek(_ofsFileSize, SeekOrigin.Begin))
|
||||
{
|
||||
writer.Write((uint)(writer.BaseStream.Length));
|
||||
}
|
||||
}
|
||||
|
||||
private string CheckSignature(FileReader reader)
|
||||
{
|
||||
string Signature = reader.ReadString(4, Encoding.ASCII);
|
||||
reader.Seek(-4, SeekOrigin.Current);
|
||||
return Signature;
|
||||
}
|
||||
|
||||
private BitmapFont bitmapFont;
|
||||
public Bitmap GetBitmap(string text, bool reversewh, LayoutBXLYT.BasePane pane)
|
||||
{
|
||||
var FontInfo = FontSection;
|
||||
var TextureGlyph = FontInfo.TextureGlyph;
|
||||
|
||||
var textPane = (LayoutBXLYT.ITextPane)pane;
|
||||
|
||||
int fontWidth = (int)textPane.FontSize.X;
|
||||
int fontHeight = (int)textPane.FontSize.Y;
|
||||
if (textPane.FontSize.X > 2)
|
||||
{
|
||||
fontWidth = (int)textPane.FontSize.X - 2;
|
||||
fontHeight = (int)textPane.FontSize.Y - 2;
|
||||
}
|
||||
|
||||
float XScale = (fontWidth / TextureGlyph.CellWidth);
|
||||
float YScale = (fontHeight / TextureGlyph.CellWidth);
|
||||
float height = (TextureGlyph.SheetHeight - 2) / TextureGlyph.LinesCount;
|
||||
|
||||
/* int pos = 0;
|
||||
for (int i = 0; i < text.Length; i++)
|
||||
{
|
||||
char character = text[i];
|
||||
|
||||
int charWidth = (int)FontInfo.DefaultCharWidth;
|
||||
int glyphWidth = (int)FontInfo.DefaultGlyphWidth;
|
||||
int leftWidth = (int)FontInfo.DefaultLeftWidth;
|
||||
|
||||
if (FontInfo.CodeMapDictionary.ContainsKey(character))
|
||||
{
|
||||
var idx = FontInfo.CodeMapDictionary[character];
|
||||
if (idx == 0xFFFF) continue;
|
||||
var charWidthInfo = GetCharWidthInfoByIndex(FontInfo, (ushort)idx);
|
||||
|
||||
charWidth = charWidthInfo.CharWidth;
|
||||
glyphWidth = charWidthInfo.GlyphWidth;
|
||||
leftWidth = charWidthInfo.Left;
|
||||
}
|
||||
|
||||
|
||||
/* Bitmap b = new Bitmap(width, height);
|
||||
using (Graphics g = Graphics.FromImage(b))
|
||||
{
|
||||
g.DrawImage();
|
||||
}
|
||||
}*/
|
||||
|
||||
if (bitmapFont == null)
|
||||
bitmapFont = GetBitmapFont(true);
|
||||
|
||||
return bitmapFont.PrintToBitmap(text, new BitmapFont.FontRenderSettings()
|
||||
{
|
||||
TopColor = textPane.FontTopColor.Color,
|
||||
BottomColor = textPane.FontBottomColor.Color,
|
||||
CharSpacing = (int)textPane.CharacterSpace,
|
||||
XScale = (textPane.FontSize.X / TextureGlyph.CellWidth),
|
||||
YScale = (textPane.FontSize.Y / TextureGlyph.CellHeight),
|
||||
LineSpacing = (int)textPane.LineSpace,
|
||||
});
|
||||
}
|
||||
|
||||
public BitmapFont GetBitmapFont(bool UseChannelComp = false)
|
||||
{
|
||||
var FontInfo = FontSection;
|
||||
var TextureGlyph = FontInfo.TextureGlyph;
|
||||
|
||||
BitmapFont f = new BitmapFont();
|
||||
f.LineHeight = FontInfo.LineFeed;
|
||||
Bitmap[] Chars = new Bitmap[TextureGlyph.LinesCount * TextureGlyph.RowCount * TextureGlyph.SheetCount];
|
||||
|
||||
float realcellwidth = TextureGlyph.CellWidth + 1;
|
||||
float realcellheight = TextureGlyph.CellHeight + 1;
|
||||
|
||||
int j = 0;
|
||||
for (int sheet = 0; sheet < TextureGlyph.SheetCount; sheet++)
|
||||
{
|
||||
Bitmap SheetBM = TextureGlyph.GetImageSheet(sheet).GetBitmap();
|
||||
|
||||
if (UseChannelComp)
|
||||
SheetBM = TextureGlyph.GetImageSheet(sheet).GetComponentBitmap(SheetBM, true);
|
||||
|
||||
if (Platform >= PlatformType.Cafe)
|
||||
SheetBM.RotateFlip(RotateFlipType.RotateNoneFlipY);
|
||||
BitmapData bd = SheetBM.LockBits(new Rectangle(0, 0, SheetBM.Width, SheetBM.Height),
|
||||
ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
|
||||
|
||||
for (int y = 0; y < TextureGlyph.LinesCount; y++)
|
||||
{
|
||||
for (int x = 0; x < TextureGlyph.RowCount; x++)
|
||||
{
|
||||
Bitmap b = new Bitmap(TextureGlyph.CellWidth, TextureGlyph.CellHeight);
|
||||
BitmapData bd2 = b.LockBits(new Rectangle(0, 0, b.Width, b.Height),
|
||||
ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
|
||||
|
||||
for (int y2 = 0; y2 < TextureGlyph.CellHeight; y2++)
|
||||
{
|
||||
for (int x2 = 0; x2 < TextureGlyph.CellWidth; x2++)
|
||||
{
|
||||
Marshal.WriteInt32(bd2.Scan0, y2 * bd2.Stride + x2 * 4,
|
||||
Marshal.ReadInt32(bd.Scan0, (int)(y * realcellheight + y2 + 1) *
|
||||
bd.Stride + (int)(x * realcellwidth + x2 + 1) * 4));
|
||||
}
|
||||
}
|
||||
b.UnlockBits(bd2);
|
||||
Chars[j++] = b;
|
||||
}
|
||||
}
|
||||
SheetBM.UnlockBits(bd);
|
||||
}
|
||||
|
||||
foreach (var charMap in FontInfo.CodeMapDictionary)
|
||||
{
|
||||
var idx = charMap.Value;
|
||||
if (idx == 0xFFFF) continue;
|
||||
var info = GetCharWidthInfoByIndex(FontInfo, (ushort)idx);
|
||||
|
||||
f.Characters.Add(charMap.Key, new BitmapFont.Character(Chars[idx], info.Left, info.GlyphWidth, info.CharWidth));
|
||||
}
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
private CharacterWidthEntry GetCharWidthInfoByIndex(FINF fontInfo, UInt16 Index)
|
||||
{
|
||||
foreach (var v in fontInfo.CharacterWidths)
|
||||
{
|
||||
if (Index < v.StartIndex || Index > v.EndIndex) continue;
|
||||
return v.WidthEntries[Index - v.StartIndex];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -9,7 +9,7 @@ namespace FirstPlugin
|
|||
{
|
||||
public class BffntCharSet2Xlor
|
||||
{
|
||||
public static string ToXlor(BFFNT bffnt)
|
||||
public static string ToXlor(BXFNT bffnt)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
using (var texWriter = new StringWriter(sb))
|
118
File_Format_Library/FileFormats/Font/BXFNT/BxfntYamlConverter.cs
Normal file
118
File_Format_Library/FileFormats/Font/BXFNT/BxfntYamlConverter.cs
Normal file
|
@ -0,0 +1,118 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using SharpYaml.Serialization;
|
||||
|
||||
namespace FirstPlugin
|
||||
{
|
||||
public class BxfntYamlConverter
|
||||
{
|
||||
public static string ToYaml(FFNT header)
|
||||
{
|
||||
YamlMappingNode mapping = new YamlMappingNode();
|
||||
mapping.Add("Platform", header.Platform.ToString());
|
||||
mapping.Add("Version", header.Version.ToString("X"));
|
||||
mapping.Add("FontInfo", SaveFontInfo(header.FontSection));
|
||||
mapping.Add("KerningTable", SaveKerningTable(header.KerningTable));
|
||||
|
||||
var doc = new YamlDocument(mapping);
|
||||
|
||||
YamlStream stream = new YamlStream(doc);
|
||||
var buffer = new StringBuilder();
|
||||
using (var writer = new StringWriter(buffer)) {
|
||||
stream.Save(writer, true);
|
||||
return writer.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
private static YamlMappingNode SaveFontInfo(FINF fontInfo)
|
||||
{
|
||||
YamlMappingNode mapping = new YamlMappingNode();
|
||||
mapping.Add("Type", fontInfo.Type.ToString());
|
||||
mapping.Add("Font_Width", fontInfo.Width.ToString());
|
||||
mapping.Add("Font_Height", fontInfo.Height.ToString());
|
||||
mapping.Add("Line_Feed", fontInfo.LineFeed.ToString());
|
||||
mapping.Add("Ascent", fontInfo.Ascent.ToString());
|
||||
mapping.Add("AlterCharIndex", fontInfo.AlterCharIndex.ToString());
|
||||
mapping.Add("DefaultCharWidth", fontInfo.DefaultCharWidth.ToString());
|
||||
mapping.Add("DefaultGlyphWidth", fontInfo.DefaultGlyphWidth.ToString());
|
||||
mapping.Add("DefaultLeftWidth", fontInfo.DefaultLeftWidth.ToString());
|
||||
mapping.Add("Texture_Glyph", SaveTextureGlyph(fontInfo.TextureGlyph));
|
||||
mapping.Add("Characters", SaveCharacterMaps(fontInfo));
|
||||
mapping.Add("Character Widths", SaveCharacterWidths(fontInfo));
|
||||
return mapping;
|
||||
}
|
||||
|
||||
private static YamlMappingNode SaveTextureGlyph(TGLP texInfo)
|
||||
{
|
||||
YamlMappingNode mapping = new YamlMappingNode();
|
||||
mapping.Add("Cell_Height", texInfo.CellHeight.ToString());
|
||||
mapping.Add("Cell_Width", texInfo.CellWidth.ToString());
|
||||
mapping.Add("Format", texInfo.Format.ToString());
|
||||
mapping.Add("BaseLinePos", texInfo.BaseLinePos.ToString());
|
||||
mapping.Add("MaxCharWidth", texInfo.MaxCharWidth.ToString());
|
||||
mapping.Add("Sheet_Height", texInfo.SheetHeight.ToString());
|
||||
mapping.Add("Sheet_Width", texInfo.SheetWidth.ToString());
|
||||
mapping.Add("RowCount", texInfo.RowCount.ToString());
|
||||
mapping.Add("LinesCount", texInfo.LinesCount.ToString());
|
||||
return mapping;
|
||||
}
|
||||
|
||||
private static YamlSequenceNode SaveCharacterMaps(FINF fontInfo)
|
||||
{
|
||||
YamlSequenceNode node = new YamlSequenceNode();
|
||||
// node.Style = SharpYaml.YamlStyle.Flow;
|
||||
foreach (var character in fontInfo.CodeMapDictionary.Keys)
|
||||
{
|
||||
YamlMappingNode mapping = new YamlMappingNode();
|
||||
mapping.Add($"0x{((ushort)character).ToString("X4")}", character.ToString());
|
||||
node.Add(mapping);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
private static YamlSequenceNode SaveCharacterWidths(FINF fontInfo)
|
||||
{
|
||||
YamlSequenceNode node = new YamlSequenceNode();
|
||||
foreach (var character in fontInfo.CodeMapDictionary)
|
||||
{
|
||||
YamlMappingNode mapping = new YamlMappingNode();
|
||||
mapping.Style = SharpYaml.YamlStyle.Flow;
|
||||
if (character.Value != -1) {
|
||||
var width = fontInfo.GetCharacterWidth(character.Value);
|
||||
mapping.Add($"0x{((ushort)character.Key).ToString("X4")}", SaveCharacterWidth(width));
|
||||
}
|
||||
node.Add(mapping);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
private static YamlSequenceNode SaveCharacterWidth(CharacterWidthEntry table)
|
||||
{
|
||||
YamlSequenceNode node = new YamlSequenceNode();
|
||||
node.Style = SharpYaml.YamlStyle.Flow;
|
||||
node.Add(NewMappingNode("CharWidth", table.CharWidth.ToString()));
|
||||
node.Add(NewMappingNode("GlyphWidth", table.GlyphWidth.ToString()));
|
||||
node.Add(NewMappingNode("Left", table.Left.ToString()));
|
||||
return node;
|
||||
}
|
||||
|
||||
private static YamlMappingNode NewMappingNode(string key, string value)
|
||||
{
|
||||
return new YamlMappingNode(new YamlScalarNode(key), new YamlScalarNode(value));
|
||||
}
|
||||
|
||||
private static YamlMappingNode SaveKerningTable(FontKerningTable table)
|
||||
{
|
||||
YamlMappingNode mapping = new YamlMappingNode();
|
||||
if (table == null)
|
||||
return mapping;
|
||||
|
||||
|
||||
return mapping;
|
||||
}
|
||||
}
|
||||
}
|
288
File_Format_Library/FileFormats/Font/BXFNT/CMAP.cs
Normal file
288
File_Format_Library/FileFormats/Font/BXFNT/CMAP.cs
Normal file
|
@ -0,0 +1,288 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Toolbox.Library.IO;
|
||||
|
||||
namespace FirstPlugin
|
||||
{
|
||||
public interface CharMapping { }
|
||||
|
||||
public class CMAPIndexTable : CharMapping
|
||||
{
|
||||
public short[] Table { get; set; }
|
||||
}
|
||||
|
||||
public class CMAPDirect : CharMapping
|
||||
{
|
||||
public ushort Offset { get; set; }
|
||||
}
|
||||
|
||||
public class CMAPScanMapping : CharMapping
|
||||
{
|
||||
public uint[] Codes { get; set; }
|
||||
public short[] Indexes { get; set; }
|
||||
}
|
||||
|
||||
public class CMAP
|
||||
{
|
||||
public uint SectionSize;
|
||||
|
||||
public char CharacterCodeBegin { get; set; }
|
||||
public char CharacterCodeEnd { get; set; }
|
||||
|
||||
public Mapping MappingMethod { get; set; }
|
||||
|
||||
private ushort Padding;
|
||||
|
||||
public CharMapping MappingData;
|
||||
|
||||
public enum Mapping : ushort
|
||||
{
|
||||
Direct,
|
||||
Table,
|
||||
Scan,
|
||||
}
|
||||
|
||||
public ushort GetIndexFromCode(ushort code)
|
||||
{
|
||||
if (code < CharacterCodeBegin || code > CharacterCodeEnd) return 0xFFFF;
|
||||
|
||||
switch (MappingMethod)
|
||||
{
|
||||
case Mapping.Direct:
|
||||
return (UInt16)(code - CharacterCodeBegin + ((CMAPDirect)MappingData).Offset);
|
||||
case Mapping.Table:
|
||||
return (ushort)((CMAPIndexTable)MappingData).Table[code - CharacterCodeBegin];
|
||||
case Mapping.Scan:
|
||||
if (!((CMAPScanMapping)MappingData).Codes.Contains(code)) return 0xFFFF;
|
||||
else
|
||||
{
|
||||
var codes = ((CMAPScanMapping)MappingData).Codes;
|
||||
var index = Array.FindIndex(codes, map => map == code);
|
||||
|
||||
return (ushort)((CMAPScanMapping)MappingData).Indexes[index];
|
||||
}
|
||||
}
|
||||
|
||||
return 0xFFFF;
|
||||
}
|
||||
|
||||
public CMAP NextCodeMapSection { get; set; }
|
||||
|
||||
public static void GenerateCMAP(FileReader reader, FFNT header)
|
||||
{
|
||||
var fontSection = header.FontSection;
|
||||
var cmap = new CMAP();
|
||||
|
||||
|
||||
|
||||
fontSection.CodeMap = cmap;
|
||||
}
|
||||
|
||||
public void Read(FileReader reader, FFNT header, List<CMAP> CodeMaps)
|
||||
{
|
||||
uint CodeBegin = 0;
|
||||
uint CodeEnd = 0;
|
||||
|
||||
long pos = reader.Position;
|
||||
|
||||
reader.ReadSignature(4, "CMAP");
|
||||
SectionSize = reader.ReadUInt32();
|
||||
if (header.Platform == FFNT.PlatformType.NX)
|
||||
{
|
||||
CodeBegin = reader.ReadUInt32();
|
||||
CodeEnd = reader.ReadUInt32();
|
||||
MappingMethod = reader.ReadEnum<Mapping>(true);
|
||||
Padding = reader.ReadUInt16();
|
||||
}
|
||||
else
|
||||
{
|
||||
CodeBegin = reader.ReadUInt16();
|
||||
CodeEnd = reader.ReadUInt16();
|
||||
MappingMethod = reader.ReadEnum<Mapping>(true);
|
||||
Padding = reader.ReadUInt16();
|
||||
}
|
||||
|
||||
CharacterCodeBegin = (char)CodeBegin;
|
||||
CharacterCodeEnd = (char)CodeEnd;
|
||||
|
||||
uint NextMapOffset = reader.ReadUInt32();
|
||||
|
||||
//Mapping methods from
|
||||
https://github.com/IcySon55/Kuriimu/blob/f670c2719affc1eaef8b4c40e40985881247acc7/src/Cetera/Font/BFFNT.cs#L211
|
||||
switch (MappingMethod)
|
||||
{
|
||||
case Mapping.Direct:
|
||||
var charOffset = reader.ReadUInt16();
|
||||
for (char i = CharacterCodeBegin; i <= CharacterCodeEnd; i++)
|
||||
{
|
||||
int idx = i - CharacterCodeBegin + charOffset;
|
||||
header.FontSection.CodeMapDictionary[i] = idx < ushort.MaxValue ? idx : 0;
|
||||
|
||||
Console.WriteLine($"direct {i} {idx}");
|
||||
}
|
||||
|
||||
MappingData = new CMAPDirect();
|
||||
((CMAPDirect)MappingData).Offset = charOffset;
|
||||
break;
|
||||
case Mapping.Table:
|
||||
List<short> table = new List<short>();
|
||||
for (char i = CharacterCodeBegin; i <= CharacterCodeEnd; i++)
|
||||
{
|
||||
short idx = reader.ReadInt16();
|
||||
if (idx != -1) header.FontSection.CodeMapDictionary[i] = idx;
|
||||
|
||||
Console.WriteLine($"direct {i} {idx}");
|
||||
|
||||
table.Add(idx);
|
||||
}
|
||||
|
||||
MappingData = new CMAPIndexTable();
|
||||
((CMAPIndexTable)MappingData).Table = table.ToArray();
|
||||
break;
|
||||
case Mapping.Scan:
|
||||
var CharEntryCount = reader.ReadUInt16();
|
||||
|
||||
if (header.Platform == FFNT.PlatformType.NX)
|
||||
reader.ReadUInt16(); //Padding
|
||||
|
||||
uint[] codes = new uint[CharEntryCount];
|
||||
short[] indexes = new short[CharEntryCount];
|
||||
|
||||
for (int i = 0; i < CharEntryCount; i++)
|
||||
{
|
||||
if (header.Platform == FFNT.PlatformType.NX)
|
||||
{
|
||||
uint charCode = reader.ReadUInt32();
|
||||
short index = reader.ReadInt16();
|
||||
short padding = reader.ReadInt16();
|
||||
if (index != -1) header.FontSection.CodeMapDictionary[(char)charCode] = index;
|
||||
|
||||
codes[i] = charCode;
|
||||
indexes[i] = index;
|
||||
}
|
||||
else
|
||||
{
|
||||
ushort charCode = reader.ReadUInt16();
|
||||
short index = reader.ReadInt16();
|
||||
if (index != -1) header.FontSection.CodeMapDictionary[(char)charCode] = index;
|
||||
|
||||
Console.WriteLine($"scan {i} {(char)charCode} {index}");
|
||||
|
||||
codes[i] = charCode;
|
||||
indexes[i] = index;
|
||||
}
|
||||
}
|
||||
|
||||
MappingData = new CMAPScanMapping();
|
||||
((CMAPScanMapping)MappingData).Codes = codes;
|
||||
((CMAPScanMapping)MappingData).Indexes = indexes;
|
||||
break;
|
||||
}
|
||||
|
||||
if (NextMapOffset != 0)
|
||||
{
|
||||
reader.SeekBegin(NextMapOffset - 8);
|
||||
NextCodeMapSection = new CMAP();
|
||||
NextCodeMapSection.Read(reader, header, CodeMaps);
|
||||
CodeMaps.Add(NextCodeMapSection);
|
||||
}
|
||||
else
|
||||
reader.SeekBegin(pos + SectionSize);
|
||||
}
|
||||
|
||||
public void Write(FileWriter writer, FFNT Header)
|
||||
{
|
||||
Header.BlockCounter += 1;
|
||||
|
||||
long pos = writer.Position;
|
||||
|
||||
writer.WriteSignature("CMAP");
|
||||
writer.Write(uint.MaxValue); //Section Size
|
||||
if (Header.Platform == FFNT.PlatformType.NX)
|
||||
{
|
||||
writer.Write((uint)CharacterCodeBegin);
|
||||
writer.Write((uint)CharacterCodeEnd);
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.Write((ushort)CharacterCodeBegin);
|
||||
writer.Write((ushort)CharacterCodeEnd);
|
||||
}
|
||||
|
||||
writer.Write(MappingMethod, true);
|
||||
writer.Seek(2);
|
||||
|
||||
long DataPos = writer.Position;
|
||||
writer.Write(0); //Next Section Offset
|
||||
|
||||
//Write the data
|
||||
switch (MappingMethod)
|
||||
{
|
||||
case Mapping.Direct:
|
||||
writer.Write(((CMAPDirect)MappingData).Offset);
|
||||
break;
|
||||
case Mapping.Table:
|
||||
for (int i = 0; i < ((CMAPIndexTable)MappingData).Table.Length; i++)
|
||||
{
|
||||
writer.Write(((CMAPIndexTable)MappingData).Table[i]);
|
||||
}
|
||||
break;
|
||||
case Mapping.Scan:
|
||||
writer.Write((ushort)((CMAPScanMapping)MappingData).Codes.Length);
|
||||
if (Header.Platform == FFNT.PlatformType.NX)
|
||||
writer.Seek(2); //Padding
|
||||
|
||||
for (int i = 0; i < ((CMAPScanMapping)MappingData).Codes.Length; i++)
|
||||
{
|
||||
if (Header.Platform == FFNT.PlatformType.NX)
|
||||
{
|
||||
writer.Write((uint)((CMAPScanMapping)MappingData).Codes[i]);
|
||||
writer.Write(((CMAPScanMapping)MappingData).Indexes[i]);
|
||||
writer.Write((ushort)0); //Padding
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.Write((ushort)((CMAPScanMapping)MappingData).Codes[i]);
|
||||
writer.Write(((CMAPScanMapping)MappingData).Indexes[i]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
writer.AlignBytes(4); //Padding
|
||||
|
||||
//Save section size
|
||||
long endPos = writer.Position;
|
||||
using (writer.TemporarySeek(pos + 4, SeekOrigin.Begin))
|
||||
{
|
||||
writer.Write((uint)(endPos - pos));
|
||||
}
|
||||
|
||||
if (NextCodeMapSection != null)
|
||||
{
|
||||
writer.WriteUint32Offset(DataPos, -8);
|
||||
NextCodeMapSection.Write(writer, Header);
|
||||
}
|
||||
}
|
||||
|
||||
//From https://github.com/dnasdw/3dsfont/blob/79e6f4ab6676d82fdcd6c0f79d9b0d7a343f82b5/src/bcfnt2charset/bcfnt2charset.cpp#L3
|
||||
//Todo add the rest of the encoding types
|
||||
public char CodeToU16Code(FINF.CharacterCode characterCode, ushort code)
|
||||
{
|
||||
if (code < 0x20)
|
||||
{
|
||||
return (char)0;
|
||||
}
|
||||
|
||||
switch (characterCode)
|
||||
{
|
||||
case FINF.CharacterCode.Unicode:
|
||||
return (char)code;
|
||||
}
|
||||
|
||||
return (char)code;
|
||||
}
|
||||
}
|
||||
}
|
100
File_Format_Library/FileFormats/Font/BXFNT/CWDH.cs
Normal file
100
File_Format_Library/FileFormats/Font/BXFNT/CWDH.cs
Normal file
|
@ -0,0 +1,100 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Toolbox.Library.IO;
|
||||
|
||||
namespace FirstPlugin
|
||||
{
|
||||
public class CWDH
|
||||
{
|
||||
public ushort StartIndex { get; set; }
|
||||
public ushort EndIndex { get; set; }
|
||||
|
||||
public List<CharacterWidthEntry> WidthEntries = new List<CharacterWidthEntry>();
|
||||
|
||||
public CWDH NextWidthSection { get; set; }
|
||||
|
||||
public ushort EntryCount
|
||||
{
|
||||
get { return (ushort)(EndIndex - StartIndex + 1); }
|
||||
}
|
||||
|
||||
public uint SectionSize;
|
||||
|
||||
public void Read(FileReader reader, FFNT header, List<CWDH> CharacterWidths)
|
||||
{
|
||||
long pos = reader.Position;
|
||||
|
||||
reader.ReadSignature(4, "CWDH");
|
||||
SectionSize = reader.ReadUInt32();
|
||||
StartIndex = reader.ReadUInt16();
|
||||
EndIndex = reader.ReadUInt16();
|
||||
uint NextWidthSectionOffset = reader.ReadUInt32();
|
||||
|
||||
for (ushort i = StartIndex; i <= EndIndex; i++)
|
||||
{
|
||||
var entry = new CharacterWidthEntry();
|
||||
entry.Left = reader.ReadSByte();
|
||||
entry.GlyphWidth = reader.ReadByte();
|
||||
entry.CharWidth = reader.ReadByte();
|
||||
WidthEntries.Add(entry);
|
||||
}
|
||||
|
||||
if (NextWidthSectionOffset != 0)
|
||||
{
|
||||
reader.SeekBegin((int)NextWidthSectionOffset - 8);
|
||||
NextWidthSection = new CWDH();
|
||||
NextWidthSection.Read(reader, header, CharacterWidths);
|
||||
CharacterWidths.Add(NextWidthSection);
|
||||
}
|
||||
else
|
||||
reader.SeekBegin(pos + SectionSize);
|
||||
}
|
||||
|
||||
public void Write(FileWriter writer, FFNT Header)
|
||||
{
|
||||
Header.BlockCounter += 1;
|
||||
|
||||
long pos = writer.Position;
|
||||
|
||||
writer.WriteSignature("CWDH");
|
||||
writer.Write(uint.MaxValue); //Section Size
|
||||
writer.Write(StartIndex);
|
||||
writer.Write(EndIndex);
|
||||
|
||||
long DataPos = writer.Position;
|
||||
writer.Write(0); //NextOffset
|
||||
|
||||
for (int i = 0; i < WidthEntries.Count; i++)
|
||||
{
|
||||
writer.Write(WidthEntries[i].Left);
|
||||
writer.Write(WidthEntries[i].GlyphWidth);
|
||||
writer.Write(WidthEntries[i].CharWidth);
|
||||
}
|
||||
|
||||
writer.Align(4);
|
||||
|
||||
if (NextWidthSection != null)
|
||||
{
|
||||
writer.WriteUint32Offset(DataPos, -8);
|
||||
NextWidthSection.Write(writer, Header);
|
||||
}
|
||||
|
||||
//Save section size
|
||||
long endPos = writer.Position;
|
||||
using (writer.TemporarySeek(pos + 4, SeekOrigin.Begin))
|
||||
{
|
||||
writer.Write((uint)(endPos - pos));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class CharacterWidthEntry
|
||||
{
|
||||
public sbyte Left { get; set; }
|
||||
public byte GlyphWidth { get; set; }
|
||||
public byte CharWidth { get; set; }
|
||||
}
|
||||
}
|
223
File_Format_Library/FileFormats/Font/BXFNT/FINF.cs
Normal file
223
File_Format_Library/FileFormats/Font/BXFNT/FINF.cs
Normal file
|
@ -0,0 +1,223 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
using Toolbox.Library;
|
||||
using Toolbox.Library.IO;
|
||||
|
||||
namespace FirstPlugin
|
||||
{
|
||||
public class FINF
|
||||
{
|
||||
public Dictionary<char, int> CodeMapDictionary = new Dictionary<char, int>();
|
||||
|
||||
public uint Size;
|
||||
public FontType Type { get; set; }
|
||||
public byte Width { get; set; }
|
||||
public byte Height { get; set; }
|
||||
public byte Ascent { get; set; }
|
||||
public ushort LineFeed { get; set; }
|
||||
public ushort AlterCharIndex { get; set; }
|
||||
public byte DefaultLeftWidth { get; set; }
|
||||
public byte DefaultGlyphWidth { get; set; }
|
||||
public byte DefaultCharWidth { get; set; }
|
||||
public CharacterCode CharEncoding { get; set; }
|
||||
public TGLP TextureGlyph;
|
||||
public CMAP CodeMap;
|
||||
public CWDH CharacterWidth;
|
||||
|
||||
public List<CWDH> CharacterWidths { get; set; }
|
||||
public List<CMAP> CodeMaps { get; set; }
|
||||
|
||||
public enum FontType : byte
|
||||
{
|
||||
Glyph = 1,
|
||||
Texture = 2,
|
||||
PackedTexture = 3,
|
||||
}
|
||||
|
||||
public enum CharacterCode : byte
|
||||
{
|
||||
UTF8 = 0,
|
||||
Unicode = 1,
|
||||
ShiftJIS = 2,
|
||||
CP1252 = 3,
|
||||
}
|
||||
|
||||
public void Read(FileReader reader, FFNT header)
|
||||
{
|
||||
CharacterWidths = new List<CWDH>();
|
||||
CodeMaps = new List<CMAP>();
|
||||
|
||||
string Signature = reader.ReadString(4, Encoding.ASCII);
|
||||
if (Signature != "FINF")
|
||||
throw new Exception($"Invalid signature {Signature}! Expected FINF.");
|
||||
Size = reader.ReadUInt32();
|
||||
|
||||
if (header.Platform <= FFNT.PlatformType.Ctr && header.Version < 0x04000000)
|
||||
{
|
||||
Type = reader.ReadEnum<FontType>(true);
|
||||
LineFeed = reader.ReadByte();
|
||||
AlterCharIndex = reader.ReadUInt16();
|
||||
DefaultLeftWidth = reader.ReadByte();
|
||||
DefaultGlyphWidth = reader.ReadByte();
|
||||
DefaultCharWidth = reader.ReadByte();
|
||||
CharEncoding = reader.ReadEnum<CharacterCode>(true);
|
||||
uint tglpOffset = reader.ReadUInt32();
|
||||
uint cwdhOffset = reader.ReadUInt32();
|
||||
uint cmapOffset = reader.ReadUInt32();
|
||||
|
||||
Height = reader.ReadByte();
|
||||
Width = reader.ReadByte();
|
||||
Ascent = reader.ReadByte();
|
||||
reader.ReadByte(); //Padding
|
||||
|
||||
//Add counter for TGLP
|
||||
//Note the other counters are inside sections due to recusive setup
|
||||
header.BlockCounter += 1;
|
||||
|
||||
TextureGlyph = new TGLP();
|
||||
using (reader.TemporarySeek(tglpOffset - 8, SeekOrigin.Begin))
|
||||
TextureGlyph.Read(reader, header);
|
||||
|
||||
CharacterWidth = new CWDH();
|
||||
CharacterWidths.Add(CharacterWidth);
|
||||
using (reader.TemporarySeek(cwdhOffset - 8, SeekOrigin.Begin))
|
||||
CharacterWidth.Read(reader, header, CharacterWidths);
|
||||
|
||||
CodeMap = new CMAP();
|
||||
CodeMaps.Add(CodeMap);
|
||||
using (reader.TemporarySeek(cmapOffset - 8, SeekOrigin.Begin))
|
||||
CodeMap.Read(reader, header, CodeMaps);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Type = reader.ReadEnum<FontType>(true);
|
||||
Height = reader.ReadByte();
|
||||
Width = reader.ReadByte();
|
||||
Ascent = reader.ReadByte();
|
||||
LineFeed = reader.ReadUInt16();
|
||||
AlterCharIndex = reader.ReadUInt16();
|
||||
DefaultLeftWidth = reader.ReadByte();
|
||||
DefaultGlyphWidth = reader.ReadByte();
|
||||
DefaultCharWidth = reader.ReadByte();
|
||||
CharEncoding = reader.ReadEnum<CharacterCode>(true);
|
||||
uint tglpOffset = reader.ReadUInt32();
|
||||
uint cwdhOffset = reader.ReadUInt32();
|
||||
uint cmapOffset = reader.ReadUInt32();
|
||||
|
||||
//Add counter for TGLP
|
||||
//Note the other counters are inside sections due to recusive setup
|
||||
header.BlockCounter += 1;
|
||||
|
||||
TextureGlyph = new TGLP();
|
||||
using (reader.TemporarySeek(tglpOffset - 8, SeekOrigin.Begin))
|
||||
TextureGlyph.Read(reader, header);
|
||||
|
||||
CharacterWidth = new CWDH();
|
||||
CharacterWidths.Add(CharacterWidth);
|
||||
using (reader.TemporarySeek(cwdhOffset - 8, SeekOrigin.Begin))
|
||||
CharacterWidth.Read(reader, header, CharacterWidths);
|
||||
|
||||
CodeMap = new CMAP();
|
||||
CodeMaps.Add(CodeMap);
|
||||
using (reader.TemporarySeek(cmapOffset - 8, SeekOrigin.Begin))
|
||||
CodeMap.Read(reader, header, CodeMaps);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void Write(FileWriter writer, FFNT header)
|
||||
{
|
||||
long pos = writer.Position;
|
||||
|
||||
writer.WriteSignature("FINF");
|
||||
writer.Write(uint.MaxValue);
|
||||
|
||||
long _ofsTGLP = 0;
|
||||
long _ofsCWDH = 0;
|
||||
long _ofsCMAP = 0;
|
||||
if (header.Platform <= FFNT.PlatformType.Ctr && header.Version < 0x04000000)
|
||||
{
|
||||
writer.Write(Type, true);
|
||||
writer.Write((byte)LineFeed);
|
||||
writer.Write(AlterCharIndex);
|
||||
writer.Write(DefaultLeftWidth);
|
||||
writer.Write(DefaultGlyphWidth);
|
||||
writer.Write(DefaultCharWidth);
|
||||
writer.Write(CharEncoding, true);
|
||||
|
||||
_ofsTGLP = writer.Position;
|
||||
writer.Write(uint.MaxValue);
|
||||
_ofsCWDH = writer.Position;
|
||||
writer.Write(uint.MaxValue);
|
||||
_ofsCMAP = writer.Position;
|
||||
writer.Write(uint.MaxValue);
|
||||
|
||||
writer.Write(Height);
|
||||
writer.Write(Width);
|
||||
writer.Write(Ascent);
|
||||
writer.Write((byte)0);
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.Write(Type, true);
|
||||
writer.Write(Height);
|
||||
writer.Write(Width);
|
||||
writer.Write(Ascent);
|
||||
writer.Write(LineFeed);
|
||||
writer.Write(AlterCharIndex);
|
||||
writer.Write(DefaultLeftWidth);
|
||||
writer.Write(DefaultGlyphWidth);
|
||||
writer.Write(DefaultCharWidth);
|
||||
writer.Write(CharEncoding, true);
|
||||
_ofsTGLP = writer.Position;
|
||||
writer.Write(uint.MaxValue);
|
||||
_ofsCWDH = writer.Position;
|
||||
writer.Write(uint.MaxValue);
|
||||
_ofsCMAP = writer.Position;
|
||||
writer.Write(uint.MaxValue);
|
||||
}
|
||||
|
||||
|
||||
//Save section size
|
||||
long endPos = writer.Position;
|
||||
using (writer.TemporarySeek(pos + 4, SeekOrigin.Begin))
|
||||
{
|
||||
writer.Write((uint)(endPos - pos));
|
||||
}
|
||||
|
||||
//Save Texture Glyph
|
||||
writer.WriteUint32Offset(_ofsTGLP, -8);
|
||||
TextureGlyph.Write(writer, header);
|
||||
|
||||
//Save Character Widths
|
||||
writer.WriteUint32Offset(_ofsCWDH, -8);
|
||||
CharacterWidth.Write(writer, header);
|
||||
|
||||
//Save Code Maps
|
||||
writer.WriteUint32Offset(_ofsCMAP, -8);
|
||||
CodeMap.Write(writer, header);
|
||||
}
|
||||
|
||||
public CharacterWidthEntry GetCharacterWidth(int index)
|
||||
{
|
||||
if (index == -1)
|
||||
return null;
|
||||
|
||||
for (int i = 0; i < CharacterWidths.Count; i++)
|
||||
{
|
||||
if (CharacterWidths[i].StartIndex <= index && CharacterWidths[i].EndIndex >= index)
|
||||
{
|
||||
int CharaIndex = index - CharacterWidths[i].StartIndex;
|
||||
return CharacterWidths[i].WidthEntries[CharaIndex];
|
||||
}
|
||||
}
|
||||
|
||||
throw new Exception("Failed to get valid character index!");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Toolbox.Library.IO;
|
||||
|
||||
namespace FirstPlugin
|
||||
{
|
||||
//Kerning Table
|
||||
//https://github.com/dnasdw/3dsfont/blob/4ead538d225d5d05929dce9d736bec91a6158052/src/bffnt/ResourceFormat.h
|
||||
public class FontKerningTable
|
||||
{
|
||||
private byte[] Data;
|
||||
|
||||
public KerningFirstTable FirstTable { get; set; }
|
||||
|
||||
public void Read(FileReader reader, FFNT Header, uint size)
|
||||
{
|
||||
Data = reader.ReadBytes((int)(size - 8));
|
||||
|
||||
/* if (Header.Platform == FFNT.PlatformType.NX)
|
||||
{
|
||||
ushort FirstWordCount = reader.ReadUInt16();
|
||||
ushort padding = reader.ReadUInt16();
|
||||
|
||||
FirstTable = new KerningFirstTable();
|
||||
FirstTable.Read(reader, Header);
|
||||
}
|
||||
else
|
||||
{
|
||||
ushort FirstWordCount = reader.ReadUInt16();
|
||||
|
||||
FirstTable = new KerningFirstTable();
|
||||
FirstTable.Read(reader, Header);
|
||||
}*/
|
||||
}
|
||||
|
||||
public void Write(FileWriter writer, FFNT Header)
|
||||
{
|
||||
long pos = writer.Position;
|
||||
writer.WriteSignature("KRNG");
|
||||
writer.Write(uint.MaxValue);
|
||||
writer.Write(Data);
|
||||
writer.WriteSectionSizeU32(pos + 4, pos, writer.Position);
|
||||
}
|
||||
}
|
||||
|
||||
public class KerningFirstTable
|
||||
{
|
||||
public uint FirstWordCount { get; set; }
|
||||
public uint Offset { get; set; }
|
||||
|
||||
public void Read(FileReader reader, FFNT Header)
|
||||
{
|
||||
if (Header.Platform == FFNT.PlatformType.NX)
|
||||
{
|
||||
uint FirstWordCount = reader.ReadUInt32();
|
||||
uint Offset = reader.ReadUInt32();
|
||||
}
|
||||
else
|
||||
{
|
||||
uint FirstWordCount = reader.ReadUInt16();
|
||||
uint Offset = reader.ReadUInt16();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,114 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Drawing;
|
||||
using Toolbox.Library;
|
||||
using System.Windows.Forms;
|
||||
using Toolbox.Library.Forms;
|
||||
|
||||
namespace FirstPlugin
|
||||
{
|
||||
public class CtrImageBlock : STGenericTexture
|
||||
{
|
||||
public TGLP TextureTGLP;
|
||||
|
||||
public int SheetIndex = 0;
|
||||
|
||||
public void Load(TGLP texture, int Index)
|
||||
{
|
||||
CanReplace = true;
|
||||
|
||||
SheetIndex = Index;
|
||||
TextureTGLP = texture;
|
||||
Height = TextureTGLP.SheetHeight;
|
||||
Width = TextureTGLP.SheetWidth;
|
||||
var BFNTFormat = (CTR_3DS.PICASurfaceFormat)TextureTGLP.Format;
|
||||
Format = CTR_3DS.ConvertPICAToGenericFormat(BFNTFormat);
|
||||
|
||||
if (Format == TEX_FORMAT.A4) {
|
||||
RedChannel = STChannelType.Alpha;
|
||||
GreenChannel = STChannelType.Alpha;
|
||||
BlueChannel = STChannelType.Alpha;
|
||||
AlphaChannel = STChannelType.Alpha;
|
||||
}
|
||||
|
||||
PlatformSwizzle = PlatformSwizzle.Platform_3DS;
|
||||
|
||||
ImageKey = "Texture";
|
||||
SelectedImageKey = "Texture";
|
||||
}
|
||||
|
||||
public override bool CanEdit { get; set; } = true;
|
||||
public override string ExportFilter => FileFilters.GTX;
|
||||
public override string ReplaceFilter => FileFilters.GTX;
|
||||
|
||||
public override void Replace(string FileName)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public override TEX_FORMAT[] SupportedFormats
|
||||
{
|
||||
get
|
||||
{
|
||||
return new TEX_FORMAT[] {
|
||||
TEX_FORMAT.R8_UNORM,
|
||||
TEX_FORMAT.BC1_UNORM_SRGB,
|
||||
TEX_FORMAT.BC1_UNORM,
|
||||
TEX_FORMAT.BC2_UNORM,
|
||||
TEX_FORMAT.BC2_UNORM_SRGB,
|
||||
TEX_FORMAT.BC3_UNORM,
|
||||
TEX_FORMAT.BC3_UNORM_SRGB,
|
||||
TEX_FORMAT.BC4_UNORM,
|
||||
TEX_FORMAT.BC5_UNORM,
|
||||
TEX_FORMAT.R8G8_UNORM,
|
||||
TEX_FORMAT.B5G6R5_UNORM,
|
||||
TEX_FORMAT.B5G5R5A1_UNORM,
|
||||
TEX_FORMAT.R8G8B8A8_UNORM_SRGB,
|
||||
TEX_FORMAT.R8G8B8A8_UNORM,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public override void SetImageData(Bitmap bitmap, int ArrayLevel)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public override byte[] GetImageData(int ArrayLevel = 0, int MipLevel = 0, int DepthLevel = 0)
|
||||
{
|
||||
return TextureTGLP.SheetDataList[SheetIndex];
|
||||
}
|
||||
|
||||
public override void OnClick(TreeView treeview)
|
||||
{
|
||||
UpdateEditor();
|
||||
}
|
||||
|
||||
private void UpdateEditor()
|
||||
{
|
||||
ImageEditorBase editor = (ImageEditorBase)LibraryGUI.GetActiveContent(typeof(ImageEditorBase));
|
||||
if (editor == null)
|
||||
{
|
||||
editor = new ImageEditorBase();
|
||||
editor.Dock = DockStyle.Fill;
|
||||
LibraryGUI.LoadEditor(editor);
|
||||
}
|
||||
|
||||
Properties prop = new Properties();
|
||||
prop.Width = Width;
|
||||
prop.Height = Height;
|
||||
prop.Depth = Depth;
|
||||
prop.MipCount = MipCount;
|
||||
prop.ArrayCount = ArrayCount;
|
||||
prop.ImageSize = (uint)TextureTGLP.SheetDataList[SheetIndex].Length;
|
||||
prop.Format = Format;
|
||||
|
||||
editor.Text = Text;
|
||||
editor.LoadProperties(prop);
|
||||
editor.LoadImage(this);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,277 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Drawing;
|
||||
using Toolbox.Library;
|
||||
using System.Windows.Forms;
|
||||
using Toolbox.Library.Forms;
|
||||
|
||||
namespace FirstPlugin
|
||||
{
|
||||
public class Gx2ImageBlock : STGenericTexture
|
||||
{
|
||||
public TGLP TextureTGLP;
|
||||
|
||||
public int SheetIndex = 0;
|
||||
|
||||
public void Load(TGLP texture, int Index)
|
||||
{
|
||||
CanReplace = true;
|
||||
|
||||
SheetIndex = Index;
|
||||
TextureTGLP = texture;
|
||||
Height = TextureTGLP.SheetHeight;
|
||||
Width = TextureTGLP.SheetWidth;
|
||||
var BFNTFormat = (Gx2ImageFormats)TextureTGLP.Format;
|
||||
Format = ConvertToGeneric(BFNTFormat);
|
||||
if (Format == TEX_FORMAT.BC4_UNORM)
|
||||
{
|
||||
AlphaChannel = STChannelType.Red;
|
||||
}
|
||||
|
||||
ImageKey = "Texture";
|
||||
SelectedImageKey = "Texture";
|
||||
}
|
||||
|
||||
|
||||
public enum Gx2ImageFormats
|
||||
{
|
||||
RGBA8_UNORM,
|
||||
RGB8_UNORM,
|
||||
RGB5A1_UNORM,
|
||||
RGB565_UNORM,
|
||||
RGBA4_UNORM,
|
||||
LA8_UNORM,
|
||||
LA4_UNORM,
|
||||
A4_UNORM,
|
||||
A8_UNORM,
|
||||
BC1_UNORM,
|
||||
BC2_UNORM,
|
||||
BC3_UNORM,
|
||||
BC4_UNORM,
|
||||
BC5_UNORM,
|
||||
RGBA8_SRGB,
|
||||
BC1_SRGB,
|
||||
BC2_SRGB,
|
||||
BC3_SRGB,
|
||||
}
|
||||
|
||||
public override bool CanEdit { get; set; } = true;
|
||||
public override string ExportFilter => FileFilters.GTX;
|
||||
public override string ReplaceFilter => FileFilters.GTX;
|
||||
|
||||
public override void Replace(string FileName)
|
||||
{
|
||||
Bfres.Structs.FTEX ftex = new Bfres.Structs.FTEX();
|
||||
ftex.ReplaceTexture(FileName, Format, 1, 0, SupportedFormats, true, true, false);
|
||||
if (ftex.texture != null)
|
||||
{
|
||||
TextureTGLP.Format = (ushort)ConvertToGx2(ftex.Format);
|
||||
TextureTGLP.SheetHeight = (ushort)ftex.texture.Height;
|
||||
TextureTGLP.SheetWidth = (ushort)ftex.texture.Width;
|
||||
TextureTGLP.SheetDataList[SheetIndex] = ftex.texture.Data;
|
||||
Format = ftex.Format;
|
||||
Width = ftex.texture.Width;
|
||||
Height = ftex.texture.Height;
|
||||
|
||||
UpdateEditor();
|
||||
}
|
||||
}
|
||||
|
||||
public override TEX_FORMAT[] SupportedFormats
|
||||
{
|
||||
get
|
||||
{
|
||||
return new TEX_FORMAT[] {
|
||||
TEX_FORMAT.R8_UNORM,
|
||||
TEX_FORMAT.BC1_UNORM_SRGB,
|
||||
TEX_FORMAT.BC1_UNORM,
|
||||
TEX_FORMAT.BC2_UNORM,
|
||||
TEX_FORMAT.BC2_UNORM_SRGB,
|
||||
TEX_FORMAT.BC3_UNORM,
|
||||
TEX_FORMAT.BC3_UNORM_SRGB,
|
||||
TEX_FORMAT.BC4_UNORM,
|
||||
TEX_FORMAT.BC5_UNORM,
|
||||
TEX_FORMAT.R8G8_UNORM,
|
||||
TEX_FORMAT.B5G6R5_UNORM,
|
||||
TEX_FORMAT.B5G5R5A1_UNORM,
|
||||
TEX_FORMAT.R8G8B8A8_UNORM_SRGB,
|
||||
TEX_FORMAT.R8G8B8A8_UNORM,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public TEX_FORMAT ConvertToGeneric(Gx2ImageFormats Format)
|
||||
{
|
||||
switch (Format)
|
||||
{
|
||||
case Gx2ImageFormats.A8_UNORM: return TEX_FORMAT.R8_UNORM;
|
||||
case Gx2ImageFormats.BC1_SRGB: return TEX_FORMAT.BC1_UNORM_SRGB;
|
||||
case Gx2ImageFormats.BC1_UNORM: return TEX_FORMAT.BC1_UNORM;
|
||||
case Gx2ImageFormats.BC2_UNORM: return TEX_FORMAT.BC2_UNORM;
|
||||
case Gx2ImageFormats.BC2_SRGB: return TEX_FORMAT.BC2_UNORM_SRGB;
|
||||
case Gx2ImageFormats.BC3_UNORM: return TEX_FORMAT.BC3_UNORM;
|
||||
case Gx2ImageFormats.BC3_SRGB: return TEX_FORMAT.BC3_UNORM_SRGB;
|
||||
case Gx2ImageFormats.BC4_UNORM: return TEX_FORMAT.BC4_UNORM;
|
||||
case Gx2ImageFormats.BC5_UNORM: return TEX_FORMAT.BC5_UNORM;
|
||||
case Gx2ImageFormats.LA4_UNORM: return TEX_FORMAT.R4G4_UNORM;
|
||||
case Gx2ImageFormats.LA8_UNORM: return TEX_FORMAT.R8G8_UNORM;
|
||||
case Gx2ImageFormats.RGB565_UNORM: return TEX_FORMAT.B5G6R5_UNORM;
|
||||
case Gx2ImageFormats.RGB5A1_UNORM: return TEX_FORMAT.B5G5R5A1_UNORM;
|
||||
case Gx2ImageFormats.RGB8_UNORM: return TEX_FORMAT.R8G8_UNORM;
|
||||
case Gx2ImageFormats.RGBA8_SRGB: return TEX_FORMAT.R8G8B8A8_UNORM_SRGB;
|
||||
case Gx2ImageFormats.RGBA8_UNORM: return TEX_FORMAT.R8G8B8A8_UNORM;
|
||||
default:
|
||||
throw new NotImplementedException("Unsupported format " + Format);
|
||||
}
|
||||
}
|
||||
|
||||
public Gx2ImageFormats ConvertToGx2(TEX_FORMAT Format)
|
||||
{
|
||||
switch (Format)
|
||||
{
|
||||
case TEX_FORMAT.R8_UNORM: return Gx2ImageFormats.A8_UNORM;
|
||||
case TEX_FORMAT.BC1_UNORM_SRGB: return Gx2ImageFormats.BC1_SRGB;
|
||||
case TEX_FORMAT.BC1_UNORM: return Gx2ImageFormats.BC1_UNORM;
|
||||
case TEX_FORMAT.BC2_UNORM_SRGB: return Gx2ImageFormats.BC2_SRGB;
|
||||
case TEX_FORMAT.BC2_UNORM: return Gx2ImageFormats.BC2_UNORM;
|
||||
case TEX_FORMAT.BC3_UNORM_SRGB: return Gx2ImageFormats.BC3_SRGB;
|
||||
case TEX_FORMAT.BC3_UNORM: return Gx2ImageFormats.BC3_UNORM;
|
||||
case TEX_FORMAT.BC4_UNORM: return Gx2ImageFormats.BC4_UNORM;
|
||||
case TEX_FORMAT.BC5_UNORM: return Gx2ImageFormats.BC5_UNORM;
|
||||
case TEX_FORMAT.R4G4_UNORM: return Gx2ImageFormats.LA4_UNORM;
|
||||
case TEX_FORMAT.R8G8_UNORM: return Gx2ImageFormats.RGB8_UNORM;
|
||||
case TEX_FORMAT.B5G6R5_UNORM: return Gx2ImageFormats.RGB565_UNORM;
|
||||
case TEX_FORMAT.B5G5R5A1_UNORM: return Gx2ImageFormats.RGB5A1_UNORM;
|
||||
case TEX_FORMAT.R8G8B8A8_UNORM_SRGB: return Gx2ImageFormats.RGBA8_SRGB;
|
||||
case TEX_FORMAT.R8G8B8A8_UNORM: return Gx2ImageFormats.RGBA8_UNORM;
|
||||
default:
|
||||
throw new NotImplementedException("Unsupported format " + Format);
|
||||
}
|
||||
}
|
||||
|
||||
public override void SetImageData(Bitmap bitmap, int ArrayLevel)
|
||||
{
|
||||
if (bitmap == null)
|
||||
return; //Image is likely disposed and not needed to be applied
|
||||
|
||||
uint Gx2Format = (uint)Bfres.Structs.FTEX.ConvertToGx2Format(Format);
|
||||
Width = (uint)bitmap.Width;
|
||||
Height = (uint)bitmap.Height;
|
||||
|
||||
MipCount = 1;
|
||||
uint[] MipOffsets = new uint[MipCount];
|
||||
|
||||
try
|
||||
{
|
||||
//Create image block from bitmap first
|
||||
var data = GenerateMipsAndCompress(bitmap, MipCount, Format);
|
||||
|
||||
//Swizzle and create surface
|
||||
var surface = GX2.CreateGx2Texture(data, Text,
|
||||
(uint)4,
|
||||
(uint)0,
|
||||
(uint)Width,
|
||||
(uint)Height,
|
||||
(uint)1,
|
||||
(uint)Gx2Format,
|
||||
(uint)SwizzlePattern,
|
||||
(uint)1,
|
||||
(uint)MipCount
|
||||
);
|
||||
|
||||
TextureTGLP.Format = (ushort)ConvertToGx2(Format);
|
||||
TextureTGLP.SheetHeight = (ushort)surface.height;
|
||||
TextureTGLP.SheetWidth = (ushort)surface.width;
|
||||
TextureTGLP.SheetDataList[SheetIndex] = surface.data;
|
||||
|
||||
IsEdited = true;
|
||||
UpdateEditor();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
STErrorDialog.Show("Failed to swizzle and compress image " + Text, "Error", ex.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
private const uint SwizzleBase = 0x00000000;
|
||||
|
||||
private uint swizzle;
|
||||
private uint Swizzle
|
||||
{
|
||||
get
|
||||
{
|
||||
swizzle = SwizzleBase;
|
||||
swizzle |= (uint)(SheetIndex * 2) << 8;
|
||||
return swizzle;
|
||||
}
|
||||
}
|
||||
|
||||
private uint SwizzlePattern
|
||||
{
|
||||
get
|
||||
{
|
||||
return (uint)(SheetIndex * 2);
|
||||
}
|
||||
}
|
||||
|
||||
public override byte[] GetImageData(int ArrayLevel = 0, int MipLevel = 0, int DepthLevel = 0)
|
||||
{
|
||||
uint bpp = GetBytesPerPixel(Format);
|
||||
|
||||
GX2.GX2Surface surf = new GX2.GX2Surface();
|
||||
surf.bpp = bpp;
|
||||
surf.height = Height;
|
||||
surf.width = Width;
|
||||
surf.aa = (uint)GX2.GX2AAMode.GX2_AA_MODE_1X;
|
||||
surf.alignment = 0;
|
||||
surf.depth = 1;
|
||||
surf.dim = (uint)GX2.GX2SurfaceDimension.DIM_2D;
|
||||
surf.format = (uint)Bfres.Structs.FTEX.ConvertToGx2Format(Format);
|
||||
surf.use = (uint)GX2.GX2SurfaceUse.USE_COLOR_BUFFER;
|
||||
surf.pitch = 0;
|
||||
surf.data = TextureTGLP.SheetDataList[SheetIndex];
|
||||
surf.numMips = 1;
|
||||
surf.mipOffset = new uint[0];
|
||||
surf.mipData = null;
|
||||
surf.tileMode = (uint)GX2.GX2TileMode.MODE_2D_TILED_THIN1;
|
||||
surf.swizzle = Swizzle;
|
||||
surf.numArray = 1;
|
||||
|
||||
return GX2.Decode(surf, ArrayLevel, MipLevel);
|
||||
}
|
||||
|
||||
public override void OnClick(TreeView treeview)
|
||||
{
|
||||
UpdateEditor();
|
||||
}
|
||||
|
||||
private void UpdateEditor()
|
||||
{
|
||||
ImageEditorBase editor = (ImageEditorBase)LibraryGUI.GetActiveContent(typeof(ImageEditorBase));
|
||||
if (editor == null)
|
||||
{
|
||||
editor = new ImageEditorBase();
|
||||
editor.Dock = DockStyle.Fill;
|
||||
LibraryGUI.LoadEditor(editor);
|
||||
}
|
||||
|
||||
Properties prop = new Properties();
|
||||
prop.Width = Width;
|
||||
prop.Height = Height;
|
||||
prop.Depth = Depth;
|
||||
prop.MipCount = MipCount;
|
||||
prop.ArrayCount = ArrayCount;
|
||||
prop.ImageSize = (uint)TextureTGLP.SheetDataList[SheetIndex].Length;
|
||||
prop.Format = Format;
|
||||
prop.Swizzle = Swizzle;
|
||||
|
||||
|
||||
editor.Text = Text;
|
||||
editor.LoadProperties(prop);
|
||||
editor.LoadImage(this);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Drawing;
|
||||
using Toolbox.Library;
|
||||
using System.Windows.Forms;
|
||||
using Toolbox.Library.Forms;
|
||||
|
||||
namespace FirstPlugin
|
||||
{
|
||||
public class RevImageBlock : STGenericTexture
|
||||
{
|
||||
public TGLP TextureTGLP;
|
||||
|
||||
public int SheetIndex = 0;
|
||||
|
||||
public void Load(TGLP texture, int Index)
|
||||
{
|
||||
CanReplace = true;
|
||||
|
||||
SheetIndex = Index;
|
||||
TextureTGLP = texture;
|
||||
Height = TextureTGLP.SheetHeight;
|
||||
Width = TextureTGLP.SheetWidth;
|
||||
var BFNTFormat = (Decode_Gamecube.TextureFormats)TextureTGLP.Format;
|
||||
Format = Decode_Gamecube.ToGenericFormat(BFNTFormat);
|
||||
|
||||
if (Format == TEX_FORMAT.A4)
|
||||
{
|
||||
AlphaChannel = STChannelType.Red;
|
||||
}
|
||||
|
||||
PlatformSwizzle = PlatformSwizzle.Platform_Gamecube;
|
||||
|
||||
ImageKey = "Texture";
|
||||
SelectedImageKey = "Texture";
|
||||
}
|
||||
|
||||
public override bool CanEdit { get; set; } = true;
|
||||
public override string ExportFilter => FileFilters.GTX;
|
||||
public override string ReplaceFilter => FileFilters.GTX;
|
||||
|
||||
public override void Replace(string FileName)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public override TEX_FORMAT[] SupportedFormats
|
||||
{
|
||||
get
|
||||
{
|
||||
return new TEX_FORMAT[] {
|
||||
TEX_FORMAT.R8_UNORM,
|
||||
TEX_FORMAT.BC1_UNORM_SRGB,
|
||||
TEX_FORMAT.BC1_UNORM,
|
||||
TEX_FORMAT.BC2_UNORM,
|
||||
TEX_FORMAT.BC2_UNORM_SRGB,
|
||||
TEX_FORMAT.BC3_UNORM,
|
||||
TEX_FORMAT.BC3_UNORM_SRGB,
|
||||
TEX_FORMAT.BC4_UNORM,
|
||||
TEX_FORMAT.BC5_UNORM,
|
||||
TEX_FORMAT.R8G8_UNORM,
|
||||
TEX_FORMAT.B5G6R5_UNORM,
|
||||
TEX_FORMAT.B5G5R5A1_UNORM,
|
||||
TEX_FORMAT.R8G8B8A8_UNORM_SRGB,
|
||||
TEX_FORMAT.R8G8B8A8_UNORM,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public override void SetImageData(Bitmap bitmap, int ArrayLevel)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public override byte[] GetImageData(int ArrayLevel = 0, int MipLevel = 0, int DepthLevel = 0)
|
||||
{
|
||||
return TextureTGLP.SheetDataList[SheetIndex];
|
||||
}
|
||||
|
||||
public override void OnClick(TreeView treeview)
|
||||
{
|
||||
UpdateEditor();
|
||||
}
|
||||
|
||||
private void UpdateEditor()
|
||||
{
|
||||
ImageEditorBase editor = (ImageEditorBase)LibraryGUI.GetActiveContent(typeof(ImageEditorBase));
|
||||
if (editor == null)
|
||||
{
|
||||
editor = new ImageEditorBase();
|
||||
editor.Dock = DockStyle.Fill;
|
||||
LibraryGUI.LoadEditor(editor);
|
||||
}
|
||||
|
||||
Properties prop = new Properties();
|
||||
prop.Width = Width;
|
||||
prop.Height = Height;
|
||||
prop.Depth = Depth;
|
||||
prop.MipCount = MipCount;
|
||||
prop.ArrayCount = ArrayCount;
|
||||
prop.ImageSize = (uint)TextureTGLP.SheetDataList[SheetIndex].Length;
|
||||
prop.Format = Format;
|
||||
|
||||
editor.Text = Text;
|
||||
editor.LoadProperties(prop);
|
||||
editor.LoadImage(this);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
160
File_Format_Library/FileFormats/Font/BXFNT/TGLP.cs
Normal file
160
File_Format_Library/FileFormats/Font/BXFNT/TGLP.cs
Normal file
|
@ -0,0 +1,160 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
using Toolbox.Library;
|
||||
using Toolbox.Library.IO;
|
||||
|
||||
namespace FirstPlugin
|
||||
{
|
||||
public class TGLP
|
||||
{
|
||||
public BNTX BinaryTextureFile;
|
||||
|
||||
private List<STGenericTexture> textures = new List<STGenericTexture>();
|
||||
public List<STGenericTexture> Textures
|
||||
{
|
||||
get { return textures; }
|
||||
set { textures = value; }
|
||||
}
|
||||
|
||||
public uint SectionSize;
|
||||
public byte CellWidth { get; set; }
|
||||
public byte CellHeight { get; set; }
|
||||
public byte MaxCharWidth { get; set; }
|
||||
public byte SheetCount { get; private set; }
|
||||
public uint SheetSize { get; set; }
|
||||
public ushort BaseLinePos { get; set; }
|
||||
public ushort Format { get; set; }
|
||||
public ushort RowCount { get; set; }
|
||||
public ushort LinesCount { get; set; }
|
||||
public ushort SheetWidth { get; set; }
|
||||
public ushort SheetHeight { get; set; }
|
||||
public List<byte[]> SheetDataList = new List<byte[]>();
|
||||
|
||||
public void Read(FileReader reader, FFNT header)
|
||||
{
|
||||
string Signature = reader.ReadString(4, Encoding.ASCII);
|
||||
if (Signature != "TGLP")
|
||||
throw new Exception($"Invalid signature {Signature}! Expected TGLP.");
|
||||
SectionSize = reader.ReadUInt32();
|
||||
CellWidth = reader.ReadByte();
|
||||
CellHeight = reader.ReadByte();
|
||||
if (header.Platform <= FFNT.PlatformType.Ctr && header.Version < 0x04000000)
|
||||
{
|
||||
BaseLinePos = reader.ReadByte();
|
||||
MaxCharWidth = reader.ReadByte();
|
||||
SheetSize = reader.ReadUInt32();
|
||||
SheetCount = (byte)reader.ReadUInt16();
|
||||
}
|
||||
else
|
||||
{
|
||||
SheetCount = reader.ReadByte();
|
||||
MaxCharWidth = reader.ReadByte();
|
||||
SheetSize = reader.ReadUInt32();
|
||||
BaseLinePos = reader.ReadUInt16();
|
||||
}
|
||||
|
||||
Format = reader.ReadUInt16();
|
||||
RowCount = reader.ReadUInt16();
|
||||
LinesCount = reader.ReadUInt16();
|
||||
SheetWidth = reader.ReadUInt16();
|
||||
SheetHeight = reader.ReadUInt16();
|
||||
|
||||
uint sheetOffset = reader.ReadUInt32();
|
||||
using (reader.TemporarySeek(sheetOffset, SeekOrigin.Begin))
|
||||
{
|
||||
for (int i = 0; i < SheetCount; i++)
|
||||
{
|
||||
SheetDataList.Add(reader.ReadBytes((int)SheetSize));
|
||||
if (SheetDataList[i].Length != SheetSize)
|
||||
throw new Exception("SheetSize mis match!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Write(FileWriter writer, FFNT header)
|
||||
{
|
||||
long pos = writer.Position;
|
||||
|
||||
if (BinaryTextureFile != null)
|
||||
{
|
||||
var mem = new System.IO.MemoryStream();
|
||||
BinaryTextureFile.Save(mem);
|
||||
SheetDataList[0] = mem.ToArray();
|
||||
}
|
||||
|
||||
writer.WriteSignature("TGLP");
|
||||
writer.Write(uint.MaxValue);
|
||||
writer.Write(CellWidth);
|
||||
writer.Write(CellHeight);
|
||||
if (header.Platform <= FFNT.PlatformType.Ctr && header.Version < 0x04000000)
|
||||
{
|
||||
writer.Write((byte)BaseLinePos);
|
||||
writer.Write(MaxCharWidth);
|
||||
writer.Write(SheetDataList[0].Length);
|
||||
writer.Write((ushort)SheetDataList.Count);
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.Write((byte)SheetDataList.Count);
|
||||
writer.Write(MaxCharWidth);
|
||||
writer.Write(SheetDataList[0].Length);
|
||||
writer.Write(BaseLinePos);
|
||||
}
|
||||
|
||||
writer.Write(Format);
|
||||
writer.Write(RowCount);
|
||||
writer.Write(LinesCount);
|
||||
writer.Write(SheetWidth);
|
||||
writer.Write(SheetHeight);
|
||||
long _ofsSheetBlocks = writer.Position;
|
||||
writer.Write(uint.MaxValue);
|
||||
|
||||
if (header.Platform == FFNT.PlatformType.NX)
|
||||
writer.Align(4096);
|
||||
else if (header.Platform == FFNT.PlatformType.Cafe)
|
||||
writer.Align(8192);
|
||||
else if (header.Platform == FFNT.PlatformType.Ctr)
|
||||
writer.Align(64);
|
||||
else
|
||||
writer.Align(32);
|
||||
|
||||
long DataPosition = writer.Position;
|
||||
using (writer.TemporarySeek(_ofsSheetBlocks, SeekOrigin.Begin))
|
||||
{
|
||||
writer.Write((uint)DataPosition);
|
||||
}
|
||||
|
||||
for (int i = 0; i < SheetDataList.Count; i++)
|
||||
{
|
||||
writer.Write(SheetDataList[i]);
|
||||
}
|
||||
|
||||
|
||||
long SectionEndPosition = writer.Position;
|
||||
//End of section. Set the size
|
||||
using (writer.TemporarySeek(pos + 4, SeekOrigin.Begin))
|
||||
{
|
||||
writer.Write((uint)(SectionEndPosition - pos));
|
||||
}
|
||||
}
|
||||
|
||||
public STGenericTexture[] GetImageSheets()
|
||||
{
|
||||
STGenericTexture[] textures = new STGenericTexture[SheetCount];
|
||||
for (int i = 0; i < SheetCount; i++)
|
||||
textures[i] = GetImageSheet(i);
|
||||
return textures;
|
||||
}
|
||||
|
||||
public STGenericTexture GetImageSheet(int Index)
|
||||
{
|
||||
if (BinaryTextureFile != null) //BNTX uses only one image with multiple arrays
|
||||
return BinaryTextureFile.Textures.ElementAt(0).Value;
|
||||
else
|
||||
return Textures[Index];
|
||||
}
|
||||
}
|
||||
}
|
79
File_Format_Library/FileFormats/Layout/BLO/BL0.cs
Normal file
79
File_Format_Library/FileFormats/Layout/BLO/BL0.cs
Normal file
|
@ -0,0 +1,79 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Toolbox;
|
||||
using System.Windows.Forms;
|
||||
using Toolbox.Library;
|
||||
using Toolbox.Library.IO;
|
||||
using LayoutBXLYT.GCBLO;
|
||||
|
||||
namespace LayoutBXLYT
|
||||
{
|
||||
public class BLO : IFileFormat, IEditorForm<LayoutEditor>
|
||||
{
|
||||
public FileType FileType { get; set; } = FileType.Archive;
|
||||
|
||||
public bool CanSave { get; set; }
|
||||
public string[] Description { get; set; } = new string[] { "GC Layout File" };
|
||||
public string[] Extension { get; set; } = new string[] { "*.bl0" };
|
||||
public string FileName { get; set; }
|
||||
public string FilePath { get; set; }
|
||||
public IFileInfo IFileInfo { get; set; }
|
||||
|
||||
public bool CanAddFiles { get; set; }
|
||||
public bool CanRenameFiles { get; set; }
|
||||
public bool CanReplaceFiles { get; set; }
|
||||
public bool CanDeleteFiles { get; set; }
|
||||
|
||||
public bool Identify(System.IO.Stream stream)
|
||||
{
|
||||
using (var reader = new Toolbox.Library.IO.FileReader(stream, true))
|
||||
{
|
||||
return reader.CheckSignature(4, "SCRN");
|
||||
}
|
||||
}
|
||||
|
||||
public Type[] Types
|
||||
{
|
||||
get
|
||||
{
|
||||
List<Type> types = new List<Type>();
|
||||
return types.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
public LayoutEditor OpenForm()
|
||||
{
|
||||
LayoutEditor editor = new LayoutEditor();
|
||||
editor.Dock = DockStyle.Fill;
|
||||
editor.LoadBxlyt(Header);
|
||||
return editor;
|
||||
}
|
||||
|
||||
public void FillEditor(Form control)
|
||||
{
|
||||
((LayoutEditor)control).LoadBxlyt(Header);
|
||||
}
|
||||
|
||||
public BLOHeader Header;
|
||||
|
||||
public void Load(System.IO.Stream stream)
|
||||
{
|
||||
using (var reader = new FileReader(stream)) {
|
||||
Header = new BLOHeader();
|
||||
Header.Read(reader, this);
|
||||
}
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void Save(System.IO.Stream stream)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
98
File_Format_Library/FileFormats/Layout/BLO/BLO1/PAN1.cs
Normal file
98
File_Format_Library/FileFormats/Layout/BLO/BLO1/PAN1.cs
Normal file
|
@ -0,0 +1,98 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Toolbox.Library.IO;
|
||||
using Syroot.Maths;
|
||||
|
||||
namespace LayoutBXLYT.GCBLO
|
||||
{
|
||||
public class PAN1 : BasePane
|
||||
{
|
||||
public float Left { get; set; }
|
||||
public float Top { get; set; }
|
||||
|
||||
public short Angle { get; set; } = 0;
|
||||
|
||||
public AnchorType Anchor { get; set; } = AnchorType.TopLeft;
|
||||
|
||||
public PAN1() : base()
|
||||
{
|
||||
}
|
||||
|
||||
public PAN1(FileReader reader, BLOHeader header) : base()
|
||||
{
|
||||
byte paramCount = reader.ReadByte();
|
||||
Visible = reader.ReadBoolean();
|
||||
reader.ReadUInt16();
|
||||
Name = reader.ReadString(4, true);
|
||||
|
||||
Left = reader.ReadUInt16();
|
||||
Top = reader.ReadUInt16();
|
||||
Width = reader.ReadUInt16();
|
||||
Height = reader.ReadInt16();
|
||||
|
||||
paramCount -= 6;
|
||||
if (paramCount > 0) {
|
||||
Angle = reader.ReadInt16();
|
||||
--paramCount;
|
||||
}
|
||||
if (paramCount > 0) {
|
||||
Anchor = (AnchorType)reader.ReadByte();
|
||||
--paramCount;
|
||||
}
|
||||
if (paramCount > 0) {
|
||||
Alpha = reader.ReadByte();
|
||||
--paramCount;
|
||||
}
|
||||
if (paramCount > 0) {
|
||||
InfluenceAlpha = reader.ReadBoolean();
|
||||
--paramCount;
|
||||
}
|
||||
Alpha = 255;
|
||||
|
||||
Translate = GetPosition();
|
||||
Scale = new Vector2F(1, 1);
|
||||
Rotate = new Vector3F(0,0,0);
|
||||
}
|
||||
|
||||
public Vector3F GetPosition()
|
||||
{
|
||||
float X = 0, Y = 0;
|
||||
switch ((byte)Anchor % 3)
|
||||
{
|
||||
case 0: X = 0; break;
|
||||
case 1: X = Left / 2; break;
|
||||
case 2: X = Left; break;
|
||||
}
|
||||
switch ((byte)Anchor / 3)
|
||||
{
|
||||
case 0: Y = 0; break;
|
||||
case 1: Y = Top / 2; break;
|
||||
case 2: Y = Top; break;
|
||||
}
|
||||
return new Vector3F(X,Y,0);
|
||||
}
|
||||
|
||||
public virtual void Write(FileWriter writer)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public enum AnchorType
|
||||
{
|
||||
TopLeft,
|
||||
TopMiddle,
|
||||
TopRight,
|
||||
|
||||
CenterLeft,
|
||||
CenterMiddle,
|
||||
CenterRight,
|
||||
|
||||
BottomLeft,
|
||||
BottomMiddle,
|
||||
BottomRight,
|
||||
}
|
||||
}
|
||||
}
|
71
File_Format_Library/FileFormats/Layout/BLO/BLO1/PIC1.cs
Normal file
71
File_Format_Library/FileFormats/Layout/BLO/BLO1/PIC1.cs
Normal file
|
@ -0,0 +1,71 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Toolbox.Library.IO;
|
||||
using Toolbox.Library;
|
||||
using Syroot.BinaryData;
|
||||
|
||||
namespace LayoutBXLYT.GCBLO
|
||||
{
|
||||
public class PIC1 : PAN1, IPicturePane
|
||||
{
|
||||
public TexCoord[] TexCoords { get; set; }
|
||||
public STColor8 ColorTopLeft { get; set; } = STColor8.White;
|
||||
public STColor8 ColorTopRight { get; set; } = STColor8.White;
|
||||
public STColor8 ColorBottomLeft { get; set; } = STColor8.White;
|
||||
public STColor8 ColorBottomRight { get; set; } = STColor8.White;
|
||||
|
||||
public string TextureName { get; set; } = "";
|
||||
public string PaletteName { get; set; } = "";
|
||||
public byte Binding { get; set; }
|
||||
|
||||
public BxlytMaterial Material { get; set; }
|
||||
|
||||
public void CopyMaterial() {
|
||||
Material = (BxlytMaterial)Material.Clone();
|
||||
}
|
||||
|
||||
public ushort MaterialIndex { get; set; }
|
||||
|
||||
public PIC1(FileReader reader, BLOHeader header) : base(reader, header)
|
||||
{
|
||||
byte numParams = reader.ReadByte();
|
||||
if (numParams > 0) {
|
||||
TextureName = BloResource.Read(reader, header);
|
||||
numParams--;
|
||||
}
|
||||
if (numParams > 0) {
|
||||
PaletteName = BloResource.Read(reader, header);
|
||||
numParams--;
|
||||
}
|
||||
if (numParams > 0) {
|
||||
Binding = reader.ReadByte();
|
||||
numParams--;
|
||||
}
|
||||
|
||||
Material = new Material();
|
||||
|
||||
if (TextureName == string.Empty)
|
||||
Material.TextureMaps = new BxlytTextureRef[0];
|
||||
else
|
||||
{
|
||||
Material.TextureMaps = new BxlytTextureRef[1];
|
||||
Material.TextureMaps[0] = new BxlytTextureRef()
|
||||
{
|
||||
Name = TextureName,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
TexCoords = new TexCoord[1];
|
||||
TexCoords[0] = new TexCoord();
|
||||
}
|
||||
|
||||
public void Write(FileWriter writer)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
12
File_Format_Library/FileFormats/Layout/BLO/BLO1/TBX1.cs
Normal file
12
File_Format_Library/FileFormats/Layout/BLO/BLO1/TBX1.cs
Normal file
|
@ -0,0 +1,12 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace LayoutBXLYT.GCBLO
|
||||
{
|
||||
class TBX1
|
||||
{
|
||||
}
|
||||
}
|
157
File_Format_Library/FileFormats/Layout/BLO/BLO1/WIN1.cs
Normal file
157
File_Format_Library/FileFormats/Layout/BLO/BLO1/WIN1.cs
Normal file
|
@ -0,0 +1,157 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Toolbox.Library.IO;
|
||||
using Toolbox.Library;
|
||||
using Syroot.BinaryData;
|
||||
|
||||
namespace LayoutBXLYT.GCBLO
|
||||
{
|
||||
public class WIN1 : PAN1, IWindowPane
|
||||
{
|
||||
public BxlytHeader layoutHeader;
|
||||
|
||||
public bool UseOneMaterialForAll
|
||||
{
|
||||
get { return Convert.ToBoolean(_flag & 1); }
|
||||
set { }
|
||||
}
|
||||
|
||||
public bool UseVertexColorForAll
|
||||
{
|
||||
get { return Convert.ToBoolean((_flag >> 1) & 1); }
|
||||
set { }
|
||||
}
|
||||
|
||||
public WindowKind WindowKind { get; set; }
|
||||
|
||||
public bool NotDrawnContent
|
||||
{
|
||||
get { return (_flag & 8) == 16; }
|
||||
set { }
|
||||
}
|
||||
|
||||
public ushort StretchLeft { get; set; }
|
||||
public ushort StretchRight { get; set; }
|
||||
public ushort StretchTop { get; set; }
|
||||
public ushort StretchBottm { get; set; }
|
||||
public ushort FrameElementLeft { get; set; }
|
||||
public ushort FrameElementRight { get; set; }
|
||||
public ushort FrameElementTop { get; set; }
|
||||
public ushort FrameElementBottm { get; set; }
|
||||
private byte _flag;
|
||||
|
||||
private byte frameCount;
|
||||
public byte FrameCount
|
||||
{
|
||||
get { return frameCount; }
|
||||
set
|
||||
{
|
||||
frameCount = value;
|
||||
}
|
||||
}
|
||||
|
||||
public System.Drawing.Color[] GetVertexColors()
|
||||
{
|
||||
return new System.Drawing.Color[4]
|
||||
{
|
||||
Content.ColorTopLeft.Color,
|
||||
Content.ColorTopRight.Color,
|
||||
Content.ColorBottomLeft.Color,
|
||||
Content.ColorBottomRight.Color,
|
||||
};
|
||||
}
|
||||
|
||||
public void ReloadFrames()
|
||||
{
|
||||
SetFrames(layoutHeader);
|
||||
}
|
||||
|
||||
public void SetFrames(BxlytHeader header)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void CopyWindows()
|
||||
{
|
||||
Content = (BxlytWindowContent)Content.Clone();
|
||||
for (int f = 0; f < WindowFrames.Count; f++)
|
||||
WindowFrames[f] = (BxlytWindowFrame)WindowFrames[f].Clone();
|
||||
}
|
||||
|
||||
public BxlytWindowContent Content { get; set; }
|
||||
|
||||
public List<BxlytWindowFrame> WindowFrames { get; set; }
|
||||
|
||||
public string PaletteName { get; set; }
|
||||
|
||||
public WIN1(FileReader reader, BLOHeader header) : base(reader, header)
|
||||
{
|
||||
byte numParams = reader.ReadByte();
|
||||
short transX = reader.ReadInt16();
|
||||
short transY = reader.ReadInt16();
|
||||
Width = reader.ReadInt16();
|
||||
Height = reader.ReadInt16();
|
||||
|
||||
Translate = GetPosition() + new Syroot.Maths.Vector3F(transX, transY, 0);
|
||||
|
||||
Content = new BxlytWindowContent(header);
|
||||
Content.Material = new Material();
|
||||
Content.Material.TextureMaps = new BxlytTextureRef[0];
|
||||
|
||||
Console.WriteLine($"numParams {numParams}");
|
||||
FrameCount = 4;
|
||||
WindowKind = WindowKind.Around;
|
||||
|
||||
numParams -= 5;
|
||||
if (numParams > 0) {
|
||||
WindowFrames = new List<BxlytWindowFrame>();
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
string texName = BloResource.Read(reader, header);
|
||||
Console.WriteLine($"texName {texName}");
|
||||
|
||||
var frame = new WindowFrame(texName);
|
||||
WindowFrames.Add(frame);
|
||||
}
|
||||
}
|
||||
|
||||
/* if (numParams > 0) {
|
||||
PaletteName = BloResource.Read(reader, header);
|
||||
numParams--;
|
||||
}
|
||||
|
||||
PaletteName = BloResource.Read(reader, header);
|
||||
byte src = reader.ReadByte();
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
var mirror = (byte)((src >> (6 - (i * 2))) & 0x3);
|
||||
if (mirror == 1)
|
||||
WindowFrames[i].TextureFlip = WindowFrameTexFlip.FlipV;
|
||||
}*/
|
||||
}
|
||||
|
||||
public void Write(FileWriter writer)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public class WindowFrame : BxlytWindowFrame
|
||||
{
|
||||
public STColor8 Color { get; set; }
|
||||
|
||||
public WindowFrame(string name)
|
||||
{
|
||||
Material = new Material();
|
||||
Material.TextureMaps = new BxlytTextureRef[1];
|
||||
Material.TextureMaps[0] = new BxlytTextureRef()
|
||||
{
|
||||
Name = name,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
27
File_Format_Library/FileFormats/Layout/BLO/BLO2/MAT1.cs
Normal file
27
File_Format_Library/FileFormats/Layout/BLO/BLO2/MAT1.cs
Normal file
|
@ -0,0 +1,27 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Toolbox.Library.IO;
|
||||
|
||||
namespace LayoutBXLYT.GCBLO
|
||||
{
|
||||
public static class MAT1
|
||||
{
|
||||
public static List<Material> ReadMaterials(
|
||||
FileReader reader, BLOHeader header)
|
||||
{
|
||||
List<Material> materials = new List<Material>();
|
||||
|
||||
ushort count = reader.ReadUInt16();
|
||||
reader.ReadUInt16(); //0xFF
|
||||
uint materialDataOffset = reader.ReadUInt32();
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
materials.Add(new Material());
|
||||
|
||||
return materials;
|
||||
}
|
||||
}
|
||||
}
|
42
File_Format_Library/FileFormats/Layout/BLO/BLO2/PAN2.cs
Normal file
42
File_Format_Library/FileFormats/Layout/BLO/BLO2/PAN2.cs
Normal file
|
@ -0,0 +1,42 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Toolbox.Library.IO;
|
||||
using Syroot.Maths;
|
||||
|
||||
namespace LayoutBXLYT.GCBLO
|
||||
{
|
||||
public class PAN2 : PAN1
|
||||
{
|
||||
public PAN2(FileReader reader, BLOHeader header) : base()
|
||||
{
|
||||
long pos = reader.Position;
|
||||
|
||||
ushort sectionSize = reader.ReadUInt16();
|
||||
ushort unk = reader.ReadUInt16();
|
||||
uint unk2 = reader.ReadUInt32();
|
||||
uint unk3 = reader.ReadUInt32();
|
||||
Name = reader.ReadString(0x0C, true);
|
||||
|
||||
Width = reader.ReadSingle();
|
||||
Height = reader.ReadSingle();
|
||||
Left = reader.ReadSingle();
|
||||
Top = reader.ReadSingle();
|
||||
|
||||
Translate = GetPosition();
|
||||
Scale = new Vector2F(1, 1);
|
||||
Rotate = new Vector3F(0, 0, 0);
|
||||
Alpha = 255;
|
||||
Visible = true;
|
||||
|
||||
reader.SeekBegin(pos + sectionSize);
|
||||
}
|
||||
|
||||
public override void Write(FileWriter writer)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
74
File_Format_Library/FileFormats/Layout/BLO/BLO2/PIC2.cs
Normal file
74
File_Format_Library/FileFormats/Layout/BLO/BLO2/PIC2.cs
Normal file
|
@ -0,0 +1,74 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Toolbox.Library.IO;
|
||||
using Toolbox.Library;
|
||||
using Syroot.Maths;
|
||||
|
||||
namespace LayoutBXLYT.GCBLO
|
||||
{
|
||||
public class PIC2 : PAN2, IPicturePane
|
||||
{
|
||||
public TexCoord[] TexCoords { get; set; }
|
||||
public STColor8 ColorTopLeft { get; set; } = STColor8.White;
|
||||
public STColor8 ColorTopRight { get; set; } = STColor8.White;
|
||||
public STColor8 ColorBottomLeft { get; set; } = STColor8.White;
|
||||
public STColor8 ColorBottomRight { get; set; } = STColor8.White;
|
||||
|
||||
public string TextureName { get; set; } = "";
|
||||
public string PaletteName { get; set; } = "";
|
||||
public byte Binding { get; set; }
|
||||
|
||||
public BxlytMaterial Material { get; set; }
|
||||
|
||||
public void CopyMaterial()
|
||||
{
|
||||
Material = (BxlytMaterial)Material.Clone();
|
||||
}
|
||||
|
||||
public ushort MaterialIndex { get; set; }
|
||||
|
||||
public PIC2(FileReader reader, BLOHeader header) : base(reader, header) {
|
||||
TexCoords = new TexCoord[1];
|
||||
TexCoords[0] = new TexCoord();
|
||||
|
||||
ushort sectionSize = reader.ReadUInt16();
|
||||
Console.WriteLine($"PIC2 {sectionSize}");
|
||||
MaterialIndex = reader.ReadUInt16();
|
||||
Material = header.Materials[MaterialIndex];
|
||||
uint unk = reader.ReadUInt32();
|
||||
//These increase for each material
|
||||
ushort index1 = reader.ReadUInt16();
|
||||
ushort index2 = reader.ReadUInt16();
|
||||
ushort index3 = reader.ReadUInt16();
|
||||
ushort index4 = reader.ReadUInt16();
|
||||
|
||||
//I think these are texture coordinates
|
||||
TexCoords[0].TopLeft = new Vector2F(
|
||||
reader.ReadInt16() / 256f,
|
||||
reader.ReadInt16() / 256f);
|
||||
TexCoords[0].TopRight = new Vector2F(
|
||||
reader.ReadInt16() / 256f,
|
||||
reader.ReadInt16() / 256f);
|
||||
TexCoords[0].BottomLeft = new Vector2F(
|
||||
reader.ReadInt16() / 256f,
|
||||
reader.ReadInt16() / 256f);
|
||||
TexCoords[0].BottomRight = new Vector2F(
|
||||
reader.ReadInt16() / 256f,
|
||||
reader.ReadInt16() / 256f);
|
||||
|
||||
ColorTopLeft = STColor8.FromBytes(reader.ReadBytes(4));
|
||||
ColorTopRight = STColor8.FromBytes(reader.ReadBytes(4));
|
||||
ColorBottomLeft = STColor8.FromBytes(reader.ReadBytes(4));
|
||||
ColorBottomRight = STColor8.FromBytes(reader.ReadBytes(4));
|
||||
|
||||
}
|
||||
|
||||
public override void Write(FileWriter writer)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Toolbox.Library.IO;
|
||||
|
||||
namespace LayoutBXLYT.GCBLO
|
||||
{
|
||||
public class StringList
|
||||
{
|
||||
public static List<string> Read(FileReader reader, BLOHeader header)
|
||||
{
|
||||
List<string> values = new List<string>();
|
||||
|
||||
ushort count = reader.ReadUInt16();
|
||||
if (count == 0) return values;
|
||||
|
||||
ushort unk = reader.ReadUInt16(); //0xFFFF
|
||||
uint headerSize = reader.ReadUInt32(); //0x10
|
||||
|
||||
long startpos = reader.Position;
|
||||
|
||||
ushort count2 = reader.ReadUInt16(); //Same as count
|
||||
ushort[] offsets = reader.ReadUInt16s((int)count);
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
reader.SeekBegin(startpos + offsets[i]);
|
||||
values.Add(BloResource.Read(reader, header));
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
public static void Write(List<string> values, FileWriter writer, BLOHeader header)
|
||||
{
|
||||
writer.Write(values.Count);
|
||||
writer.Write((ushort)0xFFFF);
|
||||
writer.Write((ushort)0x10);
|
||||
|
||||
long startpos = writer.Position;
|
||||
writer.Write(values.Count);
|
||||
writer.Write(new ushort[values.Count]);
|
||||
for (int i = 0; i < values.Count; i++)
|
||||
{
|
||||
writer.WriteUint16Offset(startpos + (i * 4), startpos);
|
||||
BloResource.Write(writer, values[i], header);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
12
File_Format_Library/FileFormats/Layout/BLO/BLO2/TBX2.cs
Normal file
12
File_Format_Library/FileFormats/Layout/BLO/BLO2/TBX2.cs
Normal file
|
@ -0,0 +1,12 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FirstPlugin.FileFormats.Layout.BLO.BLO2
|
||||
{
|
||||
class TBX2
|
||||
{
|
||||
}
|
||||
}
|
12
File_Format_Library/FileFormats/Layout/BLO/BLO2/WIN2.cs
Normal file
12
File_Format_Library/FileFormats/Layout/BLO/BLO2/WIN2.cs
Normal file
|
@ -0,0 +1,12 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FirstPlugin.FileFormats.Layout.BLO.BLO2
|
||||
{
|
||||
class WIN2
|
||||
{
|
||||
}
|
||||
}
|
209
File_Format_Library/FileFormats/Layout/BLO/BLOHeader.cs
Normal file
209
File_Format_Library/FileFormats/Layout/BLO/BLOHeader.cs
Normal file
|
@ -0,0 +1,209 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Toolbox.Library.IO;
|
||||
using Toolbox.Library;
|
||||
using FirstPlugin;
|
||||
|
||||
namespace LayoutBXLYT.GCBLO
|
||||
{
|
||||
public class BLOHeader : BxlytHeader
|
||||
{
|
||||
public Dictionary<string, BloResource.bloResourceType> Resources =
|
||||
new Dictionary<string, BloResource.bloResourceType>();
|
||||
|
||||
private List<string> textureList = new List<string>();
|
||||
private List<string> fontList = new List<string>();
|
||||
private List<BxlytMaterial> materialList = new List<BxlytMaterial>();
|
||||
|
||||
public override List<string> Textures
|
||||
{
|
||||
get { return textureList; }
|
||||
}
|
||||
|
||||
public override List<string> Fonts
|
||||
{
|
||||
get { return fontList; }
|
||||
}
|
||||
|
||||
public override List<BxlytMaterial> Materials
|
||||
{
|
||||
get { return materialList; }
|
||||
}
|
||||
|
||||
public override Dictionary<string, STGenericTexture> GetTextures {
|
||||
get {
|
||||
Dictionary<string, STGenericTexture> textures = new Dictionary<string, STGenericTexture>();
|
||||
|
||||
var archive = this.FileInfo.IFileInfo.ArchiveParent;
|
||||
foreach (var tex in Textures)
|
||||
{
|
||||
if (archive != null)
|
||||
{
|
||||
foreach (var file in archive.Files)
|
||||
{
|
||||
string name = System.IO.Path.GetFileName(file.FileName);
|
||||
|
||||
Console.WriteLine($"{name} {tex} {tex.Contains(name)}");
|
||||
if (tex.Contains(name))
|
||||
{
|
||||
var fileFormat = file.OpenFile();
|
||||
if (fileFormat is BTI) {
|
||||
textures.Add(tex, (BTI)fileFormat);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return textures;
|
||||
}
|
||||
}
|
||||
|
||||
public INF1 LayoutInfo;
|
||||
|
||||
public void Read(FileReader reader, BLO bloFile)
|
||||
{
|
||||
FileInfo = bloFile;
|
||||
|
||||
reader.SetByteOrder(true);
|
||||
reader.ReadSignature(4, "SCRN");
|
||||
string version = reader.ReadString(4, Encoding.ASCII);
|
||||
switch (version)
|
||||
{
|
||||
case "blo0": Version = 0; break;
|
||||
case "blo1": Version = 1; break;
|
||||
case "blo2": Version = 2; break;
|
||||
default:
|
||||
throw new Exception("Unknown blo version! " + version);
|
||||
}
|
||||
uint fileSize = reader.ReadUInt32();
|
||||
uint numSections = reader.ReadUInt32();
|
||||
reader.Seek(0x10); //padding
|
||||
|
||||
bool setRoot = false;
|
||||
bool setGroupRoot = false;
|
||||
|
||||
BasePane currentPane = null;
|
||||
BasePane parentPane = null;
|
||||
this.RootGroup = new GroupPane();
|
||||
for (int i = 0; i < numSections; i++)
|
||||
{
|
||||
long pos = reader.Position;
|
||||
|
||||
string Signature = reader.ReadString(4, Encoding.ASCII);
|
||||
uint SectionSize = reader.ReadUInt32();
|
||||
switch (Signature)
|
||||
{
|
||||
case "INF1":
|
||||
LayoutInfo = new INF1(reader, this);
|
||||
break;
|
||||
case "TEX1":
|
||||
textureList = StringList.Read(reader, this);
|
||||
break;
|
||||
case "FNT1":
|
||||
fontList = StringList.Read(reader, this);
|
||||
break;
|
||||
case "MAT1":
|
||||
var mats = MAT1.ReadMaterials(reader, this);
|
||||
foreach (var mat in mats)
|
||||
materialList.Add(mat);
|
||||
break;
|
||||
case "PAN1":
|
||||
{
|
||||
var panel = new PAN1(reader, this);
|
||||
AddPaneToTable(panel);
|
||||
if (!setRoot)
|
||||
{
|
||||
RootPane = panel;
|
||||
setRoot = true;
|
||||
}
|
||||
|
||||
SetPane(panel, parentPane);
|
||||
currentPane = panel;
|
||||
}
|
||||
break;
|
||||
case "PAN2":
|
||||
{
|
||||
var panel = new PAN2(reader, this);
|
||||
AddPaneToTable(panel);
|
||||
if (!setRoot)
|
||||
{
|
||||
RootPane = panel;
|
||||
setRoot = true;
|
||||
}
|
||||
SetPane(panel, parentPane);
|
||||
currentPane = panel;
|
||||
}
|
||||
break;
|
||||
case "PIC1":
|
||||
{
|
||||
var picturePanel = new PIC1(reader, this);
|
||||
AddPaneToTable(picturePanel);
|
||||
|
||||
if (picturePanel.TextureName != string.Empty &&
|
||||
!textureList.Contains(picturePanel.TextureName))
|
||||
{
|
||||
textureList.Add(picturePanel.TextureName);
|
||||
}
|
||||
|
||||
SetPane(picturePanel, parentPane);
|
||||
currentPane = picturePanel;
|
||||
break;
|
||||
}
|
||||
case "PIC2":
|
||||
{
|
||||
reader.ReadUInt32(); //pan1 magic
|
||||
reader.ReadUInt32(); //pan1 size
|
||||
var picturePanel = new PIC2(reader, this);
|
||||
AddPaneToTable(picturePanel);
|
||||
|
||||
SetPane(picturePanel, parentPane);
|
||||
currentPane = picturePanel;
|
||||
break;
|
||||
}
|
||||
case "WIN1":
|
||||
var windowPane = new WIN1(reader, this);
|
||||
AddPaneToTable(windowPane);
|
||||
|
||||
SetPane(windowPane, parentPane);
|
||||
currentPane = windowPane;
|
||||
break;
|
||||
case "BGN1":
|
||||
if (currentPane != null)
|
||||
parentPane = currentPane;
|
||||
break;
|
||||
case "END1":
|
||||
if (parentPane != null)
|
||||
currentPane = parentPane;
|
||||
parentPane = currentPane.Parent;
|
||||
break;
|
||||
case "EXT1":
|
||||
// reader.ReadUInt32();
|
||||
// reader.Align(0x20);
|
||||
break;
|
||||
default:
|
||||
Console.WriteLine("Unknown section!" + Signature);
|
||||
break;
|
||||
}
|
||||
|
||||
reader.SeekBegin(pos + SectionSize);
|
||||
}
|
||||
}
|
||||
|
||||
private void SetPane(BasePane pane, BasePane parentPane)
|
||||
{
|
||||
if (parentPane != null)
|
||||
{
|
||||
parentPane.Childern.Add(pane);
|
||||
pane.Parent = parentPane;
|
||||
}
|
||||
}
|
||||
|
||||
public void Write(FileWriter writer)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
43
File_Format_Library/FileFormats/Layout/BLO/BloResource.cs
Normal file
43
File_Format_Library/FileFormats/Layout/BLO/BloResource.cs
Normal file
|
@ -0,0 +1,43 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Toolbox.Library.IO;
|
||||
|
||||
namespace LayoutBXLYT.GCBLO
|
||||
{
|
||||
public class BloResource
|
||||
{
|
||||
public static string Read(FileReader reader, BLOHeader header)
|
||||
{
|
||||
var type = (bloResourceType)reader.ReadByte();
|
||||
byte length = reader.ReadByte();
|
||||
string name = reader.ReadString(length, true);
|
||||
Console.WriteLine($"{type} {length} {name}");
|
||||
|
||||
if (!header.Resources.ContainsKey(name))
|
||||
header.Resources.Add(name, type);
|
||||
return name;
|
||||
}
|
||||
|
||||
public static void Write(FileWriter writer, string value, BLOHeader header)
|
||||
{
|
||||
if (header.Resources.ContainsKey(value))
|
||||
writer.Write((byte)header.Resources[value]);
|
||||
else
|
||||
writer.Write((byte)bloResourceType.LocalArchive);
|
||||
|
||||
writer.Write((byte)value.Length);
|
||||
writer.WriteString(value);
|
||||
}
|
||||
|
||||
public enum bloResourceType
|
||||
{
|
||||
None,
|
||||
LocalDirectory,
|
||||
LocalArchive,
|
||||
Global,
|
||||
}
|
||||
}
|
||||
}
|
100
File_Format_Library/FileFormats/Layout/BLO/BloShader.cs
Normal file
100
File_Format_Library/FileFormats/Layout/BLO/BloShader.cs
Normal file
|
@ -0,0 +1,100 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Drawing;
|
||||
using Toolbox.Library;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics.OpenGL;
|
||||
|
||||
namespace LayoutBXLYT
|
||||
{
|
||||
public class BloShader : BxlytShader
|
||||
{
|
||||
public BloShader() : base() {
|
||||
LoadShaders();
|
||||
}
|
||||
|
||||
public override void OnCompiled()
|
||||
{
|
||||
SetColor("whiteColor", Color.FromArgb(255, 255, 255, 255));
|
||||
SetColor("blackColor", Color.FromArgb(0, 0, 0, 0));
|
||||
SetInt("debugShading", 0);
|
||||
SetInt("hasTexture0", 0);
|
||||
SetInt("numTextureMaps", 0);
|
||||
SetInt("flipTexture", 0);
|
||||
SetInt("textures0", 0);
|
||||
SetInt("textures1", 0);
|
||||
SetInt("textures2", 0);
|
||||
SetBool("AlphaInterpolation", false);
|
||||
var rotationMatrix = Matrix4.Identity;
|
||||
SetMatrix("rotationMatrix", ref rotationMatrix);
|
||||
SetInt("numTevStages", 0);
|
||||
|
||||
SetVec2("uvScale0", new Vector2(1, 1));
|
||||
SetFloat("uvRotate0", 0);
|
||||
SetVec2("uvTranslate0", new Vector2(0, 0));
|
||||
SetVec4("IndirectMat0", new Vector4(1, 1, 0, 0));
|
||||
SetVec4("IndirectMat1", new Vector4(1, 1, 0, 0));
|
||||
SetInt($"texCoords0GenType", 0);
|
||||
SetInt($"texCoords0Source", 0);
|
||||
}
|
||||
|
||||
public static void SetMaterials(BxlytShader shader, GCBLO.Material material,
|
||||
BasePane pane, Dictionary<string, STGenericTexture> textures)
|
||||
{
|
||||
var rotationMatrix = pane.GetRotationMatrix();
|
||||
shader.SetMatrix("rotationMatrix", ref rotationMatrix);
|
||||
|
||||
STColor8 WhiteColor = material.WhiteColor;
|
||||
STColor8 BlackColor = material.BlackColor;
|
||||
|
||||
shader.SetColor("whiteColor", WhiteColor.Color);
|
||||
shader.SetColor("blackColor", BlackColor.Color);
|
||||
shader.SetInt("debugShading", (int)Runtime.LayoutEditor.Shading);
|
||||
shader.SetInt("numTextureMaps", material.TextureMaps.Length);
|
||||
shader.SetVec2("uvScale0", new Vector2(1, 1));
|
||||
shader.SetFloat("uvRotate0", 0);
|
||||
shader.SetVec2("uvTranslate0", new Vector2(0, 0));
|
||||
shader.SetInt("flipTexture", 0);
|
||||
shader.SetInt("numTevStages", 0);
|
||||
shader.SetBool("AlphaInterpolation", material.AlphaInterpolation);
|
||||
shader.SetVec4("IndirectMat0", new Vector4(1, 1, 0, 0));
|
||||
shader.SetVec4("IndirectMat1", new Vector4(1, 1, 0, 0));
|
||||
shader.SetInt("tevTexMode", 0);
|
||||
shader.SetInt($"texCoords0GenType", 0);
|
||||
shader.SetInt($"texCoords0Source", 0);
|
||||
|
||||
LoadTextureUniforms(shader, material, textures);
|
||||
LoadDefaultBlending();
|
||||
}
|
||||
|
||||
public override string VertexShader
|
||||
{
|
||||
get
|
||||
{
|
||||
string path = System.IO.Path.Combine(Runtime.ExecutableDir, "Shader", "Layout", "Bflyt.vert");
|
||||
string legacyPath = System.IO.Path.Combine(Runtime.ExecutableDir, "Shader", "Layout", "Legacy", "Bflyt.vert");
|
||||
|
||||
if (LayoutEditor.UseLegacyGL)
|
||||
return System.IO.File.ReadAllText(legacyPath);
|
||||
else
|
||||
return System.IO.File.ReadAllText(path);
|
||||
}
|
||||
}
|
||||
|
||||
public override string FragmentShader
|
||||
{
|
||||
get
|
||||
{
|
||||
string path = System.IO.Path.Combine(Runtime.ExecutableDir, "Shader", "Layout", "Bflyt.frag");
|
||||
string legacyPath = System.IO.Path.Combine(Runtime.ExecutableDir, "Shader", "Layout", "Legacy", "Bflyt.frag");
|
||||
|
||||
if (LayoutEditor.UseLegacyGL)
|
||||
return System.IO.File.ReadAllText(legacyPath);
|
||||
else
|
||||
return System.IO.File.ReadAllText(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
41
File_Format_Library/FileFormats/Layout/BLO/INF1.cs
Normal file
41
File_Format_Library/FileFormats/Layout/BLO/INF1.cs
Normal file
|
@ -0,0 +1,41 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Toolbox.Library.IO;
|
||||
using Toolbox.Library;
|
||||
|
||||
namespace LayoutBXLYT.GCBLO
|
||||
{
|
||||
public class INF1 : LayoutInfo
|
||||
{
|
||||
public uint Unknown { get; set; }
|
||||
|
||||
public STColor8 TintColor { get; set; }
|
||||
|
||||
public INF1()
|
||||
{
|
||||
Unknown = 0;
|
||||
Width = 0;
|
||||
Height = 0;
|
||||
TintColor = STColor8.White;
|
||||
}
|
||||
|
||||
public INF1(FileReader reader, BLOHeader header)
|
||||
{
|
||||
Unknown = reader.ReadUInt32();
|
||||
Width = reader.ReadUInt16();
|
||||
Height = reader.ReadInt16();
|
||||
TintColor = reader.ReadColor8RGBA();
|
||||
}
|
||||
|
||||
public void Write(FileWriter writer)
|
||||
{
|
||||
writer.Write(Unknown);
|
||||
writer.Write((ushort)Width);
|
||||
writer.Write((ushort)Height);
|
||||
writer.Write(TintColor);
|
||||
}
|
||||
}
|
||||
}
|
20
File_Format_Library/FileFormats/Layout/BLO/Material.cs
Normal file
20
File_Format_Library/FileFormats/Layout/BLO/Material.cs
Normal file
|
@ -0,0 +1,20 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Toolbox.Library;
|
||||
|
||||
namespace LayoutBXLYT.GCBLO
|
||||
{
|
||||
public class Material : BxlytMaterial
|
||||
{
|
||||
public Material()
|
||||
{
|
||||
WhiteColor = STColor8.White;
|
||||
BlackColor = STColor8.Black;
|
||||
TevStages = new BxlytTevStage[0];
|
||||
TextureMaps = new BxlytTextureRef[0];
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,6 +5,7 @@ using System.Text;
|
|||
using System.Threading.Tasks;
|
||||
using OpenTK.Graphics.OpenGL;
|
||||
using OpenTK;
|
||||
using Toolbox.Library;
|
||||
|
||||
namespace LayoutBXLYT
|
||||
{
|
||||
|
@ -234,5 +235,119 @@ namespace LayoutBXLYT
|
|||
GL.DeleteShader(fragmentShader);
|
||||
return program;
|
||||
}
|
||||
|
||||
public static void LoadDefaultBlending()
|
||||
{
|
||||
GL.Enable(EnableCap.Blend);
|
||||
GL.Enable(EnableCap.AlphaTest);
|
||||
GL.AlphaFunc(AlphaFunction.Always, 0f);
|
||||
GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha);
|
||||
GL.BlendEquation(BlendEquationMode.FuncAdd);
|
||||
GL.Disable(EnableCap.ColorLogicOp);
|
||||
GL.LogicOp(LogicOp.Noop);
|
||||
}
|
||||
|
||||
public static void LoadTextureUniforms(BxlytShader shader, BxlytMaterial material,
|
||||
Dictionary<string, STGenericTexture> textures)
|
||||
{
|
||||
shader.SetInt("hasTexture0", 0);
|
||||
shader.SetInt("hasTexture1", 0);
|
||||
shader.SetInt("hasTexture2", 0);
|
||||
shader.SetInt("textures0", 0);
|
||||
shader.SetInt("textures1", 0);
|
||||
shader.SetInt("textures2", 0);
|
||||
|
||||
BindTextureUniforms(shader, material);
|
||||
|
||||
if (material.TextureMaps.Length > 0 || Runtime.LayoutEditor.Shading == Runtime.LayoutEditor.DebugShading.UVTestPattern)
|
||||
GL.Enable(EnableCap.Texture2D);
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
//Default UVs as centered
|
||||
var matTranslate = Matrix4.CreateTranslation(0 / 1 - 0.5f, 0 / 1 - 0.5f, 0);
|
||||
shader.SetMatrix(String.Format("textureTransforms[{0}]", i), ref matTranslate);
|
||||
}
|
||||
|
||||
int id = 1;
|
||||
for (int i = 0; i < material.TextureMaps.Length; i++)
|
||||
{
|
||||
string TexName = material.TextureMaps[i].Name;
|
||||
|
||||
if (material.animController.TexturePatterns.ContainsKey((LTPTarget)i))
|
||||
TexName = material.animController.TexturePatterns[(LTPTarget)i];
|
||||
|
||||
if (textures.ContainsKey(TexName))
|
||||
{
|
||||
GL.ActiveTexture(TextureUnit.Texture0 + id);
|
||||
shader.SetInt($"textures{i}", id);
|
||||
bool isBinded = BxlytToGL.BindGLTexture(material.TextureMaps[i], textures[TexName]);
|
||||
if (isBinded)
|
||||
shader.SetInt($"hasTexture{i}", 1);
|
||||
|
||||
var scale = new Syroot.Maths.Vector2F(1, 1);
|
||||
float rotate = 0;
|
||||
var translate = new Syroot.Maths.Vector2F(0, 0);
|
||||
|
||||
int index = i;
|
||||
|
||||
if (material.TextureTransforms.Length > index)
|
||||
{
|
||||
var transform = material.TextureTransforms[index];
|
||||
scale = transform.Scale;
|
||||
rotate = transform.Rotate;
|
||||
translate = transform.Translate;
|
||||
|
||||
foreach (var animItem in material.animController.TextureSRTS)
|
||||
{
|
||||
switch (animItem.Key)
|
||||
{
|
||||
case LTSTarget.ScaleS: scale.X = animItem.Value; break;
|
||||
case LTSTarget.ScaleT: scale.Y = animItem.Value; break;
|
||||
case LTSTarget.Rotate: rotate = animItem.Value; break;
|
||||
case LTSTarget.TranslateS: translate.X = animItem.Value; break;
|
||||
case LTSTarget.TranslateT: translate.Y = animItem.Value; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var matScale = Matrix4.CreateScale(scale.X, scale.Y, 1.0f);
|
||||
var matRotate = Matrix4.CreateFromAxisAngle(new Vector3(0, 0, 1), MathHelper.DegreesToRadians(rotate));
|
||||
var matTranslate = Matrix4.CreateTranslation(
|
||||
translate.X / scale.X - 0.5f,
|
||||
translate.Y / scale.Y - 0.5f, 0);
|
||||
|
||||
Matrix4 matTransform = matRotate * matTranslate * matScale;
|
||||
shader.SetMatrix(String.Format("textureTransforms[{0}]", i), ref matTransform);
|
||||
|
||||
id++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void BindTextureUniforms(BxlytShader shader, BxlytMaterial material)
|
||||
{
|
||||
//Do uv test pattern
|
||||
GL.ActiveTexture(TextureUnit.Texture10);
|
||||
GL.Uniform1(GL.GetUniformLocation(shader.program, "uvTestPattern"), 10);
|
||||
GL.BindTexture(TextureTarget.Texture2D, RenderTools.uvTestPattern.RenderableTex.TexID);
|
||||
|
||||
if (material.TextureMaps.Length > 0)
|
||||
{
|
||||
var tex = material.TextureMaps[0];
|
||||
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, BxlytToGL.ConvertTextureWrap(tex.WrapModeU));
|
||||
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, BxlytToGL.ConvertTextureWrap(tex.WrapModeV));
|
||||
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, BxlytToGL.ConvertMagFilterMode(tex.MaxFilterMode));
|
||||
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, BxlytToGL.ConvertMinFilterMode(tex.MinFilterMode));
|
||||
}
|
||||
else
|
||||
{
|
||||
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureParameterName.ClampToEdge);
|
||||
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureParameterName.ClampToEdge);
|
||||
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
|
||||
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -169,6 +169,84 @@ namespace LayoutBXLYT
|
|||
GL.Disable(EnableCap.Texture2D);
|
||||
// ShaderLoader.RevShader.Disable();
|
||||
}
|
||||
else if (pane is GCBLO.PIC1)
|
||||
{
|
||||
var pic1Pane = pane as GCBLO.PIC1;
|
||||
|
||||
ShaderLoader.BLOShader.Enable();
|
||||
BloShader.SetMaterials(ShaderLoader.BLOShader, (GCBLO.Material)pic1Pane.Material, pane, Textures);
|
||||
|
||||
Color[] Colors = new Color[] {
|
||||
pic1Pane.ColorBottomLeft.Color,
|
||||
pic1Pane.ColorBottomRight.Color,
|
||||
pic1Pane.ColorTopRight.Color,
|
||||
pic1Pane.ColorTopLeft.Color,
|
||||
};
|
||||
|
||||
if (pic1Pane.TexCoords.Length > 0)
|
||||
{
|
||||
TexCoords = new Vector2[] {
|
||||
pic1Pane.TexCoords[0].BottomLeft.ToTKVector2(),
|
||||
pic1Pane.TexCoords[0].BottomRight.ToTKVector2(),
|
||||
pic1Pane.TexCoords[0].TopRight.ToTKVector2(),
|
||||
pic1Pane.TexCoords[0].TopLeft.ToTKVector2(),
|
||||
};
|
||||
}
|
||||
|
||||
DrawRectangle(pane, gameWindow, pane.Rectangle, TexCoords, Colors, false, effectiveAlpha, isSelected);
|
||||
ShaderLoader.BLOShader.Disable();
|
||||
}
|
||||
else if (pane is GCBLO.PIC2)
|
||||
{
|
||||
var pic1Pane = pane as GCBLO.PIC2;
|
||||
|
||||
ShaderLoader.BLOShader.Enable();
|
||||
BloShader.SetMaterials(ShaderLoader.BLOShader, (GCBLO.Material)pic1Pane.Material, pane, Textures);
|
||||
|
||||
Color[] Colors = new Color[] {
|
||||
pic1Pane.ColorBottomLeft.Color,
|
||||
pic1Pane.ColorBottomRight.Color,
|
||||
pic1Pane.ColorTopRight.Color,
|
||||
pic1Pane.ColorTopLeft.Color,
|
||||
};
|
||||
|
||||
if (pic1Pane.TexCoords.Length > 0)
|
||||
{
|
||||
TexCoords = new Vector2[] {
|
||||
pic1Pane.TexCoords[0].BottomLeft.ToTKVector2(),
|
||||
pic1Pane.TexCoords[0].BottomRight.ToTKVector2(),
|
||||
pic1Pane.TexCoords[0].TopRight.ToTKVector2(),
|
||||
pic1Pane.TexCoords[0].TopLeft.ToTKVector2(),
|
||||
};
|
||||
}
|
||||
|
||||
DrawRectangle(pane, gameWindow, pane.Rectangle, TexCoords, Colors, false, effectiveAlpha, isSelected);
|
||||
ShaderLoader.BLOShader.Disable();
|
||||
}
|
||||
else
|
||||
{
|
||||
var pic1Pane = pane as IPicturePane;
|
||||
|
||||
Color[] Colors = new Color[] {
|
||||
pic1Pane.ColorBottomLeft.Color,
|
||||
pic1Pane.ColorBottomRight.Color,
|
||||
pic1Pane.ColorTopRight.Color,
|
||||
pic1Pane.ColorTopLeft.Color,
|
||||
};
|
||||
|
||||
if (pic1Pane.TexCoords.Length > 0)
|
||||
{
|
||||
TexCoords = new Vector2[] {
|
||||
pic1Pane.TexCoords[0].BottomLeft.ToTKVector2(),
|
||||
pic1Pane.TexCoords[0].BottomRight.ToTKVector2(),
|
||||
pic1Pane.TexCoords[0].TopRight.ToTKVector2(),
|
||||
pic1Pane.TexCoords[0].TopLeft.ToTKVector2(),
|
||||
};
|
||||
}
|
||||
|
||||
DrawRectangle(pane, gameWindow, pane.Rectangle, TexCoords, Colors, false, effectiveAlpha, isSelected);
|
||||
|
||||
}
|
||||
|
||||
// GL.BindTexture(TextureTarget.Texture2D, 0);
|
||||
// GL.Disable(EnableCap.Texture2D);
|
||||
|
@ -228,8 +306,8 @@ namespace LayoutBXLYT
|
|||
GL.LogicOp(logicOp);
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
Matrix4 matTransform = Matrix4.Identity;
|
||||
mat.Shader.SetMatrix4(String.Format("textureTransforms[{0}]", i), ref matTransform);
|
||||
var matTranslate = Matrix4.CreateTranslation(0 / 1 - 0.5f, 0 / 1 - 0.5f, 0);
|
||||
mat.Shader.SetMatrix4(String.Format("textureTransforms[{0}]", i), ref matTranslate);
|
||||
}
|
||||
|
||||
mat.Shader.Enable();
|
||||
|
@ -576,6 +654,8 @@ namespace LayoutBXLYT
|
|||
shader = ShaderLoader.CtrShader;
|
||||
if (pane is Revolution.PAN1)
|
||||
shader = ShaderLoader.RevShader;
|
||||
if (pane is GCBLO.PAN1)
|
||||
shader = ShaderLoader.BLOShader;
|
||||
|
||||
var window = (IWindowPane)pane;
|
||||
|
||||
|
@ -1120,7 +1200,7 @@ namespace LayoutBXLYT
|
|||
{
|
||||
if (mat is Revolution.Material)
|
||||
((Revolution.Material)mat).Shader.SetInt("flipTexture", (int)flip);
|
||||
else
|
||||
else
|
||||
shader.SetInt("flipTexture", (int)flip);
|
||||
}
|
||||
|
||||
|
@ -1252,6 +1332,11 @@ namespace LayoutBXLYT
|
|||
ShaderLoader.CtrShader.Enable();
|
||||
BclytShader.SetMaterials(ShaderLoader.CtrShader, (CTR.Material)mat, pane, textures);
|
||||
}
|
||||
else if (mat is GCBLO.Material)
|
||||
{
|
||||
ShaderLoader.BLOShader.Enable();
|
||||
BloShader.SetMaterials(ShaderLoader.CtrShader, (GCBLO.Material)mat, pane, textures);
|
||||
}
|
||||
}
|
||||
|
||||
private static void RenderWindowContent(BasePane pane, uint sizeX, uint sizeY, BxlytWindowContent content,
|
||||
|
|
|
@ -130,59 +130,8 @@ namespace LayoutBXLYT
|
|||
shader.SetInt($"tevStage{i}A", (int)material.TevStages[i].AlphaMode);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
Matrix4 matTransform = Matrix4.Identity;
|
||||
shader.SetMatrix(String.Format("textureTransforms[{0}]", i), ref matTransform);
|
||||
}
|
||||
|
||||
for (int i = 0; i < material.TextureMaps.Length; i++)
|
||||
{
|
||||
var scale = new Syroot.Maths.Vector2F(1, 1);
|
||||
float rotate = 0;
|
||||
var translate = new Syroot.Maths.Vector2F(0, 0);
|
||||
|
||||
int index = i;
|
||||
// if (material.TexCoordGens?.Length > i)
|
||||
// index = (int)material.TexCoordGens[i].Source / 3 - 10;
|
||||
|
||||
if (material.TextureTransforms.Length > index)
|
||||
{
|
||||
var transform = material.TextureTransforms[index];
|
||||
scale = transform.Scale;
|
||||
rotate = transform.Rotate;
|
||||
translate = transform.Translate;
|
||||
|
||||
foreach (var animItem in material.animController.TextureSRTS)
|
||||
{
|
||||
switch (animItem.Key)
|
||||
{
|
||||
case LTSTarget.ScaleS: scale.X = animItem.Value; break;
|
||||
case LTSTarget.ScaleT: scale.Y = animItem.Value; break;
|
||||
case LTSTarget.Rotate: rotate = animItem.Value; break;
|
||||
case LTSTarget.TranslateS: translate.X = animItem.Value; break;
|
||||
case LTSTarget.TranslateT: translate.Y = animItem.Value; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var matScale = Matrix4.CreateScale(scale.X, scale.Y, 1.0f);
|
||||
var matRotate = Matrix4.CreateFromAxisAngle(new Vector3(0, 0, 1), MathHelper.DegreesToRadians(rotate));
|
||||
var matTranslate = Matrix4.CreateTranslation(
|
||||
translate.X / scale.X - 0.5f,
|
||||
translate.Y / scale.Y - 0.5f, 0);
|
||||
|
||||
Matrix4 matTransform = matRotate * matTranslate * matScale;
|
||||
shader.SetMatrix(String.Format("textureTransforms[{0}]", i), ref matTransform);
|
||||
}
|
||||
|
||||
|
||||
GL.Enable(EnableCap.Blend);
|
||||
GL.Enable(EnableCap.AlphaTest);
|
||||
GL.AlphaFunc(AlphaFunction.Always, 0f);
|
||||
GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha);
|
||||
GL.BlendEquation(BlendEquationMode.FuncAdd);
|
||||
GL.Disable(EnableCap.ColorLogicOp);
|
||||
GL.LogicOp(LogicOp.Noop);
|
||||
LoadTextureUniforms(shader, material, textures);
|
||||
LoadDefaultBlending();
|
||||
|
||||
if (material.BlendMode != null && material.EnableBlend)
|
||||
{
|
||||
|
|
|
@ -336,6 +336,9 @@ namespace LayoutBXLYT.Cafe
|
|||
if (userDataOffset != 0)
|
||||
{
|
||||
reader.SeekBegin(StartPosition + userDataOffset);
|
||||
reader.ReadUInt32();//magic
|
||||
reader.ReadUInt32();//section size
|
||||
|
||||
UserData = new USD1(reader, header);
|
||||
}
|
||||
if (panelInfoOffset != 0)
|
||||
|
@ -376,7 +379,12 @@ namespace LayoutBXLYT.Cafe
|
|||
if (UserData != null)
|
||||
{
|
||||
writer.WriteUint32Offset(_ofsPos + 4, startPos);
|
||||
long pos = writer.Position;
|
||||
writer.WriteSignature("usd1");
|
||||
writer.Write(uint.MaxValue);
|
||||
UserData.Write(writer, header);
|
||||
writer.Align(4);
|
||||
writer.WriteSectionSizeU32(pos + 4, pos, writer.Position);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -252,6 +252,8 @@ namespace LayoutBXLYT.Cafe
|
|||
|
||||
long startPos = reader.Position - 84;
|
||||
|
||||
Console.WriteLine($"{Name}");
|
||||
|
||||
TextLength = reader.ReadUInt16();
|
||||
MaxTextLength = reader.ReadUInt16();
|
||||
MaterialIndex = reader.ReadUInt16();
|
||||
|
@ -302,7 +304,6 @@ namespace LayoutBXLYT.Cafe
|
|||
TextBoxName = reader.ReadZeroTerminatedString();
|
||||
}
|
||||
|
||||
|
||||
if (header.VersionMajor > 2 && PerCharTransformEnabled)
|
||||
{
|
||||
reader.SeekBegin(startPos + perCharTransformOffset);
|
||||
|
|
|
@ -60,86 +60,8 @@ namespace LayoutBXLYT
|
|||
shader.SetInt($"texCoords0GenType", 0);
|
||||
shader.SetInt($"texCoords0Source", 0);
|
||||
|
||||
BindTextureUniforms(shader, material);
|
||||
|
||||
int id = 1;
|
||||
for (int i = 0; i < material.TextureMaps.Length; i++)
|
||||
{
|
||||
string TexName = material.TextureMaps[i].Name;
|
||||
if (material.animController.TexturePatterns.ContainsKey((LTPTarget)i))
|
||||
TexName = material.animController.TexturePatterns[(LTPTarget)i];
|
||||
|
||||
shader.SetInt($"hasTexture{i}", 0);
|
||||
if (textures.ContainsKey(TexName))
|
||||
{
|
||||
GL.ActiveTexture(TextureUnit.Texture0 + id);
|
||||
shader.SetInt($"textures{i}", id);
|
||||
bool binded = BxlytToGL.BindGLTexture(material.TextureMaps[i], textures[TexName]);
|
||||
shader.SetInt($"hasTexture{i}", binded ? 1 : 0);
|
||||
id++;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
Matrix4 matTransform = Matrix4.Identity;
|
||||
shader.SetMatrix(String.Format("textureTransforms[{0}]", i), ref matTransform);
|
||||
}
|
||||
|
||||
for (int i = 0; i < material.TextureMaps.Length; i++) {
|
||||
var scale = new Syroot.Maths.Vector2F(1, 1);
|
||||
float rotate = 0;
|
||||
var translate = new Syroot.Maths.Vector2F(0, 0);
|
||||
|
||||
int index = i;
|
||||
// if (material.TexCoordGens?.Length > i)
|
||||
// index = (int)material.TexCoordGens[i].Source / 3 - 10;
|
||||
|
||||
if (material.TextureTransforms.Length > index)
|
||||
{
|
||||
var transform = material.TextureTransforms[index];
|
||||
scale = transform.Scale;
|
||||
rotate = transform.Rotate;
|
||||
translate = transform.Translate;
|
||||
|
||||
foreach (var animItem in material.animController.TextureSRTS)
|
||||
{
|
||||
switch (animItem.Key)
|
||||
{
|
||||
case LTSTarget.ScaleS: scale.X = animItem.Value; break;
|
||||
case LTSTarget.ScaleT: scale.Y = animItem.Value; break;
|
||||
case LTSTarget.Rotate: rotate = animItem.Value; break;
|
||||
case LTSTarget.TranslateS: translate.X = animItem.Value; break;
|
||||
case LTSTarget.TranslateT: translate.Y = animItem.Value; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var matScale = Matrix4.CreateScale(scale.X, scale.Y, 1.0f);
|
||||
var matRotate = Matrix4.CreateFromAxisAngle(new Vector3(0, 0, 1), MathHelper.DegreesToRadians(rotate));
|
||||
var matTranslate = Matrix4.CreateTranslation(
|
||||
translate.X / scale.X - 0.5f,
|
||||
translate.Y / scale.Y - 0.5f, 0);
|
||||
|
||||
Matrix4 matTransform = matRotate * matTranslate * matScale;
|
||||
shader.SetMatrix(String.Format("textureTransforms[{0}]", i), ref matTransform);
|
||||
}
|
||||
}
|
||||
|
||||
private static void BindTextureUniforms(BxlytShader shader, BxlytMaterial material)
|
||||
{
|
||||
//Do uv test pattern
|
||||
GL.ActiveTexture(TextureUnit.Texture10);
|
||||
GL.Uniform1(GL.GetUniformLocation(shader.program, "uvTestPattern"), 10);
|
||||
GL.BindTexture(TextureTarget.Texture2D, RenderTools.uvTestPattern.RenderableTex.TexID);
|
||||
|
||||
if (material.TextureMaps.Length > 0)
|
||||
{
|
||||
var tex = material.TextureMaps[0];
|
||||
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, BxlytToGL.ConvertTextureWrap(tex.WrapModeU));
|
||||
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, BxlytToGL.ConvertTextureWrap(tex.WrapModeV));
|
||||
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, BxlytToGL.ConvertMagFilterMode(tex.MaxFilterMode));
|
||||
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, BxlytToGL.ConvertMinFilterMode(tex.MinFilterMode));
|
||||
}
|
||||
LoadTextureUniforms(shader, material, textures);
|
||||
LoadDefaultBlending();
|
||||
}
|
||||
|
||||
public override string VertexShader
|
||||
|
|
|
@ -334,7 +334,7 @@ namespace LayoutBXLYT
|
|||
|
||||
[Browsable(false)]
|
||||
[YamlIgnore]
|
||||
public CustomRectangle Rectangle
|
||||
public virtual CustomRectangle Rectangle
|
||||
{
|
||||
get
|
||||
{
|
||||
|
@ -1405,6 +1405,15 @@ namespace LayoutBXLYT
|
|||
return this.MemberwiseClone();
|
||||
}
|
||||
|
||||
public BxlytWindowContent(BxlytHeader header) {
|
||||
LayoutFile = header;
|
||||
ColorTopLeft = STColor8.White;
|
||||
ColorTopRight = STColor8.White;
|
||||
ColorBottomLeft = STColor8.White;
|
||||
ColorBottomRight = STColor8.White;
|
||||
TexCoords.Add(new TexCoord());
|
||||
}
|
||||
|
||||
public BxlytWindowContent(BxlytHeader header, string name)
|
||||
{
|
||||
LayoutFile = header;
|
||||
|
@ -1476,6 +1485,11 @@ namespace LayoutBXLYT
|
|||
return this.MemberwiseClone();
|
||||
}
|
||||
|
||||
public BxlytWindowFrame()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public BxlytWindowFrame(BxlytHeader header, string materialName)
|
||||
{
|
||||
TextureFlip = WindowFrameTexFlip.None;
|
||||
|
@ -2548,6 +2562,8 @@ namespace LayoutBXLYT
|
|||
public OpenTK.Vector2 BottomLeftPoint;
|
||||
public OpenTK.Vector2 BottomRightPoint;
|
||||
|
||||
public CustomRectangle() { }
|
||||
|
||||
public CustomRectangle(OpenTK.Vector2 topLeft, OpenTK.Vector2 topRight,
|
||||
OpenTK.Vector2 bottomLeft, OpenTK.Vector2 bottomRight)
|
||||
{
|
||||
|
|
|
@ -108,60 +108,6 @@ namespace LayoutBXLYT
|
|||
shader.SetInt("tevTexMode", 0);
|
||||
shader.SetInt($"texCoords0GenType", 0);
|
||||
shader.SetInt($"texCoords0Source", 0);
|
||||
|
||||
BindTextureUniforms(shader, material);
|
||||
|
||||
int id = 1;
|
||||
for (int i = 0; i < material.TextureMaps.Length; i++)
|
||||
{
|
||||
string TexName = material.TextureMaps[i].Name;
|
||||
|
||||
if (material.animController.TexturePatterns.ContainsKey((LTPTarget)i))
|
||||
TexName = material.animController.TexturePatterns[(LTPTarget)i];
|
||||
|
||||
if (textures.ContainsKey(TexName))
|
||||
{
|
||||
GL.ActiveTexture(TextureUnit.Texture0 + id);
|
||||
shader.SetInt($"textures{i}", id);
|
||||
bool isBinded = BxlytToGL.BindGLTexture(material.TextureMaps[i], textures[TexName]);
|
||||
if (isBinded)
|
||||
shader.SetInt($"hasTexture{i}", 1);
|
||||
|
||||
id++;
|
||||
}
|
||||
}
|
||||
|
||||
if (material.TextureTransforms.Length > 0)
|
||||
{
|
||||
var transform = material.TextureTransforms[0];
|
||||
var scale = transform.Scale;
|
||||
var rotate = transform.Rotate;
|
||||
var translate = transform.Translate;
|
||||
|
||||
foreach (var animItem in material.animController.TextureSRTS)
|
||||
{
|
||||
switch (animItem.Key)
|
||||
{
|
||||
case LTSTarget.ScaleS: scale.X = animItem.Value; break;
|
||||
case LTSTarget.ScaleT: scale.Y = animItem.Value; break;
|
||||
case LTSTarget.Rotate: rotate = animItem.Value; break;
|
||||
case LTSTarget.TranslateS: translate.X = animItem.Value; break;
|
||||
case LTSTarget.TranslateT: translate.Y = animItem.Value; break;
|
||||
}
|
||||
}
|
||||
|
||||
shader.SetVec2("uvScale0", new Vector2(scale.X, scale.Y));
|
||||
shader.SetFloat("uvRotate0", rotate);
|
||||
shader.SetVec2("uvTranslate0", new Vector2(translate.X, translate.Y));
|
||||
}
|
||||
|
||||
GL.Enable(EnableCap.Blend);
|
||||
GL.Enable(EnableCap.AlphaTest);
|
||||
GL.AlphaFunc(AlphaFunction.Always, 0f);
|
||||
GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha);
|
||||
GL.BlendEquation(BlendEquationMode.FuncAdd);
|
||||
GL.Disable(EnableCap.ColorLogicOp);
|
||||
GL.LogicOp(LogicOp.Noop);
|
||||
}
|
||||
|
||||
private static void BindTextureUniforms(BxlytShader shader, BxlytMaterial material)
|
||||
|
|
|
@ -11,6 +11,7 @@ namespace LayoutBXLYT
|
|||
private static BflytShader cafeShader;
|
||||
private static BrlytShader revShader;
|
||||
private static BclytShader ctrShader;
|
||||
private static BloShader bloShader;
|
||||
|
||||
public static BflytShader CafeShader
|
||||
{
|
||||
|
@ -39,5 +40,14 @@ namespace LayoutBXLYT
|
|||
return ctrShader;
|
||||
}
|
||||
}
|
||||
public static BloShader BLOShader
|
||||
{
|
||||
get
|
||||
{
|
||||
if (bloShader == null)
|
||||
bloShader = new BloShader();
|
||||
return bloShader;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ using Toolbox.Library.IO;
|
|||
|
||||
namespace FirstPlugin
|
||||
{
|
||||
public class MSBT : IEditor<MSBTEditor>, IFileFormat
|
||||
public class MSBT : IEditor<MSBTEditor>, IFileFormat, IConvertableTextFormat
|
||||
{
|
||||
public FileType FileType { get; set; } = FileType.Message;
|
||||
|
||||
|
@ -39,6 +39,21 @@ namespace FirstPlugin
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
#region Text Converter Interface
|
||||
public TextFileType TextFileType => TextFileType.Xml;
|
||||
public bool CanConvertBack => false;
|
||||
|
||||
public string ConvertToString() {
|
||||
return MSYT.ToYaml(this);
|
||||
}
|
||||
|
||||
public void ConvertFromString(string text)
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public MSBTEditor OpenForm()
|
||||
{
|
||||
MSBTEditor editor = new MSBTEditor();
|
||||
|
@ -56,7 +71,7 @@ namespace FirstPlugin
|
|||
|
||||
public void Load(System.IO.Stream stream)
|
||||
{
|
||||
CanSave = false;
|
||||
CanSave = true;
|
||||
|
||||
header = new Header();
|
||||
header.Read(new FileReader(stream));
|
||||
|
@ -113,7 +128,13 @@ namespace FirstPlugin
|
|||
uint FileSize = reader.ReadUInt32();
|
||||
Reserved = reader.ReadBytes(10);
|
||||
|
||||
StringEncoding = (encoding == 0x01 ? Encoding.BigEndianUnicode : Encoding.UTF8);
|
||||
|
||||
if (encoding == 0x00)
|
||||
StringEncoding = Encoding.UTF8;
|
||||
else if (reader.IsBigEndian)
|
||||
StringEncoding = Encoding.BigEndianUnicode;
|
||||
else
|
||||
StringEncoding = Encoding.Unicode;
|
||||
|
||||
for (int i = 0; i < SectionCount; i++)
|
||||
{
|
||||
|
@ -151,18 +172,13 @@ namespace FirstPlugin
|
|||
MSBTEntry entry = new MSBTEntry();
|
||||
entry.Signature = Signature;
|
||||
entry.Padding = reader.ReadBytes(8);
|
||||
entry.EntryCount = reader.ReadUInt32();
|
||||
entry.Data = reader.ReadBytes((int)SectionSize);
|
||||
entries.Add(entry);
|
||||
break;
|
||||
}
|
||||
|
||||
reader.SeekBegin(pos + SectionSize + 0x10);
|
||||
|
||||
while (reader.BaseStream.Position % 16 != 0 && reader.BaseStream.Position != reader.BaseStream.Length)
|
||||
{
|
||||
reader.ReadByte();
|
||||
}
|
||||
reader.Align(16);
|
||||
}
|
||||
|
||||
//Setup labels to text properly
|
||||
|
@ -202,6 +218,16 @@ namespace FirstPlugin
|
|||
writer.Write((uint)writer.BaseStream.Length);
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
using (var textWriter = new StringWriter(builder))
|
||||
{
|
||||
textWriter.Write($"");
|
||||
}
|
||||
return builder.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
public class LabelGroup
|
||||
|
@ -236,13 +262,15 @@ namespace FirstPlugin
|
|||
{
|
||||
private uint _index;
|
||||
|
||||
public StringEntry(byte[] data)
|
||||
{
|
||||
public StringEntry(byte[] data) {
|
||||
Data = data;
|
||||
}
|
||||
|
||||
public StringEntry(string text, Encoding encoding)
|
||||
{
|
||||
public StringEntry(byte[] data, Encoding encoding) {
|
||||
Data = data;
|
||||
}
|
||||
|
||||
public StringEntry(string text, Encoding encoding) {
|
||||
Data = encoding.GetBytes(text);
|
||||
}
|
||||
|
||||
|
@ -264,6 +292,35 @@ namespace FirstPlugin
|
|||
{
|
||||
return encoding.GetString(Data);
|
||||
}
|
||||
|
||||
public byte[] ToBytes(Encoding encoding, bool isBigEndian)
|
||||
{
|
||||
return Data;
|
||||
|
||||
var mem = new MemoryStream();
|
||||
var text = GetText(encoding);
|
||||
using (var writer = new FileWriter(mem, encoding)) {
|
||||
writer.SetByteOrder(isBigEndian);
|
||||
for (int i = 0; i < text.Length; i++)
|
||||
{
|
||||
var c = text[i];
|
||||
writer.Write(c);
|
||||
if (c == 0xE)
|
||||
{
|
||||
writer.Write((short)text[++i]);
|
||||
writer.Write((short)text[++i]);
|
||||
int count = text[++i];
|
||||
writer.Write((short)count);
|
||||
for (var j = 0; j < count; j++)
|
||||
{
|
||||
writer.Write((byte)text[++i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
writer.Write('\0');
|
||||
}
|
||||
return mem.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
public class TXT2 : MSBTEntry
|
||||
|
@ -274,29 +331,33 @@ namespace FirstPlugin
|
|||
|
||||
public override void Read(FileReader reader, Header header)
|
||||
{
|
||||
reader.Seek(-4);
|
||||
uint sectionSize = reader.ReadUInt32();
|
||||
|
||||
Padding = reader.ReadBytes(8);
|
||||
|
||||
long Position = reader.Position;
|
||||
long pos = reader.Position;
|
||||
EntryCount = reader.ReadUInt32();
|
||||
Offsets = reader.ReadUInt32s((int)EntryCount);
|
||||
|
||||
for (int i = 0; i < EntryCount; i++)
|
||||
{
|
||||
reader.SeekBegin(Offsets[i] + Position);
|
||||
ReadMessageString(reader, header, (uint)i);
|
||||
//Get the start and end position
|
||||
uint startPos = Offsets[i] + (uint)pos;
|
||||
uint endPos = i + 1 < EntryCount ? (uint)pos + Offsets[i + 1] :
|
||||
(uint)pos + sectionSize;
|
||||
|
||||
reader.SeekBegin(startPos);
|
||||
ReadMessageString(reader, header, (uint)i, endPos - startPos);
|
||||
}
|
||||
}
|
||||
|
||||
private void ReadMessageString(FileReader reader, Header header, uint index)
|
||||
private void ReadMessageString(FileReader reader, Header header, uint index, uint size)
|
||||
{
|
||||
string text = "";
|
||||
if (header.StringEncoding == Encoding.BigEndianUnicode)
|
||||
text = reader.ReadUTF16String();
|
||||
else
|
||||
text = reader.ReadZeroTerminatedString(header.StringEncoding);
|
||||
byte[] textData = reader.ReadBytes((int)size);
|
||||
|
||||
TextData.Add(new StringEntry(text, header.StringEncoding) { Index = index, });
|
||||
OriginalTextData.Add(new StringEntry(text, header.StringEncoding) { Index = index, });
|
||||
TextData.Add(new StringEntry(textData, header.StringEncoding) { Index = index, });
|
||||
OriginalTextData.Add(new StringEntry(textData, header.StringEncoding) { Index = index, });
|
||||
}
|
||||
|
||||
public override void Write(FileWriter writer, Header header)
|
||||
|
@ -307,19 +368,9 @@ namespace FirstPlugin
|
|||
writer.Write(TextData.Count);
|
||||
writer.Write(new uint[TextData.Count]);
|
||||
|
||||
for (int i = 0; i < EntryCount; i++)
|
||||
{
|
||||
for (int i = 0; i < EntryCount; i++) {
|
||||
writer.WriteUint32Offset(pos + 4 + (i * 4), pos);
|
||||
if (header.StringEncoding == Encoding.UTF8)
|
||||
writer.WriteString(TextData[i].ToString(), Encoding.UTF8);
|
||||
else
|
||||
{
|
||||
for (int j = 0; j < TextData[i].ToString().Length; j+= 2)
|
||||
{
|
||||
writer.Write(TextData[i].ToString()[j + 1]);
|
||||
writer.Write(TextData[i].ToString()[j]);
|
||||
}
|
||||
}
|
||||
writer.Write(TextData[i].ToBytes(header.StringEncoding, header.IsBigEndian));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -527,13 +578,11 @@ namespace FirstPlugin
|
|||
for (int i = 0; i < group.NumberOfLabels; i++)
|
||||
{
|
||||
LabelEntry entry = new LabelEntry();
|
||||
entry.Length = reader.ReadByte();
|
||||
entry.Length = reader.ReadByte();
|
||||
entry.Name = reader.ReadString((int)entry.Length);
|
||||
entry.Index = reader.ReadUInt32();
|
||||
entry.Checksum = (uint)Groups.IndexOf(group);
|
||||
Labels.Add(entry);
|
||||
|
||||
Console.WriteLine("label entry " + entry.Name);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -542,11 +591,26 @@ namespace FirstPlugin
|
|||
|
||||
public override void Write(FileWriter writer, Header header)
|
||||
{
|
||||
writer.Write(Padding);
|
||||
writer.Seek(8);
|
||||
|
||||
for (int i = 0; i < Groups.Count; i++)
|
||||
{
|
||||
long pos = writer.Position;
|
||||
writer.Write(Groups.Count);
|
||||
for (int i = 0; i < Groups.Count; i++) {
|
||||
writer.Write(Groups[i].NumberOfLabels);
|
||||
writer.Write(uint.MaxValue);
|
||||
}
|
||||
|
||||
int index = 0;
|
||||
for (int g = 0; g < Groups.Count; g++) {
|
||||
writer.WriteUint32Offset(pos + 8 + (g * 8), pos);
|
||||
for (int i = 0; i < Groups[g].NumberOfLabels; i++)
|
||||
{
|
||||
writer.Write((byte)Labels[index].Name.Length);
|
||||
writer.WriteString(Labels[index].Name, Labels[index].Length);
|
||||
writer.Write(Labels[index].Index);
|
||||
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -557,23 +621,11 @@ namespace FirstPlugin
|
|||
writer.WriteSignature(magic);
|
||||
writer.Write(uint.MaxValue);
|
||||
section.Write(writer, header);
|
||||
long endPos = writer.Position - 16;
|
||||
WritePadding(writer);
|
||||
long endPos = writer.Position;
|
||||
|
||||
using (writer.TemporarySeek(startPos + 4, System.IO.SeekOrigin.Begin))
|
||||
{
|
||||
writer.Write((uint)(endPos - startPos));
|
||||
}
|
||||
}
|
||||
|
||||
private static void WritePadding(FileWriter writer)
|
||||
{
|
||||
long alignedBytes = writer.BaseStream.Position % 16;
|
||||
if (alignedBytes > 0)
|
||||
{
|
||||
for (int i = 0; i < 16 - alignedBytes; i++)
|
||||
writer.Write((byte)0xAB);
|
||||
}
|
||||
writer.AlignBytes(16, 0xAB);
|
||||
//Skip 20 bytes from the header
|
||||
writer.WriteSectionSizeU32(startPos + 4, startPos + 0x10, endPos);
|
||||
}
|
||||
|
||||
public class MSBTEntry
|
||||
|
@ -590,7 +642,6 @@ namespace FirstPlugin
|
|||
public virtual void Write(FileWriter writer, Header header)
|
||||
{
|
||||
writer.Write(Padding);
|
||||
writer.Write(EntryCount);
|
||||
writer.Write(Data);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -160,7 +160,7 @@ namespace FirstPlugin
|
|||
|
||||
OpenFileDialog ofd = new OpenFileDialog();
|
||||
ofd.Multiselect = true;
|
||||
ofd.Filter = Utils.GetAllFilters(new Type[] { typeof(BFLIM), typeof(BFFNT), typeof(BFRES), typeof(PTCL), typeof(SARC) });
|
||||
ofd.Filter = Utils.GetAllFilters(new Type[] { typeof(BFLIM), typeof(BXFNT), typeof(BFRES), typeof(PTCL), typeof(SARC) });
|
||||
|
||||
if (ofd.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
|
@ -169,7 +169,7 @@ namespace FirstPlugin
|
|||
{
|
||||
foreach (string file in ofd.FileNames)
|
||||
{
|
||||
var FileFormat = STFileLoader.OpenFileFormat(file, new Type[] { typeof(BFLIM), typeof(PTCL), typeof(BFRES), typeof(BFFNT), typeof(SARC) });
|
||||
var FileFormat = STFileLoader.OpenFileFormat(file, new Type[] { typeof(BFLIM), typeof(PTCL), typeof(BFRES), typeof(BXFNT), typeof(SARC) });
|
||||
if (FileFormat == null)
|
||||
continue;
|
||||
|
||||
|
@ -202,16 +202,16 @@ namespace FirstPlugin
|
|||
|
||||
foreach (var file in ((SARC)FileFormat).Files)
|
||||
{
|
||||
var archiveFile = STFileLoader.OpenFileFormat(file.FileName, new Type[] { typeof(BFLIM), typeof(BFFNT), typeof(PTCL), typeof(BFRES), typeof(SARC) }, file.FileData);
|
||||
var archiveFile = STFileLoader.OpenFileFormat(file.FileName, new Type[] { typeof(BFLIM), typeof(BXFNT), typeof(PTCL), typeof(BFRES), typeof(SARC) }, file.FileData);
|
||||
if (archiveFile == null)
|
||||
continue;
|
||||
|
||||
SearchBinary(archiveFile, ArchiveFilePath, Extension);
|
||||
}
|
||||
}
|
||||
if (FileFormat is BFFNT)
|
||||
if (FileFormat is BXFNT)
|
||||
{
|
||||
foreach (STGenericTexture texture in ((BFFNT)FileFormat).bffnt.FontSection.TextureGlyph.Gx2Textures)
|
||||
foreach (STGenericTexture texture in ((BXFNT)FileFormat).bffnt.FontSection.TextureGlyph.Textures)
|
||||
texture.Export(Path.Combine(Folder, $"{texture.Text}{Extension}"));
|
||||
}
|
||||
if (FileFormat is BFRES)
|
||||
|
@ -488,7 +488,7 @@ namespace FirstPlugin
|
|||
{
|
||||
[0] = TEX_FORMAT.L8,
|
||||
[1] = TEX_FORMAT.A8_UNORM,
|
||||
[2] = TEX_FORMAT.A4,
|
||||
[2] = TEX_FORMAT.LA4,
|
||||
[3] = TEX_FORMAT.LA8,
|
||||
[4] = TEX_FORMAT.HIL08,
|
||||
[5] = TEX_FORMAT.B5G6R5_UNORM,
|
||||
|
@ -512,7 +512,7 @@ namespace FirstPlugin
|
|||
{
|
||||
[0] = TEX_FORMAT.L8,
|
||||
[1] = TEX_FORMAT.A8_UNORM,
|
||||
[2] = TEX_FORMAT.A4,
|
||||
[2] = TEX_FORMAT.LA4,
|
||||
[3] = TEX_FORMAT.LA8,
|
||||
[4] = TEX_FORMAT.R8G8_UNORM, //HILO8
|
||||
[5] = TEX_FORMAT.B5G6R5_UNORM,
|
||||
|
|
|
@ -190,7 +190,7 @@ namespace FirstPlugin
|
|||
|
||||
OpenFileDialog ofd = new OpenFileDialog();
|
||||
ofd.Multiselect = true;
|
||||
ofd.Filter = Utils.GetAllFilters(new Type[] { typeof(BNTX), typeof(BFFNT), typeof(BFRES), typeof(PTCL), typeof(SARC) });
|
||||
ofd.Filter = Utils.GetAllFilters(new Type[] { typeof(BNTX), typeof(BXFNT), typeof(BFRES), typeof(PTCL), typeof(SARC) });
|
||||
|
||||
if (ofd.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
|
@ -199,7 +199,7 @@ namespace FirstPlugin
|
|||
{
|
||||
foreach (string file in ofd.FileNames)
|
||||
{
|
||||
var FileFormat = STFileLoader.OpenFileFormat(file, new Type[] { typeof(BNTX), typeof(BFFNT), typeof(BFRES), typeof(PTCL), typeof(SARC) });
|
||||
var FileFormat = STFileLoader.OpenFileFormat(file, new Type[] { typeof(BNTX), typeof(BXFNT), typeof(BFRES), typeof(PTCL), typeof(SARC) });
|
||||
if (FileFormat == null)
|
||||
continue;
|
||||
|
||||
|
@ -230,7 +230,7 @@ namespace FirstPlugin
|
|||
|
||||
foreach (var file in ((SARC)FileFormat).Files)
|
||||
{
|
||||
var archiveFile = STFileLoader.OpenFileFormat(file.FileName, new Type[] { typeof(BNTX), typeof(BFFNT), typeof(BFRES), typeof(PTCL), typeof(SARC) }, file.FileData);
|
||||
var archiveFile = STFileLoader.OpenFileFormat(file.FileName, new Type[] { typeof(BNTX), typeof(BXFNT), typeof(BFRES), typeof(PTCL), typeof(SARC) }, file.FileData);
|
||||
if (archiveFile == null)
|
||||
continue;
|
||||
|
||||
|
@ -264,9 +264,9 @@ namespace FirstPlugin
|
|||
bntx.Unload();
|
||||
}
|
||||
}
|
||||
if (FileFormat is BFFNT)
|
||||
if (FileFormat is BXFNT)
|
||||
{
|
||||
var bntx = ((BFFNT)FileFormat).bffnt.FontSection.TextureGlyph.BinaryTextureFile;
|
||||
var bntx = ((BXFNT)FileFormat).bffnt.FontSection.TextureGlyph.BinaryTextureFile;
|
||||
if (bntx != null)
|
||||
{
|
||||
foreach (var texture in bntx.Textures.Values)
|
||||
|
|
|
@ -8,7 +8,7 @@ using System.Runtime.InteropServices;
|
|||
|
||||
namespace FirstPlugin
|
||||
{
|
||||
class BTI : STGenericTexture, IFileFormat, ISingleTextureIconLoader
|
||||
public class BTI : STGenericTexture, IFileFormat, ISingleTextureIconLoader
|
||||
{
|
||||
public STGenericTexture IconTexture { get { return this; } }
|
||||
|
||||
|
|
|
@ -58,6 +58,8 @@
|
|||
this.stLabel5 = new Toolbox.Library.Forms.STLabel();
|
||||
this.scaleYUD = new BarSlider.BarSlider();
|
||||
this.scaleXUD = new BarSlider.BarSlider();
|
||||
this.stLabel8 = new Toolbox.Library.Forms.STLabel();
|
||||
this.textureNameTB = new Toolbox.Library.Forms.STTextBox();
|
||||
((System.ComponentModel.ISupportInitialize)(this.stPanel1)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.stPanel2)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.stPanel3)).BeginInit();
|
||||
|
@ -214,6 +216,8 @@
|
|||
// stDropDownPanel2
|
||||
//
|
||||
this.stDropDownPanel2.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
|
||||
this.stDropDownPanel2.Controls.Add(this.textureNameTB);
|
||||
this.stDropDownPanel2.Controls.Add(this.stLabel8);
|
||||
this.stDropDownPanel2.Controls.Add(this.shrinkCB);
|
||||
this.stDropDownPanel2.Controls.Add(this.stLabel3);
|
||||
this.stDropDownPanel2.Controls.Add(this.expandCB);
|
||||
|
@ -243,7 +247,7 @@
|
|||
this.shrinkCB.ButtonColor = System.Drawing.Color.Empty;
|
||||
this.shrinkCB.FormattingEnabled = true;
|
||||
this.shrinkCB.IsReadOnly = false;
|
||||
this.shrinkCB.Location = new System.Drawing.Point(263, 131);
|
||||
this.shrinkCB.Location = new System.Drawing.Point(263, 152);
|
||||
this.shrinkCB.Name = "shrinkCB";
|
||||
this.shrinkCB.Size = new System.Drawing.Size(142, 21);
|
||||
this.shrinkCB.TabIndex = 14;
|
||||
|
@ -252,7 +256,7 @@
|
|||
// stLabel3
|
||||
//
|
||||
this.stLabel3.AutoSize = true;
|
||||
this.stLabel3.Location = new System.Drawing.Point(183, 134);
|
||||
this.stLabel3.Location = new System.Drawing.Point(183, 155);
|
||||
this.stLabel3.Name = "stLabel3";
|
||||
this.stLabel3.Size = new System.Drawing.Size(65, 13);
|
||||
this.stLabel3.TabIndex = 13;
|
||||
|
@ -265,7 +269,7 @@
|
|||
this.expandCB.ButtonColor = System.Drawing.Color.Empty;
|
||||
this.expandCB.FormattingEnabled = true;
|
||||
this.expandCB.IsReadOnly = false;
|
||||
this.expandCB.Location = new System.Drawing.Point(263, 104);
|
||||
this.expandCB.Location = new System.Drawing.Point(263, 125);
|
||||
this.expandCB.Name = "expandCB";
|
||||
this.expandCB.Size = new System.Drawing.Size(142, 21);
|
||||
this.expandCB.TabIndex = 12;
|
||||
|
@ -274,7 +278,7 @@
|
|||
// stLabel4
|
||||
//
|
||||
this.stLabel4.AutoSize = true;
|
||||
this.stLabel4.Location = new System.Drawing.Point(183, 107);
|
||||
this.stLabel4.Location = new System.Drawing.Point(183, 128);
|
||||
this.stLabel4.Name = "stLabel4";
|
||||
this.stLabel4.Size = new System.Drawing.Size(71, 13);
|
||||
this.stLabel4.TabIndex = 11;
|
||||
|
@ -287,7 +291,7 @@
|
|||
this.wrapModeVCB.ButtonColor = System.Drawing.Color.Empty;
|
||||
this.wrapModeVCB.FormattingEnabled = true;
|
||||
this.wrapModeVCB.IsReadOnly = false;
|
||||
this.wrapModeVCB.Location = new System.Drawing.Point(263, 66);
|
||||
this.wrapModeVCB.Location = new System.Drawing.Point(263, 87);
|
||||
this.wrapModeVCB.Name = "wrapModeVCB";
|
||||
this.wrapModeVCB.Size = new System.Drawing.Size(142, 21);
|
||||
this.wrapModeVCB.TabIndex = 10;
|
||||
|
@ -296,7 +300,7 @@
|
|||
// stLabel2
|
||||
//
|
||||
this.stLabel2.AutoSize = true;
|
||||
this.stLabel2.Location = new System.Drawing.Point(183, 69);
|
||||
this.stLabel2.Location = new System.Drawing.Point(183, 90);
|
||||
this.stLabel2.Name = "stLabel2";
|
||||
this.stLabel2.Size = new System.Drawing.Size(76, 13);
|
||||
this.stLabel2.TabIndex = 9;
|
||||
|
@ -309,7 +313,7 @@
|
|||
this.wrapModeUCB.ButtonColor = System.Drawing.Color.Empty;
|
||||
this.wrapModeUCB.FormattingEnabled = true;
|
||||
this.wrapModeUCB.IsReadOnly = false;
|
||||
this.wrapModeUCB.Location = new System.Drawing.Point(263, 39);
|
||||
this.wrapModeUCB.Location = new System.Drawing.Point(263, 60);
|
||||
this.wrapModeUCB.Name = "wrapModeUCB";
|
||||
this.wrapModeUCB.Size = new System.Drawing.Size(142, 21);
|
||||
this.wrapModeUCB.TabIndex = 8;
|
||||
|
@ -318,7 +322,7 @@
|
|||
// stLabel1
|
||||
//
|
||||
this.stLabel1.AutoSize = true;
|
||||
this.stLabel1.Location = new System.Drawing.Point(183, 42);
|
||||
this.stLabel1.Location = new System.Drawing.Point(183, 63);
|
||||
this.stLabel1.Name = "stLabel1";
|
||||
this.stLabel1.Size = new System.Drawing.Size(77, 13);
|
||||
this.stLabel1.TabIndex = 7;
|
||||
|
@ -590,6 +594,23 @@
|
|||
this.scaleXUD.Value = 30F;
|
||||
this.scaleXUD.ValueChanged += new System.EventHandler(this.transformUV_ValueChanged);
|
||||
//
|
||||
// stLabel8
|
||||
//
|
||||
this.stLabel8.AutoSize = true;
|
||||
this.stLabel8.Location = new System.Drawing.Point(183, 30);
|
||||
this.stLabel8.Name = "stLabel8";
|
||||
this.stLabel8.Size = new System.Drawing.Size(38, 13);
|
||||
this.stLabel8.TabIndex = 15;
|
||||
this.stLabel8.Text = "Name:";
|
||||
//
|
||||
// textureNameTB
|
||||
//
|
||||
this.textureNameTB.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
|
||||
this.textureNameTB.Location = new System.Drawing.Point(263, 28);
|
||||
this.textureNameTB.Name = "textureNameTB";
|
||||
this.textureNameTB.Size = new System.Drawing.Size(142, 20);
|
||||
this.textureNameTB.TabIndex = 16;
|
||||
//
|
||||
// PaneMatTextureMapsEditor
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
|
@ -643,5 +664,7 @@
|
|||
private Toolbox.Library.Forms.STLabel stLabel5;
|
||||
private BarSlider.BarSlider scaleYUD;
|
||||
private BarSlider.BarSlider scaleXUD;
|
||||
private Toolbox.Library.Forms.STTextBox textureNameTB;
|
||||
private Toolbox.Library.Forms.STLabel stLabel8;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,6 +56,7 @@ namespace LayoutBXLYT
|
|||
|
||||
ResetImagePanels();
|
||||
Images.Clear();
|
||||
textureNameTB.Text = "";
|
||||
|
||||
for (int i = 0; i < ActiveMaterial.TextureMaps?.Length; i++)
|
||||
{
|
||||
|
@ -93,6 +94,7 @@ namespace LayoutBXLYT
|
|||
}
|
||||
else
|
||||
{
|
||||
textureNameTB.Text = "";
|
||||
editBtn.Enabled = true;
|
||||
removebtn.Enabled = true;
|
||||
addbtn.Enabled = true;
|
||||
|
@ -165,6 +167,7 @@ namespace LayoutBXLYT
|
|||
wrapModeVCB.SelectedItem = texMap.WrapModeV;
|
||||
expandCB.SelectedItem = texMap.MaxFilterMode;
|
||||
shrinkCB.SelectedItem = texMap.MinFilterMode;
|
||||
textureNameTB.Text = texMap.Name;
|
||||
|
||||
if (ActiveMaterial.TextureTransforms?.Length > SelectedIndex)
|
||||
{
|
||||
|
|
|
@ -49,7 +49,7 @@ namespace LayoutBXLYT
|
|||
{
|
||||
OpenFileDialog ofd = new OpenFileDialog();
|
||||
ofd.Filter = Utils.GetAllFilters(new Type[]
|
||||
{ typeof(BFFNT), typeof(BFTTF) });
|
||||
{ typeof(BXFNT), typeof(BXFNT) });
|
||||
|
||||
if (ofd.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
|
@ -58,7 +58,7 @@ namespace LayoutBXLYT
|
|||
btnOk.Enabled = true;
|
||||
|
||||
var file = STFileLoader.OpenFileFormat(ofd.FileName);
|
||||
if (file is BFFNT)
|
||||
if (file is BXFNT)
|
||||
{
|
||||
|
||||
}
|
||||
|
|
|
@ -293,7 +293,8 @@ namespace LayoutBXLYT
|
|||
{
|
||||
AnimationPanel?.Reset();
|
||||
foreach (ListViewItem item in LayoutAnimList.GetSelectedAnimations)
|
||||
UpdateAnimationPlayer((BxlanHeader)item.Tag);
|
||||
if (item.Tag is BxlanHeader)
|
||||
UpdateAnimationPlayer((BxlanHeader)item.Tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -704,10 +705,8 @@ namespace LayoutBXLYT
|
|||
LoadBxlyt(((BRLYT)layouts[0]).header);
|
||||
}
|
||||
}
|
||||
else if (file is BFLAN)
|
||||
LoadBxlan(((BFLAN)file).BxlanHeader);
|
||||
else if (file is BRLAN)
|
||||
LoadBxlan(((BRLAN)file).BxlanHeader);
|
||||
else if (file is BXLAN)
|
||||
LoadBxlan(((BXLAN)file).BxlanHeader);
|
||||
else if (file is BNTX)
|
||||
{
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ using System.Windows.Forms;
|
|||
using Toolbox.Library.Forms;
|
||||
using Toolbox.Library;
|
||||
using LibEveryFileExplorer.GFX;
|
||||
using Toolbox.Library.IO;
|
||||
|
||||
namespace FirstPlugin.Forms
|
||||
{
|
||||
|
@ -34,9 +35,9 @@ namespace FirstPlugin.Forms
|
|||
private BitmapFont bitmapFont;
|
||||
|
||||
private FFNT ActiveFile;
|
||||
private BFFNT FileFormat;
|
||||
private BXFNT FileFormat;
|
||||
|
||||
public void LoadFontFile(BFFNT fontFile)
|
||||
public void LoadFontFile(BXFNT fontFile)
|
||||
{
|
||||
FileFormat = fontFile;
|
||||
ActiveFile = fontFile.bffnt;
|
||||
|
@ -129,18 +130,12 @@ namespace FirstPlugin.Forms
|
|||
bool IsBntx = ActiveFile.FontSection.TextureGlyph.BinaryTextureFile != null;
|
||||
|
||||
if (IsBntx)
|
||||
{
|
||||
PanelImage = image.GetBitmap(ImageIndex);
|
||||
}
|
||||
PanelImage = image.GetComponentBitmap(image.GetBitmap(ImageIndex));
|
||||
else
|
||||
{
|
||||
PanelImage = image.GetBitmap();
|
||||
}
|
||||
PanelImage = image.GetComponentBitmap(image.GetBitmap());
|
||||
|
||||
if (PanelImage != null)
|
||||
{
|
||||
if (PanelImage != null && ActiveFile.Platform >= FFNT.PlatformType.Cafe)
|
||||
PanelImage.RotateFlip(RotateFlipType.RotateNoneFlipY);
|
||||
}
|
||||
|
||||
FillCells();
|
||||
|
||||
|
@ -168,7 +163,8 @@ namespace FirstPlugin.Forms
|
|||
form.editorBase.Text = Text;
|
||||
form.editorBase.Dock = DockStyle.Fill;
|
||||
|
||||
image.Parameters.FlipY = true;
|
||||
if (ActiveFile.Platform >= FFNT.PlatformType.Cafe)
|
||||
image.Parameters.FlipY = true;
|
||||
|
||||
if (IsBntx)
|
||||
{
|
||||
|
@ -331,6 +327,8 @@ namespace FirstPlugin.Forms
|
|||
return;
|
||||
|
||||
Graphics graphics = e.Graphics;
|
||||
|
||||
graphics.Clear(Color.FromArgb(30,30,30));
|
||||
graphics.DrawImage(PanelImage, 0.0f, 0.0f);
|
||||
|
||||
if (ActiveFile == null)
|
45
File_Format_Library/GUI/BXFNT/CharacterSelector.Designer.cs
generated
Normal file
45
File_Format_Library/GUI/BXFNT/CharacterSelector.Designer.cs
generated
Normal file
|
@ -0,0 +1,45 @@
|
|||
namespace FirstPlugin.GUI.BFFNT
|
||||
{
|
||||
partial class CharacterSelector
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Component Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// CharacterSelector
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.Name = "CharacterSelector";
|
||||
this.Size = new System.Drawing.Size(483, 275);
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
20
File_Format_Library/GUI/BXFNT/CharacterSelector.cs
Normal file
20
File_Format_Library/GUI/BXFNT/CharacterSelector.cs
Normal file
|
@ -0,0 +1,20 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace FirstPlugin.GUI.BFFNT
|
||||
{
|
||||
public partial class CharacterSelector : UserControl
|
||||
{
|
||||
public CharacterSelector()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
120
File_Format_Library/GUI/BXFNT/CharacterSelector.resx
Normal file
120
File_Format_Library/GUI/BXFNT/CharacterSelector.resx
Normal file
|
@ -0,0 +1,120 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
|
@ -349,7 +349,7 @@ namespace FirstPlugin
|
|||
Formats.Add(typeof(BEA));
|
||||
Formats.Add(typeof(BYAML));
|
||||
Formats.Add(typeof(XTX));
|
||||
Formats.Add(typeof(BFFNT));
|
||||
Formats.Add(typeof(BXFNT));
|
||||
Formats.Add(typeof(MSBT));
|
||||
Formats.Add(typeof(BARS));
|
||||
Formats.Add(typeof(GFPAK));
|
||||
|
@ -451,8 +451,7 @@ namespace FirstPlugin
|
|||
Formats.Add(typeof(WTA));
|
||||
Formats.Add(typeof(BinGzArchive));
|
||||
Formats.Add(typeof(BNR));
|
||||
|
||||
|
||||
// Formats.Add(typeof(LayoutBXLYT.BLO));
|
||||
|
||||
// Formats.Add(typeof(MSBP));
|
||||
// Formats.Add(typeof(BFGRP));
|
||||
|
|
|
@ -730,6 +730,37 @@ namespace Toolbox.Library
|
|||
}
|
||||
}
|
||||
|
||||
public static Bitmap AdjustBrightness(Image image, float level)
|
||||
{
|
||||
ImageAttributes attributes = new ImageAttributes();
|
||||
|
||||
ColorMatrix cm = new ColorMatrix(new float[][]
|
||||
{
|
||||
new float[] { level, 0, 0, 0, 0},
|
||||
new float[] {0, level, 0, 0, 0},
|
||||
new float[] {0, 0, level, 0, 0},
|
||||
new float[] {0, 0, 0, 1, 0},
|
||||
new float[] {0, 0, 0, 0, 1},
|
||||
});
|
||||
attributes.SetColorMatrix(cm);
|
||||
|
||||
Point[] points =
|
||||
{
|
||||
new Point(0, 0),
|
||||
new Point(image.Width, 0),
|
||||
new Point(0, image.Height),
|
||||
};
|
||||
Rectangle rect = new Rectangle(0, 0, image.Width, image.Height);
|
||||
|
||||
Bitmap bm = new Bitmap(image.Width, image.Height);
|
||||
using (Graphics gr = Graphics.FromImage(bm))
|
||||
{
|
||||
gr.DrawImage(image, points, rect,
|
||||
GraphicsUnit.Pixel, attributes);
|
||||
}
|
||||
return bm;
|
||||
}
|
||||
|
||||
public static Bitmap AdjustGamma(Image image, float gamma)
|
||||
{
|
||||
ImageAttributes attributes = new ImageAttributes();
|
||||
|
|
|
@ -802,6 +802,29 @@ namespace Toolbox.Library
|
|||
return decodedData;
|
||||
}
|
||||
|
||||
public static byte[] DecodeC14X2(FileReader stream, uint width, uint height)
|
||||
{
|
||||
byte[] decodedData = new byte[width * height * 2];
|
||||
uint numBlocksW = width / 4; //4 pixel block width
|
||||
uint numBlocksH = height / 4; //4 pixel block height
|
||||
|
||||
for (int yBlock = 0; yBlock < numBlocksH; yBlock++) {
|
||||
for (int xBlock = 0; xBlock < numBlocksW; xBlock++) {
|
||||
for (int pY = 0; pY < 4; pY++) {
|
||||
for (int pX = 0; pX < 4; pX++)
|
||||
{
|
||||
if ((xBlock * 4 + pX >= width) || (yBlock * 4 + pY >= height))
|
||||
continue;
|
||||
|
||||
ushort value = stream.ReadUInt16();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return decodedData;
|
||||
}
|
||||
|
||||
private static byte[] DecodeRgb5A3(FileReader stream, uint width, uint height)
|
||||
{
|
||||
byte[] decodedData = new byte[width * height * 4];
|
||||
|
|
Loading…
Reference in a new issue