class ComponentSelectionTracker(object): """ A variant of ScriptContextOptions which tracks component selections in user selected order -- the stupid mel callback system makes this extremely awkward to do in the tool scripts themselves, so it's easier to just use this. """ def __init__(self): self.selected = [] self.watcher = None def track_selection(self, *_, **__): new_sel = cmds.ls(sl=True, fl=True, l=True) or [] results = [] for item in self.selected: if item in new_sel: results.append(item) for item in new_sel: if not item in results: results.append(item) self.selected = results Logger.debug("selection %s" % self.selected) def start(self, *args, **kwargs): Logger.debug("starting selection watcher") self.watcher = SelectionChanged() self.watcher += self.track_selection self.selected = cmds.ls(sl=True, fl=True, l=True) or [] self.watcher.start() def finish(self): # reserved for future needs self.track_selection() if self.watcher and self.watcher.running: self.watcher.kill() def exit(self, *args, **kwargs): self.track_selection() if self.watcher and self.watcher.running: self.watcher.kill() def component_selection(self): return [i for i in self.selected]
class SelectionListWatcher(BindableObject): """ A BindableObject which can be attached to a piece of UI and will update the maya selection list automatically using a script job. For examnple: with Window(None,title='xxx') as z: sw = SelectionListWatcher() with ColumnLayout(None, 'zzz') as col: this_button = Button('b', 'Button') this_button.bind.label < bind(str) < sw creates a window with a button whose name will be updated to reflect the currently active selection (the default bind target of the SelectionListWatcher is the selected_items property). The watcher has two properties: - selected_items: a boolean value, true if anything is selected - is_selected: a list of all currently selected items (or an empty list) By default the SelectionListWatcher will update for all selection changes. You can, however, filter the list by providing a list of node type strings, in which case the select By default the SelectionListWatcher will parented to the currently active layout and it's associated scriptJob will be deleted when the UI is deleted. You can pass an explicit UI parent to the constructor if you want to attach to a different UI object ( mGui objects or maya strings both work). """ _BIND_SRC = 'selected_items' def __init__(self, parent=None, types=None): """ constructor. :param parent: a UI element name. The selection monitoring script job will be attached to that element and automatically stopped when that element is deleted :param types: an optional collection of string node type names """ self.selection_changed = SelectionChanged() self.selection_changed += self._forward_update self.filter = types self.selection_changed.start(**_get_active_ui(parent)) self._forward_update() def _forward_update(self, *args, **kwargs): self.update_bindings() @property def selected_items(self): if self.filter: return cmds.ls(sl=True, l=True, type=self.filter) or [] else: return cmds.ls(sl=True, l=True) or [] @property def is_selected(self): return any(self.selected_items) @property def selection_size(self): return len(self.selected_items) @property def hilited(self): if self.filter: return cmds.ls(hl=True, l=True, type=self.filter) or [] else: return cmds.ls(hl=True, l=True) or [] @property def is_hilited(self): return any(self.hilited)
class SelectionListWatcher(BindableObject): """ A BindableObject which can be attached to a piece of UI and will update the maya selection list automatically using a script job. For examnple: with Window(None,title='xxx') as z: sw = SelectionListWatcher() with ColumnLayout(None, 'zzz') as col: this_button = Button('b', 'Button') this_button.bind.label < bind(str) < sw creates a window with a button whose name will be updated to reflect the currently active selection (the default bind target of the SelectionListWatcher is the selected_items property). The watcher has two properties: - selected_items: a boolean value, true if anything is selected - is_selected: a list of all currently selected items (or an empty list) By default the SelectionListWatcher will update for all selection changes. You can, however, filter the list by providing a list of node type strings, in which case the select By default the SelectionListWatcher will parented to the currently active layout and it's associated scriptJob will be deleted when the UI is deleted. You can pass an explicit UI parent to the constructor if you want to attach to a different UI object ( mGui objects or maya strings both work). """ _BIND_SRC = 'selected_items' def __init__(self, parent=None, types=None): """ constructor. :param parent: a UI element name. The selection monitoring script job will be attached to that element and automatically stopped when that element is deleted :param types: an optional collection of string node type names """ self.selection_changed = SelectionChanged() self.selection_changed += self._forward_update self.filter = types self.selection_changed.start(**_get_active_ui(parent)) self._forward_update() def _forward_update(self, *args, **kwargs): self.update_bindings() @property def selected_items(self): if self.filter: return cmds.ls(sl=True, l=True, type=self.filter) or [] else: return cmds.ls(sl=True, l=True) or [] @property def is_selected(self): return self.selection_size > 0 @property def selection_size(self): return len(self.selected_items)