/* * RsiWriter.cs * Copyright (c) 2007-2009 kbinani * * This file is part of LipSync. * * LipSync is free software; you can redistribute it and/or * modify it under the terms of the BSD License. * * LipSync is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ using System.Collections.Generic; using System.IO; using System.Text; using System.Windows.Forms; using System.Xml; using Boare.Lib.AppUtil; namespace LipSync { public class RsiWriter { #region Constant String static readonly string[] mouth_set = new string[]{ "a", "aa", "i", "u", "e", "o", "xo", "nn" }; static readonly string[] mouth_set_ja = new string[]{ "あ", "ああ", "い", "う", "え", "お", "ぉ", "ん" }; // mouth_setと同順で対応して無いとNG static readonly string[] dict_text = new string[]{ "あ,a", "か,a", "が,a", "さ,a", "ざ,a", "た,a", "だ,a", "な,a", "は,a", "ば,a", "ぱ,a", "ま,a", "や,a", "ら,a", "わ,a", "い,i", "き,i", "ぎ,i", "し,i", "じ,i", "ち,i", "ぢ,i", "に,i", "ひ,i", "び,i", "ぴ,i", "み,i", "り,i", "う,u", "く,u", "ぐ,u", "す,u", "ず,u", "つ,u", "づ,u", "ぬ,u", "ふ,u", "ぶ,u", "む,u", "ゆ,u", "る,u", "え,e", "け,e", "げ,e", "せ,e", "ぜ,e", "て,e", "で,e", "ね,e", "へ,e", "べ,e", "め,e", "れ,e", "お,o", "こ,o", "ご,o", "そ,o", "ぞ,o", "と,o", "ど,o", "の,o", "ほ,o", "ぼ,o", "ぽ,o", "も,o", "よ,o", "ろ,o", "を,xo", "ん,nn" }; static readonly string[] dict_symbol = new string[]{ "a,a", "i,i", "M,u", "e,e", "o,o", "k,xo", "k',i", "g,e", "g',i", "s,a", "S,i", "z,u", "Z,i", "dz,u", "dZ,i", "t,e", "t',i", "ts,u", "tS,i", "d,a", "d',i", "n,a", "J,i", "h,a", @"h\,xo", "C,i", @"p\,u", @"p\',i", "b,o", "b',i", "p,o", "p',i", "m,a", "m',i", "j,u", "4,aa", "4',i", "w,a", @"N\,nn" }; #endregion public static string _( string s ) { return Messaging.GetMessage( s ); } /// /// a, aa, i, u, e, o, xo, nnを、あ・ああ・い・う・え・お・ぉ・んに変換します。それ以外は""を返す /// /// /// private static string Translate( string symbol ) { for ( int i = 0; i < mouth_set.Length; i++ ) { if ( mouth_set[i] == symbol ) { return mouth_set_ja[i]; } } return ""; } /// /// 与えられたタイトルの画像が口パク用の基本画像セットの物かどうかを判定します /// /// /// private static bool IsImageNameForMouth( string name ) { foreach ( string s in mouth_set ) { if ( s == name ) { return true; } } return false; } public static void Write( Character3 character, string fpath ) { string image_folder_name = Path.GetFileNameWithoutExtension( fpath ); string image_folder = Path.Combine( Path.GetDirectoryName( fpath ), image_folder_name ); if ( Directory.Exists( image_folder ) ) { DialogResult res = MessageBox.Show( _( "Image directory already exists. Would you like to overwrite them?" ), _( "warning" ), MessageBoxButtons.YesNoCancel, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button2 ); if ( res == DialogResult.No ) { using ( OpenFileDialog dlg = new OpenFileDialog() ) { dlg.FileName = Path.GetDirectoryName( fpath ); if ( dlg.ShowDialog() == DialogResult.OK ) { image_folder = dlg.FileName; image_folder_name = Path.GetFileName( image_folder ); } else { return; } } } else if ( res == DialogResult.Cancel ) { return; } } else { Directory.CreateDirectory( image_folder ); } #if DEBUG Common.DebugWriteLine( "image_folder_name=" + image_folder_name ); Common.DebugWriteLine( "image_folder=" + image_folder ); #endif XmlTextWriter doc = new XmlTextWriter( fpath, Encoding.UTF8 ); doc.Formatting = Formatting.Indented; doc.Indentation = 2; doc.IndentChar = ' '; // タグが未指定な物のgroup名を決めておく string group_name_for_empty = "Another"; bool found = true; int count = 0; while ( found ) { found = false; foreach ( ImageEntry img in character ) { if ( img.tag == group_name_for_empty ) { found = true; break; } } if ( found ) { count++; group_name_for_empty = "Another" + count; } } doc.WriteStartElement( "SingerConfig" ); { doc.WriteElementString( "Title", character.Name ); doc.WriteElementString( "Size", character.Size.Width + "," + character.Size.Height ); doc.WriteElementString( "RootImageName", "root" ); List sets = new List(); // root以下のsetのリスト #region "SingerConfig/Images" doc.WriteStartElement( "Images" ); { // トリガー込み foreach ( ImageEntry img in character ) { if ( IsImageNameForMouth( img.title ) ) { continue; } doc.WriteStartElement( "Image" ); { doc.WriteAttributeString( "center", (-img.XOffset) + ", " + (-img.YOffset) ); doc.WriteAttributeString( "name", img.title ); doc.WriteAttributeString( "size", img.Image.Width + ", " + img.Image.Height ); string img_fname = img.title + ".png"; img.Image.Save( Path.Combine( image_folder, img_fname ), System.Drawing.Imaging.ImageFormat.Png ); doc.WriteAttributeString( "path", image_folder_name + "/" + img_fname ); doc.WriteAttributeString( "trigger", img.title ); } doc.WriteEndElement(); } // 基本口画像。トリガー指定の無い奴も出力しないといけない?(未確認 foreach ( ImageEntry img in character ) { if ( !IsImageNameForMouth( img.title ) ) { continue; } // 自動用 doc.WriteStartElement( "Image" ); { doc.WriteAttributeString( "center", (-img.XOffset) + ", " + (-img.YOffset) ); doc.WriteAttributeString( "name", img.title ); doc.WriteAttributeString( "size", img.Image.Width + ", " + img.Image.Height ); string img_fname = img.title + ".png"; img.Image.Save( Path.Combine( image_folder, img_fname ), System.Drawing.Imaging.ImageFormat.Png ); doc.WriteAttributeString( "path", image_folder_name + "/" + "mouth_" + img_fname ); } doc.WriteEndElement(); // トリガー用 doc.WriteStartElement( "Image" ); { doc.WriteAttributeString( "center", (-img.XOffset) + ", " + (-img.YOffset) ); doc.WriteAttributeString( "name", "mouth_" + img.title ); doc.WriteAttributeString( "size", img.Image.Width + ", " + img.Image.Height ); string img_fname = "mouth_" + img.title + ".png"; img.Image.Save( Path.Combine( image_folder, img_fname ), System.Drawing.Imaging.ImageFormat.Png ); doc.WriteAttributeString( "path", image_folder_name + "/" + img_fname ); doc.WriteAttributeString( "trigger", Translate( img.title ) ); } doc.WriteEndElement(); } // root/mouth_auto_set doc.WriteStartElement( "Set" ); { doc.WriteAttributeString( "name", "mouth_auto_set" ); doc.WriteAttributeString( "size", character.Size.Width + "," + character.Size.Height ); doc.WriteAttributeString( "count", 1 + "" ); doc.WriteAttributeString( "trigger", "mouth_auto" ); doc.WriteStartElement( "Image" ); { doc.WriteAttributeString( "index", 0 + "" ); doc.WriteAttributeString( "imageName", "mouth" ); doc.WriteAttributeString( "offset", "0,0" ); } doc.WriteEndElement(); sets.Add( "mouth_auto" ); } doc.WriteEndElement(); // root/{tag}_manual List listed_tag = new List(); // 出力済みのタグのリスト bool added = true; while ( added ) { added = false; // 次に出力すべきタグを検索 string next_tag = ""; List print = new List(); foreach ( ImageEntry img in character ) { bool found2 = false; foreach ( string s in listed_tag ) { if ( s == img.tag ) { found2 = true; break; } } if ( !found2 ) { if ( img.tag == "" ) { next_tag = group_name_for_empty; } else { next_tag = img.tag; } break; } } if ( next_tag != "" ) { added = true; if ( next_tag == group_name_for_empty ) { listed_tag.Add( "" ); } else { listed_tag.Add( next_tag ); } foreach ( ImageEntry img in character ) { if ( img.tag == next_tag ) { print.Add( img.title ); } } foreach ( string s in print ) { // 本体画像が含まれてたらキャンセル if ( s == "base" ) { print.Clear(); break; } } if ( print.Count > 0 ) { doc.WriteStartElement( "Set" ); { doc.WriteAttributeString( "name", next_tag + "_manual_set" ); doc.WriteAttributeString( "trigger", next_tag + "_manual" ); sets.Add( next_tag + "_manual" ); doc.WriteAttributeString( "size", character.Size.Width + ", " + character.Size.Height ); doc.WriteAttributeString( "count", print.Count + "" ); for ( int i = 0; i < print.Count; i++ ) { doc.WriteStartElement( "Image" ); { doc.WriteAttributeString( "index", i + "" ); if ( IsImageNameForMouth( print[i] ) ) { doc.WriteAttributeString( "imageName", "mouth_" + print[i] ); } else { doc.WriteAttributeString( "imageName", print[i] ); } doc.WriteAttributeString( "offset", "0,0" ); } doc.WriteEndElement(); } } doc.WriteEndElement(); } } else { break; } } // root doc.WriteStartElement( "Set" ); { doc.WriteAttributeString( "name", "root" ); doc.WriteAttributeString( "size", character.Size.Width + ", " + character.Size.Height ); doc.WriteAttributeString( "count", (1 + sets.Count) + "" ); doc.WriteStartElement( "Image" ); { doc.WriteAttributeString( "index", 0 + "" ); doc.WriteAttributeString( "imageName", "base" ); doc.WriteAttributeString( "offset", "0,0" ); } doc.WriteEndElement(); for ( int i = 0; i < sets.Count; i++ ) { doc.WriteStartElement( "Image" ); { doc.WriteAttributeString( "index", (i + 1) + "" ); doc.WriteAttributeString( "imageName", sets[i] + "_set" ); doc.WriteAttributeString( "offset", "0,0" ); } doc.WriteEndElement(); } } doc.WriteEndElement(); } doc.WriteEndElement(); #endregion #region "SingerConfig/Triggers" doc.WriteStartElement( "Triggers" ); { foreach ( string s in sets ) { doc.WriteStartElement( "Trigger" ); { doc.WriteAttributeString( "group", s + "_control" ); doc.WriteAttributeString( "name", s ); if ( s == "mouth_auto" ) { doc.WriteAttributeString( "default", "on" ); } } doc.WriteEndElement(); } foreach ( ImageEntry img in character ) { if ( img.title == "base" ) { continue; } doc.WriteStartElement( "Trigger" ); { if ( img.tag == "" ) { doc.WriteAttributeString( "group", group_name_for_empty ); } else { doc.WriteAttributeString( "group", img.tag ); } if ( IsImageNameForMouth( img.title ) ) { doc.WriteAttributeString( "name", Translate( img.title ) ); } else { doc.WriteAttributeString( "name", img.title ); } } doc.WriteEndElement(); } Dictionary dic = new Dictionary(); foreach ( ImageEntry img in character ) { if ( img.tag == "" || img.title == "base" ) { continue; } if ( dic.ContainsKey( img.tag ) ) { dic[img.tag] = dic[img.tag] + "\n" + img.title; } else { dic[img.tag] = img.title; } } foreach ( string key in dic.Keys ) { string items = dic[key]; string[] spl = items.Split( "\n".ToCharArray() ); doc.WriteStartElement( "Selection" ); { foreach ( string s in spl ) { doc.WriteStartElement( "Item" ); { doc.WriteAttributeString( "Trigger", s ); } doc.WriteEndElement(); } } doc.WriteEndElement(); } } doc.WriteEndElement(); #endregion #region "SingerConfig/Mouths" doc.WriteStartElement( "Mouths" ); { doc.WriteStartElement( "Default" ); { doc.WriteAttributeString( "imageName", "nn" ); } doc.WriteEndElement(); foreach ( string s in dict_text ) { string[] spl = s.Split( ",".ToCharArray() ); doc.WriteStartElement( "Attach" ); { doc.WriteAttributeString( "text", spl[0] ); doc.WriteAttributeString( "imageName", spl[1] ); } doc.WriteEndElement(); } foreach ( string s in dict_symbol ) { string[] spl = s.Split( ",".ToCharArray() ); doc.WriteStartElement( "Attach" ); { doc.WriteAttributeString( "symbol", spl[0] ); doc.WriteAttributeString( "imageName", spl[1] ); } doc.WriteEndElement(); } } doc.WriteEndElement(); #endregion } doc.WriteEndElement(); doc.Close(); } } }