Copy rotation from cursor or active object to selected

cursor rotation 2 active object

import bpy
from bpy import context
cao=context.active_object
to_qt = context.scene.cursor.rotation_quaternion
R = to_qt.to_matrix().to_4x4()
cao.matrix_world @= R

this is working whatever rotation modes are

active rotation 2 selection

import bpy
from bpy import context
from mathutils import Matrix

cao=context.active_object
if cao.rotation_mode == 'AXIS_ANGLE':
    angle, *axis = cao.rotation_axis_angle
    R = Matrix.Rotation(angle, 4, axis)
    to_qt = R.to_quaternion()
elif cao.rotation_mode == 'QUATERNION':
    to_qt = cao.rotation_quaternion
else:
    to_qt = cao.rotation_euler.to_quaternion()

R = to_qt.to_matrix().to_4x4()
for ob in context.selected_objects:
    if ob != cao:
        ob.matrix_world @= R

or?

import bpy
from bpy import context

cao = context.active_object
rot_cao_mod = cao.rotation_mode
cao.rotation_mode = 'XYZ'

for ob in context.selected_objects:
    if ob != cao:
        rot_ob_mod = ob.rotation_mode
        ob.rotation_mode = 'XYZ'
        ob.rotation_euler = cao.rotation_euler
        ob.rotation_mode = rot_ob_mod
cao.rotation_mode = rot_cao_mod

ok all this code is not working when objects has parents, I found the solution in copy attribute addon. lower in comments

These won’t work visually if the source object is under multiple parents. It is probably a better idea to get the world matrix, deconstruct the matrix to rotation and pass that to the intended object. Obviously there will be cases when the final rotation won’t look like the source object’s rotation if they are not facing the same directions.

1 Like

ok it was much more harder. I found this code from copy attribute addon

import bpy
from bpy import context
from mathutils import Matrix
    
def world_to_basis(active, ob, context):
    """put world coords of active as basis coords of ob"""
    local = ob.parent.matrix_world.inverted() @ active.matrix_world
    P = ob.matrix_basis @ ob.matrix_local.inverted()
    mat = P @ local
    return(mat)

def rotcopy(item, mat):
    """Copy rotation to item from matrix mat depending on item.rotation_mode"""
    if item.rotation_mode == 'QUATERNION':
        item.rotation_quaternion = mat.to_3x3().to_quaternion()
    elif item.rotation_mode == 'AXIS_ANGLE':
        rot = mat.to_3x3().to_quaternion().to_axis_angle()    # returns (Vector((x, y, z)), w)
        axis_angle = rot[1], rot[0][0], rot[0][1], rot[0][2]  # convert to w, x, y, z
        item.rotation_axis_angle = axis_angle
    else:
        item.rotation_euler = mat.to_3x3().to_euler(item.rotation_mode)

  
active=context.active_object
ob = context.object

for ob in context.selected_objects:
    if ob.parent:
        mat = world_to_basis(active, ob, context)
        rotcopy(ob, mat.to_3x3())
    else:
        rotcopy(ob, active.matrix_world.to_3x3())