diff options
Diffstat (limited to 'uv_magic_uv/common.py')
-rw-r--r-- | uv_magic_uv/common.py | 180 |
1 files changed, 174 insertions, 6 deletions
diff --git a/uv_magic_uv/common.py b/uv_magic_uv/common.py index bad88167..83c6ae74 100644 --- a/uv_magic_uv/common.py +++ b/uv_magic_uv/common.py @@ -41,10 +41,10 @@ __all__ = [ 'debug_print', 'check_version', 'redraw_all_areas', - 'get_space', - 'mouse_on_region', - 'mouse_on_area', - 'mouse_on_regions', + 'get_space_legacy', + 'mouse_on_region_legacy', + 'mouse_on_area_legacy', + 'mouse_on_regions_legacy', 'create_bmesh', 'create_new_uv_map', 'get_island_info', @@ -54,7 +54,7 @@ __all__ = [ 'calc_polygon_2d_area', 'calc_polygon_3d_area', 'measure_mesh_area', - 'measure_uv_area', + 'measure_uv_area_legacy', 'diff_point_to_segment', 'get_loop_sequences', 'get_overlapped_uv_info', @@ -119,6 +119,70 @@ def redraw_all_areas(): area.tag_redraw() +def get_space_legacy(area_type, region_type, space_type): + """ + Get current area/region/space + """ + + area = None + region = None + space = None + + for area in bpy.context.screen.areas: + if area.type == area_type: + break + else: + return (None, None, None) + for region in area.regions: + if region.type == region_type: + break + for space in area.spaces: + if space.type == space_type: + break + + return (area, region, space) + + +def mouse_on_region_legacy(event, area_type, region_type): + pos = Vector((event.mouse_x, event.mouse_y)) + + _, region, _ = get_space_legacy(area_type, region_type, "") + if region is None: + return False + + if (pos.x > region.x) and (pos.x < region.x + region.width) and \ + (pos.y > region.y) and (pos.y < region.y + region.height): + return True + + return False + + +def mouse_on_area_legacy(event, area_type): + pos = Vector((event.mouse_x, event.mouse_y)) + + area, _, _ = get_space_legacy(area_type, "", "") + if area is None: + return False + + if (pos.x > area.x) and (pos.x < area.x + area.width) and \ + (pos.y > area.y) and (pos.y < area.y + area.height): + return True + + return False + + +def mouse_on_regions_legacy(event, area_type, regions): + if not mouse_on_area_legacy(event, area_type): + return False + + for region in regions: + result = mouse_on_region_legacy(event, area_type, region) + if result: + return True + + return False + + def get_space(area_type, region_type, space_type): """ Get current area/region/space @@ -135,10 +199,16 @@ def get_space(area_type, region_type, space_type): return (None, None, None) for region in area.regions: if region.type == region_type: + if region.width <= 1 or region.height <= 1: + continue break + else: + return (area, None, None) for space in area.spaces: if space.type == space_type: break + else: + return (area, region, None) return (area, region, space) @@ -390,7 +460,7 @@ def measure_mesh_area(obj): return mesh_area -def measure_uv_area(obj, tex_size=None): +def measure_uv_area_legacy(obj, tex_size=None): bm = bmesh.from_edit_mesh(obj.data) if check_version(2, 73, 0) >= 0: bm.verts.ensure_lookup_table() @@ -449,6 +519,88 @@ def measure_uv_area(obj, tex_size=None): return uv_area +def find_texture_layer(bm): + if check_version(2, 80, 0) >= 0: + return None + if bm.faces.layers.tex is None: + return None + + return bm.faces.layers.tex.verify() + + +def find_texture_nodes(obj): + nodes = [] + for mat in obj.material_slots: + if not mat.material.node_tree: + continue + for node in mat.material.node_tree.nodes: + tex_node_types = [ + 'TEX_ENVIRONMENT', + 'TEX_IMAGE', + ] + if node.type not in tex_node_types: + continue + if not node.image: + continue + nodes.append(node) + + return nodes + + +def find_image(obj, face=None, tex_layer=None): + # try to find from texture_layer + img = None + if tex_layer and face: + img = face[tex_layer].image + + # not found, then try to search from node + if not img: + nodes = find_texture_nodes(obj) + if len(nodes) >= 2: + raise RuntimeError("Find more than 2 texture nodes") + img = nodes[0].image + + return img + + +def measure_uv_area(obj, tex_size=None): + bm = bmesh.from_edit_mesh(obj.data) + if check_version(2, 73, 0) >= 0: + bm.verts.ensure_lookup_table() + bm.edges.ensure_lookup_table() + bm.faces.ensure_lookup_table() + + if not bm.loops.layers.uv: + return None + uv_layer = bm.loops.layers.uv.verify() + + tex_layer = find_texture_layer(bm) + + sel_faces = [f for f in bm.faces if f.select] + + # measure + uv_area = 0.0 + for f in sel_faces: + uvs = [l[uv_layer].uv for l in f.loops] + f_uv_area = calc_polygon_2d_area(uvs) + + # user specified + if tex_size: + uv_area = uv_area + f_uv_area * tex_size[0] * tex_size[1] + continue + + img = find_image(obj, f, tex_layer) + + # can not find from node, so we can not get texture size + if not img: + return None + + img_size = img.size + uv_area = uv_area + f_uv_area * img_size[0] * img_size[1] + + return uv_area + + def diff_point_to_segment(a, b, p): ab = b - a normal_ab = ab.normalized() @@ -941,6 +1093,9 @@ def __do_weiler_atherton_cliping(clip, subject, uv_layer, mode): if result != current: print("Internal Error") return None + if not exiting: + print("Internal Error: No exiting UV") + return None # enter if entering.count(current) >= 1: @@ -949,10 +1104,20 @@ def __do_weiler_atherton_cliping(clip, subject, uv_layer, mode): current_list.find_and_next(current) current = current_list.get() + prev = None + error = False while exiting.count(current) == 0: p.append(current.copy()) current_list.find_and_next(current) current = current_list.get() + if prev == current: + error = True + break + prev = current + + if error: + print("Internal Error: Infinite loop") + return None # exit p.append(current.copy()) @@ -975,6 +1140,9 @@ def __do_weiler_atherton_cliping(clip, subject, uv_layer, mode): current_uv = traverse(current_uv_list, current_entering, current_exiting, poly, current_uv, other_uv_list) + if current_uv is None: + break + if current_uv_list == subject_uvs: current_uv_list = clip_uvs other_uv_list = subject_uvs |