mod_layerbutton-vpad.hsp

common\ mod_layerbutton-vpad.hsp

/* /////////////////////////////////////////////////////////////////////////////
mod_layerbutton-vpad モジュール
--------------------------------------------------------------------------------
%dll ; モジュール名
mod_layerbutton-vpad
%ver ; バージョン
1.0.2
%date ; 更新日
2025/9/13
%author ; 著作者
MIZUSHIKI
%note
layerbutton命令を利用してバーチャルパッドを作成 (mod_layerbuttonのおまけモジュール)
%type
拡張命令
%url
https://suwa.pupu.jp/HSP/index.html
%port ; 対応環境
Win
*/ /////////////////////////////////////////////////////////////////////////////
#if 0
%index ;========================================================================
AnalogCon
アナログパッドコントローラを作成
%group ;------------------------------------------------------------------------
オブジェクト制御命令
%prm   ;------------------------------------------------------------------------
p1,p2,p3,p4,p5,p6,p7
p1=0〜(0) : パッド画像素材を持つウインドウID (要celdiv)
p2=0〜(0) : パッドのノブ画像素材を持つウインドウID (要celdiv)
p3=0.0〜 : コントローラの表示倍率(実数)
p4=0〜(0) : layerbuttonのグループID
p5=変数 : アナログコントローラのX軸の入力値が格納される変数を登録
p6=変数 : アナログコントローラのY軸の入力値が格納される変数を登録
p7=0,1(0) : オプション-範囲外まで動かしたとき本体を追従させる
%inst  ;------------------------------------------------------------------------
p1,p2の画像素材は、あらかじめceldivによって分割しておく必要があります。
celdivの第4,第5引数による中心座標も必ず指定しておいてください。
画像は「通常/フォーカス/押下」の3状態を並べて用意することで、各状態に応じた表示が可能です。
通常状態の画像1枚だけを用意して3状態すべてで兼用することもできます。
(2枚の場合は「通常」と「フォーカス/押下」の2状態として扱われます。)

p7のオプションに1を指定すると、ノブを範囲外まで動かした際に本体も追従します。
この設定により、反転操作でノブを逆方向へ動かす際に、例え初期位置から離れていても常に一定のスライド量で反対側まで操作できるといった利点があります。

laybtn_enableで無効にするとコントローラは表示されなくなり、有効に戻すと再び表示されます。

※ AnalogCon特有の仕様として、p4表示倍率はdouble型配列も指定できます。
   その場合、配列の各要素が以下の通りに割り当てられます。
   [ 0:SHOW, 1:FOCUS, 2:PRESS ]
%href  ;-----------------------------------------------------------------------
JujikeyCon
ButtonCon
BeanCon

%index ;========================================================================
JujikeyCon
十字キーコントローラを作成
%group ;------------------------------------------------------------------------
オブジェクト制御命令
%prm   ;------------------------------------------------------------------------
p1,p2,p3,p4,p5,p6
p1=0〜(0) : 十字キー画像素材を持つウインドウID (要celdiv)
p2=0〜(0) : 十字キーどうしの隙間
p3=0.0〜 : コントローラの表示倍率(実数)
p4=0〜(0) : layerbuttonのグループID
p5=変数 : 十字キーコントローラの入力値が格納される変数を登録
p6=0〜(0) : 非トリガータイプキー指定
%inst  ;------------------------------------------------------------------------
p1の画像素材は、あらかじめceldivで分割しておく必要があります。
画像は「通常/フォーカス/押下」の3状態を並べたものを、さらに「左上右下」の順に繋げて、合計で12分割の画像になるようにします。
「左上右下」で同じ画像を使用する場合は、「通常/フォーカス/押下」の3状態1組を用意するだけで、全方向に共通して適用されます。

p5で登録した変数には、キーの押下状態が毎フレーム更新されます。
代入される値はstick命令と同じで、「左:1」「上:2」「右:4」「下:8」の値を合算したものとなります。
また、p6もstick命令と同様の設定であり、非トリガータイプキー指定を行うことで、押しっぱなしの状態も検出可能です。

laybtn_enableで無効にするとコントローラは表示されなくなり、有効に戻すと再び表示されます。
%href  ;------------------------------------------------------------------------
AnalogCon
ButtonCon
BeanCon

%index ;========================================================================
ButtonCon
4ボタンコントローラの作成
%group ;------------------------------------------------------------------------
オブジェクト制御命令
%prm   ;------------------------------------------------------------------------
p1,p2,p3,p4,p5,p6
p1=0〜(0) : ボタン画像素材を持つウインドウID (要celdiv)
p2=0〜(0) : ボタンどうしの隙間
p3=0.0〜 : コントローラの表示倍率(実数)
p4=0〜(0) : layerbuttonのグループID
p5=変数 : ボタンコントローラの入力値が格納される変数を登録
p6=0〜(0) : 非トリガータイプキー指定
%inst  ;------------------------------------------------------------------------
p1の画像素材は、あらかじめceldivで分割しておく必要があります。
画像は「通常/フォーカス/押下」3状態を並べたものを、さらに「左側/上側/右側/下側」の順に繋げて、合計で12分割の画像になるようにします。
「左側/上側/右側/下側」で同じ画像を使用する場合は、「通常/フォーカス/押下」の3状態1組を用意するだけで、全方向に共通して適用されます。

p5で登録した変数には、ボタンの押下状態が毎フレーム更新されます。
代入される値はJujikeyConと同じように、「左側:1」「上側:2」「右側:4」「下側:8」の値を合算したものとなります。
また、p6もJujikeyConと同様の設定であり、非トリガータイプキー指定を行うことで、押しっぱなしの状態も検出可能です。

laybtn_enableで無効にするとコントローラは表示されなくなり、有効に戻すと再び表示されます。

※ ボタンに文字やマークを表示させたい場合は、各ボタン用の画像を用意するのが手っ取り早いです。
%href  ;------------------------------------------------------------------------
AnalogCon
JujikeyCon
BeanCon

%index ;========================================================================
BeanCon
長方形型の1ボタンコントローラ(角度指定可能)の作成
%group ;------------------------------------------------------------------------
オブジェクト制御命令
%prm   ;------------------------------------------------------------------------
p1,p2,p3,p4,p5,p6
p1=0〜(0) : 回転させて使うボタン画像素材を持つウインドウID (要celdiv)
p2=0.0〜 : 角度値(ラジアン)
p3=0.0〜 : コントローラの表示倍率(実数)
p4=0〜(0) : layerbuttonのグループID
p5=変数 : ボタンコントローラの入力値が格納される変数を登録
p6=0,1(0) : 非トリガータイプキー指定
%inst  ;------------------------------------------------------------------------
p1の画像素材は、あらかじめceldivで分割しておく必要があります。
回転処理に必要なのでceldivの第4,第5引数の中心座標も必ず指定しておいてください。
画像は「通常/フォーカス/押下」の3状態を並べたものを用意してください。

p2で回転角度を指定できますが、回転されるのは画像とヒットエリアのみであり、objlayer_axis_xなどのオブジェクトの座標/サイズ値は変化しません。

p5で登録した変数には、ボタンの押下状態が毎フレーム更新されます。
押されたときには1が代入されます。
p6の非トリガータイプキーに1を指定することで、押しっぱなしの状態も検出可能です。

laybtn_enableで無効にするとコントローラは表示されなくなり、有効に戻すと再び表示されます。
%href  ;------------------------------------------------------------------------
AnalogCon
JujikeyCon
ButtonCon
% ;=============================================================================
#endif

#include "mod_layerbutton.hsp"

#ifndef AnalogCon

#module modlaybtn_vpad
celx=0:cely=0:celofsx=0:celofsy=0:celmax=0:_arA=0:num_Analogpad=0:num_jujikey=0:num_btnkey=0:num_beankey=0  ; 未初期化警告避け
#define global AnalogCon(%1=0,%2=0,%3,%4=0,%5,%6,%7=0) if pChk@modlaybtn_vpad("%3"){dup _arA@modlaybtn_vpad,%3:AnalogCon@modlaybtn_vpad %1,%2,-1.0,%4,%5,%6,%7}else{AnalogCon@modlaybtn_vpad %1,%2,%3,%4,%5,%6,%7}
#deffunc AnalogCon@modlaybtn_vpad int cel_pad, int cel_nub, double ratio, int group, var out_ax, var out_ay, int zurizuri
	getCelSize@modlaybtn cel_pad, celx, cely, celofsx, celofsy, celmax
	out_ax = 0.0 : out_ay = 0.0
	ratio_ = ratio
	if ratio != -1.0 {
		d_ana(num_Analogpad*7) = 0.0, 0.0, 0.0, 0.0, double(ratio), double(ratio), double(ratio)
	}else {
		d_ana(num_Analogpad*7) = 0.0, 0.0, 0.0, 0.0, double(_arA(0)), double(_arA(limit(1,0,length(_arA)-1))), double(_arA(limit(2,0,length(_arA)-1)))
		ratio_ = double(_arA(0))
	}
	i_ana(num_Analogpad*6) = cel_pad, cel_nub, group, zurizuri, varptr(out_ax), varptr(out_ay)
	pos ginfo_cx-s4n5(ratio_*celx/2), ginfo_cy-s4n5(ratio_*cely/2)
	layerbutton s4n5(ratio_*celx),s4n5(ratio_*cely), num_Analogpad,group {
		laybtn_settings 0, 4+8+16, 1+4
		laybtn_hitarea -1, objlayer_size_x/2,objlayer_size_y/2, objlayer_size_x  ; 円形ヒットエリア
		if lparam == objlayer_cmddraw {
			laybtn_enable i_ana(objlayer_option*6+2), -1
			if stat == 0 : return  ; disenable時は描画しない
			if layerbtn_clickx!=-1 && layerbtn_clicky!=-1 {  ; クリック/タッチ中 (ポーズ時は操作させない)
				layerbtn_clickx_ = double(layerbtn_clickx) + d_ana(objlayer_option*7+2)
				layerbtn_clicky_ = double(layerbtn_clicky) + d_ana(objlayer_option*7+3)
				rr = double(objlayer_size_x)/2  ; スティックが動く範囲の半径
				dx = -layerbtn_clickx_ + layerbtn_mousex
				dy = -layerbtn_clicky_ + layerbtn_mousey
				_dist = dx*dx + dy*dy
				if _dist > rr*rr {
					dist = sqrt(_dist)
					layerbtn_mousex_ = double(dx * rr) / dist + layerbtn_clickx_
					layerbtn_mousey_ = double(dy * rr) / dist + layerbtn_clicky_
					if i_ana(objlayer_option*6+3) : d_ana(objlayer_option*7+2)-=layerbtn_mousex_-layerbtn_mousex : d_ana(objlayer_option*7+3)-=layerbtn_mousey_-layerbtn_mousey
				}else{
					layerbtn_mousex_ = double(layerbtn_mousex)
					layerbtn_mousey_ = double(layerbtn_mousey)
				}
				// パッドのアナログ値
				d_ana(objlayer_option*7+0) = (layerbtn_mousex_ - (layerbtn_clickx_))*2 / objlayer_size_x
				d_ana(objlayer_option*7+1) = (layerbtn_mousey_ - (layerbtn_clicky_))*2 / objlayer_size_y
				// 表示用の補正
				layerbtn_mousex_ -= objlayer_size_x/2
				layerbtn_mousey_ -= objlayer_size_y/2
				layerbtn_clickx_ -= objlayer_size_x/2
				layerbtn_clicky_ -= objlayer_size_y/2
			}else {
				d_ana(objlayer_option*7+2)=0.0 : d_ana(objlayer_option*7+3)=0.0
				d_ana(objlayer_option*7+0)=0.0 : d_ana(objlayer_option*7+1)=0.0
				// 表示用の補正
				layerbtn_mousex_ = 0.0
				layerbtn_mousey_ = 0.0
				layerbtn_clickx_ = layerbtn_mousex_
				layerbtn_clicky_ = layerbtn_mousey_
			}
			// pad, nub 描画
			switch (layerbtn_stat|1^1)  ; _SELECTED状態を除去して分岐 [(layerbtn_stat & $FFFE)でもOK]
			case LAYBTN_FOCUS_IN : ratio_ = d_ana(objlayer_option*7+4+1) : swbreak
			case LAYBTN_PRESS_IN : ratio_ = d_ana(objlayer_option*7+4+2) : swbreak
			default : ratio_ = d_ana(objlayer_option*7+4+0)
			swend
			laybtn_ezcel i_ana(objlayer_option*6+0), 0,,,,,,, layerbtn_clickx_, layerbtn_clicky_, ratio_,ratio_  ; ezcelの裏技 : 第9引数から ボタン画像ずらし量, 強制倍率 を指定できる
			laybtn_ezcel i_ana(objlayer_option*6+1), 0,,,,,,, layerbtn_mousex_, layerbtn_mousey_, ratio_,ratio_
			dupptr out_ax_, i_ana(objlayer_option*6+4), 8, 3
			dupptr out_ay_, i_ana(objlayer_option*6+5), 8, 3
			out_ax_ = d_ana(objlayer_option*7+0)
			out_ay_ = d_ana(objlayer_option*7+1)
		}
		return
	}
	num_Analogpad++
	return

#deffunc JujikeyCon int cel_juji, int sukima, double ratio, int group, var out_key, int trig
	getCelSize@modlaybtn cel_juji, celx, cely, celofsx, celofsy, celmax
	pxConL = ginfo_cx : pyConL = ginfo_cy : ratio_ = ratio
	i_juji(num_jujikey*6) = cel_juji, celmax, group, varptr(out_key), trig, 0
	; 左
	pos pxConL-s4n5(ratio*(celx+sukima)), pyConL-s4n5(ratio*(cely/2))
	layerbutton s4n5(ratio*celx),s4n5(ratio*cely), num_jujikey,group {
		laybtn_settings 0,4+8,5  ; 設定 : ボタン外からスライドしてもクリック + ボタンを押しても消さない
		laybtn_hitarea 5, 0,0, objlayer_size_x/2,-objlayer_size_y/2, objlayer_size_x-ratio_*8,objlayer_size_y/2, objlayer_size_x/2,objlayer_size_y*3/2, 0,objlayer_size_y  ; ヒットエリア調整 : 斜め入力できるように
		if lparam == objlayer_cmddraw {
			laybtn_enable i_juji(objlayer_option*6+2), -1
			if stat : laybtn_ezcel i_juji(objlayer_option*6+0),(0\i_juji(objlayer_option*6+1))  ; ボタン描画 (disenable時は描画しない)
			_out_key = 0  ; 初期化 (オブジェクトIDが並んでいるので左〜下は順番に一気に呼び出されるから、一時変数として使っても混線しない)
			if layerbtn_stat & LAYBTN_PRESS_IN : _out_key |= 1
		}
		return
	}
	; 上
	pos pxConL-s4n5(ratio*(celx/2)), pyConL-s4n5(ratio*(cely+sukima))
	layerbutton s4n5(ratio*celx),s4n5(ratio*cely), num_jujikey,group {
		laybtn_settings 0,4+8,5  ; 設定 : ボタン外からスライドしてもクリック + ボタンを押しても消さない
		laybtn_hitarea 5, 0,0, objlayer_size_x,0, objlayer_size_x*3/2,objlayer_size_y/2, objlayer_size_x/2,objlayer_size_y-ratio_*8, -objlayer_size_x/2,objlayer_size_y/2  ; ヒットエリア調整 : 斜め入力できるように
		if lparam == objlayer_cmddraw {
			laybtn_enable i_juji(objlayer_option*6+2), -1
			if stat : laybtn_ezcel i_juji(objlayer_option*6+0),(3\i_juji(objlayer_option*6+1))  ; ボタン描画 (disenable時は描画しない)
			if layerbtn_stat & LAYBTN_PRESS_IN : _out_key |= 2
		}
		return
	}
	; 右
	pos pxConL+s4n5(ratio*sukima), pyConL-s4n5(ratio*cely/2)
	layerbutton s4n5(ratio*celx),s4n5(ratio*cely), num_jujikey,group {
		laybtn_settings 0,4+8,5  ; 設定 : ボタン外からスライドしてもクリック + ボタンを押しても消さない
		laybtn_hitarea 5, ratio_*8,objlayer_size_y/2, objlayer_size_x/2,-objlayer_size_y/2, objlayer_size_x,0, objlayer_size_x,objlayer_size_y, objlayer_size_x/2,objlayer_size_y*3/2  ; ヒットエリア調整 : 斜め入力できるように
		if lparam == objlayer_cmddraw {
			laybtn_enable i_juji(objlayer_option*6+2), -1
			if stat : laybtn_ezcel i_juji(objlayer_option*6+0),(6\i_juji(objlayer_option*6+1))  ; ボタン描画 (disenable時は描画しない)
			if layerbtn_stat & LAYBTN_PRESS_IN : _out_key |= 4
		}
		return
	}
	; 下
	pos pxConL-s4n5(ratio*celx/2), pyConL+s4n5(ratio*sukima)
	layerbutton s4n5(ratio*celx),s4n5(ratio*cely), num_jujikey,group {
		laybtn_settings 0,4+8,5  ; 設定 : ボタン外からスライドしてもクリック + ボタンを押しても消さない
		laybtn_hitarea 5, objlayer_size_x/2,ratio_*8, objlayer_size_x*3/2,objlayer_size_y/2, objlayer_size_x,objlayer_size_y, 0,objlayer_size_y, -objlayer_size_x/2,objlayer_size_y/2  ; ヒットエリア調整 : 斜め入力できるように
		if lparam == objlayer_cmddraw {
			laybtn_enable i_juji(objlayer_option*6+2), -1
			if stat : laybtn_ezcel i_juji(objlayer_option*6+0),(9\i_juji(objlayer_option*6+1))  ; ボタン描画 (disenable時は描画しない)
			if layerbtn_stat & LAYBTN_PRESS_IN : _out_key |= 8
			dupptr out_key_, i_juji(objlayer_option*6+3), 4, 4  ; 最後のオブジェクトなのでout_keyを書き換える
			out_key_ = (_out_key | i_juji(objlayer_option*6+5) ^ i_juji(objlayer_option*6+5)) | (_out_key & i_juji(objlayer_option*6+4))
			i_juji(objlayer_option*6+5) = _out_key  ; 前回のkeyを記憶
		}
		return
	}
	num_jujikey++
	return

#deffunc ButtonCon int cel_btn, int sukima, double ratio, int group, var out_key, int trig
	getCelSize@modlaybtn cel_btn, celx, cely, celofsx, celofsy, celmax
	pxConL=ginfo_cx : pyConL=ginfo_cy : ratio_=ratio : sukima_=sukima
	i_btn(num_btnkey*6) = cel_btn, celmax, group, varptr(out_key), trig, 0
	; 左
	pos pxConL-(ratio*(celx+sukima)), pyConL-(ratio*(cely/2))
	layerbutton s4n5(ratio*celx),s4n5(ratio*cely), num_btnkey,group {
		laybtn_settings 0,4+8,5  ; 設定 : 同グループ押下中ならボタン外からスライドしてもクリック + ボタンを押しても消さない
		laybtn_hitarea -4, (objlayer_size_x/2+ratio_*sukima_)/4+objlayer_size_x/2,-(objlayer_size_y/2+ratio_*sukima_)/4+objlayer_size_y/2,objlayer_size_x, objlayer_size_x/2,objlayer_size_y/2,objlayer_size_x, (objlayer_size_x/2+ratio_*sukima_)/4+objlayer_size_x/2,(objlayer_size_y/2+ratio_*sukima_)/4+objlayer_size_y/2,objlayer_size_x  ; ヒットエリア調整 : 斜め入力できるように
		if lparam == objlayer_cmddraw {
			laybtn_enable i_btn(objlayer_option*6+2), -1
			if stat : laybtn_ezcel i_btn(objlayer_option*6+0),(0\i_btn(objlayer_option*6+1))  ; ボタン描画 (disenable時は描画しない)
			_out_key = 0  ; 初期化 (オブジェクトIDが並んでいるので左〜下は順番に一気に呼び出されるから、一時変数として使っても混線しない)
			if layerbtn_stat & LAYBTN_PRESS_IN : _out_key |= 1
		}
		return
	}
	; 上
	pos pxConL-(ratio*(celx/2)), pyConL-(ratio*(cely+sukima))
	layerbutton s4n5(ratio*celx),s4n5(ratio*cely), num_btnkey,group {
		laybtn_settings 0,4+8,5  ; 設定 : 同グループ押下中ならボタン外からスライドしてもクリック + ボタンを押しても消さない
		laybtn_hitarea -4, -(objlayer_size_x/2+ratio_*sukima_)/4+objlayer_size_x/2,(objlayer_size_y/2+ratio_*sukima_)/4+objlayer_size_y/2,objlayer_size_x, objlayer_size_x/2,objlayer_size_y/2,objlayer_size_x, (objlayer_size_x/2+ratio_*sukima_)/4+objlayer_size_x/2,(objlayer_size_y/2+ratio_*sukima_)/4+objlayer_size_y/2,objlayer_size_x  ; ヒットエリア調整 : 斜め入力できるように
		if lparam == objlayer_cmddraw {
			laybtn_enable i_btn(objlayer_option*6+2), -1
			if stat : laybtn_ezcel i_btn(objlayer_option*6+0),(3\i_btn(objlayer_option*6+1))  ; ボタン描画 (disenable時は描画しない)
			if layerbtn_stat & LAYBTN_PRESS_IN : _out_key |= 2
		}
		return
	}
	; 右
	pos pxConL+(ratio*sukima), pyConL-(ratio*cely/2)
	layerbutton s4n5(ratio*celx),s4n5(ratio*cely), num_btnkey,group {
		laybtn_settings 0,4+8,5  ; 設定 : 同グループ押下中ならボタン外からスライドしてもクリック + ボタンを押しても消さない
		laybtn_hitarea -4, -(objlayer_size_x/2+ratio_*sukima_)/4+objlayer_size_x/2,-(objlayer_size_y/2+ratio_*sukima_)/4+objlayer_size_y/2,objlayer_size_x, objlayer_size_x/2,objlayer_size_y/2,objlayer_size_x, -(objlayer_size_x/2+ratio_*sukima_)/4+objlayer_size_x/2,(objlayer_size_y/2+ratio_*sukima_)/4+objlayer_size_y/2,objlayer_size_x  ; ヒットエリア調整 : 斜め入力できるように
		if lparam == objlayer_cmddraw {
			laybtn_enable i_btn(objlayer_option*6+2), -1
			if stat : laybtn_ezcel i_btn(objlayer_option*6+0),(6\i_btn(objlayer_option*6+1))  ; ボタン描画 (disenable時は描画しない)
			if layerbtn_stat & LAYBTN_PRESS_IN : _out_key |= 4
		}
		return
	}
	; 下
	pos pxConL-(ratio*celx/2), pyConL+(ratio*sukima)
	layerbutton s4n5(ratio*celx),s4n5(ratio*cely), num_btnkey,group {
		laybtn_settings 0,4+8,5  ; 設定 : 同グループ押下中ならボタン外からスライドしてもクリック + ボタンを押しても消さない
		laybtn_hitarea -4, -(objlayer_size_x/2+ratio_*sukima_)/4+objlayer_size_x/2,-(objlayer_size_y/2+ratio_*sukima_)/4+objlayer_size_y/2,objlayer_size_x, objlayer_size_x/2,objlayer_size_y/2,objlayer_size_x, (objlayer_size_x/2+ratio_*sukima_)/4+objlayer_size_x/2,-(objlayer_size_y/2+ratio_*sukima_)/4+objlayer_size_y/2,objlayer_size_x  ; ヒットエリア調整 : 斜め入力できるように
		if lparam == objlayer_cmddraw {
			laybtn_enable i_btn(objlayer_option*6+2), -1
			if stat : laybtn_ezcel i_btn(objlayer_option*6+0),(9\i_btn(objlayer_option*6+1))  ; ボタン描画 (disenable時は描画しない)
			if layerbtn_stat & LAYBTN_PRESS_IN : _out_key |= 8
			dupptr out_key_, i_btn(objlayer_option*6+3), 4, 4  ; 最後のオブジェクトなのでout_keyを書き換える
			out_key_ = (_out_key | i_btn(objlayer_option*6+5) ^ i_btn(objlayer_option*6+5)) | (_out_key & i_btn(objlayer_option*6+4))
			i_btn(objlayer_option*6+5) = _out_key  ; 前回のkeyを記憶
		}
		return
	}
	num_btnkey++
	return

