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:
-rw-r--r--build_files/build_environment/cmake/ffmpeg.cmake1
-rw-r--r--intern/clog/clog.c6
-rw-r--r--release/datafiles/blender_icons_geom.py82
-rw-r--r--release/datafiles/icons/ops.transform.resize.cage.datbin3248 -> 3248 bytes
-rw-r--r--release/datafiles/icons/ops.transform.resize.datbin512 -> 440 bytes
-rw-r--r--release/datafiles/icons/ops.transform.rotate.datbin6092 -> 2636 bytes
-rw-r--r--release/datafiles/icons/ops.transform.transform.datbin3734 -> 890 bytes
-rw-r--r--release/datafiles/icons/ops.transform.translate.datbin116 -> 98 bytes
-rw-r--r--release/scripts/startup/bl_ui/space_toolsystem_common.py3
-rw-r--r--release/scripts/startup/bl_ui/space_toolsystem_toolbar.py11
-rw-r--r--release/scripts/startup/bl_ui/space_topbar.py19
-rw-r--r--release/scripts/startup/bl_ui/space_view3d.py41
-rw-r--r--source/blender/alembic/intern/abc_util.cc3
-rw-r--r--source/blender/blenkernel/BKE_library.h1
-rw-r--r--source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c2
-rw-r--r--source/blender/blenkernel/intern/appdir.c4
-rw-r--r--source/blender/blenkernel/intern/curve.c4
-rw-r--r--source/blender/blenkernel/intern/lamp.c1
-rw-r--r--source/blender/blenkernel/intern/lattice.c4
-rw-r--r--source/blender/blenkernel/intern/library.c4
-rw-r--r--source/blender/blenkernel/intern/mesh.c4
-rw-r--r--source/blender/blenkernel/intern/studiolight.c48
-rw-r--r--source/blender/blenlib/BLI_kdopbvh.h14
-rw-r--r--source/blender/blenlib/BLI_math_geom.h13
-rw-r--r--source/blender/blenlib/BLI_math_vector.h12
-rw-r--r--source/blender/blenlib/BLI_utildefines.h49
-rw-r--r--source/blender/blenlib/intern/BLI_kdopbvh.c198
-rw-r--r--source/blender/blenlib/intern/math_geom.c158
-rw-r--r--source/blender/blenlib/intern/math_vector_inline.c12
-rw-r--r--source/blender/blenloader/intern/readfile.c2
-rw-r--r--source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl1
-rw-r--r--source/blender/draw/engines/eevee/shaders/lamps_lib.glsl28
-rw-r--r--source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl59
-rw-r--r--source/blender/draw/engines/workbench/workbench_materials.c2
-rw-r--r--source/blender/draw/intern/draw_armature.c3
-rw-r--r--source/blender/draw/intern/draw_cache_impl_displist.c2
-rw-r--r--source/blender/editors/armature/pose_edit.c2
-rw-r--r--source/blender/editors/armature/pose_select.c2
-rw-r--r--source/blender/editors/include/ED_manipulator_library.h12
-rw-r--r--source/blender/editors/include/UI_interface.h5
-rw-r--r--source/blender/editors/interface/interface.c8
-rw-r--r--source/blender/editors/interface/interface_handlers.c3
-rw-r--r--source/blender/editors/interface/interface_intern.h2
-rw-r--r--source/blender/editors/interface/interface_layout.c137
-rw-r--r--source/blender/editors/interface/interface_region_popup.c14
-rw-r--r--source/blender/editors/interface/interface_widgets.c29
-rw-r--r--source/blender/editors/manipulator_library/manipulator_types/button2d_manipulator.c96
-rw-r--r--source/blender/editors/manipulator_library/manipulator_types/cage2d_manipulator.c14
-rw-r--r--source/blender/editors/mesh/editmesh_extrude.c255
-rw-r--r--source/blender/editors/mesh/editmesh_select.c138
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c527
-rw-r--r--source/blender/editors/physics/particle_edit.c3
-rw-r--r--source/blender/editors/screen/workspace_edit.c7
-rw-r--r--source/blender/editors/space_view3d/view3d_manipulator_navigate.c1
-rw-r--r--source/blender/editors/space_view3d/view3d_ops.c24
-rw-r--r--source/blender/editors/space_view3d/view3d_snap.c67
-rw-r--r--source/blender/editors/transform/transform_snap_object.c330
-rw-r--r--source/blender/editors/uvedit/uvedit_unwrap_ops.c106
-rw-r--r--source/blender/gpu/GPU_texture.h50
-rw-r--r--source/blender/gpu/intern/gpu_texture.c120
-rw-r--r--source/blender/makesrna/intern/rna_armature.c18
-rw-r--r--source/blender/makesrna/intern/rna_object.c6
-rw-r--r--source/blender/makesrna/intern/rna_space.c7
-rw-r--r--source/blender/makesrna/intern/rna_ui.c22
-rw-r--r--source/blender/modifiers/intern/MOD_boolean.c7
-rw-r--r--source/blender/modifiers/intern/MOD_laplaciansmooth.c2
-rw-r--r--source/blender/modifiers/intern/MOD_util.c8
-rw-r--r--source/blender/render/intern/source/pointdensity.c17
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c23
-rw-r--r--source/blender/windowmanager/manipulators/WM_manipulator_api.h5
-rw-r--r--source/blender/windowmanager/manipulators/intern/wm_manipulator.c16
71 files changed, 1870 insertions, 1004 deletions
diff --git a/build_files/build_environment/cmake/ffmpeg.cmake b/build_files/build_environment/cmake/ffmpeg.cmake
index bd49621bf26..3ea1b282d9a 100644
--- a/build_files/build_environment/cmake/ffmpeg.cmake
+++ b/build_files/build_environment/cmake/ffmpeg.cmake
@@ -103,6 +103,7 @@ ExternalProject_Add(external_ffmpeg
--disable-indev=jack
--disable-indev=alsa
--disable-outdev=alsa
+ --disable-crystalhd
PATCH_COMMAND ${PATCH_CMD} --verbose -p 0 -N -d ${BUILD_DIR}/ffmpeg/src/external_ffmpeg < ${PATCH_DIR}/ffmpeg.diff
BUILD_COMMAND ${CONFIGURE_ENV_NO_PERL} && cd ${BUILD_DIR}/ffmpeg/src/external_ffmpeg/ && make -j${MAKE_THREADS}
INSTALL_COMMAND ${CONFIGURE_ENV_NO_PERL} && cd ${BUILD_DIR}/ffmpeg/src/external_ffmpeg/ && make install
diff --git a/intern/clog/clog.c b/intern/clog/clog.c
index e93ba9ec2b7..e96cbbe7f14 100644
--- a/intern/clog/clog.c
+++ b/intern/clog/clog.c
@@ -404,7 +404,8 @@ void CLG_log_str(
clg_str_append(&cstr, "\n");
/* could be optional */
- write(lg->ctx->output, cstr.data, cstr.len);
+ int bytes_written = write(lg->ctx->output, cstr.data, cstr.len);
+ (void)bytes_written;
clg_str_free(&cstr);
@@ -435,7 +436,8 @@ void CLG_logf(
clg_str_append(&cstr, "\n");
/* could be optional */
- write(lg->ctx->output, cstr.data, cstr.len);
+ int bytes_written = write(lg->ctx->output, cstr.data, cstr.len);
+ (void)bytes_written;
clg_str_free(&cstr);
diff --git a/release/datafiles/blender_icons_geom.py b/release/datafiles/blender_icons_geom.py
index fa2d8273370..e9155a91fc8 100644
--- a/release/datafiles/blender_icons_geom.py
+++ b/release/datafiles/blender_icons_geom.py
@@ -74,6 +74,24 @@ class TriMesh:
return me
+def object_material_colors(ob):
+ material_colors = []
+ color_default = (1.0, 1.0, 1.0, 1.0)
+ for slot in ob.material_slots:
+ material = slot.material
+ color = color_default
+ if material is not None and material.use_nodes:
+ node_tree = material.node_tree
+ if node_tree is not None:
+ color = next((
+ node.outputs[0].default_value[:]
+ for node in node_tree.nodes
+ if node.type == 'RGB'
+ ), color_default)
+ material_colors.append(color)
+ return material_colors
+
+
def object_child_map(objects):
objects_children = {}
for ob in objects:
@@ -89,24 +107,25 @@ def object_child_map(objects):
return objects_children
-def mesh_data_lists_from_mesh(me):
+def mesh_data_lists_from_mesh(me, material_colors):
me_loops = me.loops[:]
me_loops_color = me.vertex_colors.active.data[:]
me_verts = me.vertices[:]
me_polys = me.polygons[:]
- # 100 layers of depth
- me_polys.sort(key=lambda p: int(p.center.z * 100))
-
- tris_coords = []
- tris_colors = []
+ tris_data = []
for p in me_polys:
-
# Backface culling (allows using spheres without tedious manual deleting).
if p.normal.z <= 0.0:
continue
+ material_index = p.material_index
+ if material_index < len(material_colors):
+ base_color = material_colors[p.material_index]
+ else:
+ base_color = (1.0, 1.0, 1.0, 1.0)
+
l_sta = p.loop_start
l_len = p.loop_total
loops_poly = me_loops[l_sta:l_sta + l_len]
@@ -130,22 +149,27 @@ def mesh_data_lists_from_mesh(me):
v1 = me_verts[l1.vertex_index]
v2 = me_verts[l2.vertex_index]
- tris_coords.append((
- v0.co.xy[:],
- v1.co.xy[:],
- v2.co.xy[:],
+ tris_data.append((
+ # float depth
+ p.center.z,
+ # XY coords.
+ (
+ v0.co.xy[:],
+ v1.co.xy[:],
+ v2.co.xy[:],
+ ),
+ # RGBA color.
+ tuple((
+ [int(c * b * 255) for c, b in zip(cn.color, base_color)]
+ for cn in (c0, c1, c2)
+ )),
))
- # Color as RGBA for each tri
- tris_colors.append(
- [[int(c * 255) for c in cn.color] for cn in (c0, c1, c2)]
- )
i1 = i2
- return (tris_coords, tris_colors)
+ return tris_data
def mesh_data_lists_from_objects(ob_parent, ob_children):
- tris_coords = []
- tris_colors = []
+ tris_data = []
has_parent = False
if ob_children:
@@ -156,11 +180,15 @@ def mesh_data_lists_from_objects(ob_parent, ob_children):
with TriMesh(ob) as me:
if has_parent:
me.transform(parent_matrix_inverted * ob.matrix_world)
- tris_coords_iter, tris_colors_iter = mesh_data_lists_from_mesh(me)
- tris_coords.extend(tris_coords_iter)
- tris_colors.extend(tris_colors_iter)
+
+ tris_data.extend(
+ mesh_data_lists_from_mesh(
+ me,
+ object_material_colors(ob),
+ )
+ )
has_parent = True
- return tris_coords, tris_colors
+ return tris_data
def write_mesh_to_py(fh, ob, ob_children):
@@ -178,7 +206,11 @@ def write_mesh_to_py(fh, ob, ob_children):
float_as_byte(v[1], coords_range_align[1]),
)
- tris_coords, tris_colors = mesh_data_lists_from_objects(ob, ob_children)
+ tris_data = mesh_data_lists_from_objects(ob, ob_children)
+
+ # 100 levels of Z depth, round to avoid differences from precision error
+ # causing different computers to write triangles in more or less random order.
+ tris_data.sort(key=lambda data: int(data[0] * 100))
if 0:
# make as large as we can, keeping alignment
@@ -211,10 +243,10 @@ def write_mesh_to_py(fh, ob, ob_children):
# X, Y
fw(bytes((0, 0)))
- for tri_coords in tris_coords:
+ for (_, tri_coords, _) in tris_data:
for vert in tri_coords:
fw(bytes(vert_as_byte_pair(vert)))
- for tri_color in tris_colors:
+ for (_, _, tri_color) in tris_data:
for color in tri_color:
fw(bytes(color))
diff --git a/release/datafiles/icons/ops.transform.resize.cage.dat b/release/datafiles/icons/ops.transform.resize.cage.dat
index 68d9393ac5f..16cf71e0cbb 100644
--- a/release/datafiles/icons/ops.transform.resize.cage.dat
+++ b/release/datafiles/icons/ops.transform.resize.cage.dat
Binary files differ
diff --git a/release/datafiles/icons/ops.transform.resize.dat b/release/datafiles/icons/ops.transform.resize.dat
index fc6aa5f5c35..27bc56987d3 100644
--- a/release/datafiles/icons/ops.transform.resize.dat
+++ b/release/datafiles/icons/ops.transform.resize.dat
Binary files differ
diff --git a/release/datafiles/icons/ops.transform.rotate.dat b/release/datafiles/icons/ops.transform.rotate.dat
index bea71aab4a3..fe86eeb962d 100644
--- a/release/datafiles/icons/ops.transform.rotate.dat
+++ b/release/datafiles/icons/ops.transform.rotate.dat
Binary files differ
diff --git a/release/datafiles/icons/ops.transform.transform.dat b/release/datafiles/icons/ops.transform.transform.dat
index 2baa5634484..af455c5e38d 100644
--- a/release/datafiles/icons/ops.transform.transform.dat
+++ b/release/datafiles/icons/ops.transform.transform.dat
Binary files differ
diff --git a/release/datafiles/icons/ops.transform.translate.dat b/release/datafiles/icons/ops.transform.translate.dat
index 64e1acab958..e717ab5c993 100644
--- a/release/datafiles/icons/ops.transform.translate.dat
+++ b/release/datafiles/icons/ops.transform.translate.dat
Binary files differ
diff --git a/release/scripts/startup/bl_ui/space_toolsystem_common.py b/release/scripts/startup/bl_ui/space_toolsystem_common.py
index 84c9b57f590..ed683bcc312 100644
--- a/release/scripts/startup/bl_ui/space_toolsystem_common.py
+++ b/release/scripts/startup/bl_ui/space_toolsystem_common.py
@@ -257,8 +257,7 @@ class ToolSelectPanelHelper:
"""
Return the active Python tool definition and index (if in sub-group, else -1).
"""
- workspace = context.workspace
- cls = ToolSelectPanelHelper._tool_class_from_space_type(workspace.tool_space_type)
+ cls = ToolSelectPanelHelper._tool_class_from_space_type(context.space_data.type)
if cls is not None:
context_mode = context.mode
for item, index in ToolSelectPanelHelper._tools_flatten_with_tool_index(cls.tools_from_context(context)):
diff --git a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
index 6250feb77eb..f70822d4dff 100644
--- a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
@@ -397,21 +397,14 @@ class _defs_edit_mesh:
@ToolDef.from_fn
def extrude():
- def draw_settings(context, layout):
- wm = context.window_manager
- props = wm.operator_properties_last("mesh.extrude_context_move")
- props_xform = props.TRANSFORM_OT_translate
- layout.prop(props_xform, "constraint_orientation")
-
return dict(
text="Extrude Region",
icon="ops.mesh.extrude_region_move",
widget="MESH_WGT_extrude",
keymap=(
("mesh.extrude_context_move", dict(TRANSFORM_OT_translate=dict(release_confirm=True)),
- dict(type='ACTIONMOUSE', value='PRESS')),
+ dict(type='EVT_TWEAK_A', value='ANY')),
),
- draw_settings=draw_settings,
)
@ToolDef.from_fn
@@ -422,7 +415,7 @@ class _defs_edit_mesh:
widget=None,
keymap=(
("mesh.extrude_faces_move", dict(TRANSFORM_OT_shrink_fatten=dict(release_confirm=True)),
- dict(type='ACTIONMOUSE', value='PRESS')),
+ dict(type='EVT_TWEAK_A', value='ANY')),
),
)
diff --git a/release/scripts/startup/bl_ui/space_topbar.py b/release/scripts/startup/bl_ui/space_topbar.py
index 6e1cd63d52c..719396ccdd1 100644
--- a/release/scripts/startup/bl_ui/space_topbar.py
+++ b/release/scripts/startup/bl_ui/space_topbar.py
@@ -116,25 +116,21 @@ class TOPBAR_HT_lower_bar(Header):
# Object Mode
# -----------
-
- # Testing move to 3D header.
- '''
object_mode = 'OBJECT' if object is None else object.mode
act_mode_item = bpy.types.Object.bl_rna.properties['mode'].enum_items[object_mode]
- layout.operator_menu_enum("object.mode_set", "mode", text=act_mode_item.name, icon=act_mode_item.icon)
- '''
- # Active Tool
- # -----------
+ layout.operator_menu_enum("object.mode_set", "mode", text=act_mode_item.name, icon=act_mode_item.icon)
- from .space_toolsystem_common import ToolSelectPanelHelper
- ToolSelectPanelHelper.draw_active_tool_header(context, layout)
+ layout.template_header_3D_mode()
def draw_center(self, context):
layout = self.layout
mode = context.mode
- layout.separator()
+ # Active Tool
+ # -----------
+ from .space_toolsystem_common import ToolSelectPanelHelper
+ ToolSelectPanelHelper.draw_active_tool_header(context, layout)
# Object Mode Options
# -------------------
@@ -242,7 +238,10 @@ class TOPBAR_HT_lower_bar(Header):
if object_mode not in {'SCULPT', 'VERTEX_PAINT', 'WEIGHT_PAINT', 'TEXTURE_PAINT'}:
show_snap = True
else:
+
+ from .properties_paint_common import UnifiedPaintPanel
paint_settings = UnifiedPaintPanel.paint_settings(context)
+
if paint_settings:
brush = paint_settings.brush
if brush and brush.stroke_method == 'CURVE':
diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index 3143089040c..dbf01257273 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -37,28 +37,40 @@ class VIEW3D_HT_header(Header):
shading = view.shading
# mode_string = context.mode
obj = context.active_object
+ overlay = view.overlay
toolsettings = context.tool_settings
row = layout.row(align=True)
row.template_header()
mode = 'OBJECT' if obj is None else obj.mode
+
+ # Testing move mode to topbar.
+ '''
act_mode_item = bpy.types.Object.bl_rna.properties['mode'].enum_items[mode]
layout.operator_menu_enum("object.mode_set", "mode", text=act_mode_item.name, icon=act_mode_item.icon)
del act_mode_item
layout.template_header_3D_mode()
-
- VIEW3D_MT_editor_menus.draw_collapsible(context, layout)
+ '''
# Contains buttons like Mode, Pivot, Manipulator, Layer, Mesh Select Mode...
- row = layout
shading_type = view.shading.type
shading_item = bpy.types.View3DShading.bl_rna.properties['type'].enum_items[shading_type]
- row.popover(space_type='VIEW_3D', region_type='HEADER', panel_type="VIEW3D_PT_shading", text=shading_item.name, icon=shading_item.icon)
- row.popover(space_type='VIEW_3D', region_type='HEADER', panel_type="VIEW3D_PT_overlay", text="Overlays", icon='WIRE')
- layout.template_header_3D()
+ row = layout.row(align=True)
+ row.prop(shading, "type", text="", expand=True)
+
+ sub = row.row(align=True)
+ sub.enabled = shading.type != 'RENDERED'
+ sub.popover(space_type='VIEW_3D', region_type='HEADER', panel_type="VIEW3D_PT_shading")
+
+ row = layout.row(align=True)
+ row.prop(overlay, "show_overlays", icon="WIRE", text="")
+
+ sub = row.row(align=True)
+ sub.active = overlay.show_overlays
+ sub.popover(space_type='VIEW_3D', region_type='HEADER', panel_type="VIEW3D_PT_overlay")
if obj:
# Set above:
@@ -66,13 +78,16 @@ class VIEW3D_HT_header(Header):
# Particle edit
if mode == 'EDIT' and obj.type == 'GROOM':
+ row = layout.row()
row.prop(toolsettings.groom_edit_settings, "mode", text="", expand=True)
elif mode == 'PARTICLE_EDIT':
+ row = layout.row()
row.prop(toolsettings.particle_edit, "select_mode", text="", expand=True)
# Occlude geometry
if ((shading.type not in {'BOUNDBOX', 'WIREFRAME'} and (mode == 'PARTICLE_EDIT' or (mode == 'EDIT' and obj.type == 'MESH'))) or
(mode in {'WEIGHT_PAINT', 'VERTEX_PAINT'})):
+ row = layout.row()
row.prop(view, "use_occlude_geometry", text="")
# Pose
@@ -95,6 +110,8 @@ class VIEW3D_HT_header(Header):
row.prop(context.tool_settings.gpencil_sculpt, "use_select_mask")
row.prop(context.tool_settings.gpencil_sculpt, "selection_alpha", slider=True)
+ VIEW3D_MT_editor_menus.draw_collapsible(context, layout)
+
class VIEW3D_MT_editor_menus(Menu):
bl_space_type = 'VIEW3D_MT_editor_menus'
@@ -3521,18 +3538,14 @@ class VIEW3D_PT_shading(Panel):
shading = view.shading
col = layout.column()
- col.prop(shading, "type", expand=True)
if shading.type == 'SOLID':
- col.separator()
col.row().prop(shading, "color_type", expand=True)
if shading.color_type == 'SINGLE':
- col.separator()
col.row().prop(shading, "single_color", text="")
if shading.type in ('SOLID', 'TEXTURED'):
- col.separator()
col.row().prop(shading, "light", expand=True)
if shading.light == 'STUDIO':
col.row().template_icon_view(shading, "studio_light")
@@ -3551,7 +3564,7 @@ class VIEW3D_PT_shading(Panel):
class VIEW3D_PT_overlay(Panel):
bl_space_type = 'VIEW_3D'
bl_region_type = 'HEADER'
- bl_label = "Overlay"
+ bl_label = "Overlays"
@classmethod
def poll(cls, context):
@@ -3567,15 +3580,13 @@ class VIEW3D_PT_overlay(Panel):
display_all = overlay.show_overlays
col = layout.column()
- col.prop(overlay, "show_overlays")
- col.separator()
col.prop(view, "show_world")
col = layout.column()
col.active = display_all
- col.prop(overlay, "show_cursor")
+ col.prop(overlay, "show_cursor", text="3D Cursor")
- col.prop(view, "show_manipulator")
+ col.prop(view, "show_manipulator", text="Manipulators")
col = layout.column()
col.active = display_all
diff --git a/source/blender/alembic/intern/abc_util.cc b/source/blender/alembic/intern/abc_util.cc
index 8bdc7ae3455..6787d118fa1 100644
--- a/source/blender/alembic/intern/abc_util.cc
+++ b/source/blender/alembic/intern/abc_util.cc
@@ -140,7 +140,10 @@ void create_swapped_rotation_matrix(
rz = -euler[1];
break;
default:
+ ry = 0.0f;
+ rz = 0.0f;
BLI_assert(false);
+ break;
}
unit_m3(rot_x_mat);
diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h
index 42b53f3939c..e80a324bd14 100644
--- a/source/blender/blenkernel/BKE_library.h
+++ b/source/blender/blenkernel/BKE_library.h
@@ -83,6 +83,7 @@ enum {
LIB_ID_COPY_ACTIONS = 1 << 19, /* EXCEPTION! Deep-copy actions used by animdata of copied ID. */
LIB_ID_COPY_KEEP_LIB = 1 << 20, /* Keep the library pointer when copying datablock outside of bmain. */
LIB_ID_COPY_NO_ANIMDATA = 1 << 21, /* Don't copy id->adt, used by ID datablock localization routines. */
+ LIB_ID_COPY_SHAPEKEY = 1 << 22, /* EXCEPTION! Deep-copy shapekeys used by copied obdata ID. */
};
void BKE_libblock_copy_ex(struct Main *bmain, const struct ID *id, struct ID **r_newid, const int flag);
diff --git a/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c b/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c
index c1a4f8dba53..fc4220277eb 100644
--- a/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c
+++ b/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c
@@ -543,7 +543,7 @@ static void opensubdiv_evaluateQuadFaceGrids(CCGSubSurf *ss,
for (S = 0; S < face->numVerts; S++) {
int x, y, k;
CCGEdge *edge = NULL;
- bool inverse_edge;
+ bool inverse_edge = false;
for (x = 0; x < gridSize; x++) {
for (y = 0; y < gridSize; y++) {
diff --git a/source/blender/blenkernel/intern/appdir.c b/source/blender/blenkernel/intern/appdir.c
index 16f8d16860f..2054442250e 100644
--- a/source/blender/blenkernel/intern/appdir.c
+++ b/source/blender/blenkernel/intern/appdir.c
@@ -790,7 +790,9 @@ static void where_is_temp(char *fullname, char *basename, const size_t maxlen, c
BLI_dir_create_recursive(tmp_name);
}
#else
- mkdtemp(tmp_name);
+ if (mkdtemp(tmp_name) == NULL) {
+ BLI_dir_create_recursive(tmp_name);
+ }
#endif
}
if (BLI_is_dir(tmp_name)) {
diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c
index cea5685a7a1..01da9857864 100644
--- a/source/blender/blenkernel/intern/curve.c
+++ b/source/blender/blenkernel/intern/curve.c
@@ -212,7 +212,7 @@ void BKE_curve_copy_data(Main *bmain, Curve *cu_dst, const Curve *cu_src, const
cu_dst->bb = MEM_dupallocN(cu_src->bb);
cu_dst->batch_cache = NULL;
- if (cu_src->key) {
+ if (cu_src->key && (flag & LIB_ID_COPY_SHAPEKEY)) {
BKE_id_copy_ex(bmain, &cu_src->key->id, (ID **)&cu_dst->key, flag, false);
}
@@ -223,7 +223,7 @@ void BKE_curve_copy_data(Main *bmain, Curve *cu_dst, const Curve *cu_src, const
Curve *BKE_curve_copy(Main *bmain, const Curve *cu)
{
Curve *cu_copy;
- BKE_id_copy_ex(bmain, &cu->id, (ID **)&cu_copy, 0, false);
+ BKE_id_copy_ex(bmain, &cu->id, (ID **)&cu_copy, LIB_ID_COPY_SHAPEKEY, false);
return cu_copy;
}
diff --git a/source/blender/blenkernel/intern/lamp.c b/source/blender/blenkernel/intern/lamp.c
index 195280aad5a..83f429762d9 100644
--- a/source/blender/blenkernel/intern/lamp.c
+++ b/source/blender/blenkernel/intern/lamp.c
@@ -88,6 +88,7 @@ void BKE_lamp_init(Lamp *la)
la->contact_bias = 0.03f;
la->contact_spread = 0.2f;
la->contact_thickness = 0.5f;
+ la->spec_fac = 1.0f;
curvemapping_initialize(la->curfalloff);
}
diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c
index b9b894db9a5..7a821483fee 100644
--- a/source/blender/blenkernel/intern/lattice.c
+++ b/source/blender/blenkernel/intern/lattice.c
@@ -282,7 +282,7 @@ void BKE_lattice_copy_data(Main *bmain, Lattice *lt_dst, const Lattice *lt_src,
{
lt_dst->def = MEM_dupallocN(lt_src->def);
- if (lt_src->key) {
+ if (lt_src->key && (flag & LIB_ID_COPY_SHAPEKEY)) {
BKE_id_copy_ex(bmain, &lt_src->key->id, (ID **)&lt_dst->key, flag, false);
}
@@ -298,7 +298,7 @@ void BKE_lattice_copy_data(Main *bmain, Lattice *lt_dst, const Lattice *lt_src,
Lattice *BKE_lattice_copy(Main *bmain, const Lattice *lt)
{
Lattice *lt_copy;
- BKE_id_copy_ex(bmain, &lt->id, (ID **)&lt_copy, 0, false);
+ BKE_id_copy_ex(bmain, &lt->id, (ID **)&lt_copy, LIB_ID_COPY_SHAPEKEY, false);
return lt_copy;
}
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c
index c8cdbe4f6a4..97803354c12 100644
--- a/source/blender/blenkernel/intern/library.c
+++ b/source/blender/blenkernel/intern/library.c
@@ -699,7 +699,7 @@ bool BKE_id_copy_ex(Main *bmain, const ID *id, ID **r_newid, const int flag, con
*/
bool id_copy(Main *bmain, const ID *id, ID **newid, bool test)
{
- return BKE_id_copy_ex(bmain, id, newid, 0, test);
+ return BKE_id_copy_ex(bmain, id, newid, LIB_ID_COPY_SHAPEKEY, test);
}
/** Does a mere memory swap over the whole IDs data (including type-specific memory).
@@ -1442,6 +1442,8 @@ void BKE_libblock_copy_ex(Main *bmain, const ID *id, ID **r_newid, const int fla
BLI_assert((flag & LIB_ID_CREATE_NO_MAIN) != 0 || bmain != NULL);
BLI_assert((flag & LIB_ID_CREATE_NO_MAIN) != 0 || (flag & LIB_ID_CREATE_NO_ALLOCATE) == 0);
BLI_assert((flag & LIB_ID_CREATE_NO_MAIN) == 0 || (flag & LIB_ID_CREATE_NO_USER_REFCOUNT) != 0);
+ /* Never implicitely copy shapekeys when generating temp data outside of Main database. */
+ BLI_assert((flag & LIB_ID_CREATE_NO_MAIN) == 0 || (flag & LIB_ID_COPY_SHAPEKEY) == 0);
if ((flag & LIB_ID_CREATE_NO_ALLOCATE) != 0) {
/* r_newid already contains pointer to allocated memory. */
diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c
index b16a5a6d75d..a64eb5aa071 100644
--- a/source/blender/blenkernel/intern/mesh.c
+++ b/source/blender/blenkernel/intern/mesh.c
@@ -558,7 +558,7 @@ void BKE_mesh_copy_data(Main *bmain, Mesh *me_dst, const Mesh *me_src, const int
me_dst->bb = MEM_dupallocN(me_dst->bb);
/* TODO Do we want to add flag to prevent this? */
- if (me_src->key) {
+ if (me_src->key && (flag & LIB_ID_COPY_SHAPEKEY)) {
BKE_id_copy_ex(bmain, &me_src->key->id, (ID **)&me_dst->key, flag, false);
}
}
@@ -661,7 +661,7 @@ Mesh * BKE_mesh_new_nomain_from_template(
Mesh *BKE_mesh_copy(Main *bmain, const Mesh *me)
{
Mesh *me_copy;
- BKE_id_copy_ex(bmain, &me->id, (ID **)&me_copy, 0, false);
+ BKE_id_copy_ex(bmain, &me->id, (ID **)&me_copy, LIB_ID_COPY_SHAPEKEY, false);
return me_copy;
}
diff --git a/source/blender/blenkernel/intern/studiolight.c b/source/blender/blenkernel/intern/studiolight.c
index 9bc678a1820..f0db054620a 100644
--- a/source/blender/blenkernel/intern/studiolight.c
+++ b/source/blender/blenkernel/intern/studiolight.c
@@ -52,6 +52,8 @@
/* Statics */
static ListBase studiolights;
+#define STUDIO_LIGHT_EXTENSIONS ".jpg", ".hdr"
+#define STUDIO_LIGHT_DIFFUSE_SAMPLE_STEP 64
static const char *STUDIO_LIGHT_FOLDER = "studiolights/";
/* FUNCTIONS */
@@ -77,8 +79,9 @@ static void direction_to_equirectangular(float r[2], const float dir[3])
r[1] = (acosf(dir[2] / 1.0) - M_PI) / -M_PI;
}
-static void studiolight_calculate_directional_diffuse_light(ImBuf *ibuf, float color[4], const float start[3], const float v1[3], const float v2[3], int steps)
+static void studiolight_calculate_directional_diffuse_light(ImBuf *ibuf, float color[4], const float start[3], const float v1[3], const float v2[3])
{
+ const int steps = STUDIO_LIGHT_DIFFUSE_SAMPLE_STEP;
float uv[2];
float dir[3];
float col[4];
@@ -110,7 +113,6 @@ static void studiolight_calculate_directional_diffuse_light(ImBuf *ibuf, float c
static void studiolight_calculate_diffuse_light(StudioLight *sl)
{
- const int steps = 16;
float start[3];
float v1[3];
float v2[3];
@@ -132,23 +134,23 @@ static void studiolight_calculate_diffuse_light(StudioLight *sl)
copy_v3_fl3(start, -1.0f, -1.0f, -1.0f);
copy_v3_fl3(v1, 0.0f, 2.0f, 0.0f);
copy_v3_fl3(v2, 0.0f, 0.0f, 2.0f);
- studiolight_calculate_directional_diffuse_light(ibuf, sl->diffuse_light[STUDIOLIGHT_Z_NEG], start, v1, v2, steps);
+ studiolight_calculate_directional_diffuse_light(ibuf, sl->diffuse_light[STUDIOLIGHT_Z_NEG], start, v1, v2);
copy_v3_fl3(start, 1.0f, -1.0f, -1.0f);
- studiolight_calculate_directional_diffuse_light(ibuf, sl->diffuse_light[STUDIOLIGHT_Z_POS], start, v1, v2, steps);
+ studiolight_calculate_directional_diffuse_light(ibuf, sl->diffuse_light[STUDIOLIGHT_Z_POS], start, v1, v2);
copy_v3_fl3(start, -1.0f, -1.0f, -1.0f);
copy_v3_fl3(v1, 2.0f, 0.0f, 0.0f);
copy_v3_fl3(v2, 0.0f, 0.0f, 2.0f);
- studiolight_calculate_directional_diffuse_light(ibuf, sl->diffuse_light[STUDIOLIGHT_X_POS], start, v1, v2, steps);
+ studiolight_calculate_directional_diffuse_light(ibuf, sl->diffuse_light[STUDIOLIGHT_X_POS], start, v1, v2);
copy_v3_fl3(start, -1.0f, 1.0f, -1.0f);
- studiolight_calculate_directional_diffuse_light(ibuf, sl->diffuse_light[STUDIOLIGHT_X_NEG], start, v1, v2, steps);
+ studiolight_calculate_directional_diffuse_light(ibuf, sl->diffuse_light[STUDIOLIGHT_X_NEG], start, v1, v2);
copy_v3_fl3(start, -1.0f, -1.0f, -1.0f);
copy_v3_fl3(v1, 2.0f, 0.0f, 0.0f);
copy_v3_fl3(v2, 0.0f, 2.0f, 0.0f);
- studiolight_calculate_directional_diffuse_light(ibuf, sl->diffuse_light[STUDIOLIGHT_Y_NEG], start, v1, v2, steps);
+ studiolight_calculate_directional_diffuse_light(ibuf, sl->diffuse_light[STUDIOLIGHT_Y_NEG], start, v1, v2);
copy_v3_fl3(start, -1.0f, -1.0f, 1.0f);
- studiolight_calculate_directional_diffuse_light(ibuf, sl->diffuse_light[STUDIOLIGHT_Y_POS], start, v1, v2, steps);
+ studiolight_calculate_directional_diffuse_light(ibuf, sl->diffuse_light[STUDIOLIGHT_Y_POS], start, v1, v2);
IMB_freeImBuf(ibuf);
}
@@ -178,23 +180,25 @@ void BKE_studiolight_init(void)
struct direntry *dir;
const char *folder = BKE_appdir_folder_id(BLENDER_DATAFILES, STUDIO_LIGHT_FOLDER);
- unsigned int totfile = BLI_filelist_dir_contents(folder, &dir);
- int i;
- for (i = 0; i < totfile; i++) {
- if ((dir[i].type & S_IFREG)) {
- const char *filename = dir[i].relname;
- const char *path = dir[i].path;
- if (BLI_testextensie(filename, ".jpg")) {
- sl = studiolight_create();
- sl->flag = STUDIOLIGHT_EXTERNAL_FILE;
- BLI_strncpy(sl->name, filename, FILE_MAXFILE);
- BLI_strncpy(sl->path, path, FILE_MAXFILE);
- BLI_addtail(&studiolights, sl);
+ if (folder) {
+ unsigned int totfile = BLI_filelist_dir_contents(folder, &dir);
+ int i;
+ for (i = 0; i < totfile; i++) {
+ if ((dir[i].type & S_IFREG)) {
+ const char *filename = dir[i].relname;
+ const char *path = dir[i].path;
+ if (BLI_testextensie_n(filename, STUDIO_LIGHT_EXTENSIONS, NULL)) {
+ sl = studiolight_create();
+ sl->flag = STUDIOLIGHT_EXTERNAL_FILE;
+ BLI_strncpy(sl->name, filename, FILE_MAXFILE);
+ BLI_strncpy(sl->path, path, FILE_MAXFILE);
+ BLI_addtail(&studiolights, sl);
+ }
}
}
+ BLI_filelist_free(dir, totfile);
+ dir = NULL;
}
- BLI_filelist_free(dir, totfile);
- dir = NULL;
}
void BKE_studiolight_free(void)
diff --git a/source/blender/blenlib/BLI_kdopbvh.h b/source/blender/blenlib/BLI_kdopbvh.h
index c92f40c67bf..76c3b6ef3fd 100644
--- a/source/blender/blenlib/BLI_kdopbvh.h
+++ b/source/blender/blenlib/BLI_kdopbvh.h
@@ -40,6 +40,8 @@ extern "C" {
#endif
struct BVHTree;
+struct DistProjectedAABBPrecalc;
+
typedef struct BVHTree BVHTree;
#define USE_KDOPBVH_WATERTIGHT
@@ -101,6 +103,12 @@ typedef bool (*BVHTree_OverlapCallback)(void *userdata, int index_a, int index_b
/* callback to range search query */
typedef void (*BVHTree_RangeQuery)(void *userdata, int index, const float co[3], float dist_sq);
+/* callback to find nearest projected */
+typedef void (*BVHTree_NearestProjectedCallback)(
+ void *userdata, int index,
+ const struct DistProjectedAABBPrecalc *precalc,
+ BVHTreeNearest *nearest);
+
/* callbacks to BLI_bvhtree_walk_dfs */
/* return true to traverse into this nodes children, else skip. */
@@ -162,6 +170,12 @@ int BLI_bvhtree_range_query(
BVHTree *tree, const float co[3], float radius,
BVHTree_RangeQuery callback, void *userdata);
+int BLI_bvhtree_find_nearest_projected(
+ BVHTree *tree, float projmat[4][4], float winsize[2], float mval[2],
+ float clip_planes[6][4], int clip_num,
+ BVHTreeNearest *nearest,
+ BVHTree_NearestProjectedCallback callback, void *userdata);
+
void BLI_bvhtree_walk_dfs(
BVHTree *tree,
BVHTree_WalkParentCallback walk_parent_cb,
diff --git a/source/blender/blenlib/BLI_math_geom.h b/source/blender/blenlib/BLI_math_geom.h
index cde956f6a39..fda23ee2ff7 100644
--- a/source/blender/blenlib/BLI_math_geom.h
+++ b/source/blender/blenlib/BLI_math_geom.h
@@ -121,11 +121,14 @@ float dist_squared_ray_to_seg_v3(
const float v0[3], const float v1[3],
float r_point[3], float *r_depth);
+void aabb_get_near_far_from_plane(
+ const float plane_no[3], const float bbmin[3], const float bbmax[3],
+ float bb_near[3], float bb_afar[3]);
+
struct DistRayAABB_Precalc {
float ray_origin[3];
float ray_direction[3];
float ray_inv_dir[3];
- bool sign[3];
};
void dist_squared_ray_to_aabb_v3_precalc(
struct DistRayAABB_Precalc *neasrest_precalc,
@@ -344,6 +347,14 @@ bool isect_ray_aabb_v3_simple(
float *tmin, float *tmax);
/* other */
+#define ISECT_AABB_PLANE_BEHIND_ANY 0
+#define ISECT_AABB_PLANE_CROSS_ANY 1
+#define ISECT_AABB_PLANE_IN_FRONT_ALL 2
+
+int isect_aabb_planes_v3(
+ const float (*planes)[4], const int totplane,
+ const float bbmin[3], const float bbmax[3]);
+
bool isect_sweeping_sphere_tri_v3(const float p1[3], const float p2[3], const float radius,
const float v0[3], const float v1[3], const float v2[3], float *r_lambda, float ipoint[3]);
diff --git a/source/blender/blenlib/BLI_math_vector.h b/source/blender/blenlib/BLI_math_vector.h
index e4e0bf22de0..20852f8fc82 100644
--- a/source/blender/blenlib/BLI_math_vector.h
+++ b/source/blender/blenlib/BLI_math_vector.h
@@ -124,12 +124,12 @@ MINLINE void mul_v4_v4fl(float r[3], const float a[3], float f);
MINLINE void mul_v2_v2_cw(float r[2], const float mat[2], const float vec[2]);
MINLINE void mul_v2_v2_ccw(float r[2], const float mat[2], const float vec[2]);
MINLINE float mul_project_m4_v3_zfac(const float mat[4][4], const float co[3]) ATTR_WARN_UNUSED_RESULT;
-MINLINE float dot_m3_v3_row_x(float M[3][3], const float a[3]) ATTR_WARN_UNUSED_RESULT;
-MINLINE float dot_m3_v3_row_y(float M[3][3], const float a[3]) ATTR_WARN_UNUSED_RESULT;
-MINLINE float dot_m3_v3_row_z(float M[3][3], const float a[3]) ATTR_WARN_UNUSED_RESULT;
-MINLINE float dot_m4_v3_row_x(float M[4][4], const float a[3]) ATTR_WARN_UNUSED_RESULT;
-MINLINE float dot_m4_v3_row_y(float M[4][4], const float a[3]) ATTR_WARN_UNUSED_RESULT;
-MINLINE float dot_m4_v3_row_z(float M[4][4], const float a[3]) ATTR_WARN_UNUSED_RESULT;
+MINLINE float dot_m3_v3_row_x(const float M[3][3], const float a[3]) ATTR_WARN_UNUSED_RESULT;
+MINLINE float dot_m3_v3_row_y(const float M[3][3], const float a[3]) ATTR_WARN_UNUSED_RESULT;
+MINLINE float dot_m3_v3_row_z(const float M[3][3], const float a[3]) ATTR_WARN_UNUSED_RESULT;
+MINLINE float dot_m4_v3_row_x(const float M[4][4], const float a[3]) ATTR_WARN_UNUSED_RESULT;
+MINLINE float dot_m4_v3_row_y(const float M[4][4], const float a[3]) ATTR_WARN_UNUSED_RESULT;
+MINLINE float dot_m4_v3_row_z(const float M[4][4], const float a[3]) ATTR_WARN_UNUSED_RESULT;
MINLINE void madd_v2_v2fl(float r[2], const float a[2], float f);
MINLINE void madd_v3_v3fl(float r[3], const float a[3], float f);
diff --git a/source/blender/blenlib/BLI_utildefines.h b/source/blender/blenlib/BLI_utildefines.h
index 65dcbf04913..c0b76aa9cbf 100644
--- a/source/blender/blenlib/BLI_utildefines.h
+++ b/source/blender/blenlib/BLI_utildefines.h
@@ -373,19 +373,48 @@ extern "C" {
#define UNPACK4_EX(pre, a, post) UNPACK3_EX(pre, a, post), (pre((a)[3])post)
/* array helpers */
-#define ARRAY_LAST_ITEM(arr_start, arr_dtype, tot) \
- (arr_dtype *)((char *)(arr_start) + (sizeof(*((arr_dtype *)NULL)) * (size_t)(tot - 1)))
+#define ARRAY_LAST_ITEM(arr_start, arr_dtype, arr_len) \
+ (arr_dtype *)((char *)(arr_start) + (sizeof(*((arr_dtype *)NULL)) * (size_t)(arr_len - 1)))
-#define ARRAY_HAS_ITEM(arr_item, arr_start, tot) ( \
+#define ARRAY_HAS_ITEM(arr_item, arr_start, arr_len) ( \
CHECK_TYPE_PAIR_INLINE(arr_start, arr_item), \
- ((unsigned int)((arr_item) - (arr_start)) < (unsigned int)(tot)))
+ ((unsigned int)((arr_item) - (arr_start)) < (unsigned int)(arr_len)))
+
+/**
+ * \note use faster #ARRAY_DELETE_REORDER_LAST when we can re-order.
+ */
+#define ARRAY_DELETE(arr, index, delete_len, arr_len) \
+ { \
+ BLI_assert((&arr[index] >= arr) && ((index) + delete_len <= arr_len)); \
+ memmove(&(arr)[index], \
+ &(arr)[(index) + (delete_len)], \
+ (((arr_len) - (index)) - (delete_len)) * sizeof(*(arr))); \
+ } ((void)0)
+
+/**
+ * Re-ordering array removal.
+ *
+ * When removing single items this compiles down to:
+ * `if (index + 1 != arr_len) { arr[index] = arr[arr_len - 1]; }` (typical reordering removal),
+ * with removing multiple items, overlap is detected to avoid memcpy errors.
+ */
+#define ARRAY_DELETE_REORDER_LAST(arr, index, delete_len, arr_len) \
+ { \
+ BLI_assert((&arr[index] >= arr) && ((index) + delete_len <= arr_len)); \
+ if ((index) + (delete_len) != (arr_len)) { \
+ if (((delete_len) == 1) || ((delete_len) <= ((arr_len) - ((index) + (delete_len))))) { \
+ memcpy(&(arr)[index], \
+ &(arr)[(arr_len) - (delete_len)], \
+ (delete_len) * sizeof(*(arr))); \
+ } \
+ else { \
+ memcpy(&(arr)[index], \
+ &(arr)[(arr_len) - ((arr_len) - ((index) + (delete_len)))], \
+ ((arr_len) - ((index) + (delete_len))) * sizeof(*(arr))); \
+ } \
+ } \
+ } ((void)0)
-#define ARRAY_DELETE(arr, index, tot_delete, tot) { \
- BLI_assert(index + tot_delete <= tot); \
- memmove(&(arr)[(index)], \
- &(arr)[(index) + (tot_delete)], \
- (((tot) - (index)) - (tot_delete)) * sizeof(*(arr))); \
- } (void)0
/* assuming a static array */
#if defined(__GNUC__) && !defined(__cplusplus) && !defined(__clang__) && !defined(__INTEL_COMPILER)
diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c
index 027c6e084f5..5571636be63 100644
--- a/source/blender/blenlib/intern/BLI_kdopbvh.c
+++ b/source/blender/blenlib/intern/BLI_kdopbvh.c
@@ -167,6 +167,18 @@ typedef struct BVHRayCastData {
BVHTreeRayHit hit;
} BVHRayCastData;
+typedef struct BVHNearestProjectedData {
+ const BVHTree *tree;
+ struct DistProjectedAABBPrecalc precalc;
+ bool closest_axis[3];
+ float clip_plane[6][4];
+ int clip_plane_len;
+ BVHTree_NearestProjectedCallback callback;
+ void *userdata;
+ BVHTreeNearest nearest;
+
+} BVHNearestProjectedData;
+
/** \} */
@@ -2020,6 +2032,192 @@ int BLI_bvhtree_range_query(
/* -------------------------------------------------------------------- */
+/** \name BLI_bvhtree_nearest_projected
+* \{ */
+
+static void bvhtree_nearest_projected_dfs_recursive(
+ BVHNearestProjectedData *__restrict data, const BVHNode *node)
+{
+ if (node->totnode == 0) {
+ if (data->callback) {
+ data->callback(data->userdata, node->index, &data->precalc, &data->nearest);
+ }
+ else {
+ data->nearest.index = node->index;
+ data->nearest.dist_sq = dist_squared_to_projected_aabb(
+ &data->precalc,
+ (float[3]) {node->bv[0], node->bv[2], node->bv[4]},
+ (float[3]) {node->bv[1], node->bv[3], node->bv[5]},
+ data->closest_axis);
+ }
+ }
+ else {
+ /* First pick the closest node to recurse into */
+ if (data->closest_axis[node->main_axis]) {
+ for (int i = 0; i != node->totnode; i++) {
+ const float *bv = node->children[i]->bv;
+
+ if (dist_squared_to_projected_aabb(
+ &data->precalc,
+ (float[3]) {bv[0], bv[2], bv[4]},
+ (float[3]) {bv[1], bv[3], bv[5]},
+ data->closest_axis) <= data->nearest.dist_sq)
+ {
+ bvhtree_nearest_projected_dfs_recursive(data, node->children[i]);
+ }
+ }
+ }
+ else {
+ for (int i = node->totnode; i--;) {
+ const float *bv = node->children[i]->bv;
+
+ if (dist_squared_to_projected_aabb(
+ &data->precalc,
+ (float[3]) {bv[0], bv[2], bv[4]},
+ (float[3]) {bv[1], bv[3], bv[5]},
+ data->closest_axis) <= data->nearest.dist_sq)
+ {
+ bvhtree_nearest_projected_dfs_recursive(data, node->children[i]);
+ }
+ }
+ }
+ }
+}
+
+static void bvhtree_nearest_projected_with_clipplane_test_dfs_recursive(
+ BVHNearestProjectedData *__restrict data, const BVHNode *node)
+{
+ if (node->totnode == 0) {
+ if (data->callback) {
+ data->callback(data->userdata, node->index, &data->precalc, &data->nearest);
+ }
+ else {
+ data->nearest.index = node->index;
+ data->nearest.dist_sq = dist_squared_to_projected_aabb(
+ &data->precalc,
+ (float[3]) {node->bv[0], node->bv[2], node->bv[4]},
+ (float[3]) {node->bv[1], node->bv[3], node->bv[5]},
+ data->closest_axis);
+ }
+ }
+ else {
+ /* First pick the closest node to recurse into */
+ if (data->closest_axis[node->main_axis]) {
+ for (int i = 0; i != node->totnode; i++) {
+ const float *bv = node->children[i]->bv;
+ const float bb_min[3] = {bv[0], bv[2], bv[4]};
+ const float bb_max[3] = {bv[1], bv[3], bv[5]};
+
+ int isect_type = isect_aabb_planes_v3(data->clip_plane, data->clip_plane_len, bb_min, bb_max);
+
+ if ((isect_type != ISECT_AABB_PLANE_BEHIND_ANY) && dist_squared_to_projected_aabb(
+ &data->precalc, bb_min, bb_max,
+ data->closest_axis) <= data->nearest.dist_sq)
+ {
+ if (isect_type == ISECT_AABB_PLANE_CROSS_ANY) {
+ bvhtree_nearest_projected_with_clipplane_test_dfs_recursive(data, node->children[i]);
+ }
+ else {
+ /* ISECT_AABB_PLANE_IN_FRONT_ALL */
+ bvhtree_nearest_projected_dfs_recursive(data, node->children[i]);
+ }
+ }
+ }
+ }
+ else {
+ for (int i = node->totnode; i--;) {
+ const float *bv = node->children[i]->bv;
+ const float bb_min[3] = {bv[0], bv[2], bv[4]};
+ const float bb_max[3] = {bv[1], bv[3], bv[5]};
+
+ int isect_type = isect_aabb_planes_v3(data->clip_plane, data->clip_plane_len, bb_min, bb_max);
+
+ if (isect_type != ISECT_AABB_PLANE_BEHIND_ANY && dist_squared_to_projected_aabb(
+ &data->precalc, bb_min, bb_max,
+ data->closest_axis) <= data->nearest.dist_sq)
+ {
+ if (isect_type == ISECT_AABB_PLANE_CROSS_ANY) {
+ bvhtree_nearest_projected_with_clipplane_test_dfs_recursive(data, node->children[i]);
+ }
+ else {
+ /* ISECT_AABB_PLANE_IN_FRONT_ALL */
+ bvhtree_nearest_projected_dfs_recursive(data, node->children[i]);
+ }
+ }
+ }
+ }
+ }
+}
+
+int BLI_bvhtree_find_nearest_projected(
+ BVHTree *tree, float projmat[4][4], float winsize[2], float mval[2],
+ float clip_plane[6][4], int clip_plane_len,
+ BVHTreeNearest *nearest,
+ BVHTree_NearestProjectedCallback callback, void *userdata)
+{
+ BVHNode *root = tree->nodes[tree->totleaf];
+ if (root != NULL) {
+ BVHNearestProjectedData data;
+ dist_squared_to_projected_aabb_precalc(
+ &data.precalc, projmat, winsize, mval);
+
+ data.callback = callback;
+ data.userdata = userdata;
+
+ if (clip_plane) {
+ data.clip_plane_len = clip_plane_len;
+ for (int i = 0; i < data.clip_plane_len; i++) {
+ copy_v4_v4(data.clip_plane[i], clip_plane[i]);
+ }
+ }
+ else {
+ data.clip_plane_len = 1;
+ planes_from_projmat(
+ projmat,
+ NULL, NULL, NULL, NULL,
+ data.clip_plane[0], NULL);
+ }
+
+ if (nearest) {
+ memcpy(&data.nearest, nearest, sizeof(*nearest));
+ }
+ else {
+ data.nearest.index = -1;
+ data.nearest.dist_sq = FLT_MAX;
+ }
+ {
+ const float bb_min[3] = {root->bv[0], root->bv[2], root->bv[4]};
+ const float bb_max[3] = {root->bv[1], root->bv[3], root->bv[5]};
+
+ int isect_type = isect_aabb_planes_v3(data.clip_plane, data.clip_plane_len, bb_min, bb_max);
+
+ if (isect_type != 0 && dist_squared_to_projected_aabb(
+ &data.precalc, bb_min, bb_max,
+ data.closest_axis) <= data.nearest.dist_sq)
+ {
+ if (isect_type == 1) {
+ bvhtree_nearest_projected_with_clipplane_test_dfs_recursive(&data, root);
+ }
+ else {
+ bvhtree_nearest_projected_dfs_recursive(&data, root);
+ }
+ }
+ }
+
+ if (nearest) {
+ memcpy(nearest, &data.nearest, sizeof(*nearest));
+ }
+
+ return data.nearest.index;
+ }
+ return -1;
+}
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
/** \name BLI_bvhtree_walk_dfs
* \{ */
diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c
index cb810b3df18..286ccbf63e7 100644
--- a/source/blender/blenlib/intern/math_geom.c
+++ b/source/blender/blenlib/intern/math_geom.c
@@ -619,6 +619,38 @@ float dist_squared_ray_to_seg_v3(
return len_squared_v3(t) - SQUARE(*r_depth);
}
+/* Returns the coordinates of the nearest vertex and
+ * the farthest vertex from a plane (or normal). */
+void aabb_get_near_far_from_plane(
+ const float plane_no[3], const float bbmin[3], const float bbmax[3],
+ float bb_near[3], float bb_afar[3])
+{
+ if (plane_no[0] < 0.0f) {
+ bb_near[0] = bbmax[0];
+ bb_afar[0] = bbmin[0];
+ }
+ else {
+ bb_near[0] = bbmin[0];
+ bb_afar[0] = bbmax[0];
+ }
+ if (plane_no[1] < 0.0f) {
+ bb_near[1] = bbmax[1];
+ bb_afar[1] = bbmin[1];
+ }
+ else {
+ bb_near[1] = bbmin[1];
+ bb_afar[1] = bbmax[1];
+ }
+ if (plane_no[2] < 0.0f) {
+ bb_near[2] = bbmax[2];
+ bb_afar[2] = bbmin[2];
+ }
+ else {
+ bb_near[2] = bbmin[2];
+ bb_afar[2] = bbmax[2];
+ }
+}
+
/* -------------------------------------------------------------------- */
/** \name dist_squared_to_ray_to_aabb and helpers
* \{ */
@@ -634,7 +666,6 @@ void dist_squared_ray_to_aabb_v3_precalc(
neasrest_precalc->ray_inv_dir[i] =
(neasrest_precalc->ray_direction[i] != 0.0f) ?
(1.0f / neasrest_precalc->ray_direction[i]) : FLT_MAX;
- neasrest_precalc->sign[i] = (neasrest_precalc->ray_inv_dir[i] < 0.0f);
}
}
@@ -648,30 +679,8 @@ float dist_squared_ray_to_aabb_v3(
{
// bool r_axis_closest[3];
float local_bvmin[3], local_bvmax[3];
- if (data->sign[0]) {
- local_bvmin[0] = bb_max[0];
- local_bvmax[0] = bb_min[0];
- }
- else {
- local_bvmin[0] = bb_min[0];
- local_bvmax[0] = bb_max[0];
- }
- if (data->sign[1]) {
- local_bvmin[1] = bb_max[1];
- local_bvmax[1] = bb_min[1];
- }
- else {
- local_bvmin[1] = bb_min[1];
- local_bvmax[1] = bb_max[1];
- }
- if (data->sign[2]) {
- local_bvmin[2] = bb_max[2];
- local_bvmax[2] = bb_min[2];
- }
- else {
- local_bvmin[2] = bb_min[2];
- local_bvmax[2] = bb_max[2];
- }
+ aabb_get_near_far_from_plane(
+ data->ray_direction, bb_min, bb_max, local_bvmin, local_bvmax);
const float tmin[3] = {
(local_bvmin[0] - data->ray_origin[0]) * data->ray_inv_dir[0],
@@ -693,38 +702,38 @@ float dist_squared_ray_to_aabb_v3(
rtmax = tmax[0];
va[0] = vb[0] = local_bvmax[0];
main_axis = 3;
- // r_axis_closest[0] = data->sign[0];
+ // r_axis_closest[0] = neasrest_precalc->ray_direction[0] < 0.0f;
}
else if ((tmax[1] <= tmax[0]) && (tmax[1] <= tmax[2])) {
rtmax = tmax[1];
va[1] = vb[1] = local_bvmax[1];
main_axis = 2;
- // r_axis_closest[1] = data->sign[1];
+ // r_axis_closest[1] = neasrest_precalc->ray_direction[1] < 0.0f;
}
else {
rtmax = tmax[2];
va[2] = vb[2] = local_bvmax[2];
main_axis = 1;
- // r_axis_closest[2] = data->sign[2];
+ // r_axis_closest[2] = neasrest_precalc->ray_direction[2] < 0.0f;
}
if ((tmin[0] >= tmin[1]) && (tmin[0] >= tmin[2])) {
rtmin = tmin[0];
va[0] = vb[0] = local_bvmin[0];
main_axis -= 3;
- // r_axis_closest[0] = !data->sign[0];
+ // r_axis_closest[0] = neasrest_precalc->ray_direction[0] >= 0.0f;
}
else if ((tmin[1] >= tmin[0]) && (tmin[1] >= tmin[2])) {
rtmin = tmin[1];
va[1] = vb[1] = local_bvmin[1];
main_axis -= 1;
- // r_axis_closest[1] = !data->sign[1];
+ // r_axis_closest[1] = neasrest_precalc->ray_direction[1] >= 0.0f;
}
else {
rtmin = tmin[2];
va[2] = vb[2] = local_bvmin[2];
main_axis -= 2;
- // r_axis_closest[2] = !data->sign[2];
+ // r_axis_closest[2] = neasrest_precalc->ray_direction[2] >= 0.0f;
}
if (main_axis < 0) {
main_axis += 3;
@@ -739,14 +748,14 @@ float dist_squared_ray_to_aabb_v3(
return 0.0f;
}
- if (data->sign[main_axis]) {
- va[main_axis] = local_bvmax[main_axis];
- vb[main_axis] = local_bvmin[main_axis];
- }
- else {
+ if (data->ray_direction[main_axis] >= 0.0f) {
va[main_axis] = local_bvmin[main_axis];
vb[main_axis] = local_bvmax[main_axis];
}
+ else {
+ va[main_axis] = local_bvmax[main_axis];
+ vb[main_axis] = local_bvmin[main_axis];
+ }
return dist_squared_ray_to_seg_v3(
data->ray_origin, data->ray_direction, va, vb,
@@ -839,35 +848,8 @@ float dist_squared_to_projected_aabb(
bool r_axis_closest[3])
{
float local_bvmin[3], local_bvmax[3];
- bool sign[3] = {
- data->ray_inv_dir[0] >= 0.0f,
- data->ray_inv_dir[1] >= 0.0f,
- data->ray_inv_dir[2] >= 0.0f,
- };
- if (sign[0]) {
- local_bvmin[0] = bbmin[0];
- local_bvmax[0] = bbmax[0];
- }
- else {
- local_bvmin[0] = bbmax[0];
- local_bvmax[0] = bbmin[0];
- }
- if (sign[1]) {
- local_bvmin[1] = bbmin[1];
- local_bvmax[1] = bbmax[1];
- }
- else {
- local_bvmin[1] = bbmax[1];
- local_bvmax[1] = bbmin[1];
- }
- if (sign[2]) {
- local_bvmin[2] = bbmin[2];
- local_bvmax[2] = bbmax[2];
- }
- else {
- local_bvmin[2] = bbmax[2];
- local_bvmax[2] = bbmin[2];
- }
+ aabb_get_near_far_from_plane(
+ data->ray_direction, bbmin, bbmax, local_bvmin, local_bvmax);
const float tmin[3] = {
(local_bvmin[0] - data->ray_origin[0]) * data->ray_inv_dir[0],
@@ -889,38 +871,38 @@ float dist_squared_to_projected_aabb(
rtmax = tmax[0];
va[0] = vb[0] = local_bvmax[0];
main_axis = 3;
- r_axis_closest[0] = !sign[0];
+ r_axis_closest[0] = data->ray_direction[0] < 0.0f;
}
else if ((tmax[1] <= tmax[0]) && (tmax[1] <= tmax[2])) {
rtmax = tmax[1];
va[1] = vb[1] = local_bvmax[1];
main_axis = 2;
- r_axis_closest[1] = !sign[1];
+ r_axis_closest[1] = data->ray_direction[1] < 0.0f;
}
else {
rtmax = tmax[2];
va[2] = vb[2] = local_bvmax[2];
main_axis = 1;
- r_axis_closest[2] = !sign[2];
+ r_axis_closest[2] = data->ray_direction[2] < 0.0f;
}
if ((tmin[0] >= tmin[1]) && (tmin[0] >= tmin[2])) {
rtmin = tmin[0];
va[0] = vb[0] = local_bvmin[0];
main_axis -= 3;
- r_axis_closest[0] = sign[0];
+ r_axis_closest[0] = data->ray_direction[0] >= 0.0f;
}
else if ((tmin[1] >= tmin[0]) && (tmin[1] >= tmin[2])) {
rtmin = tmin[1];
va[1] = vb[1] = local_bvmin[1];
main_axis -= 1;
- r_axis_closest[1] = sign[1];
+ r_axis_closest[1] = data->ray_direction[1] >= 0.0f;
}
else {
rtmin = tmin[2];
va[2] = vb[2] = local_bvmin[2];
main_axis -= 2;
- r_axis_closest[2] = sign[2];
+ r_axis_closest[2] = data->ray_direction[2] >= 0.0f;
}
if (main_axis < 0) {
main_axis += 3;
@@ -931,7 +913,7 @@ float dist_squared_to_projected_aabb(
return 0;
}
- if (sign[main_axis]) {
+ if (data->ray_direction[main_axis] >= 0.0f) {
va[main_axis] = local_bvmin[main_axis];
vb[main_axis] = local_bvmax[main_axis];
}
@@ -2278,6 +2260,38 @@ static bool getLowestRoot(const float a, const float b, const float c, const flo
return false;
}
+
+/**
+ * Checks status of an AABB in relation to a list of planes.
+ *
+ * \returns intersection type:
+ * - ISECT_AABB_PLANE_BEHIND_ONE (0): AABB is completely behind at least 1 plane;
+ * - ISECT_AABB_PLANE_CROSS_ANY (1): AABB intersects at least 1 plane;
+ * - ISECT_AABB_PLANE_IN_FRONT_ALL (2): AABB is completely in front of all planes;
+ */
+int isect_aabb_planes_v3(
+ const float (*planes)[4], const int totplane,
+ const float bbmin[3], const float bbmax[3])
+{
+ int ret = ISECT_AABB_PLANE_IN_FRONT_ALL;
+
+ float bb_near[3], bb_far[3];
+ for (int i = 0; i < totplane; i++) {
+ aabb_get_near_far_from_plane(planes[i], bbmin, bbmax, bb_near, bb_far);
+
+ if (plane_point_side_v3(planes[i], bb_far) < 0.0f) {
+ return ISECT_AABB_PLANE_BEHIND_ANY;
+ }
+ else if ((ret != ISECT_AABB_PLANE_CROSS_ANY) &&
+ (plane_point_side_v3(planes[i], bb_near) < 0.0f))
+ {
+ ret = ISECT_AABB_PLANE_CROSS_ANY;
+ }
+ }
+
+ return ret;
+}
+
bool isect_sweeping_sphere_tri_v3(const float p1[3], const float p2[3], const float radius,
const float v0[3], const float v1[3], const float v2[3],
float *r_lambda, float ipoint[3])
diff --git a/source/blender/blenlib/intern/math_vector_inline.c b/source/blender/blenlib/intern/math_vector_inline.c
index 4f658ef015f..4c40921edb6 100644
--- a/source/blender/blenlib/intern/math_vector_inline.c
+++ b/source/blender/blenlib/intern/math_vector_inline.c
@@ -501,15 +501,15 @@ MINLINE float mul_project_m4_v3_zfac(const float mat[4][4], const float co[3])
/**
* Has the effect of #mul_m3_v3(), on a single axis.
*/
-MINLINE float dot_m3_v3_row_x(float M[3][3], const float a[3])
+MINLINE float dot_m3_v3_row_x(const float M[3][3], const float a[3])
{
return M[0][0] * a[0] + M[1][0] * a[1] + M[2][0] * a[2];
}
-MINLINE float dot_m3_v3_row_y(float M[3][3], const float a[3])
+MINLINE float dot_m3_v3_row_y(const float M[3][3], const float a[3])
{
return M[0][1] * a[0] + M[1][1] * a[1] + M[2][1] * a[2];
}
-MINLINE float dot_m3_v3_row_z(float M[3][3], const float a[3])
+MINLINE float dot_m3_v3_row_z(const float M[3][3], const float a[3])
{
return M[0][2] * a[0] + M[1][2] * a[1] + M[2][2] * a[2];
}
@@ -518,15 +518,15 @@ MINLINE float dot_m3_v3_row_z(float M[3][3], const float a[3])
* Has the effect of #mul_mat3_m4_v3(), on a single axis.
* (no adding translation)
*/
-MINLINE float dot_m4_v3_row_x(float M[4][4], const float a[3])
+MINLINE float dot_m4_v3_row_x(const float M[4][4], const float a[3])
{
return M[0][0] * a[0] + M[1][0] * a[1] + M[2][0] * a[2];
}
-MINLINE float dot_m4_v3_row_y(float M[4][4], const float a[3])
+MINLINE float dot_m4_v3_row_y(const float M[4][4], const float a[3])
{
return M[0][1] * a[0] + M[1][1] * a[1] + M[2][1] * a[2];
}
-MINLINE float dot_m4_v3_row_z(float M[4][4], const float a[3])
+MINLINE float dot_m4_v3_row_z(const float M[4][4], const float a[3])
{
return M[0][2] * a[0] + M[1][2] * a[1] + M[2][2] * a[2];
}
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 6315eb7ba93..140e66a4572 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -6378,7 +6378,7 @@ static void direct_link_region(FileData *fd, ARegion *ar, int spacetype)
ar->v2d.tab_num = 0;
ar->v2d.tab_cur = 0;
ar->v2d.sms = NULL;
- ar->v2d.alpha_hor = ar->v2d.alpha_vert = 0;
+ ar->v2d.alpha_hor = ar->v2d.alpha_vert = 255; /* visible by default */
ar->v2d.size_hor = ar->v2d.size_vert = 0;
BLI_listbase_clear(&ar->panels_category);
BLI_listbase_clear(&ar->handlers);
diff --git a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
index 80d305cb1e8..704b039e0f6 100644
--- a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
@@ -671,6 +671,7 @@ struct Closure {
/* This is hacking ssr_id to tag transparent bsdf */
#define TRANSPARENT_CLOSURE_FLAG -2
#define REFRACT_CLOSURE_FLAG -3
+#define NO_SSR -999
# ifdef USE_SSS
# ifdef USE_SSS_ALBEDO
diff --git a/source/blender/draw/engines/eevee/shaders/lamps_lib.glsl b/source/blender/draw/engines/eevee/shaders/lamps_lib.glsl
index 62f4c0c1c93..198a05ccf97 100644
--- a/source/blender/draw/engines/eevee/shaders/lamps_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/lamps_lib.glsl
@@ -423,31 +423,3 @@ vec3 light_translucent(LightData ld, vec3 W, vec3 N, vec4 l_vector, float scale)
return vis;
#endif
}
-
-#ifdef HAIR_SHADER
-void light_hair_common(
- LightData ld, vec3 N, vec3 V, vec4 l_vector, vec3 norm_view,
- out float occlu_trans, out float occlu,
- out vec3 norm_lamp, out vec3 view_vec)
-{
- const float transmission = 0.3; /* Uniform internal scattering factor */
-
- vec3 lamp_vec;
-
- if (ld.l_type == SUN || ld.l_type == AREA) {
- lamp_vec = ld.l_forward;
- }
- else {
- lamp_vec = -l_vector.xyz;
- }
-
- norm_lamp = cross(lamp_vec, N);
- norm_lamp = normalize(cross(N, norm_lamp)); /* Normal facing lamp */
-
- /* Rotate view vector onto the cross(tangent, light) plane */
- view_vec = normalize(norm_lamp * dot(norm_view, V) + N * dot(N, V));
-
- occlu = (dot(norm_view, norm_lamp) * 0.5 + 0.5);
- occlu_trans = transmission + (occlu * (1.0 - transmission)); /* Includes transmission component */
-}
-#endif
diff --git a/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl
index 88fde8929cb..737a2977146 100644
--- a/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl
@@ -168,15 +168,28 @@ void CLOSURE_NAME(
vec4 rand = texelFetch(utilTex, ivec3(ivec2(gl_FragCoord.xy) % LUT_SIZE, 2.0), 0);
+#ifdef HAIR_SHADER
+ /* Random normal distribution on the hair surface. */
+ vec3 T = normalize(worldNormal); /* meh, TODO fix worldNormal misnaming. */
+ vec3 B = normalize(cross(V, T));
+ N = cross(T, B); /* Normal facing view */
+ /* We want a cosine distribution. */
+ float cos_theta = rand.x * 2.0 - 1.0;
+ float sin_theta = sqrt(max(0.0, 1.0f - cos_theta*cos_theta));;
+ N = N * sin_theta + B * cos_theta;
+
+# ifdef CLOSURE_GLOSSY
+ /* Hair random normal does not work with SSR :(.
+ * It just create self reflection feedback (which is beautifful btw)
+ * but not correct. */
+ ssr_id = NO_SSR; /* Force bypass */
+# endif
+#endif
+
/* ---------------------------------------------------------------- */
/* -------------------- SCENE LAMPS LIGHTING ---------------------- */
/* ---------------------------------------------------------------- */
-#ifdef HAIR_SHADER
- vec3 norm_view = cross(V, N);
- norm_view = normalize(cross(norm_view, N)); /* Normal facing view */
-#endif
-
for (int i = 0; i < MAX_LIGHT && i < laNumLight; ++i) {
LightData ld = lights_data[i];
@@ -186,29 +199,6 @@ void CLOSURE_NAME(
vec3 l_color_vis = ld.l_color * light_visibility(ld, worldPosition, viewPosition, viewNormal, l_vector);
-#ifdef HAIR_SHADER
- vec3 norm_lamp, view_vec;
- float occlu_trans, occlu;
- light_hair_common(ld, N, V, l_vector, norm_view, occlu_trans, occlu, norm_lamp, view_vec);
-
- #ifdef CLOSURE_DIFFUSE
- out_diff += l_color_vis * light_diffuse(ld, -norm_lamp, V, l_vector) * occlu_trans;
- #endif
-
- #ifdef CLOSURE_SUBSURFACE
- out_trans += ld.l_color * light_translucent(ld, worldPosition, -norm_lamp, l_vector, sss_scale) * occlu_trans;
- #endif
-
- #ifdef CLOSURE_GLOSSY
- out_spec += l_color_vis * light_specular(ld, N, view_vec, l_vector, roughnessSquared, f0) * occlu * ld.l_spec;
- #endif
-
- #ifdef CLOSURE_CLEARCOAT
- out_spec += l_color_vis * light_specular(ld, C_N, view_vec, l_vector, C_roughnessSquared, f0) * C_intensity * occlu * ld.l_spec;
- #endif
-
-#else /* HAIR_SHADER */
-
#ifdef CLOSURE_DIFFUSE
out_diff += l_color_vis * light_diffuse(ld, N, V, l_vector);
#endif
@@ -224,15 +214,8 @@ void CLOSURE_NAME(
#ifdef CLOSURE_CLEARCOAT
out_spec += l_color_vis * light_specular(ld, C_N, V, l_vector, C_roughnessSquared, f0) * C_intensity * ld.l_spec;
#endif
-
-#endif /* HAIR_SHADER */
}
-#ifdef HAIR_SHADER
- N = -norm_view;
-#endif
-
-
/* ---------------------------------------------------------------- */
/* ---------------- SPECULAR ENVIRONMENT LIGHTING ----------------- */
@@ -409,6 +392,12 @@ void CLOSURE_NAME(
}
out_spec += spec_accum.rgb * ssr_spec * spec_occlu * float(specToggle);
+
+# ifdef HAIR_SHADER
+ /* Hack: Overide spec color so that ssr will not be computed
+ * even if ssr_id match the active ssr. */
+ ssr_spec = vec3(0.0);
+# endif
#endif
#ifdef CLOSURE_REFRACTION
diff --git a/source/blender/draw/engines/workbench/workbench_materials.c b/source/blender/draw/engines/workbench/workbench_materials.c
index 680ac264233..631ee0d92b1 100644
--- a/source/blender/draw/engines/workbench/workbench_materials.c
+++ b/source/blender/draw/engines/workbench/workbench_materials.c
@@ -578,10 +578,12 @@ void workbench_materials_draw_background(WORKBENCH_Data *vedata)
const float clear_color[4] = {0.0f, 0.0f, 0.0f, 0.0f};
uint clear_stencil = 0xFF;
+ DRW_stats_group_start("Clear Background");
GPU_framebuffer_bind(fbl->prepass_fb);
int clear_bits = GPU_DEPTH_BIT | GPU_COLOR_BIT;
SET_FLAG_FROM_TEST(clear_bits, SHADOW_ENABLED(wpd), GPU_STENCIL_BIT);
GPU_framebuffer_clear(fbl->prepass_fb, clear_bits, clear_color, clear_depth, clear_stencil);
+ DRW_stats_group_end();
}
void workbench_materials_draw_scene(WORKBENCH_Data *vedata)
diff --git a/source/blender/draw/intern/draw_armature.c b/source/blender/draw/intern/draw_armature.c
index 5ad05da5cbf..d07febfdd22 100644
--- a/source/blender/draw/intern/draw_armature.c
+++ b/source/blender/draw/intern/draw_armature.c
@@ -1577,11 +1577,8 @@ static void draw_armature_pose(Object *ob, const float const_color[4])
const bool show_relations = true; /* TODO get value from overlays settings. */
/* being set below */
- arm->layer_used = 0;
-
for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
bone = pchan->bone;
- arm->layer_used |= bone->layer;
/* bone must be visible */
if ((bone->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG)) == 0) {
diff --git a/source/blender/draw/intern/draw_cache_impl_displist.c b/source/blender/draw/intern/draw_cache_impl_displist.c
index 627fb38d9d6..09531220d9a 100644
--- a/source/blender/draw/intern/draw_cache_impl_displist.c
+++ b/source/blender/draw/intern/draw_cache_impl_displist.c
@@ -285,7 +285,7 @@ Gwn_Batch **DRW_displist_batch_calc_tri_pos_normals_and_uv_split_by_material(Lis
displist_vertbuf_attr_set_tri_pos_normals_and_uv(
&pos_step[col], &nor_step[col], &uv_step[col],
verts[idx[0]], verts[idx[2]], verts[idx[1]],
- nors[idx[0]], nors[idx[2]], nors[idx[1]],
+ dl->nors, dl->nors, dl->nors,
uv[0], uv[1], uv[2]);
}
}
diff --git a/source/blender/editors/armature/pose_edit.c b/source/blender/editors/armature/pose_edit.c
index d24848b4b76..09190af0360 100644
--- a/source/blender/editors/armature/pose_edit.c
+++ b/source/blender/editors/armature/pose_edit.c
@@ -917,7 +917,7 @@ void ARMATURE_OT_armature_layers(wmOperatorType *ot)
/* Present a popup to get the layers that should be used */
static int pose_bone_layers_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- int layers[32]; /* hardcoded for now - we can only have 32 armature layers, so this should be fine... */
+ int layers[32] = {0}; /* hardcoded for now - we can only have 32 armature layers, so this should be fine... */
/* get layers that are active already */
CTX_DATA_BEGIN (C, bPoseChannel *, pchan, selected_pose_bones)
diff --git a/source/blender/editors/armature/pose_select.c b/source/blender/editors/armature/pose_select.c
index 55fceba4368..d4b89cd6a00 100644
--- a/source/blender/editors/armature/pose_select.c
+++ b/source/blender/editors/armature/pose_select.c
@@ -546,6 +546,8 @@ static int pose_select_constraint_target_exec(bContext *C, wmOperator *UNUSED(op
/* mask modifier ('armature' mode), etc. */
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
+ /* tag armature for copy on write, since selection status is armature data */
+ DEG_id_tag_update(&arm->id, DEG_TAG_COPY_ON_WRITE);
ob_prev = ob;
}
}
diff --git a/source/blender/editors/include/ED_manipulator_library.h b/source/blender/editors/include/ED_manipulator_library.h
index 7166292147e..b67af4274a6 100644
--- a/source/blender/editors/include/ED_manipulator_library.h
+++ b/source/blender/editors/include/ED_manipulator_library.h
@@ -192,6 +192,18 @@ enum {
ED_MANIPULATOR_GRAB_STYLE_CROSS_2D = 1,
};
+/* -------------------------------------------------------------------- */
+/* Button Manipulator */
+
+enum {
+ ED_MANIPULATOR_BUTTON_SHOW_OUTLINE = (1 << 0),
+ /**
+ * Draw a line from the origin to the offset (similar to an arrow)
+ * sometimes needed to show what the button edits.
+ */
+ ED_MANIPULATOR_BUTTON_SHOW_HELPLINE = (1 << 1),
+};
+
/* -------------------------------------------------------------------- */
/* Primitive Manipulator */
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index c1aae483644..f0db1782a7e 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -100,6 +100,8 @@ enum {
UI_EMBOSS_NONE = 1, /* Nothing, only icon and/or text */
UI_EMBOSS_PULLDOWN = 2, /* Pulldown menu style */
UI_EMBOSS_RADIAL = 3, /* Pie Menu */
+
+ UI_EMBOSS_UNDEFINED = 255, /* For layout engine, use emboss from block. */
};
/* uiBlock->direction */
@@ -523,6 +525,7 @@ void UI_block_direction_set(uiBlock *block, char direction);
void UI_block_order_flip(uiBlock *block);
void UI_block_flag_enable(uiBlock *block, int flag);
void UI_block_flag_disable(uiBlock *block, int flag);
+void UI_block_translate(uiBlock *block, int x, int y);
int UI_but_return_value_get(uiBut *but);
@@ -946,6 +949,7 @@ void uiLayoutSetAlignment(uiLayout *layout, char alignment);
void uiLayoutSetKeepAspect(uiLayout *layout, bool keepaspect);
void uiLayoutSetScaleX(uiLayout *layout, float scale);
void uiLayoutSetScaleY(uiLayout *layout, float scale);
+void uiLayoutSetEmboss(uiLayout *layout, char emboss);
int uiLayoutGetOperatorContext(uiLayout *layout);
bool uiLayoutGetActive(uiLayout *layout);
@@ -956,6 +960,7 @@ bool uiLayoutGetKeepAspect(uiLayout *layout);
int uiLayoutGetWidth(uiLayout *layout);
float uiLayoutGetScaleX(uiLayout *layout);
float uiLayoutGetScaleY(uiLayout *layout);
+int uiLayoutGetEmboss(uiLayout *layout);
/* layout specifiers */
uiLayout *uiLayoutRow(uiLayout *layout, int align);
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index b63ba4166a7..be0c84f7d80 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -262,7 +262,7 @@ void ui_region_winrct_get_no_margin(const struct ARegion *ar, struct rcti *r_rec
/* ******************* block calc ************************* */
-void ui_block_translate(uiBlock *block, int x, int y)
+void UI_block_translate(uiBlock *block, int x, int y)
{
uiBut *but;
@@ -372,7 +372,7 @@ static void ui_block_bounds_calc_centered(wmWindow *window, uiBlock *block)
startx = (xmax * 0.5f) - (width * 0.5f);
starty = (ymax * 0.5f) - (height * 0.5f);
- ui_block_translate(block, startx - block->rect.xmin, starty - block->rect.ymin);
+ UI_block_translate(block, startx - block->rect.xmin, starty - block->rect.ymin);
/* now recompute bounds and safety */
ui_block_bounds_calc(block);
@@ -386,7 +386,7 @@ static void ui_block_bounds_calc_centered_pie(uiBlock *block)
block->pie_data.pie_center_spawned[1]
};
- ui_block_translate(block, xy[0], xy[1]);
+ UI_block_translate(block, xy[0], xy[1]);
/* now recompute bounds and safety */
ui_block_bounds_calc(block);
@@ -446,7 +446,7 @@ static void ui_block_bounds_calc_popup(
rect_bounds.ymax = ymax - UI_POPUP_MENU_TOP;
BLI_rcti_clamp(&rect, &rect_bounds, ofs_dummy);
- ui_block_translate(block, rect.xmin - block->rect.xmin, rect.ymin - block->rect.ymin);
+ UI_block_translate(block, rect.xmin - block->rect.xmin, rect.ymin - block->rect.ymin);
/* now recompute bounds and safety */
ui_block_bounds_calc(block);
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index 1687562d3e0..7ca3ffc8c84 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -8927,6 +8927,9 @@ static int ui_menu_scroll(ARegion *ar, uiBlock *block, int my, uiBut *to_bt)
dy = block->rect.ymin - ymin + UI_MENU_SCROLL_PAD;
}
+ /* remember scroll offset for refreshes */
+ block->handle->scrolloffset += dy;
+
/* apply scroll offset */
for (bt = block->buttons.first; bt; bt = bt->next) {
bt->rect.ymin += dy;
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index de2217a3d3e..280156a5290 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -501,7 +501,6 @@ extern int ui_but_is_pushed(uiBut *but) ATTR_WARN_UNUSED_RESULT;
void ui_but_override_flag(uiBut *but);
extern void ui_block_bounds_calc(uiBlock *block);
-extern void ui_block_translate(uiBlock *block, int x, int y);
extern struct ColorManagedDisplay *ui_block_cm_display_get(uiBlock *block);
void ui_block_cm_to_display_space_v3(uiBlock *block, float pixel[3]);
@@ -554,6 +553,7 @@ struct uiPopupBlockHandle {
bool refresh;
struct wmTimer *scrolltimer;
+ float scrolloffset;
struct uiKeyNavLock keynav_state;
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index da1f57409a8..d9db5c930fc 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -151,6 +151,7 @@ struct uiLayout {
bool redalert;
bool keepaspect;
char alignment;
+ char emboss;
};
typedef struct uiLayoutItemFlow {
@@ -844,8 +845,10 @@ static uiBut *uiItemFullO_ptr_ex(
w = ui_text_icon_width(layout, name, icon, 0);
- if (flag & UI_ITEM_R_NO_BG)
- UI_block_emboss_set(block, UI_EMBOSS_NONE);
+ int prev_emboss = layout->emboss;
+ if (flag & UI_ITEM_R_NO_BG) {
+ layout->emboss = UI_EMBOSS_NONE;
+ }
/* create the button */
if (icon) {
@@ -866,8 +869,9 @@ static uiBut *uiItemFullO_ptr_ex(
if ((layout->root->type == UI_LAYOUT_TOOLBAR) && !icon)
but->drawflag |= UI_BUT_TEXT_LEFT;
- if (flag & UI_ITEM_R_NO_BG)
- UI_block_emboss_set(block, UI_EMBOSS);
+ if (flag & UI_ITEM_R_NO_BG) {
+ layout->emboss = prev_emboss;
+ }
if (flag & UI_ITEM_O_DEPRESS) {
but->flag |= UI_SELECT_DRAW;
@@ -1496,8 +1500,10 @@ void uiItemFullR(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index
/* get size */
ui_item_rna_size(layout, name, icon, ptr, prop, index, icon_only, compact, &w, &h);
- if (no_bg)
- UI_block_emboss_set(block, UI_EMBOSS_NONE);
+ int prev_emboss = layout->emboss;
+ if (no_bg) {
+ layout->emboss = UI_EMBOSS_NONE;
+ }
/* array property */
if (index == RNA_NO_INDEX && is_array)
@@ -1543,8 +1549,9 @@ void uiItemFullR(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index
UI_but_flag_enable(but, UI_BUT_LIST_ITEM);
}
- if (no_bg)
- UI_block_emboss_set(block, UI_EMBOSS);
+ if (no_bg) {
+ layout->emboss = prev_emboss;
+ }
/* ensure text isn't added to icon_only buttons */
if (but && icon_only) {
@@ -1880,9 +1887,6 @@ static uiBut *ui_item_menu(
UI_block_layout_set_current(block, layout);
- if (layout->root->type == UI_LAYOUT_HEADER)
- UI_block_emboss_set(block, UI_EMBOSS);
-
if (!name)
name = "";
if (layout->root->type == UI_LAYOUT_MENU && !icon)
@@ -1914,9 +1918,6 @@ static uiBut *ui_item_menu(
but->func_argN = argN;
}
- if (layout->root->type == UI_LAYOUT_HEADER) {
- UI_block_emboss_set(block, UI_EMBOSS);
- }
if (ELEM(layout->root->type, UI_LAYOUT_PANEL, UI_LAYOUT_TOOLBAR) ||
(force_menu && layout->root->type != UI_LAYOUT_MENU)) /* We never want a dropdown in menu! */
{
@@ -2938,22 +2939,29 @@ static void ui_litem_layout_overlap(uiLayout *litem)
litem->y = y - litem->h;
}
-/* layout create functions */
-uiLayout *uiLayoutRow(uiLayout *layout, int align)
+static void ui_litem_init_from_parent(uiLayout *litem, uiLayout *layout, int align)
{
- uiLayout *litem;
-
- litem = MEM_callocN(sizeof(uiLayout), "uiLayoutRow");
- litem->item.type = ITEM_LAYOUT_ROW;
litem->root = layout->root;
litem->align = align;
litem->active = true;
litem->enabled = true;
litem->context = layout->context;
- litem->space = (align) ? 0 : layout->root->style->buttonspacex;
litem->redalert = layout->redalert;
litem->w = layout->w;
+ litem->emboss = layout->emboss;
BLI_addtail(&layout->items, litem);
+}
+
+/* layout create functions */
+uiLayout *uiLayoutRow(uiLayout *layout, int align)
+{
+ uiLayout *litem;
+
+ litem = MEM_callocN(sizeof(uiLayout), "uiLayoutRow");
+ ui_litem_init_from_parent(litem, layout, align);
+
+ litem->item.type = ITEM_LAYOUT_ROW;
+ litem->space = (align) ? 0 : layout->root->style->buttonspacex;
UI_block_layout_set_current(layout->root->block, litem);
@@ -2965,16 +2973,10 @@ uiLayout *uiLayoutColumn(uiLayout *layout, int align)
uiLayout *litem;
litem = MEM_callocN(sizeof(uiLayout), "uiLayoutColumn");
+ ui_litem_init_from_parent(litem, layout, align);
+
litem->item.type = ITEM_LAYOUT_COLUMN;
- litem->root = layout->root;
- litem->align = align;
- litem->active = true;
- litem->enabled = true;
- litem->context = layout->context;
- litem->space = (litem->align) ? 0 : layout->root->style->buttonspacey;
- litem->redalert = layout->redalert;
- litem->w = layout->w;
- BLI_addtail(&layout->items, litem);
+ litem->space = (align) ? 0 : layout->root->style->buttonspacey;
UI_block_layout_set_current(layout->root->block, litem);
@@ -2986,17 +2988,11 @@ uiLayout *uiLayoutColumnFlow(uiLayout *layout, int number, int align)
uiLayoutItemFlow *flow;
flow = MEM_callocN(sizeof(uiLayoutItemFlow), "uiLayoutItemFlow");
+ ui_litem_init_from_parent(&flow->litem, layout, align);
+
flow->litem.item.type = ITEM_LAYOUT_COLUMN_FLOW;
- flow->litem.root = layout->root;
- flow->litem.align = align;
- flow->litem.active = true;
- flow->litem.enabled = true;
- flow->litem.context = layout->context;
flow->litem.space = (flow->litem.align) ? 0 : layout->root->style->columnspace;
- flow->litem.redalert = layout->redalert;
- flow->litem.w = layout->w;
flow->number = number;
- BLI_addtail(&layout->items, flow);
UI_block_layout_set_current(layout->root->block, &flow->litem);
@@ -3008,15 +3004,10 @@ static uiLayoutItemBx *ui_layout_box(uiLayout *layout, int type)
uiLayoutItemBx *box;
box = MEM_callocN(sizeof(uiLayoutItemBx), "uiLayoutItemBx");
+ ui_litem_init_from_parent(&box->litem, layout, false);
+
box->litem.item.type = ITEM_LAYOUT_BOX;
- box->litem.root = layout->root;
- box->litem.active = 1;
- box->litem.enabled = 1;
- box->litem.context = layout->context;
box->litem.space = layout->root->style->columnspace;
- box->litem.redalert = layout->redalert;
- box->litem.w = layout->w;
- BLI_addtail(&layout->items, box);
UI_block_layout_set_current(layout->root->block, &box->litem);
@@ -3044,14 +3035,9 @@ uiLayout *uiLayoutRadial(uiLayout *layout)
}
litem = MEM_callocN(sizeof(uiLayout), "uiLayoutRadial");
+ ui_litem_init_from_parent(litem, layout, false);
+
litem->item.type = ITEM_LAYOUT_RADIAL;
- litem->root = layout->root;
- litem->active = true;
- litem->enabled = true;
- litem->context = layout->context;
- litem->redalert = layout->redalert;
- litem->w = layout->w;
- BLI_addtail(&layout->root->layout->items, litem);
UI_block_layout_set_current(layout->root->block, litem);
@@ -3108,14 +3094,9 @@ uiLayout *uiLayoutAbsolute(uiLayout *layout, int align)
uiLayout *litem;
litem = MEM_callocN(sizeof(uiLayout), "uiLayoutAbsolute");
+ ui_litem_init_from_parent(litem, layout, align);
+
litem->item.type = ITEM_LAYOUT_ABSOLUTE;
- litem->root = layout->root;
- litem->align = align;
- litem->active = 1;
- litem->enabled = 1;
- litem->context = layout->context;
- litem->redalert = layout->redalert;
- BLI_addtail(&layout->items, litem);
UI_block_layout_set_current(layout->root->block, litem);
@@ -3137,13 +3118,9 @@ uiLayout *uiLayoutOverlap(uiLayout *layout)
uiLayout *litem;
litem = MEM_callocN(sizeof(uiLayout), "uiLayoutOverlap");
+ ui_litem_init_from_parent(litem, layout, false);
+
litem->item.type = ITEM_LAYOUT_OVERLAP;
- litem->root = layout->root;
- litem->active = true;
- litem->enabled = true;
- litem->context = layout->context;
- litem->redalert = layout->redalert;
- BLI_addtail(&layout->items, litem);
UI_block_layout_set_current(layout->root->block, litem);
@@ -3155,17 +3132,11 @@ uiLayout *uiLayoutSplit(uiLayout *layout, float percentage, int align)
uiLayoutItemSplit *split;
split = MEM_callocN(sizeof(uiLayoutItemSplit), "uiLayoutItemSplit");
+ ui_litem_init_from_parent(&split->litem, layout, align);
+
split->litem.item.type = ITEM_LAYOUT_SPLIT;
- split->litem.root = layout->root;
- split->litem.align = align;
- split->litem.active = true;
- split->litem.enabled = true;
- split->litem.context = layout->context;
split->litem.space = layout->root->style->columnspace;
- split->litem.redalert = layout->redalert;
- split->litem.w = layout->w;
split->percentage = percentage;
- BLI_addtail(&layout->items, split);
UI_block_layout_set_current(layout->root->block, &split->litem);
@@ -3207,6 +3178,11 @@ void uiLayoutSetScaleY(uiLayout *layout, float scale)
layout->scale[1] = scale;
}
+void uiLayoutSetEmboss(uiLayout *layout, char emboss)
+{
+ layout->emboss = emboss;
+}
+
bool uiLayoutGetActive(uiLayout *layout)
{
return layout->active;
@@ -3247,6 +3223,16 @@ float uiLayoutGetScaleY(uiLayout *layout)
return layout->scale[1];
}
+int uiLayoutGetEmboss(uiLayout *layout)
+{
+ if (layout->emboss == UI_EMBOSS_UNDEFINED) {
+ return layout->root->block->dt;
+ }
+ else {
+ return layout->emboss;
+ }
+}
+
/********************** Layout *******************/
static void ui_item_scale(uiLayout *litem, const float scale[2])
@@ -3500,6 +3486,7 @@ uiLayout *UI_block_layout(uiBlock *block, int dir, int type, int x, int y, int s
layout->active = 1;
layout->enabled = 1;
layout->context = NULL;
+ layout->emboss = UI_EMBOSS_UNDEFINED;
if (type == UI_LAYOUT_MENU || type == UI_LAYOUT_PIEMENU)
layout->space = 0;
@@ -3564,6 +3551,10 @@ void ui_layout_add_but(uiLayout *layout, uiBut *but)
but->context = layout->context;
but->context->used = true;
}
+
+ if (layout->emboss != UI_EMBOSS_UNDEFINED) {
+ but->dt = layout->emboss;
+ }
}
void uiLayoutSetOperatorContext(uiLayout *layout, int opcontext)
diff --git a/source/blender/editors/interface/interface_region_popup.c b/source/blender/editors/interface/interface_region_popup.c
index e971edb95cb..db3c8742e09 100644
--- a/source/blender/editors/interface/interface_region_popup.c
+++ b/source/blender/editors/interface/interface_region_popup.c
@@ -560,7 +560,7 @@ uiBlock *ui_popup_block_refresh(
block->pie_data.pie_center_spawned[0] += x_offset;
block->pie_data.pie_center_spawned[1] += y_offset;
- ui_block_translate(block, x_offset, y_offset);
+ UI_block_translate(block, x_offset, y_offset);
if (U.pie_initial_timeout > 0)
block->pie_data.flags |= UI_PIE_INITIAL_DIRECTION;
@@ -590,7 +590,7 @@ uiBlock *ui_popup_block_refresh(
* the same height. */
if (handle->refresh && handle->prev_block_rect.ymax > block->rect.ymax) {
float offset = handle->prev_block_rect.ymax - block->rect.ymax;
- ui_block_translate(block, 0, offset);
+ UI_block_translate(block, 0, offset);
block->rect.ymin = handle->prev_block_rect.ymin;
}
@@ -604,7 +604,15 @@ uiBlock *ui_popup_block_refresh(
ar->winrct.ymin = block->rect.ymin - margin;
ar->winrct.ymax = block->rect.ymax + UI_POPUP_MENU_TOP;
- ui_block_translate(block, -ar->winrct.xmin, -ar->winrct.ymin);
+ UI_block_translate(block, -ar->winrct.xmin, -ar->winrct.ymin);
+
+ /* apply scroll offset */
+ if (handle->scrolloffset != 0.0f) {
+ for (uiBut *bt = block->buttons.first; bt; bt = bt->next) {
+ bt->rect.ymin += handle->scrolloffset;
+ bt->rect.ymax += handle->scrolloffset;
+ }
+ }
}
if (block_old) {
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index 6c558bcc961..7053f2833c3 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -4621,16 +4621,8 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
}
}
-void ui_draw_menu_back(uiStyle *UNUSED(style), uiBlock *block, rcti *rect)
+static void ui_draw_clip_tri(uiBlock *block, rcti *rect, uiWidgetType *wt)
{
- uiWidgetType *wt = widget_type(UI_WTYPE_MENU_BACK);
-
- wt->state(wt, 0);
- if (block)
- wt->draw(&wt->wcol, rect, block->flag, block->direction);
- else
- wt->draw(&wt->wcol, rect, 0, 0);
-
if (block) {
float draw_color[4];
unsigned char *color = (unsigned char *)wt->wcol.text;
@@ -4651,6 +4643,19 @@ void ui_draw_menu_back(uiStyle *UNUSED(style), uiBlock *block, rcti *rect)
}
}
+void ui_draw_menu_back(uiStyle *UNUSED(style), uiBlock *block, rcti *rect)
+{
+ uiWidgetType *wt = widget_type(UI_WTYPE_MENU_BACK);
+
+ wt->state(wt, 0);
+ if (block)
+ wt->draw(&wt->wcol, rect, block->flag, block->direction);
+ else
+ wt->draw(&wt->wcol, rect, 0, 0);
+
+ ui_draw_clip_tri(block, rect, wt);
+}
+
/**
* Similar to 'widget_menu_back', however we can't use the widget preset system
* because we need to pass in the original location so we know where to show the arrow.
@@ -4708,17 +4713,19 @@ static void ui_draw_popover_back_impl(
void ui_draw_popover_back(ARegion *ar, uiStyle *UNUSED(style), uiBlock *block, rcti *rect)
{
+ uiWidgetType *wt = widget_type(UI_WTYPE_MENU_BACK);
+
if (block) {
float mval_origin[2] = {block->mx, block->my};
ui_window_to_block_fl(ar, block, &mval_origin[0], &mval_origin[1]);
ui_draw_popover_back_impl(&wcol_menu_back, rect, block->direction, mval_origin);
}
else {
- uiWidgetType *wt = widget_type(UI_WTYPE_MENU_BACK);
-
wt->state(wt, 0);
wt->draw(&wt->wcol, rect, 0, 0);
}
+
+ ui_draw_clip_tri(block, rect, wt);
}
static void draw_disk_shaded(
diff --git a/source/blender/editors/manipulator_library/manipulator_types/button2d_manipulator.c b/source/blender/editors/manipulator_library/manipulator_types/button2d_manipulator.c
index a6964359595..770e7716dd2 100644
--- a/source/blender/editors/manipulator_library/manipulator_types/button2d_manipulator.c
+++ b/source/blender/editors/manipulator_library/manipulator_types/button2d_manipulator.c
@@ -98,11 +98,12 @@ static void button2d_geom_draw_backdrop(
}
static void button2d_draw_intern(
- const bContext *UNUSED(C), wmManipulator *mpr,
+ const bContext *C, wmManipulator *mpr,
const bool select, const bool highlight)
{
ButtonManipulator2D *button = (ButtonManipulator2D *)mpr;
+ const int draw_options = RNA_enum_get(mpr->ptr, "draw_options");
if (button->is_init == false) {
button->is_init = true;
PropertyRNA *prop = RNA_struct_find_property(mpr->ptr, "icon");
@@ -115,8 +116,8 @@ static void button2d_draw_intern(
/* We shouldn't need the +1, but a NULL char is set. */
char *polys = MEM_mallocN(polys_len + 1, __func__);
RNA_property_string_get(mpr->ptr, prop, polys);
- button->shape_batch[0] = GPU_batch_wire_from_poly_2d_encoded((uchar *)polys, polys_len, NULL);
- button->shape_batch[1] = GPU_batch_tris_from_poly_2d_encoded((uchar *)polys, polys_len, NULL);
+ button->shape_batch[0] = GPU_batch_tris_from_poly_2d_encoded((uchar *)polys, polys_len, NULL);
+ button->shape_batch[1] = GPU_batch_wire_from_poly_2d_encoded((uchar *)polys, polys_len, NULL);
MEM_freeN(polys);
}
}
@@ -127,41 +128,90 @@ static void button2d_draw_intern(
manipulator_color_get(mpr, highlight, color);
WM_manipulator_calc_matrix_final(mpr, matrix_final);
+
+ bool is_3d = (mpr->parent_mgroup->type->flag & WM_MANIPULATORGROUPTYPE_3D) != 0;
+
+
+ if (draw_options & ED_MANIPULATOR_BUTTON_SHOW_HELPLINE) {
+ float matrix_final_no_offset[4][4];
+ WM_manipulator_calc_matrix_final_no_offset(mpr, matrix_final_no_offset);
+ uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformColor4fv(color);
+ glLineWidth(mpr->line_width);
+ immUniformColor4fv(color);
+ immBegin(GWN_PRIM_LINE_STRIP, 2);
+ immVertex3fv(pos, matrix_final[3]);
+ immVertex3fv(pos, matrix_final_no_offset[3]);
+ immEnd();
+ immUnbindProgram();
+ }
+
+ bool need_to_pop = true;
gpuPushMatrix();
gpuMultMatrix(matrix_final);
- glEnable(GL_BLEND);
+ if (is_3d) {
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ float matrix_align[4][4];
+ float matrix_final_unit[4][4];
+ normalize_m4_m4(matrix_final_unit, matrix_final);
+ mul_m4_m4m4(matrix_align, rv3d->viewmat, matrix_final_unit);
+ zero_v3(matrix_align[3]);
+ transpose_m4(matrix_align);
+ gpuMultMatrix(matrix_align);
+ }
- if (select == false) {
+ if (select) {
+ BLI_assert(is_3d);
+ button2d_geom_draw_backdrop(mpr, color, select);
+ }
+ else {
+
+ glEnable(GL_BLEND);
if (button->shape_batch[0] != NULL) {
glEnable(GL_LINE_SMOOTH);
+ glDisable(GL_POLYGON_SMOOTH);
glLineWidth(1.0f);
for (uint i = 0; i < ARRAY_SIZE(button->shape_batch) && button->shape_batch[i]; i++) {
/* Invert line color for wire. */
- color[0] = 1.0f - color[0];
- color[1] = 1.0f - color[1];
- color[2] = 1.0f - color[2];
-
GWN_batch_program_set_builtin(button->shape_batch[i], GPU_SHADER_2D_UNIFORM_COLOR);
GWN_batch_uniform_4f(button->shape_batch[i], "color", UNPACK4(color));
GWN_batch_draw(button->shape_batch[i]);
+
+ if (draw_options & ED_MANIPULATOR_BUTTON_SHOW_OUTLINE) {
+ color[0] = 1.0f - color[0];
+ color[1] = 1.0f - color[1];
+ color[2] = 1.0f - color[2];
+ }
}
glDisable(GL_LINE_SMOOTH);
- gpuPopMatrix();
+ glEnable(GL_POLYGON_SMOOTH);
}
else if (button->icon != ICON_NONE) {
button2d_geom_draw_backdrop(mpr, color, select);
- gpuPopMatrix();
- UI_icon_draw(
- mpr->matrix_basis[3][0] - (ICON_DEFAULT_WIDTH / 2.0) * UI_DPI_FAC,
- mpr->matrix_basis[3][1] - (ICON_DEFAULT_HEIGHT / 2.0) * UI_DPI_FAC,
- button->icon);
- }
- else {
- gpuPopMatrix();
+ float size[2];
+ if (is_3d) {
+ const float fac = 2.0f;
+ gpuTranslate2f(-(fac / 2), -(fac / 2));
+ gpuScale2f(fac / (ICON_DEFAULT_WIDTH * UI_DPI_FAC), fac / (ICON_DEFAULT_HEIGHT * UI_DPI_FAC));
+ size[0] = 1.0f;
+ size[1] = 1.0f;
+ }
+ else {
+ size[0] = mpr->matrix_basis[3][0] - (ICON_DEFAULT_WIDTH / 2.0) * UI_DPI_FAC;
+ size[1] = mpr->matrix_basis[3][1] - (ICON_DEFAULT_HEIGHT / 2.0) * UI_DPI_FAC;
+ gpuPopMatrix();
+ need_to_pop = false;
+ }
+ UI_icon_draw(size[0], size[1], button->icon);
}
+ glDisable(GL_BLEND);
+ }
+
+ if (need_to_pop) {
+ gpuPopMatrix();
}
- glDisable(GL_BLEND);
}
static void manipulator_button2d_draw_select(const bContext *C, wmManipulator *mpr, int select_id)
@@ -244,7 +294,15 @@ static void MANIPULATOR_WT_button_2d(wmManipulatorType *wt)
wt->struct_size = sizeof(ButtonManipulator2D);
/* rna */
+ static EnumPropertyItem rna_enum_draw_options[] = {
+ {ED_MANIPULATOR_BUTTON_SHOW_OUTLINE, "OUTLINE", 0, "Outline", ""},
+ {ED_MANIPULATOR_BUTTON_SHOW_HELPLINE, "HELPLINE", 0, "Help Line", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
PropertyRNA *prop;
+
+ RNA_def_enum_flag(wt->srna, "draw_options", rna_enum_draw_options, 0, "Draw Options", "");
+
prop = RNA_def_property(wt->srna, "icon", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, rna_enum_icon_items);
diff --git a/source/blender/editors/manipulator_library/manipulator_types/cage2d_manipulator.c b/source/blender/editors/manipulator_library/manipulator_types/cage2d_manipulator.c
index 784c03be949..fe748f33d35 100644
--- a/source/blender/editors/manipulator_library/manipulator_types/cage2d_manipulator.c
+++ b/source/blender/editors/manipulator_library/manipulator_types/cage2d_manipulator.c
@@ -66,16 +66,6 @@
#define MANIPULATOR_RESIZER_SIZE 10.0f
#define MANIPULATOR_MARGIN_OFFSET_SCALE 1.5f
-static void manipulator_calc_matrix_final_no_offset(
- const wmManipulator *mpr, float orig_matrix_final_no_offset[4][4])
-{
- float mat_identity[4][4];
- struct WM_ManipulatorMatrixParams params = {NULL};
- unit_m4(mat_identity);
- params.matrix_offset = mat_identity;
- WM_manipulator_calc_matrix_final_params(mpr, &params, orig_matrix_final_no_offset);
-}
-
static void manipulator_calc_rect_view_scale(
const wmManipulator *mpr, const float dims[2], float scale[2])
{
@@ -88,7 +78,7 @@ static void manipulator_calc_rect_view_scale(
asp[1] = dims[0] / dims[1];
}
float x_axis[3], y_axis[3];
- manipulator_calc_matrix_final_no_offset(mpr, matrix_final_no_offset);
+ WM_manipulator_calc_matrix_final_no_offset(mpr, matrix_final_no_offset);
mul_v3_mat3_m4v3(x_axis, matrix_final_no_offset, mpr->matrix_offset[0]);
mul_v3_mat3_m4v3(y_axis, matrix_final_no_offset, mpr->matrix_offset[1]);
@@ -841,7 +831,7 @@ static int manipulator_cage2d_invoke(
RectTransformInteraction *data = MEM_callocN(sizeof(RectTransformInteraction), "cage_interaction");
copy_m4_m4(data->orig_matrix_offset, mpr->matrix_offset);
- manipulator_calc_matrix_final_no_offset(mpr, data->orig_matrix_final_no_offset);
+ WM_manipulator_calc_matrix_final_no_offset(mpr, data->orig_matrix_final_no_offset);
if (manipulator_window_project_2d(
C, mpr, (const float[2]){UNPACK2(event->mval)}, 2, false, data->orig_mouse) == 0)
diff --git a/source/blender/editors/mesh/editmesh_extrude.c b/source/blender/editors/mesh/editmesh_extrude.c
index 6c6283633cd..2e3d0a9c675 100644
--- a/source/blender/editors/mesh/editmesh_extrude.c
+++ b/source/blender/editors/mesh/editmesh_extrude.c
@@ -365,15 +365,58 @@ void MESH_OT_extrude_repeat(wmOperatorType *ot)
#ifdef USE_MANIPULATOR
+const float extrude_button_scale = 0.15f;
+const float extrude_button_offset_scale = 1.5f;
+const float extrude_arrow_scale = 1.0f;
+const float extrude_arrow_xyz_axis_scale = 1.0f;
+const float extrude_arrow_normal_axis_scale = 1.75f;
+
+static const uchar shape_plus[] = {
+ 0x5f, 0xfb, 0x40, 0xee, 0x25, 0xda, 0x11, 0xbf, 0x4, 0xa0, 0x0, 0x80, 0x4, 0x5f, 0x11,
+ 0x40, 0x25, 0x25, 0x40, 0x11, 0x5f, 0x4, 0x7f, 0x0, 0xa0, 0x4, 0xbf, 0x11, 0xda, 0x25,
+ 0xee, 0x40, 0xfb, 0x5f, 0xff, 0x7f, 0xfb, 0xa0, 0xee, 0xbf, 0xda, 0xda, 0xbf, 0xee,
+ 0xa0, 0xfb, 0x80, 0xff, 0x6e, 0xd7, 0x92, 0xd7, 0x92, 0x90, 0xd8, 0x90, 0xd8, 0x6d,
+ 0x92, 0x6d, 0x92, 0x27, 0x6e, 0x27, 0x6e, 0x6d, 0x28, 0x6d, 0x28, 0x90, 0x6e,
+ 0x90, 0x6e, 0xd7, 0x80, 0xff, 0x5f, 0xfb, 0x5f, 0xfb,
+};
+
typedef struct ManipulatorExtrudeGroup {
- /* Extrude . */
- struct wmManipulator *axis_arrow;
- /* Redo Z-axis translation. */
- struct wmManipulator *axis_redo;
+
+ /* XYZ & normal. */
+ struct wmManipulator *invoke_xyz_no[4];
+ struct wmManipulator *adjust_xyz_no[5];
+
+ struct {
+ float normal_mat3[3][3]; /* use Z axis for normal. */
+ int orientation_type;
+ } data;
wmOperatorType *ot_extrude;
} ManipulatorExtrudeGroup;
+static void manipulator_mesh_extrude_orientation_matrix_set(
+ struct ManipulatorExtrudeGroup *man, const float mat[3][3])
+{
+ for (int i = 0; i < 3; i++) {
+ /* Set orientation without location. */
+ for (int j = 0; j < 3; j++) {
+ copy_v3_v3(man->adjust_xyz_no[i]->matrix_basis[j], mat[j]);
+ }
+ /* nop when (i == 2). */
+ swap_v3_v3(man->adjust_xyz_no[i]->matrix_basis[i], man->adjust_xyz_no[i]->matrix_basis[2]);
+ /* Orient to normal gives generally less awkward results. */
+ if (man->data.orientation_type != V3D_MANIP_NORMAL) {
+ if (dot_v3v3(man->adjust_xyz_no[i]->matrix_basis[2], man->data.normal_mat3[2]) < 0.0f) {
+ negate_v3(man->adjust_xyz_no[i]->matrix_basis[2]);
+ }
+ }
+ mul_v3_v3fl(
+ man->invoke_xyz_no[i]->matrix_offset[3],
+ man->adjust_xyz_no[i]->matrix_basis[2],
+ (extrude_arrow_xyz_axis_scale * extrude_button_offset_scale) / extrude_button_scale);
+ }
+}
+
static bool manipulator_mesh_extrude_poll(const bContext *C, wmManipulatorGroupType *wgt)
{
WorkSpace *workspace = CTX_wm_workspace(C);
@@ -388,54 +431,72 @@ static bool manipulator_mesh_extrude_poll(const bContext *C, wmManipulatorGroupT
static void manipulator_mesh_extrude_setup(const bContext *UNUSED(C), wmManipulatorGroup *mgroup)
{
- const int constraint_z[3] = {0, 0, 1};
-
struct ManipulatorExtrudeGroup *man = MEM_callocN(sizeof(ManipulatorExtrudeGroup), __func__);
mgroup->customdata = man;
const wmManipulatorType *wt_arrow = WM_manipulatortype_find("MANIPULATOR_WT_arrow_3d", true);
- const wmManipulatorType *wt_grab = WM_manipulatortype_find("MANIPULATOR_WT_grab_3d", true);
-
- man->axis_arrow = WM_manipulator_new_ptr(wt_arrow, mgroup, NULL);
- man->axis_redo = WM_manipulator_new_ptr(wt_grab, mgroup, NULL);
+ const wmManipulatorType *wt_grab = WM_manipulatortype_find("MANIPULATOR_WT_button_2d", true);
- man->ot_extrude = WM_operatortype_find("MESH_OT_extrude_context_move", true);
+ for (int i = 0; i < 4; i++) {
+ man->adjust_xyz_no[i] = WM_manipulator_new_ptr(wt_arrow, mgroup, NULL);
+ man->invoke_xyz_no[i] = WM_manipulator_new_ptr(wt_grab, mgroup, NULL);
+ man->invoke_xyz_no[i]->flag |= WM_MANIPULATOR_DRAW_OFFSET_SCALE;
+ }
- UI_GetThemeColor3fv(TH_MANIPULATOR_PRIMARY, man->axis_arrow->color);
- UI_GetThemeColor3fv(TH_MANIPULATOR_SECONDARY, man->axis_redo->color);
+ {
+ PropertyRNA *prop = RNA_struct_find_property(man->invoke_xyz_no[3]->ptr, "shape");
+ for (int i = 0; i < 4; i++) {
+ RNA_property_string_set_bytes(
+ man->invoke_xyz_no[i]->ptr, prop,
+ (const char *)shape_plus, ARRAY_SIZE(shape_plus));
+ }
+ }
- man->axis_redo->color[3] = 0.3f;
- man->axis_redo->color_hi[3] = 0.3f;
+ man->ot_extrude = WM_operatortype_find("MESH_OT_extrude_context_move", true);
- WM_manipulator_set_scale(man->axis_arrow, 2.0);
- WM_manipulator_set_scale(man->axis_redo, 1.0);
+ for (int i = 0; i < 3; i++) {
+ UI_GetThemeColor3fv(TH_AXIS_X + i, man->invoke_xyz_no[i]->color);
+ UI_GetThemeColor3fv(TH_AXIS_X + i, man->adjust_xyz_no[i]->color);
+ }
+ UI_GetThemeColor3fv(TH_MANIPULATOR_PRIMARY, man->invoke_xyz_no[3]->color);
+ UI_GetThemeColor3fv(TH_MANIPULATOR_PRIMARY, man->adjust_xyz_no[3]->color);
- RNA_enum_set(man->axis_arrow->ptr, "draw_style", ED_MANIPULATOR_ARROW_STYLE_NORMAL);
- RNA_enum_set(man->axis_redo->ptr, "draw_style", ED_MANIPULATOR_GRAB_STYLE_RING_2D);
+ for (int i = 0; i < 4; i++) {
+ WM_manipulator_set_scale(man->invoke_xyz_no[i], extrude_button_scale);
+ WM_manipulator_set_scale(man->adjust_xyz_no[i], extrude_arrow_scale);
+ }
+ WM_manipulator_set_scale(man->adjust_xyz_no[3], extrude_arrow_normal_axis_scale);
- RNA_enum_set(man->axis_redo->ptr, "draw_options",
- ED_MANIPULATOR_GRAB_DRAW_FLAG_FILL);
+ for (int i = 0; i < 4; i++) {
+ }
- WM_manipulator_set_flag(man->axis_redo, WM_MANIPULATOR_DRAW_VALUE, true);
+ for (int i = 0; i < 4; i++) {
+ WM_manipulator_set_flag(man->adjust_xyz_no[i], WM_MANIPULATOR_DRAW_VALUE, true);
+ }
- /* New extrude. */
- {
- PointerRNA *ptr = WM_manipulator_operator_set(man->axis_arrow, 0, man->ot_extrude, NULL);
+ /* XYZ & normal axis extrude. */
+ for (int i = 0; i < 4; i++) {
+ PointerRNA *ptr = WM_manipulator_operator_set(man->invoke_xyz_no[i], 0, man->ot_extrude, NULL);
{
+ int constraint[3] = {0, 0, 0};
+ constraint[MIN2(i, 2)] = 1;
PointerRNA macroptr = RNA_pointer_get(ptr, "TRANSFORM_OT_translate");
RNA_boolean_set(&macroptr, "release_confirm", true);
- RNA_boolean_set_array(&macroptr, "constraint_axis", constraint_z);
+ RNA_boolean_set_array(&macroptr, "constraint_axis", constraint);
}
}
+
/* Adjust extrude. */
- {
- PointerRNA *ptr = WM_manipulator_operator_set(man->axis_redo, 0, man->ot_extrude, NULL);
+ for (int i = 0; i < 4; i++) {
+ PointerRNA *ptr = WM_manipulator_operator_set(man->adjust_xyz_no[i], 0, man->ot_extrude, NULL);
{
+ int constraint[3] = {0, 0, 0};
+ constraint[MIN2(i, 2)] = 1;
PointerRNA macroptr = RNA_pointer_get(ptr, "TRANSFORM_OT_translate");
RNA_boolean_set(&macroptr, "release_confirm", true);
- RNA_boolean_set_array(&macroptr, "constraint_axis", constraint_z);
+ RNA_boolean_set_array(&macroptr, "constraint_axis", constraint);
}
- wmManipulatorOpElem *mpop = WM_manipulator_operator_get(man->axis_redo, 0);
+ wmManipulatorOpElem *mpop = WM_manipulator_operator_get(man->adjust_xyz_no[i], 0);
mpop->is_redo = true;
}
}
@@ -444,72 +505,141 @@ static void manipulator_mesh_extrude_refresh(const bContext *C, wmManipulatorGro
{
ManipulatorExtrudeGroup *man = mgroup->customdata;
- WM_manipulator_set_flag(man->axis_arrow, WM_MANIPULATOR_HIDDEN, true);
- WM_manipulator_set_flag(man->axis_redo, WM_MANIPULATOR_HIDDEN, true);
+ for (int i = 0; i < 4; i++) {
+ WM_manipulator_set_flag(man->invoke_xyz_no[i], WM_MANIPULATOR_HIDDEN, true);
+ WM_manipulator_set_flag(man->adjust_xyz_no[i], WM_MANIPULATOR_HIDDEN, true);
+ }
if (G.moving) {
return;
}
- int orientation_type;
- {
- PointerRNA ot_ptr;
- WM_operator_last_properties_ensure(man->ot_extrude, &ot_ptr);
- PointerRNA macroptr = RNA_pointer_get(&ot_ptr, "TRANSFORM_OT_translate");
- orientation_type = RNA_enum_get(&macroptr, "constraint_orientation");
- }
+ Scene *scene = CTX_data_scene(C);
+ man->data.orientation_type = scene->orientation_type;
+ bool use_normal = (man->data.orientation_type != V3D_MANIP_NORMAL);
+ const int axis_len_used = use_normal ? 4 : 3;
struct TransformBounds tbounds;
+
+ if (use_normal) {
+ struct TransformBounds tbounds_normal;
+ if (!ED_transform_calc_manipulator_stats(
+ C, &(struct TransformCalcParams){
+ .orientation_type = V3D_MANIP_NORMAL + 1,
+ }, &tbounds_normal))
+ {
+ unit_m3(tbounds_normal.axis);
+ }
+ copy_m3_m3(man->data.normal_mat3, tbounds_normal.axis);
+ }
+
+ /* TODO(campbell): run second since this modifies the 3D view, it should not. */
if (!ED_transform_calc_manipulator_stats(
C, &(struct TransformCalcParams){
- .orientation_type = orientation_type + 1,
+ .orientation_type = man->data.orientation_type + 1,
}, &tbounds))
{
return;
}
+ /* Main axis is normal. */
+ if (!use_normal) {
+ copy_m3_m3(man->data.normal_mat3, tbounds.axis);
+ }
+
+ /* Offset the add icon. */
+ mul_v3_v3fl(
+ man->invoke_xyz_no[3]->matrix_offset[3],
+ man->data.normal_mat3[2],
+ (extrude_arrow_normal_axis_scale * extrude_button_offset_scale) / extrude_button_scale);
+
/* Needed for normal orientation. */
- copy_m4_m3(man->axis_arrow->matrix_basis, tbounds.axis);
- copy_m4_m3(man->axis_redo->matrix_basis, tbounds.axis);
+ manipulator_mesh_extrude_orientation_matrix_set(man, tbounds.axis);
+ if (use_normal) {
+ copy_m4_m3(man->adjust_xyz_no[3]->matrix_basis, man->data.normal_mat3);
+ }
- WM_manipulator_set_matrix_location(man->axis_arrow, tbounds.center);
- WM_manipulator_set_matrix_location(man->axis_redo, tbounds.center);
+ /* Location. */
+ for (int i = 0; i < axis_len_used; i++) {
+ WM_manipulator_set_matrix_location(man->invoke_xyz_no[i], tbounds.center);
+ WM_manipulator_set_matrix_location(man->adjust_xyz_no[i], tbounds.center);
+ }
wmOperator *op = WM_operator_last_redo(C);
bool has_redo = (op && op->type == man->ot_extrude);
- WM_manipulator_set_flag(man->axis_arrow, WM_MANIPULATOR_HIDDEN, false);
- WM_manipulator_set_flag(man->axis_redo, WM_MANIPULATOR_HIDDEN, !has_redo);
+ /* Un-hide. */
+ for (int i = 0; i < axis_len_used; i++) {
+ WM_manipulator_set_flag(man->invoke_xyz_no[i], WM_MANIPULATOR_HIDDEN, false);
+ WM_manipulator_set_flag(man->adjust_xyz_no[i], WM_MANIPULATOR_HIDDEN, !has_redo);
+ }
- {
- wmManipulatorOpElem *mpop = WM_manipulator_operator_get(man->axis_arrow, 0);
+ /* Operator properties. */
+ if (use_normal) {
+ wmManipulatorOpElem *mpop = WM_manipulator_operator_get(man->invoke_xyz_no[3], 0);
PointerRNA macroptr = RNA_pointer_get(&mpop->ptr, "TRANSFORM_OT_translate");
- RNA_enum_set(&macroptr, "constraint_orientation", orientation_type);
+ RNA_enum_set(&macroptr, "constraint_orientation", V3D_MANIP_NORMAL);
}
/* Redo with current settings. */
if (has_redo) {
- /* We could also access this from 'ot->last_properties' */
-
wmOperator *op_transform = op->macro.last;
- wmManipulatorOpElem *mpop = WM_manipulator_operator_get(man->axis_redo, 0);
-
- PointerRNA macroptr = RNA_pointer_get(&mpop->ptr, "TRANSFORM_OT_translate");
-
float value[4];
RNA_float_get_array(op_transform->ptr, "value", value);
- RNA_float_set_array(&macroptr, "value", value);
-
int constraint_axis[3];
RNA_boolean_get_array(op_transform->ptr, "constraint_axis", constraint_axis);
- RNA_boolean_set_array(&macroptr, "constraint_axis", constraint_axis);
+ int orientation_type = RNA_enum_get(op_transform->ptr, "constraint_orientation");
+
+ /* We could also access this from 'ot->last_properties' */
+ for (int i = 0; i < 4; i++) {
+ if ((i != 3) ?
+ (orientation_type == man->data.orientation_type && constraint_axis[i]) :
+ (orientation_type == V3D_MANIP_NORMAL && constraint_axis[2]))
+ {
+ wmManipulatorOpElem *mpop = WM_manipulator_operator_get(man->adjust_xyz_no[i], 0);
+
+ PointerRNA macroptr = RNA_pointer_get(&mpop->ptr, "TRANSFORM_OT_translate");
+
+ RNA_float_set_array(&macroptr, "value", value);
+ RNA_boolean_set_array(&macroptr, "constraint_axis", constraint_axis);
+ RNA_enum_set(&macroptr, "constraint_orientation", orientation_type);
+ }
+ else {
+ /* TODO(campbell): ideally we could adjust all,
+ * this is complicated by how operator redo and the transform macro works. */
+ WM_manipulator_set_flag(man->adjust_xyz_no[i], WM_MANIPULATOR_HIDDEN, true);
+ }
+ }
+ }
+
+ for (int i = 0; i < 4; i++) {
+ RNA_enum_set(
+ man->invoke_xyz_no[i]->ptr,
+ "draw_options",
+ (man->adjust_xyz_no[i]->flag & WM_MANIPULATOR_HIDDEN) ?
+ ED_MANIPULATOR_BUTTON_SHOW_HELPLINE : 0);
+ }
+}
+
+static void manipulator_mesh_extrude_draw_prepare(const bContext *C, wmManipulatorGroup *mgroup)
+{
+ ManipulatorExtrudeGroup *man = mgroup->customdata;
+ switch (man->data.orientation_type) {
+ case V3D_MANIP_VIEW:
+ {
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ float mat[3][3];
+ copy_m3_m4(mat, rv3d->viewinv);
+ normalize_m3(mat);
+ manipulator_mesh_extrude_orientation_matrix_set(man, mat);
+ break;
+ }
}
}
static void manipulator_mesh_extrude_message_subscribe(
const bContext *C, wmManipulatorGroup *mgroup, struct wmMsgBus *mbus)
{
- ManipulatorExtrudeGroup *man = mgroup->customdata;
ARegion *ar = CTX_wm_region(C);
/* Subscribe to view properties */
@@ -520,11 +650,9 @@ static void manipulator_mesh_extrude_message_subscribe(
};
{
- PointerRNA ot_ptr;
- WM_operator_last_properties_ensure(man->ot_extrude, &ot_ptr);
- PointerRNA macroptr = RNA_pointer_get(&ot_ptr, "TRANSFORM_OT_translate");
- WM_msg_subscribe_rna(mbus, &macroptr, NULL, &msg_sub_value_mpr_tag_refresh, __func__);
+ WM_msg_subscribe_rna_anon_prop(mbus, Scene, transform_orientation, &msg_sub_value_mpr_tag_refresh);
}
+
}
static void MESH_WGT_extrude(struct wmManipulatorGroupType *wgt)
@@ -540,6 +668,7 @@ static void MESH_WGT_extrude(struct wmManipulatorGroupType *wgt)
wgt->poll = manipulator_mesh_extrude_poll;
wgt->setup = manipulator_mesh_extrude_setup;
wgt->refresh = manipulator_mesh_extrude_refresh;
+ wgt->draw_prepare = manipulator_mesh_extrude_draw_prepare;
wgt->message_subscribe = manipulator_mesh_extrude_message_subscribe;
}
diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c
index 0387f3e002e..0066afca540 100644
--- a/source/blender/editors/mesh/editmesh_select.c
+++ b/source/blender/editors/mesh/editmesh_select.c
@@ -3207,47 +3207,56 @@ void MESH_OT_select_linked_pick(wmOperatorType *ot)
static int edbm_select_face_by_sides_exec(bContext *C, wmOperator *op)
{
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMFace *efa;
- BMIter iter;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len = 0;
+ const bool extend = RNA_boolean_get(op->ptr, "extend");
const int numverts = RNA_int_get(op->ptr, "number");
const int type = RNA_enum_get(op->ptr, "type");
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, &objects_len);
- if (!RNA_boolean_get(op->ptr, "extend"))
- EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMFace *efa;
+ BMIter iter;
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (!extend) {
+ EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+ }
- bool select;
+ BM_ITER_MESH(efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ bool select;
+
+ switch (type) {
+ case 0:
+ select = (efa->len < numverts);
+ break;
+ case 1:
+ select = (efa->len == numverts);
+ break;
+ case 2:
+ select = (efa->len > numverts);
+ break;
+ case 3:
+ select = (efa->len != numverts);
+ break;
+ default:
+ BLI_assert(0);
+ select = false;
+ break;
+ }
- switch (type) {
- case 0:
- select = (efa->len < numverts);
- break;
- case 1:
- select = (efa->len == numverts);
- break;
- case 2:
- select = (efa->len > numverts);
- break;
- case 3:
- select = (efa->len != numverts);
- break;
- default:
- BLI_assert(0);
- select = false;
- break;
+ if (select) {
+ BM_face_select_set(em->bm, efa, true);
+ }
}
- if (select) {
- BM_face_select_set(em->bm, efa, true);
- }
- }
+ EDBM_selectmode_flush(em);
- EDBM_selectmode_flush(em);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ }
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ MEM_freeN(objects);
return OPERATOR_FINISHED;
}
@@ -3375,28 +3384,46 @@ void MESH_OT_select_loose(wmOperatorType *ot)
static int edbm_select_mirror_exec(bContext *C, wmOperator *op)
{
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
const int axis_flag = RNA_enum_get(op->ptr, "axis");
const bool extend = RNA_boolean_get(op->ptr, "extend");
+ Object *obedit_active = CTX_data_edit_object(C);
+ BMEditMesh *em_active = BKE_editmesh_from_object(obedit_active);
+ const int select_mode = em_active->bm->selectmode;
+ int tot_mirr = 0, tot_fail = 0;
+
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, &objects_len);
+
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
- if (em->bm->totvert && em->bm->totvertsel) {
- int totmirr, totfail;
+ if (em->bm->totvertsel == 0) {
+ continue;
+ }
+
+ int tot_mirr_iter = 0, tot_fail_iter = 0;
for (int axis = 0; axis < 3; axis++) {
if ((1 << axis) & axis_flag) {
- EDBM_select_mirrored(em, axis, extend, &totmirr, &totfail);
+ EDBM_select_mirrored(em, axis, extend, &tot_mirr_iter, &tot_fail_iter);
}
}
- if (totmirr) {
+ if (tot_mirr_iter) {
EDBM_selectmode_flush(em);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
}
- ED_mesh_report_mirror_ex(op, totmirr, totfail, em->bm->selectmode);
+ tot_fail += tot_fail_iter;
+ tot_mirr += tot_mirr_iter;
}
+ MEM_freeN(objects);
+ if (tot_mirr || tot_fail) {
+ ED_mesh_report_mirror_ex(op, tot_mirr, tot_fail, select_mode);
+ }
return OPERATOR_FINISHED;
}
@@ -3712,18 +3739,39 @@ static bool edbm_deselect_nth(BMEditMesh *em, const struct CheckerIntervalParams
static int edbm_select_nth_exec(bContext *C, wmOperator *op)
{
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
struct CheckerIntervalParams op_params;
-
WM_operator_properties_checker_interval_from_op(op, &op_params);
+ bool found_active_elt = false;
- if (edbm_deselect_nth(em, &op_params) == false) {
- BKE_report(op->reports, RPT_ERROR, "Mesh has no active vert/edge/face");
- return OPERATOR_CANCELLED;
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, &objects_len);
+
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+
+ if ((em->bm->totvertsel == 0) &&
+ (em->bm->totedgesel == 0) &&
+ (em->bm->totfacesel == 0))
+ {
+ continue;
+ }
+
+ if (edbm_deselect_nth(em, &op_params) == true) {
+ found_active_elt = true;
+ EDBM_update_generic(em, false, false);
+ }
}
+ MEM_SAFE_FREE(objects);
- EDBM_update_generic(em, false, false);
+ if (!found_active_elt) {
+ BKE_report(op->reports, RPT_ERROR,
+ (objects_len == 1 ?
+ "Mesh has no active vert/edge/face" :
+ "Meshes have no active vert/edge/face"));
+ return OPERATOR_CANCELLED;
+ }
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index f0e5d7f9118..e03f04c48f0 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -857,70 +857,83 @@ static void edbm_add_edge_face_exec__tricky_finalize_sel(BMesh *bm, BMElem *ele_
static int edbm_add_edge_face_exec(bContext *C, wmOperator *op)
{
- BMOperator bmop;
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- const bool use_smooth = edbm_add_edge_face__smooth_get(em->bm);
- const int totedge_orig = em->bm->totedge;
- const int totface_orig = em->bm->totface;
/* when this is used to dissolve we could avoid this, but checking isnt too slow */
-#ifdef USE_FACE_CREATE_SEL_EXTEND
- BMElem *ele_desel;
- BMFace *ele_desel_face;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, &objects_len);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
- /* be extra clever, figure out if a partial selection should be extended so we can create geometry
- * with single vert or single edge selection */
- ele_desel = edbm_add_edge_face_exec__tricky_extend_sel(em->bm);
-#endif
+ if ((em->bm->totvertsel == 0) &&
+ (em->bm->totedgesel == 0) &&
+ (em->bm->totvertsel == 0))
+ {
+ continue;
+ }
- if (!EDBM_op_init(
- em, &bmop, op,
- "contextual_create geom=%hfev mat_nr=%i use_smooth=%b",
- BM_ELEM_SELECT, em->mat_nr, use_smooth))
- {
- return OPERATOR_CANCELLED;
- }
+ bool use_smooth = edbm_add_edge_face__smooth_get(em->bm);
+ int totedge_orig = em->bm->totedge;
+ int totface_orig = em->bm->totface;
- BMO_op_exec(em->bm, &bmop);
+ BMOperator bmop;
+#ifdef USE_FACE_CREATE_SEL_EXTEND
+ BMElem *ele_desel;
+ BMFace *ele_desel_face;
- /* cancel if nothing was done */
- if ((totedge_orig == em->bm->totedge) &&
- (totface_orig == em->bm->totface))
- {
- EDBM_op_finish(em, &bmop, op, true);
- return OPERATOR_CANCELLED;
- }
+ /* be extra clever, figure out if a partial selection should be extended so we can create geometry
+ * with single vert or single edge selection */
+ ele_desel = edbm_add_edge_face_exec__tricky_extend_sel(em->bm);
+#endif
+ if (!EDBM_op_init(
+ em, &bmop, op,
+ "contextual_create geom=%hfev mat_nr=%i use_smooth=%b",
+ BM_ELEM_SELECT, em->mat_nr, use_smooth))
+ {
+ continue;
+ }
+
+ BMO_op_exec(em->bm, &bmop);
+ /* cancel if nothing was done */
+ if ((totedge_orig == em->bm->totedge) &&
+ (totface_orig == em->bm->totface))
+ {
+ EDBM_op_finish(em, &bmop, op, true);
+ continue;
+ }
#ifdef USE_FACE_CREATE_SEL_EXTEND
- /* normally we would want to leave the new geometry selected,
- * but being able to press F many times to add geometry is too useful! */
- if (ele_desel &&
- (BMO_slot_buffer_count(bmop.slots_out, "faces.out") == 1) &&
- (ele_desel_face = BMO_slot_buffer_get_first(bmop.slots_out, "faces.out")))
- {
- edbm_add_edge_face_exec__tricky_finalize_sel(em->bm, ele_desel, ele_desel_face);
- }
- else
+ /* normally we would want to leave the new geometry selected,
+ * but being able to press F many times to add geometry is too useful! */
+ if (ele_desel &&
+ (BMO_slot_buffer_count(bmop.slots_out, "faces.out") == 1) &&
+ (ele_desel_face = BMO_slot_buffer_get_first(bmop.slots_out, "faces.out")))
+ {
+ edbm_add_edge_face_exec__tricky_finalize_sel(em->bm, ele_desel, ele_desel_face);
+ }
+ else
#endif
- {
- /* Newly created faces may include existing hidden edges,
- * copying face data from surrounding, may have copied hidden face flag too.
- *
- * Important that faces use flushing since 'edges.out' wont include hidden edges that already existed.
- */
- BMO_slot_buffer_hflag_disable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_HIDDEN, true);
- BMO_slot_buffer_hflag_disable(em->bm, bmop.slots_out, "edges.out", BM_EDGE, BM_ELEM_HIDDEN, false);
+ {
+ /* Newly created faces may include existing hidden edges,
+ * copying face data from surrounding, may have copied hidden face flag too.
+ *
+ * Important that faces use flushing since 'edges.out' wont include hidden edges that already existed.
+ */
+ BMO_slot_buffer_hflag_disable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_HIDDEN, true);
+ BMO_slot_buffer_hflag_disable(em->bm, bmop.slots_out, "edges.out", BM_EDGE, BM_ELEM_HIDDEN, false);
- BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, true);
- BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "edges.out", BM_EDGE, BM_ELEM_SELECT, true);
- }
+ BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, true);
+ BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "edges.out", BM_EDGE, BM_ELEM_SELECT, true);
+ }
- if (!EDBM_op_finish(em, &bmop, op, true)) {
- return OPERATOR_CANCELLED;
- }
+ if (!EDBM_op_finish(em, &bmop, op, true)) {
+ continue;
+ }
- EDBM_update_generic(em, true, true);
+ EDBM_update_generic(em, true, true);
+ }
+ MEM_freeN(objects);
return OPERATOR_FINISHED;
}
@@ -1094,91 +1107,97 @@ void MESH_OT_mark_sharp(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
-static int edbm_vert_connect_exec(bContext *C, wmOperator *op)
+static bool edbm_connect_vert_pair(BMEditMesh *em, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- uint objects_len = 0;
- uint failed_objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, &objects_len);
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
- BMOperator bmop;
- bool is_pair = (bm->totvertsel == 2);
- int len = 0;
- bool check_degenerate = true;
- const int verts_len = bm->totvertsel;
- BMVert **verts;
- bool checks_succeded = true;
-
- if (!is_pair) {
- continue;
+ BMesh *bm = em->bm;
+ BMOperator bmop;
+ const int verts_len = bm->totvertsel;
+ bool is_pair = (verts_len == 2);
+ int len = 0;
+ bool check_degenerate = true;
+
+ BMVert **verts;
+ bool checks_succeded = true;
+
+ /* sanity check */
+ if (!is_pair) {
+ return false;
+ }
+
+ verts = MEM_mallocN(sizeof(*verts) * verts_len, __func__);
+ {
+ BMIter iter;
+ BMVert *v;
+ int i = 0;
+
+ BM_ITER_MESH(v, &iter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
+ verts[i++] = v;
+ }
}
- verts = MEM_mallocN(sizeof(*verts) * verts_len, __func__);
+ if (BM_vert_pair_share_face_check_cb(
+ verts[0], verts[1],
+ BM_elem_cb_check_hflag_disabled_simple(BMFace *, BM_ELEM_HIDDEN)))
{
- BMIter iter;
- BMVert *v;
- int i = 0;
+ check_degenerate = false;
+ is_pair = false;
+ }
+ }
- BM_ITER_MESH(v, &iter, bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
- verts[i++] = v;
- }
- }
+ if (is_pair) {
+ if (!EDBM_op_init(
+ em, &bmop, op,
+ "connect_vert_pair verts=%eb verts_exclude=%hv faces_exclude=%hf",
+ verts, verts_len, BM_ELEM_HIDDEN, BM_ELEM_HIDDEN))
+ {
+ checks_succeded = false;
+ }
+ }
+ else {
+ if (!EDBM_op_init(
+ em, &bmop, op,
+ "connect_verts verts=%eb faces_exclude=%hf check_degenerate=%b",
+ verts, verts_len, BM_ELEM_HIDDEN, check_degenerate))
+ {
+ checks_succeded = false;
+ }
+ }
+ if (checks_succeded) {
+ BMO_op_exec(bm, &bmop);
+ len = BMO_slot_get(bmop.slots_out, "edges.out")->len;
- if (is_pair) {
- if (BM_vert_pair_share_face_check_cb(
- verts[0], verts[1],
- BM_elem_cb_check_hflag_disabled_simple(BMFace *, BM_ELEM_HIDDEN)))
- {
- check_degenerate = false;
- is_pair = false;
- }
- }
+ if (len && is_pair) {
+ /* new verts have been added, we have to select the edges, not just flush */
+ BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "edges.out", BM_EDGE, BM_ELEM_SELECT, true);
}
- if (is_pair) {
- if (!EDBM_op_init(
- em, &bmop, op,
- "connect_vert_pair verts=%eb verts_exclude=%hv faces_exclude=%hf",
- verts, verts_len, BM_ELEM_HIDDEN, BM_ELEM_HIDDEN))
- {
- checks_succeded = false;
- }
+ if (!EDBM_op_finish(em, &bmop, op, true)) {
+ len = 0;
}
else {
- if (!EDBM_op_init(
- em, &bmop, op,
- "connect_verts verts=%eb faces_exclude=%hf check_degenerate=%b",
- verts, verts_len, BM_ELEM_HIDDEN, check_degenerate))
- {
- checks_succeded = false;
- }
+ EDBM_selectmode_flush(em); /* so newly created edges get the selection state from the vertex */
+
+ EDBM_update_generic(em, true, true);
}
- if (checks_succeded) {
- BMO_op_exec(bm, &bmop);
- len = BMO_slot_get(bmop.slots_out, "edges.out")->len;
+ }
+ MEM_freeN(verts);
- if (len) {
- if (is_pair) {
- /* new verts have been added, we have to select the edges, not just flush */
- BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "edges.out", BM_EDGE, BM_ELEM_SELECT, true);
- }
- }
+ return len;
+}
- if (!EDBM_op_finish(em, &bmop, op, true)) {
- len = 0;
- }
- else {
- EDBM_selectmode_flush(em); /* so newly created edges get the selection state from the vertex */
+static int edbm_vert_connect_exec(bContext *C, wmOperator *op)
+{
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len = 0;
+ uint failed_objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, &objects_len);
- EDBM_update_generic(em, true, true);
- }
- }
- MEM_freeN(verts);
- if (len == 0) {
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+
+ if (!edbm_connect_vert_pair(em, op)) {
failed_objects_len++;
}
}
@@ -1422,43 +1441,66 @@ static bool bm_vert_connect_select_history_edge_to_vert_path(BMesh *bm, ListBase
static int edbm_vert_connect_path_exec(bContext *C, wmOperator *op)
{
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
- bool is_pair = (em->bm->totvertsel == 2);
- ListBase selected_orig = {NULL, NULL};
- int retval;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len = 0;
+ uint failed_selection_order_len = 0;
+ uint failed_connect_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, &objects_len);
- /* when there is only 2 vertices, we can ignore selection order */
- if (is_pair) {
- return edbm_vert_connect_exec(C, op);
- }
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+ const bool is_pair = (em->bm->totvertsel == 2);
+ ListBase selected_orig = {NULL, NULL};
- if (bm->selected.first) {
- BMEditSelection *ese = bm->selected.first;
- if (ese->htype == BM_EDGE) {
- if (bm_vert_connect_select_history_edge_to_vert_path(bm, &selected_orig)) {
- SWAP(ListBase, bm->selected, selected_orig);
+ if (bm->totvertsel == 0) {
+ continue;
+ }
+
+ /* when there is only 2 vertices, we can ignore selection order */
+ if (is_pair) {
+ if(!edbm_connect_vert_pair(em, op)) {
+ failed_connect_len++;
}
+ continue;
}
- }
- if (bm_vert_connect_select_history(bm)) {
- EDBM_selectmode_flush(em);
- EDBM_update_generic(em, true, true);
- retval = OPERATOR_FINISHED;
+ if (bm->selected.first) {
+ BMEditSelection *ese = bm->selected.first;
+ if (ese->htype == BM_EDGE) {
+ if (bm_vert_connect_select_history_edge_to_vert_path(bm, &selected_orig)) {
+ SWAP(ListBase, bm->selected, selected_orig);
+ }
+ }
+ }
+
+ if (bm_vert_connect_select_history(bm)) {
+ EDBM_selectmode_flush(em);
+ EDBM_update_generic(em, true, true);
+ }
+ else {
+ failed_selection_order_len++;
+ }
+
+ if (!BLI_listbase_is_empty(&selected_orig)) {
+ BM_select_history_clear(bm);
+ bm->selected = selected_orig;
+ }
}
- else {
+
+ MEM_freeN(objects);
+
+ if (failed_selection_order_len == objects_len) {
BKE_report(op->reports, RPT_ERROR, "Invalid selection order");
- retval = OPERATOR_CANCELLED;
+ return OPERATOR_CANCELLED;
}
-
- if (!BLI_listbase_is_empty(&selected_orig)) {
- BM_select_history_clear(bm);
- bm->selected = selected_orig;
+ else if (failed_connect_len == objects_len) {
+ BKE_report(op->reports, RPT_ERROR, "Could not connect vertices");
+ return OPERATOR_CANCELLED;
}
- return retval;
+ return OPERATOR_FINISHED;
}
void MESH_OT_vert_connect_path(wmOperatorType *ot)
@@ -1478,20 +1520,29 @@ void MESH_OT_vert_connect_path(wmOperatorType *ot)
static int edbm_vert_connect_concave_exec(bContext *C, wmOperator *op)
{
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, &objects_len);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
- if (!EDBM_op_call_and_selectf(
- em, op,
- "faces.out", true,
- "connect_verts_concave faces=%hf",
- BM_ELEM_SELECT))
- {
- return OPERATOR_CANCELLED;
- }
+ if (em->bm->totfacesel == 0) {
+ continue;
+ }
+ if (!EDBM_op_call_and_selectf(
+ em, op,
+ "faces.out", true,
+ "connect_verts_concave faces=%hf",
+ BM_ELEM_SELECT))
+ {
+ continue;
+ }
+ EDBM_update_generic(em, true, true);
+ }
- EDBM_update_generic(em, true, true);
+ MEM_freeN(objects);
return OPERATOR_FINISHED;
}
@@ -1518,22 +1569,32 @@ void MESH_OT_vert_connect_concave(wmOperatorType *ot)
static int edbm_vert_connect_nonplaner_exec(bContext *C, wmOperator *op)
{
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
-
+ ViewLayer *view_layer = CTX_data_view_layer(C);
const float angle_limit = RNA_float_get(op->ptr, "angle_limit");
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, &objects_len);
- if (!EDBM_op_call_and_selectf(
- em, op,
- "faces.out", true,
- "connect_verts_nonplanar faces=%hf angle_limit=%f",
- BM_ELEM_SELECT, angle_limit))
- {
- return OPERATOR_CANCELLED;
- }
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ if (em->bm->totfacesel == 0) {
+ continue;
+ }
+
+ if (!EDBM_op_call_and_selectf(
+ em, op,
+ "faces.out", true,
+ "connect_verts_nonplanar faces=%hf angle_limit=%f",
+ BM_ELEM_SELECT, angle_limit))
+ {
+ continue;
+ }
+
+ EDBM_update_generic(em, true, true);
+ }
+ MEM_freeN(objects);
- EDBM_update_generic(em, true, true);
return OPERATOR_FINISHED;
}
@@ -6361,73 +6422,89 @@ void MESH_OT_offset_edge_loops(wmOperatorType *ot)
#ifdef WITH_BULLET
static int edbm_convex_hull_exec(bContext *C, wmOperator *op)
{
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMOperator bmop;
+ const bool use_existing_faces = RNA_boolean_get(op->ptr, "use_existing_faces");
+ const bool delete_unused = RNA_boolean_get(op->ptr, "delete_unused");
+ const bool make_holes = RNA_boolean_get(op->ptr, "make_holes");
+ const bool join_triangles = RNA_boolean_get(op->ptr, "join_triangles");
- EDBM_op_init(
- em, &bmop, op, "convex_hull input=%hvef "
- "use_existing_faces=%b",
- BM_ELEM_SELECT,
- RNA_boolean_get(op->ptr, "use_existing_faces"));
- BMO_op_exec(em->bm, &bmop);
+ float angle_face_threshold = RNA_float_get(op->ptr, "face_threshold");
+ float angle_shape_threshold = RNA_float_get(op->ptr, "shape_threshold");
- /* Hull fails if input is coplanar */
- if (BMO_error_occurred(em->bm)) {
- EDBM_op_finish(em, &bmop, op, true);
- return OPERATOR_CANCELLED;
- }
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, &objects_len);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "geom.out", BM_FACE, BM_ELEM_SELECT, true);
+ if (em->bm->totvertsel == 0) {
+ continue;
+ }
- /* Delete unused vertices, edges, and faces */
- if (RNA_boolean_get(op->ptr, "delete_unused")) {
- if (!EDBM_op_callf(
- em, op, "delete geom=%S context=%i",
- &bmop, "geom_unused.out", DEL_ONLYTAGGED))
- {
+ BMOperator bmop;
+
+ EDBM_op_init(
+ em, &bmop, op, "convex_hull input=%hvef "
+ "use_existing_faces=%b",
+ BM_ELEM_SELECT,
+ use_existing_faces);
+ BMO_op_exec(em->bm, &bmop);
+
+ /* Hull fails if input is coplanar */
+ if (BMO_error_occurred(em->bm)) {
EDBM_op_finish(em, &bmop, op, true);
- return OPERATOR_CANCELLED;
+ continue;
}
- }
- /* Delete hole edges/faces */
- if (RNA_boolean_get(op->ptr, "make_holes")) {
- if (!EDBM_op_callf(
- em, op, "delete geom=%S context=%i",
- &bmop, "geom_holes.out", DEL_ONLYTAGGED))
- {
- EDBM_op_finish(em, &bmop, op, true);
- return OPERATOR_CANCELLED;
+ BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "geom.out", BM_FACE, BM_ELEM_SELECT, true);
+
+ /* Delete unused vertices, edges, and faces */
+ if (delete_unused) {
+ if (!EDBM_op_callf(
+ em, op, "delete geom=%S context=%i",
+ &bmop, "geom_unused.out", DEL_ONLYTAGGED))
+ {
+ EDBM_op_finish(em, &bmop, op, true);
+ continue;
+ }
}
- }
- /* Merge adjacent triangles */
- if (RNA_boolean_get(op->ptr, "join_triangles")) {
- float angle_face_threshold = RNA_float_get(op->ptr, "face_threshold");
- float angle_shape_threshold = RNA_float_get(op->ptr, "shape_threshold");
+ /* Delete hole edges/faces */
+ if (make_holes) {
+ if (!EDBM_op_callf(
+ em, op, "delete geom=%S context=%i",
+ &bmop, "geom_holes.out", DEL_ONLYTAGGED))
+ {
+ EDBM_op_finish(em, &bmop, op, true);
+ continue;
+ }
+ }
- if (!EDBM_op_call_and_selectf(
- em, op,
- "faces.out", true,
- "join_triangles faces=%S "
- "angle_face_threshold=%f angle_shape_threshold=%f",
- &bmop, "geom.out",
- angle_face_threshold, angle_shape_threshold))
- {
- EDBM_op_finish(em, &bmop, op, true);
- return OPERATOR_CANCELLED;
+ /* Merge adjacent triangles */
+ if (join_triangles) {
+ if (!EDBM_op_call_and_selectf(
+ em, op,
+ "faces.out", true,
+ "join_triangles faces=%S "
+ "angle_face_threshold=%f angle_shape_threshold=%f",
+ &bmop, "geom.out",
+ angle_face_threshold, angle_shape_threshold))
+ {
+ EDBM_op_finish(em, &bmop, op, true);
+ continue;
+ }
+ }
+
+ if (!EDBM_op_finish(em, &bmop, op, true)) {
+ continue;
}
- }
- if (!EDBM_op_finish(em, &bmop, op, true)) {
- return OPERATOR_CANCELLED;
- }
- else {
EDBM_update_generic(em, true, true);
EDBM_selectmode_flush(em);
- return OPERATOR_FINISHED;
}
+
+ MEM_freeN(objects);
+ return OPERATOR_FINISHED;
}
void MESH_OT_convex_hull(wmOperatorType *ot)
diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c
index f65e598e204..0e03b0eeb84 100644
--- a/source/blender/editors/physics/particle_edit.c
+++ b/source/blender/editors/physics/particle_edit.c
@@ -1312,8 +1312,6 @@ void PE_update_object(Depsgraph *depsgraph, Scene *scene, Object *ob, int usefla
if (edit->psys)
edit->psys->flag &= ~PSYS_HAIR_UPDATED;
-
- DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
/************************************************/
@@ -4004,6 +4002,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
if (edit->psys) {
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob);
+ BKE_particle_batch_cache_dirty(edit->psys, BKE_MESH_BATCH_DIRTY_ALL);
}
else {
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
diff --git a/source/blender/editors/screen/workspace_edit.c b/source/blender/editors/screen/workspace_edit.c
index c8aa4560dc4..bd4381f4099 100644
--- a/source/blender/editors/screen/workspace_edit.c
+++ b/source/blender/editors/screen/workspace_edit.c
@@ -331,6 +331,12 @@ static void WORKSPACE_OT_workspace_delete(wmOperatorType *ot)
ot->exec = workspace_delete_exec;
}
+static int workspace_append_activate_poll(bContext *C)
+{
+ wmOperatorType *ot = WM_operatortype_find("WM_OT_append", false);
+ return WM_operator_poll(C, ot);
+}
+
static int workspace_append(bContext *C, const char *directory, const char *idname)
{
wmOperatorType *ot = WM_operatortype_find("WM_OT_append", false);
@@ -384,6 +390,7 @@ static void WORKSPACE_OT_append_activate(wmOperatorType *ot)
/* api callbacks */
ot->exec = workspace_append_activate_exec;
+ ot->poll = workspace_append_activate_poll;
RNA_def_string(ot->srna, "idname", NULL, MAX_ID_NAME - 2, "Identifier",
"Name of the workspace to append and activate");
diff --git a/source/blender/editors/space_view3d/view3d_manipulator_navigate.c b/source/blender/editors/space_view3d/view3d_manipulator_navigate.c
index 2d3f42f9c61..0a209767003 100644
--- a/source/blender/editors/space_view3d/view3d_manipulator_navigate.c
+++ b/source/blender/editors/space_view3d/view3d_manipulator_navigate.c
@@ -211,6 +211,7 @@ static void WIDGETGROUP_navigate_setup(const bContext *UNUSED(C), wmManipulatorG
RNA_property_string_set_bytes(
mpr->ptr, prop,
(const char *)info->shape, info->shape_size);
+ RNA_enum_set(mpr->ptr, "draw_options", ED_MANIPULATOR_BUTTON_SHOW_OUTLINE);
}
wmOperatorType *ot = WM_operatortype_find(info->opname, true);
diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c
index d986e8ff6ee..7fc582a1511 100644
--- a/source/blender/editors/space_view3d/view3d_ops.c
+++ b/source/blender/editors/space_view3d/view3d_ops.c
@@ -415,6 +415,9 @@ void view3d_keymap(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "VIEW3D_OT_toggle_render", ZKEY, KM_PRESS, KM_SHIFT, 0);
+ kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", ZKEY, KM_PRESS, 0, 0);
+ RNA_string_set(kmi->ptr, "data_path", "space_data.use_occlude_geometry");
+
/* selection*/
kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_select", SELECTMOUSE, KM_PRESS, 0, 0);
RNA_boolean_set(kmi->ptr, "extend", false);
@@ -506,31 +509,32 @@ void view3d_keymap(wmKeyConfig *keyconf)
/* context ops */
kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", COMMAKEY, KM_PRESS, 0, 0);
- RNA_string_set(kmi->ptr, "data_path", "space_data.pivot_point");
+ RNA_string_set(kmi->ptr, "data_path", "tool_settings.transform_pivot_point");
RNA_string_set(kmi->ptr, "value", "BOUNDING_BOX_CENTER");
- kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", COMMAKEY, KM_PRESS, KM_CTRL, 0); /* 2.4x allowed Comma+Shift too, rather not use both */
- RNA_string_set(kmi->ptr, "data_path", "space_data.pivot_point");
+ /* 2.4x allowed Comma+Shift too, rather not use both */
+ kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", COMMAKEY, KM_PRESS, KM_CTRL, 0);
+ RNA_string_set(kmi->ptr, "data_path", "tool_settings.transform_pivot_point");
RNA_string_set(kmi->ptr, "value", "MEDIAN_POINT");
kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", COMMAKEY, KM_PRESS, KM_ALT, 0); /* new in 2.5 */
- RNA_string_set(kmi->ptr, "data_path", "space_data.use_pivot_point_align");
-
- kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", SPACEKEY, KM_PRESS, KM_CTRL, 0); /* new in 2.5 */
- RNA_string_set(kmi->ptr, "data_path", "space_data.show_manipulator");
+ RNA_string_set(kmi->ptr, "data_path", "tool_settings.use_transform_pivot_point_align");
kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", PERIODKEY, KM_PRESS, 0, 0);
- RNA_string_set(kmi->ptr, "data_path", "space_data.pivot_point");
+ RNA_string_set(kmi->ptr, "data_path", "tool_settings.transform_pivot_point");
RNA_string_set(kmi->ptr, "value", "CURSOR");
kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", PERIODKEY, KM_PRESS, KM_CTRL, 0);
- RNA_string_set(kmi->ptr, "data_path", "space_data.pivot_point");
+ RNA_string_set(kmi->ptr, "data_path", "tool_settings.transform_pivot_point");
RNA_string_set(kmi->ptr, "value", "INDIVIDUAL_ORIGINS");
kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", PERIODKEY, KM_PRESS, KM_ALT, 0);
- RNA_string_set(kmi->ptr, "data_path", "space_data.pivot_point");
+ RNA_string_set(kmi->ptr, "data_path", "tool_settings.transform_pivot_point");
RNA_string_set(kmi->ptr, "value", "ACTIVE_ELEMENT");
+ kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", SPACEKEY, KM_PRESS, KM_CTRL, 0); /* new in 2.5 */
+ RNA_string_set(kmi->ptr, "data_path", "space_data.show_manipulator");
+
transform_keymap_for_space(keyconf, keymap, SPACE_VIEW3D);
fly_modal_keymap(keyconf);
diff --git a/source/blender/editors/space_view3d/view3d_snap.c b/source/blender/editors/space_view3d/view3d_snap.c
index 95ab30d3352..c5dd5d9ed24 100644
--- a/source/blender/editors/space_view3d/view3d_snap.c
+++ b/source/blender/editors/space_view3d/view3d_snap.c
@@ -30,6 +30,8 @@
*/
+#include "MEM_guardedalloc.h"
+
#include "DNA_armature_types.h"
#include "DNA_object_types.h"
@@ -40,6 +42,8 @@
#include "BKE_action.h"
#include "BKE_armature.h"
#include "BKE_context.h"
+#include "BKE_editmesh.h"
+#include "BKE_layer.h"
#include "BKE_main.h"
#include "BKE_mball.h"
#include "BKE_object.h"
@@ -81,30 +85,49 @@ static int snap_sel_to_grid_exec(bContext *C, wmOperator *UNUSED(op))
gridf = rv3d->gridview;
if (obedit) {
- if (ED_transverts_check_obedit(obedit))
- ED_transverts_create_from_obedit(&tvs, obedit, 0);
- if (tvs.transverts_tot == 0)
- return OPERATOR_CANCELLED;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, &objects_len);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+
+ if ((em->bm->totvertsel == 0) &&
+ (em->bm->totedgesel == 0) &&
+ (em->bm->totfacesel == 0))
+ {
+ continue;
+ }
- copy_m3_m4(bmat, obedit->obmat);
- invert_m3_m3(imat, bmat);
-
- tv = tvs.transverts;
- for (a = 0; a < tvs.transverts_tot; a++, tv++) {
- copy_v3_v3(vec, tv->loc);
- mul_m3_v3(bmat, vec);
- add_v3_v3(vec, obedit->obmat[3]);
- vec[0] = gridf * floorf(0.5f + vec[0] / gridf);
- vec[1] = gridf * floorf(0.5f + vec[1] / gridf);
- vec[2] = gridf * floorf(0.5f + vec[2] / gridf);
- sub_v3_v3(vec, obedit->obmat[3]);
-
- mul_m3_v3(imat, vec);
- copy_v3_v3(tv->loc, vec);
+ if (ED_transverts_check_obedit(obedit)) {
+ ED_transverts_create_from_obedit(&tvs, obedit, 0);
+ }
+
+ if (tvs.transverts_tot == 0) {
+ continue;
+ }
+
+ copy_m3_m4(bmat, obedit->obmat);
+ invert_m3_m3(imat, bmat);
+
+ tv = tvs.transverts;
+ for (a = 0; a < tvs.transverts_tot; a++, tv++) {
+ copy_v3_v3(vec, tv->loc);
+ mul_m3_v3(bmat, vec);
+ add_v3_v3(vec, obedit->obmat[3]);
+ vec[0] = gridf * floorf(0.5f + vec[0] / gridf);
+ vec[1] = gridf * floorf(0.5f + vec[1] / gridf);
+ vec[2] = gridf * floorf(0.5f + vec[2] / gridf);
+ sub_v3_v3(vec, obedit->obmat[3]);
+
+ mul_m3_v3(imat, vec);
+ copy_v3_v3(tv->loc, vec);
+ }
+
+ ED_transverts_update_obedit(&tvs, obedit);
+ ED_transverts_free(&tvs);
}
-
- ED_transverts_update_obedit(&tvs, obedit);
- ED_transverts_free(&tvs);
+ MEM_freeN(objects);
}
else {
struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOCATION_ID);
diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c
index 00976311887..5df3107e40b 100644
--- a/source/blender/editors/transform/transform_snap_object.c
+++ b/source/blender/editors/transform/transform_snap_object.c
@@ -690,32 +690,37 @@ static bool raycastObj(
{
bool retval = false;
- if (ob->type == OB_MESH) {
- if (use_obedit) {
- BMEditMesh *em = BKE_editmesh_from_object(ob);
- retval = raycastEditMesh(
- sctx,
- ray_start, ray_dir,
- ob, em, obmat, ob_index,
- ray_depth, r_loc, r_no, r_index, r_hit_list);
- }
- else {
- retval = raycastMesh(
- sctx,
- ray_start, ray_dir,
- ob, ob->data, obmat, ob_index,
- ray_depth, r_loc, r_no, r_index, r_hit_list);
- }
+ switch (ob->type) {
+ case OB_MESH:
+ if (use_obedit) {
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
+ retval = raycastEditMesh(
+ sctx,
+ ray_start, ray_dir,
+ ob, em, obmat, ob_index,
+ ray_depth, r_loc, r_no, r_index, r_hit_list);
+ }
+ else {
+ retval = raycastMesh(
+ sctx,
+ ray_start, ray_dir,
+ ob, ob->data, obmat, ob_index,
+ ray_depth, r_loc, r_no, r_index, r_hit_list);
+ }
+ break;
}
if (retval) {
if (r_ob) {
*r_ob = ob;
+ }
+ if (r_obmat) {
copy_m4_m4(r_obmat, obmat);
}
+ return true;
}
- return retval;
+ return false;
}
@@ -896,9 +901,9 @@ static void cb_mlooptri_verts_get(
}
static bool test_projected_vert_dist(
- struct DistProjectedAABBPrecalc *neasrest_precalc,
- const float depth_range[2], const float co[3],
- const bool is_persp,
+ const struct DistProjectedAABBPrecalc *neasrest_precalc,
+ const float depth_range[2],
+ const bool is_persp, const float co[3],
float *dist_px_sq, float r_co[3])
{
float w;
@@ -928,21 +933,21 @@ static bool test_projected_vert_dist(
}
static bool test_projected_edge_dist(
- struct DistProjectedAABBPrecalc *neasrest_precalc,
+ const struct DistProjectedAABBPrecalc *neasrest_precalc,
const float depth_range[2], const bool is_persp,
const float va[3], const float vb[3],
float *dist_px_sq, float r_co[3])
{
- float tmp_co[3], dummy_depth;
+ float near_co[3], dummy_depth;
dist_squared_ray_to_seg_v3(
neasrest_precalc->ray_origin,
neasrest_precalc->ray_direction,
- va, vb, tmp_co, &dummy_depth);
+ va, vb, near_co, &dummy_depth);
return test_projected_vert_dist(
neasrest_precalc, depth_range,
- tmp_co, is_persp, dist_px_sq, r_co);
+ is_persp, near_co, dist_px_sq, r_co);
}
/** \} */
@@ -958,8 +963,6 @@ typedef void (*Nearest2DGetTriEdgesCallback)(const int index, int e_index[3], vo
typedef void (*Nearest2DCopyVertNoCallback)(const int index, float r_no[3], void *data);
typedef struct Nearest2dUserData {
- struct DistProjectedAABBPrecalc data_precalc;
- bool r_axis_closest[3];
bool is_persp;
float depth_range[2];
short snap_to;
@@ -971,32 +974,13 @@ typedef struct Nearest2dUserData {
Nearest2DGetTriEdgesCallback get_tri_edges_index;
Nearest2DCopyVertNoCallback copy_vert_no;
- float dist_px_sq;
- int index;
- float co[3];
- float no[3];
} Nearest2dUserData;
-static bool cb_walk_parent_snap_project(const BVHTreeAxisRange *bounds, void *user_data)
-{
- Nearest2dUserData *data = user_data;
- const float bbmin[3] = {bounds[0].min, bounds[1].min, bounds[2].min};
- const float bbmax[3] = {bounds[0].max, bounds[1].max, bounds[2].max};
- const float rdist = dist_squared_to_projected_aabb(
- &data->data_precalc, bbmin, bbmax, data->r_axis_closest);
- return rdist < data->dist_px_sq;
-}
-
-static bool cb_nearest_walk_order(
- const BVHTreeAxisRange *UNUSED(bounds), char axis, void *userdata)
-{
- const bool *r_axis_closest = ((struct Nearest2dUserData *)userdata)->r_axis_closest;
- return r_axis_closest[axis];
-}
-
-static bool cb_walk_leaf_snap_vert(
- const BVHTreeAxisRange *UNUSED(bounds), int index, void *userdata)
+static void cb_walk_leaf_snap_vert(
+ void *userdata, int index,
+ const struct DistProjectedAABBPrecalc *precalc,
+ BVHTreeNearest *nearest)
{
struct Nearest2dUserData *data = userdata;
@@ -1004,20 +988,22 @@ static bool cb_walk_leaf_snap_vert(
data->get_vert_co(index, &co, data->userdata);
if (test_projected_vert_dist(
- &data->data_precalc,
- data->depth_range, co,
+ precalc,
+ data->depth_range,
data->is_persp,
- &data->dist_px_sq,
- data->co))
+ co,
+ &nearest->dist_sq,
+ nearest->co))
{
- data->copy_vert_no(index, data->no, data->userdata);
- data->index = index;
+ data->copy_vert_no(index, nearest->no, data->userdata);
+ nearest->index = index;
}
- return true;
}
-static bool cb_walk_leaf_snap_edge(
- const BVHTreeAxisRange *UNUSED(bounds), int index, void *userdata)
+static void cb_walk_leaf_snap_edge(
+ void *userdata, int index,
+ const struct DistProjectedAABBPrecalc *precalc,
+ BVHTreeNearest *nearest)
{
struct Nearest2dUserData *data = userdata;
@@ -1030,31 +1016,31 @@ static bool cb_walk_leaf_snap_edge(
data->get_vert_co(vindex[1], &v_pair[1], data->userdata);
if (test_projected_edge_dist(
- &data->data_precalc,
+ precalc,
data->depth_range,
data->is_persp,
v_pair[0], v_pair[1],
- &data->dist_px_sq,
- data->co))
+ &nearest->dist_sq,
+ nearest->co))
{
- sub_v3_v3v3(data->no, v_pair[0], v_pair[1]);
- data->index = index;
+ sub_v3_v3v3(nearest->no, v_pair[0], v_pair[1]);
+ nearest->index = index;
}
}
else {
for (int i = 0; i < 2; i++) {
- if (vindex[i] == data->index) {
+ if (vindex[i] == nearest->index) {
continue;
}
- cb_walk_leaf_snap_vert(NULL, vindex[i], userdata);
+ cb_walk_leaf_snap_vert(userdata, vindex[i], precalc, nearest);
}
}
-
- return true;
}
-static bool cb_walk_leaf_snap_tri(
- const BVHTreeAxisRange *UNUSED(bounds), int index, void *userdata)
+static void cb_walk_leaf_snap_tri(
+ void *userdata, int index,
+ const struct DistProjectedAABBPrecalc *precalc,
+ BVHTreeNearest *nearest)
{
struct Nearest2dUserData *data = userdata;
@@ -1063,10 +1049,10 @@ static bool cb_walk_leaf_snap_tri(
data->get_tri_edges_index(index, eindex, data->userdata);
for (int i = 0; i < 3; i++) {
if (eindex[i] != -1) {
- if (eindex[i] == data->index) {
+ if (eindex[i] == nearest->index) {
continue;
}
- cb_walk_leaf_snap_edge(NULL, eindex[i], userdata);
+ cb_walk_leaf_snap_edge(userdata, eindex[i], precalc, nearest);
}
}
}
@@ -1074,13 +1060,12 @@ static bool cb_walk_leaf_snap_tri(
int vindex[3];
data->get_tri_verts_index(index, vindex, data->userdata);
for (int i = 0; i < 3; i++) {
- if (vindex[i] == data->index) {
+ if (vindex[i] == nearest->index) {
continue;
}
- cb_walk_leaf_snap_vert(NULL, vindex[i], userdata);
+ cb_walk_leaf_snap_vert(userdata, vindex[i], precalc, nearest);
}
}
- return true;
}
/** \} */
@@ -1134,10 +1119,10 @@ static bool snapArmature(
case SCE_SNAP_MODE_VERTEX:
retval |= test_projected_vert_dist(
&neasrest_precalc, snapdata->depth_range,
- eBone->head, is_persp, &dist_px_sq, r_loc);
+ is_persp, eBone->head, &dist_px_sq, r_loc);
retval |= test_projected_vert_dist(
&neasrest_precalc, snapdata->depth_range,
- eBone->tail, is_persp, &dist_px_sq, r_loc);
+ is_persp, eBone->tail, &dist_px_sq, r_loc);
break;
case SCE_SNAP_MODE_EDGE:
retval |= test_projected_edge_dist(
@@ -1162,10 +1147,10 @@ static bool snapArmature(
case SCE_SNAP_MODE_VERTEX:
retval |= test_projected_vert_dist(
&neasrest_precalc, snapdata->depth_range,
- head_vec, is_persp, &dist_px_sq, r_loc);
+ is_persp, head_vec, &dist_px_sq, r_loc);
retval |= test_projected_vert_dist(
&neasrest_precalc, snapdata->depth_range,
- tail_vec, is_persp, &dist_px_sq, r_loc);
+ is_persp, tail_vec, &dist_px_sq, r_loc);
break;
case SCE_SNAP_MODE_EDGE:
retval |= test_projected_edge_dist(
@@ -1239,7 +1224,7 @@ static bool snapCurve(
}
retval |= test_projected_vert_dist(
&neasrest_precalc, snapdata->depth_range,
- nu->bezt[u].vec[1], is_persp, &dist_px_sq,
+ is_persp, nu->bezt[u].vec[1], &dist_px_sq,
r_loc);
/* don't snap if handle is selected (moving), or if it is aligning to a moving handle */
if (!(nu->bezt[u].f1 & SELECT) &&
@@ -1247,7 +1232,7 @@ static bool snapCurve(
{
retval |= test_projected_vert_dist(
&neasrest_precalc, snapdata->depth_range,
- nu->bezt[u].vec[0], is_persp, &dist_px_sq,
+ is_persp, nu->bezt[u].vec[0], &dist_px_sq,
r_loc);
}
if (!(nu->bezt[u].f3 & SELECT) &&
@@ -1255,7 +1240,7 @@ static bool snapCurve(
{
retval |= test_projected_vert_dist(
&neasrest_precalc, snapdata->depth_range,
- nu->bezt[u].vec[2], is_persp, &dist_px_sq,
+ is_persp, nu->bezt[u].vec[2], &dist_px_sq,
r_loc);
}
}
@@ -1266,7 +1251,7 @@ static bool snapCurve(
}
retval |= test_projected_vert_dist(
&neasrest_precalc, snapdata->depth_range,
- nu->bp[u].vec, is_persp, &dist_px_sq,
+ is_persp, nu->bp[u].vec, &dist_px_sq,
r_loc);
}
}
@@ -1276,13 +1261,13 @@ static bool snapCurve(
if (nu->bezt) {
retval |= test_projected_vert_dist(
&neasrest_precalc, snapdata->depth_range,
- nu->bezt[u].vec[1], is_persp, &dist_px_sq,
+ is_persp, nu->bezt[u].vec[1], &dist_px_sq,
r_loc);
}
else {
retval |= test_projected_vert_dist(
&neasrest_precalc, snapdata->depth_range,
- nu->bp[u].vec, is_persp, &dist_px_sq,
+ is_persp, nu->bp[u].vec, &dist_px_sq,
r_loc);
}
}
@@ -1328,11 +1313,11 @@ static bool snapEmpty(
bool is_persp = snapdata->view_proj == VIEW_PROJ_PERSP;
float dist_px_sq = SQUARE(*dist_px);
- float tmp_co[3];
- copy_v3_v3(tmp_co, obmat[3]);
+ float co[3];
+ copy_v3_v3(co, obmat[3]);
if (test_projected_vert_dist(
&neasrest_precalc, snapdata->depth_range,
- tmp_co, is_persp, &dist_px_sq, r_loc))
+ is_persp, co, &dist_px_sq, r_loc))
{
*dist_px = sqrtf(dist_px_sq);
*ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir);
@@ -1423,7 +1408,7 @@ static bool snapCamera(
mul_m4_v3(vertex_obmat, bundle_pos);
retval |= test_projected_vert_dist(
&neasrest_precalc, snapdata->depth_range,
- bundle_pos, is_persp, &dist_px_sq, r_loc);
+ is_persp, bundle_pos, &dist_px_sq, r_loc);
}
}
@@ -1465,23 +1450,22 @@ static bool snapMesh(
float lpmat[4][4];
mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
- Nearest2dUserData neasrest2d;
- dist_squared_to_projected_aabb_precalc(
- &neasrest2d.data_precalc, lpmat, snapdata->win_size, snapdata->mval);
-
- neasrest2d.r_axis_closest[0] = true;
- neasrest2d.r_axis_closest[1] = true;
- neasrest2d.r_axis_closest[2] = true;
- neasrest2d.dist_px_sq = SQUARE(*dist_px);
+ float dist_px_sq = SQUARE(*dist_px);
/* Test BoundBox */
BoundBox *bb = BKE_mesh_boundbox_get(ob);
if (bb) {
/* In vertex and edges you need to get the pixel distance from ray to BoundBox, see: T46099, T46816 */
- float dist_px_sq = dist_squared_to_projected_aabb(
- &neasrest2d.data_precalc, bb->vec[0], bb->vec[6], neasrest2d.r_axis_closest);
- if (dist_px_sq > neasrest2d.dist_px_sq) {
+ struct DistProjectedAABBPrecalc data_precalc;
+ dist_squared_to_projected_aabb_precalc(
+ &data_precalc, lpmat, snapdata->win_size, snapdata->mval);
+
+ bool dummy[3];
+ float bb_dist_px_sq = dist_squared_to_projected_aabb(
+ &data_precalc, bb->vec[0], bb->vec[6], dummy);
+
+ if (bb_dist_px_sq > dist_px_sq) {
return retval;
}
}
@@ -1582,56 +1566,58 @@ static bool snapMesh(
* And more... ray_depth is being confused with Z-depth here... (varies only the precision) */
const float ray_depth_max_global = *ray_depth + snapdata->depth_range[0];
- neasrest2d.is_persp = snapdata->view_proj == VIEW_PROJ_PERSP;
-
- neasrest2d.depth_range[0] = snapdata->depth_range[0];
- neasrest2d.depth_range[1] = ray_depth_max_global;
-
- neasrest2d.snap_to = snapdata->snap_to;
- neasrest2d.userdata = treedata;
- neasrest2d.get_vert_co = (Nearest2DGetVertCoCallback)cb_mvert_co_get;
- neasrest2d.get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_medge_verts_get;
- neasrest2d.get_tri_verts_index = (Nearest2DGetTriVertsCallback)cb_mlooptri_verts_get;
- neasrest2d.get_tri_edges_index = (Nearest2DGetTriEdgesCallback)cb_mlooptri_edges_get;
- neasrest2d.copy_vert_no = (Nearest2DCopyVertNoCallback)cb_mvert_no_copy;
- neasrest2d.index = -1;
+ Nearest2dUserData neasrest2d = {
+ .is_persp = snapdata->view_proj == VIEW_PROJ_PERSP,
+ .depth_range = {snapdata->depth_range[0], ray_depth_max_global},
+ .snap_to = snapdata->snap_to,
+ .userdata = treedata,
+ .get_vert_co = (Nearest2DGetVertCoCallback)cb_mvert_co_get,
+ .get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_medge_verts_get,
+ .get_tri_verts_index = (Nearest2DGetTriVertsCallback)cb_mlooptri_verts_get,
+ .get_tri_edges_index = (Nearest2DGetTriEdgesCallback)cb_mlooptri_edges_get,
+ .copy_vert_no = (Nearest2DCopyVertNoCallback)cb_mvert_no_copy,
+ };
+ BVHTreeNearest nearest = {
+ .index = -1,
+ .dist_sq = dist_px_sq,
+ };
if (bvhtree[1]) {
/* snap to loose verts */
- BLI_bvhtree_walk_dfs(
- bvhtree[1],
- cb_walk_parent_snap_project, cb_walk_leaf_snap_vert, cb_nearest_walk_order, &neasrest2d);
+ BLI_bvhtree_find_nearest_projected(
+ bvhtree[1], lpmat, snapdata->win_size, snapdata->mval,
+ NULL, 0, &nearest, cb_walk_leaf_snap_vert, &neasrest2d);
}
if (bvhtree[0]) {
/* snap to loose edges */
- BLI_bvhtree_walk_dfs(
- bvhtree[0],
- cb_walk_parent_snap_project, cb_walk_leaf_snap_edge, cb_nearest_walk_order, &neasrest2d);
+ BLI_bvhtree_find_nearest_projected(
+ bvhtree[0], lpmat, snapdata->win_size, snapdata->mval,
+ NULL, 0, &nearest, cb_walk_leaf_snap_edge, &neasrest2d);
}
if (treedata->tree) {
/* snap to looptris */
- BLI_bvhtree_walk_dfs(
- treedata->tree,
- cb_walk_parent_snap_project, cb_walk_leaf_snap_tri, cb_nearest_walk_order, &neasrest2d);
+ BLI_bvhtree_find_nearest_projected(
+ treedata->tree, lpmat, snapdata->win_size, snapdata->mval,
+ NULL, 0, &nearest, cb_walk_leaf_snap_tri, &neasrest2d);
}
- if (neasrest2d.index != -1) {
+ if (nearest.index != -1) {
float imat[4][4];
float timat[3][3]; /* transpose inverse matrix for normals */
invert_m4_m4(imat, obmat);
transpose_m3_m4(timat, imat);
- copy_v3_v3(r_loc, neasrest2d.co);
+ copy_v3_v3(r_loc, nearest.co);
mul_m4_v3(obmat, r_loc);
if (r_no) {
- copy_v3_v3(r_no, neasrest2d.no);
+ copy_v3_v3(r_no, nearest.no);
mul_m3_v3(timat, r_no);
normalize_v3(r_no);
}
- *dist_px = sqrtf(neasrest2d.dist_px_sq);
+ *dist_px = sqrtf(nearest.dist_sq);
*ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir);
retval = true;
@@ -1733,7 +1719,6 @@ static bool snapEditMesh(
}
Nearest2dUserData neasrest2d = {
- .r_axis_closest = {true, true, true},
.is_persp = snapdata->view_proj == VIEW_PROJ_PERSP,
.depth_range = {snapdata->depth_range[0], *ray_depth + snapdata->depth_range[0]},
.snap_to = snapdata->snap_to,
@@ -1741,36 +1726,37 @@ static bool snapEditMesh(
.get_vert_co = (Nearest2DGetVertCoCallback)cb_bvert_co_get,
.get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_bedge_verts_get,
.copy_vert_no = (Nearest2DCopyVertNoCallback)cb_bvert_no_copy,
- .dist_px_sq = SQUARE(*dist_px),
- .index = -1};
+ };
- float lpmat[4][4];
- mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
- dist_squared_to_projected_aabb_precalc(
- &neasrest2d.data_precalc, lpmat, snapdata->win_size, snapdata->mval);
+ BVHTreeNearest nearest = {
+ .index = -1,
+ .dist_sq = SQUARE(*dist_px),
+ };
- BVHTree_WalkLeafCallback cb_walk_leaf =
+ BVHTree_NearestProjectedCallback cb_walk_leaf =
(snapdata->snap_to == SCE_SNAP_MODE_VERTEX) ?
cb_walk_leaf_snap_vert : cb_walk_leaf_snap_edge;
- BLI_bvhtree_walk_dfs(
- treedata->tree,
- cb_walk_parent_snap_project, cb_walk_leaf, cb_nearest_walk_order, &neasrest2d);
+ float lpmat[4][4];
+ mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
+ BLI_bvhtree_find_nearest_projected(
+ treedata->tree, lpmat, snapdata->win_size, snapdata->mval,
+ NULL, 0, &nearest, cb_walk_leaf, &neasrest2d);
- if (neasrest2d.index != -1) {
+ if (nearest.index != -1) {
float imat[4][4];
float timat[3][3]; /* transpose inverse matrix for normals */
invert_m4_m4(imat, obmat);
transpose_m3_m4(timat, imat);
- copy_v3_v3(r_loc, neasrest2d.co);
+ copy_v3_v3(r_loc, nearest.co);
mul_m4_v3(obmat, r_loc);
if (r_no) {
- copy_v3_v3(r_no, neasrest2d.no);
+ copy_v3_v3(r_no, nearest.no);
mul_m3_v3(timat, r_no);
normalize_v3(r_no);
}
- *dist_px = sqrtf(neasrest2d.dist_px_sq);
+ *dist_px = sqrtf(nearest.dist_sq);
*ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir);
retval = true;
@@ -1786,71 +1772,75 @@ static bool snapEditMesh(
*/
static bool snapObject(
SnapObjectContext *sctx, SnapData *snapdata,
- Object *ob, float obmat[4][4],
- bool use_obedit,
+ Object *ob, float obmat[4][4], bool use_obedit,
/* read/write args */
float *ray_depth, float *dist_px,
/* return args */
float r_loc[3], float r_no[3],
Object **r_ob, float r_obmat[4][4])
{
+ BLI_assert(snapdata->snap_to != SCE_SNAP_MODE_FACE);
bool retval = false;
- if (ob->type == OB_MESH) {
- BMEditMesh *em;
+ switch (ob->type) {
+ case OB_MESH:
+ if (use_obedit) {
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
+ retval = snapEditMesh(
+ sctx, snapdata, ob, em, obmat,
+ ray_depth, dist_px,
+ r_loc, r_no);
+ }
+ else {
+ retval = snapMesh(
+ sctx, snapdata, ob, ob->data, obmat,
+ ray_depth, dist_px,
+ r_loc, r_no);
+ }
+ break;
- if (use_obedit) {
- em = BKE_editmesh_from_object(ob);
- retval = snapEditMesh(
- sctx, snapdata, ob, em, obmat,
- ray_depth, dist_px,
- r_loc, r_no);
- }
- else {
- retval = snapMesh(
- sctx, snapdata, ob, ob->data, obmat,
- ray_depth, dist_px,
- r_loc, r_no);
- }
- }
- else if (snapdata->snap_to != SCE_SNAP_MODE_FACE) {
- if (ob->type == OB_ARMATURE) {
+ case OB_ARMATURE:
retval = snapArmature(
snapdata,
ob, ob->data, obmat,
ray_depth, dist_px,
r_loc, r_no);
- }
- else if (ob->type == OB_CURVE) {
+ break;
+
+ case OB_CURVE:
retval = snapCurve(
snapdata,
ob, obmat, use_obedit,
ray_depth, dist_px,
r_loc, r_no);
- }
- else if (ob->type == OB_EMPTY) {
+ break;
+
+ case OB_EMPTY:
retval = snapEmpty(
- snapdata,
- ob, obmat,
+ snapdata, ob, obmat,
ray_depth, dist_px,
r_loc, r_no);
- }
- else if (ob->type == OB_CAMERA) {
+ break;
+
+ case OB_CAMERA:
retval = snapCamera(
sctx, snapdata, ob, obmat,
ray_depth, dist_px,
r_loc, r_no);
- }
+ break;
}
if (retval) {
if (r_ob) {
*r_ob = ob;
+ }
+ if (r_obmat) {
copy_m4_m4(r_obmat, obmat);
}
+ return true;
}
- return retval;
+ return false;
}
diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
index 8029759551d..d13a4646a2f 100644
--- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c
+++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
@@ -1222,7 +1222,7 @@ static void uv_map_clip_correct_properties(wmOperatorType *ot)
"Scale UV coordinates to bounds after unwrapping");
}
-static void uv_map_clip_correct(Scene *scene, Object *ob, BMEditMesh *em, wmOperator *op)
+static void uv_map_clip_correct_multi(Scene *scene, Object **objects, uint objects_len, wmOperator *op)
{
BMFace *efa;
BMLoop *l;
@@ -1233,25 +1233,46 @@ static void uv_map_clip_correct(Scene *scene, Object *ob, BMEditMesh *em, wmOper
const bool clip_to_bounds = RNA_boolean_get(op->ptr, "clip_to_bounds");
const bool scale_to_bounds = RNA_boolean_get(op->ptr, "scale_to_bounds");
- const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
+ INIT_MINMAX2(min, max);
- /* correct for image aspect ratio */
- if (correct_aspect)
- correct_uv_aspect(scene, ob, em);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *ob = objects[ob_index];
- if (scale_to_bounds) {
- INIT_MINMAX2(min, max);
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
+ const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
- continue;
+ /* correct for image aspect ratio */
+ if (correct_aspect)
+ correct_uv_aspect(scene, ob, em);
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- minmax_v2v2_v2(min, max, luv->uv);
+ if (scale_to_bounds) {
+ /* find uv limits */
+ BM_ITER_MESH(efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
+ continue;
+
+ BM_ITER_ELEM(l, &liter, efa, BM_LOOPS_OF_FACE) {
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ minmax_v2v2_v2(min, max, luv->uv);
+ }
+ }
+ }
+ else if (clip_to_bounds) {
+ /* clipping and wrapping */
+ BM_ITER_MESH(efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
+ continue;
+
+ BM_ITER_ELEM(l, &liter, efa, BM_LOOPS_OF_FACE) {
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ CLAMP(luv->uv[0], 0.0f, 1.0f);
+ CLAMP(luv->uv[1], 0.0f, 1.0f);
+ }
}
}
+ }
+ if (scale_to_bounds) {
/* rescale UV to be in 1/1 */
dx = (max[0] - min[0]);
dy = (max[1] - min[1]);
@@ -1261,33 +1282,32 @@ static void uv_map_clip_correct(Scene *scene, Object *ob, BMEditMesh *em, wmOper
if (dy > 0.0f)
dy = 1.0f / dy;
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
- continue;
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *ob = objects[ob_index];
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
+ const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
- luv->uv[0] = (luv->uv[0] - min[0]) * dx;
- luv->uv[1] = (luv->uv[1] - min[1]) * dy;
- }
- }
- }
- else if (clip_to_bounds) {
- /* clipping and wrapping */
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
- continue;
+ BM_ITER_MESH(efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
+ continue;
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- CLAMP(luv->uv[0], 0.0f, 1.0f);
- CLAMP(luv->uv[1], 0.0f, 1.0f);
+ BM_ITER_ELEM(l, &liter, efa, BM_LOOPS_OF_FACE) {
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+
+ luv->uv[0] = (luv->uv[0] - min[0]) * dx;
+ luv->uv[1] = (luv->uv[1] - min[1]) * dy;
+ }
}
}
}
}
+static void uv_map_clip_correct(Scene *scene, Object *ob, wmOperator *op)
+{
+ uv_map_clip_correct_multi(scene, &ob, 1, op);
+}
+
/* ******************** Unwrap operator **************** */
/* assumes UV Map is checked, doesn't run update funcs */
@@ -1466,9 +1486,9 @@ static int uv_from_view_exec(bContext *C, wmOperator *op)
float rotmat[4][4];
bool changed_multi = false;
+ /* Note: objects that aren't touched are set to NULL (to skip clipping). */
uint objects_len = 0;
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, &objects_len);
-
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
Object *obedit = objects[ob_index];
BMEditMesh *em = BKE_editmesh_from_object(obedit);
@@ -1534,13 +1554,21 @@ static int uv_from_view_exec(bContext *C, wmOperator *op)
if (changed) {
changed_multi = true;
- uv_map_clip_correct(scene, obedit, em, op);
-
DEG_id_tag_update(obedit->data, 0);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
}
+ else {
+ ARRAY_DELETE_REORDER_LAST(objects, ob_index, 1, objects_len);
+ objects_len -= 1;
+ ob_index -= 1;
+ }
}
- MEM_SAFE_FREE(objects);
+
+ if (changed_multi) {
+ uv_map_clip_correct_multi(scene, objects, objects_len, op);
+ }
+
+ MEM_freeN(objects);
if (changed_multi) {
return OPERATOR_FINISHED;
@@ -1718,7 +1746,7 @@ static int sphere_project_exec(bContext *C, wmOperator *op)
uv_map_mirror(em, efa);
}
- uv_map_clip_correct(scene, obedit, em, op);
+ uv_map_clip_correct(scene, obedit, op);
DEG_id_tag_update(obedit->data, 0);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
@@ -1806,7 +1834,7 @@ static int cylinder_project_exec(bContext *C, wmOperator *op)
uv_map_mirror(em, efa);
}
- uv_map_clip_correct(scene, obedit, em, op);
+ uv_map_clip_correct(scene, obedit, op);
DEG_id_tag_update(obedit->data, 0);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
@@ -1923,7 +1951,7 @@ static int cube_project_exec(bContext *C, wmOperator *op)
ED_uvedit_unwrap_cube_project(em->bm, cube_size, true, center);
- uv_map_clip_correct(scene, obedit, em, op);
+ uv_map_clip_correct(scene, obedit, op);
DEG_id_tag_update(obedit->data, 0);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
diff --git a/source/blender/gpu/GPU_texture.h b/source/blender/gpu/GPU_texture.h
index 84fd8049bcd..aeea7319ef9 100644
--- a/source/blender/gpu/GPU_texture.h
+++ b/source/blender/gpu/GPU_texture.h
@@ -39,6 +39,7 @@ extern "C" {
struct Image;
struct ImageUser;
struct PreviewImage;
+struct Gwn_VertBuf;
struct GPUFrameBuffer;
typedef struct GPUTexture GPUTexture;
@@ -62,38 +63,36 @@ typedef struct GPUTexture GPUTexture;
* specification. */
typedef enum GPUTextureFormat {
/* Formats texture & renderbuffer */
+ GPU_RGBA8UI,
+ GPU_RGBA8I,
+ GPU_RGBA8,
+ GPU_RGBA32UI,
+ GPU_RGBA32I,
GPU_RGBA32F,
+ GPU_RGBA16UI,
+ GPU_RGBA16I,
GPU_RGBA16F,
- GPU_RGBA8,
+ GPU_RGBA16,
+ GPU_RG8UI,
+ GPU_RG8I,
+ GPU_RG8,
+ GPU_RG32UI,
+ GPU_RG32I,
GPU_RG32F,
- GPU_RG16F,
+ GPU_RG16UI,
GPU_RG16I,
+ GPU_RG16F,
GPU_RG16,
- GPU_R32F,
- GPU_R32UI,
- GPU_R16F,
- GPU_R16I,
- GPU_R16UI,
- GPU_RG8,
+ GPU_R8UI,
+ GPU_R8I,
GPU_R8,
-#if 0
- GPU_RGBA32I,
- GPU_RGBA32UI,
- GPU_RGBA16,
- GPU_RGBA16I,
- GPU_RGBA16UI,
- GPU_RGBA8I,
- GPU_RGBA8UI,
- GPU_RG32I,
- GPU_RG32UI,
- GPU_RG16UI,
- GPU_RG8I,
- GPU_RG8UI,
+ GPU_R32UI,
GPU_R32I,
- GPU_R16,
- GPU_R8I,
- GPU_R8UI,
-#endif
+ GPU_R32F,
+ GPU_R16UI,
+ GPU_R16I,
+ GPU_R16F,
+ GPU_R16, /* Max texture buffer format. */
/* Special formats texture & renderbuffer */
#if 0
@@ -157,6 +156,7 @@ GPUTexture *GPU_texture_create_3D(
int w, int h, int d, GPUTextureFormat data_type, const float *pixels, char err_out[256]);
GPUTexture *GPU_texture_create_cube(
int w, GPUTextureFormat data_type, const float *pixels, char err_out[256]);
+GPUTexture *GPU_texture_create_from_vertbuf(struct Gwn_VertBuf *vert);
GPUTexture *GPU_texture_from_blender(
struct Image *ima, struct ImageUser *iuser, int textarget, bool is_data, double time, int mipmap);
diff --git a/source/blender/gpu/intern/gpu_texture.c b/source/blender/gpu/intern/gpu_texture.c
index 19e26dcce8c..3961278ad1a 100644
--- a/source/blender/gpu/intern/gpu_texture.c
+++ b/source/blender/gpu/intern/gpu_texture.c
@@ -35,6 +35,7 @@
#include "BKE_global.h"
+#include "GPU_batch.h"
#include "GPU_debug.h"
#include "GPU_draw.h"
#include "GPU_extensions.h"
@@ -608,6 +609,57 @@ static GPUTexture *GPU_texture_cube_create(
return tex;
}
+/* Special buffer textures. data_type must be compatible with the buffer content. */
+static GPUTexture *GPU_texture_create_buffer(GPUTextureFormat data_type, const GLuint buffer)
+{
+ GPUTexture *tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
+ tex->number = -1;
+ tex->refcount = 1;
+ tex->format = data_type;
+ tex->components = gpu_texture_get_component_count(data_type);
+ tex->format_flag = 0;
+ tex->target_base = tex->target = GL_TEXTURE_BUFFER;
+
+ GLenum format, internalformat, data_format;
+ internalformat = gpu_texture_get_format(tex->components, data_type, &format, &data_format,
+ &tex->format_flag, &tex->bytesize);
+
+ if (!(ELEM(data_type, GPU_R8, GPU_R16) ||
+ ELEM(data_type, GPU_R16F, GPU_R32F) ||
+ ELEM(data_type, GPU_R8I, GPU_R16I, GPU_R32I) ||
+ ELEM(data_type, GPU_R8UI, GPU_R16UI, GPU_R32UI) ||
+ ELEM(data_type, GPU_RG8, GPU_RG16) ||
+ ELEM(data_type, GPU_RG16F, GPU_RG32F) ||
+ ELEM(data_type, GPU_RG8I, GPU_RG16I, GPU_RG32I) ||
+ ELEM(data_type, GPU_RG8UI, GPU_RG16UI, GPU_RG32UI) ||
+ //ELEM(data_type, GPU_RGB32F, GPU_RGB32I, GPU_RGB32UI) || /* Not available until gl 4.0 */
+ ELEM(data_type, GPU_RGBA8, GPU_RGBA16) ||
+ ELEM(data_type, GPU_RGBA16F, GPU_RGBA32F) ||
+ ELEM(data_type, GPU_RGBA8I, GPU_RGBA16I, GPU_RGBA32I) ||
+ ELEM(data_type, GPU_RGBA8UI, GPU_RGBA16UI, GPU_RGBA32UI)))
+ {
+ fprintf(stderr, "GPUTexture: invalid format for texture buffer");
+ GPU_texture_free(tex);
+ return NULL;
+ }
+
+ /* Generate Texture object */
+ glGenTextures(1, &tex->bindcode);
+
+ if (!tex->bindcode) {
+ fprintf(stderr, "GPUTexture: texture create failed");
+ GPU_texture_free(tex);
+ BLI_assert(0 && "glGenTextures failled: Are you sure a valid OGL context is active on this thread?");
+ return NULL;
+ }
+
+ glBindTexture(tex->target, tex->bindcode);
+ glTexBuffer(tex->target, internalformat, buffer);
+ glBindTexture(tex->target, 0);
+
+ return tex;
+}
+
GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, int textarget, bool is_data, double UNUSED(time), int mipmap)
{
int gputt;
@@ -768,6 +820,74 @@ GPUTexture *GPU_texture_create_cube(
data_type, err_out);
}
+GPUTexture *GPU_texture_create_from_vertbuf(Gwn_VertBuf *vert)
+{
+ Gwn_VertFormat *format = &vert->format;
+ Gwn_VertAttr *attr = &format->attribs[0];
+
+ /* Detect incompatible cases (not supported by texture buffers) */
+ BLI_assert(format->attrib_ct == 1 && vert->vbo_id != 0);
+ BLI_assert(attr->comp_ct != 3); /* Not until OGL 4.0 */
+ BLI_assert(attr->comp_type != GWN_COMP_I10);
+ BLI_assert(attr->fetch_mode != GWN_FETCH_INT_TO_FLOAT);
+
+ unsigned int byte_per_comp = attr->sz / attr->comp_ct;
+ bool is_uint = ELEM(attr->comp_type, GWN_COMP_U8, GWN_COMP_U16, GWN_COMP_U32);
+
+ /* Cannot fetch signed int or 32bit ints as normalized float. */
+ if (attr->fetch_mode == GWN_FETCH_INT_TO_FLOAT_UNIT) {
+ BLI_assert(is_uint || byte_per_comp <= 2);
+ }
+
+ GPUTextureFormat data_type;
+ switch (attr->fetch_mode) {
+ case GWN_FETCH_FLOAT:
+ switch (attr->comp_ct) {
+ case 1: data_type = GPU_R32F; break;
+ case 2: data_type = GPU_RG32F; break;
+ // case 3: data_type = GPU_RGB32F; break; /* Not supported */
+ default: data_type = GPU_RGBA32F; break;
+ }
+ break;
+ case GWN_FETCH_INT:
+ switch (attr->comp_ct) {
+ case 1:
+ switch (byte_per_comp) {
+ case 1: data_type = (is_uint) ? GPU_R8UI : GPU_R8I; break;
+ case 2: data_type = (is_uint) ? GPU_R16UI : GPU_R16I; break;
+ default: data_type = (is_uint) ? GPU_R32UI : GPU_R32I; break;
+ }
+ break;
+ case 2:
+ switch (byte_per_comp) {
+ case 1: data_type = (is_uint) ? GPU_RG8UI : GPU_RG8I; break;
+ case 2: data_type = (is_uint) ? GPU_RG16UI : GPU_RG16I; break;
+ default: data_type = (is_uint) ? GPU_RG32UI : GPU_RG32I; break;
+ }
+ break;
+ default:
+ switch (byte_per_comp) {
+ case 1: data_type = (is_uint) ? GPU_RGBA8UI : GPU_RGBA8I; break;
+ case 2: data_type = (is_uint) ? GPU_RGBA16UI : GPU_RGBA16I; break;
+ default: data_type = (is_uint) ? GPU_RGBA32UI : GPU_RGBA32I; break;
+ }
+ break;
+ }
+ break;
+ case GWN_FETCH_INT_TO_FLOAT_UNIT:
+ switch (attr->comp_ct) {
+ case 1: data_type = (byte_per_comp == 1) ? GPU_R8 : GPU_R16; break;
+ case 2: data_type = (byte_per_comp == 1) ? GPU_RG8 : GPU_RG16; break;
+ default: data_type = (byte_per_comp == 1) ? GPU_RGBA8 : GPU_RGBA16; break;
+ }
+ break;
+ default:
+ BLI_assert(0);
+ }
+
+ return GPU_texture_create_buffer(data_type, vert->vbo_id);
+}
+
void GPU_texture_update(GPUTexture *tex, const float *pixels)
{
BLI_assert(tex->format > -1);
diff --git a/source/blender/makesrna/intern/rna_armature.c b/source/blender/makesrna/intern/rna_armature.c
index 1747d2fbc23..0819a5e828e 100644
--- a/source/blender/makesrna/intern/rna_armature.c
+++ b/source/blender/makesrna/intern/rna_armature.c
@@ -140,6 +140,7 @@ static void rna_Armature_update_layers(Main *bmain, Scene *UNUSED(scene), Pointe
ob->pose->proxy_layer = arm->layer;
}
+ DEG_id_tag_update(&arm->id, DEG_TAG_COPY_ON_WRITE);
WM_main_add_notifier(NC_GEOM | ND_DATA, arm);
}
@@ -239,6 +240,18 @@ static IDProperty *rna_EditBone_idprops(PointerRNA *ptr, bool create)
return ebone->prop;
}
+/* Update the layers_used variable after bones are moved between layer
+ * NOTE: Used to be done in drawing code in 2.7, but that won't work with
+ * Copy-on-Write, as drawing uses evaluated copies.
+ */
+static void rna_Armature_layer_used_refresh(bArmature *arm, ListBase *bones)
+{
+ for (Bone *bone = bones->first; bone; bone = bone->next) {
+ arm->layer_used |= bone->layer;
+ rna_Armature_layer_used_refresh(arm, &bone->childbase);
+ }
+}
+
static void rna_bone_layer_set(int *layer, const int *values)
{
int i, tot = 0;
@@ -259,8 +272,13 @@ static void rna_bone_layer_set(int *layer, const int *values)
static void rna_Bone_layer_set(PointerRNA *ptr, const int *values)
{
+ bArmature *arm = (bArmature *)ptr->id.data;
Bone *bone = (Bone *)ptr->data;
+
rna_bone_layer_set(&bone->layer, values);
+
+ arm->layer_used = 0;
+ rna_Armature_layer_used_refresh(arm, &arm->bonebase);
}
static void rna_Armature_layer_set(PointerRNA *ptr, const int *values)
diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c
index 3e1a75fdc57..258aaa3b9d2 100644
--- a/source/blender/makesrna/intern/rna_object.c
+++ b/source/blender/makesrna/intern/rna_object.c
@@ -1002,6 +1002,11 @@ static char *rna_MaterialSlot_path(PointerRNA *ptr)
* logic from check_body_type()
* */
+static char *rna_ObjectDisplay_path(PointerRNA *UNUSED(ptr))
+{
+ return BLI_strdup("display");
+}
+
static PointerRNA rna_Object_active_particle_system_get(PointerRNA *ptr)
{
Object *ob = (Object *)ptr->id.data;
@@ -1827,6 +1832,7 @@ static void rna_def_object_display(BlenderRNA *brna)
srna = RNA_def_struct(brna, "ObjectDisplay", NULL);
RNA_def_struct_ui_text(srna, "Object Display", "Object display settings for 3d viewport");
RNA_def_struct_sdna(srna, "ObjectDisplay");
+ RNA_def_struct_path_func(srna, "rna_ObjectDisplay_path");
prop = RNA_def_property(srna, "show_shadows", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", OB_SHOW_SHADOW);
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index 306c659fbf6..e8ab86c51a3 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -714,13 +714,15 @@ static const EnumPropertyItem *rna_View3DShading_studio_light_itemf(
PropertyRNA *UNUSED(prop), bool *r_free)
{
EnumPropertyItem *item = NULL;
+ EnumPropertyItem *lastitem;
int totitem = 0;
- /* XXX: add studio lights */
LISTBASE_FOREACH(StudioLight*, sl, BKE_studiolight_listbase()) {
if (totitem < NUM_STUDIO_LIGHT_ITEMS) {
RNA_enum_items_add_value(&item, &totitem, rna_enum_studio_light_items, totitem);
- item[totitem-1].icon = sl->icon_id;
+ lastitem = &item[totitem-1];
+ lastitem->icon = sl->icon_id;
+ lastitem->name = sl->name;
}
}
@@ -2587,7 +2589,6 @@ static void rna_def_space_view3d(BlenderRNA *brna)
prop = RNA_def_property(srna, "show_manipulator", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "twflag", V3D_MANIPULATOR_DRAW);
RNA_def_property_ui_text(prop, "Manipulator", "Use a 3D manipulator widget for controlling transforms");
- RNA_def_property_ui_icon(prop, ICON_MANIPUL, 0);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
prop = RNA_def_property(srna, "lock_camera_and_layers", PROP_BOOLEAN, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_ui.c b/source/blender/makesrna/intern/rna_ui.c
index bb4f6719fbc..9e868cf17e9 100644
--- a/source/blender/makesrna/intern/rna_ui.c
+++ b/source/blender/makesrna/intern/rna_ui.c
@@ -904,6 +904,16 @@ static void rna_UILayout_scale_y_set(PointerRNA *ptr, float value)
uiLayoutSetScaleY(ptr->data, value);
}
+static int rna_UILayout_emboss_get(PointerRNA *ptr)
+{
+ return uiLayoutGetEmboss(ptr->data);
+}
+
+static void rna_UILayout_emboss_set(PointerRNA *ptr, int value)
+{
+ uiLayoutSetEmboss(ptr->data, value);
+}
+
#else /* RNA_RUNTIME */
static void rna_def_ui_layout(BlenderRNA *brna)
@@ -919,6 +929,14 @@ static void rna_def_ui_layout(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
+ static const EnumPropertyItem emboss_items[] = {
+ {UI_EMBOSS, "NORMAL", 0, "Normal", "Draw standard button emboss style"},
+ {UI_EMBOSS_NONE, "NONE", 0, "None", "Draw only text and icons"},
+ {UI_EMBOSS_PULLDOWN, "PULLDOWN_MENU", 0, "Pulldown Menu", "Draw pulldown menu style"},
+ {UI_EMBOSS_RADIAL, "RADIAL_MENU", 0, "Radial Menu", "Draw radial menu style"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
/* layout */
srna = RNA_def_struct(brna, "UILayout", NULL);
@@ -956,6 +974,10 @@ static void rna_def_ui_layout(BlenderRNA *brna)
RNA_def_property_float_funcs(prop, "rna_UILayout_scale_y_get", "rna_UILayout_scale_y_set", NULL);
RNA_def_property_ui_text(prop, "Scale Y", "Scale factor along the Y for items in this (sub)layout");
RNA_api_ui_layout(srna);
+
+ prop = RNA_def_property(srna, "emboss", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, emboss_items);
+ RNA_def_property_enum_funcs(prop, "rna_UILayout_emboss_get", "rna_UILayout_emboss_set", NULL);
}
static void rna_def_panel(BlenderRNA *brna)
diff --git a/source/blender/modifiers/intern/MOD_boolean.c b/source/blender/modifiers/intern/MOD_boolean.c
index 7694265a172..ebe5aacd888 100644
--- a/source/blender/modifiers/intern/MOD_boolean.c
+++ b/source/blender/modifiers/intern/MOD_boolean.c
@@ -119,7 +119,12 @@ static Mesh *get_quick_mesh(
result = mesh_self;
}
else {
- BKE_id_copy_ex(NULL, &mesh_other->id, (ID **)&result, LIB_ID_CREATE_NO_MAIN | LIB_ID_CREATE_NO_USER_REFCOUNT | LIB_ID_CREATE_NO_DEG_TAG, false);
+ BKE_id_copy_ex(NULL, &mesh_other->id, (ID **)&result,
+ LIB_ID_CREATE_NO_MAIN |
+ LIB_ID_CREATE_NO_USER_REFCOUNT |
+ LIB_ID_CREATE_NO_DEG_TAG |
+ LIB_ID_COPY_NO_PREVIEW,
+ false);
float imat[4][4];
float omat[4][4];
diff --git a/source/blender/modifiers/intern/MOD_laplaciansmooth.c b/source/blender/modifiers/intern/MOD_laplaciansmooth.c
index 04821b01e05..59e4faee633 100644
--- a/source/blender/modifiers/intern/MOD_laplaciansmooth.c
+++ b/source/blender/modifiers/intern/MOD_laplaciansmooth.c
@@ -333,7 +333,7 @@ static void validate_solution(LaplacianSystem *sys, short flag, float lambda, fl
{
int i;
float lam;
- float vini, vend;
+ float vini = 0.0f, vend = 0.0f;
if (flag & MOD_LAPLACIANSMOOTH_PRESERVE_VOLUME) {
vini = compute_volume(sys->vert_centroid, sys->vertexCos, sys->mpoly, sys->numPolys, sys->mloop);
diff --git a/source/blender/modifiers/intern/MOD_util.c b/source/blender/modifiers/intern/MOD_util.c
index 56349f48a37..a83da188356 100644
--- a/source/blender/modifiers/intern/MOD_util.c
+++ b/source/blender/modifiers/intern/MOD_util.c
@@ -300,8 +300,9 @@ Mesh *get_mesh(
/* pass */
}
else if (ob->type == OB_MESH) {
- struct BMeshToMeshParams bmtmp = {0};
- if (em) mesh = BKE_bmesh_to_mesh_nomain(em->bm, &bmtmp);
+ if (em) {
+ mesh = BKE_bmesh_to_mesh_nomain(em->bm, &(struct BMeshToMeshParams){0});
+ }
else {
/* TODO(sybren): after modifier conversion of DM to Mesh is done, check whether
* we really need a copy here. Maybe the CoW ob->data can be directly used. */
@@ -309,7 +310,8 @@ Mesh *get_mesh(
NULL, ob->data, (ID **)&mesh,
LIB_ID_CREATE_NO_MAIN |
LIB_ID_CREATE_NO_USER_REFCOUNT |
- LIB_ID_CREATE_NO_DEG_TAG,
+ LIB_ID_CREATE_NO_DEG_TAG |
+ LIB_ID_COPY_NO_PREVIEW,
false);
}
diff --git a/source/blender/render/intern/source/pointdensity.c b/source/blender/render/intern/source/pointdensity.c
index a6350e3c448..51eaba3a054 100644
--- a/source/blender/render/intern/source/pointdensity.c
+++ b/source/blender/render/intern/source/pointdensity.c
@@ -634,9 +634,6 @@ static int pointdensity(PointDensity *pd,
texres->tin = 0.0f;
- if ((!pd) || (!pd->point_tree))
- return 0;
-
init_pointdensityrangedata(pd, &pdr, &density, vec, &age, col,
(pd->flag & TEX_PD_FALLOFF_CURVE ? pd->falloff_curve : NULL),
pd->falloff_speed_scale * 0.001f);
@@ -694,9 +691,9 @@ static int pointdensity(PointDensity *pd,
return retval;
}
-static int pointdensity_color(PointDensity *pd, TexResult *texres, float age, const float vec[3], const float col[3])
+static void pointdensity_color(PointDensity *pd, TexResult *texres, float age, const float vec[3], const float col[3])
{
- int retval = TEX_RGB;
+ texres->tr = texres->tg = texres->tb = texres->ta = 1.0f;
if (pd->source == TEX_PD_PSYS) {
float rgba[4];
@@ -733,8 +730,6 @@ static int pointdensity_color(PointDensity *pd, TexResult *texres, float age, co
break;
case TEX_PD_COLOR_CONSTANT:
default:
- texres->tr = texres->tg = texres->tb = texres->ta = 1.0f;
- retval = TEX_INT;
break;
}
}
@@ -765,13 +760,9 @@ static int pointdensity_color(PointDensity *pd, TexResult *texres, float age, co
break;
case TEX_PD_COLOR_CONSTANT:
default:
- texres->tr = texres->tg = texres->tb = texres->ta = 1.0f;
- retval = TEX_INT;
break;
}
}
-
- return retval;
}
static void sample_dummy_point_density(int resolution, float *values)
@@ -920,6 +911,10 @@ static void point_density_sample_func(
PointDensity *pd = data->pd;
float *values = data->values;
+ if (!pd || !pd->point_tree) {
+ return;
+ }
+
size_t z = (size_t)iter;
for (size_t y = 0; y < resolution; ++y) {
for (size_t x = 0; x < resolution; ++x) {
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index 4e21607d847..a154f6b83ea 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -1839,8 +1839,21 @@ static int wm_operator_tool_set_exec(bContext *C, wmOperator *op)
bToolDef tool_def = {{0}};
+ {
+ PropertyRNA *prop = RNA_struct_find_property(op->ptr, "space_type");
+ if (RNA_property_is_set(op->ptr, prop)) {
+ tool_def.spacetype = RNA_property_enum_get(op->ptr, prop);
+ }
+ else {
+ if (sa == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Space type not set");
+ return OPERATOR_CANCELLED;
+ }
+ tool_def.spacetype = sa->spacetype;
+ }
+ }
+
tool_def.index = RNA_int_get(op->ptr, "index");
- tool_def.spacetype = sa->spacetype;
RNA_string_get(op->ptr, "keymap", tool_def.keymap);
RNA_string_get(op->ptr, "manipulator_group", tool_def.manipulator_group);
RNA_string_get(op->ptr, "data_block", tool_def.data_block);
@@ -1848,7 +1861,12 @@ static int wm_operator_tool_set_exec(bContext *C, wmOperator *op)
WM_toolsystem_set(C, &tool_def);
/* For some reason redraw fails with menus (even though 'ar' isn't the menu's region). */
- ED_area_tag_redraw(sa);
+ if (sa) {
+ ED_area_tag_redraw(sa);
+ }
+ else {
+ WM_event_add_notifier(C, NC_WINDOW, NULL);
+ }
return OPERATOR_FINISHED;
}
@@ -1863,6 +1881,7 @@ static void WM_OT_tool_set(wmOperatorType *ot)
ot->flag = OPTYPE_INTERNAL;
+ RNA_def_enum(ot->srna, "space_type", rna_enum_space_type_items + 1, SPACE_EMPTY, "Space Type", "");
RNA_def_string(ot->srna, "keymap", NULL, KMAP_MAX_NAME, "Key Map", "");
RNA_def_string(ot->srna, "manipulator_group", NULL, MAX_NAME, "Manipulator Group", "");
RNA_def_string(ot->srna, "data_block", NULL, MAX_NAME, "Data Block", "");
diff --git a/source/blender/windowmanager/manipulators/WM_manipulator_api.h b/source/blender/windowmanager/manipulators/WM_manipulator_api.h
index 748cc18480f..b88956ac28d 100644
--- a/source/blender/windowmanager/manipulators/WM_manipulator_api.h
+++ b/source/blender/windowmanager/manipulators/WM_manipulator_api.h
@@ -125,8 +125,11 @@ struct WM_ManipulatorMatrixParams {
void WM_manipulator_calc_matrix_final_params(
const struct wmManipulator *mpr, const struct WM_ManipulatorMatrixParams *params,
float r_mat[4][4]);
+void WM_manipulator_calc_matrix_final_no_offset(
+ const struct wmManipulator *mpr, float r_mat[4][4]);
-void WM_manipulator_calc_matrix_final(const struct wmManipulator *mpr, float r_mat[4][4]);
+void WM_manipulator_calc_matrix_final(
+ const struct wmManipulator *mpr, float r_mat[4][4]);
/* properties */
void WM_manipulator_properties_create_ptr(struct PointerRNA *ptr, struct wmManipulatorType *wt);
diff --git a/source/blender/windowmanager/manipulators/intern/wm_manipulator.c b/source/blender/windowmanager/manipulators/intern/wm_manipulator.c
index 42232950cc4..f5a8746f807 100644
--- a/source/blender/windowmanager/manipulators/intern/wm_manipulator.c
+++ b/source/blender/windowmanager/manipulators/intern/wm_manipulator.c
@@ -598,6 +598,22 @@ void WM_manipulator_calc_matrix_final_params(
mul_m4_m4m4(r_mat, matrix_space, final_matrix);
}
+void WM_manipulator_calc_matrix_final_no_offset(const wmManipulator *mpr, float r_mat[4][4])
+{
+ float mat_identity[4][4];
+ unit_m4(mat_identity);
+
+ WM_manipulator_calc_matrix_final_params(
+ mpr,
+ &((struct WM_ManipulatorMatrixParams) {
+ .matrix_space = NULL,
+ .matrix_basis = NULL,
+ .matrix_offset = mat_identity,
+ .scale_final = NULL,
+ }), r_mat
+ );
+}
+
void WM_manipulator_calc_matrix_final(const wmManipulator *mpr, float r_mat[4][4])
{
WM_manipulator_calc_matrix_final_params(