예제 #1
0
 def create_mesh(self,context,name="Sprite",width=100,height=100,pos=Vector((0,0,0))):
     me = bpy.data.meshes.new(name)
     me.show_double_sided = True
     obj = bpy.data.objects.new(name,me)
     context.scene.objects.link(obj)
     context.scene.objects.active = obj
     obj.select = True
     
     bpy.ops.object.mode_set(mode="EDIT")
     bm = bmesh.from_edit_mesh(me)
     vert1 = bm.verts.new(Vector((0,0,-height))*self.scale)
     vert2 = bm.verts.new(Vector((width,0,-height))*self.scale)
     vert3 = bm.verts.new(Vector((width,0,0))*self.scale)
     vert4 = bm.verts.new(Vector((0,0,0))*self.scale)
     
     bm.faces.new([vert1,vert2,vert3,vert4])
     
     bmesh.update_edit_mesh(me)
     bpy.ops.object.mode_set(mode="OBJECT")
     obj.data.uv_textures.new("UVMap")
     set_uv_default_coords(context,obj)
     
     obj.location = Vector((pos[0],pos[1],-pos[2]))*self.scale + Vector((self.offset[0],self.offset[1],self.offset[2]))*self.scale
     obj["coa_sprite"] = True
     if self.parent != "None":
         obj.parent = bpy.data.objects[self.parent]
     return obj
예제 #2
0
    def execute(self, context):
        obj = context.active_object
        bm = bmesh.from_edit_mesh(obj.data)
        if common.check_version(2, 73, 0) >= 0:
            bm.faces.ensure_lookup_table()
        uv_layer = bm.loops.layers.uv.verify()

        if context.tool_settings.use_uv_select_sync:
            sel_faces = [f for f in bm.faces]
        else:
            sel_faces = [f for f in bm.faces if f.select]

        overlapped_info = common.get_overlapped_uv_info(bm, sel_faces,
                                                        uv_layer, 'FACE')

        for info in overlapped_info:
            if context.tool_settings.use_uv_select_sync:
                info["subject_face"].select = True
            else:
                for l in info["subject_face"].loops:
                    l[uv_layer].select = True

        bmesh.update_edit_mesh(obj.data)

        return {'FINISHED'}
def create_streets(offset_val):
    #grab selection, etc.
    mode("EDIT")
    mode("FACE")
    obj = bpy.context.edit_object
    me = obj.data
    bm = bmesh.from_edit_mesh(me)
    for i in bm.faces:
        i.select = True
    #bevel out streets
    bpy.ops.mesh.bevel(
        offset_type = "WIDTH",
        offset = offset_val,
        clamp_overlap = True
    )
    for i in bm.faces:
        if i.select:
            i.material_index = 1
            bpy.ops.object.material_slot_assign
        else:
            i.material_index = 0
            bpy.ops.object.material_slot_assign
    bpy.ops.object.material_slot_assign
    mode("EDIT")
    bmesh.update_edit_mesh(me)
예제 #4
0
 def modal(self, context, event):
     if self.confirm:
         sface = self.bm.faces.active
         if not sface:
             for face in self.bm.faces:
                 if face.select == True:
                     sface = face
                     break
             else:
                 return {'FINISHED'}
         edges = set()
         for v in sface.verts:
             for ed in v.link_edges:
                 edges.add(ed)
         edges = list(edges)
         bm_edges = self.bm.edges
         #bm_edges.difference_update(set_edges)
         set_edges, bm_edges = edges_BVH_overlap(edges, bm_edges, precision = 0.001)
         new_edges, targetmap = intersect_edges_edges(set_edges, bm_edges, precision = 4)
         if targetmap:
             bmesh.ops.weld_verts(self.bm, targetmap=targetmap)
         bmesh.update_edit_mesh(self.mesh, tessface=True, destructive=True)
         return {'FINISHED'}
     if self.cancel:
         return {'FINISHED'}
     self.cancel = event.type == 'ESC'
     self.confirm = event.type == 'LEFTMOUSE'
     return {'PASS_THROUGH'}
예제 #5
0
    def main(self, context, chboxhide, chboxshow):

        obj = bpy.context.object
        me = obj.data
        bm = bmesh.from_edit_mesh(me)
        try:
            v1 = [v for v in bm.verts if (v.select == True and v.hide == False)]

            e1 = [e for e in bm.edges if (e.select == True and e.hide == False)]

            f1 = [f for f in bm.faces if (f.select == True and f.hide == False)]

            if len(v1) > 0 or len(e1) > 0 or f1 > 0:
                if chboxhide:
                    bpy.ops.mesh.select_all(action='INVERT')
                    bpy.ops.mesh.hide(unselected=False)
                    bpy.ops.mesh.select_all(action='SELECT')

                elif chboxshow:
                    bpy.ops.mesh.reveal()
        except:

            if chboxshow:
                bpy.ops.mesh.reveal()

        bmesh.update_edit_mesh(me, True)
    def offset_profile(self, ob_edit, info_profile):
        me = ob_edit.data
        bm = bmesh.from_edit_mesh(me)

        if self.caches_valid and self._cache_offset_infos:
            offset_infos, edges_orig = self.get_caches(bm)
        else:
            offset_infos, edges_orig = self.get_offset_infos(bm, ob_edit)
            if offset_infos is False:
                return {'CANCELLED'}
            self.save_caches(offset_infos, edges_orig)

        ref_verts = [v for v, _, _ in offset_infos]
        edges = edges_orig
        for width, depth, _ in info_profile:
            exverts, exedges, _ = self.extrude_and_pairing(bm, edges, ref_verts)
            self.move_verts(bm, me, width * self.magni_w, depth * self.magni_d, offset_infos,
                            exverts, update=False)
            ref_verts = exverts
            edges = exedges

        bm.normal_update()
        bmesh.update_edit_mesh(me)

        self.caches_valid = False

        return {'FINISHED'}
예제 #7
0
	def modal(self, context, event):

		if event.type in {'LEFTMOUSE', 'MIDDLEMOUSE', 'RIGHTMOUSE', 'WHEELDOWNMOUSE', 'WHEELUPMOUSE', 'G', 'X', 'Y', 'Z', 'MOUSEMOVE'}:
			return {'PASS_THROUGH'}
			
		elif event.type in {'RET', 'NUMPAD_ENTER'}:
			del bpy.types.Scene.PreSelOff
			# Consolidate changes.
			for v in self.vsellist:
				v.select = True
			for e in self.esellist:
				e.select = True
			for f in self.fsellist:
				f.select = True
			self.bm.verts.remove(self.originvert)
			bmesh.update_edit_mesh(self.mesh, destructive=True)
			self.mesh.update()
			self.bm.free()
			self.snapelem = context.tool_settings.snap_element
			self.snapstate = context.tool_settings.use_snap
			context.tool_settings.snap_element = self.snapelsave
			context.tool_settings.use_snap = self.snapstsave
			bpy.ops.object.editmode_toggle()
			bpy.ops.object.origin_set(type='ORIGIN_CURSOR')
			self.space3d.cursor_location = self.cursorsave			
			if self.mode == 'EDIT':
				bpy.ops.object.editmode_toggle()
			bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
			return {'FINISHED'}
		
		return {'RUNNING_MODAL'}
예제 #8
0
 def modal_tweak_move_tool(self, context, eventd):
     if eventd['release'] in self.keymap['action']:
         return 'main'
     
     rgn,r3d = eventd['region'],eventd['r3d']
     
     if eventd['type'] == 'MOUSEMOVE' and self.tweak_data:
         cx,cy = eventd['mouse']
         lx,ly = self.tweak_data['mouse']
         dx,dy = cx-lx,cy-ly
         dv = Vector((dx,dy))
         
         imx = self.imx
         
         def update(p3d, d):
             if d >= 1.0: return p3d
             p2d = location_3d_to_region_2d(rgn, r3d, p3d)
             p2d += dv * (1.0-d)
             hit_p3d,_ = self.src_bmc.raycast_screen(p2d, rgn, r3d)
             return hit_p3d or p3d
         
         vertices = self.dest_bme.verts
         for i_v,c,d in self.tweak_data['lmverts']:
             nc = update(c,d)
             vertices[i_v].co = imx * nc
             
         
         bmesh.update_edit_mesh(self.dest_obj.data, tessface=True, destructive=False)
         self.tar_bmeshrender.dirty()
          
     return ''
예제 #9
0
def noise_obj(obj, context, self):
    bm = bmesh.from_edit_mesh(obj.data)
    verts = [v for v in bm.verts if v.select]
    if not verts:
        verts = [v for v in bm.verts if v.hide is False]

    for vert in verts:
        noise_pos = self.frequency * vert.co.copy()
        noise_pos.x += self.offset_x
        noise_pos.z += self.offset_y
        noise_pos.z += self.offset_z

        noise_val = None
        if self.noise_type == 'Turbulence':
            noise_val = mathu.noise.turbulence(noise_pos, self.octaves, self.hard, mathu.noise.types.STDPERLIN, self.amplitude_scale, self.frequency_scale)
        elif self.noise_type == 'Fractal':
            noise_val = mathu.noise.fractal(noise_pos, self.amplitude_scale, self.frequency_scale, self.octaves, mathu.noise.types.STDPERLIN)
        else:
            noise_val = mathu.noise.hetero_terrain(noise_pos, self.amplitude_scale, self.frequency_scale, self.octaves, 0, mathu.noise.types.STDPERLIN)

        vert_offset = vert.normal.copy().normalized() * noise_val
        vert.co += vert_offset * self.intensity

    bm.normal_update()
    bmesh.update_edit_mesh(obj.data)
예제 #10
0
def extend_vertex():

    obj = bpy.context.edit_object
    me = obj.data
    bm = bmesh.from_edit_mesh(me)
    verts = bm.verts
    faces = bm.faces

    plane = [f for f in faces if f.select][0]
    plane_vert_indices = [v for v in plane.verts[:]]
    all_selected_vert_indices = [v for v in verts if v.select]

    M = set(plane_vert_indices)
    N = set(all_selected_vert_indices)
    O = N.difference(M)
    O = list(O)
    (v1_ref, v1_idx, v1), (v2_ref, v2_idx, v2) = [(i, i.index, i.co) for i in O]

    plane_co = plane.calc_center_median()
    plane_no = plane.normal

    new_co = intersect_line_plane(v1, v2, plane_co, plane_no, False)
    new_vertex = verts.new(new_co)

    A_len = (v1 - new_co).length
    B_len = (v2 - new_co).length

    vertex_reference = v1_ref if (A_len < B_len) else v2_ref
    bm.edges.new([vertex_reference, new_vertex])

    bmesh.update_edit_mesh(me, True)
예제 #11
0
 def modal(self, context, event):
     op = context.window_manager.operators
     #print([o.name for o in op])
     if op and op[-1].name == 'Translate':
         # print('-------------------')
         sface = self.bm.faces.active
         if not sface:
             for face in self.bm.faces:
                 if face.select == True:
                     sface = face
                     break
             else:
                 return {'FINISHED'}
         set_edges = set()
         for v in sface.verts:
             for ed in v.link_edges:
                 set_edges.add(ed)
         bm_edges = set(self.bm.edges)  # .difference_update(set_edges)
         bm_edges.difference_update(set_edges)
         set_edges, bm_edges = list_BVH(set_edges, bm_edges, precision=0.0001)
         new_edges, targetmap = intersect_edges_edges(set_edges, bm_edges)
         if targetmap:
             bmesh.ops.weld_verts(self.bm, targetmap=targetmap)
         bmesh.update_edit_mesh(self.mesh, tessface=True, destructive=True)
         return {'FINISHED'}
     if self.cancel:
         return {'FINISHED'}
     self.cancel = event.type == 'ESC'
     return {'PASS_THROUGH'}
예제 #12
0
def extrude_buildings(bm, me, height_min=.10, height_max=.25):
    extrude_buildings.roofs = []
    #create array to put selected faces in
    bm_faces = []
    for face in bm.faces[:]:
        face.select = False
        #select by criteria: plot index with certain area
        if face.material_index == 0:
            if face.calc_area() > (.01 * create_grid.size) and face.calc_area() < (0.3 * create_grid.size):
                bm_faces.append(face)
    #extrude geometry
    for face in bm_faces[:]:
        new_faces = bmesh.ops.extrude_face_region(
            bm,
            geom = [face])
        #new face[0] is equal to the newly created geometry translated upwards
        new_face = [e for e in new_faces['geom'] if isinstance(e, bmesh.types.BMFace)]
        #get roofs for reference
        extrude_buildings.roofs.append(new_face[0])
        #translate extrusion up
        bmesh.ops.translate(
            bm,
            vec = Vector((0, 0, uniform(height_min, height_max))),
            verts = new_face[0].verts
        )
    bmesh.update_edit_mesh(bpy.context.object.data)
예제 #13
0
def mat_slot_assign(bm, me):
    for i in bm.faces[:]:
        #i.material_index = 0 <- Plot
        #i.material_index = 1 <- Streets
        #i.material_index = 2 <- Rivers
        if i.index in geo.rivers:
            i.select = True
            i.material_index = 2
            bpy.ops.object.material_slot_assign
            i.select = False
        #i.material_index = 3 <- Buildings
        elif i in buildings.master_list:
            i.select = True
            i.material_index = 3
            bpy.ops.object.material_slot_assign
            i.select = False
        #i.material_index = 4 <- Parks
        elif i.index in geo.parks:
            i.select = True
            i.material_index = 4
            bpy.ops.object.material_slot_assign
            i.select = False
    #scrub materials that don't contain users
    for mat in bpy.data.materials:
        if not mat.users:
            bpy.data.materials.remove(mat)
    bmesh.update_edit_mesh(me)
예제 #14
0
    def execute(self, context):
        self.report({'INFO'}, "Flip/Rotate UV")
        obj = context.active_object
        bm = bmesh.from_edit_mesh(obj.data)
        if common.check_version(2, 73, 0) >= 0:
            bm.faces.ensure_lookup_table()

        # get UV layer
        uv_layer = _get_uv_layer(self, bm)
        if not uv_layer:
            return {'CANCELLED'}

        # get selected face
        src_info = _get_src_face_info(self, bm, [uv_layer], True)
        if not src_info:
            return {'CANCELLED'}

        face_count = len(src_info[list(src_info.keys())[0]])
        self.report({'INFO'}, "{} face(s) are selected".format(face_count))

        # paste
        ret = _paste_uv(self, bm, src_info, src_info, [uv_layer], 'N_N',
                        self.flip, self.rotate, self.seams)
        if ret:
            return {'CANCELLED'}

        bmesh.update_edit_mesh(obj.data)

        if compat.check_version(2, 80, 0) < 0:
            if self.seams is True:
                obj.data.show_edge_seams = True

        return {'FINISHED'}
예제 #15
0
def main(context):
    obj = context.active_object
    me = obj.data
    bm = bmesh.from_edit_mesh(me)

    uv_layer = bm.loops.layers.uv.verify()
    bm.faces.layers.tex.verify()  # currently blender needs both layers.

    # adjust UVs
    for f in bm.faces:
        norm = f.normal
        ax, ay, az = abs(norm.x), abs(norm.y), abs(norm.z)
        axis = -1
        if ax > ay and ax > az:
            axis = 0
        if ay > ax and ay > az:
            axis = 1
        if az > ax and az > ay:
            axis = 2
        for l in f.loops:
            luv = l[uv_layer]
            if axis == 0: # x plane     
                luv.uv.x = l.vert.co.y
                luv.uv.y = l.vert.co.z
            if axis == 1: # u plane
                luv.uv.x = l.vert.co.x
                luv.uv.y = l.vert.co.z
            if axis == 2: # z plane
                luv.uv.x = l.vert.co.x
                luv.uv.y = l.vert.co.y

    bmesh.update_edit_mesh(me)
예제 #16
0
    def modal(self, context, event):
        if event.type == 'INBETWEEN_MOUSEMOVE':
            return {'RUNNING_MODAL'}

        actob = context.active_object
        mat = actob.matrix_world
        bm = bmesh.from_edit_mesh(actob.data)
        bm.clear()
        bm.from_mesh(self.mesh)

        retval = self.modal_mouse.modal(context, event)

        if self.modal_mouse.orientation.orientation == 'GLOBAL':
            self.use_world_coords = True
        else:
            self.use_world_coords = False

        if retval == {'PASS_THROUGH'}:
            if event.value == 'PRESS':
                if event.type == 'E':
                    ls = ['none', 'extrude', 'individual']
                    i = ls.index(self.extrude)
                    self.extrude = ls[(i + 1) % 3]
                elif event.type == 'V':
                    if self.use_even_offset_tangent:
                        self.use_even_offset_tangent = False
                        self.use_even_offset_normal = False
                    else:
                        self.use_even_offset_tangent = True
                        self.use_even_offset_normal = True
                elif event.type == 'C':
                    ls = ['all', 'selected', 'deselected', 'individual']
                    i = ls.index(self.normal_calculation)
                    s = ls[(i + 1) % 4]
                    self.tangent_calculation = ls[1] if s == 'all' else s
                    self.normal_calculation = s

        result = self.modal_mouse.result
        translation = result['translation']
        self.offset_tangent = translation[0]
        self.offset_normal = translation[1]

        self.execute(context)

        if event.type in ('SPACE', 'RET', 'NUMPAD_ENTER', 'LEFTMOUSE'):
            self.modal_mouse.draw_handler_remove(context)
            bpy.data.meshes.remove(self.mesh)
            context.area.tag_redraw()
            return {'FINISHED'}
        elif event.type in ('ESC', 'RIGHTMOUSE'):
            self.modal_mouse.draw_handler_remove(context)
            bm.clear()
            bm.from_mesh(self.mesh)
            bm.normal_update()
            bmesh.update_edit_mesh(actob.data, True, True)
            bpy.data.meshes.remove(self.mesh)
            context.area.tag_redraw()
            return {'FINISHED'}

        return {'RUNNING_MODAL'}
    def execute(self, context):
        mesh = context.object.data
        bm = bmesh.from_edit_mesh(mesh)
        try:
            selection = bm.select_history[0]
        except:
            for face in bm.faces:
                if face.select == True:
                    selection = face
            #else:
                #selection = None
        if not isinstance(selection, bmesh.types.BMFace):
            raise SelectionError('The selection is not a face')
        else:
            face = selection
            geom = []
            for edge in face.edges:
                #print(edge.calc_face_angle()- 1.5707963267948966)
                if abs(edge.calc_face_angle(0) - 1.5707963267948966) < 0.001:
                    geom.append(edge)

            dict = bmesh.ops.extrude_discrete_faces(bm, faces = [face])
            bpy.ops.mesh.select_all(action='DESELECT')
            for face in dict['faces']:
                face.select = True
            bmesh.ops.dissolve_edges(bm, edges = geom, use_verts=True, use_face_split=False)
            bmesh.update_edit_mesh(mesh, tessface=True, destructive=True)
            bpy.ops.transform.translate('INVOKE_DEFAULT', constraint_axis=(False, False, True), constraint_orientation='NORMAL')
        return {'FINISHED'}
def align_uvs(context, influence):
    editor = bpy.context.area.spaces[0]
    gps = editor.grease_pencil.layers[-1].active_frame.strokes[-1].points
    obj = bpy.context.edit_object
    me = obj.data
    bm = bmesh.from_edit_mesh(me)

    uv_layer = bm.loops.layers.uv.verify()
    bm.faces.layers.tex.verify()

    selected_uv_verts = []
    for f in bm.faces:
        for l in f.loops:
            l_uv = l[uv_layer]
            if l_uv.select:
                selected_uv_verts.append(l_uv)

    selected_uv_verts_positions = []
    for vert in selected_uv_verts:
        selected_uv_verts_positions.append(vert.uv)

    gpencil_points = []
    for point in gps:
        gpencil_points.append(point.co)

    for i, v in enumerate(selected_uv_verts):
        nearest_point = get_nearest_interpolated_point_on_stroke(selected_uv_verts_positions[i], gpencil_points, context)
        # newcoord = obj.matrix_world.inverted() * region_to_location(nearest_point, obj.matrix_world * v.co)
        v.uv = v.uv.lerp(nearest_point, influence)

    bmesh.update_edit_mesh(me, True)

    if context.user_preferences.addons[__name__].preferences.clear_strokes:
        editor.grease_pencil.layers[-1].active_frame.clear()
예제 #19
0
    def execute(self, context):
        self.init(context)

        ob = context.active_object
        bm = bmesh.from_edit_mesh(ob.data)

        # Add Layers
        layer = bm.verts.layers.int.new('at_shift_outline_extrude')
        for i, eve in enumerate(bm.verts):
            # 完全新規の頂点の値は0になるので、それと被らないように +1
            eve[layer] = i + 1

        layer_loop = bm.loops.layers.int.new('at_shift_outline_extrude')
        for i, efa in enumerate(bm.faces):
            for loop in efa.loops:
                loop[layer_loop] = i + 1

        # Extrude
        if self.extrude == 'individual':
            # 面の選択状態を確保
            selected_faces = [i for i, f in enumerate(bm.faces)
                              if f.select]
            # 全ての面を非選択
            for efa in bm.faces:
                efa.select = False
            # 頂点・辺のみ押し出し
            bpy.ops.mesh.extrude_region(False, mirror=False)
            # 頂点・辺の選択状態を確保
            selected_verts = [i for i, v in enumerate(bm.verts)
                              if v.select]
            selected_edges = [i for i, e in enumerate(bm.edges)
                              if e.select]
            # 面再選択、押し出し
            bm.faces.ensure_lookup_table()
            for i in selected_faces:
                bm.faces[i].select = True
            bpy.ops.mesh.extrude_faces_indiv(False, mirror=False)
            # 頂点・辺を再選択
            for i in selected_verts:
                bm.verts[i].select = True
            for i in selected_edges:
                bm.edges[i].select = True
            # select_flush_mode()はしなくても大丈夫か
        elif self.extrude == 'extrude':
            bpy.ops.mesh.extrude_region(False, mirror=False)

        # Translate
        self.execute_tangent(context, bm)
        self.execute_normal(context, bm)

        # Remove Layers
        bm.verts.layers.int.remove(layer)
        bm.loops.layers.int.remove(layer_loop)

        # Update
        bm.normal_update()
        bmesh.update_edit_mesh(ob.data, True, True)
        context.area.tag_redraw()

        return {'FINISHED'}
예제 #20
0
    def execute(self, context):

        # final attempt to enter unfragmented bm/mesh
        # ghastly, but what can I do? it works with these
        # fails without.
        bpy.ops.object.mode_set(mode='OBJECT')
        bpy.ops.object.mode_set(mode='EDIT')

        obj = context.active_object
        me = obj.data

        bm = bmesh.from_edit_mesh(me)
        bm.verts.ensure_lookup_table()
        bm.edges.ensure_lookup_table()

        edges = [e for e in bm.edges if e.select and not e.hide]

        if len(edges) == 2:
            message = do_vtx_if_appropriate(bm, edges)
            if isinstance(message, set):
                msg = messages.get(message.pop())
                return self.cancel_message(msg)
            bm = message
        else:
            return self.cancel_message('select two edges!')

        bm.verts.index_update()
        bm.edges.index_update()
        bmesh.update_edit_mesh(me, True)

        return {'FINISHED'}
def align_vertices(context, influence):
    # Object currently in edit mode.
    obj = bpy.context.edit_object
    # Object's mesh datablock.
    me = obj.data
    # Convert mesh data to bmesh.
    bm = bmesh.from_edit_mesh(me)

    # Get all selected vertices (in their local space).
    selected_verts = [v for v in bm.verts if v.select]

    verts_local_3d = [v.co for v in selected_verts]

    # Convert selected vertices' positions to 2D screen space.
    # IMPORTANT: Multiply vertex coordinates with the world matrix to get their WORLD position, not local position.
    verts_world_2d = vectors_to_screenpos(context, verts_local_3d, obj.matrix_world)

    # For each vert, look up or to the side and find the nearest interpolated gpencil point for this vertex.
    for i, v in enumerate(selected_verts):
        nearest_point = get_nearest_interpolated_point_on_stroke(verts_world_2d[i], gpencil_to_screenpos(context), context)
        # Get new vertex coordinate by converting from 2D screen space to 3D world space. Must multiply depth coordinate
        # with world matrix and then final result by INVERTED world matrix to get a correct final value.
        newcoord = obj.matrix_world.inverted() * region_to_location(nearest_point, obj.matrix_world * v.co)
        # Apply the final position using an influence slider.
        v.co = v.co.lerp(newcoord, influence)

    # Recalculate mesh normals (so lighting looks right).
    for edge in bm.edges:
        edge.normal_update()

    # Push bmesh changes back to the actual mesh datablock.
    bmesh.update_edit_mesh(me, True)
예제 #22
0
def cut_visible_by_perpendicular(self):

    obj = bpy.context.object
    me = obj.data
    bm = bmesh.from_edit_mesh(me)

    verts = [v for v in bm.verts if (v.select and not v.hide)]

    if not len(verts) == 2:
        msg = "select two vertices"
        self.report({"WARNING"}, msg)
        return {'CANCELLED'}

    v1, v2 = [v.co for v in verts]
    print('vectors found:\n', v1, '\n', v2)

    mid_vec = v1.lerp(v2, 0.5)
    plane_no = v2 - mid_vec
    plane_co = mid_vec
    dist = 0.0001

    # hidden geometry will not be affected.
    visible_geom = [g for g in bm.faces[:]
                    + bm.verts[:] + bm.edges[:] if not g.hide]

    bmesh.ops.bisect_plane(
        bm,
        geom=visible_geom,
        dist=dist,
        plane_co=plane_co, plane_no=plane_no,
        use_snap_center=False,
        clear_outer=False,
        clear_inner=False)

    bmesh.update_edit_mesh(me, True)
예제 #23
0
 def draw_verts(self,context,obj):
     bm = bmesh.from_edit_mesh(obj.data)
     
     selected_verts_count = 0
     for vert in bm.verts:
         if vert.select:
             selected_verts_count += 1
     if selected_verts_count > 1:
         for vert in bm.verts:
             if vert.select:
                 vert.select = False
         for face in bm.faces:
             if face.select:
                 face.select = False  
         for edge in bm.edges:
             if edge.select:
                 edge.select = False        
     bmesh.update_edit_mesh(obj.data)
     
     selected_vert = []
     for vert in bm.verts:
         if vert.select:
             selected_vert.append(vert)
     new_vert = bm.verts.new(obj.matrix_world.inverted() * context.scene.cursor_location)
     new_vert.select = True
     if len(selected_vert) > 0:
         bm.edges.new([selected_vert[0],new_vert])
     for vert in selected_vert:
         vert.select = False
     
     bmesh.update_edit_mesh(obj.data)
예제 #24
0
def clean_verts(bm,obj):
    ### find corrupted faces
    faces = []     
    for face in bm.faces:
        i = 0
        for edge in face.edges:
            if not edge.is_manifold:
                i += 1
            if i == len(face.edges):
                faces.append(face)           
    bmesh.ops.delete(bm,geom=faces,context=5)

    edges = []
    for face in bm.faces:
        i = 0
        for vert in face.verts:
            if not vert.is_manifold and not vert.is_boundary:
                i+=1
            if i == len(face.verts):
                for edge in face.edges:
                    if edge not in edges:
                        edges.append(edge)
    bmesh.ops.collapse(bm,edges=edges)
    
    bmesh.update_edit_mesh(obj.data)
    for vert in bm.verts:
        if not vert.is_boundary:
            vert.select = False
            
    verts = []
    for vert in bm.verts:
        if len(vert.link_edges) in [3,4] and not vert.is_boundary:
            verts.append(vert)
    bmesh.ops.dissolve_verts(bm,verts=verts)
    bmesh.update_edit_mesh(obj.data)
예제 #25
0
 def normal_fill(self,context):
     obj = context.active_object
     
     bpy.ops.mesh.edge_face_add()
     bpy.ops.uv.project_from_view(camera_bounds=False, correct_aspect=True, scale_to_bounds=True)
     
     self.reset_spritesheet(context,obj)
     
     
     bm = bmesh.from_edit_mesh(obj.data)
     unselected_faces = []
     for face in bm.faces:
         if face.select == False:
             unselected_faces.append(face)
         face.select = True    
         
         
     bpy.ops.uv.project_from_view(camera_bounds=False, correct_aspect=True, scale_to_bounds=True)
     
     
     for face in unselected_faces:
         face.select = False
         
     bmesh.update_edit_mesh(obj.data)
     
     self.revert_rest_spritesheet(context,obj)
예제 #26
0
    def execute(self, context):
        mesh = bpy.context.active_object.data
        bm = bmesh.from_edit_mesh(mesh)
        face_normal_influence_layer = bm.faces.layers.int['face-normal-influence']

        # Determine enumerated face normal influence value.
        face_normal_influence = self.face_influence_map[self.influence]

        # Select faces by given normal vector influence.
        if self.action == 'GET':
            context.tool_settings.mesh_select_mode = (False, False, True)
            for f in bm.faces:
                if f[face_normal_influence_layer] == face_normal_influence:
                    f.select = True
                else:
                    f.select = False
            bm.select_mode = {'FACE'}
            bm.select_flush_mode()

        # Assign given face normal influence to selected faces.
        elif self.action == 'SET' and mesh.total_face_sel:
            selected_faces = [f for f in bm.faces if f.select]
            for f in selected_faces:
                f[face_normal_influence_layer] = face_normal_influence

        # Update the mesh.
        bmesh.update_edit_mesh(mesh)
        if self.action == 'SET' and self.update:
            bpy.ops.mesh.yavne_update_vertex_normals()

        return {'FINISHED'}
예제 #27
0
    def __init__(self):
        mesh = bpy.context.active_object.data
        bm = bmesh.from_edit_mesh(mesh)
        vert_float_layers = bm.verts.layers.float
        vert_int_layers = bm.verts.layers.int
        face_int_layers = bm.faces.layers.int

        # Reference addon.
        self.addon = bpy.context.user_preferences.addons[self.addon_key]

        # Ensure that the 'vertex-normal-weight' custom data layer exists.
        if not 'vertex-normal-weight' in vert_int_layers.keys():
            vert_int_layers.new('vertex-normal-weight')

        # Ensure that the 'face-normal-influence' custom data layer exists.
        if not 'face-normal-influence' in face_int_layers.keys():
            face_int_layers.new('face-normal-influence')

        # Ensure that vertex normal component layers exist.
        if not 'vertex-normal-x' in vert_float_layers.keys():
            vert_float_layers.new('vertex-normal-x')
        if not 'vertex-normal-y' in vert_float_layers.keys():
            vert_float_layers.new('vertex-normal-y')
        if not 'vertex-normal-z' in vert_float_layers.keys():
            vert_float_layers.new('vertex-normal-z')

        # Update the mesh.
        bmesh.update_edit_mesh(mesh)
    def main(self, context, chboxVert0, chboxVert1, chboxVert2):

        obj = bpy.context.object
        me = obj.data
        bm = bmesh.from_edit_mesh(me)

        vertices = [v for v in bm.verts if (v.select and not v.hide)]

        if not len(vertices) == 3:
            msg = "select ONLY 3 vertices"
            self.report({"WARNING"}, msg)
            return {'CANCELLED'}

        v1, v2, v3 = [v for v in vertices]

        if chboxVert0:
            corte(bm, v1, v2, v3)

        if chboxVert1:
            corte(bm, v2, v1, v3)

        if chboxVert2:
            corte(bm, v3, v1, v2)
            verticeje = v3.co

        else:
            print("Select 1 option")

        bmesh.update_edit_mesh(me, True)
예제 #29
0
    def execute(self, context):
        mesh = context.object.data
        bm = bmesh.from_edit_mesh(mesh)

        # get or create color layer
        colors = bm.loops.layers.color.active
        if not colors:
            colors = bm.loops.layers.color.new("Col")

        # get Draw brush current color
        color = bpy.data.brushes["Draw"].color

        if tuple(bm.select_mode)[0] == 'FACE':
            # in face mode, assign colors to selected faces loops only (faces color)
            floops = [ l for f in bm.faces for l in f.loops if f.select ]
            for loop in floops:
                loop[colors] = color
        else:
            # assign colors to all loops connected to selected vertices (vertex color)
            vloops = [ l for v in bm.verts for l in v.link_loops if v.select ]
            for loop in vloops:
                loop[colors] = color

        bmesh.update_edit_mesh(mesh)

        return {'FINISHED'}
예제 #30
0
def SuccessFinished(me, startTime):
    #use for backtrack of steps 
    #bpy.ops.ed.undo_push()
    bmesh.update_edit_mesh(me)
    #elapsed = round(time.clock()-startTime, 2)
    #if (elapsed >= 0.05): operator.report({'INFO'}, "UvSquares finished, elapsed:", elapsed, "s.")
    return
    bm.faces.ensure_lookup_table()


    ## Deselect all and select the required faces
    bpy.ops.mesh.select_all(action = 'DESELECT')


    ## Select alternate faces
    for i in range(0, len(bm.faces)):
        if i % 2 == 0:
            bm.faces[i].select = True  # select index 4



    ## Show the updates in the viewport
    bmesh.update_edit_mesh(me, True)



    ## Extrude selected faces
    bpy.ops.mesh.extrude_region_move(MESH_OT_extrude_region={"use_normal_flip":False, "mirror":False}, TRANSFORM_OT_translate={"value":(0, 0, 0), "orient_type":'GLOBAL', "orient_matrix":((0, 0, 0), (0, 0, 0), (0, 0, 0)), "orient_matrix_type":'GLOBAL', "constraint_axis":(False, False, False), "mirror":False, "use_proportional_edit":False, "proportional_edit_falloff":'SMOOTH', "proportional_size":1, "use_proportional_connected":False, "use_proportional_projected":False, "snap":False, "snap_target":'CLOSEST', "snap_point":(0, 0, 0), "snap_align":False, "snap_normal":(0, 0, 0), "gpencil_strokes":False, "cursor_transform":False, "texture_space":False, "remove_on_cancel":False, "release_confirm":False, "use_accurate":False})


    ## Scaled the extruded part
    bpy.ops.transform.resize(value=(2, 2, 2), orient_type='GLOBAL', orient_matrix=((1, 0, 0), (0, 1, 0), (0, 0, 1)), orient_matrix_type='GLOBAL', mirror=True, use_proportional_edit=False, proportional_edit_falloff='SMOOTH', proportional_size=1, use_proportional_connected=False, use_proportional_projected=False)



    ## Exit edit mode
    bpy.ops.object.editmode_toggle()
예제 #32
0
    def execute(self, context):
        self.report({'INFO'}, "Flip/Rotate UV")
        obj = context.active_object
        bm = bmesh.from_edit_mesh(obj.data)
        if common.check_version(2, 73, 0) >= 0:
            bm.faces.ensure_lookup_table()

        # get UV layer
        if not bm.loops.layers.uv:
            self.report({'WARNING'}, "Object must have more than one UV map")
            return {'CANCELLED'}
        uv_layer = bm.loops.layers.uv.verify()

        # get selected face
        dest_uvs = []
        dest_pin_uvs = []
        dest_seams = []
        dest_face_indices = []
        for face in bm.faces:
            if face.select:
                dest_face_indices.append(face.index)
                uvs = [l[uv_layer].uv.copy() for l in face.loops]
                pin_uvs = [l[uv_layer].pin_uv for l in face.loops]
                seams = [l.edge.seam for l in face.loops]
                dest_uvs.append(uvs)
                dest_pin_uvs.append(pin_uvs)
                dest_seams.append(seams)
        if not dest_uvs or not dest_pin_uvs:
            self.report({'WARNING'}, "No faces are selected")
            return {'CANCELLED'}
        self.report({'INFO'}, "%d face(s) are selected" % len(dest_uvs))

        # paste
        for idx, duvs, dpuvs, dss in zip(dest_face_indices, dest_uvs,
                                         dest_pin_uvs, dest_seams):
            duvs_fr = [uv for uv in duvs]
            dpuvs_fr = [pin_uv for pin_uv in dpuvs]
            dss_fr = [s for s in dss]
            # flip UVs
            if self.flip is True:
                duvs_fr.reverse()
                dpuvs_fr.reverse()
                dss_fr.reverse()
            # rotate UVs
            for _ in range(self.rotate):
                uv = duvs_fr.pop()
                pin_uv = dpuvs_fr.pop()
                s = dss_fr.pop()
                duvs_fr.insert(0, uv)
                dpuvs_fr.insert(0, pin_uv)
                dss_fr.insert(0, s)
            # paste UVs
            for l, duv, dpuv, ds in zip(
                    bm.faces[idx].loops, duvs_fr, dpuvs_fr, dss_fr):
                l[uv_layer].uv = duv
                l[uv_layer].pin_uv = dpuv
                if self.seams is True:
                    l.edge.seam = ds

        self.report({'INFO'}, "%d face(s) are flipped/rotated" % len(dest_uvs))

        bmesh.update_edit_mesh(obj.data)
        if self.seams is True:
            obj.data.show_edge_seams = True

        return {'FINISHED'}
예제 #33
0
def make_line(self, bm_geom, location):
    obj = self.main_snap_obj.data[0]
    bm = self.main_bm
    split_faces = set()

    update_edit_mesh = False

    if bm_geom is None:
        vert = bm.verts.new(location)
        self.list_verts.append(vert)
        update_edit_mesh = True

    elif isinstance(bm_geom, bmesh.types.BMVert):
        if (bm_geom.co - location).length_squared < .001:
            if self.list_verts == [] or self.list_verts[-1] != bm_geom:
                self.list_verts.append(bm_geom)
        else:
            vert = bm.verts.new(location)
            self.list_verts.append(vert)
            update_edit_mesh = True

    elif isinstance(bm_geom, bmesh.types.BMEdge):
        self.list_edges.append(bm_geom)
        ret = intersect_point_line(location, bm_geom.verts[0].co, bm_geom.verts[1].co)

        if (ret[0] - location).length_squared < .001:
            if ret[1] == 0.0:
                vert = bm_geom.verts[0]
            elif ret[1] == 1.0:
                vert = bm_geom.verts[1]
            else:
                edge, vert = bmesh.utils.edge_split(bm_geom, bm_geom.verts[0], ret[1])
                update_edit_mesh = True

            if self.list_verts == [] or self.list_verts[-1] != vert:
                self.list_verts.append(vert)
                self.geom = vert # hack to highlight in the drawing
            # self.list_edges.append(edge)

        else:  # constrain point is near
            vert = bm.verts.new(location)
            self.list_verts.append(vert)
            update_edit_mesh = True

    elif isinstance(bm_geom, bmesh.types.BMFace):
        split_faces.add(bm_geom)
        vert = bm.verts.new(location)
        self.list_verts.append(vert)
        update_edit_mesh = True

    # draw, split and create face
    if len(self.list_verts) >= 2:
        v1, v2 = self.list_verts[-2:]
        edge = bm.edges.get([v1, v2])
        if edge:
                self.list_edges.append(edge)
        else:
            if not v2.link_edges:
                edge = bm.edges.new([v1, v2])
                self.list_edges.append(edge)
            else:  # split face
                v1_link_faces = v1.link_faces
                v2_link_faces = v2.link_faces
                if v1_link_faces and v2_link_faces:
                    split_faces.update(set(v1_link_faces).intersection(v2_link_faces))

                else:
                    if v1_link_faces:
                        faces = v1_link_faces
                        co2 = v2.co.copy()
                    else:
                        faces = v2_link_faces
                        co2 = v1.co.copy()

                    for face in faces:
                        if bmesh.geometry.intersect_face_point(face, co2):
                            co = co2 - face.calc_center_median()
                            if co.dot(face.normal) < 0.001:
                                split_faces.add(face)

                if split_faces:
                    edge = bm.edges.new([v1, v2])
                    self.list_edges.append(edge)
                    ed_list = get_loose_linked_edges(v2)
                    for face in split_faces:
                        facesp = bmesh.utils.face_split_edgenet(face, ed_list)
                    del split_faces
                else:
                    if self.intersect:
                        facesp = bmesh.ops.connect_vert_pair(bm, verts=[v1, v2], verts_exclude=bm.verts)
                        # print(facesp)
                    if not self.intersect or not facesp['edges']:
                        edge = bm.edges.new([v1, v2])
                        self.list_edges.append(edge)
                    else:
                        for edge in facesp['edges']:
                            self.list_edges.append(edge)
            update_edit_mesh = True

        # create face
        if self.create_face:
            ed_list = set(self.list_edges)
            for edge in v2.link_edges:
                if edge not in ed_list and edge.other_vert(v2) in self.list_verts:
                    ed_list.add(edge)
                    break

            ed_list.update(get_loose_linked_edges(v2))

            bmesh.ops.edgenet_fill(bm, edges=list(ed_list))
            update_edit_mesh = True
            # print('face created')

    if update_edit_mesh:
        obj.data.update_gpu_tag()
        obj.data.update_tag()
        obj.update_from_editmode()
        obj.update_tag()
        bmesh.update_edit_mesh(obj.data)
        self.sctx.tag_update_drawn_snap_object(self.main_snap_obj)
        #bm.verts.index_update()

        bpy.ops.ed.undo_push(message="Undo draw line*")

    return [obj.matrix_world @ v.co for v in self.list_verts]
예제 #34
0
    def align(self, context, type, axis, direction, orientation):
        active = context.active_object

        mx = active.matrix_world if orientation == 'LOCAL' else context.scene.cursor.matrix if orientation == 'CURSOR' else Matrix(
        )

        mode = context.scene.M3.align_mode

        # in VIEW mode the axis is calculated from from viewport direction giving in the pie
        if mode == 'VIEW':
            axis_right, axis_up, flip_right, flip_up = get_right_and_up_axes(
                context, mx=mx)

            if type == 'MINMAX':
                axis = axis_right if direction in ['RIGHT', 'LEFT'
                                                   ] else axis_up

            elif type in ['ZERO', 'AVERAGE', 'CURSOR']:
                axis = axis_right if direction == "HORIZONTAL" else axis_up

        bm = bmesh.from_edit_mesh(active.data)
        bm.normal_update()
        bm.verts.ensure_lookup_table()

        verts = [v for v in bm.verts if v.select]

        # axis coordinates in local space
        if orientation == 'LOCAL':
            axiscoords = [v.co[axis] for v in verts]

        # coordinates in world space
        elif orientation == 'WORLD':
            axiscoords = [(active.matrix_world @ v.co)[axis] for v in verts]

        # coordinates in cursor space
        elif orientation == 'CURSOR':
            axiscoords = [
                (mx.inverted_safe() @ active.matrix_world @ v.co)[axis]
                for v in verts
            ]

        # get min or max target value
        if type == "MIN":
            target = min(axiscoords)

        elif type == "MAX":
            target = max(axiscoords)

        # min or max in VIEW mode
        elif type == 'MINMAX':
            if direction == 'RIGHT':
                target = min(axiscoords) if flip_right else max(axiscoords)

            elif direction == 'LEFT':
                target = max(axiscoords) if flip_right else min(axiscoords)

            elif direction == 'TOP':
                target = min(axiscoords) if flip_up else max(axiscoords)

            elif direction == 'BOTTOM':
                target = max(axiscoords) if flip_up else min(axiscoords)

        # get the zero target value
        elif type == "ZERO":
            target = 0

        # get the average target value
        elif type == "AVERAGE":
            target = sum(axiscoords) / len(axiscoords)

        # get cursor target value
        elif type == "CURSOR":
            if orientation == 'LOCAL':
                c_world = context.scene.cursor.location
                c_local = mx.inverted() @ c_world
                target = c_local[axis]

            elif orientation == 'WORLD':
                target = context.scene.cursor.location[axis]

            elif orientation == 'CURSOR':
                target = 0

        # set the new coordinates
        for v in verts:
            if orientation == 'LOCAL':
                v.co[axis] = target

            elif orientation == 'WORLD':
                # bring vertex coords into world space
                world_co = active.matrix_world @ v.co

                # set the target value
                world_co[axis] = target

                # bring it back into local space
                v.co = active.matrix_world.inverted_safe() @ world_co

            elif orientation == 'CURSOR':
                # bring vertex coords into cursor space
                cursor_co = mx.inverted_safe() @ active.matrix_world @ v.co

                # set the target value
                cursor_co[axis] = target

                # bring it back into local space
                v.co = active.matrix_world.inverted_safe() @ mx @ cursor_co

        bm.normal_update()
        bmesh.update_edit_mesh(active.data)
예제 #35
0
    def center(self, context, axis, direction, orientation):
        active = context.active_object
        mx = active.matrix_world if orientation == 'LOCAL' else context.scene.cursor.matrix if orientation == 'CURSOR' else Matrix(
        )

        mode = context.scene.M3.align_mode

        # calculate axis from viewport
        if mode == 'VIEW':
            axis_right, axis_up, flip_right, flip_up = get_right_and_up_axes(
                context, mx=mx)

            axis = axis_right if direction == "HORIZONTAL" else axis_up

        bm = bmesh.from_edit_mesh(active.data)
        bm.normal_update()
        bm.verts.ensure_lookup_table()

        verts = [v for v in bm.verts if v.select]

        # use the single vert's coordinate as the origin
        if len(verts) == 1:
            origin = verts[0].co

        # use the midpoint between two verts/one edge as the origin
        elif len(verts) == 2:
            origin = get_center_between_verts(*verts)

        # use the bounding box center as the origin
        else:
            _, origin = create_selection_bbox([v.co for v in verts])

        # the target location will be the origin with the axis zeroed out
        if orientation == 'LOCAL':
            target = origin.copy()
            target[axis] = 0

            # create translation matrix
            mxt = get_loc_matrix(target - origin)

        elif orientation == 'WORLD':
            # bring into world space
            origin = active.matrix_world @ origin
            target = origin.copy()
            target[axis] = 0

            # create translation matrix (in local space again)
            mxt = get_loc_matrix(
                active.matrix_world.inverted().to_3x3() @ (target - origin))

        elif orientation == 'CURSOR':
            # bring into cursor space
            origin = mx.inverted_safe() @ active.matrix_world @ origin
            target = origin.copy()
            target[axis] = 0

            # create translation matrix (in local space again)
            mxt = get_loc_matrix(active.matrix_world.inverted().to_3x3()
                                 @ mx.to_3x3() @ (target - origin))

        # move the selection
        for v in verts:
            v.co = mxt @ v.co

        bmesh.update_edit_mesh(active.data)
