# ##### BEGIN GPL LICENSE BLOCK ############################################### # # # This program is free software; you can redistribute it and/or # # modify it under the terms of the GNU General Public License # # as published by the Free Software Foundation; either version 2 # # of the License, or (at your option) any later version. # # # # This program is distributed in the hope that it will be useful, # # but WITHOUT ANY WARRANTY; without even the implied warranty of # # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # # GNU General Public License for more details. # # # # You should have received a copy of the GNU General Public License # # along with this program; if not, write to the Free Software Foundation, # # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # # # # ##### END GPL LICENSE BLOCK ################################################# ############################################################################################################################################################################### # # This B version of the retopology tool needs Iceking's Addon, Bsurfaces, Looptools and Auto mirror and surface Constraint tools to work # - Iceking's Addon > http://www.blenderartists.org/forum/showthread.php?343641-Iceking-s-Tools # - Auto Mirror By Lapineige > http://le-terrier-de-lapineige.over-blog.com/2014/07/automirror-mon-add-on-pour-symetriser-vos-objets-rapidement.html # - Bsurface 1.5 > http://www.blenderartists.org/forum/showthread.php?225190-Bsurfaces-v1-5&highlight=bsurface # - Surface Constraint tools > http://www.blenderartists.org/forum/showthread.php?350794-Addon-Surface-Constraint-Tools # ############################################################################################################################################################################### bl_info = { "name": "Retopology Tools", "author": "Cédric Lepiller", "Gert De Roost for the Laprelax code" "version": (0, 1, 5), "blender": (2, 7, 2), "location": "View 3D > Toolbar > Tools tab > Retopology (panel)", "description": "Tools for fast retopology", "category": "3D View"} import bpy, os from bpy.types import Menu, Header import bmesh from mathutils import * import math from bpy.props import IntProperty, FloatProperty, BoolProperty ############### Prefs ######################## #Class Prefs class WazouRetopoTools(bpy.types.AddonPreferences): """Creates the tools in a Panel, in the scene context of the properties editor""" bl_idname = __name__ bpy.types.Scene.Enable_Tab_01 = bpy.props.BoolProperty(default=False) bpy.types.Scene.Enable_Tab_02 = bpy.props.BoolProperty(default=False) def draw(self, context): layout = self.layout layout.prop(context.scene, "Enable_Tab_01", text="Info", icon="QUESTION") if context.scene.Enable_Tab_01: row = layout.row() layout.label(text="This Addon Need to activate 'Loop Tools' and 'Bsurfaces' in the Addon Tab to work properly.") layout.label(text="You need to install Iceking's Tool, Surface Constraint tools, Retopo MT And Auto Mirror") layout.operator("wm.url_open", text="IceKing's tools").url = "http://www.blenderartists.org/forum/showthread.php?343641-Iceking-s-Tools" layout.operator("wm.url_open", text="Auto Mirror").url = "http://le-terrier-de-lapineige.over-blog.com/2014/07/automirror-mon-add-on-pour-symetriser-vos-objets-rapidement.html" layout.operator("wm.url_open", text="Surface Constraint tools").url = "http://www.blenderartists.org/forum/showthread.php?350794-Addon-Surface-Constraint-Tools" layout.operator("wm.url_open", text="Retopo MT").url = "http://www.blenderartists.org/forum/showthread.php?355154-Addon-Retopo-MT" layout.prop(context.scene, "Enable_Tab_02", text="URL's", icon="URL") if context.scene.Enable_Tab_02: row = layout.row() row.operator("wm.url_open", text="Pitiwazou.com").url = "http://www.pitiwazou.com/" row.operator("wm.url_open", text="Wazou's Ghitub").url = "https://github.com/pitiwazou/Scripts-Blender" row.operator("wm.url_open", text="BlenderLounge Forum ").url = "http://blenderlounge.fr/forum/" ############### Operators ######################## #Setup Retopo Mesh class SetupRetopoMesh(bpy.types.Operator): bl_idname = "setup.retopomesh" bl_label = "Setup Retopo Mesh" bl_options = {'REGISTER', 'UNDO'} def execute(self, context): bpy.ops.setup.retopo() bpy.context.object.show_x_ray = True bpy.context.space_data.show_occlude_wire = True return {'FINISHED'} #Double Threshold 0.001 class DoubleThreshold0001(bpy.types.Operator): bl_idname = "double.threshold0001" bl_label = "Double Threshold 0001" bl_options = {'REGISTER', 'UNDO'} @classmethod def poll(cls, context): return context.active_object is not None def execute(self, context): bpy.context.scene.tool_settings.double_threshold = 0.001 return {'FINISHED'} #Double Threshold 0.1 class DoubleThreshold01(bpy.types.Operator): bl_idname = "double.threshold01" bl_label = "Double Threshold 01" bl_options = {'REGISTER', 'UNDO'} @classmethod def poll(cls, context): return context.active_object is not None def execute(self, context): bpy.context.scene.tool_settings.double_threshold = 0.1 return {'FINISHED'} #LapRelax class LapRelax(bpy.types.Operator): bl_idname = "mesh.laprelax" bl_label = "LapRelax" bl_description = "Smoothing mesh keeping volume" bl_options = {'REGISTER', 'UNDO'} Repeat = bpy.props.IntProperty( name = "Repeat", description = "Repeat how many times", default = 1, min = 1, max = 100) @classmethod def poll(cls, context): obj = context.active_object return (obj and obj.type == 'MESH' and context.mode == 'EDIT_MESH') def invoke(self, context, event): # smooth #Repeat times for i in range(self.Repeat): self.do_laprelax() return {'FINISHED'} def do_laprelax(self): context = bpy.context region = context.region area = context.area selobj = bpy.context.active_object mesh = selobj.data bm = bmesh.from_edit_mesh(mesh) bmprev = bm.copy() for v in bmprev.verts: if v.select: tot = Vector((0, 0, 0)) cnt = 0 for e in v.link_edges: for f in e.link_faces: if not(f.select): cnt = 1 if len(e.link_faces) == 1: cnt = 1 break if cnt: # dont affect border edges: they cause shrinkage continue # find Laplacian mean for e in v.link_edges: tot += e.other_vert(v).co tot /= len(v.link_edges) # cancel movement in direction of vertex normal delta = (tot - v.co) if delta.length != 0: ang = delta.angle(v.normal) deltanor = math.cos(ang) * delta.length nor = v.normal nor.length = abs(deltanor) bm.verts[v.index].co = tot + nor mesh.update() bm.free() bmprev.free() bpy.ops.object.editmode_toggle() bpy.ops.object.editmode_toggle() #Align to X class AlignToX(bpy.types.Operator): bl_idname = "object.align2x" bl_label = "Align To X" bl_options = {'REGISTER', 'UNDO'} def execute(self, context): bpy.ops.object.mode_set(mode = 'OBJECT') bpy.ops.object.transform_apply(location=True, rotation=True, scale=True) for vert in bpy.context.object.data.vertices: if vert.select: vert.co[0] = 0 bpy.ops.object.editmode_toggle() return {'FINISHED'} #Wire on selected objects class WireSelectedAll(bpy.types.Operator): """Wire on selected Object, Wire All if no objects selected""" bl_idname = "wire.selectedall" bl_label = "Wire Selected All" bl_options = {'REGISTER', 'UNDO'} @classmethod def poll(cls, context): return context.active_object is not None def execute(self, context): for obj in bpy.data.objects: if bpy.context.selected_objects: if obj.select: if obj.show_wire: obj.show_all_edges = False obj.show_wire = False else: obj.show_all_edges = True obj.show_wire = True elif not bpy.context.selected_objects: if obj.show_wire: obj.show_all_edges = False obj.show_wire = False else: obj.show_all_edges = True obj.show_wire = True return {'FINISHED'} #Shading Smooth class ShadingSmooth(bpy.types.Operator): bl_idname = "shading.smooth" bl_label = "Shading Smooth" bl_options = {'REGISTER', 'UNDO'} def execute(self, context): if bpy.context.object.mode == "OBJECT": bpy.ops.object.shade_smooth() elif bpy.context.object.mode == "EDIT": bpy.ops.object.mode_set(mode = 'OBJECT') bpy.ops.object.shade_smooth() bpy.ops.object.mode_set(mode = 'EDIT') return {'FINISHED'} #Shading Flat class ShadingFlat(bpy.types.Operator): bl_idname = "shading.flat" bl_label = "Shading Flat" bl_options = {'REGISTER', 'UNDO'} def execute(self, context): if bpy.context.object.mode == "OBJECT": bpy.ops.object.shade_flat() elif bpy.context.object.mode == "EDIT": bpy.ops.object.mode_set(mode = 'OBJECT') bpy.ops.object.shade_flat() bpy.ops.object.mode_set(mode = 'EDIT') return {'FINISHED'} #Create Hole class CreateHole(bpy.types.Operator): """This Operator create a hole on a selection""" bl_idname = "object.createhole" bl_label = "Create Hole" bl_options = {'REGISTER', 'UNDO'} @classmethod def poll(cls, context): return context.active_object is not None def execute(self, context): bpy.ops.mesh.extrude_region_move() bpy.ops.transform.resize(value=(0.6, 0.6, 0.6)) bpy.ops.mesh.looptools_circle() bpy.ops.mesh.extrude_region_move() bpy.ops.transform.resize(value=(0.8, 0.8, 0.8)) bpy.ops.mesh.delete(type='FACE') return {'FINISHED'} #Delete modifiers class DeleteModifiers(bpy.types.Operator): bl_idname = "delete.modifiers" bl_label = "Delete modifiers" bl_options = {'REGISTER', 'UNDO'} def execute(self, context): selection = bpy.context.selected_objects if not(selection): for obj in bpy.data.objects: for mod in obj.modifiers: bpy.context.scene.objects.active = obj bpy.ops.object.modifier_remove(modifier = mod.name) else: for obj in selection: for mod in obj.modifiers: bpy.context.scene.objects.active = obj bpy.ops.object.modifier_remove(modifier = mod.name) return {'FINISHED'} #Add Mirror Object class AddMirrorObject(bpy.types.Operator): bl_idname = "add.mirrorobject" bl_label = "Add Mirror Object" bl_options = {'REGISTER', 'UNDO'} def execute(self, context): if bpy.context.object.mode == "OBJECT": bpy.ops.object.modifier_add(type='MIRROR') bpy.context.object.modifiers["Mirror"].use_clip = True bpy.context.object.modifiers["Mirror"].show_on_cage = True elif bpy.context.object.mode == "EDIT": bpy.ops.object.modifier_add(type='MIRROR') bpy.context.object.modifiers["Mirror"].use_clip = True bpy.context.object.modifiers["Mirror"].show_on_cage = True bpy.context.object.modifiers["Mirror"].show_in_editmode = True return {'FINISHED'} #Apply Mirror class ApplyMirror(bpy.types.Operator): bl_idname = "apply.mirror" bl_label = "Apply Mirror" bl_options = {'REGISTER', 'UNDO'} def execute(self, context): if bpy.context.object.mode == "OBJECT": bpy.ops.object.modifier_apply(apply_as='DATA', modifier="Mirror") elif bpy.context.object.mode == "EDIT": bpy.ops.object.mode_set(mode = 'OBJECT') bpy.ops.object.modifier_apply(apply_as='DATA', modifier="Mirror") bpy.ops.object.mode_set(mode = 'EDIT') return {'FINISHED'} #Subsurf 2 class SubSurf2(bpy.types.Operator): bl_idname = "object.subsurf2" bl_label = "SubSurf 2" bl_options = {'REGISTER', 'UNDO'} def execute(self, context): if bpy.context.object.mode == "OBJECT": bpy.ops.object.subdivision_set(level=2) bpy.context.object.modifiers["Subsurf"].show_only_control_edges = True if bpy.context.object.mode == "EDIT": bpy.ops.object.subdivision_set(level=2) bpy.context.object.modifiers["Subsurf"].show_on_cage = True bpy.context.object.modifiers["Subsurf"].show_only_control_edges = True bpy.ops.object.mode_set(mode = 'EDIT') return {'FINISHED'} #Remove Subsurf class RemoveSubSurf2(bpy.types.Operator): bl_idname = "object.removesubsurf2" bl_label = "Remove SubSurf" bl_options = {'REGISTER', 'UNDO'} def execute(self, context): if bpy.context.object.mode == "OBJECT": bpy.ops.object.modifier_remove(modifier="Subsurf") if bpy.context.object.mode == "EDIT": bpy.ops.object.mode_set(mode = 'OBJECT') bpy.ops.object.modifier_remove(modifier="Subsurf") bpy.ops.object.mode_set(mode = 'EDIT') return {'FINISHED'} #Apply Subsurf class ApplySubSurf(bpy.types.Operator): bl_idname = "object.applysubsurf" bl_label = "Apply subsurf" bl_options = {'REGISTER', 'UNDO'} def execute(self, context): if bpy.context.object.mode == "OBJECT": bpy.ops.object.modifier_apply(apply_as='DATA', modifier="Subsurf") if bpy.context.object.mode == "EDIT": bpy.ops.object.mode_set(mode = 'OBJECT') bpy.ops.object.modifier_apply(apply_as='DATA', modifier="Subsurf") bpy.ops.object.mode_set(mode = 'EDIT') return {'FINISHED'} #Sursurf On/Off class SursurfOnOff(bpy.types.Operator): bl_idname = "object.subsurfonoff" bl_label = "Sursurf On/Off" bl_options = {'REGISTER', 'UNDO'} def execute(self, context): layout = self.layout bpy.context.object.modifiers["Subsurf"].show_viewport = not bpy.context.object.modifiers["Subsurf"].show_viewport return {'FINISHED'} #Sursurf Edit On/Off class SursurfEditOnOff(bpy.types.Operator): bl_idname = "object.subsurfeditonoff" bl_label = "Sursurf Edit On/Off" bl_options = {'REGISTER', 'UNDO'} def execute(self, context): layout = self.layout bpy.context.object.modifiers["Subsurf"].show_in_editmode = not bpy.context.object.modifiers["Subsurf"].show_in_editmode return {'FINISHED'} #Sursurf Cage On/Off class SursurfCageOnOff(bpy.types.Operator): bl_idname = "object.subsurfcageonoff" bl_label = "Sursurf Cage On/Off" bl_options = {'REGISTER', 'UNDO'} def execute(self, context): layout = self.layout bpy.context.object.modifiers["Subsurf"].show_on_cage = not bpy.context.object.modifiers["Subsurf"].show_on_cage return {'FINISHED'} #Sursurf Optimal Display class SursurfOptimalDisplay(bpy.types.Operator): bl_idname = "object.subsurfoptimaldisplay" bl_label = "Sursurf Optimal Display" bl_options = {'REGISTER', 'UNDO'} def execute(self, context): layout = self.layout bpy.context.object.modifiers["Subsurf"].show_only_control_edges = not bpy.context.object.modifiers["Subsurf"].show_only_control_edges return {'FINISHED'} #######Mirror########### #Mirror On/Off class MirrorOnOff(bpy.types.Operator): bl_idname = "object.mirroronoff" bl_label = "Mirror On/Off" bl_options = {'REGISTER', 'UNDO'} def execute(self, context): layout = self.layout bpy.context.object.modifiers["Mirror"].show_viewport = not bpy.context.object.modifiers["Mirror"].show_viewport return {'FINISHED'} #Mirror Edit On/Off class MirrorEditOnOff(bpy.types.Operator): bl_idname = "object.mirroreditonoff" bl_label = "Mirror Edit On/Off" bl_options = {'REGISTER', 'UNDO'} def execute(self, context): layout = self.layout bpy.context.object.modifiers["Mirror"].show_in_editmode = not bpy.context.object.modifiers["Mirror"].show_in_editmode return {'FINISHED'} #Mirror Cage On/Off class MirrorCageOnOff(bpy.types.Operator): bl_idname = "object.mirrorcageonoff" bl_label = "Mirror Cage On/Off" bl_options = {'REGISTER', 'UNDO'} def execute(self, context): layout = self.layout bpy.context.object.modifiers["Mirror"].show_on_cage = not bpy.context.object.modifiers["Mirror"].show_on_cage return {'FINISHED'} #Mirror Clipping class MirrorClipping(bpy.types.Operator): bl_idname = "object.mirrorclipping" bl_label = "Mirror Clipping" bl_options = {'REGISTER', 'UNDO'} def execute(self, context): layout = self.layout bpy.context.object.modifiers["Mirror"].use_clip = not bpy.context.object.modifiers["Mirror"].use_clip return {'FINISHED'} #################### Panel #################### bpy.types.Scene.retopo_Tools = bpy.props.BoolProperty(default=True) bpy.types.Scene.retopo_Modifiers = bpy.props.BoolProperty(default=True) bpy.types.Scene.retopo_Shading = bpy.props.BoolProperty(default=True) bpy.types.Scene.retopo_Normals = bpy.props.BoolProperty(default=True) class RetopologyTools(bpy.types.Panel): bl_label = "Retopology Tools" bl_space_type = 'VIEW_3D' bl_region_type = 'TOOLS' bl_category = "Retopology" def draw(self, context): layout = self.layout if bpy.context.object and bpy.context.object.type == 'MESH': if bpy.context.object.select: #Tools if context.scene.retopo_Tools==False: layout.prop(context.scene, "retopo_Tools", text="Tools", icon='TRIA_DOWN') layout.operator("setup.retopomesh", icon = 'UV_FACESEL') layout.operator("polysculpt.retopo", text = "Sculpt Mesh", icon = 'SCULPTMODE_HLT') if bpy.context.object.mode == "EDIT": row = layout.row(align=True) row.operator("freeze_verts.retopo", text = 'Freeze') row.operator("thaw_freeze_verts.retopo", text = 'Thaw') row.operator("show_freeze_verts.retopo", text = 'Show') layout.operator("shrink.update", text = "Shrinkwrap Update", icon = 'MOD_SHRINKWRAP') layout.separator() layout.operator("gpencil.surfsk_add_surface", text="Add Bsurface", icon = 'MOD_DYNAMICPAINT') layout.operator("mesh.looptools_gstretch", text="GStretch", icon='GREASEPENCIL') layout.operator("mesh.laprelax", icon = 'MOD_LATTICE') layout.menu("VIEW3D_MT_edit_mesh_looptools") layout.operator("object.createhole", icon='CLIPUV_DEHLT', text="Create Hole") layout.operator("object.align2x", icon='MOD_WIREFRAME') else: layout.separator() box = layout.box() row = box.row() row.prop(context.space_data, "show_occlude_wire") row.prop(context.object, "show_x_ray", text="X-Ray") row = box.row() row.prop(context.space_data, "show_backface_culling", text="BF Culling") row.prop(context.object.data, "show_double_sided") row = box.row() row.prop(context.tool_settings, "use_mesh_automerge", text = "Auto Merge") row.prop(context.space_data, "use_occlude_geometry", text = "Occlude Geo") row = layout.row() box.label("Double Threshold:") row = box.split(percentage=0.5) tool_settings = context.tool_settings row.prop(tool_settings, "double_threshold", text="") row.operator("double.threshold01", text= "0.1") row.operator("double.threshold0001", text= "0.001") col = layout.column(align=True) else: layout.prop(context.scene, "retopo_Tools", text="Tools", icon='TRIA_RIGHT') #Shading if context.scene.retopo_Shading==False: layout.prop(context.scene, "retopo_Shading", text="Shading", icon='TRIA_DOWN') box = layout.box() row = box.row() row.operator("shading.smooth", text="Smooth") row.operator("shading.flat", text="Flat") row.operator("wire.selectedall", text="Wire", icon='WIRE') if bpy.context.object.mode == "EDIT": row = layout.row() row.operator("mesh.flip_normals", icon = 'FILE_REFRESH') row.operator("mesh.normals_make_consistent", icon = 'MATCUBE') row = layout.row() row.operator("wm.context_toggle", text="Show Norms", icon='FACESEL').data_path = "object.data.show_normal_face" row.operator("mesh.remove_doubles",icon='X') else: layout.separator() #Matcaps view = context.space_data col = layout.column() if view.viewport_shade == 'SOLID': col.prop(context.space_data, "use_matcap") if view.use_matcap: col.template_icon_view(context.space_data, "matcap_icon") else: layout.prop(context.scene, "retopo_Shading", text="Shading", icon='TRIA_RIGHT') #Modifiers if context.scene.retopo_Modifiers==False: layout.prop(context.scene, "retopo_Modifiers", text="Modifiers", icon='TRIA_DOWN') #Mirror box = layout.box() row = box.row() is_mirror = False for mode in bpy.context.object.modifiers : if mode.type == 'MIRROR' : is_mirror = True if is_mirror == True : row.operator("object.modifier_remove", text="Del Mirror", icon='X').modifier="Mirror" else: row.operator("add.mirrorobject", icon = 'MOD_MIRROR', text="Add Mirror") row.operator("object.automirror", icon = 'MOD_MIRROR') row = box.row() row.operator("apply.mirror", text="Apply Mirror", icon='FILE_TICK') #On/Off, Edit, Cage row = box.row() for mode in bpy.context.object.modifiers : if mode.type == 'MIRROR' : is_mirror = True if is_mirror == True : #View On/Off if bpy.context.object.modifiers["Mirror"].show_viewport == (True) : row.operator("object.mirroronoff", text="View",icon='RESTRICT_VIEW_OFF') else: row.operator("object.mirroronoff", text="View",icon='VISIBLE_IPO_OFF') #Edit On/Off if bpy.context.object.modifiers["Mirror"].show_in_editmode == (True) : row.operator("object.mirroreditonoff", text="Edit",icon='EDITMODE_HLT') else: row.operator("object.mirroreditonoff", text="Edit",icon='SNAP_VERTEX') #Cage On/Off if bpy.context.object.modifiers["Mirror"].show_on_cage == (True) : row.operator("object.mirrorcageonoff", text="Cage",icon='OUTLINER_OB_MESH') else: row.operator("object.mirrorcageonoff", text="Cage",icon='OUTLINER_DATA_MESH') #Clipping if bpy.context.object.modifiers["Mirror"].use_clip == (True) : row.operator("object.mirrorclipping", text="Clip",icon='UV_EDGESEL') else: row.operator("object.mirrorclipping", text="Clip",icon='SNAP_EDGE') #Subsurf box = layout.box() row = box.row() is_subsurf = False for mode in bpy.context.object.modifiers : if mode.type == 'SUBSURF' : is_subsurf = True if is_subsurf == True : row.operator("object.removesubsurf2", text="Del Subsurf", icon='X') else : row.operator("object.subsurf2", text="Add Subsurf", icon='MOD_SUBSURF') row.operator("object.applysubsurf", text="Apply Subsurf", icon='FILE_TICK') layout.operator("delete.modifiers", text="Delete Modifiers", icon='X') #On/Off, Edit, Cage row = box.row() for mode in bpy.context.object.modifiers : if mode.type == 'SUBSURF' : is_subsurf = True if is_subsurf == True : #View On/Off if bpy.context.object.modifiers["Subsurf"].show_viewport == (True) : row.operator("object.subsurfonoff", text="View",icon='RESTRICT_VIEW_OFF') else: row.operator("object.subsurfonoff", text="View",icon='VISIBLE_IPO_OFF') #Edit On/Off if bpy.context.object.modifiers["Subsurf"].show_in_editmode == (True) : row.operator("object.subsurfeditonoff", text="Edit",icon='EDITMODE_HLT') else: row.operator("object.subsurfeditonoff", text="Edit",icon='SNAP_VERTEX') #Cage On/Off if bpy.context.object.modifiers["Subsurf"].show_on_cage == (True) : row.operator("object.subsurfcageonoff", text="Cage",icon='OUTLINER_OB_MESH') else: row.operator("object.subsurfcageonoff", text="Cage",icon='OUTLINER_DATA_MESH') #Optimal display if bpy.context.object.modifiers["Subsurf"].show_only_control_edges == (True) : row.operator("object.subsurfoptimaldisplay", text="OD",icon='SOLID') else: row.operator("object.subsurfoptimaldisplay", text="OD",icon='WIRE') else: layout.prop(context.scene, "retopo_Modifiers", text="Modifiers", icon='TRIA_RIGHT') else: layout.label(icon="ERROR", text="No Reference Selected") else: layout.label(icon="ERROR", text="No Reference Selected") ###################### # Pie Menus # ###################### #################### Operators #################### #Space class RetopoSpace(bpy.types.Operator): bl_idname = "retopo.space" bl_label = "Retopo Space" def execute(self, context): bpy.ops.mesh.looptools_space(influence=100, input='selected', interpolation='cubic', lock_x=False, lock_y=False, lock_z=False) return {'FINISHED'} #SCT_Select_Only class SCTSelectOnly(bpy.types.Operator): bl_idname = "object.sctselectonly" bl_label = "Select Only" bl_options = {'REGISTER', 'UNDO'} def execute(self, context): addon = bpy.context.user_preferences.addons["surface-constraint-tools-master"] props = addon.preferences.smooth_vertices props.only_selected_are_affected = not props.only_selected_are_affected return {'FINISHED'} #SCT_Lock_Boundary class SCTLockBoundary(bpy.types.Operator): bl_idname = "object.sctlockboundary" bl_label = "Lock Boundary Smooth" bl_options = {'REGISTER', 'UNDO'} def execute(self, context): addon = bpy.context.user_preferences.addons["surface-constraint-tools-master"] props = addon.preferences.smooth_vertices props.boundary_is_locked = not props.boundary_is_locked return {'FINISHED'} #SCT_Isolate_Selection class SCTIsolateSelection(bpy.types.Operator): bl_idname = "object.sctisolateselection" bl_label = "SCT_Isolate_Selection" bl_options = {'REGISTER', 'UNDO'} def execute(self, context): addon = bpy.context.user_preferences.addons["surface-constraint-tools-master"] props = addon.preferences.mesh_brush props.selection_is_isolated = not props.selection_is_isolated return {'FINISHED'} #SCT_Lock_Boundary_Brush class SCTLockBoundaryBrush(bpy.types.Operator): bl_idname = "object.sctlockboundarybrush" bl_label = "Lock Boundary Brush" bl_options = {'REGISTER', 'UNDO'} def execute(self, context): addon = bpy.context.user_preferences.addons["surface-constraint-tools-master"] props = addon.preferences.mesh_brush props.boundary_is_locked = not props.boundary_is_locked return {'FINISHED'} #SCT_Select_Only_Shrinkwrap class SCTSelectOnlyShrinkwrap(bpy.types.Operator): bl_idname = "object.sctselectonlyshrinkwrap" bl_label = "Select Only Shrinkwrap" bl_options = {'REGISTER', 'UNDO'} def execute(self, context): addon = bpy.context.user_preferences.addons["surface-constraint-tools-master"] props = addon.preferences.shrinkwrap props.only_selected_are_affected = not props.only_selected_are_affected return {'FINISHED'} #################### Pie Menus #################### #Pie Retopo - Shift + RMB class PieRetopo(Menu): bl_idname = "pie.retopo" bl_label = "Pie Retopo" def draw(self, context): layout = self.layout pie = layout.menu_pie() #4 - LEFT pie.operator("mesh.sct_mesh_brush", text="Mesh Brush", icon='BRUSH_DATA') #6 - RIGHT pie.operator("align.2x0", icon='MOD_WIREFRAME') #2 - BOTTOM pie.operator("mesh.sct_smooth_vertices", icon = 'MOD_LATTICE') #8 - TOP pie.operator("gpencil.surfsk_add_surface", text="Add Bsurface", icon = 'MOD_DYNAMICPAINT') #7 - TOP - LEFT box = pie.split().column() row = box.split(align=True) row.operator("setup.retopomesh", icon = 'UV_FACESEL') row = box.split(align=True) row.operator("freeze_verts.retopo", text = 'Freeze') row.operator("thaw_freeze_verts.retopo", text = 'Thaw') row.operator("show_freeze_verts.retopo", text = 'Show') #9 - TOP - RIGHT pie.operator("mesh.retopomt", icon='VPAINT_HLT') #1 - BOTTOM - LEFT box = pie.split().column() row = box.split(align=True) addon = bpy.context.user_preferences.addons["surface-constraint-tools-master"] props = addon.preferences.mesh_brush #Isolate Selection if props.selection_is_isolated == False: row.operator("object.sctisolateselection",text="Brush IS", icon = 'CHECKBOX_DEHLT') else : row.operator("object.sctisolateselection",text="Brush IS", icon = 'CHECKBOX_HLT') #Lock Boundary if props.boundary_is_locked == False: row.operator("object.sctlockboundarybrush",text="Brush LB", icon = 'CHECKBOX_DEHLT') else : row.operator("object.sctlockboundarybrush",text="Brush LB", icon = 'CHECKBOX_HLT') row = box.row(align=True) addon = bpy.context.user_preferences.addons["surface-constraint-tools-master"] props = addon.preferences.smooth_vertices #Select Only if props.only_selected_are_affected == False: row.operator("object.sctselectonly",text="Smooth SO", icon = 'CHECKBOX_DEHLT') else : row.operator("object.sctselectonly",text="Smooth SO", icon = 'CHECKBOX_HLT') #Lock Boundary if props.boundary_is_locked == False: row.operator("object.sctlockboundary",text="Smooth LB", icon = 'CHECKBOX_DEHLT') else : row.operator("object.sctlockboundary",text="Smooth LB", icon = 'CHECKBOX_HLT') row = box.split(align=True) addon = bpy.context.user_preferences.addons["surface-constraint-tools-master"] props = addon.preferences.shrinkwrap #Only Selected Shrinkwrap if props.only_selected_are_affected == False: row.operator("object.sctselectonlyshrinkwrap",text="Shrinkwrap SO", icon = 'CHECKBOX_DEHLT') else : row.operator("object.sctselectonlyshrinkwrap",text="Shrinkwrap SO", icon = 'CHECKBOX_HLT') #3 - BOTTOM - RIGHT box = pie.split().column() box.operator("shrink.update", text = "Ice Shrink Update", icon = 'MOD_SHRINKWRAP') box.operator("mesh.sct_shrinkwrap", text = "SCT Shrink Update", icon = 'MOD_SHRINKWRAP') box.operator("retopo.space", icon='ALIGN', text="Space") #################### Register/Unregister/Keymap #################### addon_keymaps = [] def register(): bpy.utils.register_module(__name__) # Keympa Config wm = bpy.context.window_manager if wm.keyconfigs.addon: #Retopo km = wm.keyconfigs.addon.keymaps.new(name = '3D View Generic', space_type = 'VIEW_3D') kmi = km.keymap_items.new('wm.call_menu_pie', 'RIGHTMOUSE', 'PRESS', shift=True) kmi.properties.name = "pie.retopo" addon_keymaps.append(km) def unregister(): bpy.utils.unregister_module(__name__) wm = bpy.context.window_manager if wm.keyconfigs.addon: for km in addon_keymaps: for kmi in km.keymap_items: km.keymap_items.remove(kmi) wm.keyconfigs.addon.keymaps.remove(km) # clear the list del addon_keymaps[:] if __name__ == "__main__": register()