Trying to produce similar behavior to the standard Blender rotate operator, for a modal operator I'm building. This stackoverflow post seems to be on the right track but I'm confused as to how I might implement the math. Also, limiting the rotation to a single axis at a time (as the locked axis image below displays) would be fine. Basically want to emulate what Blender's rotate operator does once you've locked an axis (doesn't seem like it should be to hard).
I've got everything else worked out, I just need a bit of code that takes, mouse_x, mouse_y, object_x and object_y and spits out a corresponding angle for say Y rotation of the object.
EDIT: Though the title reads (not in bge) I'm not at all opposed to importing something from the bge module to use it if it can solve this problem (just meant that this is for use directly in Blender, not for the game engine).
Below is what I've got so far. Thought it might help if I traded out the direct object 3D coordinates with those from the screen (only found region coordinates via bpy_extras.view3d_utils though). Currently, the mouse rotation does not correctly equate to the y axis rotation. Any ideas? Another approach perhaps?
import bpy, math
from bpy_extras import view3d_utils
#Call from Space menu in 3D View. For this example
#you would want to be looking in front perspective.
class custom_rotate(bpy.types.Operator):
bl_idname = "transform.custom_rotate"
bl_label = "Custom Rotate"
def modal(self, context, event):
#Grab active
ob = bpy.context.object
#Region context for view3d_utils
region = context.region
rv3d = context.region_data
coord = ob.location.x, ob.location.y, ob.location.z
#Convert ob loc to region loc (maybe would work with screen loc
#if I could get it some how?)
ob_region = view3d_utils.location_3d_to_region_2d(region,
rv3d, coord)
val1_x = ob_region.x
val1_y = ob_region.y
val2_x = event.mouse_x
val2_y = event.mouse_y
#Get rotation angle and update object rotation
alpha_angle = math.atan2(val2_y-val1_y, val2_x-val1_x)
ob.rotation_euler.y = alpha_angle
#Print angle in degrees to help with testing...
print('alpha angle:',math.degrees(alpha_angle))
#FINISH
if event.type in ['LEFTMOUSE','ENTER']:
print('finished')
return{'FINISHED'}
if event.type in ['ESC','RIGHTMOUSE']:
return {'CANCELLED'}
return {'RUNNING_MODAL'}
def invoke(self, context, event):
context.window_manager.modal_handler_add(self)
return {'RUNNING_MODAL'}
def register():
bpy.utils.register_module(__name__)
def unregister():
bpy.utils.unregister_module(__name__)
if __name__ == "__main__":
register()