/* * SettingsEx.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.Drawing.Drawing2D; using System.Drawing.Imaging; using System.Runtime.Serialization; using Boare.Lib.AppUtil; using Boare.Lib.Vsq; namespace LipSync { public delegate void CommandExecutedEventHandler( TimeTableType command_target, CommandType command_type ); [Serializable] public class SettingsEx : IDisposable, ICloneable { const double tpq_sec = 480000000.0; public TimeTableGroup m_group_vsq; //ok public List m_groups_character; //ok public TimeTableGroup m_group_another; //ok public TimeTableGroup m_group_plugin; //ok public int m_screenWidth = 512; //ok public int m_screenHeight = 384; //ok public float m_totalSec = 0.0f; //ok public Size m_movieSize; // = new Size( 512, 384 ); //ok public List m_plugins_config; //ok public string m_audioFile = ""; //ok [OptionalField] public Color CANVAS_BACKGROUND; // = Color.White; //ok [OptionalField] public float REPEAT_START; //ok [OptionalField] public float REPEAT_END; //ok [OptionalField] public List m_timesig_ex; [OptionalField] public List m_tempo; [OptionalField] public int m_base_tempo; [OptionalField] public uint m_dwRate = 30; [OptionalField] public uint m_dwScale = 1; [NonSerialized] private float m_fps_buffer = 30f; [NonSerialized] public PluginInfo[] m_plugins; [OptionalField] public List m_telop_ex2 = new List(); [OptionalField] public bool TelopListFolded = false; /// /// 描画順序で格納された描画物のリスト /// [NonSerialized] public List m_zorder = new List(); [OptionalField] public string VersionMarker = AppManager.VERSION;// "2.4.4"; public static event CommandExecutedEventHandler CommandExecuted; private static string _( string s ) { return Messaging.GetMessage( s ); } public void DrawTo( Graphics g, Size mSize, float now, bool is_transparent ) { DrawTo( g, mSize, now, is_transparent, "", 0 ); } public void DrawTo( Graphics g, Size mSize, float now, bool is_transparent, string mouth, int mouth_force_group_index ) { if ( mouth.Length == 0 ) { mouth_force_group_index = -1; } #if DEBUG //Common.DebugWriteLine( "SettingsEx+DrawTo(Graphics,Size,float,bool)" ); int chrpos = 10; #endif g.SmoothingMode = SmoothingMode.AntiAlias; g.InterpolationMode = InterpolationMode.HighQualityBicubic; if ( is_transparent ) { g.Clear( Color.Transparent ); } else { g.Clear( CANVAS_BACKGROUND ); } ColorMatrix cm = new ColorMatrix(); cm.Matrix00 = 1; cm.Matrix11 = 1; cm.Matrix22 = 1; cm.Matrix33 = 1f; cm.Matrix44 = 1; for ( int z = 0; z < m_zorder.Count; z++ ) { ZorderItemType type = m_zorder[z].Type; int index = m_zorder[z].Index; Bitmap tmp = null; PointF position = new PointF(); float scale = 1f; float alpha = 1f; float rotate = 0f; Size size = new Size(); if ( type == ZorderItemType.another ) { if ( !m_group_another[index].IsAviMode ) { if ( m_group_another[index].Image == null ) { continue; } int start_entry = m_group_another[index].Value; for ( int entry = start_entry; entry < m_group_another[index].Count; entry++ ) { if ( m_group_another[index][entry].begin <= now && now <= m_group_another[index][entry].end ) { m_group_another[index].Value = entry; tmp = m_group_another[index].Image; break; } } } else { tmp = m_group_another[index].GetImage( now ); } position = m_group_another[index].GetPosition( now ); size = m_group_another[index].ImageSize; scale = m_group_another[index].GetScale( now ); alpha = m_group_another[index].GetAlpha( now ); rotate = m_group_another[index].GetRotate( now ); } else if ( type == ZorderItemType.character ) { if ( m_groups_character[index].Character.Type == CharacterType.def ) { int[] draw; if ( mouth_force_group_index == index ) { draw = m_groups_character[index].GetDrawObjectIndex( now, mouth ); } else { draw = m_groups_character[index].GetDrawObjectIndex( now, "" ); } position = m_groups_character[index].GetPosition( now ); size = m_groups_character[index].Character.Size; scale = m_groups_character[index].GetScale( now ); float tscale = Math.Abs( scale ); if ( tscale == 0.0f ) { continue; } alpha = m_groups_character[index].GetAlpha( now ); if ( alpha <= 0.0f ) { continue; } rotate = m_groups_character[index].GetRotate( now ); #if DEBUG chrpos += 10; g.DrawString( "character: position=" + position + ", m_groups_character[group].Position=" + m_groups_character[index].Position, AppManager.Config.Font.GetFont(), Brushes.Black, new PointF( 0, chrpos ) ); #endif tmp = m_groups_character[index].Character.Face( draw ); } else { string[] draw = m_groups_character[index].GetDrawObjectNames( now ); int target_plugin = -1; for ( int i = 0; i < m_plugins_config.Count; i++ ) { if ( m_plugins_config[i].ID == m_groups_character[index].Character.PluginConfig.ID ) { target_plugin = i; break; } } if ( target_plugin >= 0 ) { string s = ""; bool first = true; for ( int i = 0; i < draw.Length; i++ ) { if ( first ) { s += draw[i]; first = false; } else { s += "\n" + draw[i]; } } m_plugins[target_plugin].Instance.Render( g, mSize, now, s, "" ); } continue; } } else if ( type == ZorderItemType.plugin ) { int start_entry = m_group_plugin[index].Value; for ( int entry = start_entry; entry < m_group_plugin[index].Count; entry++ ) { if ( m_group_plugin[index][entry].begin <= now && now <= m_group_plugin[index][entry].end ) { m_group_plugin[index].Value = entry; #if DEBUG chrpos += 10; g.DrawString( "plugin", AppManager.Config.Font.GetFont(), Brushes.Black, new PointF( 0, chrpos ) ); #endif tmp = new Bitmap( mSize.Width, mSize.Height ); TimeTableEntry tmptt = m_group_plugin[index][entry]; m_plugins[index].Instance.Apply( ref tmp, now, tmptt.begin, tmptt.end, ref tmptt.body ); m_group_plugin[index][entry] = tmptt; size = mSize; position = new PointF( 0f, 0f ); alpha = 1f; scale = 1f; rotate = 0f; break; } } } else { continue; } if ( tmp != null ) { float tscale = Math.Abs( scale ); if ( scale < 0 ) { tmp.RotateFlip( RotateFlipType.RotateNoneFlipX ); } if ( scale != 0.0f ) { g.ResetTransform(); float half_width = size.Width / 2f; float half_height = size.Height / 2f; g.TranslateTransform( position.X + half_width * tscale, position.Y + half_height * tscale ); if ( scale != 1f ) { g.ScaleTransform( tscale, tscale ); } InterpolationMode im = g.InterpolationMode; SmoothingMode sm = g.SmoothingMode; if ( scale == 1f && rotate == 0f ) { g.InterpolationMode = InterpolationMode.Default; g.SmoothingMode = SmoothingMode.Default; } if ( rotate != 0f ) { g.RotateTransform( rotate ); } if ( 0 < alpha && alpha < 1f ) { cm.Matrix33 = alpha; ImageAttributes ia = new ImageAttributes(); ia.SetColorMatrix( cm ); g.DrawImage( tmp, new PointF[]{ new PointF( -half_width, - half_height ), new PointF( half_width, -half_height ), new PointF( -half_width, half_height ) }, new RectangleF( 0f, 0f, size.Width, size.Height ), GraphicsUnit.Pixel, ia ); } else if ( alpha != 0f ) { g.DrawImage( tmp, -half_width, -half_height, (float)size.Width, (float)size.Height ); } g.InterpolationMode = im; g.SmoothingMode = sm; g.ResetTransform(); } } } //最後に字幕を入れる foreach ( Telop telop in m_telop_ex2 ) { if ( telop.Start <= now && now <= telop.End ) { float alpha = 1f; if ( telop.FadeIn ) { float diff = now - telop.Start; if ( 0f <= diff && diff <= telop.FadeInSpan ) { alpha = 1.0f / telop.FadeInSpan * diff; } } if ( telop.FadeOut ) { float diff = telop.End - now; if ( 0f <= diff && diff <= telop.FadeOutSpan ) { alpha = 1.0f / telop.FadeOutSpan * diff; } } PointF position = telop.GetPosition( now ); Size size = telop.ImageSize; float scale = telop.GetScale( now ); float talpha = telop.GetAlpha( now ); float rotate = telop.GetRotate( now ); g.ResetTransform(); if ( scale != 0.0f ) { g.TranslateTransform( position.X + size.Width / 2f * scale, position.Y + size.Height / 2f * scale ); if ( scale != 1f ) { g.ScaleTransform( scale, scale ); } if ( rotate != 0f ) { g.RotateTransform( rotate ); } g.DrawString( telop.Text, telop.Font, new SolidBrush( Color.FromArgb( (int)(talpha * alpha * 255), telop.Color ) ), (int)(-size.Width / 2), (int)(-size.Height / 2) ); g.ResetTransform(); } } } //} //return bmp; } /// /// Settingsからのコンバート /// /// public SettingsEx( Settings s ) { #if DEBUG Common.DebugWriteLine( "SettingsEx..ctor(Settings)" ); #endif m_group_vsq = (TimeTableGroup)s.m_group_vsq.Clone(); m_groups_character = new List(); for( int i = 0; i < s.m_groups_character.Count; i++ ){ m_groups_character.Add( (TimeTableGroup)s.m_groups_character[i].Clone() ); } m_group_another = (TimeTableGroup)s.m_group_another.Clone(); m_group_plugin = (TimeTableGroup)s.m_group_plugin.Clone(); m_screenWidth = s.m_screenWidth; m_screenHeight = s.m_screenHeight; m_totalSec = s.m_totalSec; m_movieSize = s.m_movieSize; m_plugins_config = new List(); for( int i = 0; i < s.m_plugins_config.Count; i++ ){ m_plugins_config.Add( s.m_plugins_config[i].Clone() ); } m_audioFile = s.m_audioFile; CANVAS_BACKGROUND = s.CANVAS_BACKGROUND; REPEAT_START = s.REPEAT_START; REPEAT_END = s.REPEAT_START; m_timesig_ex = new List(); for( int i = 0; i < s.m_timesig_ex.Count; i++ ){ if ( s.m_timesig_ex[i].Numerator == 0 || s.m_timesig_ex[i].Denominator == 0 ) { m_timesig_ex.Clear(); break; } m_timesig_ex.Add( (TimeSigTableEntry)s.m_timesig_ex[i].Clone() ); } m_tempo = new List(); for( int i = 0; i < s.m_tempo.Count; i++ ){ m_tempo.Add( (TempoTableEntry)s.m_tempo[i].Clone() ); } m_base_tempo = s.m_base_tempo; m_dwRate = s.m_dwRate; m_dwScale = s.m_dwScale; m_fps_buffer = m_dwRate / (float)m_dwScale; m_telop_ex2 = new List(); for ( int i = 0; i < s.m_telop_ex2.Count; i++ ) { m_telop_ex2.Add( (Telop)s.m_telop_ex2[i].Clone() ); } } public Telop this[int id] { get { foreach ( Telop item in m_telop_ex2 ) { if ( item.ID == id ) { return item; } } return null; } set { for ( int i = 0; i < m_telop_ex2.Count; i++ ) { if ( m_telop_ex2[i].ID == id ) { m_telop_ex2[i] = value; break; } } } } public float FrameRate { get { return m_fps_buffer; } } public uint DwRate { get { return m_dwRate; } set { m_dwRate = value; m_fps_buffer = (float)m_dwRate / (float)m_dwScale; } } public uint DwScale { get { return m_dwScale; } set { m_dwScale = value; m_fps_buffer = (float)m_dwRate / (float)m_dwScale; } } public object Clone() { SettingsEx res = new SettingsEx(); res.m_group_vsq = (TimeTableGroup)m_group_vsq.Clone(); res.m_groups_character = new List(); for ( int i = 0; i < m_groups_character.Count; i++ ) { res.m_groups_character.Add( (TimeTableGroup)m_groups_character[i].Clone() ); } res.m_group_another = (TimeTableGroup)m_group_another.Clone(); res.m_group_plugin = (TimeTableGroup)m_group_plugin.Clone(); //res.fps = fps; res.m_screenWidth = m_screenWidth; res.m_screenHeight = m_screenHeight; res.m_totalSec = m_totalSec; res.m_movieSize = m_movieSize; res.m_plugins_config = new List(); for ( int i = 0; i < m_plugins_config.Count; i++ ) { res.m_plugins_config.Add( m_plugins_config[i].Clone() ); } res.m_audioFile = m_audioFile; res.CANVAS_BACKGROUND = CANVAS_BACKGROUND; res.REPEAT_START = REPEAT_START; res.REPEAT_END = REPEAT_END; res.m_telop_ex2 = new List(); foreach ( Telop item in m_telop_ex2 ) { res.m_telop_ex2.Add( (Telop)item.Clone() ); } res.m_timesig_ex = new List(); for ( int i = 0; i < m_timesig_ex.Count; i++ ) { res.m_timesig_ex.Add( (TimeSigTableEntry)m_timesig_ex[i].Clone() ); } res.m_tempo = new List(); for ( int i = 0; i < m_tempo.Count; i++ ) { res.m_tempo.Add( (TempoTableEntry)m_tempo[i].Clone() ); } res.m_base_tempo = m_base_tempo; res.m_zorder = new List(); for ( int i = 0; i < m_zorder.Count; i++ ) { res.m_zorder.Add( (ZorderItem)m_zorder[i].Clone() ); } /*res.m_commands = new List(); for ( int i = 0; i < m_commands.Count; i++ ) { res.m_commands.Add( m_commands[i].Clone() ); } res.m_command_position = m_command_position;*/ res.DwRate = m_dwRate; res.DwScale = m_dwScale; return res; } public TimeTableGroup this[TimeTableType type, int group] { get { if ( type == TimeTableType.character ) { return m_groups_character[group]; } else { switch ( type ) { case TimeTableType.another: return m_group_another; case TimeTableType.plugin: return m_group_plugin; case TimeTableType.vsq: return m_group_vsq; default: return null; } } } set { if ( type == TimeTableType.character ) { m_groups_character[group] = value; } else { switch ( type ) { case TimeTableType.another: m_group_another = value; break; case TimeTableType.plugin: m_group_plugin = value; break; case TimeTableType.vsq: m_group_vsq = value; break; } } } } public SettingsEx() { m_zorder = new List(); m_group_vsq = new TimeTableGroup( _( "VSQ Tracks" ), -1, null ); m_groups_character = new List(); m_group_another = new TimeTableGroup( _( "Another images" ), -1, null ); m_group_plugin = new TimeTableGroup( _( "Plugin" ), -1, null ); m_telop_ex2 = new List(); m_screenWidth = 512; m_screenHeight = 384; m_totalSec = 0.0f; m_movieSize = new Size( 512, 384 ); m_plugins_config = new List(); m_audioFile = ""; CANVAS_BACKGROUND = Color.White; m_telop_ex2 = new List(); m_timesig_ex = new List(); m_tempo = new List(); m_base_tempo = 480000; m_dwRate = 30; m_dwScale = 1; m_fps_buffer = (float)m_dwRate / (float)m_dwScale; } [OnDeserializing] private void onDeserializing( StreamingContext sc ) { CANVAS_BACKGROUND = Color.White; m_telop_ex2 = new List(); REPEAT_START = 0f; REPEAT_END = -1f; m_dwRate = 0; m_dwScale = 0; } [OnDeserialized] private void onDeserialized( StreamingContext sc ) { #if DEBUG Common.DebugWriteLine( "SettingsEx.onDeserialized(StreamingContext)" ); Common.DebugWriteLine( " m_timesig_ex" ); #endif m_zorder = new List(); if ( m_timesig_ex == null ) { m_timesig_ex = new List(); } else { for ( int i = 0; i < m_timesig_ex.Count; i++ ) { #if DEBUG Common.DebugWriteLine( " " + m_timesig_ex[i].ToString() ); #endif if ( m_timesig_ex[i].Numerator == 0 || m_timesig_ex[i].Denominator == 0 ) { m_timesig_ex.Clear(); break; } } } if( m_tempo == null ) { m_tempo = new List(); } if ( m_dwRate == 0 ) { m_dwScale = 1; m_dwRate = 30; } m_fps_buffer = (float)m_dwRate / (float)m_dwScale; #if DEBUG Common.DebugWriteLine( " m_telop_ex2" ); for ( int i = 0; i < m_telop_ex2.Count; i++ ) { Common.DebugWriteLine( " i=" + i + "; ID=" + m_telop_ex2[i].ID + "; Text=" + m_telop_ex2[i].Text ); } #endif } public void Dispose() { if ( m_group_vsq != null ) { m_group_vsq.Dispose(); m_group_vsq = null; } if ( m_groups_character != null ) { m_groups_character.Clear(); m_groups_character = null; } if ( m_group_another != null ) { m_group_another.Dispose(); m_group_another = null; } if ( m_group_plugin != null ) { m_group_plugin.Dispose(); m_group_plugin = null; } if ( m_plugins_config != null ) { m_plugins_config.Clear(); m_plugins_config = null; } } /// /// m_telop_ex用。次に利用可能なIDを調べます /// /// public int GetNextID() { return GetNextID( 0 ); } public int GetNextID( int skip ) { int draft = -1; while ( true ) { draft++; bool found = false; foreach ( Telop item in m_telop_ex2 ) { if ( draft == item.ID ) { found = true; } } if ( !found ) { break; } } return draft + skip; } public void SetZorder( ZorderItem item, int zorder ) { switch ( item.Type ) { case ZorderItemType.plugin: m_group_plugin[item.Index].ZOrder = zorder; break; case ZorderItemType.another: m_group_another[item.Index].ZOrder = zorder; break; case ZorderItemType.character: m_groups_character[item.Index].ZOrder = zorder; break; } } public int GetZorder( ZorderItem item ) { switch ( item.Type ) { case ZorderItemType.plugin: return m_group_plugin[item.Index].ZOrder; case ZorderItemType.another: return m_group_another[item.Index].ZOrder; case ZorderItemType.character: return m_groups_character[item.Index].ZOrder; } return 0; } public void UpdateZorder() { m_zorder.Clear(); for ( int i = 0; i < m_plugins_config.Count; i++ ) { m_zorder.Add( new ZorderItem( m_plugins_config[i].ID, ZorderItemType.plugin, i ) ); } for ( int i = 0; i < m_groups_character.Count; i++ ) { m_zorder.Add( new ZorderItem( m_groups_character[i].Text, ZorderItemType.character, i ) ); } for ( int i = 0; i < m_group_another.Count; i++ ) { m_zorder.Add( new ZorderItem( m_group_another[i].Text, ZorderItemType.another, i ) ); } bool changed = true; ZorderItem tmp; while ( changed ) { changed = false; for ( int i = 0; i < m_zorder.Count - 1; i++ ) { int order_i = GetZorder( m_zorder[i] ); int order_ipp = GetZorder( m_zorder[i + 1] ); if ( order_i < order_ipp || (order_i == order_ipp && m_zorder[i + 1].Type.CompareTo( m_zorder[i].Type ) > 0) ) { tmp = (ZorderItem)m_zorder[i].Clone(); m_zorder[i] = (ZorderItem)m_zorder[i + 1].Clone(); m_zorder[i + 1] = (ZorderItem)tmp.Clone(); changed = true; } } } for ( int i = 0; i < m_zorder.Count; i++ ) { SetZorder( m_zorder[i], m_zorder.Count - 1 - i ); } } /// /// 指定されたコマンドを実行します /// /// public Command Execute( Command command ) { int group = command.group; int track = command.track; int entry = command.entry; TimeTableType target = command.target; Command ret = null; switch ( command.target ) { case TimeTableType.telop: #region telop switch ( command.type ) { case CommandType.addTelop: Telop adding = (Telop)command.telop.Clone( GetNextID() ); ret = Command.GCommandDeleteTelop( adding ); m_telop_ex2.Add( adding ); break; case CommandType.editTelop: ret = Command.GCommandEditTelop( command.telop.ID, this[command.telop.ID] ); this[command.telop.ID] = (Telop)command.telop.Clone(); break; case CommandType.deleteTelop: ret = Command.GCommandAddTelop( this[command.telop.ID] ); for ( int i = 0; i < m_telop_ex2.Count; i++ ) { if ( m_telop_ex2[i].ID == command.telop.ID ) { m_telop_ex2.RemoveAt( i ); break; } } Property.Instance.Editing = null; //dirty... break; case CommandType.shiftTimeTable: ret = Command.GCommandShiftTimeTable( target, -1, -command.floatValue ); for ( int i = 0; i < m_telop_ex2.Count; i++ ) { m_telop_ex2[i].Start += command.floatValue; m_telop_ex2[i].End += command.floatValue; } break; case CommandType.addTelopRange: Telop[] adding2 = (Telop[])command.args[0]; for ( int i = 0; i < adding2.Length; i++ ) { adding2[i] = (Telop)adding2[i].Clone( GetNextID( i ) ); } ret = Command.GCommandDeleteTelopRange( adding2 ); m_telop_ex2.AddRange( adding2 ); break; case CommandType.deleteTelopRange: Telop[] adding3 = (Telop[])command.args[0]; ret = Command.GCommandAddTelopRange( adding3 ); for ( int i = 0; i < adding3.Length; i++ ) { for ( int j = 0; j < m_telop_ex2.Count; j++ ) { if ( m_telop_ex2[j].ID == adding3[i].ID ) { m_telop_ex2.RemoveAt( j ); break; } } } break; } Telop.DecideLane( m_telop_ex2 ); #endregion break; case TimeTableType.another: #region another switch ( command.type ) { case CommandType.addEntry: ret = Command.GCommandDeleteTimeTableEntry( target, -1, track, command.item ); m_group_another[track].Add( (TimeTableEntry)command.item.Clone() ); m_group_another[track].Sort(); break; case CommandType.deleteEntry: ret = Command.GCommandAddTimeTableEntry( target, -1, track, command.item ); m_group_another[track].Remove( command.item ); break; case CommandType.editEntry: ret = Command.GCommandEditTimeTableEntry( target, -1, track, entry, m_group_another[track][entry] ); m_group_another[track][entry] = (TimeTableEntry)command.item.Clone(); break; case CommandType.addTimeTable: ret = Command.GCommandDeleteTimeTable( target, -1, m_group_another.Count ); m_group_another.Insert( command.track, (TimeTable)command.table.Clone() ); UpdateZorder(); break; case CommandType.deleteTimeTable: ret = Command.GCommandAddTimeTable( target, -1, track, m_group_another[track] ); m_group_another.RemoveAt( command.track ); UpdateZorder(); break; case CommandType.editTimeTable: ret = Command.GCommandEditTimeTable( target, -1, track, m_group_another[track] ); m_group_another[command.track].Clear(); m_group_another[command.track] = (TimeTable)command.table.Clone(); break; case CommandType.setImage: if ( m_group_another[track].IsAviMode ) { ret = Command.GCommandSetAvi( track, m_group_another[track].AviConfig ); } else { ret = Command.GCommandSetImage( track, m_group_another[track].Image ); } m_group_another[command.track].SetImage( command.image ); break; case CommandType.setPosition: ret = Command.GCommandSetPosition( target, -1, track, m_group_another[track].Position ); m_group_another[command.track].Position = command.position; break; case CommandType.changeScale: ret = Command.GCommandChangeScale( target, -1, track, m_group_another[track].Scale ); m_group_another[command.track].Scale = command.floatValue; break; case CommandType.editGroup: ret = Command.GCommandEditGroup( target, -1, m_group_another ); m_group_another = null; m_group_another = (TimeTableGroup)command.tablegroup.Clone(); break; case CommandType.setAvi: if ( m_group_another[track].IsAviMode ) { ret = Command.GCommandSetAvi( track, m_group_another[track].AviConfig ); } else { ret = Command.GCommandSetImage( track, m_group_another[track].Image ); } m_group_another[command.track].SetAvi( command.str ); break; case CommandType.shiftTimeTable: ret = Command.GCommandShiftTimeTable( target, track, -command.floatValue ); for ( int i = 0; i < m_group_another[track].Count; i++ ) { m_group_another[track][i].begin += command.floatValue; m_group_another[track][i].end += command.floatValue; } break; } #endregion break; case TimeTableType.character: #region character switch ( command.type ) { case CommandType.addEntry: ret = Command.GCommandDeleteTimeTableEntry( target, group, track, command.item ); m_groups_character[group][track].Add( (TimeTableEntry)command.item.Clone() ); m_groups_character[group][track].Sort(); break; case CommandType.deleteEntry: ret = Command.GCommandAddTimeTableEntry( target, group, track, command.item ); m_groups_character[group][track].Remove( command.item ); break; case CommandType.editEntry: ret = Command.GCommandEditTimeTableEntry( target, group, track, entry, m_groups_character[group][track][entry] ); m_groups_character[group][track][entry] = (TimeTableEntry)command.item.Clone(); break; case CommandType.addTimeTable: ret = Command.GCommandDeleteTimeTable( target, group, m_groups_character[group].Count ); m_groups_character[group].Insert( command.track, (TimeTable)command.table.Clone() ); UpdateZorder(); break; case CommandType.deleteTimeTable: ret = Command.GCommandAddTimeTable( target, group, track, m_groups_character[group][track] ); m_groups_character[group].RemoveAt( command.track ); UpdateZorder(); break; case CommandType.editTimeTable: ret = Command.GCommandEditTimeTable( target, group, track, m_groups_character[group][track] ); m_groups_character[command.group][command.track].Clear(); m_groups_character[command.group][command.track] = (TimeTable)command.table.Clone(); break; case CommandType.addGroup: ret = Command.GCommandDeleteTimeTableGroup( target, m_groups_character.Count ); m_groups_character.Insert( command.group, (TimeTableGroup)command.tablegroup.Clone() ); UpdateZorder(); break; case CommandType.deleteGroup: ret = Command.GCommandAddGroup( target, group, m_groups_character[group] ); m_groups_character.RemoveAt( command.group ); Property.Instance.Editing = null; UpdateZorder(); break; case CommandType.editGroup: ret = Command.GCommandEditGroup( target, group, m_groups_character[group] ); m_groups_character[command.group].Dispose(); m_groups_character[command.group] = (TimeTableGroup)command.tablegroup.Clone(); break; case CommandType.setPosition: ret = Command.GCommandSetPosition( target, group, track, m_groups_character[group].Position ); m_groups_character[command.group].Position = command.position; break; case CommandType.changeScale: ret = Command.GCommandChangeScale( target, group, -1, m_groups_character[group].Scale ); m_groups_character[command.group].Scale = command.floatValue; break; case CommandType.shiftTimeTable: ret = Command.GCommandShiftTimeTable( target, group, -command.floatValue ); for ( int i = 0; i < m_groups_character[group].Count; i++ ) { for ( int j = 0; j < m_groups_character[group][i].Count; j++ ) { m_groups_character[group][i][j].begin += command.floatValue; m_groups_character[group][i][j].end += command.floatValue; } } break; } #endregion break; case TimeTableType.plugin: #region plugin switch ( command.type ) { case CommandType.addEntry: ret = Command.GCommandDeleteTimeTableEntry( target, -1, track, command.item ); m_group_plugin[track].Add( (TimeTableEntry)command.item.Clone() ); m_group_plugin[track].Sort(); break; case CommandType.deleteEntry: ret = Command.GCommandAddTimeTableEntry( target, -1, track, command.item ); m_group_plugin[track].Remove( command.item ); break; case CommandType.editEntry: ret = Command.GCommandEditTimeTableEntry( target, -1, track, entry, m_group_plugin[track][entry] ); m_group_plugin[track][entry] = (TimeTableEntry)command.item.Clone(); break; case CommandType.addTimeTable: ret = Command.GCommandDeleteTimeTable( target, -1, m_group_plugin.Count ); m_group_plugin.Insert( command.track, (TimeTable)command.table.Clone() ); UpdateZorder(); break; case CommandType.deleteTimeTable: ret = Command.GCommandAddTimeTable( target, -1, track, m_group_plugin[track] ); m_group_plugin.RemoveAt( command.track ); UpdateZorder(); break; case CommandType.editTimeTable: ret = Command.GCommandEditTimeTable( target, -1, track, m_group_plugin[track] ); m_group_plugin[command.track].Clear(); m_group_plugin[command.track] = (TimeTable)command.table.Clone(); break; case CommandType.editGroup: ret = Command.GCommandEditGroup( target, -1, m_group_plugin ); m_group_plugin = null; m_group_plugin = (TimeTableGroup)command.tablegroup.Clone(); break; case CommandType.shiftTimeTable: ret = Command.GCommandShiftTimeTable( target, track, -command.floatValue ); for ( int i = 0; i < m_group_plugin[track].Count; i++ ) { m_group_plugin[track][i].begin += command.floatValue; m_group_plugin[track][i].end += command.floatValue; } break; } #endregion break; case TimeTableType.vsq: #region vsq switch ( command.type ) { case CommandType.addEntry: ret = Command.GCommandDeleteTimeTableEntry( target, -1, track, command.item ); m_group_vsq[track].Add( (TimeTableEntry)command.item.Clone() ); m_group_vsq[track].Sort(); break; case CommandType.deleteEntry: ret = Command.GCommandAddTimeTableEntry( target, -1, track, command.item ); m_group_vsq[track].Remove( command.item ); break; case CommandType.editEntry: ret = Command.GCommandEditTimeTableEntry( target, -1, track, entry, m_group_vsq[track][entry] ); m_group_vsq[track][entry] = (TimeTableEntry)command.item.Clone(); break; case CommandType.addTimeTable: ret = Command.GCommandDeleteTimeTable( target, -1, m_group_vsq.Count ); m_group_vsq.Insert( command.track, (TimeTable)command.table.Clone() ); break; case CommandType.deleteTimeTable: ret = Command.GCommandAddTimeTable( target, -1, track, m_group_vsq[track] ); m_group_vsq.RemoveAt( command.track ); break; case CommandType.editTimeTable: ret = Command.GCommandEditTimeTable( target, -1, track, m_group_vsq[track] ); m_group_vsq[command.track].Clear(); m_group_vsq[command.track] = (TimeTable)command.table.Clone(); break; case CommandType.editGroup: ret = Command.GCommandEditGroup( target, -1, m_group_vsq ); m_group_vsq = null; m_group_vsq = (TimeTableGroup)command.tablegroup.Clone(); break; case CommandType.shiftTimeTable: ret = Command.GCommandShiftTimeTable( target, track, -command.floatValue ); for ( int i = 0; i < m_group_vsq[track].Count; i++ ) { m_group_vsq[track][i].begin += command.floatValue; m_group_vsq[track][i].end += command.floatValue; } break; } #endregion break; case TimeTableType.whole: #region whole switch ( command.type ) { case CommandType.changePluginConfig: ret = Command.GCommandChangePluginConfig( track, m_plugins_config[track].Config ); m_plugins_config[command.track].Config = command.str; // キャラクタ描画用プラグインの場合は、該当キャラクタトラックのグループ番号に応じて、command.group(>=0)に値がセットされる if ( command.group >= 0 ) { m_groups_character[command.group].Character.PluginConfig.Config = command.str; } m_plugins[command.track].Instance.Config = command.str; break; case CommandType.changeFps: ret = Command.GCommandChangeFps( m_dwRate, m_dwScale ); DwRate = command.dwRate; DwScale = command.dwScale; break; case CommandType.changeVideoSize: ret = Command.GCommandChangeVideoSize( m_movieSize ); m_movieSize = command.size; break; case CommandType.shiftTimeTable: ret = Command.GCommandShiftTimeTable( TimeTableType.whole, -1, -command.floatValue ); float shift = command.floatValue; // vsq shiftTimeTable( ref m_group_vsq, shift ); // character for ( int i = 0; i < m_groups_character.Count; i++ ) { TimeTableGroup tmp = m_groups_character[i]; shiftTimeTable( ref tmp, shift ); m_groups_character[i] = tmp; } // another shiftTimeTable( ref m_group_another, shift ); // plugin shiftTimeTable( ref m_group_plugin, shift ); // telop for ( int i = 0; i < m_telop_ex2.Count; i++ ) { m_telop_ex2[i].Start += shift; m_telop_ex2[i].End += shift; } break; case CommandType.setMP3: ret = Command.GCommandSetMp3( m_audioFile ); m_audioFile = command.str; break; case CommandType.changeBackgroundColor: ret = Command.GCommandChangeBackgroundColor( CANVAS_BACKGROUND ); CANVAS_BACKGROUND = command.color; break; } #endregion break; } if ( command.child != null ) { ret.child = Execute( command.child ); } if ( CommandExecuted != null ) { CommandExecuted( command.target, command.type ); } return ret; } private void shiftTimeTable( ref TimeTableGroup table, float shift ) { for ( int track = 0; track < table.Count; track++ ) { for ( int entry = 0; entry < table[track].Count; entry++ ) { table[track][entry].begin += shift; table[track][entry].end += shift; } } } public IEnumerable GetZorderItemEnumerator() { for( int i = 0; i < m_groups_character.Count; i++ ) { yield return new ZorderItem( m_groups_character[i].Text, ZorderItemType.character, i ); } for( int i = 0; i < m_group_another.Count; i++ ) { yield return new ZorderItem( m_group_another[i].Text, ZorderItemType.another, i ); } for( int i = 0; i < m_telop_ex2.Count; i++ ) { yield return new ZorderItem( m_telop_ex2[i].Text, ZorderItemType.telop, m_telop_ex2[i].ID ); } } public IEnumerable GetBarLineTypeEnumerator( QuantizeMode mode, bool triplet ) { int local_denominator; int local_numerator; int local_clock; int local_bar_count; int clock_step; int end_clock; int clock_per_bar; for( int i = 0; i < m_timesig_ex.Count; i++ ) { local_denominator = m_timesig_ex[i].Denominator; local_numerator = m_timesig_ex[i].Numerator; local_clock = m_timesig_ex[i].Clock; local_bar_count = m_timesig_ex[i].BarCount; clock_per_bar = 480 * 4 * local_numerator / local_denominator; clock_step = 480 * 4 / local_denominator; switch( mode ) { case QuantizeMode.off: clock_step = 480 * 4 / local_denominator; break; case QuantizeMode.q04: clock_step = 480 * 4 / 4; break; case QuantizeMode.q08: clock_step = 480 * 4 / 8; break; case QuantizeMode.q16: clock_step = 480 * 4 / 16; break; case QuantizeMode.q32: clock_step = 480 * 4 / 32; break; case QuantizeMode.q64: clock_step = 480 * 4 / 64; break; } if ( mode != QuantizeMode.off && triplet ) { clock_step = clock_step * 4 / 3; } if( i == m_timesig_ex.Count - 1 ) { double tempo; if( m_tempo.Count > 0 ) { tempo = m_tempo[m_tempo.Count - 1].Tempo; } else { tempo = m_base_tempo; } end_clock = (int)((m_totalSec - SecFromClock( m_timesig_ex[i].Clock ) + 1.0) * tpq_sec / tempo); } else { end_clock = m_timesig_ex[i + 1].Clock; } // todo: SettingsEx+GetBarLineTypeEnumerator; clock_per_barがclock_stepの整数倍とならない場合の処理 for( int clock = local_clock; clock < end_clock; clock += clock_step ) { if( (clock - local_clock) % clock_per_bar == 0 ) { yield return new BarLineType( SecFromClock( clock ), true, false ); } else { yield return new BarLineType( SecFromClock( clock ), false, false ); } } } } /// /// 指定したクロックにおける、clock=0からの演奏経過時間(sec) /// /// /// private double SecFromClock( int clock ) { if( m_tempo.Count == 0 ) { return (double)m_base_tempo * (double)clock / tpq_sec; } else { int index = 0; for( int i = 0; i < m_tempo.Count; i++ ) { if( clock <= m_tempo[i].Clock ) { index = i; break; } } return m_tempo[index].Time + (double)(m_tempo[index].Tempo) * (clock - m_tempo[index].Clock) / tpq_sec; } } } }