How to add functionality to the 3D cursor Panel on 3D view (and other coding primers)

Hello, all

I’m an egress of 3dsmax and I’ve just adapted a maxscript tool I used a lot back there to Blender/python.

It works. Basically, right now, it picks a 4-object selection and put the active one in the center of the circle defined by the other three ones.

I’m figuring, though, that it’s not trivial to make things like outputting to the python console and creating global variables, things I consider valuable to explore what methods and properties give me back according to selection and etc. Could you guys point me to some direction?

Also, it’s now quite obvious that, while it was easy (and lazy) for me to just define it as a global function in 3dsmax and use it this way whenever I needed, it’s become quite obvious that in Blender this thing should make use of the 3D cursor and make it to the 3D cursor panel in the 3D view Properties shelf.

Any tips on how to create a button below the X,Y and Z boxes? The Templates offered in the Text Editor are quite confusing for beginners and it’s still a bit hard to figure what operators are, for instance.

Finally, in case you guys are wondering about the code I’ve written, here it is. Feel free to criticize, use, modify and whatever.


import bpy
from mathutils import *; from math import *
import mathutils


C = bpy.context


def circumcenter():


    def baricenter (p0, p1, p2, u, v, w): 
        return (u*p0 + v*p1 + w*p2) / (u + v + w)
    
    if (len(C.selected_objects) >= 4):
        
        p=[];
        for obj in C.selected_objects:
            if (obj != C.object):
                p.append(obj.location)
        
        a = p[2] - p[1]
        b = p[0] - p[2]
        c = p[1] - p[0]
        u = a.dot(a) * c.dot(b)
        v = b.dot(b) * c.dot(a)
        w = c.dot(c) * b.dot(a)


        circumcenter_cache = baricenter(p[0], p[1], p[2], u, v, w);
        
        C.object.location = circumcenter_cache
    else:
        circumcenter_cache = mathutils.Vector((0.0, 0.0, 0.0))            


    return circumcenter_cache


print(circumcenter())

Ok, I figured everything out myself. I have a finalized thing that behaves like a proper addon (seemingly).

Code below. Where should I publish it?


bl_info = {
    "name": "3D Cursor Panel extension",
    "author": "Fernando D'Andrea",
    "version": (0, 1),
    "blender": (2, 78, 0),
    "location": "View3D > 3D Cursor",
    "description": "Extends 3D Cursor panel funcionality",
    "warning": "",
    "wiki_url": "",
    "category": "3D View"
    }
    
import bpy
import mathutils
def dandrea_3dcursor_panel(self, context):


    layout = self.layout
    row1 = layout.row(align=True)
    row1.operator("view3d.snap_cursor_to_selected", text="Cursor to Selected")
    row1.operator("view3d.snap_selected_to_cursor", text="Selected to Cursor")
    row2 = layout.row(align=True)
    row2.operator("view3d.circumcenter3dcursor", text="Circumcenter")




class circumcenter3dcursor(bpy.types.Operator):
    """Center the 3D Cursor in the circle defined by three selected objects."""
    bl_idname = "view3d.circumcenter3dcursor"
    bl_label = "Circumcenter 3d Cursor"


    circumcenter_cache = mathutils.Vector((0.0, 0.0, 0.0))            


    @classmethod
    def poll(cls, context):
        return (len(bpy.context.selected_objects) >= 3)


    def execute(self, context):
    
        def barycentricToWorld (p0, p1, p2, u, v, w): 
            return (u*p0 + v*p1 + w*p2) / (u + v + w)    
            
        print ("circumcenter3dcursor(): running...")
        
        p=[];
        for obj in bpy.context.selected_objects:
            p.append(obj.location)
        
        a = p[2] - p[1]
        b = p[0] - p[2]
        c = p[1] - p[0]
        u = a.dot(a) * c.dot(b)
        v = b.dot(b) * c.dot(a)
        w = c.dot(c) * b.dot(a)


        circumcenter_cache = barycentricToWorld(p[0], p[1], p[2], u, v, w);
        
        print (circumcenter_cache)
        
        bpy.context.scene.cursor_location = circumcenter_cache


        return {'FINISHED'}


def register():
    bpy.utils.register_class(circumcenter3dcursor)
    bpy.types.VIEW3D_PT_view3d_cursor.append(dandrea_3dcursor_panel)


def unregister():
    bpy.utils.unregister_class(circumcenter3dcursor)
    bpy.types.VIEW3D_PT_view3d_cursor.remove(dandrea_3dcursor_panel)


if __name__ == "__main__":
    unregister()
    register()