Last active
August 11, 2020 16:50
-
-
Save Eterea/95d5d934b765c312abff35e86e6c3f98 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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