Is there a simple way to copy a custom transform orientation to an object's rotation vector?

There is a command "Object / Transform / Align to transform orientation", but what I need is kind of "inverted" version of it.

I created an animation to make it clear what exactly I mean.

Now I join one object to another in order to inherit its rotation. And doing so I feel stupid. I'm sure there is a simple way, but I just can't find it.

Please help.

enter image description here

  • 1
    $\begingroup$ I don't believe there is actually... Your solution might be THE solution. $\endgroup$ – Bert VdB Jun 16 '18 at 15:54
  • $\begingroup$ Bert VdB. do you mean the only solution? $\endgroup$ – Mechanic Jun 16 '18 at 16:32

I've contrived some code to do the trick. Please don't laugh on the lame-code - it works. :-) Maybe somebody will find it useful.

If you want to use it, just save the the text below as the "align_to_to_inverted.py" file, and then install it as an add-on. And you will have the "Align to Transform Orientation inverted" command in your Object menu. It's tricky to insert it in the "Object > Transform", so let's let it be there =).

To use it, in the Object mode select the source object and then the target object (if you want to copy source object's rotation), and execute the command. Selction will be reset, but the target object will remain active.

If you want to align to Transform Orientation, select the only target object, and execute the command. Note that you must set some custom transform orientation. Built in orientations, like Global, View, etc, will not do.

# align_to_to_inverted.py
# The script will align active object to selected one (if there is another selected object).
# or it will use current custom Transform Orientation (if any).
# It changes object's rotation values, but leaves its orientation intact.
# (c) LIII A.S. Mechanic Kharkov

bl_info = {
    "name": "Align to Transform Orientation inverted",
    "description": "Operator to set object's rotation as another's or current custom transform orientation.",
    "location": "Object menu",
    "version": (0, 1, 1),
    "blender": (2, 76, 0),
    "support": "COMMUNITY",
    "wiki_url": "https://blender.stackexchange.com/q/110894/23172",
    "warning": "",
    "category": "Object",
    "author" : "Mechanic. Kharkov."

import bpy
from mathutils import * # yes, I know

class AlignToTOInverted(bpy.types.Operator):
    """Aligns active object's rotation values only to selected or TO"""
    bl_idname = "object.align_to_to_inverted"
    bl_label = "Align to Transform Orientation inverted"
    bl_options = {'REGISTER', 'UNDO'}  # Enable undo for the operator.

    def poll(cls, context):
        return context.active_object is not None

    def execute(self, context):

        trg = bpy.context.active_object
        print("trg: %s" %(trg))

        #find source object
        src = None
        for o in bpy.context.selected_objects:
            if o != trg:
                src = o

        if not src:

            #try to find current user Transform Orientation
            #but this will work only in 3DVIEW space.
            mco = None
                co = bpy.context.space_data.current_orientation
                if co:
                    mco = co.matrix
                    print("Using Ttansform Oientation %s" % (co.name))
                    print("matrix= %s" % (mco))
                    print("No Ttansform Oientation found")
                mco = None

            if not mco:    
                self.report({'ERROR_INVALID_INPUT'},"No source object selected\nYou have to select two objects, or be in a custom Transform Orientation.")
                return {'CANCELLED'}

            # ger src natrix, and transposed
            msrc = mco
            trs = msrc.transposed()
            q = trs.to_quaternion()

            # source given as object
            print("Source object: %s" %(src))
            # ger src natrix, and transposed
            msrc = src.matrix_world
            trs = msrc.transposed()
            q = trs.to_quaternion()

        #now we rotate trg back to apply zero rotation
        mtrg = trg.matrix_world.copy().to_3x3()
        mtrg = mtrg.to_4x4()
        trg.matrix_world *= mtrg
        #deselect all but trg object
        #select trg as active object
        trg.select = True
        bpy.context.scene.objects.active = trg
        #apply this as default rotation
        bpy.ops.object.transform_apply(location=False, rotation=True, scale=False)
        #and now rotate back to src rotation
        q = msrc.to_quaternion()
        mtrg = trg.matrix_world.to_3x3()
        mtrg = mtrg.to_4x4()
        trg.matrix_world *= mtrg

        return {'FINISHED'}

def menu_func(self, context):

def register():

def unregister():

# This allows you to run the script directly from Blender's Text editor
# to test the add-on without having to install it.
if __name__ == "__main__":

    # test call

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.