def onHandleToState(self, kwargs):
		uiEvent = kwargs['ui_event']
		reason = uiEvent.reason()
		handle = kwargs['handle']

		if handle == 'edit_xform':

			parms = kwargs['parms']
			translate = hou.Vector3(parms['tx'], parms['ty'], parms['tz'])
			rotate = hou.Vector3(parms['rx'], parms['ry'], parms['rz'])
			scale = hou.Vector3(parms['sx'], parms['sy'], parms['sz'])
			handleXform = buildXformByTRS(translate, rotate, scale)

			if reason == hou.uiEventReason.Start:
				self.sceneViewer.beginStateUndo('Transform elements')
				self.updatePivotCache(handleXform)
				self.cursorGuide.show(False)

			self.movePivotWithoutTransform(translate, rotate, scale)

			if reason == hou.uiEventReason.Active:
				self.transformWithPivot(handleXform)

			if reason == hou.uiEventReason.Changed:
				self.updatePivotCache(handleXform)
				self.cursorGuide.show(True)
				self.sceneViewer.endStateUndo()
    def onMouseEvent(self, kwargs):
        uiEvent = kwargs['ui_event']
        reason = uiEvent.reason()

        self.updateCursor(uiEvent)

        if reason == hou.uiEventReason.Picked or reason == hou.uiEventReason.Start:

            if self.node.parm('tool').eval() == State.TOOL_ADD:

                rotate = hou.Vector3(self.node.parmTuple('r').eval())
                scale = hou.Vector3(self.node.parmTuple('s').eval())

                xform = buildXformByTRS(self.cursor.position, rotate, scale)
                instanceIndex = self.node.parm('instanceindex').eval()
                primnum = self.elements.add(xform, instanceIndex)

                self.updateSelection([primnum])

        # Deselect when selection has cleared
        if reason == hou.uiEventReason.Located:
            sel = self.sceneViewer.currentGeometrySelection()
            if sel and len(sel.selections()) == 0 and len(
                    self.state('selected_prims')) > 0:
                self.updateSelection([])
    def updatePivotCache(self, pivotXform=None):

        if pivotXform == None:
            translate = hou.Vector3(self.node.parmTuple('t').eval())
            rotate = hou.Vector3(self.node.parmTuple('r').eval())
            scale = hou.Vector3(self.node.parmTuple('s').eval())
            pivotXform = buildXformByTRS(translate, rotate, scale)

        selection = self.state('selected_prims')
        xforms = [self.elements.transform(primnum) for primnum in selection]
        self.setState('selection_xforms', xforms)
        self.setState('pivot_original_xform', pivotXform)
	def alignPivot(self):
		selection = self.state('selected_prims')
		numSelected = len(selection)

		pivotPos = self.node.parm('pivot_pos').evalAsString()
		pivotAlign = self.node.parm('pivot_orient').evalAsString()

		translate = hou.Vector3(self.node.parmTuple('t').eval())
		rotate = hou.Vector3(self.node.parmTuple('r').eval())
		scale = hou.Vector3(self.node.parmTuple('s').eval())

		if pivotPos == 'centroid':
			centroidNode = self.node.node('./CENTROID')
			translate = centroidNode.geometry().attribValue('centroid')

		elif pivotPos == 'first' and numSelected > 0:
			primnum = selection[0]
			translate = self.elements.transform(primnum).extractTranslates()

		elif pivotPos == 'last' and numSelected > 0:
			primnum = selection[numSelected - 1]
			translate = self.elements.transform(primnum).extractTranslates()

		if pivotAlign == 'auto':
			if numSelected == 1:
				xform = self.elements.transform(selection[0])
				components = xform.explode()
				rotate = components['rotate']
				scale = components['scale']
			else:
				rotate = hou.Vector3()
				scale = hou.Vector3(1, 1, 1)

		xform = buildXformByTRS(translate, rotate, scale)

		# Update interface
		self.movePivotWithoutTransform(translate, rotate, scale)
		self.updatePivotCache(xform)
	def detectParmChange(self):
		changed = {}

		for name in State.WATCH_PARMS:
			key = 'cache_%s' % name
			value = self.node.parm(name).eval()
			prevValue = self.state(key)

			if prevValue != value:
				changed[name] = {
					'prev_value': prevValue,
					'value': value
				}
				self.setState(key, value)

		# Side effects
		if 'selection' in changed:
			selection = changed['selection']['value']
			self.updateSelection(
				selection, updateParm=False, updateViewer=True)

		if 'tool' in changed:
			self.updateSelection([])
			self.onChangeTool()

		for key in ('tx', 'ty', 'tz', 'rx', 'ry', 'rz', 'sx', 'sy', 'sz'):
			if key in changed:
				# On either transform component has changed
				t = hou.Vector3(self.node.parmTuple('t').eval())
				r = hou.Vector3(self.node.parmTuple('r').eval())
				s = hou.Vector3(self.node.parmTuple('s').eval())
				xform = buildXformByTRS(t, r, s)
				self.transformWithPivot(xform)
				break

		if 'attach_to_geo' in changed:
			if changed['attach_to_geo']['value']:
				self.updatePivotCache()
	def onMouseEvent(self, kwargs):
		uiEvent = kwargs['ui_event']
		reason = uiEvent.reason()

		tool = self.node.parm('tool').eval()

		self.updateCursor(uiEvent)

		if reason == hou.uiEventReason.Picked or reason == hou.uiEventReason.Start:

			if tool == State.TOOL_ADD:

				rotate = hou.Vector3(self.node.parmTuple('r').eval())
				scale = hou.Vector3(self.node.parmTuple('s').eval())

				xform = buildXformByTRS(self.cursor.position, rotate, scale)
				instanceIndex = self.node.parm('instanceindex').eval()

				with hou.undos.group('Add an instance'):
					primnum = self.elements.add(xform, instanceIndex)
					self.updateSelection([primnum])

		
		if reason == hou.uiEventReason.Located:

			if tool == State.TOOL_ADD and self.cursor.normal != None:
				rotate = computeDirectionRotates(self.cursor.normal)

				with hou.undos.disabler():
					self.movePivotWithoutTransform(rotate=rotate)


			# Deselect when selection has cleared
			sel = self.sceneViewer.currentGeometrySelection()
			if sel and len(sel.selections()) == 0 and len(self.state('selected_prims')) > 0:
				with hou.undos.group('Clear selection'):
					self.updateSelection([])