Skip to content

Instantly share code, notes, and snippets.

@Eterea
Last active August 11, 2020 16:50
Show Gist options
  • Save Eterea/95d5d934b765c312abff35e86e6c3f98 to your computer and use it in GitHub Desktop.
Save Eterea/95d5d934b765c312abff35e86e6c3f98 to your computer and use it in GitHub Desktop.
#python
# ------------------------------------------------------------------------------------------------
# NAME: etr_super_getSelectedVerts_position.py
# VERS: 1.0
# DATE: August 11, 2020
#
# MADE: Made by Shawn Frueh, shawnfrueh.com/me/
# Shared by Cristobal Vila, etereaestudios.com
# ------------------------------------------------------------------------------------------------
"""
------------------------------------------------------------------------------------------------
SUPER VERTS POSITION CALCULATOR
------------------------------------------------------------------------------------------------
Next pure Python API snippet kindly shared by Shawn Frueh:
https://foundry-modo.slack.com/archives/C6F918JEB/p1596930293212700
THIS IS WHAT REALLY MAKES THIS TOOL SO POWERFULL. A BIG THANKS TO SHAWN FOR THIS!
------------------------------------------------------------------------------------------------
Here is a pure API method that uses the selection service to get all selected points on any object in Modo.
This will include points that are selected even in ghost mode of the procedural stack.
When getting the selection mesh, it should be the "deformed" version that you are seeing in the view-port,
thus working with procedurals. If you want to also handle global positions you will have to multiply the point
by it's items world matix. I hope this helps! Tried to break it down as simple as possible.
I does look like a lot of code but the joy is once you wrap this bad boy up into a package/library
that you just import you never have to worry about it again. That's essentially where this came from.
I have a method that's a bit more advanced than this that also handles the other elements.
"""
import lxu, lx
def fn_get_selVertsPos(world=False):
# Args: world (bool): If true, return the world positions, else return local
# Returns: list(Vector3): List with XYZ positions for each selected vert
# Initialize the selection service
SELECTION_SERVICE = lxu.service.Selection()
# Get the vertex selection int type: 1447383640
vertex_selection_type = SELECTION_SERVICE.LookupType(lx.symbol.sSELTYP_VERTEX)
# Get the selection object: lxu.object.SelectionType
vertex_selection_object = SELECTION_SERVICE.Allocate(lx.symbol.sSELTYP_VERTEX)
# Convert that type into a packet so that we can access the selection data
vertex_packet = lx.object.VertexPacketTranslation(vertex_selection_object)
# Get the total count of selected points
selected_vertex_count = SELECTION_SERVICE.Count(vertex_selection_type)
position_list = []
# Iterate over each point and get some data. These points could be coming from multiple meshes
# and so you will need to check the item they be
for vertex in range(selected_vertex_count):
# Get a pointer to the vertex data in the given index.
vertex_pointer = SELECTION_SERVICE.ByIndex(vertex_selection_type, vertex)
# If we don't get a pointer, skip to the next index in the loop.
# This is necessary to prevent any crashes.
if not vertex_pointer:
continue
# Get the id data from the pointer: ex. 495128304
vertex_id = vertex_packet.Vertex(vertex_pointer)
# Get the item the point belongs to: lxu.object.Item
selection_item = vertex_packet.Item(vertex_pointer)
# Get the matrix channel index
matrix_index = selection_item.ChannelLookup("worldMatrix")
# Prep the selection item to be read at the current time. You want those animated points!
selection_item.ReadEvaluated(SELECTION_SERVICE.GetTime())
# Get the matrix from the channel as a COM object and convert it to a matrix object.
item_world_matrix = lx.object.Matrix(selection_item.ChannelValue(matrix_index))
# Get the mesh item the point belongs to: lxu.object.Mesh
selection_mesh = vertex_packet.Mesh(vertex_pointer)
# Get the point accessor of the mesh item: lxu.object.Point
point_item = selection_mesh.PointAccessor()
# Select the vertex in the accessor so that we can query any Point data.
point_item.Select(vertex_id)
# Get the position of the internally selected point. This point is relative to the mesh
# So if the mesh is not zero you will need to multiply this position by the transform
# data of the item it belongs to.
localPosition = point_item.Pos()
# Get the world position of the point by multiplying it by the world matrix of it's item.
worldPosition = item_world_matrix.MultiplyVector(point_item.Pos())
# Deliver world or local depending on world argument ('true', 'false')
if world:
position_list.append(worldPosition)
else:
position_list.append(localPosition)
return position_list
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment