diff options
author | Joerg Mueller <nexyon@gmail.com> | 2011-07-22 01:11:58 +0400 |
---|---|---|
committer | Joerg Mueller <nexyon@gmail.com> | 2011-07-22 01:11:58 +0400 |
commit | 4532bd731d5edbe348d4df810856f6bdfdea705c (patch) | |
tree | 778fdcd594b5f384eacf5cd82f50afc10bbed513 /release/scripts/modules | |
parent | cf34f7509f4ea8c3f0c92045933f089c72de5313 (diff) | |
parent | bbfe3c9c49523d3987a3144da119d8f6afd09cf9 (diff) |
Merge with trunk up to r38584.
Diffstat (limited to 'release/scripts/modules')
-rw-r--r-- | release/scripts/modules/addon_utils.py | 12 | ||||
-rw-r--r-- | release/scripts/modules/bpy/path.py | 13 | ||||
-rw-r--r-- | release/scripts/modules/bpy/utils.py | 9 | ||||
-rw-r--r-- | release/scripts/modules/bpy_extras/image_utils.py | 6 | ||||
-rw-r--r-- | release/scripts/modules/bpy_extras/io_utils.py | 41 | ||||
-rw-r--r-- | release/scripts/modules/bpy_extras/mesh_utils.py | 73 |
6 files changed, 145 insertions, 9 deletions
diff --git a/release/scripts/modules/addon_utils.py b/release/scripts/modules/addon_utils.py index 07f1dc618dc..cf74282d064 100644 --- a/release/scripts/modules/addon_utils.py +++ b/release/scripts/modules/addon_utils.py @@ -31,6 +31,8 @@ __all__ = ( import bpy as _bpy +error_duplicates = False + def paths(): # RELEASE SCRIPTS: official scripts distributed in Blender releases paths = _bpy.utils.script_paths("addons") @@ -47,8 +49,11 @@ def paths(): def modules(module_cache): + global error_duplicates import os + error_duplicates = False + path_list = paths() # fake module importing @@ -117,7 +122,12 @@ def modules(module_cache): modules_stale -= {mod_name} mod = module_cache.get(mod_name) if mod: - if mod.__time__ != os.path.getmtime(mod_path): + if mod.__file__ != mod_path: + print("multiple addons with the same name:\n %r\n %r" % + (mod.__file__, mod_path)) + error_duplicates = True + + elif mod.__time__ != os.path.getmtime(mod_path): print("reloading addon:", mod_name, mod.__time__, os.path.getmtime(mod_path), mod_path) del module_cache[mod_name] mod = None diff --git a/release/scripts/modules/bpy/path.py b/release/scripts/modules/bpy/path.py index 5e95428f641..f6254efac2e 100644 --- a/release/scripts/modules/bpy/path.py +++ b/release/scripts/modules/bpy/path.py @@ -35,7 +35,7 @@ def abspath(path, start=None): :type start: string """ if path.startswith("//"): - return _os.path.join(_os.path.dirname(_bpy.data.filepath if start is None else start), path[2:]) + return _os.path.join(_os.path.dirname(_bpy.data.filepath) if start is None else start, path[2:]) return path @@ -117,7 +117,7 @@ def display_name_from_filepath(name): """ Returns the path stripped of directort and extension, ensured to be utf8 compatible. """ - return _os.path.splitext(_os.path.basename(name))[0].encode("utf8", "replace").decode("utf8") + return _os.path.splitext(basename(name))[0].encode("utf8", "replace").decode("utf8") def resolve_ncase(path): @@ -231,3 +231,12 @@ def module_names(path, recursive=False): modules.append(("%s.%s" % (filename, mod_name), mod_path)) return modules + + +def basename(path): + """ + Equivalent to os.path.basename, but skips a "//" suffix. + + Use for Windows compatibility. + """ + return _os.path.basename(path[2:] if path.startswith("//") else path) diff --git a/release/scripts/modules/bpy/utils.py b/release/scripts/modules/bpy/utils.py index 7c0d3d24cba..57d3e6dd703 100644 --- a/release/scripts/modules/bpy/utils.py +++ b/release/scripts/modules/bpy/utils.py @@ -298,11 +298,18 @@ _presets = _os.path.join(_scripts[0], "presets") # FIXME - multiple paths def preset_paths(subdir): """ Returns a list of paths for a specific preset. + + :arg subdir: preset subdirectory (must not be an absolute path). + :type subdir: string + :return: script paths. + :rtype: list """ dirs = [] for path in script_paths("presets", all=True): directory = _os.path.join(path, subdir) - if _os.path.isdir(directory): + if not directory.startswith(path): + raise Exception("invalid subdir given %r" % subdir) + elif _os.path.isdir(directory): dirs.append(directory) return dirs diff --git a/release/scripts/modules/bpy_extras/image_utils.py b/release/scripts/modules/bpy_extras/image_utils.py index f91535a0ad4..e56c1c651c4 100644 --- a/release/scripts/modules/bpy_extras/image_utils.py +++ b/release/scripts/modules/bpy_extras/image_utils.py @@ -86,7 +86,9 @@ def load_image(imagepath, variants = [imagepath] if dirname: - variants += [os.path.join(dirname, imagepath), os.path.join(dirname, os.path.basename(imagepath))] + variants += [os.path.join(dirname, imagepath), + os.path.join(dirname, bpy.path.basename(imagepath)), + ] for filepath_test in variants: if ncase_cmp: @@ -99,7 +101,7 @@ def load_image(imagepath, return _image_load(nfilepath) if place_holder: - image = bpy.data.images.new(os.path.basename(imagepath), 128, 128) + image = bpy.data.images.new(bpy.path.basename(imagepath), 128, 128) # allow the path to be resolved later image.filepath = imagepath return image diff --git a/release/scripts/modules/bpy_extras/io_utils.py b/release/scripts/modules/bpy_extras/io_utils.py index cfa2233f7b6..9545e20b025 100644 --- a/release/scripts/modules/bpy_extras/io_utils.py +++ b/release/scripts/modules/bpy_extras/io_utils.py @@ -22,6 +22,7 @@ __all__ = ( "ExportHelper", "ImportHelper", "axis_conversion", + "axis_conversion_ensure", "create_derived_objects", "free_derived_objects", "unpack_list", @@ -154,12 +155,50 @@ def axis_conversion(from_forward='Y', from_up='Z', to_forward='Y', to_up='Z'): if from_forward == to_forward and from_up == to_up: return Matrix().to_3x3() + if from_forward[-1] == from_up[-1] or to_forward[-1] == to_up[-1]: + raise Exception("invalid axis arguments passed, " + "can't use up/forward on the same axis.") + value = reduce(int.__or__, (_axis_convert_num[a] << (i * 3) for i, a in enumerate((from_forward, from_up, to_forward, to_up)))) for i, axis_lut in enumerate(_axis_convert_lut): if value in axis_lut: return Matrix(_axis_convert_matrix[i]) - assert("internal error") + assert(0) + + +def axis_conversion_ensure(operator, forward_attr, up_attr): + """ + Function to ensure an operator has valid axis conversion settings, intended + to be used from :class:`Operator.check`. + + :arg operator: the operator to access axis attributes from. + :type operator: :class:`Operator` + :arg forward_attr: + :type forward_attr: string + :arg up_attr: the directory the *filepath* will be referenced from (normally the export path). + :type up_attr: string + :return: True if the value was modified. + :rtype: boolean + """ + def validate(axis_forward, axis_up): + if axis_forward[-1] == axis_up[-1]: + axis_up = axis_up[0:-1] + 'XYZ'[('XYZ'.index(axis_up[-1]) + 1) % 3] + + return axis_forward, axis_up + + change = False + + axis = getattr(operator, forward_attr), getattr(operator, up_attr) + axis_new = validate(*axis) + + if axis != axis_new: + setattr(operator, forward_attr, axis_new[0]) + setattr(operator, up_attr, axis_new[1]) + + return True + else: + return False # return a tuple (free, object list), free is True if memory should be freed later with free_derived_objects() diff --git a/release/scripts/modules/bpy_extras/mesh_utils.py b/release/scripts/modules/bpy_extras/mesh_utils.py index 34925ccb5e9..c42d3d0236a 100644 --- a/release/scripts/modules/bpy_extras/mesh_utils.py +++ b/release/scripts/modules/bpy_extras/mesh_utils.py @@ -16,7 +16,7 @@ # # ##### END GPL LICENSE BLOCK ##### -# <pep8 compliant> +# <pep8-80 compliant> __all__ = ( "mesh_linked_faces", @@ -25,6 +25,7 @@ __all__ = ( "edge_loops_from_faces", "edge_loops_from_edges", "ngon_tesselate", + "face_random_points", ) @@ -67,7 +68,8 @@ def mesh_linked_faces(mesh): if mapped_index != nxt_mapped_index: ok = True - # Assign mapping to this group so they all map to this group + # Assign mapping to this group so they + # all map to this group for grp_f in face_groups[nxt_mapped_index]: face_mapping[grp_f.index] = mapped_index @@ -433,3 +435,70 @@ def ngon_tesselate(from_data, indices, fix_loops=True): fill[i] = tuple([ii for ii in reversed(fi)]) return fill + + +def face_random_points(num_points, faces): + """ + Generates a list of random points over mesh faces. + + :arg num_points: the number of random points to generate on each face. + :type int: + :arg faces: list of the faces to generate points on. + :type faces: :class:`MeshFaces`, sequence + :return: list of random points over all faces. + :rtype: list + """ + + from random import random + from mathutils.geometry import area_tri + + # Split all quads into 2 tris, tris remain unchanged + tri_faces = [] + for f in faces: + tris = [] + verts = f.id_data.vertices + fv = f.vertices[:] + tris.append((verts[fv[0]].co, + verts[fv[1]].co, + verts[fv[2]].co, + )) + if len(fv) == 4: + tris.append((verts[fv[0]].co, + verts[fv[3]].co, + verts[fv[2]].co, + )) + tri_faces.append(tris) + + # For each face, generate the required number of random points + sampled_points = [None] * (num_points * len(faces)) + for i, tf in enumerate(tri_faces): + for k in range(num_points): + # If this is a quad, we need to weight its 2 tris by their area + if len(tf) != 1: + area1 = area_tri(*tf[0]) + area2 = area_tri(*tf[1]) + area_tot = area1 + area2 + + area1 = area1 / area_tot + area2 = area2 / area_tot + + vecs = tf[0 if (random() < area1) else 1] + else: + vecs = tf[0] + + u1 = random() + u2 = random() + u_tot = u1 + u2 + + if u_tot > 1: + u1 = 1.0 - u1 + u2 = 1.0 - u2 + + side1 = vecs[1] - vecs[0] + side2 = vecs[2] - vecs[0] + + p = vecs[0] + u1 * side1 + u2 * side2 + + sampled_points[num_points * i + k] = p + + return sampled_points |