Skip to content

Instantly share code, notes, and snippets.

@JacRossiter
Created December 7, 2019 00:00
Show Gist options
  • Save JacRossiter/7c0e9c0e187f254bbf2867de1ab52932 to your computer and use it in GitHub Desktop.
Save JacRossiter/7c0e9c0e187f254bbf2867de1ab52932 to your computer and use it in GitHub Desktop.
Adds 'Apply Delta' Button to Ctrl A menu. also various link transform buttons added to Ctrl L menu.
bl_info = {
"name" : "JLink: Link Transforms",
"author" : "Jac Rossiter",
"description" : "Adds to Object Link and Apply menus",
"blender" : (2, 81, 0),
"version" : (0, 0, 0, 4),
"warning" : "",
"category" : "Object"
}
import bpy
import mathutils
from bpy.types import Panel, Operator
class LinkLocation_Operator(Operator):
bl_idname = "link.location"
bl_label = "Link Location"
bl_description = "............."
bl_options = {'REGISTER'}
def execute(self, context):
active_location = bpy.context.view_layer.objects.active.location
for obj in bpy.context.selected_objects:
try:
bpy.context.view_layer.objects.active = obj
bpy.context.view_layer.objects.active.location = active_location
except:
pass
return {'FINISHED'}
class LinkRotation_Operator(Operator):
bl_idname = "link.rotation"
bl_label = "Link Rotation"
bl_description = "............."
bl_options = {'REGISTER'}
def execute(self, context):
active_rotation = bpy.context.view_layer.objects.active.rotation_euler
for obj in bpy.context.selected_objects:
try:
bpy.context.view_layer.objects.active = obj
bpy.context.view_layer.objects.active.rotation_euler = active_rotation
except:
pass
return {'FINISHED'}
class LinkScale_Operator(Operator):
bl_idname = "link.scale"
bl_label = "Link Scale"
bl_description = "............."
bl_options = {'REGISTER'}
def execute(self, context):
active_scale = bpy.context.view_layer.objects.active.scale
for obj in bpy.context.selected_objects:
try:
bpy.context.view_layer.objects.active = obj
bpy.context.view_layer.objects.active.scale = active_scale
except:
pass
return {'FINISHED'}
class LinkTransform_Operator(Operator):
bl_idname = "link.transform"
bl_label = "Link Transform"
bl_description = "............."
bl_options = {'REGISTER'}
def execute(self, context):
active_location = bpy.context.view_layer.objects.active.location
active_rotation = bpy.context.view_layer.objects.active.rotation_euler
active_scale = bpy.context.view_layer.objects.active.scale
for obj in bpy.context.selected_objects:
try:
bpy.context.view_layer.objects.active = obj
bpy.context.view_layer.objects.active.location = active_location
bpy.context.view_layer.objects.active.rotation_euler = active_rotation
bpy.context.view_layer.objects.active.scale = active_scale
except:
pass
return {'FINISHED'}
class RotationFromCursor_Operator(Operator):
bl_idname = "link.cursor_rotation"
bl_label = "Set Object Rotation using 3D Cursor"
bl_description = "Orients your object rotation in relation to your 3D Cursor"
bl_options = {'REGISTER'}
def execute(self, context):
#Code from Sergey Kritskiy
def Rotate(myMesh, mat):
for v in myMesh.vertices:
vec = mat @ v.co
v.co = vec
def RotateFromCursor():
source = bpy.context.scene.cursor
objects = bpy.context.selected_objects
mat_source = source.rotation_euler.to_matrix()
mat_source.invert()
for ob in objects:
mat_ob = ob.rotation_euler.to_matrix()
if ob.type == 'MESH':
mat = mat_source @ mat_ob
Rotate(ob.data, mat)
ob.rotation_euler = source.rotation_euler
RotateFromCursor()#
return {'FINISHED'}
class ApplyDelta_Operator(Operator):
bl_idname = "apply.delta"
bl_label = "Apply Delta Transforms"
bl_description = "Applies Delta Transforms to selected objects"
bl_options = {'REGISTER'}
def execute(self, context):
for obj in bpy.context.selected_objects:
bpy.context.view_layer.objects.active = obj
bpy.ops.object.make_single_user(type='SELECTED_OBJECTS', obdata=True)
# Store delta location of object
loc_delta = obj.delta_location
scale_delta = obj.delta_scale
rot_delta = obj.delta_rotation_euler
positionToCheck = obj.delta_location
positionToCompareTo = mathutils.Vector([0,0,0])
distance = (positionToCheck - positionToCompareTo).length
nearDistance = 0.00001
if distance < nearDistance:
print("the positions are nearly equal")
pass
else:
print("the positions are too different")
obj.location = loc_delta
obj.delta_location = (0,0,0)
positionToCheck = obj.delta_scale
positionToCompareTo = mathutils.Vector([1,1,1])
if distance < nearDistance:
print("the scales are nearly equal")
pass
else:
print("the scales are too different")
obj.scale = scale_delta
obj.delta_scale = (1,1,1)
positionToCheck = obj.delta_rotation_euler
positionToCompareTo = mathutils.Vector([0,0,0])
if distance < nearDistance:
print("the scales are nearly equal")
pass
else:
print("the scales are too different")
obj.rotation_euler = rot_delta
obj.delta_rotation_euler = (0,0,0)
def link_menu(self, context):
layout = self.layout
layout.separator()
layout.operator("link.location", text="Location")
layout.operator("link.rotation", text="Rotation")
layout.operator("link.scale", text="Scale")
layout.operator("link.transform", text="All Transforms")
layout.operator("link.cursor_rotation", text="Rotation from 3D Cursor")
def apply_menu(self, context):
layout = self.layout
layout.separator()
layout.operator("apply.delta", text="Apply Delta Transforms")
classes = (
LinkLocation_Operator,
LinkRotation_Operator,
LinkScale_Operator,
LinkTransform_Operator,
RotationFromCursor_Operator,
ApplyDelta_Operator
)
def register():
from bpy.utils import register_class
for cls in classes:
register_class(cls)
bpy.types.VIEW3D_MT_make_links.append(link_menu)
bpy.types.VIEW3D_MT_object_apply.append(apply_menu)
def unregister():
from bpy.utils import unregister_class
for cls in reversed(classes):
unregister_class(cls)
bpy.types.VIEW3D_MT_make_links.remove(draw_menu)
if __name__ == "__main__":
register()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment