simpleManipulator help


#1

I have couple of questions about scripted manipulators
#1
Is it possible that when cloning this node each copy need to be unique object (not instance or reference) even if this options are selected in “CloneOptions” dialog.
The reason why I need this is because when user check “Set As RefCoordSys” checkbutton
only that node can be used as RefCoordSys, and all other will be set to checkbutton.checked = off
#2 Can simpleManipulator have “Point Helper” options like “Draw on top” and “Constant screen size”.
This is my first attempt to write this kind of plugin.


plugin simpleManipulator NewPivot name:"PivotHelper" invisible:false classID:#(0x38ba17e3, 0x451d9fac) category:"Manipulators" version:1
(
	local ppNode, ppClass = NewPivot, gizClrR = [1,0,0], gizClrG = [0,1,0], gizClrB = [0,0,1]
	local ppDotsA = #([0,0,0], [-0.5,0.5,1], [-0.15,0.15,8.0], [-0.5,0.5,8.5], [0,0,10.0], [0.5,-0.5,8.5], [0.15,-0.15,8.0], [0.5,-0.5,1], [0,0,0], [0.5,0.5,1], [0.15,0.15,8.0], [0.5,0.5,8.5], [0,0,10.0], [-0.5,-0.5,8.5], [-0.15,-0.1,8.0], [-0.5,-0.5,1], [0,0,0])
	local ppDotsN = #([0,0,0], [-0.5,0.5,1], [0,0,10.0], [0.5,-0.5,1], [0,0,0], [0.5,0.5,1], [0,0,10.0], [-0.5,-0.5,1], [0,0,0])
	
	fn rotatePoints rotAxis:[0,0,1] rotCenter:[0,0,0] rotAngle:90 posArr: =
	(
		q = quat rotAngle (normalize rotAxis)
		for p in posArr collect (((p - rotCenter) * q) + rotCenter)
	) 
	
	parameters main rollout:paramRoll
	( 
		currentRCS type:#string ui:et_note default:(getRefCoordSys()) animatable:off
		shownote type:#boolean ui:cb_shownote default:off animatable:off
		note type:#string ui:et_note default:"PivotNote" animatable:off
		notecolor type:#color ui:cp_notecolor default:yellow animatable:false		
		size type:#worldUnits ui:spn_size default:20 animatable:off
		type type:#radiobtnIndex ui:rb_Type default:1	 animatable:off
		rcs type:#boolean ui:btn_rcs default:off animatable:off

		on viewLabel set value do if isKindOf ppNode ppClass do (setUserPropBuffer ppNode value)
		on rcs set value do if isKindOf ppNode ppClass do 
		(
			if value == on then 
			(
				currentRCS = getRefCoordSys()
				toolMode.coordsys ppNode
				enableRefCoordSys (not value)
			)
			else
			(
				enableRefCoordSys (not value)
				setRefCoordSys (currentRCS as name) 
			)
		)
	)

	rollout paramRoll "Parameters"
	(
		colorpicker cp_notecolor "" pos:[1,6] fieldwidth:12 height:12
		checkbox cb_shownote "Show Note In Viewport" pos:[20,5]
		edittext et_note "" pos:[0,22] fieldWidth:134 height:18
		button btn_X "X" pos:[139,22] width:18 height:18
		label lbl1 "Gizmo:" pos:[3,43] width:30
		radiobuttons	rb_type "" labels:#("Arrow","Needle") default:1 columns:2 pos:[50,43]		
		spinner spn_size "Gizmo Size:	  " pos:[3,60] fieldwidth:70 range:[0.01, 1e5, 20.0]
		checkbutton btn_rcs "Set As RefCoordSys" pos:[3,80]	width:154 height:20 highlightColor:((colorMan.getColor #background) * 150.0)

		on cb_showViewLabel changed state do et_viewLabel.enabled = cb_showViewLabel.checked
		on btn_X pressed do et_note.text = ""
		on paramRoll open do 
		(
			if ppNode == null do (ppNode = refs.dependentNodes this firstOnly:on)
			if isKindOf ppNode ppClass do
			(
				if not (isKindOf ppNode[3][3].track Scale_Expression) do
				(
					ppNode[3][3].track = Scale_Expression()
					ppNode[3][3].track.SetExpression "[1,1,1]"
				)
			)
		)
	)
	
	on canManipulate target return false
	tool create (on mousePoint click do (nodeTM.translation = gridPoint ; #stop))
	on updateGizmos do
	(
		this.clearGizmos()
		local coords = if type == 1 then ppDotsA else ppDotsN
		local giz = manip.makeGizmoShape()
		for n in coords do (giz.AddPoint (n * (size/10)))
		this.addGizmoShape giz 0 gizClrB gizClrB
		local giz = manip.makeGizmoShape()
		for n in (rotatePoints rotAxis:[1,0,0] posArr:coords) do (giz.AddPoint (n * (size/10)))
		this.addGizmoShape giz 0 gizClrG gizClrG
		local giz = manip.makeGizmoShape()
		for n in (rotatePoints rotAxis:[0,-1,0] posArr:coords) do (giz.AddPoint (n * (size/10)))
		this.addGizmoShape giz 0 gizClrR gizClrR				
		if not shownote then (this.addGizmoText "" [0,0,0] 0 (notecolor/255.0) (notecolor/255.0))
		else (this.addGizmoText note [0,0,0] 0 (notecolor/255.0) (notecolor/255.0))
	)
) ; ok


#2

#1… the best you can do activate with you manipulator plugin the NodeEventCallback and check if new your manipulator added. is so using InstanceMgr make it unique (MakeObjectsUnique)

#2… there is no built-in “constant screen size” functionality for manipulators. but you can use getScreenScaleFactor and transform all manipulator’s gizmos using this factor…

you can do “draw on top” only for gizmos which are flagged as gizmoUseScreenSpace or gizmoUseRelativeScreenSpace


#3

Thanks for reply.
Anyway 2nd options will be only optional in this case. I was just curious if there is already built-in solution. It’s not important as first question.
Can you show me at least I you have some free time how to properly use NodeEventCallback in my case. I not have any expiriance using this callback mechanism.
edit:
can I use InstanceMgr inside plug like this


if InstanceMgr.CanMakeObjectsUnique (nodes = refs.dependentNodes this) do 
(
	InstanceMgr.MakeObjectsUnique &nodes #individual
)


#4

sure you can. the question is - when will you do it?


#5

I forget to ask you that :slight_smile:
Maybe to roll open event, but maybe I’m not sure.


#6

here is it. it makes all Box class objects unique when an object was added to the scene:


  try
  (
  	MakeUnique_NodeEventCallback.enabled = off
  	MakeUnique_NodeEventCallback = undefined
  )
  catch()
  
  fn MakeUnique_Callback event handles = 
  (
  	nodes = for n in handles where isvalidnode (node = getanimbyhandle n) and iskindof node Box collect 
  	(
  		if InstanceMgr.CanMakeObjectsUnique node do 
  		(
  			InstanceMgr.MakeObjectsUnique node #individual
  			--format ">>>> % %
" node (InstanceMgr.CanMakeObjectsUnique node)
  		)
  		node
  	)
  )
  MakeUnique_NodeEventCallback = NodeEventCallback added:MakeUnique_Callback modelStructured:MakeUnique_Callback
  MakeUnique_NodeEventCallback.enabled = on
  

edited. we also have to monitor another event (structure changed) to prevent changing an node instancing after creation (by a script or some another tools).


#7

Now I need to guess where to put all of theses.
First “try-catch” at the top ei belove plugin definition.
Then “MakeUnique_Callback” fn above parameter block
And before last bracket i will place ei enabled NodeEventCallback.


#8

Good point. Maybe callbacks like #preNodesCloned and #preMirrorNodes.
This is also node related but not useful I this case (#nodeCreated, #nodeCloned, #sceneNodeAdded)


#9

that’s an interesting thing… technically you can do it if your plugin is initializing in startup directory (or any other directory which loads after the system was loaded). but if you want to put your plugin in the right place (like sdtscripts) you have to force activating your callback after the system was competelly load. you can use sytem #postSystemStartup general callback for it


#10

another solution might be to create and activate the node event callback when first plugin instance was created or loaded… it should work


#11

I read about node event callback but I don’t understand how to setup to works.
All theses arguments just confuse me. :shrug:


#12

here is it… i also wrote a manipulator which supports constant screen size. :slight_smile:


try
(
	MakeUnique_NodeEventCallback.enabled = off
	MakeUnique_NodeEventCallback = undefined
)
catch()

global MakeUnique_NodeEventCallback

plugin simpleManipulator UniqueManip
	name:"UniqueManip"
	classID:#(-0x0001967, 0x0e598a4)
	silentErrors:off
	category:"Manipulators"
(
	local c = colorMan.getColor #manipulatorsInactive
	local node, giz
	parameters main rollout:main
	( 
		size type:#float default:1.0 ui:ui_size 
		constantscreensize type:#boolean default:on ui:ui_constantscreensize
	)
	rollout main "Parameters"
	(
		spinner ui_size "Size: " fieldwidth:56 range:[0, 1e9, 1.0] type:#float align:#right offset:[0,0]
		checkbox ui_constantscreensize "Constant Screen Size" 
	)
	
	tool create 
	(
		on mousePoint click do 
		(
			nodeTM.translation = gridPoint
			#stop 
		)
	)
	on canmanipulate target do return false
	on updateGizmos do 
	(
		if not isvalidnode node do node = refs.dependentnodes this firstOnly:on
		ntm = node.transform
			
		this.clearGizmos()
		giz = manip.makeCircle [0,0,0] size 24
			
		if constantscreensize do
		(
			s = (getScreenScaleFactor ntm.pos)/25.0
			giz.transform (scalematrix [s,s,s])
		)
		this.addGizmoShape giz (gizmoActiveViewportOnly) c c
	)
	fn makeCallback = if not iskindof MakeUnique_NodeEventCallback NodeEventCallback do
	(
		fn MakeUnique_Callback event handles = 
		(
			nodes = for n in handles where isvalidnode (local node = getanimbyhandle n) and iskindof node UniqueManip collect 
			(
				if InstanceMgr.CanMakeObjectsUnique node do InstanceMgr.MakeObjectsUnique node #individual
				node
			)
			format "tm changed > event:% nodes:%
" event nodes
		)
		MakeUnique_NodeEventCallback = NodeEventCallback added:MakeUnique_Callback modelStructured:MakeUnique_Callback --all:MakeUnique_Callback
		MakeUnique_NodeEventCallback.enabled = on
	)
	on create do makeCallback()
	on load do makeCallback()
)

looks like a half your work is done :wink:


#13

I will skip constant screen size. It behave very bad when I scroll mouse wheel or copy manipulator.
I’m going to study your method and see how could integrate this in my plug.
I realy appreciate your time and effort.Thank you Denis.


#14

I integrated your method and works really well, as expected:). Also I added uncheck option for “Set as RefCoordSys” checkbutton.


try(MakeUnique_NodeEventCallback.enabled = off ; MakeUnique_NodeEventCallback = null)catch()
plugin simpleManipulator NewPivot name:"PivotHelper" invisible:false classID:#(0x38ba17e3, 0x451d9fac) category:"Manipulators" version:1
(
	local ppNode, ppClass = NewPivot, gizClrR = [1,0,0], gizClrG = [0,1,0], gizClrB = [0,0,1]
	local ppDotsA = #([0,0,0], [-0.5,0.5,1], [-0.15,0.15,8.0], [-0.5,0.5,8.5], [0,0,10.0], [0.5,-0.5,8.5], [0.15,-0.15,8.0], [0.5,-0.5,1], [0,0,0], [0.5,0.5,1], [0.15,0.15,8.0], [0.5,0.5,8.5], [0,0,10.0], [-0.5,-0.5,8.5], [-0.15,-0.1,8.0], [-0.5,-0.5,1], [0,0,0])
	local ppDotsN = #([0,0,0], [-0.5,0.5,1], [0,0,10.0], [0.5,-0.5,1], [0,0,0], [0.5,0.5,1], [0,0,10.0], [-0.5,-0.5,1], [0,0,0])
	
	fn rotatePoints rotAxis:[0,0,1] rotCenter:[0,0,0] rotAngle:90 posArr: =
	(
		q = quat rotAngle (normalize rotAxis)
		for p in posArr collect (((p - rotCenter) * q) + rotCenter)
	) 
	fn makeCallback = if not iskindof MakeUnique_NodeEventCallback NodeEventCallback do
	(
		fn MakeUnique_Callback event handles = 
		(
			nodes = for n in handles where isvalidnode (local node = getanimbyhandle n) and iskindof node ppClass collect 
			(
				if InstanceMgr.CanMakeObjectsUnique node do (node.rcs = off ; InstanceMgr.MakeObjectsUnique node #individual)
				node
			)
			--format "tm changed > event:% nodes:%
" event nodes
		)
		MakeUnique_NodeEventCallback = NodeEventCallback added:MakeUnique_Callback modelStructured:MakeUnique_Callback
		MakeUnique_NodeEventCallback.enabled = on
	)	
	parameters main rollout:paramRoll
	( 
		currentRCS type:#string ui:et_note default:(getRefCoordSys()) animatable:off
		shownote type:#boolean ui:cb_shownote default:off animatable:off
		note type:#string ui:et_note default:"PivotNote" animatable:off
		notecolor type:#color ui:cp_notecolor default:yellow animatable:false		
		size type:#worldUnits ui:spn_size default:20 animatable:off
		type type:#radiobtnIndex ui:rb_Type default:1	 animatable:off
		rcs type:#boolean ui:btn_rcs default:off animatable:off

		on viewLabel set value do if isKindOf ppNode ppClass do (setUserPropBuffer ppNode value)
		on rcs set value do if isKindOf ppNode ppClass do 
		(
			if value == on then 
			(
				currentRCS = getRefCoordSys()
				toolMode.coordsys ppNode
				enableRefCoordSys (not value)
			)
			else
			(
				enableRefCoordSys (not value)
				setRefCoordSys (currentRCS as name) 
			)
		)
	)

	rollout paramRoll "Parameters"
	(
		colorpicker cp_notecolor "" pos:[1,6] fieldwidth:12 height:12
		checkbox cb_shownote "Show Note In Viewport" pos:[20,5]
		edittext et_note "" pos:[0,22] fieldWidth:134 height:18
		button btn_X "X" pos:[139,22] width:18 height:18
		label lbl1 "Gizmo:" pos:[3,43] width:30
		radiobuttons	rb_type "" labels:#("Arrow","Needle") default:1 columns:2 pos:[50,43]		
		spinner spn_size "Gizmo Size:	  " pos:[3,60] fieldwidth:70 range:[0.01, 1e5, 20.0]
		checkbutton btn_rcs "Set As RefCoordSys" pos:[3,80]	width:154 height:20 highlightColor:((colorMan.getColor #background) * 150.0)

		on cb_showViewLabel changed state do et_viewLabel.enabled = cb_showViewLabel.checked
		on btn_X pressed do et_note.text = ""
		on paramRoll open do 
		(
			if ppNode == null do (ppNode = refs.dependentNodes this firstOnly:on)
			if isKindOf ppNode ppClass do
			(
				if not (isKindOf ppNode[3][3].track Scale_Expression) do
				(
					ppNode[3][3].track = Scale_Expression()
					ppNode[3][3].track.SetExpression "[1,1,1]"
				)
			)
		)
	)
	
	on canManipulate target return false
	tool create (on mousePoint click do (nodeTM.translation = gridPoint ; #stop))
	on updateGizmos do
	(
		this.clearGizmos()
		local coords = if type == 1 then ppDotsA else ppDotsN
		local giz = manip.makeGizmoShape()
		for n in coords do (giz.AddPoint (n * (size/10)))
		this.addGizmoShape giz 0 gizClrB gizClrB
		local giz = manip.makeGizmoShape()
		for n in (rotatePoints rotAxis:[1,0,0] posArr:coords) do (giz.AddPoint (n * (size/10)))
		this.addGizmoShape giz 0 gizClrG gizClrG
		local giz = manip.makeGizmoShape()
		for n in (rotatePoints rotAxis:[0,-1,0] posArr:coords) do (giz.AddPoint (n * (size/10)))
		this.addGizmoShape giz 0 gizClrR gizClrR				
		if not shownote then (this.addGizmoText "" [0,0,0] 0 (notecolor/255.0) (notecolor/255.0))
		else (this.addGizmoText note [0,0,0] 0 (notecolor/255.0) (notecolor/255.0))
	)
	on create do makeCallback()
	on load do makeCallback()
) ; ok


#15

This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.