Enter into viewer state/context of a node inside an HDA

   7774   18   5
User Avatar
Member
75 posts
Joined:
Offline
I have a node I'm trying to build where I'd like to switch between several group pick types (using prim number, using bounding geometry, and group by lasso)
Each is set up in with its own internal node to do the grouping.

Is there a way from the top level of an HDA to set the viewer state to a specific internal nodes existing viewer state? instead of having to write a new one from scratch?

For example if I have my HDA's “mode” set for bounding geometry, I'd like to be able to press enter in the viewport and have the viewer state jump into the state of my bounding geometry “group” node that gives me the handles of the bounding sphere to edit. then I can hit escape and jump back out again.

Or is the only way to do this sort of thing, either..
to write your own custom viewer state and hook it all up to the nodes inside,
or to specifically set the node via python.. node.setCurrent() and then you have to navigate back out again after you're done editing?

thanks in advance

-john
User Avatar
スタッフ
396 posts
Joined: 2月 2018
Offline
If I understand you have an HDA with several inner HDA nodes, where each is binding specific handles like a bounding box ? If you have a python state set for each of these nodes, then you could just invoke the state with hou.SceneViewer.setCurrentState. You don't need to write a specific state for each node, you can just implement one in your top HDA node and set the inner nodes Default State with the name of the state.
User Avatar
Member
75 posts
Joined:
Offline
Thanks for the response!

Will hou.SceneViewer.setCurrentState work if i wanted to set the state to an internal group_create node's bounding box/bounding_sphere handle state? Or does it have to be a python programmed state? Since the group_create node doesn't have any python code to define the name of the state, how do I find the available states of a compiled (non HDA) node, so I can use it within python commands? (or is that not available/allowed?)

thanks!
-john
User Avatar
スタッフ
396 posts
Joined: 2月 2018
Offline
setCurrentState works with any state, builtin or python states. Each HDA node should have an implicit state set with the HDA node's name. If you don't need a specific python state, you can just call setCurrentState with the HDA node name or select the HDA node and hit enter in the viewer.
User Avatar
Member
75 posts
Joined:
Offline
Hi again, back at this on a new HDA. I still haven't gotten this working unfortunately.

I want the default "enter" key state for my wrapper HDA to invoke the state of the internal pathdeform node,
so I can get the handles that the pathDeform node has to slide / scale an object down the path.

The simplest thing, putting "pathdeform" in the default state in my wrapper HDA doesn't work, I've seen this work however with the "stroke" node? so why is it not working with pathdeform?

I also tried making my own State in my wrapper HDA, using the simple keyboard template, and setting the onEnter to do
hou.SceneViewer.setCurrentState(self.scene_viewer,"pathdeform") or
self.scene_viewer.setCurrentState("pathdeform")
and I even tried to pass the setCurrentState the nodeObject of the pathdeform node inside my HDA

Nothing has worked thus far, and I don't know what else to try. It seems that the "state" its looking for is a string/char? is that correct?

So far the only thing I've gotten some success with is setting the actual selected node to the pathdeform node on enter or from another GUI button I created.. this sets the selected node to the pathdeform node inside and allows the handles to be drawn.
Its not ideal however because It switches the parm window as well. Ideally i'd like it to work like the stroke sop/paint attributes HDA does.. where the wrapper HDA just shows the state/context of the node you want that's wired inside.

Any ideas as to what I'm doing wrong here?
Thanks

-johnc
User Avatar
Member
122 posts
Joined: 6月 2019
Online
Here: https://vimeo.com/375839266 [vimeo.com] (from 53:45 mark) Jeff Lait explains how to expose state to the parent hda. The whole video is actually worth watching if you're interested in states, because it's more about the tool development rather than attribute paint.

