Blender 2.5: Extending grab mode?

Is there a way to write an operator which would go into grab mode (assuming that’s what it’s still called), and then do something in addition to moving the object around?

Let’s say I want to go into grab mode and additionally: change scale based on position, or initially set the mouse cursor to object position, so that, when object is visible on screen, its center is right behind the mouse cursor.

Bump.

/ten chars

Yes… and 10

Something as this?


##bruno franci - orinoco56
##Testing an operator to grab and to scale at the same time
##
##Call operator "grabscale" with barspace
##Select one or more objects
##Click and drag with left mouse how many times you want (click only in the view)
##Click right mouse to release operator

import bpy
from bpy.props import * 




class VIEW3D_OT_grabScale(bpy.types.Operator):
    bl_idname = "view3d.grabscale"
    bl_label = "grabscale"
    
    offset = FloatProperty(name="Offset") 
    lastX = FloatProperty(name="LastX") 
    access = BoolProperty(name="Acess") 
    #To change factor of scale
    scaleX = FloatProperty(name="ScaleX",default=0.1,description="Scale = mouse deplacement * scale - on axis X")
    scaleY = FloatProperty(name="ScaleY",default=0.1,description="Scale = mouse deplacement * scale - on axis Y")
    scaleZ = FloatProperty(name="ScaleZ",default=0.1,description="Scale = mouse deplacement * scale - on axis Z")
    
    def execute(self, context):
        props = self.properties
        objs_sel = [ob for ob in context.scene.objects if ob.selected]
        
        if len(objs_sel) >=1:
            for ob in objs_sel:
                ob.location[0] += props.offset
                ob.location[1] += 0.0
                ob.location[2] += 0.0
                ob.scale[0] += props.scaleX*props.offset
                ob.scale[1] += props.scaleY*props.offset
                ob.scale[2] += props.scaleZ*props.offset
        else:
            print("no_selected")
        
        return {'FINISHED'}
    
    def modal(self, context, event):
        objs_sel =  [ob for ob in context.selected_objects]
        if event.type == 'LEFTMOUSE': 
            self.properties.access = True
            if event.value == 'RELEASE':
                self.properties.access = False
                self.properties.lastX = 0.0
        elif event.type == 'MOUSEMOVE' and self.properties.access == True:
            
            if self.properties.lastX == 0.0:
                x = 0
            else:
                x =event.mouse_x * 0.05
            
            self.properties.offset = (x - self.properties.lastX) 
            self.properties.lastX = event.mouse_x * 0.05
            
            self.execute(context)
            
        elif event.type in ('RIGHTMOUSE', 'ESC'):
            return {'CANCELLED'}

        
        return {'RUNNING_MODAL'}


    def invoke(self, context, event):
        if context.space_data.type == 'VIEW_3D':
            context.manager.add_modal_handler(self)
            self.properties.lastX = 0
            self.properties.access = False
            return{'RUNNING_MODAL'}
        else:
            self.report({'WARNING'}, "Active space must be a View3d")
            return {'CANCELLED'}


bpy.types.register(VIEW3D_OT_grabScale)


@orinoco56

Thanks for the script; that will certainly help me.

However, that’s not really extending the operator - you just created a new one, and you had to write the code to change location yourself.

I was hoping that there was a way to extend an existing operator, or to call an existing operator from a custom operator, so that you don’t have to rewrite “grab” in “grabscale”.

@Uncle Entity

How could it be done?

I may be mistaken, but I doubt that python can extend an internal operator
But you can write an operator that call another operator. In your case at the place of ob.location
you can use:
Operator grab
bpy.ops.transform.translate(value=(x,y,z,w) …)
and for ob.scale operator resize
bpy.ops.transform.resize(value=(x,y,z,w) …)

doc here http://www.blender.org/documentation/250PythonDoc/bpy.ops.transform.html

Yeah, I think you’ll have to write the code yourself.

No way to tell blender to run one operator before another without using python AFAICT.

Once they get macros working though…

event.mouse_x returns the pixel location…how do I get that to a real location in the scene?