Distance Align Then Distribute

I would like a script that does two things with the option of doing both or each individually.

It is just like the Distribute tools for layers in Photoshop.

Example: You have a scene with a handful of objects that you want to distribute.

http://www.scriptspot.com/files/distance.png

Option 1: The script takes the selected objects and without moving/adjusting the end objects (which would be the two objects furthest from each other) the script would align them all. Think of it as if you made a straight line between the 2 end objects and then moved each object in between to match that line.

http://www.scriptspot.com/files/distancealign.png

Option 2: Would take all the objects except for the 2 end objects and then evenly distribute those objects along the virtual line that would be drawn between the 2 end objects. Which would result in all the objects being evenly space apart based on there pivot or bounding box.

http://www.scriptspot.com/files/distancedistribute.png

Thanks
JokerMartini

AttachmentSize
distance.png40.81 KB
distancealign.png40.78 KB
distancedistribute.png39.9 KB

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
Monaco Felice's picture

Distribute different objects - how I can do it???

Please explain how to use this script, evenly distribute the objects that have different sizes? The script does equal intervals between the centers of the objects. But how to make equal intervals between the objects???

dub73's picture

nice script

nice script, but when I have objects which are not at 0,0,0 and I check "Distribute" and then "align in X", the scripts move the objects back to the x axis? the objects doesn't stay at their position (the two guide objects at the sides)?

AttachmentSize
003.jpg 226.38 KB
JokerMartini's picture

Check out this. It works way

Check out this. It works way better.
http://jokermartini.com/2011/05/09/get-in-line/

John Martini
Digital Artist
http://www.JokerMartini.com (new site)

JokerMartini's picture

Great

Great work Garp. This is a very useful script you've created here.

I've noticed that when you use the option of the first and second end objects and hit the buttons that the end objects tend to move? Why is that?

John Martini
Digital Artist
http://www.JokerMartini.com (new site)

Garp's picture

Here you go.

Here you go.

AttachmentSize
align_and_distribute.ms 2.88 KB
JokerMartini's picture

Garps

Hey Garp, Great script. I took what you wrote and threw it into a UI as well as tried to go ahead and add the option of choosing a start or end object if the user wants to.

It is a bit finiky. I figured I would post it in here and seek some help.
This is a great script.
I just added variables objA and objB for the option of a start and end obj. I'd like to add checkboxes which would allow users to choose X Y or Z

(   
	local distrib = true
    local cnt = selection.count
    local obj1, obj2
    local max_dist = 0
	local objA = undefined
	local objB = undefined
 
	fn AutoLineup =
	(
		if cnt > 2 do
		(
			for i = 1 to cnt - 1 do for j = i + 1 to cnt do
			(
				local dist = distance selection[i] selection[j]
				if dist > max_dist do
				(
					if objA ==undefined then 
					(
						obj1 = selection[i]
					)
					else
					(
						obj1 = objA
					)
					if objB ==undefined then 
					(
						obj2 = selection[j]
					)
					else
					(
						obj1 = objB
					)
					max_dist = dist
				)
			)
 
			local dum = dummy pos:obj1.pos dir:(obj2.pos - obj1.pos)
 
			in coordsys dum
			(
				local arr = selection as array
				fn order o1 o2 = o1.pos.z - o2.pos.z
				qsort arr order
				local dz = obj2.pos.z / (cnt - 1)
 
				for i = 2 to cnt - 1 do
				(
					obj = arr[i]
					obj.pos.x = obj.pos.y = 0
					if distrib do obj.pos.z = (i - 1) * dz
				)
			)
 
			delete dum
		)
	)
 
 
 
	rollout rlAlignDistribute "Lineup"
	(
		button btnClearStart "X" width:20 height:20 pos:[2,2]
		button btnClearEnd "X" width:20 height:20 pos:[2,24]
		pickbutton pkbtnPickStart "Start Object" width:126 height:20 pos:[22,2]
		pickbutton pkbtnPickEnd "End Object" width:126 height:20 pos:[22,24]
		button btnAutoLineUp "Auto Lineup" width:146 height:24 pos:[2,46]
 
		on btnAutoLineUp pressed do
		(
			AutoLineup()
		)
 
		on pkbtnPickStart picked obj do
		(
			if obj != undefined then
			(
				pkbtnPickStart.text = obj.name
				objA = obj
			)
		)
 
		on pkbtnPickEnd picked obj do
		(
			if obj != undefined then
			(
				pkbtnPickEnd.text = obj.name
				objB = obj
			)
		)
 
		on btnClearStart pressed do
		(
			pkbtnPickStart.text = "Start Object"
			objA = undefined
		)
 
		on btnClearEnd pressed do
		(
			pkbtnPickEnd.text = "End Object"
			objB = undefined
		)
 
	)
	createDialog rlAlignDistribute 150 72
)

John Martini
Digital Artist
http://www.JokerMartini.com (new site)

JokerMartini's picture

Great

That is great Garp.
I'm going to try and make it work for all axis. X Y and Z for aligning.

John Martini
Digital Artist
http://www.JokerMartini.com (new site)

Garp's picture

This one seems to

This one seems to work.
(could use a rollout though)

(
    local distrib = true
 
    local cnt = selection.count
    local obj1, obj2
    local max_dist = 0
 
    if cnt > 2 do
    (
        for i = 1 to cnt - 1 do for j = i + 1 to cnt do
        (
            local dist = distance selection[i] selection[j]
            if dist > max_dist do
            (
                obj1 = selection[i]
                obj2 = selection[j]
                max_dist = dist
            )
        )
 
        local dum = dummy pos:obj1.pos dir:(obj2.pos - obj1.pos)
 
        in coordsys dum
        (
            local arr = selection as array
            fn order o1 o2 = o1.pos.z - o2.pos.z
            qsort arr order
            local dz = obj2.pos.z / (cnt - 1)
 
            for i = 2 to cnt - 1 do
            (
                obj = arr[i]
                obj.pos.x = obj.pos.y = 0
                if distrib do obj.pos.z = (i - 1) * dz
            )
        )
 
        delete dum
    )
)
JokerMartini's picture

Solution

All i need to do really to make this work from here is figure out a way to find the two objects furthest away from each other and use those as the start and end objects for the function.
That is it then.

John Martini

John Martini
Digital Artist
http://www.JokerMartini.com (new site)

Swordslayer's picture

One way to get the objects

One way to get the objects furthest away from each other is to use parts of the previous scripts (you can merge them later, I don't have much time right now so I leave that part to you), like:

fn getFurthestNodes objs =
(
	struct geom_item (obj1, obj2, dist)
 
	fn compareDist obj1 obj2 =
		obj1.dist - obj2.dist
 
	local already_checked = #()
	distances_arr = for o in objs collect
	(
			local item_arr = for item in objs
				where findItem already_checked item == 0 AND item != o collect
					geom_item obj1:o obj2:item dist:(distance o.pos item.pos)
 
			with redraw off
				qsort item_arr compareDist					
 
			append already_checked o
			if item_arr.count == 0 then continue else item_arr[item_arr.count]
	)
	with redraw off qsort distances_arr compareDist	
	local result = if distances_arr.count != 0 do
		distances_arr[distances_arr.count]
	if result != undefined do
		select #(result.obj1,result.obj2)
)

Again, to use it just evaluate it and then you can pass it whatever you like, e.g. getFurthestNodes selection It selects the resulting nodes for you this time ;)

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.