# 02 demo-stateflow.hsp

sample\ 02 demo-stateflow.hsp

    #include "hsp3dish.as"

    #include "mod_layerbutton.hsp"
    #include "d3m.hsp"  ; FPS計測用

    #packopt xsize 480
    #packopt ysize 800

    	screen 0,480,800
    	title "layerbutton stateflow"
    	log = ""
    	fps2 = 0
    	// HSP3Dish.js用フォルダ設定
    	info_os = sysinfo(0)
    	if instr(info_os,0,"Emscripten")>=0 : mm_dir="" : else : mm_dir="data/"

    	// 画像読み込み
    	celload mm_dir+"03_01-btn.png", -1
    	cel_btn = stat
    	celdiv cel_btn,172,66
    	celload mm_dir+"icon.png", -1
    	cel_ico = stat
    	celdiv cel_ico,32,32, 16,16

    	// オブジェクト作成
    	gosub *create_button_hidari
    	gosub *create_button_shita

    	// 表示ループ
    	repeat
    		redraw 0 :color 240,240,240 : boxf : color : pos 0,0 : font msgothic,14
    		mes "fps = " + d3getfps() : color 200,200,200
    		mes log
    		gosub *flowchart
    		redraw 1
    		await (1000<<fps2)/60
    	loop
    	stop

    // フローチャート
    *flowchart
    	font msgothic, 14, 1 : color
    	pos 240, 20 : mes "- ボタン01 の 状態遷移図 -"
    	font msgothic, 12

    	; フローチャート描画
    	color : boxf 225, 50, 340, 100
    	color 230,230,230 : if btn_state & LAYBTN_SHOW_IN : color 255,200,200
    	boxf 226, 51, 339, 99
    	color : mesz "LAYBTN_SHOW_IN",0, 225,50,340,100, 1,1
    	if (btn_state & LAYBTN_SHOW_IN)!=0 && (btn_exstate & 1)!=0 : mesz "(showing)",0, 225,50,340,98, 1,2
    	color 128,128,128 : line 280, 150, 280, 100 : line 275, 140

    	color : boxf 225, 150, 340, 200
    	color 230,230,230 : if btn_state & LAYBTN_FOCUS_IN : color 255,200,200
    	boxf 226, 151, 339, 199
    	color : mesz "LAYBTN_FOCUS_IN",0, 225,150,340,200, 1,1
    	color 128,128,128 : line 280, 250, 280, 200 : line 275, 240

    	pos 340,165 : line 375,165 : line 365,170
    	color : boxf 375, 150, 460, 200
    	color 230,230,230 : if btn_state & LAYBTN_FOCUS_OUT : color 255,200,200
    	boxf 376, 151, 459, 199
    	color : mesz "_FOCUS_OUT",0, 375,150,460,200, 1,1
    	color 128,128,128 : pos 417,150 : line 417,75 : line 340,75 : line 350,70

    	color : boxf 225, 250, 340, 300
    	color 230,230,230 : if btn_state & LAYBTN_PRESS_IN : color 255,200,200
    	boxf 226, 251, 339, 299
    	color : mesz "LAYBTN_PRESS_IN",0, 225,250,340,300, 1,1
    	color 128,128,128 : line 280, 350, 280, 300 : line 275, 340

    	pos 340,275 : line 375,275 : line 365,280
    	color : boxf 375, 250, 460, 300
    	color 230,230,230 : if btn_state & LAYBTN_PRESS_OUT : color 255,200,200
    	boxf 376, 251, 459, 299
    	color : mesz "_PRESS_OUT",0, 375,250,460,300, 1,1
    	color 128,128,128 : pos 417,250 : line 417,225 : line 362,225 : line 362,185 : line 340,185 : line 350,180

    	color : boxf 225, 350, 340, 400
    	color 230,230,230 : if btn_state & LAYBTN_SHOW_OUT : color 255,200,200
    	boxf 226, 351, 339, 399
    	color : mesz "LAYBTN_SHOW_OUT",0, 225,350,340,400, 1,1
    	if (btn_state & LAYBTN_SHOW_OUT)!=0 && (btn_exstate & 1)!=0 : mesz "(showing)",0, 225,350,340,398, 1,2
    	color 128,128,128 : line 280, 430, 280, 400 : line 275, 420

    	color 128,128,128 : if btn_state & LAYBTN_COMPLETE : color 255,0,0
    	mesz "LAYBTN_COMPLETE",0, 225,415,340,465, 1,1
    	if btn_state == LAYBTN_COMPLETE_SELECTED : mesz "(+_SELECTED)",0, 225,415,340,463, 1,2
    	return

    #module
    #deffunc mesz str wd, int tp, int ax, int ay, int bx, int by, int px, int py
    	wd_=wd : sz=0 : pos -ginfo_sx,-ginfo_sy
    	notesel wd_ : repeat notemax : noteget w,cnt : mes w,tp : sz=limit(ginfo(14),sz) : loop
    	pos ax+(bx-ax)*limit(px,0,2)/2-sz*limit(px,0,2)/2,ay+(by-ay)*limit(py,0,2)/2-ginfo(15)*notemax*limit(py,0,2)/2
    	noteunsel : mes wd,tp : return
    #global

    // 左側ボタン作成
    *create_button_hidari
    	if laybtn_length(0) > 0 : return  ; グループID 0 がすでに存在する場合はreturn
    	pos 30,20
    	repeat 4
    		pos ,ginfo_cy+40  ; ボタンの位置を調整
    		tien = cnt * 10  ; IDごとに表示遅延をつける(SHOW_IN:10フレーム、SHOW_OUT:5フレーム)
    		// ボタン作成 : グループID 0
    		layerbutton 172,66, cnt, 0, 30+tien,20,10, 15+tien/2,10,5 {
    			if lparam == objlayer_cmddraw {
    				if objlayer_option == 0 {  ; フローチャート表示用の情報を取得
    					btn_state = layerbtn_stat
    					btn_exstate = flagBits@_modlaybtn
    				}else {
    					btn_exstate |= flagBits@_modlaybtn
    				}
    				mes_zurasi = 0,-5  ; テキスト表示の基準位置
    				tien = objlayer_option * 10  ; optionに代入したボタンIDに合わせて遅延時間を計算
    				// ボタンの状態に応じて描画を振り分ける
    				switch layerbtn_stat
    				case LAYBTN_SHOW_IN // 表示開始
    					pos objlayer_axis_x-laybtn_ease(200, 0, tien), objlayer_axis_y  ; 左からスライドイン(ボタンIDごとの遅延時間を考慮)
    					gmode 3,,,255 : celput cel_btn, 0  ; ボタン描画
    					mes_zurasi = -laybtn_ease(200, 0, tien),-5  ; スライドインに合わせてテキスト位置もスライド
    					swbreak
    				case LAYBTN_FOCUS_IN // フォーカス表示
    					pos objlayer_axis_x, objlayer_axis_y
    					gmode 3,,,256 : celput cel_btn, 0  ; ボタン描画 : 通常状態
    					pos objlayer_axis_x, objlayer_axis_y
    					gmode 3,,,laybtn_ease(0,256) : celput cel_btn, 1  ; ボタン描画 : フォーカス状態(透明度をイージングで徐々に変化)
    					swbreak
    				case LAYBTN_FOCUS_OUT // フォーカス解除
    					pos objlayer_axis_x, objlayer_axis_y
    					gmode 3,,,256 : celput cel_btn, 0  ; ボタン描画 : 通常状態
    					pos objlayer_axis_x, objlayer_axis_y
    					gmode 3,,,laybtn_ease(256,0) : celput cel_btn, 1  ; ボタン描画 : フォーカス状態(透明度をイージングで徐々に変化)
    					swbreak
    				case LAYBTN_PRESS_IN // 押し込み表示 (解説のためイージング追加)
    					pos objlayer_axis_x, objlayer_axis_y
    					gmode 3,,,laybtn_ease(256,0) : celput cel_btn, 1  ; ボタン描画 : フォーカス状態
    					pos objlayer_axis_x, objlayer_axis_y
    					gmode 3,,,laybtn_ease(0,256) : celput cel_btn, 2  ; ボタン描画 : 押し込み状態
    					mes_zurasi = 0,laybtn_ease(-5,-1)  ; ボタン押し込みに合わせてテキスト位置を下げる(-5 → -1)
    					swbreak
    				case LAYBTN_PRESS_OUT // 押し込み表示 (解説のためイージング追加)
    					pos objlayer_axis_x, objlayer_axis_y
    					gmode 3,,,laybtn_ease(256,0) : celput cel_btn, 2  ; ボタン描画 : 押し込み状態
    					pos objlayer_axis_x, objlayer_axis_y
    					gmode 3,,,laybtn_ease(0,256) : celput cel_btn, 1  ; ボタン描画 : フォーカス状態
    					mes_zurasi = 0,laybtn_ease(-1,-5)  ; ボタンを離すのに合わせてテキスト位置を戻す(-1 → -5)
    					swbreak
    				case LAYBTN_SHOW_OUT // 非表示処理
    				case LAYBTN_SHOW_OUT_SELECTED
    					if layerbtn_stat == LAYBTN_SHOW_OUT_SELECTED && layerbtn_cnt == 0 {
    						// ボタンが選択された瞬間！！
    						log += "hidari - SELECTED! opt="+objlayer_option+" wparam="+wparam +"\n"
    					}
    					pos objlayer_axis_x-laybtn_ease(0, 200, tien/2), objlayer_axis_y  ; 左へスライドアウト(ボタンIDごとの遅延時間を考慮)
    					if layerbtn_stat & LAYBTN_SELECTED {  ; 選択されたボタンのスライドアウト表示
    						gmode 3,,,256 : celput cel_btn, 2  ; ボタン描画 : 押し込み状態
    						mes_zurasi = -laybtn_ease(0, 200, tien/2),-1  ; スライドインに合わせてテキスト位置もスライド + 押し込みテキスト位置
    					} else {                              ; 選択されていないボタンのスライドアウト表示
    						gmode 3,,,256 : celput cel_btn, 0  ; ボタン描画 : 通常状態
    						mes_zurasi = -laybtn_ease(0, 200, tien/2),-5  ; スライドインに合わせてテキスト位置もスライド
    					}
    					swbreak
    				case LAYBTN_COMPLETE
    				case LAYBTN_COMPLETE_SELECTED
    					if layerbtn_stat & LAYBTN_SELECTED {
    						// グループ内のすべてのボタンの非表示処理が完了したとき (選択されたボタンはLAYBTN_COMPLETE_SELECTEDで通知される)
    						log += "hidari - COMPLETE! opt="+objlayer_option+" wparam="+wparam +"\n"
    					}
    					return
    					swbreak
    				swend
    				color 0,0,0 : objcolor 255,255,255 : font msgothic, 18, 1  ; laybtn_ezboxのテキスト設定
    				laybtn_mes "ボタン0"+(objlayer_option+1),4, 1,1, mes_zurasi(0),mes_zurasi(1)  ; テキスト描画
    				font msgothic, 14
    				laybtn_mes "stat="+layerbtn_stat,0, 0,2, 0,14  ; テキスト描画
    				laybtn_mes "cnt ="+layerbtn_cnt,0, 0,2, 0,28  ; テキスト描画

    				// ボタンの無効表示
    				laybtn_enable 0, -1
    				if stat == 0  {
    					gmode 3,,,100 : color
    					laybtn_boxfb objlayer_axis_x, objlayer_axis_y-20, objlayer_axis_x2, objlayer_axis_y2+20
    					if objlayer_option == 3 : color 0,0,0 : font msgothic, 14 : laybtn_mes "無効 : 適当に黒フィルターを被せてます\n(好みの表示にして下さい)",0, 1,2, 25,52
    				}
    			}
    			return
    		}
    		if cnt == 0 : hidari_fobj = stat
    	loop
    	return

    // 下側ボタン作成
    *create_button_shita
    	repeat 4
    		pos 65+50*cnt, 500
    		layerbutton 50,50, cnt, 2, 0,15,20, 0,0,0 {
    			laybtn_settings 0,2,1+2+8  ; 設定変更 : 押しても消えない＋PRESSアニメ待ち＋マウスクリック即ボタン決定
    			if lparam == objlayer_cmddraw {
    				// ボタンの描画
    				color 255,255,255 : boxf objlayer_axis_x, objlayer_axis_y, objlayer_axis_x2, objlayer_axis_y2  ; ボタン下地描画
    				pos objlayer_axis_x+25, objlayer_axis_y+25  ; アイコンの基準位置をpos
    				switch layerbtn_stat
    				case LAYBTN_FOCUS_IN // フォーカスと押し込み両方で虹色カーソル描画をするのでまとめる
    				case LAYBTN_PRESS_IN
    				case LAYBTN_PRESS_IN_SELECTED
    					// グラデーション四角カーソルの描画
    					if layerbtn_stat & LAYBTN_FOCUS_IN  : fade = 0,255   ; フェードイン
    					if layerbtn_stat & LAYBTN_PRESS_IN  : fade = 255,255 ; ボタンクリック
    					grdc++  ; グラデーションカラーをくるくるさせるためにカウント(HSV形式 H値:0~191)
    					hsvcolor (grdc \ 192), laybtn_ease(fade.0, fade.1), 255  ; グラデーションパラメータ
    					x(0)=objlayer_axis_x +2 : y(0)=objlayer_axis_y +2 : col(0)=ginfo_r<<16|ginfo_g<<8|ginfo_b
    					hsvcolor (grdc+48 \ 192), laybtn_ease(fade.0, fade.1), 255
    					x(1)=objlayer_axis_x2-2 : y(1)=objlayer_axis_y +2 : col(1)=ginfo_r<<16|ginfo_g<<8|ginfo_b
    					hsvcolor (grdc+96 \ 192), laybtn_ease(fade.0, fade.1), 255
    					x(2)=objlayer_axis_x2-2 : y(2)=objlayer_axis_y2-2 : col(2)=ginfo_r<<16|ginfo_g<<8|ginfo_b
    					hsvcolor (grdc+144 \ 192), laybtn_ease(fade.0, fade.1), 255
    					x(3)=objlayer_axis_x +2 : y(3)=objlayer_axis_y2-2 : col(3)=ginfo_r<<16|ginfo_g<<8|ginfo_b
    					gmode 0,,,256 : gsquare -257, x,y,col  ; カーソル描画
    					color 255,255,255 : boxf objlayer_axis_x+4, objlayer_axis_y+4, objlayer_axis_x2-5, objlayer_axis_y2-5  ; 中抜きして枠にする
    					// アイコンが跳ねたような描画位置になるよう調整 (一度_PRESS_INに入ったら_IN→_OUTが終わるまでカウントされる)
    					if layerbtn_stat & LAYBTN_PRESS_IN {
    						if layerbtn_cnt <= 5 {
    							pos objlayer_axis_x+25, objlayer_axis_y+25-laybtn_ease(0, 13)  ; 5フレーム上にあげる
    						}else {
    							pos objlayer_axis_x+25, objlayer_axis_y+25-laybtn_ease(13, 0, 5, ease_bounce_out)  ; 残りのフレームをバウンド落下
    						}
    					}
    					swbreak
    				swend
    				// アイコン描画
    				if objlayer_option < 3 {
    					gmode 3,,,256 : celput cel_ico, objlayer_option
    				}else {
    					font msgothic, 12 : color 255 : laybtn_mes "FPS\n"+(60>>fps2),0, 1,1, ,ginfo_cy-(objlayer_axis_y+25)
    				}
    				// テキスト描画
    				if (layerbtn_stat & LAYBTN_FOCUS_IN)!=0 || (layerbtn_stat & LAYBTN_PRESS_IN)!=0 {
    					color 0,0,200 : font msgothic, 14  ; laybtn_ezboxのテキスト設定
    					switch objlayer_option
    					case 0 : laybtn_mes "左ボタン表示/非表示",0, 1,1, 0,40 : swbreak
    					case 2 : laybtn_mes "左ボタン有効/無効",0, 1,1, 0,40 : swbreak
    					case 3 : laybtn_mes "FPS切り替え(60/30/15/7)",0, 1,1, 0,40 : swbreak
    					default :
    						laybtn_mes "1つ目のボタンにフォーカス",0, 1,1, 0,40
    						laybtn_mes "(キー入力でもフォーカス移動と決定が可能)",0, 1,1, 0,54
    						swbreak
    					swend
    				}

    				// ボタンのクリック判定 (設定:マウスクリック即ボタン決定)
    				if layerbtn_stat == LAYBTN_PRESS_IN_SELECTED {
    					log += "shita - SELECTED! opt="+objlayer_option+" wparam="+wparam +"\n"
    					switch objlayer_option
    					case 0 : if laybtn_length(0) != 0 { laybtn_hide 0 }else{ gosub *create_button_hidari } : swbreak
    					case 1 : objsel hidari_fobj : swbreak
    					case 2 : laybtn_enable 0, -1 : laybtn_enable 0, 1 - stat : swbreak
    					case 3 : fps2++ : fps2 \= 4 : swbreak
    					swend
    				}
    			}
    			return
    		}
    	loop
    	return