diff options
author | meta-androcto <meta.androcto1@gmail.com> | 2017-04-03 13:52:14 +0300 |
---|---|---|
committer | meta-androcto <meta.androcto1@gmail.com> | 2017-04-03 13:52:14 +0300 |
commit | 89f92968a76d4138f4d79e4b6c140a90879bcb93 (patch) | |
tree | 0ff8d6db4dcae62fe9c8884f285c70315e5e2b7d /mesh_extra_tools | |
parent | 16df27d62e6a0aa3d1450bc56f5d90fdd05cf4a4 (diff) |
mesh edit tools, update multi extrude, add vertex align
Diffstat (limited to 'mesh_extra_tools')
-rw-r--r-- | mesh_extra_tools/__init__.py | 28 | ||||
-rw-r--r-- | mesh_extra_tools/mesh_mextrude_plus.py | 57 | ||||
-rw-r--r-- | mesh_extra_tools/vertex_align.py | 334 |
3 files changed, 390 insertions, 29 deletions
diff --git a/mesh_extra_tools/__init__.py b/mesh_extra_tools/__init__.py index 89b9a453..d8e8792a 100644 --- a/mesh_extra_tools/__init__.py +++ b/mesh_extra_tools/__init__.py @@ -64,6 +64,7 @@ if "bpy" in locals(): importlib.reload(mesh_info_select) importlib.reload(mesh_extrude_and_reshape) importlib.reload(mesh_check) + importlib.reload(vertex_align) else: from . import face_inset_fillet @@ -85,6 +86,7 @@ else: from . import mesh_help from . import mesh_extrude_and_reshape from . import mesh_check + from . import vertex_align from .mesh_select_tools import mesh_select_by_direction from .mesh_select_tools import mesh_select_by_edge_length @@ -238,6 +240,30 @@ class EditToolsPanel(Panel): row.operator("mesh.random_vertices", text="Random Vertices") row.operator("mesh.extra_tools_help", icon="LAYER_USED").help_ids = "random_vertices" + cen0 = context.scene.va_custom_props.en0 + layout = self.layout + layout.label(text="Vertex Align:", icon="VERTEXSEL") + layout.prop(context.scene.va_custom_props, 'en0', expand = False) + + if cen0 == 'opt0': + row = layout.split(0.60) + row.label('Store data:') + row.operator('va.op0_id', text = 'Vertex') + row1 = layout.split(0.8, align=True) + row1.operator('va.op2_id', text = 'Align') + row1.operator('va.op7_id', text = '', icon = "LAYER_USED") + elif cen0 == 'opt1': + layout.operator('va.op3_id', text = 'Align') + elif cen0 == 'opt2': + row = layout.split(0.40) + row.label('Store data:') + row.operator('va.op0_id', text = 'Two vertices') + layout.operator('va.op5_id', text = 'Align') + elif cen0 == 'opt3': + row = layout.split(0.60) + row.label('Store data:') + row.operator('va.op1_id', text = 'Face') + layout.operator('va.op6_id', text = 'Align') # Edge options box1 = self.layout.box() @@ -784,6 +810,7 @@ def register(): vfe_specials.register() mesh_extrude_and_reshape.register() mesh_check.register() + vertex_align.register() bpy.utils.register_module(__name__) # Register Scene Properties @@ -808,6 +835,7 @@ def unregister(): vfe_specials.unregister() mesh_extrude_and_reshape.unregister() mesh_check.unregister() + vertex_align.unregister() del bpy.types.Scene.mesh_extra_tools del bpy.types.Object.tkkey diff --git a/mesh_extra_tools/mesh_mextrude_plus.py b/mesh_extra_tools/mesh_mextrude_plus.py index cb7c8b69..0ae161b7 100644 --- a/mesh_extra_tools/mesh_mextrude_plus.py +++ b/mesh_extra_tools/mesh_mextrude_plus.py @@ -19,7 +19,7 @@ # 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 +# normal rotation, probability, scaled offset, object coörds, initial and per step noise bl_info = { @@ -81,29 +81,29 @@ class MExtrude(Operator): off = FloatProperty( name="Offset", - soft_min=0.001, soft_max=2, - min=-2, max=5, + soft_min=0.001, soft_max=10, + min=-100, max=100, default=1.0, description="Translation" ) offx = FloatProperty( name="Loc X", - soft_min=-2.0, soft_max=2.0, - min=-5.0, max=5.0, + soft_min=-10.0, soft_max=10.0, + min=-100.0, max=100.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, + soft_min=-10.0, soft_max=10.0, + min=-100.0, max=100.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, + soft_min=-10.0, soft_max=10.0, + min=-100.0, max=100.0, default=0.0, description="Global translation Z" ) @@ -152,27 +152,27 @@ class MExtrude(Operator): ) sca = FloatProperty( name="Scale", - min=0.1, max=2, - soft_min=0.5, soft_max=1.2, + min=0.01, max=10, + soft_min=0.5, soft_max=1.5, default=1.0, description="Scaling of the selected faces after extrusion" ) var1 = FloatProperty( - name="Offset Var", min=-5, max=5, + name="Offset Var", min=-10, max=10, soft_min=-1, soft_max=1, default=0, description="Offset variation" ) var2 = FloatProperty( name="Rotation Var", - min=-5, max=5, + min=-10, max=10, soft_min=-1, soft_max=1, default=0, description="Rotation variation" ) var3 = FloatProperty( name="Scale Noise", - min=-5, max=5, + min=-10, max=10, soft_min=-1, soft_max=1, default=0, description="Scaling noise" @@ -185,7 +185,7 @@ class MExtrude(Operator): ) num = IntProperty( name="Repeat", - min=1, max=250, + min=1, max=500, soft_max=100, default=5, description="Repetitions" @@ -207,17 +207,16 @@ class MExtrude(Operator): description="Scale * Offset" ) opt3 = BoolProperty( - name="Per step scale noise", + name="Per step rotation noise", default=False, - description="Per step scale noise, Initial scale noise" + description="Per step rotation noise, Initial rotation noise" ) opt4 = BoolProperty( - name="Per step rotation noise", + name="Per step scale noise", default=False, - description="Per step rotation noise, Initial rotation noise" + description="Per step scale noise, Initial scale noise" ) - @classmethod def poll(cls, context): obj = context.object @@ -253,7 +252,7 @@ class MExtrude(Operator): col.prop(self, 'num') col = layout.column(align=True) - col.label(text="Extra settings:") + col.label(text="Options:") col.prop(self, "opt1") col.prop(self, "opt2") col.prop(self, "opt3") @@ -280,12 +279,12 @@ class MExtrude(Operator): 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: + if self.opt3 is False: rot = vrot(self, i) + # initial scale noise + if self.opt4 is False: + s = vsca(self, i) # extrusion loop for r in range(self.num): @@ -303,12 +302,12 @@ class MExtrude(Operator): 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: + if self.opt3 is True: rot = vrot(self, i + r) + # per step scale noise + if self.opt4 is True: + s = vsca(self, i + r) # proportional, scale * offset if self.opt2 is True: diff --git a/mesh_extra_tools/vertex_align.py b/mesh_extra_tools/vertex_align.py new file mode 100644 index 00000000..04401aef --- /dev/null +++ b/mesh_extra_tools/vertex_align.py @@ -0,0 +1,334 @@ +# -*- coding: utf-8 -*- + +# ***** 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 LICENCE BLOCK ***** + +# ------ ------ +bl_info = { + 'name': 'vertex align', + 'author': '', + 'version': (0, 1, 6), + 'blender': (2, 6, 1), + 'location': 'View3D > Tool Shelf', + 'description': '', + 'warning': '', + 'wiki_url': '', + 'tracker_url': '', + 'category': 'Mesh' } + +# ------ ------ +import bpy +from bpy.props import PointerProperty, EnumProperty, FloatProperty, BoolProperty +from mathutils import Vector +from mathutils.geometry import intersect_point_line, intersect_line_plane + +# ------ Edit Mode Toggle------ +def edit_mode_out(): + bpy.ops.object.mode_set(mode = 'OBJECT') + +def edit_mode_in(): + bpy.ops.object.mode_set(mode = 'EDIT') + +# ------ ------ +def get_mesh_data_(): + edit_mode_out() + ob_act = bpy.context.active_object + me = ob_act.data + edit_mode_in() + return me + +def list_clear_(l): + l[:] = [] + return l + +# -- -- Prpoerty Group-- -- +class va_p_group0(bpy.types.PropertyGroup): + + en0 = EnumProperty( items =( ('opt0', 'Original vertex', ''), + ('opt1', 'Custom coordinates', '')), + ## REMOVED BROKEN ('opt2', 'Line', ''), ('opt3', 'Plane', '')), + name = 'Align to', + default = 'opt0' ) + + en1 = EnumProperty( items =( ('en1_opt0', 'x', ''), + ('en1_opt1', 'y', ''), + ('en1_opt2', 'z', '')), + name = 'Axis', + default = 'en1_opt0' ) + +# ------ ------ +class va_buf(): + list_v = [] + list_f = [] + list_0 = [] + +# ------ operator 0 ------ +class va_op0(bpy.types.Operator): + bl_idname = 'va.op0_id' + bl_label = '' + bl_description = "Store single vert as align point" + + def execute(self, context): + me = get_mesh_data_() + list_clear_(va_buf.list_v) + for v in me.vertices: + if v.select: + va_buf.list_v.append(v.index) + bpy.ops.mesh.select_all(action = 'DESELECT') + return {'FINISHED'} + +# ------ operator 1 ------ +class va_op1(bpy.types.Operator): + bl_idname = 'va.op1_id' + bl_label = '' + bl_description = "test2" + + def execute(self, context): + me = get_mesh_data_() + list_clear_(va_buf.list_f) + for f in me.faces: + if f.select: + va_buf.list_f.append(f.index) + bpy.ops.mesh.select_all(action = 'DESELECT') + return {'FINISHED'} + +# ------ operator 2 ------ align to original +class va_op2(bpy.types.Operator): + bl_idname = 'va.op2_id' + bl_label = 'Align to original' + bl_options = {'REGISTER', 'UNDO'} + bl_description = "Align selection to stored single vert" + + + def draw(self, context): + layout = self.layout + layout.label('Axis:') + layout.prop(context.scene.va_custom_props, 'en1', expand = True) + + def execute(self, context): + + edit_mode_out() + ob_act = context.active_object + me = ob_act.data + cen1 = context.scene.va_custom_props.en1 + list_0 = [v.index for v in me.vertices if v.select] + + if len(va_buf.list_v) == 0: + self.report({'INFO'}, 'Original vertex not stored in memory') + edit_mode_in() + return {'CANCELLED'} + elif len(va_buf.list_v) != 0: + if len(list_0) == 0: + self.report({'INFO'}, 'No vertices selected') + edit_mode_in() + return {'CANCELLED'} + elif len(list_0) != 0: + vo = (me.vertices[va_buf.list_v[0]].co).copy() + if cen1 == 'en1_opt0': + for i in list_0: + v = (me.vertices[i].co).copy() + me.vertices[i].co = Vector(( vo[0], v[1], v[2] )) + elif cen1 == 'en1_opt1': + for i in list_0: + v = (me.vertices[i].co).copy() + me.vertices[i].co = Vector(( v[0], vo[1], v[2] )) + elif cen1 == 'en1_opt2': + for i in list_0: + v = (me.vertices[i].co).copy() + me.vertices[i].co = Vector(( v[0], v[1], vo[2] )) + edit_mode_in() + return {'FINISHED'} + +# ------ operator 3 ------ align to custom coordinates +class va_op3(bpy.types.Operator): + bl_idname = 'va.op3_id' + bl_label = '' + bl_description = "Align to custom coordinates" + + def execute(self, context): + edit_mode_out() + ob_act = context.active_object + me = ob_act.data + list_clear_(va_buf.list_0) + va_buf.list_0 = [v.index for v in me.vertices if v.select][:] + if len(va_buf.list_0) == 0: + self.report({'INFO'}, 'No vertices selected') + edit_mode_in() + return {'CANCELLED'} + elif len(va_buf.list_0) != 0: + bpy.ops.va.op4_id('INVOKE_DEFAULT') + edit_mode_in() + return {'FINISHED'} + +# ------ operator 4 ------ align to custom coordinates +class va_op4(bpy.types.Operator): + bl_idname = 'va.op4_id' + bl_label = 'Align to custom coordinates' + bl_options = {'REGISTER', 'UNDO'} + bl_description = "Align to custom coordinates2" + + x = y = z = FloatProperty( name = '', default = 0.0, min = -100.0, max = 100.0, step = 1, precision = 3 ) + b_x = b_y = b_z = BoolProperty() + + def draw(self, context): + layout = self.layout + row = layout.split(0.25) + row.prop(self, 'b_x', text = 'x') + row.prop(self, 'x') + row = layout.split(0.25) + row.prop(self, 'b_y', text = 'y') + row.prop(self, 'y') + row = layout.split(0.25) + row.prop(self, 'b_z', text = 'z') + row.prop(self, 'z') + + def invoke(self, context, event): + return context.window_manager.invoke_props_dialog(self, width = 200) + + def execute(self, context): + edit_mode_out() + ob_act = context.active_object + me = ob_act.data + + for i in va_buf.list_0: + v = (me.vertices[i].co).copy() + tmp = Vector((v[0], v[1], v[2])) + if self.b_x == True: + tmp[0] = self.x + if self.b_y == True: + tmp[1] = self.y + if self.b_z == True: + tmp[2] = self.z + me.vertices[i].co = tmp + edit_mode_in() + return {'FINISHED'} + +# ------ operator 5 ------ align to line +class va_op5(bpy.types.Operator): + bl_idname = 'va.op5_id' + bl_label = 'Align to line' + bl_options = {'REGISTER', 'UNDO'} + bl_description = "Align to line" + + def execute(self, context): + edit_mode_out() + ob_act = context.active_object + me = ob_act.data + list_0 = [v.index for v in me.vertices if v.select] + + if len(va_buf.list_v) != 2: + self.report({'INFO'}, 'Two guide vertices must be stored in memory.') + edit_mode_in() + return {'CANCELLED'} + elif len(va_buf.list_v) > 1: + if len(list_0) == 0: + self.report({'INFO'}, 'No vertices selected') + edit_mode_in() + return {'CANCELLED'} + elif len(list_0) != 0: + p1 = (me.vertices[va_buf.list_v[0]].co).copy() + p2 = (me.vertices[va_buf.list_v[1]].co).copy() + for i in list_0: + v = (me.vertices[i].co).copy() + me.vertices[i].co = intersect_point_line( v, p1, p2)[0] + edit_mode_in() + return {'FINISHED'} + +# ------ operator 6 ------ align to plane +class va_op6(bpy.types.Operator): + bl_idname = 'va.op6_id' + bl_label = 'Align to plane' + bl_options = {'REGISTER', 'UNDO'} + bl_description = "Align to Plane" + + def execute(self, context): + edit_mode_out() + ob_act = context.active_object + me = ob_act.data + list_0 = [v.index for v in me.vertices if v.select] + + if len(va_buf.list_f) == 0: + self.report({'INFO'}, 'No face stored in memory') + edit_mode_in() + return {'CANCELLED'} + elif len(va_buf.list_f) != 0: + if len(list_0) == 0: + self.report({'INFO'}, 'No vertices selected') + edit_mode_in() + return {'CANCELLED'} + elif len(list_0) != 0: + f = me.faces[va_buf.list_f[0]] + for i in list_0: + v = (me.vertices[i].co).copy() + p = v + ((f.normal).copy() * 0.1) + pp = (me.vertices[f.vertices[0]].co).copy() + pn = (f.normal).copy() + me.vertices[i].co = intersect_line_plane(v, p, pp, pn) + edit_mode_in() + return {'FINISHED'} + +# ------ operator 7 Help------ +class va_op7(bpy.types.Operator): + + bl_idname = 'va.op7_id' + bl_label = '' + bl_description = "Info" + + def draw(self, context): + layout = self.layout + layout.label('Help:') + layout.label('To use select whatever you want vertices to be aligned to ') + layout.label('and click button next to store data label. ') + layout.label('Select vertices that you want to align and click Align button. ') + + def execute(self, context): + return {'FINISHED'} + + def invoke(self, context, event): + return context.window_manager.invoke_popup(self, width = 400) + +# ------ operator 8 ------ +class va_op8(bpy.types.Operator): + bl_idname = 'va.op8_id' + bl_label = '' + bl_description = "Executs" + def execute(self, context): + bpy.ops.va.op7_id('INVOKE_DEFAULT') + return {'FINISHED'} + +# ------ ------ +class_list = [ va_op0, va_op1, va_op2, va_op3, va_op4, va_op5, va_op6, va_op7, va_op8, va_p_group0 ] + +# ------ ------ +def register(): + for c in class_list: + bpy.utils.register_class(c) + + bpy.types.Scene.va_custom_props = PointerProperty(type = va_p_group0) + +# ------ ------ +def unregister(): + for c in class_list: + bpy.utils.unregister_class(c) + + del bpy.context.scene['va_custom_props'] + +# ------ ------ +if __name__ == "__main__": + register() |