Update Mesh Edit Tools: T50680

This commit is contained in:
Brendon Murphy 2017-03-30 17:31:07 +11:00
parent f53017167b
commit ba89ec341c
7 changed files with 668 additions and 68 deletions

View File

@ -63,6 +63,7 @@ if "bpy" in locals():
importlib.reload(mesh_selection_topokit)
importlib.reload(mesh_info_select)
importlib.reload(mesh_extrude_and_reshape)
importlib.reload(mesh_check)
else:
from . import face_inset_fillet
@ -83,6 +84,7 @@ else:
from . import vfe_specials
from . import mesh_help
from . import mesh_extrude_and_reshape
from . import mesh_check
from .mesh_select_tools import mesh_select_by_direction
from .mesh_select_tools import mesh_select_by_edge_length
@ -93,7 +95,11 @@ else:
from .mesh_select_tools import mesh_selection_topokit
from .mesh_select_tools import mesh_info_select
from . icons.icons import load_icons
import bpy
import bmesh
from bpy.props import EnumProperty
from bpy.types import (
Menu,
Panel,
@ -316,6 +322,11 @@ class EditToolsPanel(Panel):
row.operator("mesh.extra_tools_help",
icon="LAYER_USED").help_ids = "split_solidify"
row = layout.split(0.8, align=True)
row.operator("mesh.add_faces_to_object", "Shape Extrude")
row.operator("mesh.extra_tools_help",
icon="LAYER_USED").help_ids = "pkhg_faces"
# Utils options
box1 = self.layout.box()
col = box1.column(align=True)
@ -353,11 +364,64 @@ class EditToolsPanel(Panel):
row = layout.row(align=True)
row.operator("mesh.select_vert_edge_face_index",
icon="VERTEXSEL", text="Vert Index").select_type = 'VERT'
row.operator("mesh.select_vert_edge_face_index",
icon="EDGESEL", text="Edge Index").select_type = 'EDGE'
row.operator("mesh.select_vert_edge_face_index",
icon="FACESEL", text="Face Index").select_type = 'FACE'
icon="VERTEXSEL", text="Select By Index").select_type = 'VERT'
layout = self.layout
icons = load_icons()
tris = icons.get("triangles")
ngons = icons.get("ngons")
mesh_check = context.window_manager.mesh_check
layout.prop(mesh_check, "mesh_check_use")
if mesh_check.mesh_check_use:
layout = self.layout
row = layout.row()
row.operator("object.face_type_select", text="Tris", icon_value=tris.icon_id).face_type = 'tris'
row.operator("object.face_type_select", text="Ngons",icon_value=ngons.icon_id).face_type = 'ngons'
row = layout.row()
row.prop(mesh_check, "display_faces", text="Display Faces")
if mesh_check.display_faces:
row = layout.row()
row.prop(mesh_check, "edge_width")
row = layout.row()
row.prop(mesh_check, "custom_tri_color",text="Tris color" )
row = layout.row()
row.prop(mesh_check, "custom_ngons_color")
row = layout.row()
row.prop(mesh_check, "face_opacity")
if bpy.context.object.mode == 'EDIT':
obj = bpy.context.object
me = obj.data
bm = bmesh.from_edit_mesh(me)
info_str = ""
tris = ngons = 0
for f in bm.faces:
v = len(f.verts)
if v == 3:
tris += 1
elif v > 4:
ngons += 1
bmesh.update_edit_mesh(me)
info_str = " Ngons: %i Tris: %i" % (ngons, tris)
split = layout.split(percentage=0.1)
split.separator()
split.label(info_str, icon='MESH_DATA')
if context.mode == 'EDIT_MESH' and not context.space_data.use_occlude_geometry:
split = layout.split(percentage=0.1)
split.separator()
split2 = split.split()
row = split2.row()
row.prop(mesh_check, "finer_lines_behind_use")
# ********** Edit Multiselect **********
@ -719,6 +783,7 @@ def register():
mesh_pen_tool.register()
vfe_specials.register()
mesh_extrude_and_reshape.register()
mesh_check.register()
bpy.utils.register_module(__name__)
# Register Scene Properties
@ -742,6 +807,7 @@ def unregister():
mesh_pen_tool.unregister()
vfe_specials.unregister()
mesh_extrude_and_reshape.unregister()
mesh_check.unregister()
del bpy.types.Scene.mesh_extra_tools
del bpy.types.Object.tkkey

View File

@ -0,0 +1,31 @@
import os
import bpy
import bpy.utils.previews
mesh_check_icon_collections = {}
mesh_check_icons_loaded = False
def load_icons():
global mesh_check_icon_collections
global mesh_check_icons_loaded
if mesh_check_icons_loaded: return mesh_check_icon_collections["main"]
custom_icons = bpy.utils.previews.new()
icons_dir = os.path.join(os.path.dirname(__file__))
custom_icons.load("ngons", os.path.join(icons_dir, "ngon.png"), 'IMAGE')
custom_icons.load("triangles", os.path.join(icons_dir, "triangle.png"), 'IMAGE')
mesh_check_icon_collections["main"] = custom_icons
mesh_check_icons_loaded = True
return mesh_check_icon_collections["main"]
def clear_icons():
global mesh_check_icons_loaded
for icon in mesh_check_icon_collections.values():
bpy.utils.previews.remove(icon)
mesh_check_icon_collections.clear()
mesh_check_icons_loaded = False

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

@ -0,0 +1,448 @@
bl_info = {"name": "Mesh Check BGL edition",
"description": "Display the triangles and ngons of the mesh",
"author": "Pistiwique",
"version": (1, 0, 0),
"blender": (2, 75, 0),
"location": "3D View(s) -> Properties -> Shading",
"category": "3D View"
}
import bpy
from bgl import (
glBegin,
glLineWidth,
glColor3f,
glColor4f,
glVertex3f,
glEnd,
GL_LINES,
glEnable,
glDisable,
GL_DEPTH_TEST,
GL_BLEND,
GL_POLYGON
)
from mathutils.geometry import tessellate_polygon as tessellate
import bmesh
from mathutils import Vector
from bpy.props import EnumProperty, PointerProperty
mesh_check_handle = []
draw_enabled = [False]
edge_width = [1.0]
face_opacity = [0.2]
edges_tri_color = [(1.0, 1.0, 0.0, 1)]
faces_tri_color = [(1.0, 1.0, 0.0, face_opacity[0])]
edges_ngons_color = [(1.0, 0.0, 0.0, 1.0)]
faces_ngons_color = [(1.0, 0.0, 0.0, face_opacity[0])]
bm_old = [None]
finer_lines = [False]
def draw_poly(points):
for i in range(len(points)):
glVertex3f(points[i][0], points[i][1], points[i][2])
def mesh_check_draw_callback():
obj = bpy.context.object
if obj and obj.type == 'MESH':
if draw_enabled[0]:
mesh = obj.data
matrix_world = obj.matrix_world
glLineWidth(edge_width[0])
if bpy.context.mode == 'EDIT_MESH':
use_occlude = True
if bm_old[0] is None or not bm_old[0].is_valid:
bm = bm_old[0] = bmesh.from_edit_mesh(mesh)
else:
bm = bm_old[0]
no_depth = not bpy.context.space_data.use_occlude_geometry
if no_depth:
glDisable(GL_DEPTH_TEST)
use_occlude = False
if finer_lines[0]:
glLineWidth(edge_width[0]/4.0)
use_occlude = True
for face in bm.faces:
if len([verts for verts in face.verts]) == 3:
faces = [matrix_world*vert.co for vert in face.verts]
glColor4f(*faces_tri_color[0])
glEnable(GL_BLEND)
glBegin(GL_POLYGON)
draw_poly(faces)
glEnd()
for edge in face.edges:
if edge.is_valid:
edges = [matrix_world*vert.co for vert in edge.verts]
glColor4f(*edges_tri_color[0])
glBegin(GL_LINES)
draw_poly(edges)
glEnd()
elif len([verts for verts in face.verts]) > 4:
new_faces = []
faces = []
coords = [v.co for v in face.verts]
indices = [v.index for v in face.verts]
for pol in tessellate([coords]):
new_faces.append([indices[i] for i in pol])
for f in new_faces:
faces.append([((matrix_world*bm.verts[i].co)[0]+face.normal.x*0.001,
(matrix_world*bm.verts[i].co)[1]+face.normal.y*0.001,
(matrix_world*bm.verts[i].co)[2]+face.normal.z*0.001)
for i in f])
for f in faces:
glColor4f(*faces_ngons_color[0])
glEnable(GL_BLEND)
glBegin(GL_POLYGON)
draw_poly(f)
glEnd()
for edge in face.edges:
if edge.is_valid:
edges = [matrix_world*vert.co for vert in edge.verts]
glColor4f(*edges_ngons_color[0])
glBegin(GL_LINES)
draw_poly(edges)
glEnd()
glDisable(GL_BLEND)
glColor4f(0.0, 0.0, 0.0, 1.0)
glLineWidth(edge_width[0])
glEnable(GL_DEPTH_TEST)
if use_occlude:
for face in bm.faces:
if len([verts for verts in face.verts]) == 3:
faces = []
for vert in face.verts:
vert_face = matrix_world*vert.co
faces.append((vert_face[0]+face.normal.x*0.001, vert_face[1]+face.normal.y*0.001, vert_face[2]+face.normal.z*0.001))
glColor4f(*faces_tri_color[0])
glEnable(GL_BLEND)
glBegin(GL_POLYGON)
draw_poly(faces)
glEnd()
for edge in face.edges:
if edge.is_valid:
edges = []
for vert in edge.verts:
vert_edge = matrix_world*vert.co
edges.append((vert_edge[0]+face.normal.x*0.001, vert_edge[1]+face.normal.y*0.001, vert_edge[2]+face.normal.z*0.001))
glColor4f(*edges_tri_color[0])
glBegin(GL_LINES)
draw_poly(edges)
glEnd()
elif len([verts for verts in face.verts]) > 4:
new_faces = []
faces = []
coords = [v.co for v in face.verts]
indices = [v.index for v in face.verts]
for pol in tessellate([coords]):
new_faces.append([indices[i] for i in pol])
for f in new_faces:
faces.append([((matrix_world*bm.verts[i].co)[0]+face.normal.x*0.001,
(matrix_world*bm.verts[i].co)[1]+face.normal.y*0.001,
(matrix_world*bm.verts[i].co)[2]+face.normal.z*0.001)
for i in f])
for f in faces:
glColor4f(*faces_ngons_color[0])
glEnable(GL_BLEND)
glBegin(GL_POLYGON)
draw_poly(f)
glEnd()
for edge in face.edges:
if edge.is_valid:
edges = []
for vert in edge.verts:
vert_edge = matrix_world*vert.co
edges.append((vert_edge[0]+face.normal.x*0.001, vert_edge[1]+face.normal.y*0.001, vert_edge[2]+face.normal.z*0.001))
glColor4f(*edges_ngons_color[0])
glBegin(GL_LINES)
draw_poly(edges)
glEnd()
glDisable(GL_BLEND)
glColor4f(0.0, 0.0, 0.0, 1.0)
def updateBGLData(self, context):
if self.mesh_check_use and self.display_faces:
bpy.ops.object.mode_set(mode='EDIT')
draw_enabled[0] = True
edge_width[0] = self.edge_width
finer_lines[0] = self.finer_lines_behind_use
face_opacity[0] = self.face_opacity
edges_tri_color[0] = (self.custom_tri_color[0],
self.custom_tri_color[1],
self.custom_tri_color[2],
1)
faces_tri_color[0] = (self.custom_tri_color[0],
self.custom_tri_color[1],
self.custom_tri_color[2],
self.face_opacity)
edges_ngons_color[0] = (self.custom_ngons_color[0],
self.custom_ngons_color[1],
self.custom_ngons_color[2],
1)
faces_ngons_color[0] = (self.custom_ngons_color[0],
self.custom_ngons_color[1],
self.custom_ngons_color[2],
self.face_opacity)
return
draw_enabled[0] = False
class FaceTypeSelect(bpy.types.Operator):
bl_idname = "object.face_type_select"
bl_label = "Face type select"
bl_options = {'REGISTER', 'UNDO'}
face_type = bpy.props.EnumProperty(
items=(('tris', 'Tris', ""),
('ngons', 'Ngons', "")),
default='ngons'
)
@classmethod
def poll(cls, context):
return context.active_object is not None and context.active_object.type == 'MESH'
def execute(self, context):
bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.mesh.select_all(action='DESELECT')
context.tool_settings.mesh_select_mode=(False, False, True)
if self.face_type == "tris":
bpy.ops.mesh.select_face_by_sides(number=3, type='EQUAL')
else:
bpy.ops.mesh.select_face_by_sides(number=4, type='GREATER')
return {'FINISHED'}
class MeshCheckCollectionGroup(bpy.types.PropertyGroup):
mesh_check_use = bpy.props.BoolProperty(
name="Mesh Check",
description="Display Mesh Check options",
default=False,
update=updateBGLData
)
display_faces = bpy.props.BoolProperty(
name="Display Faces",
description="Use BGL to display ngons en tris of the mesh",
default=False,
update=updateBGLData
)
edge_width = bpy.props.FloatProperty(
name="Width",
description="Edges width in pixels",
min=1.0,
max=10.0,
default=3.0,
subtype='PIXEL',
update=updateBGLData)
finer_lines_behind_use = bpy.props.BoolProperty(
name="Finer Lines behind",
description="Display partially hidden edges finer in non-occlude mode",
default=True,
update=updateBGLData)
custom_tri_color = bpy.props.FloatVectorProperty(
name="Tri Color",
description="Custom color for the triangles",
min=0.0,
max=1.0,
default=(1.0, 1.0, 0.0),
size=3,
subtype='COLOR',
update=updateBGLData)
custom_ngons_color = bpy.props.FloatVectorProperty(
name="Ngons Color",
description="custom color for the ngons",
min=0.0,
max=1.0,
default=(1.0, 0.0, 0.0),
size=3,
subtype='COLOR',
update=updateBGLData)
face_opacity = bpy.props.FloatProperty(
name="Face Opacity",
description="Opacity of the color for the face",
min=0.0,
max=1.0,
default=0.2,
subtype='FACTOR',
update=updateBGLData)
class DATA_OP_facetype_select(bpy.types.Operator):
"""Select all faces of a certain type"""
bl_idname = "data.facetype_select"
bl_label = "Select by face type"
bl_options = {'REGISTER', 'UNDO'}
select_mode = bpy.props.StringProperty()
face_type = EnumProperty(name="Select faces:",
items=(("3", "Triangles", "Faces made up of 3 vertices"),
("5", "Ngons", "Faces made up of 5 and more vertices")),
default="5")
@classmethod
def poll(cls, context):
return context.object is not None and context.object.type == 'MESH'
def execute(self, context):
bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.mesh.select_all(action='DESELECT')
if tuple(bpy.context.tool_settings.mesh_select_mode) == (True, False, False):
self.select_mode = "VERT"
elif tuple(bpy.context.tool_settings.mesh_select_mode) == (False, True, False):
self.select_mode = "EDGE"
elif tuple(bpy.context.tool_settings.mesh_select_mode) == (False, False, True):
self.select_mode = "FACE"
context.tool_settings.mesh_select_mode = (False, False, True)
if self.face_type == "3":
bpy.ops.mesh.select_face_by_sides(number=3, type='EQUAL')
bpy.ops.mesh.select_mode(type=self.select_mode)
else:
bpy.ops.mesh.select_face_by_sides(number=4, type='GREATER')
bpy.ops.mesh.select_mode(type=self.select_mode)
return {'FINISHED'}
def displayMeshCheckPanel(self, context):
layout = self.layout
icons = load_icons()
tris = icons.get("triangles")
ngons = icons.get("ngons")
mesh_check = context.window_manager.mesh_check
layout.prop(mesh_check, "mesh_check_use")
if mesh_check.mesh_check_use:
split = layout.split(percentage=0.1)
split.separator()
split2 = split.split()
row = split2.row(align=True)
row.operator("object.face_type_select", text="Tris", icon_value=tris.icon_id).face_type = 'tris'
row.operator("object.face_type_select", text="Ngons",icon_value=ngons.icon_id).face_type = 'ngons'
split = layout.split(percentage=0.1)
split.separator()
split.prop(mesh_check, "display_faces", text="Display Faces")
if mesh_check.display_faces:
split = layout.split(percentage=0.1)
split.separator()
split2 = split.split()
row = split2.row(align=True)
row.prop(mesh_check, "edge_width")
split = layout.split(percentage=0.1)
split.separator()
split2 = split.split()
row = split2.row()
row.prop(mesh_check, "custom_tri_color",text="Tris color" )
split = layout.split(percentage=0.1)
split.separator()
split2 = split.split()
row = split2.row()
row.prop(mesh_check, "custom_ngons_color")
split = layout.split(percentage=0.1)
split.separator()
split2 = split.split()
row = split2.row()
row.prop(mesh_check, "face_opacity")
if bpy.context.object.mode == 'EDIT':
obj = bpy.context.object
me = obj.data
bm = bmesh.from_edit_mesh(me)
info_str = ""
tris = ngons = 0
for f in bm.faces:
v = len(f.verts)
if v == 3:
tris += 1
elif v > 4:
ngons += 1
bmesh.update_edit_mesh(me)
info_str = " Ngons: %i Tris: %i" % (ngons, tris)
split = layout.split(percentage=0.1)
split.separator()
split.label(info_str, icon='MESH_DATA')
if context.mode == 'EDIT_MESH' and not context.space_data.use_occlude_geometry:
split = layout.split(percentage=0.1)
split.separator()
split2 = split.split()
row = split2.row()
row.prop(mesh_check, "finer_lines_behind_use")
classes = (
FaceTypeSelect,
MeshCheckCollectionGroup,
DATA_OP_facetype_select
)
def register():
for cls in classes:
bpy.utils.register_class(cls)
bpy.types.WindowManager.mesh_check = bpy.props.PointerProperty(
type=MeshCheckCollectionGroup)
if mesh_check_handle:
bpy.types.SpaceView3D.draw_handler_remove(mesh_check_handle[0], 'WINDOW')
mesh_check_handle[:] = [bpy.types.SpaceView3D.draw_handler_add(mesh_check_draw_callback, (), 'WINDOW', 'POST_VIEW')]
def unregister():
del bpy.types.WindowManager.mesh_check
if mesh_check_handle:
bpy.types.SpaceView3D.draw_handler_remove(mesh_check_handle[0], 'WINDOW')
mesh_check_handle[:] = []
for cls in classes:
bpy.utils.unregister_class(cls)
if __name__ == "__main__":
register()

