Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormeta-androcto <meta.androcto1@gmail.com>2017-03-30 09:31:07 +0300
committermeta-androcto <meta.androcto1@gmail.com>2017-03-30 09:31:07 +0300
commitba89ec341ccea23d480d3c23c51ebaaf2bb88ee5 (patch)
treee32332cba3cb599b7c1e19126b9273a5d14964e1 /mesh_extra_tools
parentf53017167bdd9854a65690c23cbc90cf1f9d37ea (diff)
Update Mesh Edit Tools: T50680
Diffstat (limited to 'mesh_extra_tools')
-rw-r--r--mesh_extra_tools/__init__.py76
-rw-r--r--mesh_extra_tools/icons/icons.py31
-rw-r--r--mesh_extra_tools/icons/ngon.pngbin0 -> 6747 bytes
-rw-r--r--mesh_extra_tools/icons/triangle.pngbin0 -> 4153 bytes
-rw-r--r--mesh_extra_tools/mesh_check.py448
-rw-r--r--mesh_extra_tools/mesh_mextrude_plus.py152
-rw-r--r--mesh_extra_tools/pkhg_faces.py27
7 files changed, 667 insertions, 67 deletions
diff --git a/mesh_extra_tools/__init__.py b/mesh_extra_tools/__init__.py
index 90f5c674..89b9a453 100644
--- a/mesh_extra_tools/__init__.py
+++ b/mesh_extra_tools/__init__.py
@@ -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
diff --git a/mesh_extra_tools/icons/icons.py b/mesh_extra_tools/icons/icons.py
new file mode 100644
index 00000000..92b7d0db
--- /dev/null
+++ b/mesh_extra_tools/icons/icons.py
@@ -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
diff --git a/mesh_extra_tools/icons/ngon.png b/mesh_extra_tools/icons/ngon.png
new file mode 100644
index 00000000..b1a79b98
--- /dev/null
+++ b/mesh_extra_tools/icons/ngon.png
Binary files differ
diff --git a/mesh_extra_tools/icons/triangle.png b/mesh_extra_tools/icons/triangle.png
new file mode 100644
index 00000000..05f3a8db
--- /dev/null
+++ b/mesh_extra_tools/icons/triangle.png
Binary files differ
diff --git a/mesh_extra_tools/mesh_check.py b/mesh_extra_tools/mesh_check.py
new file mode 100644
index 00000000..a8f1ab6a
--- /dev/null
+++ b/mesh_extra_tools/mesh_check.py
@@ -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()
diff --git a/mesh_extra_tools/mesh_mextrude_plus.py b/mesh_extra_tools/mesh_mextrude_plus.py
index 786db0f5..cb7c8b69 100644
--- a/mesh_extra_tools/mesh_mextrude_plus.py
+++ b/mesh_extra_tools/mesh_mextrude_plus.py
@@ -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()
+ # initial scale noise
+ if self.opt3 is False:
+ s = vsca(self, i)
+ # initial rotation noise
+ if self.opt4 is False:
+ rot = vrot(self, i)
+
# extrusion loop
- for r in range( self.num ):
+ for r in range(self.num):
- ## random % skip some extrusions
- if self.var4 >= int(random.random()*100):
+ ## 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()
diff --git a/mesh_extra_tools/pkhg_faces.py b/mesh_extra_tools/pkhg_faces.py
index 10b0ca97..36992e65 100644
--- a/mesh_extra_tools/pkhg_faces.py
+++ b/mesh_extra_tools/pkhg_faces.py
@@ -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 = []