How to draw text in the viewport regardless of viewer state?

   7725   20   3
User Avatar
Member
146 posts
Joined: 9月 2011
Offline
I'm working with music, and I'd like to put beats and bars in the corner of the viewport. Not dissimilar to the fps/render time display you can enable with Display Options > Guides > Show Time.

I've got an external MIDI display working by registering a callback with hou.playbar.addEventCallback() so I imagine I'd need to take a similar approach, but how do I actually write a string of text to the viewport?

The only clues I've got are the custom viewer state examples in the docs; there's a text_drawable object I could create but I'm not sure how to actually tie its draw function into things.

Suggestions etc appreciated
User Avatar
スタッフ
396 posts
Joined: 2月 2018
Offline
You need to write a python state for drawing text in the viewport. Use the code generator to create a blank python state and use viewerstate.utils.HUD to add your text. There is an example in $HH/viewer_states/examples/state_dragdrop_demo.hip to demonstrate how to use it.
User Avatar
Member
146 posts
Joined: 9月 2011
Offline
This seems to create a new viewer state though - ie the text will disappear the moment I exit it, say, by hitting Escape to go into viewport navigation mode, or Enter to use a handle/manipulator.

I'm trying to create a persistent UI element, independent of viewer state: is this not possible with Python?
User Avatar
Member
620 posts
Joined: 11月 2013
Online
Hi,

You can add The OGL Viewport Comment (vcomment) property to camera from render properties section of spare parameter editor.
User Avatar
Member
146 posts
Joined: 9月 2011
Offline
Ha! That's spectacular. I'd never have guessed that existed… crikey, I'm going to be using that for all sorts of feedback now. Thanks!
User Avatar
スタッフ
396 posts
Joined: 2月 2018
Offline
howiem
This seems to create a new viewer state though - ie the text will disappear the moment I exit it, say, by hitting Escape to go into viewport navigation mode, or Enter to use a handle/manipulator.

I'm trying to create a persistent UI element, independent of viewer state: is this not possible with Python?

You can write a nodeless python state that can run in multiple contexts. But yea you currently need a python state, there is a bug logged however to draw text in the viewport (via a callback probably).
User Avatar
Member
146 posts
Joined: 9月 2011
Offline
Cool. A TC/beats display may as well have its own pane you can put where you like, rather than being in the viewport, but this'll do me nicely until I get time to learn some Houdini-UI skillz
Edited by howiem - 2020年3月17日 09:07:13

Attachments:
Screenshot from 2020-03-17 13-02-04.png (178.1 KB)

User Avatar
スタッフ
396 posts
Joined: 2月 2018
Offline
Or if you feel like extending the HDK you can write a scene hook.

There is an example here:
$SHT/samples/DM/DM_SceneBoundsHook.C

But a python hook would make sense.
User Avatar
Member
4484 posts
Joined: 2月 2012
Offline
mabelzile
nodeless python state that can run in multiple contexts.

Is there an example of "nodeless python state that can run in multiple contexts."? I want to show some text over the viewport regardless of context, something like the cook time/FPS so that should allow at least using a larger font and offseted from one of the corners of the viewport.

Is this possible?
Senior FX TD @ Industrial Light & Magic
Get to the NEXT level in Houdini & VEX with Pragmatic VEX! [www.pragmatic-vfx.com]

youtube.com/@pragmaticvfx | patreon.com/animatrix | animatrix2k7.gumroad.com
User Avatar
スタッフ
396 posts
Joined: 2月 2018
Offline
To setup a multi-context state you just need to pass an array of contexts to the ViewerStateTemplate [www.sidefx.com] constructor. You ca use a text drawable or resourceutils.HUD to draw text, both supports hou.drawableTextOrigin for placing the text.
User Avatar
Member
4484 posts
Joined: 2月 2012
Offline
Thanks for replying. But there is no way to query the corner of a viewport, right? I just have to hard code the position?
Senior FX TD @ Industrial Light & Magic
Get to the NEXT level in Houdini & VEX with Pragmatic VEX! [www.pragmatic-vfx.com]

youtube.com/@pragmaticvfx | patreon.com/animatrix | animatrix2k7.gumroad.com
User Avatar
Member
731 posts
Joined: 12月 2006
Offline
jerry7
Hi,

You can add The OGL Viewport Comment (vcomment) property to camera from render properties section of spare parameter editor.

This is cool! Any way to creat a line break though? I tried adding "\n" and even "\\n" and (GAD!) "\\\n" and no dice.

EDIT: Actually, putting the text in a python SOP with line breaks, then using this as a channel ref works. It's a bit ugly though.
Edited by mrCatfish - 2021年3月26日 11:22:10
Sean Lewkiw
CG Supervisor
Machine FX - Cinesite MTL
User Avatar
スタッフ
396 posts
Joined: 2月 2018
Offline
animatrix_
Thanks for replying. But there is no way to query the corner of a viewport, right? I just have to hard code the position?
There is no query API for that. hou.GeometryViewport.size() returns the viewport size (x,y,w,h) in UI space. You could use it to compute the corners but unfortunately there is a bug as the returned x,y origin is always 0,0... We have hou.GeometryViewport.viewerGeometry() in beta that returns the viewport geometry size (x,y,w,h) relative to the viewer origin in the UI space.
User Avatar
Member
4484 posts
Joined: 2月 2012
Offline
I put this together from the help but I can't get anything to show up at the obj level for example. I run the code using the Python SOP for testing first.

