Skip to content
Snippets Groups Projects
Commit df326083 authored by Howard Trickey's avatar Howard Trickey
Browse files

Added percent option; preserve material and smoothing

parent ec7aaa44
No related branches found
No related tags found
No related merge requests found
...@@ -16,26 +16,30 @@ ...@@ -16,26 +16,30 @@
# #
# ##### END GPL LICENSE BLOCK ##### # ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
bl_info = { bl_info = {
"name": "Inset Polygon", "name": "Inset Polygon",
"author": "Howard Trickey", "author": "Howard Trickey",
"version": (0, 2), "version": (0, 2),
"blender": (2, 5, 7), "blender": (2, 5, 7),
"api": 36147, "api": 36147,
"location": "View3D > Tools", "location": "View3D > Tools",
"description": "Make an inset polygon inside selection.", "description": "Make an inset polygon inside selection.",
"warning": "", "warning": "",
"wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/Scripts/Modeling/Inset-Polygon", "wiki_url": \
"tracker_url": "http://projects.blender.org/tracker/index.php?func=detail&aid=27290&group_id=153&atid=468", "http://wiki.blender.org/index.php/Extensions:2.5/Py/Scripts/Modeling/Inset-Polygon",
"category": "Mesh"} "tracker_url": \
"http://projects.blender.org/tracker/index.php?func=detail&aid=27290&group_id=153&atid=468",
"category": "Mesh"}
if "bpy" in locals(): if "bpy" in locals():
import imp import imp
else: else:
from . import geom from . import geom
from . import model from . import model
from . import offset from . import offset
from . import triquad from . import triquad
import math import math
import bpy import bpy
...@@ -44,134 +48,156 @@ from bpy.props import * ...@@ -44,134 +48,156 @@ from bpy.props import *
class Inset(bpy.types.Operator): class Inset(bpy.types.Operator):
bl_idname = "mesh.inset" bl_idname = "mesh.inset"
bl_label = "Inset" bl_label = "Inset"
bl_description = "Make an inset polygon inside selection" bl_description = "Make an inset polygon inside selection"
bl_options = {'REGISTER', 'UNDO'} bl_options = {'REGISTER', 'UNDO'}
inset_amount = FloatProperty(name="Amount", inset_amount = FloatProperty(name="Amount",
description="Distance of inset edges from outer ones", description="Amount to move inset edges",
default = 0.05, default=5.0,
min = 0.0, min=0.0,
max = 1000.0, max=1000.0,
soft_min = 0.0, soft_min=0.0,
soft_max = 1.0, soft_max=100.0,
unit = 'LENGTH') unit='LENGTH')
inset_height = FloatProperty(name="Height", inset_height = FloatProperty(name="Height",
description="Distance to raise inset faces", description="Amount to raise inset faces",
default = 0.0, default=0.0,
min = -1000.0, min=-10000.0,
max = 1000.0, max=10000.0,
soft_min = -1.0, soft_min=-500.0,
soft_max = 1.0, soft_max=500.0,
unit = 'LENGTH') unit='LENGTH')
region = BoolProperty(name="Region", region = BoolProperty(name="Region",
description="Inset selection as one region?", description="Inset selection as one region?",
default = True) default=True)
scale = EnumProperty(name="Scale",
@classmethod description="Scale for amount",
def poll(cls, context): items=[
obj = context.active_object ('PERCENT', "Percent",
return (obj and obj.type == 'MESH' and context.mode == 'EDIT_MESH') "Percentage of maximum inset amount"),
('ABSOLUTE', "Absolute",
def draw(self, context): "Length in blender units")
layout= self.layout ],
box = layout.box() default='PERCENT')
box.label("Inset Options")
box.prop(self, "inset_amount") @classmethod
box.prop(self, "inset_height") def poll(cls, context):
box.prop(self, "region") obj = context.active_object
return (obj and obj.type == 'MESH' and context.mode == 'EDIT_MESH')
def invoke(self, context, event):
self.action(context) def draw(self, context):
return {'FINISHED'} layout = self.layout
box = layout.box()
def execute(self, context): box.label("Inset Options")
self.action(context) box.prop(self, "scale")
return {'FINISHED'} box.prop(self, "inset_amount")
box.prop(self, "inset_height")
def action(self, context): box.prop(self, "region")
save_global_undo = bpy.context.user_preferences.edit.use_global_undo
bpy.context.user_preferences.edit.use_global_undo = False 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') bpy.ops.object.mode_set(mode='OBJECT')
obj = bpy.context.active_object for fi in selface_indices:
mesh = obj.data mesh.faces[fi].select = True
do_inset(mesh, self.inset_amount, self.inset_height, self.region)
bpy.ops.object.mode_set(mode='EDIT') bpy.ops.object.mode_set(mode='EDIT')
bpy.context.user_preferences.edit.use_global_undo = save_global_undo bpy.ops.mesh.delete(type='FACE')
bpy.context.tool_settings.mesh_select_mode = save_select_mode
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
def panel_func(self, context): def panel_func(self, context):
self.layout.label(text="Inset:") self.layout.label(text="Inset:")
self.layout.operator("mesh.inset", text="Inset") self.layout.operator("mesh.inset", text="Inset")
def register(): def register():
bpy.utils.register_class(Inset) bpy.utils.register_class(Inset)
bpy.types.VIEW3D_PT_tools_meshedit.append(panel_func) bpy.types.VIEW3D_PT_tools_meshedit.append(panel_func)
def unregister(): def unregister():
bpy.utils.unregister_class(Inset) bpy.utils.unregister_class(Inset)
bpy.types.VIEW3D_PT_tools_meshedit.remove(panel_func) bpy.types.VIEW3D_PT_tools_meshedit.remove(panel_func)
if __name__ == "__main__": if __name__ == "__main__":
register() register()
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment