Blender Addon — corn.py

bl_info = { "name": "Corn Device", "author": "dustractor@gmail.com", "version": (99, 0), "blender": (2, 5, 8), "api": 37702, "location": "View3D > UI > example", "description": "these are some of the tools i use most frequently.", "warning": "", "wiki_url": "", "tracker_url": "", "category": "3D View" }

import bpy
import math
import types
import random
def sl(x):x.select=True
def nv(x):x.select=not x.select
sel=lambda x:sl(x)
inv=lambda x:nv(x)
ptp=lambda x:print(type(x))
lsm=lambda x,y:list(map(x,y))
seln=lambda x,y:lsm(sel,[x[i] for i in range(0,len(x),y)])
flipn=lambda x,y:lsm(inv,[x[i] for i in range(0,len(x),y)])
OB='OBJECT'
ED='EDIT'
VM=[True,False,False]
EM=[False,True,False]
FM=[False,False,True]
idname=lambda x:'object.'+x.__name__
IDNAME=lambda x:'OBJECT_OT_'+x.__name__
label=lambda x:x.__name__.replace('_',' ')

ops={}
units={}
panels=[]

def UiUnit(group,editing_mode=None,selection_mode=None):
    print (group,editing_mode,selection_mode)
    if group not in units:
        print('making group:',group)
        units[group]={'ops':[],'props':[]}
        print (units[group])

    def make_unit(u):
        print ('making unit:',u)
        if isinstance(u,types.FunctionType):
            opdict= {'bl_idname':idname(u), 'bl_label':label(u), 'bl_options':{'REGISTER','UNDO'}, 'f':u, 'editing_mode':editing_mode, 'selection_mode':selection_mode}
            ops[idname(u)]= type(IDNAME(u),(Op,),opdict)
            print ('new op:',ops[idname(u)])
            units[group]['ops'].append(idname(u))
            return u
        elif isinstance(u,bpy.types.PropertyGroup.__class__):
            for p in [x for x in u.__dict__.keys() if not (x.startswith('__') and x.endswith('__'))]:
                units[group]['props'].append((p,u.__doc__))
            bpy.utils.register_class(u)
            e='bpy.types.Scene.'+u.__doc__+'=bpy.props.PointerProperty(type=u)'
            print (e)
            exec(e)
            return u
    return make_unit

class Op(bpy.types.Operator):
    @classmethod
    def poll(self,context):return context.active_object.type=='MESH'

    @classmethod
    def __init__(cls):
        cls.lastobstats=None
        cls.VtoV={}
        cls.VtoE={}
        cls.EtoF={}
        cls.EKtoEI={}

    @classmethod
    def object_stat_check(cls,self):
        print(cls,self)
        c=(len(self.ob.data.vertices),len(self.ob.data.edges),len(self.ob.data.faces))
        p=cls.lastobstats
        print("p:",p)
        print("c:",c)
        cls.lastobstats=c
        return p == c

    @classmethod
    def build_map(cls,self):
        for v in self.ob.data.vertices:
            cls.VtoE[v.index]=[]
            cls.VtoV[v.index]=set()
        for e in [e.key for e in self.ob.data.edges]:
            cls.VtoV[e[0]].add(e[1])
            cls.VtoV[e[1]].add(e[0])
        for e in self.ob.data.edges:
            for v in e.vertices:
                cls.VtoE[v].append(e.index)
            cls.EtoF[e.index]=[]
            cls.EKtoEI[e.key]=e.index
        for f in self.ob.data.faces:
            for k in f.edge_keys:
                cls.EtoF[cls.EKtoEI[k]].append(f.index)

    def getVsel(self):
        return [v for v in self.ob.data.vertices if v.select]

    def getEsel(self):
        return [e for e in self.ob.data.edges if e.select]

    def getFsel(self):
        return [f for f in self.ob.data.faces if f.select]

    def getVselIndices(self):
        return [v.index for v in self.ob.data.vertices if v.select]

    def getEselIndices(self):
        return [e.index for e in self.ob.data.edges if e.select]

    def getFselIndices(self):
        return [f.index for f in self.ob.data.faces if f.select]

    def preOp(self,context):
        self.ob=context.active_object
        if context.scene.topo.only_this:
            self.not_this_then=self.getEselIndices()

        if not self.object_stat_check(self):
            self.build_map(self)
        bpy.ops.object.mode_set(mode=self.editing_mode)
        bpy.context.tool_settings.mesh_select_mode=self.selection_mode

    def postOp(self,context):
        if context.scene.topo.only_this:
            bpy.ops.object.mode_set(mode='OBJECT')
            for e in self.not_this_then:
                self.ob.data.edges[e].select=False
        if context.scene.general.endmode:
            bpy.ops.object.mode_set(mode='EDIT')

    def invoke(self,context,event):
        self.preOp(context)
        self.execute(context)
        self.postOp(context)
        return {'FINISHED'}

    def execute(self,context):self.f(context)

