BS Modify Pivot Addon Release!

Hi guys.

I want to present our first addon for Blender.

In this case, since we come from 3dsmax and Maya, we missed a lot the ability to change the objects pivot orientation and I saw a lot of people here in the forums asking for the same thing, some people suggested to use the Hook modifer, but we wanted something simpler, similar to the ¨Affect Pivot Only¨ button present in 3dsmax… so we did it :slight_smile:

Here you have a video explaining it:

And here is the direct download link to the addon:

http://www.bone-studio.com/blenderaddons/BS_Modify_Pivot.zip

Hope you like it, comment it and if you have improvements in mind or you find any bugs, please tell me, I´ll try to fix it when I have a bit of time.

Cheers!

5 Likes

I thought it would be nice to have it as a modal operator and use it on the fly while working. It seems a bit more convenient. Like this:


You are welcome to use the code if you wish since I already wrote it (it might need a bit of cleaning up):


import bpy
selection = list()

def AlignPivotRotation(object, pivot_object):
    rotation = object.matrix_world.to_quaternion().inverted() * pivot_object.matrix_world.to_quaternion()  
    for v in object.data.vertices:
        v.co = rotation.inverted().to_matrix().to_4x4() * v.co
    object.matrix_world *= rotation.to_matrix().to_4x4()
    return 
def AlignPivotLocation(object, pivot_object):
    # remember selection, active, cursor location and mode
    original_cursor_location = bpy.context.scene.cursor_location.copy()
    original_selection = list()
    if len(bpy.context.selected_objects): 
        for everyobject in bpy.context.selected_objects:
            original_selection.append(everyobject)
    original_active = bpy.context.scene.objects.active
    original_mode = bpy.context.object.mode 
    bpy.ops.object.mode_set(mode = 'OBJECT')
    bpy.ops.object.select_all(action='DESELECT')
    
    # set pivot location
    bpy.context.scene.cursor_location = pivot_object.location
    object.select = True
    bpy.context.scene.objects.active = object
    bpy.ops.object.origin_set(type='ORIGIN_CURSOR')
    
    # reset selection, active, cursor location and mode
    bpy.ops.object.select_all(action='DESELECT')
    if original_selection:
        for every_object in original_selection:
            every_object.select = True 
    bpy.context.scene.objects.active = original_active
    bpy.ops.object.mode_set(mode = original_mode)  
    bpy.context.scene.cursor_location = original_cursor_location
    return

class MZPivot(bpy.types.Operator):
    bl_idname = "object.mz_pivot"
    bl_label = "Pivot" 
    bl_options = {"REGISTER", "UNDO"} 
    operation = bpy.props.EnumProperty(
    name="Operation:",
    description="Operation - Rotate or Grab",
    items=(
        ('ROTATE', "ROTATE", ""),
        ('GRAB', "GRAB", "")
           ),
    default='GRAB',
    )
    original_mode = bpy.props.StringProperty()
    object_name = bpy.props.StringProperty()
    start = 0 
    def modal(self, context, event):
        self.start += 1             
        if self.start == 1:
            if self.operation == 'ROTATE':
                bpy.ops.transform.rotate('INVOKE_DEFAULT') 
            if self.operation == 'GRAB':
                bpy.ops.transform.transform('INVOKE_DEFAULT') 
        if event.type in {'ENTER', 'LEFTMOUSE'}:  # modal rotation finished:     
            # math    
            AlignPivotRotation(bpy.data.objects[self.object_name], bpy.context.scene.objects.active)
            bpy.data.objects[self.object_name].rotation_euler = bpy.context.scene.objects.active.rotation_euler # in case greater than 180 degrees
            AlignPivotLocation(bpy.data.objects[self.object_name], bpy.context.scene.objects.active)                 
            # cleanup
            bpy.ops.object.delete()            
            if selection:
                for obj in selection:
                    obj.select = True                         
            bpy.context.scene.objects.active = bpy.data.objects[self.object_name]
            bpy.ops.object.mode_set(mode = self.original_mode)                                  
            del(selection[:])
            return {'FINISHED'}   
                   
        if event.type in {'RIGHTMOUSE', 'ESC', 'SPACE'}:  # modal rotation canceled: 
            bpy.ops.object.delete()
            if selection:
                for obj in selection:
                    obj.select = True
            bpy.context.scene.objects.active = bpy.data.objects[self.object_name]
            bpy.ops.object.mode_set(mode = self.original_mode)
            del(selection[:])
            return {'CANCELLED'}

        return {'RUNNING_MODAL'}

    def invoke(self, context, event):
        if context.object is not None : 
            # remember stuff
            self.original_mode = context.object.mode
            self.object_name = context.active_object.name
            bpy.ops.object.mode_set(mode = 'OBJECT')           
            if len(context.selected_objects): 
                for objs in context.selected_objects:
                    selection.append(objs)
                bpy.ops.object.select_all(action='DESELECT') 
                           
            tempPivot = bpy.data.objects.new( ("Pivot Point of " + self.object_name), None )
            tempPivot.show_x_ray = 1  
            tempPivot.show_axis = 1   
            tempPivot.matrix_world = bpy.context.scene.objects.active.matrix_world # place temp empty at the center of the object
            bpy.context.scene.objects.link( tempPivot )
            bpy.ops.object.select_all(action='DESELECT')
            tempPivot.select = True 
            bpy.context.scene.objects.active = tempPivot            
            context.window_manager.modal_handler_add(self)            
            return {'RUNNING_MODAL'}
        else:
            self.report({'ERROR'}, "No active object")
            return {'CANCELLED'}
            

def register():
    bpy.utils.register_class(MZPivot)

def unregister():
    bpy.utils.unregister_class(MZPivot)


if __name__ == "__main__":
    register()
2 Likes

Pretty cool Martin, I´ll implement it as soon as I have some time, but as something optional, one of the cool things with our addon is that the axis created is an standard object, so you can do whatever you want to it, a friend asked me if it could be constrained to another object, don´t ask me why, but it seems that it is something standard in maya´s world.

But in any case your implementation seems great too for many situations, how does this affect to the transform values and the delta transform values?

Cheers and thanks for the code and the suggestion! :smiley:

I did like the idea of separate object very much as well. I create an empty its just that it gets deleted when the operation is finished, so you can use all the usual rotate and grab snapping, numerical input, axis constraints and so on. I also like the idea that it can toggle between edit and object mode as needed, because I need to set origin location for symmetrize action quite a lot and want to be able to do it from edit mode.

Your implementation is pretty cool, I’ll include it as soon as i can.

At first I thought to do it modal but since it is my first add on I have not too much experience with Blender and Python, so finally I decided to do it as it is right now, and my testers liked it more than if it were modal, but I clearly see the benefits of being modal, specially the one you named about edit mode :slight_smile:

Cheers and thanks again!

Very good addon. Coming from 3dsmax, moving pivots in this way is one of this features that you love.

Totally agree!!

But I´m happy that this won´t be needed in 2.8! :smiley:

Finally the cursor witl have also orientation, so the cursor workflow will debunk this, and IMHO it is much better than this :slight_smile:

Cheers!

not really… As we don’t have yet transform operations for the cursor. It just snaps, isn’t it?

But we will have those transform values soon, it was confirmed to me by Pablo Vazquez :slight_smile:

Nice one. It will helps to those who jumped in blender from 3d max :slight_smile:
One more feature i miss in blender is “turn hidden edge” command very usefull for low poly modelling.

1 Like

I want to use this add-on with 2.8:flushed:

Really nice tool that , imo, is missing from Blender.
The one thing I would love to see is baking the modify and commit pivot functions into one command.

Something along the lines of
if modify Pivot active>commit pivot else modify pivot.
That way you could bind it to a single key, press it once to turn on modify pivot, place it where you want it to be, press the same keybind and it will then commit it (since modify pivot is still active). Not sure this makes sense.
In the meanwhile I’ll use two separate binds for this :slight_smile:

edit: making it so that when activating the modify pivot tool you immediately go into move mode would make this a lot more intuitive and cut down another keypress (and it could be cancelled quickly with right mouse click if you need to rotate it instead).

1 Like

Mmmmh, good ideas, but I did not merged commit because sometimes you want to do various operation with the pivot, translate, rotate, align, and also for being in one command I would have to do a modal operator, so it enters in modify pivot mode and when yo confirm it it exits that mode, but in that case you would be unable to change between translate and rotate, we could have two modes, but in that case I think the commit button is more comfortable.

But I will think into it :slight_smile:

Cheers!

Will you be updating this for 2.8? Looks really useful, I love the pivot system in Maya so this is pretty close.

1 Like

I already ported it to 2.8, the link to download it is in the video description in YouTube :slight_smile:

Cheers!

4 Likes

To save time for those who are searching for the download link (for Blender 2.8), here it is : https://www.Bone-Studio.com/blenderaddons/BS_Modify_Pivot_2_8.zip

1 Like

Hi @Bone-Studio. Thank you for your addon.

I noticed this message in the console :

Warning: ‘BSModifyPivotPanel’ doesn’t contain _ PT _ with prefix & suffix

I don’t know if it’s important or not, I just wanted to report it to you.

We need to update it, we will do ASAP

1 Like