import bpy import bmesh import operator from mathutils import Vector from collections import defaultdict from math import pi import math from . import utilities_meshtex from . import utilities_ui class op(bpy.types.Operator): bl_idname = "uv.textools_meshtex_pattern" bl_label = "Create Pattern" bl_description = "Create mesh pattern" bl_options = {'REGISTER', 'UNDO'} mode : bpy.props.EnumProperty(items= [('hexagon', 'Hexagons', ''), ('triangle', 'Triangles', ''), ('diamond', 'Diamonds', ''), ('rectangle', 'Rectangles', ''), ('stripe', 'Stripes', ''), ('brick', 'Bricks', '')], name = "Mode", default = 'brick' ) size : bpy.props.IntProperty( name = "Size", description = "Size X and Y of the repetition", default = 4, min = 1, max = 128 ) scale : bpy.props.FloatProperty( name = "Scale", description = "Scale of the mesh pattern", default = 1, min = 0 ) @classmethod def poll(cls, context): if bpy.context.active_object and bpy.context.active_object.mode != 'OBJECT': return False return True def draw(self, context): layout = self.layout layout.prop(self, "mode") layout.prop(self, "size") layout.prop(self, "scale") def execute(self, context): create_pattern(self, self.mode, self.size, self.scale) return {'FINISHED'} def AddArray(name, offset_x, offset_y, count): modifier = bpy.context.object.modifiers.new(name=name, type='ARRAY') # modifier = bpy.context.object.modifiers.new(name="{}_{}".format(name,count), type='ARRAY') modifier.relative_offset_displace[0] = offset_x modifier.relative_offset_displace[1] = offset_y modifier.count = count modifier.show_expanded = False return modifier def create_pattern(self, mode, size, scale): print("Create pattern {}".format(mode)) # bpy.ops.object.mode_set(mode='OBJECT', toggle=False) context_override = None if bpy.context.area.type != 'VIEW_3D': context_override = utilities_ui.GetContextView3D() if not context_override: self.report({'ERROR_INVALID_INPUT'}, "This tool requires an available View3D view.") return print("Mode '{}' size: '{}'".format(mode, size)) if mode == 'hexagon': bpy.ops.mesh.primitive_circle_add(vertices=6, radius=scale, fill_type='NGON') bpy.ops.object.mode_set(mode = 'EDIT') if context_override: bpy.ops.transform.rotate(context_override, value=math.pi*0.5, orient_axis='Z') else: bpy.ops.transform.rotate(value=math.pi*0.5, orient_axis='Z') bpy.ops.object.mode_set(mode = 'OBJECT') AddArray("Array0", 0.75,-0.5,2) AddArray("Array1", 0,-0.66666666666,size) AddArray("Array2", 1 - (0.5/3.5),0,size*0.66) elif mode == 'triangle': bpy.ops.mesh.primitive_circle_add(vertices=3, radius=scale, fill_type='NGON') bpy.ops.object.mode_set(mode = 'EDIT') if context_override: bpy.ops.transform.translate(context_override, value=(0, scale*0.5, 0), constraint_axis=(False, True, False)) else: bpy.ops.transform.translate(value=(0, scale*0.5, 0), constraint_axis=(False, True, False)) bpy.ops.object.mode_set(mode = 'OBJECT') modifier = bpy.context.object.modifiers.new(name="Mirror", type='MIRROR') modifier.use_axis[0] = False modifier.use_axis[1] = True modifier.show_expanded = False AddArray("Array0", 0.5,-0.5,2) AddArray("Array1", 1-1/3.0,0,size) AddArray("Array1", 0,-(1-1/3.0),size*0.66) elif mode == 'rectangle': bpy.ops.mesh.primitive_plane_add(size=scale) AddArray("Array0", 1,0,size) AddArray("Array1", 0,-1,size) elif mode == 'diamond': bpy.ops.mesh.primitive_plane_add(size=scale) bpy.ops.object.mode_set(mode = 'EDIT') if context_override: bpy.ops.transform.rotate(context_override, value=math.pi*0.25, orient_axis='Z') else: bpy.ops.transform.rotate(value=math.pi*0.25, orient_axis='Z') bpy.ops.object.mode_set(mode = 'OBJECT') AddArray("Array0", 0.5,-0.5,2) AddArray("Array1", 1-1/3,0,size) AddArray("Array2", 0,-(1-1/3),size) elif mode == 'brick': bpy.ops.mesh.primitive_plane_add(size=scale) bpy.ops.object.mode_set(mode = 'EDIT') if context_override: bpy.ops.transform.resize(context_override, value=(1, 0.5, 1), constraint_axis=(True, True, False), orient_type='GLOBAL') else: bpy.ops.transform.resize(value=(1, 0.5, 1), constraint_axis=(True, True, False), orient_type='GLOBAL') bpy.ops.object.mode_set(mode = 'OBJECT') AddArray("Array0", 0.5,-1,2) AddArray("Array1", 1-(1/3),0,size) AddArray("Array2", 0,-1,size) elif mode == 'stripe': bpy.ops.mesh.primitive_plane_add(size=1) bpy.ops.object.mode_set(mode = 'EDIT') if context_override: bpy.ops.transform.resize(context_override, value=(0.5, size/2, 1), constraint_axis=(True, True, False), orient_type='GLOBAL') bpy.ops.transform.resize(context_override, value=(scale, scale, 1), constraint_axis=(True, True, False), orient_type='GLOBAL') bpy.ops.transform.translate(context_override, value=(0, (-size/2)*scale, 0), constraint_axis=(False, True, False)) else: bpy.ops.transform.resize(value=(0.5, size/2, 1), constraint_axis=(True, True, False), orient_type='GLOBAL') bpy.ops.transform.resize(value=(scale, scale, 1), constraint_axis=(True, True, False), orient_type='GLOBAL') bpy.ops.transform.translate(value=(0, (-size/2)*scale, 0), constraint_axis=(False, True, False)) bpy.ops.object.mode_set(mode = 'OBJECT') AddArray("Array0", 1,0, size) # if bpy.context.object: # bpy.context.object.name = "pattern_{}".format(mode) # bpy.context.object.show_wire = True bpy.utils.register_class(op)