mirror of
https://git.femboyfinancial.jp/james/lipsync.git
synced 2024-11-25 03:52:02 -08:00
509 lines
20 KiB
C#
509 lines
20 KiB
C#
|
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 = "MS ゴシック";
|
|||
|
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( "MS ゴシック", 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;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
}
|