class automagic_panel(bpy.types.Panel):
    bl_space_type,bl_region_type,bl_context=['VIEW_3D','UI','object']

    @classmethod
    def poll(self,context):return context.active_object.type=='MESH'

    def draw(self,context):
        l=self.layout
        r=l.row()
        r.label(self.bl_label)
        r=l.row()
        b=r.box()
        for p in units[self.bl_label]['props']:
            r=b.row()
            s='r.prop(context.scene.'+p[1]+', p[0])'
            exec(s)
        for o in units[self.bl_label]['ops']:
            r=b.row()
            r.operator(o)

def make_panel(name):
    panels.append(type('OBJECT_PT_'+name,(automagic_panel,),{'bl_label':name}))
#########################################################

@UiUnit('tesser')
class TesseraSettings(bpy.types.PropertyGroup):
    '''tessera'''
    r= bpy.props.IntProperty(name='r',min=2,max=33,default=5)
    xflip= bpy.props.BoolProperty(name="xflip")
    yflip= bpy.props.BoolProperty(name="yflip")

@UiUnit('nbase')
class nBaseSettings(bpy.types.PropertyGroup):
    '''nbase'''
    n=bpy.props.IntProperty(min=2,max=99)
    sel_action=bpy.props.EnumProperty(name="select action", items=[('seln','select','select'),('flipn','flip','flip')],default='seln')

@UiUnit('topo')
class topoSettings(bpy.types.PropertyGroup):
    '''topo'''
    only_this=bpy.props.BoolProperty(name='only this')

@UiUnit('materials')
class MatOpSettings(bpy.types.PropertyGroup):
    '''mats'''
    n=bpy.props.IntProperty(min=1,max=20)
    shade=bpy.props.BoolProperty(name="shadeless")
    wires=bpy.props.BoolProperty(name="wireframe")

@UiUnit('general')
class GeneralSettings(bpy.types.PropertyGroup):
    '''general'''
    endmode=bpy.props.BoolProperty(name="end in edit mode")

@UiUnit('general',ED,FM)
def select_tris(op,c):
    bpy.ops.mesh.select_by_number_vertices(type='TRIANGLES')

@UiUnit('general',ED,FM)
def select_quads(op,c):
    bpy.ops.mesh.select_by_number_vertices(type='QUADS')

@UiUnit('general',OB,EM)
def just_edges(op,c):
    selEIdict=dict({e:0 for e in op.getEselIndices()})
    for f in op.getFsel():
        for k in f.edge_keys:
            selEIdict[op.EKtoEI[k]]+=1
    for e in selEIdict.items():
        if e[1]>1:
            op.ob.data.edges[e[0]].select=False
    for f in op.getFsel():
        f.select=False

@UiUnit('topo',ED,EM)
def multi_select_loops(ob,c):
    bpy.ops.mesh.loop_multi_select(ring=False)

@UiUnit('topo',ED,EM)
def multi_select_ring(ob,c):
    bpy.ops.mesh.loop_multi_select(ring=True)

@UiUnit('topo',OB,VM)
def vertex_neighbors(op,c):
    vsi=op.getVselIndices()
    vsn=set()
    for v in vsi:
        for vn in op.VtoV[v]:
            vsn.add(vn)
    for v in vsn:
        op.ob.data.vertices[v].select=True
    for v in vsi:
        op.ob.data.vertices[v].select=False

@UiUnit('topo',OB,EM)
def eloop(op,c):
    edges_to_select=set()
    for edge in op.getEsel():
        for f in op.EtoF[edge.index]:
            for k in op.ob.data.faces[f].edge_keys:
                vin=False
                for v in edge.key:
                    if v in k:
                        vin=True
                if vin:
                    continue
                else:
                    edges_to_select.add(op.EKtoEI[k])
    for e in edges_to_select:
        op.ob.data.edges[e].select=True

