lipsync/LipSync/NicoComment/NicoComment.cs

509 lines
20 KiB
C#
Raw Permalink Normal View History

using System;
using System.Collections.Generic;
using System.Text;
using Plugin;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace NicoComment {
public class NicoComment : IPlugin{
private List<string> config = new List<string>();
private List<NComment> comments = new List<NComment>();
public void ApplyLanguage( string language_code ) {
}
public string Name {
get {
return "Nico Comment";
}
}
public ulong Type {
get {
return 0;
}
}
public string Abstract {
get {
return "ニコニコ動画ぽい字幕を、ニコニコ動画と同様なコマンドで追加できるプラグイン。";
}
}
public void Apply( ref Bitmap frame, float time, float e_begin, float e_end, ref string e_body ) {
using ( Graphics g = Graphics.FromImage( frame ) ) {
Rectangle rc = new Rectangle( 0, 0, frame.Width, frame.Height );
int skip_count_def = 0;
bool first_def = true;
bool first_shita = true;
bool first_ue = true;
int y_def = 0;
int y_shita = rc.Height;
int y_ue = 0;
for ( int i = 0; i < comments.Count; i++ ) {
if ( comments[i].time <= time && time < comments[i].time + 3.0 ) {
double t = time - comments[i].time;
int height = (int)comments[i].type.Size.Size;
if ( comments[i].type.Position == NComTypePosition.def ) {
if ( !first_def ) {
y_def += height;
if ( y_def > rc.Height ) {
y_def -= rc.Height;
skip_count_def++;
}
t += 0.1 * skip_count_def;
} else {
first_def = false;
}
if ( comments[i].y == NComment.NULL ) {
comments[i].y = y_def;
}
} else if ( comments[i].type.Position == NComTypePosition.shita ) {
if ( !first_shita ) {
y_shita -= (int)(1.1f * height);
if ( y_shita + height < 0 ) {
y_shita += rc.Height;
}
} else {
y_shita -= (int)(1.1f * height);
first_shita = false;
}
if ( comments[i].y == NComment.NULL ) {
comments[i].y = y_shita;
}
} else if ( comments[i].type.Position == NComTypePosition.ue ) {
if ( !first_ue ) {
y_ue += (int)(1.1f * height);
if ( y_ue > rc.Height ) {
y_ue += rc.Height;
}
} else {
first_ue = false;
}
if ( comments[i].y == NComment.NULL ) {
comments[i].y = y_ue;
}
}
NComment entry = comments[i];
drawString( g, entry, rc, t, comments.Count );
comments[i] = entry;
}
}
}
}
public string Config {
get {
string result = "";
if( config.Count > 0 ){
result = config[0];
}
for ( int i = 1; i < config.Count; i++ ) {
result += "\n" + config[i];
}
return result;
}
set {
List<string> work_config = new List<string>();
foreach ( string item in config ) {
work_config.Add( item );
}
config.Clear();
List<NComment> work_comments = new List<NComment>();
foreach ( NComment item in comments ) {
work_comments.Add( item );
}
comments.Clear();
//timing.Clear();
string[] result = value.Split( new char[] { '\n' } );
config.Add( result[0] );
for( int i = 1; i < result.Length; i++ ){
config.Add( result[i] );
string[] spl = result[i].Split( new char[] { '\t' } );
if ( spl.Length < 3 ) {
config.Clear();
foreach ( string item in work_config ) {
config.Add( item );
}
work_config.Clear();
comments.Clear();
foreach ( NComment item in work_comments ) {
comments.Add( item );
}
work_comments.Clear();
MessageBox.Show( "コメントにエラーがありました。エラーのあった行は次の通りです\n" + i + "行目\n" + result[i] );
return;
}
//timing.Add( double.Parse( spl[0] ) );
float time;
try {
time = float.Parse( spl[0] );
} catch {
config.Clear();
foreach ( string item in work_config ) {
config.Add( item );
}
work_config.Clear();
comments.Clear();
foreach ( NComment item in work_comments ) {
comments.Add( item );
}
work_comments.Clear();
MessageBox.Show( "コメントにエラーがありました。エラーのあった行は次の通りです\n" + i + "行目\n" + result[i] );
return;
}
comments.Add( new NComment( float.Parse( spl[0] ), spl[1], spl[2], i ) );
//MessageBox.Show( "Config::set; comments[i-1].type.Position.ToString()=" + comments[i - 1].type.Position.ToString() );
}
comments.Sort();
}
}
public DialogResult EntrySetting( ref string entry_config ) {
return DialogResult.Cancel;
}
public DialogResult BaseSetting() {
FConfig fconf = new FConfig( Config );
DialogResult result = fconf.ShowDialog();
if ( result == DialogResult.OK ) {
Config = fconf.ConfigString;
}
fconf.Dispose();
return result;
}
/// <summary>
/// comで指定されたコメント・タイプのニコニココメントを、
/// Graphics gの位置xに描画します。
/// </summary>
/// <param name="time">このコメントが表示され始めてからの経過時間</param>
/// <param name="g"></param>
/// <param name="com"></param>
/// <param name="x"></param>
public static void drawString( Graphics g, NComment com, Rectangle rc, double time, int comment_num ) {
const string font_name = " ゴシック";
Font font = new Font( font_name, com.type.Size.Size, FontStyle.Bold, GraphicsUnit.Pixel );
Color color = com.type.Color.Color;
int axy = com.type.Position.getPosition( rc.Height, com.type.Size.Size );
int x;
if ( com.type.Position == NComTypePosition.ue || com.type.Position == NComTypePosition.shita ) {
x = (int)(rc.Width / 2.0f - com.width / 2.0f);
} else {
x = (int)(rc.Width - time * ((com.width + rc.Width) / 3.0f));
}
GraphicsPath path = new GraphicsPath();
//FontFamily ff = new FontFamily( font_name );
FontFamily ff = font.FontFamily;
path.AddString( com.message, ff, (int)FontStyle.Bold, com.type.Size.Size, new Point( 0, 0 ), StringFormat.GenericDefault );
using ( Bitmap tmp = new Bitmap( com.width, com.height, PixelFormat.Format32bppArgb ) ) {
using ( Graphics gx = Graphics.FromImage( tmp ) ) {
gx.Clear( Color.FromArgb( 0, Color.White ) );
Color shadow;
if ( color != Color.Black ) {
shadow = Color.Black;
} else {
shadow = Color.White;
}
gx.DrawPath( new Pen( Color.FromArgb( 50, shadow ), 3.5f ), path );
gx.DrawPath( new Pen( Color.FromArgb( 180, shadow ), 2.5f ), path );
gx.FillPath( new SolidBrush( color ), path );
//gx.DrawString( com.message, font, new SolidBrush( color ), new PointF( 0, 0 ) );
}
float alpha = 0.6f + 0.4f * ((float)com.count / (float)comment_num);
ColorMatrix cm = new ColorMatrix();
cm.Matrix00 = 1;
cm.Matrix11 = 1;
cm.Matrix22 = 1;
cm.Matrix33 = alpha;
cm.Matrix44 = 1;
ImageAttributes ia = new ImageAttributes();
ia.SetColorMatrix( cm );
g.DrawImage( tmp, new Rectangle( x, com.y, tmp.Width, tmp.Height ),
0, 0, tmp.Width, tmp.Height, GraphicsUnit.Pixel, ia );
}
}
public void Render( Graphics g, Size size, float time, string mouth, string reserved ) {
}
}
public class NComment : IComparable {
public const int NULL = -999;
public float time;
public NComType type;
public string message;
public int width;
public int height;
public int count;
public int y;
public NComment( float time, string command, string message, int count ) {
this.time = time;
this.type = new NComType( command );
this.message = message;
this.count = count;
this.y = NULL;
SizeF sizef;
Bitmap dumy = new Bitmap( 1, 1 );
Font font = new Font( " ゴシック", this.type.Size.Size, FontStyle.Bold, GraphicsUnit.Pixel );
using ( Graphics g = Graphics.FromImage( dumy ) ) {
sizef = g.MeasureString( message, font );
}
this.width = (int)sizef.Width;
this.height = (int)sizef.Height;
dumy.Dispose();
font.Dispose();
}
public int CompareTo( object obj ) {
NComment com = (NComment)obj;
if ( this.time > com.time ) {
return 1;
} else if ( this.time < com.time ) {
return -1;
} else {
return 0;
}
}
}
public class NComType {
public NComTypePosition Position;
public NComTypeColor Color;
public NComTypeSize Size;
public NComType( string command ) {
Position = NComTypePosition.def;
Color = NComTypeColor.def;
Size = NComTypeSize.def;
string[] spl = command.Split( new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries );
for ( int i = spl.Length - 1; i >= 0; i-- ) {
NComTypePosition pos = NComTypePosition.fromCommand( spl[i] );
if ( pos != NComTypePosition.INVALID ) {
Position = pos;
continue;
}
NComTypeColor col = NComTypeColor.fromCommand( spl[i] );
if ( col != NComTypeColor.INVALID ) {
Color = col;
continue;
}
NComTypeSize size = NComTypeSize.fromCommand( spl[i] );
if ( size != NComTypeSize.INVALID ) {
Size = size;
continue;
}
}
}
}
public class NComTypePosition {
private int m_value;
public static NComTypePosition ue = new NComTypePosition( 0 );
public static NComTypePosition shita = new NComTypePosition( 1 );
public static NComTypePosition def = new NComTypePosition( 2 );
public static NComTypePosition INVALID = new NComTypePosition( -1 );
private NComTypePosition( int value ) {
m_value = value;
}
public static NComTypePosition fromCommand( string command ) {
switch ( command ) {
case "ue":
return ue;
case "shita":
return shita;
case "naka":
return def;
default:
return INVALID;
}
}
public int getPosition( float height, float fontsize ) {
switch ( m_value ) {
case 0:
return 0;
case 1:
return (int)(height - fontsize * 1.2f);
default:
return -1;
}
}
new public string ToString() {
switch ( m_value ) {
case 0:
return "ue";
case 1:
return "shita";
case 2:
return "def";
default:
return "INVALID";
}
}
}
public class NComTypeColor {
private int m_value;
public static NComTypeColor white = new NComTypeColor( 0 );
public static NComTypeColor def = new NComTypeColor( 0 );
public static NComTypeColor red = new NComTypeColor( 1 );
public static NComTypeColor pink = new NComTypeColor( 2 );
public static NComTypeColor orange = new NComTypeColor( 3 );
public static NComTypeColor yellow = new NComTypeColor( 4 );
public static NComTypeColor green = new NComTypeColor( 5 );
public static NComTypeColor cyan = new NComTypeColor( 6 );
public static NComTypeColor blue = new NComTypeColor( 7 );
public static NComTypeColor purple = new NComTypeColor( 8 );
public static NComTypeColor niconicowhite = new NComTypeColor( 9 );
public static NComTypeColor truered = new NComTypeColor( 10 );
public static NComTypeColor passionorange = new NComTypeColor( 11 );
public static NComTypeColor madyellow = new NComTypeColor( 12 );
public static NComTypeColor elementalgreen = new NComTypeColor( 13 );
public static NComTypeColor marineblue = new NComTypeColor( 14 );
public static NComTypeColor nobleviolet = new NComTypeColor( 15 );
public static NComTypeColor black = new NComTypeColor( 16 );
public static NComTypeColor INVALID = new NComTypeColor( -1 );
private NComTypeColor( int value ) {
m_value = value;
}
public static NComTypeColor fromCommand( string command ) {
switch ( command ) {
case "white":
return white;
case "red":
return red;
case "pink":
return pink;
case "orange":
return orange;
case "yellow":
return yellow;
case "green":
return green;
case "cyan":
return cyan;
case "blue":
return blue;
case "purple":
return purple;
case "niconicowhite":
case "white2":
return niconicowhite;
case "truered":
case "red2":
return truered;
case "passionorange":
case "orange2":
return passionorange;
case "madyellow":
case "yellow2":
return madyellow;
case "elementalgree":
case "green2":
return elementalgreen;
case "marineblue":
case "blue2":
return marineblue;
case "nobleviolet":
case "purple2":
return nobleviolet;
case "black":
return black;
default:
return INVALID;
}
}
public Color Color {
get {
switch ( m_value ) {
case 0:
return Color.White;
case 1:
return Color.Red;
case 2:
return Color.Pink;
case 3:
return Color.Orange;
case 4:
return Color.Yellow;
case 5:
return Color.FromArgb( 0, 255, 0 );
case 6:
return Color.Cyan;
case 7:
return Color.Blue;
case 8:
return Color.Purple;
case 9:
return Color.FromArgb( 204, 204, 153 );
case 10:
return Color.FromArgb( 204, 0, 51 );
case 11:
return Color.FromArgb( 255, 102, 0 );
case 12:
return Color.FromArgb( 153, 153, 0 );
case 13:
return Color.FromArgb( 0, 204, 102 );
case 14:
return Color.FromArgb( 51, 255, 252 );
case 15:
return Color.FromArgb( 102, 51, 204 );
case 16:
return Color.Black;
}
return Color.White;
}
}
}
public class NComTypeSize {
private int m_value;
public static NComTypeSize big = new NComTypeSize( 0 );
public static NComTypeSize medium = new NComTypeSize( 1 );
public static NComTypeSize small = new NComTypeSize( 2 );
public static NComTypeSize def = new NComTypeSize( 1 );
public static NComTypeSize INVALID = new NComTypeSize( -1 );
private NComTypeSize( int value ) {
m_value = value;
}
public static NComTypeSize fromCommand( string command ) {
switch ( command ) {
case "big":
return big;
case "medium":
return medium;
case "small":
return small;
default:
return INVALID;
}
}
public float Size {
get {
switch ( m_value ) {
case 0:
return 39f;
case 1:
return 24f;
case 2:
return 15f;
default:
return 24f;
}
}
}
}
}