mirror of
https://git.femboyfinancial.jp/james/lipsync.git
synced 2024-11-28 21:11:59 -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;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
}
|