diff options
author | Howard Trickey <howard.trickey@gmail.com> | 2011-05-18 18:15:18 +0400 |
---|---|---|
committer | Howard Trickey <howard.trickey@gmail.com> | 2011-05-18 18:15:18 +0400 |
commit | df326083828858b4489fb31c1b8bcbb63fce5a14 (patch) | |
tree | 87021ac68019130a918934a3f854e42f10d2a7bf /mesh_inset/__init__.py | |
parent | ec7aaa4402261950d803cd69e4ecdd33c51cd56a (diff) |
Added percent option; preserve material and smoothing
Diffstat (limited to 'mesh_inset/__init__.py')
-rw-r--r-- | mesh_inset/__init__.py | 292 |
1 files changed, 159 insertions, 133 deletions
diff --git a/mesh_inset/__init__.py b/mesh_inset/__init__.py index 108ff365..0a441d1b 100644 --- a/mesh_inset/__init__.py +++ b/mesh_inset/__init__.py @@ -16,26 +16,30 @@ # # ##### END GPL LICENSE BLOCK ##### +# <pep8 compliant> + bl_info = { - "name": "Inset Polygon", - "author": "Howard Trickey", - "version": (0, 2), - "blender": (2, 5, 7), - "api": 36147, - "location": "View3D > Tools", - "description": "Make an inset polygon inside selection.", - "warning": "", - "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/Scripts/Modeling/Inset-Polygon", - "tracker_url": "http://projects.blender.org/tracker/index.php?func=detail&aid=27290&group_id=153&atid=468", - "category": "Mesh"} + "name": "Inset Polygon", + "author": "Howard Trickey", + "version": (0, 2), + "blender": (2, 5, 7), + "api": 36147, + "location": "View3D > Tools", + "description": "Make an inset polygon inside selection.", + "warning": "", + "wiki_url": \ + "http://wiki.blender.org/index.php/Extensions:2.5/Py/Scripts/Modeling/Inset-Polygon", + "tracker_url": \ + "http://projects.blender.org/tracker/index.php?func=detail&aid=27290&group_id=153&atid=468", + "category": "Mesh"} if "bpy" in locals(): - import imp + import imp else: - from . import geom - from . import model - from . import offset - from . import triquad + from . import geom + from . import model + from . import offset + from . import triquad import math import bpy @@ -44,134 +48,156 @@ from bpy.props import * class Inset(bpy.types.Operator): - bl_idname = "mesh.inset" - bl_label = "Inset" - bl_description = "Make an inset polygon inside selection" - bl_options = {'REGISTER', 'UNDO'} - - inset_amount = FloatProperty(name="Amount", - description="Distance of inset edges from outer ones", - default = 0.05, - min = 0.0, - max = 1000.0, - soft_min = 0.0, - soft_max = 1.0, - unit = 'LENGTH') - inset_height = FloatProperty(name="Height", - description="Distance to raise inset faces", - default = 0.0, - min = -1000.0, - max = 1000.0, - soft_min = -1.0, - soft_max = 1.0, - unit = 'LENGTH') - region = BoolProperty(name="Region", - description="Inset selection as one region?", - default = True) - - @classmethod - def poll(cls, context): - obj = context.active_object - return (obj and obj.type == 'MESH' and context.mode == 'EDIT_MESH') - - def draw(self, context): - layout= self.layout - box = layout.box() - box.label("Inset Options") - box.prop(self, "inset_amount") - box.prop(self, "inset_height") - box.prop(self, "region") - - def invoke(self, context, event): - self.action(context) - return {'FINISHED'} - - def execute(self, context): - self.action(context) - return {'FINISHED'} - - def action(self, context): - save_global_undo = bpy.context.user_preferences.edit.use_global_undo - bpy.context.user_preferences.edit.use_global_undo = False + bl_idname = "mesh.inset" + bl_label = "Inset" + bl_description = "Make an inset polygon inside selection" + bl_options = {'REGISTER', 'UNDO'} + + inset_amount = FloatProperty(name="Amount", + description="Amount to move inset edges", + default=5.0, + min=0.0, + max=1000.0, + soft_min=0.0, + soft_max=100.0, + unit='LENGTH') + inset_height = FloatProperty(name="Height", + description="Amount to raise inset faces", + default=0.0, + min=-10000.0, + max=10000.0, + soft_min=-500.0, + soft_max=500.0, + unit='LENGTH') + region = BoolProperty(name="Region", + description="Inset selection as one region?", + default=True) + scale = EnumProperty(name="Scale", + description="Scale for amount", + items=[ + ('PERCENT', "Percent", + "Percentage of maximum inset amount"), + ('ABSOLUTE', "Absolute", + "Length in blender units") + ], + default='PERCENT') + + @classmethod + def poll(cls, context): + obj = context.active_object + return (obj and obj.type == 'MESH' and context.mode == 'EDIT_MESH') + + def draw(self, context): + layout = self.layout + box = layout.box() + box.label("Inset Options") + box.prop(self, "scale") + box.prop(self, "inset_amount") + box.prop(self, "inset_height") + box.prop(self, "region") + + def invoke(self, context, event): + self.action(context) + return {'FINISHED'} + + def execute(self, context): + self.action(context) + return {'FINISHED'} + + def action(self, context): + save_global_undo = bpy.context.user_preferences.edit.use_global_undo + bpy.context.user_preferences.edit.use_global_undo = False + bpy.ops.object.mode_set(mode='OBJECT') + obj = bpy.context.active_object + mesh = obj.data + do_inset(mesh, self.inset_amount, self.inset_height, self.region, + self.scale == 'PERCENT') + bpy.ops.object.mode_set(mode='EDIT') + bpy.context.user_preferences.edit.use_global_undo = save_global_undo + + +def do_inset(mesh, amount, height, region, as_percent): + if amount <= 0.0: + return + pitch = math.atan(height / amount) + selfaces = [] + selface_indices = [] + for face in mesh.faces: + if face.select and not face.hide: + selfaces.append(face) + selface_indices.append(face.index) + m = geom.Model() + # if add all mesh.vertices, coord indices will line up + # Note: not using Points.AddPoint which does dup elim + # because then would have to map vertices in and out + m.points.pos = [v.co.to_tuple() for v in mesh.vertices] + for f in selfaces: + m.faces.append(list(f.vertices)) + m.face_data.append(f.index) + orig_numv = len(m.points.pos) + orig_numf = len(m.faces) + model.BevelSelectionInModel(m, amount, pitch, True, region, as_percent) + if len(m.faces) == orig_numf: + # something went wrong with Bevel - just treat as no-op + return + # blender_faces: newfaces but all 4-tuples and no 0 + # in 4th position if a 4-sided poly + blender_faces = [] + blender_old_face_index = [] + for i in range(orig_numf, len(m.faces)): + f = m.faces[i] + if len(f) == 3: + blender_faces.append(list(f) + [0]) + blender_old_face_index.append(m.face_data[i]) + elif len(f) == 4: + if f[3] == 0: + blender_faces.append([f[3], f[0], f[1], f[2]]) + else: + blender_faces.append(f) + blender_old_face_index.append(m.face_data[i]) + num_new_vertices = len(m.points.pos) - orig_numv + mesh.vertices.add(num_new_vertices) + for i in range(orig_numv, len(m.points.pos)): + mesh.vertices[i].co = mathutils.Vector(m.points.pos[i]) + start_faces = len(mesh.faces) + mesh.faces.add(len(blender_faces)) + for i, newf in enumerate(blender_faces): + mesh.faces[start_faces + i].vertices_raw = newf + # copy face attributes from old face that it was derived from + bfi = blender_old_face_index[i] + if bfi and 0 <= bfi < start_faces: + bfacenew = mesh.faces[start_faces + i] + bface = mesh.faces[bfi] + bfacenew.material_index = bface.material_index + bfacenew.use_smooth = bface.use_smooth + mesh.update(calc_edges=True) + # remove original faces + bpy.ops.object.mode_set(mode='EDIT') + save_select_mode = bpy.context.tool_settings.mesh_select_mode + bpy.context.tool_settings.mesh_select_mode = [False, False, True] + bpy.ops.mesh.select_all(action='DESELECT') bpy.ops.object.mode_set(mode='OBJECT') - obj = bpy.context.active_object - mesh = obj.data - do_inset(mesh, self.inset_amount, self.inset_height, self.region) + for fi in selface_indices: + mesh.faces[fi].select = True bpy.ops.object.mode_set(mode='EDIT') - bpy.context.user_preferences.edit.use_global_undo = save_global_undo - - -def do_inset(mesh, amount, height, region): - if amount <= 0.0: - return - pitch = math.atan(height / amount) - selfaces = [] - selface_indices = [] - for face in mesh.faces: - if face.select and not face.hide: - selfaces.append(face) - selface_indices.append(face.index) - m = geom.Model() - # if add all mesh.vertices, coord indices will line up - # Note: not using Points.AddPoint which does dup elim - # because then would have to map vertices in and out - m.points.pos = [ v.co.to_tuple() for v in mesh.vertices ] - for f in selfaces: - m.faces.append(list(f.vertices)) - orig_numv = len(m.points.pos) - orig_numf = len(m.faces) - model.BevelSelectionInModel(m, m.faces, amount, pitch, True, region) - if len(m.faces) == orig_numf: - # something went wrong with Bevel - just treat as no-op - return - # blender_faces: newfaces but all 4-tuples and no 0 - # in 4th position if a 4-sided poly - blender_faces = [] - for i in range(orig_numf, len(m.faces)): - f = m.faces[i] - if len(f) == 3: - blender_faces.append(list(f) + [0]) - elif len(f) == 4: - if f[3] == 0: - blender_faces.append([f[3], f[0], f[1], f[2]]) - else: - blender_faces.append(f) - num_new_vertices = len(m.points.pos) - orig_numv - mesh.vertices.add(num_new_vertices) - for i in range(orig_numv, len(m.points.pos)): - mesh.vertices[i].co = mathutils.Vector(m.points.pos[i]) - start_faces = len(mesh.faces) - mesh.faces.add(len(blender_faces)) - for i, newf in enumerate(blender_faces): - mesh.faces[start_faces + i].vertices_raw = newf - mesh.update(calc_edges = True) - # remove original faces - bpy.ops.object.mode_set(mode='EDIT') - save_select_mode = bpy.context.tool_settings.mesh_select_mode - bpy.context.tool_settings.mesh_select_mode = [False, False, True] - bpy.ops.mesh.select_all(action = 'DESELECT') - bpy.ops.object.mode_set(mode = 'OBJECT') - for fi in selface_indices: - mesh.faces[fi].select = True - bpy.ops.object.mode_set(mode = 'EDIT') - bpy.ops.mesh.delete(type = 'FACE') - bpy.context.tool_settings.mesh_select_mode = save_select_mode + bpy.ops.mesh.delete(type='FACE') + bpy.context.tool_settings.mesh_select_mode = save_select_mode def panel_func(self, context): - self.layout.label(text="Inset:") - self.layout.operator("mesh.inset", text="Inset") + self.layout.label(text="Inset:") + self.layout.operator("mesh.inset", text="Inset") def register(): - bpy.utils.register_class(Inset) - bpy.types.VIEW3D_PT_tools_meshedit.append(panel_func) + bpy.utils.register_class(Inset) + bpy.types.VIEW3D_PT_tools_meshedit.append(panel_func) def unregister(): - bpy.utils.unregister_class(Inset) - bpy.types.VIEW3D_PT_tools_meshedit.remove(panel_func) + bpy.utils.unregister_class(Inset) + bpy.types.VIEW3D_PT_tools_meshedit.remove(panel_func) if __name__ == "__main__": - register() + register() |