Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'release/scripts/modules/bpy_extras')
-rw-r--r--release/scripts/modules/bpy_extras/anim_utils.py56
-rw-r--r--release/scripts/modules/bpy_extras/io_utils.py65
-rw-r--r--release/scripts/modules/bpy_extras/keyconfig_utils.py8
-rw-r--r--release/scripts/modules/bpy_extras/object_utils.py58
-rw-r--r--release/scripts/modules/bpy_extras/view3d_utils.py37
5 files changed, 185 insertions, 39 deletions
diff --git a/release/scripts/modules/bpy_extras/anim_utils.py b/release/scripts/modules/bpy_extras/anim_utils.py
index d87c207e2d0..021a8bbb530 100644
--- a/release/scripts/modules/bpy_extras/anim_utils.py
+++ b/release/scripts/modules/bpy_extras/anim_utils.py
@@ -25,6 +25,7 @@ __all__ = (
import bpy
+# XXX visual keying is actually always considered as True in this code...
def bake_action(frame_start,
frame_end,
frame_step=1,
@@ -73,7 +74,7 @@ def bake_action(frame_start,
# -------------------------------------------------------------------------
# Helper Functions and vars
- def pose_frame_info(obj, do_visual_keying):
+ def pose_frame_info(obj):
matrix = {}
for name, pbone in obj.pose.bones.items():
if do_visual_keying:
@@ -84,16 +85,29 @@ def bake_action(frame_start,
return matrix
if do_parents_clear:
- def obj_frame_info(obj, do_visual_keying):
- parent = obj.parent
- matrix = obj.matrix_local if do_visual_keying else obj.matrix_local
- if parent:
- return parent.matrix_world * matrix
- else:
- return matrix.copy()
+ if do_visual_keying:
+ def obj_frame_info(obj):
+ return obj.matrix_world.copy()
+ else:
+ def obj_frame_info(obj):
+ parent = obj.parent
+ matrix = obj.matrix_basis
+ if parent:
+ return parent.matrix_world * matrix
+ else:
+ return matrix.copy()
else:
- def obj_frame_info(obj, do_visual_keying):
- return obj.matrix_local.copy() if do_visual_keying else obj.matrix_local.copy()
+ if do_visual_keying:
+ def obj_frame_info(obj):
+ parent = obj.parent
+ matrix = obj.matrix_world
+ if parent:
+ return parent.matrix_world.inverted_safe() * matrix
+ else:
+ return matrix.copy()
+ else:
+ def obj_frame_info(obj):
+ return obj.matrix_basis.copy()
# -------------------------------------------------------------------------
# Setup the Context
@@ -123,9 +137,16 @@ def bake_action(frame_start,
scene.frame_set(f)
scene.update()
if do_pose:
- pose_info.append(pose_frame_info(obj, do_visual_keying))
+ pose_info.append(pose_frame_info(obj))
if do_object:
- obj_info.append(obj_frame_info(obj, do_visual_keying))
+ obj_info.append(obj_frame_info(obj))
+
+ # -------------------------------------------------------------------------
+ # Clean (store initial data)
+ if do_clean and action is not None:
+ clean_orig_data = {fcu: {p.co[1] for p in fcu.keyframe_points} for fcu in action.fcurves}
+ else:
+ clean_orig_data = {}
# -------------------------------------------------------------------------
# Create action
@@ -216,12 +237,19 @@ def bake_action(frame_start,
if do_clean:
for fcu in action.fcurves:
+ fcu_orig_data = clean_orig_data.get(fcu, set())
+
keyframe_points = fcu.keyframe_points
i = 1
- while i < len(fcu.keyframe_points) - 1:
+ while i < len(keyframe_points) - 1:
+ val = keyframe_points[i].co[1]
+
+ if val in fcu_orig_data:
+ i += 1
+ continue
+
val_prev = keyframe_points[i - 1].co[1]
val_next = keyframe_points[i + 1].co[1]
- val = keyframe_points[i].co[1]
if abs(val - val_prev) + abs(val - val_next) < 0.0001:
keyframe_points.remove(keyframe_points[i])
diff --git a/release/scripts/modules/bpy_extras/io_utils.py b/release/scripts/modules/bpy_extras/io_utils.py
index b1877a9d439..65ccc3f8dc3 100644
--- a/release/scripts/modules/bpy_extras/io_utils.py
+++ b/release/scripts/modules/bpy_extras/io_utils.py
@@ -21,6 +21,7 @@
__all__ = (
"ExportHelper",
"ImportHelper",
+ "orientation_helper_factory",
"axis_conversion",
"axis_conversion_ensure",
"create_derived_objects",
@@ -34,7 +35,11 @@ __all__ = (
)
import bpy
-from bpy.props import StringProperty, BoolProperty, EnumProperty
+from bpy.props import (
+ StringProperty,
+ BoolProperty,
+ EnumProperty,
+ )
def _check_axis_conversion(op):
@@ -60,6 +65,12 @@ class ExportHelper:
options={'HIDDEN'},
)
+ # needed for mix-ins
+ order = [
+ "filepath",
+ "check_existing",
+ ]
+
# subclasses can override with decorator
# True == use ext, False == no ext, None == do nothing.
check_extension = True
@@ -108,6 +119,11 @@ class ImportHelper:
subtype='FILE_PATH',
)
+ # needed for mix-ins
+ order = [
+ "filepath",
+ ]
+
def invoke(self, context, event):
context.window_manager.fileselect_add(self)
return {'RUNNING_MODAL'}
@@ -116,6 +132,51 @@ class ImportHelper:
return _check_axis_conversion(self)
+def orientation_helper_factory(name, axis_forward='Y', axis_up='Z'):
+ members = {}
+
+ def _update_axis_forward(self, context):
+ if self.axis_forward[-1] == self.axis_up[-1]:
+ self.axis_up = self.axis_up[0:-1] + 'XYZ'[('XYZ'.index(self.axis_up[-1]) + 1) % 3]
+
+ members['axis_forward'] = EnumProperty(
+ name="Forward",
+ items=(('X', "X Forward", ""),
+ ('Y', "Y Forward", ""),
+ ('Z', "Z Forward", ""),
+ ('-X', "-X Forward", ""),
+ ('-Y', "-Y Forward", ""),
+ ('-Z', "-Z Forward", ""),
+ ),
+ default=axis_forward,
+ update=_update_axis_forward,
+ )
+
+ def _update_axis_up(self, context):
+ if self.axis_up[-1] == self.axis_forward[-1]:
+ self.axis_forward = self.axis_forward[0:-1] + 'XYZ'[('XYZ'.index(self.axis_forward[-1]) + 1) % 3]
+
+ members['axis_up'] = EnumProperty(
+ name="Up",
+ items=(('X', "X Up", ""),
+ ('Y', "Y Up", ""),
+ ('Z', "Z Up", ""),
+ ('-X', "-X Up", ""),
+ ('-Y', "-Y Up", ""),
+ ('-Z', "-Z Up", ""),
+ ),
+ default=axis_up,
+ update=_update_axis_up,
+ )
+
+ members["order"] = [
+ "axis_forward",
+ "axis_up",
+ ]
+
+ return type(name, (object,), members)
+
+
# Axis conversion function, not pretty LUT
# use lookup table to convert between any axis
_axis_convert_matrix = (
@@ -311,7 +372,7 @@ def unpack_list(list_of_tuples):
# same as above except that it adds 0 for triangle faces
def unpack_face_list(list_of_tuples):
- #allocate the entire list
+ # allocate the entire list
flat_ls = [0] * (len(list_of_tuples) * 4)
i = 0
diff --git a/release/scripts/modules/bpy_extras/keyconfig_utils.py b/release/scripts/modules/bpy_extras/keyconfig_utils.py
index c50b320dceb..7e4c9e885e7 100644
--- a/release/scripts/modules/bpy_extras/keyconfig_utils.py
+++ b/release/scripts/modules/bpy_extras/keyconfig_utils.py
@@ -32,7 +32,10 @@ KM_HIERARCHY = [
('View2D', 'EMPTY', 'WINDOW', []), # view 2d navigation (per region)
('View2D Buttons List', 'EMPTY', 'WINDOW', []), # view 2d with buttons navigation
('Header', 'EMPTY', 'WINDOW', []), # header stuff (per region)
- ('Grease Pencil', 'EMPTY', 'WINDOW', []), # grease pencil stuff (per region)
+
+ ('Grease Pencil', 'EMPTY', 'WINDOW', [ # grease pencil stuff (per region)
+ ('Grease Pencil Stroke Edit Mode', 'EMPTY', 'WINDOW', []),
+ ]),
('3D View', 'VIEW_3D', 'WINDOW', [ # view 3d navigation and generic stuff (select, transform)
('Object Mode', 'EMPTY', 'WINDOW', []),
@@ -56,6 +59,7 @@ KM_HIERARCHY = [
('Knife Tool Modal Map', 'EMPTY', 'WINDOW', []),
('Paint Stroke Modal', 'EMPTY', 'WINDOW', []),
+ ('Paint Curve', 'EMPTY', 'WINDOW', []),
('Object Non-modal', 'EMPTY', 'WINDOW', []), # mode change
@@ -241,7 +245,7 @@ def keyconfig_export(wm, kc, filepath):
# the default blender keyconfig, recreating the current setup from a fresh blender
# without needing to export keymaps which haven't been edited.
- class FakeKeyConfig():
+ class FakeKeyConfig:
keymaps = []
edited_kc = FakeKeyConfig()
for km in wm.keyconfigs.user.keymaps:
diff --git a/release/scripts/modules/bpy_extras/object_utils.py b/release/scripts/modules/bpy_extras/object_utils.py
index 01390760c76..c2c306e5145 100644
--- a/release/scripts/modules/bpy_extras/object_utils.py
+++ b/release/scripts/modules/bpy_extras/object_utils.py
@@ -31,7 +31,11 @@ __all__ = (
import bpy
-from bpy.props import BoolProperty, FloatVectorProperty
+from bpy.props import (
+ BoolProperty,
+ BoolVectorProperty,
+ FloatVectorProperty,
+ )
def add_object_align_init(context, operator):
@@ -99,7 +103,7 @@ def add_object_align_init(context, operator):
return location * rotation
-def object_data_add(context, obdata, operator=None, use_active_layer=True):
+def object_data_add(context, obdata, operator=None, use_active_layer=True, name=None):
"""
Add an object using the view context and preference to to initialize the
location, rotation and layer.
@@ -110,6 +114,8 @@ def object_data_add(context, obdata, operator=None, use_active_layer=True):
:type obdata: valid object data type or None.
:arg operator: The operator, checked for location and rotation properties.
:type operator: :class:`bpy.types.Operator`
+ :arg name: Optional name
+ :type name: string
:return: the newly created object in the scene.
:rtype: :class:`bpy.types.ObjectBase`
"""
@@ -119,7 +125,10 @@ def object_data_add(context, obdata, operator=None, use_active_layer=True):
for ob in scene.objects:
ob.select = False
- obj_new = bpy.data.objects.new(obdata.name, obdata)
+ if name is None:
+ name = "Object" if obdata is None else obdata.name
+
+ obj_new = bpy.data.objects.new(name, obdata)
base = scene.objects.link(obj_new)
base.select = True
@@ -128,16 +137,22 @@ def object_data_add(context, obdata, operator=None, use_active_layer=True):
if context.space_data and context.space_data.type == 'VIEW_3D':
v3d = context.space_data
- if use_active_layer:
- if v3d and v3d.local_view:
- base.layers_from_view(context.space_data)
- base.layers[scene.active_layer] = True
- else:
- base.layers = [True if i == scene.active_layer
- else False for i in range(len(scene.layers))]
+ if operator is not None and any(operator.layers):
+ base.layers = operator.layers
else:
- if v3d:
- base.layers_from_view(context.space_data)
+ if use_active_layer:
+ if v3d and v3d.local_view:
+ base.layers_from_view(context.space_data)
+ base.layers[scene.active_layer] = True
+ else:
+ base.layers = [True if i == scene.active_layer
+ else False for i in range(len(scene.layers))]
+ else:
+ if v3d:
+ base.layers_from_view(context.space_data)
+
+ if operator is not None:
+ operator.layers = base.layers
obj_new.matrix_world = add_object_align_init(context, operator)
@@ -150,7 +165,7 @@ def object_data_add(context, obdata, operator=None, use_active_layer=True):
obj_act.mode == 'EDIT' and
obj_act.type == obj_new.type):
- _obdata = bpy.data.meshes.new(obdata.name)
+ _obdata = bpy.data.meshes.new(name)
obj_act = bpy.data.objects.new(_obdata.name, _obdata)
obj_act.matrix_world = obj_new.matrix_world
scene.objects.link(obj_act)
@@ -166,10 +181,11 @@ def object_data_add(context, obdata, operator=None, use_active_layer=True):
obj_act.select = True
scene.update() # apply location
- #scene.objects.active = obj_new
+ # scene.objects.active = obj_new
bpy.ops.object.join() # join into the active.
- bpy.data.meshes.remove(obdata)
+ if obdata:
+ bpy.data.meshes.remove(obdata)
# base is freed, set to active object
base = scene.object_bases.active
@@ -200,6 +216,12 @@ class AddObjectHelper:
name="Rotation",
subtype='EULER',
)
+ layers = BoolVectorProperty(
+ name="Layers",
+ size=20,
+ subtype='LAYER',
+ options={'HIDDEN', 'SKIP_SAVE'},
+ )
@classmethod
def poll(self, context):
@@ -281,7 +303,8 @@ def world_to_camera_view(scene, obj, coord):
Returns the camera space coords for a 3d point.
(also known as: normalized device coordinates - NDC).
- Where (0, 0) is the bottom left and (1, 1) is the top right of the camera frame.
+ Where (0, 0) is the bottom left and (1, 1)
+ is the top right of the camera frame.
values outside 0-1 are also supported.
A negative 'z' value means the point is behind the camera.
@@ -294,7 +317,8 @@ def world_to_camera_view(scene, obj, coord):
:type obj: :class:`bpy.types.Object`
:arg coord: World space location.
:type coord: :class:`mathutils.Vector`
- :return: a vector where X and Y map to the view plane and Z is the depth on the view axis.
+ :return: a vector where X and Y map to the view plane and
+ Z is the depth on the view axis.
:rtype: :class:`mathutils.Vector`
"""
from mathutils import Vector
diff --git a/release/scripts/modules/bpy_extras/view3d_utils.py b/release/scripts/modules/bpy_extras/view3d_utils.py
index b25024fca9b..4aa06262970 100644
--- a/release/scripts/modules/bpy_extras/view3d_utils.py
+++ b/release/scripts/modules/bpy_extras/view3d_utils.py
@@ -63,10 +63,20 @@ def region_2d_to_vector_3d(region, rv3d, coord):
return view_vector
-def region_2d_to_origin_3d(region, rv3d, coord):
+def region_2d_to_origin_3d(region, rv3d, coord, clamp=None):
"""
Return the 3d view origin from the region relative 2d coords.
+ .. note::
+
+ Orthographic views have a less obvious origin,
+ the far clip is used to define the viewport near/far extents.
+ Since far clip can be a very large value,
+ the result may give with numeric precision issues.
+
+ To avoid this problem, you can optionally clamp the far clip to a
+ smaller value based on the data you're operating on.
+
:arg region: region of the 3D viewport, typically bpy.context.region.
:type region: :class:`bpy.types.Region`
:arg rv3d: 3D region data, typically bpy.context.space_data.region_3d.
@@ -74,6 +84,9 @@ def region_2d_to_origin_3d(region, rv3d, coord):
:arg coord: 2d coordinates relative to the region;
(event.mouse_region_x, event.mouse_region_y) for example.
:type coord: 2d vector
+ :arg clamp: Clamp the maximum far-clip value used.
+ (negative value will move the offset away from the view_location)
+ :type clamp: float or None
:return: The origin of the viewpoint in 3d space.
:rtype: :class:`mathutils.Vector`
"""
@@ -89,6 +102,20 @@ def region_2d_to_origin_3d(region, rv3d, coord):
origin_start = ((persinv.col[0].xyz * dx) +
(persinv.col[1].xyz * dy) +
viewinv.translation)
+
+ if clamp != 0.0:
+ if rv3d.view_perspective != 'CAMERA':
+ # this value is scaled to the far clip already
+ origin_offset = persinv.col[2].xyz
+ if clamp is not None:
+ if clamp < 0.0:
+ origin_offset.negate()
+ clamp = -clamp
+ if origin_offset.length > clamp:
+ origin_offset.length = clamp
+
+ origin_start -= origin_offset
+
return origin_start
@@ -135,7 +162,7 @@ def region_2d_to_location_3d(region, rv3d, coord, depth_location):
)[0]
-def location_3d_to_region_2d(region, rv3d, coord):
+def location_3d_to_region_2d(region, rv3d, coord, default=None):
"""
Return the *region* relative 2d location of a 3d position.
@@ -145,8 +172,10 @@ def location_3d_to_region_2d(region, rv3d, coord):
:type rv3d: :class:`bpy.types.RegionView3D`
:arg coord: 3d worldspace location.
:type coord: 3d vector
+ :arg default: Return this value if ``coord``
+ is behind the origin of a perspective view.
:return: 2d location
- :rtype: :class:`mathutils.Vector`
+ :rtype: :class:`mathutils.Vector` or ``default`` argument.
"""
from mathutils import Vector
@@ -159,4 +188,4 @@ def location_3d_to_region_2d(region, rv3d, coord):
height_half + height_half * (prj.y / prj.w),
))
else:
- return None
+ return default