def get_scene_range(): frame_range = modo.Scene().currentRange first_frame = frame_range[0] last_frame = frame_range[1] frame_step = int(modo.Scene().renderItem.channel( lx.symbol.sICHAN_POLYRENDER_STEP).get()) return "{}-{}x{}".format(first_frame, last_frame, frame_step)
def exportSelected(self): if not modo.Scene().selected: modo.dialogs.alert( title='Error', message= 'Export Halted:\nplease select either a Group with one or more Meshes inside it, or a single Mesh item.' ) return self.exportNodes(nodes=modo.Scene().selected)
def do_preset(preset_path, target_mask=None): """Drops a material preset, deletes the cruft, and returns the good stuff.""" # preset.do has a habit of arranging things based on selection. To avoid havoc, # we need to drop all texture layer selections before running it, then pick them # back up again. recall_selection = [ i for i in modo.Scene().selected if i.superType == 'textureLayer' ] for i in recall_selection: i.deselect() lx.eval('preset.do {%s}' % preset_path) # debug("Did preset.") for i in recall_selection: i.select() preset_group = modo.Scene().groups[-1] preset_parent_mask = preset_group.itemGraph('itemGroups').forward()[0] preset_contents = preset_parent_mask.children() # debug("preset_group: %s" % preset_group.name) # debug("preset_parent_mask: %s" % preset_parent_mask.name) # debug("preset_contents:") # for i in preset_contents: # debug("- %s" % i.name) if target_mask: preset_parent_mask.setParent(target_mask) # debug("Set parent to '%s'" % target_mask.name) modo.Scene().removeItems(preset_parent_mask) modo.Scene().removeItems(preset_group) # debug("Removed preset cruft.") if len(preset_contents) == 1 and preset_contents[0].type == 'mask': # debug("Unpacking preset root mask...") parent_mask = preset_contents[0] preset_contents = parent_mask.children() for child in parent_mask.children()[::-1]: child.setParent(parent_mask.parent) modo.Scene().removeItems(parent_mask) # debug("...success") return preset_contents
def commander_execute(self, msg, flags): saved_selection = modo.Scene().selected fusion_items = modo.Scene().items('sdf.item') for i in fusion_items: i.select(True) lx.eval('@StripMacro') lx.eval('select.drop item') for i in saved_selection: i.select() lx.eval('noodles.toggleStrips true')
def commander_execute(self, msg, flags): meshes = modo.Scene().selectedByType('mesh') lx.eval('item.create mesh {%s}' % ("-".join([mesh.name for mesh in meshes]) + "_merge")) lx.eval( 'preset.do "[itemtypes]:MeshOperations/edit/pmodel.meshmerge.itemtype"' ) mesh_merge = modo.Scene().selected[0].id for mesh in meshes: lx.eval( 'item.link pmodel.meshmerge.graph %s %s posT:0 replace:false' % (mesh.id, mesh_merge)) mesh.channel('visible').set(2)
def main(mode="update"): global scene global selected scene = modo.Scene() selected = scene.selected if mode == "assign": assign() if mode == "list": list() if mode == "update": if len(selected) == 0: modo.dialogs.alert("Warning", "Please select at least one item.", dtype='warning') update() if mode == "overwrite": if len(selected) == 0: modo.dialogs.alert("Warning", "Please select at least one item.", dtype='warning') overwrite()
def get_layers_by_pTag(pTags,i_POLYTAG=lx.symbol.i_POLYTAG_MATERIAL): """Returns a list of all mesh layers containing any of the provided pTag(s) of type i_POLYTAG, e.g. lx.symbol.i_POLYTAG_MATERIAL. """ timer = DebugTimer() if not isinstance(pTags,list): pTags = [pTags] scene = modo.Scene() mm = set() for m in scene.meshes: for i in range(m.geometry.internalMesh.PTagCount(i_POLYTAG)): tag = m.geometry.internalMesh.PTagByIndex(i_POLYTAG,i) if i_POLYTAG == lx.symbol.i_POLYTAG_PICK: if [i for i in tag.split(";") if i in pTags]: mm.add(m) else: if tag in pTags: mm.add(m) timer.end() return list(mm)
def construct_filename(self, item, pattern, filename, ext, increment): scnName = os.path.splitext(modo.Scene().name)[0] today = str(date.today()) now = str(datetime.now().time().hour)+':'+str(datetime.now().time().minute) kw = {keywords[0]:scnName, keywords[1]:filename, keywords[2]:item, keywords[3]:ext, keywords[4]:today, keywords[5]:now} sliced = slice(pattern, increment) construced_filename = '' for s in sliced: if s in keywords: construced_filename += kw[s] else: construced_filename += s return construced_filename
def selevent_Add(self, type, subtType): SceneService = lx.service.Scene() type_id = SceneService.ItemTypeSuper(subtType) if modo.constants.LIGHT_TYPE == type_id: scene = modo.Scene() selected = scene.selectedByType(subtType)[0] lx.out('Selected Light: %s' % selected.id)
def basic_Execute(self, msg, flags): reload(t) reload(batch_export) try: scn = modo.Scene() currScn = modo.scene.current() userSelection = scn.selected userSelectionCount = len(userSelection) currPath = currScn.filename if currPath is None: currPath = "" scnIndex = lx.eval('query sceneservice scene.index ? current') userValues = user_value.query_User_Values(self, t.kit_prefix) tbe = batch_export.TilaBacthExport userValues[1] = True if userValues[3]: tbe.batch_folder( tbe(userSelection, userSelectionCount, scn, currScn, currPath, scnIndex, userValues)) elif userValues[2]: tbe.batch_files( tbe(userSelection, userSelectionCount, scn, currScn, currPath, scnIndex, userValues)) except: lx.out(traceback.format_exc())
def selected(num=1): """ Returns: A list of last N selected items. If the minimum number of selected items is not selected a warning dialog pops up. """ scene = modo.Scene() selected = scene.selected if len(selected) < num: if num == 1: filler = "item" else: filler = "items" modo.dialogs.alert("Warning", "Please select at least {1} {0}.".format( filler, num), dtype='warning') return None if len(selected) > num: selected = selected[-num:] return selected if len(selected) == num: return selected
def main(source=None, target=None): # These channels show up as animated even if there are no keys on them. Not a reliable source to determin animation. forbidden_channels = ["localMatrix", "wposMatrix", "wrotMatrix", "wsclMatrix", "wpivPosMatrix", "wpivRotMatrix", "worldMatrix", "glstate", "crvGroup", "matrix", "wParentMatrix", "glsurf", "mesh"] scene = modo.Scene() if source is None or target is None: selected = bd_helpers.selected(2) source = selected[0] target = selected[1] source_channels = bd_helpers.get_channels(source, type="name", forbidden_channels=forbidden_channels, isAnimated=False) target_channels = bd_helpers.get_channels(target, type="name", forbidden_channels=forbidden_channels, isAnimated=False) differences = list(set(source_channels) - set(target_channels)) for difference in differences: forbidden_channels.append(difference) animated = False # First we copy the item's channels for channel in source.channels(): if channel.isAnimated: if channel.name not in forbidden_channels: if channel.envelope.keyframes.numKeys > 0: animated = True bd_helpers.channel_copy_paste(source.id, channel.name, cmd="copy") bd_helpers.channel_copy_paste(target.id, channel.name, cmd="paste") # Now we find any Transform items associated with the source item and copy those for source_transform in modo.item.LocatorSuperType(item=source).transforms: source_transform_type = source_transform.type exists = False for target_transform in modo.item.LocatorSuperType(item=target).transforms: if target_transform.type == source_transform_type: exists = True target_transform_id = target_transform.id if not exists: target_transform_id = target.transforms.insert(source_transform_type) target_transform_id = target_transform_id.id for channel in source_transform.channels(): if channel.isAnimated: if channel.name not in forbidden_channels: if channel.envelope.keyframes.numKeys > 0: animated = True bd_helpers.channel_copy_paste(source_transform.id, channel.name, cmd="copy") bd_helpers.channel_copy_paste(target_transform_id, channel.name, cmd="paste") if len(differences) != 0: warning = "The following channels could not be copied because they do not exist on the target item:\n{0}".format( differences) modo.dialogs.alert("Warning", warning, dtype='warning') return animated
def commander_execute(self, msg, flags): del_empty = self.commander_arg_value(0) del_unused = self.commander_arg_value(1) hitlist = set() for m in modo.Scene().iterItems(lx.symbol.sITYPE_MASK): if not m.children() and del_empty: hitlist.add(m) if del_unused: i_POLYTAG = tagger.convert_to_iPOLYTAG( m.channel(lx.symbol.sICHAN_MASK_PTYP).get()) sICHAN_MASK_PTAG = m.channel(lx.symbol.sICHAN_MASK_PTAG).get() if (sICHAN_MASK_PTAG and not tagger.items.get_layers_by_pTag( sICHAN_MASK_PTAG, i_POLYTAG)): hitlist.add(m) tagger.safe_removeItems(hitlist, True) try: modo.dialogs.alert( tagger.DIALOGS_CLEANED_UP_SHADERTREE[0], tagger.DIALOGS_CLEANED_UP_SHADERTREE[1] % len(hitlist)) except: pass notifier = tagger.Notifier() notifier.Notify(lx.symbol.fCMDNOTIFY_DATATYPE)
def createNode(self): ''' Create a Modo locator node and initialize its data holding attributes :return: DataNode Modo Locator Object ''' # Original logic used Modo script to create the in-scene node, # but this is apparently not required. lx.eval('item.create type:{locator} name:{%s}' % DataNode) lx.eval('layer.setVisibility item:{%s}, visible:False' % DataNode) node = modo.Scene().item(DataNode) # node = modo.Scene().addItem(DataNode) # node.PackageAdd('glItemShape') # # channelValues = {'isRadius' : (316000000 * .00000000001), # 'drawShape': 'custom', # 'isShape' : 'Sphere', # 'isAxis' : 'y', # 'visible' : 'off'} # # node._setChannelValuesFromDict(channelValues) # node.name = DataNode self.initAttributes() return node
def capture_path(): """ Gets the projects path and turns it into the preview output path. Returns: """ scene = modo.Scene() scene_path = scene.filename output = os.path.expanduser('~') + "/" file = 'playblast' if scene_path is not None: project = bd_globals.find_project(scene_path) project_config = bd_globals.projectconfig(scene_path) file = os.path.splitext(os.path.basename(scene_path))[0] output = '{project_dir}{sep}{img}{sep}{previews}{sep}'.format( sep=os.sep, project_dir=project['project_dir'], img=project_config['images/parent folder'], previews=project_config['images/playblasts']) if not os.path.exists(output): os.makedirs(output) return {'output_path': output, 'filename': file}
def main(state='custom'): """ Toggles a scenes or selection hierarchies instances to Bounding Box or Default Display. Args: state: Custom or Default Returns: Nothing """ start_timer = bd_helpers.timer() scene = modo.Scene() selected = scene.selected drawShape = state # default / custom if len(selected) == 0: for item in scene.iterItemsFast(itype='meshInst'): item.channel('drawShape').set(drawShape) else: for item in selected: if item.type == "meshInst": item.channel('drawShape').set(drawShape) for child in item.children(recursive=True, itemType='meshInst'): child.channel('drawShape').set(drawShape) bd_helpers.timer(start_timer, ' Overall')
def add_pTag_to_recent(pTag, tagType): old_tag = modo.Scene().sceneItem.getTags().get(SCENE_TAG_RECENT) if old_tag: tags_list = old_tag.split(TAG_SEP) else: tags_list = [] tags_list = [TAGTYPE_SEP.join((tagType, pTag))] + tags_list # removes duplicates while maintainint list order tags_list = [ii for n,ii in enumerate(tags_list) if ii not in tags_list[:n]] if len(tags_list) > SCENE_TAG_RECENT_MAX: tags_list = tags_list[:SCENE_TAG_RECENT_MAX] modo.Scene().sceneItem.setTag(SCENE_TAG_RECENT, TAG_SEP.join(tags_list))
def basic_Execute(self, msg, flags): try: scene = modo.Scene() clipboard = QtGui.QClipboard() # The QtGui.QClipboard gives you access # to your operating system's Copy/Paste Clipboard text = None if len(scene.selected) == 0: # If you have nothing selected, don't do anything pass elif len(scene.selected) == 1: # If you have a single item selected text = scene.selected[0].name # set text to that item's name elif len(scene.selected) > 1: # If you have more than one item selected selItemsAsNames = [item.name for item in scene.selected] # Create a list and grab just the names # This join command allows you to take a list text = ', '.join(selItemsAsNames) # and turn it in to a single long string. # Very useful for displaying lists in a non-python way if text is not None: # Only the above elifs were accessed, will this be true clipboard.setText(text) lx.out('Text copied to clipboard: %s' %(text)) except Exception as e: lx.out(e)
def main(): scene = modo.Scene() i = 0 instance_types = [] items = [] for item in scene.selected: m = lx.Monitor(len(scene.selected)) m.init(len(scene.selected)) if item.isAnInstance: scene.select(item) if item.type == "meshInst": lx.eval("item.setType mesh") lx.eval("mesh.setBBox false") else: lx.eval("item.setType {0}".format(item.type)) i += 1 items.append(item.name) instance_types.append(item.type) m.step() output = ["{0} Instances de-instanced.\n\n".format(i)] for instance_type in set(instance_types): out = "{0} {1}s".format(instance_types.count(instance_type), instance_type) output.append(out) message = "\n".join(output) modo.dialogs.alert("De-instance complete", message, dtype='info')
def basic_Execute(self, msg, flags): if not self.dyna_IsSet(0): format = "win32" format = self.dyna_String(0, "") unix_path = "/Volumes/ProjectsRaid/WorkingProjects" win_path = "Z:\AzureSync\CloudComputing\WorkingProjects" scene = modo.Scene() for i in scene.iterItemsFast('renderOutput'): filename = i.channel('filename').get() if format == "win32": filename = filename.replace(unix_path, win_path) filename = filename.replace('/', '\\') return filename elif format == "darwin": filename = filename.replace(win_path, unix_path) filename = filename.replace('\\', '/') i.channel('filename').set(filename) else: print("ERROR no valid OS given for path transform")
def get_layers_by_pTag(pTags, i_POLYTAG=lx.symbol.i_POLYTAG_MATERIAL): """Returns a list of all mesh layers containing any of the provided pTag(s) of type i_POLYTAG, e.g. lx.symbol.i_POLYTAG_MATERIAL. """ # If signle value is passed put into list if not isinstance(pTags, list): pTags = [pTags] scene = modo.Scene() mm = set() # Collect result meshes in mm for m in scene.meshes: # For each polygon tag for i in range(m.geometry.internalMesh.PTagCount(i_POLYTAG)): tag = m.geometry.internalMesh.PTagByIndex(i_POLYTAG, i) # If need to be found in i_POLYTAG_PIC (polygon belongs to each selection set in tag) if i_POLYTAG == lx.symbol.i_POLYTAG_PICK: # Add mesh if one of selection sets present in pTags if [i for i in tag.split(";") if i in pTags]: mm.add(m) else: # Add mesh if tag exists in pTags if tag in pTags: mm.add(m) return list(mm)
def main(): scene = modo.Scene() graph = lx.object.ItemGraph(scene.GraphLookup('deformers')) items = scene.items('mesh') if (len(items) == 0): sys.exit() targetFile = customfile('fileOpen', 'Choose any MDD file', 'mdd', 'MDD', '*.mdd', None) if (targetFile != None): targetLocation = os.path.dirname(targetFile) lx.out('targetLocation: {%s}' % targetLocation) monitor = lx.Monitor(len(items)) for item in items: monitor.step() lx.eval('select.drop item') meshName = item.UniqueName() # Take out character naming off the end. Only for Anima 1.x tempArray = meshName.split('--') if len(tempArray) > 1: # Add back a trailing dash to match naming convention for MDD files meshName = tempArray[0] + "-" lx.out('meshName: {%s}' % meshName) filepath = targetLocation + os.sep lx.out('filepath: {%s}' % filepath) filepath = filepath + meshName + ".mdd" ''' mesh = item.Ident()''' deformer = scene.addItem('deformMDD2') graph.AddLink(deformer, item) deformer.channel('file').set(filepath) lx.eval('select.drop item') lx.eval('select.item {%s}' % deformer.Ident()) lx.eval('deform.mddReload') else: sys.exit()
def main(): scene = modo.Scene() instances, replacement_mesh, original_mesh = get_meshes(scene) duplicate_original = scene.duplicateItem(original_mesh) duplicate_original.name = replacement_mesh.name + "_RI" duplicate_instances = [] for i in instances: item = scene.duplicateItem(duplicate_original, True) item.name = i.name + "_RI" duplicate_instances.append(item) # update the xforms to match those of the original instance update_xforms(instances, duplicate_instances) # replace the duplicate original with the replacement mesh scene.select(replacement_mesh) lx.eval("select.typeFrom polygon") lx.eval("select.all") lx.eval("copy") scene.select(duplicate_original) lx.eval("select.all") lx.eval("delete") lx.eval("paste") # put them into a group grp = scene.addItem(modo.constants.GROUPLOCATOR_TYPE, name=replacement_mesh.name + "_RI_GROUP") duplicate_original.setParent(grp) for i in duplicate_instances: i.setParent(grp) # select the new group we just added so they know what happened scene.select(grp)
def commander_execute(self, msg, flags): masks = set() for i in modo.Scene().selected: if i.type == tagger.MASK: masks.add(i) if len(masks) < 1: try: modo.dialogs.alert(tagger.DIALOGS_NO_MASK_SELECTED) except: pass return if len(masks) > 1: try: modo.dialogs.alert(tagger.DIALOGS_TOO_MANY_MASKS) except: pass return mask = list(masks)[0] tagLabel = mask.channel(lx.symbol.sICHAN_MASK_PTYP).get() tagType = tagger.convert_to_tagType_string(tagLabel) tag = mask.channel(lx.symbol.sICHAN_MASK_PTAG).get() global _clipboard _clipboard[tagType] = tag
def getPosition(self): ''' A vertex's final position is an evaluation of its weights. Each weight caries a position, a bias, and a joint the bias is multiplied against the position, and then offset by the joint. If a vert sits right on top of a bone and is 100% influenced by that bone, its position is 0,0,0 If it's 100% weighted to a bone but is not on top of the bone, its position will be its distance from that bone. If smooth skinning comes in to play, each joint adds to the final position of the bone, and the bias is simply the skinning value from 0 to 1, giving each joint more sway in the final position. ''' x, y, z = 0, 0, 0 scene = modo.Scene() for weight in self.weights: Jx, Jy, Jz = weight.joint.position # We need to rotate the weight.pos vector around the bone's rotation matrix. wMtx = modo.mathutils.Matrix4(position=weight.pos) mObj = modo.Item(weight.joint.name) jMtx = modo.mathutils.Matrix4( mObj.channel('worldMatrix').get()) # fMtx = wMtx.__mul__(jMtx) fMtx = wMtx.__mul__(jMtx.asRotateMatrix()) fVec = fMtx.position x += (Jx + fVec[0]) * weight.bias y += (Jy + fVec[1]) * weight.bias z += (Jz + fVec[2]) * weight.bias return [x, y, z]
def function_wrapper(*args, **kwargs): scene = modo.Scene() selected = scene.selected x = func(*args, **kwargs) scene.deselect() scene.select(selected) return x
def __init__(self): lxu.command.BasicCommand.__init__(self) self.dyna_Add('passgroup_name', lx.symbol.sTYPE_STRING) # self.basic_SetFlags (0, lx.symbol.fCMDARG_OPTIONAL) self.dyna_Add('prefix', lx.symbol.sTYPE_STRING) self.basic_SetFlags(1, lx.symbol.fCMDARG_OPTIONAL) self.dyna_Add('suffix', lx.symbol.sTYPE_STRING) self.basic_SetFlags(2, lx.symbol.fCMDARG_OPTIONAL) self.dyna_Add('trim', lx.symbol.sTYPE_BOOLEAN) # self.basic_SetFlags (1, lx.symbol.fCMDARG_OPTIONAL) self.dyna_Add('trim_separator', lx.symbol.sTYPE_STRING) self.basic_SetFlags(4, lx.symbol.fCMDARG_OPTIONAL) self.dyna_Add('trim_range', lx.symbol.sTYPE_STRING) self.basic_SetFlags(5, lx.symbol.fCMDARG_OPTIONAL) self.scn = modo.Scene() self.renderpass_groups = self.get_renderpass_groups() self.current_renderpass_group = self.get_current_renderpass_group() #DefaultValue self.prefix = '' self.suffix = ''
def __init__(self): ''' Constructor ''' QDialog.__init__(self) # since exec_() is unstable, use setModal() # Turns out setModal() may also be unstabe, so... #self.setModal(True) # ensure the widget it deleted when closed self.setAttribute(Qt.WA_DeleteOnClose) # remove the window frame, ensure pop-up look and feel self.setWindowFlags(Qt.FramelessWindowHint | Qt.Popup) # gather data to display in our listView self.selection = modo.Scene().selected[0] self.channels = self.selection.channelNames # create a label self.label = QLabel('Select a channel...') self.label.setAlignment(Qt.AlignCenter) # create a search field and set it to accept custom events self.lineEdit = QLineEdit('', self) self.lineEdit.installEventFilter(self) # create a non-editable list view and set it to accept custom events self.listView = QListView() self.listView.setFixedWidth(200) self.listView.installEventFilter(self) self.listView.setEditTriggers(QAbstractItemView.NoEditTriggers) # set up a data model with a proxy so we can filter it self.listModel = CustomStringModel(self.channels) self.proxyModel = QSortFilterProxyModel() self.proxyModel.setDynamicSortFilter(True) self.proxyModel.setSourceModel(self.listModel) # set the model on the listView self.listView.setModel(self.proxyModel) # create a layout and add our widgets to it self.layout = QVBoxLayout() self.layout.setSpacing(2) self.layout.setContentsMargins(2, 2, 2, 2) self.layout.addWidget(self.label) self.layout.addWidget(self.lineEdit) self.layout.addWidget(self.listView) # set connections self.lineEdit.textChanged.connect(self.updateList) self.lineEdit.returnPressed.connect(self.process_selection) self.listView.doubleClicked.connect(self.process_selection) # set the layout and focus on the search field self.setLayout(self.layout) self.lineEdit.setFocus()
def basic_Execute(self, msg, flags): ''' Create the item ''' self.item = self.dyna_String(0) scene = modo.Scene() newItem = scene.addItem(self.item) scene.select(newItem)
def group_selected_and_maskable(name): scene = modo.Scene() group = scene.addItem(lx.symbol.sITYPE_GROUP) group.name = name group.addItems(get_selected_and_maskable()) return group