#deffunc BeanCon int cel_bean, double rad, double ratio, int group, var out_key, int trig
	getCelSize@modlaybtn cel_bean, celx, cely, celofsx, celofsy, celmax
	rad_=rad
	i_bean(num_beankey*6) = cel_bean, celmax, group, varptr(out_key), trig, 0
	d_bean(num_beankey*2) = ratio, rad
	pos ginfo_cx-(ratio*celx/2), ginfo_cy-(ratio*cely/2)
	layerbutton s4n5(ratio*celx),s4n5(ratio*cely), num_beankey,group {
		laybtn_settings 0,4+8,1+4  ; 設定 : 同グループ押下中ならボタン外からスライドしてもクリック + ボタンを押しても消さない
		laybtn_hitarea -3, objlayer_size_x/2,objlayer_size_y/2, objlayer_size_x,objlayer_size_y, rad_  ; ヒットエリア
		if lparam == objlayer_cmddraw {
			laybtn_enable i_bean(objlayer_option*6+2), -1
			if stat {  ; ボタン描画 (disenable時は描画しない)
				pos objlayer_axis_x+objlayer_size_x/2, objlayer_axis_y+objlayer_size_y/2
				switch (layerbtn_stat|1^1)  ; _SELECTED状態を除去して分岐 [(layerbtn_stat & $FFFE)でもOK]
				case LAYBTN_FOCUS_IN : id_celdiv = 1 : swbreak
				case LAYBTN_PRESS_IN : id_celdiv = 2 : swbreak
				default : id_celdiv = 0
				swend
				celput i_bean(objlayer_option*6+0), limit(id_celdiv,0,i_bean(objlayer_option*6+1)-1), d_bean(objlayer_option*2+0),d_bean(objlayer_option*2+0), d_bean(objlayer_option*2+1)
			}
			if layerbtn_stat & LAYBTN_PRESS_IN : _out_key = 1 : else : _out_key = 0
			dupptr out_key_, i_bean(objlayer_option*6+3), 4, 4  ; out_keyを書き換える
			out_key_ = (_out_key | i_bean(objlayer_option*6+5) ^ i_bean(objlayer_option*6+5)) | (_out_key & i_bean(objlayer_option*6+4))
			i_bean(objlayer_option*6+5) = _out_key  ; 前回のkeyを記憶
		}
		return
	}
	num_beankey++
	return
#defcfunc local s4n5 double p1
	if p1<0 : return int(p1-0.5)
	return int(p1+0.5)

//関数に渡されたパラメータが変数か確認する
#defcfunc pChk@modlaybtn_vpad str _chkStr
	chkStr = _chkStr : chkShift = 0
	chkStr = strtrim(chkStr,3)
	flg = 0
	repeat strlen(chkStr)
		if 'a'<=peek(chkStr,cnt)&&peek(chkStr,cnt)<='z' :flg=1 :continue
		if 'A'<=peek(chkStr,cnt)&&peek(chkStr,cnt)<='Z' :flg=1 :continue
		if peek(chkStr,cnt)=='_' :flg=1 :continue
		if peek(chkStr,cnt)=='@' :flg=1 :continue
		if flg=0 : break
		if '0'<=peek(chkStr,cnt)&&peek(chkStr,cnt)<='9' :continue
		flg = 0 : break
	loop
	return flg
#global

#endif