예제 #36
0
 def __exit__(self, type, value, traceback):
     bmesh.update_edit_mesh(self.mesh)
    def execute(self, context):
        props = context.scene.muv_props.cpuv_selseq
        if len(props.src_uvs) == 0 or len(props.src_pin_uvs) == 0:
            self.report({'WARNING'}, "Need copy UV at first")
            return {'CANCELLED'}
        if self.uv_map == "":
            self.report({'INFO'}, "Paste UV coordinate (selection sequence)")
        else:
            self.report(
                {'INFO'},
                "Paste UV coordinate (selection sequence) (UV map:%s)" %
                (self.uv_map))

        obj = context.active_object
        bm = bmesh.from_edit_mesh(obj.data)
        if muv_common.check_version(2, 73, 0) >= 0:
            bm.faces.ensure_lookup_table()

        # get UV layer
        if self.uv_map == "":
            if not bm.loops.layers.uv:
                self.report({'WARNING'},
                            "Object must have more than one UV map")
                return {'CANCELLED'}
            uv_layer = bm.loops.layers.uv.verify()
        else:
            uv_layer = bm.loops.layers.uv[self.uv_map]

        # get selected face
        dest_uvs = []
        dest_pin_uvs = []
        dest_seams = []
        dest_face_indices = []
        for hist in bm.select_history:
            if isinstance(hist, bmesh.types.BMFace) and hist.select:
                dest_face_indices.append(hist.index)
                uvs = [l[uv_layer].uv.copy() for l in hist.loops]
                pin_uvs = [l[uv_layer].pin_uv for l in hist.loops]
                seams = [l.edge.seam for l in hist.loops]
                dest_uvs.append(uvs)
                dest_pin_uvs.append(pin_uvs)
                dest_seams.append(seams)
        if len(dest_uvs) == 0 or len(dest_pin_uvs) == 0:
            self.report({'WARNING'}, "No faces are selected")
            return {'CANCELLED'}
        if self.strategy == 'N_N' and len(props.src_uvs) != len(dest_uvs):
            self.report(
                {'WARNING'},
                "Number of selected faces is different from copied faces " +
                "(src:%d, dest:%d)" % (len(props.src_uvs), len(dest_uvs)))
            return {'CANCELLED'}

        # paste
        for i, idx in enumerate(dest_face_indices):
            suv = None
            spuv = None
            ss = None
            duv = None
            if self.strategy == 'N_N':
                suv = props.src_uvs[i]
                spuv = props.src_pin_uvs[i]
                ss = props.src_seams[i]
                duv = dest_uvs[i]
            elif self.strategy == 'N_M':
                suv = props.src_uvs[i % len(props.src_uvs)]
                spuv = props.src_pin_uvs[i % len(props.src_pin_uvs)]
                ss = props.src_seams[i % len(props.src_seams)]
                duv = dest_uvs[i]
            if len(suv) != len(duv):
                self.report({'WARNING'}, "Some faces are different size")
                return {'CANCELLED'}
            suvs_fr = [uv for uv in suv]
            spuvs_fr = [pin_uv for pin_uv in spuv]
            ss_fr = [s for s in ss]
            # flip UVs
            if self.flip_copied_uv is True:
                suvs_fr.reverse()
                spuvs_fr.reverse()
                ss_fr.reverse()
            # rotate UVs
            for _ in range(self.rotate_copied_uv):
                uv = suvs_fr.pop()
                pin_uv = spuvs_fr.pop()
                s = ss_fr.pop()
                suvs_fr.insert(0, uv)
                spuvs_fr.insert(0, pin_uv)
                ss_fr.insert(0, s)
            # paste UVs
            for l, suv, spuv, ss in zip(bm.faces[idx].loops, suvs_fr, spuvs_fr,
                                        ss_fr):
                l[uv_layer].uv = suv
                l[uv_layer].pin_uv = spuv
                if self.copy_seams is True:
                    l.edge.seam = ss

        self.report({'INFO'}, "%d face(s) are copied" % len(dest_uvs))

        bmesh.update_edit_mesh(obj.data)
        if self.copy_seams is True:
            obj.data.show_edge_seams = True

        return {'FINISHED'}
예제 #38
0
    def adapt(self, event):

        global started

        def removecaps():
            self.capped = False
            for posn in range(len(self.vertlist)):
                for [e1, e2, v1, v2, fj, fo1, fo2] in self.caplist[posn]:
                    if e1 == None:
                        continue
                    bmesh.utils.face_split(fj, v1, v2)
                    templ = []
                    for f in e1.link_faces:
                        templ.append(f)
                    bmesh.utils.face_join(templ)
                    templ = []
                    for f in e2.link_faces:
                        templ.append(f)
                    bmesh.utils.face_join(templ)
            self.mesh.calc_tessface()

        if self.mbns == 0:
            if self.Cap != self.oldcap:
                if self.dist != 0:
                    self.mbns = 2
                if self.Cap == True:
                    self.capped = False
                else:
                    removecaps()
                self.oldcap = self.Cap
            if self.Both != self.oldboth:
                if self.dist != 0:
                    # enter edge-building through the backdoor to instantaneously show both inserts
                    self.mbns = 2
                if self.Both == True:
                    # if just set
                    for posn in range(len(self.vertlist)):
                        if self.negsubd[posn]:
                            self.possubd[posn] = False
                        if self.possubd[posn]:
                            self.negsubd[posn] = False
                else:
                    if self.capped:
                        self.capped = False
                        removecaps()
                    # if just unset: remove one side of edges
                    if self.dist < 0:
                        for posn in range(len(self.vertlist)):
                            bpy.ops.mesh.select_all(action='DESELECT')
                            for vert in self.dissverts2[posn]:
                                vert.select = True
                            for edge in self.dissedges2[posn]:
                                edge.select = True
                            bpy.ops.mesh.dissolve_edges(use_verts=True)
                            self.mesh.calc_tessface()
                            for vert in self.dissverts1[posn]:
                                vert.select = True
                            for edge in self.dissedges1[posn]:
                                edge.select = True
                            self.possubd[posn] = False
                            self.railedges2[posn] = []
                            self.railverts2[posn] = []
                            self.dissverts2[posn] = []
                            self.dissedges2[posn] = []
                    if self.dist >= 0:
                        for posn in range(len(self.vertlist)):
                            if self.railedges1[posn] != []:
                                bpy.ops.mesh.select_all(action='DESELECT')
                                for vert in self.dissverts1[posn]:
                                    vert.select = True
                                for edge in self.dissedges1[posn]:
                                    edge.select = True
                                bpy.ops.mesh.dissolve_edges(use_verts=True)
                                self.mesh.calc_tessface()
                                for vert in self.dissverts2[posn]:
                                    vert.select = True
                                for edge in self.dissedges2[posn]:
                                    edge.select = True
                                self.negsubd[posn] = False
                                self.railedges1[posn] = []
                                self.railverts1[posn] = []
                                self.dissverts1[posn] = []
                                self.dissedges1[posn] = []
                    for vert in self.vertlist[posn]:
                        vert.select = True
                    for edge in self.edgelist[posn]:
                        edge.select = True
            self.oldboth = self.Both
            self.dist = self.Distance
            if self.dist != self.olddist:
                self.mbns = 2
            self.olddist = self.dist
        else:
            if self.mbns != 2:
                if event != None:
                    # do mouse handling left-right
                    mx = event.mouse_region_x
                    mean = max(-1 * self.meanmin, self.meanmax)
                    self.dist = self.basev + ((mx - self.basex) / 200) * mean
                    self.Distance = self.dist
                    self.distset = True
            else:
                self.mbns = 0
            # dont do anything if zero - removing edges will be handled once exiting with ENTER
            if self.Distance == 0:
                return

            #negative side handling
            if self.dist < 0 or self.Both == True:
                for posn in range(len(self.vertlist)):
                    if not (self.negsubd[posn]):
                        if self.Both == False:
                            # if just switched sides: remove positive side
                            if self.possubd[posn] == True:
                                bpy.ops.mesh.select_all(action='DESELECT')
                                for vert in self.dissverts2[posn]:
                                    vert.select = True
                                for edge in self.dissedges2[posn]:
                                    edge.select = True
                                self.mesh.update()
                                bpy.ops.mesh.dissolve_edges(
                                    use_verts=True, use_face_split=False)
                                self.railedges2[posn] = []
                                self.railverts2[posn] = []
                                self.dissverts2[posn] = []
                                self.dissedges2[posn] = []
                                bpy.ops.mesh.select_all(action='DESELECT')
                            self.possubd[posn] = False
                        self.railedges1[posn] = []
                        self.railverts1[posn] = []
                        self.dissverts1[posn] = []
                        self.dissedges1[posn] = []

                for posn in range(len(self.vertlist)):
                    if not (self.negsubd[posn]):
                        self.negsubd[posn] = True
                        # if just switched sides: look for slide constellations
                        for i, vert in enumerate(self.vertlist[posn]):
                            if i == len(self.vertlist[posn]) - 1:
                                break
                            for loop in vert.link_loops:
                                if loop.link_loop_next.vert == self.vertlist[
                                        posn][i + 1]:
                                    self.railverts1[posn].append(
                                        loop.link_loop_prev.vert)
                                    e = loop.link_loop_prev.edge
                                    self.railedges1[posn].append(e)
                                    if self.vertlist[posn].index(vert) == len(
                                            self.vertlist[posn]) - 2:
                                        self.railverts1[posn].append(
                                            loop.link_loop_next.link_loop_next.
                                            vert)
                                        e = loop.link_loop_next.edge
                                        self.railedges1[posn].append(e)
                        if self.railedges1[posn] != []:
                            # insert parallel edges
                            prev = None
                            popout = False
                            for idx in range(len(self.railedges1[posn])):
                                if popout:
                                    break
                                edge = self.railedges1[posn][idx]
                                if idx == len(
                                        self.railedges1[posn]
                                ) - 1 and self.railverts1[posn][
                                        0] == self.railverts1[posn][
                                            len(self.railverts1[posn]) - 1]:
                                    # this handles closed edgeloops
                                    vert = startvert
                                    self.railedges1[posn].pop(
                                        len(self.railedges1[posn]) - 1)
                                    self.railverts1[posn].pop(
                                        len(self.railverts1[posn]) - 1)
                                    popout = True
                                else:
                                    dummy, vert = bmesh.utils.edge_split(
                                        edge, self.vertlist[posn][
                                            self.railedges1[posn].index(edge)],
                                        0.5)
                                if idx == 0:
                                    startvert = vert
                                self.dissverts1[posn].append(vert)
                                if not (prev == None):
                                    e = bmesh.ops.connect_verts(
                                        self.bm, verts=[vert, prev])
                                    self.dissedges1[posn].append(e['edges'][0])
                                prev = vert
                            self.mesh.calc_tessface()

                # select inserted edges/verts
                for posn in range(len(self.vertlist)):
                    for v in self.dissverts1[posn]:
                        v.select = True
                    for e in self.dissedges1[posn]:
                        e.select = True

            # do distance shifting
            for posn in range(len(self.vertlist)):
                if self.railedges1[posn] != []:
                    for v in self.vertlist[posn]:
                        pv = self.dissverts1[posn][self.vertlist[posn].index(
                            v)]
                        rv = self.railverts1[posn][self.vertlist[posn].index(
                            v)]
                        sv = self.bmundo.verts[v.index]
                        vec = rv.co - sv.co
                        vec.length = abs(self.dist)
                        pv.co = sv.co + vec

            #positive side handling
            if self.dist > 0 or self.Both == True:
                for posn in range(len(self.vertlist)):
                    if not (self.possubd[posn]):
                        if self.Both == False:
                            # if just switched sides: remove positive side
                            if self.negsubd[posn] == True:
                                bpy.ops.mesh.select_all(action='DESELECT')
                                for vert in self.dissverts1[posn]:
                                    vert.select = True
                                for edge in self.dissedges1[posn]:
                                    edge.select = True
                                bpy.ops.mesh.dissolve_edges(
                                    use_verts=True, use_face_split=False)
                                self.railedges1[posn] = []
                                self.railverts1[posn] = []
                                self.dissverts1[posn] = []
                                self.dissedges1[posn] = []
                                bpy.ops.mesh.select_all(action='DESELECT')
                            self.negsubd[posn] = False
                        self.railedges2[posn] = []
                        self.railverts2[posn] = []
                        self.dissverts2[posn] = []
                        self.dissedges2[posn] = []
                for posn in range(len(self.vertlist)):
                    if not (self.possubd[posn]):
                        # if just switched sides: look for slide constellations
                        for i, vert in enumerate(self.vertlist[posn]):
                            if (i == len(self.vertlist[posn]) -
                                    1) or (i > 0
                                           and vert == self.vertlist[posn][0]):
                                break
                            for loop in vert.link_loops:
                                if loop.link_loop_prev.vert == self.vertlist[
                                        posn][i + 1]:
                                    self.railverts2[posn].append(
                                        loop.link_loop_next.vert)
                                    e = loop.edge
                                    self.railedges2[posn].append(e)
                                    if self.vertlist[posn].index(vert) == len(
                                            self.vertlist[posn]) - 2:
                                        self.railverts2[posn].append(
                                            loop.link_loop_prev.link_loop_prev.
                                            vert)
                                        e = loop.link_loop_prev.link_loop_prev.edge
                                        self.railedges2[posn].append(e)
                for posn in range(len(self.vertlist)):
                    if not (self.possubd[posn]):
                        self.possubd[posn] = True
                        if self.railedges2[posn] != []:
                            # insert parallel edges
                            prev = None
                            popout = False
                            for idx in range(len(self.railedges2[posn])):
                                if popout:
                                    break
                                edge = self.railedges2[posn][idx]
                                if idx == len(
                                        self.railedges2[posn]
                                ) - 1 and self.railverts2[posn][
                                        0] == self.railverts2[posn][
                                            len(self.railverts2[posn]) - 1]:
                                    # this handles closed edgeloops
                                    vert = startvert
                                    self.railedges2[posn].pop(
                                        len(self.railedges2[posn]) - 1)
                                    self.railverts2[posn].pop(
                                        len(self.railverts2[posn]) - 1)
                                    popout = True
                                else:
                                    dummy, vert = bmesh.utils.edge_split(
                                        edge, self.vertlist[posn][
                                            self.railedges2[posn].index(edge)],
                                        0.5)
                                if idx == 0:
                                    startvert = vert
                                self.dissverts2[posn].append(vert)
                                if not (prev == None):
                                    e = bmesh.ops.connect_verts(
                                        self.bm, verts=[vert, prev])
                                    self.dissedges2[posn].append(e['edges'][0])
                                prev = vert
                                prevedge = edge
                            self.mesh.calc_tessface()

                # select inserted edges/verts
                for posn in range(len(self.vertlist)):
                    for v in self.dissverts2[posn]:
                        v.select = True
                    for e in self.dissedges2[posn]:
                        e.select = True

            # do distance shifting
            for posn in range(len(self.vertlist)):
                if self.railedges2[posn] != []:
                    for v in self.vertlist[posn]:
                        pv = self.dissverts2[posn][self.vertlist[posn].index(
                            v)]
                        rv = self.railverts2[posn][self.vertlist[posn].index(
                            v)]
                        sv = self.bmundo.verts[v.index]
                        vec = rv.co - sv.co
                        vec.length = abs(self.dist)
                        pv.co = sv.co + vec

            # create cap
            if not (self.capped):
                self.capsellist = []
                for posn in range(len(self.vertlist)):
                    if self.Both and self.Cap:
                        self.capped = True

                        def capendpoint(i):
                            self.capedges = []
                            es1 = None
                            es2 = None
                            vert = self.vertlist[posn][i]
                            for e in vert.link_edges:
                                v = e.other_vert(vert)
                                if not (v in self.vertlist[posn]) and not (
                                        v in self.dissverts1[posn]) and not (
                                            v in self.dissverts2[posn]):
                                    self.capedges.append(e)
                            if len(self.capedges) == 1:
                                e = self.capedges[0]
                                for f in e.link_faces:
                                    v2 = e.other_vert(vert)
                                    v2.select = True
                                    if self.dissverts1[posn][i] in f.verts:
                                        f1, l1 = bmesh.utils.face_split(
                                            f, v2, self.dissverts1[posn][i])
                                        if e in f.edges:
                                            fj1 = f
                                            fo1 = f1
                                        else:
                                            fj1 = f1
                                            fo1 = f
                                        for es in v2.link_edges:
                                            if es.other_vert(
                                                    v2
                                            ) == self.dissverts1[posn][i]:
                                                es.select = True
                                                es1 = es
                                    elif self.dissverts2[posn][i] in f.verts:
                                        f2, l1 = bmesh.utils.face_split(
                                            f, v2, self.dissverts2[posn][i])
                                        if e in f.edges:
                                            fj2 = f
                                            fo2 = f2
                                        else:
                                            fj2 = f2
                                            fo2 = f
                                        for es in v2.link_edges:
                                            if es.other_vert(
                                                    v2
                                            ) == self.dissverts2[posn][i]:
                                                es.select = True
                                                es2 = es
                                f3 = bmesh.utils.face_join((fj1, fj2))
                            if es1 == None:
                                self.caplist[posn].append(
                                    (None, None, None, None, None, None, None))
                            else:
                                self.caplist[posn].append(
                                    (es1, es2, vert, v2, f3, fo1, fo2))
                            self.capsellist.append(es1)
                            self.capsellist.append(es2)

                        self.caplist[posn] = []
                        capendpoint(0)
                        capendpoint(-1)
                self.mesh.calc_tessface()

            # select original verts/edges
            for posn in range(len(self.vertlist)):
                for edge in self.edgelist[posn]:
                    edge.select = True
                for vert in self.vertlist[posn]:
                    vert.select = True

        bmesh.update_edit_mesh(self.mesh, destructive=True)
        self.mesh.update()
예제 #39
0
    def uv_checkforerrors(self, context, node):
        if node.type == "MESH":
            if (node.data is not None):

                #os.system("cls")

                mesh = node.data

                bm = bmesh.from_edit_mesh(mesh)
                bm.select_mode = {"VERT"}
                #bm.select_mode = {"VERT"}
                bm.select_flush(False)
                uv_layer = bm.loops.layers.uv.active

                uv_errors = []

                for face in bm.faces:
                    for loop in face.loops:
                        vert = loop.vert
                        vert.select_set(False)
                        #loop.select(False)

                        #print("  Vert: (%f,%f,%f)" % vert.co[:])
                        uv_loop = loop[uv_layer]
                        uv = uv_loop.uv
                        #print("    UV: %f, %f" % uv[:])
                        ux = uv[0]
                        uy = uv[1]

                        for checkloop in face.loops:
                            if checkloop == loop:
                                break

                            vert2 = checkloop.vert
                            checkuv_loop = checkloop[uv_layer]
                            checkuv = checkuv_loop.uv

                            if self.uv_error(vert, vert2, uv, checkuv):
                                uv_error_entry = LLUVHelpers_TriangleError(
                                    vert, vert2, uv_loop, checkuv_loop)
                                uv_errors.append(uv_error_entry)

                total_errors = len(uv_errors)

                if total_errors > 0:
                    can_select = True
                    for uv_error in uv_errors:
                        print("[ERROR]: UV problem detected!")
                        print("  Vert1: (%f,%f,%f)" % uv_error.vert1.co[:])
                        print("  Vert2: (%f,%f,%f)" % uv_error.vert2.co[:])
                        print("  UV1: (%f,%f)" % uv_error.loop1.uv[:])
                        print("  UV2: (%f,%f)" % uv_error.loop2.uv[:])

                        if can_select:
                            uv_error.vert1.select_set(True)
                            uv_error.vert2.select_set(True)
                            uv_error.loop1.select = True
                            uv_error.loop2.select = True
                            if self.select_all == False:
                                can_select = False

                    self.report({
                        "WARNING"
                    }, "[LL-UV-Helper] {} total problems found on UV map. Check selected vertices for wrapping issues."
                                .format(total_errors))
                else:
                    self.report({"INFO"},
                                "[LL-UV-Helper] No UV problems found.")

                bm.select_flush(True)
                bmesh.update_edit_mesh(mesh)
예제 #40
0
    def execute(self, context):

        mortise_properties = context.scene.woodwork.mortise_properties
        thickness_properties = mortise_properties.thickness_properties
        height_properties = mortise_properties.height_properties

        obj = context.object
        matrix_world = obj.matrix_world
        mesh = obj.data

        if mesh.is_editmode:
            # Gain direct access to the mesh
            bm = bmesh.from_edit_mesh(mesh)
        else:
            # Create a bmesh from mesh
            # (won't affect mesh, unless explicitly written back)
            bm = bmesh.new()
            bm.from_mesh(mesh)

        # Get active face
        faces = bm.faces
        face = faces.active

        # Check if face could be transformed to mortise ...
        if not self.__check_face(face):
            return {'CANCELLED'}

        # Extract face infos
        face_to_be_transformed = FaceToBeTransformed(face)
        face_to_be_transformed.extract_features(matrix_world)

        # Init default values, look if face has changed too
        if (thickness_properties.value == -1.0
                or (not MathUtils.almost_equal_relative_or_absolute(
                    face_to_be_transformed.shortest_length,
                    self.shortest_length))):
            thickness_properties.value = \
                face_to_be_transformed.shortest_length / 3.0
            thickness_properties.percentage = 1.0 / 3.0
            thickness_properties.centered = True
        if (height_properties.value == -1.0 or
            (not MathUtils.almost_equal_relative_or_absolute(
                face_to_be_transformed.longest_length, self.longest_length))):
            height_properties.value = (face_to_be_transformed.longest_length *
                                       2.0) / 3.0
            height_properties.percentage = 2.0 / 3.0
            height_properties.centered = True
        if (mortise_properties.depth_value == -1.0 or
            (not MathUtils.almost_equal_relative_or_absolute(
                face_to_be_transformed.longest_length, self.longest_length))):
            mortise_properties.depth_value = \
                face_to_be_transformed.shortest_length

            haunch_properties = height_properties.haunch_first_side
            haunch_properties.depth_value = \
                mortise_properties.depth_value / 3.0
            haunch_properties.depth_percentage = 1.0 / 3.0
            haunch_properties = height_properties.haunch_second_side
            haunch_properties.depth_value = \
                mortise_properties.depth_value / 3.0
            haunch_properties.depth_percentage = 1.0 / 3.0

            haunch_properties = thickness_properties.haunch_first_side
            haunch_properties.depth_value = \
                mortise_properties.depth_value / 3.0
            haunch_properties.depth_percentage = 1.0 / 3.0
            haunch_properties = thickness_properties.haunch_second_side
            haunch_properties.depth_value = \
                mortise_properties.depth_value / 3.0
            haunch_properties.depth_percentage = 1.0 / 3.0

        # used to reinit default values when face changes
        self.shortest_length = face_to_be_transformed.shortest_length
        self.longest_length = face_to_be_transformed.longest_length

        # If percentage specified, compute length values
        if thickness_properties.type == "percentage":
            thickness_properties.value = \
                face_to_be_transformed.shortest_length * \
                thickness_properties.percentage

        if height_properties.type == "percentage":
            height_properties.value = face_to_be_transformed.longest_length * \
                height_properties.percentage

        # Init values linked to shoulder size
        if thickness_properties.centered:
            thickness_properties.shoulder_value = (
                (face_to_be_transformed.shortest_length -
                 thickness_properties.value) / 2.0)
            thickness_properties.shoulder_percentage = \
                thickness_properties.shoulder_value / \
                face_to_be_transformed.shortest_length
        if height_properties.centered:
            height_properties.shoulder_value = (
                (face_to_be_transformed.longest_length -
                 height_properties.value) / 2.0)
            height_properties.shoulder_percentage = \
                height_properties.shoulder_value / \
                face_to_be_transformed.longest_length

        # If shoulder percentage specified, compute length values
        if thickness_properties.shoulder_type == "percentage":
            thickness_properties.shoulder_value = \
                face_to_be_transformed.shortest_length * \
                thickness_properties.shoulder_percentage
            if thickness_properties.type != "max":
                if (thickness_properties.shoulder_value +
                        thickness_properties.value >
                        face_to_be_transformed.shortest_length):
                    thickness_properties.value = \
                        face_to_be_transformed.shortest_length - \
                        thickness_properties.shoulder_value
                    thickness_properties.percentage =\
                        thickness_properties.value / \
                        face_to_be_transformed.shortest_length

        if height_properties.shoulder_type == "percentage":
            height_properties.shoulder_value = \
                face_to_be_transformed.longest_length * \
                height_properties.shoulder_percentage
            if height_properties.type != "max":
                if (height_properties.shoulder_value + height_properties.value
                        > face_to_be_transformed.longest_length):
                    height_properties.value = \
                        face_to_be_transformed.longest_length - \
                        height_properties.shoulder_value
                    height_properties.percentage = \
                        height_properties.value / \
                        face_to_be_transformed.longest_length

        if height_properties.haunched_first_side:
            haunch_properties = height_properties.haunch_first_side
            if haunch_properties.type == "percentage":
                haunch_properties.depth_value = \
                    mortise_properties.depth_value * \
                    haunch_properties.depth_percentage

        if height_properties.haunched_second_side:
            haunch_properties = height_properties.haunch_second_side
            if haunch_properties.type == "percentage":
                haunch_properties.depth_value = \
                    mortise_properties.depth_value * \
                    haunch_properties.depth_percentage

        if thickness_properties.haunched_first_side:
            haunch_properties = thickness_properties.haunch_first_side
            if haunch_properties.type == "percentage":
                haunch_properties.depth_value = \
                    mortise_properties.depth_value * \
                    haunch_properties.depth_percentage

        if thickness_properties.haunched_second_side:
            haunch_properties = thickness_properties.haunch_second_side
            if haunch_properties.type == "percentage":
                haunch_properties.depth_value = \
                    mortise_properties.depth_value * \
                    haunch_properties.depth_percentage

        # Check input values
        if height_properties.type != "max":
            total_length = height_properties.shoulder_value + \
                height_properties.value
        elif height_properties.centered:
            total_length = face_to_be_transformed.longest_length
        else:
            total_length = height_properties.shoulder_value

        if ((not MathUtils.almost_equal_relative_or_absolute(
                total_length, face_to_be_transformed.longest_length))
                and (total_length > face_to_be_transformed.longest_length)):
            self.report({'ERROR_INVALID_INPUT'},
                        "Size of length size shoulder and mortise height are "
                        "too long.")
            return {'CANCELLED'}

        if thickness_properties.type != "max":
            total_length = thickness_properties.shoulder_value + \
                thickness_properties.value
        elif thickness_properties.centered:
            total_length = face_to_be_transformed.shortest_length
        else:
            total_length = thickness_properties.shoulder_value

        if ((not MathUtils.almost_equal_relative_or_absolute(
                total_length, face_to_be_transformed.shortest_length))
                and (total_length > face_to_be_transformed.shortest_length)):
            self.report(
                {'ERROR_INVALID_INPUT'},
                "Size of width size shoulder and mortise thickness are "
                "too long.")
            return {'CANCELLED'}

        # Create mortise
        builder_properties = \
            MortiseOperator.__mortise_properties_to_builder_properties(
                mortise_properties)
        mortise_builder = TenonMortiseBuilder(builder_properties)
        mortise_builder.create(bm, matrix_world, face_to_be_transformed)

        # Flush selection
        bm.select_flush_mode()

        if mesh.is_editmode:
            bmesh.update_edit_mesh(mesh)
        else:
            bm.to_mesh(mesh)
            mesh.update()

        return {'FINISHED'}
예제 #41
0
def Duplicate(self, context, act_obj):
	"""Create 2 copy selection. the firs orygnal posisiton. the second modifi"""
	main_select_obj = bpy.context.selected_objects
	object_B = firstD(context)
	print(object_B)
	bm = bmesh.from_edit_mesh(act_obj.data)
	face = [f for f in bm.faces if f.select]  # get select faces
	angle = 0.0
	save_pos = {}
	distance = -0.000002
	for i in face:#?? ??????
		for edge in i.edges:# ?? ?????? ??? ?????
			angle = edge.calc_face_angle_signed()# ??????? ????
			angle = degrees(angle)# ????????? ???? ? ???????????? ???
			if angle > 89.99:# ???? 90 ????????1
				vert1, vert2 = edge.verts# ??????? ??????? ???? ????????
				if not vert1.index in save_pos:
					save_pos[vert1.index] = vert1.co.copy()
				if not vert2.index in save_pos:
					save_pos[vert2.index] = vert2.co.copy()

				# ??????? ???? ?????, ??? ?????? ??????? ?????, ???? ????? ???? ??? ??? ??????
				link1 = vert1.link_edges
				link2  = vert2.link_edges
				for l in link1:
					for e in i.edges:
						if l == e and not l == edge:
							V1, V2 = l.verts
							vec = V2.co
							#if V1 == vert1:
							vec = V2.co - V1.co
							if V2 == vert1:
								vec = V1.co - V2.co
							vec.normalize()
							vert1.co += vec * distance
				for l in link2:
					for e in i.edges:
						if l == e and not l == edge:
							V1, V2 = l.verts
							vec = V2.co
							if V1 == vert2:
								vec = V2.co - V1.co
							if V2 == vert2:
								vec = V1.co - V2.co
							vec.normalize()
							vert2.co += vec * distance

	bpy.ops.mesh.duplicate_move(MESH_OT_duplicate={"mode": 1})

	bm.verts.ensure_lookup_table()
	for key, value in save_pos.items():
		bm.verts[key].co = value

	bmesh.update_edit_mesh(act_obj.data)
	bm.free()

	bpy.ops.mesh.separate(type='SELECTED')
	bpy.ops.object.mode_set(mode='OBJECT')

	sel_obj = bpy.context.selected_objects
	object_C = None
	object_C_Name = None
	for i in sel_obj:
		object_C_Name = i.name
		object_C = i
		break

	for i in main_select_obj:
		i.select = True
	print(object_B)
	print(object_C)

	return object_B, object_C
예제 #42
0
    def modal(self, context, event):
        if self.confirm:
            sface = self.bm.faces.active
            if not sface:
                for face in self.bm.faces:
                    if face.select is True:
                        sface = face
                        break
                else:
                    return {'FINISHED'}
            # edges to intersect
            edges = set()
            [[edges.add(ed) for ed in v.link_edges] for v in sface.verts]

            overlap = edges_BVH_overlap(self.bm, edges, epsilon=0.0001)
            overlap = {k: v
                       for k, v in overlap.items()
                       if k not in edges}  # remove repetition
            """
            print([e.index for e in edges])
            for a, b in overlap.items():
                print(a.index, [e.index for e in b])
            """
            new_edges1, new_edges2, targetmap = intersect_edges_edges(overlap)
            pos_weld = set()
            for e in new_edges1:
                v1, v2 = e.verts
                if v1 in targetmap and v2 in targetmap:
                    pos_weld.add((targetmap[v1], targetmap[v2]))
            if targetmap:
                bmesh.ops.weld_verts(self.bm, targetmap=targetmap)
            """
            print([e.is_valid for e in new_edges1])
            print([e.is_valid for e in new_edges2])
            sp_faces1 = set()
            """
            for e in pos_weld:
                v1, v2 = e
                lf1 = set(v1.link_faces)
                lf2 = set(v2.link_faces)
                rlfe = lf1.intersection(lf2)
                for f in rlfe:
                    try:
                        nf = bmesh.utils.face_split(f, v1, v2)
                        # sp_faces1.update({f, nf[0]})
                    except:
                        pass

            # sp_faces2 = set()
            for e in new_edges2:
                lfe = set(e.link_faces)
                v1, v2 = e.verts
                lf1 = set(v1.link_faces)
                lf2 = set(v2.link_faces)
                rlfe = lf1.intersection(lf2)
                for f in rlfe.difference(lfe):
                    nf = bmesh.utils.face_split(f, v1, v2)
                    # sp_faces2.update({f, nf[0]})

            bmesh.update_edit_mesh(self.mesh, tessface=True, destructive=True)
            return {'FINISHED'}
        if self.cancel:
            return {'FINISHED'}
        self.cancel = event.type in {'ESC', 'NDOF_BUTTON_ESC'}
        self.confirm = event.type in {'LEFTMOUSE', 'RET', 'NUMPAD_ENTER'}
        return {'PASS_THROUGH'}
예제 #43
0
    def invoke(self, context, event):
        reset_params(self)

        if context.area.type == 'VIEW_3D':
            # the arguments we pass the the callbackection
            args = (self, context)
            # Add the region OpenGL drawing callback
            # draw in view space with 'POST_VIEW' and 'PRE_VIEW'

            cur_stretch_settings = context.scene.mi_cur_stretch_settings
            curve_settings = context.scene.mi_settings

            active_obj = context.scene.objects.active
            bm = bmesh.from_edit_mesh(active_obj.data)

            # get loops
            self.loops = loop_t.get_connected_input(bm)
            self.loops = loop_t.check_loops(self.loops, bm)

            if self.loops:
                self.manipulator = context.space_data.show_manipulator
                context.space_data.show_manipulator = False


                for loop in self.loops:
                    loop_verts = [active_obj.matrix_world * bm.verts[i].co for i in loop[0]]
                    loop_line = cur_main.pass_line(loop_verts, loop[1])
                    new_curve = cur_main.create_curve_to_line(cur_stretch_settings.points_number, loop_line, self.all_curves, loop[1])

                    # set closed curve
                    if loop[1] is True:
                        new_curve.closed = True

                    self.all_curves.append(new_curve)
                    self.active_curve = new_curve

                    cur_main.generate_bezier_points(self.active_curve, self.active_curve.display_bezier, curve_settings.curve_resolution)

                    self.original_verts_data.append( cur_main.pass_line([bm.verts[i].co.copy() for i in loop[0]] , loop[1]) )

                    # move point to the curve
                    for curve in self.all_curves:
                        update_curve_line(active_obj, curve, self.loops, self.all_curves, bm, curve_settings.spread_mode, self.original_verts_data[self.all_curves.index(curve)])

                    # get meshes for snapping
                    if curve_settings.surface_snap is True:
                        meshes_array = ut_base.get_obj_dup_meshes(curve_settings.snap_objects, curve_settings.convert_instances, context)
                        if meshes_array:
                            self.picked_meshes = meshes_array

                self.mi_deform_handle_3d = bpy.types.SpaceView3D.draw_handler_add(mi_curve_draw_3d, args, 'WINDOW', 'POST_VIEW')
                self.mi_deform_handle_2d = bpy.types.SpaceView3D.draw_handler_add(mi_curve_draw_2d, args, 'WINDOW', 'POST_PIXEL')
                self.gh_circle_select_handle = bpy.types.SpaceView3D.draw_handler_add(gh_circle_draw_2d, args, 'WINDOW', 'POST_PIXEL')
                context.window_manager.modal_handler_add(self)

                bm.normal_update()
                bmesh.update_edit_mesh(active_obj.data)

                return {'RUNNING_MODAL'}
            else:
                #finish_work(self, context)
                self.report({'WARNING'}, "No loops found!")
                return {'CANCELLED'}
        else:
            #finish_work(self, context)
            self.report({'WARNING'}, "View3D not found, cannot run operator!")
            return {'CANCELLED'}
예제 #44
0
    def uv_checkforerrors_v2(self, context, node):
        if node.type == "MESH":
            if (node.data is not None):

                preferences = leader.get_preferences(context)
                if preferences is not None:
                    select_mode = preferences.uvhelpers_errorchecker_select_mode
                else:
                    select_mode = "VERTEX"

                if select_mode == "FACE":
                    bpy.context.tool_settings.mesh_select_mode = (False, False,
                                                                  True)
                elif select_mode == "EDGE":
                    bpy.context.tool_settings.mesh_select_mode = (False, True,
                                                                  False)
                else:
                    bpy.context.tool_settings.mesh_select_mode = (True, False,
                                                                  False)
                #py.context.tool_settings.mesh_select_mode = (False, False, True)

                mesh = node.data

                bm = bmesh.from_edit_mesh(mesh)
                bm.select_flush(False)
                uv_layer = bm.loops.layers.uv.active

                uv_errors = []

                for face in bm.faces:
                    if face in uv_errors:
                        continue

                    face.select = False

                    if (len(face.loops) == 3):
                        vloop1 = face.loops[0]
                        vloop2 = face.loops[1]
                        vloop3 = face.loops[2]

                        vert1 = vloop1.vert
                        vert2 = vloop2.vert
                        vert3 = vloop3.vert

                        vert1.select_set(False)
                        vert2.select_set(False)
                        vert3.select_set(False)

                        uvloop1 = vloop1[uv_layer]
                        uvloop2 = vloop2[uv_layer]
                        uvloop3 = vloop3[uv_layer]

                        uv1 = uvloop1.uv
                        uv2 = uvloop2.uv
                        uv3 = uvloop3.uv

                        #uv1 = vert1.co.xy
                        #uv2 = vert2.co.xy
                        #uv3 = vert3.co.xy

                        if self.uv_error_v2(uv1, uv2, uv3):
                            uv_error_entry = LLUVHelpers_TriangleErrorv2(
                                face, vert1, vert2, vert3, uvloop1, uvloop2,
                                uvloop3)
                            uv_errors.append(uv_error_entry)

                total_errors = len(uv_errors)
                if total_errors > 0:
                    can_select = True
                    select_all = preferences is not None and preferences.uvhelpers_errorchecker_select_all is True
                    for uv_error in uv_errors:
                        print("[ERROR]: UV problem detected!")
                        print("  Vert1: (%f,%f,%f)" % uv_error.vert1.co[:])
                        print("  Vert2: (%f,%f,%f)" % uv_error.vert2.co[:])
                        print("  Vert3: (%f,%f,%f)" % uv_error.vert3.co[:])
                        print("  UV1: (%f,%f)" % uv_error.loop1.uv[:])
                        print("  UV2: (%f,%f)" % uv_error.loop2.uv[:])
                        print("  UV3: (%f,%f)" % uv_error.loop3.uv[:])

                        if can_select:
                            uv_error.vert1.select_set(True)
                            uv_error.vert2.select_set(True)
                            uv_error.vert3.select_set(True)
                            uv_error.loop1.select = True
                            uv_error.loop2.select = True
                            uv_error.loop3.select = True
                            if select_all == False:
                                can_select = False
                                break

                    self.report({
                        "WARNING"
                    }, "[LL-UV-Helper] {} total problems found on UV map. Check selected vertices for wrapping issues."
                                .format(total_errors))
                else:
                    self.report({"INFO"},
                                "[LL-UV-Helper] No UV problems found.")

                #total_errors.clear()

                bm.select_flush(True)
                bmesh.update_edit_mesh(mesh)
    def execute(self, context):
        mesh = context.object.data
        if not mesh.is_editmode:
            self.report({'INFO'}, 'Must be in edit mode')
            return {'CANCELLED'}        

        bm = bmesh.from_edit_mesh(mesh)
        
        bm = bmesh.from_edit_mesh(mesh)
        bm.faces.ensure_lookup_table()
        uv_layer = bm.loops.layers.uv[0]
        
        for face in bm.faces:
            if not face.select:
                continue
            
            center = face.calc_center_median()
            loops = face.loops
        
            # find the bottom two verticies
            nLoops = len(loops)
            firstBottomLoop = 0
            bottomValue = loopSortValue(loops, 0)
            for li in range(nLoops):
                testValue = loopSortValue(loops, li)
                if testValue < bottomValue:
                    bottomValue = testValue
                    firstBottomLoop = li
        
            # the "x-axis" is the bottom verticies vector
            secondBottomLoop = firstBottomLoop + 1
            if secondBottomLoop == len(loops):
                secondBottomLoop = 0
            x = loops[secondBottomLoop].vert.co - loops[firstBottomLoop].vert.co
            x.normalize()
        
            # get the "y-axis" from the bottom verticies vector
            y = x.cross(face.normal)
            y.normalize()
            y.negate()
        
            # find texture scale and center of current UV screen area
            offset = [0.5, 0.5]
            scale = self.pixelSize / 128.0
            roundSize = 128
            for area in bpy.context.screen.areas :
                if area.type == 'IMAGE_EDITOR':
                    currentTexture = area.spaces.active.image
                    scale = self.pixelSize / currentTexture.size[1]
                    roundSize = currentTexture.size[1]
                    for region in area.regions:
                        if region.type == 'WINDOW':
                            offset = region.view2d.region_to_view(region.width / 2, region.height / 2)
        
            # calculate UVs
            for li in range(nLoops):
                loop = loops[li]
                d = loop.vert.co - center
                u = min(max(round(d.dot(x) * 100), -1), 1) * scale / 2 + offset[0]
                v = min(max(round(d.dot(y) * 100), -1), 1) * scale / 2 + offset[1]
                uv =   (round(u * roundSize) / roundSize,
                        round(v * roundSize) / roundSize)
                loop[uv_layer].uv = uv       
            
            bmesh.update_edit_mesh(mesh, True)
            
        return {'FINISHED'}
예제 #46
0
    def execute(self, ops_obj, context):
        # Note: the current system only works if the
        # f[tex_layer].image doesn't return None
        # which will happen in certain cases
        obj = context.active_object
        bm = bmesh.from_edit_mesh(obj.data)

        if common.check_version(2, 73, 0) >= 0:
            bm.faces.ensure_lookup_table()

        if not bm.loops.layers.uv:
            ops_obj.report({'WARNING'},
                           "Object must have more than one UV map")
            return {'CANCELLED'}

        uv_layer = bm.loops.layers.uv.verify()
        tex_layer = bm.faces.layers.tex.verify()

        sel_faces = [f for f in bm.faces if f.select]
        dest_img = bpy.data.images[ops_obj.dest_img_name]

        info = {}

        for f in sel_faces:
            if not f[tex_layer].image in info.keys():
                info[f[tex_layer].image] = {}
                info[f[tex_layer].image]['faces'] = []
            info[f[tex_layer].image]['faces'].append(f)

        for img in info:
            if img is None:
                continue

            src_img = img
            ratio = Vector((dest_img.size[0] / src_img.size[0],
                            dest_img.size[1] / src_img.size[1]))

            if ops_obj.origin == 'CENTER':
                origin = Vector((0.0, 0.0))
                num = 0
                for f in info[img]['faces']:
                    for l in f.loops:
                        uv = l[uv_layer].uv
                        origin = origin + uv
                        num = num + 1
                origin = origin / num
            elif ops_obj.origin == 'LEFT_TOP':
                origin = Vector((100000.0, -100000.0))
                for f in info[img]['faces']:
                    for l in f.loops:
                        uv = l[uv_layer].uv
                        origin.x = min(origin.x, uv.x)
                        origin.y = max(origin.y, uv.y)
            elif ops_obj.origin == 'LEFT_CENTER':
                origin = Vector((100000.0, 0.0))
                num = 0
                for f in info[img]['faces']:
                    for l in f.loops:
                        uv = l[uv_layer].uv
                        origin.x = min(origin.x, uv.x)
                        origin.y = origin.y + uv.y
                        num = num + 1
                origin.y = origin.y / num
            elif ops_obj.origin == 'LEFT_BOTTOM':
                origin = Vector((100000.0, 100000.0))
                for f in info[img]['faces']:
                    for l in f.loops:
                        uv = l[uv_layer].uv
                        origin.x = min(origin.x, uv.x)
                        origin.y = min(origin.y, uv.y)
            elif ops_obj.origin == 'CENTER_TOP':
                origin = Vector((0.0, -100000.0))
                num = 0
                for f in info[img]['faces']:
                    for l in f.loops:
                        uv = l[uv_layer].uv
                        origin.x = origin.x + uv.x
                        origin.y = max(origin.y, uv.y)
                        num = num + 1
                origin.x = origin.x / num
            elif ops_obj.origin == 'CENTER_BOTTOM':
                origin = Vector((0.0, 100000.0))
                num = 0
                for f in info[img]['faces']:
                    for l in f.loops:
                        uv = l[uv_layer].uv
                        origin.x = origin.x + uv.x
                        origin.y = min(origin.y, uv.y)
                        num = num + 1
                origin.x = origin.x / num
            elif ops_obj.origin == 'RIGHT_TOP':
                origin = Vector((-100000.0, -100000.0))
                for f in info[img]['faces']:
                    for l in f.loops:
                        uv = l[uv_layer].uv
                        origin.x = max(origin.x, uv.x)
                        origin.y = max(origin.y, uv.y)
            elif ops_obj.origin == 'RIGHT_CENTER':
                origin = Vector((-100000.0, 0.0))
                num = 0
                for f in info[img]['faces']:
                    for l in f.loops:
                        uv = l[uv_layer].uv
                        origin.x = max(origin.x, uv.x)
                        origin.y = origin.y + uv.y
                        num = num + 1
                origin.y = origin.y / num
            elif ops_obj.origin == 'RIGHT_BOTTOM':
                origin = Vector((-100000.0, 100000.0))
                for f in info[img]['faces']:
                    for l in f.loops:
                        uv = l[uv_layer].uv
                        origin.x = max(origin.x, uv.x)
                        origin.y = min(origin.y, uv.y)

            info[img]['ratio'] = ratio
            info[img]['origin'] = origin

        for img in info:
            if img is None:
                continue

            for f in info[img]['faces']:
                f[tex_layer].image = dest_img
                for l in f.loops:
                    uv = l[uv_layer].uv
                    origin = info[img]['origin']
                    ratio = info[img]['ratio']
                    diff = uv - origin
                    diff.x = diff.x / ratio.x
                    diff.y = diff.y / ratio.y
                    uv.x = origin.x + diff.x
                    uv.y = origin.y + diff.y
                    l[uv_layer].uv = uv

        bmesh.update_edit_mesh(obj.data)

        return {'FINISHED'}
예제 #47
0
def edgeMerger():

    # Lets start gathering the stuff we will use later
    ob = bpy.context.selected_objects[0]
    obData = ob.data
    print(_warnMsg[3] % str(len(obData.polygons)))
    global _mergeAgain, _mergeAgainCount
    _mergeAgain = False

    # Lets just make sure we are in edit mode before we begin
    if (ob.mode != 'EDIT'):
        bpy.ops.object.mode_set(mode='EDIT', toggle=False)
        showme(_apply)

    # Runs only the first time the script start
    if _mergeAgainCount == 0:
        # clean slate, deselect anything and show everything
        bpy.ops.mesh.reveal()
        bpy.ops.mesh.select_all(action='DESELECT')
        showme(_apply)
    _mergeAgainCount += 1

    # We are ready to begin the actual mesh editing
    # Documentation recomends that for any nitty gritty operations
    # We use Bmesh
    bm = bmesh.new()
    bm = bmesh.from_edit_mesh(obData)
    print(_warnMsg[4] % str(len(bm.faces)))
    showme(_apply)
    findingDoubles = []

    # Store a verts dict for referece
    edge_medians = {}

    # Loop over edges
    #for edg_pos,edge in enumerate(bm.edges):
    for edg_pos, edge in enumerate(bm.edges):
        #print("Edge %s in pos: %s" % (str(edge.index), str(edg_pos)))
        this_edge_median = median_get(edge.verts)
        edge_medians[str(edge.index)] = this_edge_median
        bm.edges.ensure_lookup_table()
        bm.verts.ensure_lookup_table()

        # Try to find identical edge medians from different edges
        for i, em in edge_medians.items():
            #print([em, i, this_edge_median] )

            # If this Edge's Median is equal to any other Median except itself
            if em == this_edge_median and (str(i) != str(edge.index)):
                #print("Edge %s matches %s " % (str(i) ,str(edge.index)))
                edge.select = True

                # TODO: Include some math from the custom normals to help decide if welded edges
                # should be smooth[True False]
                # Lets get some math on the normals
                # having two edges, treat common vertex as individual
                # option 1
                # ((e1v1 + e1v2)/2)-e1
                # option 2
                # e1v1.angle(e1v2) + e2v1.angle(e2v2)
                '''
        print ([
        edge.verts[0].normal.angle(Vector([0,0,1])),edge.verts[1].normal.angle(Vector([0,0,1])),
        bm.edges[int(i)].verts[0].normal.angle(Vector([0,0,1])),bm.edges[int(i)].verts[1].normal.angle(Vector([0,0,1]))
        ])
        '''

                # These lists will hold the welding params
                vert_keeper = []
                vert_welder = []

                # Loop over verts in the matched edge
                for vert in edge.verts:
                    if vert not in vert_welder:
                        vert_welder.append(vert)

                # Loop over verts in the matching edge
                # TODO: Is there a reason to maybe revert matching and matched?
                # bottom edge being in matched in matcher allows edge welding stacks
                for vert in bm.edges[int(i)].verts:
                    if vert not in vert_welder:
                        vert_welder.append(vert)
                    if vert not in vert_keeper:
                        vert_keeper.append(vert)

                # Build a tracemap list of verts to merge thru weld
                findingDoubles.append(
                    bmesh.ops.find_doubles(bm,
                                           verts=vert_welder,
                                           keep_verts=vert_keeper,
                                           dist=0.0001))

    # Use core operator weld_verts, cause all the cool kids use it
    if len(findingDoubles):
        for fd in findingDoubles:
            for fd_vm, fd_vk in fd["targetmap"].items():
                if fd_vm.is_valid and fd_vk.is_valid:
                    bmesh.ops.weld_verts(bm, targetmap={fd_vm: fd_vk})
                # Dead vertices in targetmap mean a merge didn't take place, set to try again
                else:
                    _mergeAgain = True

    # return all changes to the actual mesh
    bmesh.update_edit_mesh(ob.data, loop_triangles=True, destructive=True)
    ob.data.calc_loop_triangles()
    showme(_apply)
    return
