ブラシスクリプトの仕様書
1. 概要
FireAlpaca はブラシ処理でスクリプト(Lua) を用いたプログラム制御が行えます。プログラム制御をすることで、プリセットに用意したような自由度の高いブラシを作成することが可能です。ブラシスクリプトは、拡張子 bs (*.bs) のUTF-8 (BOMなし) で作成します。
作成したブラシスクリプトは、
- ブラシリストウィンドウにドロップ
- ブラシリストウィンドウの下、左から3番目のアイコン (追加(スクリプト)) から追加
の二通りの方法で使用することができます。
一番シンプルなスクリプトは、こんな具合です。
function main( x, y, p )
local r,g,b,a = bs_pixel_get( x, y )
bs_pixel_set( x,y, 255 - r, 255 - g, 255 - b, 255 )
return 1
end
ブラシ描画に使うマウスやタブレット座標の頂点間を、十分に細かい間隔・頻度で main( x, y, p ) 関数が呼ばれます。
かなりの頻度で呼ばれる事になるので、間隔調整が必要になります。この間隔は今後微調整される可能性がありますので、調整が入っても問題なく動作するような処理をおすすめします (呼び出された回数を処理に使わない、など)。
上記のスクリプトの場合、bs_pixel_get 命令で、x,y座標のRGBA値 (色と不透明度) を取得し、bs_pixel_set 命令で、RGB値を反転した値のピクセルを書き込むような処理になっています。
何かしら描画した場合は return 1 を、何も描かなかった場合は return 0 してください。
次はもう少し複雑なスクリプトを見てみましょう。
function main( x, y, p )
local w = bs_width()
if w < 5 then
w = 5
end
if not firstDraw then
local distance = bs_distance( lastDrawX - x, lastDrawY - y )
if distance < w then
return 0
end
end
local dx,dy = bs_dir()
local nx,ny = bs_normal()
bs_polygon( x + nx * w/ 3 , y + ny * w/ 3 )
bs_polygon( x - nx * w/ 3 , y - ny * w/ 3 )
bs_polygon( x + dx * w, y + dy * w )
local r,g,b = bs_fore()
bs_fill( r,g,b, 255 )
lastDrawX = x
lastDrawY = y
firstDraw = false
return 1
end
lastDrawX = 0
lastDrawY = 0
firstDraw = true
このようなブラシになります。順を追って説明します。
lastDrawX = 0
lastDrawY = 0
firstDraw = true
最後の3行に注目してください。ここはグローバル宣言部なので、 main(x,y,p) が呼び出される前 に、 一度だけ 必ず実行されます。ここでは、firstDraw = true といったように、 最初の描画を判定 する為の変数を初期化しています。
local w = bs_width()
if w < 5 then
w = 5
end
bs_width() は現在のブラシ幅(直径)を所得する関数です (筆圧適用した幅)。5 pixel 以下のブラシ幅にしないように調整しています。
if not firstDraw then
local distance = bs_distance( lastDrawX - x, lastDrawY - y )
if distance < w then
return 0
end
end
最初の描画でない時、あまりにブラシが進んでいない場合は描画を避けるような処理をしています。bs_distance() で差分の距離を測っています。
local dx,dy = bs_dir()
local nx,ny = bs_normal()
bs_dir() はブラシの進行方向の正規ベクトル、bs_normal() はブラシの進行方向の垂直方向の正規ベクトルを取得する関数です。正規ベクトルとは、大きさが1になるベクトルのことです。進行方向が必要なので取得しています。
bs_polygon( x + nx * w/ 3 , y + ny * w/ 3 )
bs_polygon( x - nx * w/ 3 , y - ny * w/ 3 )
bs_polygon( x + dx * w, y + dy * w )
bs_polygon() は多角形を設定する命令です。現在の座標値 x, y をベースに、進行方向を指す3頂点を指定しています。
local r,g,b = bs_fore()
bs_fill( r,g,b, 255 )
bs_fore() で前景色のRGB値を取得し、その色を使い bs_fill() で先ほど定義した3頂点を塗りつぶしています。
ストロークの最後だけ何かしたい
全てのストローク処理が終わった後、last関数が呼ばれます。このスクリプトを参考にしてください。 last関数は実装されていなくても構いません 。
function last( x, y, p )
local r,g,b = bs_fore()
local w = bs_width_max()
bs_ellipse( x, y, w * 2, w, 0, r,g,b, bs_opaque() * 255 )
return 1
end
function main( x, y, p )
return 1
end
パラメータの扱い
function param1()
return "param1", 0, 100, 50
end
function param2()
return "param2", 50, 100, 75
end
function param3()
return "param3", 10, 20, 15
end
function param4()
return "checked", 0, 1, 0
end
function param5()
return "unchecked", 0, 1, 1
end
スクリプト内に param1(), param2(), param3() ... という関数を定義しておくと、ブラシコントロールウィンドウでパラメータ設定、取得できるようになります (最大10個。param1 から param10 まで)。
第1 戻り値
ブラシコントロール上に表示される文字です (UTF8 の文字列)
第2 戻り値
設定の 最小値 です(0~100まで)
第3 戻り値
設定の 最大値 です(0~100まで)
第4 戻り値
設定の デフォルト値 です(0~100まで)
設定値はスクリプト内で、
local param1 = bs_param1()
local param2 = bs_param2()
local param3 = bs_param3()
local param4 = bs_param4()
local param5 = bs_param5()
といった形で取得できます。
最小値が 0、最大値が 1 の場合、チェックボックス表示 になります。チェックされている場合は1、チェックされていない場合は 0 が戻り値になります。
デフォルトのサイズ(幅・最小サイズ)
ブラシによっては、細いものを推奨するものもあれば、太いものを推奨するものもあります。
function default_size()
return 17, 0.25
end
という関数をスクリプト内で定義しておけば、デフォルトの幅、デフォルトの最小サイズを指定することができます。この場合、最大幅は17px、最小サイズは 25% になります。
基点の指定
左右対称・回転対称ブラシなど、基点(基準点)が必要な場合があります。基点が必要なブラシは、 キャンバス上でCtrl (Command) +クリック をする事で基点が指定できます。
基点を使いたいスクリプトは、スクリプト内で、
function use_base()
return true
end
と定義しておきます。設定された起点は、
local bsx,bsy = bs_base()
という形で、bs_base()命令を使い取得できます。
基点が指定されてない場合は、(-1,-1) が返ります。(-1,-1)の場合は、特別処理を入れておくと良いでしょう。
描画モード
指定のない通常のモードでは、カラーレイヤーならRGB好きな色を指定して描画できます。しかし、半透明で描画した際に、 重なる部分が濃く なってしまいます。滑らかなブラシ処理には向きません。そこで、
bs_setmode( 1 )
というコードを初期化部分に追加すると、通常のペンのように、半透明部分の合成が綺麗になるモードになります。ただし、RGB任意の色で図形を描画することはできず、 前景色を使った描画 になります。
bs_setmode は「最初に」「一度だけ」呼ぶようにしてください。
通常のモード
bs_setmode( 1 ) を指定
プレビュー中か判定する
ブラシのプレビュー画像が描画されない場合があります (マウスやタブレットの場合は問題ないのに)。時間情報 (bs_ms()) を使った場合に起こりやすい問題です。
if bs_preview() then
プレビュー時の特殊処理をここに挟む
end
のような感じで、bs_preview() 関数を使ってプレビュー中か判定できます。
2. API一覧 (基本命令)
w = bs_width()
w = bs_width_max()
w = bs_width_min()
bs_width()
筆圧を適用したブラシ幅(直径)を取得します
bs_width_max()
ブラシの最大幅を取得します (最大筆圧時の直径)
bs_width_min()
ブラシの最小幅を取得します (最小筆圧時の直径)
distance = bs_distance( x, y )
rad = bs_atan( x, y )
x, y = bs_rotate( x, y, radAngle )
value = bs_grand( ave, std )
milisec = bs_ms()
num = bs_count()
bs_distance( x, y )
原点から (x,y) の距離を取得します
bs_atan( x, y )
原点から (x,y) の角度を取得します (ラジアン)
bs_rotate( x, y, radAngle )
x,y座標を、原点を中心に、radAngle(ラジアン) だけ回転させます
bs_grand( ave, sd1 )
aveを中心に、±sd1の範囲に約68%の確率で収まるようなガウス分布の乱数値を取得します
bs_ms()
OS起動時からの経過ミリ秒を取得します
bs_count()
FireAlpaca の起動後、ブラシスクリプトが呼ばれた回数を取得します
1ストローク毎に何かを変えたい場合などに用います
w = bs_canvas_width()
h = bs_canvas_height()
dpi = bs_canvas_dpi()
rad = bs_canvas_angle()
bs_canvas_width()
キャンバスの幅を取得します
bs_canvas_height()
キャンバスの高さを取得します
bs_canvas_dpi()
キャンバスのdpiを取得します
bs_canvas_angle()
キャンバスの回転角度を取得します (ラジアン角)
r,g,b = bs_fore()
r,g,b = bs_bg()
r,g,b = bs_forebg( t )
alpha = bs_opaque()
bs_fore()
前景色のRGB値を取得します
bs_bg()
背景色のRGB値を取得します
bs_forebg( t )
前景色と背景色の補間値を取得します (0.0~1.0)
0.0: 背景色, 0.5:中間色, 1.0: 前景色
bs_opaque()
ブラシの不透明度 (0.0~1.0) を取得します。
ブラシコントロールのUI上で設定されている不透明度です。
dx,dy = bs_dir()
nx,ny = bs_normal()
bs_dir()
ブラシの進行方向のベクトルを取得します (正規ベクトル)
bs_normal()
ブラシの進行方向から90度傾けたベクトル(法線方向) を取得します (正規ベクトル)
3. API一覧 (描画命令)
r,g,b,a = bs_pixel_get( x, y )
alpha = bs_pixel_get_alpha( x, y )
bs_pixel_set( x, y, r,g,b,a )
bs_pixel_get( x, y )
x,y座標のRGBA値を取得します
R,G,B,A = 0~255
1,8bppレイヤーのA値は、常に255です
bs_pixel_get_alpha( x, y )
x,y座標のA値 (不透明度・濃度) を取得します
alpha = 0~255
1bppレイヤーの場合は、0 または 255 です
bs_pixel_set( x, y, r,g,b,a )
x,y座標に、RGB値を不透明度Aで描画します
R,G,B,A = 0~255
bs_pixel_set を使って沢山描画するのは現実的ではありません
bs_polygon( x, y )
bs_polygon_move( dx, dy )
bs_polygon_move_center()
bs_polygon_rotate( radAngle )
bs_polygon_mul( zx, zy )
bs_polygon_clear()
rx,ry,rw,rh = bs_polygon_region()
bs_polygon( x, y )
多角形を定義する為、頂点x,yを追加します
三角形を定義する場合は、bs_polygon命令を三回実行します
bs_polygon_move( dx, dy )
追加されている多角形の頂点を、dx,dyだけ移動させます
bs_polygon_move_center()
追加されている多角形の頂点を、重心を原点に移動させます
bs_polygon_rotate( radAngle )
追加されている多角形の頂点を、原点を中心に radAngle だけ回転させます
bs_polygon_mul( zx, zy )
追加されている多角形の頂点を、x方向にzx倍、y方向にzy倍にします
bs_polygon_clear()
追加されている多角形をクリアします (bs_fill 直後にも自動的にクリアされます)
rx,ry,rw,rh = bs_polygon_region()
追加されている多角形の範囲を取得します (rx:X始点、ry:Y始点、rw:幅、rh:高さ)
多角形が設定されていない場合、面積のない場合の戻り値は不定です
bs_bezier_begin( x, y )
bs_bezier_c( x1, y1, x2, y2, x3, y3 )
bs_bezier_v( x2, y2, x3, y3 )
bs_bezier_y( x1, y1, x3, y3 )
bs_bezier_l( x3, y3 )
bs_bezier_m( x, y )
bs_bezier_move( dx, dy )
bs_bezier_move_center()
bs_bezier_rotate( rad )
bs_bezier_mul( zx, zy )
bs_bezier_clear()
rx,ry,rw,rh = bs_bezier_region()
bs_bezier_begin( x, y )
(x,y)を始点にベジェ曲線を定義します
サンプルコードはこちら。ハート形状をセットする関数 set_heart を参照ください。
function param1()
return "interval", 10, 100, 50
end
function set_heart( w )
bs_bezier_begin( 0, 0 )
bs_bezier_c( -1, -1, -0.5, -2, 0, -1.3 )
bs_bezier_c( 0.5, -2, 1, -1, 0, 0 )
bs_bezier_mul( w, w * 0.7 )
bs_bezier_move_center()
end
function main( x, y, p )
local w = bs_width_max()
if w < 5 then
w = 5
end
if not firstDraw then
local distance = bs_distance( lastDrawX - x, lastDrawY - y )
if distance < w * 2.0 * bs_param1() / 100 then
return 0
end
end
local dx,dy = bs_dir()
local nx,ny = bs_normal()
local r,g,b = bs_forebg( p )
set_heart( w )
bs_bezier_rotate( bs_atan( dx, dy ) )
bs_bezier_move( x, y )
bs_fill( r,g,b, 255 )
lastDrawX = x
lastDrawY = y
firstDraw = false
return 1
end
lastDrawX = 0
lastDrawY = 0
firstDraw = true
bs_bezier_c( x1, y1, x2, y2, x3, y3 )
制御点1 (x1,y1) 制御点2 (x2,y2)、次点 (x3,y3) の辺を追加します
bs_bezier_v( x2, y2, x3, y3 )
制御点1は現在位置、制御点2 (x2,y2)、次点 (x3,y3) の辺を追加します
bs_bezier_y( x1, y1, x3, y3 )
制御点1 (x1,y1)、制御点2&次点 (x3,y3) の辺を追加します
bs_bezier_l( x3, y3 )
直線の辺を加えます
bs_bezier_m( x, y )
新規サブパスを生成します
重なる部分は、抜けが起こります (奇偶規則)
function main( x, y, p )
if not firstDraw then
local distance = bs_distance( lastDrawX - x, lastDrawY - y )
if distance < 50 then
return 0
end
end
local r,g,b = bs_fore()
-- first path
bs_bezier_begin( x,y )
bs_bezier_l( x + 100 , y )
bs_bezier_l( x + 100 , y + 100 )
bs_bezier_l( x, y + 100 )
bs_bezier_l( x, y )
-- second path
bs_bezier_m( x + 10, y + 10 )
bs_bezier_l( x + 100 - 10 , y + 10 )
bs_bezier_l( x + 100 - 10 , y + 100 - 10 )
bs_bezier_l( x + 10 , y + 100 - 10 )
bs_bezier_l( x + 10 , y + 10 )
bs_fill( r,g,b, 255 )
lastDrawX = x
lastDrawY = y
firstDraw = false
return 1
end
lastDrawX = 0
lastDrawY = 0
firstDraw = true
bs_bezier_move( dx, dy )
追加されているベジェ曲線を、dx,dyだけ移動させます
bs_bezier_move_center()
追加されているベジェ曲線の頂点を、重心を原点に移動させます
bs_bezier_rotate( rad )
追加されているベジェ曲線の頂点を、原点を中心に radAngle だけ回転させます
bs_bezier_mul( zx, zy )
追加されているベジェ曲線の頂点を、x方向にzx倍、y方向にzy倍にします
bs_bezier_clear()
追加されているパスをクリアします (bs_fill 直後にも自動的にクリアされます)
rx,ry,rw,rh = bs_bezier_region()
追加されているパスの範囲を取得します (rx:X始点、ry:Y始点、rw:幅、rh:高さ)
パスが設定されていない場合、面積のない場合の戻り値は不定です
bs_fill( r, g, b, a )
bs_fill( r, g, b, a )
定義されている多角形・ベジェ曲線をRGBA値で塗りつぶします。
アンチエイリアシングの有無はブラシ設定に依存します
実行後、多角形・ベジェ曲線の定義はクリアされます
bs_rect( x, y, w, h, r,g,b,a )
bs_ellipse( mx, my, w, h, radAngle, r,g,b,a )
bs_rect( x, y, w, h, r,g,b,a )
座標(x,y) に、幅高さ (w,h) の矩形を描画します
bs_ellipse( mx, my, w, h, radAngle , r,g,b,a )
座標(mx,my) を中心に、幅高さ (w,h) 角度 (radAngle) の楕円を描画します
アンチエイリアシングの有無はブラシ設定に依存します
真円 (w == h) の場合、高速描画 されます