/* * TimeTable.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.ComponentModel; using System.Drawing; using System.IO; using System.Runtime.Serialization; using CurveEditor; namespace LipSync { [Serializable] public class TimeTable : IDisposable, ICloneable, IDrawObject { private List list; private string stringValue; private int type; [Obsolete] private Image image; private Point position; private int intValue; private int m_zOrder; private float scale; [OptionalField] public BezierChain mc_x; [OptionalField] public BezierChain mc_y; [OptionalField] public BezierChain mc_scale; [OptionalField] public BezierChain mc_alpha; [OptionalField] public BezierChain mc_rotate; /// /// aviをはっつけるモード /// [OptionalField] private bool m_avi_mode = false; [OptionalField] private string m_avi_config = ""; [NonSerialized] private AviReaderEx m_avi_reader; [NonSerialized] private bool m_avi_reader_opened = false; [OptionalField] private bool m_position_fixed = false; [OptionalField] private Bitmap m_image; /// /// aviファイルのOpen時に許される失敗回数 /// const int THRESHOLD_FAILED = 10; public bool IsXFixedAt( float time ) { float min, max; if ( mc_x.GetKeyMinMax( out min, out max ) ) { if ( min <= time && time <= max ) { return true; } } return false; } public bool IsYFixedAt( float time ) { float min, max; if ( mc_y.GetKeyMinMax( out min, out max ) ) { if ( min <= time && time <= max ) { return true; } } return false; } /// /// 描画オブジェクトの位置が固定されるかどうかを示す値を取得,または設定します /// public bool PositionFixed { get { return m_position_fixed; } set { m_position_fixed = value; } } [Browsable(false)] public Size ImageSize { get { if ( m_avi_mode ) { if ( m_avi_reader.Opened ) { return m_avi_reader.BitmapSize; } } else { if ( m_image != null ) { return m_image.Size; } } return new Size(); } } public string GetAviPath() { if ( !m_avi_mode ) { return ""; } else { string[] spl = m_avi_config.Split( "\n".ToCharArray(), StringSplitOptions.RemoveEmptyEntries ); if ( spl.Length > 0 ) { return spl[0]; } else { return ""; } } } [Browsable(false)] public string AviConfig { get { return m_avi_config; } } [Browsable(false)] public bool IsAviMode { get { return m_avi_mode; } } public void SetAvi( string avi_config ) { m_avi_mode = true; m_avi_config = avi_config; string avi_file = GetAviPath(); /*if ( m_bmp != null ) { m_bmp = null; //.Dispose(); }*/ if ( m_avi_reader != null ) { if ( m_avi_reader.Opened ) { m_avi_reader.Close(); m_avi_reader = null; m_avi_reader = new AviReaderEx(); } } else { m_avi_reader = new AviReaderEx(); } if ( m_avi_reader.NumFailed < THRESHOLD_FAILED ) { if ( File.Exists( avi_file ) ) { m_avi_reader.Open( avi_file ); m_avi_reader_opened = true; #if DEBUG Common.DebugWriteLine( "TimeTable.SetAvi; avi_file exists" ); #endif } } } public void SetImage( Image img ) { /*if ( m_bmp != null ) { //m_bmp.Dispose(); m_bmp = null; }*/ #if DEBUG Common.DebugWriteLine( "TimeTable.SetImage; before clone from argument \"img\"" ); try { int i = image.Width; } catch { } #endif if ( img != null ) { m_image = new Bitmap( img ); } #if DEBUG Common.DebugWriteLine( "TimeTable.SetImage; after cloned from argument \"img\"" ); try { int i = image.Width; } catch { } #endif m_avi_mode = false; if ( m_avi_reader_opened ) { if ( m_avi_reader.Opened ) { m_avi_reader.Close(); } m_avi_reader_opened = false; } } public Bitmap GetImage( float time ) { #if DEBUG Common.DebugWriteLine( "TimeTable.GetImage(float); m_avi_mode=" + m_avi_mode ); #endif if ( m_avi_mode ) { #if DEBUG Common.DebugWriteLine( "TimeTable.GetImage(float); m_avi_reader_opened=" + m_avi_reader_opened ); #endif if ( !m_avi_reader_opened ) { if ( m_avi_reader == null ) { m_avi_reader = new AviReaderEx(); } if ( File.Exists( GetAviPath() ) ) { try { m_avi_reader.Open( GetAviPath() ); m_avi_reader_opened = m_avi_reader.Opened; } catch { } } } if ( m_avi_reader_opened ) { bool found = false; float dt = 0f; for ( int i = 0; i < list.Count; i++ ) { if ( list[i].begin <= time && time <= list[i].end ) { dt = time - list[i].begin; found = true; break; } } #if DEBUG Common.DebugWriteLine( "TimeTable.GetImage(float); found=" + found ); #endif if ( found ) { int frame = (int)((double)m_avi_reader.dwRate / (double)m_avi_reader.dwScale * dt); if ( 0 <= frame && frame < m_avi_reader.CountFrames ) { return m_avi_reader.Export( frame ); } } } return null; } else { if ( m_image != null ) { return m_image; } else { return null; } } } public PointF GetPosition( float time ) { return new PointF( mc_x.GetValue( time ), mc_y.GetValue( time ) ); } public float GetScale( float time ) { return mc_scale.GetValue( time ); } public float GetAlpha( float time ) { float a = mc_alpha.GetValue( time ); if ( a > 1f ) { a = 1f; } else if ( a < 0f ) { a = 0f; } return a; } public float GetRotate( float time ) { float r = mc_rotate.GetValue( time ); if ( r > 360f ) { r = r % 360f; } else if ( r < 0f ) { r = r % 360f + 360f; } return r; } [OnDeserialized] private void onDeserialized( StreamingContext sc ) { if ( type == 3 ) { type = (int)TimeTableType.character; } if ( mc_x == null ) { mc_x = new BezierChain( Common.CURVE_X ); mc_x.Default = position.X; } if ( mc_y == null ) { mc_y = new BezierChain( Common.CURVE_Y ); mc_y.Default = position.Y; } if ( mc_scale == null ) { mc_scale = new BezierChain( Common.CURVE_SCALE ); mc_scale.Default = scale; } if ( mc_alpha == null ) { mc_alpha = new BezierChain( Common.CURVE_ALPHA ); mc_alpha.Default = 1.0f; } if ( mc_rotate == null ) { mc_rotate = new BezierChain( Common.CURVE_ROTATE ); } mc_x.Color = Common.CURVE_X; mc_y.Color = Common.CURVE_Y; mc_scale.Color = Common.CURVE_SCALE; mc_alpha.Color = Common.CURVE_ALPHA; if ( image != null ) { m_image = new Bitmap( image ); image.Dispose(); } } public float Scale { get { return mc_scale.Default; } set { mc_scale.Default = value; } } /// /// 時刻nowにOnとなっているエントリが存在するかどうかを判定します /// /// /// public bool IsOn( float now ) { foreach ( TimeTableEntry entry in list ) { if ( entry.begin <= now && now <= entry.end ) { return true; } } return false; } public void Dispose() { if ( list != null ) { list.Clear(); } if ( image != null ) { image.Dispose(); } if ( m_image != null ) { m_image.Dispose(); } if ( mc_x != null ) { mc_x.Dispose(); } if ( mc_y != null ) { mc_y.Dispose(); } if ( mc_alpha != null ) { mc_alpha.Dispose(); } if ( mc_rotate != null ) { mc_rotate.Dispose(); } if ( mc_scale != null ) { mc_scale.Dispose(); } if ( m_avi_reader != null ) { if ( m_avi_reader.Opened ) { m_avi_reader.Close(); } } } public void Remove( TimeTableEntry item ) { int index = -1; for ( int i = 0; i < list.Count; i++ ) { if ( list[i].begin == item.begin && list[i].end == item.end && list[i].body == item.body ) { index = i; break; } } if ( index >= 0 ) { list.RemoveAt( index ); } } public object Clone() { TimeTable tmp = new TimeTable( stringValue, intValue, this.Type, m_image ); for ( int i = 0; i < list.Count; i++ ) { tmp.list.Add( (TimeTableEntry)list[i].Clone() ); } tmp.position = position; tmp.intValue = intValue; tmp.m_zOrder = m_zOrder; tmp.scale = scale; tmp.mc_alpha = (BezierChain)this.mc_alpha.Clone(); tmp.mc_rotate = (BezierChain)this.mc_rotate.Clone(); tmp.mc_scale = (BezierChain)this.mc_scale.Clone(); tmp.mc_x = (BezierChain)this.mc_x.Clone(); tmp.mc_y = (BezierChain)this.mc_y.Clone(); tmp.m_avi_config = this.m_avi_config; tmp.m_avi_mode = this.m_avi_mode; tmp.m_avi_reader = new AviReaderEx(); tmp.m_avi_reader_opened = false; tmp.m_position_fixed = this.m_position_fixed; return tmp; } [Browsable(false)] public TimeTableType Type { get { foreach ( TimeTableType t in Enum.GetValues( System.Type.GetType( "LipSync.TimeTableType" ) ) ) { if ( (int)t == type ) { return t; } } return TimeTableType.none; } set { type = (int)value; } } public void Sort() { list.Sort(); } public void RemoveAt( int entry ) { list.RemoveAt( entry ); } public TimeTable( string stringValue, int intValue, TimeTableType type, Bitmap image ) : this( stringValue, intValue, type, image, 1f ) { } public TimeTable( string stringValue, int intValue, TimeTableType type, Bitmap img, float scale ) { this.list = new List(); this.stringValue = stringValue; this.type = (int)type; if ( img != null ) { m_image =(Bitmap)img.Clone(); } else { m_image = null; } this.intValue = intValue; this.position = new Point( 0, 0 ); this.scale = scale; this.m_zOrder = 0; mc_x = new BezierChain( Common.CURVE_X ); mc_y = new BezierChain( Common.CURVE_Y ); mc_scale = new BezierChain( Common.CURVE_SCALE ); mc_scale.Default = 1f; mc_alpha = new BezierChain( Common.CURVE_ALPHA ); mc_alpha.Default = 1f; mc_rotate = new BezierChain( Common.CURVE_ROTATE ); m_avi_reader = new AviReaderEx(); m_avi_reader_opened = false; } [Browsable(false)] public int ZOrder { get { return m_zOrder; } set { m_zOrder = value; } } [Browsable(false)] public int Value { get { return intValue; } set { intValue = value; } } public string Text { get { return stringValue; } set { stringValue = value; } } [Browsable(false)] public Bitmap Image { get { return m_image; } } [Browsable(false)] public int Count { get { return list.Count; } } public void Clear() { list.Clear(); } [Browsable(false)] public TimeTableEntry this[int entry] { get { return list[entry]; } set { list[entry] = (TimeTableEntry)value; } } public void Add( TimeTableEntry entry ) { list.Add( entry ); } [Browsable(false)] public Point Position { get { return new Point( (int)mc_x.Default, (int)mc_y.Default ); } set { mc_x.Default = value.X; mc_y.Default = value.Y; } } public Position Location { get { return new Position( mc_x.Default, mc_y.Default ); } set { mc_x.Default = value.X; mc_y.Default = value.Y; } } } }