Jump to content

How can I write a custom shelf tool that gets Key and Mouse events or modifies the ViewerStates?


a41b

Recommended Posts

Hello there,

I'm pretty new in Houdini and want to script a measuring tool that I can use from the tool shelf or via a keyboard shortcut.

So, I want to have the following behavior:

  1. Click shelf button ("ruler")
  2. Select first Point or Edge in Scene View (with edge/point snapping)
  3. Set marker on selected Point/Edge and draw a line with measured text in the scene. The line is the connection between the selected Point and the mouse.
  4. After selecting the second Point, the line, the measure text and markers should be visible for a short time and then vanish.

So my main problem is that I don't know how I get the mouse or keyboard events into my tool script. I only know that I can check for a few key commands (Ctrl, etc). But I want to draw a line and update a distance text field depending on my current mouse position. So how do I get this live interaction? I already checked the tutorials about writing custom viewer states but they are all based on nodes in the network and need to be registered/unregistered at the install/uninstall event. I tried to move the logic of the simple state viewer tutorials into my tool script but was unsuccessful and never managed to receive any custom mouse or key events.

The second thing is more of a workflow issue. How am I supposed to generate the geometry (markers, line, text field) and remove it afterward? Will these new nodes always be added to my network editor or is there a kind of temporary node network for it?

A lot of questions but I hope someone can help me :)

 

P.S. The link shows a measuring tool in use. It's more or less what I'm after
https://www.youtube.com/watch?v=MIcUW9QFMLE&feature=youtu.be&t=299

Link to comment
Share on other sites

It is possible to have nodeless state. See here: https://www.sidefx.com/docs/houdini/hom/state_nodeless.html

The example is a little wrong. Below is an actual working version. You can paste this on a shelf tool.

 

import hou


class ScrubState(object):
    def __init__(self, scene_viewer, state_name):
        self.state_name = state_name
        self.scene_viewer = scene_viewer
        self._base_x = self._base_frame = None

    def onGenerate(self, kwargs):
        self.scene_viewer.setPromptMessage(
            "Drag left/right to scrub along timeline"
        )

    def onExit(self, kwargs):
        self.scene_viewer.clearPromptMessage()

    def _scrub_abs(self, x):
        # Take the absolute position of the mouse pointer (as a percentage
        # of the total viewer width) and move that far along the current
        # frame range

        width, _ = self.scene_viewer.contentSize()
        pct = x / float(width)
        start_frame, end_frame = hou.playbar.frameRange()
        frame = int((end_frame - start_frame) * pct + start_frame)
        hou.setFrame(frame)

    def _scrub_rel(self, x):
        # Use the difference between the mouse pointer's current position
        # and the previous position to calculate how many frames to move
        # forward/back

        if self._base_x is not None:
            delta = int((x - self._base_x) / 10.0)
            frame = max(0, self._base_frame + delta)
            hou.setFrame(frame)
        else:
            self._base_x = x
            self._base_frame = hou.intFrame()

    def onMouseEvent(self, kwargs):
        device = kwargs["ui_event"].device()
        if device.isLeftButton():
            x = device.mouseX()
            if kwargs["mode"] == "abs":
                self._scrub_abs(x)
            elif kwargs["mode"] == "rel":
                self._scrub_rel(x)
        else:
            self._base_x = None


template = hou.ViewerStateTemplate("scrub", "Scrub", hou.objNodeTypeCategory())
template.bindFactory(ScrubState)

menu = hou.ViewerStateMenu("scrub", "Scrub")
menu.addRadioStrip("mode", "Mode", "rel")
menu.addRadioStripItem("mode", "rel", "Relative")
menu.addRadioStripItem("mode", "abs", "Absolute")
template.bindMenu(menu)

try:
    hou.ui.registerViewerState(template)
except:
    pass
scene_viewer = hou.ui.paneTabOfType(hou.paneTabType.SceneViewer)
scene_viewer.setCurrentState("scrub")

As for the other questions, it's not really something that can be explained in a single comment. But the documentation, which as you can see, isn't the best, is there. For example, the mouse event is here https://www.sidefx.com/docs/houdini/hom/hou/UIEventDevice.html

 

 

  • Like 1
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...