import processing.pdf.*; /* 時計盤を描画するProcessingスクリプト. ついでにストップウォッチ機能も書いてみた. by mieki256 ver. 0.0.5 2012/01/31 - FPSがおかしくなる不具合への対策。 - System.nanoTime()を使って測定するよう変更。 - 記録のファイル書き出しがバグってたので修正。 ver. 0.0.4 2012/01/30 - 時間をミリ秒で取得するように変更。 - 24/30コマを切り替える機能を追加。(@キー押し) - 表示用フレームレート変更機能を追加。(Pキー押し) ver. 0.0.3 2012/01/29 - 時計盤を事前に描画して高速化。 - ウインドウサイズを小さくして高速化。 ver. 0.0.2 2012/01/26 - LAP機能を追加。 ver. 0.0.1 2012/01/25 - とりあえず作成。 */ String verinfo = "Ver. 0.0.5"; // pdf出力の設定 // 0ならストップウォッチとして動く。 // 1にするとpdf出力して終了。 int pdf_out = 0; // pdf出力ファイル名 String pdf_name = "watch_base.pdf"; // フレームレート (24か30を指定可能) int fpsv = 24; // 表示用フレームレート int[] frate_list = { 24, 30, 48, 60 }; int frate_idx = 0; int disp_fps; // 記録保存用テキストファイル名 String log_filename = "_log.txt"; // 0なら用意済みのフォントデータを利用 // 1ならフォントデータ生成 int create_font_use = 1; // 使用フォント名 String[] font_name = { "Times New Roman Bold", "Times New Roman Bold", }; // フォントデータを事前準備してある場合のフォントファイル名 String[] font_file = { "DejaVuSerifCondensed-Bold-32.vlw", "mplus-1m-medium-14.vlw", }; // フォントサイズ int[] fsize = { 32, 14, }; // 0以外なら、環境で使えるフォント一覧を出力 int font_list_out = 0; // 0なら記録を描画しない(処理速度が遅い時は0にする) int lap_draw = 1; long[] lap = new long[1000]; // 時間記録用 int lapidx = 0; int frm = 0; // フレーム数記録用 boolean watching = false; // trueならカウントする int req = 0; String msg = ""; int msg_disp_cnt = 0; PGraphics pg; long starttime = 0; long totaltime = 0; boolean irq = false; // フォントの使用 PFont[] fnt; // ---------------------------------------- // 初期化処理 void setup() { // 画像サイズ指定 // 記録表示領域の幅は190ドット必要 size(510, 320, JAVA2D); // size(670, 480); // size(790, 600); // 使えるフォント一覧を出力 if (font_list_out != 0) { String[] fontList = PFont.list(); println(fontList); } // フォントのロード fnt = new PFont[font_name.length]; if (create_font_use != 0) { // 起動時に使用フォントデータを作成する例 for ( int i=0; i 0 ) { set_time(ntime, mode); } irq = false; } // 秒針の制御 void set_time(long ntime, int mode) { switch(mode) { case 0: break; case 1: // START/STOP切り替え要求 if ( watching ) { // 秒針が動いている totaltime += (ntime - starttime); watching = false; save_lap(totaltime); } else { // 秒針が止まっている start_watching(ntime); } break; case 2: // RESET要求 init_lap(); break; case 3: // 記録を要求 if ( watching ) { // 秒針が動いている save_lap(totaltime + (ntime - starttime)); } else { // 秒針が止まっている start_watching(ntime); } } } // 秒針を動かし始める void start_watching(long ntime) { starttime = ntime; watching = true; } // ナノ秒をフレーム数に変換 long conv_m2f(long ntime) { return int(fpsv * ntime / 1e+9); } // 時間記録初期化 void init_lap() { frm = 0; // フレームカウンタクリア watching = false; // 秒針を止める starttime = 0; totaltime = 0; lapidx = 0; for (int i=0; i height-28) ) { // 画面の右下をクリックされたなら mode = 2; // RESET } else if ( mouseButton == LEFT ) { // マウス左ボタンが押された mode = (watching)? 3 : 1; } else if ( mouseButton == RIGHT ) { // マウス右ボタンが押された mode = 1; // START/STOP切り替え } else if ( mouseButton == CENTER ) { // マウス中ボタンが押された mode = 2; // RESET } if ( mode > 0 ) { set_time(ntime, mode); } irq = false; } // ---------------------------------------- // 時計盤を描画する void drawWatch(PGraphics pg, int w, int lfps) { // 円の幅を算出 // 画面サイズに対する割合で直径を記述 float[] r = { 0.95, // 0, 最も外側の円の下地 0.9, // 1, 最も外側の円の線 0.84, // 2, 2番目の円の線 0.81, // 3, 3番目の円の線 0.78, // 4, 1秒を4分割する目盛の線の内径 0.76, // 5, 秒を示す目盛の線の内径 0.68, // 6, 秒を示す数字の配置位置 0.73, // 7, 「6,12,18」の数字の配置位置 0.55 // 8, 秒の横の小さい秒数文字の配置位置 }; // 目盛線の太さ float[] lw = { 1.0, 1.0, 1.0, 2.0 }; // 目盛線の色(明度) int[] lv = { 0, 0, 0, 0 }; // 目盛を描く際の、何番目の半径を参照するか int[] ridx = { 2, 3, 4, 5 }; // 画面サイズに足しうる割合を使って、直径を求めておく for ( int i=0; i= 32 && n > 0 && ( (ntime - n) < c) ) { // 記録と現在フレームが異なるなら、半透明な針を描画 if ( n != ntime ) { float ang = radians((n % c) * 360.0 / c - 90); float x = rw * cos(ang); float y = rw * sin(ang); // alpha は透明度(255で不透明、0で完全に透明) stroke(0, 0, 255, alpha); line(0, 0, x, y); } j--; if ( j < 0 ) { j += lap.length; } n = lap[j]; // 次の記録を取得 alpha -= 8; // より透明にしていく } } float ang = radians((ntime % c) * 360.0 / c - 90); float x = rw * cos(ang); float y = rw * sin(ang); // 秒針を描く stroke(255, 0, 0); strokeWeight(2.0); noFill(); line(0, 0, x, y); // 秒針の真ん中の小さな円を描く noStroke(); fill(255, 0, 0); ellipse(0, 0, 8, 8); strokeWeight(1.0); } // ---------------------------------------- // 時間を示す文字列を取得する String get_time_str(long frm) { int koma = int(frm % fpsv); frm -= koma; int hh = int(frm / (360 * fpsv)) % 100; int mm = int(frm / (60 * fpsv)) % 60; int ss = int(frm / fpsv) % 60; return nf(hh, 2) + ":" + nf(mm, 2) + ":" + nf(ss, 2) + "+" + nf(koma, 2); } // ---------------------------------------- // 時間記録を描画する void drawLap() { int fs = fsize[1]; int j = (lapidx + lap.length -1) % lap.length; int x = height; int y = height - fs - 16; int fh = fs + 6; int cnt = int(height / fh) - 2; for ( int i=0; i 0 ) { return; } String[] lines = new String[lapidx+1]; long old = 0; long n = 0; for (int i=0; i<=lapidx; i++ ) { long d = n - old; lines[i] = get_time_str(n) + ",,#(+ " + get_time_str(d) + ")"; old = n; n = conv_m2f(lap[i]); } saveStrings(log_filename, lines); set_msg(log_filename + " saved."); } // ---------------------------------------- // メッセージ描画 void draw_msg() { if ( msg_disp_cnt > 0 ) { fill(255); stroke(128); strokeWeight(2.0); int cx = width / 2; int cy = height / 2; int w = width * 4 / 5; int h = fsize[1] * 4; rect(cx - w/2, cy - h/2, w, h); drawText(msg, cx, cy, 1, false); msg_disp_cnt--; } } // メッセージ登録 void set_msg(String s) { msg = s; msg_disp_cnt = fpsv * 3; } // ---------------------------------------- // 実フレームレートをグラフで表示 void drawFpsBar(float nfr, float tfr, int x, int y, int wb) { float w0 = tfr * wb / tfr; float w1 = nfr * wb / tfr; noSmooth(); noStroke(); fill(0, 255, 0); rect(x, y, w0, 8); fill(255, 0, 0); rect(x, y + 4, w1, 4); }