Am I missing something?

import hou

class State(object):       
    def __init__(self, state_name, scene_viewer):
        self.state_name = state_name
        self.scene_viewer = scene_viewer

        # Create an empty text drawable
        self.text_drawable = hou.TextDrawable(self.scene_viewer, 'text_drawable_name')

        # Display the text on the next viewport redraw
        self.text_drawable.show(True)

    def onDraw( self, kwargs ):
        # draw the text in the viewport upper left
        handle = kwargs['draw_handle']

        (x,y,width,height) = self.scene_viewer.curViewport().size()
        margin = 100
        params = { 
            'text': 'First line<br>Second line<br>Third line',
            'multi_line' : True,
            'color' : hou.Color(1.0,0.0,0.0),
            'translate' : hou.Vector3(0, height, 0),
            'origin' : hou.drawableTextOrigin.UpperLeft,
            'margins': hou.Vector2(margin, -margin) }

        self.text_drawable.draw( handle, params )
        
def createViewerStateTemplate():
    """ Mandatory entry point to create and return the viewer state 
        template to register. """

    state_typename = "statedemo"
    state_label = "Statedemo"
    state_cat = hou.objNodeTypeCategory()

    template = hou.ViewerStateTemplate(state_typename, state_label, state_cat)
    template.bindFactory(State)
    template.bindIcon("MISC_python")

    return template
    
createViewerStateTemplate()
Senior FX TD @ Industrial Light & Magic
Get to the NEXT level in Houdini & VEX with Pragmatic VEX! [www.pragmatic-vfx.com]

youtube.com/@pragmaticvfx | patreon.com/animatrix | animatrix2k7.gumroad.com
User Avatar
Member
122 posts
Joined: 6月 2019
Offline
animatrix_
I put this together from the help but I can't get anything to show up at the obj level for example. I run the code using the Python SOP for testing first.

Am I missing something?


I don't think you can register the state from Python SOP. You still need either create a state from Viewer State Browser or just create a .py file in viewer_states directory (either in your package or $HFS/houdini). In this file you don't have to call createViewerStateTemplate() (I think this is just a method exposed for states factory)

couple of things:
1. "color" param is not supported for TextDrawable (should be "color1")
2. afaik you still need to enter the state (ie call somewhere toolutils.sceneViewer().setCurrentState("statedemo")). it's not like a permanent hook to inject additional drawables.
User Avatar
Member
4484 posts
Joined: 2月 2012
Offline
Thanks for replying. I thought it would be permanent, because I want me text to be visible in the viewport permanently like the FPS display.

If color is not supported the help file should be fixed
Senior FX TD @ Industrial Light & Magic
Get to the NEXT level in Houdini & VEX with Pragmatic VEX! [www.pragmatic-vfx.com]

youtube.com/@pragmaticvfx | patreon.com/animatrix | animatrix2k7.gumroad.com
User Avatar
スタッフ
396 posts
Joined: 2月 2018
Offline
animatrix_
createViewerStateTemplate()
you are missing a call to registerViewerState in your code

e.g.
hou.ui.registerViewerState(createViewerStateTemplate())

And yes you need to enter the state to take effect.

You're right the text drawable example in the doc is wrongly using the color parameter
Edited by mabelzile - 2021年3月27日 19:30:22
User Avatar
Member
4484 posts
Joined: 2月 2012
Offline
Thanks a lot! But a python state can always persists? Would another state override it?

In Python SOP I can not test this?

I tried your code:
hou.ui.registerViewerState(createViewerStateTemplate())

It did register it but I didnt see any texts in the viewport.
Senior FX TD @ Industrial Light & Magic
Get to the NEXT level in Houdini & VEX with Pragmatic VEX! [www.pragmatic-vfx.com]

youtube.com/@pragmaticvfx | patreon.com/animatrix | animatrix2k7.gumroad.com
User Avatar
スタッフ
396 posts
Joined: 2月 2018
Offline
Once a state is registered you have to activate it by entering the viewport (enter key) or call hou.SceneViewer.setCurrentState. The running state disappears as soon as you exit (Esc. key in the viewport or by calling hou.SceneViewer.setCurrentState, hou.SceneViewer.enterViewState, etc...). Your state remains registered until you call hou.ui.unregisterViewerState or exit Houdini.
Edited by mabelzile - 2021年3月28日 10:20:07
User Avatar
Member
12 posts
Joined: 6月 2014
Offline
mrCatfish
jerry7
Hi,

You can add The OGL Viewport Comment (vcomment) property to camera from render properties section of spare parameter editor.

This is cool! Any way to creat a line break though? I tried adding "\n" and even "\\n" and (GAD!) "\\\n" and no dice.

EDIT: Actually, putting the text in a python SOP with line breaks, then using this as a channel ref works. It's a bit ugly though.

You can just tick "multiline" on the vcomment parm.


mabelzile
howiem
This seems to create a new viewer state though - ie the text will disappear the moment I exit it, say, by hitting Escape to go into viewport navigation mode, or Enter to use a handle/manipulator.

I'm trying to create a persistent UI element, independent of viewer state: is this not possible with Python?

You can write a nodeless python state that can run in multiple contexts. But yea you currently need a python state, there is a bug logged however to draw text in the viewport (via a callback probably).

Mabelzile, do you have any news regarding a viewport callback in python?
  • Quick Links