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.
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.
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?
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).
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
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.
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.
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.
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?
importhouclassState(object):def__init__(self,state_name,scene_viewer):self.state_name=state_nameself.scene_viewer=scene_viewer# Create an empty text drawableself.text_drawable=hou.TextDrawable(self.scene_viewer,'text_drawable_name')# Display the text on the next viewport redrawself.text_drawable.show(True)defonDraw(self,kwargs):# draw the text in the viewport upper lefthandle=kwargs['draw_handle'](x,y,width,height)=self.scene_viewer.curViewport().size()margin=100params={'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)defcreateViewerStateTemplate():""" 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")returntemplatecreateViewerStateTemplate()
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.
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.
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?