mirror of
https://git.femboyfinancial.jp/james/lipsync.git
synced 2024-12-01 22:11:59 -08:00
693 lines
41 KiB
C#
693 lines
41 KiB
C#
/*
|
||
* RspImporter.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;
|
||
using System.Collections.Generic;
|
||
using System.Drawing;
|
||
using System.IO;
|
||
using System.Web;
|
||
using System.Xml;
|
||
|
||
using Boare.Lib.AppUtil;
|
||
|
||
namespace LipSync {
|
||
|
||
class RspTriggerEvent : IComparable{
|
||
public float time;
|
||
public string triggerName;
|
||
public RspTriggerStatus status;
|
||
public RspTriggerEvent( float time, string triggerName, string status ){
|
||
this.time = time;
|
||
this.triggerName = triggerName.Trim();
|
||
if( status.Trim() == "ON" ){
|
||
this.status = RspTriggerStatus.ON;
|
||
}else{
|
||
this.status = RspTriggerStatus.OFF;
|
||
}
|
||
}
|
||
public int CompareTo( object obj ) {
|
||
RspTriggerEvent item = (RspTriggerEvent)obj;
|
||
if ( this.time > item.time ) {
|
||
return 1;
|
||
} else if ( this.time < item.time ) {
|
||
return -1;
|
||
} else {
|
||
if ( this.status == RspTriggerStatus.OFF && item.status == RspTriggerStatus.ON ) {
|
||
return -1;
|
||
} else if ( this.status == RspTriggerStatus.ON && item.status == RspTriggerStatus.OFF ) {
|
||
return 1;
|
||
}
|
||
return 0;
|
||
}
|
||
}
|
||
new public string ToString() {
|
||
return time.ToString() + "," + triggerName + "," + status.ToString();
|
||
}
|
||
}
|
||
|
||
enum RspTriggerStatus{
|
||
ON,
|
||
OFF,
|
||
}
|
||
|
||
public class RspImporter {
|
||
|
||
private static XmlDocument doc;
|
||
|
||
private static TimeTableGroup group_vsq;
|
||
private static List<TimeTableGroup> groups_character;
|
||
private static TimeTableGroup group_another;
|
||
private static List<Telop> telop = new List<Telop>();
|
||
private static float optional_length;
|
||
private static int width;
|
||
private static int height;
|
||
private static int back_color;
|
||
private static string sound_file;
|
||
|
||
public static string gettext( string s ) {
|
||
return Messaging.GetMessage( s );
|
||
}
|
||
|
||
|
||
public static string _( string s ) {
|
||
return gettext( s );
|
||
}
|
||
|
||
|
||
public static bool Import( string filepath, ref SettingsEx save ) {
|
||
string rsp_path = Path.GetDirectoryName( filepath );
|
||
|
||
doc = new XmlDocument();
|
||
doc.Load( filepath );
|
||
|
||
group_vsq = new TimeTableGroup( _( "VSQ Tracks" ), 0, null );
|
||
groups_character = new List<TimeTableGroup>();
|
||
group_another = new TimeTableGroup( _( "Another images" ), 0, null );
|
||
|
||
// 最初にtotal_lengthを取得
|
||
foreach( XmlNode level1 in doc.DocumentElement.ChildNodes ){
|
||
if( level1.LocalName == "View" ){
|
||
optional_length = -1f;
|
||
foreach ( XmlNode level2 in level1.ChildNodes ) {
|
||
if ( level2.LocalName == "OptionalLength" ) {
|
||
optional_length = float.Parse( level2.InnerText );
|
||
break;
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
|
||
foreach ( XmlNode level1 in doc.DocumentElement.ChildNodes ) {
|
||
switch ( level1.LocalName ) {
|
||
case "Canvas":
|
||
#region Canvas
|
||
width = 100;
|
||
height = 100;
|
||
back_color = -1;
|
||
foreach ( XmlNode level2 in level1.ChildNodes ) {
|
||
switch ( level2.LocalName ) {
|
||
case "Width":
|
||
width = int.Parse( level2.InnerText );
|
||
break;
|
||
|
||
case "Height":
|
||
height = int.Parse( level2.InnerText );
|
||
break;
|
||
|
||
case "BackColor":
|
||
back_color = int.Parse( level2.InnerText );
|
||
break;
|
||
}
|
||
}
|
||
#endregion
|
||
break;
|
||
case "Sound":
|
||
#region Sound
|
||
sound_file = "";
|
||
foreach ( XmlNode level2 in level1.ChildNodes ) {
|
||
switch ( level2.LocalName ) {
|
||
case "FileName":
|
||
sound_file = level2.InnerText;
|
||
break;
|
||
}
|
||
}
|
||
#endregion
|
||
break;
|
||
case "TimeTable":
|
||
#region TimeTable
|
||
foreach ( XmlNode level2 in level1.ChildNodes ) {
|
||
if ( level2.LocalName == "Table" ) {
|
||
group_vsq.Add( new TimeTable( "", 0, TimeTableType.vsq, null ) );
|
||
int index = group_vsq.Count - 1;
|
||
foreach ( XmlNode level3 in level2.ChildNodes ) {
|
||
switch ( level3.LocalName ) {
|
||
case "Name":
|
||
group_vsq[index].Text = level3.InnerText;
|
||
break;
|
||
case "Unit":
|
||
float start = 0f;
|
||
float end = 0f;
|
||
string lyric = "";
|
||
string symbol = "";
|
||
foreach ( XmlNode level4 in level3.ChildNodes ) {
|
||
switch ( level4.LocalName ) {
|
||
case "Start":
|
||
start = float.Parse( level4.InnerText );
|
||
break;
|
||
case "End":
|
||
end = float.Parse( level4.InnerText );
|
||
break;
|
||
case "Text":
|
||
lyric = level4.InnerText;
|
||
break;
|
||
case "Symbol":
|
||
symbol = level4.InnerText;
|
||
break;
|
||
}
|
||
}
|
||
group_vsq[index].Add( new TimeTableEntry( start, end, lyric + "(" + symbol + ")" ) );
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
#endregion
|
||
break;
|
||
case "DrawObject":
|
||
#region DrawObject
|
||
foreach ( XmlNode level2 in level1.ChildNodes ) {
|
||
if ( level2.LocalName == "Object" ) {
|
||
// まずtypeを調べる
|
||
string type_name = "";
|
||
foreach ( XmlNode level3 in level2.ChildNodes ) {
|
||
if ( level3.LocalName == "TypeName" ) {
|
||
type_name = level3.InnerText;
|
||
break;
|
||
}
|
||
}
|
||
|
||
// typeで動作を切り替え
|
||
switch ( type_name ) {
|
||
case "RipSync.Plugins.Extensions.RipSyncImage.RipSyncImage":
|
||
#region RipSync.Plugins.Extensions.RipSyncImage.RipSyncImage
|
||
string source_table = "";
|
||
CharacterEx cex = new CharacterEx();
|
||
List<RspTriggerEvent> events = new List<RspTriggerEvent>();
|
||
groups_character.Add( new TimeTableGroup( "", 0, null ) );
|
||
int index = groups_character.Count - 1;
|
||
foreach ( XmlNode level3 in level2.ChildNodes ) {
|
||
switch( level3.LocalName ){
|
||
case "Name":
|
||
groups_character[index].Text = level3.InnerText;
|
||
break;
|
||
case "Parameter":
|
||
//MessageBox.Show( "Parameter node" );
|
||
foreach( XmlNode level4 in level3.ChildNodes ){
|
||
switch( level4.LocalName ){
|
||
case "FileName":
|
||
string rsi_path = Path.Combine( rsp_path, level4.InnerText );
|
||
cex = RsiReader.Read( rsi_path );
|
||
groups_character[index].Character = cex.character;
|
||
break;
|
||
case "Table":
|
||
source_table = level4.InnerText;
|
||
break;
|
||
case "Triggers":
|
||
foreach( XmlNode level5 in level4.ChildNodes ){
|
||
if ( level5.LocalName == "TriggerEvent" ) {
|
||
float time = 0f;
|
||
string trigger_name = "";
|
||
string status = "";
|
||
foreach ( XmlNode level6 in level5.ChildNodes ) {
|
||
switch ( level6.LocalName ) {
|
||
case "Time":
|
||
time = float.Parse( level6.InnerText );
|
||
break;
|
||
case "TriggerName":
|
||
trigger_name = level6.InnerText;
|
||
break;
|
||
case "Status":
|
||
status = level6.InnerText;
|
||
break;
|
||
}
|
||
}
|
||
events.Add( new RspTriggerEvent( time, trigger_name, status ) );
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
// source_tableから、口パクを作成
|
||
// group_vsqから、タイトルがsource_tableで或るやつを検索
|
||
int source = -1;
|
||
for ( int i = 0; i < group_vsq.Count; i++ ) {
|
||
if ( group_vsq[i].Text == source_table ) {
|
||
source = i;
|
||
break;
|
||
}
|
||
}
|
||
if ( source >= 0 ) {
|
||
// 口パク用のタイムテーブルが指定されていた場合
|
||
TimeTableGroup temp = (TimeTableGroup)groups_character[index].Clone();
|
||
TimeTableGroup.GenerateLipSyncFromVsq(
|
||
group_vsq[source],
|
||
ref temp,
|
||
groups_character[index].Character,
|
||
optional_length,
|
||
true,
|
||
save.FrameRate,
|
||
0f ); //todo: ここのoptional_lengthが怪しい
|
||
groups_character[index] = temp;
|
||
} else {
|
||
//口パク用タイムテーブルが指定されていなかった場合
|
||
// 画像分だけトラックを用意
|
||
/*groups_character[index].Add( new TimeTable( "base", 0, TimeTableType.eye, cex.character.Base ) );
|
||
groups_character[index].Add( new TimeTable( "a", 0, TimeTableType.mouth, cex.character.a ) );
|
||
groups_character[index].Add( new TimeTable( "aa", 0, TimeTableType.mouth, cex.character.aa ) );
|
||
groups_character[index].Add( new TimeTable( "i", 0, TimeTableType.mouth, cex.character.i ) );
|
||
groups_character[index].Add( new TimeTable( "u", 0, TimeTableType.mouth, cex.character.u ) );
|
||
groups_character[index].Add( new TimeTable( "e", 0, TimeTableType.mouth, cex.character.e ) );
|
||
groups_character[index].Add( new TimeTable( "o", 0, TimeTableType.mouth, cex.character.o ) );
|
||
groups_character[index].Add( new TimeTable( "xo", 0, TimeTableType.mouth, cex.character.xo ) );
|
||
groups_character[index].Add( new TimeTable( "nn", 0, TimeTableType.mouth, cex.character.nn ) );*/
|
||
for ( int k = 0; k < groups_character[index].Character.Count; k++ ) {
|
||
groups_character[index].Add( new TimeTable( groups_character[index].Character[k].title, 0, TimeTableType.character, null ) );
|
||
}
|
||
}
|
||
|
||
// triggerから、表情を追加。
|
||
// まず、排他も考慮して、OFFのイベントを追加
|
||
events.Sort();
|
||
//MessageBox.Show( "events.Cocunt=" + events.Count );
|
||
#region 排他を考慮して、OFFイベントを追加
|
||
int ii = -1;
|
||
while( (ii + 1) < events.Count ){
|
||
ii++;
|
||
//for ( int i = 0; i < events.Count; i++ ) {
|
||
string trigger_name = events[ii].triggerName;
|
||
//MessageBox.Show( "trigger_name=" + trigger_name );
|
||
float begin = events[ii].time;
|
||
float end = begin - 10f; // begin > endであれば-10じゃなくてもいい
|
||
// 排他に該当して無いかどうか検査
|
||
bool exclusion = isExclusionTrigger( cex, trigger_name );
|
||
bool defined = false; // 排他制御で、OFF位置が定義できたか否か
|
||
if ( exclusion ) {
|
||
// 排他制御をする必要がある場合
|
||
// 他の排他要素の中で、beginより後にONしていて、かつそれがもっとも早いものを検索
|
||
float first_begin = end;
|
||
//bool int_exclusion = false;
|
||
for ( int j = ii + 1; j < events.Count; j++ ) {
|
||
if ( isExclusionTrigger( cex, events[j].triggerName ) ) {
|
||
defined = true;
|
||
end = events[j].time;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
//MessageBox.Show( "defined=" + defined );
|
||
if ( !defined ) {
|
||
// この後で同じトリガが再びON指定になってたり、作為的にOFFにされて無いかどうかを検査
|
||
for ( int j = ii + 1; j < events.Count; j++ ) {
|
||
if ( events[j].triggerName == trigger_name ) {
|
||
end = events[j].time;
|
||
defined = true;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
if ( defined ) {
|
||
events.Add( new RspTriggerEvent( end, trigger_name, "OFF" ) );
|
||
events.Sort();
|
||
ii++; //++しないと∞ループだな
|
||
}
|
||
}
|
||
#endregion
|
||
|
||
for ( int i = 0; i < events.Count; i++ ) {
|
||
float begin, end;
|
||
if ( events[i].status == RspTriggerStatus.ON ){
|
||
// まず、開始と終了の時刻を設定
|
||
begin = events[i].time;
|
||
end = -1f;
|
||
if ( i + 1 < events.Count ) {
|
||
if ( events[i + 1].triggerName == events[i].triggerName && events[i + 1].status == RspTriggerStatus.OFF ) {
|
||
end = events[i + 1].time;
|
||
}
|
||
}
|
||
|
||
// どのタイムラインに追加するのかを決定
|
||
string trigger = events[i].triggerName;
|
||
int target = -1;
|
||
for ( int j = 0; j < groups_character[index].Count; j++ ) {
|
||
if ( groups_character[index][j].Text == trigger ) {
|
||
target = j;
|
||
break;
|
||
}
|
||
}
|
||
|
||
// 追加を実行
|
||
if ( target >= 0 ) {
|
||
groups_character[index][target].Add( new TimeTableEntry( begin, end, trigger ) );
|
||
}
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
break;
|
||
case "RipSync.Plugins.Extensions.SimpleImage.SimpleImage":
|
||
#region RipSync.Plugins.Extensions.SimpleImage.SimpleImage
|
||
string image_file = "";
|
||
string name = "";
|
||
foreach ( XmlNode level3 in level2.ChildNodes ) {
|
||
switch ( level3.LocalName ) {
|
||
case "Parameter":
|
||
foreach ( XmlNode level4 in level3.ChildNodes ) {
|
||
if ( level4.LocalName == "FileName" ) {
|
||
image_file = level3.InnerText;
|
||
break;
|
||
}
|
||
}
|
||
break;
|
||
case "Name":
|
||
name = level3.InnerText;
|
||
break;
|
||
}
|
||
}
|
||
|
||
image_file = HttpUtility.UrlDecode( image_file );
|
||
string file = Path.Combine( rsp_path, image_file );
|
||
if ( File.Exists( file ) ) {
|
||
Bitmap img = new Bitmap( Common.ImageFromFile( file ) );
|
||
group_another.Add( new TimeTable( name, 0, TimeTableType.another, img ) );
|
||
} else {
|
||
group_another.Add( new TimeTable( name, 0, TimeTableType.another, null ) );
|
||
}
|
||
|
||
#endregion
|
||
break;
|
||
case "RipSync.Plugins.Extensions.TextObject.TextObject":
|
||
#region RipSync.Plugins.Extensions.TextObject.TextObject
|
||
string tname = "";
|
||
string text = "";
|
||
Color color = Color.Black;
|
||
Font font = new Font( "MS UI Gothc", 10 );
|
||
foreach ( XmlNode level3 in level2.ChildNodes ) {
|
||
switch ( level3.LocalName ) {
|
||
case "Name":
|
||
tname = level3.InnerText;
|
||
break;
|
||
case "Parameter":
|
||
foreach ( XmlNode level4 in level3.ChildNodes ) {
|
||
switch ( level4.LocalName ) {
|
||
case "Text":
|
||
text = level4.InnerText;
|
||
break;
|
||
case "Color":
|
||
int col = int.Parse( level4.InnerText );
|
||
color = Color.FromArgb( col );
|
||
break;
|
||
case "Font":
|
||
string font_name = level4.InnerText;
|
||
//Microsoft Sans Serif, 12pt, style=Bold
|
||
string[] spl = font_name.Split( new string[] { ", " }, StringSplitOptions.RemoveEmptyEntries );
|
||
string font_family = spl[0];
|
||
string font_size = spl[1];
|
||
font_size = font_size.Replace( "pt", "" );
|
||
int em_size = int.Parse( font_size );
|
||
string font_style = "";
|
||
//style=Bold, Italic, Underline, Strikeout
|
||
FontStyle t_font_style = FontStyle.Regular;
|
||
if ( spl.Length >= 3 ) {
|
||
//spl[2]のみ、Style=がついてるのでそれをはずす
|
||
string[] spl2 = spl[2].Split( new string[] { "=" }, StringSplitOptions.RemoveEmptyEntries );
|
||
font_style = spl2[1];
|
||
}
|
||
for ( int ic = 3; ic < spl.Length; ic++ ) {
|
||
font_style += "," + spl[ic];
|
||
}
|
||
spl = font_style.Split( new string[] { "," }, StringSplitOptions.RemoveEmptyEntries );
|
||
foreach ( string style_name in spl ) {
|
||
switch ( style_name ) {
|
||
case "Bold":
|
||
t_font_style = t_font_style | FontStyle.Bold;
|
||
break;
|
||
case "Italic":
|
||
t_font_style = t_font_style | FontStyle.Italic;
|
||
break;
|
||
case "Underline":
|
||
t_font_style = t_font_style | FontStyle.Underline;
|
||
break;
|
||
case "Strikeout":
|
||
t_font_style = t_font_style | FontStyle.Strikeout;
|
||
break;
|
||
}
|
||
}
|
||
font = new Font( font_family, em_size, t_font_style );
|
||
break;
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
Telop temp_telop = new Telop( save.GetNextID() );
|
||
temp_telop.Text = text;
|
||
temp_telop.Color = color;
|
||
temp_telop.Font = font;
|
||
temp_telop.Tag = tname;
|
||
telop.Add( temp_telop );
|
||
#endregion
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
#endregion
|
||
break;
|
||
case "TimeLine":
|
||
#region TimeLine
|
||
foreach ( XmlNode level2 in level1.ChildNodes ) {
|
||
if ( level2.LocalName == "Unit" ) {
|
||
int zindex = 0;
|
||
float start = 0f;
|
||
float end = -10f;
|
||
int position_x = 0;
|
||
int position_y = 0;
|
||
float scale = 1f;
|
||
string draw_object = "";
|
||
bool fadein = false;
|
||
bool fadeout = false;
|
||
foreach ( XmlNode level3 in level2.ChildNodes ) {
|
||
switch ( level3.LocalName ) {
|
||
case "ZIndex":
|
||
zindex = int.Parse( level3.InnerText );
|
||
break;
|
||
case "Start":
|
||
start = float.Parse( level3.InnerText );
|
||
break;
|
||
case "End":
|
||
end = float.Parse( level3.InnerText );
|
||
break;
|
||
case "PositionX":
|
||
position_x = int.Parse( level3.InnerText );
|
||
break;
|
||
case "PositionY":
|
||
position_y = int.Parse( level3.InnerText );
|
||
break;
|
||
case "Scale":
|
||
scale = float.Parse( level3.InnerText );
|
||
break;
|
||
case "DrawObject":
|
||
draw_object = level3.InnerText;
|
||
break;
|
||
case "FadeIn":
|
||
if( level3.InnerText == "True" ){
|
||
fadein = true;
|
||
}
|
||
break;
|
||
case "FadeOut":
|
||
if( level3.InnerText == "True" ){
|
||
fadeout = true;
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
|
||
// 名前がdraw_objectであるトラック(orキャラクタ)を検索
|
||
// group_another
|
||
for ( int i = 0; i < group_another.Count; i++ ) {
|
||
if ( draw_object == group_another[i].Text ) {
|
||
group_another[i].ZOrder = zindex;
|
||
group_another[i].Clear();
|
||
group_another[i].Add( new TimeTableEntry( start, end, draw_object ) );
|
||
group_another[i].Position = new Point( position_x, position_y );
|
||
group_another[i].Scale = scale;
|
||
}
|
||
}
|
||
|
||
// group_character
|
||
for ( int i = 0; i < groups_character.Count; i++ ) {
|
||
if ( draw_object == groups_character[i].Text ) {
|
||
groups_character[i].ZOrder = zindex;
|
||
groups_character[i].Position = new Point( position_x, position_y );
|
||
}
|
||
}
|
||
|
||
// telop
|
||
for ( int i = 0; i < telop.Count; i++ ) {
|
||
if ( draw_object == (string)telop[i].Tag ) {
|
||
telop[i].Start = start;
|
||
telop[i].End = end;
|
||
telop[i].FadeIn = fadein;
|
||
telop[i].FadeOut = fadeout;
|
||
telop[i].Position = new Point( position_x, position_y );
|
||
if ( scale != 1 ) {
|
||
Font tnew = new Font( telop[i].Font.FontFamily, telop[i].Font.SizeInPoints * scale, telop[i].Font.Style );
|
||
telop[i].Font.Dispose();
|
||
telop[i].Font = null;
|
||
telop[i].Font = tnew;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
#endregion
|
||
break;
|
||
}
|
||
}
|
||
//MessageBox.Show( "tables=" + group_vsq.Count );
|
||
if ( optional_length < 0 ) {
|
||
float thismax = -1;
|
||
for ( int track = 0; track < group_vsq.Count; track++ ) {
|
||
int last = group_vsq[track].Count - 1;
|
||
if ( last >= 0 ) {
|
||
thismax = group_vsq[track][last].end;
|
||
optional_length = Math.Max( optional_length, thismax );
|
||
}
|
||
}
|
||
|
||
for ( int group = 0; group < groups_character.Count; group++ ) {
|
||
for ( int track = 0; track < groups_character[group].Count; track++ ) {
|
||
int last = groups_character[group][track].Count - 1;
|
||
if ( last >= 0 ) {
|
||
thismax = groups_character[group][track][last].end;
|
||
optional_length = Math.Max( optional_length, thismax );
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 時間が負になってる表情用エントリを整理
|
||
for ( int group = 0; group < groups_character.Count; group++ ) {
|
||
for ( int track = 0; track < groups_character[group].Count; track++ ) {
|
||
for( int entry = 0; entry < groups_character[group][track].Count; entry++ ){
|
||
if ( groups_character[group][track][entry].end < 0 ) {
|
||
groups_character[group][track][entry].end = optional_length;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
// 時間が負になっているその他のイメージのエントリを整理
|
||
for ( int track = 0; track < group_another.Count; track++ ) {
|
||
for ( int entry = 0; entry < group_another[track].Count; entry++ ) {
|
||
if ( group_another[track][entry].end < 0f ) {
|
||
group_another[track][entry].end = optional_length;
|
||
}
|
||
}
|
||
}
|
||
// 時間が負になっているテロップのエントリを整理
|
||
for ( int i = 0; i < telop.Count; i++ ) {
|
||
if ( telop[i].End < 0f ) {
|
||
telop[i].End = optional_length;
|
||
}
|
||
}
|
||
|
||
// base画像エントリの修正。genMouthFromVsqCore実行時にはoptional_length == 0なので、修正。
|
||
for ( int group = 0; group < groups_character.Count; group++ ) {
|
||
int index_base = -1;
|
||
for ( int track = 0; track < groups_character[group].Count; track++ ) {
|
||
if ( groups_character[group][track].Text == "base" ) {
|
||
index_base = track;
|
||
break;
|
||
}
|
||
}
|
||
if ( index_base >= 0 ) {
|
||
groups_character[group][index_base].Clear();
|
||
groups_character[group][index_base].Add( new TimeTableEntry( 0.0f, optional_length, "base" ) );
|
||
}
|
||
}
|
||
|
||
// zorderの数値がrip syncでは逆なので修正
|
||
// まずzorderの最大値を探す
|
||
int zmax = -100;
|
||
for ( int i = 0; i < group_another.Count; i++ ) {
|
||
zmax = Math.Max( zmax, group_another[i].ZOrder );
|
||
}
|
||
for ( int i = 0; i < groups_character.Count; i++ ) {
|
||
zmax = Math.Max( zmax, groups_character[i].ZOrder );
|
||
}
|
||
// 修正
|
||
for ( int i = 0; i < group_another.Count; i++ ) {
|
||
group_another[i].ZOrder = zmax - group_another[i].ZOrder;
|
||
}
|
||
for ( int i = 0; i < groups_character.Count; i++ ) {
|
||
groups_character[i].ZOrder = zmax - groups_character[i].ZOrder;
|
||
}
|
||
|
||
if ( optional_length > 0 ) {
|
||
save.m_totalSec = optional_length;
|
||
} else {
|
||
save.m_totalSec = 0;
|
||
}
|
||
save.m_group_vsq = (TimeTableGroup)group_vsq.Clone();
|
||
save.m_groups_character.Clear();
|
||
for ( int i = 0; i < groups_character.Count; i++ ) {
|
||
save.m_groups_character.Add( groups_character[i] );
|
||
}
|
||
save.m_group_another = (TimeTableGroup)group_another.Clone();
|
||
save.m_movieSize = new Size( width, height );
|
||
save.m_telop_ex2.Clear();
|
||
save.m_telop_ex2 = new List<Telop>();
|
||
for ( int i = 0; i < telop.Count; i++ ) {
|
||
save.m_telop_ex2.Add( telop[i] );
|
||
}
|
||
save.UpdateZorder();
|
||
save.m_audioFile = sound_file;
|
||
//s.InvertZOrder();
|
||
return true;
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 指定された名前のトリガーが、排他指定されているか否かを判定します
|
||
/// </summary>
|
||
/// <param name="cex">判定に使用されるCharacterEx</param>
|
||
/// <param name="name">検査するトリガーの名前</param>
|
||
/// <returns></returns>
|
||
private static bool isExclusionTrigger( CharacterEx cex, string name ) {
|
||
for ( int i = 0; i < cex.exclusion.Count; i++ ) {
|
||
if ( cex.exclusion[i] == name ) {
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
}
|
||
|
||
|
||
|
||
}
|