Skip to content

Instantly share code, notes, and snippets.

@mattcox
Last active November 9, 2021 08:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mattcox/6147502 to your computer and use it in GitHub Desktop.
Save mattcox/6147502 to your computer and use it in GitHub Desktop.
Auto generates material masks for every new, unique material ptag in the scene.
#!/usr/bin/env python
'''
Auto generates material masks for every material ptag in the scene.
Usage: Put the script in a folder called lxserv inside your modo scripts
folder. Restart modo. Run the command: material.generate
'''
import lx
import lxu.command
import lxu.select
SERVER_NAME = 'material.generate'
def PtagMasks_Get ():
ptags = []
scn_svc = lx.service.Scene()
scene = lxu.select.SceneSelection().current()
chan_read = scene.Channels(lx.symbol.s_ACTIONLAYER_EDIT, 0.0)
mask_type = scn_svc.ItemTypeLookup(lx.symbol.sITYPE_MASK)
for i in range (scene.ItemCount(mask_type)):
mask = scene.ItemByIndex(mask_type, i)
if chan_read.String(mask, mask.ChannelLookup(lx.symbol.sICHAN_MASK_PTYP)) == 'Material':
ptag_value = chan_read.String(mask, mask.ChannelLookup(lx.symbol.sICHAN_MASK_PTAG))
if ptags.count(ptag_value) == 0:
ptags.append(ptag_value)
return ptags
class Command (lxu.command.BasicCommand):
def __init__ (self):
lxu.command.BasicCommand.__init__ (self)
self.scn_svc = lx.service.Scene()
self.cmd_svc = lx.service.Command()
def cmd_Flags(self):
return lx.symbol.fCMD_MODEL | lx.symbol.fCMD_UNDO
def basic_Enable (self, msg):
return True
def basic_Execute (self, msg, flags):
ptags_new = []
scene = lxu.select.SceneSelection().current()
chan_read = scene.Channels(lx.symbol.s_ACTIONLAYER_EDIT, 0.0)
'''
First, get the list of all the ptags currently in the scene so we
don't create any duplicates.
'''
ptags_original = PtagMasks_Get()
'''
We want to loop through every mesh in the scene and get the material
polygon tags on that mesh.
'''
mesh_type = self.scn_svc.ItemTypeLookup(lx.symbol.sITYPE_MESH)
for i in range (scene.ItemCount(mesh_type)):
mesh_item = scene.ItemByIndex(mesh_type, i)
if mesh_item.test() == False:
continue
'''
Read the mesh channel on the mesh item.
'''
mesh_obj = chan_read.ValueObj(mesh_item, mesh_item.ChannelLookup(lx.symbol.sICHAN_MESH_MESH))
mesh = lx.object.Mesh(mesh_obj)
if mesh.test() == False:
continue
'''
Loop over all the ptags that match the material type.
'''
ptag_count = mesh.PTagCount(lx.symbol.i_PTAG_MATR)
for ii in range (ptag_count):
ptag_value = mesh.PTagByIndex(lx.symbol.i_PTAG_MATR, ii)
'''
If it's the default mask, skip it.
'''
if ptag_value == 'Default':
continue
'''
Check that the material tag doesn't exist in the shader tree
already, also check that we haven't already added it to the
list of masks to create.
'''
if ptags_original.count(ptag_value) == 0 and ptags_new.count(ptag_value) == 0:
ptags_new.append(ptag_value)
'''
Now we should have a list of all the polygon tags that need creating.
Simply loop through the list and call new material.new for each of
them.
'''
for ptag in ptags_new:
self.cmd_svc.ExecuteArgString(-1, lx.symbol.iCTAG_NULL, 'material.new name:{%s} assign:false useLib:false' % ptag)
lx.bless (Command, SERVER_NAME)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment