From d0c0b7390a54be93a1b3448f3c50482a453b42c8 Mon Sep 17 00:00:00 2001 From: beta-tester <alpha-beta-release@gmx.net> Date: Sun, 11 Jan 2015 12:38:53 +0100 Subject: [PATCH] fixes issues ensure_lookup_table and grease_pencil, related to new blender 2.73 behavior. # blender 2.73 needs to call ensure_lookup_table() for bm.verts[], bm.edges[], bm.faces[]. # generically the fix will do this... # the lookup_table will get "dirty" after: # bm.new(), bm.from_mesh(), bm.from_edit_mesh() # bm.verts.new(), bm.edges.new(), bm.faces.new() # bm.verts.remove(), bm.edges.remove(), bm.faces.remove() # bm.normal_update(), bm.copy() # # bm.verts.ensure_lookup_table() ### 2.73 # bm.edges.ensure_lookup_table() ### 2.73 # bm.faces.ensure_lookup_table() ### 2.73 # blender 2.73 has a new grease_pencil per object and new per scene # gp = object.grease_pencil # if not gp: # gp = context.scene.grease_pencil --- mesh_looptools.py | 94 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 64 insertions(+), 30 deletions(-) diff --git a/mesh_looptools.py b/mesh_looptools.py index d6e98ecaf..cb1792729 100644 --- a/mesh_looptools.py +++ b/mesh_looptools.py @@ -19,8 +19,8 @@ bl_info = { "name": "LoopTools", "author": "Bart Crouch", - "version": (4, 6, 3), - "blender": (2, 71, 3), + "version": (4, 6, 5), + "blender": (2, 72, 2), "location": "View3D > Toolbar and View3D > Specials (W-key)", "warning": "", "description": "Mesh modelling toolkit. Several tools to aid modelling", @@ -29,6 +29,22 @@ bl_info = { "category": "Mesh", } +# blender 2.73 needs to call ensure_lookup_table() for bm.verts[], bm.edges[], bm.faces[]. +# generically the fix will do this... +# the lookup_table will get "dirty" after: +# bm.new(), bm.from_mesh(), bm.from_edit_mesh() +# bm.verts.new(), bm.edges.new(), bm.faces.new() +# bm.verts.remove(), bm.edges.remove(), bm.faces.remove() +# bm.normal_update(), bm.copy() +# +# bm.verts.ensure_lookup_table() ### 2.73 +# bm.edges.ensure_lookup_table() ### 2.73 +# bm.faces.ensure_lookup_table() ### 2.73 + +# blender 2.73 has a new grease_pencil per object and new per scene +# gp = object.grease_pencil +# if not gp: +# gp = context.scene.grease_pencil import bmesh import bpy @@ -47,6 +63,14 @@ from bpy_extras import view3d_utils looptools_cache = {} +### 2.73 +def get_grease_pencil(object, context): + gp = object.grease_pencil + if not gp: + gp = context.scene.grease_pencil + return gp + + # force a full recalculation next time def cache_delete(tool): if tool in looptools_cache: @@ -206,7 +230,6 @@ def calculate_linear_splines(bm_mod, tknots, knots): # calculate a best-fit plane to the given vertices def calculate_plane(bm_mod, loop, method="best_fit", object=False): - bm_mod.verts.ensure_lookup_table() # to work in 2.73 # getting the vertex locations locs = [bm_mod.verts[v].co.copy() for v in loop[0]] @@ -301,7 +324,6 @@ def calculate_splines(interpolation, bm_mod, tknots, knots): # check loops and only return valid ones def check_loops(loops, mapping, bm_mod): valid_loops = [] - bm_mod.verts.ensure_lookup_table() # to work in 2.73 for loop, circular in loops: # loop needs to have at least 3 vertices if len(loop) < 3: @@ -525,6 +547,10 @@ def get_derived_bmesh(object, bm, scene): derived = False bm_mod = bm + bm_mod.verts.ensure_lookup_table() ### 2.73 + bm_mod.edges.ensure_lookup_table() ### 2.73 + bm_mod.faces.ensure_lookup_table() ### 2.73 + return(derived, bm_mod) @@ -605,7 +631,6 @@ def get_parallel_loops(bm_mod, loops): connected_faces = dict_face_faces(bm_mod, edge_faces) # turn vertex loops into edge loops edgeloops = [] - bm_mod.faces.ensure_lookup_table() # to work in 2.73 for loop in loops: edgeloop = [[sorted([loop[0][i], loop[0][i+1]]) for i in \ range(len(loop[0])-1)], loop[1]] @@ -676,7 +701,7 @@ def get_parallel_loops(bm_mod, loops): sides.append(side_a) if side_b: sides.append(side_b) - + for side in sides: extraloop = [] for fi in side: @@ -740,6 +765,10 @@ def initialise(): bpy.ops.object.mode_set(mode='EDIT') bm = bmesh.from_edit_mesh(object.data) + bm.verts.ensure_lookup_table() ### 2.73 + bm.edges.ensure_lookup_table() ### 2.73 + bm.faces.ensure_lookup_table() ### 2.73 + return(global_undo, object, bm) @@ -780,13 +809,16 @@ def move_verts(object, bm, mapping, move, lock, influence): if influence < 0: new_loc = loc else: - bm.verts.ensure_lookup_table() new_loc = loc*(influence/100) + \ bm.verts[index].co*((100-influence)/100) bm.verts[index].co = new_loc bm.normal_update() object.data.update() + bm.verts.ensure_lookup_table() ### 2.73 + bm.edges.ensure_lookup_table() ### 2.73 + bm.faces.ensure_lookup_table() ### 2.73 + # load custom tool settings def settings_load(self): @@ -972,7 +1004,6 @@ def bridge_calculate_lines(bm, loops, mode, twist, reverse): # calculate loop centers centers = [] - bm.verts.ensure_lookup_table() # to work in 2.73 for loop in [loop1, loop2]: center = mathutils.Vector() for vertex in loop: @@ -1400,6 +1431,7 @@ edgekey_to_edge): def bridge_create_vertices(bm, vertices): for i in range(len(vertices)): bm.verts.new(vertices[i]) + bm.verts.ensure_lookup_table() ### 2.73 # add faces to mesh @@ -1423,13 +1455,14 @@ def bridge_create_faces(object, bm, faces, twist): new_faces = [] for i in range(len(faces)): - bm.faces.ensure_lookup_table() - bm.verts.ensure_lookup_table() new_faces.append(bm.faces.new([bm.verts[v] for v in faces[i]])) - bm.normal_update() object.data.update(calc_edges=True) # calc_edges prevents memory-corruption + bm.verts.ensure_lookup_table() ### 2.73 + bm.edges.ensure_lookup_table() ### 2.73 + bm.faces.ensure_lookup_table() ### 2.73 + return(new_faces) @@ -1511,7 +1544,6 @@ def bridge_match_loops(bm, loops): normal = mathutils.Vector() center = mathutils.Vector() for vertex in vertices: - bm.verts.ensure_lookup_table() normal += bm.verts[vertex].normal center += bm.verts[vertex].co normals.append(normal / len(vertices) / 10) @@ -1567,7 +1599,6 @@ def bridge_match_loops(bm, loops): # remove old_selected_faces def bridge_remove_internal_faces(bm, old_selected_faces): # collect bmesh faces and internal bmesh edges - bm.faces.ensure_lookup_table() remove_faces = [bm.faces[face] for face in old_selected_faces] edges = collections.Counter([edge.index for face in remove_faces for \ edge in face.edges]) @@ -1579,11 +1610,14 @@ def bridge_remove_internal_faces(bm, old_selected_faces): for edge in remove_edges: bm.edges.remove(edge) + bm.faces.ensure_lookup_table() ### 2.73 + bm.edges.ensure_lookup_table() ### 2.73 + bm.verts.ensure_lookup_table() ### 2.73 + # update list of internal faces that are flagged for removal def bridge_save_unused_faces(bm, old_selected_faces, loops): # key: vertex index, value: lists of selected faces using it - bm.faces.ensure_lookup_table() vertex_to_face = dict([[i, []] for i in range(len(bm.verts))]) [[vertex_to_face[vertex.index].append(face) for vertex in \ @@ -1788,7 +1822,6 @@ def circle_calculate_verts(flatten, bm_mod, locs_2d, com, p, q, normal): vert_edges = dict_vert_edges(bm_mod) vert_faces = dict_vert_faces(bm_mod) faces = [f for f in bm_mod.faces if not f.hide] - bm_mod.faces.ensure_lookup_table() # to work in 2.73 rays = [normal, -normal] new_locs = [] for loc in locs_3d: @@ -2264,7 +2297,6 @@ def curve_get_input(object, bm, boundaries, scene): vert_edges = dict_vert_edges(bm_mod) edge_faces = dict_edge_faces(bm_mod) correct_loops = [] - bm_mod.verts.ensure_lookup_table() # to work in 2.73 # find loops through each selected vertex while len(verts_unsorted) > 0: loops = curve_vertex_loops(bm_mod, verts_unsorted[0], vert_edges, @@ -2379,7 +2411,6 @@ def curve_project_knots(bm_mod, verts_selected, knots, points, circular): start = 1 end = -1 pknots = [mathutils.Vector(bm_mod.verts[knots[0]].co[:])] - bm_mod.verts.ensure_lookup_table() # to work in 2.73 for knot in knots[start:end]: if knot in verts_selected: knot_left = knot_right = False @@ -2679,6 +2710,7 @@ conversion_distance, conversion_max, conversion_min, conversion_vertices): mat_world * point.co)) # force even spreading of points, so they are placed on stroke method = 'regular' + bm_mod.verts.ensure_lookup_table() ### 2.73 bm_mod.verts.index_update() for stroke, verts_seq in stroke_verts: if len(verts_seq) < 2: @@ -2699,7 +2731,7 @@ conversion_distance, conversion_max, conversion_min, conversion_vertices): if m_stroke != stroke: continue bm_mod.edges.new((vert, verts_seq[point])) - + bm_mod.edges.ensure_lookup_table() ### 2.73 bmesh.update_edit_mesh(object.data) return(move) @@ -2776,8 +2808,8 @@ def gstretch_get_fake_strokes(object, bm_mod, loops): # get grease pencil strokes for the active object -def gstretch_get_strokes(object): - gp = object.grease_pencil +def gstretch_get_strokes(object, context): + gp = get_grease_pencil(object, context) if not gp: return(None) layer = gp.layers.active @@ -2802,9 +2834,7 @@ def gstretch_match_loops_strokes(loops, strokes, object, bm_mod): loop_centers = [] for loop in loops: center = mathutils.Vector() - for v_index in loop[0]: - bm_mod.verts.ensure_lookup_table() center += bm_mod.verts[v_index].co center /= len(loop[0]) center = object.matrix_world * center @@ -2988,7 +3018,6 @@ def relax_calculate_knots(loops): def relax_calculate_t(bm_mod, knots, points, regular): all_tknots = [] all_tpoints = [] - bm_mod.verts.ensure_lookup_table() # to work in 2.73 for i in range(len(knots)): amount = len(knots[i]) + len(points[i]) mix = [] @@ -3071,7 +3100,6 @@ def space_calculate_t(bm_mod, knots): tknots = [] loc_prev = False len_total = 0 - bm_mod.verts.ensure_lookup_table() # to work in 2.73 for k in knots: loc = mathutils.Vector(bm_mod.verts[k].co[:]) if not loc_prev: @@ -3841,31 +3869,37 @@ class GStretch(bpy.types.Operator): if safe_strokes: strokes = gstretch_safe_to_true_strokes(safe_strokes) # cached strokes were flushed (see operator's invoke function) - elif object.grease_pencil: - strokes = gstretch_get_strokes(object) + elif get_grease_pencil(object, context): + strokes = gstretch_get_strokes(object, context) else: # straightening function (no GP) -> loops ignore modifiers straightening = True derived = False bm_mod = bm.copy() + bm_mod.verts.ensure_lookup_table() ### 2.73 + bm_mod.edges.ensure_lookup_table() ### 2.73 + bm_mod.faces.ensure_lookup_table() ### 2.73 strokes = gstretch_get_fake_strokes(object, bm_mod, loops) if not straightening: derived, bm_mod = get_derived_bmesh(object, bm, context.scene) else: # get loops and strokes - if object.grease_pencil: + if get_grease_pencil(object, context): # find loops derived, bm_mod, loops = get_connected_input(object, bm, context.scene, input='selected') mapping = get_mapping(derived, bm, bm_mod, False, False, loops) loops = check_loops(loops, mapping, bm_mod) # get strokes - strokes = gstretch_get_strokes(object) + strokes = gstretch_get_strokes(object, context) else: # straightening function (no GP) -> loops ignore modifiers derived = False mapping = False bm_mod = bm.copy() + bm_mod.verts.ensure_lookup_table() ### 2.73 + bm_mod.edges.ensure_lookup_table() ### 2.73 + bm_mod.faces.ensure_lookup_table() ### 2.73 edge_keys = [edgekey(edge) for edge in bm_mod.edges if \ edge.select and not edge.hide] loops = get_connected_selections(edge_keys) @@ -3903,8 +3937,8 @@ class GStretch(bpy.types.Operator): if self.delete_strokes: if type(stroke) != bpy.types.GPencilStroke: # in case of cached fake stroke, get the real one - if object.grease_pencil: - strokes = gstretch_get_strokes(object) + if get_grease_pencil(object, context): + strokes = gstretch_get_strokes(object, context) if loops and strokes: ls_pairs = gstretch_match_loops_strokes(loops, strokes, object, bm_mod) -- GitLab