def _node_renamed(self, node, old_name, unused): # A node was renamed. Refresh the node list if it's a zMouthController node. dep_node = om.MFnDependencyNode(node) if dep_node.typeId() != plugin_node_id: return qt_helpers.run_async_once(self.refresh_weight_node_list)
def _singleton_node_changed(self, msg, plug, otherPlug, data): # For some reason, this is called once per output, but not actually called for changed inputs. # It seems to not notice when a value has changed because its input key connection has changed. # # kAttributeSet is sent for most things, like moving the time slider causing the current key # to change and us making changes directly. kAttributeEval catches some things that doesn't, # in particular editing keys with the graph editor, but this only works if something is connected # to the output to trigger an evaluation. Note that Set usually comes from the main thread, but # Eval tends to come from a worker thread, so we depend on the async dispatching to move this to # the main thread. if msg & (om.MNodeMessage.kConnectionMade | om.MNodeMessage.kConnectionBroken | om.MNodeMessage.kAttributeSet | om.MNodeMessage.kAttributeEval): # kConnectionMade and kConnectionBroken will tell us when we've been connected # or disconnected and should refresh our listeners in case we have a new animCurve. # # However, they're not sent if we're already connected to a character set and the # character set gets connected to an animCurve, or any other in-between # proxy of animCurves (the time editor does this as well). We could detect # this with MDGMessage.addConnectionCallback, but that's called on every # connection change in the scene, which is too slow when things like render # setups are making wide-scale changes to the scene. # # Most of the time a new animCurve is connected, it'll change the current value, # which will cause kAttributeSet or kAttributeEval to be sent. qt_helpers.run_async_once(self._check_listeners)
def _time_changed(self): """ When the scene time changes, update the current selection to match. This isn't called during playback. """ qt_helpers.run_async_once(self.set_selected_frame_from_current_time)
def _connection_changed(self, src_plug, dst_plug, made, data): # When a connection is made or broken to .output, refresh the list. Check if # the source node is a zMouthController node. src_dep_node = om.MFnDependencyNode(src_plug.node()) if src_dep_node.typeId() != plugin_node_id: return qt_helpers.run_async_once(self.refresh_weight_node_list)
def _attribute_changed(self, msg, plug, otherPlug, data): # If this isn't an attribute change type that we're interested in, ignore it. if (msg & self.mask) == 0: return if not self._user_async: self._user_callback(msg, plug, otherPlug, data) else: qt_helpers.run_async_once(self._async_user_callback)
def _check_listeners(self): """ This is called when our zKeyframeNaming node or its singleton may have changed. Check if we need to reestablish listeners with the new nodes, and refresh the UI. """ # We should have our listeners registered if we're visible and we're not # in the middle of file I/O. in_file_io = self.in_file_io() should_be_listening = self.shown and not in_file_io if not should_be_listening: # If we're listening, stop. self._unregister_listeners() # If we're in file I/O, we want to reestablish listeners once the operation # completes. Queue a job to come back here and recheck during idle (if # we don't already have one waiting). if in_file_io and not self._reregister_callback_queued: def reestablish_callbacks(): self._reregister_callback_queued = False self._check_listeners() qt_helpers.run_async_once(reestablish_callbacks) self._reregister_callback_queued = True # If we're not listening anyway, return # We do want to be listening. # # If a keyframe node is connected or disconnected from zKeyframeNaming.keyframes, # we need to reestablish listeners to listen for keyframe changes. # # There's no obvious quick way to find out if this connection affects that, though. # We can't just look at the plugs, since there might be other nodes in between, like # character sets. Instead, we have to look at the actual animation curve node and # see if it's changed. singleton = get_singleton(create=False) anim_curve = self._get_keyframe_anim_curve() if singleton is not self._listening_to_singleton or anim_curve is not self._listening_to_anim_curve: # One of our nodes have changed. self._unregister_listeners() # If we're (still) listening, then we're done. if self.callback_ids.length(): return # Register our listeners. self._register_listeners() # Since we weren't listening, the UI may be out of date and should be refreshed. self.refresh()
def _async_refresh(self): """ Queue a refresh. If this is called multiple times before we do the refresh, we'll only refresh once. """ qt_helpers.run_async_once(self.refresh)
def _weight_nodes_changed(self, node, data): # A zMouthController node was added or removed, so refresh the list. Queue this instead of doing # it now, since node removed callbacks happen before the node is actually deleted. qt_helpers.run_async_once(self.refresh_weight_node_list)
def _async_check_listeners(self): qt_helpers.run_async_once(self._check_listeners)
def _queue_callback(self): qt_helpers.run_async_once(self._async_callback)