예제 #48
0
    def modal(self, context, event):
        context.area.tag_redraw()

        context.area.header_text_set("NewPoint: Ctrl+Click, SelectAdditive: Shift+Click, DeletePoint: Del, SurfaceSnap: Shift+Tab, SelectLinked: L/Shift+L, SpreadMode: M, CircleSelect: C, BoxSelect: B")

        user_preferences = context.user_preferences
        addon_prefs = user_preferences.addons[__package__].preferences
        curve_settings = context.scene.mi_settings
        cur_stretch_settings = context.scene.mi_cur_stretch_settings

        active_obj = context.scene.objects.active
        bm = bmesh.from_edit_mesh(active_obj.data)

        region = context.region
        rv3d = context.region_data
        m_coords = event.mouse_region_x, event.mouse_region_y
        self.select_coords = m_coords

        keys_pass = mi_inputs.get_input_pass(mi_inputs.pass_keys, addon_prefs.key_inputs, event)

        # make picking
        if self.curve_tool_mode == 'IDLE' and event.value == 'PRESS' and keys_pass is False:
            if event.type in {'LEFTMOUSE', 'SELECTMOUSE'}:
                # pick point test
                picked_point, picked_length, picked_curve = cur_main.pick_all_curves_point(self.all_curves, context, m_coords)
                if picked_point:
                    self.deform_mouse_pos = m_coords
                    self.active_curve = picked_curve
                    self.active_curve.active_point = picked_point.point_id
                    additive_sel = event.shift

                    if additive_sel is False and picked_point.select is False:
                        for curve in self.all_curves:
                            if curve is not self.active_curve:
                                cur_main.select_all_points(curve.curve_points, False)  # deselect points
                                curve.active_point = None

                    cur_main.select_point(self.active_curve, picked_point, additive_sel)

                    self.curve_tool_mode = 'SELECT_POINT'
                else:
                    # add point
                    if event.ctrl and self.active_curve and self.active_curve.active_point:
                        act_point = cur_main.get_point_by_id(self.active_curve.curve_points, self.active_curve.active_point)
                        new_point_pos = ut_base.get_mouse_on_plane(context, act_point.position, None, m_coords)

                        if new_point_pos:
                            for curve in self.all_curves:
                                if curve is not self.active_curve:
                                    cur_main.select_all_points(curve.curve_points, False)  # deselect points
                                    curve.active_point = None

                            new_point = cur_main.add_point(new_point_pos, self.active_curve)

                            self.active_curve.active_point = new_point.point_id
                            self.curve_tool_mode = 'MOVE_POINT'

                            # add to display
                            cur_main.curve_point_changed(self.active_curve, self.active_curve.curve_points.index(new_point), curve_settings.curve_resolution, self.active_curve.display_bezier)

                #return {'RUNNING_MODAL'}

            elif event.type in {'DEL'}:
                for curve in self.all_curves:
                    sel_points = cur_main.get_selected_points(curve.curve_points)
                    if sel_points:
                        for point in sel_points:
                            #the_act_point = cur_main.get_point_by_id(self.active_curve.curve_points, self.active_curve.active_point)
                            #the_act_point_index = self.active_curve.curve_points.index(point)

                            if len(curve.curve_points) > 2:
                                cur_main.delete_point(point, curve, curve.display_bezier, curve_settings.curve_resolution)
                            else:
                                point.select = False

                        curve.display_bezier.clear()
                        cur_main.generate_bezier_points(curve, curve.display_bezier, curve_settings.curve_resolution)
                        curve.active_point = None

                        # move point to the curve
                        update_curve_line(active_obj, curve, self.loops, self.all_curves, bm, curve_settings.spread_mode, self.original_verts_data[self.all_curves.index(curve)])

                    bm.normal_update()
                    bmesh.update_edit_mesh(active_obj.data)

            elif event.type in {'TAB'} and event.shift:
                if curve_settings.surface_snap is True:
                    curve_settings.surface_snap = False
                else:
                    curve_settings.surface_snap = True
                    if not self.picked_meshes:
                        # get meshes for snapping
                        meshes_array = ut_base.get_obj_dup_meshes(curve_settings.snap_objects, curve_settings.convert_instances, context)
                        if meshes_array:
                            self.picked_meshes = meshes_array

            # Select Linked
            elif event.type == 'L':
                picked_point, picked_length, picked_curve = cur_main.pick_all_curves_point(self.all_curves, context, m_coords)

                if picked_point:
                    if not event.shift:
                        for curve in self.all_curves:
                            if curve is not picked_curve:
                                cur_main.select_all_points(curve.curve_points, False)
                                curve.active_point = None

                    cur_main.select_all_points(picked_curve.curve_points, True)
                    picked_curve.active_point = picked_point.point_id
                    self.active_curve = picked_curve

            # Change Spread Type
            elif event.type == 'M':
                if curve_settings.spread_mode == 'Original':
                    curve_settings.spread_mode = 'Uniform'
                else:
                    curve_settings.spread_mode = 'Original'

                for curve in self.all_curves:
                    update_curve_line(active_obj, curve, self.loops, self.all_curves, bm, curve_settings.spread_mode, self.original_verts_data[self.all_curves.index(curve)])

                # update mesh
                bm.normal_update()
                bmesh.update_edit_mesh(active_obj.data)

            # Set to Select Multy
            elif event.type == 'C':
                self.curve_tool_mode = 'SELECT_MULTI'
                self.curve_tool_mult_mode = 'CIRCLE'

            elif event.type == 'B':
                self.curve_tool_mode = 'SELECT_MULTI'
                self.curve_tool_mult_mode = 'BOX'

        elif self.curve_tool_mode == 'SELECT_MULTI':
            # Switch Selection tool off
            if event.value == 'PRESS':
                if self.curve_tool_mult_mode == 'CIRCLE' and event.type == 'C':
                    self.curve_tool_mode = 'IDLE'
                    self.mouse_down = False
                    self.mmouse_down = False
                    return {'RUNNING_MODAL'}

                if self.curve_tool_mult_mode == 'BOX' and event.type == 'B':
                    self.curve_tool_mode = 'IDLE'
                    self.mouse_down = False
                    self.mmouse_down = False
                    return {'RUNNING_MODAL'}

        # TOOLS WORK
        if self.curve_tool_mode == 'SELECT_POINT':
            if event.type in {'LEFTMOUSE', 'SELECTMOUSE'} and event.value == 'RELEASE':
                self.curve_tool_mode = 'IDLE'
                return {'RUNNING_MODAL'}
            else:
                # set to move point
                if ( Vector((m_coords[0], m_coords[1])) - Vector((self.deform_mouse_pos[0], self.deform_mouse_pos[1])) ).length > 4.0:
                    self.curve_tool_mode = 'MOVE_POINT'
                    return {'RUNNING_MODAL'}

        elif self.curve_tool_mode == 'MOVE_POINT':
            if event.type in {'LEFTMOUSE', 'SELECTMOUSE'} and event.value == 'RELEASE':

                # Snap to Surface
                if curve_settings.surface_snap is True and self.picked_meshes:
                    for curve in self.all_curves:
                        selected_points = cur_main.get_selected_points(curve.curve_points)
                        if selected_points:
                            cur_main.snap_to_surface(context, selected_points, self.picked_meshes, region, rv3d, None)

                            if len(selected_points) == 1:
                                cur_main.curve_point_changed(curve, curve.curve_points.index(selected_points[0]), curve_settings.curve_resolution, curve.display_bezier)
                            else:
                                cur_main.generate_bezier_points(curve, curve.display_bezier, curve_settings.curve_resolution)

                # move point to the curve
                for curve in self.all_curves:
                    selected_points = cur_main.get_selected_points(curve.curve_points)
                    if selected_points:
                        update_curve_line(active_obj, curve, self.loops, self.all_curves, bm, curve_settings.spread_mode, self.original_verts_data[self.all_curves.index(curve)])

                bm.normal_update()
                bmesh.update_edit_mesh(active_obj.data)

                self.curve_tool_mode = 'IDLE'
                return {'RUNNING_MODAL'}
            else:
                # move points
                act_point = cur_main.get_point_by_id(self.active_curve.curve_points, self.active_curve.active_point)
                new_point_pos = ut_base.get_mouse_on_plane(context, act_point.position, None, m_coords)

                if new_point_pos:
                    move_offset = new_point_pos - act_point.position
                    camera_dir = (rv3d.view_rotation * Vector((0.0, 0.0, -1.0))).normalized()

                    for curve in self.all_curves:
                        selected_points = cur_main.get_selected_points(curve.curve_points)
                        if selected_points:
                            # Move Points without Snapping
                            for point in selected_points:
                                point.position += move_offset

                            if len(selected_points) == 1:
                                cur_main.curve_point_changed(curve, curve.curve_points.index(selected_points[0]), curve_settings.curve_resolution, curve.display_bezier)
                            else:
                                cur_main.generate_bezier_points(curve, curve.display_bezier, curve_settings.curve_resolution)

                return {'RUNNING_MODAL'}

        elif self.curve_tool_mode == 'SELECT_MULTI':

            # first check
            if self.curve_tool_mult_mode == 'CIRCLE':
                if event.type == 'WHEELDOWNMOUSE':
                    self.select_radius *= 1.2

                elif event.type == 'WHEELUPMOUSE':
                    self.select_radius /= 1.2
                    if self.select_radius < 4:
                        self.select_radius = 4

            # second check
            if event.type in {'LEFTMOUSE', 'SELECTMOUSE'} and event.value == 'PRESS':
                self.mouse_down = True
                if self.curve_tool_mult_mode == 'CIRCLE':
                    pts, lns, crvs = cur_main.pick_all_curves_points_radius(self.all_curves, context, m_coords, self.select_radius)
                    cur_main.select_point_multi(self.all_curves, pts, True)
                if self.curve_tool_mult_mode == 'BOX':
                    self.select_box_anchor = m_coords

            if event.type in {'LEFTMOUSE', 'SELECTMOUSE'} and event.value == 'RELEASE':
                self.mouse_down = False
                if self.curve_tool_mult_mode == 'BOX':
                    pts, crvs = cur_main.pick_all_curves_points_box(self.all_curves, context, m_coords, self.select_box_anchor)
                    cur_main.select_point_multi(self.all_curves, pts, True)

            if event.type in {'MIDDLEMOUSE'} and event.value == 'PRESS':
                self.mmouse_down = True
                if self.curve_tool_mult_mode == 'CIRCLE':
                    pts, lns, crvs = cur_main.pick_all_curves_points_radius(self.all_curves, context, m_coords, self.select_radius)
                    cur_main.select_point_multi(self.all_curves, pts, False)
                if self.curve_tool_mult_mode == 'BOX':
                    self.select_box_anchor = m_coords

            if event.type in {'MIDDLEMOUSE'} and event.value == 'RELEASE':
                self.mmouse_down = False
                if self.curve_tool_mult_mode == 'BOX':
                    pts, crvs = cur_main.pick_all_curves_points_box(self.all_curves, context, m_coords, self.select_box_anchor)
                    cur_main.select_point_multi(self.all_curves, pts, False)

            if event.type in {'RIGHTMOUSE', 'ESC'} and event.value == 'RELEASE':
                self.curve_tool_mode = 'IDLE'
                return {'RUNNING_MODAL'}

            if event.type in {'MOUSEMOVE'}:
                if not self.mouse_down and not self.mmouse_down:
                    return {'PASS_THROUGH'}
                elif self.mouse_down:
                    if self.curve_tool_mult_mode == 'CIRCLE':
                        pts, lns, crvs = cur_main.pick_all_curves_points_radius(self.all_curves, context, m_coords, self.select_radius)
                        cur_main.select_point_multi(self.all_curves,pts, True)

                elif self.mmouse_down:
                    if self.curve_tool_mult_mode == 'CIRCLE':
                        pts, lns, crvs = cur_main.pick_all_curves_points_radius(self.all_curves, context, m_coords, self.select_radius)
                        cur_main.select_point_multi(self.all_curves, pts, False)

            return {'RUNNING_MODAL'}

        else:
            if event.value == 'RELEASE' and event.type in {'LEFTMOUSE', 'SELECTMOUSE'}:
                self.curve_tool_mode = 'IDLE'
                return {'RUNNING_MODAL'}


        # get keys
        if keys_pass is True:
            # allow navigation
            return {'PASS_THROUGH'}

        elif event.type in {'RIGHTMOUSE', 'ESC'}:
            bpy.types.SpaceView3D.draw_handler_remove(self.mi_deform_handle_3d, 'WINDOW')
            bpy.types.SpaceView3D.draw_handler_remove(self.mi_deform_handle_2d, 'WINDOW')
            bpy.types.SpaceView3D.draw_handler_remove(self.gh_circle_select_handle, 'WINDOW')

            finish_work(self, context)

            context.area.header_text_set()

            return {'FINISHED'}

        return {'RUNNING_MODAL'}
예제 #49
0
 def execute(self, context):
     active_obj = context.scene.objects.active
     active_mesh = active_obj.data
     #if WPLSMTHDEF_G.mesh_name != active_obj.name:
     if (active_mesh.uv_textures.get(kWPLSmoothHolderUVMap1) is None) or (
             active_mesh.uv_textures.get(kWPLSmoothHolderUVMap2) is None):
         self.report({'ERROR'}, "No interpolate, save mesh state first!")
         return {'FINISHED'}
     selverts = get_selected_vertsIdx(active_mesh)
     select_and_change_mode(active_obj, 'EDIT')
     edit_obj = bpy.context.edit_object
     active_mesh = edit_obj.data
     matrix_world = active_obj.matrix_world
     matrix_world_inv = active_obj.matrix_world.inverted()
     matrix_world_nrml = matrix_world_inv.transposed().to_3x3()
     bm = bmesh.from_edit_mesh(active_mesh)
     bm.verts.ensure_lookup_table()
     bm.faces.ensure_lookup_table()
     bm.verts.index_update()
     verts_map = {}
     uv_layer_holdr1 = bm.loops.layers.uv.get(kWPLSmoothHolderUVMap1)
     uv_layer_holdr2 = bm.loops.layers.uv.get(kWPLSmoothHolderUVMap2)
     for face in bm.faces:
         for vert, loop in zip(face.verts, face.loops):
             verts_map[vert.index] = mathutils.Vector(
                 (loop[uv_layer_holdr1].uv[0], loop[uv_layer_holdr1].uv[1],
                  loop[uv_layer_holdr2].uv[0]))
     if len(selverts) == 0:
         selverts = []
         for v in bm.verts:
             if verts_map[v.index] is not None:
                 if (v.co - verts_map[v.index]).length > kRaycastEpsilon:
                     # vert moved
                     selverts.append(v.index)
     if len(selverts) == 0:
         self.report({'ERROR'}, "No selected verts found!")
         return {'FINISHED'}
     checked_verts = copy.copy(selverts)
     verts_shifts = {}
     propagation_stages = []
     for stage in range(1, self.SmoothingLoops + 1):
         stage_verts = {}
         checked_verts_cc = copy.copy(checked_verts)
         for v_idx in checked_verts_cc:
             v = bm.verts[v_idx]
             if (v_idx not in verts_shifts) and (v_idx in verts_map):
                 verts_shifts[v_idx] = mathutils.Vector(v.co -
                                                        verts_map[v_idx])
             for edg in v.link_edges:
                 v2 = edg.other_vert(v)
                 if v2.index not in checked_verts_cc:
                     #print("found new vert",v2.index,"at stage",stage)
                     #v2.select = True
                     if v2.index not in checked_verts:
                         checked_verts.append(v2.index)
                     if (v2.index not in stage_verts):
                         stage_verts[v2.index] = []
                     if v_idx not in stage_verts[v2.index]:
                         stage_verts[v2.index].append(v_idx)
         if len(stage_verts) == 0:
             break
         propagation_stages.append(stage_verts)
     #print("vert stages",propagation_stages)
     #print("verts_shifts",verts_shifts)
     new_positions = {}
     stage_cnt = 1.0
     for stage_verts in propagation_stages:
         stage_weight = pow(1.0 - stage_cnt / len(propagation_stages),
                            self.Sloppiness)
         for s_idx in stage_verts:
             avg_shift = mathutils.Vector((0, 0, 0))
             avg_count = 0.0
             for p_idx in stage_verts[s_idx]:
                 avg_shift = avg_shift + verts_shifts[p_idx]
                 avg_count = avg_count + 1.0
             if avg_count > 0:
                 s_shift = mathutils.Vector(avg_shift) / avg_count
                 verts_shifts[s_idx] = s_shift
                 s_v = bm.verts[s_idx]
                 #print("shifting vert",s_idx, s_v.index, s_v.co,verts_map[s_idx])
                 s_v_co2 = s_v.co + s_shift * stage_weight
                 if (self.CollisionDist > 0.0):
                     s_dir_g = (matrix_world_nrml * s_shift.normalized())
                     s_v_g = matrix_world * s_v.co
                     min_okdst = (s_shift * stage_weight).length
                     loc_g = fuzzySceneRayCast(s_v_g, s_dir_g,
                                               self.CollisionFuzz,
                                               [active_obj.name])
                     if loc_g is not None:
                         loc_l = matrix_world_inv * loc_g
                         hit_dst = (loc_l -
                                    s_v.co).length - self.CollisionDist
                         if hit_dst < min_okdst:
                             if hit_dst > 0:
                                 #s_v_co2 = s_v.co+hit_dst*(loc_l-s_v.co).normalized()
                                 s_v_co2 = s_v.co + hit_dst * s_shift.normalized(
                                 )
                             else:
                                 s_v_co2 = s_v.co
                 #s_v.co = s_v_co2
                 new_positions[s_idx] = s_v_co2
         stage_cnt = stage_cnt + 1.0
     # updateing positions as post-step
     for s_idx in new_positions:
         s_v = bm.verts[s_idx]
         s_v.co = new_positions[s_idx]
     bm.normal_update()
     bmesh.update_edit_mesh(active_mesh, True)
     return {'FINISHED'}
예제 #50
0
def deform_obj(obj, context, self):
    offset_rotation = 0.2
    offset_axis = 5.0
    bend_scale = 0.7

    # get vertices
    verts = None
    if obj.mode == 'EDIT':
        # this works only in edit mode,
        bm = bmesh.from_edit_mesh(obj.data)

        verts = [v for v in bm.verts if v.select]
        if len(verts) == 0:
            verts = [v for v in bm.verts if v.hide is False]

    else:
        # this works only in object mode,
        verts = [v for v in obj.data.vertices if v.select]
        if len(verts) == 0:
            verts = [v for v in obj.data.vertices if v.hide is False]

    # TODO Move it into utilities method. As Extrude class has the same
    # min/max.
    if verts:
        if obj.mode == 'EDIT':
            bm.verts.ensure_lookup_table()
        x_min = verts[0].co.x
        x_max = verts[0].co.x
        y_min = verts[0].co.y
        y_max = verts[0].co.y
        z_min = verts[0].co.z
        z_max = verts[0].co.z

        for vert in verts:
            if vert.co.x > x_max:
                x_max = vert.co.x
            if vert.co.x < x_min:
                x_min = vert.co.x
            if vert.co.y > y_max:
                y_max = vert.co.y
            if vert.co.y < y_min:
                y_min = vert.co.y
            if vert.co.z > z_max:
                z_max = vert.co.z
            if vert.co.z < z_min:
                z_min = vert.co.z

        x_orig = ((x_max - x_min) / 2.0) + x_min
        y_orig = ((y_max - y_min) / 2.0) + y_min
        z_orig = z_min
        if self.deform_axis == 'Z':
            y_orig = y_min
            z_orig = ((z_max - z_min) / 2.0) + z_min

        rot_origin = Vector((x_orig, y_orig, z_orig))

        visual_max = z_max - z_min
        if self.deform_axis == 'Z':
            visual_max = y_max - y_min

        if visual_max != 0.0:
            for vert in verts:
                vec = vert.co.copy()
                visual_up_pos = None
                if self.deform_axis != 'Z':
                    visual_up_pos = vec.z - z_min
                else:
                    visual_up_pos = vec.y - y_min

                # TAPER CODE
                # scale the vert
                if self.taper_value != 0:
                    taper_value = ((self.taper_value) *
                                   (visual_up_pos / visual_max))
                    if self.deform_axis != 'Z':
                        vert.co.xy -= (vert.co.xy -
                                       rot_origin.xy) * taper_value
                    else:
                        vert.co.xz -= (vert.co.xz -
                                       rot_origin.xz) * taper_value

                # TWIST CODE
                # rotate the vert
                if self.twist_angle != 0:
                    twist_angle = self.twist_angle * (visual_up_pos /
                                                      visual_max)
                    # if self.deform_axis == 'X':
                    # rot_angle = -rot_angle
                    rot_mat = None
                    if self.deform_axis != 'Z':
                        rot_mat = Matrix.Rotation(twist_angle, 3, 'Z')
                    else:
                        rot_mat = Matrix.Rotation(twist_angle, 3, 'Y')
                    vert.co = rot_mat * (vert.co - rot_origin) + rot_origin

                # BEND CODE
                beta = math.radians(self.bend_angle *
                                    (visual_up_pos / visual_max))
                if beta != 0:
                    final_offset = visual_up_pos * self.offset_rotation
                    if beta < 0:
                        final_offset = -final_offset

                    move_to_rotate = ((visual_up_pos / beta) +
                                      final_offset) * self.bend_scale
                    if self.deform_axis == 'X':
                        vert.co.y -= move_to_rotate
                    elif self.deform_axis == 'Y' or self.deform_axis == 'Z':
                        vert.co.x -= move_to_rotate

                    if self.deform_axis != 'Z':
                        vert.co.z = rot_origin.z
                    else:
                        vert.co.y = rot_origin.y

                    # rotate the vert
                    rot_angle = beta
                    if self.deform_axis == 'X' or self.deform_axis == 'Z':
                        rot_angle = -rot_angle
                    rot_mat = Matrix.Rotation(rot_angle, 3, self.deform_axis)
                    vert.co = rot_mat * (vert.co - rot_origin) + rot_origin

                    # back the rotation offset
                    back_offset = (visual_up_pos / (beta)) * self.bend_scale
                    if self.deform_axis == 'X':
                        vert.co.y += back_offset
                    elif self.deform_axis == 'Y' or self.deform_axis == 'Z':
                        vert.co.x += back_offset

                    # offset axys
                    move_offset = self.offset_axis * (visual_up_pos /
                                                      visual_max)
                    if self.deform_axis == 'X':
                        vert.co.x += move_offset
                    elif self.deform_axis == 'Y':
                        vert.co.y += move_offset
                    elif self.deform_axis == 'Z':
                        vert.co.z += move_offset

    # obj.data.update()
    #bpy.ops.mesh.normals_make_consistent()  # recalculate normals
    #bpy.ops.object.editmode_toggle()
    #bpy.ops.object.editmode_toggle()
    bm.normal_update()
    bmesh.update_edit_mesh(obj.data)
예제 #51
0
    def main(self, context, chboxexplote, chboxjoin, chboxaxisx, chboxaxisy,
             chboxaxisz, distance):

        if chboxexplote:

            distancia = distance / 10

            #almacena caras
            obj = bpy.context.object
            me = obj.data
            bm = bmesh.from_edit_mesh(me)

            obj = bpy.context.object

            cara_activa = bm.faces.active

            listacaras = [v for v in bm.faces if (v.select and not v.hide)]

            listacarasdes = [
                v for v in bm.faces if (v.select == False and not v.hide)
            ]

            contador = len(listacaras)
            #print(len(listacaras))

            if distancia != 0:
                separarcaras()

            while contador != 0:
                contador -= 1
                cara = listacaras[contador]
                posicion = contador * distancia
                if cara == cara_activa:
                    print("cara eje")

                for vertice in cara.verts:
                    if chboxaxisx:
                        vertice.co.x = vertice.co.x + posicion
                    if chboxaxisy:
                        vertice.co.y = vertice.co.y + posicion
                    if chboxaxisz:
                        vertice.co.z = vertice.co.z + posicion

            for cara in listacaras:
                cara.select = False

            if len(listacaras) != (len(bm.faces)):
                bpy.ops.mesh.select_all(action='INVERT')
            else:
                bpy.ops.mesh.select_all(action='SELECT')

            bmesh.ops.remove_doubles(bm, verts=bm.verts, dist=0.001)
            cara_activa.select = True
            bmesh.update_edit_mesh(me, True)

        ######### unir caras

        elif chboxjoin:

            #almacena caras
            obj = bpy.context.object
            me = obj.data
            bm = bmesh.from_edit_mesh(me)

            listacaras = []

            if len(bm.faces) > 1:
                for face in bm.faces:
                    if face.select:
                        listacaras.append(face)
                #bmesh.update_edit_mesh(me, True)

            distanciax = bm.faces.active.verts[0].co.x
            distanciay = bm.faces.active.verts[0].co.y
            distanciaz = bm.faces.active.verts[0].co.z
            contador = len(listacaras)
            #print(len(listacaras))

            listavertices = [bm.faces.active.verts[0]]

            for cara in listacaras:
                for vertice in cara.verts:
                    listavertices.append(vertice)
                    if chboxaxisx:
                        vertice.co.x = distanciax
                    if chboxaxisy:
                        vertice.co.y = distanciay
                    if chboxaxisz:
                        vertice.co.z = distanciaz

            bmesh.ops.remove_doubles(bm, verts=bm.verts, dist=0.001)

            bpy.ops.mesh.select_mode(use_extend=False,
                                     use_expand=False,
                                     type='VERT')
            for vertice in bm.verts:
                if vertice.co.x == distanciax:
                    vertice.select = True
                elif vertice.co.y == distanciay:
                    vertice.select = True
                elif vertice.co.z == distanciaz:
                    vertice.select = True

            bpy.ops.mesh.select_mode(use_extend=False,
                                     use_expand=False,
                                     type='FACE')

            bmesh.update_edit_mesh(me, True)
예제 #52
0
파일: planks.py 프로젝트: huggaida/scripts
def updateMesh(self, context):
	o = context.object

	material_list = getMaterialList(o)
		
	if o.pattern == 'Regular':
		nplanks = (o.width + o.originy) / o.plankwidth
		verts, faces, uvs = planks(nplanks, o.length + o.originx,
												o.planklength, o.planklengthvar,
												o.plankwidth, o.plankwidthvar,
												o.longgap, o.shortgap,
												o.offset, o.randomoffset, o.minoffset,
												o.randomseed,
												o.randrotx, o.randroty, o.randrotz,
												o.originx, o.originy)
	elif o.pattern == 'Herringbone':
		# note that there is a lot of extra length and width here to make sure that  we create a pattern w.o. gaps at the edges
		v = o.plankwidth * sqrt(2.0)
		w = o.planklength * sqrt(2.0)
		nplanks = int((o.width+o.planklength + o.originy*2) / v)+1
		nplanksc = int((o.length + o.originx*2) / w)+1
		verts, faces, uvs = herringbone(nplanks, nplanksc,
												o.planklength, o.plankwidth,
												o.longgap, o.shortgap,
												o.randomseed,
												o.randrotx, o.randroty, o.randrotz,
												o.originx, o.originy)
	elif o.pattern == 'Square':
		rows = int((o.width + o.originy)/ o.planklength)+1
		cols = int((o.length + o.originx)/ o.planklength)+1
		verts, faces, uvs = square(rows, cols, o.planklength, o.nsquare, o.border, o.longgap, o.shortgap, o.randomseed,
									o.randrotx, o.randroty, o.randrotz,
									o.originx, o.originy)
	elif o.pattern == 'Versaille':
		rows = int((o.width + o.originy)/ o.planklength)+2
		cols = int((o.length + o.originx)/ o.planklength)+2
		verts, faces, uvs = versaille(rows, cols, 
										o.planklength, o.plankwidth,
										o.longgap, o.shortgap,
										o.randrotx, o.randroty, o.randrotz,
										o.originx, o.originy,
										o.borderswitch)

	# create mesh &link object to scene
	emesh = o.data

	mesh = bpy.data.meshes.new(name='Planks')
	mesh.from_pydata(verts, [], faces)

	mesh.update(calc_edges=True)

	# more than one object can refer to the same emesh
	for i in bpy.data.objects:
		if i.data == emesh:
			i.data = mesh

	name = emesh.name
	emesh.user_clear() # this way the old mesh is marked as used by noone and not saved on exit
	bpy.data.meshes.remove(emesh)
	mesh.name = name
  
  
	if bpy.context.mode != 'EDIT_MESH':
		bpy.ops.object.editmode_toggle()
		bpy.ops.object.editmode_toggle()


	bpy.ops.object.shade_smooth()
	bpy.context.object.data.use_auto_smooth = 1
	bpy.context.object.data.auto_smooth_angle = 1

	# add uv-coords and per face random vertex colors
	rot = Euler((0,0,o.uvrotation))
	mesh.uv_textures.new()
	uv_layer = mesh.uv_layers.active.data
	vertex_colors = mesh.vertex_colors.new().data
	offset = Vector()
	# note that the uvs that are returned are shuffled
	for poly in mesh.polygons:
		color = [rand(), rand(), rand()]
		if o.randomuv == 'Random':
			offset = Vector((rand(), rand(), 0))
		if o.randomuv == 'Restricted':
			offset = Vector((rand()*2-1, rand()*2-1, 0))
			for loop_index in range(poly.loop_start, poly.loop_start + poly.loop_total):
				co = offset + mesh.vertices[mesh.loops[loop_index].vertex_index].co
				if co.x > o.length or co.x < 0:
					offset[0] = 0
				if co.y > o.width or co.y < 0:
					offset[1] = 0
		elif o.randomuv == 'Packed':
			x = []
			y = []
			for loop_index in range(poly.loop_start, poly.loop_start + poly.loop_total):
				x.append(uvs[mesh.loops[loop_index].vertex_index].x)
				y.append(uvs[mesh.loops[loop_index].vertex_index].y)
			offset = Vector((-min(x), -min(y), 0))
		for loop_index in range(poly.loop_start, poly.loop_start + poly.loop_total):
			if o.randomuv == 'Shuffle':
				coords = uvs[mesh.loops[loop_index].vertex_index]
			elif o.randomuv in ('Random', 'Restricted'):
				coords = mesh.vertices[mesh.loops[loop_index].vertex_index].co + offset
			elif o.randomuv == 'Packed':
				coords = uvs[mesh.loops[loop_index].vertex_index] + offset
			else:
				coords = mesh.vertices[mesh.loops[loop_index].vertex_index].co
			coords = Vector(coords) # copy
			coords.x *= o.uvscalex
			coords.y *= o.uvscaley
			coords.rotate(rot)
			uv_layer[loop_index].uv = coords.xy
			vertex_colors[loop_index].color = color

	# subdivide mesh and warp it
	warped = o.hollowlong > 0 or o.hollowshort > 0 or o.twist > 0
	if warped:
		bm = bmesh.new()
		bm.from_mesh(mesh)

		# calculate hollowness for each face
		dshortmap = {}
		dlongmap = {}
		for face in bm.faces:
			dshort = o.hollowshort * rand()
			dlong = o.hollowlong * rand()
			for v in face.verts:
				dshortmap[v.index] = dshort
				dlongmap[v.index] = dlong

		bm.to_mesh(mesh)
		bm.free()

		# at this point all new geometry is selected and subdivide works in all selection modes
		bpy.ops.object.editmode_toggle()
		bpy.ops.mesh.subdivide()  # bmesh subdivide doesn't work for me ...
		bpy.ops.object.editmode_toggle()

		bm = bmesh.new()
		bm.from_mesh(mesh)

		for v in bm.verts:
			if o.twist and len(v.link_edges) == 4:  # vertex in the middle of the plank
				dtwist = o.twist * randuni(-1, 1)
				for e in v.link_edges:
					v2 = e.other_vert(v)  # the vertices on the side of the plank
					if shortside(v2):
						for e2 in v2.link_edges:
							v3 = e2.other_vert(v2)
							if len(v3.link_edges) == 2:
								v3.co.z += dtwist
								dtwist = -dtwist  # one corner up, the other corner down
			elif len(v.link_edges) == 3:  # vertex in the middle of a side of the plank
				for e in v.link_edges:
					v2 = e.other_vert(v)
					if len(v2.link_edges) == 2:  # hollowness values are stored with the all original corner vertices
						dshort = dshortmap[v2.index]
						dlong = dlongmap[v2.index]
						break
				if shortside(v):
					v.co.z -= dlong
				else:
					v.co.z -= dshort

		creases = bm.edges.layers.crease.new()
		for edge in bm.edges:
			edge[creases] = 1
			for vert in edge.verts:
				if len(vert.link_edges) == 4:
					edge[creases] = 0
					break

		bm.to_mesh(mesh)
		bm.free()


	# remove all modifiers to make sure the boolean will be last & only modifier
	n = len(o.modifiers)
	while n > 0:
		n -= 1
		bpy.ops.object.modifier_remove(modifier=o.modifiers[-1].name)

	# add thickness
	bpy.ops.object.mode_set(mode='EDIT')
	bm = bmesh.from_edit_mesh(o.data)

	# extrude to given thickness
	ret=bmesh.ops.extrude_face_region(bm,geom=bm.faces[:]) # all planks are separate faces, except when subdivided by random twist or hollowness
	if warped:  # we have a extra subdivision
		Z = Vector((0,0,1))
		for el in ret['geom']:
			if isinstance(el, bmesh.types.BMVert) and len(el.link_edges) == 4 and el.normal.dot(Z) > 0.99 : # we look start at the vertex in the middle of the 4 faces but only on the top
				d = Vector((0,0,o.thickness + rand() * o.randomthickness))
				verts = set(v for f in el.link_faces for v in f.verts)  # some vertices are shared, this way we make them unique
				bmesh.ops.translate(bm, vec=d, verts=list(verts))
	else:
		for el in ret['geom']:
			if isinstance(el, bmesh.types.BMFace):
				d = Vector((0,0,o.thickness + rand() * o.randomthickness))
				bmesh.ops.translate(bm, vec=d, verts=el.verts)

	# trim excess flooring
	ret = bmesh.ops.bisect_plane(bm, geom=bm.verts[:]+bm.edges[:]+bm.faces[:], plane_co=(o.length,0,0), plane_no=(1,0,0), clear_outer=True)
	ret = bmesh.ops.bisect_plane(bm, geom=bm.verts[:]+bm.edges[:]+bm.faces[:], plane_co=(0,0,0), plane_no=(-1,0,0), clear_outer=True)
	ret = bmesh.ops.bisect_plane(bm, geom=bm.verts[:]+bm.edges[:]+bm.faces[:], plane_co=(0,o.width,0), plane_no=(0,1,0), clear_outer=True)
	ret = bmesh.ops.bisect_plane(bm, geom=bm.verts[:]+bm.edges[:]+bm.faces[:], plane_co=(0,0,0), plane_no=(0,-1,0), clear_outer=True)

	# fill in holes caused by the trimming
	open_edges = [e for e in bm.edges if len(e.link_faces)==1]
	bmesh.ops.edgeloop_fill(bm, edges=open_edges, mat_nr=0, use_smooth=False)

	creases = bm.edges.layers.crease.active
	if creases is not None:
		for edge in open_edges:
			edge[creases] = 1

	bmesh.update_edit_mesh(o.data)
	bpy.ops.object.mode_set(mode='OBJECT')
	
	# intersect with a floorplan. Note the floorplan must be 2D (all z-coords must be identical) and a closed polygon.
	if self.usefloorplan and self.floorplan != ' None ':
		# make the floorplan the only active an selected object
		bpy.ops.object.select_all(action='DESELECT')
		context.scene.objects.active = bpy.data.objects[self.floorplan]
		bpy.data.objects[self.floorplan].select = True

		# duplicate the selected geometry into a separate object
		me = context.scene.objects.active.data
		selected_faces = [p.index for p in me.polygons if p.select]
		bpy.ops.object.editmode_toggle()
		bpy.ops.mesh.duplicate()
		bpy.ops.mesh.separate()
		bpy.ops.object.editmode_toggle()
		me = context.scene.objects.active.data
		for i in selected_faces:
			me.polygons[i].select = True

		# now there will be two selected objects
		# the one with the new name will be the copy
		for ob in context.selected_objects:
			if ob.name != self.floorplan:
				fpob = ob
		
		# make that copy active and selected
		for ob in context.selected_objects:
			ob.select = False
		fpob.select = True
		context.scene.objects.active = fpob
		# add thickness
		# let normals of select faces point in same direction
		bpy.ops.object.editmode_toggle()
		bpy.ops.mesh.select_all(action='SELECT')
		bpy.ops.mesh.normals_make_consistent(inside=False)
		bpy.ops.object.editmode_toggle()
		# add solidify modifier
		# NOTE: for some reason bpy.ops.object.modifier_add doesn't work here
		# even though fpob at this point is verifyable the active and selected object ...
		mod = fpob.modifiers.new(name='Solidify', type='SOLIDIFY')
		mod.offset = 1.0 # in the direction of the normals
		mod.thickness = 2000 # very thick
		bpy.ops.object.modifier_apply(apply_as='DATA', modifier="Solidify")
		bpy.ops.object.editmode_toggle()
		bpy.ops.mesh.select_all(action='SELECT')
		bpy.ops.mesh.normals_make_consistent(inside=False)
		bpy.ops.object.editmode_toggle()
		fpob.location -= Vector((0,0,1000)) # actually this should be in the negative direction of the normals not just plain downward...
		
		# at this point the floorplan object is the active and selected object
		if True:
			# make the floorboards active and selected
			for ob in context.selected_objects:
				ob.select = False
			context.scene.objects.active = o
			o.select = True
			
			# add-and-apply a boolean modifier to get the intersection with the floorplan copy
			bpy.ops.object.modifier_add(type='BOOLEAN') # default is intersect
			o.modifiers[-1].object = fpob
			if True:
				bpy.ops.object.modifier_apply(apply_as='DATA', modifier="Boolean")
				# delete the copy
				bpy.ops.object.select_all(action='DESELECT')
				context.scene.objects.active = fpob
				fpob.select = True
				bpy.ops.object.delete()
			# make the floorboards active and selected
			context.scene.objects.active = o
			o.select = True
		
	if self.modify:
		mods = o.modifiers
		if len(mods) == 0: # always true
			bpy.ops.object.modifier_add(type='BEVEL')
			mods[0].use_clamp_overlap = False     # clamp overlap causes some issues
			#bpy.ops.object.modifier_add(type='EDGE_SPLIT')
			mods = o.modifiers
			mods[0].show_expanded = False
			#mods[1].show_expanded = False
			mods[0].width = self.bevel
			mods[0].segments = 2
			mods[0].limit_method = 'ANGLE'
			mods[0].angle_limit = (85/90.0)*PI/2
		if warped and not ('SUBSURF' in [m.type for m in mods]):
			bpy.ops.object.modifier_add(type='SUBSURF')
			mods[-1].show_expanded = False
			mods[-1].show_viewport = False    # subsurf in viewport is not necessary and slow things down
			mods[-1].levels = 2
		if not warped and ('SUBSURF' in [m.type for m in mods]):
			bpy.ops.object.modifier_remove(modifier='Subsurf')

	if self.preservemats and len(material_list)>0:
		rebuildMaterialList(o, material_list)    
		assignRandomMaterial(len(material_list))
  
  # correct the shading artefacts  
	bpy.ops.object.editmode_toggle()
	bpy.ops.mesh.select_all(action='SELECT')
	bpy.ops.mesh.remove_doubles()
	bpy.ops.mesh.normals_make_consistent()
	bpy.ops.mesh.select_all(action='DESELECT')
	bpy.ops.mesh.edges_select_sharp(sharpness=1.4)
	bpy.ops.mesh.mark_sharp() 
	bpy.ops.mesh.select_face_by_sides(number=5, type='GREATER', extend=False)
	bpy.ops.mesh.quads_convert_to_tris(quad_method='BEAUTY', ngon_method='BEAUTY')
	bpy.ops.mesh.tris_convert_to_quads()
	bpy.ops.object.editmode_toggle()
예제 #53
0
    def execute(self, context):
        mesh = bpy.context.object.data
        bm = bmesh.from_edit_mesh(mesh)
        bm.faces.ensure_lookup_table()
        uv_layer = bm.loops.layers.uv.active

        faces = list()
        #MAKE FACE LIST
        for face in bm.faces:
            if face.select:
                faces.append(face)

        mirrored = False
        #check if mirrored:
        for face in faces:
            sum_edges = 0
            # Only loop 3 verts ignore others: faster!
            for i in range(3):
                uv_A = face.loops[i][uv_layer].uv
                uv_B = face.loops[(i + 1) % 3][uv_layer].uv
                sum_edges += (uv_B.x - uv_A.x) * (uv_B.y + uv_A.y)

            if sum_edges > 0:
                mirrored = True

        #get original size
        xmin, xmax = faces[0].loops[0][uv_layer].uv.x, faces[0].loops[0][
            uv_layer].uv.x
        ymin, ymax = faces[0].loops[0][uv_layer].uv.y, faces[0].loops[0][
            uv_layer].uv.y

        for face in faces:
            for vert in face.loops:
                xmin = min(xmin, vert[uv_layer].uv.x)
                xmax = max(xmax, vert[uv_layer].uv.x)
                ymin = min(ymin, vert[uv_layer].uv.y)
                ymax = max(ymax, vert[uv_layer].uv.y)

        xcenter = (xmin + xmax) / 2
        ycenter = (ymin + ymax) / 2

        #step rotation
        module_name = __name__.split('.')[0]
        addon_prefs = bpy.context.preferences.addons[module_name].preferences
        scale_snap_x = addon_prefs.scale_snap
        scale_snap_y = addon_prefs.scale_snap

        if self.direction == "+XY":
            scale_snap_x = 1 / scale_snap_x
            scale_snap_y = 1 / scale_snap_y
        #if self.direction == "-XY":

        if self.direction == "+X":
            scale_snap_x = 1 / scale_snap_x
            scale_snap_y = 1
        if self.direction == "-X":
            scale_snap_x = scale_snap_x
            scale_snap_y = 1
        if self.direction == "+Y":
            scale_snap_x = 1
            scale_snap_y = 1 / scale_snap_y
        if self.direction == "-Y":
            scale_snap_x = 1
            scale_snap_y = scale_snap_y

        #PI/4=0.78539816339
        #PIdiv=3.14159265359/(180/rotate_snap)
        #delta = (3.14159265359/180)*rotate_snap
        #delta = math.floor(delta/PIdiv)*PIdiv
        #if self.direction == "reverse":
        #    print("reverse")
        #delta = (3.14159265359/180)-delta
        #    delta = -delta
        #if mirrored:
        #    delta = -delta

        #loop through every selected face and scale the uv's using original uv as reference
        for face in faces:
            for loop in face.loops:
                loop[uv_layer].uv.x -= xcenter
                loop[uv_layer].uv.y -= ycenter

                #oldx = loop[uv_layer].uv.x
                #oldy = loop[uv_layer].uv.y

                loop[uv_layer].uv.x = loop[uv_layer].uv.x * scale_snap_x
                loop[uv_layer].uv.y = loop[uv_layer].uv.y * scale_snap_y

                loop[uv_layer].uv.x += xcenter
                loop[uv_layer].uv.y += ycenter

        #update mesh
        bmesh.update_edit_mesh(mesh, False, False)

        return {'FINISHED'}
예제 #54
0
    def execute(self, context):

        self.hcol = context.preferences.addons[
            'kekit'].preferences.modal_color_header
        self.tcol = context.preferences.addons[
            'kekit'].preferences.modal_color_text
        self.scol = context.preferences.addons[
            'kekit'].preferences.modal_color_subtext

        if self.ke_fitprim_option == "BOX":
            self.boxmode, self.world = True, False
        elif self.ke_fitprim_option == "CYL":
            self.boxmode, self.world = False, False
        elif self.ke_fitprim_option == "SPHERE":
            self.boxmode, self.world, self.sphere = False, False, True
        elif self.ke_fitprim_option == "QUADSPHERE":
            self.boxmode, self.world, self.sphere = False, False, True
        else:
            self.boxmode, self.world, self.sphere = False, False, False

        if bpy.context.scene.kekit.fitprim_item:
            self.itemize = True
        else:
            self.itemize = self.ke_fitprim_itemize

        self.modal = bpy.context.scene.kekit.fitprim_modal
        self.cyl_sides = bpy.context.scene.kekit.fitprim_sides
        self.select = bpy.context.scene.kekit.fitprim_select
        self.unit = round(bpy.context.scene.kekit.fitprim_unit, 4)
        self.sphere_ring = bpy.context.scene.kekit.fitprim_sphere_ring
        self.sphere_seg = bpy.context.scene.kekit.fitprim_sphere_seg
        self.quadsphere_seg = bpy.context.scene.kekit.fitprim_quadsphere_seg

        self.edit_mode = bpy.context.mode
        sel_verts = []
        sel_verts2 = []
        multi_object_mode = False

        cursor = context.scene.cursor
        self.og_cloc = cursor.location.copy()
        self.og_crot = cursor.rotation_euler.copy()
        og_orientation = str(context.scene.transform_orientation_slots[0].type)

        if self.itemize or self.edit_mode == "OBJECT" and context.object is not None:
            # make sure the new object is in the same layer as context object
            objc = context.object.users_collection[0]
            layer_collection = context.view_layer.layer_collection
            layer_coll = get_layer_collection(layer_collection, objc.name)
            alc = context.view_layer.active_layer_collection

            if objc.name != alc.name and alc.name != "Master Collection":
                context.view_layer.active_layer_collection = layer_coll

            elif objc.name != "Master Collection" and objc.name != alc.name:
                context.view_layer.active_layer_collection = layer_coll

        # -----------------------------------------------------------------------------------------
        # MULTI OBJECT CHECK & SETUP
        # -----------------------------------------------------------------------------------------
        if self.edit_mode == "EDIT_MESH":
            sel_mode = [b for b in bpy.context.tool_settings.mesh_select_mode]
            other_side = []
            sel_obj = [
                o for o in bpy.context.selected_objects if o.type == "MESH"
            ]
            if len(sel_obj) == 2:
                multi_object_mode = True

            obj = bpy.context.active_object
            obj_mtx = obj.matrix_world.copy()
            second_obj = []

            bm = bmesh.from_edit_mesh(obj.data)
            bm.faces.ensure_lookup_table()
            bm.verts.ensure_lookup_table()

            sel_verts = [v for v in bm.verts if v.select]

            if sel_mode[2]:
                sel_poly = [p for p in bm.faces if p.select]
                active_face = bm.faces.active
                if active_face not in sel_poly:
                    active_face = None

            if multi_object_mode:
                second_obj = [o for o in sel_obj if o != obj][0]
                bm2 = bmesh.from_edit_mesh(second_obj.data)
                obj_mtx2 = second_obj.matrix_world.copy()

                sel_poly2 = [p for p in bm2.faces if p.select]
                if sel_poly2:
                    active_face2 = bm2.faces.active
                    if active_face2 not in sel_poly2:
                        active_face2 = None
                    if active_face2:
                        sel_verts2 = active_face2.verts
                    else:
                        sel_verts2 = sel_poly2[0].verts
                        active_face2 = sel_poly2[0]  # haxxfixxx
                else:
                    sel_verts2 = [v for v in bm2.verts if v.select]

                if not sel_verts2:
                    multi_object_mode = False

                elif sel_mode[0]:
                    # Just for 2-vert mode in multiobj mode
                    ole = sel_verts2[0].link_edges[:]
                    other_side = get_shortest(obj_mtx2, ole)

            side = None
            distance = 0
            vps = []
            normal, setpos, setrot, center = None, None, None, None
            first_island = None
            island_mode = False

        # -----------------------------------------------------------------------------------------
        # NO SELECTION MODE
        # -----------------------------------------------------------------------------------------
        if not sel_verts or self.edit_mode == "OBJECT":

            # Check mouse over target
            if not self.edit_mode == "OBJECT":
                bpy.ops.object.mode_set(mode="OBJECT")

            hit_obj, hit_wloc, hit_normal, hit_face = mouse_raycast(
                context, self.mouse_pos, evaluated=True)

            if not self.edit_mode == "OBJECT":
                bpy.ops.object.mode_set(mode="EDIT")

            if self.edit_mode != "OBJECT" and hit_obj is not None:
                if len(hit_obj.modifiers) > 0:
                    self.report({
                        "INFO"
                    }, "FitPrim: Selected elements required in Edit Mode if Modifiers exist"
                                )
                    return {"CANCELLED"}

            if hit_obj and hit_face is not None:
                # mouse over placement on face
                self.world = False
                mtx = hit_obj.matrix_world
                eks = hit_obj.data.polygons[hit_face].edge_keys
                vecs = []

                for vp in eks:
                    vc1 = mtx @ hit_obj.data.vertices[vp[0]].co
                    vc2 = mtx @ hit_obj.data.vertices[vp[1]].co
                    vecs.append(Vector(vc1 - vc2).normalized())

                evps = []
                for vp in eks:
                    v1, v2 = hit_obj.data.vertices[
                        vp[0]], hit_obj.data.vertices[vp[1]]
                    evps.append([v1, v2])

                side, center, start_vec = get_sides(mtx, vecs, evps)

                if self.ke_fitprim_option == "PLANE" and self.edit_mode == "OBJECT":
                    setpos = center
                    # setpos = mtx @ hit_obj.data.polygons[hit_face].center
                    side *= 2

                else:
                    offset = hit_normal * (side / 2)
                    setpos = center + offset
                    # setpos = mtx @ hit_obj.data.polygons[hit_face].center + offset

                setrot = rotation_from_vector(hit_normal, start_vec)

            else:
                # view placement compensation & Z0 drop
                view_vec = region_2d_to_vector_3d(context.region,
                                                  context.space_data.region_3d,
                                                  self.mouse_pos)
                view_pos = context.space_data.region_3d.view_matrix.inverted(
                ).translation

                if get_view_type() != "ORTHO":
                    ground = ((0, 0, 0), (0, 1, 0), (1, 0, 0))
                    raypos = intersect_ray_tri(ground[0], ground[1], ground[2],
                                               view_vec, view_pos, False)
                    snap_val = str(self.unit).split('.')
                    if int(snap_val[0]) > 0:
                        snap = 0
                    else:
                        snap = len(snap_val[1])

                    setpos = Vector((round(raypos[0],
                                           snap), round(raypos[1],
                                                        snap), self.unit / 2))
                else:
                    setpos = region_2d_to_location_3d(
                        context.region, context.space_data.region_3d,
                        self.mouse_pos, view_vec)

                self.world = True

                side = self.unit
                if self.ke_fitprim_option == "PLANE" and self.edit_mode == "OBJECT":
                    side *= 2

            distance = side
            sel_mode = (True, False, False)

        # -----------------------------------------------------------------------------------------
        # VERT MODE(s)
        # -----------------------------------------------------------------------------------------
        elif sel_mode[0]:

            if len(sel_verts) == 1 and not multi_object_mode:
                # 1-VERT MODE
                self.world = True
                side = get_shortest(obj_mtx, sel_verts[0].link_edges[:])
                distance = side
                setpos = obj_mtx @ sel_verts[0].co

            elif len(sel_verts) == 2 and not multi_object_mode or \
                    multi_object_mode and len(sel_verts2) == 1 and len(sel_verts) == 1:
                # 2 Vert mode
                if multi_object_mode:
                    p1 = obj_mtx @ sel_verts[0].co
                    p2 = obj_mtx2 @ sel_verts2[0].co
                    side = [other_side]
                    con_edges = sel_verts[0].link_edges[:]
                    side.append(get_shortest(obj_mtx, con_edges))
                    side = sorted(side)[0]
                else:
                    p1 = obj_mtx @ sel_verts[0].co
                    p2 = obj_mtx @ sel_verts[1].co
                    con_edges = sel_verts[0].link_edges[:] + sel_verts[
                        1].link_edges[:]
                    side = get_shortest(obj_mtx, con_edges)

                v_1 = Vector(p1 - p2).normalized()
                v_2 = Vector((0, 0, 1))
                if abs(v_1.dot(v_2)) == 1:
                    v_2 = Vector((1, 0, 0))
                n_v = v_1.cross(v_2).normalized()
                u_v = n_v.cross(v_1).normalized()
                t_v = u_v.cross(n_v).normalized()

                setrot = Matrix((u_v, n_v, t_v)).to_4x4().inverted()
                distance = get_distance(p1, p2)
                setpos = Vector(get_midpoint(p1, p2))

            elif len(sel_verts) == 4 or multi_object_mode and len(
                    sel_verts2) + len(sel_verts) <= 4:
                # 4-vert Rectangle mode
                # holy brute force batman
                if not second_obj:
                    second_obj = obj
                tri = tri_order(((obj, sel_verts), (second_obj, sel_verts2)))
                q = tri[-1]
                # just placing a unit prim with min side in the center (for this one) so disregarding other vecs
                v1 = Vector(tri[0][0].matrix_world @ tri[0][1].co -
                            tri[1][0].matrix_world @ tri[1][1].co)
                v2 = Vector(tri[0][0].matrix_world @ tri[0][1].co -
                            tri[2][0].matrix_world @ tri[2][1].co)
                # v3 = Vector(q[0].matrix_world @ q[1].co - tri[1][0].matrix_world @ tri[1][1].co)
                # v4 = Vector(q[0].matrix_world @ q[1].co - tri[2][0].matrix_world @ tri[2][1].co)

                d1 = get_distance(tri[0][0].matrix_world @ tri[0][1].co,
                                  tri[1][0].matrix_world @ tri[1][1].co)
                # d2 = get_distance(tri[0][0].matrix_world @ tri[0][1].co, tri[2][0].matrix_world @ tri[2][1].co)
                # d3 = get_distance(q[0].matrix_world @ q[1].co, tri[1][0].matrix_world @ tri[1][1].co)
                d4 = get_distance(q[0].matrix_world @ q[1].co,
                                  tri[2][0].matrix_world @ tri[2][1].co)

                if d1 < d4:
                    side = d1
                else:
                    side = d4
                distance = side

                ap1 = average_vector([obj_mtx @ v.co for v in sel_verts])
                if sel_verts2:
                    ap2 = average_vector([obj_mtx2 @ v.co for v in sel_verts2])
                    setpos = average_vector((ap1, ap2))
                else:
                    setpos = ap1

                n = v1.normalized().cross(v2.normalized())
                u = n.cross(v1.normalized())
                t = u.cross(n)
                setrot = Matrix((u, n, t)).to_4x4().inverted()

            else:
                self.report({
                    "INFO"
                }, "FitPrim: Invalid Vert Mode Selection: Select 1, 2 or 4 verts"
                            )
                return {"CANCELLED"}

        # -----------------------------------------------------------------------------------------
        # EDGE MODE
        # -----------------------------------------------------------------------------------------
        elif sel_mode[1]:

            one_line, loops, loops2 = False, [], []
            sel_edges = [e for e in bm.edges if e.select]
            vps = [e.verts[:] for e in sel_edges]

            active_edge = bm.select_history.active
            if active_edge:
                active_edge_facenormals = [
                    correct_normal(obj_mtx, p.normal)
                    for p in active_edge.link_faces
                ]
                active_edge_normal = Vector(
                    average_vector(active_edge_facenormals)).normalized()

            # GET ISLANDS
            if multi_object_mode and active_edge:
                # print("multi obj mode") # todo: limited multiobj mode, rework one-for-all?
                sel_edges2 = [e for e in bm2.edges if e.select]
                vps2 = [e.verts for e in sel_edges2]
                p1 = get_loops(vps, legacy=True)
                p2 = get_loops(vps2, legacy=True)
                if p1 and p2:
                    a1, a2 = obj_mtx @ p1[0][0].co, obj_mtx @ p1[0][-1].co
                    b1, b2 = obj_mtx2 @ p2[0][0].co, obj_mtx2 @ p2[0][-1].co
                else:
                    a1, a2 = obj_mtx @ sel_verts[0].co, obj_mtx @ sel_verts[
                        -1].co
                    b1, b2 = obj_mtx2 @ sel_verts2[
                        0].co, obj_mtx2 @ sel_verts2[-1].co

                b_avg = get_midpoint(b1, b2)
                spacing, mp = get_closest_midpoint(a1, a2, b_avg)

                u_v = Vector(a1 - b1).normalized()
                t_v = Vector(a1 - a2).normalized()
                n_v = u_v.cross(t_v).normalized()

                setrot = rotation_from_vector(n_v, t_v, rotate90=True)
                setpos = mp
                side = spacing
                distance = spacing

            elif active_edge:  # same (active) obj island selections
                if len(sel_edges) > 1:

                    if len(sel_edges) == 2 and not bool(
                            set(sel_edges[0].verts).intersection(
                                sel_edges[1].verts)):
                        a1p, a2p = sel_edges[0].verts, sel_edges[1].verts
                        a1, a2 = obj_mtx @ a1p[0].co, obj_mtx @ a1p[1].co
                        b_avg = average_vector(
                            [obj_mtx @ a2p[0].co, obj_mtx @ a2p[1].co])

                        lf1 = sel_edges[0].link_faces[:]
                        lf = [
                            f for f in sel_edges[1].link_faces[:] if f in lf1
                        ]

                        v1 = Vector((obj_mtx @ a1p[0].co -
                                     obj_mtx @ a1p[1].co)).normalized()
                        v2 = Vector((obj_mtx @ a2p[0].co -
                                     obj_mtx @ a2p[1].co)).normalized()

                        if not lf:
                            u_v = Vector(a1 -
                                         (obj_mtx @ a2p[0].co)).normalized()
                            t_v = Vector(a1 - a2).normalized()
                            n_v = u_v.cross(t_v).normalized()
                            setrot = rotation_from_vector(n_v,
                                                          t_v,
                                                          rotate90=True)
                        else:
                            n = correct_normal(obj_mtx, lf[0].normal)
                            # t = average_vector((v1, v2))
                            # if sum(t) == 0:
                            #     print("AVG FAIL")
                            t = v1
                            setrot = rotation_from_vector(n, t, rotate90=True)

                        spacing, mp = get_closest_midpoint(a1, a2, b_avg)
                        setpos = mp
                        side = spacing
                        distance = spacing
                    else:
                        loops = get_loops(vps, legacy=True)

                if len(loops) > 1:
                    # print ("single obj - multi loop", len(loops))
                    # Check for closed loops
                    a_ep1, a_ep2 = loops[0][0], loops[0][-1]
                    b_ep1, b_ep2 = loops[1][0], loops[1][-1]
                    if a_ep1 == a_ep2:
                        a_ep2 = loops[0][-2]
                    if b_ep1 == b_ep2:
                        b_ep2 = loops[1][-2]

                    # get coords & set vals
                    a1, a2 = obj_mtx @ a_ep1.co, obj_mtx @ a_ep2.co
                    b1, b2 = obj_mtx @ b_ep1.co, obj_mtx @ b_ep2.co

                    b_avg = get_midpoint(b1, b2)
                    spacing, mp = get_closest_midpoint(a1, a2, b_avg)

                    u_v = Vector((0, 0, 1))
                    t_v = Vector(a1 - a2).normalized()
                    if abs(u_v.dot(t_v)) == 1:
                        u_v = Vector((1, 0, 0))

                    n_v = u_v.cross(t_v).normalized()

                    setrot = rotation_from_vector(n_v, t_v, rotate90=False)
                    setpos = mp
                    side = spacing
                    distance = spacing

                elif len(loops) == 1 or len(sel_edges) == 1:
                    # print ("single obj - single loop")
                    single_line = False
                    if len(sel_edges) != 1:
                        if loops[0][0] != loops[0][-1]:
                            single_line = True

                    if len(sel_edges) != 1 and not single_line:
                        vecs = [
                            Vector((obj_mtx @ vp[0].co) -
                                   (obj_mtx @ vp[1].co)).normalized()
                            for vp in vps
                        ]
                        normal = average_vector([
                            correct_normal(obj_mtx, v.normal)
                            for v in flatten(vps)
                        ])

                        side, center, start_vec = get_sides(obj_mtx, vecs, vps)
                        distance = side
                        setpos = center
                        setrot = rotation_from_vector(normal, start_vec)

                    elif len(sel_edges) == 1 or single_line:
                        # print("1 edge --> one line", one_line)
                        p1, p2 = obj_mtx @ sel_verts[
                            0].co, obj_mtx @ sel_verts[1].co
                        t_v = Vector(p1 - p2).normalized()
                        n_v = active_edge_normal

                        setrot = rotation_from_vector(n_v, t_v)
                        distance = get_distance(p1, p2)
                        setpos = get_midpoint(p1, p2)
                        side = distance
                    else:
                        print("Unexpected: Aborting operation.")
                        return {'CANCELLED'}

        # -----------------------------------------------------------------------------------------
        # FACE MODE
        # -----------------------------------------------------------------------------------------
        elif sel_mode[2] and active_face and sel_poly:
            fail_island = False

            # GET ISLANDS
            if multi_object_mode and active_face:
                first_island = sel_verts
                point = obj_mtx @ active_face.calc_center_median()
                firstcos = [obj_mtx @ v.co for v in active_face.verts]
                secondcos = [obj_mtx2 @ v.co for v in active_face2.verts]

                if firstcos and secondcos:
                    island_mode = True

                    distance = point_to_plane(point, firstcos, secondcos)
                    if distance:
                        distance = abs(distance)
                    else:
                        # print("Multi obj Point to plane failed for some reason - using single island mode.")
                        # island_mode = False
                        fail_island = True

            else:  # same (active) obj island selections
                first_island, second_island = get_selection_islands(
                    sel_poly, active_face)
                # Ofc, needs correct order for point to plane, and I'll just rely on face.verts for that:
                calc_island_1 = active_face.verts[:]
                calc_island_2 = []
                for p in sel_poly:
                    verts = p.verts[:]
                    for v in verts:
                        if v in second_island:
                            calc_island_2 = verts
                            break

                if len(first_island) != 0 and len(second_island) != 0:
                    firstcos = [obj_mtx @ v.co for v in calc_island_1]
                    secondcos = [obj_mtx @ v.co for v in calc_island_2]
                    distance = point_to_plane(
                        obj_mtx @ active_face.calc_center_median(), firstcos,
                        secondcos)

                    if distance:
                        distance = abs(distance)
                        island_mode = True
                    else:
                        # print("Point to plane failed for some reason - using single island mode.")
                        fail_island = True
                    # print(distance)
                else:
                    # Ngon mode
                    first_island = sel_verts

            # GETVALUES
            if island_mode or fail_island:
                bpy.ops.mesh.select_all(action='DESELECT')

                for v in first_island:
                    bm.verts[v.index].select = True

                bmesh.update_edit_mesh(obj.data)
                bpy.ops.mesh.select_mode(type='VERT')
                bpy.ops.mesh.select_mode(type='FACE')
                bm.faces.ensure_lookup_table()

            faces = [f for f in bm.faces if f.select]
            normal = average_vector(
                [correct_normal(obj_mtx, f.normal) for f in faces])
            bpy.ops.mesh.region_to_loop()

            sel_edges = [e for e in bm.edges if e.select]
            vps = [e.verts[:] for e in sel_edges]
            vecs = [
                Vector((obj_mtx @ vp[0].co) -
                       (obj_mtx @ vp[1].co)).normalized() for vp in vps
            ]

            side, center, start_vec = get_sides(obj_mtx, vecs, vps)
            setrot = rotation_from_vector(normal, start_vec)

        # -----------------------------------------------------------------------------------------
        # PROCESS
        # -----------------------------------------------------------------------------------------
        if side:
            if self.ke_fitprim_option == "PLANE" and self.edit_mode != "OBJECT":
                if sel_mode[2]:
                    setpos = center

            elif len(sel_verts) == 0 or sel_mode[0] or sel_mode[1]:
                side *= .5
                distance = distance / 2
                if self.sphere and sel_mode[0]:
                    if not len(sel_verts) == 0:
                        side = distance

            elif sel_mode[2]:
                if island_mode:
                    side *= .5
                    offset = normal * distance * .5
                    distance *= .5
                    if self.sphere:
                        side = distance
                else:
                    side *= .5
                    distance = side
                    offset = normal * side

                setpos = center + offset
                if not island_mode and self.sphere:
                    setpos = setpos - offset

            # SET FINAL ROTATION
            if self.world:
                setrot = (0, 0, 0)
                if self.ke_fitprim_option == "PLANE" and not sel_verts:
                    setpos[2] = 0
            else:
                setrot = setrot.to_euler()

            # RUN OP
            if not self.edit_mode == "OBJECT":
                bpy.ops.mesh.select_mode(type='FACE')

            if self.itemize:
                if self.edit_mode != "OBJECT":
                    bpy.ops.object.mode_set(mode="OBJECT")
                bpy.ops.transform.select_orientation(orientation='GLOBAL')
                cursor.location = setpos
                cursor.rotation_euler = setrot

            # -----------------------------------------------------------------------------------------
            # CUBE
            # -----------------------------------------------------------------------------------------
            if self.boxmode:
                bpy.ops.mesh.primitive_box_add(width=side,
                                               depth=side,
                                               height=distance,
                                               align='WORLD',
                                               location=setpos,
                                               rotation=setrot)
                if self.itemize or self.edit_mode == "OBJECT":
                    bpy.ops.object.shade_smooth()
                    bpy.context.object.data.use_auto_smooth = True

            # -----------------------------------------------------------------------------------------
            # PLANE
            # -----------------------------------------------------------------------------------------
            elif self.ke_fitprim_option == "PLANE":

                # side *= 2
                enter = True

                if self.edit_mode == 'OBJECT' or self.itemize:
                    enter = False

                bpy.ops.mesh.primitive_plane_add(enter_editmode=enter,
                                                 align='WORLD',
                                                 location=setpos,
                                                 rotation=setrot,
                                                 size=side,
                                                 scale=(1, 1, 1))
                if self.itemize or self.edit_mode == "OBJECT":
                    bpy.ops.object.shade_smooth()
                    bpy.context.object.data.use_auto_smooth = True

            # -----------------------------------------------------------------------------------------
            # SPHERE
            # -----------------------------------------------------------------------------------------
            elif self.sphere and not self.ke_fitprim_option == "QUADSPHERE":
                bpy.ops.mesh.primitive_uv_sphere_add(
                    segments=self.sphere_seg,
                    ring_count=self.sphere_ring,
                    radius=side,
                    align='WORLD',
                    location=setpos,
                    rotation=setrot)
                if self.itemize or self.edit_mode == "OBJECT":
                    bpy.ops.object.shade_smooth()
                    bpy.context.object.data.use_auto_smooth = True

            # -----------------------------------------------------------------------------------------
            # QUADSPHERE
            # -----------------------------------------------------------------------------------------
            elif self.ke_fitprim_option == "QUADSPHERE":
                cutnr = self.quadsphere_seg

                # calc compensated subd radius from cube
                v1_pos = setpos[0] + side, setpos[1] + side, setpos[2] + side
                rad = sqrt(sum([(a - b)**2 for a, b in zip(setpos, v1_pos)]))
                diff = side / rad

                side = (side * diff)
                distance = side

                bpy.ops.mesh.primitive_box_add(width=side,
                                               depth=side,
                                               height=distance,
                                               align='WORLD',
                                               location=setpos,
                                               rotation=setrot,
                                               name="QuadSphere")

                if self.itemize or self.edit_mode == "OBJECT":
                    bpy.ops.object.mode_set(mode="EDIT")
                    bpy.ops.mesh.subdivide(number_cuts=cutnr, smoothness=1)
                    bpy.ops.mesh.faces_shade_smooth()
                    bpy.ops.object.mode_set(mode="OBJECT")
                else:
                    bpy.ops.mesh.subdivide(number_cuts=cutnr, smoothness=1)
                    bpy.ops.mesh.faces_shade_smooth()

                bpy.ops.ed.undo_push()
                # bpy.context.object.data.use_auto_smooth = as_check

                if self.itemize or self.edit_mode == "OBJECT":
                    bpy.ops.object.shade_smooth()
                    bpy.context.object.data.use_auto_smooth = True

            # -----------------------------------------------------------------------------------------
            # CYLINDER
            # -----------------------------------------------------------------------------------------
            else:
                bpy.ops.mesh.primitive_cylinder_add(vertices=self.cyl_sides,
                                                    radius=side,
                                                    depth=distance * 2,
                                                    enter_editmode=False,
                                                    align='WORLD',
                                                    location=setpos,
                                                    rotation=setrot)

                if self.modal:
                    if self.itemize or self.edit_mode == "OBJECT":
                        bpy.ops.object.mode_set(mode="EDIT")

                    self.settings = (side, distance, setpos, setrot)
                    context.window_manager.modal_handler_add(self)

                    self._timer = context.window_manager.event_timer_add(
                        0.5, window=context.window)

                    args = (self, context, self.screen_x)
                    self._handle = bpy.types.SpaceView3D.draw_handler_add(
                        draw_callback_px, args, 'WINDOW', 'POST_PIXEL')
                    bpy.context.space_data.overlay.show_cursor = False
                    return {'RUNNING_MODAL'}

            if multi_object_mode and not self.itemize:
                second_obj.select_set(state=True)
                obj.select_set(state=True)
                bpy.ops.object.editmode_toggle()
                bpy.ops.object.editmode_toggle()
        else:
            self.report({"INFO"},
                        "FitPrim: Invalid Selection / No Active Element?")

        if not self.select and not self.itemize and not self.edit_mode == "OBJECT":
            bpy.ops.mesh.select_all(action='DESELECT')

        if self.itemize:
            bpy.ops.transform.select_orientation(orientation=og_orientation)
            cursor.location = self.og_cloc
            cursor.rotation_euler = self.og_crot
            bpy.context.active_object.select_set(state=True)

        self.ke_fitprim_itemize = False
        return {"FINISHED"}
def extend(obj, EXTEND_MODE):
    import bmesh
    me = obj.data

    bm = bmesh.from_edit_mesh(me)

    faces = [f for f in bm.faces if f.select and len(f.verts) == 4]
    if not faces:
        return 0

    f_act = bm.faces.active

    if f_act is None:
        return STATUS_ERR_ACTIVE_FACE
    if not f_act.select:
        return STATUS_ERR_NOT_SELECTED
    elif len(f_act.verts) != 4:
        return STATUS_ERR_NOT_QUAD

    # Script will fail without UVs.
    if not me.uv_layers:
        me.uv_layers.new()

    uv_act = bm.loops.layers.uv.active

    # our own local walker
    def walk_face_init(faces, f_act):
        # first tag all faces True (so we don't uvmap them)
        for f in bm.faces:
            f.tag = True
        # then tag faces arg False
        for f in faces:
            f.tag = False
        # tag the active face True since we begin there
        f_act.tag = True

    def walk_face(f):
        # all faces in this list must be tagged
        f.tag = True
        faces_a = [f]
        faces_b = []

        while faces_a:
            for f in faces_a:
                for l in f.loops:
                    l_edge = l.edge
                    if (l_edge.is_manifold is True) and (l_edge.seam is False):
                        l_other = l.link_loop_radial_next
                        f_other = l_other.face
                        if not f_other.tag:
                            yield (f, l, f_other)
                            f_other.tag = True
                            faces_b.append(f_other)
            # swap
            faces_a, faces_b = faces_b, faces_a
            faces_b.clear()

    def walk_edgeloop(l):
        """
        Could make this a generic function
        """
        e_first = l.edge
        e = None
        while True:
            e = l.edge
            yield e

            # don't step past non-manifold edges
            if e.is_manifold:
                # welk around the quad and then onto the next face
                l = l.link_loop_radial_next
                if len(l.face.verts) == 4:
                    l = l.link_loop_next.link_loop_next
                    if l.edge is e_first:
                        break
                else:
                    break
            else:
                break

    def extrapolate_uv(
            fac,
            l_a_outer, l_a_inner,
            l_b_outer, l_b_inner,
    ):
        l_b_inner[:] = l_a_inner
        l_b_outer[:] = l_a_inner + ((l_a_inner - l_a_outer) * fac)

    def apply_uv(_f_prev, l_prev, _f_next):
        l_a = [None, None, None, None]
        l_b = [None, None, None, None]

        l_a[0] = l_prev
        l_a[1] = l_a[0].link_loop_next
        l_a[2] = l_a[1].link_loop_next
        l_a[3] = l_a[2].link_loop_next

        #  l_b
        #  +-----------+
        #  |(3)        |(2)
        #  |           |
        #  |l_next(0)  |(1)
        #  +-----------+
        #        ^
        #  l_a   |
        #  +-----------+
        #  |l_prev(0)  |(1)
        #  |    (f)    |
        #  |(3)        |(2)
        #  +-----------+
        #  copy from this face to the one above.

        # get the other loops
        l_next = l_prev.link_loop_radial_next
        if l_next.vert != l_prev.vert:
            l_b[1] = l_next
            l_b[0] = l_b[1].link_loop_next
            l_b[3] = l_b[0].link_loop_next
            l_b[2] = l_b[3].link_loop_next
        else:
            l_b[0] = l_next
            l_b[1] = l_b[0].link_loop_next
            l_b[2] = l_b[1].link_loop_next
            l_b[3] = l_b[2].link_loop_next

        l_a_uv = [l[uv_act].uv for l in l_a]
        l_b_uv = [l[uv_act].uv for l in l_b]

        if EXTEND_MODE == 'LENGTH_AVERAGE':
            d1 = edge_lengths[l_a[1].edge.index][0]
            d2 = edge_lengths[l_b[2].edge.index][0]
            try:
                fac = d2 / d1
            except ZeroDivisionError:
                fac = 1.0
        elif EXTEND_MODE == 'LENGTH':
            a0, b0, c0 = l_a[3].vert.co, l_a[0].vert.co, l_b[3].vert.co
            a1, b1, c1 = l_a[2].vert.co, l_a[1].vert.co, l_b[2].vert.co

            d1 = (a0 - b0).length + (a1 - b1).length
            d2 = (b0 - c0).length + (b1 - c1).length
            try:
                fac = d2 / d1
            except ZeroDivisionError:
                fac = 1.0
        else:
            fac = 1.0

        extrapolate_uv(fac,
                       l_a_uv[3], l_a_uv[0],
                       l_b_uv[3], l_b_uv[0])

        extrapolate_uv(fac,
                       l_a_uv[2], l_a_uv[1],
                       l_b_uv[2], l_b_uv[1])

    # -------------------------------------------
    # Calculate average length per loop if needed

    if EXTEND_MODE == 'LENGTH_AVERAGE':
        bm.edges.index_update()
        edge_lengths = [None] * len(bm.edges)

        for f in faces:
            # we know its a quad
            l_quad = f.loops[:]
            l_pair_a = (l_quad[0], l_quad[2])
            l_pair_b = (l_quad[1], l_quad[3])

            for l_pair in (l_pair_a, l_pair_b):
                if edge_lengths[l_pair[0].edge.index] is None:

                    edge_length_store = [-1.0]
                    edge_length_accum = 0.0
                    edge_length_total = 0

                    for l in l_pair:
                        if edge_lengths[l.edge.index] is None:
                            for e in walk_edgeloop(l):
                                if edge_lengths[e.index] is None:
                                    edge_lengths[e.index] = edge_length_store
                                    edge_length_accum += e.calc_length()
                                    edge_length_total += 1

                    edge_length_store[0] = edge_length_accum / edge_length_total

    # done with average length
    # ------------------------

    walk_face_init(faces, f_act)
    for f_triple in walk_face(f_act):
        apply_uv(*f_triple)

    bmesh.update_edit_mesh(me, False)
    return STATUS_OK
    def main(self, context, chboxVert0, chboxVert1, chboxVert2):
        finalizar_uniendocaras = True

        #almacena caras
        obj = bpy.context.object
        me = obj.data
        bm = bmesh.from_edit_mesh(me)

        listacaras = []

        for face in bm.faces:
            if face.select and len(face.verts) == 3:
                listacaras.append(face)
        #bmesh.update_edit_mesh(me, True)

        #################### separa caras
        separarcaras()
        ##########################
        #obj = bpy.context.object
        #me = obj.data
        #bm = bmesh.from_edit_mesh(me)

        #vuelve a seleccionar caras
        for face in listacaras:
            face.select = True

        ##########################
        obj = bpy.context.object
        me = obj.data
        bm = bmesh.from_edit_mesh(me)

        ### aplicar división

        for face in listacaras:
            if face.select:
                print("cara seleccionada")
                centro_cara = mathutils.Vector(
                    face.calc_center_median_weighted())

                if len(face.verts) == 3:
                    print("es un triangulo")
                    vertices = [v for v in face.verts]
                    print(len(vertices))
                    vv1, vv2, vv3 = [v for v in vertices]
                    print(vv1, vv2, vv3)
                    v1, v2, v3 = [v.co for v in vertices]
                    print("cordenada vertice  " + str(v1))
                    print("cordenada vertice  " + str(v2))
                    print("cordenada vertice  " + str(v3))

                    #agrupamos todas las aristas seleccionadas y no ocultas de la cara
                    aristas = [
                        a for a in face.edges if (a.select and not a.hide)
                    ]
                    #las asignamos a variables independientes
                    a1, a2, a3 = [a for a in aristas]
                    #creamos los largos de cada una de las aristas
                    l1, l2, l3 = [a.calc_length() for a in aristas]
                    print(l1, '\n', l2, '\n', l3)

                    #distancia entre vertices segun sus cordinadas
                    c = ((((v1[0]) - (v2[0]) * (v1[0]) - (v2[0]))),
                         (((v1[1]) - (v2[1]) * (v1[1]) - (v2[1]))),
                         (((v1[2]) - (v2[2]) * (v1[2]) - (v2[2]))))
                    print(c)

                    distancia1 = math.sqrt(math.fabs(c[0])) + math.sqrt(
                        math.fabs(c[1])) + math.sqrt(math.fabs(c[2]))

                    print(distancia1)

                    #divide uno de los bordes.
                    #mid_vec1 = v3.lerp(v2, razon_bisectriz1)
                    #bmesh.utils.edge_split(a2, a2.verts[0], 0.5)

                    #####################################
                    #llamo a la funcion que calcula los angulos:
                    #calcularangulos(l1,l2,l3)  #funcionando
                    #calcularbisectrices(l1,l2,l3,v1,v2,v3) #falta por comprobar

                    if chboxVert0:
                        vertice1 = True
                        calcularpuntobisectrices(face, l2, l3, l1, v2, v3, v1,
                                                 a2, a3, a1, vv2, vv3, vv1,
                                                 chboxVert0, chboxVert1,
                                                 chboxVert2)
                    if chboxVert1:
                        calcularpuntobisectrices(face, l1, l2, l3, v1, v2, v3,
                                                 a1, a2, a3, vv1, vv2, vv3,
                                                 chboxVert0, chboxVert1,
                                                 chboxVert2)
                    if chboxVert2:
                        calcularpuntobisectrices(face, l3, l1, l2, v3, v1, v2,
                                                 a3, a1, a2, vv3, vv1, vv2,
                                                 chboxVert0, chboxVert1,
                                                 chboxVert2)

                else:
                    print("DEBE SER UN TRIANGULO")
            else:
                print("cara no seleccionada")

        ## actualizar toda la malla
            bmesh.update_edit_mesh(me, True)

        if finalizar_uniendocaras:
            bpy.ops.mesh.select_all(action='SELECT')
            bpy.ops.mesh.remove_doubles()
            bpy.ops.mesh.select_all(action='DESELECT')
            return {'FINISHED'}
예제 #57
0
location_list = []
uv_list = []

uv_list.clear()
location_list.clear()

obj = bpy.context.active_object
for v in obj.data.vertices:
    vec = copy.copy(v.co)
    vec.x = random()
    vec.y = random()
    vec.z = random()
    location_list.append(vec)

uv_list = [p[:2] for p in location_list]

import bmesh
mesh = obj.data
bm = bmesh.from_edit_mesh(mesh)
uv_layer = bm.loops.layers.uv.active
for bm_face in bm.faces:
    id = bm_face.loops[0].vert.index
    print(id)
    for v in bm_face.loops:
        v[uv_layer].uv[0] = v[uv_layer].uv[0] + uv_list[id][0]
        v[uv_layer].uv[1] = v[uv_layer].uv[1] + uv_list[id][1]

bmesh.update_edit_mesh(mesh)
bpy.ops.object.editmode_toggle()
예제 #58
0
    def modal(self, context, event):

        if event.type == 'X':
            self.xlock = False
            self.ylock = True
        if event.type == 'Y':
            self.xlock = True
            self.ylock = False

        #test is middle mouse held down
        if event.type == 'MIDDLEMOUSE' and event.value == 'PRESS':
            self.constrainttest = True
        if event.type == 'MIDDLEMOUSE' and event.value == 'RELEASE':
            self.constrainttest = False

        #test if mouse is in the right quadrant for X or Y movement
        if self.constrainttest:
            mouseangle = math.atan2(event.mouse_y - self.first_mouse_y,
                                    event.mouse_x - self.first_mouse_x)
            mousetestx = False
            if (mouseangle < 0.785
                    and mouseangle > -0.785) or (mouseangle > 2.355
                                                 or mouseangle < -2.355):
                mousetestx = True
            if mousetestx:
                self.xlock = True
                self.ylock = False
            else:
                self.xlock = False
                self.ylock = True

        if event.type == 'MOUSEMOVE':

            deltax = self.first_mouse_x - event.mouse_x
            deltay = self.first_mouse_y - event.mouse_y

            if event.shift and not event.ctrl:
                #self.delta*=.1
                #reset origin position to shift into precision mode

                if not self.shiftreset:
                    self.shiftreset = True
                    self.first_mouse_x = event.mouse_x + 1000 / self.s2
                    self.first_mouse_y = event.mouse_y + 1000 / self.s2
                    for i, face in enumerate(self.bm.faces):
                        if face.select:
                            for o, vert in enumerate(face.loops):
                                self.bm2.faces[i].loops[o][
                                    self.bm2.loops.layers.uv.active].uv = vert[
                                        self.bm.loops.layers.uv.active].uv
                deltax = self.first_mouse_x - event.mouse_x
                deltay = self.first_mouse_y - event.mouse_y
                deltax *= 0.001 * self.s2
                deltay *= 0.001 * self.s2

            else:
                #reset origin position to shift into normal mode
                if self.shiftreset:
                    self.shiftreset = False
                    self.first_mouse_x = event.mouse_x + 1000 / self.s1
                    self.first_mouse_y = event.mouse_y + 1000 / self.s1
                    for i, face in enumerate(self.bm.faces):
                        if face.select:
                            for o, vert in enumerate(face.loops):
                                self.bm2.faces[i].loops[o][
                                    self.bm2.loops.layers.uv.active].uv = vert[
                                        self.bm.loops.layers.uv.active].uv
                deltax = self.first_mouse_x - event.mouse_x
                deltay = self.first_mouse_y - event.mouse_y
                deltax *= 0.001 * self.s1
                deltay *= 0.001 * self.s1

            if not self.xlock and not self.ylock:
                delta = (deltax + deltay) * .5
                deltax = delta
                deltay = delta

            if self.xlock:
                deltax = 1

            if self.ylock:
                deltay = 1

            if event.ctrl and not event.shift:
                deltax = math.floor(deltax * self.scale_snap) / self.scale_snap
                deltay = math.floor(deltay * self.scale_snap) / self.scale_snap
            if event.ctrl and event.shift:
                deltax = math.floor(
                    deltax * self.scale_snap *
                    self.scale_snap) / (self.scale_snap * self.scale_snap)
                deltay = math.floor(
                    deltay * self.scale_snap *
                    self.scale_snap) / (self.scale_snap * self.scale_snap)

            #loop through every selected face and move the uv's using original uv as reference
            for i, face in enumerate(self.bm.faces):
                if face.select:
                    for o, vert in enumerate(face.loops):

                        vert[self.bm.loops.layers.uv.active].uv.x = (
                            (deltax) * self.bm2.faces[i].loops[o][
                                self.bm2.loops.layers.uv.active].uv.x) + (
                                    (1 - (deltax)) * self.xcenter)
                        vert[self.bm.loops.layers.uv.active].uv.y = (
                            (deltay) * self.bm2.faces[i].loops[o][
                                self.bm2.loops.layers.uv.active].uv.y) + (
                                    (1 - (deltay)) * self.ycenter)

            #update mesh
            bmesh.update_edit_mesh(self.mesh, False, False)

        elif event.type == 'LEFTMOUSE':

            #finish up and make sure changes are locked in place
            bpy.ops.object.mode_set(mode='OBJECT')
            bpy.ops.object.mode_set(mode='EDIT')
            return {'FINISHED'}

        elif event.type in {'RIGHTMOUSE', 'ESC'}:

            #reset all uvs to reference
            for i, face in enumerate(self.bm.faces):
                if face.select:
                    for o, vert in enumerate(face.loops):
                        vert[self.bm.loops.layers.uv.
                             active].uv = self.bm2.faces[i].loops[o][
                                 self.bm2.loops.layers.uv.active].uv
            #update mesh
            bmesh.update_edit_mesh(self.mesh, False, False)
            return {'CANCELLED'}

        return {'RUNNING_MODAL'}
예제 #59
0
    def modal(self, context, event):
        #context.area.header_text_set(
        #    "DUV UVTranslate: X/Y - contrain along X/Y Axis, MMB drag - alternative axis contrain method, SHIFT - precision mode, CTRL - stepped mode, CTRL + SHIFT - stepped with smaller increments")
        #context.area.tag_redraw()

        # setup constraints first
        if event.type == 'X':
            self.stateswitch = True
            self.xlock = False
            self.ylock = True
        if event.type == 'Y':
            self.stateswitch = True
            self.xlock = True
            self.ylock = False

        # test is middle mouse held down
        if event.type == 'MIDDLEMOUSE' and event.value == 'PRESS':
            self.constrainttest = True
        if event.type == 'MIDDLEMOUSE' and event.value == 'RELEASE':
            self.constrainttest = False

        # test if mouse is in the right quadrant for X or Y movement
        if self.constrainttest:
            mouseangle = math.atan2(event.mouse_y - self.first_mouse_y,
                                    event.mouse_x - self.first_mouse_x)
            mousetestx = False
            if (mouseangle < 0.785
                    and mouseangle > -0.785) or (mouseangle > 2.355
                                                 or mouseangle < -2.355):
                mousetestx = True
            if mousetestx:
                self.xlock = False
                self.ylock = True
            else:
                self.xlock = True
                self.ylock = False
            if mousetestx is not self.mousetestx:
                self.stateswitch = True
                self.mousetestx = not self.mousetestx

        if self.stateswitch:
            self.stateswitch = False
            # reset to start editing from start position
            for i, face in enumerate(self.bm.faces):
                if face.select:
                    for o, vert in enumerate(face.loops):
                        reset_uv = self.bm2.faces[i].loops[o][
                            self.bm2.loops.layers.uv.active].uv
                        vert[self.bm.loops.layers.uv.active].uv = reset_uv

        if event.type == 'MOUSEMOVE':
            self.delta = ((self.first_mouse_x - event.mouse_x),
                          (self.first_mouse_y - event.mouse_y))

            sensitivity = 0.001 if not self.do_pixel_snap else 0.1

            self.delta = Vector(self.delta) * sensitivity

            if self.do_pixel_snap:
                self.delta.x = int(round(self.delta.x))
                self.delta.y = int(round(self.delta.y))

            if event.shift and not event.ctrl:
                self.delta *= .1
                # reset origin position to shift into precision mode
                if not self.shiftreset:
                    self.shiftreset = True
                    self.first_mouse_x = event.mouse_x
                    self.first_mouse_y = event.mouse_y
                    for i, face in enumerate(self.bm.faces):
                        if face.select:
                            for o, vert in enumerate(face.loops):
                                reset_uv = vert[
                                    self.bm.loops.layers.uv.active].uv
                                self.bm2.faces[i].loops[o][
                                    self.bm2.loops.layers.uv.
                                    active].uv = reset_uv
                    self.delta = (0, 0)
                    self.delta = Vector(self.delta)

            else:
                # reset origin position to shift into normal mode
                if self.shiftreset:
                    self.shiftreset = False
                    self.first_mouse_x = event.mouse_x
                    self.first_mouse_y = event.mouse_y
                    for i, face in enumerate(self.bm.faces):
                        if face.select:
                            for o, vert in enumerate(face.loops):
                                reset_uv = vert[
                                    self.bm.loops.layers.uv.active].uv
                                self.bm2.faces[i].loops[o][
                                    self.bm2.loops.layers.uv.
                                    active].uv = reset_uv
                    self.delta = (0, 0)
                    self.delta = Vector(self.delta)

            if event.ctrl and not event.shift:
                self.delta.x = math.floor(
                    self.delta.x * self.move_snap) / self.move_snap
                self.delta.y = math.floor(
                    self.delta.y * self.move_snap) / self.move_snap
            if event.ctrl and event.shift:
                self.delta.x = math.floor(
                    self.delta.x *
                    (self.move_snap * self.move_snap)) / (self.move_snap *
                                                          self.move_snap)
                self.delta.y = math.floor(
                    self.delta.y *
                    (self.move_snap * self.move_snap)) / (self.move_snap *
                                                          self.move_snap)

            # loop through every selected face and move the uv's using original uv as reference
            for i, face in enumerate(self.bm.faces):
                if face.select is False:
                    continue

                local_delta = self.delta.copy()
                if self.do_pixel_snap and face.index in self.pixel_steps.keys(
                ):
                    pixel_step = self.pixel_steps[face.index]
                    local_delta.x *= pixel_step.x
                    local_delta.y *= pixel_step.y

                uv_x_axis = Vector((1.0, 0.0))
                uv_y_axis = Vector((0.0, 1.0))

                if self.xlock:
                    uv_x_axis = Vector((0, 0))
                if self.ylock:
                    uv_y_axis = Vector((0, 0))

                for o, vert in enumerate(face.loops):
                    origin_uv = self.bm2.faces[i].loops[o][
                        self.bm2.loops.layers.uv.active].uv
                    uv_offset = local_delta.x * uv_x_axis + local_delta.y * uv_y_axis
                    vert[self.bm.loops.layers.uv.
                         active].uv = origin_uv + uv_offset

            # update mesh
            bmesh.update_edit_mesh(self.mesh, False, False)

        elif event.type == 'LEFTMOUSE':
            # finish up and make sure changes are locked in place
            bpy.ops.object.mode_set(mode='OBJECT')
            bpy.ops.object.mode_set(mode='EDIT')
            return {'FINISHED'}

        elif event.type in {'RIGHTMOUSE', 'ESC'}:

            # reset all uvs to reference
            for i, face in enumerate(self.bm.faces):
                if face.select:
                    for o, vert in enumerate(face.loops):
                        reset_uv = self.bm_orig.faces[i].loops[o][
                            self.bm_orig.loops.layers.uv.active].uv
                        vert[self.bm.loops.layers.uv.active].uv = reset_uv
            # update mesh
            bmesh.update_edit_mesh(self.mesh, False, False)
            return {'CANCELLED'}

        return {'RUNNING_MODAL'}
예제 #60
0
def expand_vert(self, context, event):
    addon_prefs = context.preferences.addons[__name__].preferences
    ob = context.active_object
    obj = bpy.context.object
    me = obj.data
    bm = bmesh.from_edit_mesh(me)
    region = context.region
    region_3d = context.space_data.region_3d
    rv3d = context.space_data.region_3d

    for v in bm.verts:
        if v.select:
            v_active = v

    try:
        depth_location = v_active.co
    except:
        return {'CANCELLED'}
    # create vert in mouse cursor location

    mouse_pos = Vector((event.mouse_region_x, event.mouse_region_y))
    location_3d = view3d_utils.region_2d_to_location_3d(region, rv3d, mouse_pos, depth_location)

    c_verts = []
    # find and select linked edges that are open (<2 faces connected) add those edge verts to c_verts list
    linked = v_active.link_edges
    for edges in linked:
        if len(edges.link_faces) < 2:
            edges.select = True
            for v in edges.verts:
                if v is not v_active:
                    c_verts.append(v)

    # Compare distance in 2d between mouse and edges middle points
    screen_pos_va = view3d_utils.location_3d_to_region_2d(region, region_3d,
                                                          ob.matrix_world @ v_active.co)
    screen_pos_v1 = view3d_utils.location_3d_to_region_2d(region, region_3d,
                                                          ob.matrix_world @ c_verts[0].co)
    screen_pos_v2 = view3d_utils.location_3d_to_region_2d(region, region_3d,
                                                          ob.matrix_world @ c_verts[1].co)

    mid_pos_v1 = Vector(((screen_pos_va[0] + screen_pos_v1[0]) / 2, (screen_pos_va[1] + screen_pos_v1[1]) / 2))
    mid_pos_V2 = Vector(((screen_pos_va[0] + screen_pos_v2[0]) / 2, (screen_pos_va[1] + screen_pos_v2[1]) / 2))

    dist1 = math.log10(pow((mid_pos_v1[0] - mouse_pos[0]), 2) + pow((mid_pos_v1[1] - mouse_pos[1]), 2))
    dist2 = math.log10(pow((mid_pos_V2[0] - mouse_pos[0]), 2) + pow((mid_pos_V2[1] - mouse_pos[1]), 2))

    bm.normal_update()
    bm.verts.ensure_lookup_table()

    # Deselect not needed point and create new face
    if dist1 < dist2:
        c_verts[1].select = False
        lleft = c_verts[0].link_faces

    else:
        c_verts[0].select = False
        lleft = c_verts[1].link_faces

    lactive = v_active.link_faces
    # lverts = lactive[0].verts

    mat_index = lactive[0].material_index
    smooth = lactive[0].smooth

    for faces in lactive:
        if faces in lleft:
            cface = faces
            if len(faces.verts) == 3:
                bm.normal_update()
                bmesh.update_edit_mesh(obj.data)
                bpy.ops.mesh.select_all(action='DESELECT')
                v_active.select = True
                bpy.ops.mesh.rip_edge_move('INVOKE_DEFAULT')
                return {'FINISHED'}

    lverts = cface.verts

    # create triangle with correct normal orientation
    # if You looking at that part - yeah... I know. I still dont get how blender calculates normals...

    # from L to R
    if dist1 < dist2:
        if (lverts[0] == v_active and lverts[3] == c_verts[0]) \
                or (lverts[2] == v_active and lverts[1] == c_verts[0]) \
                or (lverts[1] == v_active and lverts[0] == c_verts[0]) \
                or (lverts[3] == v_active and lverts[2] == c_verts[0]):
            v_new = bm.verts.new(v_active.co)
            face_new = bm.faces.new((c_verts[0], v_new, v_active))

        elif (lverts[1] == v_active and lverts[2] == c_verts[0]) \
                or (lverts[0] == v_active and lverts[1] == c_verts[0]) \
                or (lverts[3] == v_active and lverts[0] == c_verts[0]) \
                or (lverts[2] == v_active and lverts[3] == c_verts[0]):
            v_new = bm.verts.new(v_active.co)
            face_new = bm.faces.new((v_active, v_new, c_verts[0]))

        else:
            pass
    # from R to L
    else:
        if (lverts[2] == v_active and lverts[3] == c_verts[1]) \
                or (lverts[0] == v_active and lverts[1] == c_verts[1]) \
                or (lverts[1] == v_active and lverts[2] == c_verts[1]) \
                or (lverts[3] == v_active and lverts[0] == c_verts[1]):
            v_new = bm.verts.new(v_active.co)
            face_new = bm.faces.new((v_active, v_new, c_verts[1]))

        elif (lverts[0] == v_active and lverts[3] == c_verts[1]) \
                or (lverts[2] == v_active and lverts[1] == c_verts[1]) \
                or (lverts[1] == v_active and lverts[0] == c_verts[1]) \
                or (lverts[3] == v_active and lverts[2] == c_verts[1]):
            v_new = bm.verts.new(v_active.co)
            face_new = bm.faces.new((c_verts[1], v_new, v_active))

        else:
            pass

    # set smooth and mat based on starting face
    if addon_prefs.tris_from_v_mat:
        face_new.material_index = bpy.context.object.active_material_index
    else:
        face_new.material_index = mat_index
    face_new.smooth = smooth

    # update normals
    bpy.ops.mesh.select_all(action='DESELECT')
    v_new.select = True
    bm.select_history.add(v_new)

    bm.normal_update()
    bmesh.update_edit_mesh(obj.data)
    bpy.ops.transform.translate('INVOKE_DEFAULT')