It involves exposing all the parameters from the node to the hda level (technically you need only the parameters the state controls but it's safer to expose all of them)

Though I'm not sure if it will work with path deform in particular. The state is just an interface to change node's parameters. In a way it doesn't care what node it manipulates, it just needs that node has particular parameters. However state can rely on nodes children which path deform state actually does for guide geometry. So this dependency probably will be broken after exposing.
Edited by elovikov - 2021年4月2日 05:52:14
User Avatar
Member
75 posts
Joined:
Offline
Thanks for the video link! It was helpful to see how its done with the Attrib-paint however it seems its a bit trickier with the node I'm trying to use, pathdeform hopefully I'll figure out the right combination at some point.
User Avatar
Member
75 posts
Joined:
Offline
Ah.. I FINALLY got it working! This may not be the easiest way, but it does work! So as in the video,
I used the "import block" to pull in all the attributes from the pathdeform node.

Then to get the handles and all the drawables to work, promoted up..
I ended up copying the whole python state, from the pathdeform to my HDA and then
I finally figured out that it needed to point at the nodes from within the pathdeform to do a lot of the drawables and custom handles. so I just did a search for anything with node.node("<nodename>") and tagged in "pathdeform1/<nodename>"
and it all works like a treat!

Thanks all for the help. If anyone has other ideas or ways for this to work differently feel free to keep chiming in!

-johnc
User Avatar
Member
53 posts
Joined: 9月 2018
Offline
I have the same problem, but I am trying to access the viewer state of capturelayerpaint node within my HDA.
None of the solutions given above works. Any ideas, how to do it?
User Avatar
スタッフ
396 posts
Joined: 2月 2018
Offline
wolskikrzys
I have the same problem, but I am trying to access the viewer state of capturelayerpaint node within my HDA.
None of the solutions given above works. Any ideas, how to do it?
If you mean binding the capturelayerpaint state to your HDA it's usually done by setting the Default State field with the state name.
User Avatar
Member
10 posts
Joined: 6月 2017
Offline
I have seen the examples where the Default State is set on an HDA, but is it possible to access multiple viewer states from internal nodes of an HDA? For example, I want to draw a curve using Draw Curve, and then also be able to paint weights later in the network using a Capture Layer Paint. Ideally, I could press buttons to enter these different states from the top level of the HDA.

Is it possible to do this?
User Avatar
スタッフ
396 posts
Joined: 2月 2018
Offline
The HOM API hou.SceneViewer.setCurrentState lets you enter a specific state. You could simply create shelf tools or HDA buttons to enter different states.
User Avatar
Member
10 posts
Joined: 6月 2017
Offline
I have switching states working with buttons, but there are some things to keep in mind. For most built in tools, the viewer state is using onEnter to initialize variables for the state, but if you use a button to switch states, you need onGenerate to do these things. This means that many built in states are inaccessible without editing the original state and resaving as a new state. To be clear, I am not changing the default state of the HDA to match an existing one. I want to use buttons to switch between multiple states for nodes within the HDA.

After trying many things I still can't get the capturelayerpaint state to load with the drawables visible in the viewport. It would be great if you could share some way to make this possible since it is an extremely useful state to be able to enter from the HDA. There are workarounds, but all of them seem to rely on the HDA being unlocked.
User Avatar
スタッフ
396 posts
Joined: 2月 2018
Offline
Just to be clear hou.SceneViewer.setCurrentState can be used to enter node base and nodeless states. For node base states, onEnter is called and for nodeless states it's onGenerate. So it's really up to the state to implement the right handler.
Edited by mabelzile - 2021年12月7日 09:06:01
User Avatar
Member
251 posts
Joined: 7月 2013
Offline
Running into some issues as well.. Trying to get an HDA to use the viewstate of a kinefx::mappoints node that's inside the HDA.

Promoted everything up as in the vimeo link, set the default view state in the hda to 'kinefx__mappoints' but this will only work for very simple viewstates.. any viewstate that uses any type of kwargs will endup with the wrong input.


This for example, this is the onEnter handler from \packages\kinefx\viewer_states\kinefx__mappoints.py:

def onEnter(self, kwargs):
        self.node = kwargs["node"]
        self.target_node = self.node.node("TARGET")
        self.source_node = self.node.node("SOURCE")
        self.target_geo_ref = self.target_node.geometry()
        self.source_geo_ref = self.source_node.geometry()

Normally the kwargs["node"]will yield the mappoints node, but when triggered through the HDA it will give the HDA itself as node and things will fall apart downstream in the code.

I could make a copy if the viewstate py etc and modify it but I'd rather not since it's a hassle and rather leverage the one that ships with, and will works with, what ever the current version of kinefx::mappoints is.

So what's the best approach here?
Edited by Jonathan de Blok - 2022年4月4日 03:26:23
More code, less clicks.
User Avatar
Member
251 posts
Joined: 7月 2013
Offline
#hacktheplanet.. The default viewstate python expects a few nodes to be present relative to the node from kwargs, which is my HDA, so I've put them there using merge object nodes that get their content from the default mappoints node. That, and copy/pasting/changing a bit of python from the mappoints' PyhtonModule to my own HDA made it work. I can now map points directly from my HDA using the normal viewstate. All nice, but needless to say this workflow could use some attention

Edited by Jonathan de Blok - 2022年4月4日 03:58:53

Attachments:
vs.png (42.8 KB)

More code, less clicks.
User Avatar
Member
1 posts
Joined: 7月 2022
Offline
Any updates on this workflow?

I tried some different approaches without much success.
1) Promoting all parameters to the parent HDA + set default_state to child state.
- sidefx_attribpaint state: works apart from not having the hudInfo.
- curve::2.0 state: kinda works but there is definitely something wrong

