Notifications
Clear all

[Closed] FFD Transform Script

Manipulate objects like an FFD cage.

 
--- FFD Free Transform  v0.7					 ---
--- Inspired by the UVW editor transform box.  But extended.  And 3D.... and in no way similar.  ---
--- Use: Select a bunch of objects.				  ---
---	  Run Script. 					  ---
---  Manipulate control box (Including at the sub object level) 		 ---
---  Delesect Control Gizmo or delete control Gizmo			---
---   Gavin Greenwalt (Straightface Studios) 			  ---
FFDUpdate = undefined
Global FFD
struct ffdStruct (
 Objs, Deltas, ControlGizmo,
 fn TransformOp OutPoints DeltaXYZ=
 (
  centerpoint = 
  (
   (
	(
	 (
	  (
	   (OutPoints[1])*(1-deltaXYZ.Y)+(OutPoints[3])*(deltaXYZ.Y)
	  )*(1-deltaXYZ.X)
	 ) + (
	  (
	   (OutPoints[2])*(1-deltaXYZ.Y)+(OutPoints[4])*(deltaXYZ.Y)
	  )*(deltaXYZ.X)
	 )
	)*(1-deltaXYZ.Z)
   ) + (
	(
	 (
	  (
	   (OutPoints[5])*(1-deltaXYZ.Y)+(OutPoints[7])*(deltaXYZ.Y)
	  )*(1-deltaXYZ.X)) + (
	  (
	   (OutPoints[6])*(1-deltaXYZ.Y)+(OutPoints[8])*(deltaXYZ.Y)
	  )*(deltaXYZ.X)
	 )
	)*(deltaXYZ.Z)
   )
  )
  centerpoint
 ),
 
 fn getDelta BoundsObj SubObj = 
 (
  (SubObj.pos - BoundsObj.min)/(BoundsObj.max-BoundsObj.min)
 ),
 fn create2xGizmo =
 (
  Dims = $.max-$.min
  ControlGizmo = box width:Dims.x length:Dims.y height:Dims.Z
  ControlGizmo.center = $.center
  ControlGizmo.wirecolor = (color 255 90 0)
  WireMat = standardmaterial()
  Wiremat.diffuse = (color 255 90 0)
  Wiremat.wire = true
  Wiremat.selfillumination = 100.0
  ControlGizmo.Material = WireMat
  converttomesh ControlGizmo
  ControlGizmo
 ),
 
 fn handleGeometryChange ev nd = 
 (
  obj = (GetAnimByHandle nd[1])
  objMesh = snapShotAsMesh obj
  OutPoints = (for j = 1 to 8 collect (getvert objmesh j))
  for i=1 to FFD.Objs.count do (FFD.Objs[i].pos = (FFD.TransformOp OutPoints FFD.Deltas[i]))
  delete objMesh
  gc light:true
 ),
 
 fn Update Objs Deltas Outpoints = 
 (
  for i=1 to Objs.count do (Objs[i].pos = (FFD.TransformOp OutPoints Deltas[i]))
 ),
 
 fn deleteGizmo =
 (
  delete FFD.ControlGizmo
 )
 
)
if $ != undefined do
(
 FFD = FFDStruct()
 FFD.Objs = (for p in selection as array where (if (isgroupmember p) == true then ((for o in (selection as array) where o == p.parent collect o).count == 0) else true) collect p)
 FFD.ControlGizmo = FFD.create2xGizmo()
 FFD.Deltas = for o in FFD.Objs collect (FFD.getDelta FFD.ControlGizmo o) 
 select FFD.ControlGizmo
 setcommandpaneltaskmode #modify
 --setSelectionLevel ControlGizmo #vertex
 
 rollout deleteGizmoDialog "DeleteGizmo" 
 (
  timer ticktock interval:1
  on ticktock tick do
  (
   try(delete FFD.ControlGizmo)catch()
   destroydialog deleteGizmoDialog
  )
 )
 
 FFDUpdate = nodeEventCallback geometryChanged:FFD.handleGeometryChange
 when geometry FFD.ControlGizmo changes id:#FFDUpdate do (FFD.Update FFD.Objs FFD.Deltas (for j = 1 to 8 collect (getvert FFD.ControlGizmo j)))
 when select FFD.ControlGizmo changes id:#FFDUpdate do (if $ != FFD.ControlGizmo do (clearselection(); FFDUpdate = undefined; createdialog DeleteGizmoDialog; deleteAllChangeHandlers id:#FFDUpdate; gc light:true))
)
 
1 Reply

Thanks Bobo and ZeBoxx.

So the only way I could get the change handler to not crash was to create a rollout to delete it. Any better ideas?

EDIT:
Updated it so that it ignores groupmembers and only manipulates group heads.

EDIT EDIT:

Further refined it so that it only manipulates group heads or sub-groups whose grouphead isn’t also selected. (so you can work with groups inside of groups, or open the group and work individually with all of the group components.)