Skip to content

Instantly share code, notes, and snippets.

@ivogrig
Last active August 29, 2015 14:22
Show Gist options
  • Save ivogrig/a09e7bc252d951ec5862 to your computer and use it in GitHub Desktop.
Save ivogrig/a09e7bc252d951ec5862 to your computer and use it in GitHub Desktop.
Modo Python API example for skin weight access
# Python API example for skin weight access
# Place this file into an lxserv folder
#
# Creates a command that takes the names of a mesh and a connected joint locator and inverts the weight values
#
# Example command usage:
# example.printJointWeights locator:"Skeleton_Joint (4)" mesh:MyCube
import lx
import lxu
import lxifc
def printJointWeights(jointLocatorName, meshName):
scn_svc = lx.service.Scene()
# Get the scene and the two items by name
scene = lxu.select.SceneSelection().current()
mesh_item = scene.ItemLookup(meshName)
locator_item = scene.ItemLookup(jointLocatorName)
# Set the mesh up
channelWrite = lx.object.ChannelWrite(scene.Channels(lx.symbol.s_ACTIONLAYER_SETUP, 0.0))
channelRead = lx.object.ChannelRead(scene.Channels(None, 0.0))
write_mesh_obj = channelWrite.ValueObj(mesh_item, mesh_item.ChannelLookup(lx.symbol.sICHAN_MESH_MESH))
mesh = lx.object.Mesh(write_mesh_obj)
# We want to find the connected influence deformer using the 'deformers' graph
graph = lx.object.ItemGraph(scene.GraphLookup('deformers'))
desired_type = scn_svc.ItemTypeLookup('genInfluence')
# In the simplest case we can assume that the first found deformer is the influence
deformer = graph.FwdByIndex(locator_item, 0)
# We need the internal name of the weight map to look it up using the meshmap accessor below
mapname = lx.object.WeightMapDeformerItem(deformer).GetMapName(channelWrite)
ui_name = deformer.UniqueName()
lx.out('-' * 80)
lx.out(ui_name)
lx.out(mapname)
# Set up a storage buffer to read the value into
storageBuffer = lx.object.storage('f', 1)
# Loop through all points
for index in range(mesh.PointCount()):
# Create a point- and meshmap accessor respectively and select the relevant component
point_accessor = mesh.PointAccessor()
point_accessor.SelectByIndex(index)
meshmap_accessor = mesh.MeshMapAccessor()
meshmap_accessor.SelectByName(lx.symbol.i_VMAP_WEIGHT, mapname)
# Read and print the value
if point_accessor.MapEvaluate(meshmap_accessor.ID(), storageBuffer):
value = storageBuffer.get()
lx.out(index, value)
# Write the inverted value back
storageBuffer.set((1.0 - value[0],))
point_accessor.SetMapValue(meshmap_accessor.ID(), storageBuffer)
# Update the mesh
mesh.SetMeshEdits(lx.symbol.f_MESHEDIT_MAP_OTHER)
class CmdPrintJointWeights(lxu.command.BasicCommand):
def __init__(self):
lxu.command.BasicCommand.__init__(self)
# Add two string arguments
self.dyna_Add('locator', lx.symbol.sTYPE_STRING)
self.dyna_Add('mesh', lx.symbol.sTYPE_STRING)
def cmd_Flags(self):
return lx.symbol.fCMD_MODEL | lx.symbol.fCMD_UNDO
def basic_Enable(self, msg):
return True
def cmd_Interact(self):
pass
def basic_Execute(self, msg, flags):
if self.dyna_IsSet(0) and self.dyna_IsSet(1):
locatorName = self.dyna_String(0, None)
meshName = self.dyna_String(1, None)
printJointWeights(locatorName, meshName)
def cmd_Query(self, index, vaQuery):
lx.notimpl()
lx.bless(CmdPrintJointWeights, "example.printJointWeights")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment