diff options
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 Binary files differindex 68d9393ac5f..16cf71e0cbb 100644 --- a/release/datafiles/icons/ops.transform.resize.cage.dat +++ b/release/datafiles/icons/ops.transform.resize.cage.dat diff --git a/release/datafiles/icons/ops.transform.resize.dat b/release/datafiles/icons/ops.transform.resize.dat Binary files differindex fc6aa5f5c35..27bc56987d3 100644 --- a/release/datafiles/icons/ops.transform.resize.dat +++ b/release/datafiles/icons/ops.transform.resize.dat diff --git a/release/datafiles/icons/ops.transform.rotate.dat b/release/datafiles/icons/ops.transform.rotate.dat Binary files differindex bea71aab4a3..fe86eeb962d 100644 --- a/release/datafiles/icons/ops.transform.rotate.dat +++ b/release/datafiles/icons/ops.transform.rotate.dat diff --git a/release/datafiles/icons/ops.transform.transform.dat b/release/datafiles/icons/ops.transform.transform.dat Binary files differindex 2baa5634484..af455c5e38d 100644 --- a/release/datafiles/icons/ops.transform.transform.dat +++ b/release/datafiles/icons/ops.transform.transform.dat diff --git a/release/datafiles/icons/ops.transform.translate.dat b/release/datafiles/icons/ops.transform.translate.dat Binary files differindex 64e1acab958..e717ab5c993 100644 --- a/release/datafiles/icons/ops.transform.translate.dat +++ b/release/datafiles/icons/ops.transform.translate.dat 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, <_src->key->id, (ID **)<_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, <->id, (ID **)<_copy, 0, false); + BKE_id_copy_ex(bmain, <->id, (ID **)<_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, ¶ms, 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(¯optr, "release_confirm", true); - RNA_boolean_set_array(¯optr, "constraint_axis", constraint_z); + RNA_boolean_set_array(¯optr, "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(¯optr, "release_confirm", true); - RNA_boolean_set_array(¯optr, "constraint_axis", constraint_z); + RNA_boolean_set_array(¯optr, "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(¯optr, "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(¯optr, "constraint_orientation", orientation_type); + RNA_enum_set(¯optr, "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(¯optr, "value", value); - int constraint_axis[3]; RNA_boolean_get_array(op_transform->ptr, "constraint_axis", constraint_axis); - RNA_boolean_set_array(¯optr, "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(¯optr, "value", value); + RNA_boolean_set_array(¯optr, "constraint_axis", constraint_axis); + RNA_enum_set(¯optr, "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, ¯optr, 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( |