MJHD

エモさ駆動開発

HSPにおいてモジュール内部でbuttonを配置して分岐先でthismodを参照する

よくわからないタイトルになってしまった。

例えば

#module mainScreen id, text

#modinit int screenId
  screen screenId, 640, 480
  button gosub "テスト", *button_click@mainScreen

  text = "Hello World!!"
return

#modcfunc get_text
return text

*button_click
  // mes text とはできない
  mes get_text(thismod) // しかし、これも当然エラー
return

#global

こんな感じのコードを動かしたい。
そこで、若干無理矢理ではあるがマクロで真っ黒な黒魔術を使うことにした。

#module mainScreen id, text

#define global new_mainScreen(%1, %2) %tnew_mainScreen \
    if 0 : *%i {\
        _thismod@mainScreen = %1 :\
        gosub *button_click@mainScreen :\
        return } :\
    %i@mainScreen = *%p1 :\
    newmod %1, mainScreen, %2, %o %o0

#modinit int screenId, var dispatcher
  screen screenId, 640, 480
  button gosub "テスト", dispatcher

  text = "Hello World!!"
return

#modcfunc get_text
return text

*button_click
  mes get_text(_thismod@mainScreen) // 参照できる
return

#global

new_mainScreenマクロにより、button命令で分岐すると自動的に_thismod変数へモジュール変数が代入されるようになる。
ただこのままだと、全てのボタンの処理が同じになってしまうため、それぞれのボタンに対して別々の処理を割り当てられるよう、以下のように書き換えた。

#module mainScreen id, text, events

#define global new_mainScreen(%1, %2) %tnew_mainScreen \
    if 0 : *%i {\
        _thismod@mainScreen = %1 :\
        gosub *button_click@mainScreen :\
        return } :\
    %i@mainScreen = *%p1 :\
    newmod %1, mainScreen, %2, %o@mainScreen %o0

#define ctype register_event(%1) %tregister_event \
    events(%1) = *%i :\
    if 0 : *%o


#modinit int screenId, var dispatcher

    dimtype events, vartype("label"), 64

    screen screenId, 640, 480

    button gosub "mes", dispatcher
    register_event(stat) {
        mes get_text(_thismod@mainScreen)
        
        return
    }

    button gosub "dialog", dispatcher
    register_event(stat) {
        dialog get_text(_thismod@mainScreen)

        return
    }

    text = "Hello World!!"
return

#modcfunc get_text
return text

#modfunc dispatch int objid
    gosub events(objid)
return

*button_click
    dispatch _thismod@mainScreen, stat
return

#global

new_mainScreen main, 0

events変数にオブジェクトIDに対応する処理を登録していく。そして、button_clickラベルにおいてそれぞれの処理を呼び出す関数dispatchを実行する。
何かもっといい方法があったらコメントしてください。