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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--intern/ffmpeg/tests/ffmpeg_codecs.cc4
-rw-r--r--release/scripts/presets/keyconfig/keymap_data/blender_default.py54
-rw-r--r--release/scripts/startup/bl_ui/properties_paint_common.py39
-rw-r--r--release/scripts/startup/bl_ui/space_toolsystem_toolbar.py53
-rw-r--r--release/scripts/startup/bl_ui/space_view3d.py53
-rw-r--r--source/blender/blenkernel/BKE_modifier.h6
-rw-r--r--source/blender/blenkernel/BKE_object.h2
-rw-r--r--source/blender/blenkernel/intern/data_transfer.c8
-rw-r--r--source/blender/blenkernel/intern/mesh.c10
-rw-r--r--source/blender/blenkernel/intern/modifier.c42
-rw-r--r--source/blender/blenkernel/intern/object.c6
-rw-r--r--source/blender/blenkernel/intern/object_dupli.c524
-rw-r--r--source/blender/blenlib/tests/BLI_path_util_test.cc4
-rw-r--r--source/blender/blenlib/tests/BLI_polyfill_2d_test.cc6
-rw-r--r--source/blender/blenlib/tests/performance/CMakeLists.txt4
-rw-r--r--source/blender/blenloader/intern/readfile.c2
-rw-r--r--source/blender/bmesh/intern/bmesh_query_uv.c14
-rw-r--r--source/blender/bmesh/intern/bmesh_query_uv.h2
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc2
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_modifier.cc22
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_modifier.h26
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.cc27
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.h4
-rw-r--r--source/blender/editors/gizmo_library/gizmo_types/snap3d_gizmo.c152
-rw-r--r--source/blender/editors/gpencil/gpencil_intern.h8
-rw-r--r--source/blender/editors/gpencil/gpencil_ops.c6
-rw-r--r--source/blender/editors/gpencil/gpencil_primitive.c231
-rw-r--r--source/blender/editors/mesh/meshtools.c2
-rw-r--r--source/blender/editors/screen/screen_edit.c1
-rw-r--r--source/blender/editors/uvedit/uvedit_intern.h1
-rw-r--r--source/blender/editors/uvedit/uvedit_ops.c16
-rw-r--r--source/blender/editors/uvedit/uvedit_select.c8
-rw-r--r--source/blender/makesdna/DNA_mesh_types.h9
-rw-r--r--source/blender/makesdna/DNA_modifier_types.h6
-rw-r--r--source/blender/modifiers/intern/MOD_datatransfer.c52
-rw-r--r--source/blender/modifiers/intern/MOD_normal_edit.c2
-rw-r--r--source/blender/modifiers/intern/MOD_uvproject.c2
-rw-r--r--source/blender/modifiers/intern/MOD_uvwarp.c2
-rw-r--r--source/blender/modifiers/intern/MOD_weighted_normal.c3
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgedit.c2
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgmix.c2
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgproximity.c2
-rw-r--r--source/blender/python/intern/bpy_operator.c9
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c14
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