View File

@ -17,12 +17,15 @@
# ##### END GPL LICENSE BLOCK #####
#
# Repeats extrusion + rotation + scale for one or more faces
# Original code by liero
# Update by Jimmy Hazevoet 03/2017 for Blender 2.79
# normal rotation, probability, scaled offset, object origin, initial scale noise
bl_info = {
"name": "MExtrude Plus1",
"author": "liero",
"version": (1, 2, 9),
"author": "liero, Jimmy Hazevoet",
"version": (1, 3, 0),
"blender": (2, 77, 0),
"location": "View3D > Tool Shelf",
"description": "Repeat extrusions from faces to create organic shapes",
@ -36,25 +39,27 @@ import bpy
import bmesh
import random
from bpy.types import Operator
from random import gauss, choice
from random import gauss
from math import radians
from mathutils import Euler
from mathutils import Euler, Vector
from bpy.props import (
FloatProperty,
IntProperty,
BoolProperty,
EnumProperty,
)
# added normal rot
def nrot(self,n):
return Euler((radians(self.nrotx) * n[0], \
radians(self.nroty) * n[1], \
radians(self.nrotz) * n[2]), 'XYZ')
def gloc(self, r):
return Vector((self.offx, self.offy, self.offz))
def vloc(self, r):
random.seed(self.ran + r)
return self.off * (1 + gauss(0, self.var1 / 3))
def nrot(self, n):
return Euler((radians(self.nrotx) * n[0],
radians(self.nroty) * n[1],
radians(self.nrotz) * n[2]), 'XYZ')
def vrot(self, r):
random.seed(self.ran + r)
@ -62,10 +67,9 @@ def vrot(self, r):
radians(self.roty) + gauss(0, self.var2 / 3),
radians(self.rotz) + gauss(0, self.var2 / 3)), 'XYZ')
def vsca(self, r):
random.seed(self.ran + r)
return self.sca * (1 + random.gauss(0, self.var3 / 3))
return self.sca * (1 + gauss(0, self.var3 / 3))
class MExtrude(Operator):
@ -73,15 +77,36 @@ class MExtrude(Operator):
bl_label = "Multi Extrude"
bl_description = ("Extrude selected Faces with Rotation,\n"
"Scaling, Variation, Randomization")
bl_options = {"REGISTER", "UNDO"}
bl_options = {"REGISTER", "UNDO", "PRESET"}
off = FloatProperty(
name="Offset",
soft_min=0.001, soft_max=2,
min=-2, max=5,
default=.5,
default=1.0,
description="Translation"
)
offx = FloatProperty(
name="Loc X",
soft_min=-2.0, soft_max=2.0,
min=-5.0, max=5.0,
default=0.0,
description="Global translation X"
)
offy = FloatProperty(
name="Loc Y",
soft_min=-2.0, soft_max=2.0,
min=-5.0, max=5.0,
default=0.0,
description="Global translation Y"
)
offz = FloatProperty(
name="Loc Z",
soft_min=-2.0, soft_max=2.0,
min=-5.0, max=5.0,
default=0.0,
description="Global translation Z"
)
rotx = FloatProperty(
name="Rot X",
min=-85, max=85,
@ -109,22 +134,21 @@ class MExtrude(Operator):
min=-85, max=85,
soft_min=-30, soft_max=30,
default=0,
description="X Rotation"
description="Normal X Rotation"
)
nroty = FloatProperty(
name="N Rot Y",
min=-85, max=85,
soft_min=-30,
soft_max=30,
soft_min=-30, soft_max=30,
default=0,
description="Y Rotation"
description="Normal Y Rotation"
)
nrotz = FloatProperty(
name="N Rot Z",
min=-85, max=85,
soft_min=-30, soft_max=30,
default=-0,
description="Z Rotation"
description="Normal Z Rotation"
)
sca = FloatProperty(
name="Scale",
@ -161,15 +185,38 @@ class MExtrude(Operator):
)
num = IntProperty(
name="Repeat",
min=1, max=50,
min=1, max=250,
soft_max=100,
default=5,
description="Repetitions")
description="Repetitions"
)
ran = IntProperty(
name="Seed",
min=-9999, max=9999,
default=0,
description="Seed to feed random values")
description="Seed to feed random values"
)
opt1 = BoolProperty(
name="Polygon coördinates",
default=True,
description="Polygon coördinates, Object coördinates"
)
opt2 = BoolProperty(
name="Proportional offset",
default=False,
description="Scale * Offset"
)
opt3 = BoolProperty(
name="Per step scale noise",
default=False,
description="Per step scale noise, Initial scale noise"
)
opt4 = BoolProperty(
name="Per step rotation noise",
default=False,
description="Per step rotation noise, Initial rotation noise"
)
@classmethod
def poll(cls, context):
@ -178,16 +225,21 @@ class MExtrude(Operator):
def draw(self, context):
layout = self.layout
col = layout.column(align=True)
col.label(text="Transformations:")
col.prop(self, "off", slider=True)
col.prop(self, "offx", slider=True)
col.prop(self, "offy", slider=True)
col.prop(self, "offz", slider=True)
col = layout.column(align=True)
col.prop(self, "rotx", slider=True)
col.prop(self, "roty", slider=True)
col.prop(self, "rotz", slider=True)
col.prop(self, 'nrotx', slider=True)
col.prop(self, 'nroty', slider=True)
col.prop(self, 'nrotz', slider=True)
col = layout.column(align=True)
col.prop(self, "sca", slider=True)
col = layout.column(align=True)
@ -200,13 +252,18 @@ class MExtrude(Operator):
col = layout.column(align=False)
col.prop(self, 'num')
col = layout.column(align=True)
col.label(text="Extra settings:")
col.prop(self, "opt1")
col.prop(self, "opt2")
col.prop(self, "opt3")
col.prop(self, "opt4")
def execute(self, context):
obj = bpy.context.object
om = obj.mode
bpy.context.tool_settings.mesh_select_mode = [False, False, True]
origin = Vector([0.0, 0.0, 0.0])
# bmesh operations
bpy.ops.object.mode_set()
@ -218,28 +275,50 @@ class MExtrude(Operator):
# faces loop
for i, of in enumerate(sel):
rot = vrot(self, i)
off = vloc(self, i)
nro = nrot(self, of.normal)
off = vloc(self, i)
loc = gloc(self, i)
of.normal_update()
# extrusion loop
for r in range( self.num ):
# initial scale noise
if self.opt3 is False:
s = vsca(self, i)
# initial rotation noise
if self.opt4 is False:
rot = vrot(self, i)
## random % skip some extrusions
if self.var4 >= int(random.random()*100):
# extrusion loop
for r in range(self.num):
## random probability % for extrusions
if self.var4 > int(random.random()*100):
nf = of.copy()
nf.normal_update()
no = nf.normal.copy()
ce = nf.calc_center_bounds()
s = vsca(self, i + r)
# face/obj coördinates
if self.opt1 is True:
ce = nf.calc_center_bounds()
else:
ce = origin
# per step scale noise
if self.opt3 is True:
s = vsca(self, i + r)
# per step rotation noise
if self.opt4 is True:
rot = vrot(self, i + r)
# proportional, scale * offset
if self.opt2 is True:
off = s * off
for v in nf.verts:
v.co -= ce
v.co.rotate(nro)
v.co.rotate(rot)
v.co += ce + no * off
v.co += ce + loc + no * off
v.co = v.co.lerp(ce, 1 - s)
# extrude code from TrumanBlending
@ -247,9 +326,9 @@ class MExtrude(Operator):
sf = bm.faces.new((a.vert, a.link_loop_next.vert,
b.link_loop_next.vert, b.vert))
sf.normal_update()
bm.faces.remove(of)
of = nf
after.append(of)
for v in bm.verts:
@ -258,7 +337,10 @@ class MExtrude(Operator):
e.select = False
for f in after:
f.select = True
if f not in sel:
f.select = True
else:
f.select = False
bm.to_mesh(obj.data)
obj.data.update()

View File

@ -461,33 +461,6 @@ class MESH_OT_add_faces_to_object(Operator):
return {'FINISHED'}
class VIEW3D_Faces_Panel(Panel):
bl_label = "Face Extrude"
bl_space_type = "VIEW_3D"
bl_region_type = "TOOLS"
bl_category = "Tools"
bl_options = {"DEFAULT_CLOSED"}
@classmethod
def poll(cls, context):
result = False
active_object = context.active_object
if active_object:
mesh_objects_name = [el.name for el in bpy.data.objects if el.type == "MESH"]
if active_object.name in mesh_objects_name:
if active_object.mode == "OBJECT":
result = True
return result
def draw(self, context):
layout = self.layout
row = layout.split(0.8, align=True)
row.operator("mesh.add_faces_to_object", "Selected Faces")
row.operator("mesh.extra_tools_help",
icon="LAYER_USED").help_ids = "pkhg_faces"
def find_one_ring(sel_vertices):
ring0 = sel_vertices.pop(0)
to_delete = []