import hou import stateutils from kinefx import rigapi scene_viewer = stateutils.findSceneViewer() geo = scene_viewer.currentGeometrySelection().nodes()[0].geometry() trans = hou.Matrix4().setToIdentity() parent_pnt = scene_viewer.currentGeometrySelection().selections()[0].points(geo)[0] pnt = rigapi.GeoSkeleton(geo).createPoint(name='point_2', transform=trans, parent=parent_pnt)
Modify Geometry from a shelf tool script?
1836 13 1- traileverse
- Member
- 357 posts
- Joined: Nov. 2015
- Offline
I'm trying to write a script where I select a point in the viewport then and do some stuff that will eventually modify the geometry. But, here the geo is read-only! what could be a solution to this problem, cause it really must be that I modify the geo that already exists. Any tips will be greatly appreciated! Below is very simplified version of what I'm trying to do; of course, it works great in a Python SOP but I want to make it work in a shelf tool script. So, essentially what I want to do is select a kinefx joint/point in the viewport and use info from that point to add another point into the rig.
Edited by traileverse - Aug. 4, 2023 21:39:49
hou.f*ckatdskmaya().forever()
- tamte
- Member
- 8605 posts
- Joined: July 2007
- Offline
the geo has to live somewhere, you can't modify geo that other SOP node owns
if you look at how SideFX builds such tools they are
- either as a viewport script that spawns a corresponding node that can do appropriate action within it's interface
- or you can spawn a node with Geometry Data Parm like Stash SOP or custom one and stash resulting geo on there
- or as a Vewer State belonging to the node
what you are describing sounds like a Skeleton SOP's viewer state
or your shelf tool can spawn new Skeleton SOP and stash the modified geo in it's "stash" data parm, which will not only store the modification but also user will gain ability to further modify it using Skeleton SOP's viewer state
but you can as well just use Stash SOP if you want to use only your shelf tools
if you look at how SideFX builds such tools they are
- either as a viewport script that spawns a corresponding node that can do appropriate action within it's interface
- or you can spawn a node with Geometry Data Parm like Stash SOP or custom one and stash resulting geo on there
- or as a Vewer State belonging to the node
what you are describing sounds like a Skeleton SOP's viewer state
or your shelf tool can spawn new Skeleton SOP and stash the modified geo in it's "stash" data parm, which will not only store the modification but also user will gain ability to further modify it using Skeleton SOP's viewer state
but you can as well just use Stash SOP if you want to use only your shelf tools
Edited by tamte - Aug. 5, 2023 00:18:44
Tomas Slancik
FX Supervisor
Method Studios, NY
FX Supervisor
Method Studios, NY
- traileverse
- Member
- 357 posts
- Joined: Nov. 2015
- Offline
tamte
the geo has to live somewhere, you can't modify geo that other SOP node owns
if you look at how SideFX builds such tools they are
- either as a viewport script that spawns a corresponding node that can do appropriate action within it's interface
- or you can spawn a node with Geometry Data Parm like Stash SOP or custom one and stash resulting geo on there
- or as a Vewer State belonging to the node
what you are describing sounds like a Skeleton SOP's viewer state
or your shelf tool can spawn new Skeleton SOP and stash the modified geo in it's "stash" data parm, which will not only store the modification but also user will gain ability to further modify it using Skeleton SOP's viewer state
but you can as well just use Stash SOP if you want to use only your shelf tools
This is very helpful tamte, so what I want is a tool that allows me to do animatable pivots without littering the scene with helper nodes; so essentially I was thinking to have two shelve scripts, when the user clicks the first one they can move a newly created helper joint to where they want the new pivot location and then the second script would take care setting the new pivot point. During animation a user might need to do this often, so I wouldn’t want the graph littered with nodes to do it. How would you tackle this?
hou.f*ckatdskmaya().forever()
- traileverse
- Member
- 357 posts
- Joined: Nov. 2015
- Offline
- DyktaT
- Member
- 6 posts
- Joined: Aug. 2023
- Offline
Here's a basic outline of how you could structure your script to achieve your goal:
create_point_on_selected()
The above script assumes that you've created a shelf tool that executes the script when clicked. The create_point_on_selected function checks for selected nodes, selects the first point, and creates a new point using the rigapi library. Remember to adjust the script according to your specific requirements and the structure of your rig.
Tell me if this is working for you.
def create_point_on_selected(): selected_nodes = hou.selectedNodes() if len(selected_nodes) > 0: selected_geo = selected_nodes[0].geometry() selected_points = selected_geo.globPoints('*') if len(selected_points) > 0: parent_point = selected_points[0] trans = hou.Matrix4().setToIdentity() new_point = rigapi.GeoSkeleton(selected_geo).createPoint(name='point_2', transform=trans, parent=parent_point) new_point.setPosition([0, 1, 0]) # Modify position as needed hou.ui.displayMessage("New point created and modified.") else: hou.ui.displayMessage("No points selected in the geometry.") else: hou.ui.displayMessage("No nodes selected.")
The above script assumes that you've created a shelf tool that executes the script when clicked. The create_point_on_selected function checks for selected nodes, selects the first point, and creates a new point using the rigapi library. Remember to adjust the script according to your specific requirements and the structure of your rig.
Tell me if this is working for you.
- traileverse
- Member
- 357 posts
- Joined: Nov. 2015
- Offline
DyktaT
Here's a basic outline of how you could structure your script to achieve your goal:create_point_on_selected()def create_point_on_selected(): selected_nodes = hou.selectedNodes() if len(selected_nodes) > 0: selected_geo = selected_nodes[0].geometry() selected_points = selected_geo.globPoints('*') if len(selected_points) > 0: parent_point = selected_points[0] trans = hou.Matrix4().setToIdentity() new_point = rigapi.GeoSkeleton(selected_geo).createPoint(name='point_2', transform=trans, parent=parent_point) new_point.setPosition([0, 1, 0]) # Modify position as needed hou.ui.displayMessage("New point created and modified.") else: hou.ui.displayMessage("No points selected in the geometry.") else: hou.ui.displayMessage("No nodes selected.")
The above script assumes that you've created a shelf tool that executes the script when clicked. The create_point_on_selected function checks for selected nodes, selects the first point, and creates a new point using the rigapi library. Remember to adjust the script according to your specific requirements and the structure of your rig.
Tell me if this is working for you.
thanks for taking the time to put this together @DyktaT, my problems at the moment though are more UI based. One issue I'm having now that I didn't realize before is that when I'm in the viewer state of a rigpose SOP and select a joint, Houdini doesn't recognize it as a point selection, so any ideas for how to turn the rigpose state selections into actual point selections would be very helpful. Is there a way to get either a hou.Selection or hou.Point object from a joint selection made via rigpose viewer state?
hou.f*ckatdskmaya().forever()
- traileverse
- Member
- 357 posts
- Joined: Nov. 2015
- Offline
I tried stashing the geo, but this still gave me an error the geometry is read-only! My understanding of modifying geo from shelf tool is still fuzzy. What's the next move I can try here?
import hou import stateutils from kinefx import rigapi, stateutils as kstateutils scene_viewer = stateutils.findSceneViewer() node_to_stash = hou.selectedNodes()[0] geo = hou.selectedNodes()[0].geometry() parent_pnt = scene_viewer.currentGeometrySelection().selections()[0].points(geo)[0] pnt_pos_mat = hou.hmath.buildTranslate(parent_pnt.attribValue('P')) node = hou.node('obj/geo1').createNode('stash') node.setInput(0, node_to_stash) set_stash = node.parm('stashinput').pressButton() node.setInput(0, None) new_geo = node.geometry() jnt_name = 'pivot_helper' helper_jnt = rigapi.GeoSkeleton(new_geo).createPoint(name=jnt_name, transform=pnt_pos_mat, parent=parent_pnt)
hou.f*ckatdskmaya().forever()
- tamte
- Member
- 8605 posts
- Joined: July 2007
- Offline
Here is one example of storing geometry in Stash SOP's data parameter using Python
https://www.sidefx.com/forum/topic/74110/#post-313189 [www.sidefx.com]
https://www.sidefx.com/forum/topic/74110/#post-313189 [www.sidefx.com]
Tomas Slancik
FX Supervisor
Method Studios, NY
FX Supervisor
Method Studios, NY
- traileverse
- Member
- 357 posts
- Joined: Nov. 2015
- Offline
tamteNice, thank you! I have one other issue now; Is there a way to get the point or geometry from a viewport selection of a joint when using the rigpose SOP? the actual point is not selected when using the rigpose viewer state.
Here is one example of storing geometry in Stash SOP's data parameter using Python
https://www.sidefx.com/forum/topic/74110/#post-313189 [www.sidefx.com]
hou.f*ckatdskmaya().forever()
- traileverse
- Member
- 357 posts
- Joined: Nov. 2015
- Offline
So, I've been trying a few things to get access to a point/joint from a rigpose viewstate selection. Absolutely no luck; the selection is coming back as a None type even though I have joints selected in the viewport. Anyone who has accomplished this, please throw an assist my way! really appreciate it.
import hou import stateutils import sys from kinefx import rigapi, stateutils as kstateutils from kinefx.ui import basestate, rigtreeutils from kinefx__skeletonstate import state as kskelstate import importlib.util import sys spec = importlib.util.spec_from_file_location("kinefx_rig_pose", "C:/Program Files/Side Effects Software/Houdini 19.5.700/packages/kinefx/viewer_states/kinefx__rig_pose.py") foo = importlib.util.module_from_spec(spec) sys.modules["kinefx_rig_pose"] = foo spec.loader.exec_module(foo) scene_viewer = stateutils.findSceneViewer() slct_node_geo = hou.selectedNodes()[0].geometry() #rigtree_state = basestate.KinefxViewerState(state_name = scene_viewer.currentState(), scene_viewer = scene_viewer) #kinefx_select = kstateutils.KinefxSelection(geo=slct_node_geo, selection=rigtree_state.selection) rig_pose_slct = foo.PoseRigState(state_name = scene_viewer.currentState(), scene_viewer = scene_viewer).active_selection() print(scene_viewer.currentState()) print(rig_pose_slct)
hou.f*ckatdskmaya().forever()
- traileverse
- Member
- 357 posts
- Joined: Nov. 2015
- Offline
- SWest
- Member
- 313 posts
- Joined: Oct. 2016
- Offline
Please clarify, is it not so when you use rigpose SOP and select a skeleton joint that it automatically appends it to the node groups?
If so, can't you just get the name of your point from the groups?
If so, can't you just get the name of your point from the groups?
Interested in character concepts, modeling, rigging, and animation. Related tool dev with Py and VEX.
- traileverse
- Member
- 357 posts
- Joined: Nov. 2015
- Offline
SWestyeah, that makes sense, but I only want the group of the point selected by the user in the viewport, the rigpose sop would have already beed preloaded with all the point groups in the rig. When I select a point via rigpose, it doesn’t register as a point selection.
Please clarify, is it not so when you use rigpose SOP and select a skeleton joint that it automatically appends it to the node groups?
If so, can't you just get the name of your point from the groups?
Maybe the question is how to get the point name from the rigpose viewport selection?
Edited by traileverse - Aug. 9, 2023 07:50:51
hou.f*ckatdskmaya().forever()
- traileverse
- Member
- 357 posts
- Joined: Nov. 2015
- Offline
got some help from sidefx on this:
The selected set of joints in the rig pose state is tracked by the state itself so there is no parameter that can be referenced but there is a state command named "getSelections" that is used by the Rig Tree to access the group.
The following function should be able to get a dictionary of selections from the Rig Pose state given the hou.SceneViewer object:
def getStateSelection(scene_viewer):
kwargs = {}
scene_viewer.runStateCommand("getSelections", kwargs)
if 'ret' not in kwargs or not kwargs:
# The command did not run successfully
return {}
selections = kwargs
return selections
The returned selection is a dictionary which maps node paths in the HDA to lists of point indices in the selection on that node's geometry.
The Rig Pose viewer state is a bit of a unique case among the KINEFX viewer states since it can operate on HDAs which contain many Rig Pose nodes.
For the other viewer states that interact with the rig tree, there is a similar state command named getselection.
This command just returns a list of point indices on the input geometry that are selected. This selection can be accessed with kwargs.
It worked like a charm for my purposes!
The selected set of joints in the rig pose state is tracked by the state itself so there is no parameter that can be referenced but there is a state command named "getSelections" that is used by the Rig Tree to access the group.
The following function should be able to get a dictionary of selections from the Rig Pose state given the hou.SceneViewer object:
def getStateSelection(scene_viewer):
kwargs = {}
scene_viewer.runStateCommand("getSelections", kwargs)
if 'ret' not in kwargs or not kwargs:
# The command did not run successfully
return {}
selections = kwargs
return selections
The returned selection is a dictionary which maps node paths in the HDA to lists of point indices in the selection on that node's geometry.
The Rig Pose viewer state is a bit of a unique case among the KINEFX viewer states since it can operate on HDAs which contain many Rig Pose nodes.
For the other viewer states that interact with the rig tree, there is a similar state command named getselection.
This command just returns a list of point indices on the input geometry that are selected. This selection can be accessed with kwargs.
It worked like a charm for my purposes!
hou.f*ckatdskmaya().forever()
-
- Quick Links