モブ沢工房

プログラミングとかLinux関連(特にOSSのグラフィックツール関連)とかレトロゲームとか3Dプリンタやら日曜大工等、色々。

Mypaint 1.2betaでinktoolのノードをキーボードから削除

inktool-なんと聞こえのよい言葉かー!

というかMypaint 1.2 beta。入れてみました。レビューしたいところなのですがとりあえずそれはまた今度…ということで備忘録的に、キーボードからinktoolのノードを消せるようにしてみました。

mypaint 1.2からはinkツールがついて、これがまた「ぼくのかんがえたさいきょうのぺんいれぐらふぃっくそふと」的な機能なのですよ。しかしベータ故にまだ細かいところが作られていない…ゆえに、わざわざマウスポインタを動かしてdelete nodeボタンを押さねばならないという面倒臭さ…

さて、そのinkツールというのは

f:id:dothiko:20151204004722j:plain

このように、描いたストロークをその場で、形状から入力時のペンの傾きから筆圧までも修正可能で、入り抜きを後から好きなように加工可能という、ペンタブ使いのみならずマウサーまで魅了しそうな実に良い機能なのです。

ちなみに今回の記事での改変、まだバグがあるっていうか消しすぎるとエラーが出る(追記、治りました、多分)んですが、とりあえず「突然天変地異が起きてマシンがぶっ壊れて改造途中のソースが失われる」と面倒だな〜とか思ったんで備忘録的にメモ!

まず、mypaintのソースのgui/resources.xmlを改変します。だいたい、723行目ぐらいに以下を挿入

      <child>
        <object class="GtkAction" id="DeleteCurrentNode">
          <property name="label" translatable="yes" context="Menu→Brush (labels), Accel Editor (labels)">Delete current node</property>
          <property name="tooltip" translatable="yes" context="Accel Editor (descriptions)">Delete currently selected node at inking tool.</property>
          <signal name="activate" handler="delete_current_node_cb"/>
        </object>
      </child>

こうしてやることで、mypaint内部で自動的にGtk.Actionオブジェクトが生成されるようになっており、delete_current_node_cbというハンドラを探してバインドしてくれるようになります。

そしてgui/inktool.pyを改変。758行目ぐらい、InkingModeクラスの末尾に次のメソッドを追加。

    def delete_current_node(self):
        if self.can_delete_node(self.current_node_index):
            self.delete_node(self.current_node_index)
            self.target_node_index=None

これで、問答無用で「現在のノード」を削除する機能がとりあえず付きました。追記ですがself.target_node_index=Noneを付加してインデクスエラー例外発生の可能性を完膚なきまでに除去。

適当すぎる処置ですが、とりあえずあまり問題もないし、これでいいのだ。

さらにgui/document.pyも改造。1953行目ぐらい、Documentクラスの末尾に以下のメソッドを追加

    ## Inking tool node manipulation
    def delete_current_node_cb(self, action):
        """Callback: delete currently selected node (from keyboard)"""
        self._delete_current_node()
    
    def _delete_current_node(self):
        mode=self.modes.top
        if getattr(mode, 'delete_current_node', False):
            mode.delete_current_node()

これで、resources.xmlに対応するハンドラができました。

これでMyPaint 1.2 betaを起動、編集→設定を編集で、Delete current nodeにキーを割り当てれば…おおっ!さくさく消せますぞっ!

これができたらgithubでなんかpull request…というのでしょうか?パッチを送るというのをやってみたいなぁ…