diff options
44 files changed, 941 insertions, 503 deletions
diff --git a/intern/ffmpeg/tests/ffmpeg_codecs.cc b/intern/ffmpeg/tests/ffmpeg_codecs.cc index d3cba6d228a..9538bac84d2 100644 --- a/intern/ffmpeg/tests/ffmpeg_codecs.cc +++ b/intern/ffmpeg/tests/ffmpeg_codecs.cc @@ -5,6 +5,8 @@ extern "C" { #include <libavutil/log.h> } +namespace { + bool test_vcodec(AVCodec *codec, AVPixelFormat pixelformat) { av_log_set_level(AV_LOG_QUIET); @@ -108,6 +110,8 @@ bool test_codec_audio_by_name(const char *codecname, AVSampleFormat fmt) EXPECT_TRUE(test_codec_audio_by_name(str(codec), fmt)); \ } +} // namespace + /* generic codec ID's used in blender */ FFMPEG_TEST_VCODEC_ID(AV_CODEC_ID_HUFFYUV, AV_PIX_FMT_BGRA) diff --git a/release/scripts/presets/keyconfig/keymap_data/blender_default.py b/release/scripts/presets/keyconfig/keymap_data/blender_default.py index c11350dca53..02f3d0e559e 100644 --- a/release/scripts/presets/keyconfig/keymap_data/blender_default.py +++ b/release/scripts/presets/keyconfig/keymap_data/blender_default.py @@ -6399,12 +6399,12 @@ def km_3d_view_tool_paint_gpencil_line(params): "3D View Tool: Paint Gpencil, Line", {"space_type": 'VIEW_3D', "region_type": 'WINDOW'}, {"items": [ - ("gpencil.primitive", {"type": params.tool_tweak, "value": 'ANY'}, - {"properties": [("type", 'LINE'), ("wait_for_input", False)]}), - ("gpencil.primitive", {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True}, - {"properties": [("type", 'LINE'), ("wait_for_input", False)]}), - ("gpencil.primitive", {"type": 'LEFTMOUSE', "value": 'PRESS', "alt": True}, - {"properties": [("type", 'LINE'), ("wait_for_input", False)]}), + ("gpencil.primitive_line", {"type": params.tool_tweak, "value": 'ANY'}, + {"properties": [("wait_for_input", False)]}), + ("gpencil.primitive_line", {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True}, + {"properties": [("wait_for_input", False)]}), + ("gpencil.primitive_line", {"type": 'LEFTMOUSE', "value": 'PRESS', "alt": True}, + {"properties": [("wait_for_input", False)]}), # Lasso select ("gpencil.select_lasso", {"type": params.action_tweak, "value": 'ANY', "ctrl": True, "alt": True}, None), ]}, @@ -6415,10 +6415,10 @@ def km_3d_view_tool_paint_gpencil_polyline(params): "3D View Tool: Paint Gpencil, Polyline", {"space_type": 'VIEW_3D', "region_type": 'WINDOW'}, {"items": [ - ("gpencil.primitive", {"type": params.tool_tweak, "value": 'ANY'}, - {"properties": [("type", 'POLYLINE'), ("wait_for_input", False)]}), - ("gpencil.primitive", {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True}, - {"properties": [("type", 'POLYLINE'), ("wait_for_input", False)]}), + ("gpencil.primitive_polyline", {"type": params.tool_tweak, "value": 'ANY'}, + {"properties": [("wait_for_input", False)]}), + ("gpencil.primitive_polyline", {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True}, + {"properties": [("wait_for_input", False)]}), # Lasso select ("gpencil.select_lasso", {"type": params.action_tweak, "value": 'ANY', "ctrl": True, "alt": True}, None), ]}, @@ -6429,12 +6429,12 @@ def km_3d_view_tool_paint_gpencil_box(params): "3D View Tool: Paint Gpencil, Box", {"space_type": 'VIEW_3D', "region_type": 'WINDOW'}, {"items": [ - ("gpencil.primitive", {"type": params.tool_tweak, "value": 'ANY'}, - {"properties": [("type", 'BOX'), ("wait_for_input", False)]}), - ("gpencil.primitive", {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True}, - {"properties": [("type", 'BOX'), ("wait_for_input", False)]}), - ("gpencil.primitive", {"type": 'LEFTMOUSE', "value": 'PRESS', "alt": True}, - {"properties": [("type", 'BOX'), ("wait_for_input", False)]}), + ("gpencil.primitive_box", {"type": params.tool_tweak, "value": 'ANY'}, + {"properties": [("wait_for_input", False)]}), + ("gpencil.primitive_box", {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True}, + {"properties": [("wait_for_input", False)]}), + ("gpencil.primitive_box", {"type": 'LEFTMOUSE', "value": 'PRESS', "alt": True}, + {"properties": [("wait_for_input", False)]}), # Lasso select ("gpencil.select_lasso", {"type": params.action_tweak, "value": 'ANY', "ctrl": True, "alt": True}, None), ]}, @@ -6446,12 +6446,12 @@ def km_3d_view_tool_paint_gpencil_circle(params): "3D View Tool: Paint Gpencil, Circle", {"space_type": 'VIEW_3D', "region_type": 'WINDOW'}, {"items": [ - ("gpencil.primitive", {"type": params.tool_tweak, "value": 'ANY'}, - {"properties": [("type", 'CIRCLE'), ("wait_for_input", False)]}), - ("gpencil.primitive", {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True}, - {"properties": [("type", 'CIRCLE'), ("wait_for_input", False)]}), - ("gpencil.primitive", {"type": 'LEFTMOUSE', "value": 'PRESS', "alt": True}, - {"properties": [("type", 'CIRCLE'), ("wait_for_input", False)]}), + ("gpencil.primitive_circle", {"type": params.tool_tweak, "value": 'ANY'}, + {"properties": [("wait_for_input", False)]}), + ("gpencil.primitive_circle", {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True}, + {"properties": [("wait_for_input", False)]}), + ("gpencil.primitive_circle", {"type": 'LEFTMOUSE', "value": 'PRESS', "alt": True}, + {"properties": [("wait_for_input", False)]}), # Lasso select ("gpencil.select_lasso", {"type": params.action_tweak, "value": 'ANY', "ctrl": True, "alt": True}, None), ]}, @@ -6463,12 +6463,12 @@ def km_3d_view_tool_paint_gpencil_arc(params): "3D View Tool: Paint Gpencil, Arc", {"space_type": 'VIEW_3D', "region_type": 'WINDOW'}, {"items": [ - ("gpencil.primitive", {"type": params.tool_tweak, "value": 'ANY'}, - {"properties": [("type", 'ARC'), ("wait_for_input", False)]}), - ("gpencil.primitive", {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True}, + ("gpencil.primitive_curve", {"type": params.tool_tweak, "value": 'ANY'}, {"properties": [("type", 'ARC'), ("wait_for_input", False)]}), - ("gpencil.primitive", {"type": 'LEFTMOUSE', "value": 'PRESS', "alt": True}, + ("gpencil.primitive_curve", {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True}, {"properties": [("type", 'ARC'), ("wait_for_input", False)]}), + ("gpencil.primitive_curve", {"type": 'LEFTMOUSE', "value": 'PRESS', "alt": True}, + {"properties": [("type",'ARC'), ("wait_for_input", False)]}), # Lasso select ("gpencil.select_lasso", {"type": params.action_tweak, "value": 'ANY', "ctrl": True, "alt": True}, None), ]}, @@ -6480,7 +6480,7 @@ def km_3d_view_tool_paint_gpencil_curve(params): "3D View Tool: Paint Gpencil, Curve", {"space_type": 'VIEW_3D', "region_type": 'WINDOW'}, {"items": [ - ("gpencil.primitive", {"type": params.tool_tweak, "value": 'ANY'}, + ("gpencil.primitive_curve", {"type": params.tool_tweak, "value": 'ANY'}, {"properties": [("type", 'CURVE'), ("wait_for_input", False)]}), # Lasso select ("gpencil.select_lasso", {"type": params.action_tweak, "value": 'ANY', "ctrl": True, "alt": True}, None), diff --git a/release/scripts/startup/bl_ui/properties_paint_common.py b/release/scripts/startup/bl_ui/properties_paint_common.py index f1004358418..397ce5d0324 100644 --- a/release/scripts/startup/bl_ui/properties_paint_common.py +++ b/release/scripts/startup/bl_ui/properties_paint_common.py @@ -1109,6 +1109,45 @@ def brush_basic_texpaint_settings(layout, context, brush, *, compact=False): header=True ) +def brush_basic__draw_color_selector(context, layout, brush, gp_settings, props): + tool_settings = context.scene.tool_settings + settings = tool_settings.gpencil_paint + ma = gp_settings.material + + row = layout.row(align=True) + if not gp_settings.use_material_pin: + ma = context.object.active_material + icon_id = 0 + if ma: + icon_id = ma.id_data.preview.icon_id + txt_ma = ma.name + maxw = 25 + if len(txt_ma) > maxw: + txt_ma = txt_ma[:maxw - 5] + '..' + txt_ma[-3:] + else: + txt_ma = "" + + sub = row.row() + sub.ui_units_x = 8 + sub.popover( + panel="TOPBAR_PT_gpencil_materials", + text=txt_ma, + icon_value=icon_id, + ) + + row.prop(gp_settings, "use_material_pin", text="") + + if brush.gpencil_tool in {'DRAW', 'FILL'}: + row.separator(factor=1.0) + row.prop_enum(settings, "color_mode", 'MATERIAL', text="", icon='MATERIAL') + row.prop_enum(settings, "color_mode", 'VERTEXCOLOR', text="", icon='VPAINT_HLT') + sub_row = row.row(align=True) + sub_row.enabled = settings.color_mode == 'VERTEXCOLOR' + sub_row.prop_with_popover(brush, "color", text="", panel="TOPBAR_PT_gpencil_vertexcolor") + + if props: + row = layout.row(align=True) + row.prop(props, "subdivision") def brush_basic_gpencil_paint_settings(layout, context, brush, *, compact=False): tool_settings = context.tool_settings diff --git a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py index d07241203fb..ae144d9e8d0 100644 --- a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py +++ b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py @@ -1671,6 +1671,29 @@ class _defs_image_uv_sculpt: class _defs_gpencil_paint: @staticmethod + def gpencil_primitive_toolbar(context, layout, tool, props): + paint = context.tool_settings.gpencil_paint + brush = paint.brush + + if brush is None: + return False + + gp_settings = brush.gpencil_settings + + row = layout.row(align=True) + tool_settings = context.scene.tool_settings + settings = tool_settings.gpencil_paint + row.template_ID_preview(settings, "brush", rows=3, cols=8, hide_buttons=True) + + from bl_ui.properties_paint_common import ( + brush_basic_gpencil_paint_settings, + brush_basic__draw_color_selector, + ) + + brush_basic__draw_color_selector(context, layout, brush, gp_settings, props) + brush_basic_gpencil_paint_settings(layout, context, brush, compact=True) + + @staticmethod def generate_from_brushes(context): return generate_from_enum_ex( context, @@ -1697,6 +1720,10 @@ class _defs_gpencil_paint: @ToolDef.from_fn def line(): + def draw_settings(context, layout, tool): + props = tool.operator_properties("gpencil.primitive_line") + _defs_gpencil_paint.gpencil_primitive_toolbar(context, layout, tool, props) + return dict( idname="builtin.line", label="Line", @@ -1704,10 +1731,15 @@ class _defs_gpencil_paint: cursor='CROSSHAIR', widget=None, keymap=(), + draw_settings=draw_settings, ) @ToolDef.from_fn def polyline(): + def draw_settings(context, layout, tool): + props = tool.operator_properties("gpencil.primitive_polyline") + _defs_gpencil_paint.gpencil_primitive_toolbar(context, layout, tool, props) + return dict( idname="builtin.polyline", label="Polyline", @@ -1715,10 +1747,15 @@ class _defs_gpencil_paint: cursor='CROSSHAIR', widget=None, keymap=(), + draw_settings=draw_settings, ) @ToolDef.from_fn def box(): + def draw_settings(context, layout, tool): + props = tool.operator_properties("gpencil.primitive_box") + _defs_gpencil_paint.gpencil_primitive_toolbar(context, layout, tool, props) + return dict( idname="builtin.box", label="Box", @@ -1726,10 +1763,15 @@ class _defs_gpencil_paint: cursor='CROSSHAIR', widget=None, keymap=(), + draw_settings=draw_settings, ) @ToolDef.from_fn def circle(): + def draw_settings(context, layout, tool): + props = tool.operator_properties("gpencil.primitive_circle") + _defs_gpencil_paint.gpencil_primitive_toolbar(context, layout, tool, props) + return dict( idname="builtin.circle", label="Circle", @@ -1737,10 +1779,15 @@ class _defs_gpencil_paint: cursor='CROSSHAIR', widget=None, keymap=(), + draw_settings=draw_settings, ) @ToolDef.from_fn def arc(): + def draw_settings(context, layout, tool): + props = tool.operator_properties("gpencil.primitive_curve") + _defs_gpencil_paint.gpencil_primitive_toolbar(context, layout, tool, props) + return dict( idname="builtin.arc", label="Arc", @@ -1748,10 +1795,15 @@ class _defs_gpencil_paint: cursor='CROSSHAIR', widget=None, keymap=(), + draw_settings=draw_settings, ) @ToolDef.from_fn def curve(): + def draw_settings(context, layout, tool): + props = tool.operator_properties("gpencil.primitive_curve") + _defs_gpencil_paint.gpencil_primitive_toolbar(context, layout, tool, props) + return dict( idname="builtin.curve", label="Curve", @@ -1759,6 +1811,7 @@ class _defs_gpencil_paint: cursor='CROSSHAIR', widget=None, keymap=(), + draw_settings=draw_settings, ) @ToolDef.from_fn diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index 7c9f632dcd2..321c3814dba 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -385,19 +385,7 @@ class _draw_tool_settings_context_mode: if tool is None: return False - # is_paint = True - # FIXME: tools must use their own UI drawing! - if tool.idname in { - "builtin.line", - "builtin.box", - "builtin.circle", - "builtin.arc", - "builtin.curve", - "builtin.polyline", - }: - # is_paint = False - pass - elif tool.idname == "builtin.cutter": + if tool.idname == "builtin.cutter": row = layout.row(align=True) row.prop(context.tool_settings.gpencil_sculpt, "intersection_threshold") return False @@ -411,47 +399,16 @@ class _draw_tool_settings_context_mode: gp_settings = brush.gpencil_settings - def draw_color_selector(): - ma = gp_settings.material - row = layout.row(align=True) - if not gp_settings.use_material_pin: - ma = context.object.active_material - icon_id = 0 - if ma: - icon_id = ma.id_data.preview.icon_id - txt_ma = ma.name - maxw = 25 - if len(txt_ma) > maxw: - txt_ma = txt_ma[:maxw - 5] + '..' + txt_ma[-3:] - else: - txt_ma = "" - - sub = row.row() - sub.ui_units_x = 8 - sub.popover( - panel="TOPBAR_PT_gpencil_materials", - text=txt_ma, - icon_value=icon_id, - ) - - row.prop(gp_settings, "use_material_pin", text="") - - if brush.gpencil_tool in {'DRAW', 'FILL'}: - row.separator(factor=1.0) - subrow = row.row(align=True) - row.prop_enum(settings, "color_mode", 'MATERIAL', text="", icon='MATERIAL') - row.prop_enum(settings, "color_mode", 'VERTEXCOLOR', text="", icon='VPAINT_HLT') - sub_row = row.row(align=True) - sub_row.enabled = settings.color_mode == 'VERTEXCOLOR' - sub_row.prop_with_popover(brush, "color", text="", panel="TOPBAR_PT_gpencil_vertexcolor") - row = layout.row(align=True) tool_settings = context.scene.tool_settings settings = tool_settings.gpencil_paint row.template_ID_preview(settings, "brush", rows=3, cols=8, hide_buttons=True) if context.object and brush.gpencil_tool in {'FILL', 'DRAW'}: - draw_color_selector() + from bl_ui.properties_paint_common import ( + brush_basic__draw_color_selector, + ) + brush_basic__draw_color_selector(context, layout, brush, gp_settings, None) if context.object and brush.gpencil_tool == 'TINT': row.separator(factor=0.4) diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h index f9590696c2e..98dc411239e 100644 --- a/source/blender/blenkernel/BKE_modifier.h +++ b/source/blender/blenkernel/BKE_modifier.h @@ -413,9 +413,13 @@ void BKE_modifier_type_panel_id(ModifierType type, char *r_idname); * default values if pointer is optional. */ struct ModifierData *BKE_modifier_new(int type); + void BKE_modifier_free_ex(struct ModifierData *md, const int flag); void BKE_modifier_free(struct ModifierData *md); +/* Generate new UUID for the given modifier. */ +void BKE_modifier_session_uuid_generate(struct ModifierData *md); + bool BKE_modifier_unique_name(struct ListBase *modifiers, struct ModifierData *md); void BKE_modifier_copydata_generic(const struct ModifierData *md, @@ -539,6 +543,8 @@ void BKE_modifier_deform_vertsEM(ModifierData *md, struct Mesh *BKE_modifier_get_evaluated_mesh_from_evaluated_object(struct Object *ob_eval, const bool get_cage_mesh); +void BKE_modifier_check_uuids_unique_and_report(const struct Object *object); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index 215f4043e34..2029f4d38a1 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -409,6 +409,8 @@ struct Mesh *BKE_object_to_mesh(struct Depsgraph *depsgraph, void BKE_object_to_mesh_clear(struct Object *object); +void BKE_object_check_uuids_unique_and_report(const struct Object *object); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/intern/data_transfer.c b/source/blender/blenkernel/intern/data_transfer.c index 179f2f44180..1b35fdd1706 100644 --- a/source/blender/blenkernel/intern/data_transfer.c +++ b/source/blender/blenkernel/intern/data_transfer.c @@ -1572,7 +1572,7 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph, space_transform)) { CustomDataTransferLayerMap *lay_mapit; - changed = (lay_map.first != NULL); + changed |= (lay_map.first != NULL); for (lay_mapit = lay_map.first; lay_mapit; lay_mapit = lay_mapit->next) { CustomData_data_transfer(&geom_map[VDATA], lay_mapit); @@ -1650,7 +1650,7 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph, space_transform)) { CustomDataTransferLayerMap *lay_mapit; - changed = (lay_map.first != NULL); + changed |= (lay_map.first != NULL); for (lay_mapit = lay_map.first; lay_mapit; lay_mapit = lay_mapit->next) { CustomData_data_transfer(&geom_map[EDATA], lay_mapit); @@ -1746,7 +1746,7 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph, space_transform)) { CustomDataTransferLayerMap *lay_mapit; - changed = (lay_map.first != NULL); + changed |= (lay_map.first != NULL); for (lay_mapit = lay_map.first; lay_mapit; lay_mapit = lay_mapit->next) { CustomData_data_transfer(&geom_map[LDATA], lay_mapit); @@ -1837,7 +1837,7 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph, space_transform)) { CustomDataTransferLayerMap *lay_mapit; - changed = (lay_map.first != NULL); + changed |= (lay_map.first != NULL); for (lay_mapit = lay_map.first; lay_mapit; lay_mapit = lay_mapit->next) { CustomData_data_transfer(&geom_map[PDATA], lay_mapit); diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index fccc4380fec..2a16d0eb0f8 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -95,7 +95,15 @@ static void mesh_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int /* This is a direct copy of a main mesh, so for now it has the same topology. */ mesh_dst->runtime.deformed_only = true; } - /* XXX WHAT? Why? Comment, please! And pretty sure this is not valid for regular Mesh copying? */ + /* This option is set for run-time meshes that have been copied from the current objects mode. + * Currently this is used for edit-mesh although it could be used for sculpt or other + * kinds of data specific to an objects mode. + * + * The flag signals that the mesh hasn't been modified from the data that generated it, + * allowing us to use the object-mode data for drawing. + * + * While this could be the callers responsibility, keep here since it's + * highly unlikely we want to create a duplicate and not use it for drawing. */ mesh_dst->runtime.is_original = false; /* Only do tessface if we have no polys. */ diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 5789e0f0557..afd02d7001e 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -41,6 +41,7 @@ #include "BLI_linklist.h" #include "BLI_listbase.h" #include "BLI_path_util.h" +#include "BLI_session_uuid.h" #include "BLI_string.h" #include "BLI_string_utils.h" #include "BLI_utildefines.h" @@ -150,6 +151,8 @@ ModifierData *BKE_modifier_new(int type) mti->initData(md); } + BKE_modifier_session_uuid_generate(md); + return md; } @@ -192,6 +195,11 @@ void BKE_modifier_free(ModifierData *md) BKE_modifier_free_ex(md, 0); } +void BKE_modifier_session_uuid_generate(ModifierData *md) +{ + md->session_uuid = BLI_session_uuid_generate(); +} + bool BKE_modifier_unique_name(ListBase *modifiers, ModifierData *md) { if (modifiers && md) { @@ -368,6 +376,17 @@ void BKE_modifier_copydata_ex(ModifierData *md, ModifierData *target, const int mti->foreachObjectLink(target, NULL, (ObjectWalkFunc)modifier_copy_data_id_us_cb, NULL); } } + + if (flag & LIB_ID_CREATE_NO_MAIN) { + /* Make sure UUID is the same between the source and the target. + * This is needed in the cases when UUID is to be preserved and when there is no copyData + * callback, or the copyData does not do full byte copy of the modifier data. */ + target->session_uuid = md->session_uuid; + } + else { + /* In the case copyData made full byte copy force UUID to be re-generated. */ + BKE_modifier_session_uuid_generate(md); + } } void BKE_modifier_copydata(ModifierData *md, ModifierData *target) @@ -1071,3 +1090,26 @@ struct ModifierData *BKE_modifier_get_evaluated(Depsgraph *depsgraph, } return BKE_modifiers_findby_name(object_eval, md->name); } + +void BKE_modifier_check_uuids_unique_and_report(const Object *object) +{ + struct GSet *used_uuids = BLI_gset_new( + BLI_session_uuid_ghash_hash, BLI_session_uuid_ghash_compare, "modifier used uuids"); + + LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) { + const SessionUUID *session_uuid = &md->session_uuid; + if (!BLI_session_uuid_is_generated(session_uuid)) { + printf("Modifier %s -> %s does not have UUID generated.\n", object->id.name + 2, md->name); + continue; + } + + if (BLI_gset_lookup(used_uuids, session_uuid) != NULL) { + printf("Modifier %s -> %s has duplicate UUID generated.\n", object->id.name + 2, md->name); + continue; + } + + BLI_gset_insert(used_uuids, (void *)session_uuid); + } + + BLI_gset_free(used_uuids, NULL); +} diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 024e60ea989..31420b3adc6 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -4714,3 +4714,9 @@ void BKE_object_to_mesh_clear(Object *object) BKE_id_free(NULL, object->runtime.object_as_temp_mesh); object->runtime.object_as_temp_mesh = NULL; } + +void BKE_object_check_uuids_unique_and_report(const Object *object) +{ + BKE_pose_check_uuids_unique_and_report(object->pose); + BKE_modifier_check_uuids_unique_and_report(object); +} diff --git a/source/blender/blenkernel/intern/object_dupli.c b/source/blender/blenkernel/intern/object_dupli.c index 553cff33fbb..897398b73d5 100644 --- a/source/blender/blenkernel/intern/object_dupli.c +++ b/source/blender/blenkernel/intern/object_dupli.c @@ -30,6 +30,7 @@ #include "BLI_listbase.h" #include "BLI_string_utf8.h" +#include "BLI_alloca.h" #include "BLI_math.h" #include "BLI_rand.h" @@ -44,6 +45,7 @@ #include "BKE_collection.h" #include "BKE_duplilist.h" #include "BKE_editmesh.h" +#include "BKE_editmesh_cache.h" #include "BKE_font.h" #include "BKE_global.h" #include "BKE_idprop.h" @@ -301,6 +303,55 @@ static void make_child_duplis(const DupliContext *ctx, /** \} */ /* -------------------------------------------------------------------- */ +/** \name Internal Data Access Utilities + * \{ */ + +static Mesh *mesh_data_from_duplicator_object(Object *ob, + BMEditMesh **r_em, + const float (**r_vert_coords)[3], + const float (**r_vert_normals)[3]) +{ + /* Gather mesh info. */ + BMEditMesh *em = BKE_editmesh_from_object(ob); + Mesh *me_eval; + + *r_em = NULL; + *r_vert_coords = NULL; + if (r_vert_normals != NULL) { + *r_vert_normals = NULL; + } + + /* We do not need any render-specific handling anymore, depsgraph takes care of that. */ + /* NOTE: Do direct access to the evaluated mesh: this function is used + * during meta balls evaluation. But even without those all the objects + * which are needed for correct instancing are already evaluated. */ + if (em != NULL) { + /* Note that this will only show deformation if #eModifierMode_OnCage is enabled. + * We could change this but it matches 2.7x behavior. */ + me_eval = em->mesh_eval_cage; + if ((me_eval == NULL) || (me_eval->runtime.wrapper_type == ME_WRAPPER_TYPE_BMESH)) { + *r_em = em; + if (me_eval != NULL) { + EditMeshData *emd = me_eval->runtime.edit_data; + if ((emd != NULL) && (emd->vertexCos != NULL)) { + *r_vert_coords = emd->vertexCos; + if (r_vert_normals != NULL) { + BKE_editmesh_cache_ensure_vert_normals(em, emd); + *r_vert_normals = emd->vertexNos; + } + } + } + } + } + else { + me_eval = BKE_object_get_evaluated_mesh(ob); + } + return me_eval; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ /** \name Dupli-Collection Implementation (#OB_DUPLICOLLECTION) * \{ */ @@ -349,120 +400,178 @@ static const DupliGenerator gen_dupli_collection = { /** \name Dupli-Vertices Implementation (#OB_DUPLIVERTS for Geometry) * \{ */ -typedef struct VertexDupliData { +typedef struct VertexDupliData_Mesh { Mesh *me_eval; - BMEditMesh *edit_mesh; + int totvert; + MVert *mvert; + float (*orco)[3]; + bool use_rotation; +} VertexDupliData_Mesh; - const DupliContext *ctx; - Object *inst_ob; /* object to instantiate (argument for vertex map callback) */ - float child_imat[4][4]; -} VertexDupliData; +typedef struct VertexDupliData_BMesh { + BMEditMesh *em; + + /* Can be NULL. */ + const float (*vert_coords)[3]; + const float (*vert_normals)[3]; + + bool has_orco; + bool use_rotation; +} VertexDupliData_BMesh; static void get_duplivert_transform(const float co[3], - const short no[3], - bool use_rotation, + const float no[3], + const bool use_rotation, short axis, short upflag, - float mat[4][4]) + float r_mat[4][4]) { float quat[4]; const float size[3] = {1.0f, 1.0f, 1.0f}; if (use_rotation) { - /* construct rotation matrix from normals */ - float nor_f[3]; - nor_f[0] = (float)-no[0]; - nor_f[1] = (float)-no[1]; - nor_f[2] = (float)-no[2]; - vec_to_quat(quat, nor_f, axis, upflag); + /* Construct rotation matrix from normals. */ + float no_flip[3]; + negate_v3_v3(no_flip, no); + vec_to_quat(quat, no_flip, axis, upflag); } else { unit_qt(quat); } - loc_quat_size_to_mat4(mat, co, quat, size); + loc_quat_size_to_mat4(r_mat, co, quat, size); } -static void vertex_dupli(const VertexDupliData *vdd, - int index, - const float co[3], - const short no[3]) +/** + * \param no: The direction, doesn't need to be normalized. + */ +static DupliObject *vertex_dupli(const DupliContext *ctx, + Object *child, + const float child_imat[4][4], + int index, + float space_mat[4][4]) { - Object *inst_ob = vdd->inst_ob; - DupliObject *dob; - float obmat[4][4], space_mat[4][4]; + float obmat[4][4]; - /* space_mat is transform to vertex */ - get_duplivert_transform( - co, no, vdd->use_rotation, inst_ob->trackflag, inst_ob->upflag, space_mat); - /* make offset relative to inst_ob using relative child transform */ - mul_mat3_m4_v3((float(*)[4])vdd->child_imat, space_mat[3]); - /* apply obmat _after_ the local vertex transform */ - mul_m4_m4m4(obmat, inst_ob->obmat, space_mat); + /* Make offset relative to child using relative child transform. */ + mul_mat3_m4_v3(child_imat, space_mat[3]); - dob = make_dupli(vdd->ctx, vdd->inst_ob, obmat, index); + /* Apply `obmat` _after_ the local vertex transform. */ + mul_m4_m4m4(obmat, child->obmat, space_mat); - if (vdd->orco) { - copy_v3_v3(dob->orco, vdd->orco[index]); - } + DupliObject *dob = make_dupli(ctx, child, obmat, index); + + /* Recursion. */ + make_recursive_duplis(ctx, child, space_mat, index); - /* recursion */ - make_recursive_duplis(vdd->ctx, vdd->inst_ob, space_mat, index); + return dob; } -static void make_child_duplis_verts(const DupliContext *ctx, void *userdata, Object *child) +static void make_child_duplis_verts_from_mesh(const DupliContext *ctx, + void *userdata, + Object *child) { - VertexDupliData *vdd = userdata; - Mesh *me_eval = vdd->me_eval; + VertexDupliData_Mesh *vdd = userdata; + + const MVert *mvert = vdd->mvert; + const int totvert = vdd->totvert; - vdd->inst_ob = child; invert_m4_m4(child->imat, child->obmat); - /* relative transform from parent to child space */ - mul_m4_m4m4(vdd->child_imat, child->imat, ctx->object->obmat); + /* Relative transform from parent to child space. */ + float child_imat[4][4]; + mul_m4_m4m4(child_imat, child->imat, ctx->object->obmat); - const MVert *mvert = me_eval->mvert; - for (int i = 0; i < me_eval->totvert; i++) { - vertex_dupli(vdd, i, mvert[i].co, mvert[i].no); + const MVert *mv = mvert; + for (int i = 0; i < totvert; i++, mv++) { + const float no[3] = {mv->no[0], mv->no[1], mv->no[2]}; + /* space_mat is transform to vertex. */ + float space_mat[4][4]; + get_duplivert_transform( + mv->co, no, vdd->use_rotation, child->trackflag, child->upflag, space_mat); + DupliObject *dob = vertex_dupli(ctx, child, child_imat, i, space_mat); + if (vdd->orco) { + copy_v3_v3(dob->orco, vdd->orco[i]); + } } } -static void make_duplis_verts(const DupliContext *ctx) +static void make_child_duplis_verts_from_bmesh(const DupliContext *ctx, + void *userdata, + Object *child) { - Object *parent = ctx->object; - VertexDupliData vdd; + VertexDupliData_BMesh *vdd = userdata; + BMEditMesh *em = vdd->em; - vdd.ctx = ctx; - vdd.use_rotation = parent->transflag & OB_DUPLIROT; + invert_m4_m4(child->imat, child->obmat); + /* Relative transform from parent to child space. */ + float child_imat[4][4]; + mul_m4_m4m4(child_imat, child->imat, ctx->object->obmat); - /* gather mesh info */ - { - vdd.edit_mesh = BKE_editmesh_from_object(parent); - - /* We do not need any render-specific handling anymore, depsgraph takes care of that. */ - /* NOTE: Do direct access to the evaluated mesh: this function is used - * during meta balls evaluation. But even without those all the objects - * which are needed for correct instancing are already evaluated. */ - if (vdd.edit_mesh != NULL) { - vdd.me_eval = vdd.edit_mesh->mesh_eval_cage; + BMVert *v; + BMIter iter; + int i; + + const float(*vert_coords)[3] = vdd->vert_coords; + const float(*vert_normals)[3] = vdd->vert_normals; + + BM_ITER_MESH_INDEX (v, &iter, em->bm, BM_VERTS_OF_MESH, i) { + const float *co, *no; + if (vert_coords != NULL) { + co = vert_coords[i]; + no = vert_normals[i]; } else { - vdd.me_eval = BKE_object_get_evaluated_mesh(parent); + co = v->co; + no = v->no; } - if (vdd.me_eval == NULL) { - return; + /* space_mat is transform to vertex. */ + float space_mat[4][4]; + get_duplivert_transform(co, no, vdd->use_rotation, child->trackflag, child->upflag, space_mat); + DupliObject *dob = vertex_dupli(ctx, child, child_imat, i, space_mat); + if (vdd->has_orco) { + copy_v3_v3(dob->orco, v->co); } - - vdd.orco = CustomData_get_layer(&vdd.me_eval->vdata, CD_ORCO); - vdd.totvert = vdd.me_eval->totvert; } +} + +static void make_duplis_verts(const DupliContext *ctx) +{ + Object *parent = ctx->object; - make_child_duplis(ctx, &vdd, make_child_duplis_verts); + const bool use_rotation = parent->transflag & OB_DUPLIROT; - vdd.me_eval = NULL; + /* Gather mesh info. */ + BMEditMesh *em = NULL; + const float(*vert_coords)[3] = NULL; + const float(*vert_normals)[3] = NULL; + Mesh *me_eval = mesh_data_from_duplicator_object(parent, &em, &vert_coords, &vert_normals); + if (em == NULL && me_eval == NULL) { + return; + } + + if (em != NULL) { + VertexDupliData_BMesh vdd = { + .em = em, + .vert_coords = vert_coords, + .vert_normals = vert_normals, + .has_orco = (vert_coords != NULL), + .use_rotation = use_rotation, + }; + make_child_duplis(ctx, &vdd, make_child_duplis_verts_from_bmesh); + } + else { + VertexDupliData_Mesh vdd = { + .use_rotation = use_rotation, + }; + vdd.orco = CustomData_get_layer(&me_eval->vdata, CD_ORCO); + vdd.totvert = me_eval->totvert; + vdd.mvert = me_eval->mvert; + make_child_duplis(ctx, &vdd, make_child_duplis_verts_from_mesh); + } } static const DupliGenerator gen_dupli_verts = { @@ -670,37 +779,55 @@ static const DupliGenerator gen_dupli_verts_pointcloud = { /** \name Dupli-Faces Implementation (#OB_DUPLIFACES) * \{ */ -typedef struct FaceDupliData { +typedef struct FaceDupliData_Mesh { Mesh *me_eval; + int totface; MPoly *mpoly; MLoop *mloop; MVert *mvert; + float (*orco)[3]; MLoopUV *mloopuv; bool use_scale; -} FaceDupliData; +} FaceDupliData_Mesh; + +typedef struct FaceDupliData_BMesh { + BMEditMesh *em; -static void get_dupliface_transform( - MPoly *mpoly, MLoop *mloop, MVert *mvert, bool use_scale, float scale_fac, float mat[4][4]) + bool has_orco, has_uvs; + int cd_loop_uv_offset; + /* Can be NULL. */ + const float (*vert_coords)[3]; + bool use_scale; +} FaceDupliData_BMesh; + +static void get_dupliface_transform_from_coords(const float coords[][3], + const int coords_len, + const bool use_scale, + const float scale_fac, + float r_mat[4][4]) { float loc[3], quat[4], scale, size[3]; - float f_no[3]; /* location */ - BKE_mesh_calc_poly_center(mpoly, mloop, mvert, loc); + { + const float w = 1.0f / (float)coords_len; + zero_v3(loc); + for (int i = 0; i < coords_len; i++) { + madd_v3_v3fl(loc, coords[i], w); + } + } /* rotation */ { - const float *v1, *v2, *v3; - BKE_mesh_calc_poly_normal(mpoly, mloop, mvert, f_no); - v1 = mvert[mloop[0].v].co; - v2 = mvert[mloop[1].v].co; - v3 = mvert[mloop[2].v].co; - tri_to_quat_ex(quat, v1, v2, v3, f_no); + float f_no[3]; + cross_poly_v3(f_no, coords, (uint)coords_len); + normalize_v3(f_no); + tri_to_quat_ex(quat, coords[0], coords[1], coords[2], f_no); } /* scale */ if (use_scale) { - float area = BKE_mesh_calc_poly_area(mpoly, mloop, mvert); + const float area = area_poly_v3(coords, (uint)coords_len); scale = sqrtf(area) * scale_fac; } else { @@ -708,58 +835,108 @@ static void get_dupliface_transform( } size[0] = size[1] = size[2] = scale; - loc_quat_size_to_mat4(mat, loc, quat, size); + loc_quat_size_to_mat4(r_mat, loc, quat, size); } -static void make_child_duplis_faces(const DupliContext *ctx, void *userdata, Object *inst_ob) +static void get_dupliface_transform_from_mesh(const MPoly *mpoly, + const MLoop *mloopstart, + const MVert *mvert, + const bool use_scale, + const float scale_fac, + float r_mat[4][4]) { - FaceDupliData *fdd = userdata; - MPoly *mpoly = fdd->mpoly, *mp; - MLoop *mloop = fdd->mloop; - MVert *mvert = fdd->mvert; - float(*orco)[3] = fdd->orco; - MLoopUV *mloopuv = fdd->mloopuv; - int a, totface = fdd->totface; - float child_imat[4][4]; - DupliObject *dob; + const MLoop *l_iter = mloopstart; + float(*coords)[3] = BLI_array_alloca(coords, (size_t)mpoly->totloop); + for (int i = 0; i < mpoly->totloop; i++, l_iter++) { + copy_v3_v3(coords[i], mvert[l_iter->v].co); + } + get_dupliface_transform_from_coords(coords, mpoly->totloop, use_scale, scale_fac, r_mat); +} - invert_m4_m4(inst_ob->imat, inst_ob->obmat); - /* relative transform from parent to child space */ - mul_m4_m4m4(child_imat, inst_ob->imat, ctx->object->obmat); +static void get_dupliface_transform_from_bmesh(BMFace *f, + const float (*vert_coords)[3], + const bool use_scale, + const float scale_fac, + float r_mat[4][4]) +{ + BMLoop *l_first, *l_iter; + float(*coords)[3] = BLI_array_alloca(coords, (size_t)f->len); + int i = 0; + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + if (vert_coords != NULL) { + do { + copy_v3_v3(coords[i], vert_coords[BM_elem_index_get(l_iter->v)]); + } while ((void)(i++), (l_iter = l_iter->next) != l_first); + } + else { + do { + copy_v3_v3(coords[i], l_iter->v->co); + } while ((void)(i++), (l_iter = l_iter->next) != l_first); + } + get_dupliface_transform_from_coords(coords, f->len, use_scale, scale_fac, r_mat); +} - for (a = 0, mp = mpoly; a < totface; a++, mp++) { - MLoop *loopstart = mloop + mp->loopstart; - float space_mat[4][4], obmat[4][4]; +static DupliObject *face_dupli(const DupliContext *ctx, + Object *child, + const float child_imat[4][4], + const int index, + float obmat[4][4]) +{ + float space_mat[4][4]; - if (UNLIKELY(mp->totloop < 3)) { - continue; - } + /* Make offset relative to child using relative child transform. */ + mul_mat3_m4_v3(child_imat, obmat[3]); - /* obmat is transform to face */ - get_dupliface_transform( - mp, loopstart, mvert, fdd->use_scale, ctx->object->instance_faces_scale, obmat); - /* make offset relative to inst_ob using relative child transform */ - mul_mat3_m4_v3(child_imat, obmat[3]); - - /* XXX ugly hack to ensure same behavior as in master - * this should not be needed, parentinv is not consistent - * outside of parenting. - */ - { - float imat[3][3]; - copy_m3_m4(imat, inst_ob->parentinv); - mul_m4_m3m4(obmat, imat, obmat); - } + /* XXX ugly hack to ensure same behavior as in master this should not be needed, + * #Object.parentinv is not consistent outside of parenting. */ + { + float imat[3][3]; + copy_m3_m4(imat, child->parentinv); + mul_m4_m3m4(obmat, imat, obmat); + } + + /* Apply `obmat` _after_ the local face transform. */ + mul_m4_m4m4(obmat, child->obmat, obmat); + + /* Space matrix is constructed by removing \a obmat transform, + * this yields the world-space transform for recursive duplis. */ + mul_m4_m4m4(space_mat, obmat, child->imat); + + DupliObject *dob = make_dupli(ctx, child, obmat, index); + + /* Recursion. */ + make_recursive_duplis(ctx, child, space_mat, index); + + return dob; +} + +static void make_child_duplis_faces_from_mesh(const DupliContext *ctx, + void *userdata, + Object *child) +{ + FaceDupliData_Mesh *fdd = userdata; + const MPoly *mpoly = fdd->mpoly, *mp; + const MLoop *mloop = fdd->mloop; + const MVert *mvert = fdd->mvert; + const float(*orco)[3] = fdd->orco; + const MLoopUV *mloopuv = fdd->mloopuv; + const int totface = fdd->totface; + int a; + + float child_imat[4][4]; - /* apply obmat _after_ the local face transform */ - mul_m4_m4m4(obmat, inst_ob->obmat, obmat); + invert_m4_m4(child->imat, child->obmat); + /* Relative transform from parent to child space. */ + mul_m4_m4m4(child_imat, child->imat, ctx->object->obmat); + const float scale_fac = ctx->object->instance_faces_scale; - /* space matrix is constructed by removing obmat transform, - * this yields the worldspace transform for recursive duplis - */ - mul_m4_m4m4(space_mat, obmat, inst_ob->imat); + for (a = 0, mp = mpoly; a < totface; a++, mp++) { + const MLoop *loopstart = mloop + mp->loopstart; + float obmat[4][4]; - dob = make_dupli(ctx, inst_ob, obmat, a); + /* `obmat` is transform to face. */ + get_dupliface_transform_from_mesh(mp, loopstart, mvert, fdd->use_scale, scale_fac, obmat); + DupliObject *dob = face_dupli(ctx, child, child_imat, a, obmat); const float w = 1.0f / (float)mp->totloop; if (orco) { @@ -772,51 +949,92 @@ static void make_child_duplis_faces(const DupliContext *ctx, void *userdata, Obj madd_v2_v2fl(dob->uv, mloopuv[mp->loopstart + j].uv, w); } } - - /* recursion */ - make_recursive_duplis(ctx, inst_ob, space_mat, a); } } -static void make_duplis_faces(const DupliContext *ctx) +static void make_child_duplis_faces_from_bmesh(const DupliContext *ctx, + void *userdata, + Object *child) { - Object *parent = ctx->object; - FaceDupliData fdd; + FaceDupliData_BMesh *fdd = userdata; + BMEditMesh *em = fdd->em; + float child_imat[4][4]; + int a; + BMFace *f; + BMIter iter; - fdd.use_scale = ((parent->transflag & OB_DUPLIFACES_SCALE) != 0); + const float(*vert_coords)[3] = fdd->vert_coords; - /* gather mesh info */ - { - BMEditMesh *em = BKE_editmesh_from_object(parent); - - /* We do not need any render-smecific handling anymore, depsgraph takes care of that. */ - /* NOTE: Do direct access to the evaluated mesh: this function is used - * during meta balls evaluation. But even without those all the objects - * which are needed for correct instancing are already evaluated. */ - if (em != NULL) { - fdd.me_eval = em->mesh_eval_cage; + BLI_assert((vert_coords == NULL) || (em->bm->elem_index_dirty & BM_VERT) == 0); + + invert_m4_m4(child->imat, child->obmat); + /* Relative transform from parent to child space. */ + mul_m4_m4m4(child_imat, child->imat, ctx->object->obmat); + const float scale_fac = ctx->object->instance_faces_scale; + + BM_ITER_MESH_INDEX (f, &iter, em->bm, BM_FACES_OF_MESH, a) { + float obmat[4][4]; + + /* `obmat` is transform to face. */ + get_dupliface_transform_from_bmesh(f, vert_coords, fdd->use_scale, scale_fac, obmat); + DupliObject *dob = face_dupli(ctx, child, child_imat, a, obmat); + + if (fdd->has_orco) { + const float w = 1.0f / (float)f->len; + BMLoop *l_first, *l_iter; + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + madd_v3_v3fl(dob->orco, l_iter->v->co, w); + } while ((l_iter = l_iter->next) != l_first); } - else { - fdd.me_eval = BKE_object_get_evaluated_mesh(parent); + if (fdd->has_uvs) { + BM_face_uv_calc_center_median(f, fdd->cd_loop_uv_offset, dob->uv); } + } +} - if (fdd.me_eval == NULL) { - return; - } +static void make_duplis_faces(const DupliContext *ctx) +{ + Object *parent = ctx->object; + const bool use_scale = ((parent->transflag & OB_DUPLIFACES_SCALE) != 0); + /* Gather mesh info. */ + BMEditMesh *em = NULL; + const float(*vert_coords)[3] = NULL; + Mesh *me_eval = mesh_data_from_duplicator_object(parent, &em, &vert_coords, NULL); + if (em == NULL && me_eval == NULL) { + return; + } + + if (em != NULL) { + FaceDupliData_BMesh fdd = { + .em = em, + .use_scale = use_scale, + .has_orco = (vert_coords != NULL), + .vert_coords = vert_coords, + }; + const int uv_idx = CustomData_get_render_layer(&em->bm->ldata, CD_MLOOPUV); + if (uv_idx != -1) { + fdd.has_uvs = true; + fdd.cd_loop_uv_offset = CustomData_get_n_offset(&em->bm->ldata, CD_MLOOPUV, uv_idx); + } + make_child_duplis(ctx, &fdd, make_child_duplis_faces_from_bmesh); + } + else { + FaceDupliData_Mesh fdd = { + .use_scale = use_scale, + .me_eval = me_eval, + }; fdd.orco = CustomData_get_layer(&fdd.me_eval->vdata, CD_ORCO); const int uv_idx = CustomData_get_render_layer(&fdd.me_eval->ldata, CD_MLOOPUV); fdd.mloopuv = CustomData_get_layer_n(&fdd.me_eval->ldata, CD_MLOOPUV, uv_idx); - fdd.totface = fdd.me_eval->totpoly; - fdd.mpoly = fdd.me_eval->mpoly; - fdd.mloop = fdd.me_eval->mloop; - fdd.mvert = fdd.me_eval->mvert; + fdd.totface = me_eval->totpoly; + fdd.mpoly = me_eval->mpoly; + fdd.mloop = me_eval->mloop; + fdd.mvert = me_eval->mvert; + make_child_duplis(ctx, &fdd, make_child_duplis_faces_from_mesh); } - - make_child_duplis(ctx, &fdd, make_child_duplis_faces); - - fdd.me_eval = NULL; } static const DupliGenerator gen_dupli_faces = { diff --git a/source/blender/blenlib/tests/BLI_path_util_test.cc b/source/blender/blenlib/tests/BLI_path_util_test.cc index 4b8e6ed8085..6cfebd0ea05 100644 --- a/source/blender/blenlib/tests/BLI_path_util_test.cc +++ b/source/blender/blenlib/tests/BLI_path_util_test.cc @@ -8,10 +8,6 @@ #include "BLI_path_util.h" #include "BLI_string.h" -#ifdef _WIN32 -# include "BKE_global.h" -#endif - /* -------------------------------------------------------------------- */ /* tests */ diff --git a/source/blender/blenlib/tests/BLI_polyfill_2d_test.cc b/source/blender/blenlib/tests/BLI_polyfill_2d_test.cc index a5949c58037..624a296e758 100644 --- a/source/blender/blenlib/tests/BLI_polyfill_2d_test.cc +++ b/source/blender/blenlib/tests/BLI_polyfill_2d_test.cc @@ -56,7 +56,7 @@ static void test_valid_polyfill_prepare(unsigned int tris[][3], unsigned int tri * - all tris set. * - all verts used at least once. */ -static void test_polyfill_simple(const float poly[][2], +static void test_polyfill_simple(const float /*poly*/[][2], const unsigned int poly_tot, const unsigned int tris[][3], const unsigned int tris_tot) @@ -79,7 +79,7 @@ static void test_polyfill_simple(const float poly[][2], MEM_freeN(tot_used); } -static void test_polyfill_topology(const float poly[][2], +static void test_polyfill_topology(const float /*poly*/[][2], const unsigned int poly_tot, const unsigned int tris[][3], const unsigned int tris_tot) @@ -125,7 +125,7 @@ static void test_polyfill_topology(const float poly[][2], * Check all faces are flipped the same way */ static void test_polyfill_winding(const float poly[][2], - const unsigned int poly_tot, + const unsigned int /*poly_tot*/, const unsigned int tris[][3], const unsigned int tris_tot) { diff --git a/source/blender/blenlib/tests/performance/CMakeLists.txt b/source/blender/blenlib/tests/performance/CMakeLists.txt index c7cb65f78b2..88fbed0a49b 100644 --- a/source/blender/blenlib/tests/performance/CMakeLists.txt +++ b/source/blender/blenlib/tests/performance/CMakeLists.txt @@ -21,10 +21,6 @@ set(INC . .. - ../../../source/blender/blenlib - ../../../source/blender/makesdna - ../../../intern/guardedalloc - ../../../intern/atomic ) setup_libdirs() diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 27f282cb760..70fc852ed1b 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -5296,6 +5296,8 @@ static void direct_link_modifiers(BlendDataReader *reader, ListBase *lb, Object BLO_read_list(reader, lb); for (md = lb->first; md; md = md->next) { + BKE_modifier_session_uuid_generate(md); + md->error = NULL; md->runtime = NULL; diff --git a/source/blender/bmesh/intern/bmesh_query_uv.c b/source/blender/bmesh/intern/bmesh_query_uv.c index b9ea51f0c4d..1aa75bfb037 100644 --- a/source/blender/bmesh/intern/bmesh_query_uv.c +++ b/source/blender/bmesh/intern/bmesh_query_uv.c @@ -95,6 +95,20 @@ void BM_face_uv_calc_center_median_weighted(const BMFace *f, #undef UV_ASPECT +void BM_face_uv_calc_center_median(const BMFace *f, const int cd_loop_uv_offset, float r_cent[2]) +{ + const BMLoop *l_iter; + const BMLoop *l_first; + zero_v2(r_cent); + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + const MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_uv_offset); + add_v2_v2(r_cent, luv->uv); + } while ((l_iter = l_iter->next) != l_first); + + mul_v2_fl(r_cent, 1.0f / (float)f->len); +} + /** * Calculate the UV cross product (use the sign to check the winding). */ diff --git a/source/blender/bmesh/intern/bmesh_query_uv.h b/source/blender/bmesh/intern/bmesh_query_uv.h index 3465a831bea..0a86c0cbeae 100644 --- a/source/blender/bmesh/intern/bmesh_query_uv.h +++ b/source/blender/bmesh/intern/bmesh_query_uv.h @@ -31,6 +31,8 @@ void BM_face_uv_calc_center_median_weighted(const BMFace *f, const float aspect[2], const int cd_loop_uv_offset, float r_cent[2]) ATTR_NONNULL(); +void BM_face_uv_calc_center_median(const BMFace *f, const int cd_loop_uv_offset, float r_cent[2]) + ATTR_NONNULL(); float BM_face_uv_calc_cross(const BMFace *f, const int cd_loop_uv_offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); diff --git a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc index d76f5991dac..0bf6c38bc89 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc @@ -292,7 +292,7 @@ bool id_copy_inplace_no_main(const ID *id, ID *newid) const ID_Type id_type = GS(id_for_copy->name); if (id_type == ID_OB) { const Object *object = reinterpret_cast<const Object *>(id_for_copy); - BKE_pose_check_uuids_unique_and_report(object->pose); + BKE_object_check_uuids_unique_and_report(object); } } diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_modifier.cc b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_modifier.cc index 934403674a9..25bcf2bfe72 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_modifier.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_modifier.cc @@ -23,28 +23,14 @@ #include "intern/eval/deg_eval_runtime_backup_modifier.h" +#include "DNA_modifier_types.h" + namespace blender { namespace deg { -ModifierDataBackupID::ModifierDataBackupID(const Depsgraph * /*depsgraph*/) - : ModifierDataBackupID(nullptr, eModifierType_None) -{ -} - -ModifierDataBackupID::ModifierDataBackupID(ModifierData *modifier_data, ModifierType type) - : modifier_data(modifier_data), type(type) -{ -} - -bool operator==(const ModifierDataBackupID &a, const ModifierDataBackupID &b) -{ - return a.modifier_data == b.modifier_data && a.type == b.type; -} - -uint64_t ModifierDataBackupID::hash() const +ModifierDataBackup::ModifierDataBackup(ModifierData *modifier_data) + : type(static_cast<ModifierType>(modifier_data->type)), runtime(modifier_data->runtime) { - uintptr_t ptr = (uintptr_t)modifier_data; - return (ptr >> 4) ^ (uintptr_t)type; } } // namespace deg diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_modifier.h b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_modifier.h index a5bdf2359ee..f02dc73c392 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_modifier.h +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_modifier.h @@ -25,38 +25,18 @@ #include "BKE_modifier.h" -#include "intern/depsgraph_type.h" - struct ModifierData; namespace blender { namespace deg { -struct Depsgraph; - -/* Identifier used to match modifiers to backup/restore their runtime data. - * Identification is happening using original modifier data pointer and the - * modifier type. - * It is not enough to only pointer, since it's possible to have a situation - * when modifier is removed and a new one added, and due to memory allocation - * policy they might have same pointer. - * By adding type into matching we are at least ensuring that modifier will not - * try to interpret runtime data created by another modifier type. */ -class ModifierDataBackupID { +class ModifierDataBackup { public: - ModifierDataBackupID(const Depsgraph *depsgraph); - ModifierDataBackupID(ModifierData *modifier_data, ModifierType type); - - friend bool operator==(const ModifierDataBackupID &a, const ModifierDataBackupID &b); + explicit ModifierDataBackup(ModifierData *modifier_data); - uint64_t hash() const; - - ModifierData *modifier_data; ModifierType type; + void *runtime; }; -/* Storage for backed up runtime modifier data. */ -typedef Map<ModifierDataBackupID, void *> ModifierRuntimeDataBackup; - } // namespace deg } // namespace blender diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.cc b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.cc index 88334e41192..addee3dc539 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.cc @@ -62,21 +62,18 @@ void ObjectRuntimeBackup::init_from_object(Object *object) backup_pose_channel_runtime_data(object); } -inline ModifierDataBackupID create_modifier_data_id(const ModifierData *modifier_data) -{ - return ModifierDataBackupID(modifier_data->orig_modifier_data, - static_cast<ModifierType>(modifier_data->type)); -} - void ObjectRuntimeBackup::backup_modifier_runtime_data(Object *object) { LISTBASE_FOREACH (ModifierData *, modifier_data, &object->modifiers) { if (modifier_data->runtime == nullptr) { continue; } + + const SessionUUID &session_uuid = modifier_data->session_uuid; + BLI_assert(BLI_session_uuid_is_generated(&session_uuid)); + BLI_assert(modifier_data->orig_modifier_data != nullptr); - ModifierDataBackupID modifier_data_id = create_modifier_data_id(modifier_data); - modifier_runtime_data.add(modifier_data_id, modifier_data->runtime); + modifier_runtime_data.add(session_uuid, ModifierDataBackup(modifier_data)); modifier_data->runtime = nullptr; } } @@ -153,17 +150,17 @@ void ObjectRuntimeBackup::restore_modifier_runtime_data(Object *object) { LISTBASE_FOREACH (ModifierData *, modifier_data, &object->modifiers) { BLI_assert(modifier_data->orig_modifier_data != nullptr); - ModifierDataBackupID modifier_data_id = create_modifier_data_id(modifier_data); - void *runtime = modifier_runtime_data.pop_default(modifier_data_id, nullptr); - if (runtime != nullptr) { - modifier_data->runtime = runtime; + const SessionUUID &session_uuid = modifier_data->session_uuid; + optional<ModifierDataBackup> backup = modifier_runtime_data.pop_try(session_uuid); + if (backup.has_value()) { + modifier_data->runtime = backup->runtime; } } - for (ModifierRuntimeDataBackup::Item item : modifier_runtime_data.items()) { - const ModifierTypeInfo *modifier_type_info = BKE_modifier_get_info(item.key.type); + for (ModifierDataBackup &backup : modifier_runtime_data.values()) { + const ModifierTypeInfo *modifier_type_info = BKE_modifier_get_info(backup.type); BLI_assert(modifier_type_info != nullptr); - modifier_type_info->freeRuntimeData(item.value); + modifier_type_info->freeRuntimeData(backup.runtime); } } diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.h b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.h index a10f15634ce..5f6b443a2b2 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.h +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.h @@ -36,6 +36,8 @@ struct Object; namespace blender { namespace deg { +struct Depsgraph; + class ObjectRuntimeBackup { public: ObjectRuntimeBackup(const Depsgraph *depsgraph); @@ -56,7 +58,7 @@ class ObjectRuntimeBackup { Object_Runtime runtime; short base_flag; unsigned short base_local_view_bits; - ModifierRuntimeDataBackup modifier_runtime_data; + Map<SessionUUID, ModifierDataBackup> modifier_runtime_data; Map<SessionUUID, bPoseChannel_Runtime> pose_channel_runtime_data; }; diff --git a/source/blender/editors/gizmo_library/gizmo_types/snap3d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/snap3d_gizmo.c index a3921791427..24943ab5318 100644 --- a/source/blender/editors/gizmo_library/gizmo_types/snap3d_gizmo.c +++ b/source/blender/editors/gizmo_library/gizmo_types/snap3d_gizmo.c @@ -78,12 +78,11 @@ typedef struct SnapGizmo3D { } SnapGizmo3D; #ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK -static bool invert_snap(const wmGizmo *gz, const wmWindowManager *wm, const wmEvent *event) +static bool invert_snap(SnapGizmo3D *snap_gizmo, const wmWindowManager *wm, const wmEvent *event) { - SnapGizmo3D *gizmo_snap = (SnapGizmo3D *)gz; - wmKeyMap *keymap = WM_keymap_active(wm, gizmo_snap->keymap); + wmKeyMap *keymap = WM_keymap_active(wm, snap_gizmo->keymap); - const int snap_on = gizmo_snap->snap_on; + const int snap_on = snap_gizmo->snap_on; for (wmKeyMapItem *kmi = keymap->items.first; kmi; kmi = kmi->next) { if (kmi->flag & KMI_INACTIVE) { continue; @@ -201,29 +200,34 @@ SnapObjectContext *ED_gizmotypes_snap_3d_context_ensure(Scene *scene, const View3D *v3d, wmGizmo *gz) { - SnapGizmo3D *gizmo_snap = (SnapGizmo3D *)gz; - if (gizmo_snap->snap_context_v3d == NULL) { - gizmo_snap->snap_context_v3d = ED_transform_snap_object_context_create_view3d( + SnapGizmo3D *snap_gizmo = (SnapGizmo3D *)gz; + if (snap_gizmo->snap_context_v3d == NULL) { + snap_gizmo->snap_context_v3d = ED_transform_snap_object_context_create_view3d( scene, 0, region, v3d); } - return gizmo_snap->snap_context_v3d; + return snap_gizmo->snap_context_v3d; } bool ED_gizmotypes_snap_3d_invert_snap_get(struct wmGizmo *gz) { - SnapGizmo3D *gizmo_snap = (SnapGizmo3D *)gz; - return gizmo_snap->invert_snap; +#ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK + SnapGizmo3D *snap_gizmo = (SnapGizmo3D *)gz; + return snap_gizmo->invert_snap; +#else + return false; +#endif } + void ED_gizmotypes_snap_3d_toggle_set(wmGizmo *gz, bool enable) { - SnapGizmo3D *gizmo_snap = (SnapGizmo3D *)gz; - gizmo_snap->use_snap_override = (int)enable; + SnapGizmo3D *snap_gizmo = (SnapGizmo3D *)gz; + snap_gizmo->use_snap_override = (int)enable; } void ED_gizmotypes_snap_3d_toggle_clear(wmGizmo *gz) { - SnapGizmo3D *gizmo_snap = (SnapGizmo3D *)gz; - gizmo_snap->use_snap_override = -1; + SnapGizmo3D *snap_gizmo = (SnapGizmo3D *)gz; + snap_gizmo->use_snap_override = -1; } short ED_gizmotypes_snap_3d_update(wmGizmo *gz, @@ -235,29 +239,29 @@ short ED_gizmotypes_snap_3d_update(wmGizmo *gz, float r_loc[3], float r_nor[3]) { - SnapGizmo3D *gizmo_snap = (SnapGizmo3D *)gz; + SnapGizmo3D *snap_gizmo = (SnapGizmo3D *)gz; Scene *scene = DEG_get_input_scene(depsgraph); float co[3], no[3]; short snap_elem = 0; int snap_elem_index[3] = {-1, -1, -1}; int index = -1; - if (gizmo_snap->use_snap_override != -1) { - if (gizmo_snap->use_snap_override == false) { - gizmo_snap->snap_elem = 0; + if (snap_gizmo->use_snap_override != -1) { + if (snap_gizmo->use_snap_override == false) { + snap_gizmo->snap_elem = 0; return 0; } } #ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK if (wm && wm->winactive) { - gizmo_snap->invert_snap = invert_snap(gz, wm, wm->winactive->eventstate); + snap_gizmo->invert_snap = invert_snap(snap_gizmo, wm, wm->winactive->eventstate); } - if (gizmo_snap->use_snap_override == -1) { + if (snap_gizmo->use_snap_override == -1) { const ToolSettings *ts = scene->toolsettings; - if (gizmo_snap->invert_snap != !(ts->snap_flag & SCE_SNAP)) { - gizmo_snap->snap_elem = 0; + if (snap_gizmo->invert_snap != !(ts->snap_flag & SCE_SNAP)) { + snap_gizmo->snap_elem = 0; return 0; } } @@ -267,8 +271,8 @@ short ED_gizmotypes_snap_3d_update(wmGizmo *gz, wmGizmoProperty *gz_prop = WM_gizmo_target_property_find(gz, "snap_elements"); int snap_elements = RNA_property_enum_get(&gz_prop->ptr, gz_prop->prop); - if (gz_prop->prop != gizmo_snap->prop_snap_force) { - int snap_elements_force = RNA_property_enum_get(gz->ptr, gizmo_snap->prop_snap_force); + if (gz_prop->prop != snap_gizmo->prop_snap_force) { + int snap_elements_force = RNA_property_enum_get(gz->ptr, snap_gizmo->prop_snap_force); snap_elements |= snap_elements_force; } snap_elements &= (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE | @@ -276,8 +280,8 @@ short ED_gizmotypes_snap_3d_update(wmGizmo *gz, if (snap_elements) { float prev_co[3] = {0.0f}; - if (RNA_property_is_set(gz->ptr, gizmo_snap->prop_prevpoint)) { - RNA_property_float_get_array(gz->ptr, gizmo_snap->prop_prevpoint, prev_co); + if (RNA_property_is_set(gz->ptr, snap_gizmo->prop_prevpoint)) { + RNA_property_float_get_array(gz->ptr, snap_gizmo->prop_prevpoint, prev_co); } else { snap_elements &= ~SCE_SNAP_MODE_EDGE_PERPENDICULAR; @@ -286,7 +290,7 @@ short ED_gizmotypes_snap_3d_update(wmGizmo *gz, float dist_px = 12.0f * U.pixelsize; ED_gizmotypes_snap_3d_context_ensure(scene, region, v3d, gz); - snap_elem = ED_transform_snap_object_project_view3d_ex(gizmo_snap->snap_context_v3d, + snap_elem = ED_transform_snap_object_project_view3d_ex(snap_gizmo->snap_context_v3d, depsgraph, snap_elements, &(const struct SnapObjectParams){ @@ -320,14 +324,15 @@ short ED_gizmotypes_snap_3d_update(wmGizmo *gz, snap_elem_index[2] = index; } - gizmo_snap->snap_elem = snap_elem; - RNA_property_float_set_array(gz->ptr, gizmo_snap->prop_location, co); - RNA_property_float_set_array(gz->ptr, gizmo_snap->prop_normal, no); - RNA_property_int_set_array(gz->ptr, gizmo_snap->prop_elem_index, snap_elem_index); + snap_gizmo->snap_elem = snap_elem; + RNA_property_float_set_array(gz->ptr, snap_gizmo->prop_location, co); + RNA_property_float_set_array(gz->ptr, snap_gizmo->prop_normal, no); + RNA_property_int_set_array(gz->ptr, snap_gizmo->prop_elem_index, snap_elem_index); if (r_loc) { copy_v3_v3(r_loc, co); } + if (r_nor) { copy_v3_v3(r_nor, no); } @@ -341,18 +346,18 @@ short ED_gizmotypes_snap_3d_update(wmGizmo *gz, /** \name GIZMO_GT_snap_3d * \{ */ -static void gizmo_snap_setup(wmGizmo *gz) +static void snap_gizmo_setup(wmGizmo *gz) { - SnapGizmo3D *gizmo_snap = (SnapGizmo3D *)gz; + SnapGizmo3D *snap_gizmo = (SnapGizmo3D *)gz; /* For quick access to the props. */ - gizmo_snap->prop_prevpoint = RNA_struct_find_property(gz->ptr, "prev_point"); - gizmo_snap->prop_location = RNA_struct_find_property(gz->ptr, "location"); - gizmo_snap->prop_normal = RNA_struct_find_property(gz->ptr, "normal"); - gizmo_snap->prop_elem_index = RNA_struct_find_property(gz->ptr, "snap_elem_index"); - gizmo_snap->prop_snap_force = RNA_struct_find_property(gz->ptr, "snap_elements_force"); + snap_gizmo->prop_prevpoint = RNA_struct_find_property(gz->ptr, "prev_point"); + snap_gizmo->prop_location = RNA_struct_find_property(gz->ptr, "location"); + snap_gizmo->prop_normal = RNA_struct_find_property(gz->ptr, "normal"); + snap_gizmo->prop_elem_index = RNA_struct_find_property(gz->ptr, "snap_elem_index"); + snap_gizmo->prop_snap_force = RNA_struct_find_property(gz->ptr, "snap_elements_force"); - gizmo_snap->use_snap_override = -1; + snap_gizmo->use_snap_override = -1; /* Prop fallback. */ WM_gizmo_target_property_def_rna(gz, "snap_elements", gz->ptr, "snap_elements_force", -1); @@ -361,10 +366,10 @@ static void gizmo_snap_setup(wmGizmo *gz) gz->flag |= WM_GIZMO_NO_TOOLTIP; } -static void gizmo_snap_draw(const bContext *C, wmGizmo *gz) +static void snap_gizmo_draw(const bContext *C, wmGizmo *gz) { - SnapGizmo3D *gizmo_snap = (SnapGizmo3D *)gz; - if (gizmo_snap->snap_elem == 0) { + SnapGizmo3D *snap_gizmo = (SnapGizmo3D *)gz; + if (snap_gizmo->snap_elem == 0) { return; } @@ -376,22 +381,22 @@ static void gizmo_snap_draw(const bContext *C, wmGizmo *gz) * And `snap_elem` is not really useful in this case. */ if ((rv3d->rflag & RV3D_NAVIGATING) || (!(gz->state & WM_GIZMO_STATE_HIGHLIGHT) && !wm_gizmomap_modal_get(region->gizmo_map))) { - gizmo_snap->snap_elem = 0; + snap_gizmo->snap_elem = 0; return; } float location[3], prev_point_stack[3], *prev_point = NULL; uchar color_line[4], color_point[4]; - RNA_property_float_get_array(gz->ptr, gizmo_snap->prop_location, location); + RNA_property_float_get_array(gz->ptr, snap_gizmo->prop_location, location); UI_GetThemeColor3ubv(TH_TRANSFORM, color_line); color_line[3] = 128; rgba_float_to_uchar(color_point, gz->color); - if (RNA_property_is_set(gz->ptr, gizmo_snap->prop_prevpoint)) { - RNA_property_float_get_array(gz->ptr, gizmo_snap->prop_prevpoint, prev_point_stack); + if (RNA_property_is_set(gz->ptr, snap_gizmo->prop_prevpoint)) { + RNA_property_float_get_array(gz->ptr, snap_gizmo->prop_prevpoint, prev_point_stack); prev_point = prev_point_stack; } @@ -399,35 +404,36 @@ static void gizmo_snap_draw(const bContext *C, wmGizmo *gz) GPU_line_width(1.0f); ED_gizmotypes_snap_3d_draw_util( - rv3d, prev_point, location, NULL, color_line, color_point, gizmo_snap->snap_elem); + rv3d, prev_point, location, NULL, color_line, color_point, snap_gizmo->snap_elem); } -static int gizmo_snap_test_select(bContext *C, wmGizmo *gz, const int mval[2]) +static int snap_gizmo_test_select(bContext *C, wmGizmo *gz, const int mval[2]) { - SnapGizmo3D *gizmo_snap = (SnapGizmo3D *)gz; + SnapGizmo3D *snap_gizmo = (SnapGizmo3D *)gz; #ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK wmWindowManager *wm = CTX_wm_manager(C); - if (gizmo_snap->keymap == NULL) { - gizmo_snap->keymap = WM_modalkeymap_find(wm->defaultconf, "Generic Gizmo Tweak Modal Map"); - RNA_enum_value_from_id(gizmo_snap->keymap->modal_items, "SNAP_ON", &gizmo_snap->snap_on); + if (snap_gizmo->keymap == NULL) { + snap_gizmo->keymap = WM_modalkeymap_find(wm->defaultconf, "Generic Gizmo Tweak Modal Map"); + RNA_enum_value_from_id(snap_gizmo->keymap->modal_items, "SNAP_ON", &snap_gizmo->snap_on); } - const bool invert = wm->winactive ? invert_snap(gz, wm, wm->winactive->eventstate) : false; - if (gizmo_snap->invert_snap == invert && gizmo_snap->mval[0] == mval[0] && - gizmo_snap->mval[1] == mval[1]) { + const bool invert = wm->winactive ? invert_snap(snap_gizmo, wm, wm->winactive->eventstate) : + false; + if (snap_gizmo->invert_snap == invert && snap_gizmo->mval[0] == mval[0] && + snap_gizmo->mval[1] == mval[1]) { /* Performance, do not update. */ - return gizmo_snap->snap_elem ? 0 : -1; + return snap_gizmo->snap_elem ? 0 : -1; } - gizmo_snap->invert_snap = invert; + snap_gizmo->invert_snap = invert; #else - if (gizmo_snap->mval[0] == mval[0] && gizmo_snap->mval[1] == mval[1]) { + if (snap_gizmo->mval[0] == mval[0] && snap_gizmo->mval[1] == mval[1]) { /* Performance, do not update. */ - return gizmo_snap->snap_elem ? 0 : -1; + return snap_gizmo->snap_elem ? 0 : -1; } #endif - copy_v2_v2_int(gizmo_snap->mval, mval); + copy_v2_v2_int(snap_gizmo->mval, mval); ARegion *region = CTX_wm_region(C); View3D *v3d = CTX_wm_view3d(C); @@ -443,7 +449,7 @@ static int gizmo_snap_test_select(bContext *C, wmGizmo *gz, const int mval[2]) return -1; } -static int gizmo_snap_modal(bContext *UNUSED(C), +static int snap_gizmo_modal(bContext *UNUSED(C), wmGizmo *UNUSED(gz), const wmEvent *UNUSED(event), eWM_GizmoFlagTweak UNUSED(tweak_flag)) @@ -451,19 +457,19 @@ static int gizmo_snap_modal(bContext *UNUSED(C), return OPERATOR_RUNNING_MODAL; } -static int gizmo_snap_invoke(bContext *UNUSED(C), +static int snap_gizmo_invoke(bContext *UNUSED(C), wmGizmo *UNUSED(gz), const wmEvent *UNUSED(event)) { return OPERATOR_RUNNING_MODAL; } -static void gizmo_snap_free(wmGizmo *gz) +static void snap_gizmo_free(wmGizmo *gz) { - SnapGizmo3D *gizmo_snap = (SnapGizmo3D *)gz; - if (gizmo_snap->snap_context_v3d) { - ED_transform_snap_object_context_destroy(gizmo_snap->snap_context_v3d); - gizmo_snap->snap_context_v3d = NULL; + SnapGizmo3D *snap_gizmo = (SnapGizmo3D *)gz; + if (snap_gizmo->snap_context_v3d) { + ED_transform_snap_object_context_destroy(snap_gizmo->snap_context_v3d); + snap_gizmo->snap_context_v3d = NULL; } } @@ -473,12 +479,12 @@ static void GIZMO_GT_snap_3d(wmGizmoType *gzt) gzt->idname = "GIZMO_GT_snap_3d"; /* api callbacks */ - gzt->setup = gizmo_snap_setup; - gzt->draw = gizmo_snap_draw; - gzt->test_select = gizmo_snap_test_select; - gzt->modal = gizmo_snap_modal; - gzt->invoke = gizmo_snap_invoke; - gzt->free = gizmo_snap_free; + gzt->setup = snap_gizmo_setup; + gzt->draw = snap_gizmo_draw; + gzt->test_select = snap_gizmo_test_select; + gzt->modal = snap_gizmo_modal; + gzt->invoke = snap_gizmo_invoke; + gzt->free = snap_gizmo_free; gzt->struct_size = sizeof(SnapGizmo3D); diff --git a/source/blender/editors/gpencil/gpencil_intern.h b/source/blender/editors/gpencil/gpencil_intern.h index c260085e763..87d3b6cf9c6 100644 --- a/source/blender/editors/gpencil/gpencil_intern.h +++ b/source/blender/editors/gpencil/gpencil_intern.h @@ -202,6 +202,8 @@ typedef struct tGPDprimitive { tGPspoint *points; /** number of edges allocated */ int point_count; + /** number of subdivisions. */ + int subdiv; /** stored number of polygon edges */ int tot_stored_edges; /** number of polygon edges */ @@ -559,7 +561,11 @@ void GPENCIL_OT_interpolate_reverse(struct wmOperatorType *ot); /* primitives ---------- */ -void GPENCIL_OT_primitive(struct wmOperatorType *ot); +void GPENCIL_OT_primitive_box(struct wmOperatorType *ot); +void GPENCIL_OT_primitive_line(struct wmOperatorType *ot); +void GPENCIL_OT_primitive_polyline(struct wmOperatorType *ot); +void GPENCIL_OT_primitive_circle(struct wmOperatorType *ot); +void GPENCIL_OT_primitive_curve(struct wmOperatorType *ot); /* vertex groups ------------ */ void GPENCIL_OT_vertex_group_assign(struct wmOperatorType *ot); diff --git a/source/blender/editors/gpencil/gpencil_ops.c b/source/blender/editors/gpencil/gpencil_ops.c index 8561985ec07..18b096d599b 100644 --- a/source/blender/editors/gpencil/gpencil_ops.c +++ b/source/blender/editors/gpencil/gpencil_ops.c @@ -687,7 +687,11 @@ void ED_operatortypes_gpencil(void) WM_operatortype_append(GPENCIL_OT_interpolate_reverse); /* Primitives */ - WM_operatortype_append(GPENCIL_OT_primitive); + WM_operatortype_append(GPENCIL_OT_primitive_box); + WM_operatortype_append(GPENCIL_OT_primitive_line); + WM_operatortype_append(GPENCIL_OT_primitive_polyline); + WM_operatortype_append(GPENCIL_OT_primitive_circle); + WM_operatortype_append(GPENCIL_OT_primitive_curve); /* convert old 2.7 files to 2.8 */ WM_operatortype_append(GPENCIL_OT_convert_old_files); diff --git a/source/blender/editors/gpencil/gpencil_primitive.c b/source/blender/editors/gpencil/gpencil_primitive.c index 5cdb32eb535..7bec95430ce 100644 --- a/source/blender/editors/gpencil/gpencil_primitive.c +++ b/source/blender/editors/gpencil/gpencil_primitive.c @@ -109,7 +109,15 @@ /* ************************************************ */ /* Core/Shared Utilities */ - +const static EnumPropertyItem gpencil_primitive_type[] = { + {GP_STROKE_BOX, "BOX", 0, "Box", ""}, + {GP_STROKE_LINE, "LINE", 0, "Line", ""}, + {GP_STROKE_POLYLINE, "POLYLINE", 0, "Polyline", ""}, + {GP_STROKE_CIRCLE, "CIRCLE", 0, "Circle", ""}, + {GP_STROKE_ARC, "ARC", 0, "Arc", ""}, + {GP_STROKE_CURVE, "CURVE", 0, "Curve", ""}, + {0, NULL, 0, NULL, NULL}, +}; /* clear the session buffers (call this before AND after a paint operation) */ static void gpencil_session_validatebuffer(tGPDprimitive *p) { @@ -427,19 +435,20 @@ static void gpencil_primitive_status_indicators(bContext *C, tGPDprimitive *tgpi } else if (tgpi->type == GP_STROKE_CIRCLE) { BLI_strncpy(msg_str, - TIP_("Circle: ESC to cancel, Enter/MMB to confirm, WHEEL/+- to adjust edge " + TIP_("Circle: ESC to cancel, Enter/MMB to confirm, WHEEL/+- to adjust subdivision " "number, Shift to square, Alt to center"), UI_MAX_DRAW_STR); } else if (tgpi->type == GP_STROKE_ARC) { - BLI_strncpy(msg_str, - TIP_("Arc: ESC to cancel, Enter/MMB to confirm, WHEEL/+- to adjust edge number, " - "Shift to square, Alt to center, M: Flip, E: extrude"), - UI_MAX_DRAW_STR); + BLI_strncpy( + msg_str, + TIP_("Arc: ESC to cancel, Enter/MMB to confirm, WHEEL/+- to adjust subdivision number, " + "Shift to square, Alt to center, M: Flip, E: extrude"), + UI_MAX_DRAW_STR); } else if (tgpi->type == GP_STROKE_CURVE) { BLI_strncpy(msg_str, - TIP_("Curve: ESC to cancel, Enter/MMB to confirm, WHEEL/+- to adjust edge " + TIP_("Curve: ESC to cancel, Enter/MMB to confirm, WHEEL/+- to adjust subdivision " "number, Shift to square, Alt to center, E: extrude"), UI_MAX_DRAW_STR); } @@ -519,16 +528,23 @@ static void gpencil_primitive_rectangle(tGPDprimitive *tgpi, tGPspoint *points2D coords[4][0] = tgpi->start[0]; coords[4][1] = tgpi->start[1]; - const float step = 1.0f / (float)(tgpi->tot_edges); - int i = tgpi->tot_stored_edges; - - for (int j = 0; j < 4; j++) { - float a = 0.0f; - for (int k = 0; k < tgpi->tot_edges; k++) { - tGPspoint *p2d = &points2D[i]; - interp_v2_v2v2(&p2d->x, coords[j], coords[j + 1], a); - a += step; - i++; + if (tgpi->tot_edges == 1) { + for (int j = 0; j < 4; j++) { + tGPspoint *p2d = &points2D[j]; + copy_v2_v2(&p2d->x, coords[j]); + } + } + else { + const float step = 1.0f / (float)(tgpi->tot_edges); + int i = tgpi->tot_stored_edges; + for (int j = 0; j < 4; j++) { + float a = 0.0f; + for (int k = 0; k < tgpi->tot_edges; k++) { + tGPspoint *p2d = &points2D[i]; + interp_v2_v2v2(&p2d->x, coords[j], coords[j + 1], a); + a += step; + i++; + } } } @@ -701,6 +717,7 @@ static void gpencil_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi) (tgpi->rv3d->persp == RV3D_CAMOB) && (!is_depth); if (tgpi->type == GP_STROKE_BOX) { + tgpi->tot_edges--; gps->totpoints = (tgpi->tot_edges * 4 + tgpi->tot_stored_edges); } else { @@ -716,7 +733,7 @@ static void gpencil_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi) /* compute screen-space coordinates for points */ tGPspoint *points2D = tgpi->points; - if (tgpi->tot_edges > 1) { + if (tgpi->tot_edges > 0) { switch (tgpi->type) { case GP_STROKE_BOX: gpencil_primitive_rectangle(tgpi, points2D); @@ -1211,31 +1228,10 @@ static void gpencil_primitive_init(bContext *C, wmOperator *op) tgpi->curve = false; } - /* set default edge count */ - switch (tgpi->type) { - case GP_STROKE_POLYLINE: { - RNA_int_set(op->ptr, "edges", 8); - break; - } - case GP_STROKE_LINE: { - RNA_int_set(op->ptr, "edges", 8); - break; - } - case GP_STROKE_BOX: { - RNA_int_set(op->ptr, "edges", 8); - break; - } - case GP_STROKE_CIRCLE: { - RNA_int_set(op->ptr, "edges", 96); - break; - } - default: { - RNA_int_set(op->ptr, "edges", 64); - break; - } - } - tgpi->tot_stored_edges = 0; + + tgpi->subdiv = RNA_int_get(op->ptr, "subdivision"); + RNA_int_set(op->ptr, "edges", tgpi->subdiv + 2); tgpi->tot_edges = RNA_int_get(op->ptr, "edges"); tgpi->flag = IDLE; tgpi->lock_axis = ts->gp_sculpt.lock_axis; @@ -1351,11 +1347,6 @@ static void gpencil_primitive_interaction_end(bContext *C, } } - /* Close stroke with geometry */ - if ((tgpi->type == GP_STROKE_BOX) || (tgpi->type == GP_STROKE_CIRCLE)) { - BKE_gpencil_stroke_close(gps); - } - DEG_id_tag_update(&tgpi->gpd->id, ID_RECALC_COPY_ON_WRITE); DEG_id_tag_update(&tgpi->gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); @@ -1629,9 +1620,12 @@ static int gpencil_primitive_modal(bContext *C, wmOperator *op, const wmEvent *e case RIGHTMOUSE: { if (event->val == KM_PRESS) { tgpi->flag = IDLE; + int last_edges = tgpi->tot_edges; tgpi->tot_edges = tgpi->tot_stored_edges ? 1 : 0; + RNA_int_set(op->ptr, "edges", tgpi->tot_edges); gpencil_primitive_update_strokes(C, tgpi); gpencil_primitive_interaction_end(C, op, win, tgpi); + RNA_int_set(op->ptr, "edges", last_edges); return OPERATOR_FINISHED; } break; @@ -1958,22 +1952,45 @@ static void gpencil_primitive_cancel(bContext *C, wmOperator *op) gpencil_primitive_exit(C, op); } -void GPENCIL_OT_primitive(wmOperatorType *ot) +static void gpencil_primitive_common_props(wmOperatorType *ot, int subdiv, int type) { - static EnumPropertyItem primitive_type[] = { - {GP_STROKE_BOX, "BOX", 0, "Box", ""}, - {GP_STROKE_LINE, "LINE", 0, "Line", ""}, - {GP_STROKE_POLYLINE, "POLYLINE", 0, "Polyline", ""}, - {GP_STROKE_CIRCLE, "CIRCLE", 0, "Circle", ""}, - {GP_STROKE_ARC, "ARC", 0, "Arc", ""}, - {GP_STROKE_CURVE, "CURVE", 0, "Curve", ""}, - {0, NULL, 0, NULL, NULL}, - }; + PropertyRNA *prop; + prop = RNA_def_int(ot->srna, + "subdivision", + subdiv, + 0, + MAX_EDGES, + "Subdivisions", + "Number of subdivision by edges", + 0, + MAX_EDGES); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + + /* Internal prop. */ + prop = RNA_def_int(ot->srna, + "edges", + MIN_EDGES, + MIN_EDGES, + MAX_EDGES, + "Edges", + "Number of points by edge", + MIN_EDGES, + MAX_EDGES); + RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN); + + RNA_def_enum(ot->srna, "type", gpencil_primitive_type, type, "Type", "Type of shape"); + + prop = RNA_def_boolean(ot->srna, "wait_for_input", true, "Wait for Input", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); +} + +void GPENCIL_OT_primitive_box(wmOperatorType *ot) +{ /* identifiers */ - ot->name = "Grease Pencil Shapes"; - ot->idname = "GPENCIL_OT_primitive"; - ot->description = "Create predefined grease pencil stroke shapes"; + ot->name = "Grease Pencil Box Shape"; + ot->idname = "GPENCIL_OT_primitive_box"; + ot->description = "Create predefined grease pencil stroke box shapes"; /* callbacks */ ot->invoke = gpencil_primitive_invoke; @@ -1982,24 +1999,88 @@ void GPENCIL_OT_primitive(wmOperatorType *ot) ot->poll = gpencil_primitive_add_poll; /* flags */ - ot->flag = OPTYPE_UNDO | OPTYPE_BLOCKING; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING; /* properties */ - PropertyRNA *prop; + gpencil_primitive_common_props(ot, 3, GP_STROKE_BOX); +} - prop = RNA_def_int(ot->srna, - "edges", - 4, - MIN_EDGES, - MAX_EDGES, - "Edges", - "Number of polygon edges", - MIN_EDGES, - MAX_EDGES); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); +void GPENCIL_OT_primitive_line(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Grease Pencil Line Shape"; + ot->idname = "GPENCIL_OT_primitive_line"; + ot->description = "Create predefined grease pencil stroke lines"; + + /* callbacks */ + ot->invoke = gpencil_primitive_invoke; + ot->modal = gpencil_primitive_modal; + ot->cancel = gpencil_primitive_cancel; + ot->poll = gpencil_primitive_add_poll; - RNA_def_enum(ot->srna, "type", primitive_type, GP_STROKE_BOX, "Type", "Type of shape"); + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING; - prop = RNA_def_boolean(ot->srna, "wait_for_input", true, "Wait for Input", ""); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + /* properties */ + gpencil_primitive_common_props(ot, 6, GP_STROKE_LINE); +} + +void GPENCIL_OT_primitive_polyline(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Grease Pencil Polyline Shape"; + ot->idname = "GPENCIL_OT_primitive_polyline"; + ot->description = "Create predefined grease pencil stroke polylines"; + + /* callbacks */ + ot->invoke = gpencil_primitive_invoke; + ot->modal = gpencil_primitive_modal; + ot->cancel = gpencil_primitive_cancel; + ot->poll = gpencil_primitive_add_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING; + + /* properties */ + gpencil_primitive_common_props(ot, 6, GP_STROKE_POLYLINE); +} + +void GPENCIL_OT_primitive_circle(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Grease Pencil Circle Shape"; + ot->idname = "GPENCIL_OT_primitive_circle"; + ot->description = "Create predefined grease pencil stroke circle shapes"; + + /* callbacks */ + ot->invoke = gpencil_primitive_invoke; + ot->modal = gpencil_primitive_modal; + ot->cancel = gpencil_primitive_cancel; + ot->poll = gpencil_primitive_add_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING; + + /* properties */ + gpencil_primitive_common_props(ot, 94, GP_STROKE_CIRCLE); +} + +void GPENCIL_OT_primitive_curve(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Grease Pencil Curve Shape"; + ot->idname = "GPENCIL_OT_primitive_curve"; + ot->description = "Create predefined grease pencil stroke curve shapes"; + + /* callbacks */ + ot->invoke = gpencil_primitive_invoke; + ot->modal = gpencil_primitive_modal; + ot->cancel = gpencil_primitive_cancel; + ot->poll = gpencil_primitive_add_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING; + + /* properties */ + gpencil_primitive_common_props(ot, 62, GP_STROKE_CURVE); } diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c index b96eeedd86f..5278da67777 100644 --- a/source/blender/editors/mesh/meshtools.c +++ b/source/blender/editors/mesh/meshtools.c @@ -1063,7 +1063,7 @@ static float *editmesh_get_mirror_uv( BMFace *efa; BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - uv_poly_center(efa, cent, cd_loop_uv_offset); + BM_face_uv_calc_center_median(efa, cd_loop_uv_offset, cent); if ((fabsf(cent[0] - cent_vec[0]) < 0.001f) && (fabsf(cent[1] - cent_vec[1]) < 0.001f)) { BMIter liter; diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c index 62720d8ca37..06e800433b1 100644 --- a/source/blender/editors/screen/screen_edit.c +++ b/source/blender/editors/screen/screen_edit.c @@ -992,6 +992,7 @@ void ED_screen_global_areas_refresh(wmWindow *win) void screen_change_prepare( bScreen *screen_old, bScreen *screen_new, Main *bmain, bContext *C, wmWindow *win) { + UNUSED_VARS_NDEBUG(bmain); BLI_assert(BLI_findindex(&bmain->screens, screen_new) != -1); if (screen_old != screen_new) { diff --git a/source/blender/editors/uvedit/uvedit_intern.h b/source/blender/editors/uvedit/uvedit_intern.h index 7455004ccb8..5a510aaf945 100644 --- a/source/blender/editors/uvedit/uvedit_intern.h +++ b/source/blender/editors/uvedit/uvedit_intern.h @@ -33,7 +33,6 @@ struct wmOperatorType; /* geometric utilities */ void uv_poly_copy_aspect(float uv_orig[][2], float uv[][2], float aspx, float aspy, int len); -void uv_poly_center(struct BMFace *f, float r_cent[2], const int cd_loop_uv_offset); /* find nearest */ diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c index 956c094c19b..d3d8c58829b 100644 --- a/source/blender/editors/uvedit/uvedit_ops.c +++ b/source/blender/editors/uvedit/uvedit_ops.c @@ -227,22 +227,6 @@ void uvedit_live_unwrap_update(SpaceImage *sima, Scene *scene, Object *obedit) /** \name Geometric Utilities * \{ */ -void uv_poly_center(BMFace *f, float r_cent[2], const int cd_loop_uv_offset) -{ - BMLoop *l; - MLoopUV *luv; - BMIter liter; - - zero_v2(r_cent); - - BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { - luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - add_v2_v2(r_cent, luv->uv); - } - - mul_v2_fl(r_cent, 1.0f / (float)f->len); -} - void uv_poly_copy_aspect(float uv_orig[][2], float uv[][2], float aspx, float aspy, int len) { int i; diff --git a/source/blender/editors/uvedit/uvedit_select.c b/source/blender/editors/uvedit/uvedit_select.c index 151c881a466..149c5cf1f96 100644 --- a/source/blender/editors/uvedit/uvedit_select.c +++ b/source/blender/editors/uvedit/uvedit_select.c @@ -724,7 +724,7 @@ bool uv_find_nearest_face(Scene *scene, Object *obedit, const float co[2], UvNea } float cent[2]; - uv_poly_center(efa, cent, cd_loop_uv_offset); + BM_face_uv_calc_center_median(efa, cd_loop_uv_offset, cent); const float dist_test_sq = len_squared_v2v2(co, cent); @@ -2841,7 +2841,7 @@ static int uv_box_select_exec(bContext *C, wmOperator *op) BM_elem_flag_disable(efa, BM_ELEM_TAG); if (uvedit_face_visible_test(scene, efa)) { - uv_poly_center(efa, cent, cd_loop_uv_offset); + BM_face_uv_calc_center_median(efa, cd_loop_uv_offset, cent); if (BLI_rctf_isect_pt_v(&rectf, cent)) { BM_elem_flag_enable(efa, BM_ELEM_TAG); changed = true; @@ -3072,7 +3072,7 @@ static int uv_circle_select_exec(bContext *C, wmOperator *op) /* assume not touched */ if (select != uvedit_face_select_test(scene, efa, cd_loop_uv_offset)) { float cent[2]; - uv_poly_center(efa, cent, cd_loop_uv_offset); + BM_face_uv_calc_center_median(efa, cd_loop_uv_offset, cent); if (uv_circle_select_is_point_inside(cent, offset, ellipse)) { BM_elem_flag_enable(efa, BM_ELEM_TAG); changed = true; @@ -3263,7 +3263,7 @@ static bool do_lasso_select_mesh_uv(bContext *C, /* assume not touched */ if (select != uvedit_face_select_test(scene, efa, cd_loop_uv_offset)) { float cent[2]; - uv_poly_center(efa, cent, cd_loop_uv_offset); + BM_face_uv_calc_center_median(efa, cd_loop_uv_offset, cent); if (do_lasso_select_mesh_uv_is_point_inside(region, &rect, mcoords, mcoords_len, cent)) { BM_elem_flag_enable(efa, BM_ELEM_TAG); changed = true; diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h index 3816cee0cf8..a6aef5b08ad 100644 --- a/source/blender/makesdna/DNA_mesh_types.h +++ b/source/blender/makesdna/DNA_mesh_types.h @@ -109,9 +109,12 @@ typedef struct Mesh_Runtime { /** Set by modifier stack if only deformed from original. */ char deformed_only; /** - * Copied from edit-mesh (hint, draw with editmesh data). - * In the future we may leave the mesh-data empty - * since its not needed if we can use edit-mesh data. */ + * Copied from edit-mesh (hint, draw with edit-mesh data when true). + * + * Modifiers that edit the mesh data in-place must set this to false + * (most #eModifierTypeType_NonGeometrical modifiers). Otherwise the edit-mesh + * data will be used for drawing, missing changes from modifiers. See T79517. + */ char is_original; /** #eMeshWrapperType and others. */ diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index b01b3f42e6a..fc50261eb03 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -22,6 +22,7 @@ #include "DNA_defs.h" #include "DNA_listBase.h" +#include "DNA_session_uuid_types.h" #ifdef __cplusplus extern "C" { @@ -124,6 +125,11 @@ typedef struct ModifierData { /* Pointer to a ModifierData in the original domain. */ struct ModifierData *orig_modifier_data; + + /* Runtime field which contains unique identifier of the modifier. */ + SessionUUID session_uuid; + + /* Runtime field which contains runtime data which is specific to a modifier type. */ void *runtime; } ModifierData; diff --git a/source/blender/modifiers/intern/MOD_datatransfer.c b/source/blender/modifiers/intern/MOD_datatransfer.c index 0b205ec4fc5..c8f49694a2f 100644 --- a/source/blender/modifiers/intern/MOD_datatransfer.c +++ b/source/blender/modifiers/intern/MOD_datatransfer.c @@ -204,32 +204,36 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * BKE_reports_init(&reports, RPT_STORE); /* Note: no islands precision for now here. */ - BKE_object_data_transfer_ex(ctx->depsgraph, - scene, - ob_source, - ctx->object, - result, - dtmd->data_types, - false, - dtmd->vmap_mode, - dtmd->emap_mode, - dtmd->lmap_mode, - dtmd->pmap_mode, - space_transform, - false, - max_dist, - dtmd->map_ray_radius, - 0.0f, - dtmd->layers_select_src, - dtmd->layers_select_dst, - dtmd->mix_mode, - dtmd->mix_factor, - dtmd->defgrp_name, - invert_vgroup, - &reports); + if (BKE_object_data_transfer_ex(ctx->depsgraph, + scene, + ob_source, + ctx->object, + result, + dtmd->data_types, + false, + dtmd->vmap_mode, + dtmd->emap_mode, + dtmd->lmap_mode, + dtmd->pmap_mode, + space_transform, + false, + max_dist, + dtmd->map_ray_radius, + 0.0f, + dtmd->layers_select_src, + dtmd->layers_select_dst, + dtmd->mix_mode, + dtmd->mix_factor, + dtmd->defgrp_name, + invert_vgroup, + &reports)) { + result->runtime.is_original = false; + } if (BKE_reports_contain(&reports, RPT_ERROR)) { - BKE_modifier_set_error(md, "%s", BKE_reports_string(&reports, RPT_ERROR)); + const char *report_str = BKE_reports_string(&reports, RPT_ERROR); + BKE_modifier_set_error(md, "%s", report_str); + MEM_freeN((void *)report_str); } else if ((dtmd->data_types & DT_TYPE_LNOR) && !(me->flag & ME_AUTOSMOOTH)) { BKE_modifier_set_error((ModifierData *)dtmd, "Enable 'Auto Smooth' in Object Data Properties"); diff --git a/source/blender/modifiers/intern/MOD_normal_edit.c b/source/blender/modifiers/intern/MOD_normal_edit.c index 66ab6b9e4db..f22ece11726 100644 --- a/source/blender/modifiers/intern/MOD_normal_edit.c +++ b/source/blender/modifiers/intern/MOD_normal_edit.c @@ -637,6 +637,8 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd, CustomData_free_layers(pdata, CD_NORMAL, num_polys); MEM_SAFE_FREE(loopnors); + result->runtime.is_original = false; + return result; } diff --git a/source/blender/modifiers/intern/MOD_uvproject.c b/source/blender/modifiers/intern/MOD_uvproject.c index 6f261f9f67a..361c778bb95 100644 --- a/source/blender/modifiers/intern/MOD_uvproject.c +++ b/source/blender/modifiers/intern/MOD_uvproject.c @@ -308,6 +308,8 @@ static Mesh *uvprojectModifier_do(UVProjectModifierData *umd, } } + mesh->runtime.is_original = false; + /* Mark tessellated CD layers as dirty. */ mesh->runtime.cd_dirty_vert |= CD_MASK_TESSLOOPNORMAL; diff --git a/source/blender/modifiers/intern/MOD_uvwarp.c b/source/blender/modifiers/intern/MOD_uvwarp.c index adc89f1b954..05224e1ffaa 100644 --- a/source/blender/modifiers/intern/MOD_uvwarp.c +++ b/source/blender/modifiers/intern/MOD_uvwarp.c @@ -235,6 +235,8 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * /* XXX TODO is this still needed? */ // me_eval->dirty |= DM_DIRTY_TESS_CDLAYERS; + mesh->runtime.is_original = false; + return mesh; } diff --git a/source/blender/modifiers/intern/MOD_weighted_normal.c b/source/blender/modifiers/intern/MOD_weighted_normal.c index f174b6d5aa4..744bab02c56 100644 --- a/source/blender/modifiers/intern/MOD_weighted_normal.c +++ b/source/blender/modifiers/intern/MOD_weighted_normal.c @@ -677,6 +677,9 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * /* Currently Modifier stack assumes there is no poly normal data passed around... */ CustomData_free_layers(pdata, CD_NORMAL, numPolys); + + result->runtime.is_original = false; + return result; } diff --git a/source/blender/modifiers/intern/MOD_weightvgedit.c b/source/blender/modifiers/intern/MOD_weightvgedit.c index 6bb4f3dc1b5..4f67fd88d4e 100644 --- a/source/blender/modifiers/intern/MOD_weightvgedit.c +++ b/source/blender/modifiers/intern/MOD_weightvgedit.c @@ -312,6 +312,8 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * MEM_freeN(new_w); MEM_freeN(dw); + mesh->runtime.is_original = false; + /* Return the vgroup-modified mesh. */ return mesh; } diff --git a/source/blender/modifiers/intern/MOD_weightvgmix.c b/source/blender/modifiers/intern/MOD_weightvgmix.c index 9821ead2340..649481a7023 100644 --- a/source/blender/modifiers/intern/MOD_weightvgmix.c +++ b/source/blender/modifiers/intern/MOD_weightvgmix.c @@ -455,6 +455,8 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * MEM_freeN(dw2); MEM_SAFE_FREE(indices); + mesh->runtime.is_original = false; + /* Return the vgroup-modified mesh. */ return mesh; } diff --git a/source/blender/modifiers/intern/MOD_weightvgproximity.c b/source/blender/modifiers/intern/MOD_weightvgproximity.c index 0668a7a086f..b23eb997f61 100644 --- a/source/blender/modifiers/intern/MOD_weightvgproximity.c +++ b/source/blender/modifiers/intern/MOD_weightvgproximity.c @@ -637,6 +637,8 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * TIMEIT_END(perf); #endif + mesh->runtime.is_original = false; + /* Return the vgroup-modified mesh. */ return mesh; } diff --git a/source/blender/python/intern/bpy_operator.c b/source/blender/python/intern/bpy_operator.c index 4b2b5f129a7..274c1934e9e 100644 --- a/source/blender/python/intern/bpy_operator.c +++ b/source/blender/python/intern/bpy_operator.c @@ -227,7 +227,14 @@ static PyObject *pyop_call(PyObject *UNUSED(self), PyObject *args) context_dict_back = CTX_py_dict_get(C); - CTX_py_dict_set(C, (void *)context_dict); + /** + * It might be that there is already a Python context override. We don't want to remove that + * except when this operator call sets a new override explicitly. This is necessary so that + * called operator runs in the same context as the calling code by default. + */ + if (context_dict != NULL) { + CTX_py_dict_set(C, (void *)context_dict); + } Py_XINCREF(context_dict); /* so we done loose it */ if (WM_operator_poll_context((bContext *)C, ot, context) == false) { diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 0941dd49d23..bea4faa779a 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -387,6 +387,18 @@ void wm_event_do_refresh_wm_and_depsgraph(bContext *C) CTX_wm_window_set(C, NULL); } +static void wm_event_execute_timers(bContext *C) +{ + wmWindowManager *wm = CTX_wm_manager(C); + + /* Set the first window as context, so that there is some minimal context. This avoids crashes + * when calling code that assumes that there is always a window in the context (which many + * operators do). */ + CTX_wm_window_set(C, wm->windows.first); + BLI_timer_execute(); + CTX_wm_window_set(C, NULL); +} + /* called in mainloop */ void wm_event_do_notifiers(bContext *C) { @@ -398,7 +410,7 @@ void wm_event_do_notifiers(bContext *C) return; } - BLI_timer_execute(); + wm_event_execute_timers(C); /* disable? - keep for now since its used for window level notifiers. */ #if 1 |