2) Using a button on my parent HDA I do: scene_viewer.setCurrentState("sidefx_attribpaint").
This does access the state (hudInfo is still missing). But when I trigger an onMouseEvent(), it complains about kwargs not containing a node key. The context in which this code is triggered (HDA module) is obviously different from when you activate the state by pressing "Enter" in the viewport. But I would still expect kwargs to contain the same keys/values, otherwise this doesn't seem possible at all.

3) I tried running method 2 but I tried changing hou.ScriptEvalContext(node). This function changes hou.pwd(). So I thought running hou.ScriptEvalContext(childNode)and afterwards doing setCurrentState(childState) would make it so kwargs would be the child node and not the parent HDA when running the viewerState. But this didn't work either.

Thinking about it further, it seems that the problem is just the context in which the viewerState is activated. Kwargs should return the parent node when accessing UI parameters on it directly (node.parm()). This way the viewerState can still change UI parms on the parent HDA. Every other occasion, kwargs should be the child node so node.node() returns a node inside of the childNode instead of the parentNode. This would make sure no code in the viewerstate that relies on relative referencing nodes would be broken. It seems that some viewerStates are already being build smarter as the attribpaint state already has something like this:

This returns the correct attribpaint node if the state is ran from a parent HDA.

I hope these problems gets adressed soon because this would open up so many more possibilities for HDA's and custom viewer states.
Edited by Jeroen_Neopica - 2022年11月30日 02:48:12

Attachments:
image_2022-11-29_160107157.png (28.8 KB)

User Avatar
Member
44 posts
Joined: 3月 2023
Offline
Hello evryone I`m trying to set the default state for an USD lops instancer wrapper to be the add1 node at `HDA/instancer1/add1`

Is this possible and whould annyone

Attachments:
lop_nanghe.dev.example.1.0.hdalc (16.9 KB)

User Avatar
Member
10 posts
Joined: 3月 2018
Offline
Any updates on this? This is the only thread I can find on this topic.
I can manage to change the state in the Default State option, but when I want to dynamically switch state using setCurrentState it changes the state according to the name in the top left corner but it doesn't actually show or do anything. Even with something simple as a state that just shows a transform handle.
  • Quick Links