Align Plus

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

  1. Simply just drag the InstallerDragnDrop.ms script to the viewport to install.
  2. Right-click on the toolbar > Customize…
  3. Choose the tab ‘Toolbars’
  4. In the Category: dropdown, select ‘ManniiCode’
  5. Drag the script to the toolbar where ever you want!
  6. 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
            

Images