public static void SaveTo(Stream outputStream, PixelArtDocument document) { // パレットの生成 var itemPalette = new List <IMCItem>(); foreach (var item in document.Pixels) { if (itemPalette.Contains(item) == false) { itemPalette.Add(item); } } // ピクセル データのインデックス変換 var pixelValues = document.Pixels.Select(item => (short)itemPalette.IndexOf(item)).ToArray(); // 書き出し using (var binaryWriter = new BinaryWriter(outputStream)) { binaryWriter.Write(_fileMn); using (var propWriter = new PropWriter(outputStream)) { var metaSec = new PropSection("mcpixart-file-meta"); metaSec.Items.Add(new PropItem("magic-number", PropType.String, " MCPIXART ")); metaSec.Items.Add(new PropItem("file-description", PropType.String, " This is MC Pixel Art Navi Document File. Please visit our web site: https://www.a32kita.net/ ")); metaSec.Items.Add(new PropItem("file-version", PropType.Int64, 1L)); metaSec.Items.Add(new PropItem("created-at", PropType.DateTime, DateTime.Now)); var docSec = new PropSection("mcpixart-file-doc"); docSec.Items.Add(new PropItem("document-title", PropType.String, document.DocumentTitle)); docSec.Items.Add(new PropItem("document-author", PropType.String, document.DocumentAuthor)); docSec.Items.Add(new PropItem("document-description", PropType.String, document.DocumentDescription)); docSec.Items.Add(new PropItem("art-size", PropType.Int16, (short)document.Size)); docSec.Items.Add(new PropItem("art-palette", PropType.StringArray, itemPalette.Select(item => item.ItemId).ToArray())); docSec.Items.Add(new PropItem("art-pixels", PropType.Int16Array, pixelValues)); propWriter.Write(new Props(new PropSection[] { metaSec, docSec })); } } }
// 公開メソッド /// <summary> /// /// </summary> /// <param name="document">マップアート データ</param> /// <param name="stream">このオプションは使用されません。</param> /// <param name="baseDirectory">出力先ディレクトリ</param> /// <returns></returns> public override async Task <ExportResult> ExportAsync(PixelArtDocument document, Stream stream, string baseDirectory) { if (baseDirectory == null) { throw new ArgumentNullException(nameof(baseDirectory)); } if (File.Exists(baseDirectory) || Directory.Exists(baseDirectory)) { throw new ArgumentException(nameof(baseDirectory)); } var baseName = Path.GetFileName(baseDirectory); var utf8nEnc = new UTF8Encoding(false); Directory.CreateDirectory(baseDirectory); using (var swPackMeta = new StreamWriter(Path.Combine(baseDirectory, "pack.mcmeta"), false, utf8nEnc)) { swPackMeta.WriteLine("{"); swPackMeta.WriteLine(" \"pack\": {"); swPackMeta.WriteLine(" \"pack_format\": 1,"); swPackMeta.WriteLine(" \"description\": \"datapack\""); swPackMeta.WriteLine(" }"); swPackMeta.WriteLine("}"); } var dataDirPath = Path.Combine(baseDirectory, "data"); Directory.CreateDirectory(dataDirPath); var packDirPath = Path.Combine(dataDirPath, baseName); Directory.CreateDirectory(packDirPath); var functionsDir = Path.Combine(packDirPath, "functions"); Directory.CreateDirectory(functionsDir); var mcFunctionFilePath = Path.Combine(functionsDir, baseName + ".mcfunction"); var sw = new StreamWriter(mcFunctionFilePath, false, utf8nEnc); IMCItem currentItem = document.Pixels[0]; var currentItemStartPositionX = 0; var currentItemStartPositionZ = 0; for (var row = 0; row < document.Size.GetHeight(); row++) { for (var col = 0; col < document.Size.GetWidth(); col++) { var nextItemNum = (row * document.Size.GetWidth()) + col; var nextItem = document.Pixels[nextItemNum]; if (currentItem != nextItem) { if (col == 0) { // 左端の場合 → 先に変更 currentItem = nextItem; } // コマンドの出力 await this._writeFillCommand(sw, currentItemStartPositionX, currentItemStartPositionZ, col, row, currentItem.ItemId); // currentItem の変更 currentItem = nextItem; currentItemStartPositionX = col + 1; } } // コマンドの出力 await this._writeFillCommand(sw, currentItemStartPositionX, currentItemStartPositionZ, document.Size.GetWidth(), row, currentItem.ItemId); currentItemStartPositionX = 0; currentItemStartPositionZ = row + 1; } await sw.FlushAsync(); return(new ExportResult()); }
/// <summary> /// /// </summary> /// <param name="document">マップアート データ</param> /// <param name="stream">書き込み先ファイルのストリーム</param> /// <param name="baseDirectory">このオプションは使用されません</param> /// <returns></returns> public override async Task <ExportResult> ExportAsync(PixelArtDocument document, Stream stream, string baseDirectory) { if (stream == null) { throw new ArgumentNullException(nameof(stream)); } var spreadsheetDocument = SpreadsheetDocument.Create(stream, SpreadsheetDocumentType.Workbook); var workbookPart = spreadsheetDocument.AddWorkbookPart(); workbookPart.Workbook = new Workbook(); var worksheetPart = workbookPart.AddNewPart <WorksheetPart>(); worksheetPart.Worksheet = new Worksheet( // SheetData よりも先に Columns が必要 new Columns(new Column() { // 列の幅など Min = 1u, Max = (uint)document.Size.GetWidth(), Width = 3, CustomWidth = true, }), new SheetData()); var sheets = spreadsheetDocument.WorkbookPart.Workbook.AppendChild <Sheets>(new Sheets()); var sheet = new Sheet() { Id = spreadsheetDocument.WorkbookPart.GetIdOfPart(worksheetPart), SheetId = 1, Name = "MCPixelArtNavi" }; sheets.Append(sheet); var sheetData = worksheetPart.Worksheet.GetFirstChild <SheetData>(); var stylesPart = workbookPart.AddNewPart <WorkbookStylesPart>(); // スタイル生成 :: アイテム塗りつぶしの生成 var enabledItems = MCItemUtils.EnabledItems.ToList(); var fillList = new List <Fill>(); // Fill[0]: デフォルト fill の追加 (頭に追加してデフォルト化) fillList.Add(new Fill() { // 固定値 PatternFill = new PatternFill() { PatternType = PatternValues.None } }); // Fill[1]: 予約枠を潰す fillList.Add(new Fill() { // 固定値 PatternFill = new PatternFill() { PatternType = PatternValues.Gray125 } }); // Fill[2 ~]: アイテムの色情報の Fill fillList.AddRange(enabledItems.Select(this._createFillFromMCItem)); // デフォルト fill を含む、すべての fill に対応する cellFormat の生成 var cellFormatList = fillList.Select((e, idx) => this._createCellFormatFromFill(idx)).ToList(); // デフォルト フォント (特に中身にこだわりはない) var font = new Font(new Color() { Theme = UInt32Value.FromUInt32(1U) }) { FontName = new FontName() { Val = StringValue.FromString("Arial") }, FontSize = new FontSize() { Val = DoubleValue.FromDouble(11d) }, FontFamilyNumbering = new FontFamilyNumbering() { Val = 2 }, FontCharSet = new FontCharSet() { Val = 128 }, FontScheme = new FontScheme() { Val = FontSchemeValues.Minor }, }; // デフォルト セル スタイル var cellStyle = new CellStyle() { Name = StringValue.FromString("Normal"), FormatId = 0, BuiltinId = 0, }; stylesPart.Stylesheet = new Stylesheet( new Fonts(font), new Fills(fillList), new Borders(new Border()), new CellFormats(cellFormatList), new CellStyles(cellStyle), new DifferentialFormats(), new TableStyles() { DefaultTableStyle = StringValue.FromString("TableStyleMedium9"), DefaultPivotStyle = StringValue.FromString("PivotStyleLight16"), }); // 行作成 var rows = new Row[document.Size.GetHeight()]; var p = 0; for (var i = 0; i < rows.Length; i++) { // 列作成 rows[i] = new Row() { RowIndex = new UInt32Value((uint)(i + 1)) }; for (var j = 0; j < document.Size.GetWidth(); j++, p++) { var cell = new Cell() { CellReference = this._toCellReference(j, i), CellValue = new CellValue(""), DataType = CellValues.String, StyleIndex = (uint)(enabledItems.IndexOf(document.Pixels[p]) + 2), }; rows[i].InsertAt(cell, j); } sheetData.Append(rows[i]); } workbookPart.Workbook.Save(); spreadsheetDocument.Close(); return(new ExportResult()); }
public abstract Task <ExportResult> ExportAsync(PixelArtDocument document, Stream stream, string baseDirectory);