Poser覚書> Poser操作 > スクリプト

インバースキネマティクスをGUIでオン・オフするミニツール IK Switch

 Poserのインバースキネマティクスをオン・オフするツールをwxPythonで作った。

 味もそっけもない外観。まあ、半分練習みたいなもんだからいいや。

ダウンロード&インストール

 Poser8、PoserPro2010限定。Poser8日本語版ではテストしてないが、たぶん動くと思う。

 https://zenryokuhp.com/poser-oboegaki/freestuff/[Zenryoku]IKSW.zip

 解凍して出てくるRuntimeフォルダを、そのままPoserインストールフォルダのRuntimeフォルダに上書きコピーすればOK。

 Poserインストールフォルダ\Runtime\Python\poserScripts\ScriptsMenu\Z enryokuにコピーされ、画面上部の「Scripts」→「Zenryoku」から使うことができる。

使い方

 ボタンを押している状態なら「オン」、押してない状態なら「オフ」で、押すたびにオン・オフが切り替わる(トグル)

 IK ALL ONまたは、IK ALL OFF(押すたびに切り替わる)をクリックで、全てのインバースキネマティクスをオン・オフする。

 ウインドウの位置をドラッグすると自動的にドッキングする。というか、ドッキングしないようには作っていないので、少々うっとおしいかも知れない。

何が嬉しいのか

 ボタンクリックの1アクションでインバースキネマティクスのオン・オフが可能。ポージングの際に、インバースキネマティクスのオン・オフを頻繁に切り替える人にとっては少し嬉しいんじゃないだろうか。

ソースコード

 世の中にはPoser用wxPythonの例が少なすぎて悲しくなったので、ソースコードを公開しておこう。Poserのイベントコールバックを指定しているせいか、他のPythonスクリプトと同時に使うと落ちるかも知れない。気をつけて欲しい。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import wx
import wx.aui
import poser

class MyPanel(wx.Panel):
    def __init__(self, *args, **kwds):
        wx.Panel.__init__(self, *args, **kwds)

        self.IK_ALL = wx.ToggleButton(self, 10, "IK ALL ON")
        self.IK1 = wx.ToggleButton(self, 1, "-")
        self.IK2 = wx.ToggleButton(self, 2, "-")
        self.IK3 = wx.ToggleButton(self, 3, "-")
        self.IK4 = wx.ToggleButton(self, 4, "-")

        self.__set_properties()
        self.__do_layout()

        self.Bind(wx.EVT_TOGGLEBUTTON, self._IKhandler, self.IK_ALL)
        self.Bind(wx.EVT_TOGGLEBUTTON, self._IKhandler, self.IK1)
        self.Bind(wx.EVT_TOGGLEBUTTON, self._IKhandler, self.IK2)
        self.Bind(wx.EVT_TOGGLEBUTTON, self._IKhandler, self.IK3)
        self.Bind(wx.EVT_TOGGLEBUTTON, self._IKhandler, self.IK4)
        self.ikbuttons = [self.IK1, self.IK2, self.IK3, self.IK4]

        figure = scene.CurrentFigure()
        self.set_buttons(figure)

    def __set_properties(self):
        pass

    def __do_layout(self):
        grid_sizer_1 = wx.GridSizer(5, 1, 0, 0)
        grid_sizer_1.Add(self.IK_ALL, 0, wx.EXPAND, 0)
        grid_sizer_1.Add(self.IK1, 0, wx.EXPAND, 0)
        grid_sizer_1.Add(self.IK2, 0, wx.EXPAND, 0)
        grid_sizer_1.Add(self.IK3, 0, wx.EXPAND, 0)
        grid_sizer_1.Add(self.IK4, 0, wx.EXPAND, 0)
        self.SetSizer(grid_sizer_1)
        self.Layout()

    def _IKhandler(self, event): # wxGlade: MyFrame.<event_handler>
        pushed = event.GetId()
        figure = scene.CurrentFigure()
        if( pushed > 0 and pushed < 5 ):
            figure.SetIkStatus(pushed - 1, event.IsChecked())
        elif ( pushed == 10 ):
            if event.IsChecked():
                self.IK_ALL.Label = "IK ALL OFF"
            else:
                self.IK_ALL.Label = "IK ALL ON"

            if event.IsChecked():
                checked = 1
            else:
                checked = 0

            # button push / unpush
            for ik in self.ikbuttons:
                ik.SetValue(event.IsChecked())

            for ik in range(figure.NumIkChains()):
                figure.SetIkStatus(ik, event.IsChecked())
        event.Skip()

    def posercallback(self, iScene, iEventType):
            figure = iScene.CurrentFigure()
            self.set_buttons(figure)

    def set_buttons(self, figure):
        iks = figure.IkNames()
        if( len(iks) == 0):
            for ikb in self.ikbuttons:
                ikb.Label = '-'
                ikb.SetValue(0)
            return

        i = 0
        for ik in iks:
            self.ikbuttons[i].Label = ik
            if( figure.IkStatus(i) == 1 ):
                self.ikbuttons[i].SetValue(1)
            i += 1


def main():
    global scene
    scene = poser.Scene()

    name = "IK Switch"
    man = poser.WxAuiManager()

    root = man.GetManagedWindow()
    for w in root.GetChildren():
        if w.GetLabel() == name:
            if not w.IsShown():
                w = man.GetPane(w).Show()
                man.Update()
            return

    win = MyPanel(root)

    pane = wx.aui.AuiPaneInfo()
    pane.Caption(name).CaptionVisible().CloseButton(True).DestroyOnClose(True)
    pane.Resizable().Float().FloatingSize(wx.Size(200, 200)).BestSize(wx.Size(50, 50))
    man.AddPane(win, pane)
    pane.Show()
    man.Update()

    scene.SetEventCallback(win.posercallback)

main()
del main

関連:
Poser8日本語版情報

次のフィギュアの関節を微妙に動かすスクリプトへ


Poser覚書> Poser操作 > スクリプト もくじ