xD oh well, yours seems to be much more useful. Mine could use another snapping with empty object instead of placing 3d cursor at mouse position in the beginning, then both would be useful for their purpose - yours for relative translate, mine for parallel shift on the initially set-up axis.
Something similar could be done for rotation, just like in Google SketchUp!
BTW: if you abort while in modal translation, macro will terminate and leave behind the helper objects. Asked Campbell and he says there’s no way to detect that “event”. And that’s true, i can detect the init by wrapping the translate operator, but it doesn’t work for the esc/end (those events seem to occur on run script).
bl_info={
"name":"NP Anchor Translate 005",
"author":"Okavango with CoDEmanX, Lukas, matali",
"version":(0,0,5),
"blender":(2,68,0),
"location":"View3D",
"description":"Translate objects with anchor and target points - install, assign shortcut, save user settings",
"category":"3D View"}
import bpy
print("-"*30)
class AnchorTranslate(bpy.types.Macro):
bl_idname = "object.add_empty_and_translate"
bl_label = "Anchor Translate"
bl_options = {'REGISTER', 'UNDO'}
def __init__(self, *args, **kwargs):
print("INIT MACRO")
def __del__(self, *args, **kwargs):
print("DEL MACRO")
__delattr__ = __del__
__delitem__ = __del__
__new__ = __init__
class Storage:
snap_element = None
snap_target = None
class StoreSelectedObjects(bpy.types.Operator):
bl_idname = "object.store_selected"
bl_label = "Store Selected Objects"
bl_options = {'REGISTER', 'UNDO'}
def execute(self, context):
Storage.ob=bpy.context.selected_objects
ob=bpy.context.selected_objects
for o in ob:
o.select = False
Storage.snap_element = bpy.context.tool_settings.snap_element
Storage.snap_target = bpy.context.tool_settings.snap_target
return {'FINISHED'}
class AddCursorDummy(bpy.types.Operator):
bl_idname = "object.add_cursor_dummy"
bl_label = "Add Cursor Dummy"
bl_options = {'REGISTER', 'UNDO'}
def execute(self, context):
bpy.ops.mesh.primitive_cube_add()
Storage.dummy = bpy.context.object
return {'FINISHED'}
class AddAnchor(bpy.types.Operator):
bl_idname = "object.add_anchor"
bl_label = "Add Anchor"
bl_options = {'REGISTER', 'UNDO'}
def execute(self, context):
bpy.ops.mesh.primitive_cube_add(enter_editmode = True)
bpy.ops.mesh.select_all
bpy.ops.mesh.delete(type ='VERT')
bpy.ops.object.mode_set(mode='OBJECT')
Storage.anchor = bpy.context.object
bpy.context.tool_settings.snap_element = 'VERTEX'
bpy.context.tool_settings.snap_target = 'ACTIVE'
return {'FINISHED'}
class ActivateDummy(bpy.types.Operator):
bl_idname = "object.activate_dummy"
bl_label = "Activate Dummy"
bl_options = {'REGISTER', 'UNDO'}
def execute(self, context):
obdm=Storage.dummy
bpy.context.scene.objects.active = obdm
return {'FINISHED'}
class ActivateAnchor(bpy.types.Operator):
bl_idname = "object.activate_anchor"
bl_label = "Activate Anchor"
bl_options = {'REGISTER', 'UNDO'}
def execute(self, context):
oban=Storage.anchor
bpy.context.scene.objects.active = oban
oban.select = False
obdm=Storage.dummy
obdm.select = True
bpy.ops.object.delete('EXEC_DEFAULT')
oban.select = True
return {'FINISHED'}
class ReselectStoredObjects(bpy.types.Operator):
bl_idname = "object.reselect_stored"
bl_label = "Reselect Stored Objects"
bl_options = {'REGISTER', 'UNDO'}
def execute(self, context):
ob=Storage.ob
for o in ob:
o.select = True
return {'FINISHED'}
class DeselectStoredObjects(bpy.types.Operator):
bl_idname = "object.deselect_stored"
bl_label = "Deselect Stored Objects"
bl_options = {'REGISTER', 'UNDO'}
def execute(self, context):
ob=Storage.ob
for o in ob:
o.select = False
return {'FINISHED'}
class DeleteAnchor(bpy.types.Operator):
bl_idname = "object.delete_anchor"
bl_label = "Delete Anchor"
bl_options = {'REGISTER', 'UNDO'}
def execute(self, context):
bpy.ops.object.delete('EXEC_DEFAULT')
bpy.context.tool_settings.snap_element = Storage.snap_element
bpy.context.tool_settings.snap_target = Storage.snap_target
return {'FINISHED'}
class TT(bpy.types.Operator):
bl_idname = "object.tt"
bl_label = "tt wrap"
bl_options = {'REGISTER', 'UNDO'}
def __init__(self):
print("INIT TT")
def __del__(self):
print("DEL TT")
__delattr__ = __del__
__delitem__ = __del__
__new__ = __init__
def invoke(self, context, event):
bpy.ops.transform.translate('INVOKE_DEFAULT')
return {'FINISHED'}
def register():
bpy.utils.register_module(__name__)
AnchorTranslate.define("OBJECT_OT_store_selected")
AnchorTranslate.define("OBJECT_OT_add_cursor_dummy")
AnchorTranslate.define("VIEW3D_OT_cursor3d")
AnchorTranslate.define("OBJECT_OT_add_anchor")
AnchorTranslate.define("OBJECT_OT_activate_dummy")
AnchorTranslate.define("VIEW3D_OT_snap_cursor_to_active")
AnchorTranslate.define("OBJECT_OT_activate_anchor")
AnchorTranslate.define("TRANSFORM_OT_translate")
AnchorTranslate.define("OBJECT_OT_reselect_stored")
AnchorTranslate.define("OBJECT_OT_tt")
#AnchorTranslate.define("TRANSFORM_OT_translate")
AnchorTranslate.define("OBJECT_OT_deselect_stored")
AnchorTranslate.define("OBJECT_OT_delete_anchor")
AnchorTranslate.define("OBJECT_OT_reselect_stored")
def unregister():
bpy.utils.unregister_module(__name__)
if __name__ == "__main__":
register()