@UiUnit('topo',OB,EM)
def extend(op,c):
    pts={}
    for v in op.getVsel():
        pts[v.index]=False
    impfs=set()
    for e in op.getEsel():
        for v in e.key:
            pts[v] = not pts[v]
        for f in op.EtoF[e.index]:
            impfs.add(f)
    evs=[pt for pt in pts if pts[pt] is True]
    implicated_face_verts=set()
    epneighbors=set()
    for f in impfs:
        for v in op.ob.data.faces[f].vertices:
            implicated_face_verts.add(v)
    for v in evs:
        for vn in op.VtoV[v]:
            epneighbors.add(vn)
    them=epneighbors.difference(implicated_face_verts)
    for v in them:
        for e in op.VtoE[v]:
            for vi in op.ob.data.edges[e].key:
                if vi in evs:
                    op.ob.data.edges[e].select=True

@UiUnit('materials',OB,FM)
def nmats(op,c):
    for i in range(len(op.ob.data.faces)):
        op.ob.data.faces[i].material_index=i%c.scene.mats.n

@UiUnit('materials',OB,FM)
def add_random_materials(op,c):
    for i in range( c.scene.mats.n):
        mat = bpy.data.materials.new("random")
        mat.diffuse_color = (random.random(),random.random(),random.random())
        mat.use_shadeless=c.scene.mats.shade
        mat.type=['SURFACE','WIRE'][c.scene.mats.wires]
        op.ob.data.materials.append(mat)

@UiUnit('nbase',OB,VM)
def nth_vertices(op,c):{'seln':seln,'flipn':flipn}[c.scene.nbase.sel_action](op.ob.data.vertices,c.scene.nbase.n)

@UiUnit('nbase',OB,EM)
def nth_edges(op,c):{'seln':seln,'flipn':flipn}[c.scene.nbase.sel_action](op.ob.data.edges,c.scene.nbase.n)

@UiUnit('nbase',OB,FM)
def nth_faces(op,c):{'seln':seln,'flipn':flipn}[c.scene.nbase.sel_action](op.ob.data.faces,c.scene.nbase.n)

@UiUnit('general',ED,FM)
def sub_1(op,c):bpy.ops.mesh.subdivide()

@UiUnit('general',ED,FM)
def sub_2(op,c):bpy.ops.mesh.subdivide(number_cuts=2)

@UiUnit('general',ED,FM)
def exmerge(op,c):
    try:
        bpy.ops.mesh.extrude(type='FACES'); bpy.ops.mesh.merge(type='COLLAPSE')
    except:
        bpy.ops.mesh.select_all(action='SELECT')
        bpy.ops.mesh.extrude(type='FACES'); bpy.ops.mesh.merge(type='COLLAPSE')
        
@UiUnit('general',ED,EM)
def border(op,c):
    bpy.ops.mesh.select_all(action='DESELECT')
    bpy.ops.mesh.select_non_manifold()
@UiUnit('general',ED,FM)
def join_tris(op,c):bpy.ops.mesh.tris_convert_to_quads()

@UiUnit('tesser',OB,VM)
def tesser_out(op,c):
    r=c.scene.tessera.r
    xt=op.ob.dimensions[0]
    yt=op.ob.dimensions[1]
    rv=math.pi/2
    xf=c.scene.tessera.xflip
    yf=c.scene.tessera.yflip
    moves=range(-r,r)
    ob=op.ob.name
    i=0
    for a in moves:
        for b in moves:
            bpy.ops.object.select_all(action='DESELECT')
            bpy.ops.object.select_name(name=ob)
            i+=1
            x=a*xt
            y=b*yt
            bpy.ops.object.duplicate()
            bpy.ops.transform.translate(value=(x,y,0), constraint_orientation='GLOBAL', release_confirm=True)
            bpy.ops.view3d.snap_cursor_to_selected()
            bpy.ops.transform.rotate(value=(rv*(a+b),),axis=(0.0,0.0,1.0), constraint_orientation='GLOBAL', release_confirm=True)
            bpy.ops.transform.mirror(constraint_axis=(yf and ((a+b)%i)==0,xf and( (a+b)%i)==0,False), constraint_orientation='GLOBAL', proportional='DISABLED', proportional_edit_falloff='SMOOTH', proportional_size=1, release_confirm=True)

@UiUnit('general',OB,FM)
def split_and_smooth(op,c):
        bpy.ops.object.modifier_add(type='EDGE_SPLIT')
        bpy.ops.object.modifier_add(type='SMOOTH')
    
for g in units.keys():
    make_panel(g)

print('ops and units:')
print('+',ops)
print('^',units)

registry=list(ops.values())+panels

def register():list(map(lambda x:bpy.utils.register_class(x),registry))

def unregister():list(map(lambda x:bpy.utils.unregister_class(x),registry))
#OLL KORRECT!
if __name__=='__main__':register()

Advertisement
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.