Problem I’m solving
Distribute Evenly, the tool that exists everywhere, but 3Ds Max. Photoshop, Illustrator, Miro, PowerPoint, etc., all have this simple function to pick multiple objects and space them evenly.
Solution
This script does just that with a little more! it gives you multiple buttons for simple aligning. Once you need the more advance one, you can use the max built-in align tool.
Installation
- Simply just drag the InstallerDragnDrop.ms script to the viewport to install.
- Right-click on the toolbar > Customize…
- Choose the tab ‘Toolbars’
- In the Category: dropdown, select ‘ManniiCode’
- Drag the script to the toolbar where ever you want!
- If you want to install each button separately to your toolbar, you can!. Click ‘No’ on the installation popup.
Video
Code
from pymxs import runtime as rt
selected_object = rt.getCurrentSelection()
sorted_sel_obj = []
def MidPointPos(the_item, the_axis):
obj_mid_point = the_item.min[the_axis] + ((the_item.max[the_axis] - the_item.min[the_axis])/2)
return obj_mid_point
#Define the space-evenly function
def align_plus_evenly(axis):
"""
0 = x
1 = y
2 = z
"""
selected_object = rt.getCurrentSelection()
if len(selected_object) > 1:
#Sort the selected object list with the position, Point3 with the index of axis
sorted_sel_obj = sorted(selected_object, key=lambda item: (MidPointPos(item, axis)))
#get the position distance for the space in each objects
obj_max_midpoint = MidPointPos(sorted_sel_obj[len(sorted_sel_obj)-1], axis)
obj_min_midpoint = MidPointPos(sorted_sel_obj[0], axis)
position_distance = (obj_max_midpoint - obj_min_midpoint) / (len(selected_object)-1)
reference_pos = obj_min_midpoint
#Loop through all the objects and place it in its place
for item in sorted_sel_obj:
#make a position default variable
item_midpoint = MidPointPos(item, axis)
newpos = rt.Point3(0, 0, 0)
newpos[axis] = reference_pos - item_midpoint
rt.move(item, newpos)
reference_pos += position_distance
#Define the align_plus function
def align_plus(axis, min_max):
"""
0 = x | 1 = y | 2 = z
0 = min | 1 = middle | 2 = max
"""
selected_object = rt.getCurrentSelection()
if len(selected_object) > 1:
#Sort the selected object list with the position, Point3 with the index of axis
#sorted_sel_obj = sorted(selected_object, key=lambda item: (MidPointPos(item, axis)))
#Set the position value for the first object position
if min_max == 2:
sorted_sel_obj = sorted(selected_object, key=lambda item: item.max[axis])
position_value = sorted_sel_obj[len(sorted_sel_obj)-1].max[axis]
elif min_max == 0:
sorted_sel_obj = sorted(selected_object, key=lambda item: item.min[axis])
position_value = sorted_sel_obj[0].min[axis]
else:
sorted_sel_obj = sorted(selected_object, key=lambda item: (MidPointPos(item, axis)))
#This takes the midpoint of the highest and lowest object, not the max and min of the highest, so,huge object will be considered by the center anyway
position_value = (MidPointPos(sorted_sel_obj[len(sorted_sel_obj)-1],axis) - MidPointPos(sorted_sel_obj[0],axis)) / 2
#Loop through all the objects and place it in its place
for item in sorted_sel_obj:
#make a position default variable
obj_dist_from_mid = ((item.max[axis] - item.min[axis])/2)
obj_mid_position = item.min[axis] + ((item.max[axis] - item.min[axis])/2)
#print(f"position_value : {item.name} = {position_value}\nobj_mid_position : {item.name} = {obj_mid_position}")
#replace the position of the selected axis
if min_max == 2:
subtracted_value = item.max[axis]
elif min_max == 0:
subtracted_value = item.min[axis]
else:
subtracted_value = obj_mid_position
newpos = rt.Point3(0,0,0)
newpos[axis] = position_value - subtracted_value
rt.move(item,newpos)
def align_plus_evenly_3d(axis):
"""
0 = x | 1 = y | 2 = z
0 = min | 1 = middle | 2 = max
"""
selected_object = rt.getCurrentSelection()
if len(selected_object) > 1:
#Sort the selected object list with the position, Point3 with the index of axis
#sorted_sel_obj = sorted(selected_object, key=lambda item: (MidPointPos(item, axis)))
#Set the position value for the first object position
sorted_sel_obj = sorted(selected_object, key=lambda item: item.pos[axis])
reference_pos = sorted_sel_obj[0].pos
position_distance = (sorted_sel_obj[len(sorted_sel_obj)-1].pos - (sorted_sel_obj[0]).pos)/rt.point3((len(selected_object)-1), (len(selected_object)-1), (len(selected_object)-1))
for item in sorted_sel_obj:
newpos = rt.Point3(0, 0, 0)
newpos = reference_pos - item.pos
rt.move(item, newpos)
reference_pos += position_distance