Notifications
Clear all

[Closed] Basic Object Placer


   try (closeRolloutFloater OPlacerFlo) catch ()
rollout OPlacerRol "Gura'sObiectPlacer"
(
	tool PlaceMouseTool
	(
		local b
		local a
		local GridAA
		local tm=(matrix3 [0,0,0] [0,0,0] [0,0,0] [0.0,0.0,0.0])
		local ScaleThing=1.0
		local BDir
		local WasMesh = 0
		fn StartPaint =
		(
			if classof OPlacerRol.PlaceOn.object == Editable_mesh then 
			(
				a=OPlacerRol.PlaceOn.object
				WasMesh = 0
			)
			else
			(
				a=SnapShot OPlacerRol.PlaceOn.object
				a.ishidden = true
				WasMesh = 1
			)
			coordSysTM = Inverse(getViewTM())
			GridAA = grid isHidden:true
			GridAA.transform = coordSysTM
			in coordsys local GridAA.pos += [0,0,-0.01]
			activeGrid = GridAA
			RayAA= ray (coordSysTM.row4) (worldPoint-(coordSysTM.row4))
			HitAA = intersectRayEx a RayAA
			if HitAA==undefined then
			(
				delete GridAA
				if WasMesh == 0 then () else (delete a)
			)
			else
			(
				Bname = OPlacerRol.Place.selection as array
				if Bname[1] == undefined then 
				(
					B=copy (getnodebyname OPlacerRol.Place.items[(random 1 (OPlacerRol.Place.items.count))])
				)
				else
				(
					BNum = random 1 Bname.count
					B=copy (getnodebyname OPlacerRol.Place.items[(Bname[BNum])])
				)
				ScaleThing =((nodeLocalBoundingBox b)[1] - (nodeLocalBoundingBox b)[2])/-2
				b.pos = HitAA[1].pos
				b.dir = HitAA[1].dir
				BDir=b.dir
			)
		)
		
		fn DropPaint =
		(
			try
			(
				select b
				b= undefined
				delete GridAA
				if WasMesh == 0 then () else (delete a)
			)
			catch()
		)
		
		on mousePoint clickno do
		(
			if clickno == 0 then ()
			else
			(
				case of
				(
					((mod ( clickno-1 ) 2) != 0.0) : StartPaint()
					((mod ( clickno-1 ) 2) == 0.0) : DropPaint()
					default : ()
				)
			)
		)
		
		on mouseMove clickno do
		(
			try
			(
				coordSysTM = Inverse(getViewTM())
				RayAA= ray (coordSysTM.row4) (worldPoint-(coordSysTM.row4))
				HitAA = intersectRayEx a RayAA
				if HitAA == undefined then ()
				else 
				(	
					ScaleThingB = (length (b.pos - HitAA[1].pos)) / ScaleThing
					if altkey == true then 
					(
						zA=(normalize (BDir))
						xA=(normalize (HitAA[1].pos - b.pos))
						yA=(normalize (cross  za xa))
						xA=(normalize (cross  ya za))
						tm=matrix3 xa ya za b.pos
						b.transform = tm
						b.scale = [-1,-1,-1]*ScaleThingB
					)
					else 
					(
						zA=(normalize (BDir))
						xA=(normalize (HitAA[1].pos - b.pos))
						yA=(normalize (cross  za xa))
						xA=(normalize (cross  ya za))
						tm=matrix3 xa ya za b.pos
						b.transform = tm
						b.scale = [1,1,1]*ScaleThingB
					)
					
					b.scale.y = b.scale.x
					b.scale.z = b.scale.x
				)
			)
			catch()
		)
		
		on stop do
		(
			try
			(
				select b
				delete GridAA
				if WasMesh == 0 then () else (delete a)
			)
			catch()
		)
	)
	
	PickButton PlaceOn "PICK_OBJ" pos:[10,10] width:170 height:30 autoDisplay:true
	MultiListBox Place "Place:" pos:[10,45] width:170 height:15
	Button GetBtn02 "GetSel" pos:[100,40] width:80 height:20
	button PlaceBtn "Place" pos:[200,230] width:170 height:30
	edittext Help pos:[200,10] text:"Please use only perspective view for placing :)
1.With PICK_OBJ U pick object to write on 
2.Use GETSEL to get selected objects 
3.Pick one or more objects from list 
4.Click Place 
5.First Click will place object 
6.Moving will rotate and scale it 
7.Use ALT for inverting hit normal.
8.Second will drop it 
9.Click right MB or ESC to exit tool" fieldWidth:270 height:150 readOnly:true
	on GetBtn01 pressed do
	(
		NamesArr= #()
		for i = 1 to selection.count do
		(
			append NamesArr Selection[i].name
		)
		PlaceOn.items=NamesArr
	)
	on GetBtn02 pressed do
	(
		NamesArr= #()
		for i = 1 to selection.count do
		(
			append NamesArr Selection[i].name
		)
		Place.items=NamesArr
	)
	on PlaceBtn pressed do
	(
		startTool PlaceMouseTool
	)
)
OPlacerFlo=newrolloutfloater "GOPlacer" 500 400
addrollout OPlacerRol OPlacerFlo
 
  
      
  Just one small tool I was looking for. It is for "painting like" placing of objects. First click will place object moving will rotate and scale it. second click will drop it.
4 Replies

Very interesting. I found a bug though right away …

When I was placing an object, and I moved the mouse in/out of the surface I was placing on, the object started to rotate randomly off the surface Normal so it wasn’t flat anymore, and the scale isn’t 1,1,1 anymore.

I have updated the code now after leaving mesh area it will do nothing:blush:

Nice. I just found another error, by trying to use it too fast I guess there isn’t error checking if the selected list count == 0? I tried placing an object from the list without anything being selected and it errored at

BNum = random 1 Bname.count
   			 B=copy (getnodebyname OPlacerRol.Place.items[(Bname[BNum])])

Edit:

Bug2 : Also… hehe… if you click outside of the surface when u start placing, it places it rotated oddly infront of the camera, so you’re viewing inside the object, and then u cant move it/scale it and have to delete it/start again.

Bug 3: I found when placing on a Teapot for Example, its inverting the object rotation, using the inverted normal of the face it seems. So when I rotate/scale the object, its inside the other object instead of pointing outward. Maybe check for that, or have a +/- Normal direction they can choose?

A nice thing to do too would be to delete/cancel the placement when u right-click or escape and only place when the user left clicks?

updated

  1. if nothing is selected in the list it just grabs random object from it
    2, if U click outside of surface on start it will do nothing but then U will need another two clicks to make it work
    3, I managed to have right scale but in process of creation the mesh flickers and jums out and in. So I left older version (inverted one) for now. Looks I have a lot to learn.