lipsync/LipSync/NicoComment/NicoComment.cs
2024-05-20 00:17:44 +00:00

509 lines
20 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;
}
}
}
}
}