Skip to content

Instantly share code, notes, and snippets.

@juliomarcos
Last active March 27, 2024 13:32
Show Gist options
  • Save juliomarcos/1578aed812a8996e9b3418c51fd6b1da to your computer and use it in GitHub Desktop.
Save juliomarcos/1578aed812a8996e9b3418c51fd6b1da to your computer and use it in GitHub Desktop.
Puts the object on top of the xy grid-floor using an align to axis strategy
# This work comes directly from a tool available on the SideLabs houdini toolset
bl_info = {
"name": "Align object to axis",
"author": "Júlio Rodrigues",
"version": (0, 1),
"blender": (2, 80, 0),
"location": "View3D > Object > Align to Axis",
"description": "Align object to axis. Useful to put an object perfectly on top of the XY floor plane.",
"warning": "",
"wiki_url": "",
"category": "Object",
}
import bpy
from mathutils import(
Matrix,
Vector)
from bpy.props import(
EnumProperty,
BoolProperty
)
def main(op, context):
for ob in context.selected_objects:
mw = ob.matrix_world
bb = ob.bound_box
lower_corner = mw @ Vector(bb[0])
upper_corner = mw @ Vector(bb[-2])
translation = Vector((0, 0, 0))
if op.xAxis == 'M':
translation[0] = -lower_corner[0]
if op.yAxis == 'M':
translation[1] = -lower_corner[1]
if op.zAxis == 'M':
translation[2] = -lower_corner[2]
if op.xAxis == 'm':
translation[0] = -upper_corner[0]
if op.yAxis == 'm':
translation[1] = -upper_corner[1]
if op.zAxis == 'm':
translation[2] = -upper_corner[2]
if op.xAxis == 'C':
translation[0] = -(lower_corner[0] + upper_corner[0]) / 2
if op.yAxis == 'C':
translation[1] = -(lower_corner[1] + upper_corner[1]) / 2
if op.zAxis == 'C':
translation[2] = -(lower_corner[2] + upper_corner[2]) / 2
bpy.ops.transform.translate(
value=translation,
orient_type='GLOBAL',
orient_matrix_type='GLOBAL',
orient_matrix=Matrix.Identity(3))
if op.applyLocationTransformation:
bpy.ops.object.transform_apply(location=True)
def produce_axis_items():
return [
('N', 'Do Nothing', 'Do Nothing'),
('C', 'Center', 'Center'),
('m', 'Min', 'Min'),
('M', 'Max', 'Max')
]
class AlignAxisOperator(bpy.types.Operator):
"""Align object to one ore more axes according to its bouding box"""
bl_idname = "object.align_axis_operator"
bl_label = "Align Object to Axis"
bl_options = {'REGISTER', 'UNDO'}
xAxis: EnumProperty(
name='X-Axis',
description='X-Axis',
items=produce_axis_items(),
default='C'
)
yAxis: EnumProperty(
name='Y-Axis',
description='Y-Axis',
items=produce_axis_items(),
default='C'
)
zAxis: EnumProperty(
name='Z-Axis',
description='X-Axis',
items=produce_axis_items(),
default='M'
)
applyLocationTransformation: BoolProperty(
name='Apply Location Transformation',
description='Automatically aplies a location transformation',
default=True
)
@classmethod
def poll(cls, context):
return context.active_object is not None
def execute(self, context):
main(self, context)
return {'FINISHED'}
def draw(self, context):
layout = self.layout
layout.prop(self, 'xAxis')
layout.prop(self, 'yAxis')
layout.prop(self, 'zAxis')
layout.separator_spacer()
layout.prop(self, 'applyLocationTransformation')
def menu_func(self, context):
layout = self.layout
layout.separator()
layout.operator_context = "INVOKE_DEFAULT"
layout.operator(AlignAxisOperator.bl_idname, text=AlignAxisOperator.bl_label)
def register():
bpy.utils.register_class(AlignAxisOperator)
bpy.types.VIEW3D_MT_object.append(menu_func)
def unregister():
bpy.utils.unregister_class(AlignAxisOperator)
bpy.types.VIEW3D_MT_object.remove(menu_func)
if __name__ == "__main__":
register()
# test call
# bpy.ops.object.align_axis_operator()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment