From c822f66bb83eaa0baf90ce662375c0b0aefb9dec Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Mon, 7 Dec 2020 17:36:11 -0300 Subject: Fix T83307: Some modal keys of transform operators don't correspond to the expected effect The transform modes `shrinkfatten` and `seq_slide` have a special way of handling events. They use modal events in a different way than expected. Therefore, this commit adds special event handles for these modes and removes the keymodal tips from the status bar. These effects are already described in the header anyway. --- source/blender/editors/transform/transform.c | 18 ++++++++---------- .../transform/transform_mode_edge_seq_slide.c | 21 +++++++++++++++++++-- .../transform/transform_mode_shrink_fatten.c | 19 ++++++++++++++++++- 3 files changed, 45 insertions(+), 13 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 5969de5b5da..2b56b30be90 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -637,6 +637,14 @@ static bool transform_modal_item_poll(const wmOperator *op, int value) } break; } + case TFM_MODAL_TRANSLATE: + case TFM_MODAL_ROTATE: + case TFM_MODAL_RESIZE: { + if (!transform_mode_is_changeable(t->mode)) { + return false; + } + break; + } } return true; } @@ -876,11 +884,6 @@ int transformEvent(TransInfo *t, const wmEvent *event) handled = true; } } - else if (t->mode == TFM_SEQ_SLIDE) { - t->flag ^= T_ALT_TRANSFORM; - t->redraw |= TREDRAW_HARD; - handled = true; - } else if (transform_mode_is_changeable(t->mode)) { restoreTransObjects(t); resetTransModal(t); @@ -922,11 +925,6 @@ int transformEvent(TransInfo *t, const wmEvent *event) handled = true; } } - else if (t->mode == TFM_SHRINKFATTEN) { - t->flag ^= T_ALT_TRANSFORM; - t->redraw |= TREDRAW_HARD; - handled = true; - } else if (transform_mode_is_changeable(t->mode)) { /* Scale isn't normally very useful after extrude along normals, see T39756 */ if ((t->con.mode & CON_APPLY) && (t->orient[t->orient_curr].type == V3D_ORIENT_NORMAL)) { diff --git a/source/blender/editors/transform/transform_mode_edge_seq_slide.c b/source/blender/editors/transform/transform_mode_edge_seq_slide.c index dfa5c164acf..1682b5bfe31 100644 --- a/source/blender/editors/transform/transform_mode_edge_seq_slide.c +++ b/source/blender/editors/transform/transform_mode_edge_seq_slide.c @@ -32,6 +32,7 @@ #include "ED_screen.h" #include "WM_api.h" +#include "WM_types.h" #include "UI_interface.h" @@ -45,6 +46,18 @@ /** \name Transform (Sequencer Slide) * \{ */ +static eRedrawFlag seq_slide_handleEvent(struct TransInfo *t, const wmEvent *event) +{ + BLI_assert(t->mode == TFM_SEQ_SLIDE); + wmKeyMapItem *kmi = t->custom.mode.data; + if (event->type == kmi->type && event->val == kmi->val) { + /* Allows the 'Expand to fit' effect to be enabled as a toogle. */ + t->flag ^= T_ALT_TRANSFORM; + return TREDRAW_HARD; + } + return TREDRAW_NOTHING; +} + static void headerSeqSlide(TransInfo *t, const float val[2], char str[UI_MAX_DRAW_STR]) { char tvec[NUM_STR_REP_LEN * 3]; @@ -61,7 +74,7 @@ static void headerSeqSlide(TransInfo *t, const float val[2], char str[UI_MAX_DRA str + ofs, UI_MAX_DRAW_STR - ofs, TIP_("Sequence Slide: %s%s, ("), &tvec[0], t->con.text); if (t->keymap) { - wmKeyMapItem *kmi = WM_modalkeymap_find_propvalue(t->keymap, TFM_MODAL_TRANSLATE); + wmKeyMapItem *kmi = t->custom.mode.data; if (kmi) { ofs += WM_keymap_item_to_string(kmi, false, str + ofs, UI_MAX_DRAW_STR - ofs); } @@ -91,7 +104,7 @@ static void applySeqSlideValue(TransInfo *t, const float val[2]) static void applySeqSlide(TransInfo *t, const int mval[2]) { char str[UI_MAX_DRAW_STR]; - float values_final[2] = {0.0f}; + float values_final[3] = {0.0f}; snapSequenceBounds(t, mval); if (applyNumInput(&t->num, values_final)) { @@ -126,6 +139,7 @@ static void applySeqSlide(TransInfo *t, const int mval[2]) void initSeqSlide(TransInfo *t) { t->transform = applySeqSlide; + t->handleEvent = seq_slide_handleEvent; initMouseInputMode(t, &t->mouse, INPUT_VECTOR); @@ -142,5 +156,8 @@ void initSeqSlide(TransInfo *t) * (supporting frames in addition to "natural" time...). */ t->num.unit_type[0] = B_UNIT_NONE; t->num.unit_type[1] = B_UNIT_NONE; + + /* Workaround to use the same key as the modal keymap. */ + t->custom.mode.data = WM_modalkeymap_find_propvalue(t->keymap, TFM_MODAL_TRANSLATE); } /** \} */ diff --git a/source/blender/editors/transform/transform_mode_shrink_fatten.c b/source/blender/editors/transform/transform_mode_shrink_fatten.c index cdea388529f..6058a2824e9 100644 --- a/source/blender/editors/transform/transform_mode_shrink_fatten.c +++ b/source/blender/editors/transform/transform_mode_shrink_fatten.c @@ -32,6 +32,7 @@ #include "ED_screen.h" #include "WM_api.h" +#include "WM_types.h" #include "UI_interface.h" @@ -45,6 +46,18 @@ /** \name Transform (Shrink-Fatten) * \{ */ +static eRedrawFlag shrinkfatten_handleEvent(struct TransInfo *t, const wmEvent *event) +{ + BLI_assert(t->mode == TFM_SHRINKFATTEN); + wmKeyMapItem *kmi = t->custom.mode.data; + if (event->type == kmi->type && event->val == kmi->val) { + /* Allows the 'Even Thickness' effect to be enabled as a toogle. */ + t->flag ^= T_ALT_TRANSFORM; + return TREDRAW_HARD; + } + return TREDRAW_NOTHING; +} + static void applyShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) { float distance; @@ -78,7 +91,7 @@ static void applyShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) ofs += BLI_strncpy_rlen(str + ofs, ", (", sizeof(str) - ofs); if (t->keymap) { - wmKeyMapItem *kmi = WM_modalkeymap_find_propvalue(t->keymap, TFM_MODAL_RESIZE); + wmKeyMapItem *kmi = t->custom.mode.data; if (kmi) { ofs += WM_keymap_item_to_string(kmi, false, str + ofs, sizeof(str) - ofs); } @@ -121,6 +134,7 @@ void initShrinkFatten(TransInfo *t) else { t->mode = TFM_SHRINKFATTEN; t->transform = applyShrinkFatten; + t->handleEvent = shrinkfatten_handleEvent; initMouseInputMode(t, &t->mouse, INPUT_VERTICAL_ABSOLUTE); @@ -134,6 +148,9 @@ void initShrinkFatten(TransInfo *t) t->num.unit_type[0] = B_UNIT_LENGTH; t->flag |= T_NO_CONSTRAINT; + + /* Workaround to use the same key as the modal keymap. */ + t->custom.mode.data = WM_modalkeymap_find_propvalue(t->keymap, TFM_MODAL_RESIZE); } } /** \} */ -- cgit v1.2.3 From 41e236c527368273fa1c171fe5c596a37823230c Mon Sep 17 00:00:00 2001 From: Yevgeny Makarov Date: Mon, 7 Dec 2020 13:46:01 -0800 Subject: UI: Correct Usage of 'Eevee' Name Use accepted capitalization of Eevee, not 'EEVEE'. Differential Revision: https://developer.blender.org/D9770 Reviewed by Julian Eisel --- source/blender/makesrna/intern/rna_scene.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source/blender') diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 08b3d4f210e..1c284468608 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -3993,7 +3993,7 @@ static void rna_def_view_layer_eevee(BlenderRNA *brna) StructRNA *srna; PropertyRNA *prop; srna = RNA_def_struct(brna, "ViewLayerEEVEE", NULL); - RNA_def_struct_ui_text(srna, "EEVEE Settings", "View layer settings for EEVEE"); + RNA_def_struct_ui_text(srna, "Eevee Settings", "View layer settings for Eevee"); prop = RNA_def_property(srna, "use_pass_volume_scatter", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "render_passes", EEVEE_RENDER_PASS_VOLUME_SCATTER); @@ -4088,7 +4088,7 @@ void rna_def_view_layer_common(StructRNA *srna, const bool scene) prop = RNA_def_property(srna, "eevee", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_struct_type(prop, "ViewLayerEEVEE"); - RNA_def_property_ui_text(prop, "EEVEE Settings", "View layer settings for EEVEE"); + RNA_def_property_ui_text(prop, "Eevee Settings", "View layer settings for Eevee"); prop = RNA_def_property(srna, "aovs", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "aovs", NULL); @@ -7958,7 +7958,7 @@ void RNA_def_scene(BlenderRNA *brna) /* EEVEE */ prop = RNA_def_property(srna, "eevee", PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, "SceneEEVEE"); - RNA_def_property_ui_text(prop, "EEVEE", "EEVEE settings for the scene"); + RNA_def_property_ui_text(prop, "Eevee", "Eevee settings for the scene"); /* Grease Pencil */ prop = RNA_def_property(srna, "grease_pencil_settings", PROP_POINTER, PROP_NONE); -- cgit v1.2.3 From ab9952e55fe1bfe84e157cd25c90f9bed3bea6aa Mon Sep 17 00:00:00 2001 From: Yevgeny Makarov Date: Mon, 7 Dec 2020 14:51:06 -0800 Subject: Spelling: Bit Depth Compound Modifiers Correct usage of compound modifiers like '32-bit'. Differential Revision: https://developer.blender.org/D9769 Reviewed by Julian Eisel --- .../editors/sculpt_paint/paint_image_proj.c | 2 +- source/blender/editors/sound/sound_ops.c | 32 +++++++++++----------- source/blender/editors/space_image/image_ops.c | 4 +-- source/blender/makesrna/intern/rna_ID.c | 4 +-- source/blender/makesrna/intern/rna_attribute.c | 8 +++--- source/blender/makesrna/intern/rna_image.c | 2 +- source/blender/makesrna/intern/rna_scene.c | 24 ++++++++-------- source/blender/makesrna/intern/rna_userdef.c | 12 ++++---- source/blender/makesrna/intern/rna_volume.c | 4 +-- 9 files changed, 46 insertions(+), 46 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c index 8c16300a047..98f4b4013cb 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.c +++ b/source/blender/editors/sculpt_paint/paint_image_proj.c @@ -6748,7 +6748,7 @@ void PAINT_OT_add_texture_paint_slot(wmOperatorType *ot) "Generated Type", "Fill the image with a grid for UV map testing"); RNA_def_boolean( - ot->srna, "float", 0, "32 bit Float", "Create image with 32 bit floating point bit depth"); + ot->srna, "float", 0, "32-bit Float", "Create image with 32-bit floating-point bit depth"); } static int add_simple_uvs_exec(bContext *C, wmOperator *UNUSED(op)) diff --git a/source/blender/editors/sound/sound_ops.c b/source/blender/editors/sound/sound_ops.c index c6961cc9d4b..8dac90c2346 100644 --- a/source/blender/editors/sound/sound_ops.c +++ b/source/blender/editors/sound/sound_ops.c @@ -518,27 +518,27 @@ static bool sound_mixdown_draw_check_prop(PointerRNA *UNUSED(ptr), static void sound_mixdown_draw(bContext *C, wmOperator *op) { static const EnumPropertyItem pcm_format_items[] = { - {AUD_FORMAT_U8, "U8", 0, "U8", "8 bit unsigned"}, - {AUD_FORMAT_S16, "S16", 0, "S16", "16 bit signed"}, + {AUD_FORMAT_U8, "U8", 0, "U8", "8-bit unsigned"}, + {AUD_FORMAT_S16, "S16", 0, "S16", "16-bit signed"}, # ifdef WITH_SNDFILE - {AUD_FORMAT_S24, "S24", 0, "S24", "24 bit signed"}, + {AUD_FORMAT_S24, "S24", 0, "S24", "24-bit signed"}, # endif - {AUD_FORMAT_S32, "S32", 0, "S32", "32 bit signed"}, - {AUD_FORMAT_FLOAT32, "F32", 0, "F32", "32 bit floating point"}, - {AUD_FORMAT_FLOAT64, "F64", 0, "F64", "64 bit floating point"}, + {AUD_FORMAT_S32, "S32", 0, "S32", "32-bit signed"}, + {AUD_FORMAT_FLOAT32, "F32", 0, "F32", "32-bit floating-point"}, + {AUD_FORMAT_FLOAT64, "F64", 0, "F64", "64-bit floating-point"}, {0, NULL, 0, NULL, NULL}, }; static const EnumPropertyItem mp3_format_items[] = { - {AUD_FORMAT_S16, "S16", 0, "S16", "16 bit signed"}, - {AUD_FORMAT_S32, "S32", 0, "S32", "32 bit signed"}, + {AUD_FORMAT_S16, "S16", 0, "S16", "16-bit signed"}, + {AUD_FORMAT_S32, "S32", 0, "S32", "32-bit signed"}, {0, NULL, 0, NULL, NULL}, }; # ifdef WITH_SNDFILE static const EnumPropertyItem flac_format_items[] = { - {AUD_FORMAT_S16, "S16", 0, "S16", "16 bit signed"}, - {AUD_FORMAT_S24, "S24", 0, "S24", "24 bit signed"}, + {AUD_FORMAT_S16, "S16", 0, "S16", "16-bit signed"}, + {AUD_FORMAT_S24, "S24", 0, "S24", "24-bit signed"}, {0, NULL, 0, NULL, NULL}, }; # endif @@ -672,12 +672,12 @@ static void SOUND_OT_mixdown(wmOperatorType *ot) { #ifdef WITH_AUDASPACE static const EnumPropertyItem format_items[] = { - {AUD_FORMAT_U8, "U8", 0, "U8", "8 bit unsigned"}, - {AUD_FORMAT_S16, "S16", 0, "S16", "16 bit signed"}, - {AUD_FORMAT_S24, "S24", 0, "S24", "24 bit signed"}, - {AUD_FORMAT_S32, "S32", 0, "S32", "32 bit signed"}, - {AUD_FORMAT_FLOAT32, "F32", 0, "F32", "32 bit floating point"}, - {AUD_FORMAT_FLOAT64, "F64", 0, "F64", "64 bit floating point"}, + {AUD_FORMAT_U8, "U8", 0, "U8", "8-bit unsigned"}, + {AUD_FORMAT_S16, "S16", 0, "S16", "16-bit signed"}, + {AUD_FORMAT_S24, "S24", 0, "S24", "24-bit signed"}, + {AUD_FORMAT_S32, "S32", 0, "S32", "32-bit signed"}, + {AUD_FORMAT_FLOAT32, "F32", 0, "F32", "32-bit floating-point"}, + {AUD_FORMAT_FLOAT64, "F64", 0, "F64", "64-bit floating-point"}, {0, NULL, 0, NULL, NULL}, }; diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 0fa48059cdc..a2c0819dc60 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -2649,7 +2649,7 @@ void IMAGE_OT_new(wmOperatorType *ot) "Generated Type", "Fill the image with a grid for UV map testing"); RNA_def_boolean( - ot->srna, "float", 0, "32 bit Float", "Create image with 32 bit floating point bit depth"); + ot->srna, "float", 0, "32-bit Float", "Create image with 32-bit floating-point bit depth"); RNA_def_property_flag(prop, PROP_HIDDEN); prop = RNA_def_boolean( ot->srna, "use_stereo_3d", 0, "Stereo 3D", "Create an image with left and right views"); @@ -3737,7 +3737,7 @@ static void def_fill_tile(StructOrFunctionRNA *srna) /* Only needed when filling the first tile. */ RNA_def_boolean( - srna, "float", 0, "32 bit Float", "Create image with 32 bit floating point bit depth"); + srna, "float", 0, "32-bit Float", "Create image with 32-bit floating-point bit depth"); RNA_def_boolean(srna, "alpha", 1, "Alpha", "Create an image with an alpha channel"); } diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c index cb316e56a68..d0e0b69a8d5 100644 --- a/source/blender/makesrna/intern/rna_ID.c +++ b/source/blender/makesrna/intern/rna_ID.c @@ -1188,7 +1188,7 @@ static void rna_def_image_preview(BlenderRNA *brna) prop = RNA_def_property(srna, "image_pixels", PROP_INT, PROP_NONE); RNA_def_property_flag(prop, PROP_DYNAMIC); RNA_def_property_multi_array(prop, 1, NULL); - RNA_def_property_ui_text(prop, "Image Pixels", "Image pixels, as bytes (always RGBA 32bits)"); + RNA_def_property_ui_text(prop, "Image Pixels", "Image pixels, as bytes (always 32-bit RGBA)"); RNA_def_property_dynamic_array_funcs(prop, "rna_ImagePreview_image_pixels_get_length"); RNA_def_property_int_funcs( prop, "rna_ImagePreview_image_pixels_get", "rna_ImagePreview_image_pixels_set", NULL); @@ -1221,7 +1221,7 @@ static void rna_def_image_preview(BlenderRNA *brna) prop = RNA_def_property(srna, "icon_pixels", PROP_INT, PROP_NONE); RNA_def_property_flag(prop, PROP_DYNAMIC); RNA_def_property_multi_array(prop, 1, NULL); - RNA_def_property_ui_text(prop, "Icon Pixels", "Icon pixels, as bytes (always RGBA 32bits)"); + RNA_def_property_ui_text(prop, "Icon Pixels", "Icon pixels, as bytes (always 32-bit RGBA)"); RNA_def_property_dynamic_array_funcs(prop, "rna_ImagePreview_icon_pixels_get_length"); RNA_def_property_int_funcs( prop, "rna_ImagePreview_icon_pixels_get", "rna_ImagePreview_icon_pixels_set", NULL); diff --git a/source/blender/makesrna/intern/rna_attribute.c b/source/blender/makesrna/intern/rna_attribute.c index ad615026343..95f6340174a 100644 --- a/source/blender/makesrna/intern/rna_attribute.c +++ b/source/blender/makesrna/intern/rna_attribute.c @@ -38,10 +38,10 @@ #include "WM_types.h" const EnumPropertyItem rna_enum_attribute_type_items[] = { - {CD_PROP_FLOAT, "FLOAT", 0, "Float", "Floating point value"}, - {CD_PROP_INT32, "INT", 0, "Integer", "32 bit integer"}, - {CD_PROP_FLOAT3, "FLOAT_VECTOR", 0, "Vector", "3D vector with floating point values"}, - {CD_PROP_COLOR, "FLOAT_COLOR", 0, "Float Color", "RGBA color with floating point precisions"}, + {CD_PROP_FLOAT, "FLOAT", 0, "Float", "Floating-point value"}, + {CD_PROP_INT32, "INT", 0, "Integer", "32-bit integer"}, + {CD_PROP_FLOAT3, "FLOAT_VECTOR", 0, "Vector", "3D vector with floating-point values"}, + {CD_PROP_COLOR, "FLOAT_COLOR", 0, "Float Color", "RGBA color with floating-point precisions"}, {CD_MLOOPCOL, "BYTE_COLOR", 0, "Byte Color", "RGBA color with 8-bit precision"}, {CD_PROP_STRING, "STRING", 0, "String", "Text string"}, {0, NULL, 0, NULL, NULL}, diff --git a/source/blender/makesrna/intern/rna_image.c b/source/blender/makesrna/intern/rna_image.c index 504a4a6bdf3..2373045d95a 100644 --- a/source/blender/makesrna/intern/rna_image.c +++ b/source/blender/makesrna/intern/rna_image.c @@ -1136,7 +1136,7 @@ static void rna_def_image(BlenderRNA *brna) RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", IMA_HIGH_BITDEPTH); RNA_def_property_ui_text(prop, "Half Float Precision", - "Use 16bits per channel to lower the memory usage during rendering"); + "Use 16 bits per channel to lower the memory usage during rendering"); RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_gpu_texture_update"); /* multiview */ diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 1c284468608..dc0876f2512 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -390,7 +390,7 @@ const EnumPropertyItem rna_enum_image_color_mode_items[] = { "BW", 0, "BW", - "Images get saved in 8 bits grayscale (only PNG, JPEG, TGA, TIF)"}, + "Images get saved in 8-bit grayscale (only PNG, JPEG, TGA, TIF)"}, {R_IMF_PLANES_RGB, "RGB", 0, "RGB", "Images are saved with RGB (color) data"}, {R_IMF_PLANES_RGBA, "RGBA", @@ -408,12 +408,12 @@ const EnumPropertyItem rna_enum_image_color_mode_items[] = { const EnumPropertyItem rna_enum_image_color_depth_items[] = { /* 1 (monochrome) not used */ - {R_IMF_CHAN_DEPTH_8, "8", 0, "8", "8 bit color channels"}, - {R_IMF_CHAN_DEPTH_10, "10", 0, "10", "10 bit color channels"}, - {R_IMF_CHAN_DEPTH_12, "12", 0, "12", "12 bit color channels"}, - {R_IMF_CHAN_DEPTH_16, "16", 0, "16", "16 bit color channels"}, + {R_IMF_CHAN_DEPTH_8, "8", 0, "8", "8-bit color channels"}, + {R_IMF_CHAN_DEPTH_10, "10", 0, "10", "10-bit color channels"}, + {R_IMF_CHAN_DEPTH_12, "12", 0, "12", "12-bit color channels"}, + {R_IMF_CHAN_DEPTH_16, "16", 0, "16", "16-bit color channels"}, /* 24 not used */ - {R_IMF_CHAN_DEPTH_32, "32", 0, "32", "32 bit color channels"}, + {R_IMF_CHAN_DEPTH_32, "32", 0, "32", "32-bit color channels"}, {0, NULL, 0, NULL, NULL}, }; @@ -5487,7 +5487,7 @@ static void rna_def_scene_image_format_data(BlenderRNA *brna) prop = RNA_def_property(srna, "use_zbuffer", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", R_IMF_FLAG_ZBUF); RNA_def_property_ui_text( - prop, "Z Buffer", "Save the z-depth per pixel (32 bit unsigned int z-buffer)"); + prop, "Z Buffer", "Save the z-depth per pixel (32-bit unsigned integer z-buffer)"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); prop = RNA_def_property(srna, "use_preview", PROP_BOOLEAN, PROP_NONE); @@ -5723,26 +5723,26 @@ static void rna_def_scene_ffmpeg_settings(BlenderRNA *brna) prop = RNA_def_property(srna, "video_bitrate", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "video_bitrate"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_ui_text(prop, "Bitrate", "Video bitrate (kb/s)"); + RNA_def_property_ui_text(prop, "Bitrate", "Video bitrate (kbit/s)"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); prop = RNA_def_property(srna, "minrate", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "rc_min_rate"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_ui_text(prop, "Min Rate", "Rate control: min rate (kb/s)"); + RNA_def_property_ui_text(prop, "Min Rate", "Rate control: min rate (kbit/s)"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); prop = RNA_def_property(srna, "maxrate", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "rc_max_rate"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_ui_text(prop, "Max Rate", "Rate control: max rate (kb/s)"); + RNA_def_property_ui_text(prop, "Max Rate", "Rate control: max rate (kbit/s)"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); prop = RNA_def_property(srna, "muxrate", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "mux_rate"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_range(prop, 0, 100000000); - RNA_def_property_ui_text(prop, "Mux Rate", "Mux rate (bits/s(!))"); + RNA_def_property_ui_text(prop, "Mux Rate", "Mux rate (bits/second)"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); prop = RNA_def_property(srna, "gopsize", PROP_INT, PROP_NONE); @@ -7423,7 +7423,7 @@ static void rna_def_scene_eevee(BlenderRNA *brna) prop = RNA_def_property(srna, "use_shadow_high_bitdepth", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SCE_EEVEE_SHADOW_HIGH_BITDEPTH); - RNA_def_property_ui_text(prop, "High Bitdepth", "Use 32bit shadows"); + RNA_def_property_ui_text(prop, "High Bit Depth", "Use 32-bit shadows"); RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 628eff54032..f1f7810bcf0 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -5273,12 +5273,12 @@ static void rna_def_userdef_system(BlenderRNA *brna) }; static const EnumPropertyItem audio_format_items[] = { - {0x01, "U8", 0, "8-bit Unsigned", "Set audio sample format to 8 bit unsigned integer"}, - {0x12, "S16", 0, "16-bit Signed", "Set audio sample format to 16 bit signed integer"}, - {0x13, "S24", 0, "24-bit Signed", "Set audio sample format to 24 bit signed integer"}, - {0x14, "S32", 0, "32-bit Signed", "Set audio sample format to 32 bit signed integer"}, - {0x24, "FLOAT", 0, "32-bit Float", "Set audio sample format to 32 bit float"}, - {0x28, "DOUBLE", 0, "64-bit Float", "Set audio sample format to 64 bit float"}, + {0x01, "U8", 0, "8-bit Unsigned", "Set audio sample format to 8-bit unsigned integer"}, + {0x12, "S16", 0, "16-bit Signed", "Set audio sample format to 16-bit signed integer"}, + {0x13, "S24", 0, "24-bit Signed", "Set audio sample format to 24-bit signed integer"}, + {0x14, "S32", 0, "32-bit Signed", "Set audio sample format to 32-bit signed integer"}, + {0x24, "FLOAT", 0, "32-bit Float", "Set audio sample format to 32-bit float"}, + {0x28, "DOUBLE", 0, "64-bit Float", "Set audio sample format to 64-bit float"}, {0, NULL, 0, NULL, NULL}, }; diff --git a/source/blender/makesrna/intern/rna_volume.c b/source/blender/makesrna/intern/rna_volume.c index 37b34f68be5..42d491b734e 100644 --- a/source/blender/makesrna/intern/rna_volume.c +++ b/source/blender/makesrna/intern/rna_volume.c @@ -228,8 +228,8 @@ static void rna_def_volume_grid(BlenderRNA *brna) {VOLUME_GRID_BOOLEAN, "BOOLEAN", 0, "Boolean", "Boolean"}, {VOLUME_GRID_FLOAT, "FLOAT", 0, "Float", "Single precision float"}, {VOLUME_GRID_DOUBLE, "DOUBLE", 0, "Double", "Double precision"}, - {VOLUME_GRID_INT, "INT", 0, "Integer", "32 bit integer"}, - {VOLUME_GRID_INT64, "INT64", 0, "Integer 64 bit", "64 bit integer"}, + {VOLUME_GRID_INT, "INT", 0, "Integer", "32-bit integer"}, + {VOLUME_GRID_INT64, "INT64", 0, "Integer 64-bit", "64-bit integer"}, {VOLUME_GRID_MASK, "MASK", 0, "Mask", "No data, boolean mask of active voxels"}, {VOLUME_GRID_STRING, "STRING", 0, "String", "Text string"}, {VOLUME_GRID_VECTOR_FLOAT, "VECTOR_FLOAT", 0, "Float Vector", "3D float vector"}, -- cgit v1.2.3 From 5f1a155a5ef39a4db144b38a607c19b763f965a3 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 8 Dec 2020 12:14:27 +1100 Subject: Fix T83117: Curve bevel not handle aligned at end-points Caused by fix for T80742, 4987b7d347a885916916a888c18401ea2fe552f4. Keep the fix that calculates the start/end direction from adjacent points but only use it as a fallback. --- source/blender/blenkernel/intern/curve.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index 2df9f362b9c..ebce28c4e23 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -2185,19 +2185,28 @@ static void bevel_list_calc_bisect(BevList *bl) bevp2++; } + /* In the unlikely situation that handles define a zeroed direction, + * calculate it from the adjacent points, see T80742. + * + * Only do this as a fallback since we typically want the end-point directions + * to be exactly aligned with the handles at the end-point, see T83117. */ if (is_cyclic == false) { bevp0 = &bl->bevpoints[0]; bevp1 = &bl->bevpoints[1]; - sub_v3_v3v3(bevp0->dir, bevp1->vec, bevp0->vec); - if (normalize_v3(bevp0->dir) == 0.0f) { - copy_v3_v3(bevp0->dir, bevp1->dir); + if (UNLIKELY(is_zero_v3(bevp0->dir))) { + sub_v3_v3v3(bevp0->dir, bevp1->vec, bevp0->vec); + if (normalize_v3(bevp0->dir) == 0.0f) { + copy_v3_v3(bevp0->dir, bevp1->dir); + } } bevp0 = &bl->bevpoints[bl->nr - 2]; bevp1 = &bl->bevpoints[bl->nr - 1]; - sub_v3_v3v3(bevp1->dir, bevp1->vec, bevp0->vec); - if (normalize_v3(bevp1->dir) == 0.0f) { - copy_v3_v3(bevp1->dir, bevp0->dir); + if (UNLIKELY(is_zero_v3(bevp1->dir))) { + sub_v3_v3v3(bevp1->dir, bevp1->vec, bevp0->vec); + if (normalize_v3(bevp1->dir) == 0.0f) { + copy_v3_v3(bevp1->dir, bevp0->dir); + } } } } -- cgit v1.2.3 From 682ccd770c629402b771491d45a0523f75750f30 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Tue, 8 Dec 2020 09:40:42 +0100 Subject: LibOverride: Refactor collection items 'local' helper functions. It's easier to read and less 'weird' to check that an item is non-local in a liboverride data-block, than the other way around. Thanks to @sybren for noticing it. --- source/blender/blenkernel/BKE_constraint.h | 4 ++-- source/blender/blenkernel/BKE_gpencil_modifier.h | 4 ++-- source/blender/blenkernel/BKE_modifier.h | 3 ++- source/blender/blenkernel/intern/constraint.c | 6 +++--- source/blender/blenkernel/intern/gpencil_modifier.c | 12 ++++++------ source/blender/blenkernel/intern/modifier.c | 6 +++--- source/blender/editors/object/object_constraint.c | 5 +++-- source/blender/editors/object/object_gpencil_modifier.c | 6 +++--- source/blender/editors/object/object_modifier.c | 5 +++-- 9 files changed, 27 insertions(+), 24 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/BKE_constraint.h b/source/blender/blenkernel/BKE_constraint.h index 1589bff7501..7a14787c191 100644 --- a/source/blender/blenkernel/BKE_constraint.h +++ b/source/blender/blenkernel/BKE_constraint.h @@ -177,8 +177,8 @@ struct bConstraint *BKE_constraint_find_from_target(struct Object *ob, struct bConstraintTarget *tgt, struct bPoseChannel **r_pchan); -bool BKE_constraint_is_local_in_liboverride(const struct Object *ob, - const struct bConstraint *con); +bool BKE_constraint_is_nonlocal_in_liboverride(const struct Object *ob, + const struct bConstraint *con); struct bConstraint *BKE_constraint_add_for_object(struct Object *ob, const char *name, short type); struct bConstraint *BKE_constraint_add_for_pose(struct Object *ob, diff --git a/source/blender/blenkernel/BKE_gpencil_modifier.h b/source/blender/blenkernel/BKE_gpencil_modifier.h index bdc583048b8..ccf65a585ef 100644 --- a/source/blender/blenkernel/BKE_gpencil_modifier.h +++ b/source/blender/blenkernel/BKE_gpencil_modifier.h @@ -278,8 +278,8 @@ void BKE_gpencil_modifiers_foreach_tex_link(struct Object *ob, GreasePencilTexWalkFunc walk, void *userData); -bool BKE_gpencil_modifier_is_local_in_liboverride(const struct Object *ob, - const struct GpencilModifierData *gmd); +bool BKE_gpencil_modifier_is_nonlocal_in_liboverride(const struct Object *ob, + const struct GpencilModifierData *gmd); typedef struct GpencilVirtualModifierData { ArmatureGpencilModifierData amd; diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h index 37f566d6f8e..73e33124b43 100644 --- a/source/blender/blenkernel/BKE_modifier.h +++ b/source/blender/blenkernel/BKE_modifier.h @@ -431,7 +431,8 @@ bool BKE_modifier_is_non_geometrical(ModifierData *md); bool BKE_modifier_is_enabled(const struct Scene *scene, struct ModifierData *md, int required_mode); -bool BKE_modifier_is_local_in_liboverride(const struct Object *ob, const struct ModifierData *md); +bool BKE_modifier_is_nonlocal_in_liboverride(const struct Object *ob, + const struct ModifierData *md); void BKE_modifier_set_error(const struct Object *ob, struct ModifierData *md, const char *format, diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 982e91dd1e0..d9135572159 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -5963,10 +5963,10 @@ static bConstraint *constraint_find_original_for_update(bConstraintOb *cob, bCon * * \note This check is only valid for a liboverride data-block, it always return \a true otherwise. */ -bool BKE_constraint_is_local_in_liboverride(const Object *ob, const bConstraint *con) +bool BKE_constraint_is_nonlocal_in_liboverride(const Object *ob, const bConstraint *con) { - return (!ID_IS_OVERRIDE_LIBRARY(ob) || - (con != NULL && (con->flag & CONSTRAINT_OVERRIDE_LIBRARY_LOCAL) != 0)); + return (ID_IS_OVERRIDE_LIBRARY(ob) && + (con == NULL || (con->flag & CONSTRAINT_OVERRIDE_LIBRARY_LOCAL) == 0)); } /* -------- Constraints and Proxies ------- */ diff --git a/source/blender/blenkernel/intern/gpencil_modifier.c b/source/blender/blenkernel/intern/gpencil_modifier.c index 7425a1a5f7a..ac81e4a5470 100644 --- a/source/blender/blenkernel/intern/gpencil_modifier.c +++ b/source/blender/blenkernel/intern/gpencil_modifier.c @@ -531,16 +531,16 @@ void BKE_gpencil_modifier_set_error(GpencilModifierData *md, const char *_format } /** - * Check whether given modifier is local when the object is a library override. + * Check whether given modifier is not local (i.e. from linked data) when the object is a library + * override. * * \param gmd May be NULL, in which case we consider it as a non-local modifier case. - * - * \note This check is only valid for a liboverride data-block, it always return \a true otherwise. */ -bool BKE_gpencil_modifier_is_local_in_liboverride(const Object *ob, const GpencilModifierData *gmd) +bool BKE_gpencil_modifier_is_nonlocal_in_liboverride(const Object *ob, + const GpencilModifierData *gmd) { - return (!ID_IS_OVERRIDE_LIBRARY(ob) || - (gmd != NULL && (gmd->flag & eGpencilModifierFlag_OverrideLibrary_Local) != 0)); + return (ID_IS_OVERRIDE_LIBRARY(ob) && + (gmd == NULL || (gmd->flag & eGpencilModifierFlag_OverrideLibrary_Local) == 0)); } /** diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 7865d44c446..405de3bdca1 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -581,10 +581,10 @@ bool BKE_modifier_is_enabled(const struct Scene *scene, ModifierData *md, int re * * \note This check is only valid for a liboverride data-block, it always return \a true otherwise. */ -bool BKE_modifier_is_local_in_liboverride(const Object *ob, const ModifierData *md) +bool BKE_modifier_is_nonlocal_in_liboverride(const Object *ob, const ModifierData *md) { - return (!ID_IS_OVERRIDE_LIBRARY(ob) || - (md != NULL && (md->flag & eModifierFlag_OverrideLibrary_Local) != 0)); + return (ID_IS_OVERRIDE_LIBRARY(ob) && + (md == NULL || (md->flag & eModifierFlag_OverrideLibrary_Local) == 0)); } CDMaskLink *BKE_modifier_calc_data_masks(struct Scene *scene, diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c index e684ad03f53..dd015f59e8d 100644 --- a/source/blender/editors/object/object_constraint.c +++ b/source/blender/editors/object/object_constraint.c @@ -706,8 +706,9 @@ static bool edit_constraint_poll_generic(bContext *C, return false; } - if (!is_liboverride_allowed && !BKE_constraint_is_local_in_liboverride(ob, con)) { - CTX_wm_operator_poll_msg_set(C, "Cannot edit constraints coming from library override"); + if (!is_liboverride_allowed && BKE_constraint_is_nonlocal_in_liboverride(ob, con)) { + CTX_wm_operator_poll_msg_set( + C, "Cannot edit constraints coming from linked data in a library override"); return false; } diff --git a/source/blender/editors/object/object_gpencil_modifier.c b/source/blender/editors/object/object_gpencil_modifier.c index d3f165678c3..af95f5581bd 100644 --- a/source/blender/editors/object/object_gpencil_modifier.c +++ b/source/blender/editors/object/object_gpencil_modifier.c @@ -443,9 +443,9 @@ static bool gpencil_edit_modifier_poll_generic(bContext *C, return false; } - if (!is_liboverride_allowed && - (mod == NULL || !BKE_gpencil_modifier_is_local_in_liboverride(ob, mod))) { - CTX_wm_operator_poll_msg_set(C, "Cannot edit modifiers coming from library override"); + if (!is_liboverride_allowed && BKE_gpencil_modifier_is_nonlocal_in_liboverride(ob, mod)) { + CTX_wm_operator_poll_msg_set( + C, "Cannot edit modifiers coming from linked data in a library override"); return false; } diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index bb4581b0ee8..3111003703f 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -1052,8 +1052,9 @@ bool edit_modifier_poll_generic(bContext *C, return false; } - if (!is_liboverride_allowed && !BKE_modifier_is_local_in_liboverride(ob, mod)) { - CTX_wm_operator_poll_msg_set(C, "Cannot edit modifiers coming from library override"); + if (!is_liboverride_allowed && BKE_modifier_is_nonlocal_in_liboverride(ob, mod)) { + CTX_wm_operator_poll_msg_set( + C, "Cannot edit modifiers coming from linked data in a library override"); return false; } -- cgit v1.2.3 From 922b8abea5f83d5465ef861b3efbd95c6c2b1908 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Tue, 8 Dec 2020 09:47:56 +0100 Subject: Cleanup: LibOverride: Forgot to update comments in previous commit. --- source/blender/blenkernel/intern/constraint.c | 5 ++--- source/blender/blenkernel/intern/modifier.c | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index d9135572159..1c17692ac36 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -5957,11 +5957,10 @@ static bConstraint *constraint_find_original_for_update(bConstraintOb *cob, bCon } /** - * Check whether given constraint is local when the object is a library override. + * Check whether given constraint is not local (i.e. from linked data) when the object is a library + * override. * * \param con May be NULL, in which case we consider it as a non-local constraint case. - * - * \note This check is only valid for a liboverride data-block, it always return \a true otherwise. */ bool BKE_constraint_is_nonlocal_in_liboverride(const Object *ob, const bConstraint *con) { diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 405de3bdca1..3496e05c6e5 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -575,11 +575,10 @@ bool BKE_modifier_is_enabled(const struct Scene *scene, ModifierData *md, int re } /** - * Check whether given modifier is local when the object is a library override. + * Check whether given modifier is not local (i.e. from linked data) when the object is a library + * override. * * \param md May be NULL, in which case we consider it as a non-local modifier case. - * - * \note This check is only valid for a liboverride data-block, it always return \a true otherwise. */ bool BKE_modifier_is_nonlocal_in_liboverride(const Object *ob, const ModifierData *md) { -- cgit v1.2.3 From d9918e3e53ff94a4e95072251594677ea88fb54e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 8 Dec 2020 20:43:42 +1100 Subject: shaders_test: correct arguments to EEVEE_shaders_cryptomatte_sh_get --- source/blender/draw/tests/shaders_test.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source/blender') diff --git a/source/blender/draw/tests/shaders_test.cc b/source/blender/draw/tests/shaders_test.cc index 6674e3eccc1..d365f76aabe 100644 --- a/source/blender/draw/tests/shaders_test.cc +++ b/source/blender/draw/tests/shaders_test.cc @@ -332,8 +332,8 @@ TEST_F(DrawTest, eevee_glsl_shaders_static) EXPECT_NE(EEVEE_shaders_probe_grid_fill_sh_get(), nullptr); EXPECT_NE(EEVEE_shaders_probe_planar_downsample_sh_get(), nullptr); EXPECT_NE(EEVEE_shaders_renderpasses_post_process_sh_get(), nullptr); - EXPECT_NE(EEVEE_shaders_cryptomatte_sh_get(index, false), nullptr); - EXPECT_NE(EEVEE_shaders_cryptomatte_sh_get(index, true), nullptr); + EXPECT_NE(EEVEE_shaders_cryptomatte_sh_get(false), nullptr); + EXPECT_NE(EEVEE_shaders_cryptomatte_sh_get(true), nullptr); EXPECT_NE(EEVEE_shaders_shadow_sh_get(), nullptr); EXPECT_NE(EEVEE_shaders_shadow_accum_sh_get(), nullptr); EXPECT_NE(EEVEE_shaders_subsurface_first_pass_sh_get(), nullptr); -- cgit v1.2.3 From f43c9499bfccbfaf7add1d57407150b1871c2f66 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 8 Dec 2020 20:44:45 +1100 Subject: Cleanup: use static declarations --- source/blender/editors/space_view3d/view3d_placement.c | 2 +- source/blender/makesrna/intern/rna_scene.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/space_view3d/view3d_placement.c b/source/blender/editors/space_view3d/view3d_placement.c index 6d10aa5f957..7e8ed276766 100644 --- a/source/blender/editors/space_view3d/view3d_placement.c +++ b/source/blender/editors/space_view3d/view3d_placement.c @@ -72,7 +72,7 @@ static void preview_plane_cursor_visible_set(wmGizmoGroup *gzgroup, bool do_draw * In this case we can't usefully project the mouse cursor onto the plane, * so use a fall-back plane instead. */ -const float eps_view_align = 1e-2f; +static const float eps_view_align = 1e-2f; /* -------------------------------------------------------------------- */ /** \name Local Types diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index dc0876f2512..da03921bca6 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -529,7 +529,7 @@ const EnumPropertyItem rna_enum_bake_pass_filter_type_items[] = { {0, NULL, 0, NULL, NULL}, }; -const EnumPropertyItem rna_enum_view_layer_aov_type_items[] = { +static const EnumPropertyItem rna_enum_view_layer_aov_type_items[] = { {AOV_TYPE_COLOR, "COLOR", 0, "Color", ""}, {AOV_TYPE_VALUE, "VALUE", 0, "Value", ""}, {0, NULL, 0, NULL, NULL}, -- cgit v1.2.3 From 276f6840eddd5e14958b66b9b0c5440eb59de523 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 8 Dec 2020 20:47:32 +1100 Subject: CMake: fix linking with WITH_SDL_DYNLOAD While this was only needed in 'source/blender/python', add to ghost to avoid problems in the future. --- source/blender/python/intern/CMakeLists.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'source/blender') diff --git a/source/blender/python/intern/CMakeLists.txt b/source/blender/python/intern/CMakeLists.txt index 772b31fd9d8..5d8330e368d 100644 --- a/source/blender/python/intern/CMakeLists.txt +++ b/source/blender/python/intern/CMakeLists.txt @@ -255,7 +255,11 @@ if(WITH_SDL) list(APPEND INC_SYS ${SDL_INCLUDE_DIR} ) - if(NOT WITH_SDL_DYNLOAD) + if(WITH_SDL_DYNLOAD) + list(APPEND LIB + extern_sdlew + ) + else() list(APPEND LIB ${SDL_LIBRARY} ) -- cgit v1.2.3 From c0bd240ad0a17402db9d2e4799a433b81b62fca8 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Mon, 7 Dec 2020 16:58:18 +0100 Subject: LibOverride: Add initial support for adding new NLA tracks. Also makes NLA tracks and strips overridable. User can either edit existing strips in existing NLA tracks (but not add or remove them), and/or add new NLA tracks after those comming from the linked data. Most of the work was as usual checking operators and adding protections against illegal operations in override context. Note that since we can only rely on indices to deal with local added tracks, we forbid any local track being before any linked/original track. Maniphest Tasks: T72629 Differential Revision: https://developer.blender.org/D9611 --- source/blender/blenkernel/BKE_nla.h | 18 ++-- source/blender/blenkernel/intern/ipo.c | 6 +- source/blender/blenkernel/intern/nla.c | 52 ++++++++---- .../blender/editors/animation/anim_channels_edit.c | 52 ++++++++++-- source/blender/editors/object/object_add.c | 5 +- source/blender/editors/space_action/action_data.c | 11 ++- source/blender/editors/space_nla/nla_channels.c | 17 ++-- source/blender/editors/space_nla/nla_edit.c | 99 +++++++++++++++++----- .../blender/editors/transform/transform_convert.c | 2 +- .../editors/transform/transform_convert_nla.c | 16 +++- source/blender/makesdna/DNA_anim_types.h | 4 + .../makesrna/intern/rna_access_compare_override.c | 7 ++ source/blender/makesrna/intern/rna_animation.c | 70 ++++++++++++++- source/blender/makesrna/intern/rna_nla.c | 10 +++ source/blender/makesrna/intern/rna_rna.c | 2 +- source/blender/makesrna/intern/rna_space.c | 2 +- 16 files changed, 305 insertions(+), 68 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/BKE_nla.h b/source/blender/blenkernel/BKE_nla.h index 8671324fab1..16d48024d07 100644 --- a/source/blender/blenkernel/BKE_nla.h +++ b/source/blender/blenkernel/BKE_nla.h @@ -60,9 +60,13 @@ struct NlaTrack *BKE_nlatrack_copy(struct Main *bmain, const int flag); void BKE_nla_tracks_copy(struct Main *bmain, ListBase *dst, ListBase *src, const int flag); -struct NlaTrack *BKE_nlatrack_add(struct AnimData *adt, struct NlaTrack *prev); +struct NlaTrack *BKE_nlatrack_add(struct AnimData *adt, + struct NlaTrack *prev, + bool is_liboverride); struct NlaStrip *BKE_nlastrip_new(struct bAction *act); -struct NlaStrip *BKE_nlastack_add_strip(struct AnimData *adt, struct bAction *act); +struct NlaStrip *BKE_nlastack_add_strip(struct AnimData *adt, + struct bAction *act, + const bool is_liboverride); struct NlaStrip *BKE_nla_add_soundstrip(struct Main *bmain, struct Scene *scene, struct Speaker *speaker); @@ -95,10 +99,14 @@ void BKE_nlatrack_solo_toggle(struct AnimData *adt, struct NlaTrack *nlt); bool BKE_nlatrack_has_space(struct NlaTrack *nlt, float start, float end); void BKE_nlatrack_sort_strips(struct NlaTrack *nlt); -bool BKE_nlatrack_add_strip(struct NlaTrack *nlt, struct NlaStrip *strip); +bool BKE_nlatrack_add_strip(struct NlaTrack *nlt, + struct NlaStrip *strip, + const bool is_liboverride); bool BKE_nlatrack_get_bounds(struct NlaTrack *nlt, float bounds[2]); +bool BKE_nlatrack_is_nonlocal_in_liboverride(const struct ID *id, const struct NlaTrack *nlt); + /* ............ */ struct NlaStrip *BKE_nlastrip_find_active(struct NlaTrack *nlt); @@ -124,11 +132,11 @@ void BKE_nla_validate_state(struct AnimData *adt); /* ............ */ bool BKE_nla_action_is_stashed(struct AnimData *adt, struct bAction *act); -bool BKE_nla_action_stash(struct AnimData *adt); +bool BKE_nla_action_stash(struct AnimData *adt, const bool is_liboverride); /* ............ */ -void BKE_nla_action_pushdown(struct AnimData *adt); +void BKE_nla_action_pushdown(struct AnimData *adt, const bool is_liboverride); bool BKE_nla_tweakmode_enter(struct AnimData *adt); void BKE_nla_tweakmode_exit(struct AnimData *adt); diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c index 9696d920640..6a852df95c6 100644 --- a/source/blender/blenkernel/intern/ipo.c +++ b/source/blender/blenkernel/intern/ipo.c @@ -1999,12 +1999,12 @@ static void nlastrips_to_animdata(ID *id, ListBase *strips) } /* try to add this strip to the current NLA-Track (i.e. the 'last' one on the stack atm) */ - if (BKE_nlatrack_add_strip(nlt, strip) == 0) { + if (BKE_nlatrack_add_strip(nlt, strip, false) == 0) { /* trying to add to the current failed (no space), * so add a new track to the stack, and add to that... */ - nlt = BKE_nlatrack_add(adt, NULL); - BKE_nlatrack_add_strip(nlt, strip); + nlt = BKE_nlatrack_add(adt, NULL, false); + BKE_nlatrack_add_strip(nlt, strip, false); } /* ensure that strip has a name */ diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index 56bd83140bf..ebd9317fcf1 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -280,7 +280,7 @@ void BKE_nla_tracks_copy(Main *bmain, ListBase *dst, ListBase *src, const int fl /* Add a NLA Track to the given AnimData * - prev: NLA-Track to add the new one after */ -NlaTrack *BKE_nlatrack_add(AnimData *adt, NlaTrack *prev) +NlaTrack *BKE_nlatrack_add(AnimData *adt, NlaTrack *prev, const bool is_liboverride) { NlaTrack *nlt; @@ -293,11 +293,15 @@ NlaTrack *BKE_nlatrack_add(AnimData *adt, NlaTrack *prev) nlt = MEM_callocN(sizeof(NlaTrack), "NlaTrack"); /* set settings requiring the track to not be part of the stack yet */ - nlt->flag = NLATRACK_SELECTED; + nlt->flag = NLATRACK_SELECTED | NLATRACK_OVERRIDELIBRARY_LOCAL; nlt->index = BLI_listbase_count(&adt->nla_tracks); /* add track to stack, and make it the active one */ - if (prev) { + if (is_liboverride) { + for (; prev != NULL && (prev->flag & NLATRACK_OVERRIDELIBRARY_LOCAL) == 0; prev = prev->next) { + } + } + if (prev != NULL) { BLI_insertlinkafter(&adt->nla_tracks, prev, nlt); } else { @@ -359,7 +363,7 @@ NlaStrip *BKE_nlastrip_new(bAction *act) /* Add new NLA-strip to the top of the NLA stack - i.e. * into the last track if space, or a new one otherwise. */ -NlaStrip *BKE_nlastack_add_strip(AnimData *adt, bAction *act) +NlaStrip *BKE_nlastack_add_strip(AnimData *adt, bAction *act, const bool is_liboverride) { NlaStrip *strip; NlaTrack *nlt; @@ -376,12 +380,12 @@ NlaStrip *BKE_nlastack_add_strip(AnimData *adt, bAction *act) } /* firstly try adding strip to last track, but if that fails, add to a new track */ - if (BKE_nlatrack_add_strip(adt->nla_tracks.last, strip) == 0) { + if (BKE_nlatrack_add_strip(adt->nla_tracks.last, strip, is_liboverride) == 0) { /* trying to add to the last track failed (no track or no space), * so add a new track to the stack, and add to that... */ - nlt = BKE_nlatrack_add(adt, NULL); - BKE_nlatrack_add_strip(nlt, strip); + nlt = BKE_nlatrack_add(adt, NULL, is_liboverride); + BKE_nlatrack_add_strip(nlt, strip, is_liboverride); } /* automatically name it too */ @@ -1138,15 +1142,16 @@ void BKE_nlatrack_sort_strips(NlaTrack *nlt) /* Add the given NLA-Strip to the given NLA-Track, assuming that it * isn't currently attached to another one */ -bool BKE_nlatrack_add_strip(NlaTrack *nlt, NlaStrip *strip) +bool BKE_nlatrack_add_strip(NlaTrack *nlt, NlaStrip *strip, const bool is_liboverride) { /* sanity checks */ if (ELEM(NULL, nlt, strip)) { return false; } - /* do not allow adding strips if this track is locked */ - if (nlt->flag & NLATRACK_PROTECTED) { + /* Do not allow adding strips if this track is locked, or not a local one in liboverride case. */ + if (nlt->flag & NLATRACK_PROTECTED || + (is_liboverride && (nlt->flag & NLATRACK_OVERRIDELIBRARY_LOCAL) == 0)) { return false; } @@ -1186,6 +1191,18 @@ bool BKE_nlatrack_get_bounds(NlaTrack *nlt, float bounds[2]) return true; } +/** + * Check whether given NLA track is not local (i.e. from linked data) when the object is a library + * override. + * + * \param nlt May be NULL, in which case we consider it as a non-local track case. + */ +bool BKE_nlatrack_is_nonlocal_in_liboverride(const ID *id, const NlaTrack *nlt) +{ + return (ID_IS_OVERRIDE_LIBRARY(id) && + (nlt == NULL || (nlt->flag & NLATRACK_OVERRIDELIBRARY_LOCAL) == 0)); +} + /* NLA Strips -------------------------------------- */ /* Find the active NLA-strip within the given track */ @@ -1857,7 +1874,7 @@ bool BKE_nla_action_is_stashed(AnimData *adt, bAction *act) /* "Stash" an action (i.e. store it as a track/layer in the NLA, but non-contributing) * to retain it in the file for future uses */ -bool BKE_nla_action_stash(AnimData *adt) +bool BKE_nla_action_stash(AnimData *adt, const bool is_liboverride) { NlaTrack *prev_track = NULL; NlaTrack *nlt; @@ -1881,7 +1898,7 @@ bool BKE_nla_action_stash(AnimData *adt) } } - nlt = BKE_nlatrack_add(adt, prev_track); + nlt = BKE_nlatrack_add(adt, prev_track, is_liboverride); BLI_assert(nlt != NULL); /* We need to ensure that if there wasn't any previous instance, @@ -1901,7 +1918,7 @@ bool BKE_nla_action_stash(AnimData *adt) strip = BKE_nlastrip_new(adt->action); BLI_assert(strip != NULL); - BKE_nlatrack_add_strip(nlt, strip); + BKE_nlatrack_add_strip(nlt, strip, is_liboverride); BKE_nlastrip_validate_name(adt, strip); /* mark the stash track and strip so that they doesn't disturb the stack animation, @@ -1931,7 +1948,7 @@ bool BKE_nla_action_stash(AnimData *adt) * so no checks for this are performed. */ /* TODO: maybe we should have checks for this too... */ -void BKE_nla_action_pushdown(AnimData *adt) +void BKE_nla_action_pushdown(AnimData *adt, const bool is_liboverride) { NlaStrip *strip; const bool is_first = (adt) && (adt->nla_tracks.first == NULL); @@ -1952,7 +1969,7 @@ void BKE_nla_action_pushdown(AnimData *adt) } /* add a new NLA strip to the track, which references the active action */ - strip = BKE_nlastack_add_strip(adt, adt->action); + strip = BKE_nlastack_add_strip(adt, adt->action, is_liboverride); if (strip == NULL) { return; } @@ -2273,6 +2290,11 @@ void BKE_nla_blend_read_lib(BlendLibReader *reader, ID *id, ListBase *tracks) { /* we only care about the NLA strips inside the tracks */ LISTBASE_FOREACH (NlaTrack *, nlt, tracks) { + /* If linking from a library, clear 'local' library override flag. */ + if (id->lib != NULL) { + nlt->flag &= ~NLATRACK_OVERRIDELIBRARY_LOCAL; + } + blend_lib_read_nla_strips(reader, id, &nlt->strips); } } diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c index ba3796ad245..124992bed71 100644 --- a/source/blender/editors/animation/anim_channels_edit.c +++ b/source/blender/editors/animation/anim_channels_edit.c @@ -49,6 +49,7 @@ #include "BKE_gpencil.h" #include "BKE_lib_id.h" #include "BKE_mask.h" +#include "BKE_nla.h" #include "BKE_scene.h" #include "DEG_depsgraph.h" @@ -1063,18 +1064,27 @@ static void rearrange_animchannels_filter_visible(ListBase *anim_data_visible, eAnim_ChannelType type) { ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale, *ale_next; - int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS); + eAnimFilter_Flags filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | + ANIMFILTER_LIST_CHANNELS); /* get all visible channels */ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); /* now, only keep the ones that are of the types we are interested in */ - for (ale = anim_data.first; ale; ale = ale_next) { - ale_next = ale->next; - + LISTBASE_FOREACH_MUTABLE (bAnimListElem *, ale, &anim_data) { if (ale->type != type) { BLI_freelinkN(&anim_data, ale); + continue; + } + + if (type == ANIMTYPE_NLATRACK) { + NlaTrack *nlt = (NlaTrack *)ale->data; + + if (BKE_nlatrack_is_nonlocal_in_liboverride(ale->id, nlt)) { + /* No re-arrangement of non-local tracks of override data. */ + BLI_freelinkN(&anim_data, ale); + continue; + } } } @@ -1146,6 +1156,7 @@ static void rearrange_nla_channels(bAnimContext *ac, AnimData *adt, eRearrangeAn { AnimChanRearrangeFp rearrange_func; ListBase anim_data_visible = {NULL, NULL}; + const bool is_liboverride = ID_IS_OVERRIDE_LIBRARY(ac->obact); /* hack: invert mode so that functions will work in right order */ mode *= -1; @@ -1156,6 +1167,29 @@ static void rearrange_nla_channels(bAnimContext *ac, AnimData *adt, eRearrangeAn return; } + /* In liboverride case, we need to extract non-local NLA tracks from current anim data before we + * can perform the move, and add then back afterwards. It's the only way to prevent them from + * being affected by the reordering. + * + * Note that both override apply code for NLA tracks collection, and NLA editing code, are + * responsible to ensure that non-local tracks always remain first in the list. */ + ListBase extracted_nonlocal_nla_tracks = {NULL, NULL}; + if (is_liboverride) { + NlaTrack *nla_track; + for (nla_track = adt->nla_tracks.first; nla_track != NULL; nla_track = nla_track->next) { + if (!BKE_nlatrack_is_nonlocal_in_liboverride(&ac->obact->id, nla_track)) { + break; + } + } + if (nla_track != NULL && nla_track->prev != NULL) { + extracted_nonlocal_nla_tracks.first = adt->nla_tracks.first; + extracted_nonlocal_nla_tracks.last = nla_track->prev; + adt->nla_tracks.first = nla_track; + nla_track->prev->next = NULL; + nla_track->prev = NULL; + } + } + /* Filter visible data. */ rearrange_animchannels_filter_visible(&anim_data_visible, ac, ANIMTYPE_NLATRACK); @@ -1163,6 +1197,14 @@ static void rearrange_nla_channels(bAnimContext *ac, AnimData *adt, eRearrangeAn rearrange_animchannel_islands( &adt->nla_tracks, rearrange_func, mode, ANIMTYPE_NLATRACK, &anim_data_visible); + /* Add back non-local NLA tracks at the begining of the animation data's list. */ + if (!BLI_listbase_is_empty(&extracted_nonlocal_nla_tracks)) { + BLI_assert(is_liboverride); + ((NlaTrack *)extracted_nonlocal_nla_tracks.last)->next = adt->nla_tracks.first; + ((NlaTrack *)adt->nla_tracks.first)->prev = extracted_nonlocal_nla_tracks.last; + adt->nla_tracks.first = extracted_nonlocal_nla_tracks.first; + } + /* free temp data */ BLI_freelistN(&anim_data_visible); } diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index 4e0f6211c18..bbfdfb2532d 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -1618,6 +1618,7 @@ static int object_speaker_add_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } Object *ob = ED_object_add_type(C, OB_SPEAKER, NULL, loc, rot, false, local_view_bits); + const bool is_liboverride = ID_IS_OVERRIDE_LIBRARY(ob); /* to make it easier to start using this immediately in NLA, a default sound clip is created * ready to be moved around to retime the sound and/or make new sound clips @@ -1625,13 +1626,13 @@ static int object_speaker_add_exec(bContext *C, wmOperator *op) { /* create new data for NLA hierarchy */ AnimData *adt = BKE_animdata_add_id(&ob->id); - NlaTrack *nlt = BKE_nlatrack_add(adt, NULL); + NlaTrack *nlt = BKE_nlatrack_add(adt, NULL, is_liboverride); NlaStrip *strip = BKE_nla_add_soundstrip(bmain, scene, ob->data); strip->start = CFRA; strip->end += strip->start; /* hook them up */ - BKE_nlatrack_add_strip(nlt, strip); + BKE_nlatrack_add_strip(nlt, strip, is_liboverride); /* auto-name the strip, and give the track an interesting name */ BLI_strncpy(nlt->name, DATA_("SoundTrack"), sizeof(nlt->name)); diff --git a/source/blender/editors/space_action/action_data.c b/source/blender/editors/space_action/action_data.c index e20be9c8328..3a584a7f0cb 100644 --- a/source/blender/editors/space_action/action_data.c +++ b/source/blender/editors/space_action/action_data.c @@ -240,7 +240,7 @@ static int action_new_exec(bContext *C, wmOperator *UNUSED(op)) /* Perform stashing operation - But only if there is an action */ if (adt && oldact) { /* stash the action */ - if (BKE_nla_action_stash(adt)) { + if (BKE_nla_action_stash(adt, ID_IS_OVERRIDE_LIBRARY(ptr.owner_id))) { /* The stash operation will remove the user already * (and unlink the action from the AnimData action slot). * Hence, we must unset the ref to the action in the @@ -339,7 +339,8 @@ static int action_pushdown_exec(bContext *C, wmOperator *op) } /* action can be safely added */ - BKE_nla_action_pushdown(adt); + const Object *ob = CTX_data_active_object(C); + BKE_nla_action_pushdown(adt, ID_IS_OVERRIDE_LIBRARY(ob)); /* Stop displaying this action in this editor * NOTE: The editor itself doesn't set a user... @@ -384,7 +385,8 @@ static int action_stash_exec(bContext *C, wmOperator *op) } /* stash the action */ - if (BKE_nla_action_stash(adt)) { + Object *ob = CTX_data_active_object(C); + if (BKE_nla_action_stash(adt, ID_IS_OVERRIDE_LIBRARY(ob))) { /* The stash operation will remove the user already, * so the flushing step later shouldn't double up * the user-count fixes. Hence, we must unset this ref @@ -486,7 +488,8 @@ static int action_stash_create_exec(bContext *C, wmOperator *op) } /* stash the action */ - if (BKE_nla_action_stash(adt)) { + Object *ob = CTX_data_active_object(C); + if (BKE_nla_action_stash(adt, ID_IS_OVERRIDE_LIBRARY(ob))) { bAction *new_action = NULL; /* Create new action not based on the old one diff --git a/source/blender/editors/space_nla/nla_channels.c b/source/blender/editors/space_nla/nla_channels.c index 561de5e82a6..9832ca975cf 100644 --- a/source/blender/editors/space_nla/nla_channels.c +++ b/source/blender/editors/space_nla/nla_channels.c @@ -292,7 +292,7 @@ static int mouse_nla_channels( /* TODO: make this use the operator instead of calling the function directly * however, calling the operator requires that we supply the args, * and that works with proper buttons only */ - BKE_nla_action_pushdown(adt); + BKE_nla_action_pushdown(adt, ID_IS_OVERRIDE_LIBRARY(ale->id)); } else { /* when in tweakmode, this button becomes the toggle for mapped editing */ @@ -516,7 +516,7 @@ static int nlachannels_pushdown_exec(bContext *C, wmOperator *op) } /* 'push-down' action - only usable when not in TweakMode */ - BKE_nla_action_pushdown(adt); + BKE_nla_action_pushdown(adt, ID_IS_OVERRIDE_LIBRARY(id)); struct Main *bmain = CTX_data_main(C); DEG_id_tag_update_ex(bmain, id, ID_RECALC_ANIMATION); @@ -648,19 +648,21 @@ bool nlaedit_add_tracks_existing(bAnimContext *ac, bool above_sel) NlaTrack *nlt = (NlaTrack *)ale->data; AnimData *adt = ale->adt; + const bool is_liboverride = ID_IS_OVERRIDE_LIBRARY(ale->id); + /* check if just adding a new track above this one, * or whether we're adding a new one to the top of the stack that this one belongs to */ if (above_sel) { /* just add a new one above this one */ - BKE_nlatrack_add(adt, nlt); + BKE_nlatrack_add(adt, nlt, is_liboverride); ale->update = ANIM_UPDATE_DEPS; added = true; } else if ((lastAdt == NULL) || (adt != lastAdt)) { /* add one track to the top of the owning AnimData's stack, * then don't add anymore to this stack */ - BKE_nlatrack_add(adt, NULL); + BKE_nlatrack_add(adt, NULL, is_liboverride); lastAdt = adt; ale->update = ANIM_UPDATE_DEPS; added = true; @@ -698,7 +700,7 @@ bool nlaedit_add_tracks_empty(bAnimContext *ac) /* ensure it is empty */ if (BLI_listbase_is_empty(&adt->nla_tracks)) { /* add new track to this AnimData block then */ - BKE_nlatrack_add(adt, NULL); + BKE_nlatrack_add(adt, NULL, ID_IS_OVERRIDE_LIBRARY(ale->id)); ale->update = ANIM_UPDATE_DEPS; added = true; } @@ -796,6 +798,11 @@ static int nlaedit_delete_tracks_exec(bContext *C, wmOperator *UNUSED(op)) NlaTrack *nlt = (NlaTrack *)ale->data; AnimData *adt = ale->adt; + if (BKE_nlatrack_is_nonlocal_in_liboverride(ale->id, nlt)) { + /* No deletion of non-local tracks of override data. */ + continue; + } + /* if track is currently 'solo', then AnimData should have its * 'has solo' flag disabled */ diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c index ed8e5ad76e9..3fa1b614a03 100644 --- a/source/blender/editors/space_nla/nla_edit.c +++ b/source/blender/editors/space_nla/nla_edit.c @@ -649,6 +649,7 @@ static int nlaedit_add_actionclip_exec(bContext *C, wmOperator *op) NlaTrack *nlt = (NlaTrack *)ale->data; AnimData *adt = ale->adt; NlaStrip *strip = NULL; + const bool is_liboverride = ID_IS_OVERRIDE_LIBRARY(ale->id); /* Sanity check: only apply actions of the right type for this ID. * NOTE: in the case that this hasn't been set, @@ -671,12 +672,12 @@ static int nlaedit_add_actionclip_exec(bContext *C, wmOperator *op) strip->start = cfra; /* firstly try adding strip to our current track, but if that fails, add to a new track */ - if (BKE_nlatrack_add_strip(nlt, strip) == 0) { + if (BKE_nlatrack_add_strip(nlt, strip, is_liboverride) == 0) { /* trying to add to the current failed (no space), * so add a new track to the stack, and add to that... */ - nlt = BKE_nlatrack_add(adt, NULL); - BKE_nlatrack_add_strip(nlt, strip); + nlt = BKE_nlatrack_add(adt, NULL, is_liboverride); + BKE_nlatrack_add_strip(nlt, strip, is_liboverride); } /* auto-name it */ @@ -886,6 +887,7 @@ static int nlaedit_add_sound_exec(bContext *C, wmOperator *UNUSED(op)) AnimData *adt = ale->adt; NlaTrack *nlt = (NlaTrack *)ale->data; NlaStrip *strip; + const bool is_liboverride = ID_IS_OVERRIDE_LIBRARY(ale->id); /* does this belong to speaker - assumed to live on Object level only */ if ((GS(ale->id->name) != ID_OB) || (ob->type != OB_SPEAKER)) { @@ -899,12 +901,12 @@ static int nlaedit_add_sound_exec(bContext *C, wmOperator *UNUSED(op)) strip->end += cfra; /* firstly try adding strip to our current track, but if that fails, add to a new track */ - if (BKE_nlatrack_add_strip(nlt, strip) == 0) { + if (BKE_nlatrack_add_strip(nlt, strip, is_liboverride) == 0) { /* trying to add to the current failed (no space), * so add a new track to the stack, and add to that... */ - nlt = BKE_nlatrack_add(adt, NULL); - BKE_nlatrack_add_strip(nlt, strip); + nlt = BKE_nlatrack_add(adt, NULL, is_liboverride); + BKE_nlatrack_add_strip(nlt, strip, is_liboverride); } /* auto-name it */ @@ -966,6 +968,11 @@ static int nlaedit_add_meta_exec(bContext *C, wmOperator *UNUSED(op)) AnimData *adt = ale->adt; NlaStrip *strip; + if (BKE_nlatrack_is_nonlocal_in_liboverride(ale->id, nlt)) { + /* No making metastrips in non-local tracks of override data. */ + continue; + } + /* create meta-strips from the continuous chains of selected strips */ BKE_nlastrips_make_metas(&nlt->strips, 0); @@ -1030,6 +1037,11 @@ static int nlaedit_remove_meta_exec(bContext *C, wmOperator *UNUSED(op)) for (ale = anim_data.first; ale; ale = ale->next) { NlaTrack *nlt = (NlaTrack *)ale->data; + if (BKE_nlatrack_is_nonlocal_in_liboverride(ale->id, nlt)) { + /* No removing metastrips from non-local tracks of override data. */ + continue; + } + /* clear all selected meta-strips, regardless of whether they are temporary or not */ BKE_nlastrips_clear_metas(&nlt->strips, 1, 0); @@ -1096,6 +1108,11 @@ static int nlaedit_duplicate_exec(bContext *C, wmOperator *op) NlaStrip *strip, *nstrip, *next; NlaTrack *track; + /* Note: We allow this operator in override context because it is almost always (from possible + * default user interactions) paired with the transform one, which will ensure that the new + * strip ends up in a valid (local) track. */ + + const bool is_liboverride = ID_IS_OVERRIDE_LIBRARY(ale->id); for (strip = nlt->strips.first; strip; strip = next) { next = strip->next; @@ -1106,13 +1123,13 @@ static int nlaedit_duplicate_exec(bContext *C, wmOperator *op) /* in case there's no space in the track above, * or we haven't got a reference to it yet, try adding */ - if (BKE_nlatrack_add_strip(nlt->next, nstrip) == 0) { + if (BKE_nlatrack_add_strip(nlt->next, nstrip, is_liboverride) == 0) { /* need to add a new track above the one above the current one * - if the current one is the last one, nlt->next will be NULL, which defaults to adding * at the top of the stack anyway... */ - track = BKE_nlatrack_add(adt, nlt->next); - BKE_nlatrack_add_strip(track, nstrip); + track = BKE_nlatrack_add(adt, nlt->next, is_liboverride); + BKE_nlatrack_add_strip(track, nstrip, is_liboverride); } /* deselect the original and the active flag */ @@ -1209,6 +1226,11 @@ static int nlaedit_delete_exec(bContext *C, wmOperator *UNUSED(op)) NlaTrack *nlt = (NlaTrack *)ale->data; NlaStrip *strip, *nstrip; + if (BKE_nlatrack_is_nonlocal_in_liboverride(ale->id, nlt)) { + /* No deletion of strips in non-local tracks of override data. */ + continue; + } + for (strip = nlt->strips.first; strip; strip = nstrip) { nstrip = strip->next; @@ -1359,6 +1381,11 @@ static int nlaedit_split_exec(bContext *C, wmOperator *UNUSED(op)) AnimData *adt = ale->adt; NlaStrip *strip, *next; + if (BKE_nlatrack_is_nonlocal_in_liboverride(ale->id, nlt)) { + /* No splitting of strips in non-local tracks of override data. */ + continue; + } + for (strip = nlt->strips.first; strip; strip = next) { next = strip->next; @@ -1502,6 +1529,12 @@ static int nlaedit_swap_exec(bContext *C, wmOperator *op) NlaStrip *strip, *stripN = NULL; NlaStrip *area = NULL, *sb = NULL; + const bool is_liboverride = ID_IS_OVERRIDE_LIBRARY(ale->id); + + if (BKE_nlatrack_is_nonlocal_in_liboverride(ale->id, nlt)) { + /* No re-ordering of strips whithin non-local tracks of override data. */ + continue; + } /* make temporary metastrips so that entire islands of selections can be moved around */ BKE_nlastrips_make_metas(&nlt->strips, 1); @@ -1610,8 +1643,8 @@ static int nlaedit_swap_exec(bContext *C, wmOperator *op) } /* add strips back to track now */ - BKE_nlatrack_add_strip(nlt, area); - BKE_nlatrack_add_strip(nlt, sb); + BKE_nlatrack_add_strip(nlt, area, is_liboverride); + BKE_nlatrack_add_strip(nlt, sb, is_liboverride); } /* clear (temp) metastrips */ @@ -1674,11 +1707,19 @@ static int nlaedit_move_up_exec(bContext *C, wmOperator *UNUSED(op)) NlaTrack *nltn = nlt->next; NlaStrip *strip, *stripn; + const bool is_liboverride = ID_IS_OVERRIDE_LIBRARY(ale->id); + /* if this track has no tracks after it, skip for now... */ if (nltn == NULL) { continue; } + if (BKE_nlatrack_is_nonlocal_in_liboverride(ale->id, nlt) || + BKE_nlatrack_is_nonlocal_in_liboverride(ale->id, nltn)) { + /* No moving of strips in non-local tracks of override data. */ + continue; + } + /* for every selected strip, try to move */ for (strip = nlt->strips.first; strip; strip = stripn) { stripn = strip->next; @@ -1689,7 +1730,7 @@ static int nlaedit_move_up_exec(bContext *C, wmOperator *UNUSED(op)) /* remove from its current track, and add to the one above * (it 'should' work, so no need to worry) */ BLI_remlink(&nlt->strips, strip); - BKE_nlatrack_add_strip(nltn, strip); + BKE_nlatrack_add_strip(nltn, strip, is_liboverride); } } } @@ -1751,11 +1792,19 @@ static int nlaedit_move_down_exec(bContext *C, wmOperator *UNUSED(op)) NlaTrack *nltp = nlt->prev; NlaStrip *strip, *stripn; + const bool is_liboverride = ID_IS_OVERRIDE_LIBRARY(ale->id); + /* if this track has no tracks before it, skip for now... */ if (nltp == NULL) { continue; } + if (BKE_nlatrack_is_nonlocal_in_liboverride(ale->id, nlt) || + BKE_nlatrack_is_nonlocal_in_liboverride(ale->id, nltp)) { + /* No moving of strips in non-local tracks of override data. */ + continue; + } + /* for every selected strip, try to move */ for (strip = nlt->strips.first; strip; strip = stripn) { stripn = strip->next; @@ -1766,7 +1815,7 @@ static int nlaedit_move_down_exec(bContext *C, wmOperator *UNUSED(op)) /* remove from its current track, and add to the one above * (it 'should' work, so no need to worry) */ BLI_remlink(&nlt->strips, strip); - BKE_nlatrack_add_strip(nltp, strip); + BKE_nlatrack_add_strip(nltp, strip, is_liboverride); } } } @@ -2023,11 +2072,11 @@ static int nlaedit_apply_scale_exec(bContext *C, wmOperator *UNUSED(op)) /* strip must be selected, and must be action-clip only * (transitions don't have scale) */ if ((strip->flag & NLASTRIP_FLAG_SELECT) && (strip->type == NLASTRIP_TYPE_CLIP)) { - /* if the referenced action is used by other strips, - * make this strip use its own copy */ - if (strip->act == NULL) { + if (strip->act == NULL || ID_IS_OVERRIDE_LIBRARY(strip->act) || ID_IS_LINKED(strip->act)) { continue; } + /* if the referenced action is used by other strips, + * make this strip use its own copy */ if (strip->act->id.us > 1) { /* make a copy of the Action to work on */ bAction *act = (bAction *)BKE_id_copy(bmain, &strip->act->id); @@ -2200,6 +2249,8 @@ static int nlaedit_snap_exec(bContext *C, wmOperator *op) NlaStrip *strip, *stripn; NlaTrack *track; + const bool is_liboverride = ID_IS_OVERRIDE_LIBRARY(ale->id); + /* create meta-strips from the continuous chains of selected strips */ BKE_nlastrips_make_metas(&nlt->strips, 1); @@ -2255,10 +2306,10 @@ static int nlaedit_snap_exec(bContext *C, wmOperator *op) BLI_remlink(&tmp_strips, strip); /* in case there's no space in the current track, try adding */ - if (BKE_nlatrack_add_strip(nlt, strip) == 0) { + if (BKE_nlatrack_add_strip(nlt, strip, is_liboverride) == 0) { /* need to add a new track above the current one */ - track = BKE_nlatrack_add(adt, nlt); - BKE_nlatrack_add_strip(track, strip); + track = BKE_nlatrack_add(adt, nlt, is_liboverride); + BKE_nlatrack_add_strip(track, strip, is_liboverride); /* clear temp meta-strips on this new track, * as we may not be able to get back to it */ @@ -2375,6 +2426,11 @@ static int nla_fmodifier_add_exec(bContext *C, wmOperator *op) NlaTrack *nlt = (NlaTrack *)ale->data; NlaStrip *strip; + if (BKE_nlatrack_is_nonlocal_in_liboverride(ale->id, nlt)) { + /* No adding f-modifiers to strips in non-local tracks of override data. */ + continue; + } + for (strip = nlt->strips.first; strip; strip = strip->next) { /* can F-Modifier be added to the current strip? */ if (active_only) { @@ -2552,6 +2608,11 @@ static int nla_fmodifier_paste_exec(bContext *C, wmOperator *op) NlaTrack *nlt = (NlaTrack *)ale->data; NlaStrip *strip; + if (BKE_nlatrack_is_nonlocal_in_liboverride(ale->id, nlt)) { + /* No pasting in non-local tracks of override data. */ + continue; + } + for (strip = nlt->strips.first; strip; strip = strip->next) { /* can F-Modifier be added to the current strip? */ if (active_only) { diff --git a/source/blender/editors/transform/transform_convert.c b/source/blender/editors/transform/transform_convert.c index c23ee5b771c..c81c954bd0a 100644 --- a/source/blender/editors/transform/transform_convert.c +++ b/source/blender/editors/transform/transform_convert.c @@ -1438,7 +1438,7 @@ void animrecord_check_state(TransInfo *t, struct Object *ob) /* only push down if action is more than 1-2 frames long */ calc_action_range(adt->action, &astart, &aend, 1); if (aend > astart + 2.0f) { - NlaStrip *strip = BKE_nlastack_add_strip(adt, adt->action); + NlaStrip *strip = BKE_nlastack_add_strip(adt, adt->action, ID_IS_OVERRIDE_LIBRARY(id)); /* clear reference to action now that we've pushed it onto the stack */ id_us_min(&adt->action->id); diff --git a/source/blender/editors/transform/transform_convert_nla.c b/source/blender/editors/transform/transform_convert_nla.c index 8f18f6a8c96..fa60a88a45b 100644 --- a/source/blender/editors/transform/transform_convert_nla.c +++ b/source/blender/editors/transform/transform_convert_nla.c @@ -462,6 +462,12 @@ void recalcData_nla(TransInfo *t) * - we need to calculate both, * as only one may have been altered by transform if only 1 handle moved. */ + /* In LibOverride case, we cannot move strips across tracks that come from the linked data. */ + const bool is_liboverride = ID_IS_OVERRIDE_LIBRARY(tdn->id); + if (BKE_nlatrack_is_nonlocal_in_liboverride(tdn->id, tdn->nlt)) { + continue; + } + delta_y1 = ((int)tdn->h1[1] / NLACHANNEL_STEP(snla) - tdn->trackIndex); delta_y2 = ((int)tdn->h2[1] / NLACHANNEL_STEP(snla) - tdn->trackIndex); @@ -477,10 +483,11 @@ void recalcData_nla(TransInfo *t) if (delta > 0) { for (track = tdn->nlt->next, n = 0; (track) && (n < delta); track = track->next, n++) { /* check if space in this track for the strip */ - if (BKE_nlatrack_has_space(track, strip->start, strip->end)) { + if (BKE_nlatrack_has_space(track, strip->start, strip->end) && + !BKE_nlatrack_is_nonlocal_in_liboverride(tdn->id, tdn->nlt)) { /* move strip to this track */ BLI_remlink(&tdn->nlt->strips, strip); - BKE_nlatrack_add_strip(track, strip); + BKE_nlatrack_add_strip(track, strip, is_liboverride); tdn->nlt = track; tdn->trackIndex++; @@ -496,10 +503,11 @@ void recalcData_nla(TransInfo *t) for (track = tdn->nlt->prev, n = 0; (track) && (n < delta); track = track->prev, n++) { /* check if space in this track for the strip */ - if (BKE_nlatrack_has_space(track, strip->start, strip->end)) { + if (BKE_nlatrack_has_space(track, strip->start, strip->end) && + !BKE_nlatrack_is_nonlocal_in_liboverride(tdn->id, tdn->nlt)) { /* move strip to this track */ BLI_remlink(&tdn->nlt->strips, strip); - BKE_nlatrack_add_strip(track, strip); + BKE_nlatrack_add_strip(track, strip, is_liboverride); tdn->nlt = track; tdn->trackIndex--; diff --git a/source/blender/makesdna/DNA_anim_types.h b/source/blender/makesdna/DNA_anim_types.h index 9a31447dacd..17d41985f80 100644 --- a/source/blender/makesdna/DNA_anim_types.h +++ b/source/blender/makesdna/DNA_anim_types.h @@ -875,6 +875,10 @@ typedef enum eNlaTrack_Flag { /** track is not allowed to execute, * usually as result of tweaking being enabled (internal flag) */ NLATRACK_DISABLED = (1 << 10), + + /** This NLA track is added to an override ID, which means it is fully editable. + * Irrelevant in case the owner ID is not an override. */ + NLATRACK_OVERRIDELIBRARY_LOCAL = 1 << 16, } eNlaTrack_Flag; /* ************************************ */ diff --git a/source/blender/makesrna/intern/rna_access_compare_override.c b/source/blender/makesrna/intern/rna_access_compare_override.c index 2bf4de7af60..c0b2de268cd 100644 --- a/source/blender/makesrna/intern/rna_access_compare_override.c +++ b/source/blender/makesrna/intern/rna_access_compare_override.c @@ -23,6 +23,7 @@ #include "MEM_guardedalloc.h" #include "DNA_ID.h" +#include "DNA_anim_types.h" #include "DNA_constraint_types.h" #include "DNA_gpencil_modifier_types.h" #include "DNA_key_types.h" @@ -84,6 +85,12 @@ bool RNA_property_overridable_get(PointerRNA *ptr, PropertyRNA *prop) return true; } } + else if (RNA_struct_is_a(ptr->type, &RNA_NlaTrack)) { + NlaTrack *nla_track = ptr->data; + if (nla_track->flag & NLATRACK_OVERRIDELIBRARY_LOCAL) { + return true; + } + } /* If this is a RNA-defined property (real or 'virtual' IDProp), * we want to use RNA prop flag. */ return !(prop->flag_override & PROPOVERRIDE_NO_COMPARISON) && diff --git a/source/blender/makesrna/intern/rna_animation.c b/source/blender/makesrna/intern/rna_animation.c index 0a9f2ff4819..10f86fe2671 100644 --- a/source/blender/makesrna/intern/rna_animation.c +++ b/source/blender/makesrna/intern/rna_animation.c @@ -587,7 +587,7 @@ static void rna_KeyingSet_paths_clear(KeyingSet *keyingset, ReportList *reports) /* needs wrapper function to push notifier */ static NlaTrack *rna_NlaTrack_new(ID *id, AnimData *adt, Main *bmain, bContext *C, NlaTrack *track) { - NlaTrack *new_track = BKE_nlatrack_add(adt, track); + NlaTrack *new_track = BKE_nlatrack_add(adt, track, ID_IS_OVERRIDE_LIBRARY(id)); WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_ADDED, NULL); @@ -732,6 +732,60 @@ bool rna_AnimaData_override_apply(Main *UNUSED(bmain), return false; } +bool rna_NLA_tracks_override_apply(Main *bmain, + PointerRNA *ptr_dst, + PointerRNA *ptr_src, + PointerRNA *UNUSED(ptr_storage), + PropertyRNA *UNUSED(prop_dst), + PropertyRNA *UNUSED(prop_src), + PropertyRNA *UNUSED(prop_storage), + const int UNUSED(len_dst), + const int UNUSED(len_src), + const int UNUSED(len_storage), + PointerRNA *UNUSED(ptr_item_dst), + PointerRNA *UNUSED(ptr_item_src), + PointerRNA *UNUSED(ptr_item_storage), + IDOverrideLibraryPropertyOperation *opop) +{ + BLI_assert(opop->operation == IDOVERRIDE_LIBRARY_OP_INSERT_AFTER && + "Unsupported RNA override operation on constraints collection"); + + AnimData *anim_data_dst = (AnimData *)ptr_dst->data; + AnimData *anim_data_src = (AnimData *)ptr_src->data; + + /* Remember that insertion operations are defined and stored in correct order, which means that + * even if we insert several items in a row, we always insert first one, then second one, etc. + * So we should always find 'anchor' track in both _src *and* _dst. */ + NlaTrack *nla_track_anchor = NULL; +# if 0 + /* This is not working so well with index-based insertion, especially in case some tracks get + * added to lib linked data. So we simply add locale tracks at the end of the list always, order + * of override operations should ensure order of local tracks is preserved properly. */ + if (opop->subitem_local_index >= 0) { + nla_track_anchor = BLI_findlink(&anim_data_dst->nla_tracks, opop->subitem_local_index); + } + /* Otherwise we just insert in first position. */ +# else + nla_track_anchor = anim_data_dst->nla_tracks.last; +# endif + + NlaTrack *nla_track_src = NULL; + if (opop->subitem_local_index >= 0) { + nla_track_src = BLI_findlink(&anim_data_src->nla_tracks, opop->subitem_local_index); + } + nla_track_src = nla_track_src ? nla_track_src->next : anim_data_src->nla_tracks.first; + + BLI_assert(nla_track_src != NULL); + + NlaTrack *nla_track_dst = BKE_nlatrack_copy(bmain, nla_track_src, true, 0); + + /* This handles NULL anchor as expected by adding at head of list. */ + BLI_insertlinkafter(&anim_data_dst->nla_tracks, nla_track_anchor, nla_track_dst); + + // printf("%s: We inserted a NLA Track...\n", __func__); + return true; +} + #else /* helper function for Keying Set -> keying settings */ @@ -1251,14 +1305,19 @@ static void rna_def_animdata(BlenderRNA *brna) RNA_def_property_collection_sdna(prop, NULL, "nla_tracks", NULL); RNA_def_property_struct_type(prop, "NlaTrack"); RNA_def_property_ui_text(prop, "NLA Tracks", "NLA Tracks (i.e. Animation Layers)"); + RNA_def_property_override_flag(prop, + PROPOVERRIDE_OVERRIDABLE_LIBRARY | + PROPOVERRIDE_LIBRARY_INSERTION | PROPOVERRIDE_NO_PROP_NAME); + RNA_def_property_override_funcs(prop, NULL, NULL, "rna_NLA_tracks_override_apply"); rna_api_animdata_nla_tracks(brna, prop); + RNA_define_lib_overridable(true); + /* Active Action */ prop = RNA_def_property(srna, "action", PROP_POINTER, PROP_NONE); /* this flag as well as the dynamic test must be defined for this to be editable... */ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT); - RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_pointer_funcs( prop, NULL, "rna_AnimData_action_set", NULL, "rna_Action_id_poll"); RNA_def_property_editable_func(prop, "rna_AnimData_action_editable"); @@ -1297,11 +1356,14 @@ static void rna_def_animdata(BlenderRNA *brna) prop = RNA_def_property(srna, "drivers", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "drivers", NULL); RNA_def_property_struct_type(prop, "FCurve"); - RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_ui_text(prop, "Drivers", "The Drivers/Expressions for this data-block"); + RNA_define_lib_overridable(false); + rna_api_animdata_drivers(brna, prop); + RNA_define_lib_overridable(true); + /* General Settings */ prop = RNA_def_property(srna, "use_nla", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", ADT_NLA_EVAL_OFF); @@ -1322,6 +1384,8 @@ static void rna_def_animdata(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Pin in Graph Editor", ""); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); + RNA_define_lib_overridable(false); + /* Animation Data API */ RNA_api_animdata(srna); } diff --git a/source/blender/makesrna/intern/rna_nla.c b/source/blender/makesrna/intern/rna_nla.c index b0dda1237b0..b7c51eac6ef 100644 --- a/source/blender/makesrna/intern/rna_nla.c +++ b/source/blender/makesrna/intern/rna_nla.c @@ -607,6 +607,8 @@ static void rna_def_nlastrip(BlenderRNA *brna) RNA_def_struct_path_func(srna, "rna_NlaStrip_path"); RNA_def_struct_ui_icon(srna, ICON_NLA); /* XXX */ + RNA_define_lib_overridable(true); + /* name property */ prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); RNA_def_property_ui_text(prop, "Name", ""); @@ -820,6 +822,8 @@ static void rna_def_nlastrip(BlenderRNA *brna) "Update range of frames referenced from action " "after tweaking strip and its keyframes"); RNA_def_property_update(prop, NC_ANIMATION | ND_NLA | NA_EDITED, "rna_NlaStrip_update"); + + RNA_define_lib_overridable(false); } static void rna_api_nlatrack_strips(BlenderRNA *brna, PropertyRNA *cprop) @@ -877,10 +881,14 @@ static void rna_def_nlatrack(BlenderRNA *brna) /* strips collection */ prop = RNA_def_property(srna, "strips", PROP_COLLECTION, PROP_NONE); RNA_def_property_struct_type(prop, "NlaStrip"); + /* We do not support inserting or removing strips in overrides of tracks for now. */ + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_ui_text(prop, "NLA Strips", "NLA Strips on this NLA-track"); rna_api_nlatrack_strips(brna, prop); + RNA_define_lib_overridable(true); + /* name property */ prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); RNA_def_property_ui_text(prop, "Name", ""); @@ -920,6 +928,8 @@ static void rna_def_nlatrack(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", NLATRACK_PROTECTED); RNA_def_property_ui_text(prop, "Locked", "NLA Track is locked"); RNA_def_property_update(prop, NC_ANIMATION | ND_NLA, NULL); /* this will do? */ + + RNA_define_lib_overridable(false); } /* --------- */ diff --git a/source/blender/makesrna/intern/rna_rna.c b/source/blender/makesrna/intern/rna_rna.c index eae1c7bc223..b8f6eba4d5a 100644 --- a/source/blender/makesrna/intern/rna_rna.c +++ b/source/blender/makesrna/intern/rna_rna.c @@ -1858,7 +1858,7 @@ int rna_property_override_diff_default(Main *bmain, is_id, is_valid_for_diffing, is_valid_for_insertion, - (RNA_property_override_flag(prop_a) & PROPOVERRIDE_LIBRARY_INSERTION) != 0, + use_collection_insertion, do_create); } # endif diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index eabb71c79d3..ff77819aae1 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -2113,7 +2113,7 @@ static void rna_SpaceDopeSheetEditor_action_update(bContext *C, PointerRNA *ptr) * and the user then uses the browse menu to get back to this action, * assigning it as the active action (i.e. the stash strip gets out of sync) */ - BKE_nla_action_stash(adt); + BKE_nla_action_stash(adt, ID_IS_OVERRIDE_LIBRARY(id)); } BKE_animdata_set_action(NULL, id, saction->action); -- cgit v1.2.3 From 296bc35638605b6172ccd058628e0d27258a5f5f Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Tue, 8 Dec 2020 12:37:46 +0100 Subject: Fix unexpected "/" path after normalizing empty directory path Caused problems in the Asset Browser branch when passing an empty path. The function shouldn't blindly add a slash but sanity-check the input parameters first. --- source/blender/blenlib/intern/path_util.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source/blender') diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c index 758feef6093..74bbe59bc04 100644 --- a/source/blender/blenlib/intern/path_util.c +++ b/source/blender/blenlib/intern/path_util.c @@ -264,6 +264,11 @@ void BLI_path_normalize(const char *relabase, char *path) */ void BLI_path_normalize_dir(const char *relabase, char *dir) { + /* Would just create an unexpected "/" path, just early exit entirely. */ + if (dir[0] == '\0') { + return; + } + BLI_path_normalize(relabase, dir); BLI_path_slash_ensure(dir); } -- cgit v1.2.3 From 2a4fe88c13a1cb5bd79787e17eeaafec01c4d294 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Tue, 8 Dec 2020 12:56:11 +0100 Subject: Cleanup: Use guarded allocator for data-block names returned from file reading Direcly using the C library allocator functions is usually avoided in favor of our guarded allocator. It's more useful when debugging. --- source/blender/blenloader/intern/blend_validate.c | 2 +- source/blender/blenloader/intern/readblenentry.c | 8 ++++---- source/blender/editors/space_file/filelist.c | 2 +- source/blender/imbuf/intern/thumbs_blend.c | 4 ++-- source/blender/python/intern/bpy_library_load.c | 4 +++- 5 files changed, 11 insertions(+), 9 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenloader/intern/blend_validate.c b/source/blender/blenloader/intern/blend_validate.c index 2848aac2c77..9b42e2d5f40 100644 --- a/source/blender/blenloader/intern/blend_validate.c +++ b/source/blender/blenloader/intern/blend_validate.c @@ -148,7 +148,7 @@ bool BLO_main_validate_libraries(Main *bmain, ReportList *reports) } } - BLI_linklist_free(names, free); + BLI_linklist_free(names, MEM_freeN); } BLO_blendhandle_close(bh); diff --git a/source/blender/blenloader/intern/readblenentry.c b/source/blender/blenloader/intern/readblenentry.c index 7a527b82e9f..1aecba5ba90 100644 --- a/source/blender/blenloader/intern/readblenentry.c +++ b/source/blender/blenloader/intern/readblenentry.c @@ -134,7 +134,7 @@ void BLO_blendhandle_print_sizes(BlendHandle *bh, void *fp) * \param bh: The blendhandle to access. * \param ofblocktype: The type of names to get. * \param tot_names: The length of the returned list. - * \return A BLI_linklist of strings. The string links should be freed with malloc. + * \return A BLI_linklist of strings. The string links should be freed with #MEM_freeN(). */ LinkNode *BLO_blendhandle_get_datablock_names(BlendHandle *bh, int ofblocktype, int *tot_names) { @@ -147,7 +147,7 @@ LinkNode *BLO_blendhandle_get_datablock_names(BlendHandle *bh, int ofblocktype, if (bhead->code == ofblocktype) { const char *idname = blo_bhead_id_name(fd, bhead); - BLI_linklist_prepend(&names, strdup(idname + 2)); + BLI_linklist_prepend(&names, BLI_strdup(idname + 2)); tot++; } else if (bhead->code == ENDB) { @@ -254,7 +254,7 @@ LinkNode *BLO_blendhandle_get_previews(BlendHandle *bh, int ofblocktype, int *to * (e.g. "Scene", "Mesh", "Light", etc.). * * \param bh: The blendhandle to access. - * \return A BLI_linklist of strings. The string links should be freed with malloc. + * \return A BLI_linklist of strings. The string links should be freed with #MEM_freeN(). */ LinkNode *BLO_blendhandle_get_linkable_groups(BlendHandle *bh) { @@ -272,7 +272,7 @@ LinkNode *BLO_blendhandle_get_linkable_groups(BlendHandle *bh) const char *str = BKE_idtype_idcode_to_name(bhead->code); if (BLI_gset_add(gathered, (void *)str)) { - BLI_linklist_prepend(&names, strdup(str)); + BLI_linklist_prepend(&names, BLI_strdup(str)); } } } diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c index 9e51b6ca4ba..b6d016aca7c 100644 --- a/source/blender/editors/space_file/filelist.c +++ b/source/blender/editors/space_file/filelist.c @@ -2620,7 +2620,7 @@ static int filelist_readjob_list_lib(const char *root, ListBase *entries, const nbr_entries++; } - BLI_linklist_free(names, free); + BLI_linklist_free(names, MEM_freeN); return nbr_entries; } diff --git a/source/blender/imbuf/intern/thumbs_blend.c b/source/blender/imbuf/intern/thumbs_blend.c index 1d0964ebb62..a338ea599f8 100644 --- a/source/blender/imbuf/intern/thumbs_blend.c +++ b/source/blender/imbuf/intern/thumbs_blend.c @@ -68,7 +68,7 @@ ImBuf *IMB_thumb_load_blend(const char *blen_path, const char *blen_group, const printf("%s: error, found %d items, %d previews\n", __func__, nnames, nprevs); } BLI_linklist_free(previews, BKE_previewimg_freefunc); - BLI_linklist_free(names, free); + BLI_linklist_free(names, MEM_freeN); return ima; } @@ -93,7 +93,7 @@ ImBuf *IMB_thumb_load_blend(const char *blen_path, const char *blen_group, const } BLI_linklist_free(previews, BKE_previewimg_freefunc); - BLI_linklist_free(names, free); + BLI_linklist_free(names, MEM_freeN); } else { BlendThumbnail *data; diff --git a/source/blender/python/intern/bpy_library_load.c b/source/blender/python/intern/bpy_library_load.c index bc3d8b2c360..64590827933 100644 --- a/source/blender/python/intern/bpy_library_load.c +++ b/source/blender/python/intern/bpy_library_load.c @@ -44,6 +44,8 @@ #include "BLO_readfile.h" +#include "MEM_guardedalloc.h" + #include "bpy_capi_utils.h" #include "bpy_library.h" @@ -225,7 +227,7 @@ static PyObject *_bpy_names(BPy_Library *self, int blocktype) PyList_SET_ITEM(list, counter, PyUnicode_FromString((char *)l->link)); counter++; } - BLI_linklist_free(names, free); /* free linklist *and* each node's data */ + BLI_linklist_free(names, MEM_freeN); /* free linklist *and* each node's data */ } return list; -- cgit v1.2.3 From 95b3c4c966f9baeb6f73b84568b7f03287e1a350 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Tue, 8 Dec 2020 13:47:37 +0100 Subject: File Browser: Refactor access to the selection parameters struct * Avoid direct access to `SpaceFile.params`, use a getter instead. This matters because once the asset-browser changes are in, there will be an alternative selection parameter object. The getter can return the correct one. * Rename the function to ensure the parameters. The old name `ED_fileselect_get_params()` wasn't a mere getter, it would create the parameters if necessary. Now we have an actual getter, so better be clear. * In some instances, I replaced the old "get" function with the new mere getter. So the ensure logic is called less often. However, in these cases we should be able to assume the selection parameters were created already as part of the editor creation routine. The term "active" in the new function names may seem a bit odd in the current context, but that is a preparation for the Asset Browser merge as well. Like said, there will be two file selection parameter objects in the space. --- source/blender/editors/include/ED_fileselect.h | 4 +- source/blender/editors/space_file/file_draw.c | 42 +-- source/blender/editors/space_file/file_ops.c | 299 +++++++++++---------- source/blender/editors/space_file/file_panels.c | 2 +- source/blender/editors/space_file/filelist.c | 3 +- source/blender/editors/space_file/filesel.c | 104 +++---- source/blender/editors/space_file/space_file.c | 6 +- source/blender/makesrna/intern/rna_space.c | 15 +- source/blender/windowmanager/intern/wm_operators.c | 3 +- 9 files changed, 257 insertions(+), 221 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/include/ED_fileselect.h b/source/blender/editors/include/ED_fileselect.h index 84808416074..a5a8df916d6 100644 --- a/source/blender/editors/include/ED_fileselect.h +++ b/source/blender/editors/include/ED_fileselect.h @@ -101,9 +101,9 @@ typedef struct FileSelection { struct View2D; struct rcti; -struct FileSelectParams *ED_fileselect_get_params(struct SpaceFile *sfile); +struct FileSelectParams *ED_fileselect_ensure_active_params(struct SpaceFile *sfile); +struct FileSelectParams *ED_fileselect_get_active_params(const struct SpaceFile *sfile); -short ED_fileselect_set_params(struct SpaceFile *sfile); void ED_fileselect_set_params_from_userdef(struct SpaceFile *sfile); void ED_fileselect_params_to_userdef(struct SpaceFile *sfile, const int temp_win_size[], diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c index 4b277435f63..e3bdda7c480 100644 --- a/source/blender/editors/space_file/file_draw.c +++ b/source/blender/editors/space_file/file_draw.c @@ -400,11 +400,12 @@ static void renamebutton_cb(bContext *C, void *UNUSED(arg1), char *oldname) wmWindowManager *wm = CTX_wm_manager(C); SpaceFile *sfile = (SpaceFile *)CTX_wm_space_data(C); ARegion *region = CTX_wm_region(C); + FileSelectParams *params = ED_fileselect_get_active_params(sfile); - BLI_join_dirfile(orgname, sizeof(orgname), sfile->params->dir, oldname); - BLI_strncpy(filename, sfile->params->renamefile, sizeof(filename)); + BLI_join_dirfile(orgname, sizeof(orgname), params->dir, oldname); + BLI_strncpy(filename, params->renamefile, sizeof(filename)); BLI_filename_make_safe(filename); - BLI_join_dirfile(newname, sizeof(newname), sfile->params->dir, filename); + BLI_join_dirfile(newname, sizeof(newname), params->dir, filename); if (!STREQ(orgname, newname)) { if (!BLI_exists(newname)) { @@ -415,8 +416,8 @@ static void renamebutton_cb(bContext *C, void *UNUSED(arg1), char *oldname) } else { /* If rename is successful, scroll to newly renamed entry. */ - BLI_strncpy(sfile->params->renamefile, filename, sizeof(sfile->params->renamefile)); - sfile->params->rename_flag = FILE_PARAMS_RENAME_POSTSCROLL_PENDING; + BLI_strncpy(params->renamefile, filename, sizeof(params->renamefile)); + params->rename_flag = FILE_PARAMS_RENAME_POSTSCROLL_PENDING; if (sfile->smoothscroll_timer != NULL) { WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), sfile->smoothscroll_timer); @@ -688,7 +689,7 @@ static void draw_details_columns(const FileSelectParams *params, void file_draw_list(const bContext *C, ARegion *region) { SpaceFile *sfile = CTX_wm_space_file(C); - FileSelectParams *params = ED_fileselect_get_params(sfile); + FileSelectParams *params = ED_fileselect_get_active_params(sfile); FileLayout *layout = ED_fileselect_get_layout(sfile, region); View2D *v2d = ®ion->v2d; struct FileList *files = sfile->files; @@ -847,26 +848,25 @@ void file_draw_list(const bContext *C, ARegion *region) } if (file_selflag & FILE_SEL_EDITING) { - uiBut *but; const short width = (params->display == FILE_IMGDISPLAY) ? textwidth : layout->attribute_columns[COLUMN_NAME].width - ATTRIBUTE_COLUMN_PADDING; - but = uiDefBut(block, - UI_BTYPE_TEXT, - 1, - "", - sx + icon_ofs, - sy - layout->tile_h - 0.15f * UI_UNIT_X, - width - icon_ofs, - textheight, - sfile->params->renamefile, - 1.0f, - (float)sizeof(sfile->params->renamefile), - 0, - 0, - ""); + uiBut *but = uiDefBut(block, + UI_BTYPE_TEXT, + 1, + "", + sx + icon_ofs, + sy - layout->tile_h - 0.15f * UI_UNIT_X, + width - icon_ofs, + textheight, + params->renamefile, + 1.0f, + (float)sizeof(params->renamefile), + 0, + 0, + ""); UI_but_func_rename_set(but, renamebutton_cb, file); UI_but_flag_enable(but, UI_BUT_NO_UTF8); /* allow non utf8 names */ UI_but_flag_disable(but, UI_BUT_UNDO); diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c index 93367ad3d3c..b98348307f3 100644 --- a/source/blender/editors/space_file/file_ops.c +++ b/source/blender/editors/space_file/file_ops.c @@ -188,7 +188,7 @@ static FileSelect file_select_do(bContext *C, int selected_idx, bool do_diropen) Main *bmain = CTX_data_main(C); FileSelect retval = FILE_SELECT_NOTHING; SpaceFile *sfile = CTX_wm_space_file(C); - FileSelectParams *params = ED_fileselect_get_params(sfile); + FileSelectParams *params = ED_fileselect_get_active_params(sfile); int numfiles = filelist_files_ensure(sfile->files); const FileDirEntry *file; @@ -302,10 +302,10 @@ static FileSelect file_select( bContext *C, const rcti *rect, FileSelType select, bool fill, bool do_diropen) { SpaceFile *sfile = CTX_wm_space_file(C); + FileSelectParams *params = ED_fileselect_get_active_params(sfile); FileSelect retval = FILE_SELECT_NOTHING; FileSelection sel = file_selection_get(C, rect, fill); /* get the selection */ - const FileCheckType check_type = (sfile->params->flag & FILE_DIRSEL_ONLY) ? CHECK_DIRS : - CHECK_ALL; + const FileCheckType check_type = (params->flag & FILE_DIRSEL_ONLY) ? CHECK_DIRS : CHECK_ALL; /* flag the files as selected in the filelist */ filelist_entries_select_index_range_set( @@ -325,7 +325,7 @@ static FileSelect file_select( } if (select != FILE_SEL_ADD && !file_is_any_selected(sfile->files)) { - sfile->params->active_file = -1; + params->active_file = -1; } else if (sel.last >= 0) { ARegion *region = CTX_wm_region(C); @@ -390,7 +390,7 @@ static int file_box_select_modal(bContext *C, wmOperator *op, const wmEvent *eve { ARegion *region = CTX_wm_region(C); SpaceFile *sfile = CTX_wm_space_file(C); - FileSelectParams *params = ED_fileselect_get_params(sfile); + FileSelectParams *params = ED_fileselect_get_active_params(sfile); FileSelection sel; rcti rect; @@ -521,8 +521,9 @@ static int file_select_invoke(bContext *C, wmOperator *op, const wmEvent *event) return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH; } - if (sfile && sfile->params) { - int idx = sfile->params->highlight_file; + const FileSelectParams *params = ED_fileselect_get_active_params(sfile); + if (sfile && params) { + int idx = params->highlight_file; int numfiles = filelist_files_ensure(sfile->files); if ((idx >= 0) && (idx < numfiles)) { @@ -613,7 +614,7 @@ static bool file_walk_select_selection_set(wmWindow *win, const bool extend, const bool fill) { - FileSelectParams *params = sfile->params; + FileSelectParams *params = ED_fileselect_get_active_params(sfile); struct FileList *files = sfile->files; const int last_sel = params->active_file; /* store old value */ int active = active_old; /* could use active_old instead, just for readability */ @@ -804,7 +805,7 @@ static bool file_walk_select_do(bContext *C, static int file_walk_select_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { SpaceFile *sfile = (SpaceFile *)CTX_wm_space_data(C); - FileSelectParams *params = sfile->params; + FileSelectParams *params = ED_fileselect_get_active_params(sfile); const int direction = RNA_enum_get(op->ptr, "direction"); const bool extend = RNA_boolean_get(op->ptr, "extend"); const bool fill = RNA_boolean_get(op->ptr, "fill"); @@ -853,6 +854,7 @@ static int file_select_all_exec(bContext *C, wmOperator *op) { ScrArea *area = CTX_wm_area(C); SpaceFile *sfile = CTX_wm_space_file(C); + FileSelectParams *params = ED_fileselect_get_active_params(sfile); FileSelection sel; const int numfiles = filelist_files_ensure(sfile->files); int action = RNA_enum_get(op->ptr, "action"); @@ -870,7 +872,7 @@ static int file_select_all_exec(bContext *C, wmOperator *op) switch (action) { case SEL_SELECT: case SEL_INVERT: { - check_type = (sfile->params->flag & FILE_DIRSEL_ONLY) ? CHECK_DIRS : CHECK_FILES; + check_type = (params->flag & FILE_DIRSEL_ONLY) ? CHECK_DIRS : CHECK_FILES; filesel_type = (action == SEL_INVERT) ? FILE_SEL_TOGGLE : FILE_SEL_ADD; break; } @@ -888,11 +890,11 @@ static int file_select_all_exec(bContext *C, wmOperator *op) filelist_entries_select_index_range_set( sfile->files, &sel, filesel_type, FILE_SEL_SELECTED, check_type); - sfile->params->active_file = -1; + params->active_file = -1; if (action != SEL_DESELECT) { for (int i = 0; i < numfiles; i++) { if (filelist_entry_select_index_get(sfile->files, i, check_type)) { - sfile->params->active_file = i; + params->active_file = i; break; } } @@ -935,8 +937,8 @@ static int bookmark_select_exec(bContext *C, wmOperator *op) PropertyRNA *prop; if ((prop = RNA_struct_find_property(op->ptr, "dir"))) { + FileSelectParams *params = ED_fileselect_get_active_params(sfile); char entry[256]; - FileSelectParams *params = sfile->params; RNA_property_string_get(op->ptr, prop, entry); BLI_strncpy(params->dir, entry, sizeof(params->dir)); @@ -978,7 +980,7 @@ static int bookmark_add_exec(bContext *C, wmOperator *UNUSED(op)) ScrArea *area = CTX_wm_area(C); SpaceFile *sfile = CTX_wm_space_file(C); struct FSMenu *fsmenu = ED_fsmenu_get(); - struct FileSelectParams *params = ED_fileselect_get_params(sfile); + struct FileSelectParams *params = ED_fileselect_get_active_params(sfile); if (params->dir[0] != '\0') { char name[FILE_MAX]; @@ -1274,7 +1276,7 @@ int file_highlight_set(SpaceFile *sfile, ARegion *region, int mx, int my) } numfiles = filelist_files_ensure(sfile->files); - params = ED_fileselect_get_params(sfile); + params = ED_fileselect_get_active_params(sfile); origfile = params->highlight_file; @@ -1345,20 +1347,21 @@ static int file_column_sort_ui_context_invoke(bContext *C, if (file_attribute_column_header_is_inside( ®ion->v2d, sfile->layout, event->mval[0], event->mval[1])) { + FileSelectParams *params = ED_fileselect_get_active_params(sfile); const FileAttributeColumnType column_type = file_attribute_column_type_find_isect( - ®ion->v2d, sfile->params, sfile->layout, event->mval[0]); + ®ion->v2d, params, sfile->layout, event->mval[0]); if (column_type != COLUMN_NONE) { const FileAttributeColumn *column = &sfile->layout->attribute_columns[column_type]; BLI_assert(column->sort_type != FILE_SORT_DEFAULT); - if (sfile->params->sort == column->sort_type) { + if (params->sort == column->sort_type) { /* Already sorting by selected column -> toggle sort invert (three state logic). */ - sfile->params->flag ^= FILE_SORT_INVERT; + params->flag ^= FILE_SORT_INVERT; } else { - sfile->params->sort = column->sort_type; - sfile->params->flag &= ~FILE_SORT_INVERT; + params->sort = column->sort_type; + params->flag &= ~FILE_SORT_INVERT; } WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL); @@ -1433,10 +1436,11 @@ void FILE_OT_cancel(struct wmOperatorType *ot) void file_sfile_to_operator_ex(Main *bmain, wmOperator *op, SpaceFile *sfile, char *filepath) { + FileSelectParams *params = ED_fileselect_get_active_params(sfile); PropertyRNA *prop; /* XXX, not real length */ - BLI_join_dirfile(filepath, FILE_MAX, sfile->params->dir, sfile->params->file); + BLI_join_dirfile(filepath, FILE_MAX, params->dir, params->file); if ((prop = RNA_struct_find_property(op->ptr, "relative_path"))) { if (RNA_property_boolean_get(op->ptr, prop)) { @@ -1445,10 +1449,10 @@ void file_sfile_to_operator_ex(Main *bmain, wmOperator *op, SpaceFile *sfile, ch } if ((prop = RNA_struct_find_property(op->ptr, "filename"))) { - RNA_property_string_set(op->ptr, prop, sfile->params->file); + RNA_property_string_set(op->ptr, prop, params->file); } if ((prop = RNA_struct_find_property(op->ptr, "directory"))) { - RNA_property_string_set(op->ptr, prop, sfile->params->dir); + RNA_property_string_set(op->ptr, prop, params->dir); } if ((prop = RNA_struct_find_property(op->ptr, "filepath"))) { RNA_property_string_set(op->ptr, prop, filepath); @@ -1479,7 +1483,7 @@ void file_sfile_to_operator_ex(Main *bmain, wmOperator *op, SpaceFile *sfile, ch * files selected */ if (0 == num_files) { RNA_property_collection_add(op->ptr, prop, &itemptr); - RNA_string_set(&itemptr, "name", sfile->params->file); + RNA_string_set(&itemptr, "name", params->file); } } @@ -1500,7 +1504,7 @@ void file_sfile_to_operator_ex(Main *bmain, wmOperator *op, SpaceFile *sfile, ch * directory selected */ if (0 == num_dirs) { RNA_property_collection_add(op->ptr, prop, &itemptr); - RNA_string_set(&itemptr, "name", sfile->params->dir); + RNA_string_set(&itemptr, "name", params->dir); } } } @@ -1514,30 +1518,28 @@ void file_sfile_to_operator(Main *bmain, wmOperator *op, SpaceFile *sfile) void file_operator_to_sfile(Main *bmain, SpaceFile *sfile, wmOperator *op) { + FileSelectParams *params = ED_fileselect_get_active_params(sfile); PropertyRNA *prop; /* If neither of the above are set, split the filepath back */ if ((prop = RNA_struct_find_property(op->ptr, "filepath"))) { char filepath[FILE_MAX]; RNA_property_string_get(op->ptr, prop, filepath); - BLI_split_dirfile(filepath, - sfile->params->dir, - sfile->params->file, - sizeof(sfile->params->dir), - sizeof(sfile->params->file)); + BLI_split_dirfile( + filepath, params->dir, params->file, sizeof(params->dir), sizeof(params->file)); } else { if ((prop = RNA_struct_find_property(op->ptr, "filename"))) { - RNA_property_string_get(op->ptr, prop, sfile->params->file); + RNA_property_string_get(op->ptr, prop, params->file); } if ((prop = RNA_struct_find_property(op->ptr, "directory"))) { - RNA_property_string_get(op->ptr, prop, sfile->params->dir); + RNA_property_string_get(op->ptr, prop, params->dir); } } /* we could check for relative_path property which is used when converting * in the other direction but doesn't hurt to do this every time */ - BLI_path_abs(sfile->params->dir, BKE_main_blendfile_path(bmain)); + BLI_path_abs(params->dir, BKE_main_blendfile_path(bmain)); /* XXX, files and dirs updates missing, not really so important though */ } @@ -1547,21 +1549,19 @@ void file_operator_to_sfile(Main *bmain, SpaceFile *sfile, wmOperator *op) */ void file_sfile_filepath_set(SpaceFile *sfile, const char *filepath) { + FileSelectParams *params = ED_fileselect_get_active_params(sfile); BLI_assert(BLI_exists(filepath)); if (BLI_is_dir(filepath)) { - BLI_strncpy(sfile->params->dir, filepath, sizeof(sfile->params->dir)); + BLI_strncpy(params->dir, filepath, sizeof(params->dir)); } else { - if ((sfile->params->flag & FILE_DIRSEL_ONLY) == 0) { - BLI_split_dirfile(filepath, - sfile->params->dir, - sfile->params->file, - sizeof(sfile->params->dir), - sizeof(sfile->params->file)); + if ((params->flag & FILE_DIRSEL_ONLY) == 0) { + BLI_split_dirfile( + filepath, params->dir, params->file, sizeof(params->dir), sizeof(params->file)); } else { - BLI_split_dir_part(filepath, sfile->params->dir, sizeof(sfile->params->dir)); + BLI_split_dir_part(filepath, params->dir, sizeof(params->dir)); } } } @@ -1605,9 +1605,10 @@ void file_draw_check_cb(bContext *C, void *UNUSED(arg1), void *UNUSED(arg2)) bool file_draw_check_exists(SpaceFile *sfile) { if (sfile->op) { /* fails on reload */ - if (sfile->params && (sfile->params->flag & FILE_CHECK_EXISTING)) { + const FileSelectParams *params = ED_fileselect_get_active_params(sfile); + if (params && (params->flag & FILE_CHECK_EXISTING)) { char filepath[FILE_MAX]; - BLI_join_dirfile(filepath, sizeof(filepath), sfile->params->dir, sfile->params->file); + BLI_join_dirfile(filepath, sizeof(filepath), params->dir, params->file); if (BLI_is_file(filepath)) { return true; } @@ -1628,21 +1629,22 @@ static int file_exec(bContext *C, wmOperator *exec_op) Main *bmain = CTX_data_main(C); wmWindowManager *wm = CTX_wm_manager(C); SpaceFile *sfile = CTX_wm_space_file(C); - struct FileDirEntry *file = filelist_file(sfile->files, sfile->params->active_file); + FileSelectParams *params = ED_fileselect_get_active_params(sfile); + struct FileDirEntry *file = filelist_file(sfile->files, params->active_file); char filepath[FILE_MAX]; if (file && file->redirection_path) { /* redirection_path is an absolute path that takes precedence - * over using sfile->params->dir + sfile->params->file. */ + * over using params->dir + params->file. */ BLI_split_dirfile(file->redirection_path, - sfile->params->dir, - sfile->params->file, - sizeof(sfile->params->dir), - sizeof(sfile->params->file)); + params->dir, + params->file, + sizeof(params->dir), + sizeof(params->file)); /* Update relpath with redirected filename as well so that the alternative - * combination of sfile->params->dir + relpath remains valid as well. */ + * combination of params->dir + relpath remains valid as well. */ MEM_freeN(file->relpath); - file->relpath = BLI_strdup(sfile->params->file); + file->relpath = BLI_strdup(params->file); } /* directory change */ @@ -1652,12 +1654,12 @@ static int file_exec(bContext *C, wmOperator *exec_op) } if (FILENAME_IS_PARENT(file->relpath)) { - BLI_path_parent_dir(sfile->params->dir); + BLI_path_parent_dir(params->dir); } else { - BLI_path_normalize(BKE_main_blendfile_path(bmain), sfile->params->dir); - BLI_path_append(sfile->params->dir, sizeof(sfile->params->dir) - 1, file->relpath); - BLI_path_slash_ensure(sfile->params->dir); + BLI_path_normalize(BKE_main_blendfile_path(bmain), params->dir); + BLI_path_append(params->dir, sizeof(params->dir) - 1, file->relpath); + BLI_path_slash_ensure(params->dir); } ED_file_change_dir(C); } @@ -1685,10 +1687,10 @@ static int file_exec(bContext *C, wmOperator *exec_op) file_sfile_to_operator_ex(bmain, op, sfile, filepath); - if (BLI_exists(sfile->params->dir)) { + if (BLI_exists(params->dir)) { fsmenu_insert_entry(ED_fsmenu_get(), FS_CATEGORY_RECENT, - sfile->params->dir, + params->dir, NULL, ICON_FILE_FOLDER, FS_INSERT_SAVE | FS_INSERT_FIRST); @@ -1792,15 +1794,16 @@ static int file_parent_exec(bContext *C, wmOperator *UNUSED(unused)) { Main *bmain = CTX_data_main(C); SpaceFile *sfile = CTX_wm_space_file(C); + FileSelectParams *params = ED_fileselect_get_active_params(sfile); - if (sfile->params) { - if (BLI_path_parent_dir(sfile->params->dir)) { - BLI_path_normalize_dir(BKE_main_blendfile_path(bmain), sfile->params->dir); + if (params) { + if (BLI_path_parent_dir(params->dir)) { + BLI_path_normalize_dir(BKE_main_blendfile_path(bmain), params->dir); ED_file_change_dir(C); - if (sfile->params->recursion_level > 1) { + if (params->recursion_level > 1) { /* Disable 'dirtree' recursion when going up in tree. */ - sfile->params->recursion_level = 0; - filelist_setrecursion(sfile->files, sfile->params->recursion_level); + params->recursion_level = 0; + filelist_setrecursion(sfile->files, params->recursion_level); } WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL); } @@ -1830,15 +1833,16 @@ void FILE_OT_parent(struct wmOperatorType *ot) static int file_previous_exec(bContext *C, wmOperator *UNUSED(op)) { SpaceFile *sfile = CTX_wm_space_file(C); + FileSelectParams *params = ED_fileselect_get_active_params(sfile); - if (sfile->params) { + if (params) { if (!sfile->folders_next) { sfile->folders_next = folderlist_new(); } - folderlist_pushdir(sfile->folders_next, sfile->params->dir); - folderlist_popdir(sfile->folders_prev, sfile->params->dir); - folderlist_pushdir(sfile->folders_next, sfile->params->dir); + folderlist_pushdir(sfile->folders_next, params->dir); + folderlist_popdir(sfile->folders_prev, params->dir); + folderlist_pushdir(sfile->folders_next, params->dir); ED_file_change_dir(C); } @@ -1868,16 +1872,17 @@ void FILE_OT_previous(struct wmOperatorType *ot) static int file_next_exec(bContext *C, wmOperator *UNUSED(unused)) { SpaceFile *sfile = CTX_wm_space_file(C); - if (sfile->params) { + FileSelectParams *params = ED_fileselect_get_active_params(sfile); + if (params) { if (!sfile->folders_next) { sfile->folders_next = folderlist_new(); } - folderlist_pushdir(sfile->folders_prev, sfile->params->dir); - folderlist_popdir(sfile->folders_next, sfile->params->dir); + folderlist_pushdir(sfile->folders_prev, params->dir); + folderlist_popdir(sfile->folders_next, params->dir); /* update folders_prev so we can check for it in #folderlist_clear_next() */ - folderlist_pushdir(sfile->folders_prev, sfile->params->dir); + folderlist_pushdir(sfile->folders_prev, params->dir); ED_file_change_dir(C); } @@ -1923,7 +1928,7 @@ static int file_smoothscroll_invoke(bContext *C, wmOperator *UNUSED(op), const w /* Due to async nature of file listing, we may execute this code before `file_refresh()` * editing entry is available in our listing, * so we also have to handle switching to rename mode here. */ - FileSelectParams *params = ED_fileselect_get_params(sfile); + FileSelectParams *params = ED_fileselect_get_active_params(sfile); if ((params->rename_flag & (FILE_PARAMS_RENAME_PENDING | FILE_PARAMS_RENAME_POSTSCROLL_PENDING)) != 0) { file_params_renamefile_activate(sfile, params); @@ -2175,9 +2180,10 @@ static int file_directory_new_exec(bContext *C, wmOperator *op) wmWindowManager *wm = CTX_wm_manager(C); SpaceFile *sfile = CTX_wm_space_file(C); + FileSelectParams *params = ED_fileselect_get_active_params(sfile); const bool do_diropen = RNA_boolean_get(op->ptr, "open"); - if (!sfile->params) { + if (!params) { BKE_report(op->reports, RPT_WARNING, "No parent directory given"); return OPERATOR_CANCELLED; } @@ -2193,7 +2199,7 @@ static int file_directory_new_exec(bContext *C, wmOperator *op) if (generate_name) { /* create a new, non-existing folder name */ - if (!new_folder_path(sfile->params->dir, path, name)) { + if (!new_folder_path(params->dir, path, name)) { BKE_report(op->reports, RPT_ERROR, "Could not create new folder name"); return OPERATOR_CANCELLED; } @@ -2226,8 +2232,8 @@ static int file_directory_new_exec(bContext *C, wmOperator *op) /* If we don't enter the directory directly, remember file to jump into editing. */ if (do_diropen == false) { - BLI_strncpy(sfile->params->renamefile, name, FILE_MAXFILE); - sfile->params->rename_flag = FILE_PARAMS_RENAME_PENDING; + BLI_strncpy(params->renamefile, name, FILE_MAXFILE); + params->rename_flag = FILE_PARAMS_RENAME_PENDING; } /* set timer to smoothly view newly generated file */ @@ -2242,7 +2248,7 @@ static int file_directory_new_exec(bContext *C, wmOperator *op) ED_fileselect_clear(wm, CTX_data_scene(C), sfile); if (do_diropen) { - BLI_strncpy(sfile->params->dir, path, sizeof(sfile->params->dir)); + BLI_strncpy(params->dir, path, sizeof(params->dir)); ED_file_change_dir(C); } @@ -2284,38 +2290,37 @@ static void file_expand_directory(bContext *C) { Main *bmain = CTX_data_main(C); SpaceFile *sfile = CTX_wm_space_file(C); + FileSelectParams *params = ED_fileselect_get_active_params(sfile); - if (sfile->params) { - if (BLI_path_is_rel(sfile->params->dir)) { + if (params) { + if (BLI_path_is_rel(params->dir)) { /* Use of 'default' folder here is just to avoid an error message on '//' prefix. */ - BLI_path_abs(sfile->params->dir, + BLI_path_abs(params->dir, G.relbase_valid ? BKE_main_blendfile_path(bmain) : BKE_appdir_folder_default()); } - else if (sfile->params->dir[0] == '~') { - char tmpstr[sizeof(sfile->params->dir) - 1]; - BLI_strncpy(tmpstr, sfile->params->dir + 1, sizeof(tmpstr)); - BLI_join_dirfile( - sfile->params->dir, sizeof(sfile->params->dir), BKE_appdir_folder_default(), tmpstr); + else if (params->dir[0] == '~') { + char tmpstr[sizeof(params->dir) - 1]; + BLI_strncpy(tmpstr, params->dir + 1, sizeof(tmpstr)); + BLI_join_dirfile(params->dir, sizeof(params->dir), BKE_appdir_folder_default(), tmpstr); } - else if (sfile->params->dir[0] == '\0') + else if (params->dir[0] == '\0') #ifndef WIN32 { - sfile->params->dir[0] = '/'; - sfile->params->dir[1] = '\0'; + params->dir[0] = '/'; + params->dir[1] = '\0'; } #else { - BLI_windows_get_default_root_dir(sfile->params->dir); + BLI_windows_get_default_root_dir(params->dir); } /* change "C:" --> "C:\", T28102. */ - else if ((isalpha(sfile->params->dir[0]) && (sfile->params->dir[1] == ':')) && - (sfile->params->dir[2] == '\0')) { - sfile->params->dir[2] = '\\'; - sfile->params->dir[3] = '\0'; + else if ((isalpha(params->dir[0]) && (params->dir[1] == ':')) && (params->dir[2] == '\0')) { + params->dir[2] = '\\'; + params->dir[3] = '\0'; } - else if (BLI_path_is_unc(sfile->params->dir)) { - BLI_path_normalize_unc(sfile->params->dir, FILE_MAX_LIBEXTRA); + else if (BLI_path_is_unc(params->dir)) { + BLI_path_normalize_unc(params->dir, FILE_MAX_LIBEXTRA); } #endif } @@ -2343,46 +2348,44 @@ void file_directory_enter_handle(bContext *C, void *UNUSED(arg_unused), void *UN { Main *bmain = CTX_data_main(C); SpaceFile *sfile = CTX_wm_space_file(C); + FileSelectParams *params = ED_fileselect_get_active_params(sfile); - if (sfile->params) { - char old_dir[sizeof(sfile->params->dir)]; + if (params) { + char old_dir[sizeof(params->dir)]; - BLI_strncpy(old_dir, sfile->params->dir, sizeof(old_dir)); + BLI_strncpy(old_dir, params->dir, sizeof(old_dir)); file_expand_directory(C); /* special case, user may have pasted a filepath into the directory */ - if (!filelist_is_dir(sfile->files, sfile->params->dir)) { + if (!filelist_is_dir(sfile->files, params->dir)) { char tdir[FILE_MAX_LIBEXTRA]; char *group, *name; - if (BLI_is_file(sfile->params->dir)) { - char path[sizeof(sfile->params->dir)]; - BLI_strncpy(path, sfile->params->dir, sizeof(path)); - BLI_split_dirfile(path, - sfile->params->dir, - sfile->params->file, - sizeof(sfile->params->dir), - sizeof(sfile->params->file)); + if (BLI_is_file(params->dir)) { + char path[sizeof(params->dir)]; + BLI_strncpy(path, params->dir, sizeof(path)); + BLI_split_dirfile( + path, params->dir, params->file, sizeof(params->dir), sizeof(params->file)); } - else if (BLO_library_path_explode(sfile->params->dir, tdir, &group, &name)) { + else if (BLO_library_path_explode(params->dir, tdir, &group, &name)) { if (group) { BLI_path_append(tdir, sizeof(tdir), group); } - BLI_strncpy(sfile->params->dir, tdir, sizeof(sfile->params->dir)); + BLI_strncpy(params->dir, tdir, sizeof(params->dir)); if (name) { - BLI_strncpy(sfile->params->file, name, sizeof(sfile->params->file)); + BLI_strncpy(params->file, name, sizeof(params->file)); } else { - sfile->params->file[0] = '\0'; + params->file[0] = '\0'; } } } - BLI_path_normalize_dir(BKE_main_blendfile_path(bmain), sfile->params->dir); + BLI_path_normalize_dir(BKE_main_blendfile_path(bmain), params->dir); - if (filelist_is_dir(sfile->files, sfile->params->dir)) { - if (!STREQ(sfile->params->dir, old_dir)) { /* Avoids flickering when nothing's changed. */ + if (filelist_is_dir(sfile->files, params->dir)) { + if (!STREQ(params->dir, old_dir)) { /* Avoids flickering when nothing's changed. */ /* if directory exists, enter it immediately */ ED_file_change_dir(C); } @@ -2392,10 +2395,10 @@ void file_directory_enter_handle(bContext *C, void *UNUSED(arg_unused), void *UN /* UI_textbutton_activate_but(C, but); */ } #if defined(WIN32) - else if (!can_create_dir(sfile->params->dir)) { + else if (!can_create_dir(params->dir)) { const char *lastdir = folderlist_peeklastdir(sfile->folders_prev); if (lastdir) { - BLI_strncpy(sfile->params->dir, lastdir, sizeof(sfile->params->dir)); + BLI_strncpy(params->dir, lastdir, sizeof(params->dir)); } } #endif @@ -2405,21 +2408,21 @@ void file_directory_enter_handle(bContext *C, void *UNUSED(arg_unused), void *UN /* If we are 'inside' a blend library, we cannot do anything... */ if (lastdir && BLO_library_path_explode(lastdir, tdir, NULL, NULL)) { - BLI_strncpy(sfile->params->dir, lastdir, sizeof(sfile->params->dir)); + BLI_strncpy(params->dir, lastdir, sizeof(params->dir)); } else { /* if not, ask to create it and enter if confirmed */ wmOperatorType *ot = WM_operatortype_find("FILE_OT_directory_new", false); PointerRNA ptr; WM_operator_properties_create_ptr(&ptr, ot); - RNA_string_set(&ptr, "directory", sfile->params->dir); + RNA_string_set(&ptr, "directory", params->dir); RNA_boolean_set(&ptr, "open", true); /* Enable confirmation prompt, else it's too easy * to accidentally create new directories. */ RNA_boolean_set(&ptr, "confirm", true); if (lastdir) { - BLI_strncpy(sfile->params->dir, lastdir, sizeof(sfile->params->dir)); + BLI_strncpy(params->dir, lastdir, sizeof(params->dir)); } WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr); @@ -2435,39 +2438,39 @@ void file_filename_enter_handle(bContext *C, void *UNUSED(arg_unused), void *arg { Main *bmain = CTX_data_main(C); SpaceFile *sfile = CTX_wm_space_file(C); + FileSelectParams *params = ED_fileselect_get_active_params(sfile); uiBut *but = arg_but; char matched_file[FILE_MAX]; - char filepath[sizeof(sfile->params->dir)]; - if (sfile->params) { + if (params) { + char filepath[sizeof(params->dir)]; int matches; matched_file[0] = '\0'; filepath[0] = '\0'; file_expand_directory(C); - matches = file_select_match(sfile, sfile->params->file, matched_file); + matches = file_select_match(sfile, params->file, matched_file); /* *After* file_select_match! */ - BLI_filename_make_safe(sfile->params->file); + BLI_filename_make_safe(params->file); if (matches) { /* replace the pattern (or filename that the user typed in, * with the first selected file of the match */ - BLI_strncpy(sfile->params->file, matched_file, sizeof(sfile->params->file)); + BLI_strncpy(params->file, matched_file, sizeof(params->file)); WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL); } if (matches == 1) { - BLI_join_dirfile( - filepath, sizeof(sfile->params->dir), sfile->params->dir, sfile->params->file); + BLI_join_dirfile(filepath, sizeof(params->dir), params->dir, params->file); /* if directory, open it and empty filename field */ if (filelist_is_dir(sfile->files, filepath)) { BLI_path_normalize_dir(BKE_main_blendfile_path(bmain), filepath); - BLI_strncpy(sfile->params->dir, filepath, sizeof(sfile->params->dir)); - sfile->params->file[0] = '\0'; + BLI_strncpy(params->dir, filepath, sizeof(params->dir)); + params->file[0] = '\0'; ED_file_change_dir(C); UI_textbutton_activate_but(C, but); WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL); @@ -2489,9 +2492,10 @@ static int file_hidedot_exec(bContext *C, wmOperator *UNUSED(unused)) { wmWindowManager *wm = CTX_wm_manager(C); SpaceFile *sfile = CTX_wm_space_file(C); + FileSelectParams *params = ED_fileselect_get_active_params(sfile); - if (sfile->params) { - sfile->params->flag ^= FILE_HIDE_DOT; + if (params) { + params->flag ^= FILE_HIDE_DOT; ED_fileselect_clear(wm, CTX_data_scene(C), sfile); WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL); } @@ -2525,7 +2529,8 @@ static bool file_filenum_poll(bContext *C) return false; } - return sfile->params && (sfile->params->flag & FILE_CHECK_EXISTING); + FileSelectParams *params = ED_fileselect_get_active_params(sfile); + return params && (params->flag & FILE_CHECK_EXISTING); } /** @@ -2563,11 +2568,12 @@ static void filenum_newname(char *name, size_t name_size, int add) static int file_filenum_exec(bContext *C, wmOperator *op) { SpaceFile *sfile = CTX_wm_space_file(C); + FileSelectParams *params = ED_fileselect_get_active_params(sfile); ScrArea *area = CTX_wm_area(C); int inc = RNA_int_get(op->ptr, "increment"); - if (sfile->params && (inc != 0)) { - filenum_newname(sfile->params->file, sizeof(sfile->params->file), inc); + if (params && (inc != 0)) { + filenum_newname(params->file, sizeof(params->file), inc); ED_area_tag_redraw(area); file_draw_check(C); // WM_event_add_notifier(C, NC_WINDOW, NULL); @@ -2606,12 +2612,14 @@ static void file_rename_state_activate(SpaceFile *sfile, int file_idx, bool requ if ((require_selected == false) || (filelist_entry_select_get(sfile->files, file, CHECK_ALL) & FILE_SEL_SELECTED)) { + FileSelectParams *params = ED_fileselect_get_active_params(sfile); + filelist_entry_select_index_set( sfile->files, file_idx, FILE_SEL_ADD, FILE_SEL_EDITING, CHECK_ALL); - BLI_strncpy(sfile->params->renamefile, file->relpath, FILE_MAXFILE); + BLI_strncpy(params->renamefile, file->relpath, FILE_MAXFILE); /* We can skip the pending state, * as we can directly set FILE_SEL_EDITING on the expected entry here. */ - sfile->params->rename_flag = FILE_PARAMS_RENAME_ACTIVE; + params->rename_flag = FILE_PARAMS_RENAME_ACTIVE; } } } @@ -2620,9 +2628,10 @@ static int file_rename_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent { ScrArea *area = CTX_wm_area(C); SpaceFile *sfile = (SpaceFile *)CTX_wm_space_data(C); + FileSelectParams *params = ED_fileselect_get_active_params(sfile); - if (sfile->params) { - file_rename_state_activate(sfile, sfile->params->active_file, true); + if (params) { + file_rename_state_activate(sfile, params->active_file, true); ED_area_tag_redraw(area); } @@ -2633,9 +2642,10 @@ static int file_rename_exec(bContext *C, wmOperator *UNUSED(op)) { ScrArea *area = CTX_wm_area(C); SpaceFile *sfile = (SpaceFile *)CTX_wm_space_data(C); + FileSelectParams *params = ED_fileselect_get_active_params(sfile); - if (sfile->params) { - file_rename_state_activate(sfile, sfile->params->highlight_file, false); + if (params) { + file_rename_state_activate(sfile, params->highlight_file, false); ED_area_tag_redraw(area); } @@ -2665,8 +2675,9 @@ static bool file_delete_poll(bContext *C) { bool poll = ED_operator_file_active(C); SpaceFile *sfile = CTX_wm_space_file(C); + FileSelectParams *params = ED_fileselect_get_active_params(sfile); - if (sfile && sfile->params) { + if (sfile && params) { char dir[FILE_MAX_LIBEXTRA]; int numfiles = filelist_files_ensure(sfile->files); int i; @@ -2695,6 +2706,7 @@ static int file_delete_exec(bContext *C, wmOperator *op) { wmWindowManager *wm = CTX_wm_manager(C); SpaceFile *sfile = CTX_wm_space_file(C); + FileSelectParams *params = ED_fileselect_get_active_params(sfile); int numfiles = filelist_files_ensure(sfile->files); const char *error_message = NULL; @@ -2704,7 +2716,7 @@ static int file_delete_exec(bContext *C, wmOperator *op) if (filelist_entry_select_index_get(sfile->files, i, CHECK_ALL)) { FileDirEntry *file = filelist_file(sfile->files, i); char str[FILE_MAX]; - BLI_join_dirfile(str, sizeof(str), sfile->params->dir, file->relpath); + BLI_join_dirfile(str, sizeof(str), params->dir, file->relpath); if (BLI_delete_soft(str, &error_message) != 0 || BLI_exists(str)) { report_error = true; } @@ -2752,11 +2764,12 @@ static int file_start_filter_exec(bContext *C, wmOperator *UNUSED(op)) { ScrArea *area = CTX_wm_area(C); ARegion *region = BKE_area_find_region_type(area, RGN_TYPE_UI); - SpaceFile *sf = CTX_wm_space_file(C); + SpaceFile *sfile = CTX_wm_space_file(C); + FileSelectParams *params = ED_fileselect_get_active_params(sfile); ARegion *region_ctx = CTX_wm_region(C); CTX_wm_region_set(C, region); - UI_textbutton_activate_rna(C, region, sf->params, "filter_search"); + UI_textbutton_activate_rna(C, region, params, "filter_search"); CTX_wm_region_set(C, region_ctx); return OPERATOR_FINISHED; diff --git a/source/blender/editors/space_file/file_panels.c b/source/blender/editors/space_file/file_panels.c index 22d206c0a70..afa85d183d8 100644 --- a/source/blender/editors/space_file/file_panels.c +++ b/source/blender/editors/space_file/file_panels.c @@ -132,7 +132,7 @@ static void file_panel_execution_buttons_draw(const bContext *C, Panel *panel) { bScreen *screen = CTX_wm_screen(C); SpaceFile *sfile = CTX_wm_space_file(C); - FileSelectParams *params = ED_fileselect_get_params(sfile); + FileSelectParams *params = ED_fileselect_get_active_params(sfile); uiBlock *block = uiLayoutGetBlock(panel->layout); uiBut *but; uiLayout *row; diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c index b6d016aca7c..58887ae745b 100644 --- a/source/blender/editors/space_file/filelist.c +++ b/source/blender/editors/space_file/filelist.c @@ -149,6 +149,7 @@ const char *folderlist_peeklastdir(ListBase *folderlist) int folderlist_clear_next(struct SpaceFile *sfile) { + const FileSelectParams *params = ED_fileselect_get_active_params(sfile); struct FolderList *folder; /* if there is no folder_next there is nothing we can clear */ @@ -159,7 +160,7 @@ int folderlist_clear_next(struct SpaceFile *sfile) /* if previous_folder, next_folder or refresh_folder operators are executed * it doesn't clear folder_next */ folder = sfile->folders_prev->last; - if ((!folder) || (BLI_path_cmp(folder->foldername, sfile->params->dir) == 0)) { + if ((!folder) || (BLI_path_cmp(folder->foldername, params->dir) == 0)) { return 0; } diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c index 15c6972c5f5..ffa44083473 100644 --- a/source/blender/editors/space_file/filesel.c +++ b/source/blender/editors/space_file/filesel.c @@ -77,18 +77,20 @@ #define VERTLIST_MAJORCOLUMN_WIDTH (25 * UI_UNIT_X) -FileSelectParams *ED_fileselect_get_params(struct SpaceFile *sfile) +FileSelectParams *ED_fileselect_get_active_params(const SpaceFile *sfile) { - if (!sfile->params) { - ED_fileselect_set_params(sfile); + if (!sfile) { + /* Sometimes called in poll before space type was checked. */ + return NULL; } + return sfile->params; } /** * \note RNA_struct_property_is_set_ex is used here because we want * the previously used settings to be used here rather than overriding them */ -short ED_fileselect_set_params(SpaceFile *sfile) +static void fileselect_ensure_file_params(SpaceFile *sfile) { FileSelectParams *params; wmOperator *op = sfile->op; @@ -136,20 +138,17 @@ short ED_fileselect_set_params(SpaceFile *sfile) RNA_string_get(op->ptr, "filepath", name); if (params->type == FILE_LOADLIB) { BLI_strncpy(params->dir, name, sizeof(params->dir)); - sfile->params->file[0] = '\0'; + params->file[0] = '\0'; } else { - BLI_split_dirfile(name, - sfile->params->dir, - sfile->params->file, - sizeof(sfile->params->dir), - sizeof(sfile->params->file)); + BLI_split_dirfile( + name, params->dir, params->file, sizeof(params->dir), sizeof(params->file)); } } else { if (is_directory && RNA_struct_property_is_set_ex(op->ptr, "directory", false)) { RNA_string_get(op->ptr, "directory", params->dir); - sfile->params->file[0] = '\0'; + params->file[0] = '\0'; } if (is_filename && RNA_struct_property_is_set_ex(op->ptr, "filename", false)) { @@ -306,26 +305,32 @@ short ED_fileselect_set_params(SpaceFile *sfile) sfile->folders_prev = folderlist_new(); } - if (!sfile->params->dir[0]) { + if (!params->dir[0]) { if (blendfile_path[0] != '\0') { - BLI_split_dir_part(blendfile_path, sfile->params->dir, sizeof(sfile->params->dir)); + BLI_split_dir_part(blendfile_path, params->dir, sizeof(params->dir)); } else { const char *doc_path = BKE_appdir_folder_default(); if (doc_path) { - BLI_strncpy(sfile->params->dir, doc_path, sizeof(sfile->params->dir)); + BLI_strncpy(params->dir, doc_path, sizeof(params->dir)); } } } - folderlist_pushdir(sfile->folders_prev, sfile->params->dir); + folderlist_pushdir(sfile->folders_prev, params->dir); /* Switching thumbnails needs to recalc layout T28809. */ if (sfile->layout) { sfile->layout->dirty = true; } +} - return 1; +FileSelectParams *ED_fileselect_ensure_active_params(SpaceFile *sfile) +{ + if (!sfile->params) { + fileselect_ensure_file_params(sfile); + } + return sfile->params; } /* The subset of FileSelectParams.flag items we store into preferences. Note that FILE_SORT_ALPHA @@ -364,28 +369,26 @@ void ED_fileselect_set_params_from_userdef(SpaceFile *sfile) wmOperator *op = sfile->op; UserDef_FileSpaceData *sfile_udata = &U.file_space_data; - ED_fileselect_set_params(sfile); - + FileSelectParams *params = ED_fileselect_ensure_active_params(sfile); if (!op) { return; } - sfile->params->thumbnail_size = sfile_udata->thumbnail_size; - sfile->params->details_flags = sfile_udata->details_flags; - sfile->params->filter_id = sfile_udata->filter_id; + params->thumbnail_size = sfile_udata->thumbnail_size; + params->details_flags = sfile_udata->details_flags; + params->filter_id = sfile_udata->filter_id; /* Combine flags we take from params with the flags we take from userdef. */ - sfile->params->flag = (sfile->params->flag & ~PARAMS_FLAGS_REMEMBERED) | - (sfile_udata->flag & PARAMS_FLAGS_REMEMBERED); + params->flag = (params->flag & ~PARAMS_FLAGS_REMEMBERED) | + (sfile_udata->flag & PARAMS_FLAGS_REMEMBERED); if (file_select_use_default_display_type(sfile)) { - sfile->params->display = sfile_udata->display_type; + params->display = sfile_udata->display_type; } if (file_select_use_default_sort_type(sfile)) { - sfile->params->sort = sfile_udata->sort_type; + params->sort = sfile_udata->sort_type; /* For the default sorting, also take invert flag from userdef. */ - sfile->params->flag = (sfile->params->flag & ~FILE_SORT_INVERT) | - (sfile_udata->flag & FILE_SORT_INVERT); + params->flag = (params->flag & ~FILE_SORT_INVERT) | (sfile_udata->flag & FILE_SORT_INVERT); } } @@ -400,25 +403,26 @@ void ED_fileselect_params_to_userdef(SpaceFile *sfile, const int temp_win_size[2], const bool is_maximized) { + FileSelectParams *params = ED_fileselect_get_active_params(sfile); UserDef_FileSpaceData *sfile_udata_new = &U.file_space_data; UserDef_FileSpaceData sfile_udata_old = U.file_space_data; - sfile_udata_new->thumbnail_size = sfile->params->thumbnail_size; - sfile_udata_new->details_flags = sfile->params->details_flags; - sfile_udata_new->flag = sfile->params->flag & PARAMS_FLAGS_REMEMBERED; - sfile_udata_new->filter_id = sfile->params->filter_id; + sfile_udata_new->thumbnail_size = params->thumbnail_size; + sfile_udata_new->details_flags = params->details_flags; + sfile_udata_new->flag = params->flag & PARAMS_FLAGS_REMEMBERED; + sfile_udata_new->filter_id = params->filter_id; /* In some rare cases, operators ask for a specific display or sort type (e.g. chronological * sorting for "Recover Auto Save"). So the settings are optimized for a specific operation. * Don't let that change the userdef memory for more general cases. */ if (file_select_use_default_display_type(sfile)) { - sfile_udata_new->display_type = sfile->params->display; + sfile_udata_new->display_type = params->display; } if (file_select_use_default_sort_type(sfile)) { - sfile_udata_new->sort_type = sfile->params->sort; + sfile_udata_new->sort_type = params->sort; /* In this case also remember the invert flag. */ sfile_udata_new->flag = (sfile_udata_new->flag & ~FILE_SORT_INVERT) | - (sfile->params->flag & FILE_SORT_INVERT); + (params->flag & FILE_SORT_INVERT); } if (temp_win_size && !is_maximized) { @@ -434,10 +438,11 @@ void ED_fileselect_params_to_userdef(SpaceFile *sfile, void ED_fileselect_reset_params(SpaceFile *sfile) { - sfile->params->type = FILE_UNIX; - sfile->params->flag = 0; - sfile->params->title[0] = '\0'; - sfile->params->active_file = -1; + FileSelectParams *params = ED_fileselect_get_active_params(sfile); + params->type = FILE_UNIX; + params->flag = 0; + params->title[0] = '\0'; + params->active_file = -1; } /** @@ -447,7 +452,8 @@ void fileselect_file_set(SpaceFile *sfile, const int index) { const struct FileDirEntry *file = filelist_file(sfile->files, index); if (file && file->relpath && file->relpath[0] && !(file->typeflag & FILE_TYPE_DIR)) { - BLI_strncpy(sfile->params->file, file->relpath, FILE_MAXFILE); + FileSelectParams *params = ED_fileselect_get_active_params(sfile); + BLI_strncpy(params->file, file->relpath, FILE_MAXFILE); } } @@ -759,7 +765,7 @@ static void file_attribute_columns_init(const FileSelectParams *params, FileLayo void ED_fileselect_init_layout(struct SpaceFile *sfile, ARegion *region) { - FileSelectParams *params = ED_fileselect_get_params(sfile); + FileSelectParams *params = ED_fileselect_get_active_params(sfile); FileLayout *layout = NULL; View2D *v2d = ®ion->v2d; int numfiles; @@ -873,7 +879,8 @@ void ED_file_change_dir_ex(bContext *C, bScreen *screen, ScrArea *area) return; } SpaceFile *sfile = area->spacedata.first; - if (sfile->params) { + FileSelectParams *params = ED_fileselect_get_active_params(sfile); + if (params) { wmWindowManager *wm = CTX_wm_manager(C); Scene *scene = WM_windows_scene_get_from_screen(wm, screen); if (LIKELY(scene != NULL)) { @@ -882,20 +889,20 @@ void ED_file_change_dir_ex(bContext *C, bScreen *screen, ScrArea *area) /* Clear search string, it is very rare to want to keep that filter while changing dir, * and usually very annoying to keep it actually! */ - sfile->params->filter_search[0] = '\0'; - sfile->params->active_file = -1; + params->filter_search[0] = '\0'; + params->active_file = -1; - if (!filelist_is_dir(sfile->files, sfile->params->dir)) { - BLI_strncpy(sfile->params->dir, filelist_dir(sfile->files), sizeof(sfile->params->dir)); + if (!filelist_is_dir(sfile->files, params->dir)) { + BLI_strncpy(params->dir, filelist_dir(sfile->files), sizeof(params->dir)); /* could return but just refresh the current dir */ } - filelist_setdir(sfile->files, sfile->params->dir); + filelist_setdir(sfile->files, params->dir); if (folderlist_clear_next(sfile)) { folderlist_free(sfile->folders_next); } - folderlist_pushdir(sfile->folders_prev, sfile->params->dir); + folderlist_pushdir(sfile->folders_prev, params->dir); file_draw_check_ex(C, area); } @@ -1010,7 +1017,8 @@ void ED_fileselect_clear(wmWindowManager *wm, Scene *owner_scene, SpaceFile *sfi filelist_clear(sfile->files); } - sfile->params->highlight_file = -1; + FileSelectParams *params = ED_fileselect_get_active_params(sfile); + params->highlight_file = -1; WM_main_add_notifier(NC_SPACE | ND_SPACE_FILE_LIST, NULL); } diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c index 6ffe553e076..c72ca58abba 100644 --- a/source/blender/editors/space_file/space_file.c +++ b/source/blender/editors/space_file/space_file.c @@ -270,7 +270,7 @@ static void file_refresh(const bContext *C, ScrArea *area) wmWindowManager *wm = CTX_wm_manager(C); wmWindow *win = CTX_wm_window(C); SpaceFile *sfile = CTX_wm_space_file(C); - FileSelectParams *params = ED_fileselect_get_params(sfile); + FileSelectParams *params = ED_fileselect_ensure_active_params(sfile); struct FSMenu *fsmenu = ED_fsmenu_get(); if (!sfile->folders_prev) { @@ -413,7 +413,7 @@ static void file_main_region_message_subscribe(const struct bContext *UNUSED(C), struct wmMsgBus *mbus) { SpaceFile *sfile = area->spacedata.first; - FileSelectParams *params = ED_fileselect_get_params(sfile); + FileSelectParams *params = ED_fileselect_ensure_active_params(sfile); /* This is a bit odd that a region owns the subscriber for an area, * keep for now since all subscribers for WM are regions. * May be worth re-visiting later. */ @@ -446,7 +446,7 @@ static void file_main_region_draw(const bContext *C, ARegion *region) { /* draw entirely, view changes should be handled here */ SpaceFile *sfile = CTX_wm_space_file(C); - FileSelectParams *params = ED_fileselect_get_params(sfile); + FileSelectParams *params = ED_fileselect_ensure_active_params(sfile); View2D *v2d = ®ion->v2d; diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index ff77819aae1..65ea155ffba 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -2467,6 +2467,18 @@ static PointerRNA rna_FileSelectParams_filter_id_get(PointerRNA *ptr) return rna_pointer_inherit_refine(ptr, &RNA_FileSelectIDFilter, ptr->data); } +static PointerRNA rna_FileBrowser_params_get(PointerRNA *ptr) +{ + SpaceFile *sfile = ptr->data; + FileSelectParams *params = ED_fileselect_get_active_params(sfile); + + if (params) { + return rna_pointer_inherit_refine(ptr, &RNA_FileSelectParams, params); + } + + return rna_pointer_inherit_refine(ptr, NULL, NULL); +} + static void rna_FileBrowser_FSMenuEntry_path_get(PointerRNA *ptr, char *value) { char *path = ED_fsmenu_entry_get_path(ptr->data); @@ -6043,7 +6055,8 @@ static void rna_def_space_filebrowser(BlenderRNA *brna) rna_def_space_generic_show_region_toggles(srna, (1 << RGN_TYPE_TOOLS) | (1 << RGN_TYPE_UI)); prop = RNA_def_property(srna, "params", PROP_POINTER, PROP_NONE); - RNA_def_property_pointer_sdna(prop, NULL, "params"); + RNA_def_property_struct_type(prop, "FileSelectParams"); + RNA_def_property_pointer_funcs(prop, "rna_FileBrowser_params_get", NULL, NULL, NULL); RNA_def_property_ui_text( prop, "Filebrowser Parameter", "Parameters and Settings for the Filebrowser"); diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 9eedd5b2faa..a5d23365df3 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -84,6 +84,7 @@ #include "IMB_imbuf_types.h" +#include "ED_fileselect.h" #include "ED_numinput.h" #include "ED_screen.h" #include "ED_undo.h" @@ -496,7 +497,7 @@ static const char *wm_context_member_from_ptr(bContext *C, const PointerRNA *ptr } case SPACE_FILE: { const SpaceFile *sfile = (SpaceFile *)space_data; - const FileSelectParams *params = sfile->params; + const FileSelectParams *params = ED_fileselect_get_active_params(sfile); TEST_PTR_DATA_TYPE("space_data", RNA_FileSelectParams, ptr, params); break; } -- cgit v1.2.3 From 2678953f699c27122d059eb8ab14e84a5be75c28 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Tue, 8 Dec 2020 15:00:31 +0100 Subject: Cleanup: Correct an own earlier commit to use an existing utility function Didn't know this function existed, better to use it then to avoid verbosity. --- source/blender/blenloader/intern/blend_validate.c | 2 +- source/blender/editors/space_file/filelist.c | 2 +- source/blender/imbuf/intern/thumbs_blend.c | 4 ++-- source/blender/python/intern/bpy_library_load.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenloader/intern/blend_validate.c b/source/blender/blenloader/intern/blend_validate.c index 9b42e2d5f40..c281e2fa643 100644 --- a/source/blender/blenloader/intern/blend_validate.c +++ b/source/blender/blenloader/intern/blend_validate.c @@ -148,7 +148,7 @@ bool BLO_main_validate_libraries(Main *bmain, ReportList *reports) } } - BLI_linklist_free(names, MEM_freeN); + BLI_linklist_freeN(names); } BLO_blendhandle_close(bh); diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c index 58887ae745b..1271feda1e7 100644 --- a/source/blender/editors/space_file/filelist.c +++ b/source/blender/editors/space_file/filelist.c @@ -2621,7 +2621,7 @@ static int filelist_readjob_list_lib(const char *root, ListBase *entries, const nbr_entries++; } - BLI_linklist_free(names, MEM_freeN); + BLI_linklist_freeN(names); return nbr_entries; } diff --git a/source/blender/imbuf/intern/thumbs_blend.c b/source/blender/imbuf/intern/thumbs_blend.c index a338ea599f8..d5ded02be62 100644 --- a/source/blender/imbuf/intern/thumbs_blend.c +++ b/source/blender/imbuf/intern/thumbs_blend.c @@ -68,7 +68,7 @@ ImBuf *IMB_thumb_load_blend(const char *blen_path, const char *blen_group, const printf("%s: error, found %d items, %d previews\n", __func__, nnames, nprevs); } BLI_linklist_free(previews, BKE_previewimg_freefunc); - BLI_linklist_free(names, MEM_freeN); + BLI_linklist_freeN(names); return ima; } @@ -93,7 +93,7 @@ ImBuf *IMB_thumb_load_blend(const char *blen_path, const char *blen_group, const } BLI_linklist_free(previews, BKE_previewimg_freefunc); - BLI_linklist_free(names, MEM_freeN); + BLI_linklist_freeN(names); } else { BlendThumbnail *data; diff --git a/source/blender/python/intern/bpy_library_load.c b/source/blender/python/intern/bpy_library_load.c index 64590827933..c6f0fbd3a2b 100644 --- a/source/blender/python/intern/bpy_library_load.c +++ b/source/blender/python/intern/bpy_library_load.c @@ -227,7 +227,7 @@ static PyObject *_bpy_names(BPy_Library *self, int blocktype) PyList_SET_ITEM(list, counter, PyUnicode_FromString((char *)l->link)); counter++; } - BLI_linklist_free(names, MEM_freeN); /* free linklist *and* each node's data */ + BLI_linklist_freeN(names); /* free linklist *and* each node's data */ } return list; -- cgit v1.2.3 From 9962e5936dd2e58319c01beb6b5392169627cfd8 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Tue, 8 Dec 2020 15:43:15 +0100 Subject: Cleanup: Use enum for file selection type definitions Makes it more clear that these belong together and allows using the enum type rather than just `int`. --- source/blender/makesdna/DNA_space_types.h | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'source/blender') diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index a554caccc4e..6fd112628a1 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -698,7 +698,7 @@ typedef struct FileSelectParams { /* short */ /** XXXXX for now store type here, should be moved to the operator. */ - short type; + short type; /* eFileSelectType */ /** Settings for filter, hiding dots files. */ short flag; /** Sort order. */ @@ -807,12 +807,14 @@ enum eFileDetails { #define FILE_MAX_LIBEXTRA (FILE_MAX + MAX_ID_NAME) /* filesel types */ -#define FILE_UNIX 8 -#define FILE_BLENDER 8 /* don't display relative paths */ -#define FILE_SPECIAL 9 - -#define FILE_LOADLIB 1 -#define FILE_MAIN 2 +typedef enum eFileSelectType { + FILE_LOADLIB = 1, + FILE_MAIN = 2, + + FILE_UNIX = 8, + FILE_BLENDER = 8, /* don't display relative paths */ + FILE_SPECIAL = 9, +} eFileSelectType; /* filesel op property -> action */ typedef enum eFileSel_Action { -- cgit v1.2.3 From 5b73083d4f207690e89f3a8863480de2bb4df24d Mon Sep 17 00:00:00 2001 From: Jamell Moore Date: Tue, 8 Dec 2020 16:48:11 +0100 Subject: Fix T81950: GPencil - Draw - Stoke Placement Stroke Feature Broken Buffer strokes weren't being the excluded from depth only draw calls so were being included in depth tests. They are now excluded by bypassing the creation of the buffer strokes. Reviewed By: fclem Differential Revision: https://developer.blender.org/D9742 --- source/blender/draw/engines/gpencil/gpencil_engine.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender') diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c index 388deec07bf..519b015a6ad 100644 --- a/source/blender/draw/engines/gpencil/gpencil_engine.c +++ b/source/blender/draw/engines/gpencil/gpencil_engine.c @@ -252,7 +252,7 @@ void GPENCIL_cache_init(void *ved) pd->do_fast_drawing = false; pd->obact = draw_ctx->obact; - if (pd->obact && pd->obact->type == OB_GPENCIL) { + if (pd->obact && pd->obact->type == OB_GPENCIL && !(pd->draw_depth_only)) { /* Check if active object has a temp stroke data. */ bGPdata *gpd = (bGPdata *)pd->obact->data; if (gpd->runtime.sbuffer_used > 0) { -- cgit v1.2.3 From 40dd70882cd32c79b2f1a9320ea32f13431b22c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Depoix?= Date: Tue, 8 Dec 2020 17:49:12 +0100 Subject: Fix T83337: boundary smooth input in subdivision surface node is inverted Differential Revision: https://developer.blender.org/D9753 --- source/blender/nodes/geometry/nodes/node_geo_subdivision_surface.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source/blender') diff --git a/source/blender/nodes/geometry/nodes/node_geo_subdivision_surface.cc b/source/blender/nodes/geometry/nodes/node_geo_subdivision_surface.cc index e5e7cf57e27..197700cc521 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_subdivision_surface.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_subdivision_surface.cc @@ -25,7 +25,7 @@ static bNodeSocketTemplate geo_node_subdivision_surface_in[] = { {SOCK_GEOMETRY, N_("Geometry")}, {SOCK_INT, N_("Level"), 1, 0, 0, 0, 0, 6}, {SOCK_BOOLEAN, N_("Use Creases")}, - {SOCK_BOOLEAN, N_("Boundary Smooth")}, + {SOCK_BOOLEAN, N_("Boundary Smooth"), true}, {SOCK_BOOLEAN, N_("Smooth UVs")}, {-1, ""}, }; @@ -76,7 +76,7 @@ static void geo_node_subdivision_surface_exec(GeoNodeExecParams params) subdiv_settings.level = subdiv_level; subdiv_settings.vtx_boundary_interpolation = BKE_subdiv_vtx_boundary_interpolation_from_subsurf( - boundary_smooth); + !boundary_smooth); subdiv_settings.fvar_linear_interpolation = BKE_subdiv_fvar_interpolation_from_uv_smooth( smooth_uvs); -- cgit v1.2.3 From e08de974c36a800538d8f9af0f902de6694e5d76 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Tue, 8 Dec 2020 18:07:50 +0100 Subject: Fix T83114: incorrect normals after joining subdivided meshes This just makes sure that the mesh coming out of the subdivision surface node has correct normals. Ideally, we would lazily compute derived data like normals in more cases, but that can be solved later. Correctness is more important right now. In order to solve this better, it would be nice if functions like `BKE_mesh_ensure_normals` would take a `const Mesh *`. The mesh could be considered to be logically const, because normals are derived data that is only cached for the current state of the mesh. --- source/blender/nodes/geometry/nodes/node_geo_subdivision_surface.cc | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source/blender') diff --git a/source/blender/nodes/geometry/nodes/node_geo_subdivision_surface.cc b/source/blender/nodes/geometry/nodes/node_geo_subdivision_surface.cc index 197700cc521..543859aef3f 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_subdivision_surface.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_subdivision_surface.cc @@ -16,6 +16,7 @@ #include "MEM_guardedalloc.h" +#include "BKE_mesh.h" #include "BKE_subdiv.h" #include "BKE_subdiv_mesh.h" @@ -90,6 +91,7 @@ static void geo_node_subdivision_surface_exec(GeoNodeExecParams params) } Mesh *mesh_out = BKE_subdiv_to_mesh(subdiv, &mesh_settings, mesh_in); + BKE_mesh_calc_normals(mesh_out); geometry_set.replace_mesh(mesh_out); -- cgit v1.2.3 From e17967f890a09c3bd810632c2c3244f9f988919f Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Tue, 8 Dec 2020 21:19:22 +0100 Subject: Fix T83559: File Browser uses wrong operation When opening a temporary File Browser, we have to make sure the file selection parameters are refreshed. When opening it in a new Window that would always be the case, if the File Browser uses a maximized window (as set in the Preferences), it might reuse space-data from a previous use. So we have to force the refresh. Also renamed the relevant function to be more clear about what it's doing. Mistake in 95b3c4c966f9. --- source/blender/editors/space_file/filesel.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c index ffa44083473..6e933e53a8f 100644 --- a/source/blender/editors/space_file/filesel.c +++ b/source/blender/editors/space_file/filesel.c @@ -90,7 +90,7 @@ FileSelectParams *ED_fileselect_get_active_params(const SpaceFile *sfile) /** * \note RNA_struct_property_is_set_ex is used here because we want * the previously used settings to be used here rather than overriding them */ -static void fileselect_ensure_file_params(SpaceFile *sfile) +static FileSelectParams *fileselect_ensure_updated_file_params(SpaceFile *sfile) { FileSelectParams *params; wmOperator *op = sfile->op; @@ -323,12 +323,14 @@ static void fileselect_ensure_file_params(SpaceFile *sfile) if (sfile->layout) { sfile->layout->dirty = true; } + + return params; } FileSelectParams *ED_fileselect_ensure_active_params(SpaceFile *sfile) { if (!sfile->params) { - fileselect_ensure_file_params(sfile); + fileselect_ensure_updated_file_params(sfile); } return sfile->params; } @@ -369,7 +371,7 @@ void ED_fileselect_set_params_from_userdef(SpaceFile *sfile) wmOperator *op = sfile->op; UserDef_FileSpaceData *sfile_udata = &U.file_space_data; - FileSelectParams *params = ED_fileselect_ensure_active_params(sfile); + FileSelectParams *params = fileselect_ensure_updated_file_params(sfile); if (!op) { return; } -- cgit v1.2.3 From 9b11a7776f2ab8ac42e835a17ed7566fd80a4b8c Mon Sep 17 00:00:00 2001 From: Henrik Dick Date: Wed, 9 Dec 2020 11:10:15 +1100 Subject: Modifier: Add "Connected" mode to the weld modifier Implement improvement from T73139 for merging along edges. It is now called "Connected" mode, while the default is called "All". With the recent performance improvement, the Connected Mode is in some cases only double the speed than the usual merge all strategy but in other cases it may be even faster. The bottleneck is somewhere further down the line of merging geometry. The motivation for this patch came from T80897, because the merging in complex solidify is making it very slow. Now merging can be removed from solidify without greater consequences, as this is just a quicker and more advanced algorithm to do the same thing that solidify currently does slowly. Reviewed by: mano-wii, campbellbarton Ref D8966 --- source/blender/makesdna/DNA_modifier_defaults.h | 1 + source/blender/makesdna/DNA_modifier_types.h | 9 ++- source/blender/makesrna/intern/rna_modifier.c | 11 ++++ source/blender/modifiers/intern/MOD_weld.c | 82 +++++++++++++++++++++++++ 4 files changed, 102 insertions(+), 1 deletion(-) (limited to 'source/blender') diff --git a/source/blender/makesdna/DNA_modifier_defaults.h b/source/blender/makesdna/DNA_modifier_defaults.h index f73f43ddade..793a229bdc5 100644 --- a/source/blender/makesdna/DNA_modifier_defaults.h +++ b/source/blender/makesdna/DNA_modifier_defaults.h @@ -801,6 +801,7 @@ #define _DNA_DEFAULT_WeldModifierData \ { \ .merge_dist = 0.001f, \ + .mode = MOD_WELD_ALL_MODE, \ .defgrp_name = "", \ } diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index af7d7e9310f..d99564ff33e 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -2004,7 +2004,8 @@ typedef struct WeldModifierData { /* Name of vertex group to use to mask, MAX_VGROUP_NAME. */ char defgrp_name[64]; - short flag; + char mode; + char flag; char _pad[2]; } WeldModifierData; @@ -2013,6 +2014,12 @@ enum { MOD_WELD_INVERT_VGROUP = (1 << 0), }; +/* #WeldModifierData.mode */ +enum { + MOD_WELD_ALL_MODE = 0, + MOD_WELD_CONNECTED_MODE = 1, +}; + typedef struct DataTransferModifierData { ModifierData modifier; diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index f0836ae59ad..4ce859ddce9 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -6231,6 +6231,12 @@ static void rna_def_modifier_weld(BlenderRNA *brna) StructRNA *srna; PropertyRNA *prop; + static const EnumPropertyItem mode_items[] = { + {MOD_WELD_ALL_MODE, "ALL", 0, "All", "Full merge by distance"}, + {MOD_WELD_CONNECTED_MODE, "CONNECTED", 0, "Connected", "Only merge along the edges"}, + {0, NULL, 0, NULL, NULL}, + }; + srna = RNA_def_struct(brna, "WeldModifier", "Modifier"); RNA_def_struct_ui_text(srna, "Weld Modifier", "Weld modifier"); RNA_def_struct_sdna(srna, "WeldModifierData"); @@ -6238,6 +6244,11 @@ static void rna_def_modifier_weld(BlenderRNA *brna) RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, mode_items); + RNA_def_property_ui_text(prop, "Mode", "Mode defines the merge rule"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + prop = RNA_def_property(srna, "merge_threshold", PROP_FLOAT, PROP_DISTANCE); RNA_def_property_float_sdna(prop, NULL, "merge_dist"); RNA_def_property_range(prop, 0, FLT_MAX); diff --git a/source/blender/modifiers/intern/MOD_weld.c b/source/blender/modifiers/intern/MOD_weld.c index 1a25c24fedc..a50323a24ee 100644 --- a/source/blender/modifiers/intern/MOD_weld.c +++ b/source/blender/modifiers/intern/MOD_weld.c @@ -1567,6 +1567,12 @@ static bool bvhtree_weld_overlap_cb(void *userdata, int index_a, int index_b, in } #endif +/** Use for #MOD_WELD_CONNECTED_MODE calculation. */ +struct WeldVertexCluster { + float co[3]; + uint merged_verts; +}; + static Mesh *weldModifier_doWeld(WeldModifierData *wmd, const ModifierEvalContext *ctx, Mesh *mesh) { Mesh *result = mesh; @@ -1606,6 +1612,7 @@ static Mesh *weldModifier_doWeld(WeldModifierData *wmd, const ModifierEvalContex * This indicates which vert it is or is going to be merged. */ uint *vert_dest_map = MEM_malloc_arrayN(totvert, sizeof(*vert_dest_map), __func__); uint vert_kill_len = 0; + if (wmd->mode == MOD_WELD_ALL_MODE) #ifdef USE_BVHTREEKDOP { /* Get overlap map. */ @@ -1701,6 +1708,80 @@ static Mesh *weldModifier_doWeld(WeldModifierData *wmd, const ModifierEvalContex BLI_kdtree_3d_free(tree); } #endif + else { + BLI_assert(wmd->mode == MOD_WELD_CONNECTED_MODE); + + MEdge *medge, *me; + + medge = mesh->medge; + totvert = mesh->totvert; + totedge = mesh->totedge; + + struct WeldVertexCluster *vert_clusters = MEM_malloc_arrayN( + totvert, sizeof(*vert_clusters), __func__); + struct WeldVertexCluster *vc = &vert_clusters[0]; + for (uint i = 0; i < totvert; i++, vc++) { + copy_v3_v3(vc->co, mvert[i].co); + vc->merged_verts = 0; + } + const float merge_dist_sq = square_f(wmd->merge_dist); + + range_vn_u(vert_dest_map, totvert, 0); + + /* Collapse Edges that are shorter than the threshold. */ + me = &medge[0]; + for (uint i = 0; i < totedge; i++, me++) { + uint v1 = me->v1; + uint v2 = me->v2; + + while (v1 != vert_dest_map[v1]) { + v1 = vert_dest_map[v1]; + } + while (v2 != vert_dest_map[v2]) { + v2 = vert_dest_map[v2]; + } + if (v1 == v2) { + continue; + } + if (v_mask && (!BLI_BITMAP_TEST(v_mask, v1) || !BLI_BITMAP_TEST(v_mask, v2))) { + continue; + } + if (v1 > v2) { + SWAP(uint, v1, v2); + } + struct WeldVertexCluster *v1_cluster = &vert_clusters[v1]; + struct WeldVertexCluster *v2_cluster = &vert_clusters[v2]; + + float edgedir[3]; + sub_v3_v3v3(edgedir, v2_cluster->co, v1_cluster->co); + const float dist_sq = len_squared_v3(edgedir); + if (dist_sq <= merge_dist_sq) { + float influence = (v2_cluster->merged_verts + 1) / + (float)(v1_cluster->merged_verts + v2_cluster->merged_verts + 2); + madd_v3_v3fl(v1_cluster->co, edgedir, influence); + + v1_cluster->merged_verts += v2_cluster->merged_verts + 1; + vert_dest_map[v2] = v1; + vert_kill_len++; + } + } + + MEM_freeN(vert_clusters); + + for (uint i = 0; i < totvert; i++) { + if (i == vert_dest_map[i]) { + vert_dest_map[i] = OUT_OF_CONTEXT; + } + else { + uint v = i; + while ((v != vert_dest_map[v]) && (vert_dest_map[v] != OUT_OF_CONTEXT)) { + v = vert_dest_map[v]; + } + vert_dest_map[v] = v; + vert_dest_map[i] = v; + } + } + } if (v_mask) { MEM_freeN(v_mask); @@ -1940,6 +2021,7 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel) uiLayoutSetPropSep(layout, true); + uiItemR(layout, ptr, "mode", 0, NULL, ICON_NONE); uiItemR(layout, ptr, "merge_threshold", 0, IFACE_("Distance"), ICON_NONE); modifier_vgroup_ui(layout, ptr, &ob_ptr, "vertex_group", "invert_vertex_group", NULL); -- cgit v1.2.3 From 5cdfceaa1a7efb71d528a04a01cb74181f1aa8e4 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 9 Dec 2020 14:10:30 +1100 Subject: Cleanup: use common 'MOD_WELD_MODE_' prefix --- source/blender/makesdna/DNA_modifier_defaults.h | 2 +- source/blender/makesdna/DNA_modifier_types.h | 4 ++-- source/blender/makesrna/intern/rna_modifier.c | 4 ++-- source/blender/modifiers/intern/MOD_weld.c | 6 +++--- 4 files changed, 8 insertions(+), 8 deletions(-) (limited to 'source/blender') diff --git a/source/blender/makesdna/DNA_modifier_defaults.h b/source/blender/makesdna/DNA_modifier_defaults.h index 793a229bdc5..e122d50cba8 100644 --- a/source/blender/makesdna/DNA_modifier_defaults.h +++ b/source/blender/makesdna/DNA_modifier_defaults.h @@ -801,7 +801,7 @@ #define _DNA_DEFAULT_WeldModifierData \ { \ .merge_dist = 0.001f, \ - .mode = MOD_WELD_ALL_MODE, \ + .mode = MOD_WELD_MODE_ALL, \ .defgrp_name = "", \ } diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index d99564ff33e..03cf4aca963 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -2016,8 +2016,8 @@ enum { /* #WeldModifierData.mode */ enum { - MOD_WELD_ALL_MODE = 0, - MOD_WELD_CONNECTED_MODE = 1, + MOD_WELD_MODE_ALL = 0, + MOD_WELD_MODE_CONNECTED = 1, }; typedef struct DataTransferModifierData { diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index 4ce859ddce9..99304d29e00 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -6232,8 +6232,8 @@ static void rna_def_modifier_weld(BlenderRNA *brna) PropertyRNA *prop; static const EnumPropertyItem mode_items[] = { - {MOD_WELD_ALL_MODE, "ALL", 0, "All", "Full merge by distance"}, - {MOD_WELD_CONNECTED_MODE, "CONNECTED", 0, "Connected", "Only merge along the edges"}, + {MOD_WELD_MODE_ALL, "ALL", 0, "All", "Full merge by distance"}, + {MOD_WELD_MODE_CONNECTED, "CONNECTED", 0, "Connected", "Only merge along the edges"}, {0, NULL, 0, NULL, NULL}, }; diff --git a/source/blender/modifiers/intern/MOD_weld.c b/source/blender/modifiers/intern/MOD_weld.c index a50323a24ee..e34dcf48c19 100644 --- a/source/blender/modifiers/intern/MOD_weld.c +++ b/source/blender/modifiers/intern/MOD_weld.c @@ -1567,7 +1567,7 @@ static bool bvhtree_weld_overlap_cb(void *userdata, int index_a, int index_b, in } #endif -/** Use for #MOD_WELD_CONNECTED_MODE calculation. */ +/** Use for #MOD_WELD_MODE_CONNECTED calculation. */ struct WeldVertexCluster { float co[3]; uint merged_verts; @@ -1612,7 +1612,7 @@ static Mesh *weldModifier_doWeld(WeldModifierData *wmd, const ModifierEvalContex * This indicates which vert it is or is going to be merged. */ uint *vert_dest_map = MEM_malloc_arrayN(totvert, sizeof(*vert_dest_map), __func__); uint vert_kill_len = 0; - if (wmd->mode == MOD_WELD_ALL_MODE) + if (wmd->mode == MOD_WELD_MODE_ALL) #ifdef USE_BVHTREEKDOP { /* Get overlap map. */ @@ -1709,7 +1709,7 @@ static Mesh *weldModifier_doWeld(WeldModifierData *wmd, const ModifierEvalContex } #endif else { - BLI_assert(wmd->mode == MOD_WELD_CONNECTED_MODE); + BLI_assert(wmd->mode == MOD_WELD_MODE_CONNECTED); MEdge *medge, *me; -- cgit v1.2.3 From cdfe733e7061d32882824896c7e62823447d7c94 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 9 Dec 2020 14:34:40 +1100 Subject: Cleanup: use doxy sections for graph_edit.c --- source/blender/editors/space_graph/graph_edit.c | 170 +++++++++++++++++++----- 1 file changed, 137 insertions(+), 33 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c index ae34cd6cf6d..c3e4eceef6e 100644 --- a/source/blender/editors/space_graph/graph_edit.c +++ b/source/blender/editors/space_graph/graph_edit.c @@ -72,7 +72,9 @@ /* ************************************************************************** */ /* INSERT DUPLICATE AND BAKE KEYFRAMES */ -/* ******************** Insert Keyframes Operator ************************* */ +/* -------------------------------------------------------------------- */ +/** \name Insert Keyframes Operator + * \{ */ /* Mode defines for insert keyframes tool. */ typedef enum eGraphKeys_InsertKey_Types { @@ -290,7 +292,11 @@ void GRAPH_OT_keyframe_insert(wmOperatorType *ot) ot->prop = RNA_def_enum(ot->srna, "type", prop_graphkeys_insertkey_types, 0, "Type", ""); } -/* ******************** Click-Insert Keyframes Operator ************************* */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Click-Insert Keyframes Operator + * \{ */ static int graphkeys_click_insert_exec(bContext *C, wmOperator *op) { @@ -444,8 +450,13 @@ void GRAPH_OT_click_insert(wmOperatorType *ot) "Extend selection instead of deselecting everything first"); } -/* ******************** Copy/Paste Keyframes Operator ************************* */ -/* NOTE: the backend code for this is shared with the dopesheet editor */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Copy/Paste Keyframes Operator + * + * \note the back-end code for this is shared with the dope-sheet editor. + * \{ */ static short copy_graph_keys(bAnimContext *ac) { @@ -605,7 +616,11 @@ void GRAPH_OT_paste(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_SKIP_SAVE); } -/* ******************** Duplicate Keyframes Operator ************************* */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Duplicate Keyframes Operator + * \{ */ static void duplicate_graph_keys(bAnimContext *ac) { @@ -667,7 +682,11 @@ void GRAPH_OT_duplicate(wmOperatorType *ot) RNA_def_enum(ot->srna, "mode", rna_enum_transform_mode_types, TFM_TRANSLATION, "Mode", ""); } -/* ******************** Delete Keyframes Operator ************************* */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Delete Keyframes Operator + * \{ */ static bool delete_graph_keys(bAnimContext *ac) { @@ -746,7 +765,11 @@ void GRAPH_OT_delete(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/* ******************** Clean Keyframes Operator ************************* */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Clean Keyframes Operator + * \{ */ static void clean_graph_keys(bAnimContext *ac, float thresh, bool clean_chan) { @@ -816,8 +839,13 @@ void GRAPH_OT_clean(wmOperatorType *ot) RNA_def_boolean(ot->srna, "channels", false, "Channels", ""); } -/* ******************** Bake F-Curve Operator *********************** */ -/* This operator bakes the data of the selected F-Curves to F-Points */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Bake F-Curve Operator + * + * This operator bakes the data of the selected F-Curves to F-Points. + * \{ */ /* Bake each F-Curve into a set of samples. */ static void bake_graph_curves(bAnimContext *ac, int start, int end) @@ -899,8 +927,13 @@ void GRAPH_OT_bake(wmOperatorType *ot) /* TODO: add props for start/end frames (Joshua Leung 2009) */ } -/* ******************** Un-Bake F-Curve Operator *********************** */ -/* This operator unbakes the data of the selected F-Points to F-Curves. */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Un-Bake F-Curve Operator + * + * This operator un-bakes the data of the selected F-Points to F-Curves. + * \{ */ /* Un-Bake F-Points into F-Curves. */ static void unbake_graph_curves(bAnimContext *ac, int start, int end) @@ -970,8 +1003,13 @@ void GRAPH_OT_unbake(wmOperatorType *ot) #ifdef WITH_AUDASPACE -/* ******************** Sound Bake F-Curve Operator *********************** */ -/* This operator bakes the given sound to the selected F-Curves */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Sound Bake F-Curve Operator + * + * This operator bakes the given sound to the selected F-Curves. + * \{ */ /* ------------------- */ @@ -1204,10 +1242,14 @@ void GRAPH_OT_sound_bake(wmOperatorType *ot) 0.1); } -/* ******************** Sample Keyframes Operator *********************** */ -/* This operator 'bakes' the values of the curve into new keyframes between pairs +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Sample Keyframes Operator + * + * This operator 'bakes' the values of the curve into new keyframes between pairs * of selected keyframes. It is useful for creating keyframes for tweaking overlap. - */ + * \{ */ /* Evaluates the curves between each selected keyframe on each frame, and keys the value. */ static void sample_graph_keys(bAnimContext *ac) @@ -1267,10 +1309,14 @@ void GRAPH_OT_sample(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +/** \} */ + /* ************************************************************************** */ /* EXTRAPOLATION MODE AND KEYFRAME HANDLE SETTINGS */ -/* ******************** Set Extrapolation-Type Operator *********************** */ +/* -------------------------------------------------------------------- */ +/** \name Set Extrapolation-Type Operator + * \{ */ /* Defines for make/clear cyclic extrapolation tools. */ #define MAKE_CYCLIC_EXPO -1 @@ -1400,7 +1446,11 @@ void GRAPH_OT_extrapolation_type(wmOperatorType *ot) ot->prop = RNA_def_enum(ot->srna, "type", prop_graphkeys_expo_types, 0, "Type", ""); } -/* ******************** Set Interpolation-Type Operator *********************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Set Interpolation-Type Operator + * \{ */ /* This function is responsible for setting interpolation mode for keyframes. */ static void setipo_graph_keys(bAnimContext *ac, short mode) @@ -1474,7 +1524,11 @@ void GRAPH_OT_interpolation_type(wmOperatorType *ot) ot->srna, "type", rna_enum_beztriple_interpolation_mode_items, 0, "Type", ""); } -/* ******************** Set Easing Operator *********************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Set Easing Operator + * \{ */ static void seteasing_graph_keys(bAnimContext *ac, short mode) { @@ -1545,7 +1599,11 @@ void GRAPH_OT_easing_type(wmOperatorType *ot) ot->srna, "type", rna_enum_beztriple_interpolation_easing_items, 0, "Type", ""); } -/* ******************** Set Handle-Type Operator *********************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Set Handle-Type Operator + * \{ */ /* This function is responsible for setting handle-type of selected keyframes. */ static void sethandles_graph_keys(bAnimContext *ac, short mode) @@ -1624,15 +1682,19 @@ void GRAPH_OT_handle_type(wmOperatorType *ot) ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_keyframe_handle_type_items, 0, "Type", ""); } +/** \} */ + /* ************************************************************************** */ /* EULER FILTER */ -/* ***************** 'Euler Filter' Operator **************************** */ -/* Euler filter tools (as seen in Maya), are necessary for working with 'baked' +/* -------------------------------------------------------------------- */ +/** \name 'Euler Filter' Operator + * + * Euler filter tools (as seen in Maya), are necessary for working with 'baked' * rotation curves (with Euler rotations). The main purpose of such tools is to * resolve any discontinuities that may arise in the curves due to the clamping * of values to -180 degrees to 180 degrees. - */ + * \{ */ /* Set of three euler-rotation F-Curves. */ typedef struct tEulerFilter { @@ -1955,10 +2017,14 @@ void GRAPH_OT_euler_filter(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +/** \} */ + /* ************************************************************************** */ /* SNAPPING */ -/* ***************** Jump to Selected Frames Operator *********************** */ +/* -------------------------------------------------------------------- */ +/** \name Jump to Selected Frames Operator + * \{ */ static bool graphkeys_framejump_poll(bContext *C) { @@ -2110,7 +2176,11 @@ void GRAPH_OT_snap_cursor_value(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/* ******************** Snap Keyframes Operator *********************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Snap Keyframes Operator + * \{ */ /* Defines for snap keyframes tool. */ static const EnumPropertyItem prop_graphkeys_snap_types[] = { @@ -2262,7 +2332,11 @@ void GRAPH_OT_snap(wmOperatorType *ot) ot->prop = RNA_def_enum(ot->srna, "type", prop_graphkeys_snap_types, 0, "Type", ""); } -/* ******************** Mirror Keyframes Operator *********************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Mirror Keyframes Operator + * \{ */ /* Defines for mirror keyframes tool. */ static const EnumPropertyItem prop_graphkeys_mirror_types[] = { @@ -2421,7 +2495,11 @@ void GRAPH_OT_mirror(wmOperatorType *ot) ot->prop = RNA_def_enum(ot->srna, "type", prop_graphkeys_mirror_types, 0, "Type", ""); } -/* ******************** Smooth Keyframes Operator *********************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Smooth Keyframes Operator + * \{ */ static int graphkeys_smooth_exec(bContext *C, wmOperator *UNUSED(op)) { @@ -2475,10 +2553,14 @@ void GRAPH_OT_smooth(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +/** \} */ + /* ************************************************************************** */ /* F-CURVE MODIFIERS */ -/* ******************** Add F-Modifier Operator *********************** */ +/* -------------------------------------------------------------------- */ +/** \name Add F-Modifier Operator + * \{ */ static const EnumPropertyItem *graph_fmodifier_itemf(bContext *C, PointerRNA *UNUSED(ptr), @@ -2596,7 +2678,11 @@ void GRAPH_OT_fmodifier_add(wmOperatorType *ot) ot->srna, "only_active", 1, "Only Active", "Only add F-Modifier to active F-Curve"); } -/* ******************** Copy F-Modifiers Operator *********************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Copy F-Modifiers Operator + * \{ */ static int graph_fmodifier_copy_exec(bContext *C, wmOperator *op) { @@ -2658,7 +2744,11 @@ void GRAPH_OT_fmodifier_copy(wmOperatorType *ot) #endif } -/* ******************** Paste F-Modifiers Operator *********************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Paste F-Modifiers Operator + * \{ */ static int graph_fmodifier_paste_exec(bContext *C, wmOperator *op) { @@ -2746,10 +2836,14 @@ void GRAPH_OT_fmodifier_paste(wmOperatorType *ot) "Replace existing F-Modifiers, instead of just appending to the end of the existing list"); } +/** \} */ + /* ************************************************************************** */ /* Drivers */ -/* ******************** Copy Driver Vars Operator *********************** */ +/* -------------------------------------------------------------------- */ +/** \name Copy Driver Variables Operator + * \{ */ static int graph_driver_vars_copy_exec(bContext *C, wmOperator *op) { @@ -2786,7 +2880,11 @@ void GRAPH_OT_driver_variables_copy(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/* ******************** Paste Driver Vars Operator *********************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Paste Driver Variables Operator + * \{ */ static int graph_driver_vars_paste_exec(bContext *C, wmOperator *op) { @@ -2838,7 +2936,11 @@ void GRAPH_OT_driver_variables_paste(wmOperatorType *ot) "existing list"); } -/* ************************************************************************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Delete Invalid Drivers Operator + * \{ */ static int graph_driver_delete_invalid_exec(bContext *C, wmOperator *op) { @@ -2926,3 +3028,5 @@ void GRAPH_OT_driver_delete_invalid(wmOperatorType *ot) /* Flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } + +/** \} */ -- cgit v1.2.3 From d1cedf53faaf11de74ca7c88da207e16ae01c497 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 9 Dec 2020 15:25:18 +1100 Subject: Revert "Fix T78823: Slash in custom property name does not work" This reverts commit cbae82ba960a0baaae6437b176a310f078ce07d8. This change introduced the following problems: - We could no longer reliably duplicate or use an existing custom property names. - We could no longer assume a bone or ID name can be used in a custom-property. - Importers that support custom properties (such as FBX) could fail with an exception creating custom properties. --- source/blender/python/generic/idprop_py_api.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'source/blender') diff --git a/source/blender/python/generic/idprop_py_api.c b/source/blender/python/generic/idprop_py_api.c index a8b66f3f2fe..1a7a0ecc6d7 100644 --- a/source/blender/python/generic/idprop_py_api.c +++ b/source/blender/python/generic/idprop_py_api.c @@ -20,8 +20,6 @@ #include -#include - #include "MEM_guardedalloc.h" #include "BLI_utildefines.h" @@ -372,11 +370,6 @@ static const char *idp_try_read_name(PyObject *name_obj) "the length of IDProperty names is limited to 63 characters"); return NULL; } - - if (strchr(name, '\"') || strchr(name, '\\') || strchr(name, '\'')) { - PyErr_SetString(PyExc_KeyError, "IDProperty names cannot include \", \\, or \'"); - return NULL; - } } else { name = ""; -- cgit v1.2.3 From ceba6b2c2161bda2e56bef7252782e0722579e95 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 9 Dec 2020 15:56:02 +1100 Subject: Fix T78823: Slash in custom property name does not work This fixes inserting key-frames for any collection names containing a back-slash too (bones, modifiers, sequence strips etc). --- source/blender/makesrna/intern/rna_access.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender') diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index 4991f34c3f6..a7f326bc79e 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -5033,7 +5033,7 @@ static char *rna_path_token(const char **path, char *fixedbuf, int fixedlen, int /* copy string, taking into account escaped ] */ if (bracket) { for (p = *path, i = 0, j = 0; i < len; i++, p++) { - if (*p == '\\' && *(p + 1) == quote) { + if (*p == '\\' && ELEM(*(p + 1), quote, '\\')) { } else { buf[j++] = *p; -- cgit v1.2.3 From 9d8aefaa5c5e2c3ed90e2fc1f6a9756f7444aa67 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 9 Dec 2020 16:52:53 +1100 Subject: Fix RNA un-escaping multiple slashes and strings ending with a slash Fix for T78823 resolved the issue reported but didn't properly support multiple back-slashes. --- source/blender/makesrna/intern/rna_access.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'source/blender') diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index a7f326bc79e..1aac9c0c0c2 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -4993,7 +4993,9 @@ static char *rna_path_token(const char **path, char *fixedbuf, int fixedlen, int len++; p++; while (*p && (*p != quote || escape)) { - escape = (*p == '\\'); + /* A pair of back-slashes represents a single back-slash, + * only use a single back-slash for escaping. */ + escape = (escape == 0) && (*p == '\\'); len++; p++; } @@ -5033,11 +5035,17 @@ static char *rna_path_token(const char **path, char *fixedbuf, int fixedlen, int /* copy string, taking into account escaped ] */ if (bracket) { for (p = *path, i = 0, j = 0; i < len; i++, p++) { - if (*p == '\\' && ELEM(*(p + 1), quote, '\\')) { - } - else { - buf[j++] = *p; + if (*p == '\\') { + if (*(p + 1) == '\\') { + /* Un-escape pairs of back-slashes into a single back-slash. */ + p++; + i += 1; + } + else if (*(p + 1) == quote) { + continue; + } } + buf[j++] = *p; } buf[j] = 0; -- cgit v1.2.3 From 6c9263d817b7b4dcd4d6e1f365d1db0a83de6e51 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 9 Dec 2020 17:16:43 +1100 Subject: Fix off by one error in id-property name validation The Python API accepted a name with 64 bytes, clipping it to 63. --- source/blender/python/generic/idprop_py_api.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender') diff --git a/source/blender/python/generic/idprop_py_api.c b/source/blender/python/generic/idprop_py_api.c index 1a7a0ecc6d7..c125edea19f 100644 --- a/source/blender/python/generic/idprop_py_api.c +++ b/source/blender/python/generic/idprop_py_api.c @@ -365,7 +365,7 @@ static const char *idp_try_read_name(PyObject *name_obj) return NULL; } - if (name_size > MAX_IDPROP_NAME) { + if (name_size >= MAX_IDPROP_NAME) { PyErr_SetString(PyExc_KeyError, "the length of IDProperty names is limited to 63 characters"); return NULL; -- cgit v1.2.3 From ebe4bf6286b165cc5f7e6f237a9c2683e109e4de Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 9 Dec 2020 17:33:11 +1100 Subject: Fix another id-property name length check Missed this in 6c9263d817b7b4dcd4d6e1f365d1db0a83de6e51 --- source/blender/python/generic/idprop_py_api.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender') diff --git a/source/blender/python/generic/idprop_py_api.c b/source/blender/python/generic/idprop_py_api.c index c125edea19f..63fb685e66d 100644 --- a/source/blender/python/generic/idprop_py_api.c +++ b/source/blender/python/generic/idprop_py_api.c @@ -253,7 +253,7 @@ static int BPy_IDGroup_SetName(BPy_IDProperty *self, PyObject *value, void *UNUS name = _PyUnicode_AsStringAndSize(value, &name_size); - if (name_size > MAX_IDPROP_NAME) { + if (name_size >= MAX_IDPROP_NAME) { PyErr_SetString(PyExc_TypeError, "string length cannot exceed 63 characters!"); return -1; } -- cgit v1.2.3 From abddd7d5f91a6b00617d4eac8616d54490d45e8d Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 9 Dec 2020 18:46:07 +1100 Subject: Fix T83566: bpy.props.CollectionProperty gives incorrect error Error in commit a7b3047cefcbfae4d8b13e15026497fd5ae92730. --- source/blender/python/intern/bpy_props.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source/blender') diff --git a/source/blender/python/intern/bpy_props.c b/source/blender/python/intern/bpy_props.c index d45c8e8b131..9d69d91c8c8 100644 --- a/source/blender/python/intern/bpy_props.c +++ b/source/blender/python/intern/bpy_props.c @@ -3494,7 +3494,6 @@ PyObject *BPy_CollectionProperty(PyObject *self, PyObject *args, PyObject *kw) if (!RNA_struct_is_a(ptype, &RNA_PropertyGroup)) { PyErr_Format(PyExc_TypeError, "CollectionProperty(...) expected an RNA type derived from %.200s", - RNA_struct_ui_name(&RNA_ID), RNA_struct_ui_name(&RNA_PropertyGroup)); return NULL; } -- cgit v1.2.3 From 55d14210cccc7a3dae98787200a6dc3649462bba Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Wed, 9 Dec 2020 12:10:32 +0100 Subject: Raised AMD CEDAR on Linux from unsupported to limited support There is a workaround available by setting the environment variable `R600_DEBUG=nosb`. --- source/blender/gpu/opengl/gl_backend.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source/blender') diff --git a/source/blender/gpu/opengl/gl_backend.cc b/source/blender/gpu/opengl/gl_backend.cc index 7e948149a7f..8f3d1ffabaa 100644 --- a/source/blender/gpu/opengl/gl_backend.cc +++ b/source/blender/gpu/opengl/gl_backend.cc @@ -152,8 +152,10 @@ void GLBackend::platform_init() } } if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_UNIX, GPU_DRIVER_ANY)) { + /* Platform seems to work when SB backend is disabled. This can be done + * by adding the environment variable `R600_DEBUG=nosb`. */ if (strstr(renderer, "AMD CEDAR")) { - GPG.support_level = GPU_SUPPORT_LEVEL_UNSUPPORTED; + GPG.support_level = GPU_SUPPORT_LEVEL_LIMITED; } } } -- cgit v1.2.3 From 1a959e9fa8c45a6cf43b4e350b1f2707ea3ac063 Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Wed, 9 Dec 2020 12:12:35 +0100 Subject: Raised AMD/Terascale2 from unsupported to supported. There is a patch that fixes the crash on startup {D9667}. --- source/blender/gpu/opengl/gl_backend.cc | 8 -------- 1 file changed, 8 deletions(-) (limited to 'source/blender') diff --git a/source/blender/gpu/opengl/gl_backend.cc b/source/blender/gpu/opengl/gl_backend.cc index 8f3d1ffabaa..26ec85ec872 100644 --- a/source/blender/gpu/opengl/gl_backend.cc +++ b/source/blender/gpu/opengl/gl_backend.cc @@ -131,14 +131,6 @@ void GLBackend::platform_init() } } - /* Since Blender 2.91 AMD TeraScale 2 GPUs crashes during startup. */ - if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_WIN, GPU_DRIVER_ANY)) { - if (strstr(renderer, "Radeon HD 4") || strstr(renderer, "Radeon HD 5") || - strstr(renderer, "Radeon HD 6") || strstr(renderer, "ATI FirePro V4") || - strstr(renderer, "AMD Radeon R5 2")) { - GPG.support_level = GPU_SUPPORT_LEVEL_UNSUPPORTED; - } - } /* Driver 20.11.2 fixes a lot of issues for the Navi cards, but introduces new ones * for Polaris based cards cards. The viewport has glitches but doesn't crash. * See T82856 */ -- cgit v1.2.3 From baf84ecbe4910d91a7e1586f207c575992f582a5 Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Wed, 9 Dec 2020 12:14:44 +0100 Subject: Workaround for Access Violation startup crash on deprecated Radeon GPUs on Windows This is a workaround for T80804. There's a startup crash that happens on 2.91.0 on Windows, an `EXCEPTION_ACCESS_VIOLATION` on `atio6axx.dll`. It is triggered by `glClear` on the `detect_mip_render_workaround` function. The workaround moves the function after the device/driver workaround section and sets the flag to the affected one to avoid running the check. It is deprecated hardware that has not meet the minimum requirements since 2.79, but is still usable and this extends its usability a bit before the cards are finally blacklisted. Reviewed By: Jeroen Bakker Differential Revision: https://developer.blender.org/D9667 --- source/blender/gpu/opengl/gl_backend.cc | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'source/blender') diff --git a/source/blender/gpu/opengl/gl_backend.cc b/source/blender/gpu/opengl/gl_backend.cc index 26ec85ec872..08ad2343ba3 100644 --- a/source/blender/gpu/opengl/gl_backend.cc +++ b/source/blender/gpu/opengl/gl_backend.cc @@ -247,10 +247,6 @@ static void detect_workarounds() return; } - /* Some Intel drivers have issues with using mips as framebuffer targets if - * GL_TEXTURE_MAX_LEVEL is higher than the target mip. - * Only check at the end after all other workarounds because this uses the drawing code. */ - GCaps.mip_render_workaround = detect_mip_render_workaround(); /* Limit support for GLEW_ARB_base_instance to OpenGL 4.0 and higher. NVIDIA Quadro FX 4800 * (TeraScale) report that they support GLEW_ARB_base_instance, but the driver does not support * GLEW_ARB_draw_indirect as it has an OpenGL3 context what also matches the minimum needed @@ -271,6 +267,7 @@ static void detect_workarounds() (strstr(version, "4.5.13399") || strstr(version, "4.5.13417") || strstr(version, "4.5.13422"))) { GLContext::unused_fb_slot_workaround = true; + GCaps.mip_render_workaround = true; GCaps.shader_image_load_store_support = false; GCaps.broken_amd_driver = true; } @@ -362,6 +359,13 @@ static void detect_workarounds() } } + /* Some Intel drivers have issues with using mips as framebuffer targets if + * GL_TEXTURE_MAX_LEVEL is higher than the target mip. + * Only check at the end after all other workarounds because this uses the drawing code. + * Also after device/driver flags to avoid the check that causes pre GCN Radeon to crash. */ + if (GCaps.mip_render_workaround == false) { + GCaps.mip_render_workaround = detect_mip_render_workaround(); + } /* Disable multidraw if the base instance cannot be read. */ if (GLContext::shader_draw_parameters_support == false) { GLContext::multi_draw_indirect_support = false; -- cgit v1.2.3 From 5a8012b6a69c42b7ad7bf7e6d55c2a4abd344ea2 Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Wed, 9 Dec 2020 12:37:20 +0100 Subject: Degraded AMD 20.11.3 driver to limited support. --- source/blender/gpu/opengl/gl_backend.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source/blender') diff --git a/source/blender/gpu/opengl/gl_backend.cc b/source/blender/gpu/opengl/gl_backend.cc index 08ad2343ba3..f683a70b4e6 100644 --- a/source/blender/gpu/opengl/gl_backend.cc +++ b/source/blender/gpu/opengl/gl_backend.cc @@ -131,11 +131,11 @@ void GLBackend::platform_init() } } - /* Driver 20.11.2 fixes a lot of issues for the Navi cards, but introduces new ones + /* Driver 20.11.2/3 fixes a lot of issues for the Navi cards, but introduces new ones * for Polaris based cards cards. The viewport has glitches but doesn't crash. - * See T82856 */ + * See T82856,T83574. */ if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_WIN, GPU_DRIVER_OFFICIAL) && - strstr(version, " 20.11.2 ")) { + (strstr(version, " 20.11.2 ") || strstr(version, " 20.11.3 "))) { if (strstr(renderer, "Radeon RX 460 ") || strstr(renderer, "Radeon RX 470 ") || strstr(renderer, "Radeon RX 480 ") || strstr(renderer, "Radeon RX 490 ") || strstr(renderer, "Radeon RX 560 ") || strstr(renderer, "Radeon RX 570 ") || -- cgit v1.2.3 From b9eb5921332922757acacd2c9251d8c89c9a239a Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Wed, 9 Dec 2020 09:10:56 -0300 Subject: Fix T83460: Regression in snap for measure tool Now the gizmo is drawn only when the eventstate located in `wm->winactive->eventstate` has not changed. So it doesn't matter if it's "selected" or not. This commit also removes the use of the private header "wm.h" Reviewed By: campbellbarton Differential Revision: https://developer.blender.org/D9539 --- .../gizmo_library/gizmo_types/snap3d_gizmo.c | 102 ++++++++++++++------- .../editors/space_view3d/view3d_gizmo_ruler.c | 9 +- .../editors/space_view3d/view3d_placement.c | 9 +- 3 files changed, 71 insertions(+), 49 deletions(-) (limited to 'source/blender') 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 f7caf8e4c6a..8755dea51e1 100644 --- a/source/blender/editors/gizmo_library/gizmo_types/snap3d_gizmo.c +++ b/source/blender/editors/gizmo_library/gizmo_types/snap3d_gizmo.c @@ -50,7 +50,6 @@ #include "WM_api.h" #include "WM_types.h" -#include "wm.h" /* own includes */ #include "../gizmo_geometry.h" @@ -66,7 +65,13 @@ typedef struct SnapGizmo3D { /* We could have other snap contexts, for now only support 3D view. */ SnapObjectContext *snap_context_v3d; - int mval[2]; + + /* Copy of the parameters of the last event state in order to detect updates. */ + struct { + int x; + int y; + short shift, ctrl, alt, oskey; + } last_eventstate; #ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK wmKeyMap *keymap; @@ -77,6 +82,37 @@ typedef struct SnapGizmo3D { short snap_elem; } SnapGizmo3D; +/* Checks if the current event is different from the one captured in the last update. */ +static bool eventstate_has_changed(SnapGizmo3D *snap_gizmo, const wmWindowManager *wm) +{ + if (wm && wm->winactive) { + const wmEvent *event = wm->winactive->eventstate; + if ((event->x != snap_gizmo->last_eventstate.x) || + (event->y != snap_gizmo->last_eventstate.y) || + (event->ctrl != snap_gizmo->last_eventstate.ctrl) || + (event->shift != snap_gizmo->last_eventstate.shift) || + (event->alt != snap_gizmo->last_eventstate.alt) || + (event->oskey != snap_gizmo->last_eventstate.oskey)) { + return true; + } + } + return false; +} + +/* Copies the current eventstate. */ +static void eventstate_save(SnapGizmo3D *snap_gizmo, const wmWindowManager *wm) +{ + if (wm && wm->winactive) { + const wmEvent *event = wm->winactive->eventstate; + snap_gizmo->last_eventstate.x = event->x; + snap_gizmo->last_eventstate.y = event->y; + snap_gizmo->last_eventstate.ctrl = event->ctrl; + snap_gizmo->last_eventstate.shift = event->shift; + snap_gizmo->last_eventstate.alt = event->alt; + snap_gizmo->last_eventstate.oskey = event->oskey; + } +} + #ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK static bool invert_snap(SnapGizmo3D *snap_gizmo, const wmWindowManager *wm) { @@ -84,6 +120,15 @@ static bool invert_snap(SnapGizmo3D *snap_gizmo, const wmWindowManager *wm) return false; } + const wmEvent *event = wm->winactive->eventstate; + if ((event->ctrl == snap_gizmo->last_eventstate.ctrl) && + (event->shift == snap_gizmo->last_eventstate.shift) && + (event->alt == snap_gizmo->last_eventstate.alt) && + (event->oskey == snap_gizmo->last_eventstate.oskey)) { + /* Nothing has changed. */ + return snap_gizmo->invert_snap; + } + if (snap_gizmo->keymap == NULL) { /* Lazy initialization. */ snap_gizmo->keymap = WM_modalkeymap_find(wm->defaultconf, "Generic Gizmo Tweak Modal Map"); @@ -92,7 +137,6 @@ static bool invert_snap(SnapGizmo3D *snap_gizmo, const wmWindowManager *wm) const int snap_on = snap_gizmo->snap_on; wmKeyMap *keymap = WM_keymap_active(wm, snap_gizmo->keymap); - const wmEvent *event = wm->winactive->eventstate; for (wmKeyMapItem *kmi = keymap->items.first; kmi; kmi = kmi->next) { if (kmi->flag & KMI_INACTIVE) { continue; @@ -250,12 +294,6 @@ short ED_gizmotypes_snap_3d_update(wmGizmo *gz, float r_nor[3]) { 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 (snap_gizmo->use_snap_override != -1) { if (snap_gizmo->use_snap_override == false) { snap_gizmo->snap_elem = 0; @@ -265,7 +303,12 @@ short ED_gizmotypes_snap_3d_update(wmGizmo *gz, #ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK snap_gizmo->invert_snap = invert_snap(snap_gizmo, wm); +#endif + eventstate_save(snap_gizmo, wm); + Scene *scene = DEG_get_input_scene(depsgraph); + +#ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK if (snap_gizmo->use_snap_override == -1) { const ToolSettings *ts = scene->toolsettings; if (snap_gizmo->invert_snap != !(ts->snap_flag & SCE_SNAP)) { @@ -273,10 +316,13 @@ short ED_gizmotypes_snap_3d_update(wmGizmo *gz, return 0; } } -#else - UNUSED_VARS(wm); #endif + float co[3], no[3]; + short snap_elem = 0; + int snap_elem_index[3] = {-1, -1, -1}; + int index = -1; + 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 != snap_gizmo->prop_snap_force) { @@ -381,14 +427,17 @@ static void snap_gizmo_draw(const bContext *C, wmGizmo *gz) return; } - ARegion *region = CTX_wm_region(C); - RegionView3D *rv3d = region->regiondata; + wmWindowManager *wm = CTX_wm_manager(C); + if (eventstate_has_changed(snap_gizmo, wm)) { + /* The eventstate has changed but the snap has not been updated. + * This means that the current position is no longer valid. */ + snap_gizmo->snap_elem = 0; + return; + } - /* Ideally, we shouldn't assign values here. - * But `test_select` is not called during navigation. - * 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))) { + RegionView3D *rv3d = CTX_wm_region_data(C); + if (rv3d->rflag & RV3D_NAVIGATING) { + /* Don't draw the gizmo while navigating. It can be distracting. */ snap_gizmo->snap_elem = 0; return; } @@ -418,30 +467,17 @@ static void snap_gizmo_draw(const bContext *C, wmGizmo *gz) static int snap_gizmo_test_select(bContext *C, wmGizmo *gz, const int mval[2]) { SnapGizmo3D *snap_gizmo = (SnapGizmo3D *)gz; - -#ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK wmWindowManager *wm = CTX_wm_manager(C); - const bool invert = invert_snap(snap_gizmo, wm); - if (snap_gizmo->invert_snap == invert && snap_gizmo->mval[0] == mval[0] && - snap_gizmo->mval[1] == mval[1]) { + if (!eventstate_has_changed(snap_gizmo, wm)) { /* Performance, do not update. */ return snap_gizmo->snap_elem ? 0 : -1; } - snap_gizmo->invert_snap = invert; -#else - if (snap_gizmo->mval[0] == mval[0] && snap_gizmo->mval[1] == mval[1]) { - /* Performance, do not update. */ - return snap_gizmo->snap_elem ? 0 : -1; - } -#endif - copy_v2_v2_int(snap_gizmo->mval, mval); - ARegion *region = CTX_wm_region(C); View3D *v3d = CTX_wm_view3d(C); const float mval_fl[2] = {UNPACK2(mval)}; short snap_elem = ED_gizmotypes_snap_3d_update( - gz, CTX_data_ensure_evaluated_depsgraph(C), region, v3d, NULL, mval_fl, NULL, NULL); + gz, CTX_data_ensure_evaluated_depsgraph(C), region, v3d, wm, mval_fl, NULL, NULL); if (snap_elem) { ED_region_tag_redraw_editor_overlays(region); diff --git a/source/blender/editors/space_view3d/view3d_gizmo_ruler.c b/source/blender/editors/space_view3d/view3d_gizmo_ruler.c index fdba74ed3a6..9b0ce27b1e3 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_ruler.c +++ b/source/blender/editors/space_view3d/view3d_gizmo_ruler.c @@ -315,8 +315,6 @@ static bool view3d_ruler_item_mousemove(struct Depsgraph *depsgraph, const float eps_bias = 0.0002f; float dist_px = MVAL_MAX_PX_DIST * U.pixelsize; /* snap dist */ - WM_gizmo_set_flag(snap_gizmo, WM_GIZMO_HIDDEN, true); - if (ruler_item) { RulerInteraction *inter = ruler_item->gz.interaction_data; float *co = ruler_item->co[inter->co_index]; @@ -388,12 +386,8 @@ static bool view3d_ruler_item_mousemove(struct Depsgraph *depsgraph, snap_gizmo->ptr, ruler_info->snap_data.prop_prevpoint, prev_point); } - short snap_elem = ED_gizmotypes_snap_3d_update( + ED_gizmotypes_snap_3d_update( snap_gizmo, depsgraph, ruler_info->region, v3d, ruler_info->wm, mval_fl, co, NULL); - - if (snap_elem) { - WM_gizmo_set_flag(snap_gizmo, WM_GIZMO_HIDDEN, false); - } } return true; } @@ -1074,7 +1068,6 @@ static void gizmo_ruler_exit(bContext *C, wmGizmo *gz, const bool cancel) if (!cancel) { if (ruler_info->state == RULER_STATE_DRAG) { - WM_gizmo_set_flag(ruler_info->snap_data.gizmo, WM_GIZMO_HIDDEN, false); RNA_property_unset(ruler_info->snap_data.gizmo->ptr, ruler_info->snap_data.prop_prevpoint); ruler_state_set(ruler_info, RULER_STATE_NORMAL); } diff --git a/source/blender/editors/space_view3d/view3d_placement.c b/source/blender/editors/space_view3d/view3d_placement.c index 7e8ed276766..bd71a768c0f 100644 --- a/source/blender/editors/space_view3d/view3d_placement.c +++ b/source/blender/editors/space_view3d/view3d_placement.c @@ -1357,7 +1357,6 @@ static int view3d_interactive_add_modal(bContext *C, wmOperator *op, const wmEve const float mval_fl[2] = {UNPACK2(event->mval)}; /* Calculate the snap location on mouse-move or when toggling snap. */ - bool is_snap_found_prev = ipd->is_snap_found; ipd->is_snap_found = false; if (ipd->use_snap) { if (ipd->snap_gizmo != NULL) { @@ -1366,7 +1365,7 @@ static int view3d_interactive_add_modal(bContext *C, wmOperator *op, const wmEve CTX_data_ensure_evaluated_depsgraph(C), ipd->region, ipd->v3d, - NULL, + G_MAIN->wm.first, mval_fl, ipd->snap_co, NULL)) { @@ -1376,12 +1375,6 @@ static int view3d_interactive_add_modal(bContext *C, wmOperator *op, const wmEve } } - /* Workaround because test_select doesn't run at the same time as the modal operator. */ - if (is_snap_found_prev != ipd->is_snap_found) { - wmGizmoMap *gzmap = ipd->region->gizmo_map; - WM_gizmo_highlight_set(gzmap, ipd->is_snap_found ? ipd->snap_gizmo : NULL); - } - if (ipd->step_index == STEP_BASE) { if (ipd->is_snap_found) { closest_to_plane_normalized_v3( -- cgit v1.2.3 From 37bf71ad0475549e0458f1e864a30c68c5880e88 Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Wed, 9 Dec 2020 10:30:23 -0300 Subject: Fix T83588: Crash with Shrink/Fatten and Offset Even `t->keymap` can be `NULL`. Bug introduced in rBc822f66bb83 --- .../editors/transform/transform_mode_edge_seq_slide.c | 17 +++++++++-------- .../editors/transform/transform_mode_shrink_fatten.c | 17 +++++++++-------- 2 files changed, 18 insertions(+), 16 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/transform/transform_mode_edge_seq_slide.c b/source/blender/editors/transform/transform_mode_edge_seq_slide.c index 1682b5bfe31..7ccfd0149bd 100644 --- a/source/blender/editors/transform/transform_mode_edge_seq_slide.c +++ b/source/blender/editors/transform/transform_mode_edge_seq_slide.c @@ -50,7 +50,7 @@ static eRedrawFlag seq_slide_handleEvent(struct TransInfo *t, const wmEvent *eve { BLI_assert(t->mode == TFM_SEQ_SLIDE); wmKeyMapItem *kmi = t->custom.mode.data; - if (event->type == kmi->type && event->val == kmi->val) { + if (kmi && event->type == kmi->type && event->val == kmi->val) { /* Allows the 'Expand to fit' effect to be enabled as a toogle. */ t->flag ^= T_ALT_TRANSFORM; return TREDRAW_HARD; @@ -73,12 +73,11 @@ static void headerSeqSlide(TransInfo *t, const float val[2], char str[UI_MAX_DRA ofs += BLI_snprintf( str + ofs, UI_MAX_DRAW_STR - ofs, TIP_("Sequence Slide: %s%s, ("), &tvec[0], t->con.text); - if (t->keymap) { - wmKeyMapItem *kmi = t->custom.mode.data; - if (kmi) { - ofs += WM_keymap_item_to_string(kmi, false, str + ofs, UI_MAX_DRAW_STR - ofs); - } + wmKeyMapItem *kmi = t->custom.mode.data; + if (kmi) { + ofs += WM_keymap_item_to_string(kmi, false, str + ofs, UI_MAX_DRAW_STR - ofs); } + ofs += BLI_snprintf(str + ofs, UI_MAX_DRAW_STR - ofs, TIP_(" or Alt) Expand to fit %s"), @@ -157,7 +156,9 @@ void initSeqSlide(TransInfo *t) t->num.unit_type[0] = B_UNIT_NONE; t->num.unit_type[1] = B_UNIT_NONE; - /* Workaround to use the same key as the modal keymap. */ - t->custom.mode.data = WM_modalkeymap_find_propvalue(t->keymap, TFM_MODAL_TRANSLATE); + if (t->keymap) { + /* Workaround to use the same key as the modal keymap. */ + t->custom.mode.data = WM_modalkeymap_find_propvalue(t->keymap, TFM_MODAL_TRANSLATE); + } } /** \} */ diff --git a/source/blender/editors/transform/transform_mode_shrink_fatten.c b/source/blender/editors/transform/transform_mode_shrink_fatten.c index 6058a2824e9..2a5c631df41 100644 --- a/source/blender/editors/transform/transform_mode_shrink_fatten.c +++ b/source/blender/editors/transform/transform_mode_shrink_fatten.c @@ -50,7 +50,7 @@ static eRedrawFlag shrinkfatten_handleEvent(struct TransInfo *t, const wmEvent * { BLI_assert(t->mode == TFM_SHRINKFATTEN); wmKeyMapItem *kmi = t->custom.mode.data; - if (event->type == kmi->type && event->val == kmi->val) { + if (kmi && event->type == kmi->type && event->val == kmi->val) { /* Allows the 'Even Thickness' effect to be enabled as a toogle. */ t->flag ^= T_ALT_TRANSFORM; return TREDRAW_HARD; @@ -90,12 +90,11 @@ static void applyShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) } ofs += BLI_strncpy_rlen(str + ofs, ", (", sizeof(str) - ofs); - if (t->keymap) { - wmKeyMapItem *kmi = t->custom.mode.data; - if (kmi) { - ofs += WM_keymap_item_to_string(kmi, false, str + ofs, sizeof(str) - ofs); - } + wmKeyMapItem *kmi = t->custom.mode.data; + if (kmi) { + ofs += WM_keymap_item_to_string(kmi, false, str + ofs, sizeof(str) - ofs); } + BLI_snprintf(str + ofs, sizeof(str) - ofs, TIP_(" or Alt) Even Thickness %s"), @@ -149,8 +148,10 @@ void initShrinkFatten(TransInfo *t) t->flag |= T_NO_CONSTRAINT; - /* Workaround to use the same key as the modal keymap. */ - t->custom.mode.data = WM_modalkeymap_find_propvalue(t->keymap, TFM_MODAL_RESIZE); + if (t->keymap) { + /* Workaround to use the same key as the modal keymap. */ + t->custom.mode.data = WM_modalkeymap_find_propvalue(t->keymap, TFM_MODAL_RESIZE); + } } } /** \} */ -- cgit v1.2.3 From 25e151cc34715f4f27f2cecad252b02d1498ba15 Mon Sep 17 00:00:00 2001 From: Antonio Vazquez Date: Wed, 9 Dec 2020 15:41:07 +0100 Subject: Fix T83575: GPencil: VFX Blur is not disabled when samples are zero Before the number of samples was not checked, only the pixel size. --- source/blender/draw/engines/gpencil/gpencil_shader_fx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender') diff --git a/source/blender/draw/engines/gpencil/gpencil_shader_fx.c b/source/blender/draw/engines/gpencil/gpencil_shader_fx.c index d01aaaed8b0..cb65fbd6ae7 100644 --- a/source/blender/draw/engines/gpencil/gpencil_shader_fx.c +++ b/source/blender/draw/engines/gpencil/gpencil_shader_fx.c @@ -95,7 +95,7 @@ static DRWShadingGroup *gpencil_vfx_pass_create(const char *name, static void gpencil_vfx_blur(BlurShaderFxData *fx, Object *ob, gpIterVfxData *iter) { - if (fx->radius[0] == 0.0f && fx->radius[1] == 0.0f) { + if ((fx->samples == 0.0f) || (fx->radius[0] == 0.0f && fx->radius[1] == 0.0f)) { return; } -- cgit v1.2.3 From 4a5f36638b0244b586607e76451669ffbc3c1174 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Wed, 9 Dec 2020 16:20:48 +0100 Subject: Geometry Nodes: simplify supporting different input socket types for attributes This is a non-functional change. The functionality introduced in this commit is not used in master yet. It is used by nodes that are being developed in other branches though. --- source/blender/blenkernel/BKE_geometry_set.hh | 8 +++++ .../blender/blenkernel/intern/attribute_access.cc | 33 +++++++++++++++++ source/blender/makesdna/DNA_node_types.h | 7 ++++ source/blender/nodes/NOD_geometry_exec.hh | 20 +++++++++++ .../blender/nodes/geometry/node_geometry_util.cc | 21 +++++++++++ .../blender/nodes/geometry/node_geometry_util.hh | 6 ++++ source/blender/nodes/intern/node_geometry_exec.cc | 41 ++++++++++++++++++++++ 7 files changed, 136 insertions(+) (limited to 'source/blender') diff --git a/source/blender/blenkernel/BKE_geometry_set.hh b/source/blender/blenkernel/BKE_geometry_set.hh index ef3ae3c381c..3398da9896b 100644 --- a/source/blender/blenkernel/BKE_geometry_set.hh +++ b/source/blender/blenkernel/BKE_geometry_set.hh @@ -157,6 +157,14 @@ class GeometryComponent { const CustomDataType data_type, const void *value) const; + /* Create a read-only dummy attribute that always returns the same value. + * The given value is converted to the correct type if necessary. */ + blender::bke::ReadAttributePtr attribute_get_constant_for_read_converted( + const AttributeDomain domain, + const CustomDataType in_data_type, + const CustomDataType out_data_type, + const void *value) const; + /* Get a read-only dummy attribute that always returns the same value. */ template blender::bke::TypedReadAttribute attribute_get_constant_for_read(const AttributeDomain domain, diff --git a/source/blender/blenkernel/intern/attribute_access.cc b/source/blender/blenkernel/intern/attribute_access.cc index 9f5795291f0..d79168d5443 100644 --- a/source/blender/blenkernel/intern/attribute_access.cc +++ b/source/blender/blenkernel/intern/attribute_access.cc @@ -668,6 +668,39 @@ blender::bke::ReadAttributePtr GeometryComponent::attribute_get_constant_for_rea domain, domain_size, *cpp_type, value); } +blender::bke::ReadAttributePtr GeometryComponent::attribute_get_constant_for_read_converted( + const AttributeDomain domain, + const CustomDataType in_data_type, + const CustomDataType out_data_type, + const void *value) const +{ + BLI_assert(this->attribute_domain_supported(domain)); + if (value == nullptr || in_data_type == out_data_type) { + return this->attribute_get_constant_for_read(domain, out_data_type, value); + } + + const blender::fn::CPPType *in_cpp_type = blender::bke::custom_data_type_to_cpp_type( + in_data_type); + const blender::fn::CPPType *out_cpp_type = blender::bke::custom_data_type_to_cpp_type( + out_data_type); + BLI_assert(in_cpp_type != nullptr); + BLI_assert(out_cpp_type != nullptr); + + const blender::nodes::DataTypeConversions &conversions = + blender::nodes::get_implicit_type_conversions(); + BLI_assert(conversions.is_convertible(*in_cpp_type, *out_cpp_type)); + + void *out_value = alloca(out_cpp_type->size()); + conversions.convert(*in_cpp_type, *out_cpp_type, value, out_value); + + const int domain_size = this->attribute_domain_size(domain); + blender::bke::ReadAttributePtr attribute = std::make_unique( + domain, domain_size, *out_cpp_type, out_value); + + out_cpp_type->destruct(out_value); + return attribute; +} + WriteAttributePtr GeometryComponent::attribute_try_ensure_for_write(const StringRef attribute_name, const AttributeDomain domain, const CustomDataType data_type) diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 29c83d2d4ed..13f8b11352a 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -1464,6 +1464,13 @@ typedef enum GeometryNodeUseAttributeFlag { GEO_NODE_USE_ATTRIBUTE_B = (1 << 1), } GeometryNodeUseAttributeFlag; +typedef enum GeometryNodeAttributeInputMode { + GEO_NODE_ATTRIBUTE_INPUT_ATTRIBUTE = 0, + GEO_NODE_ATTRIBUTE_INPUT_FLOAT = 1, + GEO_NODE_ATTRIBUTE_INPUT_VECTOR = 2, + GEO_NODE_ATTRIBUTE_INPUT_COLOR = 3, +} GeometryNodeAttributeInputMode; + #ifdef __cplusplus } #endif diff --git a/source/blender/nodes/NOD_geometry_exec.hh b/source/blender/nodes/NOD_geometry_exec.hh index fde576d7429..a7df4bc3e1b 100644 --- a/source/blender/nodes/NOD_geometry_exec.hh +++ b/source/blender/nodes/NOD_geometry_exec.hh @@ -148,6 +148,26 @@ class GeoNodeExecParams { return self_object_; } + /** + * Creates a read-only attribute based on node inputs. The method automatically detects which + * input with the given name is available. + */ + ReadAttributePtr get_input_attribute(const StringRef name, + const GeometryComponent &component, + const AttributeDomain domain, + const CustomDataType type, + const void *default_value) const; + + template + bke::TypedReadAttribute get_input_attribute(const StringRef name, + const GeometryComponent &component, + const AttributeDomain domain, + const T &default_value) const + { + const CustomDataType type = bke::cpp_type_to_custom_data_type(CPPType::get()); + return this->get_input_attribute(name, component, domain, type, &default_value); + } + private: /* Utilities for detecting common errors at when using this class. */ void check_extract_input(StringRef identifier, const CPPType *requested_type = nullptr) const; diff --git a/source/blender/nodes/geometry/node_geometry_util.cc b/source/blender/nodes/geometry/node_geometry_util.cc index 41bdb1cfff0..34c7d224f03 100644 --- a/source/blender/nodes/geometry/node_geometry_util.cc +++ b/source/blender/nodes/geometry/node_geometry_util.cc @@ -17,6 +17,27 @@ #include "node_geometry_util.hh" #include "node_util.h" +namespace blender::nodes { + +void update_attribute_input_socket_availabilities(bNode &node, + const StringRef name, + const GeometryNodeAttributeInputMode mode) +{ + const GeometryNodeAttributeInputMode mode_ = (GeometryNodeAttributeInputMode)mode; + LISTBASE_FOREACH (bNodeSocket *, socket, &node.inputs) { + if (name == socket->name) { + const bool is_available = + ((socket->type == SOCK_STRING && mode_ == GEO_NODE_ATTRIBUTE_INPUT_ATTRIBUTE) || + (socket->type == SOCK_FLOAT && mode_ == GEO_NODE_ATTRIBUTE_INPUT_FLOAT) || + (socket->type == SOCK_VECTOR && mode_ == GEO_NODE_ATTRIBUTE_INPUT_VECTOR) || + (socket->type == SOCK_RGBA && mode_ == GEO_NODE_ATTRIBUTE_INPUT_COLOR)); + nodeSetSocketAvailability(socket, is_available); + } + } +} + +} // namespace blender::nodes + bool geo_node_poll_default(bNodeType *UNUSED(ntype), bNodeTree *ntree) { return STREQ(ntree->idname, "GeometryNodeTree"); diff --git a/source/blender/nodes/geometry/node_geometry_util.hh b/source/blender/nodes/geometry/node_geometry_util.hh index bb26763642b..ec389961615 100644 --- a/source/blender/nodes/geometry/node_geometry_util.hh +++ b/source/blender/nodes/geometry/node_geometry_util.hh @@ -37,3 +37,9 @@ void geo_node_type_base( struct bNodeType *ntype, int type, const char *name, short nclass, short flag); bool geo_node_poll_default(struct bNodeType *ntype, struct bNodeTree *ntree); + +namespace blender::nodes { +void update_attribute_input_socket_availabilities(bNode &node, + const StringRef name, + const GeometryNodeAttributeInputMode mode); +} diff --git a/source/blender/nodes/intern/node_geometry_exec.cc b/source/blender/nodes/intern/node_geometry_exec.cc index 50292cb8cfb..a6d9115f01f 100644 --- a/source/blender/nodes/intern/node_geometry_exec.cc +++ b/source/blender/nodes/intern/node_geometry_exec.cc @@ -19,6 +19,47 @@ namespace blender::nodes { +ReadAttributePtr GeoNodeExecParams::get_input_attribute(const StringRef name, + const GeometryComponent &component, + const AttributeDomain domain, + const CustomDataType type, + const void *default_value) const +{ + const bNodeSocket *found_socket = nullptr; + LISTBASE_FOREACH (const bNodeSocket *, socket, &node_.inputs) { + if ((socket->flag & SOCK_UNAVAIL) != 0) { + continue; + } + if (name == socket->name) { + found_socket = socket; + break; + } + } + BLI_assert(found_socket != nullptr); + + if (found_socket->type == SOCK_STRING) { + const std::string name = this->get_input(found_socket->identifier); + return component.attribute_get_for_read(name, domain, type, default_value); + } + if (found_socket->type == SOCK_FLOAT) { + const float value = this->get_input(found_socket->identifier); + return component.attribute_get_constant_for_read_converted( + domain, CD_PROP_FLOAT, type, &value); + } + if (found_socket->type == SOCK_VECTOR) { + const float3 value = this->get_input(found_socket->identifier); + return component.attribute_get_constant_for_read_converted( + domain, CD_PROP_FLOAT3, type, &value); + } + if (found_socket->type == SOCK_RGBA) { + const Color4f value = this->get_input(found_socket->identifier); + return component.attribute_get_constant_for_read_converted( + domain, CD_PROP_COLOR, type, &value); + } + BLI_assert(false); + return component.attribute_get_constant_for_read(domain, type, default_value); +} + void GeoNodeExecParams::check_extract_input(StringRef identifier, const CPPType *requested_type) const { -- cgit v1.2.3 From c93f826661334926fc15504243f61c85242bec42 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Wed, 9 Dec 2020 16:29:11 +0100 Subject: Cleanup: various clang tidy fixes --- source/blender/blenkernel/intern/mesh_validate.cc | 4 ++-- source/blender/blenlib/intern/task_pool.cc | 4 ++-- source/blender/compositor/intern/COM_NodeOperationBuilder.cpp | 2 +- source/blender/compositor/intern/COM_OpenCLDevice.cpp | 2 +- source/blender/compositor/operations/COM_DilateErodeOperation.cpp | 4 ++-- source/blender/compositor/operations/COM_GlareFogGlowOperation.cpp | 2 +- source/blender/compositor/operations/COM_VectorBlurOperation.cpp | 5 ++--- source/blender/depsgraph/intern/depsgraph_query_foreach.cc | 2 +- source/blender/depsgraph/intern/eval/deg_eval_flush.cc | 2 +- source/blender/editors/space_outliner/tree/tree_display_data.cc | 2 +- source/blender/editors/space_outliner/tree/tree_display_orphaned.cc | 2 +- source/blender/editors/space_outliner/tree/tree_display_scenes.cc | 4 ++-- .../blender/editors/space_outliner/tree/tree_display_sequencer.cc | 6 +++--- source/blender/editors/space_outliner/tree/tree_element.h | 2 +- source/blender/freestyle/intern/application/Controller.cpp | 2 +- source/blender/freestyle/intern/geometry/FitCurve.cpp | 2 +- source/blender/freestyle/intern/geometry/GeomCleaner.cpp | 2 +- source/blender/gpu/opengl/gl_debug_layer.cc | 2 +- source/blender/ikplugin/intern/itasc_plugin.cpp | 6 +++--- source/blender/imbuf/intern/dds/FlipDXT.cpp | 2 +- source/blender/imbuf/intern/oiio/openimageio_api.cpp | 2 +- source/blender/imbuf/intern/openexr/openexr_api.cpp | 2 +- source/blender/io/collada/collada_internal.cpp | 2 +- source/blender/simulation/intern/hair_volume.cpp | 4 ++-- 24 files changed, 34 insertions(+), 35 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/intern/mesh_validate.cc b/source/blender/blenkernel/intern/mesh_validate.cc index 16733729be0..0aaca33124a 100644 --- a/source/blender/blenkernel/intern/mesh_validate.cc +++ b/source/blender/blenkernel/intern/mesh_validate.cc @@ -76,10 +76,10 @@ struct OrderedEdge { }; /* The map first contains an edge pointer and later an index. */ -typedef union OrigEdgeOrIndex { +union OrigEdgeOrIndex { const MEdge *original_edge; int index; -} OrigEdgeOrIndex; +}; using EdgeMap = Map; static void reserve_hash_maps(const Mesh *mesh, diff --git a/source/blender/blenlib/intern/task_pool.cc b/source/blender/blenlib/intern/task_pool.cc index 142496dce20..dfed24da2d9 100644 --- a/source/blender/blenlib/intern/task_pool.cc +++ b/source/blender/blenlib/intern/task_pool.cc @@ -149,13 +149,13 @@ class TBBTaskGroup : public tbb::task_group { /* Task Pool */ -typedef enum TaskPoolType { +enum TaskPoolType { TASK_POOL_TBB, TASK_POOL_TBB_SUSPENDED, TASK_POOL_NO_THREADS, TASK_POOL_BACKGROUND, TASK_POOL_BACKGROUND_SERIAL, -} TaskPoolType; +}; struct TaskPool { TaskPoolType type; diff --git a/source/blender/compositor/intern/COM_NodeOperationBuilder.cpp b/source/blender/compositor/intern/COM_NodeOperationBuilder.cpp index 43928f6f915..35a3314db3b 100644 --- a/source/blender/compositor/intern/COM_NodeOperationBuilder.cpp +++ b/source/blender/compositor/intern/COM_NodeOperationBuilder.cpp @@ -304,7 +304,7 @@ void NodeOperationBuilder::add_operation_input_constants() /* Note: unconnected inputs cached first to avoid modifying * m_operations while iterating over it */ - typedef std::vector Inputs; + using Inputs = std::vector; Inputs pending_inputs; for (Operations::const_iterator it = m_operations.begin(); it != m_operations.end(); ++it) { NodeOperation *op = *it; diff --git a/source/blender/compositor/intern/COM_OpenCLDevice.cpp b/source/blender/compositor/intern/COM_OpenCLDevice.cpp index 51ae9d6652e..acfe800e433 100644 --- a/source/blender/compositor/intern/COM_OpenCLDevice.cpp +++ b/source/blender/compositor/intern/COM_OpenCLDevice.cpp @@ -19,7 +19,7 @@ #include "COM_OpenCLDevice.h" #include "COM_WorkScheduler.h" -typedef enum COM_VendorID { NVIDIA = 0x10DE, AMD = 0x1002 } COM_VendorID; +enum COM_VendorID { NVIDIA = 0x10DE, AMD = 0x1002 }; const cl_image_format IMAGE_FORMAT_COLOR = { CL_RGBA, CL_FLOAT, diff --git a/source/blender/compositor/operations/COM_DilateErodeOperation.cpp b/source/blender/compositor/operations/COM_DilateErodeOperation.cpp index 74f5fceacfb..b2dfb558028 100644 --- a/source/blender/compositor/operations/COM_DilateErodeOperation.cpp +++ b/source/blender/compositor/operations/COM_DilateErodeOperation.cpp @@ -330,11 +330,11 @@ void DilateStepOperation::initExecution() } // small helper to pass data from initializeTileData to executePixel -typedef struct tile_info { +struct tile_info { rcti rect; int width; float *buffer; -} tile_info; +}; static tile_info *create_cache(int xmin, int xmax, int ymin, int ymax) { diff --git a/source/blender/compositor/operations/COM_GlareFogGlowOperation.cpp b/source/blender/compositor/operations/COM_GlareFogGlowOperation.cpp index acc1dddacdd..362905761bb 100644 --- a/source/blender/compositor/operations/COM_GlareFogGlowOperation.cpp +++ b/source/blender/compositor/operations/COM_GlareFogGlowOperation.cpp @@ -23,7 +23,7 @@ * 2D Fast Hartley Transform, used for convolution */ -typedef float fREAL; +using fREAL = float; // returns next highest power of 2 of x, as well its log2 in L2 static unsigned int nextPow2(unsigned int x, unsigned int *L2) diff --git a/source/blender/compositor/operations/COM_VectorBlurOperation.cpp b/source/blender/compositor/operations/COM_VectorBlurOperation.cpp index 6254f93472e..f7b908deaf4 100644 --- a/source/blender/compositor/operations/COM_VectorBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_VectorBlurOperation.cpp @@ -141,7 +141,7 @@ void VectorBlurOperation::generateVectorBlur(float *data, /* ****************** Spans ******************************* */ /* span fill in method, is also used to localize data for zbuffering */ -typedef struct ZSpan { +struct ZSpan { /* range for clipping */ int rectx, recty; @@ -157,8 +157,7 @@ typedef struct ZSpan { int *rectz; DrawBufPixel *rectdraw; float clipcrop; - -} ZSpan; +}; /* each zbuffer has coordinates transformed to local rect coordinates, so we can simply clip */ void zbuf_alloc_span(ZSpan *zspan, int rectx, int recty, float clipcrop) diff --git a/source/blender/depsgraph/intern/depsgraph_query_foreach.cc b/source/blender/depsgraph/intern/depsgraph_query_foreach.cc index 1c050edc386..6ce7cc0837b 100644 --- a/source/blender/depsgraph/intern/depsgraph_query_foreach.cc +++ b/source/blender/depsgraph/intern/depsgraph_query_foreach.cc @@ -47,7 +47,7 @@ namespace deg = blender::deg; namespace blender::deg { namespace { -typedef deque TraversalQueue; +using TraversalQueue = deque; using DEGForeachOperation = void (*)(OperationNode *, void *); diff --git a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc index fa7cfb305ee..1b24e2b7ad2 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc @@ -82,7 +82,7 @@ enum { COMPONENT_STATE_DONE = 2, }; -typedef deque FlushQueue; +using FlushQueue = deque; namespace { diff --git a/source/blender/editors/space_outliner/tree/tree_display_data.cc b/source/blender/editors/space_outliner/tree/tree_display_data.cc index 41ca4f72903..8a5c2e7d9f3 100644 --- a/source/blender/editors/space_outliner/tree/tree_display_data.cc +++ b/source/blender/editors/space_outliner/tree/tree_display_data.cc @@ -41,7 +41,7 @@ ListBase TreeDisplayDataAPI::buildTree(const TreeSourceData &source_data) RNA_main_pointer_create(source_data.bmain, &mainptr); TreeElement *te = outliner_add_element( - &space_outliner_, &tree, (void *)&mainptr, NULL, TSE_RNA_STRUCT, -1); + &space_outliner_, &tree, (void *)&mainptr, nullptr, TSE_RNA_STRUCT, -1); /* On first view open parent data elements */ const int show_opened = !space_outliner_.treestore || diff --git a/source/blender/editors/space_outliner/tree/tree_display_orphaned.cc b/source/blender/editors/space_outliner/tree/tree_display_orphaned.cc index 71c1d344057..0b17ea98831 100644 --- a/source/blender/editors/space_outliner/tree/tree_display_orphaned.cc +++ b/source/blender/editors/space_outliner/tree/tree_display_orphaned.cc @@ -68,7 +68,7 @@ ListBase TreeDisplayIDOrphans::buildTree(const TreeSourceData &source_data) TreeElement *te = nullptr; if (!filter_id_type) { ID *id = (ID *)lbarray[a]->first; - te = outliner_add_element(&space_outliner_, &tree, lbarray[a], NULL, TSE_ID_BASE, 0); + te = outliner_add_element(&space_outliner_, &tree, lbarray[a], nullptr, TSE_ID_BASE, 0); te->directdata = lbarray[a]; te->name = outliner_idcode_to_plural(GS(id->name)); } diff --git a/source/blender/editors/space_outliner/tree/tree_display_scenes.cc b/source/blender/editors/space_outliner/tree/tree_display_scenes.cc index c4a5688504d..f377512d81e 100644 --- a/source/blender/editors/space_outliner/tree/tree_display_scenes.cc +++ b/source/blender/editors/space_outliner/tree/tree_display_scenes.cc @@ -46,7 +46,7 @@ ListBase TreeDisplayScenes::buildTree(const TreeSourceData &source_data) for (ID *id : List(source_data.bmain->scenes)) { Scene *scene = reinterpret_cast(id); - TreeElement *te = outliner_add_element(&space_outliner_, &tree, scene, NULL, 0, 0); + TreeElement *te = outliner_add_element(&space_outliner_, &tree, scene, nullptr, 0, 0); TreeStoreElem *tselem = TREESTORE(te); /* New scene elements open by default */ @@ -60,4 +60,4 @@ ListBase TreeDisplayScenes::buildTree(const TreeSourceData &source_data) return tree; } -} // namespace blender::ed::outliner \ No newline at end of file +} // namespace blender::ed::outliner diff --git a/source/blender/editors/space_outliner/tree/tree_display_sequencer.cc b/source/blender/editors/space_outliner/tree/tree_display_sequencer.cc index 486f735be9f..48f0322ccb9 100644 --- a/source/blender/editors/space_outliner/tree/tree_display_sequencer.cc +++ b/source/blender/editors/space_outliner/tree/tree_display_sequencer.cc @@ -18,7 +18,7 @@ * \ingroup spoutliner */ -#include +#include #include "BLI_listbase.h" #include "BLI_listbase_wrapper.hh" @@ -51,11 +51,11 @@ ListBase TreeDisplaySequencer::buildTree(const TreeSourceData &source_data) for (Sequence *seq : List(ed->seqbasep)) { SequenceAddOp op = need_add_seq_dup(seq); if (op == SEQUENCE_DUPLICATE_NONE) { - outliner_add_element(&space_outliner_, &tree, seq, NULL, TSE_SEQUENCE, 0); + outliner_add_element(&space_outliner_, &tree, seq, nullptr, TSE_SEQUENCE, 0); } else if (op == SEQUENCE_DUPLICATE_ADD) { TreeElement *te = outliner_add_element( - &space_outliner_, &tree, seq, NULL, TSE_SEQUENCE_DUP, 0); + &space_outliner_, &tree, seq, nullptr, TSE_SEQUENCE_DUP, 0); add_seq_dup(seq, te, 0); } } diff --git a/source/blender/editors/space_outliner/tree/tree_element.h b/source/blender/editors/space_outliner/tree/tree_element.h index 9012321a323..d88c37180b3 100644 --- a/source/blender/editors/space_outliner/tree/tree_element.h +++ b/source/blender/editors/space_outliner/tree/tree_element.h @@ -36,7 +36,7 @@ extern "C" { typedef struct TreeElementType TreeElementType; TreeElementType *outliner_tree_element_type_create(int type, TreeElement *legacy_te, void *idv); -void outliner_tree_element_type_free(TreeElementType **element); +void outliner_tree_element_type_free(TreeElementType **type); void outliner_tree_element_type_expand(TreeElementType *type, SpaceOutliner *space_outliner); diff --git a/source/blender/freestyle/intern/application/Controller.cpp b/source/blender/freestyle/intern/application/Controller.cpp index e24700a57d8..ddd11729e67 100644 --- a/source/blender/freestyle/intern/application/Controller.cpp +++ b/source/blender/freestyle/intern/application/Controller.cpp @@ -1067,7 +1067,7 @@ void Controller::displayDensityCurves(int x, int y) } unsigned int i, j; - typedef vector densityCurve; + using densityCurve = vector; vector curves(svm->getNumberOfOrientations() + 1); vector curvesDirection(svm->getNumberOfPyramidLevels()); diff --git a/source/blender/freestyle/intern/geometry/FitCurve.cpp b/source/blender/freestyle/intern/geometry/FitCurve.cpp index 66914929960..5768f88e95f 100644 --- a/source/blender/freestyle/intern/geometry/FitCurve.cpp +++ b/source/blender/freestyle/intern/geometry/FitCurve.cpp @@ -30,7 +30,7 @@ using namespace std; namespace Freestyle { -typedef Vector2 *BezierCurve; +using BezierCurve = Vector2 *; /* Forward declarations */ static double *Reparameterize(Vector2 *d, int first, int last, double *u, BezierCurve bezCurve); diff --git a/source/blender/freestyle/intern/geometry/GeomCleaner.cpp b/source/blender/freestyle/intern/geometry/GeomCleaner.cpp index 6a499c07061..7ec18fb2801 100644 --- a/source/blender/freestyle/intern/geometry/GeomCleaner.cpp +++ b/source/blender/freestyle/intern/geometry/GeomCleaner.cpp @@ -202,7 +202,7 @@ void GeomCleaner::CleanIndexedVertexArray(const float *iVertices, unsigned *oVSize, unsigned **oIndices) { - typedef map cleanHashTable; + using cleanHashTable = map; vector vertices; unsigned i; for (i = 0; i < iVSize; i += 3) { diff --git a/source/blender/gpu/opengl/gl_debug_layer.cc b/source/blender/gpu/opengl/gl_debug_layer.cc index 9c2b6c0e547..7d2abfb2cff 100644 --- a/source/blender/gpu/opengl/gl_debug_layer.cc +++ b/source/blender/gpu/opengl/gl_debug_layer.cc @@ -30,7 +30,7 @@ #include "gl_debug.hh" -typedef void *GPUvoidptr; +using GPUvoidptr = void *; #define GPUvoidptr_set void *ret = #define GPUvoidptr_ret return ret diff --git a/source/blender/ikplugin/intern/itasc_plugin.cpp b/source/blender/ikplugin/intern/itasc_plugin.cpp index c91da839d25..9512bce1914 100644 --- a/source/blender/ikplugin/intern/itasc_plugin.cpp +++ b/source/blender/ikplugin/intern/itasc_plugin.cpp @@ -76,9 +76,9 @@ struct IK_Data { using Vector3 = float[3]; using Vector4 = float[4]; struct IK_Target; -typedef void (*ErrorCallback)(const iTaSC::ConstraintValues *values, - unsigned int nvalues, - IK_Target *iktarget); +using ErrorCallback = void (*)(const iTaSC::ConstraintValues *values, + unsigned int nvalues, + IK_Target *iktarget); /* one structure for each target in the scene */ struct IK_Target { diff --git a/source/blender/imbuf/intern/dds/FlipDXT.cpp b/source/blender/imbuf/intern/dds/FlipDXT.cpp index e96b7891f1e..2acf072556a 100644 --- a/source/blender/imbuf/intern/dds/FlipDXT.cpp +++ b/source/blender/imbuf/intern/dds/FlipDXT.cpp @@ -45,7 +45,7 @@ #include /* A function that flips a DXTC block. */ -typedef void (*FlipBlockFunction)(uint8_t *block); +using FlipBlockFunction = void (*)(uint8_t *block); /* Flips a full DXT1 block in the y direction. */ static void FlipDXT1BlockFull(uint8_t *block) diff --git a/source/blender/imbuf/intern/oiio/openimageio_api.cpp b/source/blender/imbuf/intern/oiio/openimageio_api.cpp index 1e8c3c25778..65c25194477 100644 --- a/source/blender/imbuf/intern/oiio/openimageio_api.cpp +++ b/source/blender/imbuf/intern/oiio/openimageio_api.cpp @@ -48,7 +48,7 @@ OIIO_NAMESPACE_USING using std::string; using std::unique_ptr; -typedef unsigned char uchar; +using uchar = unsigned char; template static void fill_all_channels(T *pixels, int width, int height, int components, Q alpha) diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp index 12faa48c81c..9726eaeed2c 100644 --- a/source/blender/imbuf/intern/openexr/openexr_api.cpp +++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp @@ -322,7 +322,7 @@ struct _RGBAZ { half z; }; -typedef struct _RGBAZ RGBAZ; +using RGBAZ = _RGBAZ; extern "C" { diff --git a/source/blender/io/collada/collada_internal.cpp b/source/blender/io/collada/collada_internal.cpp index ed5cc62d05f..787af933e8f 100644 --- a/source/blender/io/collada/collada_internal.cpp +++ b/source/blender/io/collada/collada_internal.cpp @@ -205,7 +205,7 @@ const unsigned char translate_name_map[256] = { 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, }; -typedef std::map> map_string_list; +using map_string_list = std::map>; map_string_list global_id_map; void clear_global_id_map() diff --git a/source/blender/simulation/intern/hair_volume.cpp b/source/blender/simulation/intern/hair_volume.cpp index 1b65dd8f22c..08af2344bc4 100644 --- a/source/blender/simulation/intern/hair_volume.cpp +++ b/source/blender/simulation/intern/hair_volume.cpp @@ -68,13 +68,13 @@ BLI_INLINE int hair_grid_size(const int res[3]) return res[0] * res[1] * res[2]; } -typedef struct HairGridVert { +struct HairGridVert { int samples; float velocity[3]; float density; float velocity_smooth[3]; -} HairGridVert; +}; struct HairGrid { HairGridVert *verts; -- cgit v1.2.3 From ac7694aee05047750f955ee2fb0d62942392f6c0 Mon Sep 17 00:00:00 2001 From: Pablo Vazquez Date: Wed, 9 Dec 2020 21:09:23 +0100 Subject: UI: Update theme to match Shader nodes category color with socket color The change to match socket color and category was already done, but it was missing versioning code to update the theme on load. Fixes T83500 (already closed as invalid, but this would solve the non-matching colors) Reviewed by Hans Goudey (HooglyBoogly) --- source/blender/blenkernel/BKE_blender_version.h | 2 +- source/blender/blenloader/intern/versioning_userdef.c | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index 2ec9e0048a6..afb6112b954 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -39,7 +39,7 @@ extern "C" { /* Blender file format version. */ #define BLENDER_FILE_VERSION BLENDER_VERSION -#define BLENDER_FILE_SUBVERSION 5 +#define BLENDER_FILE_SUBVERSION 6 /* Minimum Blender version that supports reading file written with the current * version. Older Blender versions will test this and show a warning if the file diff --git a/source/blender/blenloader/intern/versioning_userdef.c b/source/blender/blenloader/intern/versioning_userdef.c index 1d85109774c..7bc11317bb4 100644 --- a/source/blender/blenloader/intern/versioning_userdef.c +++ b/source/blender/blenloader/intern/versioning_userdef.c @@ -255,6 +255,10 @@ static void do_versions_theme(const UserDef *userdef, bTheme *btheme) FROM_DEFAULT_V4_UCHAR(space_node.nodeclass_attribute); } + if (!USER_VERSION_ATLEAST(292, 6)) { + FROM_DEFAULT_V4_UCHAR(space_node.nodeclass_shader); + } + /** * Versioning code until next subversion bump goes here. * -- cgit v1.2.3 From 3b57927651fe31ea5576cdc69f3ce134bc56a285 Mon Sep 17 00:00:00 2001 From: Philipp Oeser Date: Fri, 30 Oct 2020 12:12:25 +0100 Subject: Fix T82242: creating particle influence textures does not set up DEG relation immediately Texture and ParticleSettings have a DEG relation, but `DEG_relations_tag_update` was not called when the texture changed. This lead to no updates when e.g. texture size changes, relation only went into full effect after save/reload or adding/removing keyframes. Two places were additional relation tagging is needed: - ParticleSettings `active_texture` changes - ParticleSettingsTextureSlot (basically any TextureSlots') texture changes Maniphest Tasks: T82242 Differential Revision: https://developer.blender.org/D9393 --- source/blender/makesrna/intern/rna_particle.c | 2 +- source/blender/makesrna/intern/rna_texture.c | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'source/blender') diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c index 5987f52328d..be9bff00b52 100644 --- a/source/blender/makesrna/intern/rna_particle.c +++ b/source/blender/makesrna/intern/rna_particle.c @@ -2484,7 +2484,7 @@ static void rna_def_particle_settings(BlenderRNA *brna) NULL, "ParticleSettingsTextureSlot", "ParticleSettingsTextureSlots", - "rna_Particle_reset", + "rna_Particle_reset_dependency", NULL); /* Fluid particle type can't be checked from the type value in RNA diff --git a/source/blender/makesrna/intern/rna_texture.c b/source/blender/makesrna/intern/rna_texture.c index fb6d40b3a55..4eb11879517 100644 --- a/source/blender/makesrna/intern/rna_texture.c +++ b/source/blender/makesrna/intern/rna_texture.c @@ -148,6 +148,7 @@ static const EnumPropertyItem blend_type_items[] = { # include "BKE_texture.h" # include "DEG_depsgraph.h" +# include "DEG_depsgraph_build.h" # include "ED_node.h" # include "ED_render.h" @@ -233,6 +234,12 @@ static void rna_Texture_type_set(PointerRNA *ptr, int value) BKE_texture_type_set(tex, value); } +void rna_TextureSlotTexture_update(bContext *C, PointerRNA *ptr) +{ + DEG_relations_tag_update(CTX_data_main(C)); + rna_TextureSlot_update(C, ptr); +} + void rna_TextureSlot_update(bContext *C, PointerRNA *ptr) { ID *id = ptr->owner_id; @@ -623,7 +630,7 @@ static void rna_def_mtex(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_EDITABLE | PROP_CONTEXT_UPDATE); RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_ui_text(prop, "Texture", "Texture data-block used by this texture slot"); - RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING_LINKS, "rna_TextureSlot_update"); + RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING_LINKS, "rna_TextureSlotTexture_update"); prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); RNA_def_property_string_funcs( -- cgit v1.2.3 From 19560eef1aedd64fc604c1f6151fa62c5c3c3957 Mon Sep 17 00:00:00 2001 From: Aaron Carlisle Date: Wed, 9 Dec 2020 16:08:21 -0500 Subject: Cleanup: Remove unused c popup menu for text editor This code hase been usused for 10 years and the right click menu is now in python. --- source/blender/editors/space_text/text_header.c | 98 ------------------------- 1 file changed, 98 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/space_text/text_header.c b/source/blender/editors/space_text/text_header.c index c583634f440..84b7a6f6831 100644 --- a/source/blender/editors/space_text/text_header.c +++ b/source/blender/editors/space_text/text_header.c @@ -108,101 +108,3 @@ void TEXT_OT_start_find(wmOperatorType *ot) ot->exec = text_text_search_exec; ot->poll = text_properties_poll; } - -/******************** XXX popup menus *******************/ - -#if 0 -{ - /* RMB */ - - uiPopupMenu *pup; - - if (text) { - pup = UI_popup_menu_begin(C, IFACE_("Text"), ICON_NONE); - if (txt_has_sel(text)) { - uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_cut"); - uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_copy"); - } - uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_paste"); - uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_new"); - uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_open"); - uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_save"); - uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_save_as"); - uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_run_script"); - UI_popup_menu_end(C, pup); - } - else { - pup = UI_popup_menu_begin(C, IFACE_("File"), ICON_NONE); - uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_new"); - uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_open"); - UI_popup_menu_end(C, pup); - } -} - -{ - /* Alt+Shift+E */ - - uiPopupMenu *pup; - - pup = UI_popup_menu_begin(C, IFACE_("Edit"), ICON_NONE); - uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_cut"); - uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_copy"); - uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_paste"); - UI_popup_menu_end(C, pup); -} - -{ - /* Alt+Shift+F */ - - uiPopupMenu *pup; - - if (text) { - pup = UI_popup_menu_begin(C, IFACE_("Text"), ICON_NONE); - uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_new"); - uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_open"); - uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_save"); - uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_save_as"); - uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_run_script"); - UI_popup_menu_end(C, pup); - } - else { - pup = UI_popup_menu_begin(C, IFACE_("File"), ICON_NONE); - uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_new"); - uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_open"); - UI_popup_menu_end(C, pup); - } -} - -{ - /* Alt+Shift+V */ - - uiPopupMenu *pup; - - pup = UI_popup_menu_begin(C, IFACE_("Text"), ICON_NONE); - uiItemEnumO(layout, - "TEXT_OT_move", - CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Top of File"), - 0, - "type", - FILE_TOP); - uiItemEnumO(layout, - "TEXT_OT_move", - CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Bottom of File"), - 0, - "type", - FILE_BOTTOM); - uiItemEnumO(layout, - "TEXT_OT_move", - CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Page Up"), - 0, - "type", - PREV_PAGE); - uiItemEnumO(layout, - "TEXT_OT_move", - CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Page Down"), - 0, - "type", - NEXT_PAGE); - UI_popup_menu_end(C, pup); -} -#endif -- cgit v1.2.3 From d870a60dd9270764d5f61457224252200376dd2d Mon Sep 17 00:00:00 2001 From: Pablo Dobarro Date: Wed, 9 Dec 2020 22:19:34 +0100 Subject: Sculpt: Elastic deform type for Snake Hook This adds deformation types to snake hook and the elastic deformation type. This mode deforms the mesh using a kelvinlet instead of applying the displacement directly inside the brush radius, which is great for stylized shapes sketching. Changes in rake rotation when using elastic are too strong when set to 1, so I'll add a nicer way to support rake rotations with smoother transitions in the future. Reviewed By: sergey, JulienKaspar Differential Revision: https://developer.blender.org/D9560 --- source/blender/editors/sculpt_paint/sculpt.c | 55 ++++++++++++++-------- .../blender/editors/sculpt_paint/sculpt_intern.h | 32 +++++++++++++ source/blender/makesdna/DNA_brush_types.h | 10 +++- source/blender/makesrna/intern/rna_brush.c | 19 ++++++++ 4 files changed, 95 insertions(+), 21 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index b9427677745..fd7ec1da497 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -4232,6 +4232,8 @@ static void do_snake_hook_brush_task_cb_ex(void *__restrict userdata, (len_v3(grab_delta) / ss->cache->radius)) : 0.0f; + const bool do_elastic = brush->snake_hook_deform_type == BRUSH_SNAKE_HOOK_DEFORM_ELASTIC; + proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co; SculptBrushTest test; @@ -4239,18 +4241,28 @@ static void do_snake_hook_brush_task_cb_ex(void *__restrict userdata, ss, &test, data->brush->falloff_shape); const int thread_id = BLI_task_parallel_thread_id(tls); + KelvinletParams params; + BKE_kelvinlet_init_params(¶ms, ss->cache->radius, bstrength, 1.0f, 0.4f); + BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - const float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); + if (do_elastic || sculpt_brush_test_sq_fn(&test, vd.co)) { + + float fade; + if (do_elastic) { + fade = 1.0f; + } + else { + fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + } mul_v3_v3fl(proxy[vd.i], grab_delta, fade); @@ -4289,6 +4301,17 @@ static void do_snake_hook_brush_task_cb_ex(void *__restrict userdata, add_v3_v3(proxy[vd.i], delta_rotate); } + if (do_elastic) { + float disp[3]; + BKE_kelvinlet_grab_triscale(disp, ¶ms, vd.co, ss->cache->location, proxy[vd.i]); + mul_v3_fl(disp, bstrength * 20.0f); + if (vd.mask) { + mul_v3_fl(disp, 1.0f - *vd.mask); + } + mul_v3_fl(disp, SCULPT_automasking_factor_get(ss->cache->automasking, ss, vd.index)); + copy_v3_v3(proxy[vd.i], disp); + } + if (vd.mvert) { vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } @@ -5714,16 +5737,8 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe /* Build a list of all nodes that are potentially within the brush's area of influence */ - /* These brushes need to update all nodes as they are not constrained by the brush radius */ - /* Elastic deform needs all nodes to avoid artifacts as the effect of the brush is not - * constrained by the radius. */ - /* Pose needs all nodes because it applies all symmetry iterations at the same time and the IK - * chain can grow to any area of the model. */ - /* This can be optimized by filtering the nodes after calculating the chain. */ - if (ELEM(brush->sculpt_tool, - SCULPT_TOOL_ELASTIC_DEFORM, - SCULPT_TOOL_POSE, - SCULPT_TOOL_BOUNDARY)) { + if (SCULPT_tool_needs_all_pbvh_nodes(brush)) { + /* These brushes need to update all nodes as they are not constrained by the brush radius */ BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode); } else if (brush->sculpt_tool == SCULPT_TOOL_CLOTH) { diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h index 99ee22328ea..3b48207f461 100644 --- a/source/blender/editors/sculpt_paint/sculpt_intern.h +++ b/source/blender/editors/sculpt_paint/sculpt_intern.h @@ -434,6 +434,38 @@ BLI_INLINE bool SCULPT_is_cloth_deform_brush(const Brush *brush) brush->deform_target == BRUSH_DEFORM_TARGET_CLOTH_SIM); } +BLI_INLINE bool SCULPT_tool_needs_all_pbvh_nodes(const Brush *brush) +{ + if (brush->sculpt_tool == SCULPT_TOOL_ELASTIC_DEFORM) { + /* Elastic deformations in any brush need all nodes to avoid artifacts as the effect + * of the Kelvinlet is not constrained by the radius. */ + return true; + } + + if (brush->sculpt_tool == SCULPT_TOOL_POSE) { + /* Pose needs all nodes because it applies all symmetry iterations at the same time + * and the IK chain can grow to any area of the model. */ + /* TODO: This can be optimized by filtering the nodes after calculating the chain. */ + return true; + } + + if (brush->sculpt_tool == SCULPT_TOOL_BOUNDARY) { + /* Boundary needs all nodes because it is not possible to know where the boundary + * deformation is going to be propagated before calculating it. */ + /* TODO: after calculating the boudnary info in the first iteration, it should be + * possible to get the nodes that have vertices included in any boundary deformation + * and cache them. */ + return true; + } + + if (brush->sculpt_tool == SCULPT_TOOL_SNAKE_HOOK && + brush->snake_hook_deform_type == BRUSH_SNAKE_HOOK_DEFORM_ELASTIC) { + /* Snake hook in elastic deform type has same requirements as the elastic deform tool. */ + return true; + } + return false; +} + /* Pose Brush. */ void SCULPT_do_pose_brush(struct Sculpt *sd, struct Object *ob, diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h index 50aac69da19..7bd3c7d0117 100644 --- a/source/blender/makesdna/DNA_brush_types.h +++ b/source/blender/makesdna/DNA_brush_types.h @@ -402,6 +402,11 @@ typedef enum eBrushBoundaryFalloffType { BRUSH_BOUNDARY_FALLOFF_LOOP_INVERT = 3, } eBrushBoundaryFalloffType; +typedef enum eBrushSnakeHookDeformType { + BRUSH_SNAKE_HOOK_DEFORM_FALLOFF = 0, + BRUSH_SNAKE_HOOK_DEFORM_ELASTIC = 1, +} eBrushSnakeHookDeformType; + /* Gpencilsettings.Vertex_mode */ typedef enum eGp_Vertex_Mode { /* Affect to Stroke only. */ @@ -573,7 +578,7 @@ typedef struct Brush { char gpencil_sculpt_tool; /** Active grease pencil weight tool. */ char gpencil_weight_tool; - char _pad1[2]; + char _pad1[6]; float autosmooth_factor; @@ -607,6 +612,9 @@ typedef struct Brush { int elastic_deform_type; float elastic_deform_volume_preservation; + /* snake hook */ + int snake_hook_deform_type; + /* pose */ int pose_deform_type; float pose_offset; diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c index cf36c1a3742..b5ce7976fd8 100644 --- a/source/blender/makesrna/intern/rna_brush.c +++ b/source/blender/makesrna/intern/rna_brush.c @@ -2072,6 +2072,20 @@ static void rna_def_brush(BlenderRNA *brna) {0, NULL, 0, NULL, NULL}, }; + static const EnumPropertyItem brush_snake_hook_deform_type_items[] = { + {BRUSH_SNAKE_HOOK_DEFORM_FALLOFF, + "FALLOFF", + 0, + "Radius Falloff", + "Applies the brush falloff in the tip of the brush"}, + {BRUSH_SNAKE_HOOK_DEFORM_ELASTIC, + "ELASTIC", + 0, + "Elastic", + "Modifies the entire mesh using elastic deform"}, + {0, NULL, 0, NULL, NULL}, + }; + static const EnumPropertyItem brush_cloth_deform_type_items[] = { {BRUSH_CLOTH_DEFORM_DRAG, "DRAG", 0, "Drag", ""}, {BRUSH_CLOTH_DEFORM_PUSH, "PUSH", 0, "Push", ""}, @@ -2309,6 +2323,11 @@ static void rna_def_brush(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Deformation", "Deformation type that is used in the brush"); RNA_def_property_update(prop, 0, "rna_Brush_update"); + prop = RNA_def_property(srna, "snake_hook_deform_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, brush_snake_hook_deform_type_items); + RNA_def_property_ui_text(prop, "Deformation", "Deformation type that is used in the brush"); + RNA_def_property_update(prop, 0, "rna_Brush_update"); + prop = RNA_def_property(srna, "cloth_deform_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, brush_cloth_deform_type_items); RNA_def_property_ui_text(prop, "Deformation", "Deformation type that is used in the brush"); -- cgit v1.2.3 From b379f9348487ad4e13650f10820a987deef76fe6 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Wed, 9 Dec 2020 23:43:01 +0100 Subject: Cleanup: Use const for filter queries --- source/blender/editors/space_file/filelist.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c index 1271feda1e7..e87142a7096 100644 --- a/source/blender/editors/space_file/filelist.c +++ b/source/blender/editors/space_file/filelist.c @@ -630,7 +630,7 @@ void filelist_setsorting(struct FileList *filelist, const short sort, bool inver /* ********** Filter helpers ********** */ /* True if filename is meant to be hidden, eg. starting with period. */ -static bool is_hidden_dot_filename(const char *filename, FileListInternEntry *file) +static bool is_hidden_dot_filename(const char *filename, const FileListInternEntry *file) { if (filename[0] == '.' && !ELEM(filename[1], '.', '\0')) { return true; /* ignore .file */ @@ -671,8 +671,8 @@ static bool is_hidden_dot_filename(const char *filename, FileListInternEntry *fi /* True if should be hidden, based on current filtering. */ static bool is_filtered_hidden(const char *filename, - FileListFilter *filter, - FileListInternEntry *file) + const FileListFilter *filter, + const FileListInternEntry *file) { if ((filename[0] == '.') && (filename[1] == '\0')) { return true; /* Ignore . */ -- cgit v1.2.3 From 65f139117db4aa23f0a59aba788cec843a43b098 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 10 Dec 2020 13:25:49 +1100 Subject: Cleanup: rename BLI_strescape to BLI_str_escape Prepare for `BLI_str_unescape` which doesn't read well without the separator. --- source/blender/blenkernel/intern/anim_data.c | 12 ++++----- source/blender/blenkernel/intern/linestyle.c | 2 +- source/blender/blenkernel/intern/node.c | 2 +- source/blender/blenkernel/intern/tracking.c | 12 ++++----- source/blender/blenlib/BLI_string.h | 2 +- source/blender/blenlib/intern/string.c | 2 +- source/blender/blenloader/intern/versioning_290.c | 4 +-- source/blender/gpu/intern/gpu_batch.cc | 2 +- source/blender/makesrna/intern/rna_access.c | 8 +++--- source/blender/makesrna/intern/rna_armature.c | 2 +- source/blender/makesrna/intern/rna_boid.c | 2 +- source/blender/makesrna/intern/rna_cloth.c | 4 +-- source/blender/makesrna/intern/rna_constraint.c | 6 ++--- source/blender/makesrna/intern/rna_dynamicpaint.c | 8 +++--- source/blender/makesrna/intern/rna_fluid.c | 6 ++--- source/blender/makesrna/intern/rna_gpencil.c | 6 ++--- .../blender/makesrna/intern/rna_gpencil_modifier.c | 2 +- source/blender/makesrna/intern/rna_key.c | 4 +-- source/blender/makesrna/intern/rna_layer.c | 2 +- source/blender/makesrna/intern/rna_linestyle.c | 8 +++--- source/blender/makesrna/intern/rna_mask.c | 2 +- source/blender/makesrna/intern/rna_mesh.c | 30 +++++++++++----------- source/blender/makesrna/intern/rna_modifier.c | 2 +- source/blender/makesrna/intern/rna_nla.c | 4 +-- source/blender/makesrna/intern/rna_nodetree.c | 6 ++--- source/blender/makesrna/intern/rna_object_force.c | 18 ++++++------- source/blender/makesrna/intern/rna_particle.c | 2 +- source/blender/makesrna/intern/rna_pose.c | 2 +- source/blender/makesrna/intern/rna_rna.c | 2 +- source/blender/makesrna/intern/rna_sequencer.c | 14 +++++----- source/blender/makesrna/intern/rna_shader_fx.c | 2 +- source/blender/makesrna/intern/rna_texture.c | 2 +- source/blender/python/intern/bpy.c | 2 +- source/blender/sequencer/intern/sequencer.c | 2 +- 34 files changed, 93 insertions(+), 93 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/intern/anim_data.c b/source/blender/blenkernel/intern/anim_data.c index a85509b11db..13abfa92032 100644 --- a/source/blender/blenkernel/intern/anim_data.c +++ b/source/blender/blenkernel/intern/anim_data.c @@ -989,8 +989,8 @@ char *BKE_animsys_fix_rna_path_rename(ID *owner_id, char *name_old_esc = BLI_array_alloca(name_old_esc, (name_old_len * 2) + 1); char *name_new_esc = BLI_array_alloca(name_new_esc, (name_new_len * 2) + 1); - BLI_strescape(name_old_esc, oldName, (name_old_len * 2) + 1); - BLI_strescape(name_new_esc, newName, (name_new_len * 2) + 1); + BLI_str_escape(name_old_esc, oldName, (name_old_len * 2) + 1); + BLI_str_escape(name_new_esc, newName, (name_new_len * 2) + 1); oldN = BLI_sprintfN("[\"%s\"]", name_old_esc); newN = BLI_sprintfN("[\"%s\"]", name_new_esc); } @@ -1048,8 +1048,8 @@ void BKE_action_fix_paths_rename(ID *owner_id, char *name_old_esc = BLI_array_alloca(name_old_esc, (name_old_len * 2) + 1); char *name_new_esc = BLI_array_alloca(name_new_esc, (name_new_len * 2) + 1); - BLI_strescape(name_old_esc, oldName, (name_old_len * 2) + 1); - BLI_strescape(name_new_esc, newName, (name_new_len * 2) + 1); + BLI_str_escape(name_old_esc, oldName, (name_old_len * 2) + 1); + BLI_str_escape(name_new_esc, newName, (name_new_len * 2) + 1); oldN = BLI_sprintfN("[\"%s\"]", name_old_esc); newN = BLI_sprintfN("[\"%s\"]", name_new_esc); } @@ -1096,8 +1096,8 @@ void BKE_animdata_fix_paths_rename(ID *owner_id, char *name_old_esc = BLI_array_alloca(name_old_esc, (name_old_len * 2) + 1); char *name_new_esc = BLI_array_alloca(name_new_esc, (name_new_len * 2) + 1); - BLI_strescape(name_old_esc, oldName, (name_old_len * 2) + 1); - BLI_strescape(name_new_esc, newName, (name_new_len * 2) + 1); + BLI_str_escape(name_old_esc, oldName, (name_old_len * 2) + 1); + BLI_str_escape(name_new_esc, newName, (name_new_len * 2) + 1); oldN = BLI_sprintfN("[\"%s\"]", name_old_esc); newN = BLI_sprintfN("[\"%s\"]", name_new_esc); } diff --git a/source/blender/blenkernel/intern/linestyle.c b/source/blender/blenkernel/intern/linestyle.c index 69e6535a59f..8542959d4b0 100644 --- a/source/blender/blenkernel/intern/linestyle.c +++ b/source/blender/blenkernel/intern/linestyle.c @@ -2017,7 +2017,7 @@ char *BKE_linestyle_path_to_color_ramp(FreestyleLineStyle *linestyle, ColorBand if (found) { char name_esc[sizeof(m->name) * 2]; - BLI_strescape(name_esc, m->name, sizeof(name_esc)); + BLI_str_escape(name_esc, m->name, sizeof(name_esc)); return BLI_sprintfN("color_modifiers[\"%s\"].color_ramp", name_esc); } } diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index b564a4c468b..31de95817fd 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -2708,7 +2708,7 @@ void nodeRemoveNode(Main *bmain, bNodeTree *ntree, bNode *node, bool do_id_user) char propname_esc[MAX_IDPROP_NAME * 2]; char prefix[MAX_IDPROP_NAME * 2]; - BLI_strescape(propname_esc, node->name, sizeof(propname_esc)); + BLI_str_escape(propname_esc, node->name, sizeof(propname_esc)); BLI_snprintf(prefix, sizeof(prefix), "nodes[\"%s\"]", propname_esc); if (BKE_animdata_fix_paths_remove((ID *)ntree, prefix)) { diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index e083f7ceec0..e5f9d59270e 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -3138,13 +3138,13 @@ void BKE_tracking_get_rna_path_for_track(const struct MovieTracking *tracking, { MovieTrackingObject *object = BKE_tracking_find_object_for_track(tracking, track); char track_name_esc[MAX_NAME * 2]; - BLI_strescape(track_name_esc, track->name, sizeof(track_name_esc)); + BLI_str_escape(track_name_esc, track->name, sizeof(track_name_esc)); if (object == NULL) { BLI_snprintf(rna_path, rna_path_len, "tracking.tracks[\"%s\"]", track_name_esc); } else { char object_name_esc[MAX_NAME * 2]; - BLI_strescape(object_name_esc, object->name, sizeof(object_name_esc)); + BLI_str_escape(object_name_esc, object->name, sizeof(object_name_esc)); BLI_snprintf(rna_path, rna_path_len, "tracking.objects[\"%s\"].tracks[\"%s\"]", @@ -3164,7 +3164,7 @@ void BKE_tracking_get_rna_path_prefix_for_track(const struct MovieTracking *trac } else { char object_name_esc[MAX_NAME * 2]; - BLI_strescape(object_name_esc, object->name, sizeof(object_name_esc)); + BLI_str_escape(object_name_esc, object->name, sizeof(object_name_esc)); BLI_snprintf(rna_path, rna_path_len, "tracking.objects[\"%s\"]", object_name_esc); } } @@ -3176,13 +3176,13 @@ void BKE_tracking_get_rna_path_for_plane_track(const struct MovieTracking *track { MovieTrackingObject *object = BKE_tracking_find_object_for_plane_track(tracking, plane_track); char track_name_esc[MAX_NAME * 2]; - BLI_strescape(track_name_esc, plane_track->name, sizeof(track_name_esc)); + BLI_str_escape(track_name_esc, plane_track->name, sizeof(track_name_esc)); if (object == NULL) { BLI_snprintf(rna_path, rna_path_len, "tracking.plane_tracks[\"%s\"]", track_name_esc); } else { char object_name_esc[MAX_NAME * 2]; - BLI_strescape(object_name_esc, object->name, sizeof(object_name_esc)); + BLI_str_escape(object_name_esc, object->name, sizeof(object_name_esc)); BLI_snprintf(rna_path, rna_path_len, "tracking.objects[\"%s\"].plane_tracks[\"%s\"]", @@ -3203,7 +3203,7 @@ void BKE_tracking_get_rna_path_prefix_for_plane_track( } else { char object_name_esc[MAX_NAME * 2]; - BLI_strescape(object_name_esc, object->name, sizeof(object_name_esc)); + BLI_str_escape(object_name_esc, object->name, sizeof(object_name_esc)); BLI_snprintf(rna_path, rna_path_len, "tracking.objects[\"%s\"].plane_tracks", object_name_esc); } } diff --git a/source/blender/blenlib/BLI_string.h b/source/blender/blenlib/BLI_string.h index 2d745e63764..94d907b2765 100644 --- a/source/blender/blenlib/BLI_string.h +++ b/source/blender/blenlib/BLI_string.h @@ -85,7 +85,7 @@ size_t BLI_vsnprintf_rlen(char *__restrict buffer, char *BLI_sprintfN(const char *__restrict format, ...) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_PRINTF_FORMAT(1, 2); -size_t BLI_strescape(char *__restrict dst, const char *__restrict src, const size_t maxncpy) +size_t BLI_str_escape(char *__restrict dst, const char *__restrict src, const size_t maxncpy) ATTR_NONNULL(); size_t BLI_str_format_int_grouped(char dst[16], int num) ATTR_NONNULL(); diff --git a/source/blender/blenlib/intern/string.c b/source/blender/blenlib/intern/string.c index 02d12d2df9b..dd120a531fa 100644 --- a/source/blender/blenlib/intern/string.c +++ b/source/blender/blenlib/intern/string.c @@ -322,7 +322,7 @@ char *BLI_sprintfN(const char *__restrict format, ...) * TODO: support more fancy string escaping. current code is primitive * this basically is an ascii version of PyUnicode_EncodeUnicodeEscape() * which is a useful reference. */ -size_t BLI_strescape(char *__restrict dst, const char *__restrict src, const size_t maxncpy) +size_t BLI_str_escape(char *__restrict dst, const char *__restrict src, const size_t maxncpy) { size_t len = 0; diff --git a/source/blender/blenloader/intern/versioning_290.c b/source/blender/blenloader/intern/versioning_290.c index 956cf1aee8a..a98e7c46f10 100644 --- a/source/blender/blenloader/intern/versioning_290.c +++ b/source/blender/blenloader/intern/versioning_290.c @@ -181,7 +181,7 @@ static void seq_convert_transform_crop(const Scene *scene, /* Convert offset animation, but only if crop is not used. */ if ((seq->flag & use_transform_flag) != 0 && (seq->flag & use_crop_flag) == 0) { char name_esc[(sizeof(seq->name) - 2) * 2], *path; - BLI_strescape(name_esc, seq->name + 2, sizeof(name_esc)); + BLI_str_escape(name_esc, seq->name + 2, sizeof(name_esc)); path = BLI_sprintfN("sequence_editor.sequences_all[\"%s\"].transform.offset_x", name_esc); seq_convert_transform_animation(scene, path, image_size_x); @@ -408,7 +408,7 @@ void do_versions_after_linking_290(Main *bmain, ReportList *UNUSED(reports)) const size_t node_name_escaped_max_length = (node_name_length * 2); char *node_name_escaped = MEM_mallocN(node_name_escaped_max_length + 1, "escaped name"); - BLI_strescape(node_name_escaped, node->name, node_name_escaped_max_length); + BLI_str_escape(node_name_escaped, node->name, node_name_escaped_max_length); char *rna_path_prefix = BLI_sprintfN("nodes[\"%s\"].inputs", node_name_escaped); BKE_animdata_fix_paths_rename_all_ex( diff --git a/source/blender/gpu/intern/gpu_batch.cc b/source/blender/gpu/intern/gpu_batch.cc index 08b2e3c0f00..9dc24c59e22 100644 --- a/source/blender/gpu/intern/gpu_batch.cc +++ b/source/blender/gpu/intern/gpu_batch.cc @@ -81,7 +81,7 @@ void GPU_batch_init_ex(GPUBatch *batch, for (int v = 1; v < GPU_BATCH_VBO_MAX_LEN; v++) { batch->verts[v] = nullptr; } - for (auto & v : batch->inst) { + for (auto &v : batch->inst) { v = nullptr; } batch->elem = elem; diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index 1aac9c0c0c2..94d839a7c30 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -6016,7 +6016,7 @@ char *RNA_path_from_ID_to_property_index(PointerRNA *ptr, } else { char propname_esc[MAX_IDPROP_NAME * 2]; - BLI_strescape(propname_esc, propname, sizeof(propname_esc)); + BLI_str_escape(propname_esc, propname, sizeof(propname_esc)); path = BLI_sprintfN("%s[\"%s\"]%s", ptrpath, propname_esc, index_str); } MEM_freeN(ptrpath); @@ -6027,7 +6027,7 @@ char *RNA_path_from_ID_to_property_index(PointerRNA *ptr, } else { char propname_esc[MAX_IDPROP_NAME * 2]; - BLI_strescape(propname_esc, propname, sizeof(propname_esc)); + BLI_str_escape(propname_esc, propname, sizeof(propname_esc)); path = BLI_sprintfN("[\"%s\"]%s", propname_esc, index_str); } } @@ -6113,7 +6113,7 @@ char *RNA_path_full_ID_py(Main *bmain, ID *id) char id_esc[(sizeof(id->name) - 2) * 2]; - BLI_strescape(id_esc, id->name + 2, sizeof(id_esc)); + BLI_str_escape(id_esc, id->name + 2, sizeof(id_esc)); return BLI_sprintfN("bpy.data.%s[\"%s\"]%s%s", BKE_idtype_idcode_to_name_plural(GS(id->name)), @@ -7067,7 +7067,7 @@ char *RNA_property_as_string( buf = MEM_mallocN(sizeof(char) * (length + 1), "RNA_property_as_string"); buf_esc = MEM_mallocN(sizeof(char) * (length * 2 + 1), "RNA_property_as_string esc"); RNA_property_string_get(ptr, prop, buf); - BLI_strescape(buf_esc, buf, length * 2 + 1); + BLI_str_escape(buf_esc, buf, length * 2 + 1); MEM_freeN(buf); BLI_dynstr_appendf(dynstr, "\"%s\"", buf_esc); MEM_freeN(buf_esc); diff --git a/source/blender/makesrna/intern/rna_armature.c b/source/blender/makesrna/intern/rna_armature.c index d586f222203..1628c978c30 100644 --- a/source/blender/makesrna/intern/rna_armature.c +++ b/source/blender/makesrna/intern/rna_armature.c @@ -245,7 +245,7 @@ static char *rna_Bone_path(PointerRNA *ptr) Bone *bone = (Bone *)ptr->data; char name_esc[sizeof(bone->name) * 2]; - BLI_strescape(name_esc, bone->name, sizeof(name_esc)); + BLI_str_escape(name_esc, bone->name, sizeof(name_esc)); /* special exception for trying to get the path where ID-block is Object * - this will be assumed to be from a Pose Bone... diff --git a/source/blender/makesrna/intern/rna_boid.c b/source/blender/makesrna/intern/rna_boid.c index 33d69f6f912..3e3452af713 100644 --- a/source/blender/makesrna/intern/rna_boid.c +++ b/source/blender/makesrna/intern/rna_boid.c @@ -183,7 +183,7 @@ static char *rna_BoidRule_path(PointerRNA *ptr) BoidRule *rule = (BoidRule *)ptr->data; char name_esc[sizeof(rule->name) * 2]; - BLI_strescape(name_esc, rule->name, sizeof(name_esc)); + BLI_str_escape(name_esc, rule->name, sizeof(name_esc)); return BLI_sprintfN("rules[\"%s\"]", name_esc); /* XXX not unique */ } diff --git a/source/blender/makesrna/intern/rna_cloth.c b/source/blender/makesrna/intern/rna_cloth.c index 27318494428..b0e0b577629 100644 --- a/source/blender/makesrna/intern/rna_cloth.c +++ b/source/blender/makesrna/intern/rna_cloth.c @@ -439,7 +439,7 @@ static char *rna_ClothSettings_path(PointerRNA *ptr) if (md) { char name_esc[sizeof(md->name) * 2]; - BLI_strescape(name_esc, md->name, sizeof(name_esc)); + BLI_str_escape(name_esc, md->name, sizeof(name_esc)); return BLI_sprintfN("modifiers[\"%s\"].settings", name_esc); } else { @@ -454,7 +454,7 @@ static char *rna_ClothCollisionSettings_path(PointerRNA *ptr) if (md) { char name_esc[sizeof(md->name) * 2]; - BLI_strescape(name_esc, md->name, sizeof(name_esc)); + BLI_str_escape(name_esc, md->name, sizeof(name_esc)); return BLI_sprintfN("modifiers[\"%s\"].collision_settings", name_esc); } else { diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c index 170de68a038..0b3dc2a3504 100644 --- a/source/blender/makesrna/intern/rna_constraint.c +++ b/source/blender/makesrna/intern/rna_constraint.c @@ -433,13 +433,13 @@ static char *rna_Constraint_do_compute_path(Object *ob, bConstraint *con) if (pchan) { char name_esc_pchan[sizeof(pchan->name) * 2]; char name_esc_const[sizeof(con->name) * 2]; - BLI_strescape(name_esc_pchan, pchan->name, sizeof(name_esc_pchan)); - BLI_strescape(name_esc_const, con->name, sizeof(name_esc_const)); + BLI_str_escape(name_esc_pchan, pchan->name, sizeof(name_esc_pchan)); + BLI_str_escape(name_esc_const, con->name, sizeof(name_esc_const)); return BLI_sprintfN("pose.bones[\"%s\"].constraints[\"%s\"]", name_esc_pchan, name_esc_const); } else { char name_esc_const[sizeof(con->name) * 2]; - BLI_strescape(name_esc_const, con->name, sizeof(name_esc_const)); + BLI_str_escape(name_esc_const, con->name, sizeof(name_esc_const)); return BLI_sprintfN("constraints[\"%s\"]", name_esc_const); } } diff --git a/source/blender/makesrna/intern/rna_dynamicpaint.c b/source/blender/makesrna/intern/rna_dynamicpaint.c index f86cfb674d1..7c4762aa3a3 100644 --- a/source/blender/makesrna/intern/rna_dynamicpaint.c +++ b/source/blender/makesrna/intern/rna_dynamicpaint.c @@ -57,7 +57,7 @@ static char *rna_DynamicPaintCanvasSettings_path(PointerRNA *ptr) ModifierData *md = (ModifierData *)settings->pmd; char name_esc[sizeof(md->name) * 2]; - BLI_strescape(name_esc, md->name, sizeof(name_esc)); + BLI_str_escape(name_esc, md->name, sizeof(name_esc)); return BLI_sprintfN("modifiers[\"%s\"].canvas_settings", name_esc); } @@ -67,7 +67,7 @@ static char *rna_DynamicPaintBrushSettings_path(PointerRNA *ptr) ModifierData *md = (ModifierData *)settings->pmd; char name_esc[sizeof(md->name) * 2]; - BLI_strescape(name_esc, md->name, sizeof(name_esc)); + BLI_str_escape(name_esc, md->name, sizeof(name_esc)); return BLI_sprintfN("modifiers[\"%s\"].brush_settings", name_esc); } @@ -78,8 +78,8 @@ static char *rna_DynamicPaintSurface_path(PointerRNA *ptr) char name_esc[sizeof(md->name) * 2]; char name_esc_surface[sizeof(surface->name) * 2]; - BLI_strescape(name_esc, md->name, sizeof(name_esc)); - BLI_strescape(name_esc_surface, surface->name, sizeof(name_esc_surface)); + BLI_str_escape(name_esc, md->name, sizeof(name_esc)); + BLI_str_escape(name_esc_surface, surface->name, sizeof(name_esc_surface)); return BLI_sprintfN( "modifiers[\"%s\"].canvas_settings.canvas_surfaces[\"%s\"]", name_esc, name_esc_surface); } diff --git a/source/blender/makesrna/intern/rna_fluid.c b/source/blender/makesrna/intern/rna_fluid.c index 02ae71e3b3d..90f5434bea0 100644 --- a/source/blender/makesrna/intern/rna_fluid.c +++ b/source/blender/makesrna/intern/rna_fluid.c @@ -872,7 +872,7 @@ static char *rna_FluidDomainSettings_path(PointerRNA *ptr) ModifierData *md = (ModifierData *)settings->fmd; char name_esc[sizeof(md->name) * 2]; - BLI_strescape(name_esc, md->name, sizeof(name_esc)); + BLI_str_escape(name_esc, md->name, sizeof(name_esc)); return BLI_sprintfN("modifiers[\"%s\"].domain_settings", name_esc); } @@ -882,7 +882,7 @@ static char *rna_FluidFlowSettings_path(PointerRNA *ptr) ModifierData *md = (ModifierData *)settings->fmd; char name_esc[sizeof(md->name) * 2]; - BLI_strescape(name_esc, md->name, sizeof(name_esc)); + BLI_str_escape(name_esc, md->name, sizeof(name_esc)); return BLI_sprintfN("modifiers[\"%s\"].flow_settings", name_esc); } @@ -892,7 +892,7 @@ static char *rna_FluidEffectorSettings_path(PointerRNA *ptr) ModifierData *md = (ModifierData *)settings->fmd; char name_esc[sizeof(md->name) * 2]; - BLI_strescape(name_esc, md->name, sizeof(name_esc)); + BLI_str_escape(name_esc, md->name, sizeof(name_esc)); return BLI_sprintfN("modifiers[\"%s\"].effector_settings", name_esc); } diff --git a/source/blender/makesrna/intern/rna_gpencil.c b/source/blender/makesrna/intern/rna_gpencil.c index 603bd51b2d9..7be9d14b1d1 100644 --- a/source/blender/makesrna/intern/rna_gpencil.c +++ b/source/blender/makesrna/intern/rna_gpencil.c @@ -308,7 +308,7 @@ static char *rna_GPencilLayer_path(PointerRNA *ptr) bGPDlayer *gpl = (bGPDlayer *)ptr->data; char name_esc[sizeof(gpl->info) * 2]; - BLI_strescape(name_esc, gpl->info, sizeof(name_esc)); + BLI_str_escape(name_esc, gpl->info, sizeof(name_esc)); return BLI_sprintfN("layers[\"%s\"]", name_esc); } @@ -406,8 +406,8 @@ static char *rna_GPencilLayerMask_path(PointerRNA *ptr) char name_layer[sizeof(gpl->info) * 2]; char name_mask[sizeof(mask->name) * 2]; - BLI_strescape(name_layer, gpl->info, sizeof(name_layer)); - BLI_strescape(name_mask, mask->name, sizeof(name_mask)); + BLI_str_escape(name_layer, gpl->info, sizeof(name_layer)); + BLI_str_escape(name_mask, mask->name, sizeof(name_mask)); return BLI_sprintfN("layers[\"%s\"].mask_layers[\"%s\"]", name_layer, name_mask); } diff --git a/source/blender/makesrna/intern/rna_gpencil_modifier.c b/source/blender/makesrna/intern/rna_gpencil_modifier.c index e30ee2e9ee7..5f131de6a40 100644 --- a/source/blender/makesrna/intern/rna_gpencil_modifier.c +++ b/source/blender/makesrna/intern/rna_gpencil_modifier.c @@ -276,7 +276,7 @@ static char *rna_GpencilModifier_path(PointerRNA *ptr) GpencilModifierData *gmd = ptr->data; char name_esc[sizeof(gmd->name) * 2]; - BLI_strescape(name_esc, gmd->name, sizeof(name_esc)); + BLI_str_escape(name_esc, gmd->name, sizeof(name_esc)); return BLI_sprintfN("grease_pencil_modifiers[\"%s\"]", name_esc); } diff --git a/source/blender/makesrna/intern/rna_key.c b/source/blender/makesrna/intern/rna_key.c index e0005766c48..3b9fc970072 100644 --- a/source/blender/makesrna/intern/rna_key.c +++ b/source/blender/makesrna/intern/rna_key.c @@ -676,7 +676,7 @@ static char *rna_ShapeKey_path(PointerRNA *ptr) ID *id = ptr->owner_id; char name_esc[sizeof(kb->name) * 2]; - BLI_strescape(name_esc, kb->name, sizeof(name_esc)); + BLI_str_escape(name_esc, kb->name, sizeof(name_esc)); if ((id) && (GS(id->name) != ID_KE)) { return BLI_sprintfN("shape_keys.key_blocks[\"%s\"]", name_esc); @@ -774,7 +774,7 @@ static char *rna_ShapeKeyPoint_path(PointerRNA *ptr) index = rna_ShapeKey_curve_find_index(key, index); } - BLI_strescape(name_esc_kb, kb->name, sizeof(name_esc_kb)); + BLI_str_escape(name_esc_kb, kb->name, sizeof(name_esc_kb)); if (GS(id->name) == ID_KE) { return BLI_sprintfN("key_blocks[\"%s\"].data[%d]", name_esc_kb, index); diff --git a/source/blender/makesrna/intern/rna_layer.c b/source/blender/makesrna/intern/rna_layer.c index abc4136bae8..afe69c37eef 100644 --- a/source/blender/makesrna/intern/rna_layer.c +++ b/source/blender/makesrna/intern/rna_layer.c @@ -115,7 +115,7 @@ static char *rna_ViewLayer_path(PointerRNA *ptr) ViewLayer *srl = (ViewLayer *)ptr->data; char name_esc[sizeof(srl->name) * 2]; - BLI_strescape(name_esc, srl->name, sizeof(name_esc)); + BLI_str_escape(name_esc, srl->name, sizeof(name_esc)); return BLI_sprintfN("view_layers[\"%s\"]", name_esc); } diff --git a/source/blender/makesrna/intern/rna_linestyle.c b/source/blender/makesrna/intern/rna_linestyle.c index 03442748854..ca97f2c9a55 100644 --- a/source/blender/makesrna/intern/rna_linestyle.c +++ b/source/blender/makesrna/intern/rna_linestyle.c @@ -257,7 +257,7 @@ static char *rna_LineStyle_color_modifier_path(PointerRNA *ptr) { LineStyleModifier *m = (LineStyleModifier *)ptr->data; char name_esc[sizeof(m->name) * 2]; - BLI_strescape(name_esc, m->name, sizeof(name_esc)); + BLI_str_escape(name_esc, m->name, sizeof(name_esc)); return BLI_sprintfN("color_modifiers[\"%s\"]", name_esc); } @@ -265,7 +265,7 @@ static char *rna_LineStyle_alpha_modifier_path(PointerRNA *ptr) { LineStyleModifier *m = (LineStyleModifier *)ptr->data; char name_esc[sizeof(m->name) * 2]; - BLI_strescape(name_esc, m->name, sizeof(name_esc)); + BLI_str_escape(name_esc, m->name, sizeof(name_esc)); return BLI_sprintfN("alpha_modifiers[\"%s\"]", name_esc); } @@ -273,7 +273,7 @@ static char *rna_LineStyle_thickness_modifier_path(PointerRNA *ptr) { LineStyleModifier *m = (LineStyleModifier *)ptr->data; char name_esc[sizeof(m->name) * 2]; - BLI_strescape(name_esc, m->name, sizeof(name_esc)); + BLI_str_escape(name_esc, m->name, sizeof(name_esc)); return BLI_sprintfN("thickness_modifiers[\"%s\"]", name_esc); } @@ -281,7 +281,7 @@ static char *rna_LineStyle_geometry_modifier_path(PointerRNA *ptr) { LineStyleModifier *m = (LineStyleModifier *)ptr->data; char name_esc[sizeof(m->name) * 2]; - BLI_strescape(name_esc, m->name, sizeof(name_esc)); + BLI_str_escape(name_esc, m->name, sizeof(name_esc)); return BLI_sprintfN("geometry_modifiers[\"%s\"]", name_esc); } diff --git a/source/blender/makesrna/intern/rna_mask.c b/source/blender/makesrna/intern/rna_mask.c index cfbaf0cccf5..db3e5195c79 100644 --- a/source/blender/makesrna/intern/rna_mask.c +++ b/source/blender/makesrna/intern/rna_mask.c @@ -182,7 +182,7 @@ static char *rna_MaskLayer_path(PointerRNA *ptr) { MaskLayer *masklay = (MaskLayer *)ptr->data; char name_esc[sizeof(masklay->name) * 2]; - BLI_strescape(name_esc, masklay->name, sizeof(name_esc)); + BLI_str_escape(name_esc, masklay->name, sizeof(name_esc)); return BLI_sprintfN("layers[\"%s\"]", name_esc); } diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c index 4afb17fe0b9..2bbfee2dcef 100644 --- a/source/blender/makesrna/intern/rna_mesh.c +++ b/source/blender/makesrna/intern/rna_mesh.c @@ -670,7 +670,7 @@ static char *rna_MeshUVLoopLayer_path(PointerRNA *ptr) { CustomDataLayer *cdl = ptr->data; char name_esc[sizeof(cdl->name) * 2]; - BLI_strescape(name_esc, cdl->name, sizeof(name_esc)); + BLI_str_escape(name_esc, cdl->name, sizeof(name_esc)); return BLI_sprintfN("uv_layers[\"%s\"]", name_esc); } @@ -913,7 +913,7 @@ static char *rna_MeshSkinVertexLayer_path(PointerRNA *ptr) { CustomDataLayer *cdl = ptr->data; char name_esc[sizeof(cdl->name) * 2]; - BLI_strescape(name_esc, cdl->name, sizeof(name_esc)); + BLI_str_escape(name_esc, cdl->name, sizeof(name_esc)); return BLI_sprintfN("skin_vertices[\"%s\"]", name_esc); } @@ -945,7 +945,7 @@ static char *rna_MeshPaintMaskLayer_path(PointerRNA *ptr) { CustomDataLayer *cdl = ptr->data; char name_esc[sizeof(cdl->name) * 2]; - BLI_strescape(name_esc, cdl->name, sizeof(name_esc)); + BLI_str_escape(name_esc, cdl->name, sizeof(name_esc)); return BLI_sprintfN("vertex_paint_masks[\"%s\"]", name_esc); } @@ -979,7 +979,7 @@ static char *rna_MeshFaceMapLayer_path(PointerRNA *ptr) { CustomDataLayer *cdl = ptr->data; char name_esc[sizeof(cdl->name) * 2]; - BLI_strescape(name_esc, cdl->name, sizeof(name_esc)); + BLI_str_escape(name_esc, cdl->name, sizeof(name_esc)); return BLI_sprintfN("face_maps[\"%s\"]", name_esc); } @@ -1189,7 +1189,7 @@ static char *rna_VertCustomData_data_path(PointerRNA *ptr, const char *collectio b = ((char *)ptr->data - ((char *)cdl->data)) / CustomData_sizeof(type); if (b >= 0 && b < totvert) { char name_esc[sizeof(cdl->name) * 2]; - BLI_strescape(name_esc, cdl->name, sizeof(name_esc)); + BLI_str_escape(name_esc, cdl->name, sizeof(name_esc)); return BLI_sprintfN("%s[\"%s\"].data[%d]", collection, name_esc, b); } } @@ -1210,7 +1210,7 @@ static char *rna_PolyCustomData_data_path(PointerRNA *ptr, const char *collectio b = ((char *)ptr->data - ((char *)cdl->data)) / CustomData_sizeof(type); if (b >= 0 && b < totpoly) { char name_esc[sizeof(cdl->name) * 2]; - BLI_strescape(name_esc, cdl->name, sizeof(name_esc)); + BLI_str_escape(name_esc, cdl->name, sizeof(name_esc)); return BLI_sprintfN("%s[\"%s\"].data[%d]", collection, name_esc, b); } } @@ -1231,7 +1231,7 @@ static char *rna_LoopCustomData_data_path(PointerRNA *ptr, const char *collectio b = ((char *)ptr->data - ((char *)cdl->data)) / CustomData_sizeof(type); if (b >= 0 && b < totloop) { char name_esc[sizeof(cdl->name) * 2]; - BLI_strescape(name_esc, cdl->name, sizeof(name_esc)); + BLI_str_escape(name_esc, cdl->name, sizeof(name_esc)); return BLI_sprintfN("%s[\"%s\"].data[%d]", collection, name_esc, b); } } @@ -1249,7 +1249,7 @@ static char *rna_MeshLoopColorLayer_path(PointerRNA *ptr) { CustomDataLayer *cdl = ptr->data; char name_esc[sizeof(cdl->name) * 2]; - BLI_strescape(name_esc, cdl->name, sizeof(name_esc)); + BLI_str_escape(name_esc, cdl->name, sizeof(name_esc)); return BLI_sprintfN("vertex_colors[\"%s\"]", name_esc); } @@ -1262,7 +1262,7 @@ static char *rna_MeshVertColorLayer_path(PointerRNA *ptr) { CustomDataLayer *cdl = ptr->data; char name_esc[sizeof(cdl->name) * 2]; - BLI_strescape(name_esc, cdl->name, sizeof(name_esc)); + BLI_str_escape(name_esc, cdl->name, sizeof(name_esc)); return BLI_sprintfN("sculpt_vertex_colors[\"%s\"]", name_esc); } @@ -1276,14 +1276,14 @@ static char *rna_MeshVertexFloatPropertyLayer_path(PointerRNA *ptr) { CustomDataLayer *cdl = ptr->data; char name_esc[sizeof(cdl->name) * 2]; - BLI_strescape(name_esc, cdl->name, sizeof(name_esc)); + BLI_str_escape(name_esc, cdl->name, sizeof(name_esc)); return BLI_sprintfN("vertex_float_layers[\"%s\"]", name_esc); } static char *rna_MeshPolygonFloatPropertyLayer_path(PointerRNA *ptr) { CustomDataLayer *cdl = ptr->data; char name_esc[sizeof(cdl->name) * 2]; - BLI_strescape(name_esc, cdl->name, sizeof(name_esc)); + BLI_str_escape(name_esc, cdl->name, sizeof(name_esc)); return BLI_sprintfN("polygon_float_layers[\"%s\"]", name_esc); } @@ -1327,14 +1327,14 @@ static char *rna_MeshVertexIntPropertyLayer_path(PointerRNA *ptr) { CustomDataLayer *cdl = ptr->data; char name_esc[sizeof(cdl->name) * 2]; - BLI_strescape(name_esc, cdl->name, sizeof(name_esc)); + BLI_str_escape(name_esc, cdl->name, sizeof(name_esc)); return BLI_sprintfN("vertex_int_layers[\"%s\"]", name_esc); } static char *rna_MeshPolygonIntPropertyLayer_path(PointerRNA *ptr) { CustomDataLayer *cdl = ptr->data; char name_esc[sizeof(cdl->name) * 2]; - BLI_strescape(name_esc, cdl->name, sizeof(name_esc)); + BLI_str_escape(name_esc, cdl->name, sizeof(name_esc)); return BLI_sprintfN("polygon_int_layers[\"%s\"]", name_esc); } @@ -1378,14 +1378,14 @@ static char *rna_MeshVertexStringPropertyLayer_path(PointerRNA *ptr) { CustomDataLayer *cdl = ptr->data; char name_esc[sizeof(cdl->name) * 2]; - BLI_strescape(name_esc, cdl->name, sizeof(name_esc)); + BLI_str_escape(name_esc, cdl->name, sizeof(name_esc)); return BLI_sprintfN("vertex_string_layers[\"%s\"]", name_esc); } static char *rna_MeshPolygonStringPropertyLayer_path(PointerRNA *ptr) { CustomDataLayer *cdl = ptr->data; char name_esc[sizeof(cdl->name) * 2]; - BLI_strescape(name_esc, cdl->name, sizeof(name_esc)); + BLI_str_escape(name_esc, cdl->name, sizeof(name_esc)); return BLI_sprintfN("polygon_string_layers[\"%s\"]", name_esc); } diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index 99304d29e00..d91b6ea19f7 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -660,7 +660,7 @@ static char *rna_Modifier_path(PointerRNA *ptr) ModifierData *md = ptr->data; char name_esc[sizeof(md->name) * 2]; - BLI_strescape(name_esc, md->name, sizeof(name_esc)); + BLI_str_escape(name_esc, md->name, sizeof(name_esc)); return BLI_sprintfN("modifiers[\"%s\"]", name_esc); } diff --git a/source/blender/makesrna/intern/rna_nla.c b/source/blender/makesrna/intern/rna_nla.c index b7c51eac6ef..f8a342e7f7e 100644 --- a/source/blender/makesrna/intern/rna_nla.c +++ b/source/blender/makesrna/intern/rna_nla.c @@ -88,8 +88,8 @@ static char *rna_NlaStrip_path(PointerRNA *ptr) char name_esc_nlt[sizeof(nlt->name) * 2]; char name_esc_strip[sizeof(strip->name) * 2]; - BLI_strescape(name_esc_nlt, nlt->name, sizeof(name_esc_nlt)); - BLI_strescape(name_esc_strip, strip->name, sizeof(name_esc_strip)); + BLI_str_escape(name_esc_nlt, nlt->name, sizeof(name_esc_nlt)); + BLI_str_escape(name_esc_strip, strip->name, sizeof(name_esc_strip)); return BLI_sprintfN( "animation_data.nla_tracks[\"%s\"].strips[\"%s\"]", name_esc_nlt, name_esc_strip); } diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 99ae1b85e0c..dd02cc214e0 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -1457,7 +1457,7 @@ static char *rna_Node_path(PointerRNA *ptr) bNode *node = (bNode *)ptr->data; char name_esc[sizeof(node->name) * 2]; - BLI_strescape(name_esc, node->name, sizeof(name_esc)); + BLI_str_escape(name_esc, node->name, sizeof(name_esc)); return BLI_sprintfN("nodes[\"%s\"]", name_esc); } @@ -1484,7 +1484,7 @@ char *rna_Node_ImageUser_path(PointerRNA *ptr) continue; } - BLI_strescape(name_esc, node->name, sizeof(name_esc)); + BLI_str_escape(name_esc, node->name, sizeof(name_esc)); return BLI_sprintfN("nodes[\"%s\"].image_user", name_esc); } @@ -2463,7 +2463,7 @@ static char *rna_NodeSocket_path(PointerRNA *ptr) return NULL; } - BLI_strescape(name_esc, node->name, sizeof(name_esc)); + BLI_str_escape(name_esc, node->name, sizeof(name_esc)); if (sock->in_out == SOCK_IN) { return BLI_sprintfN("nodes[\"%s\"].inputs[%d]", name_esc, socketindex); diff --git a/source/blender/makesrna/intern/rna_object_force.c b/source/blender/makesrna/intern/rna_object_force.c index 39783f9e31f..db4f3754b25 100644 --- a/source/blender/makesrna/intern/rna_object_force.c +++ b/source/blender/makesrna/intern/rna_object_force.c @@ -154,7 +154,7 @@ static char *rna_PointCache_path(PointerRNA *ptr) } char name_esc[sizeof(md->name) * 2]; - BLI_strescape(name_esc, md->name, sizeof(name_esc)); + BLI_str_escape(name_esc, md->name, sizeof(name_esc)); switch (md->type) { case eModifierType_ParticleSystem: { @@ -171,7 +171,7 @@ static char *rna_PointCache_path(PointerRNA *ptr) for (; surface; surface = surface->next) { if (surface->pointcache == cache) { char name_surface_esc[sizeof(surface->name) * 2]; - BLI_strescape(name_surface_esc, surface->name, sizeof(name_surface_esc)); + BLI_str_escape(name_surface_esc, surface->name, sizeof(name_surface_esc)); return BLI_sprintfN( "modifiers[\"%s\"].canvas_settings.canvas_surfaces[\"%s\"].point_cache", name_esc, @@ -436,7 +436,7 @@ static char *rna_CollisionSettings_path(PointerRNA *UNUSED(ptr)) if (md) { char name_esc[sizeof(md->name) * 2]; - BLI_strescape(name_esc, md->name, sizeof(name_esc)); + BLI_str_escape(name_esc, md->name, sizeof(name_esc)); return BLI_sprintfN("modifiers[\"%s\"].settings", name_esc); } else { @@ -608,7 +608,7 @@ static char *rna_SoftBodySettings_path(PointerRNA *ptr) ModifierData *md = (ModifierData *)BKE_modifiers_findby_type(ob, eModifierType_Softbody); char name_esc[sizeof(md->name) * 2]; - BLI_strescape(name_esc, md->name, sizeof(name_esc)); + BLI_str_escape(name_esc, md->name, sizeof(name_esc)); return BLI_sprintfN("modifiers[\"%s\"].settings", name_esc); } @@ -797,7 +797,7 @@ static char *rna_EffectorWeight_path(PointerRNA *ptr) /* no pointer from modifier data to actual softbody storage, would be good to add */ if (ob->soft->effector_weights == ew) { char name_esc[sizeof(md->name) * 2]; - BLI_strescape(name_esc, md->name, sizeof(name_esc)); + BLI_str_escape(name_esc, md->name, sizeof(name_esc)); return BLI_sprintfN("modifiers[\"%s\"].settings.effector_weights", name_esc); } } @@ -808,7 +808,7 @@ static char *rna_EffectorWeight_path(PointerRNA *ptr) ClothModifierData *cmd = (ClothModifierData *)md; if (cmd->sim_parms->effector_weights == ew) { char name_esc[sizeof(md->name) * 2]; - BLI_strescape(name_esc, md->name, sizeof(name_esc)); + BLI_str_escape(name_esc, md->name, sizeof(name_esc)); return BLI_sprintfN("modifiers[\"%s\"].settings.effector_weights", name_esc); } } @@ -820,7 +820,7 @@ static char *rna_EffectorWeight_path(PointerRNA *ptr) if (fmd->type == MOD_FLUID_TYPE_DOMAIN && fmd->domain && fmd->domain->effector_weights == ew) { char name_esc[sizeof(md->name) * 2]; - BLI_strescape(name_esc, md->name, sizeof(name_esc)); + BLI_str_escape(name_esc, md->name, sizeof(name_esc)); return BLI_sprintfN("modifiers[\"%s\"].domain_settings.effector_weights", name_esc); } } @@ -838,8 +838,8 @@ static char *rna_EffectorWeight_path(PointerRNA *ptr) char name_esc[sizeof(md->name) * 2]; char name_esc_surface[sizeof(surface->name) * 2]; - BLI_strescape(name_esc, md->name, sizeof(name_esc)); - BLI_strescape(name_esc_surface, surface->name, sizeof(name_esc_surface)); + BLI_str_escape(name_esc, md->name, sizeof(name_esc)); + BLI_str_escape(name_esc_surface, surface->name, sizeof(name_esc_surface)); return BLI_sprintfN( "modifiers[\"%s\"].canvas_settings.canvas_surfaces[\"%s\"]" ".effector_weights", diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c index be9bff00b52..e04ef105071 100644 --- a/source/blender/makesrna/intern/rna_particle.c +++ b/source/blender/makesrna/intern/rna_particle.c @@ -1490,7 +1490,7 @@ static char *rna_ParticleSystem_path(PointerRNA *ptr) ParticleSystem *psys = (ParticleSystem *)ptr->data; char name_esc[sizeof(psys->name) * 2]; - BLI_strescape(name_esc, psys->name, sizeof(name_esc)); + BLI_str_escape(name_esc, psys->name, sizeof(name_esc)); return BLI_sprintfN("particle_systems[\"%s\"]", name_esc); } diff --git a/source/blender/makesrna/intern/rna_pose.c b/source/blender/makesrna/intern/rna_pose.c index bc9aabbefe6..5f74e8cfc78 100644 --- a/source/blender/makesrna/intern/rna_pose.c +++ b/source/blender/makesrna/intern/rna_pose.c @@ -132,7 +132,7 @@ static char *rna_PoseBone_path(PointerRNA *ptr) bPoseChannel *pchan = ptr->data; char name_esc[sizeof(pchan->name) * 2]; - BLI_strescape(name_esc, pchan->name, sizeof(name_esc)); + BLI_str_escape(name_esc, pchan->name, sizeof(name_esc)); return BLI_sprintfN("pose.bones[\"%s\"]", name_esc); } diff --git a/source/blender/makesrna/intern/rna_rna.c b/source/blender/makesrna/intern/rna_rna.c index b8f6eba4d5a..98ae7591062 100644 --- a/source/blender/makesrna/intern/rna_rna.c +++ b/source/blender/makesrna/intern/rna_rna.c @@ -1360,7 +1360,7 @@ static int rna_property_override_diff_propptr(Main *bmain, BLI_assert(STREQ(rna_itemname_a, rna_itemname_b)); char esc_item_name[RNA_PATH_BUFFSIZE]; - const size_t esc_item_name_len = BLI_strescape( + const size_t esc_item_name_len = BLI_str_escape( esc_item_name, rna_itemname_a, RNA_PATH_BUFFSIZE); extended_rna_path_len = rna_path_len + 2 + esc_item_name_len + 2; if (extended_rna_path_len >= RNA_PATH_BUFFSIZE) { diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c index 4313b468deb..9e7fbf2f9a9 100644 --- a/source/blender/makesrna/intern/rna_sequencer.c +++ b/source/blender/makesrna/intern/rna_sequencer.c @@ -506,7 +506,7 @@ static char *rna_SequenceTransform_path(PointerRNA *ptr) if (seq && seq->name + 2) { char name_esc[(sizeof(seq->name) - 2) * 2]; - BLI_strescape(name_esc, seq->name + 2, sizeof(name_esc)); + BLI_str_escape(name_esc, seq->name + 2, sizeof(name_esc)); return BLI_sprintfN("sequence_editor.sequences_all[\"%s\"].transform", name_esc); } else { @@ -558,7 +558,7 @@ static char *rna_SequenceCrop_path(PointerRNA *ptr) if (seq && seq->name + 2) { char name_esc[(sizeof(seq->name) - 2) * 2]; - BLI_strescape(name_esc, seq->name + 2, sizeof(name_esc)); + BLI_str_escape(name_esc, seq->name + 2, sizeof(name_esc)); return BLI_sprintfN("sequence_editor.sequences_all[\"%s\"].crop", name_esc); } else { @@ -704,7 +704,7 @@ static char *rna_Sequence_path(PointerRNA *ptr) if (seq->name + 2) { char name_esc[(sizeof(seq->name) - 2) * 2]; - BLI_strescape(name_esc, seq->name + 2, sizeof(name_esc)); + BLI_str_escape(name_esc, seq->name + 2, sizeof(name_esc)); return BLI_sprintfN("sequence_editor.sequences_all[\"%s\"]", name_esc); } else { @@ -1023,7 +1023,7 @@ static char *rna_SequenceColorBalance_path(PointerRNA *ptr) if (seq && seq->name + 2) { char name_esc[(sizeof(seq->name) - 2) * 2]; - BLI_strescape(name_esc, seq->name + 2, sizeof(name_esc)); + BLI_str_escape(name_esc, seq->name + 2, sizeof(name_esc)); if (!smd) { /* path to old filter color balance */ @@ -1033,7 +1033,7 @@ static char *rna_SequenceColorBalance_path(PointerRNA *ptr) /* path to modifier */ char name_esc_smd[sizeof(smd->name) * 2]; - BLI_strescape(name_esc_smd, smd->name, sizeof(name_esc_smd)); + BLI_str_escape(name_esc_smd, smd->name, sizeof(name_esc_smd)); return BLI_sprintfN("sequence_editor.sequences_all[\"%s\"].modifiers[\"%s\"].color_balance", name_esc, name_esc_smd); @@ -1168,8 +1168,8 @@ static char *rna_SequenceModifier_path(PointerRNA *ptr) char name_esc[(sizeof(seq->name) - 2) * 2]; char name_esc_smd[sizeof(smd->name) * 2]; - BLI_strescape(name_esc, seq->name + 2, sizeof(name_esc)); - BLI_strescape(name_esc_smd, smd->name, sizeof(name_esc_smd)); + BLI_str_escape(name_esc, seq->name + 2, sizeof(name_esc)); + BLI_str_escape(name_esc_smd, smd->name, sizeof(name_esc_smd)); return BLI_sprintfN( "sequence_editor.sequences_all[\"%s\"].modifiers[\"%s\"]", name_esc, name_esc_smd); } diff --git a/source/blender/makesrna/intern/rna_shader_fx.c b/source/blender/makesrna/intern/rna_shader_fx.c index 7b039b91188..451cc56eba7 100644 --- a/source/blender/makesrna/intern/rna_shader_fx.c +++ b/source/blender/makesrna/intern/rna_shader_fx.c @@ -161,7 +161,7 @@ static char *rna_ShaderFx_path(PointerRNA *ptr) ShaderFxData *gmd = ptr->data; char name_esc[sizeof(gmd->name) * 2]; - BLI_strescape(name_esc, gmd->name, sizeof(name_esc)); + BLI_str_escape(name_esc, gmd->name, sizeof(name_esc)); return BLI_sprintfN("shader_effects[\"%s\"]", name_esc); } diff --git a/source/blender/makesrna/intern/rna_texture.c b/source/blender/makesrna/intern/rna_texture.c index 4eb11879517..cf8abf26c0a 100644 --- a/source/blender/makesrna/intern/rna_texture.c +++ b/source/blender/makesrna/intern/rna_texture.c @@ -324,7 +324,7 @@ char *rna_TextureSlot_path(PointerRNA *ptr) if (mtex->tex) { char name_esc[(sizeof(mtex->tex->id.name) - 2) * 2]; - BLI_strescape(name_esc, mtex->tex->id.name + 2, sizeof(name_esc)); + BLI_str_escape(name_esc, mtex->tex->id.name + 2, sizeof(name_esc)); return BLI_sprintfN("texture_slots[\"%s\"]", name_esc); } else { diff --git a/source/blender/python/intern/bpy.c b/source/blender/python/intern/bpy.c index 804a28d0ebc..2e085f08946 100644 --- a/source/blender/python/intern/bpy.c +++ b/source/blender/python/intern/bpy.c @@ -277,7 +277,7 @@ static PyObject *bpy_escape_identifier(PyObject *UNUSED(self), PyObject *value) size = (value_str_len * 2) + 1; value_escape_str = PyMem_MALLOC(size); - value_escape_str_len = BLI_strescape(value_escape_str, value_str, size); + value_escape_str_len = BLI_str_escape(value_escape_str, value_str, size); if (value_escape_str_len == value_str_len) { Py_INCREF(value); diff --git a/source/blender/sequencer/intern/sequencer.c b/source/blender/sequencer/intern/sequencer.c index 0ebf8f3c8e7..c998886626c 100644 --- a/source/blender/sequencer/intern/sequencer.c +++ b/source/blender/sequencer/intern/sequencer.c @@ -505,7 +505,7 @@ static size_t sequencer_rna_path_prefix(char str[SEQ_RNAPATH_MAXSTR], const char { char name_esc[SEQ_NAME_MAXSTR * 2]; - BLI_strescape(name_esc, name, sizeof(name_esc)); + BLI_str_escape(name_esc, name, sizeof(name_esc)); return BLI_snprintf_rlen( str, SEQ_RNAPATH_MAXSTR, "sequence_editor.sequences_all[\"%s\"]", name_esc); } -- cgit v1.2.3 From 7fc1d760378f5c538c44bc4730c98af820678e4d Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 10 Dec 2020 13:33:55 +1100 Subject: Fix BLI_str_escape with control characters, add unit tests --- source/blender/blenlib/BLI_string.h | 2 +- source/blender/blenlib/intern/string.c | 65 +++++++++++------------- source/blender/blenlib/tests/BLI_string_test.cc | 66 +++++++++++++++++++++++++ 3 files changed, 95 insertions(+), 38 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenlib/BLI_string.h b/source/blender/blenlib/BLI_string.h index 94d907b2765..d88a28a2fb8 100644 --- a/source/blender/blenlib/BLI_string.h +++ b/source/blender/blenlib/BLI_string.h @@ -85,7 +85,7 @@ size_t BLI_vsnprintf_rlen(char *__restrict buffer, char *BLI_sprintfN(const char *__restrict format, ...) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_PRINTF_FORMAT(1, 2); -size_t BLI_str_escape(char *__restrict dst, const char *__restrict src, const size_t maxncpy) +size_t BLI_str_escape(char *__restrict dst, const char *__restrict src, const size_t dst_maxncpy) ATTR_NONNULL(); size_t BLI_str_format_int_grouped(char dst[16], int num) ATTR_NONNULL(); diff --git a/source/blender/blenlib/intern/string.c b/source/blender/blenlib/intern/string.c index dd120a531fa..4734753d304 100644 --- a/source/blender/blenlib/intern/string.c +++ b/source/blender/blenlib/intern/string.c @@ -317,49 +317,40 @@ char *BLI_sprintfN(const char *__restrict format, ...) return n; } -/* match pythons string escaping, assume double quotes - (") - * TODO: should be used to create RNA animation paths. - * TODO: support more fancy string escaping. current code is primitive - * this basically is an ascii version of PyUnicode_EncodeUnicodeEscape() - * which is a useful reference. */ -size_t BLI_str_escape(char *__restrict dst, const char *__restrict src, const size_t maxncpy) +/** + * This roughly matches C and Python's string escaping with double quotes - `"`. + * + * Since every character may need escaping, + * it's common to create a buffer twice as large as the input. + * + * \param dst: The destination string, at least \a dst_maxncpy, typically `(strlen(src) * 2) + 1`. + * \param src: The un-escaped source string. + * \param dst_maxncpy: The maximum number of bytes allowable to copy. + * + * \note This is used for creating animation paths in blend files. + */ +size_t BLI_str_escape(char *__restrict dst, const char *__restrict src, const size_t dst_maxncpy) { - size_t len = 0; - BLI_assert(maxncpy != 0); + BLI_assert(dst_maxncpy != 0); - while (len < maxncpy) { - switch (*src) { - case '\0': - goto escape_finish; - case '\\': - case '"': - ATTR_FALLTHROUGH; - - /* less common but should also be support */ - case '\t': - case '\n': - case '\r': - if (len + 1 < maxncpy) { - *dst++ = '\\'; - len++; - } - else { - /* not enough space to escape */ - break; - } - ATTR_FALLTHROUGH; - default: - *dst = *src; + size_t len = 0; + for (; (len < dst_maxncpy) && (*src != '\0'); dst++, src++, len++) { + char c = *src; + if (ELEM(c, '\\', '"') || /* Use as-is. */ + ((c == '\t') && ((void)(c = 't'), true)) || /* Tab. */ + ((c == '\n') && ((void)(c = 'n'), true)) || /* Newline. */ + ((c == '\r') && ((void)(c = 'r'), true))) /* Carriage return. */ + { + if (UNLIKELY(len + 1 >= dst_maxncpy)) { + /* Not enough space to escape. */ break; + } + *dst++ = '\\'; + len++; } - dst++; - src++; - len++; + *dst = c; } - -escape_finish: - *dst = '\0'; return len; diff --git a/source/blender/blenlib/tests/BLI_string_test.cc b/source/blender/blenlib/tests/BLI_string_test.cc index 58135adbcca..7ef2f5a888e 100644 --- a/source/blender/blenlib/tests/BLI_string_test.cc +++ b/source/blender/blenlib/tests/BLI_string_test.cc @@ -802,3 +802,69 @@ TEST_F(StringCasecmpNatural, TextAndNumbers) testReturnsLessThanZeroForAll(negative); testReturnsMoreThanZeroForAll(positive); } + +/* BLI_str_escape */ + +class StringEscape : public testing::Test { + protected: + StringEscape() + { + } + + using CompareWordsArray = vector>; + + void testEscapeWords(const CompareWordsArray &items) + { + size_t dst_test_len; + char dst_test[64]; + for (const auto &item : items) { + /* Escape the string. */ + dst_test_len = BLI_str_escape(dst_test, item[0], SIZE_MAX); + EXPECT_STREQ(dst_test, item[1]); + EXPECT_EQ(dst_test_len, strlen(dst_test)); + } + } +}; + +TEST_F(StringEscape, Simple) +{ + const CompareWordsArray equal{ + {"", ""}, + {"/", "/"}, + {"'", "'"}, + {"?", "?"}, + }; + + const CompareWordsArray escaped{ + {"\\", "\\\\"}, + {"A\\", "A\\\\"}, + {"\\A", "\\\\A"}, + {"A\\B", "A\\\\B"}, + {"?", "?"}, + {"\"\\", "\\\"\\\\"}, + {"\\\"", "\\\\\\\""}, + {"\"\\\"", "\\\"\\\\\\\""}, + + {"\"\"\"", "\\\"\\\"\\\""}, + {"\\\\\\", "\\\\\\\\\\\\"}, + }; + + testEscapeWords(equal); + testEscapeWords(escaped); +} + +TEST_F(StringEscape, Control) +{ + const CompareWordsArray escaped{ + {"\n", "\\n"}, + {"\r", "\\r"}, + {"\t", "\\t"}, + {"A\n", "A\\n"}, + {"\nA", "\\nA"}, + {"\n\r\t", "\\n\\r\\t"}, + {"\n_\r_\t", "\\n_\\r_\\t"}, + {"\n\\\r\\\t", "\\n\\\\\\r\\\\\\t"}, + }; + + testEscapeWords(escaped); +} -- cgit v1.2.3 From 15d801625cbb2566815a6fed2fc036a14336fec0 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 10 Dec 2020 13:42:59 +1100 Subject: BLI_string: add BLI_str_unescape utility function Performs the reverse of BLI_str_escape. This allows logic to be removed from RNA path handling. --- source/blender/blenlib/BLI_string.h | 2 ++ source/blender/blenlib/intern/string.c | 35 +++++++++++++++++++++++++ source/blender/blenlib/tests/BLI_string_test.cc | 6 ++++- 3 files changed, 42 insertions(+), 1 deletion(-) (limited to 'source/blender') diff --git a/source/blender/blenlib/BLI_string.h b/source/blender/blenlib/BLI_string.h index d88a28a2fb8..2d1f8ac9c5e 100644 --- a/source/blender/blenlib/BLI_string.h +++ b/source/blender/blenlib/BLI_string.h @@ -87,6 +87,8 @@ char *BLI_sprintfN(const char *__restrict format, ...) ATTR_WARN_UNUSED_RESULT size_t BLI_str_escape(char *__restrict dst, const char *__restrict src, const size_t dst_maxncpy) ATTR_NONNULL(); +size_t BLI_str_unescape(char *__restrict dst, const char *__restrict src, const size_t src_maxncpy) + ATTR_NONNULL(); size_t BLI_str_format_int_grouped(char dst[16], int num) ATTR_NONNULL(); size_t BLI_str_format_uint64_grouped(char dst[16], uint64_t num) ATTR_NONNULL(); diff --git a/source/blender/blenlib/intern/string.c b/source/blender/blenlib/intern/string.c index 4734753d304..c8b2f3f6e93 100644 --- a/source/blender/blenlib/intern/string.c +++ b/source/blender/blenlib/intern/string.c @@ -356,6 +356,41 @@ size_t BLI_str_escape(char *__restrict dst, const char *__restrict src, const si return len; } +/** + * This roughly matches C and Python's string escaping with double quotes - `"`. + * + * The destination will never be larger than the source, it will either be the same + * or up to half when all characters are escaped. + * + * \param dst: The destination string, at least the size of `strlen(src) + 1`. + * \param src: The escaped source string. + * \param dst_maxncpy: The maximum number of bytes allowable to copy. + * + * \note This is used for for parsing animation paths in blend files. + */ +size_t BLI_str_unescape(char *__restrict dst, const char *__restrict src, const size_t src_maxncpy) +{ + size_t len = 0; + for (size_t i = 0; i < src_maxncpy && (*src != '\0'); i++, src++) { + char c = *src; + if (c == '\\') { + char c_next = *(src + 1); + if (((c_next == '"') && ((void)(c = '"'), true)) || /* Quote. */ + ((c_next == '\\') && ((void)(c = '\\'), true)) || /* Backslash. */ + ((c_next == 't') && ((void)(c = '\t'), true)) || /* Tab. */ + ((c_next == 'n') && ((void)(c = '\n'), true))) /* Newline. */ + { + i++; + src++; + } + } + + dst[len++] = c; + } + dst[len] = 0; + return len; +} + /** * Makes a copy of the text within the "" that appear after some text 'blahblah' * i.e. for string 'pose["apples"]' with prefix 'pose[', it should grab "apples" diff --git a/source/blender/blenlib/tests/BLI_string_test.cc b/source/blender/blenlib/tests/BLI_string_test.cc index 7ef2f5a888e..4b6cad12813 100644 --- a/source/blender/blenlib/tests/BLI_string_test.cc +++ b/source/blender/blenlib/tests/BLI_string_test.cc @@ -803,7 +803,7 @@ TEST_F(StringCasecmpNatural, TextAndNumbers) testReturnsMoreThanZeroForAll(positive); } -/* BLI_str_escape */ +/* BLI_str_escape, BLI_str_unescape */ class StringEscape : public testing::Test { protected: @@ -822,6 +822,10 @@ class StringEscape : public testing::Test { dst_test_len = BLI_str_escape(dst_test, item[0], SIZE_MAX); EXPECT_STREQ(dst_test, item[1]); EXPECT_EQ(dst_test_len, strlen(dst_test)); + /* Escape back. */ + dst_test_len = BLI_str_unescape(dst_test, item[1], strlen(item[1])); + EXPECT_STREQ(dst_test, item[0]); + EXPECT_EQ(dst_test_len, strlen(dst_test)); } } }; -- cgit v1.2.3 From 82e1b65d91f9ac8f09a9a4698776f21113db46c9 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 10 Dec 2020 13:45:57 +1100 Subject: BLI_string: support escaping additional control character Add support for escaping \a, \b & \f for completeness, currently it's not required. --- source/blender/blenlib/intern/string.c | 11 +++++++++-- source/blender/blenlib/tests/BLI_string_test.cc | 9 ++++++--- 2 files changed, 15 insertions(+), 5 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenlib/intern/string.c b/source/blender/blenlib/intern/string.c index c8b2f3f6e93..98eed838197 100644 --- a/source/blender/blenlib/intern/string.c +++ b/source/blender/blenlib/intern/string.c @@ -340,7 +340,10 @@ size_t BLI_str_escape(char *__restrict dst, const char *__restrict src, const si if (ELEM(c, '\\', '"') || /* Use as-is. */ ((c == '\t') && ((void)(c = 't'), true)) || /* Tab. */ ((c == '\n') && ((void)(c = 'n'), true)) || /* Newline. */ - ((c == '\r') && ((void)(c = 'r'), true))) /* Carriage return. */ + ((c == '\r') && ((void)(c = 'r'), true)) || /* Carriage return. */ + ((c == '\a') && ((void)(c = 'a'), true)) || /* Bell. */ + ((c == '\b') && ((void)(c = 'b'), true)) || /* Backspace. */ + ((c == '\f') && ((void)(c = 'f'), true))) /* Form-feed. */ { if (UNLIKELY(len + 1 >= dst_maxncpy)) { /* Not enough space to escape. */ @@ -378,7 +381,11 @@ size_t BLI_str_unescape(char *__restrict dst, const char *__restrict src, const if (((c_next == '"') && ((void)(c = '"'), true)) || /* Quote. */ ((c_next == '\\') && ((void)(c = '\\'), true)) || /* Backslash. */ ((c_next == 't') && ((void)(c = '\t'), true)) || /* Tab. */ - ((c_next == 'n') && ((void)(c = '\n'), true))) /* Newline. */ + ((c_next == 'n') && ((void)(c = '\n'), true)) || /* Newline. */ + ((c_next == 'r') && ((void)(c = '\r'), true)) || /* Carriage return. */ + ((c_next == 'a') && ((void)(c = '\a'), true)) || /* Bell. */ + ((c_next == 'b') && ((void)(c = '\b'), true)) || /* Backspace. */ + ((c_next == 'f') && ((void)(c = '\f'), true))) /* Form-feed. */ { i++; src++; diff --git a/source/blender/blenlib/tests/BLI_string_test.cc b/source/blender/blenlib/tests/BLI_string_test.cc index 4b6cad12813..4446639322c 100644 --- a/source/blender/blenlib/tests/BLI_string_test.cc +++ b/source/blender/blenlib/tests/BLI_string_test.cc @@ -863,11 +863,14 @@ TEST_F(StringEscape, Control) {"\n", "\\n"}, {"\r", "\\r"}, {"\t", "\\t"}, + {"\a", "\\a"}, + {"\b", "\\b"}, + {"\f", "\\f"}, {"A\n", "A\\n"}, {"\nA", "\\nA"}, - {"\n\r\t", "\\n\\r\\t"}, - {"\n_\r_\t", "\\n_\\r_\\t"}, - {"\n\\\r\\\t", "\\n\\\\\\r\\\\\\t"}, + {"\n\r\t\a\b\f", "\\n\\r\\t\\a\\b\\f"}, + {"\n_\r_\t_\a_\b_\f", "\\n_\\r_\\t_\\a_\\b_\\f"}, + {"\n\\\r\\\t\\\a\\\b\\\f", "\\n\\\\\\r\\\\\\t\\\\\\a\\\\\\b\\\\\\f"}, }; testEscapeWords(escaped); -- cgit v1.2.3 From 2f86518ac085dde77977912b3cfcadd2bbd41080 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 10 Dec 2020 14:02:02 +1100 Subject: RNA: use BLI_str_unescape utility for parsing escaped strings --- source/blender/makesrna/intern/rna_access.c | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) (limited to 'source/blender') diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index 94d839a7c30..80e9d15bb28 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -4959,7 +4959,7 @@ static char *rna_path_token(const char **path, char *fixedbuf, int fixedlen, int const char *p; char *buf; char quote = '\0'; - int i, j, len, escape; + int len, escape; len = 0; @@ -5034,21 +5034,8 @@ static char *rna_path_token(const char **path, char *fixedbuf, int fixedlen, int /* copy string, taking into account escaped ] */ if (bracket) { - for (p = *path, i = 0, j = 0; i < len; i++, p++) { - if (*p == '\\') { - if (*(p + 1) == '\\') { - /* Un-escape pairs of back-slashes into a single back-slash. */ - p++; - i += 1; - } - else if (*(p + 1) == quote) { - continue; - } - } - buf[j++] = *p; - } - - buf[j] = 0; + BLI_str_unescape(buf, *path, len); + p = (*path) + len; } else { memcpy(buf, *path, sizeof(char) * len); -- cgit v1.2.3 From b5bc9d80a11dc99a296d0621bf3fdd156b70b754 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 10 Dec 2020 14:09:29 +1100 Subject: PyAPI: add bpy.utils.unescape_identifier Utility to perform the reverse of `bpy.utils.escape_identifier` --- source/blender/python/intern/bpy.c | 53 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) (limited to 'source/blender') diff --git a/source/blender/python/intern/bpy.c b/source/blender/python/intern/bpy.c index 2e085f08946..bd2f40569f6 100644 --- a/source/blender/python/intern/bpy.c +++ b/source/blender/python/intern/bpy.c @@ -292,6 +292,50 @@ static PyObject *bpy_escape_identifier(PyObject *UNUSED(self), PyObject *value) return value_escape; } +PyDoc_STRVAR(bpy_unescape_identifier_doc, + ".. function:: unescape_identifier(string)\n" + "\n" + " Simple string un-escape function used for animation paths.\n" + " This performs the reverse of `escape_identifier`.\n" + "\n" + " :arg string: text\n" + " :type string: string\n" + " :return: The un-escaped string.\n" + " :rtype: string\n"); +static PyObject *bpy_unescape_identifier(PyObject *UNUSED(self), PyObject *value) +{ + const char *value_str; + Py_ssize_t value_str_len; + + char *value_unescape_str; + Py_ssize_t value_unescape_str_len; + PyObject *value_unescape; + size_t size; + + value_str = _PyUnicode_AsStringAndSize(value, &value_str_len); + + if (value_str == NULL) { + PyErr_SetString(PyExc_TypeError, "expected a string"); + return NULL; + } + + size = value_str_len + 1; + value_unescape_str = PyMem_MALLOC(size); + value_unescape_str_len = BLI_str_unescape(value_unescape_str, value_str, size); + + if (value_unescape_str_len == value_str_len) { + Py_INCREF(value); + value_unescape = value; + } + else { + value_unescape = PyUnicode_FromStringAndSize(value_unescape_str, value_unescape_str_len); + } + + PyMem_FREE(value_unescape_str); + + return value_unescape; +} + static PyMethodDef meth_bpy_script_paths = { "script_paths", (PyCFunction)bpy_script_paths, @@ -328,6 +372,12 @@ static PyMethodDef meth_bpy_escape_identifier = { METH_O, bpy_escape_identifier_doc, }; +static PyMethodDef meth_bpy_unescape_identifier = { + "unescape_identifier", + (PyCFunction)bpy_unescape_identifier, + METH_O, + bpy_unescape_identifier_doc, +}; static PyObject *bpy_import_test(const char *modname) { @@ -429,6 +479,9 @@ void BPy_init_modules(struct bContext *C) PyModule_AddObject(mod, meth_bpy_escape_identifier.ml_name, (PyObject *)PyCFunction_New(&meth_bpy_escape_identifier, NULL)); + PyModule_AddObject(mod, + meth_bpy_unescape_identifier.ml_name, + (PyObject *)PyCFunction_New(&meth_bpy_unescape_identifier, NULL)); /* register funcs (bpy_rna.c) */ PyModule_AddObject(mod, -- cgit v1.2.3 From 564ef8279b5f7b25a4a5f23877c70135c1ec920a Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 10 Dec 2020 14:23:13 +1100 Subject: Cleanup: use snake-case instead of camel-case --- source/blender/blenlib/intern/string.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenlib/intern/string.c b/source/blender/blenlib/intern/string.c index 98eed838197..c4b51338360 100644 --- a/source/blender/blenlib/intern/string.c +++ b/source/blender/blenlib/intern/string.c @@ -412,27 +412,27 @@ size_t BLI_str_unescape(char *__restrict dst, const char *__restrict src, const */ char *BLI_str_quoted_substrN(const char *__restrict str, const char *__restrict prefix) { - const char *startMatch, *endMatch; + const char *start_match, *end_match; - /* get the starting point (i.e. where prefix starts, and add prefixLen+1 + /* get the starting point (i.e. where prefix starts, and add prefix_len+1 * to it to get be after the first " */ - startMatch = strstr(str, prefix); - if (startMatch) { - const size_t prefixLen = strlen(prefix); - startMatch += prefixLen + 1; + start_match = strstr(str, prefix); + if (start_match) { + const size_t prefix_len = strlen(prefix); + start_match += prefix_len + 1; /* get the end point (i.e. where the next occurrence of " is after the starting point) */ - endMatch = startMatch; - while ((endMatch = strchr(endMatch, '"'))) { - if (LIKELY(*(endMatch - 1) != '\\')) { + end_match = start_match; + while ((end_match = strchr(end_match, '"'))) { + if (LIKELY(*(end_match - 1) != '\\')) { break; } - endMatch++; + end_match++; } - if (endMatch) { + if (end_match) { /* return the slice indicated */ - return BLI_strdupn(startMatch, (size_t)(endMatch - startMatch)); + return BLI_strdupn(start_match, (size_t)(end_match - start_match)); } } return BLI_strdupn("", 0); -- cgit v1.2.3 From 51cbd5d91d426ecf987585e49585e09db7cb2bc9 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 10 Dec 2020 14:25:20 +1100 Subject: Cleanup: avoid '_ln' suffix Use '_len' or '_line_number'. --- source/blender/blenlib/tests/BLI_string_test.cc | 108 +++++++++++------------ source/blender/editors/interface/interface_ops.c | 16 ++-- 2 files changed, 62 insertions(+), 62 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenlib/tests/BLI_string_test.cc b/source/blender/blenlib/tests/BLI_string_test.cc index 4446639322c..88cecaa5fee 100644 --- a/source/blender/blenlib/tests/BLI_string_test.cc +++ b/source/blender/blenlib/tests/BLI_string_test.cc @@ -27,14 +27,14 @@ TEST(string, StrPartition) { const char delim[] = {'-', '.', '_', '~', '\\', '\0'}; const char *sep, *suf; - size_t pre_ln; + size_t pre_len; { const char *str = "mat.e-r_ial"; /* "mat.e-r_ial" -> "mat", '.', "e-r_ial", 3 */ - pre_ln = BLI_str_partition(str, delim, &sep, &suf); - EXPECT_EQ(pre_ln, 3); + pre_len = BLI_str_partition(str, delim, &sep, &suf); + EXPECT_EQ(pre_len, 3); EXPECT_EQ(&str[3], sep); EXPECT_STREQ("e-r_ial", suf); } @@ -44,8 +44,8 @@ TEST(string, StrPartition) const char *str = ".mate-rial--"; /* ".mate-rial--" -> "", '.', "mate-rial--", 0 */ - pre_ln = BLI_str_partition(str, delim, &sep, &suf); - EXPECT_EQ(pre_ln, 0); + pre_len = BLI_str_partition(str, delim, &sep, &suf); + EXPECT_EQ(pre_len, 0); EXPECT_EQ(&str[0], sep); EXPECT_STREQ("mate-rial--", suf); } @@ -54,8 +54,8 @@ TEST(string, StrPartition) const char *str = ".__.--_"; /* ".__.--_" -> "", '.', "__.--_", 0 */ - pre_ln = BLI_str_partition(str, delim, &sep, &suf); - EXPECT_EQ(pre_ln, 0); + pre_len = BLI_str_partition(str, delim, &sep, &suf); + EXPECT_EQ(pre_len, 0); EXPECT_EQ(&str[0], sep); EXPECT_STREQ("__.--_", suf); } @@ -64,8 +64,8 @@ TEST(string, StrPartition) const char *str = ""; /* "" -> "", NULL, NULL, 0 */ - pre_ln = BLI_str_partition(str, delim, &sep, &suf); - EXPECT_EQ(pre_ln, 0); + pre_len = BLI_str_partition(str, delim, &sep, &suf); + EXPECT_EQ(pre_len, 0); EXPECT_EQ(sep, (void *)nullptr); EXPECT_EQ(suf, (void *)nullptr); } @@ -74,8 +74,8 @@ TEST(string, StrPartition) const char *str = "material"; /* "material" -> "material", NULL, NULL, 8 */ - pre_ln = BLI_str_partition(str, delim, &sep, &suf); - EXPECT_EQ(pre_ln, 8); + pre_len = BLI_str_partition(str, delim, &sep, &suf); + EXPECT_EQ(pre_len, 8); EXPECT_EQ(sep, (void *)nullptr); EXPECT_EQ(suf, (void *)nullptr); } @@ -86,14 +86,14 @@ TEST(string, StrRPartition) { const char delim[] = {'-', '.', '_', '~', '\\', '\0'}; const char *sep, *suf; - size_t pre_ln; + size_t pre_len; { const char *str = "mat.e-r_ial"; /* "mat.e-r_ial" -> "mat.e-r", '_', "ial", 7 */ - pre_ln = BLI_str_rpartition(str, delim, &sep, &suf); - EXPECT_EQ(pre_ln, 7); + pre_len = BLI_str_rpartition(str, delim, &sep, &suf); + EXPECT_EQ(pre_len, 7); EXPECT_EQ(&str[7], sep); EXPECT_STREQ("ial", suf); } @@ -103,8 +103,8 @@ TEST(string, StrRPartition) const char *str = ".mate-rial--"; /* ".mate-rial--" -> ".mate-rial-", '-', "", 11 */ - pre_ln = BLI_str_rpartition(str, delim, &sep, &suf); - EXPECT_EQ(pre_ln, 11); + pre_len = BLI_str_rpartition(str, delim, &sep, &suf); + EXPECT_EQ(pre_len, 11); EXPECT_EQ(&str[11], sep); EXPECT_STREQ("", suf); } @@ -113,8 +113,8 @@ TEST(string, StrRPartition) const char *str = ".__.--_"; /* ".__.--_" -> ".__.--", '_', "", 6 */ - pre_ln = BLI_str_rpartition(str, delim, &sep, &suf); - EXPECT_EQ(pre_ln, 6); + pre_len = BLI_str_rpartition(str, delim, &sep, &suf); + EXPECT_EQ(pre_len, 6); EXPECT_EQ(&str[6], sep); EXPECT_STREQ("", suf); } @@ -123,8 +123,8 @@ TEST(string, StrRPartition) const char *str = ""; /* "" -> "", NULL, NULL, 0 */ - pre_ln = BLI_str_rpartition(str, delim, &sep, &suf); - EXPECT_EQ(pre_ln, 0); + pre_len = BLI_str_rpartition(str, delim, &sep, &suf); + EXPECT_EQ(pre_len, 0); EXPECT_EQ(sep, (void *)nullptr); EXPECT_EQ(suf, (void *)nullptr); } @@ -133,8 +133,8 @@ TEST(string, StrRPartition) const char *str = "material"; /* "material" -> "material", NULL, NULL, 8 */ - pre_ln = BLI_str_rpartition(str, delim, &sep, &suf); - EXPECT_EQ(pre_ln, 8); + pre_len = BLI_str_rpartition(str, delim, &sep, &suf); + EXPECT_EQ(pre_len, 8); EXPECT_EQ(sep, (void *)nullptr); EXPECT_EQ(suf, (void *)nullptr); } @@ -145,7 +145,7 @@ TEST(string, StrPartitionEx) { const char delim[] = {'-', '.', '_', '~', '\\', '\0'}; const char *sep, *suf; - size_t pre_ln; + size_t pre_len; /* Only considering 'from_right' cases here. */ @@ -153,8 +153,8 @@ TEST(string, StrPartitionEx) const char *str = "mat.e-r_ia.l"; /* "mat.e-r_ia.l" over "mat.e-r" -> "mat.e", '.', "r_ia.l", 3 */ - pre_ln = BLI_str_partition_ex(str, str + 6, delim, &sep, &suf, true); - EXPECT_EQ(pre_ln, 5); + pre_len = BLI_str_partition_ex(str, str + 6, delim, &sep, &suf, true); + EXPECT_EQ(pre_len, 5); EXPECT_EQ(&str[5], sep); EXPECT_STREQ("r_ia.l", suf); } @@ -164,8 +164,8 @@ TEST(string, StrPartitionEx) const char *str = "mate.rial"; /* "mate.rial" over "mate" -> "mate.rial", NULL, NULL, 4 */ - pre_ln = BLI_str_partition_ex(str, str + 4, delim, &sep, &suf, true); - EXPECT_EQ(pre_ln, 4); + pre_len = BLI_str_partition_ex(str, str + 4, delim, &sep, &suf, true); + EXPECT_EQ(pre_len, 4); EXPECT_EQ(sep, (void *)nullptr); EXPECT_EQ(suf, (void *)nullptr); } @@ -176,14 +176,14 @@ TEST(string, StrPartitionUtf8) { const unsigned int delim[] = {'-', '.', '_', 0x00F1 /* n tilde */, 0x262F /* ying-yang */, '\0'}; const char *sep, *suf; - size_t pre_ln; + size_t pre_len; { const char *str = "ma\xc3\xb1te-r\xe2\x98\xafial"; /* "ma\xc3\xb1te-r\xe2\x98\xafial" -> "ma", '\xc3\xb1', "te-r\xe2\x98\xafial", 2 */ - pre_ln = BLI_str_partition_utf8(str, delim, &sep, &suf); - EXPECT_EQ(pre_ln, 2); + pre_len = BLI_str_partition_utf8(str, delim, &sep, &suf); + EXPECT_EQ(pre_len, 2); EXPECT_EQ(&str[2], sep); EXPECT_STREQ("te-r\xe2\x98\xafial", suf); } @@ -193,8 +193,8 @@ TEST(string, StrPartitionUtf8) const char *str = "\xe2\x98\xafmate-rial-\xc3\xb1"; /* "\xe2\x98\xafmate-rial-\xc3\xb1" -> "", '\xe2\x98\xaf', "mate-rial-\xc3\xb1", 0 */ - pre_ln = BLI_str_partition_utf8(str, delim, &sep, &suf); - EXPECT_EQ(pre_ln, 0); + pre_len = BLI_str_partition_utf8(str, delim, &sep, &suf); + EXPECT_EQ(pre_len, 0); EXPECT_EQ(&str[0], sep); EXPECT_STREQ("mate-rial-\xc3\xb1", suf); } @@ -203,8 +203,8 @@ TEST(string, StrPartitionUtf8) const char *str = "\xe2\x98\xaf.\xc3\xb1_.--\xc3\xb1"; /* "\xe2\x98\xaf.\xc3\xb1_.--\xc3\xb1" -> "", '\xe2\x98\xaf', ".\xc3\xb1_.--\xc3\xb1", 0 */ - pre_ln = BLI_str_partition_utf8(str, delim, &sep, &suf); - EXPECT_EQ(pre_ln, 0); + pre_len = BLI_str_partition_utf8(str, delim, &sep, &suf); + EXPECT_EQ(pre_len, 0); EXPECT_EQ(&str[0], sep); EXPECT_STREQ(".\xc3\xb1_.--\xc3\xb1", suf); } @@ -213,8 +213,8 @@ TEST(string, StrPartitionUtf8) const char *str = ""; /* "" -> "", NULL, NULL, 0 */ - pre_ln = BLI_str_partition_utf8(str, delim, &sep, &suf); - EXPECT_EQ(pre_ln, 0); + pre_len = BLI_str_partition_utf8(str, delim, &sep, &suf); + EXPECT_EQ(pre_len, 0); EXPECT_EQ(sep, (void *)nullptr); EXPECT_EQ(suf, (void *)nullptr); } @@ -223,8 +223,8 @@ TEST(string, StrPartitionUtf8) const char *str = "material"; /* "material" -> "material", NULL, NULL, 8 */ - pre_ln = BLI_str_partition_utf8(str, delim, &sep, &suf); - EXPECT_EQ(pre_ln, 8); + pre_len = BLI_str_partition_utf8(str, delim, &sep, &suf); + EXPECT_EQ(pre_len, 8); EXPECT_EQ(sep, (void *)nullptr); EXPECT_EQ(suf, (void *)nullptr); } @@ -235,14 +235,14 @@ TEST(string, StrRPartitionUtf8) { const unsigned int delim[] = {'-', '.', '_', 0x00F1 /* n tilde */, 0x262F /* ying-yang */, '\0'}; const char *sep, *suf; - size_t pre_ln; + size_t pre_len; { const char *str = "ma\xc3\xb1te-r\xe2\x98\xafial"; /* "ma\xc3\xb1te-r\xe2\x98\xafial" -> "mat\xc3\xb1te-r", '\xe2\x98\xaf', "ial", 8 */ - pre_ln = BLI_str_rpartition_utf8(str, delim, &sep, &suf); - EXPECT_EQ(pre_ln, 8); + pre_len = BLI_str_rpartition_utf8(str, delim, &sep, &suf); + EXPECT_EQ(pre_len, 8); EXPECT_EQ(&str[8], sep); EXPECT_STREQ("ial", suf); } @@ -252,8 +252,8 @@ TEST(string, StrRPartitionUtf8) const char *str = "\xe2\x98\xafmate-rial-\xc3\xb1"; /* "\xe2\x98\xafmate-rial-\xc3\xb1" -> "\xe2\x98\xafmate-rial-", '\xc3\xb1', "", 13 */ - pre_ln = BLI_str_rpartition_utf8(str, delim, &sep, &suf); - EXPECT_EQ(pre_ln, 13); + pre_len = BLI_str_rpartition_utf8(str, delim, &sep, &suf); + EXPECT_EQ(pre_len, 13); EXPECT_EQ(&str[13], sep); EXPECT_STREQ("", suf); } @@ -262,8 +262,8 @@ TEST(string, StrRPartitionUtf8) const char *str = "\xe2\x98\xaf.\xc3\xb1_.--\xc3\xb1"; /* "\xe2\x98\xaf.\xc3\xb1_.--\xc3\xb1" -> "\xe2\x98\xaf.\xc3\xb1_.--", '\xc3\xb1', "", 10 */ - pre_ln = BLI_str_rpartition_utf8(str, delim, &sep, &suf); - EXPECT_EQ(pre_ln, 10); + pre_len = BLI_str_rpartition_utf8(str, delim, &sep, &suf); + EXPECT_EQ(pre_len, 10); EXPECT_EQ(&str[10], sep); EXPECT_STREQ("", suf); } @@ -272,8 +272,8 @@ TEST(string, StrRPartitionUtf8) const char *str = ""; /* "" -> "", NULL, NULL, 0 */ - pre_ln = BLI_str_rpartition_utf8(str, delim, &sep, &suf); - EXPECT_EQ(pre_ln, 0); + pre_len = BLI_str_rpartition_utf8(str, delim, &sep, &suf); + EXPECT_EQ(pre_len, 0); EXPECT_EQ(sep, (void *)nullptr); EXPECT_EQ(suf, (void *)nullptr); } @@ -282,8 +282,8 @@ TEST(string, StrRPartitionUtf8) const char *str = "material"; /* "material" -> "material", NULL, NULL, 8 */ - pre_ln = BLI_str_rpartition_utf8(str, delim, &sep, &suf); - EXPECT_EQ(pre_ln, 8); + pre_len = BLI_str_rpartition_utf8(str, delim, &sep, &suf); + EXPECT_EQ(pre_len, 8); EXPECT_EQ(sep, (void *)nullptr); EXPECT_EQ(suf, (void *)nullptr); } @@ -294,7 +294,7 @@ TEST(string, StrPartitionExUtf8) { const unsigned int delim[] = {'-', '.', '_', 0x00F1 /* n tilde */, 0x262F /* ying-yang */, '\0'}; const char *sep, *suf; - size_t pre_ln; + size_t pre_len; /* Only considering 'from_right' cases here. */ @@ -303,8 +303,8 @@ TEST(string, StrPartitionExUtf8) /* "ma\xc3\xb1te-r\xe2\x98\xafial" over * "ma\xc3\xb1te" -> "ma", '\xc3\xb1', "te-r\xe2\x98\xafial", 2 */ - pre_ln = BLI_str_partition_ex_utf8(str, str + 6, delim, &sep, &suf, true); - EXPECT_EQ(pre_ln, 2); + pre_len = BLI_str_partition_ex_utf8(str, str + 6, delim, &sep, &suf, true); + EXPECT_EQ(pre_len, 2); EXPECT_EQ(&str[2], sep); EXPECT_STREQ("te-r\xe2\x98\xafial", suf); } @@ -314,8 +314,8 @@ TEST(string, StrPartitionExUtf8) const char *str = "mate\xe2\x98\xafrial"; /* "mate\xe2\x98\xafrial" over "mate" -> "mate\xe2\x98\xafrial", NULL, NULL, 4 */ - pre_ln = BLI_str_partition_ex_utf8(str, str + 4, delim, &sep, &suf, true); - EXPECT_EQ(pre_ln, 4); + pre_len = BLI_str_partition_ex_utf8(str, str + 4, delim, &sep, &suf, true); + EXPECT_EQ(pre_len, 4); EXPECT_EQ(sep, (void *)nullptr); EXPECT_EQ(suf, (void *)nullptr); } diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c index 0d1e2802242..e5aa0665a16 100644 --- a/source/blender/editors/interface/interface_ops.c +++ b/source/blender/editors/interface/interface_ops.c @@ -1223,7 +1223,7 @@ typedef struct uiEditSourceStore { typedef struct uiEditSourceButStore { char py_dbg_fn[FILE_MAX]; - int py_dbg_ln; + int py_dbg_line_number; } uiEditSourceButStore; /* should only ever be set while the edit source operator is running */ @@ -1276,21 +1276,21 @@ void UI_editsource_active_but_test(uiBut *but) struct uiEditSourceButStore *but_store = MEM_callocN(sizeof(uiEditSourceButStore), __func__); const char *fn; - int lineno = -1; + int line_number = -1; # if 0 printf("comparing buttons: '%s' == '%s'\n", but->drawstr, ui_editsource_info->but_orig.drawstr); # endif - PyC_FileAndNum_Safe(&fn, &lineno); + PyC_FileAndNum_Safe(&fn, &line_number); - if (lineno != -1) { + if (line_number != -1) { BLI_strncpy(but_store->py_dbg_fn, fn, sizeof(but_store->py_dbg_fn)); - but_store->py_dbg_ln = lineno; + but_store->py_dbg_line_number = line_number; } else { but_store->py_dbg_fn[0] = '\0'; - but_store->py_dbg_ln = -1; + but_store->py_dbg_line_number = -1; } BLI_ghash_insert(ui_editsource_info->hash, but, but_store); @@ -1375,8 +1375,8 @@ static int editsource_exec(bContext *C, wmOperator *op) } if (but_store) { - if (but_store->py_dbg_ln != -1) { - ret = editsource_text_edit(C, op, but_store->py_dbg_fn, but_store->py_dbg_ln); + if (but_store->py_dbg_line_number != -1) { + ret = editsource_text_edit(C, op, but_store->py_dbg_fn, but_store->py_dbg_line_number); } else { BKE_report( -- cgit v1.2.3 From c5aaa11c3bfc98a168128971f1e85a014efba07f Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 10 Dec 2020 14:12:55 +1100 Subject: Cleanup: declare variables when used (bpy) --- source/blender/python/intern/bpy.c | 32 ++++++++++---------------------- 1 file changed, 10 insertions(+), 22 deletions(-) (limited to 'source/blender') diff --git a/source/blender/python/intern/bpy.c b/source/blender/python/intern/bpy.c index bd2f40569f6..6462f8320d7 100644 --- a/source/blender/python/intern/bpy.c +++ b/source/blender/python/intern/bpy.c @@ -260,25 +260,19 @@ PyDoc_STRVAR(bpy_escape_identifier_doc, " :rtype: string\n"); static PyObject *bpy_escape_identifier(PyObject *UNUSED(self), PyObject *value) { - const char *value_str; Py_ssize_t value_str_len; - - char *value_escape_str; - Py_ssize_t value_escape_str_len; - PyObject *value_escape; - size_t size; - - value_str = _PyUnicode_AsStringAndSize(value, &value_str_len); + const char *value_str = _PyUnicode_AsStringAndSize(value, &value_str_len); if (value_str == NULL) { PyErr_SetString(PyExc_TypeError, "expected a string"); return NULL; } - size = (value_str_len * 2) + 1; - value_escape_str = PyMem_MALLOC(size); - value_escape_str_len = BLI_str_escape(value_escape_str, value_str, size); + const size_t size = (value_str_len * 2) + 1; + char *value_escape_str = PyMem_MALLOC(size); + const Py_ssize_t value_escape_str_len = BLI_str_escape(value_escape_str, value_str, size); + PyObject *value_escape; if (value_escape_str_len == value_str_len) { Py_INCREF(value); value_escape = value; @@ -304,25 +298,19 @@ PyDoc_STRVAR(bpy_unescape_identifier_doc, " :rtype: string\n"); static PyObject *bpy_unescape_identifier(PyObject *UNUSED(self), PyObject *value) { - const char *value_str; Py_ssize_t value_str_len; - - char *value_unescape_str; - Py_ssize_t value_unescape_str_len; - PyObject *value_unescape; - size_t size; - - value_str = _PyUnicode_AsStringAndSize(value, &value_str_len); + const char *value_str = _PyUnicode_AsStringAndSize(value, &value_str_len); if (value_str == NULL) { PyErr_SetString(PyExc_TypeError, "expected a string"); return NULL; } - size = value_str_len + 1; - value_unescape_str = PyMem_MALLOC(size); - value_unescape_str_len = BLI_str_unescape(value_unescape_str, value_str, size); + const size_t size = value_str_len + 1; + char *value_unescape_str = PyMem_MALLOC(size); + const Py_ssize_t value_unescape_str_len = BLI_str_unescape(value_unescape_str, value_str, size); + PyObject *value_unescape; if (value_unescape_str_len == value_str_len) { Py_INCREF(value); value_unescape = value; -- cgit v1.2.3 From ed2556e22cc2d3629833bdc39ec1852ee5c4470e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 10 Dec 2020 14:19:20 +1100 Subject: Cleanup: declare variables when used (RNA) --- source/blender/makesrna/intern/rna_access.c | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) (limited to 'source/blender') diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index 80e9d15bb28..67f88d31afd 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -4957,11 +4957,7 @@ PointerRNA rna_array_lookup_int( static char *rna_path_token(const char **path, char *fixedbuf, int fixedlen, int bracket) { const char *p; - char *buf; - char quote = '\0'; - int len, escape; - - len = 0; + int len = 0; if (bracket) { /* get data between [], check escaping ] with \] */ @@ -4975,9 +4971,9 @@ static char *rna_path_token(const char **path, char *fixedbuf, int fixedlen, int p = *path; /* 2 kinds of lookups now, quoted or unquoted */ - quote = *p; + char quote = *p; - if (quote != '"') { /* " - this comment is hack for Aligorith's text editor's sanity */ + if (quote != '"') { quote = 0; } @@ -4988,14 +4984,14 @@ static char *rna_path_token(const char **path, char *fixedbuf, int fixedlen, int } } else { - escape = 0; + bool escape = false; /* skip the first quote */ len++; p++; while (*p && (*p != quote || escape)) { /* A pair of back-slashes represents a single back-slash, * only use a single back-slash for escaping. */ - escape = (escape == 0) && (*p == '\\'); + escape = (escape == false) && (*p == '\\'); len++; p++; } @@ -5024,13 +5020,8 @@ static char *rna_path_token(const char **path, char *fixedbuf, int fixedlen, int return NULL; } - /* try to use fixed buffer if possible */ - if (len + 1 < fixedlen) { - buf = fixedbuf; - } - else { - buf = MEM_mallocN(sizeof(char) * (len + 1), "rna_path_token"); - } + /* Try to use fixed buffer if possible. */ + char *buf = (len + 1 < fixedlen) ? fixedbuf : MEM_mallocN(sizeof(char) * (len + 1), __func__); /* copy string, taking into account escaped ] */ if (bracket) { -- cgit v1.2.3 From aef9243ebb4f3d97d4d9f0eb731250a8c6c1db28 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 10 Dec 2020 14:52:11 +1100 Subject: Cleanup: remove unnecessary vars in RNA token reading --- source/blender/makesrna/intern/rna_access.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) (limited to 'source/blender') diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index 67f88d31afd..70b4d4204df 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -4970,14 +4970,8 @@ static char *rna_path_token(const char **path, char *fixedbuf, int fixedlen, int p = *path; - /* 2 kinds of lookups now, quoted or unquoted */ - char quote = *p; - - if (quote != '"') { - quote = 0; - } - - if (quote == 0) { + /* 2 kinds of look-ups now, quoted or unquoted. */ + if (*p != '"') { while (*p && (*p != ']')) { len++; p++; @@ -4985,10 +4979,10 @@ static char *rna_path_token(const char **path, char *fixedbuf, int fixedlen, int } else { bool escape = false; - /* skip the first quote */ + /* Skip the first quote. */ len++; p++; - while (*p && (*p != quote || escape)) { + while (*p && (*p != '"' || escape)) { /* A pair of back-slashes represents a single back-slash, * only use a single back-slash for escaping. */ escape = (escape == false) && (*p == '\\'); @@ -4996,7 +4990,7 @@ static char *rna_path_token(const char **path, char *fixedbuf, int fixedlen, int p++; } - /* skip the last quoted char to get the ']' */ + /* Skip the last quoted char to get the `]`. */ len++; p++; } -- cgit v1.2.3 From 2814cdbd86389516eeea570ae12f7c2c7338d81b Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 10 Dec 2020 15:06:16 +1100 Subject: BLI_string: extract quote utility into BLI_str_escape_find_quote Duplicate logic for this exists in BLI_str_quoted_substrN, which doesn't properly support escaping. --- source/blender/blenlib/BLI_string.h | 1 + source/blender/blenlib/intern/string.c | 15 +++++++++++++++ source/blender/makesrna/intern/rna_access.c | 21 ++++++++------------- 3 files changed, 24 insertions(+), 13 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenlib/BLI_string.h b/source/blender/blenlib/BLI_string.h index 2d1f8ac9c5e..096e7818013 100644 --- a/source/blender/blenlib/BLI_string.h +++ b/source/blender/blenlib/BLI_string.h @@ -89,6 +89,7 @@ size_t BLI_str_escape(char *__restrict dst, const char *__restrict src, const si ATTR_NONNULL(); size_t BLI_str_unescape(char *__restrict dst, const char *__restrict src, const size_t src_maxncpy) ATTR_NONNULL(); +const char *BLI_str_escape_find_quote(const char *str) ATTR_NONNULL(); size_t BLI_str_format_int_grouped(char dst[16], int num) ATTR_NONNULL(); size_t BLI_str_format_uint64_grouped(char dst[16], uint64_t num) ATTR_NONNULL(); diff --git a/source/blender/blenlib/intern/string.c b/source/blender/blenlib/intern/string.c index c4b51338360..d02241230de 100644 --- a/source/blender/blenlib/intern/string.c +++ b/source/blender/blenlib/intern/string.c @@ -398,6 +398,21 @@ size_t BLI_str_unescape(char *__restrict dst, const char *__restrict src, const return len; } +/** + * Find the first un-escaped quote in the string (to find the end of the string). + */ +const char *BLI_str_escape_find_quote(const char *str) +{ + bool escape = false; + while (*str && (*str != '"' || escape)) { + /* A pair of back-slashes represents a single back-slash, + * only use a single back-slash for escaping. */ + escape = (escape == false) && (*str == '\\'); + str++; + } + return (*str == '"') ? str : NULL; +} + /** * Makes a copy of the text within the "" that appear after some text 'blahblah' * i.e. for string 'pose["apples"]' with prefix 'pose[', it should grab "apples" diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index 70b4d4204df..deedf72600a 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -4978,21 +4978,16 @@ static char *rna_path_token(const char **path, char *fixedbuf, int fixedlen, int } } else { - bool escape = false; - /* Skip the first quote. */ - len++; - p++; - while (*p && (*p != '"' || escape)) { - /* A pair of back-slashes represents a single back-slash, - * only use a single back-slash for escaping. */ - escape = (escape == false) && (*p == '\\'); - len++; - p++; + const char *p_end = BLI_str_escape_find_quote(p + 1); + if (p_end == NULL) { + /* No Matching quote. */ + return NULL; } - /* Skip the last quoted char to get the `]`. */ - len++; - p++; + p_end += 1; + + len += (p_end - p); + p = p_end; } if (*p != ']') { -- cgit v1.2.3 From 3ec7cf64bcf8b8bfa098529c784d73c41f46a348 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 10 Dec 2020 16:01:04 +1100 Subject: Fix BLI_str_quoted_substrN use with escaped strings BLI_str_quoted_substrN didn't unescape the resulting string, yet all callers were using this with animation paths which are created using BLI_str_escape(). - Fix BLI_str_quoted_substrN use with escaped strings by calling BLI_str_unescape(). Note that it's possible we want an a version of this function that keeps escape characters. This could be added if it's required. - Fix end quote detection using BLI_str_escape_find_quote checking for `\"` isn't reliable since an even number of back-slashes before a quote means it's not escaped. --- source/blender/blenlib/intern/string.c | 33 ++++++++++++++------------------- 1 file changed, 14 insertions(+), 19 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenlib/intern/string.c b/source/blender/blenlib/intern/string.c index d02241230de..dccc700c761 100644 --- a/source/blender/blenlib/intern/string.c +++ b/source/blender/blenlib/intern/string.c @@ -414,16 +414,14 @@ const char *BLI_str_escape_find_quote(const char *str) } /** - * Makes a copy of the text within the "" that appear after some text 'blahblah' - * i.e. for string 'pose["apples"]' with prefix 'pose[', it should grab "apples" + * Makes a copy of the text within the "" that appear after some text `blahblah`. + * i.e. for string `pose["apples"]` with prefix `pose[`, it will return `apples`. * - * - str: is the entire string to chop - * - prefix: is the part of the string to leave out + * \param str: is the entire string to chop. + * \param prefix: is the part of the string to step over. * - * Assume that the strings returned must be freed afterwards, and that the inputs will contain - * data we want... - * - * \return the offset and a length so as to avoid doing an allocation. + * Assume that the strings returned must be freed afterwards, + * and that the inputs will contain data we want. */ char *BLI_str_quoted_substrN(const char *__restrict str, const char *__restrict prefix) { @@ -436,18 +434,15 @@ char *BLI_str_quoted_substrN(const char *__restrict str, const char *__restrict const size_t prefix_len = strlen(prefix); start_match += prefix_len + 1; /* get the end point (i.e. where the next occurrence of " is after the starting point) */ - - end_match = start_match; - while ((end_match = strchr(end_match, '"'))) { - if (LIKELY(*(end_match - 1) != '\\')) { - break; - } - end_match++; - } - + end_match = BLI_str_escape_find_quote(start_match); if (end_match) { - /* return the slice indicated */ - return BLI_strdupn(start_match, (size_t)(end_match - start_match)); + const size_t unescaped_len = (size_t)(end_match - start_match); + char *result = MEM_mallocN(sizeof(char) * (unescaped_len + 1), __func__); + const size_t escaped_len = BLI_str_unescape(result, start_match, unescaped_len); + if (escaped_len != unescaped_len) { + result = MEM_reallocN(result, sizeof(char) * (escaped_len + 1)); + } + return result; } } return BLI_strdupn("", 0); -- cgit v1.2.3 From d97845a693c28b8d56934c1b34bdb5c346a2603b Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 10 Dec 2020 16:46:04 +1100 Subject: BLI_string: return NULL from BLI_str_quoted_substrN on failure This was returning an empty allocated string, however almost all callers checked if the return value was NULL before freeing, making for misunderstandings on the intended use of this function. BCAnimationSampler::initialize_curves for example detected the f-curves animation type to 'bone' based on a non-NULL return value which never failed. Also fixes two leaks where the the result of BLI_str_quoted_substrN wasn't freed. --- source/blender/blenlib/intern/string.c | 2 +- source/blender/editors/animation/anim_deps.c | 8 ++++--- source/blender/editors/animation/anim_filter.c | 19 +++++++-------- source/blender/editors/animation/anim_ipo_utils.c | 3 ++- .../blender/editors/animation/keyframes_general.c | 13 +++++----- source/blender/editors/animation/keyframing.c | 23 ++++++++---------- source/blender/editors/armature/pose_select.c | 4 +--- .../editors/transform/transform_convert_armature.c | 28 +++++++++++----------- source/blender/io/collada/BCAnimationCurve.cpp | 10 ++++++-- source/blender/io/collada/BCAnimationSampler.cpp | 1 + 10 files changed, 56 insertions(+), 55 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenlib/intern/string.c b/source/blender/blenlib/intern/string.c index dccc700c761..b0d87838d06 100644 --- a/source/blender/blenlib/intern/string.c +++ b/source/blender/blenlib/intern/string.c @@ -445,7 +445,7 @@ char *BLI_str_quoted_substrN(const char *__restrict str, const char *__restrict return result; } } - return BLI_strdupn("", 0); + return NULL; } /** diff --git a/source/blender/editors/animation/anim_deps.c b/source/blender/editors/animation/anim_deps.c index e552a321bca..32ce78e405e 100644 --- a/source/blender/editors/animation/anim_deps.c +++ b/source/blender/editors/animation/anim_deps.c @@ -216,11 +216,13 @@ static void animchan_sync_fcurve_scene(bAnimListElem *ale) /* get strip name, and check if this strip is selected */ char *seq_name = BLI_str_quoted_substrN(fcu->rna_path, "sequences_all["); - Sequence *seq = BKE_sequence_get_by_name(ed->seqbasep, seq_name, false); - if (seq_name) { - MEM_freeN(seq_name); + if (seq_name == NULL) { + return; } + Sequence *seq = BKE_sequence_get_by_name(ed->seqbasep, seq_name, false); + MEM_freeN(seq_name); + if (seq == NULL) { return; } diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index 2e65fff69f1..f4a487140ff 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -1063,13 +1063,12 @@ static bool skip_fcurve_selected_data(bDopeSheet *ads, FCurve *fcu, ID *owner_id /* only consider if F-Curve involves pose.bones */ if ((fcu->rna_path) && strstr(fcu->rna_path, "pose.bones")) { - bPoseChannel *pchan; - char *bone_name; /* get bone-name, and check if this bone is selected */ - bone_name = BLI_str_quoted_substrN(fcu->rna_path, "pose.bones["); - pchan = BKE_pose_channel_find_name(ob->pose, bone_name); + bPoseChannel *pchan = NULL; + char *bone_name = BLI_str_quoted_substrN(fcu->rna_path, "pose.bones["); if (bone_name) { + pchan = BKE_pose_channel_find_name(ob->pose, bone_name); MEM_freeN(bone_name); } @@ -1106,13 +1105,12 @@ static bool skip_fcurve_selected_data(bDopeSheet *ads, FCurve *fcu, ID *owner_id if ((fcu->rna_path) && strstr(fcu->rna_path, "sequences_all")) { Editing *ed = BKE_sequencer_editing_get(scene, false); Sequence *seq = NULL; - char *seq_name; if (ed) { /* get strip name, and check if this strip is selected */ - seq_name = BLI_str_quoted_substrN(fcu->rna_path, "sequences_all["); - seq = BKE_sequence_get_by_name(ed->seqbasep, seq_name, false); + char *seq_name = BLI_str_quoted_substrN(fcu->rna_path, "sequences_all["); if (seq_name) { + seq = BKE_sequence_get_by_name(ed->seqbasep, seq_name, false); MEM_freeN(seq_name); } } @@ -1130,13 +1128,12 @@ static bool skip_fcurve_selected_data(bDopeSheet *ads, FCurve *fcu, ID *owner_id /* check for selected nodes */ if ((fcu->rna_path) && strstr(fcu->rna_path, "nodes")) { - bNode *node; - char *node_name; + bNode *node = NULL; /* get strip name, and check if this strip is selected */ - node_name = BLI_str_quoted_substrN(fcu->rna_path, "nodes["); - node = nodeFindNodebyName(ntree, node_name); + char *node_name = BLI_str_quoted_substrN(fcu->rna_path, "nodes["); if (node_name) { + node = nodeFindNodebyName(ntree, node_name); MEM_freeN(node_name); } diff --git a/source/blender/editors/animation/anim_ipo_utils.c b/source/blender/editors/animation/anim_ipo_utils.c index 72103d68b05..5992545bdbe 100644 --- a/source/blender/editors/animation/anim_ipo_utils.c +++ b/source/blender/editors/animation/anim_ipo_utils.c @@ -112,7 +112,8 @@ int getname_anim_fcurve(char *name, ID *id, FCurve *fcu) char *constName = BLI_str_quoted_substrN(fcu->rna_path, "constraints["); /* assemble the string to display in the UI... */ - structname = BLI_sprintfN("%s : %s", pchanName, constName); + structname = BLI_sprintfN( + "%s : %s", pchanName ? pchanName : "", constName ? constName : ""); free_structname = 1; /* free the temp names */ diff --git a/source/blender/editors/animation/keyframes_general.c b/source/blender/editors/animation/keyframes_general.c index 08b02020f76..6ed9803dbd3 100644 --- a/source/blender/editors/animation/keyframes_general.c +++ b/source/blender/editors/animation/keyframes_general.c @@ -767,16 +767,15 @@ short copy_animedit_keys(bAnimContext *ac, ListBase *anim_data) * Storing the relevant information here helps avoiding crashes if we undo-repaste. */ if ((aci->id_type == ID_OB) && (((Object *)aci->id)->type == OB_ARMATURE) && aci->rna_path) { Object *ob = (Object *)aci->id; - bPoseChannel *pchan; - char *bone_name; - bone_name = BLI_str_quoted_substrN(aci->rna_path, "pose.bones["); - pchan = BKE_pose_channel_find_name(ob->pose, bone_name); - if (pchan) { - aci->is_bone = true; - } + char *bone_name = BLI_str_quoted_substrN(aci->rna_path, "pose.bones["); if (bone_name) { + bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, bone_name); MEM_freeN(bone_name); + + if (pchan) { + aci->is_bone = true; + } } } diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c index 09c33c48170..e8146ca960a 100644 --- a/source/blender/editors/animation/keyframing.c +++ b/source/blender/editors/animation/keyframing.c @@ -2236,20 +2236,18 @@ static int clear_anim_v3d_exec(bContext *C, wmOperator *UNUSED(op)) /* in pose mode, only delete the F-Curve if it belongs to a selected bone */ if (ob->mode & OB_MODE_POSE) { if ((fcu->rna_path) && strstr(fcu->rna_path, "pose.bones[")) { - bPoseChannel *pchan; - char *bone_name; /* get bone-name, and check if this bone is selected */ - bone_name = BLI_str_quoted_substrN(fcu->rna_path, "pose.bones["); - pchan = BKE_pose_channel_find_name(ob->pose, bone_name); + char *bone_name = BLI_str_quoted_substrN(fcu->rna_path, "pose.bones["); if (bone_name) { + bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, bone_name); MEM_freeN(bone_name); - } - /* delete if bone is selected*/ - if ((pchan) && (pchan->bone)) { - if (pchan->bone->flag & BONE_SELECTED) { - can_delete = true; + /* delete if bone is selected*/ + if ((pchan) && (pchan->bone)) { + if (pchan->bone->flag & BONE_SELECTED) { + can_delete = true; + } } } } @@ -2342,13 +2340,12 @@ static int delete_key_v3d_exec(bContext *C, wmOperator *op) * In object mode, we're dealing with the entire object. */ if ((ob->mode & OB_MODE_POSE) && strstr(fcu->rna_path, "pose.bones[\"")) { - bPoseChannel *pchan; - char *bone_name; + bPoseChannel *pchan = NULL; /* get bone-name, and check if this bone is selected */ - bone_name = BLI_str_quoted_substrN(fcu->rna_path, "pose.bones["); - pchan = BKE_pose_channel_find_name(ob->pose, bone_name); + char *bone_name = BLI_str_quoted_substrN(fcu->rna_path, "pose.bones["); if (bone_name) { + pchan = BKE_pose_channel_find_name(ob->pose, bone_name); MEM_freeN(bone_name); } diff --git a/source/blender/editors/armature/pose_select.c b/source/blender/editors/armature/pose_select.c index 731d0d10e0b..6a03207b3b0 100644 --- a/source/blender/editors/armature/pose_select.c +++ b/source/blender/editors/armature/pose_select.c @@ -1090,6 +1090,7 @@ static bool pose_select_same_keyingset(bContext *C, ReportList *reports, bool ex if (boneName) { bPoseChannel *pchan = BKE_pose_channel_find_name(pose, boneName); + MEM_freeN(boneName); if (pchan) { /* select if bone is visible and can be affected */ @@ -1098,9 +1099,6 @@ static bool pose_select_same_keyingset(bContext *C, ReportList *reports, bool ex changed = true; } } - - /* free temp memory */ - MEM_freeN(boneName); } } } diff --git a/source/blender/editors/transform/transform_convert_armature.c b/source/blender/editors/transform/transform_convert_armature.c index a7301161570..e9b2273b343 100644 --- a/source/blender/editors/transform/transform_convert_armature.c +++ b/source/blender/editors/transform/transform_convert_armature.c @@ -164,21 +164,21 @@ static void autokeyframe_pose( /* only if bone name matches too... * NOTE: this will do constraints too, but those are ok to do here too? */ - if (pchanName && STREQ(pchanName, pchan->name)) { - insert_keyframe(bmain, - reports, - id, - act, - ((fcu->grp) ? (fcu->grp->name) : (NULL)), - fcu->rna_path, - fcu->array_index, - &anim_eval_context, - ts->keyframe_type, - &nla_cache, - flag); - } - if (pchanName) { + if (STREQ(pchanName, pchan->name)) { + insert_keyframe(bmain, + reports, + id, + act, + ((fcu->grp) ? (fcu->grp->name) : (NULL)), + fcu->rna_path, + fcu->array_index, + &anim_eval_context, + ts->keyframe_type, + &nla_cache, + flag); + } + MEM_freeN(pchanName); } } diff --git a/source/blender/io/collada/BCAnimationCurve.cpp b/source/blender/io/collada/BCAnimationCurve.cpp index 33eaf3376cd..5065accf554 100644 --- a/source/blender/io/collada/BCAnimationCurve.cpp +++ b/source/blender/io/collada/BCAnimationCurve.cpp @@ -173,8 +173,14 @@ std::string BCAnimationCurve::get_animation_name(Object *ob) const name = ""; } else { - const char *boneName = BLI_str_quoted_substrN(fcurve->rna_path, "pose.bones["); - name = (boneName) ? id_name(ob) + "_" + std::string(boneName) : ""; + char *boneName = BLI_str_quoted_substrN(fcurve->rna_path, "pose.bones["); + if (boneName) { + name = id_name(ob) + "_" + std::string(boneName); + MEM_freeN(boneName); + } + else { + name = ""; + } } } break; diff --git a/source/blender/io/collada/BCAnimationSampler.cpp b/source/blender/io/collada/BCAnimationSampler.cpp index abc770ceef5..a6ee0b8bee6 100644 --- a/source/blender/io/collada/BCAnimationSampler.cpp +++ b/source/blender/io/collada/BCAnimationSampler.cpp @@ -448,6 +448,7 @@ void BCAnimationSampler::initialize_curves(BCAnimationCurveMap &curves, Object * char *boneName = BLI_str_quoted_substrN(fcu->rna_path, "pose.bones["); if (boneName) { object_type = BC_ANIMATION_TYPE_BONE; + MEM_freeN(boneName); } } -- cgit v1.2.3 From 2fbf9cb55182edd4b04c5e36651627bc3c0448ba Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 10 Dec 2020 17:10:19 +1100 Subject: Cleanup: remove unused function bc_find_bonename_in_path --- source/blender/io/collada/collada_utils.cpp | 11 ----------- source/blender/io/collada/collada_utils.h | 2 -- 2 files changed, 13 deletions(-) (limited to 'source/blender') diff --git a/source/blender/io/collada/collada_utils.cpp b/source/blender/io/collada/collada_utils.cpp index 25c10c717e2..ad1cc1035fb 100644 --- a/source/blender/io/collada/collada_utils.cpp +++ b/source/blender/io/collada/collada_utils.cpp @@ -1176,17 +1176,6 @@ static std::string bc_get_uvlayer_name(Mesh *me, int layer) return ""; } -std::string bc_find_bonename_in_path(std::string path, std::string probe) -{ - std::string result; - char *boneName = BLI_str_quoted_substrN(path.c_str(), probe.c_str()); - if (boneName) { - result = std::string(boneName); - MEM_freeN(boneName); - } - return result; -} - static bNodeTree *prepare_material_nodetree(Material *ma) { if (ma->nodetree == nullptr) { diff --git a/source/blender/io/collada/collada_utils.h b/source/blender/io/collada/collada_utils.h index fa65d398954..d0a5d37d6d2 100644 --- a/source/blender/io/collada/collada_utils.h +++ b/source/blender/io/collada/collada_utils.h @@ -146,8 +146,6 @@ extern void bc_bubble_sort_by_Object_name(LinkNode *export_set); extern bool bc_is_root_bone(Bone *aBone, bool deform_bones_only); extern int bc_get_active_UVLayer(Object *ob); -std::string bc_find_bonename_in_path(std::string path, std::string probe); - inline std::string bc_string_after(const std::string &s, const std::string probe) { size_t i = s.rfind(probe); -- cgit v1.2.3 From 83f5a0b972abf2569ca338a268199ab989f33bc7 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 10 Dec 2020 17:54:33 +1100 Subject: Fix missing string escaping in RNA_path_append This was escaping the '[' character, which isn't needed for quoted text. --- source/blender/makesrna/intern/rna_access.c | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) (limited to 'source/blender') diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index deedf72600a..6586cfc7969 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -31,6 +31,7 @@ #include "DNA_scene_types.h" #include "DNA_windowmanager_types.h" +#include "BLI_alloca.h" #include "BLI_blenlib.h" #include "BLI_dynstr.h" #include "BLI_ghash.h" @@ -4960,7 +4961,7 @@ static char *rna_path_token(const char **path, char *fixedbuf, int fixedlen, int int len = 0; if (bracket) { - /* get data between [], check escaping ] with \] */ + /* get data between [], check escaping quotes and back-slashes with #BLI_str_unescape. */ if (**path == '[') { (*path)++; } @@ -5527,8 +5528,7 @@ char *RNA_path_append( const char *path, PointerRNA *UNUSED(ptr), PropertyRNA *prop, int intkey, const char *strkey) { DynStr *dynstr; - const char *s; - char appendstr[128], *result; + char *result; dynstr = BLI_dynstr_new(); @@ -5547,22 +5547,15 @@ char *RNA_path_append( BLI_dynstr_append(dynstr, "["); if (strkey) { + const int strkey_esc_max_size = (strlen(strkey) * 2) + 1; + char *strkey_esc = BLI_array_alloca(strkey_esc, strkey_esc_max_size); + BLI_str_escape(strkey_esc, strkey, strkey_esc_max_size); BLI_dynstr_append(dynstr, "\""); - for (s = strkey; *s; s++) { - if (*s == '[') { - appendstr[0] = '\\'; - appendstr[1] = *s; - appendstr[2] = 0; - } - else { - appendstr[0] = *s; - appendstr[1] = 0; - } - BLI_dynstr_append(dynstr, appendstr); - } + BLI_dynstr_append(dynstr, strkey_esc); BLI_dynstr_append(dynstr, "\""); } else { + char appendstr[128]; BLI_snprintf(appendstr, sizeof(appendstr), "%d", intkey); BLI_dynstr_append(dynstr, appendstr); } -- cgit v1.2.3 From e795ba1529a28ec276a5178fda2025e5ec071bbf Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Thu, 10 Dec 2020 10:23:54 +0100 Subject: Geometry Nodes: fix recursive instance transforms Previously, the transformation of recursive instances did not work as on would expect. Second-level instances would detach from first-level instances when the object was moved. --- source/blender/blenkernel/intern/object_dupli.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/intern/object_dupli.c b/source/blender/blenkernel/intern/object_dupli.c index 9a8c560f116..d5434710e23 100644 --- a/source/blender/blenkernel/intern/object_dupli.c +++ b/source/blender/blenkernel/intern/object_dupli.c @@ -829,13 +829,18 @@ static void make_duplis_instances_component(const DupliContext *ctx) size_to_mat4(scale_matrix, scales[i]); float rotation_matrix[4][4]; eul_to_mat4(rotation_matrix, rotations[i]); - float matrix[4][4]; - mul_m4_m4m4(matrix, rotation_matrix, scale_matrix); - copy_v3_v3(matrix[3], positions[i]); - mul_m4_m4_pre(matrix, ctx->object->obmat); + float instance_offset_matrix[4][4]; + mul_m4_m4m4(instance_offset_matrix, rotation_matrix, scale_matrix); + copy_v3_v3(instance_offset_matrix[3], positions[i]); + float matrix[4][4]; + mul_m4_m4m4(matrix, ctx->object->obmat, instance_offset_matrix); make_dupli(ctx, object, matrix, i); - make_recursive_duplis(ctx, object, matrix, i); + + float space_matrix[4][4]; + mul_m4_m4m4(space_matrix, instance_offset_matrix, object->imat); + mul_m4_m4_pre(space_matrix, ctx->object->obmat); + make_recursive_duplis(ctx, object, space_matrix, i); } } -- cgit v1.2.3 From 2b9eb5eee58acb81d8ae7e64a5a95526623d64d7 Mon Sep 17 00:00:00 2001 From: Philipp Oeser Date: Tue, 8 Dec 2020 16:10:08 +0100 Subject: Fix T83361: UV Editor does not draw pinned selected UVs as pinned Caused by rB4212b6528af. outlineColor is computed by the vertex shader, so not a uniform. So outlineColor was undefined. note: it was still possible to run into the situation that a selected UV is drawn ontop of a selected pinned UV [you had to disable sticky selection for this], now also make sure selected-pinned are drawn topmost, then selected, then unselected UVs. Maniphest Tasks: T83361 Differential Revision: https://developer.blender.org/D9786 --- source/blender/draw/engines/overlay/shaders/edit_uv_verts_frag.glsl | 3 +-- source/blender/draw/engines/overlay/shaders/edit_uv_verts_vert.glsl | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'source/blender') diff --git a/source/blender/draw/engines/overlay/shaders/edit_uv_verts_frag.glsl b/source/blender/draw/engines/overlay/shaders/edit_uv_verts_frag.glsl index 1d936e4e072..ea2715a3c32 100644 --- a/source/blender/draw/engines/overlay/shaders/edit_uv_verts_frag.glsl +++ b/source/blender/draw/engines/overlay/shaders/edit_uv_verts_frag.glsl @@ -1,6 +1,5 @@ -uniform vec4 outlineColor; - +in vec4 outlineColor; in vec4 radii; in vec4 fillColor; out vec4 fragColor; diff --git a/source/blender/draw/engines/overlay/shaders/edit_uv_verts_vert.glsl b/source/blender/draw/engines/overlay/shaders/edit_uv_verts_vert.glsl index 9e9df82a77d..cb70a3b433c 100644 --- a/source/blender/draw/engines/overlay/shaders/edit_uv_verts_vert.glsl +++ b/source/blender/draw/engines/overlay/shaders/edit_uv_verts_vert.glsl @@ -26,7 +26,7 @@ void main() /* Move selected vertices to the top * Vertices are between 0.0 and 0.2, Edges between 0.2 and 0.4 * actual pixels are at 0.75, 1.0 is used for the background. */ - float depth = is_selected ? 0.05 : 0.15; + float depth = is_selected ? (is_pinned ? 0.05 : 0.10) : 0.15; gl_Position = vec4(point_world_to_ndc(world_pos).xy, depth, 1.0); gl_PointSize = pointSize; -- cgit v1.2.3 From efb741b280f20cb189e23f2b1335358a95ab609c Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Thu, 10 Dec 2020 14:35:02 +0100 Subject: Geometry Nodes: rename modifyPointCloud to modifyGeometrySet Since the initial merge of the geometry nodes project, the modifyPointCloud function already was already modifying a geometry set. The function wasn't renamed back then, because then the merge would have touched many more files. Ref T83357. --- source/blender/blenkernel/BKE_modifier.h | 14 +++++++++++--- source/blender/blenkernel/intern/object.c | 2 +- source/blender/blenkernel/intern/pointcloud.cc | 4 ++-- source/blender/modifiers/intern/MOD_armature.c | 2 +- source/blender/modifiers/intern/MOD_array.c | 2 +- source/blender/modifiers/intern/MOD_bevel.c | 2 +- source/blender/modifiers/intern/MOD_boolean.c | 2 +- source/blender/modifiers/intern/MOD_build.c | 2 +- source/blender/modifiers/intern/MOD_cast.c | 2 +- source/blender/modifiers/intern/MOD_cloth.c | 2 +- source/blender/modifiers/intern/MOD_collision.c | 2 +- source/blender/modifiers/intern/MOD_correctivesmooth.c | 2 +- source/blender/modifiers/intern/MOD_curve.c | 2 +- source/blender/modifiers/intern/MOD_datatransfer.c | 2 +- source/blender/modifiers/intern/MOD_decimate.c | 2 +- source/blender/modifiers/intern/MOD_displace.c | 2 +- source/blender/modifiers/intern/MOD_dynamicpaint.c | 2 +- source/blender/modifiers/intern/MOD_edgesplit.c | 2 +- source/blender/modifiers/intern/MOD_explode.c | 2 +- source/blender/modifiers/intern/MOD_fluid.c | 2 +- source/blender/modifiers/intern/MOD_hook.c | 2 +- source/blender/modifiers/intern/MOD_laplaciandeform.c | 2 +- source/blender/modifiers/intern/MOD_laplaciansmooth.c | 2 +- source/blender/modifiers/intern/MOD_lattice.c | 2 +- source/blender/modifiers/intern/MOD_mask.cc | 2 +- source/blender/modifiers/intern/MOD_mesh_to_volume.cc | 2 +- source/blender/modifiers/intern/MOD_meshcache.c | 2 +- source/blender/modifiers/intern/MOD_meshdeform.c | 2 +- source/blender/modifiers/intern/MOD_meshsequencecache.c | 2 +- source/blender/modifiers/intern/MOD_mirror.c | 2 +- source/blender/modifiers/intern/MOD_multires.c | 2 +- source/blender/modifiers/intern/MOD_nodes.cc | 8 ++++---- source/blender/modifiers/intern/MOD_none.c | 2 +- source/blender/modifiers/intern/MOD_normal_edit.c | 2 +- source/blender/modifiers/intern/MOD_ocean.c | 2 +- source/blender/modifiers/intern/MOD_particleinstance.c | 2 +- source/blender/modifiers/intern/MOD_particlesystem.c | 2 +- source/blender/modifiers/intern/MOD_remesh.c | 2 +- source/blender/modifiers/intern/MOD_screw.c | 2 +- source/blender/modifiers/intern/MOD_shapekey.c | 2 +- source/blender/modifiers/intern/MOD_shrinkwrap.c | 2 +- source/blender/modifiers/intern/MOD_simpledeform.c | 2 +- source/blender/modifiers/intern/MOD_skin.c | 2 +- source/blender/modifiers/intern/MOD_smooth.c | 2 +- source/blender/modifiers/intern/MOD_softbody.c | 2 +- source/blender/modifiers/intern/MOD_solidify.c | 2 +- source/blender/modifiers/intern/MOD_subsurf.c | 2 +- source/blender/modifiers/intern/MOD_surface.c | 2 +- source/blender/modifiers/intern/MOD_surfacedeform.c | 2 +- source/blender/modifiers/intern/MOD_triangulate.c | 2 +- source/blender/modifiers/intern/MOD_uvproject.c | 2 +- source/blender/modifiers/intern/MOD_uvwarp.c | 2 +- source/blender/modifiers/intern/MOD_volume_displace.cc | 2 +- source/blender/modifiers/intern/MOD_volume_to_mesh.cc | 2 +- source/blender/modifiers/intern/MOD_warp.c | 2 +- source/blender/modifiers/intern/MOD_wave.c | 2 +- source/blender/modifiers/intern/MOD_weighted_normal.c | 2 +- source/blender/modifiers/intern/MOD_weightvgedit.c | 2 +- source/blender/modifiers/intern/MOD_weightvgmix.c | 2 +- source/blender/modifiers/intern/MOD_weightvgproximity.c | 2 +- source/blender/modifiers/intern/MOD_weld.c | 2 +- source/blender/modifiers/intern/MOD_wireframe.c | 2 +- 62 files changed, 76 insertions(+), 68 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h index 73e33124b43..38b449cd92d 100644 --- a/source/blender/blenkernel/BKE_modifier.h +++ b/source/blender/blenkernel/BKE_modifier.h @@ -244,12 +244,20 @@ typedef struct ModifierTypeInfo { struct Mesh *(*modifyMesh)(struct ModifierData *md, const struct ModifierEvalContext *ctx, struct Mesh *mesh); + struct Hair *(*modifyHair)(struct ModifierData *md, const struct ModifierEvalContext *ctx, struct Hair *hair); - void (*modifyPointCloud)(struct ModifierData *md, - const struct ModifierEvalContext *ctx, - struct GeometrySet *geometry_set); + + /** + * The modifier has to change the geometry set in-place. The geometry set can contain zero or + * more geometry components. This callback can be used by modifiers that don't work on any + * specific type of geometry (e.g. mesh). + */ + void (*modifyGeometrySet)(struct ModifierData *md, + const struct ModifierEvalContext *ctx, + struct GeometrySet *geometry_set); + struct Volume *(*modifyVolume)(struct ModifierData *md, const struct ModifierEvalContext *ctx, struct Volume *volume); diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index d747da2213e..88a604a7b62 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -1325,7 +1325,7 @@ bool BKE_object_support_modifier_type_check(const Object *ob, int modifier_type) return (mti->modifyHair != NULL) || (mti->flags & eModifierTypeFlag_AcceptsVertexCosOnly); } if (ob->type == OB_POINTCLOUD) { - return (mti->modifyPointCloud != NULL); + return (mti->modifyGeometrySet != NULL); } if (ob->type == OB_VOLUME) { return (mti->modifyVolume != NULL); diff --git a/source/blender/blenkernel/intern/pointcloud.cc b/source/blender/blenkernel/intern/pointcloud.cc index 5f6685817b9..b4a9ad73048 100644 --- a/source/blender/blenkernel/intern/pointcloud.cc +++ b/source/blender/blenkernel/intern/pointcloud.cc @@ -365,8 +365,8 @@ static void pointcloud_evaluate_modifiers(struct Depsgraph *depsgraph, continue; } - if (mti->modifyPointCloud) { - mti->modifyPointCloud(md, &mectx, &geometry_set); + if (mti->modifyGeometrySet) { + mti->modifyGeometrySet(md, &mectx, &geometry_set); } } } diff --git a/source/blender/modifiers/intern/MOD_armature.c b/source/blender/modifiers/intern/MOD_armature.c index 38fb19e3233..6769f14f88f 100644 --- a/source/blender/modifiers/intern/MOD_armature.c +++ b/source/blender/modifiers/intern/MOD_armature.c @@ -295,7 +295,7 @@ ModifierTypeInfo modifierType_Armature = { /* deformMatricesEM */ deformMatricesEM, /* modifyMesh */ NULL, /* modifyHair */ NULL, - /* modifyPointCloud */ NULL, + /* modifyGeometrySet */ NULL, /* modifyVolume */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_array.c b/source/blender/modifiers/intern/MOD_array.c index da1754b8ebd..412d6b87d82 100644 --- a/source/blender/modifiers/intern/MOD_array.c +++ b/source/blender/modifiers/intern/MOD_array.c @@ -1018,7 +1018,7 @@ ModifierTypeInfo modifierType_Array = { /* deformMatricesEM */ NULL, /* modifyMesh */ modifyMesh, /* modifyHair */ NULL, - /* modifyPointCloud */ NULL, + /* modifyGeometrySet */ NULL, /* modifyVolume */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_bevel.c b/source/blender/modifiers/intern/MOD_bevel.c index 04ddac338e5..a94411d897e 100644 --- a/source/blender/modifiers/intern/MOD_bevel.c +++ b/source/blender/modifiers/intern/MOD_bevel.c @@ -447,7 +447,7 @@ ModifierTypeInfo modifierType_Bevel = { /* deformMatricesEM */ NULL, /* modifyMesh */ modifyMesh, /* modifyHair */ NULL, - /* modifyPointCloud */ NULL, + /* modifyGeometrySet */ NULL, /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_boolean.c b/source/blender/modifiers/intern/MOD_boolean.c index 0513d3af13a..e290fd9dab7 100644 --- a/source/blender/modifiers/intern/MOD_boolean.c +++ b/source/blender/modifiers/intern/MOD_boolean.c @@ -819,7 +819,7 @@ ModifierTypeInfo modifierType_Boolean = { /* deformMatricesEM */ NULL, /* modifyMesh */ modifyMesh, /* modifyHair */ NULL, - /* modifyPointCloud */ NULL, + /* modifyGeometrySet */ NULL, /* modifyVolume */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_build.c b/source/blender/modifiers/intern/MOD_build.c index 96ed0a5d069..0b1c661baed 100644 --- a/source/blender/modifiers/intern/MOD_build.c +++ b/source/blender/modifiers/intern/MOD_build.c @@ -346,7 +346,7 @@ ModifierTypeInfo modifierType_Build = { /* deformMatricesEM */ NULL, /* modifyMesh */ modifyMesh, /* modifyHair */ NULL, - /* modifyPointCloud */ NULL, + /* modifyGeometrySet */ NULL, /* modifyVolume */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_cast.c b/source/blender/modifiers/intern/MOD_cast.c index 06bd9ada0fb..f905a38ae12 100644 --- a/source/blender/modifiers/intern/MOD_cast.c +++ b/source/blender/modifiers/intern/MOD_cast.c @@ -590,7 +590,7 @@ ModifierTypeInfo modifierType_Cast = { /* deformMatricesEM */ NULL, /* modifyMesh */ NULL, /* modifyHair */ NULL, - /* modifyPointCloud */ NULL, + /* modifyGeometrySet */ NULL, /* modifyVolume */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_cloth.c b/source/blender/modifiers/intern/MOD_cloth.c index 8f876213cd6..4e15149083b 100644 --- a/source/blender/modifiers/intern/MOD_cloth.c +++ b/source/blender/modifiers/intern/MOD_cloth.c @@ -309,7 +309,7 @@ ModifierTypeInfo modifierType_Cloth = { /* deformMatricesEM */ NULL, /* modifyMesh */ NULL, /* modifyHair */ NULL, - /* modifyPointCloud */ NULL, + /* modifyGeometrySet */ NULL, /* modifyVolume */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_collision.c b/source/blender/modifiers/intern/MOD_collision.c index faba08f9613..7db0706c706 100644 --- a/source/blender/modifiers/intern/MOD_collision.c +++ b/source/blender/modifiers/intern/MOD_collision.c @@ -309,7 +309,7 @@ ModifierTypeInfo modifierType_Collision = { /* deformMatricesEM */ NULL, /* modifyMesh */ NULL, /* modifyHair */ NULL, - /* modifyPointCloud */ NULL, + /* modifyGeometrySet */ NULL, /* modifyVolume */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_correctivesmooth.c b/source/blender/modifiers/intern/MOD_correctivesmooth.c index 5884ec0aa17..15c4e8af6ce 100644 --- a/source/blender/modifiers/intern/MOD_correctivesmooth.c +++ b/source/blender/modifiers/intern/MOD_correctivesmooth.c @@ -851,7 +851,7 @@ ModifierTypeInfo modifierType_CorrectiveSmooth = { /* deformMatricesEM */ NULL, /* modifyMesh */ NULL, /* modifyHair */ NULL, - /* modifyPointCloud */ NULL, + /* modifyGeometrySet */ NULL, /* modifyVolume */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_curve.c b/source/blender/modifiers/intern/MOD_curve.c index bed53cb0f51..d5d53edfd54 100644 --- a/source/blender/modifiers/intern/MOD_curve.c +++ b/source/blender/modifiers/intern/MOD_curve.c @@ -235,7 +235,7 @@ ModifierTypeInfo modifierType_Curve = { /* deformMatricesEM */ NULL, /* modifyMesh */ NULL, /* modifyHair */ NULL, - /* modifyPointCloud */ NULL, + /* modifyGeometrySet */ NULL, /* modifyVolume */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_datatransfer.c b/source/blender/modifiers/intern/MOD_datatransfer.c index d4c941d144d..8b299a82f95 100644 --- a/source/blender/modifiers/intern/MOD_datatransfer.c +++ b/source/blender/modifiers/intern/MOD_datatransfer.c @@ -494,7 +494,7 @@ ModifierTypeInfo modifierType_DataTransfer = { /* deformMatricesEM */ NULL, /* modifyMesh */ modifyMesh, /* modifyHair */ NULL, - /* modifyPointCloud */ NULL, + /* modifyGeometrySet */ NULL, /* modifyVolume */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_decimate.c b/source/blender/modifiers/intern/MOD_decimate.c index 10ed4f8d80b..b28b8fd39fc 100644 --- a/source/blender/modifiers/intern/MOD_decimate.c +++ b/source/blender/modifiers/intern/MOD_decimate.c @@ -299,7 +299,7 @@ ModifierTypeInfo modifierType_Decimate = { /* deformMatricesEM */ NULL, /* modifyMesh */ modifyMesh, /* modifyHair */ NULL, - /* modifyPointCloud */ NULL, + /* modifyGeometrySet */ NULL, /* modifyVolume */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_displace.c b/source/blender/modifiers/intern/MOD_displace.c index d432559fcfa..abe78943508 100644 --- a/source/blender/modifiers/intern/MOD_displace.c +++ b/source/blender/modifiers/intern/MOD_displace.c @@ -506,7 +506,7 @@ ModifierTypeInfo modifierType_Displace = { /* deformMatricesEM */ NULL, /* modifyMesh */ NULL, /* modifyHair */ NULL, - /* modifyPointCloud */ NULL, + /* modifyGeometrySet */ NULL, /* modifyVolume */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_dynamicpaint.c b/source/blender/modifiers/intern/MOD_dynamicpaint.c index b69179f464d..7f57183ff13 100644 --- a/source/blender/modifiers/intern/MOD_dynamicpaint.c +++ b/source/blender/modifiers/intern/MOD_dynamicpaint.c @@ -220,7 +220,7 @@ ModifierTypeInfo modifierType_DynamicPaint = { /* deformMatricesEM */ NULL, /* modifyMesh */ modifyMesh, /* modifyHair */ NULL, - /* modifyPointCloud */ NULL, + /* modifyGeometrySet */ NULL, /* modifyVolume */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_edgesplit.c b/source/blender/modifiers/intern/MOD_edgesplit.c index 30c38623f68..e02befd7efa 100644 --- a/source/blender/modifiers/intern/MOD_edgesplit.c +++ b/source/blender/modifiers/intern/MOD_edgesplit.c @@ -186,7 +186,7 @@ ModifierTypeInfo modifierType_EdgeSplit = { /* deformMatricesEM */ NULL, /* modifyMesh */ modifyMesh, /* modifyHair */ NULL, - /* modifyPointCloud */ NULL, + /* modifyGeometrySet */ NULL, /* modifyVolume */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_explode.c b/source/blender/modifiers/intern/MOD_explode.c index d5e065ad321..c12019a325e 100644 --- a/source/blender/modifiers/intern/MOD_explode.c +++ b/source/blender/modifiers/intern/MOD_explode.c @@ -1254,7 +1254,7 @@ ModifierTypeInfo modifierType_Explode = { /* deformMatricesEM */ NULL, /* modifyMesh */ modifyMesh, /* modifyHair */ NULL, - /* modifyPointCloud */ NULL, + /* modifyGeometrySet */ NULL, /* modifyVolume */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_fluid.c b/source/blender/modifiers/intern/MOD_fluid.c index 6dc4fe79f88..8a8d6f2305f 100644 --- a/source/blender/modifiers/intern/MOD_fluid.c +++ b/source/blender/modifiers/intern/MOD_fluid.c @@ -238,7 +238,7 @@ ModifierTypeInfo modifierType_Fluid = { /* deformMatricesEM */ NULL, /* modifyMesh */ modifyMesh, /* modifyHair */ NULL, - /* modifyPointCloud */ NULL, + /* modifyGeometrySet */ NULL, /* modifyVolume */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_hook.c b/source/blender/modifiers/intern/MOD_hook.c index e0c362171f2..2fa05a319d5 100644 --- a/source/blender/modifiers/intern/MOD_hook.c +++ b/source/blender/modifiers/intern/MOD_hook.c @@ -573,7 +573,7 @@ ModifierTypeInfo modifierType_Hook = { /* deformMatricesEM */ NULL, /* modifyMesh */ NULL, /* modifyHair */ NULL, - /* modifyPointCloud */ NULL, + /* modifyGeometrySet */ NULL, /* modifyVolume */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_laplaciandeform.c b/source/blender/modifiers/intern/MOD_laplaciandeform.c index a484b4d8147..bda0f9ba5a4 100644 --- a/source/blender/modifiers/intern/MOD_laplaciandeform.c +++ b/source/blender/modifiers/intern/MOD_laplaciandeform.c @@ -888,7 +888,7 @@ ModifierTypeInfo modifierType_LaplacianDeform = { /* deformMatricesEM */ NULL, /* modifyMesh */ NULL, /* modifyHair */ NULL, - /* modifyPointCloud */ NULL, + /* modifyGeometrySet */ NULL, /* modifyVolume */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_laplaciansmooth.c b/source/blender/modifiers/intern/MOD_laplaciansmooth.c index d51f95bd18d..fc527304e76 100644 --- a/source/blender/modifiers/intern/MOD_laplaciansmooth.c +++ b/source/blender/modifiers/intern/MOD_laplaciansmooth.c @@ -634,7 +634,7 @@ ModifierTypeInfo modifierType_LaplacianSmooth = { /* deformMatricesEM */ NULL, /* modifyMesh */ NULL, /* modifyHair */ NULL, - /* modifyPointCloud */ NULL, + /* modifyGeometrySet */ NULL, /* modifyVolume */ NULL, /* initData */ init_data, diff --git a/source/blender/modifiers/intern/MOD_lattice.c b/source/blender/modifiers/intern/MOD_lattice.c index 5aadc171394..e3c42e39dda 100644 --- a/source/blender/modifiers/intern/MOD_lattice.c +++ b/source/blender/modifiers/intern/MOD_lattice.c @@ -192,7 +192,7 @@ ModifierTypeInfo modifierType_Lattice = { /* deformMatricesEM */ NULL, /* modifyMesh */ NULL, /* modifyHair */ NULL, - /* modifyPointCloud */ NULL, + /* modifyGeometrySet */ NULL, /* modifyVolume */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_mask.cc b/source/blender/modifiers/intern/MOD_mask.cc index 92ee5a84df9..191d39d9fce 100644 --- a/source/blender/modifiers/intern/MOD_mask.cc +++ b/source/blender/modifiers/intern/MOD_mask.cc @@ -462,7 +462,7 @@ ModifierTypeInfo modifierType_Mask = { /* deformMatricesEM */ nullptr, /* modifyMesh */ modifyMesh, /* modifyHair */ nullptr, - /* modifyPointCloud */ nullptr, + /* modifyGeometrySet */ nullptr, /* modifyVolume */ nullptr, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_mesh_to_volume.cc b/source/blender/modifiers/intern/MOD_mesh_to_volume.cc index e137a59e10f..cc007651733 100644 --- a/source/blender/modifiers/intern/MOD_mesh_to_volume.cc +++ b/source/blender/modifiers/intern/MOD_mesh_to_volume.cc @@ -295,7 +295,7 @@ ModifierTypeInfo modifierType_MeshToVolume = { /* deformMatricesEM */ nullptr, /* modifyMesh */ nullptr, /* modifyHair */ nullptr, - /* modifyPointCloud */ nullptr, + /* modifyGeometrySet */ nullptr, /* modifyVolume */ modifyVolume, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_meshcache.c b/source/blender/modifiers/intern/MOD_meshcache.c index b808d738fe8..6d2e0f242d7 100644 --- a/source/blender/modifiers/intern/MOD_meshcache.c +++ b/source/blender/modifiers/intern/MOD_meshcache.c @@ -388,7 +388,7 @@ ModifierTypeInfo modifierType_MeshCache = { /* deformMatricesEM */ NULL, /* modifyMesh */ NULL, /* modifyHair */ NULL, - /* modifyPointCloud */ NULL, + /* modifyGeometrySet */ NULL, /* modifyVolume */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_meshdeform.c b/source/blender/modifiers/intern/MOD_meshdeform.c index 0e530312238..4bd306e7679 100644 --- a/source/blender/modifiers/intern/MOD_meshdeform.c +++ b/source/blender/modifiers/intern/MOD_meshdeform.c @@ -646,7 +646,7 @@ ModifierTypeInfo modifierType_MeshDeform = { /* deformMatricesEM */ NULL, /* modifyMesh */ NULL, /* modifyHair */ NULL, - /* modifyPointCloud */ NULL, + /* modifyGeometrySet */ NULL, /* modifyVolume */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_meshsequencecache.c b/source/blender/modifiers/intern/MOD_meshsequencecache.c index 73106b2e816..2c01857adb1 100644 --- a/source/blender/modifiers/intern/MOD_meshsequencecache.c +++ b/source/blender/modifiers/intern/MOD_meshsequencecache.c @@ -270,7 +270,7 @@ ModifierTypeInfo modifierType_MeshSequenceCache = { /* deformMatricesEM */ NULL, /* modifyMesh */ modifyMesh, /* modifyHair */ NULL, - /* modifyPointCloud */ NULL, + /* modifyGeometrySet */ NULL, /* modifyVolume */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_mirror.c b/source/blender/modifiers/intern/MOD_mirror.c index 9346f601981..7f34c6581ad 100644 --- a/source/blender/modifiers/intern/MOD_mirror.c +++ b/source/blender/modifiers/intern/MOD_mirror.c @@ -234,7 +234,7 @@ ModifierTypeInfo modifierType_Mirror = { /* deformMatricesEM */ NULL, /* modifyMesh */ modifyMesh, /* modifyHair */ NULL, - /* modifyPointCloud */ NULL, + /* modifyGeometrySet */ NULL, /* modifyVolume */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_multires.c b/source/blender/modifiers/intern/MOD_multires.c index 9f99e036601..1182c8db093 100644 --- a/source/blender/modifiers/intern/MOD_multires.c +++ b/source/blender/modifiers/intern/MOD_multires.c @@ -519,7 +519,7 @@ ModifierTypeInfo modifierType_Multires = { /* deformMatricesEM */ NULL, /* modifyMesh */ modifyMesh, /* modifyHair */ NULL, - /* modifyPointCloud */ NULL, + /* modifyGeometrySet */ NULL, /* modifyVolume */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_nodes.cc b/source/blender/modifiers/intern/MOD_nodes.cc index 80c69398d15..35cb1dc7410 100644 --- a/source/blender/modifiers/intern/MOD_nodes.cc +++ b/source/blender/modifiers/intern/MOD_nodes.cc @@ -934,9 +934,9 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * return new_mesh; } -static void modifyPointCloud(ModifierData *md, - const ModifierEvalContext *ctx, - GeometrySet *geometry_set) +static void modifyGeometrySet(ModifierData *md, + const ModifierEvalContext *ctx, + GeometrySet *geometry_set) { modifyGeometry(md, ctx, *geometry_set); } @@ -1063,7 +1063,7 @@ ModifierTypeInfo modifierType_Nodes = { /* deformMatricesEM */ nullptr, /* modifyMesh */ modifyMesh, /* modifyHair */ nullptr, - /* modifyPointCloud */ modifyPointCloud, + /* modifyGeometrySet */ modifyGeometrySet, /* modifyVolume */ nullptr, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_none.c b/source/blender/modifiers/intern/MOD_none.c index 02307622d06..4daa527577b 100644 --- a/source/blender/modifiers/intern/MOD_none.c +++ b/source/blender/modifiers/intern/MOD_none.c @@ -59,7 +59,7 @@ ModifierTypeInfo modifierType_None = { /* deformMatricesEM */ NULL, /* modifyMesh */ NULL, /* modifyHair */ NULL, - /* modifyPointCloud */ NULL, + /* modifyGeometrySet */ NULL, /* modifyVolume */ NULL, /* initData */ NULL, diff --git a/source/blender/modifiers/intern/MOD_normal_edit.c b/source/blender/modifiers/intern/MOD_normal_edit.c index 0ec564d2e2d..ec10b18665e 100644 --- a/source/blender/modifiers/intern/MOD_normal_edit.c +++ b/source/blender/modifiers/intern/MOD_normal_edit.c @@ -804,7 +804,7 @@ ModifierTypeInfo modifierType_NormalEdit = { /* deformMatricesEM */ NULL, /* modifyMesh */ modifyMesh, /* modifyHair */ NULL, - /* modifyPointCloud */ NULL, + /* modifyGeometrySet */ NULL, /* modifyVolume */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_ocean.c b/source/blender/modifiers/intern/MOD_ocean.c index 5aef497c0c4..9c940745920 100644 --- a/source/blender/modifiers/intern/MOD_ocean.c +++ b/source/blender/modifiers/intern/MOD_ocean.c @@ -736,7 +736,7 @@ ModifierTypeInfo modifierType_Ocean = { /* deformMatricesEM */ NULL, /* modifyMesh */ modifyMesh, /* modifyHair */ NULL, - /* modifyPointCloud */ NULL, + /* modifyGeometrySet */ NULL, /* modifyVolume */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_particleinstance.c b/source/blender/modifiers/intern/MOD_particleinstance.c index f660874a5ea..e7f1fa9943e 100644 --- a/source/blender/modifiers/intern/MOD_particleinstance.c +++ b/source/blender/modifiers/intern/MOD_particleinstance.c @@ -678,7 +678,7 @@ ModifierTypeInfo modifierType_ParticleInstance = { /* deformMatricesEM */ NULL, /* modifyMesh */ modifyMesh, /* modifyHair */ NULL, - /* modifyPointCloud */ NULL, + /* modifyGeometrySet */ NULL, /* modifyVolume */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_particlesystem.c b/source/blender/modifiers/intern/MOD_particlesystem.c index 86480a17083..e49f16b994c 100644 --- a/source/blender/modifiers/intern/MOD_particlesystem.c +++ b/source/blender/modifiers/intern/MOD_particlesystem.c @@ -331,7 +331,7 @@ ModifierTypeInfo modifierType_ParticleSystem = { /* deformMatricesEM */ NULL, /* modifyMesh */ NULL, /* modifyHair */ NULL, - /* modifyPointCloud */ NULL, + /* modifyGeometrySet */ NULL, /* modifyVolume */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_remesh.c b/source/blender/modifiers/intern/MOD_remesh.c index f8fc4ad658e..175435fcd44 100644 --- a/source/blender/modifiers/intern/MOD_remesh.c +++ b/source/blender/modifiers/intern/MOD_remesh.c @@ -300,7 +300,7 @@ ModifierTypeInfo modifierType_Remesh = { /* deformMatricesEM */ NULL, /* modifyMesh */ modifyMesh, /* modifyHair */ NULL, - /* modifyPointCloud */ NULL, + /* modifyGeometrySet */ NULL, /* modifyVolume */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_screw.c b/source/blender/modifiers/intern/MOD_screw.c index 6521a0859e5..94d5c402abe 100644 --- a/source/blender/modifiers/intern/MOD_screw.c +++ b/source/blender/modifiers/intern/MOD_screw.c @@ -1259,7 +1259,7 @@ ModifierTypeInfo modifierType_Screw = { /* deformMatricesEM */ NULL, /* modifyMesh */ modifyMesh, /* modifyHair */ NULL, - /* modifyPointCloud */ NULL, + /* modifyGeometrySet */ NULL, /* modifyVolume */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_shapekey.c b/source/blender/modifiers/intern/MOD_shapekey.c index bb267386dfb..5d2e19eb2d2 100644 --- a/source/blender/modifiers/intern/MOD_shapekey.c +++ b/source/blender/modifiers/intern/MOD_shapekey.c @@ -139,7 +139,7 @@ ModifierTypeInfo modifierType_ShapeKey = { /* deformMatricesEM */ deformMatricesEM, /* modifyMesh */ NULL, /* modifyHair */ NULL, - /* modifyPointCloud */ NULL, + /* modifyGeometrySet */ NULL, /* modifyVolume */ NULL, /* initData */ NULL, diff --git a/source/blender/modifiers/intern/MOD_shrinkwrap.c b/source/blender/modifiers/intern/MOD_shrinkwrap.c index dddabb12f61..93626309727 100644 --- a/source/blender/modifiers/intern/MOD_shrinkwrap.c +++ b/source/blender/modifiers/intern/MOD_shrinkwrap.c @@ -292,7 +292,7 @@ ModifierTypeInfo modifierType_Shrinkwrap = { /* deformMatricesEM */ NULL, /* modifyMesh */ NULL, /* modifyHair */ NULL, - /* modifyPointCloud */ NULL, + /* modifyGeometrySet */ NULL, /* modifyVolume */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_simpledeform.c b/source/blender/modifiers/intern/MOD_simpledeform.c index ec89176f97e..e41e70864dc 100644 --- a/source/blender/modifiers/intern/MOD_simpledeform.c +++ b/source/blender/modifiers/intern/MOD_simpledeform.c @@ -552,7 +552,7 @@ ModifierTypeInfo modifierType_SimpleDeform = { /* deformMatricesEM */ NULL, /* modifyMesh */ NULL, /* modifyHair */ NULL, - /* modifyPointCloud */ NULL, + /* modifyGeometrySet */ NULL, /* modifyVolume */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_skin.c b/source/blender/modifiers/intern/MOD_skin.c index 6936f5a53f8..5e412185cea 100644 --- a/source/blender/modifiers/intern/MOD_skin.c +++ b/source/blender/modifiers/intern/MOD_skin.c @@ -2043,7 +2043,7 @@ ModifierTypeInfo modifierType_Skin = { /* deformMatricesEM */ NULL, /* modifyMesh */ modifyMesh, /* modifyHair */ NULL, - /* modifyPointCloud */ NULL, + /* modifyGeometrySet */ NULL, /* modifyVolume */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_smooth.c b/source/blender/modifiers/intern/MOD_smooth.c index e73a59f1ae8..e76a2baf6b6 100644 --- a/source/blender/modifiers/intern/MOD_smooth.c +++ b/source/blender/modifiers/intern/MOD_smooth.c @@ -286,7 +286,7 @@ ModifierTypeInfo modifierType_Smooth = { /* deformMatricesEM */ NULL, /* modifyMesh */ NULL, /* modifyHair */ NULL, - /* modifyPointCloud */ NULL, + /* modifyGeometrySet */ NULL, /* modifyVolume */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_softbody.c b/source/blender/modifiers/intern/MOD_softbody.c index 4bdb3ba60b1..9a657c44fca 100644 --- a/source/blender/modifiers/intern/MOD_softbody.c +++ b/source/blender/modifiers/intern/MOD_softbody.c @@ -119,7 +119,7 @@ ModifierTypeInfo modifierType_Softbody = { /* deformMatricesEM */ NULL, /* modifyMesh */ NULL, /* modifyHair */ NULL, - /* modifyPointCloud */ NULL, + /* modifyGeometrySet */ NULL, /* modifyVolume */ NULL, /* initData */ NULL, diff --git a/source/blender/modifiers/intern/MOD_solidify.c b/source/blender/modifiers/intern/MOD_solidify.c index 8886d3718c9..e501dc3210f 100644 --- a/source/blender/modifiers/intern/MOD_solidify.c +++ b/source/blender/modifiers/intern/MOD_solidify.c @@ -274,7 +274,7 @@ ModifierTypeInfo modifierType_Solidify = { /* deformMatricesEM */ NULL, /* modifyMesh */ modifyMesh, /* modifyHair */ NULL, - /* modifyPointCloud */ NULL, + /* modifyGeometrySet */ NULL, /* modifyVolume */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_subsurf.c b/source/blender/modifiers/intern/MOD_subsurf.c index 1aa015682dd..d089894a6e9 100644 --- a/source/blender/modifiers/intern/MOD_subsurf.c +++ b/source/blender/modifiers/intern/MOD_subsurf.c @@ -507,7 +507,7 @@ ModifierTypeInfo modifierType_Subsurf = { /* deformMatricesEM */ NULL, /* modifyMesh */ modifyMesh, /* modifyHair */ NULL, - /* modifyPointCloud */ NULL, + /* modifyGeometrySet */ NULL, /* modifyVolume */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_surface.c b/source/blender/modifiers/intern/MOD_surface.c index 72f19efe3a4..7416a4baf38 100644 --- a/source/blender/modifiers/intern/MOD_surface.c +++ b/source/blender/modifiers/intern/MOD_surface.c @@ -240,7 +240,7 @@ ModifierTypeInfo modifierType_Surface = { /* deformMatricesEM */ NULL, /* modifyMesh */ NULL, /* modifyHair */ NULL, - /* modifyPointCloud */ NULL, + /* modifyGeometrySet */ NULL, /* modifyVolume */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_surfacedeform.c b/source/blender/modifiers/intern/MOD_surfacedeform.c index 5407397e3bf..e00c5ba7f04 100644 --- a/source/blender/modifiers/intern/MOD_surfacedeform.c +++ b/source/blender/modifiers/intern/MOD_surfacedeform.c @@ -1546,7 +1546,7 @@ ModifierTypeInfo modifierType_SurfaceDeform = { /* deformMatricesEM */ NULL, /* modifyMesh */ NULL, /* modifyHair */ NULL, - /* modifyPointCloud */ NULL, + /* modifyGeometrySet */ NULL, /* modifyVolume */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_triangulate.c b/source/blender/modifiers/intern/MOD_triangulate.c index 1930a38b825..04d24ac0883 100644 --- a/source/blender/modifiers/intern/MOD_triangulate.c +++ b/source/blender/modifiers/intern/MOD_triangulate.c @@ -177,7 +177,7 @@ ModifierTypeInfo modifierType_Triangulate = { /* deformMatricesEM */ NULL, /* modifyMesh */ modifyMesh, /* modifyHair */ NULL, - /* modifyPointCloud */ NULL, + /* modifyGeometrySet */ NULL, /* modifyVolume */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_uvproject.c b/source/blender/modifiers/intern/MOD_uvproject.c index bfbc27abb88..8122f4617c1 100644 --- a/source/blender/modifiers/intern/MOD_uvproject.c +++ b/source/blender/modifiers/intern/MOD_uvproject.c @@ -370,7 +370,7 @@ ModifierTypeInfo modifierType_UVProject = { /* deformMatricesEM */ NULL, /* modifyMesh */ modifyMesh, /* modifyHair */ NULL, - /* modifyPointCloud */ NULL, + /* modifyGeometrySet */ NULL, /* modifyVolume */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_uvwarp.c b/source/blender/modifiers/intern/MOD_uvwarp.c index b326494815e..77b79167c2f 100644 --- a/source/blender/modifiers/intern/MOD_uvwarp.c +++ b/source/blender/modifiers/intern/MOD_uvwarp.c @@ -341,7 +341,7 @@ ModifierTypeInfo modifierType_UVWarp = { /* deformMatricesEM */ NULL, /* modifyMesh */ modifyMesh, /* modifyHair */ NULL, - /* modifyPointCloud */ NULL, + /* modifyGeometrySet */ NULL, /* modifyVolume */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_volume_displace.cc b/source/blender/modifiers/intern/MOD_volume_displace.cc index 90e570f55fb..745e089b8ff 100644 --- a/source/blender/modifiers/intern/MOD_volume_displace.cc +++ b/source/blender/modifiers/intern/MOD_volume_displace.cc @@ -328,7 +328,7 @@ ModifierTypeInfo modifierType_VolumeDisplace = { /* deformMatricesEM */ nullptr, /* modifyMesh */ nullptr, /* modifyHair */ nullptr, - /* modifyPointCloud */ nullptr, + /* modifyGeometrySet */ nullptr, /* modifyVolume */ modifyVolume, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_volume_to_mesh.cc b/source/blender/modifiers/intern/MOD_volume_to_mesh.cc index ec53914f115..941bc8409f7 100644 --- a/source/blender/modifiers/intern/MOD_volume_to_mesh.cc +++ b/source/blender/modifiers/intern/MOD_volume_to_mesh.cc @@ -335,7 +335,7 @@ ModifierTypeInfo modifierType_VolumeToMesh = { /* deformMatricesEM */ nullptr, /* modifyMesh */ modifyMesh, /* modifyHair */ nullptr, - /* modifyPointCloud */ nullptr, + /* modifyGeometrySet */ nullptr, /* modifyVolume */ nullptr, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_warp.c b/source/blender/modifiers/intern/MOD_warp.c index 53e41484606..9d3d5b0658c 100644 --- a/source/blender/modifiers/intern/MOD_warp.c +++ b/source/blender/modifiers/intern/MOD_warp.c @@ -538,7 +538,7 @@ ModifierTypeInfo modifierType_Warp = { /* deformMatricesEM */ NULL, /* modifyMesh */ NULL, /* modifyHair */ NULL, - /* modifyPointCloud */ NULL, + /* modifyGeometrySet */ NULL, /* modifyVolume */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_wave.c b/source/blender/modifiers/intern/MOD_wave.c index 45f06a7778c..863656b85a5 100644 --- a/source/blender/modifiers/intern/MOD_wave.c +++ b/source/blender/modifiers/intern/MOD_wave.c @@ -491,7 +491,7 @@ ModifierTypeInfo modifierType_Wave = { /* deformMatricesEM */ NULL, /* modifyMesh */ NULL, /* modifyHair */ NULL, - /* modifyPointCloud */ NULL, + /* modifyGeometrySet */ NULL, /* modifyVolume */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_weighted_normal.c b/source/blender/modifiers/intern/MOD_weighted_normal.c index bd15d909834..40265e37db9 100644 --- a/source/blender/modifiers/intern/MOD_weighted_normal.c +++ b/source/blender/modifiers/intern/MOD_weighted_normal.c @@ -763,7 +763,7 @@ ModifierTypeInfo modifierType_WeightedNormal = { /* deformMatricesEM */ NULL, /* modifyMesh */ modifyMesh, /* modifyHair */ NULL, - /* modifyPointCloud */ NULL, + /* modifyGeometrySet */ NULL, /* modifyVolume */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_weightvgedit.c b/source/blender/modifiers/intern/MOD_weightvgedit.c index df554f6bc4e..915adccc745 100644 --- a/source/blender/modifiers/intern/MOD_weightvgedit.c +++ b/source/blender/modifiers/intern/MOD_weightvgedit.c @@ -427,7 +427,7 @@ ModifierTypeInfo modifierType_WeightVGEdit = { /* deformMatricesEM */ NULL, /* modifyMesh */ modifyMesh, /* modifyHair */ NULL, - /* modifyPointCloud */ NULL, + /* modifyGeometrySet */ NULL, /* modifyVolume */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_weightvgmix.c b/source/blender/modifiers/intern/MOD_weightvgmix.c index 9be36fe6846..52cee7ce7e5 100644 --- a/source/blender/modifiers/intern/MOD_weightvgmix.c +++ b/source/blender/modifiers/intern/MOD_weightvgmix.c @@ -513,7 +513,7 @@ ModifierTypeInfo modifierType_WeightVGMix = { /* deformMatricesEM */ NULL, /* modifyMesh */ modifyMesh, /* modifyHair */ NULL, - /* modifyPointCloud */ NULL, + /* modifyGeometrySet */ NULL, /* modifyVolume */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_weightvgproximity.c b/source/blender/modifiers/intern/MOD_weightvgproximity.c index 7232ffd3d9d..aac29cabf0f 100644 --- a/source/blender/modifiers/intern/MOD_weightvgproximity.c +++ b/source/blender/modifiers/intern/MOD_weightvgproximity.c @@ -767,7 +767,7 @@ ModifierTypeInfo modifierType_WeightVGProximity = { /* deformMatricesEM */ NULL, /* modifyMesh */ modifyMesh, /* modifyHair */ NULL, - /* modifyPointCloud */ NULL, + /* modifyGeometrySet */ NULL, /* modifyVolume */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_weld.c b/source/blender/modifiers/intern/MOD_weld.c index e34dcf48c19..fd1254fc948 100644 --- a/source/blender/modifiers/intern/MOD_weld.c +++ b/source/blender/modifiers/intern/MOD_weld.c @@ -2052,7 +2052,7 @@ ModifierTypeInfo modifierType_Weld = { /* deformMatricesEM */ NULL, /* modifyMesh */ modifyMesh, /* modifyHair */ NULL, - /* modifyPointCloud */ NULL, + /* modifyGeometrySet */ NULL, /* modifyVolume */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_wireframe.c b/source/blender/modifiers/intern/MOD_wireframe.c index 206c514826c..3d8e74d2cf5 100644 --- a/source/blender/modifiers/intern/MOD_wireframe.c +++ b/source/blender/modifiers/intern/MOD_wireframe.c @@ -195,7 +195,7 @@ ModifierTypeInfo modifierType_Wireframe = { /* deformMatricesEM */ NULL, /* modifyMesh */ modifyMesh, /* modifyHair */ NULL, - /* modifyPointCloud */ NULL, + /* modifyGeometrySet */ NULL, /* modifyVolume */ NULL, /* initData */ initData, -- cgit v1.2.3 From 348bd319d5a88f45410a22f8ce2f527d8da48ef0 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Thu, 10 Dec 2020 07:58:45 -0600 Subject: Geometry Nodes: Attribute Fill Node This commit adds a node that fills every element of an attribute with the same value. Currently it supports float, vector, and color attributes. An immediate use case is for "billboard" scattering. Currently people are using the same input to a Random Attribute node's min and max input to fill every element of a vector with the same value, which is an unintuitive way to accomplish the same thing. Differential Revision: https://developer.blender.org/D9790 --- source/blender/blenkernel/BKE_node.h | 1 + source/blender/blenkernel/intern/node.c | 1 + source/blender/editors/space_node/drawnode.c | 11 ++ source/blender/makesrna/intern/rna_nodetree.c | 31 +++++ source/blender/nodes/CMakeLists.txt | 1 + source/blender/nodes/NOD_geometry.h | 1 + source/blender/nodes/NOD_static_types.h | 1 + .../geometry/nodes/node_geo_attribute_fill.cc | 130 +++++++++++++++++++++ 8 files changed, 177 insertions(+) create mode 100644 source/blender/nodes/geometry/nodes/node_geo_attribute_fill.cc (limited to 'source/blender') diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index a8a94958772..56ed60c1f67 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -1350,6 +1350,7 @@ int ntreeTexExecTree(struct bNodeTree *ntree, #define GEO_NODE_RANDOM_ATTRIBUTE 1008 #define GEO_NODE_ATTRIBUTE_MATH 1009 #define GEO_NODE_JOIN_GEOMETRY 1010 +#define GEO_NODE_ATTRIBUTE_FILL 1011 /** \} */ diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 31de95817fd..ecc17ff0e5e 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -4682,6 +4682,7 @@ static void registerGeometryNodes(void) { register_node_type_geo_group(); + register_node_type_geo_attribute_fill(); register_node_type_geo_triangulate(); register_node_type_geo_edge_split(); register_node_type_geo_transform(); diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 84e7a74fab3..2ff32a4a82e 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -3182,6 +3182,14 @@ static void node_geometry_buts_attribute_math(uiLayout *layout, uiItemR(layout, ptr, "input_type_b", DEFAULT_FLAGS, IFACE_("Type B"), ICON_NONE); } +static void node_geometry_buts_attribute_fill(uiLayout *layout, + bContext *UNUSED(C), + PointerRNA *ptr) +{ + uiItemR(layout, ptr, "data_type", DEFAULT_FLAGS, "", ICON_NONE); + // uiItemR(layout, ptr, "domain", DEFAULT_FLAGS, "", ICON_NONE); +} + static void node_geometry_set_butfunc(bNodeType *ntype) { switch (ntype->type) { @@ -3200,6 +3208,9 @@ static void node_geometry_set_butfunc(bNodeType *ntype) case GEO_NODE_ATTRIBUTE_MATH: ntype->draw_buttons = node_geometry_buts_attribute_math; break; + case GEO_NODE_ATTRIBUTE_FILL: + ntype->draw_buttons = node_geometry_buts_attribute_fill; + break; } } diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index dd02cc214e0..07dba3e55a1 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -1879,6 +1879,30 @@ static const EnumPropertyItem *rna_GeometryNodeAttributeRandom_domain_itemf( return itemf_function_check(rna_enum_attribute_domain_items, attribute_random_domain_supported); } +static bool attribute_fill_type_supported(const EnumPropertyItem *item) +{ + return ELEM(item->value, CD_PROP_FLOAT, CD_PROP_FLOAT3, CD_PROP_COLOR); +} +static const EnumPropertyItem *rna_GeometryNodeAttributeFill_type_itemf(bContext *UNUSED(C), + PointerRNA *UNUSED(ptr), + PropertyRNA *UNUSED(prop), + bool *r_free) +{ + *r_free = true; + return itemf_function_check(rna_enum_attribute_type_items, attribute_fill_type_supported); +} + +static bool attribute_fill_domain_supported(const EnumPropertyItem *item) +{ + return item->value == ATTR_DOMAIN_POINT; +} +static const EnumPropertyItem *rna_GeometryNodeAttributeFill_domain_itemf( + bContext *UNUSED(C), PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free) +{ + *r_free = true; + return itemf_function_check(rna_enum_attribute_domain_items, attribute_fill_domain_supported); +} + static bool attribute_math_operation_supported(const EnumPropertyItem *item) { return ELEM(item->value, @@ -8343,6 +8367,13 @@ static void def_geo_random_attribute(StructRNA *srna) "rna_GeometryNodeAttributeRandom_domain_itemf"); } +static void def_geo_attribute_fill(StructRNA *srna) +{ + def_geo_attribute_create_common(srna, + "rna_GeometryNodeAttributeFill_type_itemf", + "rna_GeometryNodeAttributeFill_domain_itemf"); +} + static void def_geo_attribute_math(StructRNA *srna) { PropertyRNA *prop; diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index a367f40dca7..d09b1a8534d 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -138,6 +138,7 @@ set(SRC function/nodes/node_fn_switch.cc function/node_function_util.cc + geometry/nodes/node_geo_attribute_fill.cc geometry/nodes/node_geo_attribute_math.cc geometry/nodes/node_geo_common.cc geometry/nodes/node_geo_boolean.cc diff --git a/source/blender/nodes/NOD_geometry.h b/source/blender/nodes/NOD_geometry.h index 0532547375f..6433841582b 100644 --- a/source/blender/nodes/NOD_geometry.h +++ b/source/blender/nodes/NOD_geometry.h @@ -26,6 +26,7 @@ void register_node_tree_type_geo(void); void register_node_type_geo_group(void); +void register_node_type_geo_attribute_fill(void); void register_node_type_geo_boolean(void); void register_node_type_geo_edge_split(void); void register_node_type_geo_transform(void); diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h index 09e0908140c..8ca978d1339 100644 --- a/source/blender/nodes/NOD_static_types.h +++ b/source/blender/nodes/NOD_static_types.h @@ -277,6 +277,7 @@ DefNode(GeometryNode, GEO_NODE_OBJECT_INFO, 0, "OBJECT_INFO", ObjectInfo, "Objec DefNode(GeometryNode, GEO_NODE_RANDOM_ATTRIBUTE, def_geo_random_attribute, "RANDOM_ATTRIBUTE", RandomAttribute, "Random Attribute", "") DefNode(GeometryNode, GEO_NODE_ATTRIBUTE_MATH, def_geo_attribute_math, "ATTRIBUTE_MATH", AttributeMath, "Attribute Math", "") DefNode(GeometryNode, GEO_NODE_JOIN_GEOMETRY, 0, "JOIN_GEOMETRY", JoinGeometry, "Join Geometry", "") +DefNode(GeometryNode, GEO_NODE_ATTRIBUTE_FILL, def_geo_attribute_fill, "ATTRIBUTE_FILL", AttributeFill, "Attribute Fill", "") /* undefine macros */ #undef DefNode diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_fill.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_fill.cc new file mode 100644 index 00000000000..d3c7e86b708 --- /dev/null +++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_fill.cc @@ -0,0 +1,130 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "node_geometry_util.hh" + +#include "BLI_rand.hh" + +#include "DNA_mesh_types.h" +#include "DNA_pointcloud_types.h" + +static bNodeSocketTemplate geo_node_attribute_fill_in[] = { + {SOCK_GEOMETRY, N_("Geometry")}, + {SOCK_STRING, N_("Attribute")}, + {SOCK_VECTOR, N_("Value"), 0.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX}, + {SOCK_FLOAT, N_("Value"), 0.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX}, + {SOCK_RGBA, N_("Value"), 0.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX}, + {-1, ""}, +}; + +static bNodeSocketTemplate geo_node_attribute_fill_out[] = { + {SOCK_GEOMETRY, N_("Geometry")}, + {-1, ""}, +}; + +static void geo_node_attribute_fill_init(bNodeTree *UNUSED(tree), bNode *node) +{ + node->custom1 = CD_PROP_FLOAT; +} + +static void geo_node_attribute_fill_update(bNodeTree *UNUSED(ntree), bNode *node) +{ + bNodeSocket *socket_value_vector = (bNodeSocket *)BLI_findlink(&node->inputs, 2); + bNodeSocket *socket_value_float = socket_value_vector->next; + bNodeSocket *socket_value_color4f = socket_value_float->next; + + const CustomDataType data_type = static_cast(node->custom1); + + nodeSetSocketAvailability(socket_value_vector, data_type == CD_PROP_FLOAT3); + nodeSetSocketAvailability(socket_value_float, data_type == CD_PROP_FLOAT); + nodeSetSocketAvailability(socket_value_color4f, data_type == CD_PROP_COLOR); +} + +namespace blender::nodes { + +static void fill_attribute(GeometryComponent &component, const GeoNodeExecParams ¶ms) +{ + const bNode &node = params.node(); + const CustomDataType data_type = static_cast(node.custom1); + const AttributeDomain domain = static_cast(node.custom2); + const std::string attribute_name = params.get_input("Attribute"); + if (attribute_name.empty()) { + return; + } + + WriteAttributePtr attribute = component.attribute_try_ensure_for_write( + attribute_name, domain, data_type); + if (!attribute) { + return; + } + + switch (data_type) { + case CD_PROP_FLOAT: { + FloatWriteAttribute float_attribute = std::move(attribute); + const float value = params.get_input("Value_001"); + MutableSpan attribute_span = float_attribute.get_span(); + attribute_span.fill(value); + float_attribute.apply_span(); + break; + } + case CD_PROP_FLOAT3: { + Float3WriteAttribute float3_attribute = std::move(attribute); + const float3 value = params.get_input("Value"); + MutableSpan attribute_span = float3_attribute.get_span(); + attribute_span.fill(value); + float3_attribute.apply_span(); + break; + } + case CD_PROP_COLOR: { + Color4fWriteAttribute color4f_attribute = std::move(attribute); + const Color4f value = params.get_input("Value_002"); + MutableSpan attribute_span = color4f_attribute.get_span(); + attribute_span.fill(value); + color4f_attribute.apply_span(); + break; + } + default: + break; + } +} + +static void geo_node_attribute_fill_exec(GeoNodeExecParams params) +{ + GeometrySet geometry_set = params.extract_input("Geometry"); + + if (geometry_set.has()) { + fill_attribute(geometry_set.get_component_for_write(), params); + } + if (geometry_set.has()) { + fill_attribute(geometry_set.get_component_for_write(), params); + } + + params.set_output("Geometry", geometry_set); +} + +} // namespace blender::nodes + +void register_node_type_geo_attribute_fill() +{ + static bNodeType ntype; + + geo_node_type_base(&ntype, GEO_NODE_ATTRIBUTE_FILL, "Attribute Fill", NODE_CLASS_ATTRIBUTE, 0); + node_type_socket_templates(&ntype, geo_node_attribute_fill_in, geo_node_attribute_fill_out); + node_type_init(&ntype, geo_node_attribute_fill_init); + node_type_update(&ntype, geo_node_attribute_fill_update); + ntype.geometry_node_execute = blender::nodes::geo_node_attribute_fill_exec; + nodeRegisterType(&ntype); +} -- cgit v1.2.3 From 1d447dcd19120ed2fd14511589220438ce1904bc Mon Sep 17 00:00:00 2001 From: Howard Trickey Date: Thu, 10 Dec 2020 09:11:43 -0500 Subject: Fix T83630 Exact Boolean assert failure in Debug build. I thought I had reasoned that the add_patch would only happen when the patch was not already in a cell, but I missed reasoning about merged cells. So switched to a set 'add' instead of 'add_new'. --- source/blender/blenlib/intern/mesh_boolean.cc | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenlib/intern/mesh_boolean.cc b/source/blender/blenlib/intern/mesh_boolean.cc index 2db939cd628..88d90a7816f 100644 --- a/source/blender/blenlib/intern/mesh_boolean.cc +++ b/source/blender/blenlib/intern/mesh_boolean.cc @@ -400,11 +400,6 @@ class Cell { Cell() = default; void add_patch(int p) - { - patches_.add_new(p); - } - - void add_patch_non_duplicates(int p) { patches_.add(p); } @@ -693,7 +688,7 @@ static void merge_cells(int merge_to, int merge_from, CellsInfo &cinfo, PatchesI merge_to_cell = cinfo.cell(final_merge_to); } for (int cell_p : merge_from_cell.patches()) { - merge_to_cell.add_patch_non_duplicates(cell_p); + merge_to_cell.add_patch(cell_p); Patch &patch = pinfo.patch(cell_p); if (patch.cell_above == merge_from) { patch.cell_above = merge_to; -- cgit v1.2.3 From 3d25312617019178455dc6f68166c65c687a7041 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Thu, 10 Dec 2020 16:12:11 +0100 Subject: Nodes: fix incorrectly parameter name and type The parameter type was incorrectly changed in rB6be56c13e96048cbc494ba5473a8deaf2cf5a6f8 by me. This can be any id and does not have to be a node tree. --- source/blender/blenkernel/BKE_node.h | 2 +- source/blender/blenkernel/intern/lib_remap.c | 2 +- source/blender/blenkernel/intern/node.c | 25 ++++++++++++++----------- 3 files changed, 16 insertions(+), 13 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 56ed60c1f67..eeef3e5c704 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -451,7 +451,7 @@ bool ntreeHasType(const struct bNodeTree *ntree, int type); bool ntreeHasTree(const struct bNodeTree *ntree, const struct bNodeTree *lookup); void ntreeUpdateTree(struct Main *main, struct bNodeTree *ntree); void ntreeUpdateAllNew(struct Main *main); -void ntreeUpdateAllUsers(struct Main *main, struct bNodeTree *ngroup); +void ntreeUpdateAllUsers(struct Main *main, struct ID *id); void ntreeGetDependencyList(struct bNodeTree *ntree, struct bNode ***deplist, int *totnodes); diff --git a/source/blender/blenkernel/intern/lib_remap.c b/source/blender/blenkernel/intern/lib_remap.c index 9e3189afee9..f0031d4191d 100644 --- a/source/blender/blenkernel/intern/lib_remap.c +++ b/source/blender/blenkernel/intern/lib_remap.c @@ -342,7 +342,7 @@ static void libblock_remap_data_postprocess_obdata_relink(Main *bmain, Object *o static void libblock_remap_data_postprocess_nodetree_update(Main *bmain, ID *new_id) { /* Update all group nodes using a node group. */ - ntreeUpdateAllUsers(bmain, (bNodeTree *)new_id); + ntreeUpdateAllUsers(bmain, new_id); } /** diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index ecc17ff0e5e..eeffaa186ab 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -3960,9 +3960,9 @@ void ntreeUpdateAllNew(Main *main) FOREACH_NODETREE_END; } -void ntreeUpdateAllUsers(Main *main, bNodeTree *ngroup) +void ntreeUpdateAllUsers(Main *main, ID *id) { - if (ngroup == NULL) { + if (id == NULL) { return; } @@ -3971,7 +3971,7 @@ void ntreeUpdateAllUsers(Main *main, bNodeTree *ngroup) bool need_update = false; LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { - if (node->id == &ngroup->id) { + if (node->id == id) { if (node->typeinfo->group_update_func) { node->typeinfo->group_update_func(ntree, node); } @@ -3986,13 +3986,16 @@ void ntreeUpdateAllUsers(Main *main, bNodeTree *ngroup) } FOREACH_NODETREE_END; - if (ngroup->type == NTREE_GEOMETRY) { - LISTBASE_FOREACH (Object *, object, &main->objects) { - LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) { - if (md->type == eModifierType_Nodes) { - NodesModifierData *nmd = (NodesModifierData *)md; - if (nmd->node_group == ngroup) { - MOD_nodes_update_interface(object, nmd); + if (GS(id->name) == ID_NT) { + bNodeTree *ngroup = (bNodeTree *)id; + if (ngroup->type == NTREE_GEOMETRY) { + LISTBASE_FOREACH (Object *, object, &main->objects) { + LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) { + if (md->type == eModifierType_Nodes) { + NodesModifierData *nmd = (NodesModifierData *)md; + if (nmd->node_group == ngroup) { + MOD_nodes_update_interface(object, nmd); + } } } } @@ -4041,7 +4044,7 @@ void ntreeUpdateTree(Main *bmain, bNodeTree *ntree) } if (bmain) { - ntreeUpdateAllUsers(bmain, ntree); + ntreeUpdateAllUsers(bmain, &ntree->id); } if (ntree->update & (NTREE_UPDATE_LINKS | NTREE_UPDATE_NODES)) { -- cgit v1.2.3 From 8bdd996cd0de794f21d5f201a3af0a9cca9e8e5e Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Thu, 10 Dec 2020 10:50:37 -0600 Subject: Geometry Nodes: Add helper function to check if attribute exists --- source/blender/blenkernel/BKE_geometry_set.hh | 3 +++ source/blender/blenkernel/intern/attribute_access.cc | 9 +++++++++ 2 files changed, 12 insertions(+) (limited to 'source/blender') diff --git a/source/blender/blenkernel/BKE_geometry_set.hh b/source/blender/blenkernel/BKE_geometry_set.hh index 3398da9896b..b7cb9320086 100644 --- a/source/blender/blenkernel/BKE_geometry_set.hh +++ b/source/blender/blenkernel/BKE_geometry_set.hh @@ -88,6 +88,9 @@ class GeometryComponent { GeometryComponentType type() const; + /* Return true when any attribute with this name exists, including built in attributes. */ + bool attribute_exists(const blender::StringRef attribute_name) const; + /* Returns true when the geometry component supports this attribute domain. */ virtual bool attribute_domain_supported(const AttributeDomain domain) const; /* Returns true when the given data type is supported in the given domain. */ diff --git a/source/blender/blenkernel/intern/attribute_access.cc b/source/blender/blenkernel/intern/attribute_access.cc index d79168d5443..282e9bc2962 100644 --- a/source/blender/blenkernel/intern/attribute_access.cc +++ b/source/blender/blenkernel/intern/attribute_access.cc @@ -590,6 +590,15 @@ Set GeometryComponent::attribute_names() const return {}; } +bool GeometryComponent::attribute_exists(const blender::StringRef attribute_name) const +{ + ReadAttributePtr attribute = this->attribute_try_get_for_read(attribute_name); + if (attribute) { + return true; + } + return false; +} + static ReadAttributePtr try_adapt_data_type(ReadAttributePtr attribute, const blender::fn::CPPType &to_type) { -- cgit v1.2.3 From a7fcca1062bcd5018682f292b0465a7f0ab7f57b Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Thu, 10 Dec 2020 11:07:26 -0600 Subject: UI: Use words instead of symbols for float comparison items Though they are nice and concise, users should not be expected to know the meaning of symbols like `!=`. --- source/blender/makesrna/intern/rna_nodetree.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'source/blender') diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 07dba3e55a1..b3f48b17ce0 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -272,32 +272,32 @@ const EnumPropertyItem rna_enum_node_float_compare_items[] = { {NODE_FLOAT_COMPARE_LESS_THAN, "LESS_THAN", 0, - "A < B", + "Less Than", "True when the first input is smaller than second input"}, {NODE_FLOAT_COMPARE_LESS_EQUAL, "LESS_EQUAL", 0, - "A <= B", + "Less Than or Equal", "True when the first input is smaller than the second input or equal"}, {NODE_FLOAT_COMPARE_GREATER_THAN, "GREATER_THAN", 0, - "A > B", + "Greater Than", "True when the first input is greater than the second input"}, {NODE_FLOAT_COMPARE_GREATER_EQUAL, "GREATER_EQUAL", 0, - "A >= B", + "Greater Than or Equal", "True when the first input is greater than the second input or equal"}, {NODE_FLOAT_COMPARE_EQUAL, "EQUAL", 0, - "A = B", + "Equal", "True when both inputs are approximately equal"}, {NODE_FLOAT_COMPARE_NOT_EQUAL, "NOT_EQUAL", 0, - "A != B", + "Not Equal", "True when both inputs are not approximately equal"}, {0, NULL, 0, NULL, NULL}, }; -- cgit v1.2.3 From caed4849d0903c09c63ef5b80e506aa4bdfcb994 Mon Sep 17 00:00:00 2001 From: Philipp Oeser Date: Thu, 10 Dec 2020 22:39:28 +0100 Subject: Fix T83640: No immediate updates when changing the settings of a just- duplicated particle system When particle settings are duplicated along with the particle system, this means a change in relations, was missing 'DEG_relations_tag_update'. Maniphest Tasks: T83640 Differential Revision: https://developer.blender.org/D9823 --- source/blender/editors/physics/particle_object.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source/blender') diff --git a/source/blender/editors/physics/particle_object.c b/source/blender/editors/physics/particle_object.c index 017cd63d9d5..f5c3fc17552 100644 --- a/source/blender/editors/physics/particle_object.c +++ b/source/blender/editors/physics/particle_object.c @@ -1203,6 +1203,9 @@ static bool copy_particle_systems_to_object(const bContext *C, #undef PSYS_FROM_FIRST #undef PSYS_FROM_NEXT + if (duplicate_settings) { + DEG_relations_tag_update(bmain); + } DEG_id_tag_update(&ob_to->id, ID_RECALC_GEOMETRY); WM_main_add_notifier(NC_OBJECT | ND_PARTICLE | NA_EDITED, ob_to); return true; -- cgit v1.2.3 From a4a42f3171c021f2f7eb28e1ed10873b3314587b Mon Sep 17 00:00:00 2001 From: Yevgeny Makarov Date: Thu, 10 Dec 2020 18:22:16 -0800 Subject: UI: Use 'and' Instead of '&' in Descriptions Use 'and' instead of ampersand in descriptions and comments. Differential Revision: https://developer.blender.org/D9797 Reviewed by Aaron Carlisle --- source/blender/editors/armature/armature_edit.c | 2 +- source/blender/editors/mesh/editmesh_tools.c | 6 +++--- source/blender/editors/screen/screen_ops.c | 2 +- source/blender/editors/transform/transform_ops.c | 2 +- source/blender/makesrna/intern/rna_access.c | 2 +- source/blender/makesrna/intern/rna_nla.c | 2 +- source/blender/makesrna/intern/rna_nodetree.c | 2 +- source/blender/makesrna/intern/rna_object_force.c | 2 +- source/blender/makesrna/intern/rna_space.c | 2 +- source/blender/makesrna/intern/rna_userdef.c | 10 +++++----- 10 files changed, 16 insertions(+), 16 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/armature/armature_edit.c b/source/blender/editors/armature/armature_edit.c index b20d2738bda..f2cb00f67f0 100644 --- a/source/blender/editors/armature/armature_edit.c +++ b/source/blender/editors/armature/armature_edit.c @@ -1014,7 +1014,7 @@ void ARMATURE_OT_switch_direction(wmOperatorType *ot) /* identifiers */ ot->name = "Switch Direction"; ot->idname = "ARMATURE_OT_switch_direction"; - ot->description = "Change the direction that a chain of bones points in (head <-> tail swap)"; + ot->description = "Change the direction that a chain of bones points in (head and tail swap)"; /* api callbacks */ ot->exec = armature_switch_direction_exec; diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index b961f81e16a..ccc27ec19b6 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -395,7 +395,7 @@ void MESH_OT_unsubdivide(wmOperatorType *ot) { /* identifiers */ ot->name = "Un-Subdivide"; - ot->description = "UnSubdivide selected edges & faces"; + ot->description = "Un-subdivide selected edges and faces"; ot->idname = "MESH_OT_unsubdivide"; /* api callbacks */ @@ -698,7 +698,7 @@ void MESH_OT_edge_collapse(wmOperatorType *ot) /* identifiers */ ot->name = "Collapse Edges & Faces"; ot->description = - "Collapse isolated edges & faces regions, merging data such as UV's and vertex colors. " + "Collapse isolated edge and face regions, merging data such as UV's and vertex colors. " "This can collapse edge-rings as well as regions of connected faces into vertices"; ot->idname = "MESH_OT_edge_collapse"; @@ -1904,7 +1904,7 @@ void MESH_OT_edge_split(wmOperatorType *ot) "VERT", 0, "Faces & Edges by Vertices", - "Split faces & edges connected to selected vertices"}, + "Split faces and edges connected to selected vertices"}, {0, NULL, 0, NULL, NULL}, }; diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 72b3b344813..649279f8e08 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -3918,7 +3918,7 @@ static void SCREEN_OT_region_quadview(wmOperatorType *ot) { /* identifiers */ ot->name = "Toggle Quad View"; - ot->description = "Split selected area into camera, front, right & top views"; + ot->description = "Split selected area into camera, front, right, and top views"; ot->idname = "SCREEN_OT_region_quadview"; /* api callbacks */ diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index 5153fdedcae..5d758a6c6c6 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -717,7 +717,7 @@ void Transform_Properties(struct wmOperatorType *ot, int flags) "use_automerge_and_split", 0, "Auto Merge & Split", - "Forces the use of Auto Merge & Split"); + "Forces the use of Auto Merge and Split"); RNA_def_property_flag(prop, PROP_HIDDEN); } } diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index 6586cfc7969..25fe37c2d02 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -1106,7 +1106,7 @@ bool RNA_struct_bl_idname_ok_or_report(ReportList *reports, #endif if (p == NULL || p == identifier || p + len_sep >= identifier + len_id) { BKE_reportf( - reports, report_level, "'%s' doesn't contain '%s' with prefix & suffix", identifier, sep); + reports, report_level, "'%s' does not contain '%s' with prefix and suffix", identifier, sep); return failure; } diff --git a/source/blender/makesrna/intern/rna_nla.c b/source/blender/makesrna/intern/rna_nla.c index f8a342e7f7e..2642ba82bc0 100644 --- a/source/blender/makesrna/intern/rna_nla.c +++ b/source/blender/makesrna/intern/rna_nla.c @@ -784,7 +784,7 @@ static void rna_def_nlastrip(BlenderRNA *brna) prop = RNA_def_property(srna, "use_animated_time_cyclic", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", NLASTRIP_FLAG_USR_TIME_CYCLIC); RNA_def_property_ui_text( - prop, "Cyclic Strip Time", "Cycle the animated time within the action start & end"); + prop, "Cyclic Strip Time", "Cycle the animated time within the action start and end"); RNA_def_property_update( prop, NC_ANIMATION | ND_NLA | NA_EDITED, "rna_NlaStrip_transform_update"); diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index b3f48b17ce0..23092fbae28 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -8178,7 +8178,7 @@ static void def_cmp_sunbeams(StructRNA *srna) RNA_def_property_range(prop, -100.0f, 100.0f); RNA_def_property_ui_range(prop, -10.0f, 10.0f, 10, 3); RNA_def_property_ui_text( - prop, "Source", "Source point of rays as a factor of the image width & height"); + prop, "Source", "Source point of rays as a factor of the image width and height"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); prop = RNA_def_property(srna, "ray_length", PROP_FLOAT, PROP_UNSIGNED); diff --git a/source/blender/makesrna/intern/rna_object_force.c b/source/blender/makesrna/intern/rna_object_force.c index db4f3754b25..106de759cfc 100644 --- a/source/blender/makesrna/intern/rna_object_force.c +++ b/source/blender/makesrna/intern/rna_object_force.c @@ -1488,7 +1488,7 @@ static void rna_def_field(BlenderRNA *brna) RNA_def_property_enum_items(prop, texture_items); RNA_def_property_ui_text(prop, "Texture Mode", - "How the texture effect is calculated (RGB & Curl need a RGB texture, " + "How the texture effect is calculated (RGB and Curl need a RGB texture, " "else Gradient will be used instead)"); RNA_def_property_update(prop, 0, "rna_FieldSettings_update"); diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 65ea155ffba..4e60db95e5b 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -4281,7 +4281,7 @@ static void rna_def_space_view3d(BlenderRNA *brna) /* Camera Object Data. */ prop = RNA_def_property(srna, "show_gizmo_camera_lens", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "gizmo_show_camera", V3D_GIZMO_SHOW_CAMERA_LENS); - RNA_def_property_ui_text(prop, "Show Camera Lens", "Gizmo to adjust camera lens & ortho size"); + RNA_def_property_ui_text(prop, "Show Camera Lens", "Gizmo to adjust camera focal length or orthographic scale"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); prop = RNA_def_property(srna, "show_gizmo_camera_dof_distance", PROP_BOOLEAN, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index f1f7810bcf0..918bcb01170 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -4575,7 +4575,7 @@ static void rna_def_userdef_view(BlenderRNA *brna) RNA_def_property_ui_text( prop, "Navigation Controls", - "Show navigation controls in 2D & 3D views which do not have scroll bars"); + "Show navigation controls in 2D and 3D views which do not have scroll bars"); RNA_def_property_update(prop, 0, "rna_userdef_gizmo_update"); /* menus */ @@ -5984,7 +5984,7 @@ static void rna_def_userdef_filepaths(BlenderRNA *brna) {2, "DJV", 0, "DJV", "Open source frame player: http://djv.sourceforge.net"}, {3, "FRAMECYCLER", 0, "FrameCycler", "Frame player from IRIDAS"}, {4, "RV", 0, "RV", "Frame player from Tweak Software"}, - {5, "MPLAYER", 0, "MPlayer", "Media player for video & png/jpeg/sgi image sequences"}, + {5, "MPLAYER", 0, "MPlayer", "Media player for video and PNG/JPEG/SGI image sequences"}, {50, "CUSTOM", 0, "Custom", "Custom animation player executable path"}, {0, NULL, 0, NULL, NULL}, }; @@ -6069,8 +6069,8 @@ static void rna_def_userdef_filepaths(BlenderRNA *brna) RNA_def_property_string_sdna(prop, NULL, "pythondir"); RNA_def_property_ui_text(prop, "Python Scripts Directory", - "Alternate script path, matching the default layout with subdirs: " - "startup, add-ons & modules (requires restart)"); + "Alternate script path, matching the default layout with subdirectories: " + "startup, add-ons and modules (requires restart)"); /* TODO, editing should reset sys.path! */ prop = RNA_def_property(srna, "i18n_branches_directory", PROP_STRING, PROP_DIRPATH); @@ -6125,7 +6125,7 @@ static void rna_def_userdef_filepaths(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Auto Save Temporary Files", "Automatic saving of temporary files in temp directory, " - "uses process ID (sculpt & edit-mode data won't be saved!)"); + "uses process ID (sculpt and edit mode data won't be saved)"); RNA_def_property_update(prop, 0, "rna_userdef_autosave_update"); prop = RNA_def_property(srna, "auto_save_time", PROP_INT, PROP_NONE); -- cgit v1.2.3 From ff6d7e907269c3e090d4234df6eb7e812c809050 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 11 Dec 2020 14:51:43 +1100 Subject: Cleanup: spelling, expand on FCurve.rna_path docstring --- source/blender/editors/sculpt_paint/sculpt_intern.h | 2 +- source/blender/makesdna/DNA_anim_types.h | 8 ++++++-- source/blender/modifiers/intern/MOD_screw.c | 4 ++-- 3 files changed, 9 insertions(+), 5 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h index 3b48207f461..e0d413bc75f 100644 --- a/source/blender/editors/sculpt_paint/sculpt_intern.h +++ b/source/blender/editors/sculpt_paint/sculpt_intern.h @@ -452,7 +452,7 @@ BLI_INLINE bool SCULPT_tool_needs_all_pbvh_nodes(const Brush *brush) if (brush->sculpt_tool == SCULPT_TOOL_BOUNDARY) { /* Boundary needs all nodes because it is not possible to know where the boundary * deformation is going to be propagated before calculating it. */ - /* TODO: after calculating the boudnary info in the first iteration, it should be + /* TODO: after calculating the boundary info in the first iteration, it should be * possible to get the nodes that have vertices included in any boundary deformation * and cache them. */ return true; diff --git a/source/blender/makesdna/DNA_anim_types.h b/source/blender/makesdna/DNA_anim_types.h index 17d41985f80..bfc72fdd45c 100644 --- a/source/blender/makesdna/DNA_anim_types.h +++ b/source/blender/makesdna/DNA_anim_types.h @@ -612,9 +612,13 @@ typedef struct FCurve { char _pad[3]; /* RNA - data link */ - /** If applicable, the index of the RNA-array item to get. */ + /** When the RNA property from `rna_path` is an array, use this to access the array index. */ int array_index; - /** RNA-path to resolve data-access. */ + /** + * RNA-path to resolve data-access, see: #RNA_path_resolve_property. + * + * \note String look-ups for collection and custom-properties are escaped using #BLI_str_escape. + */ char *rna_path; /* curve coloring (for editor) */ diff --git a/source/blender/modifiers/intern/MOD_screw.c b/source/blender/modifiers/intern/MOD_screw.c index 94d5c402abe..ba370b401f3 100644 --- a/source/blender/modifiers/intern/MOD_screw.c +++ b/source/blender/modifiers/intern/MOD_screw.c @@ -701,8 +701,8 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * /*printf("flip direction %i\n", ed_loop_flip);*/ - /* switch the flip option if set - * note: flip is now done at face level so copying vgroup slizes is easier */ + /* Switch the flip option if set + * NOTE: flip is now done at face level so copying group slices is easier. */ #if 0 if (do_flip) { ed_loop_flip = !ed_loop_flip; -- cgit v1.2.3 From 8cc951d2aebe27651ba9a2b8a3ee4c59fafdb920 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 11 Dec 2020 14:59:08 +1100 Subject: Cleanup: trailing space --- source/blender/blenkernel/BKE_cryptomatte.h | 2 +- source/blender/draw/engines/eevee/shaders/cryptomatte_frag.glsl | 2 +- source/blender/editors/space_graph/graph_view.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/BKE_cryptomatte.h b/source/blender/blenkernel/BKE_cryptomatte.h index 9ad4770c754..929266d1b89 100644 --- a/source/blender/blenkernel/BKE_cryptomatte.h +++ b/source/blender/blenkernel/BKE_cryptomatte.h @@ -39,4 +39,4 @@ float BKE_cryptomatte_hash_to_float(uint32_t cryptomatte_hash); #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/source/blender/draw/engines/eevee/shaders/cryptomatte_frag.glsl b/source/blender/draw/engines/eevee/shaders/cryptomatte_frag.glsl index 1e499dbf991..9426b8e4a7b 100644 --- a/source/blender/draw/engines/eevee/shaders/cryptomatte_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/cryptomatte_frag.glsl @@ -4,4 +4,4 @@ out vec4 fragColor; void main() { fragColor = cryptohash; -} \ No newline at end of file +} diff --git a/source/blender/editors/space_graph/graph_view.c b/source/blender/editors/space_graph/graph_view.c index 0b9ba3762a3..cde0dab3503 100644 --- a/source/blender/editors/space_graph/graph_view.c +++ b/source/blender/editors/space_graph/graph_view.c @@ -533,4 +533,4 @@ void GRAPH_OT_ghost_curves_clear(wmOperatorType *ot) /* Flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; -} \ No newline at end of file +} -- cgit v1.2.3 From 392a8e2907ee1c08813258c1a477bbea060ba06d Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 11 Dec 2020 15:00:22 +1100 Subject: Cleanup: sort cmake file lists --- source/blender/blenkernel/CMakeLists.txt | 4 ++-- source/blender/editors/object/CMakeLists.txt | 2 +- source/blender/editors/space_graph/CMakeLists.txt | 2 +- source/blender/editors/space_node/CMakeLists.txt | 2 +- source/blender/editors/space_outliner/CMakeLists.txt | 6 +++--- source/blender/editors/space_view3d/CMakeLists.txt | 2 +- source/blender/editors/transform/CMakeLists.txt | 2 +- source/blender/editors/uvedit/CMakeLists.txt | 2 +- source/blender/modifiers/CMakeLists.txt | 2 +- source/blender/nodes/CMakeLists.txt | 12 ++++++------ source/blender/render/CMakeLists.txt | 2 +- source/blender/sequencer/CMakeLists.txt | 2 +- 12 files changed, 20 insertions(+), 20 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index c962f0a6a8c..65161317351 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -36,10 +36,10 @@ set(INC ../makesrna ../modifiers ../nodes + ../render ../sequencer ../shader_fx ../simulation - ../render ../../../intern/ghost ../../../intern/glew-mx ../../../intern/guardedalloc @@ -726,8 +726,8 @@ if(WITH_GTESTS) intern/armature_test.cc intern/fcurve_test.cc intern/lattice_deform_test.cc - intern/tracking_test.cc intern/layer_test.cc + intern/tracking_test.cc ) set(TEST_INC ../editors/include diff --git a/source/blender/editors/object/CMakeLists.txt b/source/blender/editors/object/CMakeLists.txt index a1be9b9df61..d872511ae03 100644 --- a/source/blender/editors/object/CMakeLists.txt +++ b/source/blender/editors/object/CMakeLists.txt @@ -31,8 +31,8 @@ set(INC ../../makesrna ../../modifiers ../../python - ../../shader_fx ../../render + ../../shader_fx ../../windowmanager ../../../../intern/clog ../../../../intern/glew-mx diff --git a/source/blender/editors/space_graph/CMakeLists.txt b/source/blender/editors/space_graph/CMakeLists.txt index 414e5c87f5a..2a795dd954c 100644 --- a/source/blender/editors/space_graph/CMakeLists.txt +++ b/source/blender/editors/space_graph/CMakeLists.txt @@ -34,8 +34,8 @@ set(SRC graph_draw.c graph_edit.c graph_ops.c - graph_slider_ops.c graph_select.c + graph_slider_ops.c graph_utils.c graph_view.c space_graph.c diff --git a/source/blender/editors/space_node/CMakeLists.txt b/source/blender/editors/space_node/CMakeLists.txt index d8f31161c20..f4a3bb96aeb 100644 --- a/source/blender/editors/space_node/CMakeLists.txt +++ b/source/blender/editors/space_node/CMakeLists.txt @@ -21,6 +21,7 @@ set(INC ../../blenkernel ../../blenlib ../../blentranslation + ../../compositor ../../depsgraph ../../draw ../../gpu @@ -29,7 +30,6 @@ set(INC ../../makesrna ../../nodes ../../render - ../../compositor ../../windowmanager ../../../../intern/glew-mx ../../../../intern/guardedalloc diff --git a/source/blender/editors/space_outliner/CMakeLists.txt b/source/blender/editors/space_outliner/CMakeLists.txt index 74f99540bee..8e989f5568e 100644 --- a/source/blender/editors/space_outliner/CMakeLists.txt +++ b/source/blender/editors/space_outliner/CMakeLists.txt @@ -46,12 +46,12 @@ set(SRC space_outliner.c tree/common.cc tree/tree_display.cc + tree/tree_display_data.cc tree/tree_display_libraries.cc - tree/tree_display_view_layer.cc - tree/tree_display_sequencer.cc tree/tree_display_orphaned.cc tree/tree_display_scenes.cc - tree/tree_display_data.cc + tree/tree_display_sequencer.cc + tree/tree_display_view_layer.cc tree/tree_element.cc tree/tree_element_anim_data.cc tree/tree_element_driver_base.cc diff --git a/source/blender/editors/space_view3d/CMakeLists.txt b/source/blender/editors/space_view3d/CMakeLists.txt index 0371b4e271f..9242fc15021 100644 --- a/source/blender/editors/space_view3d/CMakeLists.txt +++ b/source/blender/editors/space_view3d/CMakeLists.txt @@ -22,13 +22,13 @@ set(INC ../../blenlib ../../blentranslation ../../bmesh + ../../depsgraph ../../draw ../../gpu ../../imbuf ../../makesdna ../../makesrna ../../render - ../../depsgraph ../../windowmanager ../../../../intern/glew-mx ../../../../intern/guardedalloc diff --git a/source/blender/editors/transform/CMakeLists.txt b/source/blender/editors/transform/CMakeLists.txt index 73d6a376da6..a2eb68a1b71 100644 --- a/source/blender/editors/transform/CMakeLists.txt +++ b/source/blender/editors/transform/CMakeLists.txt @@ -22,12 +22,12 @@ set(INC ../../blenlib ../../blentranslation ../../bmesh + ../../depsgraph ../../gpu ../../ikplugin ../../makesdna ../../makesrna ../../render - ../../depsgraph ../../sequencer ../../windowmanager ../../../../intern/glew-mx diff --git a/source/blender/editors/uvedit/CMakeLists.txt b/source/blender/editors/uvedit/CMakeLists.txt index 8e4a3df920e..1c8a56e0608 100644 --- a/source/blender/editors/uvedit/CMakeLists.txt +++ b/source/blender/editors/uvedit/CMakeLists.txt @@ -35,11 +35,11 @@ set(INC set(SRC uvedit_buttons.c uvedit_draw.c + uvedit_islands.c uvedit_ops.c uvedit_parametrizer.c uvedit_path.c uvedit_rip.c - uvedit_islands.c uvedit_select.c uvedit_smart_stitch.c uvedit_unwrap_ops.c diff --git a/source/blender/modifiers/CMakeLists.txt b/source/blender/modifiers/CMakeLists.txt index 26f31412724..60c102de515 100644 --- a/source/blender/modifiers/CMakeLists.txt +++ b/source/blender/modifiers/CMakeLists.txt @@ -78,6 +78,7 @@ set(SRC intern/MOD_meshsequencecache.c intern/MOD_mirror.c intern/MOD_multires.c + intern/MOD_nodes.cc intern/MOD_none.c intern/MOD_normal_edit.c intern/MOD_ocean.c @@ -88,7 +89,6 @@ set(SRC intern/MOD_shapekey.c intern/MOD_shrinkwrap.c intern/MOD_simpledeform.c - intern/MOD_nodes.cc intern/MOD_skin.c intern/MOD_smooth.c intern/MOD_softbody.c diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index d09b1a8534d..87055a934fd 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -22,9 +22,9 @@ set(INC . composite function + geometry intern shader - geometry texture ../blenkernel ../blenlib @@ -140,15 +140,15 @@ set(SRC geometry/nodes/node_geo_attribute_fill.cc geometry/nodes/node_geo_attribute_math.cc - geometry/nodes/node_geo_common.cc geometry/nodes/node_geo_boolean.cc + geometry/nodes/node_geo_common.cc geometry/nodes/node_geo_edge_split.cc geometry/nodes/node_geo_join_geometry.cc geometry/nodes/node_geo_object_info.cc - geometry/nodes/node_geo_subdivision_surface.cc geometry/nodes/node_geo_point_distribute.cc geometry/nodes/node_geo_point_instance.cc geometry/nodes/node_geo_random_attribute.cc + geometry/nodes/node_geo_subdivision_surface.cc geometry/nodes/node_geo_transform.cc geometry/nodes/node_geo_triangulate.cc geometry/node_geometry_exec.cc @@ -296,12 +296,12 @@ set(SRC NOD_composite.h NOD_derived_node_tree.hh NOD_function.h + NOD_geometry.h + NOD_math_functions.hh NOD_node_tree_dependencies.hh NOD_node_tree_multi_function.hh NOD_node_tree_ref.hh NOD_shader.h - NOD_geometry.h - NOD_math_functions.hh NOD_socket.h NOD_static_types.h NOD_texture.h @@ -312,9 +312,9 @@ set(SRC ) set(LIB + bf_bmesh bf_functions bf_intern_sky - bf_bmesh ) if(WITH_PYTHON) diff --git a/source/blender/render/CMakeLists.txt b/source/blender/render/CMakeLists.txt index d1f69ddfc02..0046474d064 100644 --- a/source/blender/render/CMakeLists.txt +++ b/source/blender/render/CMakeLists.txt @@ -60,9 +60,9 @@ set(SRC RE_texture.h intern/initrender.h + intern/pipeline.h intern/render_result.h intern/render_types.h - intern/pipeline.h intern/texture_common.h intern/zbuf.h ) diff --git a/source/blender/sequencer/CMakeLists.txt b/source/blender/sequencer/CMakeLists.txt index 18755e7e6bc..db46fe91718 100644 --- a/source/blender/sequencer/CMakeLists.txt +++ b/source/blender/sequencer/CMakeLists.txt @@ -21,6 +21,7 @@ set(INC . intern + ../blenfont ../blenkernel ../blenlib ../blenloader @@ -30,7 +31,6 @@ set(INC ../makesdna ../makesrna ../render - ../blenfont ../windowmanager ../../../intern/atomic ../../../intern/guardedalloc -- cgit v1.2.3 From 219dba8506ffca7b5cc4ba0a849f9c3a9394334e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 11 Dec 2020 15:30:30 +1100 Subject: Workaround T83651: Crash dragging multiple buttons in the clip editor Avoid the crash, dragging multiple buttons still needs fixing. --- source/blender/editors/interface/interface_handlers.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source/blender') diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index f914ccd7497..bcb79743b12 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -1349,6 +1349,9 @@ static void ui_multibut_states_apply(bContext *C, uiHandleButtonData *data, uiBl if (mbut_state == NULL) { /* Highly unlikely. */ printf("%s: Can't find button\n", __func__); + /* While this avoids crashing, multi-button dragging will fail, + * which is still a bug from the user perspective. See T83651. */ + continue; } void *active_back; -- cgit v1.2.3 From 6e4fccd9fae37c20bc3b8ff52aeb5bf1328c56ad Mon Sep 17 00:00:00 2001 From: Evan Wilson Date: Fri, 11 Dec 2020 08:44:52 +0100 Subject: Correct the order of the last two arguments in `eevee_cryptomatte_shading_group_create` When compiling on Windows, the following warnings occur: ```[3468/4560] Building C object source\blender\draw\CMakeFiles\bf_draw.dir\engines\eevee\eevee_cryptomatte.c.obj C:\blender-git\blender\source\blender\draw\engines\eevee\eevee_cryptomatte.c(306): warning C4047: 'function': 'bool' differs in levels of indirection from 'void *' C:\blender-git\blender\source\blender\draw\engines\eevee\eevee_cryptomatte.c(306): warning C4024: 'eevee_cryptomatte_shading_group_create': different types for formal and actual parameter 5``` As @Severin pointed out [here](https://developer.blender.org/rB76a0b322e4d3244e59a154c8255b84a4fbc33117#288960), this is due to the last two arguments being flipped. This diff corrects the order. Reviewed By: Severin, fclem Differential Revision: https://developer.blender.org/D9809 --- source/blender/draw/engines/eevee/eevee_cryptomatte.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender') diff --git a/source/blender/draw/engines/eevee/eevee_cryptomatte.c b/source/blender/draw/engines/eevee/eevee_cryptomatte.c index 44ff86b3333..95f5aa8b628 100644 --- a/source/blender/draw/engines/eevee/eevee_cryptomatte.c +++ b/source/blender/draw/engines/eevee/eevee_cryptomatte.c @@ -303,7 +303,7 @@ void EEVEE_cryptomatte_cache_populate(EEVEE_Data *vedata, EEVEE_ViewLayerData *s GPUBatch *geom = DRW_cache_object_surface_get(ob); if (geom) { DRWShadingGroup *grp = eevee_cryptomatte_shading_group_create( - vedata, sldata, ob, false, NULL); + vedata, sldata, ob, NULL, false); DRW_shgroup_call(grp, geom, ob); } } -- cgit v1.2.3 From b62a9ef66faad1ba37dde053af3394eca9559e46 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Fri, 11 Dec 2020 09:37:29 +0100 Subject: Cleanup: Fix typo in comment. --- source/blender/editors/interface/interface_layout.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender') diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index 0403287125c..ebd2235cb82 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -651,7 +651,7 @@ static void ui_item_array(uiLayout *layout, uiDefAutoButR(block, ptr, prop, -1, "", ICON_NONE, 0, 0, w, UI_UNIT_Y); } else { - /* even if 'expand' is fale, expanding anyway */ + /* Even if 'expand' is false, we expand anyway. */ /* layout for known array subtypes */ char str[3] = {'\0'}; -- cgit v1.2.3 From f7e5f96f56b1594c718232a9541c35389f23abab Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Fri, 11 Dec 2020 10:52:23 +0100 Subject: GeometryNodes: Make properties exposed in modifier overridable. --- source/blender/blenloader/intern/versioning_290.c | 15 +++++++++++++++ source/blender/modifiers/intern/MOD_nodes.cc | 2 ++ 2 files changed, 17 insertions(+) (limited to 'source/blender') diff --git a/source/blender/blenloader/intern/versioning_290.c b/source/blender/blenloader/intern/versioning_290.c index a98e7c46f10..f390f0b48d8 100644 --- a/source/blender/blenloader/intern/versioning_290.c +++ b/source/blender/blenloader/intern/versioning_290.c @@ -1243,5 +1243,20 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain) */ { /* Keep this block, even when empty. */ + + /* Make all IDProperties used as interface of geometry node trees overridable. */ + LISTBASE_FOREACH (Object *, ob, &bmain->objects) { + LISTBASE_FOREACH (ModifierData *, md, &ob->modifiers) { + if (md->type == eModifierType_Nodes) { + NodesModifierData *nmd = (NodesModifierData *)md; + IDProperty *nmd_properties = nmd->settings.properties; + + BLI_assert(nmd_properties->type == IDP_GROUP); + LISTBASE_FOREACH (IDProperty *, nmd_socket_idprop, &nmd_properties->data.group) { + nmd_socket_idprop->flag |= IDP_FLAG_OVERRIDABLE_LIBRARY; + } + } + } + } } } diff --git a/source/blender/modifiers/intern/MOD_nodes.cc b/source/blender/modifiers/intern/MOD_nodes.cc index 35cb1dc7410..29ed08f0367 100644 --- a/source/blender/modifiers/intern/MOD_nodes.cc +++ b/source/blender/modifiers/intern/MOD_nodes.cc @@ -439,6 +439,8 @@ static IDProperty *socket_add_property(IDProperty *settings_prop_group, IDProperty *prop = property_type.create_prop(socket, new_prop_name); IDP_AddToGroup(settings_prop_group, prop); + prop->flag |= IDP_FLAG_OVERRIDABLE_LIBRARY; + /* Make the group in the ui container group to hold the property's UI settings. */ IDProperty *prop_ui_group; { -- cgit v1.2.3 From f5c72467176c1f5e8922c86c697e58861cf782a4 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Fri, 11 Dec 2020 11:05:28 +0100 Subject: Fix wrong operator return values in Outliner code. Mistakes in rBac8b641b77e0 and rBf254f66587f2. Spotted while inverstigating T83592. --- source/blender/editors/space_outliner/outliner_tools.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c index 159a4616ba7..098a0edb614 100644 --- a/source/blender/editors/space_outliner/outliner_tools.c +++ b/source/blender/editors/space_outliner/outliner_tools.c @@ -2791,7 +2791,7 @@ static int do_outliner_operation_event(bContext *C, } if (datalevel == TSE_ID_BASE) { /* do nothing... there are no ops needed here yet */ - return 0; + return OPERATOR_CANCELLED; } if (datalevel == TSE_CONSTRAINT) { return outliner_operator_menu(C, "OUTLINER_OT_constraint_operation"); @@ -2802,7 +2802,7 @@ static int do_outliner_operation_event(bContext *C, return outliner_operator_menu(C, "OUTLINER_OT_data_operation"); } - return 0; + return OPERATOR_CANCELLED; } static int outliner_operation(bContext *C, wmOperator *op, const wmEvent *event) -- cgit v1.2.3 From 150a1d158a79582802bb17dacdd790f0f88aeedb Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Fri, 11 Dec 2020 11:48:58 +0100 Subject: Cleanup: remove some forward declared enums Forward declaring enums are not allowed in C++. Differential Revision: https://developer.blender.org/D9811 --- source/blender/CMakeLists.txt | 1 + source/blender/blenkernel/BKE_multires.h | 3 +- source/blender/blenkernel/BKE_paint.h | 3 +- source/blender/makesdna/DNA_brush_enums.h | 613 ++++++++++++++++++++++++++++++ source/blender/makesdna/DNA_brush_types.h | 585 +--------------------------- 5 files changed, 617 insertions(+), 588 deletions(-) create mode 100644 source/blender/makesdna/DNA_brush_enums.h (limited to 'source/blender') diff --git a/source/blender/CMakeLists.txt b/source/blender/CMakeLists.txt index da6df831c0a..c38da14be96 100644 --- a/source/blender/CMakeLists.txt +++ b/source/blender/CMakeLists.txt @@ -24,6 +24,7 @@ set(SRC_DNA_INC ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_anim_types.h ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_armature_types.h ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_boid_types.h + ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_brush_enums.h ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_brush_types.h ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_cachefile_types.h ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_camera_types.h diff --git a/source/blender/blenkernel/BKE_multires.h b/source/blender/blenkernel/BKE_multires.h index 5a668532033..fce25abba7f 100644 --- a/source/blender/blenkernel/BKE_multires.h +++ b/source/blender/blenkernel/BKE_multires.h @@ -23,14 +23,13 @@ * \ingroup bke */ +#include "BKE_subsurf.h" #include "BLI_compiler_compat.h" #ifdef __cplusplus extern "C" { #endif -enum MultiresModifiedFlags; - struct Depsgraph; struct DerivedMesh; struct MDisps; diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h index 479bc56b2dc..0a50dde1874 100644 --- a/source/blender/blenkernel/BKE_paint.h +++ b/source/blender/blenkernel/BKE_paint.h @@ -25,6 +25,7 @@ #include "BLI_bitmap.h" #include "BLI_utildefines.h" +#include "DNA_brush_enums.h" #include "DNA_object_enums.h" #ifdef __cplusplus @@ -70,8 +71,6 @@ struct BlendWriter; struct BlendDataReader; struct BlendLibReader; -enum eOverlayFlags; - extern const char PAINT_CURSOR_SCULPT[3]; extern const char PAINT_CURSOR_VERTEX_PAINT[3]; extern const char PAINT_CURSOR_WEIGHT_PAINT[3]; diff --git a/source/blender/makesdna/DNA_brush_enums.h b/source/blender/makesdna/DNA_brush_enums.h new file mode 100644 index 00000000000..96e870cff8e --- /dev/null +++ b/source/blender/makesdna/DNA_brush_enums.h @@ -0,0 +1,613 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** \file + * \ingroup DNA + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +/* BrushGpencilSettings->preset_type. + * Use a range for each group and not continuous values.*/ +typedef enum eGPBrush_Presets { + GP_BRUSH_PRESET_UNKNOWN = 0, + + /* Draw 1-99. */ + GP_BRUSH_PRESET_AIRBRUSH = 1, + GP_BRUSH_PRESET_INK_PEN = 2, + GP_BRUSH_PRESET_INK_PEN_ROUGH = 3, + GP_BRUSH_PRESET_MARKER_BOLD = 4, + GP_BRUSH_PRESET_MARKER_CHISEL = 5, + GP_BRUSH_PRESET_PEN = 6, + GP_BRUSH_PRESET_PENCIL_SOFT = 7, + GP_BRUSH_PRESET_PENCIL = 8, + GP_BRUSH_PRESET_FILL_AREA = 9, + GP_BRUSH_PRESET_ERASER_SOFT = 10, + GP_BRUSH_PRESET_ERASER_HARD = 11, + GP_BRUSH_PRESET_ERASER_POINT = 12, + GP_BRUSH_PRESET_ERASER_STROKE = 13, + GP_BRUSH_PRESET_TINT = 14, + + /* Vertex Paint 100-199. */ + GP_BRUSH_PRESET_VERTEX_DRAW = 100, + GP_BRUSH_PRESET_VERTEX_BLUR = 101, + GP_BRUSH_PRESET_VERTEX_AVERAGE = 102, + GP_BRUSH_PRESET_VERTEX_SMEAR = 103, + GP_BRUSH_PRESET_VERTEX_REPLACE = 104, + + /* Sculpt 200-299. */ + GP_BRUSH_PRESET_SMOOTH_STROKE = 200, + GP_BRUSH_PRESET_STRENGTH_STROKE = 201, + GP_BRUSH_PRESET_THICKNESS_STROKE = 202, + GP_BRUSH_PRESET_GRAB_STROKE = 203, + GP_BRUSH_PRESET_PUSH_STROKE = 204, + GP_BRUSH_PRESET_TWIST_STROKE = 205, + GP_BRUSH_PRESET_PINCH_STROKE = 206, + GP_BRUSH_PRESET_RANDOMIZE_STROKE = 207, + GP_BRUSH_PRESET_CLONE_STROKE = 208, + + /* Weight Paint 300-399. */ + GP_BRUSH_PRESET_DRAW_WEIGHT = 300, +} eGPBrush_Presets; + +/* BrushGpencilSettings->flag */ +typedef enum eGPDbrush_Flag { + /* brush use pressure */ + GP_BRUSH_USE_PRESSURE = (1 << 0), + /* brush use pressure for alpha factor */ + GP_BRUSH_USE_STRENGTH_PRESSURE = (1 << 1), + /* brush use pressure for alpha factor */ + GP_BRUSH_USE_JITTER_PRESSURE = (1 << 2), + /* fill hide transparent */ + GP_BRUSH_FILL_HIDE = (1 << 6), + /* show fill help lines */ + GP_BRUSH_FILL_SHOW_HELPLINES = (1 << 7), + /* lazy mouse */ + GP_BRUSH_STABILIZE_MOUSE = (1 << 8), + /* lazy mouse override (internal only) */ + GP_BRUSH_STABILIZE_MOUSE_TEMP = (1 << 9), + /* default eraser brush for quick switch */ + GP_BRUSH_DEFAULT_ERASER = (1 << 10), + /* settings group */ + GP_BRUSH_GROUP_SETTINGS = (1 << 11), + /* Random settings group */ + GP_BRUSH_GROUP_RANDOM = (1 << 12), + /* Keep material assigned to brush */ + GP_BRUSH_MATERIAL_PINNED = (1 << 13), + /* Do not show fill color while drawing (no lasso mode) */ + GP_BRUSH_DISSABLE_LASSO = (1 << 14), + /* Do not erase strokes oLcluded */ + GP_BRUSH_OCCLUDE_ERASER = (1 << 15), + /* Post process trim stroke */ + GP_BRUSH_TRIM_STROKE = (1 << 16), +} eGPDbrush_Flag; + +typedef enum eGPDbrush_Flag2 { + /* Brush use random Hue at stroke level */ + GP_BRUSH_USE_HUE_AT_STROKE = (1 << 0), + /* Brush use random Saturation at stroke level */ + GP_BRUSH_USE_SAT_AT_STROKE = (1 << 1), + /* Brush use random Value at stroke level */ + GP_BRUSH_USE_VAL_AT_STROKE = (1 << 2), + /* Brush use random Pressure at stroke level */ + GP_BRUSH_USE_PRESS_AT_STROKE = (1 << 3), + /* Brush use random Strength at stroke level */ + GP_BRUSH_USE_STRENGTH_AT_STROKE = (1 << 4), + /* Brush use random UV at stroke level */ + GP_BRUSH_USE_UV_AT_STROKE = (1 << 5), + /* Brush use Hue random pressure */ + GP_BRUSH_USE_HUE_RAND_PRESS = (1 << 6), + /* Brush use Saturation random pressure */ + GP_BRUSH_USE_SAT_RAND_PRESS = (1 << 7), + /* Brush use Value random pressure */ + GP_BRUSH_USE_VAL_RAND_PRESS = (1 << 8), + /* Brush use Pressure random pressure */ + GP_BRUSH_USE_PRESSURE_RAND_PRESS = (1 << 9), + /* Brush use Strength random pressure */ + GP_BRUSH_USE_STRENGTH_RAND_PRESS = (1 << 10), + /* Brush use UV random pressure */ + GP_BRUSH_USE_UV_RAND_PRESS = (1 << 11), +} eGPDbrush_Flag2; + +/* BrushGpencilSettings->gp_fill_draw_mode */ +typedef enum eGP_FillDrawModes { + GP_FILL_DMODE_BOTH = 0, + GP_FILL_DMODE_STROKE = 1, + GP_FILL_DMODE_CONTROL = 2, +} eGP_FillDrawModes; + +/* BrushGpencilSettings->fill_layer_mode */ +typedef enum eGP_FillLayerModes { + GP_FILL_GPLMODE_VISIBLE = 0, + GP_FILL_GPLMODE_ACTIVE = 1, + GP_FILL_GPLMODE_ALL_ABOVE = 2, + GP_FILL_GPLMODE_ALL_BELOW = 3, + GP_FILL_GPLMODE_ABOVE = 4, + GP_FILL_GPLMODE_BELOW = 5, +} eGP_FillLayerModes; + +/* BrushGpencilSettings->gp_eraser_mode */ +typedef enum eGP_BrushEraserMode { + GP_BRUSH_ERASER_SOFT = 0, + GP_BRUSH_ERASER_HARD = 1, + GP_BRUSH_ERASER_STROKE = 2, +} eGP_BrushEraserMode; + +/* BrushGpencilSettings->brush_draw_mode */ +typedef enum eGP_BrushMode { + GP_BRUSH_MODE_ACTIVE = 0, + GP_BRUSH_MODE_MATERIAL = 1, + GP_BRUSH_MODE_VERTEXCOLOR = 2, +} eGP_BrushMode; + +/* BrushGpencilSettings default brush icons */ +typedef enum eGP_BrushIcons { + GP_BRUSH_ICON_PENCIL = 1, + GP_BRUSH_ICON_PEN = 2, + GP_BRUSH_ICON_INK = 3, + GP_BRUSH_ICON_INKNOISE = 4, + GP_BRUSH_ICON_BLOCK = 5, + GP_BRUSH_ICON_MARKER = 6, + GP_BRUSH_ICON_FILL = 7, + GP_BRUSH_ICON_ERASE_SOFT = 8, + GP_BRUSH_ICON_ERASE_HARD = 9, + GP_BRUSH_ICON_ERASE_STROKE = 10, + GP_BRUSH_ICON_AIRBRUSH = 11, + GP_BRUSH_ICON_CHISEL = 12, + GP_BRUSH_ICON_TINT = 13, + GP_BRUSH_ICON_VERTEX_DRAW = 14, + GP_BRUSH_ICON_VERTEX_BLUR = 15, + GP_BRUSH_ICON_VERTEX_AVERAGE = 16, + GP_BRUSH_ICON_VERTEX_SMEAR = 17, + GP_BRUSH_ICON_VERTEX_REPLACE = 18, + GP_BRUSH_ICON_GPBRUSH_SMOOTH = 19, + GP_BRUSH_ICON_GPBRUSH_THICKNESS = 20, + GP_BRUSH_ICON_GPBRUSH_STRENGTH = 21, + GP_BRUSH_ICON_GPBRUSH_RANDOMIZE = 22, + GP_BRUSH_ICON_GPBRUSH_GRAB = 23, + GP_BRUSH_ICON_GPBRUSH_PUSH = 24, + GP_BRUSH_ICON_GPBRUSH_TWIST = 25, + GP_BRUSH_ICON_GPBRUSH_PINCH = 26, + GP_BRUSH_ICON_GPBRUSH_CLONE = 27, + GP_BRUSH_ICON_GPBRUSH_WEIGHT = 28, +} eGP_BrushIcons; + +typedef enum eBrushCurvePreset { + BRUSH_CURVE_CUSTOM = 0, + BRUSH_CURVE_SMOOTH = 1, + BRUSH_CURVE_SPHERE = 2, + BRUSH_CURVE_ROOT = 3, + BRUSH_CURVE_SHARP = 4, + BRUSH_CURVE_LIN = 5, + BRUSH_CURVE_POW4 = 6, + BRUSH_CURVE_INVSQUARE = 7, + BRUSH_CURVE_CONSTANT = 8, + BRUSH_CURVE_SMOOTHER = 9, +} eBrushCurvePreset; + +typedef enum eBrushDeformTarget { + BRUSH_DEFORM_TARGET_GEOMETRY = 0, + BRUSH_DEFORM_TARGET_CLOTH_SIM = 1, +} eBrushDeformTarget; + +typedef enum eBrushElasticDeformType { + BRUSH_ELASTIC_DEFORM_GRAB = 0, + BRUSH_ELASTIC_DEFORM_GRAB_BISCALE = 1, + BRUSH_ELASTIC_DEFORM_GRAB_TRISCALE = 2, + BRUSH_ELASTIC_DEFORM_SCALE = 3, + BRUSH_ELASTIC_DEFORM_TWIST = 4, +} eBrushElasticDeformType; + +typedef enum eBrushClothDeformType { + BRUSH_CLOTH_DEFORM_DRAG = 0, + BRUSH_CLOTH_DEFORM_PUSH = 1, + BRUSH_CLOTH_DEFORM_GRAB = 2, + BRUSH_CLOTH_DEFORM_PINCH_POINT = 3, + BRUSH_CLOTH_DEFORM_PINCH_PERPENDICULAR = 4, + BRUSH_CLOTH_DEFORM_INFLATE = 5, + BRUSH_CLOTH_DEFORM_EXPAND = 6, + BRUSH_CLOTH_DEFORM_SNAKE_HOOK = 7, +} eBrushClothDeformType; + +typedef enum eBrushSmoothDeformType { + BRUSH_SMOOTH_DEFORM_LAPLACIAN = 0, + BRUSH_SMOOTH_DEFORM_SURFACE = 1, +} eBrushSmoothDeformType; + +typedef enum eBrushClothForceFalloffType { + BRUSH_CLOTH_FORCE_FALLOFF_RADIAL = 0, + BRUSH_CLOTH_FORCE_FALLOFF_PLANE = 1, +} eBrushClothForceFalloffType; + +typedef enum eBrushClothSimulationAreaType { + BRUSH_CLOTH_SIMULATION_AREA_LOCAL = 0, + BRUSH_CLOTH_SIMULATION_AREA_GLOBAL = 1, + BRUSH_CLOTH_SIMULATION_AREA_DYNAMIC = 2, +} eBrushClothSimulationAreaType; + +typedef enum eBrushPoseDeformType { + BRUSH_POSE_DEFORM_ROTATE_TWIST = 0, + BRUSH_POSE_DEFORM_SCALE_TRASLATE = 1, + BRUSH_POSE_DEFORM_SQUASH_STRETCH = 2, +} eBrushPoseDeformType; + +typedef enum eBrushPoseOriginType { + BRUSH_POSE_ORIGIN_TOPOLOGY = 0, + BRUSH_POSE_ORIGIN_FACE_SETS = 1, + BRUSH_POSE_ORIGIN_FACE_SETS_FK = 2, +} eBrushPoseOriginType; + +typedef enum eBrushSmearDeformType { + BRUSH_SMEAR_DEFORM_DRAG = 0, + BRUSH_SMEAR_DEFORM_PINCH = 1, + BRUSH_SMEAR_DEFORM_EXPAND = 2, +} eBrushSmearDeformType; + +typedef enum eBrushSlideDeformType { + BRUSH_SLIDE_DEFORM_DRAG = 0, + BRUSH_SLIDE_DEFORM_PINCH = 1, + BRUSH_SLIDE_DEFORM_EXPAND = 2, +} eBrushSlideDeformType; + +typedef enum eBrushBoundaryDeformType { + BRUSH_BOUNDARY_DEFORM_BEND = 0, + BRUSH_BOUNDARY_DEFORM_EXPAND = 1, + BRUSH_BOUNDARY_DEFORM_INFLATE = 2, + BRUSH_BOUNDARY_DEFORM_GRAB = 3, + BRUSH_BOUNDARY_DEFORM_TWIST = 4, + BRUSH_BOUNDARY_DEFORM_SMOOTH = 5, +} eBrushBushBoundaryDeformType; + +typedef enum eBrushBoundaryFalloffType { + BRUSH_BOUNDARY_FALLOFF_CONSTANT = 0, + BRUSH_BOUNDARY_FALLOFF_RADIUS = 1, + BRUSH_BOUNDARY_FALLOFF_LOOP = 2, + BRUSH_BOUNDARY_FALLOFF_LOOP_INVERT = 3, +} eBrushBoundaryFalloffType; + +typedef enum eBrushSnakeHookDeformType { + BRUSH_SNAKE_HOOK_DEFORM_FALLOFF = 0, + BRUSH_SNAKE_HOOK_DEFORM_ELASTIC = 1, +} eBrushSnakeHookDeformType; + +/* Gpencilsettings.Vertex_mode */ +typedef enum eGp_Vertex_Mode { + /* Affect to Stroke only. */ + GPPAINT_MODE_STROKE = 0, + /* Affect to Fill only. */ + GPPAINT_MODE_FILL = 1, + /* Affect to both. */ + GPPAINT_MODE_BOTH = 2, +} eGp_Vertex_Mode; + +/* sculpt_flag */ +typedef enum eGP_Sculpt_Flag { + /* invert the effect of the brush */ + GP_SCULPT_FLAG_INVERT = (1 << 0), + /* smooth brush affects pressure values as well */ + GP_SCULPT_FLAG_SMOOTH_PRESSURE = (1 << 2), + /* temporary invert action */ + GP_SCULPT_FLAG_TMP_INVERT = (1 << 3), +} eGP_Sculpt_Flag; + +/* sculpt_mode_flag */ +typedef enum eGP_Sculpt_Mode_Flag { + /* apply brush to position */ + GP_SCULPT_FLAGMODE_APPLY_POSITION = (1 << 0), + /* apply brush to strength */ + GP_SCULPT_FLAGMODE_APPLY_STRENGTH = (1 << 1), + /* apply brush to thickness */ + GP_SCULPT_FLAGMODE_APPLY_THICKNESS = (1 << 2), + /* apply brush to uv data */ + GP_SCULPT_FLAGMODE_APPLY_UV = (1 << 3), +} eGP_Sculpt_Mode_Flag; + +typedef enum eAutomasking_flag { + BRUSH_AUTOMASKING_TOPOLOGY = (1 << 0), + BRUSH_AUTOMASKING_FACE_SETS = (1 << 1), + BRUSH_AUTOMASKING_BOUNDARY_EDGES = (1 << 2), + BRUSH_AUTOMASKING_BOUNDARY_FACE_SETS = (1 << 3), +} eAutomasking_flag; + +typedef enum ePaintBrush_flag { + BRUSH_PAINT_HARDNESS_PRESSURE = (1 << 0), + BRUSH_PAINT_HARDNESS_PRESSURE_INVERT = (1 << 1), + BRUSH_PAINT_FLOW_PRESSURE = (1 << 2), + BRUSH_PAINT_FLOW_PRESSURE_INVERT = (1 << 3), + BRUSH_PAINT_WET_MIX_PRESSURE = (1 << 4), + BRUSH_PAINT_WET_MIX_PRESSURE_INVERT = (1 << 5), + BRUSH_PAINT_WET_PERSISTENCE_PRESSURE = (1 << 6), + BRUSH_PAINT_WET_PERSISTENCE_PRESSURE_INVERT = (1 << 7), + BRUSH_PAINT_DENSITY_PRESSURE = (1 << 8), + BRUSH_PAINT_DENSITY_PRESSURE_INVERT = (1 << 9), +} ePaintBrush_flag; + +/* Brush.gradient_source */ +typedef enum eBrushGradientSourceStroke { + BRUSH_GRADIENT_PRESSURE = 0, /* gradient from pressure */ + BRUSH_GRADIENT_SPACING_REPEAT = 1, /* gradient from spacing */ + BRUSH_GRADIENT_SPACING_CLAMP = 2, /* gradient from spacing */ +} eBrushGradientSourceStroke; + +typedef enum eBrushGradientSourceFill { + BRUSH_GRADIENT_LINEAR = 0, /* gradient from pressure */ + BRUSH_GRADIENT_RADIAL = 1, /* gradient from spacing */ +} eBrushGradientSourceFill; + +/* Brush.flag */ +typedef enum eBrushFlags { + BRUSH_AIRBRUSH = (1 << 0), + BRUSH_INVERT_TO_SCRAPE_FILL = (1 << 1), + BRUSH_ALPHA_PRESSURE = (1 << 2), + BRUSH_SIZE_PRESSURE = (1 << 3), + BRUSH_JITTER_PRESSURE = (1 << 4), + BRUSH_SPACING_PRESSURE = (1 << 5), + BRUSH_ORIGINAL_PLANE = (1 << 6), + BRUSH_GRAB_ACTIVE_VERTEX = (1 << 7), + BRUSH_ANCHORED = (1 << 8), + BRUSH_DIR_IN = (1 << 9), + BRUSH_SPACE = (1 << 10), + BRUSH_SMOOTH_STROKE = (1 << 11), + BRUSH_PERSISTENT = (1 << 12), + BRUSH_ACCUMULATE = (1 << 13), + BRUSH_LOCK_ALPHA = (1 << 14), + BRUSH_ORIGINAL_NORMAL = (1 << 15), + BRUSH_OFFSET_PRESSURE = (1 << 16), + BRUSH_SCENE_SPACING = (1 << 17), + BRUSH_SPACE_ATTEN = (1 << 18), + BRUSH_ADAPTIVE_SPACE = (1 << 19), + BRUSH_LOCK_SIZE = (1 << 20), + BRUSH_USE_GRADIENT = (1 << 21), + BRUSH_EDGE_TO_EDGE = (1 << 22), + BRUSH_DRAG_DOT = (1 << 23), + BRUSH_INVERSE_SMOOTH_PRESSURE = (1 << 24), + BRUSH_FRONTFACE_FALLOFF = (1 << 25), + BRUSH_PLANE_TRIM = (1 << 26), + BRUSH_FRONTFACE = (1 << 27), + BRUSH_CUSTOM_ICON = (1 << 28), + BRUSH_LINE = (1 << 29), + BRUSH_ABSOLUTE_JITTER = (1 << 30), + BRUSH_CURVE = (1u << 31), +} eBrushFlags; + +/* Brush.sampling_flag */ +typedef enum eBrushSamplingFlags { + BRUSH_PAINT_ANTIALIASING = (1 << 0), +} eBrushSamplingFlags; + +/* Brush.flag2 */ +typedef enum eBrushFlags2 { + BRUSH_MULTIPLANE_SCRAPE_DYNAMIC = (1 << 0), + BRUSH_MULTIPLANE_SCRAPE_PLANES_PREVIEW = (1 << 1), + BRUSH_POSE_IK_ANCHORED = (1 << 2), + BRUSH_USE_CONNECTED_ONLY = (1 << 3), + BRUSH_CLOTH_PIN_SIMULATION_BOUNDARY = (1 << 4), + BRUSH_POSE_USE_LOCK_ROTATION = (1 << 5), + BRUSH_CLOTH_USE_COLLISION = (1 << 6), + BRUSH_AREA_RADIUS_PRESSURE = (1 << 7), + BRUSH_GRAB_SILHOUETTE = (1 << 8), +} eBrushFlags2; + +typedef enum { + BRUSH_MASK_PRESSURE_RAMP = (1 << 1), + BRUSH_MASK_PRESSURE_CUTOFF = (1 << 2), +} BrushMaskPressureFlags; + +/* Brush.overlay_flags */ +typedef enum eOverlayFlags { + BRUSH_OVERLAY_CURSOR = (1), + BRUSH_OVERLAY_PRIMARY = (1 << 1), + BRUSH_OVERLAY_SECONDARY = (1 << 2), + BRUSH_OVERLAY_CURSOR_OVERRIDE_ON_STROKE = (1 << 3), + BRUSH_OVERLAY_PRIMARY_OVERRIDE_ON_STROKE = (1 << 4), + BRUSH_OVERLAY_SECONDARY_OVERRIDE_ON_STROKE = (1 << 5), +} eOverlayFlags; + +#define BRUSH_OVERLAY_OVERRIDE_MASK \ + (BRUSH_OVERLAY_CURSOR_OVERRIDE_ON_STROKE | BRUSH_OVERLAY_PRIMARY_OVERRIDE_ON_STROKE | \ + BRUSH_OVERLAY_SECONDARY_OVERRIDE_ON_STROKE) + +/* Brush.sculpt_tool */ +typedef enum eBrushSculptTool { + SCULPT_TOOL_DRAW = 1, + SCULPT_TOOL_SMOOTH = 2, + SCULPT_TOOL_PINCH = 3, + SCULPT_TOOL_INFLATE = 4, + SCULPT_TOOL_GRAB = 5, + SCULPT_TOOL_LAYER = 6, + SCULPT_TOOL_FLATTEN = 7, + SCULPT_TOOL_CLAY = 8, + SCULPT_TOOL_FILL = 9, + SCULPT_TOOL_SCRAPE = 10, + SCULPT_TOOL_NUDGE = 11, + SCULPT_TOOL_THUMB = 12, + SCULPT_TOOL_SNAKE_HOOK = 13, + SCULPT_TOOL_ROTATE = 14, + SCULPT_TOOL_SIMPLIFY = 15, + SCULPT_TOOL_CREASE = 16, + SCULPT_TOOL_BLOB = 17, + SCULPT_TOOL_CLAY_STRIPS = 18, + SCULPT_TOOL_MASK = 19, + SCULPT_TOOL_DRAW_SHARP = 20, + SCULPT_TOOL_ELASTIC_DEFORM = 21, + SCULPT_TOOL_POSE = 22, + SCULPT_TOOL_MULTIPLANE_SCRAPE = 23, + SCULPT_TOOL_SLIDE_RELAX = 24, + SCULPT_TOOL_CLAY_THUMB = 25, + SCULPT_TOOL_CLOTH = 26, + SCULPT_TOOL_DRAW_FACE_SETS = 27, + SCULPT_TOOL_PAINT = 28, + SCULPT_TOOL_SMEAR = 29, + SCULPT_TOOL_BOUNDARY = 30, + SCULPT_TOOL_DISPLACEMENT_ERASER = 31, +} eBrushSculptTool; + +/* Brush.uv_sculpt_tool */ +typedef enum eBrushUVSculptTool { + UV_SCULPT_TOOL_GRAB = 0, + UV_SCULPT_TOOL_RELAX = 1, + UV_SCULPT_TOOL_PINCH = 2, +} eBrushUVSculptTool; + +/** When #BRUSH_ACCUMULATE is used */ +#define SCULPT_TOOL_HAS_ACCUMULATE(t) \ + ELEM(t, \ + SCULPT_TOOL_DRAW, \ + SCULPT_TOOL_DRAW_SHARP, \ + SCULPT_TOOL_SLIDE_RELAX, \ + SCULPT_TOOL_CREASE, \ + SCULPT_TOOL_BLOB, \ + SCULPT_TOOL_INFLATE, \ + SCULPT_TOOL_CLAY, \ + SCULPT_TOOL_CLAY_STRIPS, \ + SCULPT_TOOL_CLAY_THUMB, \ + SCULPT_TOOL_ROTATE, \ + SCULPT_TOOL_SCRAPE, \ + SCULPT_TOOL_FLATTEN) + +#define SCULPT_TOOL_HAS_NORMAL_WEIGHT(t) \ + ELEM(t, SCULPT_TOOL_GRAB, SCULPT_TOOL_SNAKE_HOOK, SCULPT_TOOL_ELASTIC_DEFORM) + +#define SCULPT_TOOL_HAS_RAKE(t) ELEM(t, SCULPT_TOOL_SNAKE_HOOK) + +#define SCULPT_TOOL_HAS_DYNTOPO(t) \ + (ELEM(t, /* These brushes, as currently coded, cannot support dynamic topology */ \ + SCULPT_TOOL_GRAB, \ + SCULPT_TOOL_ROTATE, \ + SCULPT_TOOL_CLOTH, \ + SCULPT_TOOL_THUMB, \ + SCULPT_TOOL_LAYER, \ + SCULPT_TOOL_DISPLACEMENT_ERASER, \ + SCULPT_TOOL_DRAW_SHARP, \ + SCULPT_TOOL_SLIDE_RELAX, \ + SCULPT_TOOL_ELASTIC_DEFORM, \ + SCULPT_TOOL_BOUNDARY, \ + SCULPT_TOOL_POSE, \ + SCULPT_TOOL_DRAW_FACE_SETS, \ + SCULPT_TOOL_PAINT, \ + SCULPT_TOOL_SMEAR, \ +\ + /* These brushes could handle dynamic topology, \ \ + * but user feedback indicates it's better not to */ \ + SCULPT_TOOL_SMOOTH, \ + SCULPT_TOOL_MASK) == 0) + +#define SCULPT_TOOL_HAS_TOPOLOGY_RAKE(t) \ + (ELEM(t, /* These brushes, as currently coded, cannot support topology rake. */ \ + SCULPT_TOOL_GRAB, \ + SCULPT_TOOL_ROTATE, \ + SCULPT_TOOL_THUMB, \ + SCULPT_TOOL_DRAW_SHARP, \ + SCULPT_TOOL_DISPLACEMENT_ERASER, \ + SCULPT_TOOL_SLIDE_RELAX, \ + SCULPT_TOOL_MASK) == 0) + +/* ImagePaintSettings.tool */ +typedef enum eBrushImagePaintTool { + PAINT_TOOL_DRAW = 0, + PAINT_TOOL_SOFTEN = 1, + PAINT_TOOL_SMEAR = 2, + PAINT_TOOL_CLONE = 3, + PAINT_TOOL_FILL = 4, + PAINT_TOOL_MASK = 5, +} eBrushImagePaintTool; + +typedef enum eBrushVertexPaintTool { + VPAINT_TOOL_DRAW = 0, + VPAINT_TOOL_BLUR = 1, + VPAINT_TOOL_AVERAGE = 2, + VPAINT_TOOL_SMEAR = 3, +} eBrushVertexPaintTool; + +typedef enum eBrushWeightPaintTool { + WPAINT_TOOL_DRAW = 0, + WPAINT_TOOL_BLUR = 1, + WPAINT_TOOL_AVERAGE = 2, + WPAINT_TOOL_SMEAR = 3, +} eBrushWeightPaintTool; + +/* BrushGpencilSettings->brush type */ +typedef enum eBrushGPaintTool { + GPAINT_TOOL_DRAW = 0, + GPAINT_TOOL_FILL = 1, + GPAINT_TOOL_ERASE = 2, + GPAINT_TOOL_TINT = 3, +} eBrushGPaintTool; + +/* BrushGpencilSettings->brush type */ +typedef enum eBrushGPVertexTool { + GPVERTEX_TOOL_DRAW = 0, + GPVERTEX_TOOL_BLUR = 1, + GPVERTEX_TOOL_AVERAGE = 2, + GPVERTEX_TOOL_TINT = 3, + GPVERTEX_TOOL_SMEAR = 4, + GPVERTEX_TOOL_REPLACE = 5, +} eBrushGPVertexTool; + +/* BrushGpencilSettings->brush type */ +typedef enum eBrushGPSculptTool { + GPSCULPT_TOOL_SMOOTH = 0, + GPSCULPT_TOOL_THICKNESS = 1, + GPSCULPT_TOOL_STRENGTH = 2, + GPSCULPT_TOOL_GRAB = 3, + GPSCULPT_TOOL_PUSH = 4, + GPSCULPT_TOOL_TWIST = 5, + GPSCULPT_TOOL_PINCH = 6, + GPSCULPT_TOOL_RANDOMIZE = 7, + GPSCULPT_TOOL_CLONE = 8, +} eBrushGPSculptTool; + +/* BrushGpencilSettings->brush type */ +typedef enum eBrushGPWeightTool { + GPWEIGHT_TOOL_DRAW = 0, +} eBrushGPWeightTool; + +/* direction that the brush displaces along */ +enum { + SCULPT_DISP_DIR_AREA = 0, + SCULPT_DISP_DIR_VIEW = 1, + SCULPT_DISP_DIR_X = 2, + SCULPT_DISP_DIR_Y = 3, + SCULPT_DISP_DIR_Z = 4, +}; + +typedef enum { + BRUSH_MASK_DRAW = 0, + BRUSH_MASK_SMOOTH = 1, +} BrushMaskTool; + +/* blur kernel types, Brush.blur_mode */ +typedef enum eBlurKernelType { + KERNEL_GAUSSIAN = 0, + KERNEL_BOX = 1, +} eBlurKernelType; + +/* Brush.falloff_shape */ +enum { + PAINT_FALLOFF_SHAPE_SPHERE = 0, + PAINT_FALLOFF_SHAPE_TUBE = 1, +}; + +#define MAX_BRUSH_PIXEL_RADIUS 500 +#define GP_MAX_BRUSH_PIXEL_RADIUS 1000 + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h index 7bd3c7d0117..4b020019062 100644 --- a/source/blender/makesdna/DNA_brush_types.h +++ b/source/blender/makesdna/DNA_brush_types.h @@ -24,6 +24,7 @@ #pragma once #include "DNA_ID.h" +#include "DNA_brush_enums.h" #include "DNA_curve_types.h" #include "DNA_texture_types.h" /* for MTex */ @@ -144,321 +145,6 @@ typedef struct BrushGpencilSettings { struct Material *material; } BrushGpencilSettings; -/* BrushGpencilSettings->preset_type. - * Use a range for each group and not continuous values.*/ -typedef enum eGPBrush_Presets { - GP_BRUSH_PRESET_UNKNOWN = 0, - - /* Draw 1-99. */ - GP_BRUSH_PRESET_AIRBRUSH = 1, - GP_BRUSH_PRESET_INK_PEN = 2, - GP_BRUSH_PRESET_INK_PEN_ROUGH = 3, - GP_BRUSH_PRESET_MARKER_BOLD = 4, - GP_BRUSH_PRESET_MARKER_CHISEL = 5, - GP_BRUSH_PRESET_PEN = 6, - GP_BRUSH_PRESET_PENCIL_SOFT = 7, - GP_BRUSH_PRESET_PENCIL = 8, - GP_BRUSH_PRESET_FILL_AREA = 9, - GP_BRUSH_PRESET_ERASER_SOFT = 10, - GP_BRUSH_PRESET_ERASER_HARD = 11, - GP_BRUSH_PRESET_ERASER_POINT = 12, - GP_BRUSH_PRESET_ERASER_STROKE = 13, - GP_BRUSH_PRESET_TINT = 14, - - /* Vertex Paint 100-199. */ - GP_BRUSH_PRESET_VERTEX_DRAW = 100, - GP_BRUSH_PRESET_VERTEX_BLUR = 101, - GP_BRUSH_PRESET_VERTEX_AVERAGE = 102, - GP_BRUSH_PRESET_VERTEX_SMEAR = 103, - GP_BRUSH_PRESET_VERTEX_REPLACE = 104, - - /* Sculpt 200-299. */ - GP_BRUSH_PRESET_SMOOTH_STROKE = 200, - GP_BRUSH_PRESET_STRENGTH_STROKE = 201, - GP_BRUSH_PRESET_THICKNESS_STROKE = 202, - GP_BRUSH_PRESET_GRAB_STROKE = 203, - GP_BRUSH_PRESET_PUSH_STROKE = 204, - GP_BRUSH_PRESET_TWIST_STROKE = 205, - GP_BRUSH_PRESET_PINCH_STROKE = 206, - GP_BRUSH_PRESET_RANDOMIZE_STROKE = 207, - GP_BRUSH_PRESET_CLONE_STROKE = 208, - - /* Weight Paint 300-399. */ - GP_BRUSH_PRESET_DRAW_WEIGHT = 300, -} eGPBrush_Presets; - -/* BrushGpencilSettings->flag */ -typedef enum eGPDbrush_Flag { - /* brush use pressure */ - GP_BRUSH_USE_PRESSURE = (1 << 0), - /* brush use pressure for alpha factor */ - GP_BRUSH_USE_STRENGTH_PRESSURE = (1 << 1), - /* brush use pressure for alpha factor */ - GP_BRUSH_USE_JITTER_PRESSURE = (1 << 2), - /* fill hide transparent */ - GP_BRUSH_FILL_HIDE = (1 << 6), - /* show fill help lines */ - GP_BRUSH_FILL_SHOW_HELPLINES = (1 << 7), - /* lazy mouse */ - GP_BRUSH_STABILIZE_MOUSE = (1 << 8), - /* lazy mouse override (internal only) */ - GP_BRUSH_STABILIZE_MOUSE_TEMP = (1 << 9), - /* default eraser brush for quick switch */ - GP_BRUSH_DEFAULT_ERASER = (1 << 10), - /* settings group */ - GP_BRUSH_GROUP_SETTINGS = (1 << 11), - /* Random settings group */ - GP_BRUSH_GROUP_RANDOM = (1 << 12), - /* Keep material assigned to brush */ - GP_BRUSH_MATERIAL_PINNED = (1 << 13), - /* Do not show fill color while drawing (no lasso mode) */ - GP_BRUSH_DISSABLE_LASSO = (1 << 14), - /* Do not erase strokes oLcluded */ - GP_BRUSH_OCCLUDE_ERASER = (1 << 15), - /* Post process trim stroke */ - GP_BRUSH_TRIM_STROKE = (1 << 16), -} eGPDbrush_Flag; - -typedef enum eGPDbrush_Flag2 { - /* Brush use random Hue at stroke level */ - GP_BRUSH_USE_HUE_AT_STROKE = (1 << 0), - /* Brush use random Saturation at stroke level */ - GP_BRUSH_USE_SAT_AT_STROKE = (1 << 1), - /* Brush use random Value at stroke level */ - GP_BRUSH_USE_VAL_AT_STROKE = (1 << 2), - /* Brush use random Pressure at stroke level */ - GP_BRUSH_USE_PRESS_AT_STROKE = (1 << 3), - /* Brush use random Strength at stroke level */ - GP_BRUSH_USE_STRENGTH_AT_STROKE = (1 << 4), - /* Brush use random UV at stroke level */ - GP_BRUSH_USE_UV_AT_STROKE = (1 << 5), - /* Brush use Hue random pressure */ - GP_BRUSH_USE_HUE_RAND_PRESS = (1 << 6), - /* Brush use Saturation random pressure */ - GP_BRUSH_USE_SAT_RAND_PRESS = (1 << 7), - /* Brush use Value random pressure */ - GP_BRUSH_USE_VAL_RAND_PRESS = (1 << 8), - /* Brush use Pressure random pressure */ - GP_BRUSH_USE_PRESSURE_RAND_PRESS = (1 << 9), - /* Brush use Strength random pressure */ - GP_BRUSH_USE_STRENGTH_RAND_PRESS = (1 << 10), - /* Brush use UV random pressure */ - GP_BRUSH_USE_UV_RAND_PRESS = (1 << 11), -} eGPDbrush_Flag2; - -/* BrushGpencilSettings->gp_fill_draw_mode */ -typedef enum eGP_FillDrawModes { - GP_FILL_DMODE_BOTH = 0, - GP_FILL_DMODE_STROKE = 1, - GP_FILL_DMODE_CONTROL = 2, -} eGP_FillDrawModes; - -/* BrushGpencilSettings->fill_layer_mode */ -typedef enum eGP_FillLayerModes { - GP_FILL_GPLMODE_VISIBLE = 0, - GP_FILL_GPLMODE_ACTIVE = 1, - GP_FILL_GPLMODE_ALL_ABOVE = 2, - GP_FILL_GPLMODE_ALL_BELOW = 3, - GP_FILL_GPLMODE_ABOVE = 4, - GP_FILL_GPLMODE_BELOW = 5, -} eGP_FillLayerModes; - -/* BrushGpencilSettings->gp_eraser_mode */ -typedef enum eGP_BrushEraserMode { - GP_BRUSH_ERASER_SOFT = 0, - GP_BRUSH_ERASER_HARD = 1, - GP_BRUSH_ERASER_STROKE = 2, -} eGP_BrushEraserMode; - -/* BrushGpencilSettings->brush_draw_mode */ -typedef enum eGP_BrushMode { - GP_BRUSH_MODE_ACTIVE = 0, - GP_BRUSH_MODE_MATERIAL = 1, - GP_BRUSH_MODE_VERTEXCOLOR = 2, -} eGP_BrushMode; - -/* BrushGpencilSettings default brush icons */ -typedef enum eGP_BrushIcons { - GP_BRUSH_ICON_PENCIL = 1, - GP_BRUSH_ICON_PEN = 2, - GP_BRUSH_ICON_INK = 3, - GP_BRUSH_ICON_INKNOISE = 4, - GP_BRUSH_ICON_BLOCK = 5, - GP_BRUSH_ICON_MARKER = 6, - GP_BRUSH_ICON_FILL = 7, - GP_BRUSH_ICON_ERASE_SOFT = 8, - GP_BRUSH_ICON_ERASE_HARD = 9, - GP_BRUSH_ICON_ERASE_STROKE = 10, - GP_BRUSH_ICON_AIRBRUSH = 11, - GP_BRUSH_ICON_CHISEL = 12, - GP_BRUSH_ICON_TINT = 13, - GP_BRUSH_ICON_VERTEX_DRAW = 14, - GP_BRUSH_ICON_VERTEX_BLUR = 15, - GP_BRUSH_ICON_VERTEX_AVERAGE = 16, - GP_BRUSH_ICON_VERTEX_SMEAR = 17, - GP_BRUSH_ICON_VERTEX_REPLACE = 18, - GP_BRUSH_ICON_GPBRUSH_SMOOTH = 19, - GP_BRUSH_ICON_GPBRUSH_THICKNESS = 20, - GP_BRUSH_ICON_GPBRUSH_STRENGTH = 21, - GP_BRUSH_ICON_GPBRUSH_RANDOMIZE = 22, - GP_BRUSH_ICON_GPBRUSH_GRAB = 23, - GP_BRUSH_ICON_GPBRUSH_PUSH = 24, - GP_BRUSH_ICON_GPBRUSH_TWIST = 25, - GP_BRUSH_ICON_GPBRUSH_PINCH = 26, - GP_BRUSH_ICON_GPBRUSH_CLONE = 27, - GP_BRUSH_ICON_GPBRUSH_WEIGHT = 28, -} eGP_BrushIcons; - -typedef enum eBrushCurvePreset { - BRUSH_CURVE_CUSTOM = 0, - BRUSH_CURVE_SMOOTH = 1, - BRUSH_CURVE_SPHERE = 2, - BRUSH_CURVE_ROOT = 3, - BRUSH_CURVE_SHARP = 4, - BRUSH_CURVE_LIN = 5, - BRUSH_CURVE_POW4 = 6, - BRUSH_CURVE_INVSQUARE = 7, - BRUSH_CURVE_CONSTANT = 8, - BRUSH_CURVE_SMOOTHER = 9, -} eBrushCurvePreset; - -typedef enum eBrushDeformTarget { - BRUSH_DEFORM_TARGET_GEOMETRY = 0, - BRUSH_DEFORM_TARGET_CLOTH_SIM = 1, -} eBrushDeformTarget; - -typedef enum eBrushElasticDeformType { - BRUSH_ELASTIC_DEFORM_GRAB = 0, - BRUSH_ELASTIC_DEFORM_GRAB_BISCALE = 1, - BRUSH_ELASTIC_DEFORM_GRAB_TRISCALE = 2, - BRUSH_ELASTIC_DEFORM_SCALE = 3, - BRUSH_ELASTIC_DEFORM_TWIST = 4, -} eBrushElasticDeformType; - -typedef enum eBrushClothDeformType { - BRUSH_CLOTH_DEFORM_DRAG = 0, - BRUSH_CLOTH_DEFORM_PUSH = 1, - BRUSH_CLOTH_DEFORM_GRAB = 2, - BRUSH_CLOTH_DEFORM_PINCH_POINT = 3, - BRUSH_CLOTH_DEFORM_PINCH_PERPENDICULAR = 4, - BRUSH_CLOTH_DEFORM_INFLATE = 5, - BRUSH_CLOTH_DEFORM_EXPAND = 6, - BRUSH_CLOTH_DEFORM_SNAKE_HOOK = 7, -} eBrushClothDeformType; - -typedef enum eBrushSmoothDeformType { - BRUSH_SMOOTH_DEFORM_LAPLACIAN = 0, - BRUSH_SMOOTH_DEFORM_SURFACE = 1, -} eBrushSmoothDeformType; - -typedef enum eBrushClothForceFalloffType { - BRUSH_CLOTH_FORCE_FALLOFF_RADIAL = 0, - BRUSH_CLOTH_FORCE_FALLOFF_PLANE = 1, -} eBrushClothForceFalloffType; - -typedef enum eBrushClothSimulationAreaType { - BRUSH_CLOTH_SIMULATION_AREA_LOCAL = 0, - BRUSH_CLOTH_SIMULATION_AREA_GLOBAL = 1, - BRUSH_CLOTH_SIMULATION_AREA_DYNAMIC = 2, -} eBrushClothSimulationAreaType; - -typedef enum eBrushPoseDeformType { - BRUSH_POSE_DEFORM_ROTATE_TWIST = 0, - BRUSH_POSE_DEFORM_SCALE_TRASLATE = 1, - BRUSH_POSE_DEFORM_SQUASH_STRETCH = 2, -} eBrushPoseDeformType; - -typedef enum eBrushPoseOriginType { - BRUSH_POSE_ORIGIN_TOPOLOGY = 0, - BRUSH_POSE_ORIGIN_FACE_SETS = 1, - BRUSH_POSE_ORIGIN_FACE_SETS_FK = 2, -} eBrushPoseOriginType; - -typedef enum eBrushSmearDeformType { - BRUSH_SMEAR_DEFORM_DRAG = 0, - BRUSH_SMEAR_DEFORM_PINCH = 1, - BRUSH_SMEAR_DEFORM_EXPAND = 2, -} eBrushSmearDeformType; - -typedef enum eBrushSlideDeformType { - BRUSH_SLIDE_DEFORM_DRAG = 0, - BRUSH_SLIDE_DEFORM_PINCH = 1, - BRUSH_SLIDE_DEFORM_EXPAND = 2, -} eBrushSlideDeformType; - -typedef enum eBrushBoundaryDeformType { - BRUSH_BOUNDARY_DEFORM_BEND = 0, - BRUSH_BOUNDARY_DEFORM_EXPAND = 1, - BRUSH_BOUNDARY_DEFORM_INFLATE = 2, - BRUSH_BOUNDARY_DEFORM_GRAB = 3, - BRUSH_BOUNDARY_DEFORM_TWIST = 4, - BRUSH_BOUNDARY_DEFORM_SMOOTH = 5, -} eBrushBushBoundaryDeformType; - -typedef enum eBrushBoundaryFalloffType { - BRUSH_BOUNDARY_FALLOFF_CONSTANT = 0, - BRUSH_BOUNDARY_FALLOFF_RADIUS = 1, - BRUSH_BOUNDARY_FALLOFF_LOOP = 2, - BRUSH_BOUNDARY_FALLOFF_LOOP_INVERT = 3, -} eBrushBoundaryFalloffType; - -typedef enum eBrushSnakeHookDeformType { - BRUSH_SNAKE_HOOK_DEFORM_FALLOFF = 0, - BRUSH_SNAKE_HOOK_DEFORM_ELASTIC = 1, -} eBrushSnakeHookDeformType; - -/* Gpencilsettings.Vertex_mode */ -typedef enum eGp_Vertex_Mode { - /* Affect to Stroke only. */ - GPPAINT_MODE_STROKE = 0, - /* Affect to Fill only. */ - GPPAINT_MODE_FILL = 1, - /* Affect to both. */ - GPPAINT_MODE_BOTH = 2, -} eGp_Vertex_Mode; - -/* sculpt_flag */ -typedef enum eGP_Sculpt_Flag { - /* invert the effect of the brush */ - GP_SCULPT_FLAG_INVERT = (1 << 0), - /* smooth brush affects pressure values as well */ - GP_SCULPT_FLAG_SMOOTH_PRESSURE = (1 << 2), - /* temporary invert action */ - GP_SCULPT_FLAG_TMP_INVERT = (1 << 3), -} eGP_Sculpt_Flag; - -/* sculpt_mode_flag */ -typedef enum eGP_Sculpt_Mode_Flag { - /* apply brush to position */ - GP_SCULPT_FLAGMODE_APPLY_POSITION = (1 << 0), - /* apply brush to strength */ - GP_SCULPT_FLAGMODE_APPLY_STRENGTH = (1 << 1), - /* apply brush to thickness */ - GP_SCULPT_FLAGMODE_APPLY_THICKNESS = (1 << 2), - /* apply brush to uv data */ - GP_SCULPT_FLAGMODE_APPLY_UV = (1 << 3), -} eGP_Sculpt_Mode_Flag; - -typedef enum eAutomasking_flag { - BRUSH_AUTOMASKING_TOPOLOGY = (1 << 0), - BRUSH_AUTOMASKING_FACE_SETS = (1 << 1), - BRUSH_AUTOMASKING_BOUNDARY_EDGES = (1 << 2), - BRUSH_AUTOMASKING_BOUNDARY_FACE_SETS = (1 << 3), -} eAutomasking_flag; - -typedef enum ePaintBrush_flag { - BRUSH_PAINT_HARDNESS_PRESSURE = (1 << 0), - BRUSH_PAINT_HARDNESS_PRESSURE_INVERT = (1 << 1), - BRUSH_PAINT_FLOW_PRESSURE = (1 << 2), - BRUSH_PAINT_FLOW_PRESSURE_INVERT = (1 << 3), - BRUSH_PAINT_WET_MIX_PRESSURE = (1 << 4), - BRUSH_PAINT_WET_MIX_PRESSURE_INVERT = (1 << 5), - BRUSH_PAINT_WET_PERSISTENCE_PRESSURE = (1 << 6), - BRUSH_PAINT_WET_PERSISTENCE_PRESSURE_INVERT = (1 << 7), - BRUSH_PAINT_DENSITY_PRESSURE = (1 << 8), - BRUSH_PAINT_DENSITY_PRESSURE_INVERT = (1 << 9), -} ePaintBrush_flag; - typedef struct Brush { ID id; @@ -725,275 +411,6 @@ typedef struct PaintCurve { int add_index; } PaintCurve; -/* Brush.gradient_source */ -typedef enum eBrushGradientSourceStroke { - BRUSH_GRADIENT_PRESSURE = 0, /* gradient from pressure */ - BRUSH_GRADIENT_SPACING_REPEAT = 1, /* gradient from spacing */ - BRUSH_GRADIENT_SPACING_CLAMP = 2, /* gradient from spacing */ -} eBrushGradientSourceStroke; - -typedef enum eBrushGradientSourceFill { - BRUSH_GRADIENT_LINEAR = 0, /* gradient from pressure */ - BRUSH_GRADIENT_RADIAL = 1, /* gradient from spacing */ -} eBrushGradientSourceFill; - -/* Brush.flag */ -typedef enum eBrushFlags { - BRUSH_AIRBRUSH = (1 << 0), - BRUSH_INVERT_TO_SCRAPE_FILL = (1 << 1), - BRUSH_ALPHA_PRESSURE = (1 << 2), - BRUSH_SIZE_PRESSURE = (1 << 3), - BRUSH_JITTER_PRESSURE = (1 << 4), - BRUSH_SPACING_PRESSURE = (1 << 5), - BRUSH_ORIGINAL_PLANE = (1 << 6), - BRUSH_GRAB_ACTIVE_VERTEX = (1 << 7), - BRUSH_ANCHORED = (1 << 8), - BRUSH_DIR_IN = (1 << 9), - BRUSH_SPACE = (1 << 10), - BRUSH_SMOOTH_STROKE = (1 << 11), - BRUSH_PERSISTENT = (1 << 12), - BRUSH_ACCUMULATE = (1 << 13), - BRUSH_LOCK_ALPHA = (1 << 14), - BRUSH_ORIGINAL_NORMAL = (1 << 15), - BRUSH_OFFSET_PRESSURE = (1 << 16), - BRUSH_SCENE_SPACING = (1 << 17), - BRUSH_SPACE_ATTEN = (1 << 18), - BRUSH_ADAPTIVE_SPACE = (1 << 19), - BRUSH_LOCK_SIZE = (1 << 20), - BRUSH_USE_GRADIENT = (1 << 21), - BRUSH_EDGE_TO_EDGE = (1 << 22), - BRUSH_DRAG_DOT = (1 << 23), - BRUSH_INVERSE_SMOOTH_PRESSURE = (1 << 24), - BRUSH_FRONTFACE_FALLOFF = (1 << 25), - BRUSH_PLANE_TRIM = (1 << 26), - BRUSH_FRONTFACE = (1 << 27), - BRUSH_CUSTOM_ICON = (1 << 28), - BRUSH_LINE = (1 << 29), - BRUSH_ABSOLUTE_JITTER = (1 << 30), - BRUSH_CURVE = (1u << 31), -} eBrushFlags; - -/* Brush.sampling_flag */ -typedef enum eBrushSamplingFlags { - BRUSH_PAINT_ANTIALIASING = (1 << 0), -} eBrushSamplingFlags; - -/* Brush.flag2 */ -typedef enum eBrushFlags2 { - BRUSH_MULTIPLANE_SCRAPE_DYNAMIC = (1 << 0), - BRUSH_MULTIPLANE_SCRAPE_PLANES_PREVIEW = (1 << 1), - BRUSH_POSE_IK_ANCHORED = (1 << 2), - BRUSH_USE_CONNECTED_ONLY = (1 << 3), - BRUSH_CLOTH_PIN_SIMULATION_BOUNDARY = (1 << 4), - BRUSH_POSE_USE_LOCK_ROTATION = (1 << 5), - BRUSH_CLOTH_USE_COLLISION = (1 << 6), - BRUSH_AREA_RADIUS_PRESSURE = (1 << 7), - BRUSH_GRAB_SILHOUETTE = (1 << 8), -} eBrushFlags2; - -typedef enum { - BRUSH_MASK_PRESSURE_RAMP = (1 << 1), - BRUSH_MASK_PRESSURE_CUTOFF = (1 << 2), -} BrushMaskPressureFlags; - -/* Brush.overlay_flags */ -typedef enum eOverlayFlags { - BRUSH_OVERLAY_CURSOR = (1), - BRUSH_OVERLAY_PRIMARY = (1 << 1), - BRUSH_OVERLAY_SECONDARY = (1 << 2), - BRUSH_OVERLAY_CURSOR_OVERRIDE_ON_STROKE = (1 << 3), - BRUSH_OVERLAY_PRIMARY_OVERRIDE_ON_STROKE = (1 << 4), - BRUSH_OVERLAY_SECONDARY_OVERRIDE_ON_STROKE = (1 << 5), -} eOverlayFlags; - -#define BRUSH_OVERLAY_OVERRIDE_MASK \ - (BRUSH_OVERLAY_CURSOR_OVERRIDE_ON_STROKE | BRUSH_OVERLAY_PRIMARY_OVERRIDE_ON_STROKE | \ - BRUSH_OVERLAY_SECONDARY_OVERRIDE_ON_STROKE) - -/* Brush.sculpt_tool */ -typedef enum eBrushSculptTool { - SCULPT_TOOL_DRAW = 1, - SCULPT_TOOL_SMOOTH = 2, - SCULPT_TOOL_PINCH = 3, - SCULPT_TOOL_INFLATE = 4, - SCULPT_TOOL_GRAB = 5, - SCULPT_TOOL_LAYER = 6, - SCULPT_TOOL_FLATTEN = 7, - SCULPT_TOOL_CLAY = 8, - SCULPT_TOOL_FILL = 9, - SCULPT_TOOL_SCRAPE = 10, - SCULPT_TOOL_NUDGE = 11, - SCULPT_TOOL_THUMB = 12, - SCULPT_TOOL_SNAKE_HOOK = 13, - SCULPT_TOOL_ROTATE = 14, - SCULPT_TOOL_SIMPLIFY = 15, - SCULPT_TOOL_CREASE = 16, - SCULPT_TOOL_BLOB = 17, - SCULPT_TOOL_CLAY_STRIPS = 18, - SCULPT_TOOL_MASK = 19, - SCULPT_TOOL_DRAW_SHARP = 20, - SCULPT_TOOL_ELASTIC_DEFORM = 21, - SCULPT_TOOL_POSE = 22, - SCULPT_TOOL_MULTIPLANE_SCRAPE = 23, - SCULPT_TOOL_SLIDE_RELAX = 24, - SCULPT_TOOL_CLAY_THUMB = 25, - SCULPT_TOOL_CLOTH = 26, - SCULPT_TOOL_DRAW_FACE_SETS = 27, - SCULPT_TOOL_PAINT = 28, - SCULPT_TOOL_SMEAR = 29, - SCULPT_TOOL_BOUNDARY = 30, - SCULPT_TOOL_DISPLACEMENT_ERASER = 31, -} eBrushSculptTool; - -/* Brush.uv_sculpt_tool */ -typedef enum eBrushUVSculptTool { - UV_SCULPT_TOOL_GRAB = 0, - UV_SCULPT_TOOL_RELAX = 1, - UV_SCULPT_TOOL_PINCH = 2, -} eBrushUVSculptTool; - -/** When #BRUSH_ACCUMULATE is used */ -#define SCULPT_TOOL_HAS_ACCUMULATE(t) \ - ELEM(t, \ - SCULPT_TOOL_DRAW, \ - SCULPT_TOOL_DRAW_SHARP, \ - SCULPT_TOOL_SLIDE_RELAX, \ - SCULPT_TOOL_CREASE, \ - SCULPT_TOOL_BLOB, \ - SCULPT_TOOL_INFLATE, \ - SCULPT_TOOL_CLAY, \ - SCULPT_TOOL_CLAY_STRIPS, \ - SCULPT_TOOL_CLAY_THUMB, \ - SCULPT_TOOL_ROTATE, \ - SCULPT_TOOL_SCRAPE, \ - SCULPT_TOOL_FLATTEN) - -#define SCULPT_TOOL_HAS_NORMAL_WEIGHT(t) \ - ELEM(t, SCULPT_TOOL_GRAB, SCULPT_TOOL_SNAKE_HOOK, SCULPT_TOOL_ELASTIC_DEFORM) - -#define SCULPT_TOOL_HAS_RAKE(t) ELEM(t, SCULPT_TOOL_SNAKE_HOOK) - -#define SCULPT_TOOL_HAS_DYNTOPO(t) \ - (ELEM(t, /* These brushes, as currently coded, cannot support dynamic topology */ \ - SCULPT_TOOL_GRAB, \ - SCULPT_TOOL_ROTATE, \ - SCULPT_TOOL_CLOTH, \ - SCULPT_TOOL_THUMB, \ - SCULPT_TOOL_LAYER, \ - SCULPT_TOOL_DISPLACEMENT_ERASER, \ - SCULPT_TOOL_DRAW_SHARP, \ - SCULPT_TOOL_SLIDE_RELAX, \ - SCULPT_TOOL_ELASTIC_DEFORM, \ - SCULPT_TOOL_BOUNDARY, \ - SCULPT_TOOL_POSE, \ - SCULPT_TOOL_DRAW_FACE_SETS, \ - SCULPT_TOOL_PAINT, \ - SCULPT_TOOL_SMEAR, \ -\ - /* These brushes could handle dynamic topology, \ \ - * but user feedback indicates it's better not to */ \ - SCULPT_TOOL_SMOOTH, \ - SCULPT_TOOL_MASK) == 0) - -#define SCULPT_TOOL_HAS_TOPOLOGY_RAKE(t) \ - (ELEM(t, /* These brushes, as currently coded, cannot support topology rake. */ \ - SCULPT_TOOL_GRAB, \ - SCULPT_TOOL_ROTATE, \ - SCULPT_TOOL_THUMB, \ - SCULPT_TOOL_DRAW_SHARP, \ - SCULPT_TOOL_DISPLACEMENT_ERASER, \ - SCULPT_TOOL_SLIDE_RELAX, \ - SCULPT_TOOL_MASK) == 0) - -/* ImagePaintSettings.tool */ -typedef enum eBrushImagePaintTool { - PAINT_TOOL_DRAW = 0, - PAINT_TOOL_SOFTEN = 1, - PAINT_TOOL_SMEAR = 2, - PAINT_TOOL_CLONE = 3, - PAINT_TOOL_FILL = 4, - PAINT_TOOL_MASK = 5, -} eBrushImagePaintTool; - -typedef enum eBrushVertexPaintTool { - VPAINT_TOOL_DRAW = 0, - VPAINT_TOOL_BLUR = 1, - VPAINT_TOOL_AVERAGE = 2, - VPAINT_TOOL_SMEAR = 3, -} eBrushVertexPaintTool; - -typedef enum eBrushWeightPaintTool { - WPAINT_TOOL_DRAW = 0, - WPAINT_TOOL_BLUR = 1, - WPAINT_TOOL_AVERAGE = 2, - WPAINT_TOOL_SMEAR = 3, -} eBrushWeightPaintTool; - -/* BrushGpencilSettings->brush type */ -typedef enum eBrushGPaintTool { - GPAINT_TOOL_DRAW = 0, - GPAINT_TOOL_FILL = 1, - GPAINT_TOOL_ERASE = 2, - GPAINT_TOOL_TINT = 3, -} eBrushGPaintTool; - -/* BrushGpencilSettings->brush type */ -typedef enum eBrushGPVertexTool { - GPVERTEX_TOOL_DRAW = 0, - GPVERTEX_TOOL_BLUR = 1, - GPVERTEX_TOOL_AVERAGE = 2, - GPVERTEX_TOOL_TINT = 3, - GPVERTEX_TOOL_SMEAR = 4, - GPVERTEX_TOOL_REPLACE = 5, -} eBrushGPVertexTool; - -/* BrushGpencilSettings->brush type */ -typedef enum eBrushGPSculptTool { - GPSCULPT_TOOL_SMOOTH = 0, - GPSCULPT_TOOL_THICKNESS = 1, - GPSCULPT_TOOL_STRENGTH = 2, - GPSCULPT_TOOL_GRAB = 3, - GPSCULPT_TOOL_PUSH = 4, - GPSCULPT_TOOL_TWIST = 5, - GPSCULPT_TOOL_PINCH = 6, - GPSCULPT_TOOL_RANDOMIZE = 7, - GPSCULPT_TOOL_CLONE = 8, -} eBrushGPSculptTool; - -/* BrushGpencilSettings->brush type */ -typedef enum eBrushGPWeightTool { - GPWEIGHT_TOOL_DRAW = 0, -} eBrushGPWeightTool; - -/* direction that the brush displaces along */ -enum { - SCULPT_DISP_DIR_AREA = 0, - SCULPT_DISP_DIR_VIEW = 1, - SCULPT_DISP_DIR_X = 2, - SCULPT_DISP_DIR_Y = 3, - SCULPT_DISP_DIR_Z = 4, -}; - -typedef enum { - BRUSH_MASK_DRAW = 0, - BRUSH_MASK_SMOOTH = 1, -} BrushMaskTool; - -/* blur kernel types, Brush.blur_mode */ -typedef enum eBlurKernelType { - KERNEL_GAUSSIAN = 0, - KERNEL_BOX = 1, -} eBlurKernelType; - -/* Brush.falloff_shape */ -enum { - PAINT_FALLOFF_SHAPE_SPHERE = 0, - PAINT_FALLOFF_SHAPE_TUBE = 1, -}; - -#define MAX_BRUSH_PIXEL_RADIUS 500 -#define GP_MAX_BRUSH_PIXEL_RADIUS 1000 - #ifdef __cplusplus } #endif -- cgit v1.2.3 From d72ec16e70721408c875040325c984941687b4a2 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Fri, 11 Dec 2020 12:00:48 +0100 Subject: Geometry Nodes: add Attribute Mix node This node can be used to mix two attributes in various ways. The blend modes are the same as in the MixRGB shader node. Differential Revision: https://developer.blender.org/D9737 Ref T82374. --- source/blender/blenkernel/BKE_node.h | 1 + source/blender/blenkernel/intern/node.c | 1 + source/blender/editors/space_node/drawnode.c | 14 ++ source/blender/makesdna/DNA_node_types.h | 10 + source/blender/makesrna/intern/rna_nodetree.c | 42 ++++ source/blender/nodes/CMakeLists.txt | 1 + source/blender/nodes/NOD_geometry.h | 1 + source/blender/nodes/NOD_static_types.h | 1 + .../nodes/geometry/nodes/node_geo_attribute_mix.cc | 219 +++++++++++++++++++++ 9 files changed, 290 insertions(+) create mode 100644 source/blender/nodes/geometry/nodes/node_geo_attribute_mix.cc (limited to 'source/blender') diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index eeef3e5c704..77a1d3989b0 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -1351,6 +1351,7 @@ int ntreeTexExecTree(struct bNodeTree *ntree, #define GEO_NODE_ATTRIBUTE_MATH 1009 #define GEO_NODE_JOIN_GEOMETRY 1010 #define GEO_NODE_ATTRIBUTE_FILL 1011 +#define GEO_NODE_ATTRIBUTE_MIX 1012 /** \} */ diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index eeffaa186ab..61bfc09cc42 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -4697,6 +4697,7 @@ static void registerGeometryNodes(void) register_node_type_geo_random_attribute(); register_node_type_geo_attribute_math(); register_node_type_geo_join_geometry(); + register_node_type_geo_attribute_mix(); } static void registerFunctionNodes(void) diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 2ff32a4a82e..0d371915316 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -3190,6 +3190,17 @@ static void node_geometry_buts_attribute_fill(uiLayout *layout, // uiItemR(layout, ptr, "domain", DEFAULT_FLAGS, "", ICON_NONE); } +static void node_geometry_buts_attribute_mix(uiLayout *layout, + bContext *UNUSED(C), + PointerRNA *ptr) +{ + uiItemR(layout, ptr, "blend_type", DEFAULT_FLAGS, "", ICON_NONE); + uiLayout *col = uiLayoutColumn(layout, false); + uiItemR(col, ptr, "input_type_factor", DEFAULT_FLAGS, IFACE_("Factor"), ICON_NONE); + uiItemR(col, ptr, "input_type_a", DEFAULT_FLAGS, IFACE_("A"), ICON_NONE); + uiItemR(col, ptr, "input_type_b", DEFAULT_FLAGS, IFACE_("B"), ICON_NONE); +} + static void node_geometry_set_butfunc(bNodeType *ntype) { switch (ntype->type) { @@ -3211,6 +3222,9 @@ static void node_geometry_set_butfunc(bNodeType *ntype) case GEO_NODE_ATTRIBUTE_FILL: ntype->draw_buttons = node_geometry_buts_attribute_fill; break; + case GEO_NODE_ATTRIBUTE_MIX: + ntype->draw_buttons = node_geometry_buts_attribute_mix; + break; } } diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 13f8b11352a..b8aeaa2bd89 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -1059,6 +1059,16 @@ typedef struct NodeDenoise { char _pad[7]; } NodeDenoise; +typedef struct NodeAttributeMix { + /* e.g. MA_RAMP_BLEND. */ + uint8_t blend_type; + + /* GeometryNodeAttributeInputMode */ + uint8_t input_type_factor; + uint8_t input_type_a; + uint8_t input_type_b; +} NodeAttributeMix; + /* script node mode */ #define NODE_SCRIPT_INTERNAL 0 #define NODE_SCRIPT_EXTERNAL 1 diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 23092fbae28..074269e4d41 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -435,6 +435,20 @@ static const EnumPropertyItem rna_node_geometry_attribute_input_b_items[] = { {0, NULL, 0, NULL, NULL}, }; +static const EnumPropertyItem rna_node_geometry_attribute_factor_input_type_items[] = { + {GEO_NODE_ATTRIBUTE_INPUT_ATTRIBUTE, "ATTRIBUTE", 0, "Attribute", ""}, + {GEO_NODE_ATTRIBUTE_INPUT_FLOAT, "FLOAT", 0, "Float", ""}, + {0, NULL, 0, NULL, NULL}, +}; + +static const EnumPropertyItem rna_node_geometry_attribute_input_type_items[] = { + {GEO_NODE_ATTRIBUTE_INPUT_ATTRIBUTE, "ATTRIBUTE", 0, "Attribute", ""}, + {GEO_NODE_ATTRIBUTE_INPUT_FLOAT, "FLOAT", 0, "Float", ""}, + {GEO_NODE_ATTRIBUTE_INPUT_VECTOR, "VECTOR", 0, "Vector", ""}, + {GEO_NODE_ATTRIBUTE_INPUT_COLOR, "COLOR", 0, "Color", ""}, + {0, NULL, 0, NULL, NULL}, +}; + #endif #ifdef RNA_RUNTIME @@ -8399,6 +8413,34 @@ static void def_geo_attribute_math(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); } +static void def_geo_attribute_mix(StructRNA *srna) +{ + PropertyRNA *prop; + + RNA_def_struct_sdna_from(srna, "NodeAttributeMix", "storage"); + + prop = RNA_def_property(srna, "blend_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, rna_enum_ramp_blend_items); + RNA_def_property_enum_default(prop, MA_RAMP_BLEND); + RNA_def_property_ui_text(prop, "Blending Mode", ""); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); + + prop = RNA_def_property(srna, "input_type_factor", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, rna_node_geometry_attribute_factor_input_type_items); + RNA_def_property_ui_text(prop, "Input Type Factor", ""); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); + + prop = RNA_def_property(srna, "input_type_a", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, rna_node_geometry_attribute_input_type_items); + RNA_def_property_ui_text(prop, "Input Type A", ""); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); + + prop = RNA_def_property(srna, "input_type_b", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, rna_node_geometry_attribute_input_type_items); + RNA_def_property_ui_text(prop, "Input Type B", ""); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); +} + /* -------------------------------------------------------------------------- */ static void rna_def_shader_node(BlenderRNA *brna) diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index 87055a934fd..11852f6f723 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -144,6 +144,7 @@ set(SRC geometry/nodes/node_geo_common.cc geometry/nodes/node_geo_edge_split.cc geometry/nodes/node_geo_join_geometry.cc + geometry/nodes/node_geo_attribute_mix.cc geometry/nodes/node_geo_object_info.cc geometry/nodes/node_geo_point_distribute.cc geometry/nodes/node_geo_point_instance.cc diff --git a/source/blender/nodes/NOD_geometry.h b/source/blender/nodes/NOD_geometry.h index 6433841582b..e3ec0451832 100644 --- a/source/blender/nodes/NOD_geometry.h +++ b/source/blender/nodes/NOD_geometry.h @@ -38,6 +38,7 @@ void register_node_type_geo_object_info(void); void register_node_type_geo_random_attribute(void); void register_node_type_geo_attribute_math(void); void register_node_type_geo_join_geometry(void); +void register_node_type_geo_attribute_mix(void); #ifdef __cplusplus } diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h index 8ca978d1339..d1032647ba8 100644 --- a/source/blender/nodes/NOD_static_types.h +++ b/source/blender/nodes/NOD_static_types.h @@ -278,6 +278,7 @@ DefNode(GeometryNode, GEO_NODE_RANDOM_ATTRIBUTE, def_geo_random_attribute, "RAND DefNode(GeometryNode, GEO_NODE_ATTRIBUTE_MATH, def_geo_attribute_math, "ATTRIBUTE_MATH", AttributeMath, "Attribute Math", "") DefNode(GeometryNode, GEO_NODE_JOIN_GEOMETRY, 0, "JOIN_GEOMETRY", JoinGeometry, "Join Geometry", "") DefNode(GeometryNode, GEO_NODE_ATTRIBUTE_FILL, def_geo_attribute_fill, "ATTRIBUTE_FILL", AttributeFill, "Attribute Fill", "") +DefNode(GeometryNode, GEO_NODE_ATTRIBUTE_MIX, def_geo_attribute_mix, "ATTRIBUTE_MIX", AttributeMix, "Attribute Mix", "") /* undefine macros */ #undef DefNode diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_mix.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_mix.cc new file mode 100644 index 00000000000..f96bc9f9e15 --- /dev/null +++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_mix.cc @@ -0,0 +1,219 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "BKE_material.h" + +#include "node_geometry_util.hh" + +static bNodeSocketTemplate geo_node_attribute_mix_in[] = { + {SOCK_GEOMETRY, N_("Geometry")}, + {SOCK_STRING, N_("Factor")}, + {SOCK_FLOAT, N_("Factor"), 0.5, 0.0, 0.0, 0.0, 0.0, 1.0, PROP_FACTOR}, + {SOCK_STRING, N_("A")}, + {SOCK_FLOAT, N_("A"), 0.0, 0.0, 0.0, 0.0, -FLT_MAX, FLT_MAX}, + {SOCK_VECTOR, N_("A"), 0.0, 0.0, 0.0, 0.0, -FLT_MAX, FLT_MAX}, + {SOCK_RGBA, N_("A"), 0.5, 0.5, 0.5, 1.0}, + {SOCK_STRING, N_("B")}, + {SOCK_FLOAT, N_("B"), 0.0, 0.0, 0.0, 0.0, -FLT_MAX, FLT_MAX}, + {SOCK_VECTOR, N_("B"), 0.0, 0.0, 0.0, 0.0, -FLT_MAX, FLT_MAX}, + {SOCK_RGBA, N_("B"), 0.5, 0.5, 0.5, 1.0}, + {SOCK_STRING, N_("Result")}, + {-1, ""}, +}; + +static bNodeSocketTemplate geo_node_mix_attribute_out[] = { + {SOCK_GEOMETRY, N_("Geometry")}, + {-1, ""}, +}; + +namespace blender::nodes { + +static void do_mix_operation_float(const int blend_mode, + const FloatReadAttribute &factors, + const FloatReadAttribute &inputs_a, + const FloatReadAttribute &inputs_b, + FloatWriteAttribute &results) +{ + const int size = results.size(); + for (const int i : IndexRange(size)) { + const float factor = factors[i]; + float3 a{inputs_a[i]}; + const float3 b{inputs_b[i]}; + ramp_blend(blend_mode, a, factor, b); + const float result = a.length(); + results.set(i, result); + } +} + +static void do_mix_operation_float3(const int blend_mode, + const FloatReadAttribute &factors, + const Float3ReadAttribute &inputs_a, + const Float3ReadAttribute &inputs_b, + Float3WriteAttribute &results) +{ + const int size = results.size(); + for (const int i : IndexRange(size)) { + const float factor = factors[i]; + float3 a = inputs_a[i]; + const float3 b = inputs_b[i]; + ramp_blend(blend_mode, a, factor, b); + results.set(i, a); + } +} + +static void do_mix_operation_color4f(const int blend_mode, + const FloatReadAttribute &factors, + const Color4fReadAttribute &inputs_a, + const Color4fReadAttribute &inputs_b, + Color4fWriteAttribute &results) +{ + const int size = results.size(); + for (const int i : IndexRange(size)) { + const float factor = factors[i]; + Color4f a = inputs_a[i]; + const Color4f b = inputs_b[i]; + ramp_blend(blend_mode, a, factor, b); + results.set(i, a); + } +} + +static void do_mix_operation(const CustomDataType result_type, + int blend_mode, + const FloatReadAttribute &attribute_factor, + ReadAttributePtr attribute_a, + ReadAttributePtr attribute_b, + WriteAttributePtr attribute_result) +{ + if (result_type == CD_PROP_FLOAT) { + FloatReadAttribute attribute_a_float = std::move(attribute_a); + FloatReadAttribute attribute_b_float = std::move(attribute_b); + FloatWriteAttribute attribute_result_float = std::move(attribute_result); + do_mix_operation_float(blend_mode, + attribute_factor, + attribute_a_float, + attribute_b_float, + attribute_result_float); + } + else if (result_type == CD_PROP_FLOAT3) { + Float3ReadAttribute attribute_a_float3 = std::move(attribute_a); + Float3ReadAttribute attribute_b_float3 = std::move(attribute_b); + Float3WriteAttribute attribute_result_float3 = std::move(attribute_result); + do_mix_operation_float3(blend_mode, + attribute_factor, + attribute_a_float3, + attribute_b_float3, + attribute_result_float3); + } + else if (result_type == CD_PROP_COLOR) { + Color4fReadAttribute attribute_a_color4f = std::move(attribute_a); + Color4fReadAttribute attribute_b_color4f = std::move(attribute_b); + Color4fWriteAttribute attribute_result_color4f = std::move(attribute_result); + do_mix_operation_color4f(blend_mode, + attribute_factor, + attribute_a_color4f, + attribute_b_color4f, + attribute_result_color4f); + } +} + +static void attribute_mix_calc(GeometryComponent &component, const GeoNodeExecParams ¶ms) +{ + const bNode &node = params.node(); + const NodeAttributeMix *node_storage = (const NodeAttributeMix *)node.storage; + + CustomDataType result_type = CD_PROP_COLOR; + AttributeDomain result_domain = ATTR_DOMAIN_POINT; + + /* Use type and domain from the result attribute, if it exists already. */ + const std::string result_name = params.get_input("Result"); + const ReadAttributePtr result_attribute_read = component.attribute_try_get_for_read(result_name); + if (result_attribute_read) { + result_type = result_attribute_read->custom_data_type(); + result_domain = result_attribute_read->domain(); + } + + WriteAttributePtr attribute_result = component.attribute_try_ensure_for_write( + result_name, result_domain, result_type); + if (!attribute_result) { + return; + } + + FloatReadAttribute attribute_factor = params.get_input_attribute( + "Factor", component, result_domain, 0.5f); + ReadAttributePtr attribute_a = params.get_input_attribute( + "A", component, result_domain, result_type, nullptr); + ReadAttributePtr attribute_b = params.get_input_attribute( + "B", component, result_domain, result_type, nullptr); + + do_mix_operation(result_type, + node_storage->blend_type, + attribute_factor, + std::move(attribute_a), + std::move(attribute_b), + std::move(attribute_result)); +} + +static void geo_node_attribute_mix_exec(GeoNodeExecParams params) +{ + GeometrySet geometry_set = params.extract_input("Geometry"); + + if (geometry_set.has()) { + attribute_mix_calc(geometry_set.get_component_for_write(), params); + } + if (geometry_set.has()) { + attribute_mix_calc(geometry_set.get_component_for_write(), params); + } + + params.set_output("Geometry", geometry_set); +} + +static void geo_node_attribute_mix_init(bNodeTree *UNUSED(ntree), bNode *node) +{ + NodeAttributeMix *data = (NodeAttributeMix *)MEM_callocN(sizeof(NodeAttributeMix), + "attribute mix node"); + data->blend_type = MA_RAMP_BLEND; + data->input_type_factor = GEO_NODE_ATTRIBUTE_INPUT_FLOAT; + data->input_type_a = GEO_NODE_ATTRIBUTE_INPUT_ATTRIBUTE; + data->input_type_b = GEO_NODE_ATTRIBUTE_INPUT_ATTRIBUTE; + node->storage = data; +} + +static void geo_node_attribute_mix_update(bNodeTree *UNUSED(ntree), bNode *node) +{ + NodeAttributeMix *node_storage = (NodeAttributeMix *)node->storage; + update_attribute_input_socket_availabilities( + *node, "Factor", (GeometryNodeAttributeInputMode)node_storage->input_type_factor); + update_attribute_input_socket_availabilities( + *node, "A", (GeometryNodeAttributeInputMode)node_storage->input_type_a); + update_attribute_input_socket_availabilities( + *node, "B", (GeometryNodeAttributeInputMode)node_storage->input_type_b); +} + +} // namespace blender::nodes + +void register_node_type_geo_attribute_mix() +{ + static bNodeType ntype; + + geo_node_type_base(&ntype, GEO_NODE_ATTRIBUTE_MIX, "Attribute Mix", NODE_CLASS_ATTRIBUTE, 0); + node_type_socket_templates(&ntype, geo_node_attribute_mix_in, geo_node_mix_attribute_out); + node_type_init(&ntype, blender::nodes::geo_node_attribute_mix_init); + node_type_update(&ntype, blender::nodes::geo_node_attribute_mix_update); + node_type_storage( + &ntype, "NodeAttributeMix", node_free_standard_storage, node_copy_standard_storage); + ntype.geometry_node_execute = blender::nodes::geo_node_attribute_mix_exec; + nodeRegisterType(&ntype); +} -- cgit v1.2.3 From 7c8e01341f87ae1d75b492d36fa24960acf356fd Mon Sep 17 00:00:00 2001 From: Thomas Beck Date: Fri, 11 Dec 2020 14:06:07 +0100 Subject: UI: Correct help text in the Parent panel Tracking Axis and Up Axis were still referring to duplis (DupliFrame) - changed it to be in line with Aaron's info about them in our manual --- source/blender/makesrna/intern/rna_object.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source/blender') diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index ee115b74379..4e170599ee6 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -2751,8 +2751,8 @@ static void rna_def_object(BlenderRNA *brna) RNA_def_property_ui_text( prop, "Track Axis", - "Axis that points in 'forward' direction (applies to InstanceFrame when " - "parent 'Follow' is enabled)"); + "Axis that points in the 'forward' direction (applies to Instance Vertices when " + "Align to Vertex Normal is enabled)"); RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_internal_update"); prop = RNA_def_property(srna, "up_axis", PROP_ENUM, PROP_NONE); @@ -2761,8 +2761,8 @@ static void rna_def_object(BlenderRNA *brna) RNA_def_property_ui_text( prop, "Up Axis", - "Axis that points in the upward direction (applies to InstanceFrame when " - "parent 'Follow' is enabled)"); + "Axis that points in the upward direction (applies to Instance Vertices when " + "Align to Vertex Normal is enabled)"); RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_internal_update"); /* proxy */ -- cgit v1.2.3 From 727d5013a7771ffa7d8f1fa799af5142b274c127 Mon Sep 17 00:00:00 2001 From: Philipp Oeser Date: Mon, 23 Nov 2020 12:44:44 +0100 Subject: Fix T82881: Paint mask 'deselect on nothing' missed viewport update Was failing for weightpaint and vertexpaint. Selection flags were actually changed, but the update in the viewport wasnt immediate, leading to confusion when the update happened later (e.g. when using the weight gradient tool as done in the report). We need to tag ID_RECALC_SELECT and send ND_SELECT notifier here. This could be done explicitly, but there is also existing functionality available that does this. Note: the way updates happen for paintfaces vs. paintverts looks a bit inconsistent (so this could be part of a later cleanup commit) Maniphest Tasks: T82881 Differential Revision: https://developer.blender.org/D9631 --- source/blender/editors/space_view3d/view3d_select.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'source/blender') diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index 5b400bbf60a..96bd25f85e7 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -2457,13 +2457,16 @@ static int view3d_select_exec(bContext *C, wmOperator *op) else if (obact && BKE_paint_select_face_test(obact)) { retval = paintface_mouse_select(C, obact, location, extend, deselect, toggle); if (!retval && deselect_all) { - retval = paintface_deselect_all_visible(C, CTX_data_active_object(C), SEL_DESELECT, false); + retval = paintface_deselect_all_visible(C, CTX_data_active_object(C), SEL_DESELECT, true); } } else if (BKE_paint_select_vert_test(obact)) { retval = ed_wpaint_vertex_select_pick(C, location, extend, deselect, toggle, obact); if (!retval && deselect_all) { retval = paintvert_deselect_all_visible(obact, SEL_DESELECT, false); + if (retval) { + paintvert_tag_select_update(C, obact); + } } } else { -- cgit v1.2.3 From c8a3d1a1fa65f2ff21202d79c5f027119203319f Mon Sep 17 00:00:00 2001 From: Antonio Vazquez Date: Thu, 10 Dec 2020 23:04:54 +0100 Subject: GPencil: Add Link support to Effects using Ctrl+L The effects were not supported in this operator, but it was supported in the Outliner. Differential Revision: https://developer.blender.org/D9824 --- source/blender/editors/object/object_relations.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'source/blender') diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index 8841b1955bf..3ad500d3d0d 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -1554,6 +1554,7 @@ enum { MAKE_LINKS_DUPLICOLLECTION = 5, MAKE_LINKS_MODIFIERS = 6, MAKE_LINKS_FONTS = 7, + MAKE_LINKS_SHADERFX = 8, }; /* Return true if make link data is allowed, false otherwise */ @@ -1589,6 +1590,11 @@ static bool allow_make_links_data(const int type, Object *ob_src, Object *ob_dst return true; } break; + case MAKE_LINKS_SHADERFX: + if ((ob_src->type == OB_GPENCIL) && (ob_dst->type == OB_GPENCIL)) { + return true; + } + break; } return false; } @@ -1720,6 +1726,11 @@ static int make_links_data_exec(bContext *C, wmOperator *op) ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION); break; } + case MAKE_LINKS_SHADERFX: + ED_object_shaderfx_link(ob_dst, ob_src); + DEG_id_tag_update(&ob_dst->id, + ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION); + break; } } } @@ -1782,6 +1793,7 @@ void OBJECT_OT_make_links_data(wmOperatorType *ot) {MAKE_LINKS_DUPLICOLLECTION, "DUPLICOLLECTION", 0, "Instance Collection", ""}, {MAKE_LINKS_MODIFIERS, "MODIFIERS", 0, "Modifiers", ""}, {MAKE_LINKS_FONTS, "FONTS", 0, "Fonts", ""}, + {MAKE_LINKS_SHADERFX, "EFFECTS", 0, "Effects", ""}, {0, NULL, 0, NULL, NULL}, }; -- cgit v1.2.3 From 273aca964e895b5a5075c3fbd02589b9a908fc22 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Fri, 11 Dec 2020 16:07:43 +0100 Subject: Refactor/extend BKE API to get special user directories The previous `BKE_appdir_folder_default()` was confusing, it would return the home directory on Linux and macOS, but the Documents directory on Windows. Plus, for the Asset Browser, we want to use the Documents directory for the default asset library on all platforms. This attempts to clean up the API to avoid confusion, while adding the newly needed functionality. * `BKE_appdir_folder_default()` should behave as before, but the implementation changed: ** Removes apparently incorrect usage of `XDG_DOCUMENTS_DIR` on Unix systems - this seems to be a config file variable, not an environment variable. Always use `$HOME` instead, which this ended up using anyway. ** On Windows it doesn't attempt to use `%HOME%` anymore and gets the Documents directory directly. * Add `BKE_appdir_folder_home()` to gives the top-level user directory on all platforms. * Add `BKE_appdir_folder_documents()` to always get the user documents directory on all platforms. There should be no user noticable behavior change. Differential Revision: https://developer.blender.org/D9800 Reviewed by: Brecht Van Lommel --- source/blender/blenkernel/BKE_appdir.h | 2 + source/blender/blenkernel/intern/appdir.c | 81 +++++++++++++++++++++---------- 2 files changed, 57 insertions(+), 26 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/BKE_appdir.h b/source/blender/blenkernel/BKE_appdir.h index 6da6079ea2a..c9d671597e8 100644 --- a/source/blender/blenkernel/BKE_appdir.h +++ b/source/blender/blenkernel/BKE_appdir.h @@ -31,6 +31,8 @@ void BKE_appdir_exit(void); /* note on naming: typical _get() suffix is omitted here, * since its the main purpose of the API. */ const char *BKE_appdir_folder_default(void); +const char *BKE_appdir_folder_home(void); +bool BKE_appdir_folder_documents(char *dir); bool BKE_appdir_folder_id_ex(const int folder_id, const char *subfolder, char *path, diff --git a/source/blender/blenkernel/intern/appdir.c b/source/blender/blenkernel/intern/appdir.c index b1462167edd..a6b3985e80d 100644 --- a/source/blender/blenkernel/intern/appdir.c +++ b/source/blender/blenkernel/intern/appdir.c @@ -36,6 +36,8 @@ #include "BKE_appdir.h" /* own include */ #include "BKE_blender_version.h" +#include "BLT_translation.h" + #include "GHOST_Path-api.h" #include "MEM_guardedalloc.h" @@ -146,47 +148,74 @@ static char *blender_version_decimal(const int version) * \{ */ /** - * This is now only used to really get the user's default document folder. + * Get the folder that's the "natural" starting point for browsing files on an OS. On Unix that is + * $HOME, on Windows it is %userprofile%/Documents. * - * \note On Windows `Users/{MyUserName}/Documents` is used - * as it's the default location to save documents. + * \note On Windows `Users/{MyUserName}/Documents` is used as it's the default location to save + * documents. */ const char *BKE_appdir_folder_default(void) { #ifndef WIN32 - const char *const xdg_documents_dir = BLI_getenv("XDG_DOCUMENTS_DIR"); + return BLI_getenv("HOME"); +#else /* Windows */ + static char documentfolder[MAXPATHLEN]; - if (xdg_documents_dir) { - return xdg_documents_dir; + if (BKE_appdir_folder_documents(documentfolder)) { + return documentfolder; } + return NULL; +#endif /* WIN32 */ +} + +/** + * Get the user's home directory, i.e. $HOME on UNIX, %userprofile% on Windows. + */ +const char *BKE_appdir_folder_home(void) +{ +#ifndef WIN32 return BLI_getenv("HOME"); -#else /* Windows */ - static char documentfolder[MAXPATHLEN]; - HRESULT hResult; +#else /* Windows */ + return BLI_getenv("userprofile"); +#endif +} - /* Check for `%HOME%` environment variable. */ - if (uput_getenv("HOME", documentfolder, MAXPATHLEN)) { - if (BLI_is_dir(documentfolder)) { - return documentfolder; - } +/** + * Get the user's document directory, i.e. $HOME/Documents on Linux, %userprofile%/Documents on + * Windows. If this can't be found using OS queries (via Ghost), try manually finding it. + * + * \returns True if the path is valid and points to an existing directory. + */ +bool BKE_appdir_folder_documents(char *dir) +{ + dir[0] = '\0'; + + const char *documents_path = (const char *)GHOST_getUserSpecialDir( + GHOST_kUserSpecialDirDocuments); + + /* Usual case: Ghost gave us the documents path. We're done here. */ + if (documents_path && BLI_is_dir(documents_path)) { + BLI_strncpy(dir, documents_path, FILE_MAXDIR); + return true; } - /* Add user profile support for WIN 2K / NT. - * This is `%APPDATA%`, which translates to either: - * - `%USERPROFILE%\Application Data` or... - * - `%USERPROFILE%\AppData\Roaming` (since Vista). - */ - hResult = SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, documentfolder); + /* Ghost couldn't give us a documents path, let's try if we can find it ourselves.*/ - if (hResult == S_OK) { - if (BLI_is_dir(documentfolder)) { - return documentfolder; - } + const char *home_path = BKE_appdir_folder_home(); + if (!home_path || !BLI_is_dir(home_path)) { + return false; } - return NULL; -#endif /* WIN32 */ + char try_documents_path[FILE_MAXDIR]; + /* Own attempt at getting a valid Documents path. */ + BLI_path_join(try_documents_path, sizeof(try_documents_path), home_path, N_("Documents"), NULL); + if (!BLI_is_dir(try_documents_path)) { + return false; + } + + BLI_strncpy(dir, try_documents_path, FILE_MAXDIR); + return true; } /** -- cgit v1.2.3 From badbf816b867ffeb5920a1575d0159ec516b2819 Mon Sep 17 00:00:00 2001 From: Yevgeny Makarov Date: Fri, 11 Dec 2020 07:35:44 -0800 Subject: UI: Consistent Range Descriptions Unifying range descriptions as a value 'to' a value. Differential Revision: https://developer.blender.org/D9771 Reviewed by Julian Eisel --- source/blender/editors/mesh/editmesh_tools.c | 2 +- source/blender/editors/sculpt_paint/paint_image.c | 2 +- source/blender/editors/space_clip/clip_ops.c | 2 +- source/blender/editors/uvedit/uvedit_ops.c | 2 +- source/blender/makesrna/intern/rna_constraint.c | 2 +- source/blender/makesrna/intern/rna_fluid.c | 2 +- source/blender/makesrna/intern/rna_modifier.c | 12 ++++++------ source/blender/makesrna/intern/rna_nodetree.c | 10 +++++----- source/blender/makesrna/intern/rna_particle.c | 2 +- source/blender/makesrna/intern/rna_pose.c | 9 ++++----- source/blender/makesrna/intern/rna_scene.c | 4 ++-- source/blender/makesrna/intern/rna_space.c | 2 +- 12 files changed, 25 insertions(+), 26 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index ccc27ec19b6..cf01170dd8a 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -180,7 +180,7 @@ void MESH_OT_subdivide(wmOperatorType *ot) "ngon", true, "Create N-Gons", - "When disabled, newly created faces are limited to 3-4 sided faces"); + "When disabled, newly created faces are limited to 3 and 4 sided faces"); RNA_def_enum( ot->srna, "quadcorner", diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c index 3a6b91443a0..999d364a3cd 100644 --- a/source/blender/editors/sculpt_paint/paint_image.c +++ b/source/blender/editors/sculpt_paint/paint_image.c @@ -934,7 +934,7 @@ void PAINT_OT_grab_clone(wmOperatorType *ot) -FLT_MAX, FLT_MAX, "Delta", - "Delta offset of clone image in 0.0..1.0 coordinates", + "Delta offset of clone image in 0.0 to 1.0 coordinates", -1.0f, 1.0f); } diff --git a/source/blender/editors/space_clip/clip_ops.c b/source/blender/editors/space_clip/clip_ops.c index 3f00e3114a5..8f36ccb019a 100644 --- a/source/blender/editors/space_clip/clip_ops.c +++ b/source/blender/editors/space_clip/clip_ops.c @@ -859,7 +859,7 @@ void CLIP_OT_view_zoom_out(wmOperatorType *ot) -FLT_MAX, FLT_MAX, "Location", - "Cursor location in normalized (0.0-1.0) coordinates", + "Cursor location in normalized (0.0 to 1.0) coordinates", -10.0f, 10.0f); RNA_def_property_flag(prop, PROP_HIDDEN); diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c index 5b3d858329a..aac5b96f737 100644 --- a/source/blender/editors/uvedit/uvedit_ops.c +++ b/source/blender/editors/uvedit/uvedit_ops.c @@ -1812,7 +1812,7 @@ static void UV_OT_cursor_set(wmOperatorType *ot) -FLT_MAX, FLT_MAX, "Location", - "Cursor location in normalized (0.0-1.0) coordinates", + "Cursor location in normalized (0.0 to 1.0) coordinates", -10.0f, 10.0f); } diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c index 0b3dc2a3504..0f34ba47165 100644 --- a/source/blender/makesrna/intern/rna_constraint.c +++ b/source/blender/makesrna/intern/rna_constraint.c @@ -1051,7 +1051,7 @@ static void rna_def_constraint_python(BlenderRNA *brna) prop = RNA_def_property(srna, "target_count", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "tarnum"); - RNA_def_property_ui_text(prop, "Number of Targets", "Usually only 1-3 are needed"); + RNA_def_property_ui_text(prop, "Number of Targets", "Usually only 1 to 3 are needed"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_dependency_update"); prop = RNA_def_property(srna, "text", PROP_POINTER, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_fluid.c b/source/blender/makesrna/intern/rna_fluid.c index 90f5434bea0..bb8280ede91 100644 --- a/source/blender/makesrna/intern/rna_fluid.c +++ b/source/blender/makesrna/intern/rna_fluid.c @@ -1552,7 +1552,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) RNA_def_property_dynamic_array_funcs(prop, "rna_FluidModifier_grid_get_length"); RNA_def_property_float_funcs(prop, "rna_FluidModifier_temperature_grid_get", NULL, NULL); RNA_def_property_ui_text( - prop, "Temperature Grid", "Smoke temperature grid, range 0..1 represents 0..1000K"); + prop, "Temperature Grid", "Smoke temperature grid, range 0 to 1 represents 0 to 1000K"); # endif /* WITH_FLUID */ /* domain object data */ diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index d91b6ea19f7..80c2cbfb3ad 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -4884,13 +4884,13 @@ static void rna_def_modifier_screw(BlenderRNA *brna) prop = RNA_def_property(srna, "use_stretch_u", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_SCREW_UV_STRETCH_U); RNA_def_property_ui_text( - prop, "Stretch U", "Stretch the U coordinates between 0-1 when UV's are present"); + prop, "Stretch U", "Stretch the U coordinates between 0 and 1 when UV's are present"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); prop = RNA_def_property(srna, "use_stretch_v", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_SCREW_UV_STRETCH_V); RNA_def_property_ui_text( - prop, "Stretch V", "Stretch the V coordinates between 0-1 when UV's are present"); + prop, "Stretch V", "Stretch the V coordinates between 0 and 1 when UV's are present"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); # if 0 @@ -5135,7 +5135,7 @@ static void rna_def_modifier_weightvgedit(BlenderRNA *brna) RNA_def_property_ui_text( prop, "Normalize Weights", - "Normalize the resulting weights (otherwise they are only clamped within [0.0, 1.0] range)"); + "Normalize the resulting weights (otherwise they are only clamped within 0.0 to 1.0 range)"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); prop = RNA_def_property(srna, "map_curve", PROP_POINTER, PROP_NONE); @@ -5300,7 +5300,7 @@ static void rna_def_modifier_weightvgmix(BlenderRNA *brna) RNA_def_property_ui_text( prop, "Normalize Weights", - "Normalize the resulting weights (otherwise they are only clamped within [0.0, 1.0] range)"); + "Normalize the resulting weights (otherwise they are only clamped within 0.0 to 1.0 range)"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); RNA_define_lib_overridable(false); @@ -5424,7 +5424,7 @@ static void rna_def_modifier_weightvgproximity(BlenderRNA *brna) RNA_def_property_ui_text( prop, "Normalize Weights", - "Normalize the resulting weights (otherwise they are only clamped within [0.0, 1.0] range)"); + "Normalize the resulting weights (otherwise they are only clamped within 0.0 to 1.0 range)"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); prop = RNA_def_property(srna, "map_curve", PROP_POINTER, PROP_NONE); @@ -5973,7 +5973,7 @@ static void rna_def_modifier_meshcache(BlenderRNA *brna) "FACTOR", 0, "Factor", - "Control playback using a value between [0, 1]"}, + "Control playback using a value between 0 and 1"}, {0, NULL, 0, NULL, NULL}, }; diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 074269e4d41..6830c1a38c2 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -4306,7 +4306,7 @@ static void def_math(StructRNA *srna) prop = RNA_def_property(srna, "use_clamp", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "custom2", SHD_MATH_CLAMP); - RNA_def_property_ui_text(prop, "Clamp", "Clamp result of the node to 0..1 range"); + RNA_def_property_ui_text(prop, "Clamp", "Clamp result of the node to 0.0 to 1.0 range"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); } @@ -4425,7 +4425,7 @@ static void def_mix_rgb(StructRNA *srna) prop = RNA_def_property(srna, "use_clamp", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "custom2", SHD_MIXRGB_CLAMP); - RNA_def_property_ui_text(prop, "Clamp", "Clamp result of the node to 0..1 range"); + RNA_def_property_ui_text(prop, "Clamp", "Clamp result of the node to 0.0 to 1.0 range"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); } @@ -5177,12 +5177,12 @@ static void def_sh_tex_pointdensity(StructRNA *srna) "PARTICLE_AGE", 0, "Particle Age", - "Lifetime mapped as 0.0 - 1.0 intensity"}, + "Lifetime mapped as 0.0 to 1.0 intensity"}, {SHD_POINTDENSITY_COLOR_PARTSPEED, "PARTICLE_SPEED", 0, "Particle Speed", - "Particle speed (absolute magnitude of velocity) mapped as 0.0-1.0 intensity"}, + "Particle speed (absolute magnitude of velocity) mapped as 0.0 to 1.0 intensity"}, {SHD_POINTDENSITY_COLOR_PARTVEL, "PARTICLE_VELOCITY", 0, @@ -5937,7 +5937,7 @@ static void def_cmp_map_range(StructRNA *srna) prop = RNA_def_property(srna, "use_clamp", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "custom1", 1); - RNA_def_property_ui_text(prop, "Clamp", "Clamp result of the node to 0..1 range"); + RNA_def_property_ui_text(prop, "Clamp", "Clamp result of the node to 0.0 to 1.0 range"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); } diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c index e04ef105071..5fa93ec3f04 100644 --- a/source/blender/makesrna/intern/rna_particle.c +++ b/source/blender/makesrna/intern/rna_particle.c @@ -2948,7 +2948,7 @@ static void rna_def_particle_settings(BlenderRNA *brna) prop, "Adaptive Subframe Threshold", "The relative distance a particle can move before requiring more subframes " - "(target Courant number); 0.01-0.3 is the recommended range"); + "(target Courant number); 0.01 to 0.3 is the recommended range"); RNA_def_property_update(prop, 0, "rna_Particle_reset"); prop = RNA_def_property(srna, "jitter_factor", PROP_FLOAT, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_pose.c b/source/blender/makesrna/intern/rna_pose.c index 5f74e8cfc78..5ffad122a5e 100644 --- a/source/blender/makesrna/intern/rna_pose.c +++ b/source/blender/makesrna/intern/rna_pose.c @@ -1551,14 +1551,13 @@ static void rna_def_pose_itasc(BlenderRNA *brna) RNA_def_property_ui_text( prop, "Feedback", - "Feedback coefficient for error correction, average response time is 1/feedback " - "(default=20)"); + "Feedback coefficient for error correction, average response time is 1/feedback"); RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Itasc_update"); prop = RNA_def_property(srna, "velocity_max", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "maxvel"); RNA_def_property_range(prop, 0.0f, 100.0f); - RNA_def_property_ui_text(prop, "Max Velocity", "Maximum joint velocity in rad/s (default=50)"); + RNA_def_property_ui_text(prop, "Max Velocity", "Maximum joint velocity in radians/second"); RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Itasc_update"); prop = RNA_def_property(srna, "solver", PROP_ENUM, PROP_NONE); @@ -1574,7 +1573,7 @@ static void rna_def_pose_itasc(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Damp", "Maximum damping coefficient when singular value is nearly 0 " - "(higher values=more stability, less reactivity - default=0.5)"); + "(higher values produce results with more stability, less reactivity)"); RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Itasc_update"); prop = RNA_def_property(srna, "damping_epsilon", PROP_FLOAT, PROP_FACTOR); @@ -1583,7 +1582,7 @@ static void rna_def_pose_itasc(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Epsilon", "Singular value under which damping is progressively applied " - "(higher values=more stability, less reactivity - default=0.1)"); + "(higher values produce results with more stability, less reactivity)"); RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Itasc_update"); } diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index da03921bca6..d418614d7a0 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -4319,7 +4319,7 @@ void rna_def_view_layer_common(StructRNA *srna, const bool scene) prop = RNA_def_property(srna, "use_pass_mist", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "passflag", SCE_PASS_MIST); - RNA_def_property_ui_text(prop, "Mist", "Deliver mist factor pass (0.0-1.0)"); + RNA_def_property_ui_text(prop, "Mist", "Deliver mist factor pass (0.0 to 1.0)"); if (scene) { RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_ViewLayer_pass_update"); } @@ -6366,7 +6366,7 @@ static void rna_def_scene_render_data(BlenderRNA *brna) RNA_def_property_range(prop, 0.0, 1000.0); RNA_def_property_ui_text(prop, "Scale", - "Instead of automatically normalizing to 0..1, " + "Instead of automatically normalizing to the range 0 to 1, " "apply a user scale to the derivative map"); /* stamp */ diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 4e60db95e5b..44d72a65adb 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -5491,7 +5491,7 @@ static void rna_def_space_graph(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", SIPO_NORMALIZE); RNA_def_property_ui_text(prop, "Use Normalization", - "Display curves in normalized to -1..1 range, " + "Display curves in normalized range from -1 to 1, " "for easier editing of multiple curves with different ranges"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_GRAPH, NULL); -- cgit v1.2.3 From 4885fbc07b50af0f7b93c0df41d6f64cc79b2fa7 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Fri, 11 Dec 2020 17:32:08 +0100 Subject: Nodes: add Collection socket type The implementation is pretty much the same as for Object sockets. The socket color is the one that is used for collections in the outliner. Part of D9739. --- source/blender/blenkernel/intern/node.c | 32 ++++++++++++++++++ .../depsgraph/intern/builder/deg_builder_nodes.cc | 3 ++ .../intern/builder/deg_builder_relations.cc | 6 ++++ source/blender/editors/space_node/drawnode.c | 5 +++ source/blender/makesdna/DNA_node_types.h | 6 ++++ source/blender/makesrna/intern/rna_nodetree.c | 39 ++++++++++++++++++++++ source/blender/nodes/intern/node_socket.cc | 24 +++++++++++++ source/blender/nodes/intern/node_util.c | 8 +++++ 8 files changed, 123 insertions(+) (limited to 'source/blender') diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 61bfc09cc42..a90d2ea36c9 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -274,6 +274,11 @@ static void library_foreach_node_socket(LibraryForeachIDData *data, bNodeSocket BKE_LIB_FOREACHID_PROCESS(data, default_value->value, IDWALK_CB_USER); break; } + case SOCK_COLLECTION: { + bNodeSocketValueCollection *default_value = sock->default_value; + BKE_LIB_FOREACHID_PROCESS(data, default_value->value, IDWALK_CB_USER); + break; + } case SOCK_FLOAT: case SOCK_VECTOR: case SOCK_RGBA: @@ -373,6 +378,9 @@ static void write_node_socket_default_value(BlendWriter *writer, bNodeSocket *so case SOCK_IMAGE: BLO_write_struct(writer, bNodeSocketValueImage, sock->default_value); break; + case SOCK_COLLECTION: + BLO_write_struct(writer, bNodeSocketValueCollection, sock->default_value); + break; case __SOCK_MESH: case SOCK_CUSTOM: case SOCK_SHADER: @@ -709,6 +717,11 @@ static void lib_link_node_socket(BlendLibReader *reader, Library *lib, bNodeSock BLO_read_id_address(reader, lib, &default_value->value); break; } + case SOCK_COLLECTION: { + bNodeSocketValueImage *default_value = sock->default_value; + BLO_read_id_address(reader, lib, &default_value->value); + break; + } case SOCK_FLOAT: case SOCK_VECTOR: case SOCK_RGBA: @@ -788,6 +801,11 @@ static void expand_node_socket(BlendExpander *expander, bNodeSocket *sock) BLO_expand(expander, default_value->value); break; } + case SOCK_COLLECTION: { + bNodeSocketValueCollection *default_value = sock->default_value; + BLO_expand(expander, default_value->value); + break; + } case SOCK_FLOAT: case SOCK_VECTOR: case SOCK_RGBA: @@ -1345,6 +1363,11 @@ static void socket_id_user_increment(bNodeSocket *sock) id_us_plus((ID *)default_value->value); break; } + case SOCK_COLLECTION: { + bNodeSocketValueCollection *default_value = sock->default_value; + id_us_plus((ID *)default_value->value); + break; + } case SOCK_FLOAT: case SOCK_VECTOR: case SOCK_RGBA: @@ -1372,6 +1395,11 @@ static void socket_id_user_decrement(bNodeSocket *sock) id_us_min(&default_value->value->id); break; } + case SOCK_COLLECTION: { + bNodeSocketValueCollection *default_value = sock->default_value; + id_us_min(&default_value->value->id); + break; + } case SOCK_FLOAT: case SOCK_VECTOR: case SOCK_RGBA: @@ -1511,6 +1539,8 @@ const char *nodeStaticSocketType(int type, int subtype) return "NodeSocketImage"; case SOCK_GEOMETRY: return "NodeSocketGeometry"; + case SOCK_COLLECTION: + return "NodeSocketCollection"; } return NULL; } @@ -1578,6 +1608,8 @@ const char *nodeStaticSocketInterfaceType(int type, int subtype) return "NodeSocketInterfaceImage"; case SOCK_GEOMETRY: return "NodeSocketInterfaceGeometry"; + case SOCK_COLLECTION: + return "NodeSocketInterfaceCollection"; } return NULL; } diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc index 5af70305e13..e5301532ddc 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc @@ -1483,6 +1483,9 @@ void DepsgraphNodeBuilder::build_nodetree_socket(bNodeSocket *socket) else if (socket->type == SOCK_IMAGE) { build_id((ID *)((bNodeSocketValueImage *)socket->default_value)->value); } + else if (socket->type == SOCK_COLLECTION) { + build_id((ID *)((bNodeSocketValueCollection *)socket->default_value)->value); + } } void DepsgraphNodeBuilder::build_nodetree(bNodeTree *ntree) diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc index 11d34782569..04686823d62 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc @@ -2316,6 +2316,12 @@ void DepsgraphRelationBuilder::build_nodetree_socket(bNodeSocket *socket) build_image(image); } } + else if (socket->type == SOCK_COLLECTION) { + Collection *collection = ((bNodeSocketValueCollection *)socket->default_value)->value; + if (collection != nullptr) { + build_collection(nullptr, nullptr, collection); + } + } } void DepsgraphRelationBuilder::build_nodetree(bNodeTree *ntree) diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 0d371915316..f1ab433c639 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -3414,6 +3414,7 @@ static const float std_node_socket_colors[][4] = { {0.93, 0.62, 0.36, 1.0}, /* SOCK_OBJECT */ {0.89, 0.76, 0.43, 1.0}, /* SOCK_IMAGE */ {0.00, 0.84, 0.64, 1.0}, /* SOCK_GEOMETRY */ + {0.96, 0.96, 0.96, 1.0}, /* SOCK_COLLECTION */ }; /* common color callbacks for standard types */ @@ -3537,6 +3538,10 @@ static void std_node_socket_draw( uiItemR(layout, ptr, "default_value", DEFAULT_FLAGS, text, 0); break; } + case SOCK_COLLECTION: { + uiItemR(layout, ptr, "default_value", DEFAULT_FLAGS, text, 0); + break; + } default: node_socket_button_label(C, layout, ptr, node_ptr, text); break; diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index b8aeaa2bd89..e04867438f1 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -44,6 +44,7 @@ struct bNodePreview; struct bNodeTreeExec; struct bNodeType; struct uiBlock; +struct Collection; #define NODE_MAXSTR 64 @@ -160,6 +161,7 @@ typedef enum eNodeSocketDatatype { SOCK_OBJECT = 8, SOCK_IMAGE = 9, SOCK_GEOMETRY = 10, + SOCK_COLLECTION = 11, } eNodeSocketDatatype; /* socket shape */ @@ -580,6 +582,10 @@ typedef struct bNodeSocketValueImage { struct Image *value; } bNodeSocketValueImage; +typedef struct bNodeSocketValueCollection { + struct Collection *value; +} bNodeSocketValueCollection; + /* data structs, for node->storage */ enum { CMP_NODE_MASKTYPE_ADD = 0, diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 6830c1a38c2..461b6af506a 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -85,6 +85,7 @@ static const EnumPropertyItem node_socket_type_items[] = { {SOCK_OBJECT, "OBJECT", 0, "Object", ""}, {SOCK_IMAGE, "IMAGE", 0, "Image", ""}, {SOCK_GEOMETRY, "GEOMETRY", 0, "Geometry", ""}, + {SOCK_COLLECTION, "COLLECTION", 0, "Collection", ""}, {0, NULL, 0, NULL, NULL}, }; @@ -98,6 +99,7 @@ static const EnumPropertyItem node_socket_data_type_items[] = { {SOCK_OBJECT, "OBJECT", 0, "Object", ""}, {SOCK_IMAGE, "IMAGE", 0, "Image", ""}, {SOCK_GEOMETRY, "GEOMETRY", 0, "Geometry", ""}, + {SOCK_COLLECTION, "COLLECTION", 0, "Collection", ""}, {0, NULL, 0, NULL, NULL}, }; @@ -9147,6 +9149,41 @@ static void rna_def_node_socket_geometry(BlenderRNA *brna, RNA_def_struct_sdna(srna, "bNodeSocket"); } +static void rna_def_node_socket_collection(BlenderRNA *brna, + const char *identifier, + const char *interface_idname) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, identifier, "NodeSocketStandard"); + RNA_def_struct_ui_text(srna, "Collection Node Socket", "Collection socket of a node"); + RNA_def_struct_sdna(srna, "bNodeSocket"); + + RNA_def_struct_sdna_from(srna, "bNodeSocketValueCollection", "default_value"); + + prop = RNA_def_property(srna, "default_value", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "value"); + RNA_def_property_struct_type(prop, "Collection"); + RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket"); + RNA_def_property_update( + prop, NC_NODE | NA_EDITED, "rna_NodeSocketStandard_value_and_relation_update"); + RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT | PROP_CONTEXT_UPDATE); + + /* socket interface */ + srna = RNA_def_struct(brna, interface_idname, "NodeSocketInterfaceStandard"); + RNA_def_struct_ui_text(srna, "Collection Node Socket Interface", "Collection socket of a node"); + RNA_def_struct_sdna(srna, "bNodeSocket"); + + RNA_def_struct_sdna_from(srna, "bNodeSocketValueCollection", "default_value"); + + prop = RNA_def_property(srna, "default_value", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "value"); + RNA_def_property_struct_type(prop, "Collection"); + RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketInterface_update"); +} + static void rna_def_node_socket_standard_types(BlenderRNA *brna) { /* XXX Workaround: Registered functions are not exposed in python by bpy, @@ -9287,6 +9324,8 @@ static void rna_def_node_socket_standard_types(BlenderRNA *brna) rna_def_node_socket_image(brna, "NodeSocketImage", "NodeSocketInterfaceImage"); rna_def_node_socket_geometry(brna, "NodeSocketGeometry", "NodeSocketInterfaceGeometry"); + + rna_def_node_socket_collection(brna, "NodeSocketCollection", "NodeSocketInterfaceCollection"); } static void rna_def_internal_node(BlenderRNA *brna) diff --git a/source/blender/nodes/intern/node_socket.cc b/source/blender/nodes/intern/node_socket.cc index ebc70956147..fda44b3d4f2 100644 --- a/source/blender/nodes/intern/node_socket.cc +++ b/source/blender/nodes/intern/node_socket.cc @@ -280,6 +280,15 @@ void node_socket_init_default_value(bNodeSocket *sock) sock->default_value = dval; break; } + case SOCK_COLLECTION: { + bNodeSocketValueCollection *dval = (bNodeSocketValueCollection *)MEM_callocN( + sizeof(bNodeSocketValueCollection), "node socket value object"); + dval->value = nullptr; + + sock->default_value = dval; + break; + break; + } } } @@ -352,6 +361,13 @@ void node_socket_copy_default_value(bNodeSocket *to, const bNodeSocket *from) id_us_plus(&toval->value->id); break; } + case SOCK_COLLECTION: { + bNodeSocketValueCollection *toval = (bNodeSocketValueCollection *)to->default_value; + bNodeSocketValueCollection *fromval = (bNodeSocketValueCollection *)from->default_value; + *toval = *fromval; + id_us_plus(&toval->value->id); + break; + } } to->flag |= (from->flag & SOCK_HIDE_VALUE); @@ -673,6 +689,12 @@ static bNodeSocketType *make_socket_type_geometry() return socktype; } +static bNodeSocketType *make_socket_type_collection() +{ + bNodeSocketType *socktype = make_standard_socket_type(SOCK_COLLECTION, PROP_NONE); + return socktype; +} + void register_standard_node_socket_types(void) { /* draw callbacks are set in drawnode.c to avoid bad-level calls */ @@ -711,5 +733,7 @@ void register_standard_node_socket_types(void) nodeRegisterSocketType(make_socket_type_geometry()); + nodeRegisterSocketType(make_socket_type_collection()); + nodeRegisterSocketType(make_socket_type_virtual()); } diff --git a/source/blender/nodes/intern/node_util.c b/source/blender/nodes/intern/node_util.c index 123347afc19..9669dc6496b 100644 --- a/source/blender/nodes/intern/node_util.c +++ b/source/blender/nodes/intern/node_util.c @@ -451,6 +451,14 @@ static int node_datatype_priority(eNodeSocketDatatype from, eNodeSocketDatatype return -1; } } + case SOCK_COLLECTION: { + switch (from) { + case SOCK_COLLECTION: + return 1; + default: + return -1; + } + } default: return -1; } -- cgit v1.2.3 From 5ced167336d49ef42e96e205c72d3935ff302a7e Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Fri, 11 Dec 2020 17:47:58 +0100 Subject: Geometry Nodes: support collection sockets Part of D9739. --- .../blenkernel/BKE_persistent_data_handle.hh | 24 ++++++++++++++++++++++ source/blender/modifiers/intern/MOD_nodes.cc | 14 +++++++++++++ source/blender/nodes/intern/node_socket.cc | 5 +++++ 3 files changed, 43 insertions(+) (limited to 'source/blender') diff --git a/source/blender/blenkernel/BKE_persistent_data_handle.hh b/source/blender/blenkernel/BKE_persistent_data_handle.hh index 42a853886d7..bbee09c7bf4 100644 --- a/source/blender/blenkernel/BKE_persistent_data_handle.hh +++ b/source/blender/blenkernel/BKE_persistent_data_handle.hh @@ -27,6 +27,7 @@ #include "DNA_ID.h" +struct Collection; struct Object; namespace blender::bke { @@ -82,6 +83,11 @@ class PersistentObjectHandle : public PersistentIDHandle { using PersistentIDHandle::PersistentIDHandle; }; +class PersistentCollectionHandle : public PersistentIDHandle { + friend PersistentDataHandleMap; + using PersistentIDHandle::PersistentIDHandle; +}; + class PersistentDataHandleMap { private: Map id_by_handle_; @@ -107,6 +113,12 @@ class PersistentDataHandleMap { return PersistentObjectHandle(handle); } + PersistentCollectionHandle lookup(Collection *collection) const + { + const int handle = handle_by_id_.lookup_default((ID *)collection, -1); + return PersistentCollectionHandle(handle); + } + ID *lookup(const PersistentIDHandle &handle) const { ID *id = id_by_handle_.lookup_default(handle.handle_, nullptr); @@ -124,6 +136,18 @@ class PersistentDataHandleMap { } return (Object *)id; } + + Collection *lookup(const PersistentCollectionHandle &handle) const + { + ID *id = this->lookup((const PersistentIDHandle &)handle); + if (id == nullptr) { + return nullptr; + } + if (GS(id->name) != ID_GR) { + return nullptr; + } + return (Collection *)id; + } }; } // namespace blender::bke diff --git a/source/blender/modifiers/intern/MOD_nodes.cc b/source/blender/modifiers/intern/MOD_nodes.cc index 29ed08f0367..513e16e1a89 100644 --- a/source/blender/modifiers/intern/MOD_nodes.cc +++ b/source/blender/modifiers/intern/MOD_nodes.cc @@ -104,6 +104,12 @@ static void addIdsUsedBySocket(const ListBase *sockets, Set &ids) ids.add(&object->id); } } + else if (socket->type == SOCK_COLLECTION) { + Collection *collection = ((bNodeSocketValueCollection *)socket->default_value)->value; + if (collection != nullptr) { + ids.add(&collection->id); + } + } } } @@ -399,6 +405,11 @@ class GeometryNodesEvaluator { blender::bke::PersistentObjectHandle object_handle = handle_map_.lookup(object); new (buffer) blender::bke::PersistentObjectHandle(object_handle); } + else if (bsocket->type == SOCK_COLLECTION) { + Collection *collection = ((bNodeSocketValueCollection *)bsocket->default_value)->value; + blender::bke::PersistentCollectionHandle collection_handle = handle_map_.lookup(collection); + new (buffer) blender::bke::PersistentCollectionHandle(collection_handle); + } else { blender::nodes::socket_cpp_value_get(*bsocket, buffer); } @@ -850,6 +861,9 @@ static void check_property_socket_sync(const Object *ob, ModifierData *md) else if (socket->type == SOCK_GEOMETRY) { BKE_modifier_set_error(ob, md, "Node group can only have one geometry input"); } + else if (socket->type == SOCK_COLLECTION) { + BKE_modifier_set_error(ob, md, "Collection socket can not be exposed in the modifier"); + } else { BKE_modifier_set_error(ob, md, "Missing property for input socket \"%s\"", socket->name); } diff --git a/source/blender/nodes/intern/node_socket.cc b/source/blender/nodes/intern/node_socket.cc index fda44b3d4f2..06dd4b8c188 100644 --- a/source/blender/nodes/intern/node_socket.cc +++ b/source/blender/nodes/intern/node_socket.cc @@ -664,6 +664,7 @@ class ObjectSocketMultiFunction : public blender::fn::MultiFunction { }; MAKE_CPP_TYPE(PersistentObjectHandle, blender::bke::PersistentObjectHandle); +MAKE_CPP_TYPE(PersistentCollectionHandle, blender::bke::PersistentCollectionHandle); static bNodeSocketType *make_socket_type_object() { @@ -692,6 +693,10 @@ static bNodeSocketType *make_socket_type_geometry() static bNodeSocketType *make_socket_type_collection() { bNodeSocketType *socktype = make_standard_socket_type(SOCK_COLLECTION, PROP_NONE); + socktype->get_cpp_type = []() { + /* Objects are not passed along as raw pointers, but as handles. */ + return &blender::fn::CPPType::get(); + }; return socktype; } -- cgit v1.2.3 From f5dc34ec9c05cc8f1163313baafe634f4798c29b Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Fri, 11 Dec 2020 18:00:37 +0100 Subject: Geometry Nodes: support instancing collections The Point Instance node can instance entire collections now. Before, only individual collections were supported. Randomly selecting objects from the collection on a per point basis is not support, yet. Last part of D9739. Ref T82372. --- source/blender/blenkernel/BKE_geometry_set.h | 16 +++++- source/blender/blenkernel/BKE_geometry_set.hh | 15 ++++-- source/blender/blenkernel/intern/geometry_set.cc | 46 ++++++++++++---- source/blender/blenkernel/intern/object_dupli.c | 53 +++++++++++++----- source/blender/editors/space_node/drawnode.c | 10 ++++ source/blender/makesdna/DNA_node_types.h | 5 ++ source/blender/makesrna/intern/rna_nodetree.c | 26 +++++++++ source/blender/nodes/NOD_static_types.h | 2 +- .../nodes/geometry/nodes/node_geo_join_geometry.cc | 4 +- .../geometry/nodes/node_geo_point_instance.cc | 63 +++++++++++++++++----- 10 files changed, 196 insertions(+), 44 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/BKE_geometry_set.h b/source/blender/blenkernel/BKE_geometry_set.h index 026f4d39d51..87bb96be145 100644 --- a/source/blender/blenkernel/BKE_geometry_set.h +++ b/source/blender/blenkernel/BKE_geometry_set.h @@ -26,16 +26,30 @@ extern "C" { struct Object; struct GeometrySet; +struct Collection; void BKE_geometry_set_free(struct GeometrySet *geometry_set); bool BKE_geometry_set_has_instances(const struct GeometrySet *geometry_set); +typedef enum InstancedDataType { + INSTANCE_DATA_TYPE_OBJECT = 0, + INSTANCE_DATA_TYPE_COLLECTION = 1, +} InstancedDataType; + +typedef struct InstancedData { + InstancedDataType type; + union { + struct Object *object; + struct Collection *collection; + } data; +} InstancedData; + int BKE_geometry_set_instances(const struct GeometrySet *geometry_set, float (**r_positions)[3], float (**r_rotations)[3], float (**r_scales)[3], - struct Object ***r_objects); + struct InstancedData **r_instanced_data); #ifdef __cplusplus } diff --git a/source/blender/blenkernel/BKE_geometry_set.hh b/source/blender/blenkernel/BKE_geometry_set.hh index b7cb9320086..617e0c45ae4 100644 --- a/source/blender/blenkernel/BKE_geometry_set.hh +++ b/source/blender/blenkernel/BKE_geometry_set.hh @@ -35,6 +35,7 @@ struct Mesh; struct PointCloud; struct Object; +struct Collection; /* Each geometry component has a specific type. The type determines what kind of data the component * stores. Functions modifying a geometry will usually just modify a subset of the component types. @@ -358,7 +359,7 @@ class InstancesComponent : public GeometryComponent { blender::Vector positions_; blender::Vector rotations_; blender::Vector scales_; - blender::Vector objects_; + blender::Vector instanced_data_; public: InstancesComponent(); @@ -366,12 +367,20 @@ class InstancesComponent : public GeometryComponent { GeometryComponent *copy() const override; void clear(); - void add_instance(const Object *object, + void add_instance(Object *object, blender::float3 position, blender::float3 rotation = {0, 0, 0}, blender::float3 scale = {1, 1, 1}); + void add_instance(Collection *collection, + blender::float3 position, + blender::float3 rotation = {0, 0, 0}, + blender::float3 scale = {1, 1, 1}); + void add_instance(InstancedData data, + blender::float3 position, + blender::float3 rotation, + blender::float3 scale); - blender::Span objects() const; + blender::Span instanced_data() const; blender::Span positions() const; blender::Span rotations() const; blender::Span scales() const; diff --git a/source/blender/blenkernel/intern/geometry_set.cc b/source/blender/blenkernel/intern/geometry_set.cc index 28695d769d3..e6a67b191f8 100644 --- a/source/blender/blenkernel/intern/geometry_set.cc +++ b/source/blender/blenkernel/intern/geometry_set.cc @@ -460,31 +460,54 @@ GeometryComponent *InstancesComponent::copy() const new_component->positions_ = positions_; new_component->rotations_ = rotations_; new_component->scales_ = scales_; - new_component->objects_ = objects_; + new_component->instanced_data_ = instanced_data_; return new_component; } void InstancesComponent::clear() { - objects_.clear(); + instanced_data_.clear(); positions_.clear(); rotations_.clear(); scales_.clear(); } -void InstancesComponent::add_instance(const Object *object, + +void InstancesComponent::add_instance(Object *object, + blender::float3 position, + blender::float3 rotation, + blender::float3 scale) +{ + InstancedData data; + data.type = INSTANCE_DATA_TYPE_OBJECT; + data.data.object = object; + this->add_instance(data, position, rotation, scale); +} + +void InstancesComponent::add_instance(Collection *collection, + blender::float3 position, + blender::float3 rotation, + blender::float3 scale) +{ + InstancedData data; + data.type = INSTANCE_DATA_TYPE_COLLECTION; + data.data.collection = collection; + this->add_instance(data, position, rotation, scale); +} + +void InstancesComponent::add_instance(InstancedData data, blender::float3 position, blender::float3 rotation, blender::float3 scale) { - objects_.append(object); + instanced_data_.append(data); positions_.append(position); rotations_.append(rotation); scales_.append(scale); } -Span InstancesComponent::objects() const +Span InstancesComponent::instanced_data() const { - return objects_; + return instanced_data_; } Span InstancesComponent::positions() const @@ -509,8 +532,11 @@ MutableSpan InstancesComponent::positions() int InstancesComponent::instances_amount() const { - BLI_assert(positions_.size() == objects_.size()); - return objects_.size(); + const int size = instanced_data_.size(); + BLI_assert(positions_.size() == size); + BLI_assert(rotations_.size() == size); + BLI_assert(scales_.size() == size); + return size; } bool InstancesComponent::is_empty() const @@ -538,7 +564,7 @@ int BKE_geometry_set_instances(const GeometrySet *geometry_set, float (**r_positions)[3], float (**r_rotations)[3], float (**r_scales)[3], - Object ***r_objects) + InstancedData **r_instanced_data) { const InstancesComponent *component = geometry_set->get_component_for_read(); if (component == nullptr) { @@ -547,7 +573,7 @@ int BKE_geometry_set_instances(const GeometrySet *geometry_set, *r_positions = (float(*)[3])component->positions().data(); *r_rotations = (float(*)[3])component->rotations().data(); *r_scales = (float(*)[3])component->scales().data(); - *r_objects = (Object **)component->objects().data(); + *r_instanced_data = (InstancedData *)component->instanced_data().data(); return component->instances_amount(); } diff --git a/source/blender/blenkernel/intern/object_dupli.c b/source/blender/blenkernel/intern/object_dupli.c index d5434710e23..8fa708f31cb 100644 --- a/source/blender/blenkernel/intern/object_dupli.c +++ b/source/blender/blenkernel/intern/object_dupli.c @@ -816,15 +816,13 @@ static void make_duplis_instances_component(const DupliContext *ctx) float(*positions)[3]; float(*rotations)[3]; float(*scales)[3]; - Object **objects; + InstancedData *instanced_data; const int amount = BKE_geometry_set_instances( - ctx->object->runtime.geometry_set_eval, &positions, &rotations, &scales, &objects); + ctx->object->runtime.geometry_set_eval, &positions, &rotations, &scales, &instanced_data); for (int i = 0; i < amount; i++) { - Object *object = objects[i]; - if (object == NULL) { - continue; - } + InstancedData *data = &instanced_data[i]; + float scale_matrix[4][4]; size_to_mat4(scale_matrix, scales[i]); float rotation_matrix[4][4]; @@ -833,14 +831,43 @@ static void make_duplis_instances_component(const DupliContext *ctx) mul_m4_m4m4(instance_offset_matrix, rotation_matrix, scale_matrix); copy_v3_v3(instance_offset_matrix[3], positions[i]); - float matrix[4][4]; - mul_m4_m4m4(matrix, ctx->object->obmat, instance_offset_matrix); - make_dupli(ctx, object, matrix, i); + if (data->type == INSTANCE_DATA_TYPE_OBJECT) { + Object *object = data->data.object; + if (object != NULL) { + float matrix[4][4]; + mul_m4_m4m4(matrix, ctx->object->obmat, instance_offset_matrix); + make_dupli(ctx, object, matrix, i); + + float space_matrix[4][4]; + mul_m4_m4m4(space_matrix, instance_offset_matrix, object->imat); + mul_m4_m4_pre(space_matrix, ctx->object->obmat); + make_recursive_duplis(ctx, object, space_matrix, i); + } + } + else if (data->type == INSTANCE_DATA_TYPE_COLLECTION) { + Collection *collection = data->data.collection; + if (collection != NULL) { + float collection_matrix[4][4]; + unit_m4(collection_matrix); + sub_v3_v3(collection_matrix[3], collection->instance_offset); + mul_m4_m4_pre(collection_matrix, instance_offset_matrix); + mul_m4_m4_pre(collection_matrix, ctx->object->obmat); + + eEvaluationMode mode = DEG_get_mode(ctx->depsgraph); + FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_BEGIN (collection, object, mode) { + if (object == ctx->object) { + continue; + } + + float instance_matrix[4][4]; + mul_m4_m4m4(instance_matrix, collection_matrix, object->obmat); - float space_matrix[4][4]; - mul_m4_m4m4(space_matrix, instance_offset_matrix, object->imat); - mul_m4_m4_pre(space_matrix, ctx->object->obmat); - make_recursive_duplis(ctx, object, space_matrix, i); + make_dupli(ctx, object, instance_matrix, i); + make_recursive_duplis(ctx, object, collection_matrix, i); + } + FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_END; + } + } } } diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index f1ab433c639..f8c71791054 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -3182,6 +3182,13 @@ static void node_geometry_buts_attribute_math(uiLayout *layout, uiItemR(layout, ptr, "input_type_b", DEFAULT_FLAGS, IFACE_("Type B"), ICON_NONE); } +static void node_geometry_buts_point_instance(uiLayout *layout, + bContext *UNUSED(C), + PointerRNA *ptr) +{ + uiItemR(layout, ptr, "instance_type", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); +} + static void node_geometry_buts_attribute_fill(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -3219,6 +3226,9 @@ static void node_geometry_set_butfunc(bNodeType *ntype) case GEO_NODE_ATTRIBUTE_MATH: ntype->draw_buttons = node_geometry_buts_attribute_math; break; + case GEO_NODE_POINT_INSTANCE: + ntype->draw_buttons = node_geometry_buts_point_instance; + break; case GEO_NODE_ATTRIBUTE_FILL: ntype->draw_buttons = node_geometry_buts_attribute_fill; break; diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index e04867438f1..8e463a8b406 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -1480,6 +1480,11 @@ typedef enum GeometryNodeUseAttributeFlag { GEO_NODE_USE_ATTRIBUTE_B = (1 << 1), } GeometryNodeUseAttributeFlag; +typedef enum GeometryNodePointInstanceType { + GEO_NODE_POINT_INSTANCE_TYPE_OBJECT = 0, + GEO_NODE_POINT_INSTANCE_TYPE_COLLECTION = 1, +} GeometryNodePointInstanceType; + typedef enum GeometryNodeAttributeInputMode { GEO_NODE_ATTRIBUTE_INPUT_ATTRIBUTE = 0, GEO_NODE_ATTRIBUTE_INPUT_FLOAT = 1, diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 461b6af506a..34d922fe2c8 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -8415,6 +8415,32 @@ static void def_geo_attribute_math(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); } +static void def_geo_point_instance(StructRNA *srna) +{ + static const EnumPropertyItem instance_type_items[] = { + {GEO_NODE_POINT_INSTANCE_TYPE_OBJECT, + "OBJECT", + ICON_NONE, + "Object", + "Instance an individual object on all points"}, + {GEO_NODE_POINT_INSTANCE_TYPE_COLLECTION, + "COLLECTION", + ICON_NONE, + "Collection", + "Instance an entire collection on all points"}, + {0, NULL, 0, NULL, NULL}, + }; + + PropertyRNA *prop; + + prop = RNA_def_property(srna, "instance_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "custom1"); + RNA_def_property_enum_items(prop, instance_type_items); + RNA_def_property_enum_default(prop, GEO_NODE_POINT_INSTANCE_TYPE_OBJECT); + RNA_def_property_ui_text(prop, "Instance Type", ""); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); +} + static void def_geo_attribute_mix(StructRNA *srna) { PropertyRNA *prop; diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h index d1032647ba8..491f49cf425 100644 --- a/source/blender/nodes/NOD_static_types.h +++ b/source/blender/nodes/NOD_static_types.h @@ -272,7 +272,7 @@ DefNode(GeometryNode, GEO_NODE_TRANSFORM, 0, "TRANSFORM", Transform, "Transform" DefNode(GeometryNode, GEO_NODE_SUBDIVISION_SURFACE, 0, "SUBDIVISION_SURFACE", SubdivisionSurface, "Subdivision Surface", "") DefNode(GeometryNode, GEO_NODE_BOOLEAN, def_geo_boolean, "BOOLEAN", Boolean, "Boolean", "") DefNode(GeometryNode, GEO_NODE_POINT_DISTRIBUTE, 0, "POINT_DISTRIBUTE", PointDistribute, "Point Distribute", "") -DefNode(GeometryNode, GEO_NODE_POINT_INSTANCE, 0, "POINT_INSTANCE", PointInstance, "Point Instance", "") +DefNode(GeometryNode, GEO_NODE_POINT_INSTANCE, def_geo_point_instance, "POINT_INSTANCE", PointInstance, "Point Instance", "") DefNode(GeometryNode, GEO_NODE_OBJECT_INFO, 0, "OBJECT_INFO", ObjectInfo, "Object Info", "") DefNode(GeometryNode, GEO_NODE_RANDOM_ATTRIBUTE, def_geo_random_attribute, "RANDOM_ATTRIBUTE", RandomAttribute, "Random Attribute", "") DefNode(GeometryNode, GEO_NODE_ATTRIBUTE_MATH, def_geo_attribute_math, "ATTRIBUTE_MATH", AttributeMath, "Attribute Math", "") diff --git a/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc b/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc index dedc3213a1f..80ac45aed4e 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc @@ -218,12 +218,12 @@ static void join_components(Span src_components, Geo InstancesComponent &dst_component = result.get_component_for_write(); for (const InstancesComponent *component : src_components) { const int size = component->instances_amount(); - Span objects = component->objects(); + Span instanced_data = component->instanced_data(); Span positions = component->positions(); Span rotations = component->rotations(); Span scales = component->scales(); for (const int i : IndexRange(size)) { - dst_component.add_instance(objects[i], positions[i], rotations[i], scales[i]); + dst_component.add_instance(instanced_data[i], positions[i], rotations[i], scales[i]); } } } diff --git a/source/blender/nodes/geometry/nodes/node_geo_point_instance.cc b/source/blender/nodes/geometry/nodes/node_geo_point_instance.cc index 6d979e3b7da..e030bc3eec6 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_point_instance.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_point_instance.cc @@ -25,6 +25,7 @@ static bNodeSocketTemplate geo_node_point_instance_in[] = { {SOCK_GEOMETRY, N_("Geometry")}, {SOCK_OBJECT, N_("Object")}, + {SOCK_COLLECTION, N_("Collection")}, {-1, ""}, }; @@ -35,9 +36,21 @@ static bNodeSocketTemplate geo_node_point_instance_out[] = { namespace blender::nodes { +static void geo_node_point_instance_update(bNodeTree *UNUSED(tree), bNode *node) +{ + bNodeSocket *object_socket = (bNodeSocket *)BLI_findlink(&node->inputs, 1); + bNodeSocket *collection_socket = object_socket->next; + + GeometryNodePointInstanceType type = (GeometryNodePointInstanceType)node->custom1; + + nodeSetSocketAvailability(object_socket, type == GEO_NODE_POINT_INSTANCE_TYPE_OBJECT); + nodeSetSocketAvailability(collection_socket, type == GEO_NODE_POINT_INSTANCE_TYPE_COLLECTION); +} + static void add_instances_from_geometry_component(InstancesComponent &instances, const GeometryComponent &src_geometry, - Object *object) + Object *object, + Collection *collection) { Float3ReadAttribute positions = src_geometry.attribute_get_for_read( "position", ATTR_DOMAIN_POINT, {0, 0, 0}); @@ -47,30 +60,51 @@ static void add_instances_from_geometry_component(InstancesComponent &instances, "scale", ATTR_DOMAIN_POINT, {1, 1, 1}); for (const int i : IndexRange(positions.size())) { - instances.add_instance(object, positions[i], rotations[i], scales[i]); + if (object != nullptr) { + instances.add_instance(object, positions[i], rotations[i], scales[i]); + } + if (collection != nullptr) { + instances.add_instance(collection, positions[i], rotations[i], scales[i]); + } } } static void geo_node_point_instance_exec(GeoNodeExecParams params) { + GeometryNodePointInstanceType type = (GeometryNodePointInstanceType)params.node().custom1; GeometrySet geometry_set = params.extract_input("Geometry"); GeometrySet geometry_set_out; - bke::PersistentObjectHandle object_handle = params.extract_input( - "Object"); - Object *object = params.handle_map().lookup(object_handle); + Object *object = nullptr; + Collection *collection = nullptr; - if (object != nullptr && object != params.self_object()) { - InstancesComponent &instances = geometry_set_out.get_component_for_write(); - if (geometry_set.has()) { - add_instances_from_geometry_component( - instances, *geometry_set.get_component_for_read(), object); - } - if (geometry_set.has()) { - add_instances_from_geometry_component( - instances, *geometry_set.get_component_for_read(), object); + if (type == GEO_NODE_POINT_INSTANCE_TYPE_OBJECT) { + bke::PersistentObjectHandle object_handle = params.extract_input( + "Object"); + object = params.handle_map().lookup(object_handle); + /* Avoid accidental recursion of instances. */ + if (object == params.self_object()) { + object = nullptr; } } + else if (type == GEO_NODE_POINT_INSTANCE_TYPE_COLLECTION) { + bke::PersistentCollectionHandle collection_handle = + params.extract_input("Collection"); + collection = params.handle_map().lookup(collection_handle); + } + + InstancesComponent &instances = geometry_set_out.get_component_for_write(); + if (geometry_set.has()) { + add_instances_from_geometry_component( + instances, *geometry_set.get_component_for_read(), object, collection); + } + if (geometry_set.has()) { + add_instances_from_geometry_component( + instances, + *geometry_set.get_component_for_read(), + object, + collection); + } params.set_output("Geometry", std::move(geometry_set_out)); } @@ -82,6 +116,7 @@ void register_node_type_geo_point_instance() geo_node_type_base(&ntype, GEO_NODE_POINT_INSTANCE, "Point Instance", NODE_CLASS_GEOMETRY, 0); node_type_socket_templates(&ntype, geo_node_point_instance_in, geo_node_point_instance_out); + node_type_update(&ntype, blender::nodes::geo_node_point_instance_update); ntype.geometry_node_execute = blender::nodes::geo_node_point_instance_exec; nodeRegisterType(&ntype); } -- cgit v1.2.3 From 561d9169fea7141b09100c563bc20560c760edd1 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Fri, 11 Dec 2020 18:12:29 +0100 Subject: Fix T83280: Crash when deleting hair collision collection. Root of the issue was missing management of ID pointers in the cloth modifier data stored in ParticleSystem for hair physics, in the 'foreach_id' particle system code. Using modifier's 'foreach_id' code in psys one unfortunately requires some ugly conversion gymnastics, but this is still better than having dedicated code for that case. Note that this is actually a fairly critical issue, fix should be backported to 2.91.1 should we do it, and to 2.83 LTS as well I think. --- source/blender/blenkernel/intern/particle_system.c | 28 ++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'source/blender') diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 35265cf8b68..79ce6769160 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -4978,6 +4978,24 @@ void particle_system_update(struct Depsgraph *depsgraph, /* ID looper */ +/* unfortunately PSys and modifier ID loopers are not directly compatible, so we need this struct + * and the callback below to map the former to the latter (thanks to psys embedding a Cloth + * modifier data struct now, for Hair physics simulations). */ +typedef struct ParticleSystemIDLoopForModifier { + ParticleSystem *psys; + ParticleSystemIDFunc func; + void *userdata; +} ParticleSystemIDLoopForModifier; + +static void particlesystem_modifiersForeachIDLink(void *user_data, + Object *UNUSED(object), + ID **id_pointer, + int cb_flag) +{ + ParticleSystemIDLoopForModifier *data = (ParticleSystemIDLoopForModifier *)user_data; + data->func(data->psys, id_pointer, data->userdata, cb_flag); +} + void BKE_particlesystem_id_loop(ParticleSystem *psys, ParticleSystemIDFunc func, void *userdata) { ParticleTarget *pt; @@ -4986,6 +5004,16 @@ void BKE_particlesystem_id_loop(ParticleSystem *psys, ParticleSystemIDFunc func, func(psys, (ID **)&psys->target_ob, userdata, IDWALK_CB_NOP); func(psys, (ID **)&psys->parent, userdata, IDWALK_CB_NOP); + if (psys->clmd != NULL) { + const ModifierTypeInfo *mti = BKE_modifier_get_info(psys->clmd->modifier.type); + + if (mti->foreachIDLink != NULL) { + ParticleSystemIDLoopForModifier data = {.psys = psys, .func = func, .userdata = userdata}; + mti->foreachIDLink( + &psys->clmd->modifier, NULL, particlesystem_modifiersForeachIDLink, &data); + } + } + for (pt = psys->targets.first; pt; pt = pt->next) { func(psys, (ID **)&pt->ob, userdata, IDWALK_CB_NOP); } -- cgit v1.2.3 From b73ed882c0d0dd3b4fed652e06240b0d705f3f80 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Fri, 11 Dec 2020 19:02:09 +0100 Subject: Cleanup: clang tidy --- source/blender/io/common/intern/abstract_hierarchy_iterator_test.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender') diff --git a/source/blender/io/common/intern/abstract_hierarchy_iterator_test.cc b/source/blender/io/common/intern/abstract_hierarchy_iterator_test.cc index 8acdba416d3..457d68953ff 100644 --- a/source/blender/io/common/intern/abstract_hierarchy_iterator_test.cc +++ b/source/blender/io/common/intern/abstract_hierarchy_iterator_test.cc @@ -36,7 +36,7 @@ namespace { /* Mapping from ID.name to set of export hierarchy path. Duplicated objects can be exported * multiple times with different export paths, hence the set. */ -typedef std::map> used_writers; +using used_writers = std::map>; class TestHierarchyWriter : public AbstractHierarchyWriter { public: -- cgit v1.2.3 From 97651f428b6ae6901cbacd9805616fe96052bc9b Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Fri, 11 Dec 2020 12:15:51 -0600 Subject: Fix T83050: Crash dragging shared collection to master collection The flag syncing code expects to find collection flags in same view layer before and after the move, it even has an assert for it. However, there is one case where this doesn't happen, when dragging a collection that exists in two scenes to the master collection. This commit removes this assert, frees the temporary flag structs separately, and updates some comments with this information. There is more detail in the adjusted comment. Differential Revision: https://developer.blender.org/D9785 --- source/blender/blenkernel/intern/collection.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c index 5eec788255d..b86b59066d6 100644 --- a/source/blender/blenkernel/intern/collection.c +++ b/source/blender/blenkernel/intern/collection.c @@ -1773,6 +1773,15 @@ static void layer_collection_flags_store(Main *bmain, } } +static void layer_collection_flags_free_recursive(LayerCollectionFlag *flag) +{ + LISTBASE_FOREACH (LayerCollectionFlag *, child, &flag->children) { + layer_collection_flags_free_recursive(child); + } + + BLI_freelistN(&flag->children); +} + static void layer_collection_flags_restore_recursive(LayerCollection *layer_collection, LayerCollectionFlag *flag) { @@ -1788,7 +1797,6 @@ static void layer_collection_flags_restore_recursive(LayerCollection *layer_coll child_flag = child_flag->next; } - BLI_freelistN(&flag->children); /* We treat exclude as a special case. * @@ -1814,10 +1822,15 @@ static void layer_collection_flags_restore(ListBase *flags, const Collection *co LayerCollection *layer_collection = BKE_layer_collection_first_from_scene_collection( view_layer, collection); - /* The flags should only be added if the collection is in the view layer. */ - BLI_assert(layer_collection != NULL); - - layer_collection_flags_restore_recursive(layer_collection, flag); + /* Check that the collection is still in the scene (and therefore its view layers). In most + * cases this is true, but if we move a sub-collection shared by several scenes to a collection + * local to the target scene, it is effectively removed from every other scene's hierarchy + * (e.g. moving into current scene's master collection). Then the other scene's view layers + * won't contain a matching layer collection anymore, so there is nothing to restore to. */ + if (layer_collection != NULL) { + layer_collection_flags_restore_recursive(layer_collection, flag); + } + layer_collection_flags_free_recursive(flag); } BLI_freelistN(flags); @@ -1877,7 +1890,7 @@ bool BKE_collection_move(Main *bmain, /* Create and remove layer collections. */ BKE_main_collection_sync(bmain); - /* Restore the original layer collection flags. */ + /* Restore the original layer collection flags and free their temporary storage. */ if (do_flag_sync) { layer_collection_flags_restore(&layer_flags, collection); } -- cgit v1.2.3 From 92ab76c38ff8f3ed1af5efeba00becbb319b77fb Mon Sep 17 00:00:00 2001 From: Harley Acheson Date: Fri, 11 Dec 2020 10:48:30 -0800 Subject: Cleanup: clang-format Forgot to run Make Format on recent spelling changes --- source/blender/makesrna/intern/rna_access.c | 7 +++++-- source/blender/makesrna/intern/rna_object_force.c | 9 +++++---- source/blender/makesrna/intern/rna_space.c | 3 ++- source/blender/makesrna/intern/rna_userdef.c | 9 +++++---- 4 files changed, 17 insertions(+), 11 deletions(-) (limited to 'source/blender') diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index 25fe37c2d02..b03df1a82f3 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -1105,8 +1105,11 @@ bool RNA_struct_bl_idname_ok_or_report(ReportList *reports, const bool failure = false; #endif if (p == NULL || p == identifier || p + len_sep >= identifier + len_id) { - BKE_reportf( - reports, report_level, "'%s' does not contain '%s' with prefix and suffix", identifier, sep); + BKE_reportf(reports, + report_level, + "'%s' does not contain '%s' with prefix and suffix", + identifier, + sep); return failure; } diff --git a/source/blender/makesrna/intern/rna_object_force.c b/source/blender/makesrna/intern/rna_object_force.c index 106de759cfc..58f0502ab34 100644 --- a/source/blender/makesrna/intern/rna_object_force.c +++ b/source/blender/makesrna/intern/rna_object_force.c @@ -1486,10 +1486,11 @@ static void rna_def_field(BlenderRNA *brna) prop = RNA_def_property(srna, "texture_mode", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "tex_mode"); RNA_def_property_enum_items(prop, texture_items); - RNA_def_property_ui_text(prop, - "Texture Mode", - "How the texture effect is calculated (RGB and Curl need a RGB texture, " - "else Gradient will be used instead)"); + RNA_def_property_ui_text( + prop, + "Texture Mode", + "How the texture effect is calculated (RGB and Curl need a RGB texture, " + "else Gradient will be used instead)"); RNA_def_property_update(prop, 0, "rna_FieldSettings_update"); prop = RNA_def_property(srna, "z_direction", PROP_ENUM, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 44d72a65adb..d0afebe5465 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -4281,7 +4281,8 @@ static void rna_def_space_view3d(BlenderRNA *brna) /* Camera Object Data. */ prop = RNA_def_property(srna, "show_gizmo_camera_lens", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "gizmo_show_camera", V3D_GIZMO_SHOW_CAMERA_LENS); - RNA_def_property_ui_text(prop, "Show Camera Lens", "Gizmo to adjust camera focal length or orthographic scale"); + RNA_def_property_ui_text( + prop, "Show Camera Lens", "Gizmo to adjust camera focal length or orthographic scale"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); prop = RNA_def_property(srna, "show_gizmo_camera_dof_distance", PROP_BOOLEAN, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 918bcb01170..2c659f06e90 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -6067,10 +6067,11 @@ static void rna_def_userdef_filepaths(BlenderRNA *brna) prop = RNA_def_property(srna, "script_directory", PROP_STRING, PROP_DIRPATH); RNA_def_property_string_sdna(prop, NULL, "pythondir"); - RNA_def_property_ui_text(prop, - "Python Scripts Directory", - "Alternate script path, matching the default layout with subdirectories: " - "startup, add-ons and modules (requires restart)"); + RNA_def_property_ui_text( + prop, + "Python Scripts Directory", + "Alternate script path, matching the default layout with subdirectories: " + "startup, add-ons and modules (requires restart)"); /* TODO, editing should reset sys.path! */ prop = RNA_def_property(srna, "i18n_branches_directory", PROP_STRING, PROP_DIRPATH); -- cgit v1.2.3 From 87b19b3aba0c8535d48ad07e2dae2e09373c913a Mon Sep 17 00:00:00 2001 From: Ray Molenkamp Date: Fri, 11 Dec 2020 11:59:14 -0700 Subject: Fix: BLI_getenv returns ascii not UTF8 on windows BLI_getenv has always incorrectly returned ascii rather than UTF-8. This change corrects this behaviour. This resolves issues when the `BLENDER_USER_CONFIG` environment variable contains a path with Unicode characters on windows as reported in T74510 (but unlikely the root cause for the issue at hand there) Differential Revision: https://developer.blender.org/D9831 Reviewed by: brecht --- source/blender/blenlib/intern/path_util.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c index 74bbe59bc04..461f8a53beb 100644 --- a/source/blender/blenlib/intern/path_util.c +++ b/source/blender/blenlib/intern/path_util.c @@ -32,6 +32,7 @@ #include "BLI_fnmatch.h" #include "BLI_path_util.h" #include "BLI_string.h" +#include "BLI_string_utf8.h" #include "BLI_utildefines.h" #ifdef WIN32 @@ -1307,18 +1308,30 @@ void BLI_setenv_if_new(const char *env, const char *val) * On windows getenv gets its variables from a static copy of the environment variables taken at * process start-up, causing it to not pick up on environment variables created during runtime. * This function uses an alternative method to get environment variables that does pick up on - * runtime environment variables. + * runtime environment variables. The result will be UTF-8 encoded. */ + const char *BLI_getenv(const char *env) { #ifdef _MSC_VER - static char buffer[32767]; /* 32767 is the total size of the environment block on windows*/ - if (GetEnvironmentVariableA(env, buffer, sizeof(buffer))) { - return buffer; - } - else { - return NULL; + const char *result = NULL; + static wchar_t buffer[32768]; /* 32767 is the maximum size of the environment variable on + windows, reserve one more character for the zero terminator. */ + wchar_t *env_16 = alloc_utf16_from_8(env, 0); + if (env_16) { + if (GetEnvironmentVariableW(env_16, buffer, ARRAY_SIZE(buffer))) { + char *res_utf8 = alloc_utf_8_from_16(buffer, 0); + // make sure the result is valid, and will fit into our temporary storage buffer + if (res_utf8 && (strlen(res_utf8) + 1) < sizeof(buffer)) { + // We are re-using the utf16 buffer here, since allocating a second static buffer to + // contain the UTF-8 version to return would be wasteful. + memcpy(buffer, res_utf8, strlen(res_utf8) + 1); + free(res_utf8); + result = (const char *)buffer; + } + } } + return result; #else return getenv(env); #endif -- cgit v1.2.3 From cada56b1f72f537f9ab007cfafd430ac10c292fb Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Fri, 11 Dec 2020 15:35:55 -0300 Subject: Cleanup: GPU Python: Use 'PyC_ParseStringEnum' for string enum --- source/blender/python/gpu/gpu_py_shader.c | 61 +++++++++---------------------- 1 file changed, 18 insertions(+), 43 deletions(-) (limited to 'source/blender') diff --git a/source/blender/python/gpu/gpu_py_shader.c b/source/blender/python/gpu/gpu_py_shader.c index c90a4a7bc9d..0e7252bc71a 100644 --- a/source/blender/python/gpu/gpu_py_shader.c +++ b/source/blender/python/gpu/gpu_py_shader.c @@ -39,41 +39,17 @@ /** \name Enum Conversion. * \{ */ -static int bpygpu_ParseBultinShaderEnum(PyObject *o, void *p) -{ - Py_ssize_t mode_id_len; - const char *mode_id = _PyUnicode_AsStringAndSize(o, &mode_id_len); - if (mode_id == NULL) { - PyErr_Format(PyExc_ValueError, "expected a string, got %s", Py_TYPE(o)->tp_name); - return 0; - } -#define MATCH_ID(id) \ - if (mode_id_len == (Py_ssize_t)strlen(STRINGIFY(id))) { \ - if (STREQ(mode_id, STRINGIFY(id))) { \ - mode = GPU_SHADER_##id; \ - goto success; \ - } \ - } \ - ((void)0) - - eGPUBuiltinShader mode; - MATCH_ID(2D_UNIFORM_COLOR); - MATCH_ID(2D_FLAT_COLOR); - MATCH_ID(2D_SMOOTH_COLOR); - MATCH_ID(2D_IMAGE); - MATCH_ID(3D_UNIFORM_COLOR); - MATCH_ID(3D_FLAT_COLOR); - MATCH_ID(3D_SMOOTH_COLOR); - MATCH_ID(3D_POLYLINE_UNIFORM_COLOR); - -#undef MATCH_ID - PyErr_Format(PyExc_ValueError, "unknown type literal: '%s'", mode_id); - return 0; - -success: - (*(eGPUBuiltinShader *)p) = mode; - return 1; -} +static const struct PyC_StringEnumItems pygpu_bultinshader_items[] = { + {GPU_SHADER_2D_UNIFORM_COLOR, "2D_UNIFORM_COLOR"}, + {GPU_SHADER_2D_FLAT_COLOR, "2D_FLAT_COLOR"}, + {GPU_SHADER_2D_SMOOTH_COLOR, "2D_SMOOTH_COLOR"}, + {GPU_SHADER_2D_IMAGE, "2D_IMAGE"}, + {GPU_SHADER_3D_UNIFORM_COLOR, "3D_UNIFORM_COLOR"}, + {GPU_SHADER_3D_FLAT_COLOR, "3D_FLAT_COLOR"}, + {GPU_SHADER_3D_SMOOTH_COLOR, "3D_SMOOTH_COLOR"}, + {GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR, "3D_POLYLINE_UNIFORM_COLOR"}, + {0, NULL}, +}; static int bpygpu_uniform_location_get(GPUShader *shader, const char *name, @@ -672,13 +648,12 @@ static PyObject *bpygpu_shader_from_builtin(PyObject *UNUSED(self), PyObject *ar { BPYGPU_IS_INIT_OR_ERROR_OBJ; - eGPUBuiltinShader shader_id; - - if (!bpygpu_ParseBultinShaderEnum(arg, &shader_id)) { + const struct PyC_StringEnum pygpu_bultinshader = {&pygpu_bultinshader_items, -1}; + if (!PyC_ParseStringEnum(arg, &pygpu_bultinshader)) { return NULL; } - GPUShader *shader = GPU_shader_get_builtin_shader(shader_id); + GPUShader *shader = GPU_shader_get_builtin_shader(pygpu_bultinshader.value_found); return BPyGPUShader_CreatePyObject(shader, true); } @@ -701,8 +676,6 @@ PyDoc_STRVAR(bpygpu_shader_code_from_builtin_doc, " :rtype: dict\n"); static PyObject *bpygpu_shader_code_from_builtin(BPyGPUShader *UNUSED(self), PyObject *arg) { - eGPUBuiltinShader shader_id; - const char *vert; const char *frag; const char *geom; @@ -710,11 +683,13 @@ static PyObject *bpygpu_shader_code_from_builtin(BPyGPUShader *UNUSED(self), PyO PyObject *item, *r_dict; - if (!bpygpu_ParseBultinShaderEnum(arg, &shader_id)) { + const struct PyC_StringEnum pygpu_bultinshader = {&pygpu_bultinshader_items, -1}; + if (!PyC_ParseStringEnum(arg, &pygpu_bultinshader)) { return NULL; } - GPU_shader_get_builtin_shader_code(shader_id, &vert, &frag, &geom, &defines); + GPU_shader_get_builtin_shader_code( + pygpu_bultinshader.value_found, &vert, &frag, &geom, &defines); r_dict = PyDict_New(); -- cgit v1.2.3 From bbd7f94d8a51e4a6c57dbcc49cea1fb2afcb8ff3 Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Fri, 11 Dec 2020 16:05:58 -0300 Subject: Cleanup: Python GPU: change prefix 'bpygpu_' to 'py_' in static functions --- source/blender/python/gpu/gpu_py_batch.c | 56 +++---- source/blender/python/gpu/gpu_py_element.c | 8 +- source/blender/python/gpu/gpu_py_matrix.c | 181 +++++++++++------------ source/blender/python/gpu/gpu_py_offscreen.c | 87 +++++------ source/blender/python/gpu/gpu_py_select.c | 14 +- source/blender/python/gpu/gpu_py_shader.c | 171 ++++++++++----------- source/blender/python/gpu/gpu_py_vertex_buffer.c | 37 +++-- source/blender/python/gpu/gpu_py_vertex_format.c | 40 ++--- 8 files changed, 283 insertions(+), 311 deletions(-) (limited to 'source/blender') diff --git a/source/blender/python/gpu/gpu_py_batch.c b/source/blender/python/gpu/gpu_py_batch.c index 81d1cb7055d..9fb7aea162a 100644 --- a/source/blender/python/gpu/gpu_py_batch.c +++ b/source/blender/python/gpu/gpu_py_batch.c @@ -48,7 +48,7 @@ /** \name Utility Functions * \{ */ -static bool bpygpu_batch_is_program_or_error(BPyGPUBatch *self) +static bool py_batch_is_program_or_error(BPyGPUBatch *self) { if (!self->batch->shader) { PyErr_SetString(PyExc_RuntimeError, "batch does not have any program assigned to it"); @@ -63,7 +63,7 @@ static bool bpygpu_batch_is_program_or_error(BPyGPUBatch *self) /** \name GPUBatch Type * \{ */ -static PyObject *bpygpu_Batch_new(PyTypeObject *UNUSED(type), PyObject *args, PyObject *kwds) +static PyObject *py_Batch_new(PyTypeObject *UNUSED(type), PyObject *args, PyObject *kwds) { BPYGPU_IS_INIT_OR_ERROR_OBJ; @@ -121,7 +121,7 @@ static PyObject *bpygpu_Batch_new(PyTypeObject *UNUSED(type), PyObject *args, Py return (PyObject *)ret; } -PyDoc_STRVAR(bpygpu_Batch_vertbuf_add_doc, +PyDoc_STRVAR(py_Batch_vertbuf_add_doc, ".. method:: vertbuf_add(buf)\n" "\n" " Add another vertex buffer to the Batch.\n" @@ -134,7 +134,7 @@ PyDoc_STRVAR(bpygpu_Batch_vertbuf_add_doc, " :param buf: The vertex buffer that will be added to the batch.\n" " :type buf: :class:`gpu.types.GPUVertBuf`\n" ); -static PyObject *bpygpu_Batch_vertbuf_add(BPyGPUBatch *self, BPyGPUVertBuf *py_buf) +static PyObject *py_Batch_vertbuf_add(BPyGPUBatch *self, BPyGPUVertBuf *py_buf) { if (!BPyGPUVertBuf_Check(py_buf)) { PyErr_Format(PyExc_TypeError, "Expected a GPUVertBuf, got %s", Py_TYPE(py_buf)->tp_name); @@ -167,7 +167,7 @@ static PyObject *bpygpu_Batch_vertbuf_add(BPyGPUBatch *self, BPyGPUVertBuf *py_b } PyDoc_STRVAR( - bpygpu_Batch_program_set_doc, + py_Batch_program_set_doc, ".. method:: program_set(program)\n" "\n" " Assign a shader to this batch that will be used for drawing when not overwritten later.\n" @@ -177,7 +177,7 @@ PyDoc_STRVAR( "\n" " :param program: The program/shader the batch will use in future draw calls.\n" " :type program: :class:`gpu.types.GPUShader`\n"); -static PyObject *bpygpu_Batch_program_set(BPyGPUBatch *self, BPyGPUShader *py_shader) +static PyObject *py_Batch_program_set(BPyGPUBatch *self, BPyGPUShader *py_shader) { if (!BPyGPUShader_Check(py_shader)) { PyErr_Format(PyExc_TypeError, "Expected a GPUShader, got %s", Py_TYPE(py_shader)->tp_name); @@ -208,7 +208,7 @@ static PyObject *bpygpu_Batch_program_set(BPyGPUBatch *self, BPyGPUShader *py_sh Py_RETURN_NONE; } -PyDoc_STRVAR(bpygpu_Batch_draw_doc, +PyDoc_STRVAR(py_Batch_draw_doc, ".. method:: draw(program=None)\n" "\n" " Run the drawing program with the parameters assigned to the batch.\n" @@ -216,7 +216,7 @@ PyDoc_STRVAR(bpygpu_Batch_draw_doc, " :param program: Program that performs the drawing operations.\n" " If ``None`` is passed, the last program set to this batch will run.\n" " :type program: :class:`gpu.types.GPUShader`\n"); -static PyObject *bpygpu_Batch_draw(BPyGPUBatch *self, PyObject *args) +static PyObject *py_Batch_draw(BPyGPUBatch *self, PyObject *args) { BPyGPUShader *py_program = NULL; @@ -224,7 +224,7 @@ static PyObject *bpygpu_Batch_draw(BPyGPUBatch *self, PyObject *args) return NULL; } if (py_program == NULL) { - if (!bpygpu_batch_is_program_or_error(self)) { + if (!py_batch_is_program_or_error(self)) { return NULL; } } @@ -236,42 +236,42 @@ static PyObject *bpygpu_Batch_draw(BPyGPUBatch *self, PyObject *args) Py_RETURN_NONE; } -static PyObject *bpygpu_Batch_program_use_begin(BPyGPUBatch *self) +static PyObject *py_Batch_program_use_begin(BPyGPUBatch *self) { - if (!bpygpu_batch_is_program_or_error(self)) { + if (!py_batch_is_program_or_error(self)) { return NULL; } GPU_shader_bind(self->batch->shader); Py_RETURN_NONE; } -static PyObject *bpygpu_Batch_program_use_end(BPyGPUBatch *self) +static PyObject *py_Batch_program_use_end(BPyGPUBatch *self) { - if (!bpygpu_batch_is_program_or_error(self)) { + if (!py_batch_is_program_or_error(self)) { return NULL; } GPU_shader_unbind(); Py_RETURN_NONE; } -static struct PyMethodDef bpygpu_Batch_methods[] = { - {"vertbuf_add", (PyCFunction)bpygpu_Batch_vertbuf_add, METH_O, bpygpu_Batch_vertbuf_add_doc}, - {"program_set", (PyCFunction)bpygpu_Batch_program_set, METH_O, bpygpu_Batch_program_set_doc}, - {"draw", (PyCFunction)bpygpu_Batch_draw, METH_VARARGS, bpygpu_Batch_draw_doc}, - {"_program_use_begin", (PyCFunction)bpygpu_Batch_program_use_begin, METH_NOARGS, ""}, - {"_program_use_end", (PyCFunction)bpygpu_Batch_program_use_end, METH_NOARGS, ""}, +static struct PyMethodDef py_Batch_methods[] = { + {"vertbuf_add", (PyCFunction)py_Batch_vertbuf_add, METH_O, py_Batch_vertbuf_add_doc}, + {"program_set", (PyCFunction)py_Batch_program_set, METH_O, py_Batch_program_set_doc}, + {"draw", (PyCFunction)py_Batch_draw, METH_VARARGS, py_Batch_draw_doc}, + {"_program_use_begin", (PyCFunction)py_Batch_program_use_begin, METH_NOARGS, ""}, + {"_program_use_end", (PyCFunction)py_Batch_program_use_end, METH_NOARGS, ""}, {NULL, NULL, 0, NULL}, }; #ifdef USE_GPU_PY_REFERENCES -static int bpygpu_Batch_traverse(BPyGPUBatch *self, visitproc visit, void *arg) +static int py_Batch_traverse(BPyGPUBatch *self, visitproc visit, void *arg) { Py_VISIT(self->references); return 0; } -static int bpygpu_Batch_clear(BPyGPUBatch *self) +static int py_Batch_clear(BPyGPUBatch *self) { Py_CLEAR(self->references); return 0; @@ -279,14 +279,14 @@ static int bpygpu_Batch_clear(BPyGPUBatch *self) #endif -static void bpygpu_Batch_dealloc(BPyGPUBatch *self) +static void py_Batch_dealloc(BPyGPUBatch *self) { GPU_batch_discard(self->batch); #ifdef USE_GPU_PY_REFERENCES if (self->references) { PyObject_GC_UnTrack(self); - bpygpu_Batch_clear(self); + py_Batch_clear(self); Py_XDECREF(self->references); } #endif @@ -319,17 +319,17 @@ PyDoc_STRVAR( PyTypeObject BPyGPUBatch_Type = { PyVarObject_HEAD_INIT(NULL, 0).tp_name = "GPUBatch", .tp_basicsize = sizeof(BPyGPUBatch), - .tp_dealloc = (destructor)bpygpu_Batch_dealloc, + .tp_dealloc = (destructor)py_Batch_dealloc, #ifdef USE_GPU_PY_REFERENCES .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, .tp_doc = py_gpu_batch_doc, - .tp_traverse = (traverseproc)bpygpu_Batch_traverse, - .tp_clear = (inquiry)bpygpu_Batch_clear, + .tp_traverse = (traverseproc)py_Batch_traverse, + .tp_clear = (inquiry)py_Batch_clear, #else .tp_flags = Py_TPFLAGS_DEFAULT, #endif - .tp_methods = bpygpu_Batch_methods, - .tp_new = bpygpu_Batch_new, + .tp_methods = py_Batch_methods, + .tp_new = py_Batch_new, }; /** \} */ diff --git a/source/blender/python/gpu/gpu_py_element.c b/source/blender/python/gpu/gpu_py_element.c index c863c9a586f..0a1aecde986 100644 --- a/source/blender/python/gpu/gpu_py_element.c +++ b/source/blender/python/gpu/gpu_py_element.c @@ -39,7 +39,7 @@ /** \name IndexBuf Type * \{ */ -static PyObject *bpygpu_IndexBuf_new(PyTypeObject *UNUSED(type), PyObject *args, PyObject *kwds) +static PyObject *py_IndexBuf_new(PyTypeObject *UNUSED(type), PyObject *args, PyObject *kwds) { BPYGPU_IS_INIT_OR_ERROR_OBJ; @@ -175,7 +175,7 @@ static PyObject *bpygpu_IndexBuf_new(PyTypeObject *UNUSED(type), PyObject *args, return BPyGPUIndexBuf_CreatePyObject(GPU_indexbuf_build(&builder)); } -static void bpygpu_IndexBuf_dealloc(BPyGPUIndexBuf *self) +static void py_IndexBuf_dealloc(BPyGPUIndexBuf *self) { GPU_indexbuf_discard(self->elem); Py_TYPE(self)->tp_free(self); @@ -199,10 +199,10 @@ PyDoc_STRVAR(py_gpu_element_doc, PyTypeObject BPyGPUIndexBuf_Type = { PyVarObject_HEAD_INIT(NULL, 0).tp_name = "GPUIndexBuf", .tp_basicsize = sizeof(BPyGPUIndexBuf), - .tp_dealloc = (destructor)bpygpu_IndexBuf_dealloc, + .tp_dealloc = (destructor)py_IndexBuf_dealloc, .tp_flags = Py_TPFLAGS_DEFAULT, .tp_doc = py_gpu_element_doc, - .tp_new = bpygpu_IndexBuf_new, + .tp_new = py_IndexBuf_new, }; /** \} */ diff --git a/source/blender/python/gpu/gpu_py_matrix.c b/source/blender/python/gpu/gpu_py_matrix.c index 93cca78bad9..a479f270770 100644 --- a/source/blender/python/gpu/gpu_py_matrix.c +++ b/source/blender/python/gpu/gpu_py_matrix.c @@ -44,7 +44,7 @@ /** \name Helper Functions * \{ */ -static bool bpygpu_stack_is_push_model_view_ok_or_error(void) +static bool py_stack_is_push_model_view_ok_or_error(void) { if (GPU_matrix_stack_level_get_model_view() >= GPU_PY_MATRIX_STACK_LEN) { PyErr_SetString( @@ -55,7 +55,7 @@ static bool bpygpu_stack_is_push_model_view_ok_or_error(void) return true; } -static bool bpygpu_stack_is_push_projection_ok_or_error(void) +static bool py_stack_is_push_projection_ok_or_error(void) { if (GPU_matrix_stack_level_get_projection() >= GPU_PY_MATRIX_STACK_LEN) { PyErr_SetString( @@ -66,7 +66,7 @@ static bool bpygpu_stack_is_push_projection_ok_or_error(void) return true; } -static bool bpygpu_stack_is_pop_model_view_ok_or_error(void) +static bool py_stack_is_pop_model_view_ok_or_error(void) { if (GPU_matrix_stack_level_get_model_view() == 0) { PyErr_SetString(PyExc_RuntimeError, "Minimum model-view stack depth reached"); @@ -75,7 +75,7 @@ static bool bpygpu_stack_is_pop_model_view_ok_or_error(void) return true; } -static bool bpygpu_stack_is_pop_projection_ok_or_error(void) +static bool py_stack_is_pop_projection_ok_or_error(void) { if (GPU_matrix_stack_level_get_projection() == 0) { PyErr_SetString(PyExc_RuntimeError, "Minimum projection stack depth reached"); @@ -90,52 +90,52 @@ static bool bpygpu_stack_is_pop_projection_ok_or_error(void) /** \name Manage Stack * \{ */ -PyDoc_STRVAR(bpygpu_matrix_push_doc, +PyDoc_STRVAR(py_matrix_push_doc, ".. function:: push()\n" "\n" " Add to the model-view matrix stack.\n"); -static PyObject *bpygpu_matrix_push(PyObject *UNUSED(self)) +static PyObject *py_matrix_push(PyObject *UNUSED(self)) { - if (!bpygpu_stack_is_push_model_view_ok_or_error()) { + if (!py_stack_is_push_model_view_ok_or_error()) { return NULL; } GPU_matrix_push(); Py_RETURN_NONE; } -PyDoc_STRVAR(bpygpu_matrix_pop_doc, +PyDoc_STRVAR(py_matrix_pop_doc, ".. function:: pop()\n" "\n" " Remove the last model-view matrix from the stack.\n"); -static PyObject *bpygpu_matrix_pop(PyObject *UNUSED(self)) +static PyObject *py_matrix_pop(PyObject *UNUSED(self)) { - if (!bpygpu_stack_is_pop_model_view_ok_or_error()) { + if (!py_stack_is_pop_model_view_ok_or_error()) { return NULL; } GPU_matrix_pop(); Py_RETURN_NONE; } -PyDoc_STRVAR(bpygpu_matrix_push_projection_doc, +PyDoc_STRVAR(py_matrix_push_projection_doc, ".. function:: push_projection()\n" "\n" " Add to the projection matrix stack.\n"); -static PyObject *bpygpu_matrix_push_projection(PyObject *UNUSED(self)) +static PyObject *py_matrix_push_projection(PyObject *UNUSED(self)) { - if (!bpygpu_stack_is_push_projection_ok_or_error()) { + if (!py_stack_is_push_projection_ok_or_error()) { return NULL; } GPU_matrix_push_projection(); Py_RETURN_NONE; } -PyDoc_STRVAR(bpygpu_matrix_pop_projection_doc, +PyDoc_STRVAR(py_matrix_pop_projection_doc, ".. function:: pop_projection()\n" "\n" " Remove the last projection matrix from the stack.\n"); -static PyObject *bpygpu_matrix_pop_projection(PyObject *UNUSED(self)) +static PyObject *py_matrix_pop_projection(PyObject *UNUSED(self)) { - if (!bpygpu_stack_is_pop_projection_ok_or_error()) { + if (!py_stack_is_pop_projection_ok_or_error()) { return NULL; } GPU_matrix_pop_projection(); @@ -162,12 +162,12 @@ enum { PYGPU_MATRIX_TYPE_PROJECTION = 2, }; -static PyObject *bpygpu_matrix_stack_context_enter(BPyGPU_MatrixStackContext *self); -static PyObject *bpygpu_matrix_stack_context_exit(BPyGPU_MatrixStackContext *self, PyObject *args); +static PyObject *py_matrix_stack_context_enter(BPyGPU_MatrixStackContext *self); +static PyObject *py_matrix_stack_context_exit(BPyGPU_MatrixStackContext *self, PyObject *args); -static PyMethodDef bpygpu_matrix_stack_context_methods[] = { - {"__enter__", (PyCFunction)bpygpu_matrix_stack_context_enter, METH_NOARGS}, - {"__exit__", (PyCFunction)bpygpu_matrix_stack_context_exit, METH_VARARGS}, +static PyMethodDef py_matrix_stack_context_methods[] = { + {"__enter__", (PyCFunction)py_matrix_stack_context_enter, METH_NOARGS}, + {"__exit__", (PyCFunction)py_matrix_stack_context_exit, METH_VARARGS}, {NULL}, }; @@ -175,10 +175,10 @@ static PyTypeObject BPyGPU_matrix_stack_context_Type = { PyVarObject_HEAD_INIT(NULL, 0).tp_name = "GPUMatrixStackContext", .tp_basicsize = sizeof(BPyGPU_MatrixStackContext), .tp_flags = Py_TPFLAGS_DEFAULT, - .tp_methods = bpygpu_matrix_stack_context_methods, + .tp_methods = py_matrix_stack_context_methods, }; -static PyObject *bpygpu_matrix_stack_context_enter(BPyGPU_MatrixStackContext *self) +static PyObject *py_matrix_stack_context_enter(BPyGPU_MatrixStackContext *self) { /* sanity - should never happen */ if (self->level != -1) { @@ -187,14 +187,14 @@ static PyObject *bpygpu_matrix_stack_context_enter(BPyGPU_MatrixStackContext *se } if (self->type == PYGPU_MATRIX_TYPE_MODEL_VIEW) { - if (!bpygpu_stack_is_push_model_view_ok_or_error()) { + if (!py_stack_is_push_model_view_ok_or_error()) { return NULL; } GPU_matrix_push(); self->level = GPU_matrix_stack_level_get_model_view(); } else if (self->type == PYGPU_MATRIX_TYPE_PROJECTION) { - if (!bpygpu_stack_is_push_projection_ok_or_error()) { + if (!py_stack_is_push_projection_ok_or_error()) { return NULL; } GPU_matrix_push_projection(); @@ -206,8 +206,8 @@ static PyObject *bpygpu_matrix_stack_context_enter(BPyGPU_MatrixStackContext *se Py_RETURN_NONE; } -static PyObject *bpygpu_matrix_stack_context_exit(BPyGPU_MatrixStackContext *self, - PyObject *UNUSED(args)) +static PyObject *py_matrix_stack_context_exit(BPyGPU_MatrixStackContext *self, + PyObject *UNUSED(args)) { /* sanity - should never happen */ if (self->level == -1) { @@ -240,7 +240,7 @@ finally: Py_RETURN_NONE; } -static PyObject *bpygpu_matrix_push_pop_impl(int type) +static PyObject *py_matrix_push_pop_impl(int type) { BPyGPU_MatrixStackContext *ret = PyObject_New(BPyGPU_MatrixStackContext, &BPyGPU_matrix_stack_context_Type); @@ -250,23 +250,23 @@ static PyObject *bpygpu_matrix_push_pop_impl(int type) } PyDoc_STRVAR( - bpygpu_matrix_push_pop_doc, + py_matrix_push_pop_doc, ".. function:: push_pop()\n" "\n" " Context manager to ensure balanced push/pop calls, even in the case of an error.\n"); -static PyObject *bpygpu_matrix_push_pop(PyObject *UNUSED(self)) +static PyObject *py_matrix_push_pop(PyObject *UNUSED(self)) { - return bpygpu_matrix_push_pop_impl(PYGPU_MATRIX_TYPE_MODEL_VIEW); + return py_matrix_push_pop_impl(PYGPU_MATRIX_TYPE_MODEL_VIEW); } PyDoc_STRVAR( - bpygpu_matrix_push_pop_projection_doc, + py_matrix_push_pop_projection_doc, ".. function:: push_pop_projection()\n" "\n" " Context manager to ensure balanced push/pop calls, even in the case of an error.\n"); -static PyObject *bpygpu_matrix_push_pop_projection(PyObject *UNUSED(self)) +static PyObject *py_matrix_push_pop_projection(PyObject *UNUSED(self)) { - return bpygpu_matrix_push_pop_impl(PYGPU_MATRIX_TYPE_PROJECTION); + return py_matrix_push_pop_impl(PYGPU_MATRIX_TYPE_PROJECTION); } /** \} */ @@ -275,14 +275,14 @@ static PyObject *bpygpu_matrix_push_pop_projection(PyObject *UNUSED(self)) /** \name Manipulate State * \{ */ -PyDoc_STRVAR(bpygpu_matrix_multiply_matrix_doc, +PyDoc_STRVAR(py_matrix_multiply_matrix_doc, ".. function:: multiply_matrix(matrix)\n" "\n" " Multiply the current stack matrix.\n" "\n" " :param matrix: A 4x4 matrix.\n" " :type matrix: :class:`mathutils.Matrix`\n"); -static PyObject *bpygpu_matrix_multiply_matrix(PyObject *UNUSED(self), PyObject *value) +static PyObject *py_matrix_multiply_matrix(PyObject *UNUSED(self), PyObject *value) { MatrixObject *pymat; if (!Matrix_Parse4x4(value, &pymat)) { @@ -292,14 +292,14 @@ static PyObject *bpygpu_matrix_multiply_matrix(PyObject *UNUSED(self), PyObject Py_RETURN_NONE; } -PyDoc_STRVAR(bpygpu_matrix_scale_doc, +PyDoc_STRVAR(py_matrix_scale_doc, ".. function:: scale(scale)\n" "\n" " Scale the current stack matrix.\n" "\n" " :param scale: Scale the current stack matrix.\n" " :type scale: sequence of 2 or 3 floats\n"); -static PyObject *bpygpu_matrix_scale(PyObject *UNUSED(self), PyObject *value) +static PyObject *py_matrix_scale(PyObject *UNUSED(self), PyObject *value) { float scale[3]; int len; @@ -316,12 +316,12 @@ static PyObject *bpygpu_matrix_scale(PyObject *UNUSED(self), PyObject *value) Py_RETURN_NONE; } -PyDoc_STRVAR(bpygpu_matrix_scale_uniform_doc, +PyDoc_STRVAR(py_matrix_scale_uniform_doc, ".. function:: scale_uniform(scale)\n" "\n" " :param scale: Scale the current stack matrix.\n" " :type scale: float\n"); -static PyObject *bpygpu_matrix_scale_uniform(PyObject *UNUSED(self), PyObject *value) +static PyObject *py_matrix_scale_uniform(PyObject *UNUSED(self), PyObject *value) { float scalar; if ((scalar = PyFloat_AsDouble(value)) == -1.0f && PyErr_Occurred()) { @@ -332,14 +332,14 @@ static PyObject *bpygpu_matrix_scale_uniform(PyObject *UNUSED(self), PyObject *v Py_RETURN_NONE; } -PyDoc_STRVAR(bpygpu_matrix_translate_doc, +PyDoc_STRVAR(py_matrix_translate_doc, ".. function:: translate(offset)\n" "\n" " Scale the current stack matrix.\n" "\n" " :param offset: Translate the current stack matrix.\n" " :type offset: sequence of 2 or 3 floats\n"); -static PyObject *bpygpu_matrix_translate(PyObject *UNUSED(self), PyObject *value) +static PyObject *py_matrix_translate(PyObject *UNUSED(self), PyObject *value) { float offset[3]; int len; @@ -362,34 +362,34 @@ static PyObject *bpygpu_matrix_translate(PyObject *UNUSED(self), PyObject *value /** \name Write State * \{ */ -PyDoc_STRVAR(bpygpu_matrix_reset_doc, +PyDoc_STRVAR(py_matrix_reset_doc, ".. function:: reset()\n" "\n" " Empty stack and set to identity.\n"); -static PyObject *bpygpu_matrix_reset(PyObject *UNUSED(self)) +static PyObject *py_matrix_reset(PyObject *UNUSED(self)) { GPU_matrix_reset(); Py_RETURN_NONE; } -PyDoc_STRVAR(bpygpu_matrix_load_identity_doc, +PyDoc_STRVAR(py_matrix_load_identity_doc, ".. function:: load_identity()\n" "\n" " Empty stack and set to identity.\n"); -static PyObject *bpygpu_matrix_load_identity(PyObject *UNUSED(self)) +static PyObject *py_matrix_load_identity(PyObject *UNUSED(self)) { GPU_matrix_identity_set(); Py_RETURN_NONE; } -PyDoc_STRVAR(bpygpu_matrix_load_matrix_doc, +PyDoc_STRVAR(py_matrix_load_matrix_doc, ".. function:: load_matrix(matrix)\n" "\n" " Load a matrix into the stack.\n" "\n" " :param matrix: A 4x4 matrix.\n" " :type matrix: :class:`mathutils.Matrix`\n"); -static PyObject *bpygpu_matrix_load_matrix(PyObject *UNUSED(self), PyObject *value) +static PyObject *py_matrix_load_matrix(PyObject *UNUSED(self), PyObject *value) { MatrixObject *pymat; if (!Matrix_Parse4x4(value, &pymat)) { @@ -399,14 +399,14 @@ static PyObject *bpygpu_matrix_load_matrix(PyObject *UNUSED(self), PyObject *val Py_RETURN_NONE; } -PyDoc_STRVAR(bpygpu_matrix_load_projection_matrix_doc, +PyDoc_STRVAR(py_matrix_load_projection_matrix_doc, ".. function:: load_projection_matrix(matrix)\n" "\n" " Load a projection matrix into the stack.\n" "\n" " :param matrix: A 4x4 matrix.\n" " :type matrix: :class:`mathutils.Matrix`\n"); -static PyObject *bpygpu_matrix_load_projection_matrix(PyObject *UNUSED(self), PyObject *value) +static PyObject *py_matrix_load_projection_matrix(PyObject *UNUSED(self), PyObject *value) { MatrixObject *pymat; if (!Matrix_Parse4x4(value, &pymat)) { @@ -422,42 +422,42 @@ static PyObject *bpygpu_matrix_load_projection_matrix(PyObject *UNUSED(self), Py /** \name Read State * \{ */ -PyDoc_STRVAR(bpygpu_matrix_get_projection_matrix_doc, +PyDoc_STRVAR(py_matrix_get_projection_matrix_doc, ".. function:: get_projection_matrix()\n" "\n" " Return a copy of the projection matrix.\n" "\n" " :return: A 4x4 projection matrix.\n" " :rtype: :class:`mathutils.Matrix`\n"); -static PyObject *bpygpu_matrix_get_projection_matrix(PyObject *UNUSED(self)) +static PyObject *py_matrix_get_projection_matrix(PyObject *UNUSED(self)) { float matrix[4][4]; GPU_matrix_projection_get(matrix); return Matrix_CreatePyObject(&matrix[0][0], 4, 4, NULL); } -PyDoc_STRVAR(bpygpu_matrix_get_model_view_matrix_doc, +PyDoc_STRVAR(py_matrix_get_model_view_matrix_doc, ".. function:: get_model_view_matrix()\n" "\n" " Return a copy of the model-view matrix.\n" "\n" " :return: A 4x4 view matrix.\n" " :rtype: :class:`mathutils.Matrix`\n"); -static PyObject *bpygpu_matrix_get_model_view_matrix(PyObject *UNUSED(self)) +static PyObject *py_matrix_get_model_view_matrix(PyObject *UNUSED(self)) { float matrix[4][4]; GPU_matrix_model_view_get(matrix); return Matrix_CreatePyObject(&matrix[0][0], 4, 4, NULL); } -PyDoc_STRVAR(bpygpu_matrix_get_normal_matrix_doc, +PyDoc_STRVAR(py_matrix_get_normal_matrix_doc, ".. function:: get_normal_matrix()\n" "\n" " Return a copy of the normal matrix.\n" "\n" " :return: A 3x3 normal matrix.\n" " :rtype: :class:`mathutils.Matrix`\n"); -static PyObject *bpygpu_matrix_get_normal_matrix(PyObject *UNUSED(self)) +static PyObject *py_matrix_get_normal_matrix(PyObject *UNUSED(self)) { float matrix[3][3]; GPU_matrix_normal_get(matrix); @@ -470,81 +470,78 @@ static PyObject *bpygpu_matrix_get_normal_matrix(PyObject *UNUSED(self)) /** \name Module * \{ */ -static struct PyMethodDef bpygpu_matrix_methods[] = { +static struct PyMethodDef py_matrix_methods[] = { /* Manage Stack */ - {"push", (PyCFunction)bpygpu_matrix_push, METH_NOARGS, bpygpu_matrix_push_doc}, - {"pop", (PyCFunction)bpygpu_matrix_pop, METH_NOARGS, bpygpu_matrix_pop_doc}, + {"push", (PyCFunction)py_matrix_push, METH_NOARGS, py_matrix_push_doc}, + {"pop", (PyCFunction)py_matrix_pop, METH_NOARGS, py_matrix_pop_doc}, {"push_projection", - (PyCFunction)bpygpu_matrix_push_projection, + (PyCFunction)py_matrix_push_projection, METH_NOARGS, - bpygpu_matrix_push_projection_doc}, + py_matrix_push_projection_doc}, {"pop_projection", - (PyCFunction)bpygpu_matrix_pop_projection, + (PyCFunction)py_matrix_pop_projection, METH_NOARGS, - bpygpu_matrix_pop_projection_doc}, + py_matrix_pop_projection_doc}, /* Stack (Context Manager) */ - {"push_pop", (PyCFunction)bpygpu_matrix_push_pop, METH_NOARGS, bpygpu_matrix_push_pop_doc}, + {"push_pop", (PyCFunction)py_matrix_push_pop, METH_NOARGS, py_matrix_push_pop_doc}, {"push_pop_projection", - (PyCFunction)bpygpu_matrix_push_pop_projection, + (PyCFunction)py_matrix_push_pop_projection, METH_NOARGS, - bpygpu_matrix_push_pop_projection_doc}, + py_matrix_push_pop_projection_doc}, /* Manipulate State */ {"multiply_matrix", - (PyCFunction)bpygpu_matrix_multiply_matrix, + (PyCFunction)py_matrix_multiply_matrix, METH_O, - bpygpu_matrix_multiply_matrix_doc}, - {"scale", (PyCFunction)bpygpu_matrix_scale, METH_O, bpygpu_matrix_scale_doc}, - {"scale_uniform", - (PyCFunction)bpygpu_matrix_scale_uniform, - METH_O, - bpygpu_matrix_scale_uniform_doc}, - {"translate", (PyCFunction)bpygpu_matrix_translate, METH_O, bpygpu_matrix_translate_doc}, + py_matrix_multiply_matrix_doc}, + {"scale", (PyCFunction)py_matrix_scale, METH_O, py_matrix_scale_doc}, + {"scale_uniform", (PyCFunction)py_matrix_scale_uniform, METH_O, py_matrix_scale_uniform_doc}, + {"translate", (PyCFunction)py_matrix_translate, METH_O, py_matrix_translate_doc}, /* TODO */ #if 0 - {"rotate", (PyCFunction)bpygpu_matrix_rotate, METH_O, bpygpu_matrix_rotate_doc}, - {"rotate_axis", (PyCFunction)bpygpu_matrix_rotate_axis, METH_O, bpygpu_matrix_rotate_axis_doc}, - {"look_at", (PyCFunction)bpygpu_matrix_look_at, METH_O, bpygpu_matrix_look_at_doc}, + {"rotate", (PyCFunction)py_matrix_rotate, METH_O, py_matrix_rotate_doc}, + {"rotate_axis", (PyCFunction)py_matrix_rotate_axis, METH_O, py_matrix_rotate_axis_doc}, + {"look_at", (PyCFunction)py_matrix_look_at, METH_O, py_matrix_look_at_doc}, #endif /* Write State */ - {"reset", (PyCFunction)bpygpu_matrix_reset, METH_NOARGS, bpygpu_matrix_reset_doc}, + {"reset", (PyCFunction)py_matrix_reset, METH_NOARGS, py_matrix_reset_doc}, {"load_identity", - (PyCFunction)bpygpu_matrix_load_identity, + (PyCFunction)py_matrix_load_identity, METH_NOARGS, - bpygpu_matrix_load_identity_doc}, - {"load_matrix", (PyCFunction)bpygpu_matrix_load_matrix, METH_O, bpygpu_matrix_load_matrix_doc}, + py_matrix_load_identity_doc}, + {"load_matrix", (PyCFunction)py_matrix_load_matrix, METH_O, py_matrix_load_matrix_doc}, {"load_projection_matrix", - (PyCFunction)bpygpu_matrix_load_projection_matrix, + (PyCFunction)py_matrix_load_projection_matrix, METH_O, - bpygpu_matrix_load_projection_matrix_doc}, + py_matrix_load_projection_matrix_doc}, /* Read State */ {"get_projection_matrix", - (PyCFunction)bpygpu_matrix_get_projection_matrix, + (PyCFunction)py_matrix_get_projection_matrix, METH_NOARGS, - bpygpu_matrix_get_projection_matrix_doc}, + py_matrix_get_projection_matrix_doc}, {"get_model_view_matrix", - (PyCFunction)bpygpu_matrix_get_model_view_matrix, + (PyCFunction)py_matrix_get_model_view_matrix, METH_NOARGS, - bpygpu_matrix_get_model_view_matrix_doc}, + py_matrix_get_model_view_matrix_doc}, {"get_normal_matrix", - (PyCFunction)bpygpu_matrix_get_normal_matrix, + (PyCFunction)py_matrix_get_normal_matrix, METH_NOARGS, - bpygpu_matrix_get_normal_matrix_doc}, + py_matrix_get_normal_matrix_doc}, {NULL, NULL, 0, NULL}, }; -PyDoc_STRVAR(bpygpu_matrix_doc, "This module provides access to the matrix stack."); +PyDoc_STRVAR(py_matrix_doc, "This module provides access to the matrix stack."); static PyModuleDef BPyGPU_matrix_module_def = { PyModuleDef_HEAD_INIT, .m_name = "gpu.matrix", - .m_doc = bpygpu_matrix_doc, - .m_methods = bpygpu_matrix_methods, + .m_doc = py_matrix_doc, + .m_methods = py_matrix_methods, }; PyObject *BPyInit_gpu_matrix(void) diff --git a/source/blender/python/gpu/gpu_py_offscreen.c b/source/blender/python/gpu/gpu_py_offscreen.c index 6d14dd0de5f..00d367c603b 100644 --- a/source/blender/python/gpu/gpu_py_offscreen.c +++ b/source/blender/python/gpu/gpu_py_offscreen.c @@ -58,9 +58,9 @@ /** \name GPUOffScreen Common Utilities * \{ */ -static int bpygpu_offscreen_valid_check(BPyGPUOffScreen *bpygpu_ofs) +static int py_offscreen_valid_check(BPyGPUOffScreen *py_ofs) { - if (UNLIKELY(bpygpu_ofs->ofs == NULL)) { + if (UNLIKELY(py_ofs->ofs == NULL)) { PyErr_SetString(PyExc_ReferenceError, "GPU offscreen was freed, no further access is valid"); return -1; } @@ -69,7 +69,7 @@ static int bpygpu_offscreen_valid_check(BPyGPUOffScreen *bpygpu_ofs) #define BPY_GPU_OFFSCREEN_CHECK_OBJ(bpygpu) \ { \ - if (UNLIKELY(bpygpu_offscreen_valid_check(bpygpu) == -1)) { \ + if (UNLIKELY(py_offscreen_valid_check(bpygpu) == -1)) { \ return NULL; \ } \ } \ @@ -81,7 +81,7 @@ static int bpygpu_offscreen_valid_check(BPyGPUOffScreen *bpygpu_ofs) /** \name GPUOffscreen Type * \{ */ -static PyObject *bpygpu_offscreen_new(PyTypeObject *UNUSED(self), PyObject *args, PyObject *kwds) +static PyObject *py_offscreen_new(PyTypeObject *UNUSED(self), PyObject *args, PyObject *kwds) { BPYGPU_IS_INIT_OR_ERROR_OBJ; @@ -112,23 +112,23 @@ static PyObject *bpygpu_offscreen_new(PyTypeObject *UNUSED(self), PyObject *args return BPyGPUOffScreen_CreatePyObject(ofs); } -PyDoc_STRVAR(bpygpu_offscreen_width_doc, "Width of the texture.\n\n:type: `int`"); -static PyObject *bpygpu_offscreen_width_get(BPyGPUOffScreen *self, void *UNUSED(type)) +PyDoc_STRVAR(py_offscreen_width_doc, "Width of the texture.\n\n:type: `int`"); +static PyObject *py_offscreen_width_get(BPyGPUOffScreen *self, void *UNUSED(type)) { BPY_GPU_OFFSCREEN_CHECK_OBJ(self); return PyLong_FromLong(GPU_offscreen_width(self->ofs)); } -PyDoc_STRVAR(bpygpu_offscreen_height_doc, "Height of the texture.\n\n:type: `int`"); -static PyObject *bpygpu_offscreen_height_get(BPyGPUOffScreen *self, void *UNUSED(type)) +PyDoc_STRVAR(py_offscreen_height_doc, "Height of the texture.\n\n:type: `int`"); +static PyObject *py_offscreen_height_get(BPyGPUOffScreen *self, void *UNUSED(type)) { BPY_GPU_OFFSCREEN_CHECK_OBJ(self); return PyLong_FromLong(GPU_offscreen_height(self->ofs)); } -PyDoc_STRVAR(bpygpu_offscreen_color_texture_doc, +PyDoc_STRVAR(py_offscreen_color_texture_doc, "OpenGL bindcode for the color texture.\n\n:type: `int`"); -static PyObject *bpygpu_offscreen_color_texture_get(BPyGPUOffScreen *self, void *UNUSED(type)) +static PyObject *py_offscreen_color_texture_get(BPyGPUOffScreen *self, void *UNUSED(type)) { BPY_GPU_OFFSCREEN_CHECK_OBJ(self); GPUTexture *texture = GPU_offscreen_color_texture(self->ofs); @@ -136,7 +136,7 @@ static PyObject *bpygpu_offscreen_color_texture_get(BPyGPUOffScreen *self, void } PyDoc_STRVAR( - bpygpu_offscreen_bind_doc, + py_offscreen_bind_doc, ".. method:: bind(save=True)\n" "\n" " Bind the offscreen object.\n" @@ -145,7 +145,7 @@ PyDoc_STRVAR( "\n" " :arg save: Save the current OpenGL state, so that it can be restored when unbinding.\n" " :type save: `bool`\n"); -static PyObject *bpygpu_offscreen_bind(BPyGPUOffScreen *self, PyObject *args, PyObject *kwds) +static PyObject *py_offscreen_bind(BPyGPUOffScreen *self, PyObject *args, PyObject *kwds) { BPY_GPU_OFFSCREEN_CHECK_OBJ(self); bool save = true; @@ -165,7 +165,7 @@ static PyObject *bpygpu_offscreen_bind(BPyGPUOffScreen *self, PyObject *args, Py return (PyObject *)self; } -PyDoc_STRVAR(bpygpu_offscreen_unbind_doc, +PyDoc_STRVAR(py_offscreen_unbind_doc, ".. method:: unbind(restore=True)\n" "\n" " Unbind the offscreen object.\n" @@ -173,7 +173,7 @@ PyDoc_STRVAR(bpygpu_offscreen_unbind_doc, " :arg restore: Restore the OpenGL state, can only be used when the state has been " "saved before.\n" " :type restore: `bool`\n"); -static PyObject *bpygpu_offscreen_unbind(BPyGPUOffScreen *self, PyObject *args, PyObject *kwds) +static PyObject *py_offscreen_unbind(BPyGPUOffScreen *self, PyObject *args, PyObject *kwds) { bool restore = true; @@ -191,7 +191,7 @@ static PyObject *bpygpu_offscreen_unbind(BPyGPUOffScreen *self, PyObject *args, } PyDoc_STRVAR( - bpygpu_offscreen_draw_view3d_doc, + py_offscreen_draw_view3d_doc, ".. method:: draw_view3d(scene, view_layer, view3d, region, view_matrix, projection_matrix)\n" "\n" " Draw the 3d viewport in the offscreen object.\n" @@ -208,9 +208,7 @@ PyDoc_STRVAR( " :type view_matrix: :class:`mathutils.Matrix`\n" " :arg projection_matrix: Projection Matrix (e.g. ``camera.calc_matrix_camera(...)``).\n" " :type projection_matrix: :class:`mathutils.Matrix`\n"); -static PyObject *bpygpu_offscreen_draw_view3d(BPyGPUOffScreen *self, - PyObject *args, - PyObject *kwds) +static PyObject *py_offscreen_draw_view3d(BPyGPUOffScreen *self, PyObject *args, PyObject *kwds) { MatrixObject *py_mat_view, *py_mat_projection; PyObject *py_scene, *py_view_layer, *py_region, *py_view3d; @@ -272,12 +270,12 @@ static PyObject *bpygpu_offscreen_draw_view3d(BPyGPUOffScreen *self, Py_RETURN_NONE; } -PyDoc_STRVAR(bpygpu_offscreen_free_doc, +PyDoc_STRVAR(py_offscreen_free_doc, ".. method:: free()\n" "\n" " Free the offscreen object.\n" " The framebuffer, texture and render objects will no longer be accessible.\n"); -static PyObject *bpygpu_offscreen_free(BPyGPUOffScreen *self) +static PyObject *py_offscreen_free(BPyGPUOffScreen *self) { BPY_GPU_OFFSCREEN_CHECK_OBJ(self); @@ -286,12 +284,12 @@ static PyObject *bpygpu_offscreen_free(BPyGPUOffScreen *self) Py_RETURN_NONE; } -static PyObject *bpygpu_offscreen_bind_context_enter(BPyGPUOffScreen *UNUSED(self)) +static PyObject *py_offscreen_bind_context_enter(BPyGPUOffScreen *UNUSED(self)) { Py_RETURN_NONE; } -static PyObject *bpygpu_offscreen_bind_context_exit(BPyGPUOffScreen *self, PyObject *UNUSED(args)) +static PyObject *py_offscreen_bind_context_exit(BPyGPUOffScreen *self, PyObject *UNUSED(args)) { GPU_offscreen_unbind(self->ofs, self->is_saved); Py_RETURN_NONE; @@ -305,41 +303,34 @@ static void BPyGPUOffScreen__tp_dealloc(BPyGPUOffScreen *self) Py_TYPE(self)->tp_free((PyObject *)self); } -static PyGetSetDef bpygpu_offscreen_getseters[] = { +static PyGetSetDef py_offscreen_getseters[] = { {"color_texture", - (getter)bpygpu_offscreen_color_texture_get, + (getter)py_offscreen_color_texture_get, (setter)NULL, - bpygpu_offscreen_color_texture_doc, - NULL}, - {"width", (getter)bpygpu_offscreen_width_get, (setter)NULL, bpygpu_offscreen_width_doc, NULL}, - {"height", - (getter)bpygpu_offscreen_height_get, - (setter)NULL, - bpygpu_offscreen_height_doc, + py_offscreen_color_texture_doc, NULL}, + {"width", (getter)py_offscreen_width_get, (setter)NULL, py_offscreen_width_doc, NULL}, + {"height", (getter)py_offscreen_height_get, (setter)NULL, py_offscreen_height_doc, NULL}, {NULL, NULL, NULL, NULL, NULL} /* Sentinel */ }; -static struct PyMethodDef bpygpu_offscreen_methods[] = { - {"bind", - (PyCFunction)bpygpu_offscreen_bind, - METH_VARARGS | METH_KEYWORDS, - bpygpu_offscreen_bind_doc}, +static struct PyMethodDef py_offscreen_methods[] = { + {"bind", (PyCFunction)py_offscreen_bind, METH_VARARGS | METH_KEYWORDS, py_offscreen_bind_doc}, {"unbind", - (PyCFunction)bpygpu_offscreen_unbind, + (PyCFunction)py_offscreen_unbind, METH_VARARGS | METH_KEYWORDS, - bpygpu_offscreen_unbind_doc}, + py_offscreen_unbind_doc}, {"draw_view3d", - (PyCFunction)bpygpu_offscreen_draw_view3d, + (PyCFunction)py_offscreen_draw_view3d, METH_VARARGS | METH_KEYWORDS, - bpygpu_offscreen_draw_view3d_doc}, - {"free", (PyCFunction)bpygpu_offscreen_free, METH_NOARGS, bpygpu_offscreen_free_doc}, - {"__enter__", (PyCFunction)bpygpu_offscreen_bind_context_enter, METH_NOARGS}, - {"__exit__", (PyCFunction)bpygpu_offscreen_bind_context_exit, METH_VARARGS}, + py_offscreen_draw_view3d_doc}, + {"free", (PyCFunction)py_offscreen_free, METH_NOARGS, py_offscreen_free_doc}, + {"__enter__", (PyCFunction)py_offscreen_bind_context_enter, METH_NOARGS}, + {"__exit__", (PyCFunction)py_offscreen_bind_context_exit, METH_VARARGS}, {NULL, NULL, 0, NULL}, }; -PyDoc_STRVAR(bpygpu_offscreen_doc, +PyDoc_STRVAR(py_offscreen_doc, ".. class:: GPUOffScreen(width, height)\n" "\n" " This object gives access to off screen buffers.\n" @@ -353,10 +344,10 @@ PyTypeObject BPyGPUOffScreen_Type = { .tp_basicsize = sizeof(BPyGPUOffScreen), .tp_dealloc = (destructor)BPyGPUOffScreen__tp_dealloc, .tp_flags = Py_TPFLAGS_DEFAULT, - .tp_doc = bpygpu_offscreen_doc, - .tp_methods = bpygpu_offscreen_methods, - .tp_getset = bpygpu_offscreen_getseters, - .tp_new = bpygpu_offscreen_new, + .tp_doc = py_offscreen_doc, + .tp_methods = py_offscreen_methods, + .tp_getset = py_offscreen_getseters, + .tp_new = py_offscreen_new, }; /** \} */ diff --git a/source/blender/python/gpu/gpu_py_select.c b/source/blender/python/gpu/gpu_py_select.c index abe46301abb..4fa9d5ebc7a 100644 --- a/source/blender/python/gpu/gpu_py_select.c +++ b/source/blender/python/gpu/gpu_py_select.c @@ -40,14 +40,14 @@ /** \name Methods * \{ */ -PyDoc_STRVAR(bpygpu_select_load_id_doc, +PyDoc_STRVAR(py_select_load_id_doc, ".. function:: load_id(id)\n" "\n" " Set the selection ID.\n" "\n" " :param id: Number (32-bit uint).\n" " :type select: int\n"); -static PyObject *bpygpu_select_load_id(PyObject *UNUSED(self), PyObject *value) +static PyObject *py_select_load_id(PyObject *UNUSED(self), PyObject *value) { uint id; if ((id = PyC_Long_AsU32(value)) == (uint)-1) { @@ -62,18 +62,18 @@ static PyObject *bpygpu_select_load_id(PyObject *UNUSED(self), PyObject *value) /** \name Module * \{ */ -static struct PyMethodDef bpygpu_select_methods[] = { +static struct PyMethodDef py_select_methods[] = { /* Manage Stack */ - {"load_id", (PyCFunction)bpygpu_select_load_id, METH_O, bpygpu_select_load_id_doc}, + {"load_id", (PyCFunction)py_select_load_id, METH_O, py_select_load_id_doc}, {NULL, NULL, 0, NULL}, }; -PyDoc_STRVAR(bpygpu_select_doc, "This module provides access to selection."); +PyDoc_STRVAR(py_select_doc, "This module provides access to selection."); static PyModuleDef BPyGPU_select_module_def = { PyModuleDef_HEAD_INIT, .m_name = "gpu.select", - .m_doc = bpygpu_select_doc, - .m_methods = bpygpu_select_methods, + .m_doc = py_select_doc, + .m_methods = py_select_methods, }; PyObject *BPyInit_gpu_select(void) diff --git a/source/blender/python/gpu/gpu_py_shader.c b/source/blender/python/gpu/gpu_py_shader.c index 0e7252bc71a..df864eea99f 100644 --- a/source/blender/python/gpu/gpu_py_shader.c +++ b/source/blender/python/gpu/gpu_py_shader.c @@ -51,9 +51,7 @@ static const struct PyC_StringEnumItems pygpu_bultinshader_items[] = { {0, NULL}, }; -static int bpygpu_uniform_location_get(GPUShader *shader, - const char *name, - const char *error_prefix) +static int py_uniform_location_get(GPUShader *shader, const char *name, const char *error_prefix) { const int uniform = GPU_shader_get_uniform(shader, name); @@ -70,7 +68,7 @@ static int bpygpu_uniform_location_get(GPUShader *shader, /** \name Shader Type * \{ */ -static PyObject *bpygpu_shader_new(PyTypeObject *UNUSED(type), PyObject *args, PyObject *kwds) +static PyObject *py_shader_new(PyTypeObject *UNUSED(type), PyObject *args, PyObject *kwds) { BPYGPU_IS_INIT_OR_ERROR_OBJ; @@ -109,17 +107,17 @@ static PyObject *bpygpu_shader_new(PyTypeObject *UNUSED(type), PyObject *args, P } PyDoc_STRVAR( - bpygpu_shader_bind_doc, + py_shader_bind_doc, ".. method:: bind()\n" "\n" " Bind the shader object. Required to be able to change uniforms of this shader.\n"); -static PyObject *bpygpu_shader_bind(BPyGPUShader *self) +static PyObject *py_shader_bind(BPyGPUShader *self) { GPU_shader_bind(self->shader); Py_RETURN_NONE; } -PyDoc_STRVAR(bpygpu_shader_uniform_from_name_doc, +PyDoc_STRVAR(py_shader_uniform_from_name_doc, ".. method:: uniform_from_name(name)\n" "\n" " Get uniform location by name.\n" @@ -128,14 +126,14 @@ PyDoc_STRVAR(bpygpu_shader_uniform_from_name_doc, " :type name: `str`\n" " :return: Location of the uniform variable.\n" " :rtype: `int`\n"); -static PyObject *bpygpu_shader_uniform_from_name(BPyGPUShader *self, PyObject *arg) +static PyObject *py_shader_uniform_from_name(BPyGPUShader *self, PyObject *arg) { const char *name = PyUnicode_AsUTF8(arg); if (name == NULL) { return NULL; } - const int uniform = bpygpu_uniform_location_get(self->shader, name, "GPUShader.get_uniform"); + const int uniform = py_uniform_location_get(self->shader, name, "GPUShader.get_uniform"); if (uniform == -1) { return NULL; @@ -145,7 +143,7 @@ static PyObject *bpygpu_shader_uniform_from_name(BPyGPUShader *self, PyObject *a } PyDoc_STRVAR( - bpygpu_shader_uniform_block_from_name_doc, + py_shader_uniform_block_from_name_doc, ".. method:: uniform_block_from_name(name)\n" "\n" " Get uniform block location by name.\n" @@ -154,7 +152,7 @@ PyDoc_STRVAR( " :type name: `str`\n" " :return: The location of the uniform block variable.\n" " :rtype: `int`\n"); -static PyObject *bpygpu_shader_uniform_block_from_name(BPyGPUShader *self, PyObject *arg) +static PyObject *py_shader_uniform_block_from_name(BPyGPUShader *self, PyObject *arg) { const char *name = PyUnicode_AsUTF8(arg); if (name == NULL) { @@ -171,12 +169,12 @@ static PyObject *bpygpu_shader_uniform_block_from_name(BPyGPUShader *self, PyObj return PyLong_FromLong(uniform); } -static bool bpygpu_shader_uniform_vector_imp(PyObject *args, - int elem_size, - int *r_location, - int *r_length, - int *r_count, - Py_buffer *r_pybuffer) +static bool py_shader_uniform_vector_imp(PyObject *args, + int elem_size, + int *r_location, + int *r_length, + int *r_count, + Py_buffer *r_pybuffer) { PyObject *buffer; @@ -199,7 +197,7 @@ static bool bpygpu_shader_uniform_vector_imp(PyObject *args, return true; } -PyDoc_STRVAR(bpygpu_shader_uniform_vector_float_doc, +PyDoc_STRVAR(py_shader_uniform_vector_float_doc, ".. method:: uniform_vector_float(location, buffer, length, count)\n" "\n" " Set the buffer to fill the uniform.\n" @@ -219,14 +217,13 @@ PyDoc_STRVAR(bpygpu_shader_uniform_vector_float_doc, " :param count: Specifies the number of elements, vector or matrices that are to " "be modified.\n" " :type count: int\n"); -static PyObject *bpygpu_shader_uniform_vector_float(BPyGPUShader *self, PyObject *args) +static PyObject *py_shader_uniform_vector_float(BPyGPUShader *self, PyObject *args) { int location, length, count; Py_buffer pybuffer; - if (!bpygpu_shader_uniform_vector_imp( - args, sizeof(float), &location, &length, &count, &pybuffer)) { + if (!py_shader_uniform_vector_imp(args, sizeof(float), &location, &length, &count, &pybuffer)) { return NULL; } @@ -237,18 +234,17 @@ static PyObject *bpygpu_shader_uniform_vector_float(BPyGPUShader *self, PyObject Py_RETURN_NONE; } -PyDoc_STRVAR(bpygpu_shader_uniform_vector_int_doc, +PyDoc_STRVAR(py_shader_uniform_vector_int_doc, ".. method:: uniform_vector_int(location, buffer, length, count)\n" "\n" " See GPUShader.uniform_vector_float(...) description.\n"); -static PyObject *bpygpu_shader_uniform_vector_int(BPyGPUShader *self, PyObject *args) +static PyObject *py_shader_uniform_vector_int(BPyGPUShader *self, PyObject *args) { int location, length, count; Py_buffer pybuffer; - if (!bpygpu_shader_uniform_vector_imp( - args, sizeof(int), &location, &length, &count, &pybuffer)) { + if (!py_shader_uniform_vector_imp(args, sizeof(int), &location, &length, &count, &pybuffer)) { return NULL; } @@ -259,7 +255,7 @@ static PyObject *bpygpu_shader_uniform_vector_int(BPyGPUShader *self, PyObject * Py_RETURN_NONE; } -PyDoc_STRVAR(bpygpu_shader_uniform_bool_doc, +PyDoc_STRVAR(py_shader_uniform_bool_doc, ".. method:: uniform_bool(name, seq)\n" "\n" " Specify the value of a uniform variable for the current program object.\n" @@ -268,7 +264,7 @@ PyDoc_STRVAR(bpygpu_shader_uniform_bool_doc, " :type name: str\n" " :param seq: Value that will be used to update the specified uniform variable.\n" " :type seq: sequence of bools\n"); -static PyObject *bpygpu_shader_uniform_bool(BPyGPUShader *self, PyObject *args) +static PyObject *py_shader_uniform_bool(BPyGPUShader *self, PyObject *args) { const char *error_prefix = "GPUShader.uniform_bool"; @@ -312,7 +308,7 @@ static PyObject *bpygpu_shader_uniform_bool(BPyGPUShader *self, PyObject *args) return NULL; } - const int location = bpygpu_uniform_location_get(self->shader, params.id, error_prefix); + const int location = py_uniform_location_get(self->shader, params.id, error_prefix); if (location == -1) { return NULL; @@ -323,7 +319,7 @@ static PyObject *bpygpu_shader_uniform_bool(BPyGPUShader *self, PyObject *args) Py_RETURN_NONE; } -PyDoc_STRVAR(bpygpu_shader_uniform_float_doc, +PyDoc_STRVAR(py_shader_uniform_float_doc, ".. method:: uniform_float(name, value)\n" "\n" " Specify the value of a uniform variable for the current program object.\n" @@ -332,7 +328,7 @@ PyDoc_STRVAR(bpygpu_shader_uniform_float_doc, " :type name: str\n" " :param value: Value that will be used to update the specified uniform variable.\n" " :type value: single number or sequence of numbers\n"); -static PyObject *bpygpu_shader_uniform_float(BPyGPUShader *self, PyObject *args) +static PyObject *py_shader_uniform_float(BPyGPUShader *self, PyObject *args) { const char *error_prefix = "GPUShader.uniform_float"; @@ -381,7 +377,7 @@ static PyObject *bpygpu_shader_uniform_float(BPyGPUShader *self, PyObject *args) return NULL; } - const int location = bpygpu_uniform_location_get(self->shader, params.id, error_prefix); + const int location = py_uniform_location_get(self->shader, params.id, error_prefix); if (location == -1) { return NULL; @@ -392,7 +388,7 @@ static PyObject *bpygpu_shader_uniform_float(BPyGPUShader *self, PyObject *args) Py_RETURN_NONE; } -PyDoc_STRVAR(bpygpu_shader_uniform_int_doc, +PyDoc_STRVAR(py_shader_uniform_int_doc, ".. method:: uniform_int(name, seq)\n" "\n" " Specify the value of a uniform variable for the current program object.\n" @@ -401,7 +397,7 @@ PyDoc_STRVAR(bpygpu_shader_uniform_int_doc, " :type name: str\n" " :param seq: Value that will be used to update the specified uniform variable.\n" " :type seq: sequence of numbers\n"); -static PyObject *bpygpu_shader_uniform_int(BPyGPUShader *self, PyObject *args) +static PyObject *py_shader_uniform_int(BPyGPUShader *self, PyObject *args) { const char *error_prefix = "GPUShader.uniform_int"; @@ -451,7 +447,7 @@ static PyObject *bpygpu_shader_uniform_int(BPyGPUShader *self, PyObject *args) return NULL; } - const int location = bpygpu_uniform_location_get(self->shader, params.id, error_prefix); + const int location = py_uniform_location_get(self->shader, params.id, error_prefix); if (location == -1) { return NULL; @@ -463,7 +459,7 @@ static PyObject *bpygpu_shader_uniform_int(BPyGPUShader *self, PyObject *args) } PyDoc_STRVAR( - bpygpu_shader_attr_from_name_doc, + py_shader_attr_from_name_doc, ".. method:: attr_from_name(name)\n" "\n" " Get attribute location by name.\n" @@ -472,7 +468,7 @@ PyDoc_STRVAR( " :type name: str\n" " :return: The location of an attribute variable.\n" " :rtype: int\n"); -static PyObject *bpygpu_shader_attr_from_name(BPyGPUShader *self, PyObject *arg) +static PyObject *py_shader_attr_from_name(BPyGPUShader *self, PyObject *arg) { const char *name = PyUnicode_AsUTF8(arg); if (name == NULL) { @@ -489,75 +485,69 @@ static PyObject *bpygpu_shader_attr_from_name(BPyGPUShader *self, PyObject *arg) return PyLong_FromLong(attr); } -PyDoc_STRVAR(bpygpu_shader_calc_format_doc, +PyDoc_STRVAR(py_shader_calc_format_doc, ".. method:: calc_format()\n" "\n" " Build a new format based on the attributes of the shader.\n" "\n" " :return: vertex attribute format for the shader\n" " :rtype: GPUVertFormat\n"); -static PyObject *bpygpu_shader_calc_format(BPyGPUShader *self, PyObject *UNUSED(arg)) +static PyObject *py_shader_calc_format(BPyGPUShader *self, PyObject *UNUSED(arg)) { BPyGPUVertFormat *ret = (BPyGPUVertFormat *)BPyGPUVertFormat_CreatePyObject(NULL); GPU_vertformat_from_shader(&ret->fmt, self->shader); return (PyObject *)ret; } -static struct PyMethodDef bpygpu_shader_methods[] = { - {"bind", (PyCFunction)bpygpu_shader_bind, METH_NOARGS, bpygpu_shader_bind_doc}, +static struct PyMethodDef py_shader_methods[] = { + {"bind", (PyCFunction)py_shader_bind, METH_NOARGS, py_shader_bind_doc}, {"uniform_from_name", - (PyCFunction)bpygpu_shader_uniform_from_name, + (PyCFunction)py_shader_uniform_from_name, METH_O, - bpygpu_shader_uniform_from_name_doc}, + py_shader_uniform_from_name_doc}, {"uniform_block_from_name", - (PyCFunction)bpygpu_shader_uniform_block_from_name, + (PyCFunction)py_shader_uniform_block_from_name, METH_O, - bpygpu_shader_uniform_block_from_name_doc}, + py_shader_uniform_block_from_name_doc}, {"uniform_vector_float", - (PyCFunction)bpygpu_shader_uniform_vector_float, + (PyCFunction)py_shader_uniform_vector_float, METH_VARARGS, - bpygpu_shader_uniform_vector_float_doc}, + py_shader_uniform_vector_float_doc}, {"uniform_vector_int", - (PyCFunction)bpygpu_shader_uniform_vector_int, + (PyCFunction)py_shader_uniform_vector_int, METH_VARARGS, - bpygpu_shader_uniform_vector_int_doc}, + py_shader_uniform_vector_int_doc}, {"uniform_bool", - (PyCFunction)bpygpu_shader_uniform_bool, + (PyCFunction)py_shader_uniform_bool, METH_VARARGS, - bpygpu_shader_uniform_bool_doc}, + py_shader_uniform_bool_doc}, {"uniform_float", - (PyCFunction)bpygpu_shader_uniform_float, + (PyCFunction)py_shader_uniform_float, METH_VARARGS, - bpygpu_shader_uniform_float_doc}, - {"uniform_int", - (PyCFunction)bpygpu_shader_uniform_int, - METH_VARARGS, - bpygpu_shader_uniform_int_doc}, + py_shader_uniform_float_doc}, + {"uniform_int", (PyCFunction)py_shader_uniform_int, METH_VARARGS, py_shader_uniform_int_doc}, {"attr_from_name", - (PyCFunction)bpygpu_shader_attr_from_name, + (PyCFunction)py_shader_attr_from_name, METH_O, - bpygpu_shader_attr_from_name_doc}, - {"format_calc", - (PyCFunction)bpygpu_shader_calc_format, - METH_NOARGS, - bpygpu_shader_calc_format_doc}, + py_shader_attr_from_name_doc}, + {"format_calc", (PyCFunction)py_shader_calc_format, METH_NOARGS, py_shader_calc_format_doc}, {NULL, NULL, 0, NULL}, }; PyDoc_STRVAR( - bpygpu_shader_program_doc, + py_shader_program_doc, "The name of the program object for use by the OpenGL API (read-only).\n\n:type: int"); -static PyObject *bpygpu_shader_program_get(BPyGPUShader *self, void *UNUSED(closure)) +static PyObject *py_shader_program_get(BPyGPUShader *self, void *UNUSED(closure)) { return PyLong_FromLong(GPU_shader_get_program(self->shader)); } -static PyGetSetDef bpygpu_shader_getseters[] = { - {"program", (getter)bpygpu_shader_program_get, (setter)NULL, bpygpu_shader_program_doc, NULL}, +static PyGetSetDef py_shader_getseters[] = { + {"program", (getter)py_shader_program_get, (setter)NULL, py_shader_program_doc, NULL}, {NULL, NULL, NULL, NULL, NULL} /* Sentinel */ }; -static void bpygpu_shader_dealloc(BPyGPUShader *self) +static void py_shader_dealloc(BPyGPUShader *self) { if (self->is_builtin == false) { GPU_shader_free(self->shader); @@ -566,7 +556,7 @@ static void bpygpu_shader_dealloc(BPyGPUShader *self) } PyDoc_STRVAR( - bpygpu_shader_doc, + py_shader_doc, ".. class:: GPUShader(vertexcode, fragcode, geocode=None, libcode=None, defines=None)\n" "\n" " GPUShader combines multiple GLSL shaders into a program used for drawing.\n" @@ -600,12 +590,12 @@ PyDoc_STRVAR( PyTypeObject BPyGPUShader_Type = { PyVarObject_HEAD_INIT(NULL, 0).tp_name = "GPUShader", .tp_basicsize = sizeof(BPyGPUShader), - .tp_dealloc = (destructor)bpygpu_shader_dealloc, + .tp_dealloc = (destructor)py_shader_dealloc, .tp_flags = Py_TPFLAGS_DEFAULT, - .tp_doc = bpygpu_shader_doc, - .tp_methods = bpygpu_shader_methods, - .tp_getset = bpygpu_shader_getseters, - .tp_new = bpygpu_shader_new, + .tp_doc = py_shader_doc, + .tp_methods = py_shader_methods, + .tp_getset = py_shader_getseters, + .tp_new = py_shader_new, }; /** \} */ @@ -614,17 +604,17 @@ PyTypeObject BPyGPUShader_Type = { /** \name gpu.shader Module API * \{ */ -PyDoc_STRVAR(bpygpu_shader_unbind_doc, +PyDoc_STRVAR(py_shader_unbind_doc, ".. function:: unbind()\n" "\n" " Unbind the bound shader object.\n"); -static PyObject *bpygpu_shader_unbind(BPyGPUShader *UNUSED(self)) +static PyObject *py_shader_unbind(BPyGPUShader *UNUSED(self)) { GPU_shader_unbind(); Py_RETURN_NONE; } -PyDoc_STRVAR(bpygpu_shader_from_builtin_doc, +PyDoc_STRVAR(py_shader_from_builtin_doc, ".. function:: from_builtin(shader_name)\n" "\n" " Shaders that are embedded in the blender internal code.\n" @@ -644,11 +634,11 @@ PyDoc_STRVAR(bpygpu_shader_from_builtin_doc, " :type shader_name: str\n" " :return: Shader object corresponding to the given name.\n" " :rtype: :class:`bpy.types.GPUShader`\n"); -static PyObject *bpygpu_shader_from_builtin(PyObject *UNUSED(self), PyObject *arg) +static PyObject *py_shader_from_builtin(PyObject *UNUSED(self), PyObject *arg) { BPYGPU_IS_INIT_OR_ERROR_OBJ; - const struct PyC_StringEnum pygpu_bultinshader = {&pygpu_bultinshader_items, -1}; + struct PyC_StringEnum pygpu_bultinshader = {&pygpu_bultinshader_items}; if (!PyC_ParseStringEnum(arg, &pygpu_bultinshader)) { return NULL; } @@ -658,7 +648,7 @@ static PyObject *bpygpu_shader_from_builtin(PyObject *UNUSED(self), PyObject *ar return BPyGPUShader_CreatePyObject(shader, true); } -PyDoc_STRVAR(bpygpu_shader_code_from_builtin_doc, +PyDoc_STRVAR(py_shader_code_from_builtin_doc, ".. function:: code_from_builtin(shader_name)\n" "\n" " Exposes the internal shader code for query.\n" @@ -674,7 +664,7 @@ PyDoc_STRVAR(bpygpu_shader_code_from_builtin_doc, " :type shader_name: str\n" " :return: Vertex, fragment and geometry shader codes.\n" " :rtype: dict\n"); -static PyObject *bpygpu_shader_code_from_builtin(BPyGPUShader *UNUSED(self), PyObject *arg) +static PyObject *py_shader_code_from_builtin(BPyGPUShader *UNUSED(self), PyObject *arg) { const char *vert; const char *frag; @@ -683,7 +673,7 @@ static PyObject *bpygpu_shader_code_from_builtin(BPyGPUShader *UNUSED(self), PyO PyObject *item, *r_dict; - const struct PyC_StringEnum pygpu_bultinshader = {&pygpu_bultinshader_items, -1}; + struct PyC_StringEnum pygpu_bultinshader = {&pygpu_bultinshader_items}; if (!PyC_ParseStringEnum(arg, &pygpu_bultinshader)) { return NULL; } @@ -710,20 +700,17 @@ static PyObject *bpygpu_shader_code_from_builtin(BPyGPUShader *UNUSED(self), PyO return r_dict; } -static struct PyMethodDef bpygpu_shader_module_methods[] = { - {"unbind", (PyCFunction)bpygpu_shader_unbind, METH_NOARGS, bpygpu_shader_unbind_doc}, - {"from_builtin", - (PyCFunction)bpygpu_shader_from_builtin, - METH_O, - bpygpu_shader_from_builtin_doc}, +static struct PyMethodDef py_shader_module_methods[] = { + {"unbind", (PyCFunction)py_shader_unbind, METH_NOARGS, py_shader_unbind_doc}, + {"from_builtin", (PyCFunction)py_shader_from_builtin, METH_O, py_shader_from_builtin_doc}, {"code_from_builtin", - (PyCFunction)bpygpu_shader_code_from_builtin, + (PyCFunction)py_shader_code_from_builtin, METH_O, - bpygpu_shader_code_from_builtin_doc}, + py_shader_code_from_builtin_doc}, {NULL, NULL, 0, NULL}, }; -PyDoc_STRVAR(bpygpu_shader_module_doc, +PyDoc_STRVAR(py_shader_module_doc, "This module provides access to GPUShader internal functions.\n" "\n" ".. rubric:: Built-in shaders\n" @@ -755,8 +742,8 @@ PyDoc_STRVAR(bpygpu_shader_module_doc, static PyModuleDef BPyGPU_shader_module_def = { PyModuleDef_HEAD_INIT, .m_name = "gpu.shader", - .m_doc = bpygpu_shader_module_doc, - .m_methods = bpygpu_shader_module_methods, + .m_doc = py_shader_module_doc, + .m_methods = py_shader_module_methods, }; /** \} */ diff --git a/source/blender/python/gpu/gpu_py_vertex_buffer.c b/source/blender/python/gpu/gpu_py_vertex_buffer.c index d8c6e67816a..8e19eac76d0 100644 --- a/source/blender/python/gpu/gpu_py_vertex_buffer.c +++ b/source/blender/python/gpu/gpu_py_vertex_buffer.c @@ -116,10 +116,10 @@ static void fill_format_sequence(void *data_dst_void, #undef WARN_TYPE_LIMIT_PUSH #undef WARN_TYPE_LIMIT_POP -static bool bpygpu_vertbuf_fill_impl(GPUVertBuf *vbo, - uint data_id, - PyObject *seq, - const char *error_prefix) +static bool py_vertbuf_fill_impl(GPUVertBuf *vbo, + uint data_id, + PyObject *seq, + const char *error_prefix) { const char *exc_str_size_mismatch = "Expected a %s of size %d, got %u"; @@ -213,10 +213,7 @@ static bool bpygpu_vertbuf_fill_impl(GPUVertBuf *vbo, return ok; } -static int bpygpu_attr_fill(GPUVertBuf *buf, - int id, - PyObject *py_seq_data, - const char *error_prefix) +static int py_attr_fill(GPUVertBuf *buf, int id, PyObject *py_seq_data, const char *error_prefix) { if (id < 0 || id >= GPU_vertbuf_get_format(buf)->attr_len) { PyErr_Format(PyExc_ValueError, "Format id %d out of range", id); @@ -228,7 +225,7 @@ static int bpygpu_attr_fill(GPUVertBuf *buf, return 0; } - if (!bpygpu_vertbuf_fill_impl(buf, (uint)id, py_seq_data, error_prefix)) { + if (!py_vertbuf_fill_impl(buf, (uint)id, py_seq_data, error_prefix)) { return 0; } @@ -241,7 +238,7 @@ static int bpygpu_attr_fill(GPUVertBuf *buf, /** \name VertBuf Type * \{ */ -static PyObject *bpygpu_VertBuf_new(PyTypeObject *UNUSED(type), PyObject *args, PyObject *kwds) +static PyObject *py_VertBuf_new(PyTypeObject *UNUSED(type), PyObject *args, PyObject *kwds) { struct { PyObject *py_fmt; @@ -263,7 +260,7 @@ static PyObject *bpygpu_VertBuf_new(PyTypeObject *UNUSED(type), PyObject *args, return BPyGPUVertBuf_CreatePyObject(vbo); } -PyDoc_STRVAR(bpygpu_VertBuf_attr_fill_doc, +PyDoc_STRVAR(py_VertBuf_attr_fill_doc, ".. method:: attr_fill(id, data)\n" "\n" " Insert data into the buffer for a single attribute.\n" @@ -272,7 +269,7 @@ PyDoc_STRVAR(bpygpu_VertBuf_attr_fill_doc, " :type id: int or str\n" " :param data: Sequence of data that should be stored in the buffer\n" " :type data: sequence of values or tuples\n"); -static PyObject *bpygpu_VertBuf_attr_fill(BPyGPUVertBuf *self, PyObject *args, PyObject *kwds) +static PyObject *py_VertBuf_attr_fill(BPyGPUVertBuf *self, PyObject *args, PyObject *kwds) { PyObject *data; PyObject *identifier; @@ -302,22 +299,22 @@ static PyObject *bpygpu_VertBuf_attr_fill(BPyGPUVertBuf *self, PyObject *args, P return NULL; } - if (!bpygpu_attr_fill(self->buf, id, data, "GPUVertBuf.attr_fill")) { + if (!py_attr_fill(self->buf, id, data, "GPUVertBuf.attr_fill")) { return NULL; } Py_RETURN_NONE; } -static struct PyMethodDef bpygpu_VertBuf_methods[] = { +static struct PyMethodDef py_VertBuf_methods[] = { {"attr_fill", - (PyCFunction)bpygpu_VertBuf_attr_fill, + (PyCFunction)py_VertBuf_attr_fill, METH_VARARGS | METH_KEYWORDS, - bpygpu_VertBuf_attr_fill_doc}, + py_VertBuf_attr_fill_doc}, {NULL, NULL, 0, NULL}, }; -static void bpygpu_VertBuf_dealloc(BPyGPUVertBuf *self) +static void py_VertBuf_dealloc(BPyGPUVertBuf *self) { GPU_vertbuf_discard(self->buf); Py_TYPE(self)->tp_free(self); @@ -335,11 +332,11 @@ PyDoc_STRVAR(py_gpu_vertex_buffer_doc, PyTypeObject BPyGPUVertBuf_Type = { PyVarObject_HEAD_INIT(NULL, 0).tp_name = "GPUVertBuf", .tp_basicsize = sizeof(BPyGPUVertBuf), - .tp_dealloc = (destructor)bpygpu_VertBuf_dealloc, + .tp_dealloc = (destructor)py_VertBuf_dealloc, .tp_flags = Py_TPFLAGS_DEFAULT, .tp_doc = py_gpu_vertex_buffer_doc, - .tp_methods = bpygpu_VertBuf_methods, - .tp_new = bpygpu_VertBuf_new, + .tp_methods = py_VertBuf_methods, + .tp_new = py_VertBuf_new, }; /** \} */ diff --git a/source/blender/python/gpu/gpu_py_vertex_format.c b/source/blender/python/gpu/gpu_py_vertex_format.c index 2d45eadcfe3..7d1e4ee4868 100644 --- a/source/blender/python/gpu/gpu_py_vertex_format.c +++ b/source/blender/python/gpu/gpu_py_vertex_format.c @@ -50,7 +50,7 @@ * Use with PyArg_ParseTuple's "O&" formatting. * \{ */ -static int bpygpu_parse_component_type(const char *str, int length) +static int py_parse_component_type(const char *str, int length) { if (length == 2) { switch (*((ushort *)str)) { @@ -83,7 +83,7 @@ static int bpygpu_parse_component_type(const char *str, int length) return -1; } -static int bpygpu_parse_fetch_mode(const char *str, int length) +static int py_parse_fetch_mode(const char *str, int length) { #define MATCH_ID(id) \ if (length == strlen(STRINGIFY(id))) { \ @@ -102,7 +102,7 @@ static int bpygpu_parse_fetch_mode(const char *str, int length) return -1; } -static int bpygpu_ParseVertCompType(PyObject *o, void *p) +static int py_ParseVertCompType(PyObject *o, void *p) { Py_ssize_t length; const char *str = _PyUnicode_AsStringAndSize(o, &length); @@ -112,7 +112,7 @@ static int bpygpu_ParseVertCompType(PyObject *o, void *p) return 0; } - const int comp_type = bpygpu_parse_component_type(str, length); + const int comp_type = py_parse_component_type(str, length); if (comp_type == -1) { PyErr_Format(PyExc_ValueError, "unknown component type: '%s", str); return 0; @@ -122,7 +122,7 @@ static int bpygpu_ParseVertCompType(PyObject *o, void *p) return 1; } -static int bpygpu_ParseVertFetchMode(PyObject *o, void *p) +static int py_ParseVertFetchMode(PyObject *o, void *p) { Py_ssize_t length; const char *str = _PyUnicode_AsStringAndSize(o, &length); @@ -132,7 +132,7 @@ static int bpygpu_ParseVertFetchMode(PyObject *o, void *p) return 0; } - const int fetch_mode = bpygpu_parse_fetch_mode(str, length); + const int fetch_mode = py_parse_fetch_mode(str, length); if (fetch_mode == -1) { PyErr_Format(PyExc_ValueError, "unknown type literal: '%s'", str); return 0; @@ -148,7 +148,7 @@ static int bpygpu_ParseVertFetchMode(PyObject *o, void *p) /** \name VertFormat Type * \{ */ -static PyObject *bpygpu_VertFormat_new(PyTypeObject *UNUSED(type), PyObject *args, PyObject *kwds) +static PyObject *py_VertFormat_new(PyTypeObject *UNUSED(type), PyObject *args, PyObject *kwds) { if (PyTuple_GET_SIZE(args) || (kwds && PyDict_Size(kwds))) { PyErr_SetString(PyExc_ValueError, "This function takes no arguments"); @@ -158,7 +158,7 @@ static PyObject *bpygpu_VertFormat_new(PyTypeObject *UNUSED(type), PyObject *arg } PyDoc_STRVAR( - bpygpu_VertFormat_attr_add_doc, + py_VertFormat_attr_add_doc, ".. method:: attr_add(id, comp_type, len, fetch_mode)\n" "\n" " Add a new attribute to the format.\n" @@ -177,7 +177,7 @@ PyDoc_STRVAR( " converted to a normal 4 byte float when used.\n" " Possible values are `FLOAT`, `INT`, `INT_TO_FLOAT_UNIT` and `INT_TO_FLOAT`.\n" " :type fetch_mode: `str`\n"); -static PyObject *bpygpu_VertFormat_attr_add(BPyGPUVertFormat *self, PyObject *args, PyObject *kwds) +static PyObject *py_VertFormat_attr_add(BPyGPUVertFormat *self, PyObject *args, PyObject *kwds) { struct { const char *id; @@ -197,10 +197,10 @@ static PyObject *bpygpu_VertFormat_attr_add(BPyGPUVertFormat *self, PyObject *ar kwds, &_parser, ¶ms.id, - bpygpu_ParseVertCompType, + py_ParseVertCompType, ¶ms.comp_type, ¶ms.len, - bpygpu_ParseVertFetchMode, + py_ParseVertFetchMode, ¶ms.fetch_mode)) { return NULL; } @@ -210,31 +210,31 @@ static PyObject *bpygpu_VertFormat_attr_add(BPyGPUVertFormat *self, PyObject *ar return PyLong_FromLong(attr_id); } -static struct PyMethodDef bpygpu_VertFormat_methods[] = { +static struct PyMethodDef py_VertFormat_methods[] = { {"attr_add", - (PyCFunction)bpygpu_VertFormat_attr_add, + (PyCFunction)py_VertFormat_attr_add, METH_VARARGS | METH_KEYWORDS, - bpygpu_VertFormat_attr_add_doc}, + py_VertFormat_attr_add_doc}, {NULL, NULL, 0, NULL}, }; -static void bpygpu_VertFormat_dealloc(BPyGPUVertFormat *self) +static void py_VertFormat_dealloc(BPyGPUVertFormat *self) { Py_TYPE(self)->tp_free(self); } -PyDoc_STRVAR(bpygpu_VertFormat_doc, +PyDoc_STRVAR(py_VertFormat_doc, ".. class:: GPUVertFormat()\n" "\n" " This object contains information about the structure of a vertex buffer.\n"); PyTypeObject BPyGPUVertFormat_Type = { PyVarObject_HEAD_INIT(NULL, 0).tp_name = "GPUVertFormat", .tp_basicsize = sizeof(BPyGPUVertFormat), - .tp_dealloc = (destructor)bpygpu_VertFormat_dealloc, + .tp_dealloc = (destructor)py_VertFormat_dealloc, .tp_flags = Py_TPFLAGS_DEFAULT, - .tp_doc = bpygpu_VertFormat_doc, - .tp_methods = bpygpu_VertFormat_methods, - .tp_new = bpygpu_VertFormat_new, + .tp_doc = py_VertFormat_doc, + .tp_methods = py_VertFormat_methods, + .tp_new = py_VertFormat_new, }; /** \} */ -- cgit v1.2.3 From 0dbbcaf1e6bb8e0296a3754df380badfd372908c Mon Sep 17 00:00:00 2001 From: Ray Molenkamp Date: Fri, 11 Dec 2020 12:09:18 -0700 Subject: Fix: Fix potential memory leak in BLI_getenv Issue introduced in rB87b19b3aba0c and unlikely to occur but no reason not to have correct code. --- source/blender/blenlib/intern/path_util.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c index 461f8a53beb..927318a923e 100644 --- a/source/blender/blenlib/intern/path_util.c +++ b/source/blender/blenlib/intern/path_util.c @@ -1322,12 +1322,14 @@ const char *BLI_getenv(const char *env) if (GetEnvironmentVariableW(env_16, buffer, ARRAY_SIZE(buffer))) { char *res_utf8 = alloc_utf_8_from_16(buffer, 0); // make sure the result is valid, and will fit into our temporary storage buffer - if (res_utf8 && (strlen(res_utf8) + 1) < sizeof(buffer)) { - // We are re-using the utf16 buffer here, since allocating a second static buffer to - // contain the UTF-8 version to return would be wasteful. - memcpy(buffer, res_utf8, strlen(res_utf8) + 1); + if (res_utf8) { + if (strlen(res_utf8) + 1 < sizeof(buffer)) { + // We are re-using the utf16 buffer here, since allocating a second static buffer to + // contain the UTF-8 version to return would be wasteful. + memcpy(buffer, res_utf8, strlen(res_utf8) + 1); + result = (const char *)buffer; + } free(res_utf8); - result = (const char *)buffer; } } } @@ -1529,7 +1531,8 @@ bool BLI_path_extension_check_glob(const char *str, const char *ext_fnmatch) } /** - * Does basic validation of the given glob string, to prevent common issues from string truncation. + * Does basic validation of the given glob string, to prevent common issues from string + * truncation. * * For now, only forbids last group to be a wildcard-only one, if there are more than one group * (i.e. things like "*.txt;*.cpp;*" are changed to "*.txt;*.cpp;") -- cgit v1.2.3 From ba83ad226d8c3b3d1a87ebbb13aacf5cfc27edfc Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Fri, 11 Dec 2020 17:54:12 -0300 Subject: Fix error in recent commit Introduced in rBcada56b1f72f537f9ab007cfafd430ac10c292fb --- source/blender/python/gpu/gpu_py_shader.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source/blender') diff --git a/source/blender/python/gpu/gpu_py_shader.c b/source/blender/python/gpu/gpu_py_shader.c index df864eea99f..526b96f8584 100644 --- a/source/blender/python/gpu/gpu_py_shader.c +++ b/source/blender/python/gpu/gpu_py_shader.c @@ -638,7 +638,7 @@ static PyObject *py_shader_from_builtin(PyObject *UNUSED(self), PyObject *arg) { BPYGPU_IS_INIT_OR_ERROR_OBJ; - struct PyC_StringEnum pygpu_bultinshader = {&pygpu_bultinshader_items}; + struct PyC_StringEnum pygpu_bultinshader = {pygpu_bultinshader_items}; if (!PyC_ParseStringEnum(arg, &pygpu_bultinshader)) { return NULL; } @@ -673,7 +673,7 @@ static PyObject *py_shader_code_from_builtin(BPyGPUShader *UNUSED(self), PyObjec PyObject *item, *r_dict; - struct PyC_StringEnum pygpu_bultinshader = {&pygpu_bultinshader_items}; + struct PyC_StringEnum pygpu_bultinshader = {pygpu_bultinshader_items}; if (!PyC_ParseStringEnum(arg, &pygpu_bultinshader)) { return NULL; } -- cgit v1.2.3 From af008f553293d91ef624ab4950e6d5dcc91650fe Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Fri, 11 Dec 2020 21:54:10 +0100 Subject: UI: Allow Outliners to pass selected data-blocks to operators via context The way the Outliner integrates operations on selected tree elements is known to be quite problematic amongst developers. The context menu is generated in an unusual way and doesn't use the normal operator system. Instead, changes are applied via a recursive callback system. Things are quite ad-hoc, and the callbacks often implement logic that should not be in the Outliner, but in entirely different modules. Often these modules already contain the logic, but as proper operators. This commit is a step into a hopefully better direction that should allow us to put actual operators into Outliner context menus. It starts solving the problem of: How can the Outliner pass selected data to operators. It implements it for data-blocks only, but other data could do it in the same way. Idea is to keep doing what operators were initially designed to do: Operate on context. Operators can now query a "selected_ids" context member (`CTX_data_selected_ids()` in C, `bpy.context.selected_ids` in .py). If an Outliner is active, it will generate a list of selected data-blocks as a response, via its `SpaceType.context` callback. Any other editor could do the same. No user visible changes. This new design isn't actually used yet. It will be soon for asset operators. Reviewed as part of https://developer.blender.org/D9717. Reviewed by: Brecht Van Lommel --- source/blender/blenkernel/BKE_context.h | 3 + source/blender/blenkernel/intern/context.c | 5 ++ .../blender/editors/space_outliner/CMakeLists.txt | 1 + .../editors/space_outliner/outliner_context.c | 73 ++++++++++++++++++++++ .../editors/space_outliner/outliner_intern.h | 7 +++ .../editors/space_outliner/space_outliner.c | 1 + 6 files changed, 90 insertions(+) create mode 100644 source/blender/editors/space_outliner/outliner_context.c (limited to 'source/blender') diff --git a/source/blender/blenkernel/BKE_context.h b/source/blender/blenkernel/BKE_context.h index 5c534803781..af9a95e1753 100644 --- a/source/blender/blenkernel/BKE_context.h +++ b/source/blender/blenkernel/BKE_context.h @@ -288,6 +288,9 @@ enum eContextObjectMode CTX_data_mode_enum(const bContext *C); void CTX_data_main_set(bContext *C, struct Main *bmain); void CTX_data_scene_set(bContext *C, struct Scene *scene); +/* Only Outliner currently! */ +int CTX_data_selected_ids(const bContext *C, ListBase *list); + int CTX_data_selected_editable_objects(const bContext *C, ListBase *list); int CTX_data_selected_editable_bases(const bContext *C, ListBase *list); diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c index a1edfd1c56d..2e4d3d62925 100644 --- a/source/blender/blenkernel/intern/context.c +++ b/source/blender/blenkernel/intern/context.c @@ -1202,6 +1202,11 @@ ToolSettings *CTX_data_tool_settings(const bContext *C) return NULL; } +int CTX_data_selected_ids(const bContext *C, ListBase *list) +{ + return ctx_data_collection_get(C, "selected_ids", list); +} + int CTX_data_selected_nodes(const bContext *C, ListBase *list) { return ctx_data_collection_get(C, "selected_nodes", list); diff --git a/source/blender/editors/space_outliner/CMakeLists.txt b/source/blender/editors/space_outliner/CMakeLists.txt index 8e989f5568e..e0262371559 100644 --- a/source/blender/editors/space_outliner/CMakeLists.txt +++ b/source/blender/editors/space_outliner/CMakeLists.txt @@ -34,6 +34,7 @@ set(INC set(SRC outliner_collections.c + outliner_context.c outliner_dragdrop.c outliner_draw.c outliner_edit.c diff --git a/source/blender/editors/space_outliner/outliner_context.c b/source/blender/editors/space_outliner/outliner_context.c new file mode 100644 index 00000000000..760fa8e4604 --- /dev/null +++ b/source/blender/editors/space_outliner/outliner_context.c @@ -0,0 +1,73 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2017 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup spoutliner + */ + +#include "BLI_listbase.h" + +#include "BKE_context.h" + +#include "DNA_space_types.h" + +#include "RNA_access.h" + +#include "outliner_intern.h" + +static void outliner_context_selected_ids_recursive(const ListBase *subtree, + bContextDataResult *result) +{ + LISTBASE_FOREACH (const TreeElement *, te, subtree) { + const TreeStoreElem *tse = TREESTORE(te); + if ((tse->flag & TSE_SELECTED) && (ELEM(tse->type, 0, TSE_LAYER_COLLECTION))) { + CTX_data_id_list_add(result, tse->id); + } + outliner_context_selected_ids_recursive(&te->subtree, result); + } +} + +static void outliner_context_selected_ids(const SpaceOutliner *space_outliner, + bContextDataResult *result) +{ + outliner_context_selected_ids_recursive(&space_outliner->tree, result); + CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION); +} + +const char *outliner_context_dir[] = {"selected_ids", NULL}; + +int /*eContextResult*/ outliner_context(const bContext *C, + const char *member, + bContextDataResult *result) +{ + SpaceOutliner *space_outliner = CTX_wm_space_outliner(C); + + if (CTX_data_dir(member)) { + CTX_data_dir_set(result, outliner_context_dir); + return CTX_RESULT_OK; + } + else if (CTX_data_equals(member, "selected_ids")) { + outliner_context_selected_ids(space_outliner, result); + return CTX_RESULT_OK; + } + /* Note: Querying non-ID selection could also work if tree elements stored their matching RNA + * struct type. */ + + return CTX_RESULT_MEMBER_NOT_FOUND; +} diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h index 0294b4836c8..ccb481197e4 100644 --- a/source/blender/editors/space_outliner/outliner_intern.h +++ b/source/blender/editors/space_outliner/outliner_intern.h @@ -32,6 +32,7 @@ extern "C" { /* internal exports only */ struct ARegion; +struct bContextDataResult; struct EditBone; struct ID; struct ListBase; @@ -561,6 +562,12 @@ void outliner_tag_redraw_avoid_rebuild_on_open_change(const struct SpaceOutliner void outliner_sync_selection(const struct bContext *C, struct SpaceOutliner *space_outliner); +/* outliner_context.c ------------------------------------------- */ + +int outliner_context(const struct bContext *C, + const char *member, + struct bContextDataResult *result); + #ifdef __cplusplus } #endif diff --git a/source/blender/editors/space_outliner/space_outliner.c b/source/blender/editors/space_outliner/space_outliner.c index 3d675fdd9e4..c7c207caca0 100644 --- a/source/blender/editors/space_outliner/space_outliner.c +++ b/source/blender/editors/space_outliner/space_outliner.c @@ -451,6 +451,7 @@ void ED_spacetype_outliner(void) st->dropboxes = outliner_dropboxes; st->id_remap = outliner_id_remap; st->deactivate = outliner_deactivate; + st->context = outliner_context; /* regions: main window */ art = MEM_callocN(sizeof(ARegionType), "spacetype outliner region"); -- cgit v1.2.3 From 0c1d4769235c95fc976be8988e2d4c529f3fdf49 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Fri, 11 Dec 2020 22:20:31 +0100 Subject: UI: Allow UI to pass focused data-block to operators via context This is similar to c4a2067130130d, but applies to the general UI and is only about single data-blocks. Here there was a similar problem: How can buttons pass the data they represent to operators? We currently resort to ugly ad-hoc solutions like `UI_context_active_but_get_tab_ID()`. So the operator would need to know that it is executed on a tab button that represents a data-block. A single button can now hand operators a data-block to operate on. The operator can request it via the "id" context member (`CTX_data_pointer_get_type(C, "id", &RNA_ID)` in C, `bpy.context.id` in .py). In this commit, it is already set in the following places: * Generic RNA button code sets it to the pointed to data-block, if the button represents a data-block RNA pointer property. (I.e for general data-block search buttons.) * Data-block selectors (`templateID`) set it to the currently active data-block. * The material slot UI-List sets it for each slot to the material it represents. The button context menu code is modified so its operators use the context set for the layout of its parent button (i.e. `layout.context_pointer_set()`). No user visible changes. This new design isn't actually used yet. It will be soon for asset operators. Reviewed as part of https://developer.blender.org/D9717. Reviewed by: Brecht Van Lommel --- source/blender/blenkernel/BKE_context.h | 3 ++- source/blender/blenkernel/intern/context.c | 7 ++++++- source/blender/editors/include/UI_interface.h | 1 + source/blender/editors/interface/interface.c | 9 +++++++++ source/blender/editors/interface/interface_context_menu.c | 10 ++++++++++ source/blender/editors/interface/interface_layout.c | 5 +++++ source/blender/editors/interface/interface_templates.c | 7 +++++++ 7 files changed, 40 insertions(+), 2 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/BKE_context.h b/source/blender/blenkernel/BKE_context.h index af9a95e1753..94392dd78da 100644 --- a/source/blender/blenkernel/BKE_context.h +++ b/source/blender/blenkernel/BKE_context.h @@ -143,8 +143,9 @@ bContext *CTX_copy(const bContext *C); /* Stored Context */ -bContextStore *CTX_store_add(ListBase *contexts, const char *name, PointerRNA *ptr); +bContextStore *CTX_store_add(ListBase *contexts, const char *name, const PointerRNA *ptr); bContextStore *CTX_store_add_all(ListBase *contexts, bContextStore *context); +bContextStore *CTX_store_get(bContext *C); void CTX_store_set(bContext *C, bContextStore *store); bContextStore *CTX_store_copy(bContextStore *store); void CTX_store_free(bContextStore *store); diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c index 2e4d3d62925..65accc66084 100644 --- a/source/blender/blenkernel/intern/context.c +++ b/source/blender/blenkernel/intern/context.c @@ -123,7 +123,7 @@ void CTX_free(bContext *C) /* store */ -bContextStore *CTX_store_add(ListBase *contexts, const char *name, PointerRNA *ptr) +bContextStore *CTX_store_add(ListBase *contexts, const char *name, const PointerRNA *ptr) { /* ensure we have a context to put the entry in, if it was already used * we have to copy the context to ensure */ @@ -178,6 +178,11 @@ bContextStore *CTX_store_add_all(ListBase *contexts, bContextStore *context) return ctx; } +bContextStore *CTX_store_get(bContext *C) +{ + return C->wm.store; +} + void CTX_store_set(bContext *C, bContextStore *store) { C->wm.store = store; diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 005dbf0e381..352c58032f5 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -1879,6 +1879,7 @@ uiBlock *uiLayoutGetBlock(uiLayout *layout); void uiLayoutSetFunc(uiLayout *layout, uiMenuHandleFunc handlefunc, void *argv); void uiLayoutSetContextPointer(uiLayout *layout, const char *name, struct PointerRNA *ptr); +struct bContextStore *uiLayoutGetContextStore(uiLayout *layout); void uiLayoutContextCopy(uiLayout *layout, struct bContextStore *context); struct wmOperatorType *UI_but_operatortype_get_from_enum_menu(struct uiBut *but, PropertyRNA **r_prop); diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index 4a02c6b6e88..254d0909367 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -4552,6 +4552,15 @@ static uiBut *ui_def_but_rna(uiBlock *block, UI_but_disable(but, info); } + if (proptype == PROP_POINTER) { + /* If the button shows an ID, automatically set it as focused in context so operators can + * access it.*/ + const PointerRNA pptr = RNA_property_pointer_get(ptr, prop); + if (pptr.data && RNA_struct_is_ID(pptr.type)) { + but->context = CTX_store_add(&block->contexts, "id", &pptr); + } + } + if (but->flag & UI_BUT_UNDO && (ui_but_is_rna_undo(but) == false)) { but->flag &= ~UI_BUT_UNDO; } diff --git a/source/blender/editors/interface/interface_context_menu.c b/source/blender/editors/interface/interface_context_menu.c index 39b405a02b8..3e76cd1cde4 100644 --- a/source/blender/editors/interface/interface_context_menu.c +++ b/source/blender/editors/interface/interface_context_menu.c @@ -503,6 +503,7 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but) uiPopupMenu *pup; uiLayout *layout; + bContextStore *previous_ctx = CTX_store_get(C); { uiStringInfo label = {BUT_GET_LABEL, NULL}; @@ -514,6 +515,11 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but) if (label.strinfo) { MEM_freeN(label.strinfo); } + + if (but->context) { + uiLayoutContextCopy(layout, but->context); + CTX_store_set(C, uiLayoutGetContextStore(layout)); + } uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT); } @@ -1210,6 +1216,10 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but) UI_menutype_draw(C, mt, uiLayoutColumn(layout, false)); } + if (but->context) { + CTX_store_set(C, previous_ctx); + } + return UI_popup_menu_end_or_cancel(C, pup); } diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index ebd2235cb82..4b19b8f97f4 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -5663,6 +5663,11 @@ void uiLayoutSetContextPointer(uiLayout *layout, const char *name, PointerRNA *p layout->context = CTX_store_add(&block->contexts, name, ptr); } +bContextStore *uiLayoutGetContextStore(uiLayout *layout) +{ + return layout->context; +} + void uiLayoutContextCopy(uiLayout *layout, bContextStore *context) { uiBlock *block = layout->root->block; diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 43ead511cfe..352afe72e76 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -895,6 +895,9 @@ static void template_ID(const bContext *C, idfrom = template_ui->ptr.owner_id; // lb = template_ui->idlb; + /* Allow opertators to take the ID from context. */ + uiLayoutSetContextPointer(layout, "id", &idptr); + block = uiLayoutGetBlock(layout); UI_block_align_begin(block); @@ -6170,6 +6173,10 @@ void uiTemplateList(uiLayout *layout, org_i, flt_flag); + /* Items should be able to set context pointers for the layout. But the listrow button + * swallows events, so it needs the context storage too for handlers to see it. */ + but->context = uiLayoutGetContextStore(sub); + /* If we are "drawing" active item, set all labels as active. */ if (i == activei) { ui_layout_list_set_labels_active(sub); -- cgit v1.2.3 From ae94a390a72763f2cd1d7108e723d153c549c310 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Sat, 12 Dec 2020 12:24:14 +0100 Subject: Cleanup: clang tidy --- source/blender/editors/space_outliner/outliner_context.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender') diff --git a/source/blender/editors/space_outliner/outliner_context.c b/source/blender/editors/space_outliner/outliner_context.c index 760fa8e4604..e7dc2780c37 100644 --- a/source/blender/editors/space_outliner/outliner_context.c +++ b/source/blender/editors/space_outliner/outliner_context.c @@ -62,7 +62,7 @@ int /*eContextResult*/ outliner_context(const bContext *C, CTX_data_dir_set(result, outliner_context_dir); return CTX_RESULT_OK; } - else if (CTX_data_equals(member, "selected_ids")) { + if (CTX_data_equals(member, "selected_ids")) { outliner_context_selected_ids(space_outliner, result); return CTX_RESULT_OK; } -- cgit v1.2.3 From 3eb66494539b58d67b1605e76a070a97e910f124 Mon Sep 17 00:00:00 2001 From: Falk David Date: Sat, 12 Dec 2020 16:34:38 +0100 Subject: GPencil: Add uniform subdivide BKE to improve interpolation This patch introduces a new BKE function that performs a uniform subdivide. The goal of this function is to subdivide the stroke to reach a target number of points while maintaining its shape, color, and weights. This is done by repeatedly subdividing the longest edge in the stroke. Every subdivision adds a new point at the exact middle point of an edge. The function is intended to be used in the interpolation operators to give better results when interpolating between different sized strokes. Reviewed By: antoniov Differential Revision: https://developer.blender.org/D9835 --- source/blender/blenkernel/BKE_gpencil_geom.h | 5 + source/blender/blenkernel/intern/gpencil_geom.c | 194 ++++++++++++++++++++++++ 2 files changed, 199 insertions(+) (limited to 'source/blender') diff --git a/source/blender/blenkernel/BKE_gpencil_geom.h b/source/blender/blenkernel/BKE_gpencil_geom.h index b107a6e72af..111f9030463 100644 --- a/source/blender/blenkernel/BKE_gpencil_geom.h +++ b/source/blender/blenkernel/BKE_gpencil_geom.h @@ -164,6 +164,11 @@ bool BKE_gpencil_convert_mesh(struct Main *bmain, const bool use_seams, const bool use_faces); +void BKE_gpencil_stroke_uniform_subdivide(struct bGPdata *gpd, + struct bGPDstroke *gps, + const uint32_t target_number, + const bool select); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/intern/gpencil_geom.c b/source/blender/blenkernel/intern/gpencil_geom.c index fc74439fd76..85b02d2ba3b 100644 --- a/source/blender/blenkernel/intern/gpencil_geom.c +++ b/source/blender/blenkernel/intern/gpencil_geom.c @@ -34,6 +34,7 @@ #include "BLI_blenlib.h" #include "BLI_ghash.h" #include "BLI_hash.h" +#include "BLI_heap.h" #include "BLI_math_vector.h" #include "BLI_polyfill_2d.h" @@ -3224,4 +3225,197 @@ void BKE_gpencil_stroke_join(bGPDstroke *gps_a, gps_a, dvert, pt, delta, pt->pressure * ratio, pt->strength, deltatime); } } + +/* Stroke Uniform Subdivide ------------------------------------- */ + +typedef struct tSamplePoint { + struct tSamplePoint *next, *prev; + float x, y, z; + float pressure, strength, time; + float vertex_color[4]; + struct MDeformWeight *dw; + int totweight; +} tSamplePoint; + +typedef struct tSampleEdge { + float length_sq; + tSamplePoint *from; + tSamplePoint *to; +} tSampleEdge; + +/* Helper: creates a tSamplePoint from a bGPDspoint and (optionally) a MDeformVert. */ +static tSamplePoint *new_sample_point_from_gp_point(const bGPDspoint *pt, const MDeformVert *dvert) +{ + tSamplePoint *new_pt = MEM_callocN(sizeof(tSamplePoint), __func__); + copy_v3_v3(&new_pt->x, &pt->x); + new_pt->pressure = pt->pressure; + new_pt->strength = pt->strength; + new_pt->time = pt->time; + copy_v4_v4((float *)&new_pt->vertex_color, (float *)&pt->vert_color); + if (dvert != NULL) { + new_pt->totweight = dvert->totweight; + new_pt->dw = MEM_callocN(sizeof(MDeformWeight) * new_pt->totweight, __func__); + for (uint i = 0; i < new_pt->totweight; ++i) { + MDeformWeight *dw = &new_pt->dw[i]; + MDeformWeight *dw_from = &dvert->dw[i]; + dw->def_nr = dw_from->def_nr; + dw->weight = dw_from->weight; + } + } + return new_pt; +} + +/* Helper: creates a tSampleEdge from two tSamplePoints. Also calculates the length (squared) of + * the edge. */ +static tSampleEdge *new_sample_edge_from_sample_points(tSamplePoint *from, tSamplePoint *to) +{ + tSampleEdge *new_edge = MEM_callocN(sizeof(tSampleEdge), __func__); + new_edge->from = from; + new_edge->to = to; + new_edge->length_sq = len_squared_v3v3(&from->x, &to->x); + return new_edge; +} + +/** + * Subdivide the grease pencil stroke so the number of points is target_number. + * Does not change the shape of the stroke. The new points will be distributed as + * uniformly as possible by repeatedly subdividing the current longest edge. + * + * \param gps: The stroke to be upsampled. + * \param target_number: The number of points the upsampled stroke should have. + * \param select: Select/Deselect the stroke. + */ +void BKE_gpencil_stroke_uniform_subdivide(bGPdata *gpd, + bGPDstroke *gps, + const uint32_t target_number, + const bool select) +{ + /* Stroke needs at least two points and strictly less points than the target number. */ + if (gps == NULL || gps->totpoints < 2 || gps->totpoints >= target_number) { + return; + } + + const int totpoints = gps->totpoints; + const bool has_dverts = (gps->dvert != NULL); + const bool is_cyclic = (gps->flag & GP_STROKE_CYCLIC); + + ListBase points = {NULL, NULL}; + Heap *edges = BLI_heap_new(); + + /* Add all points into list. */ + for (uint32_t i = 0; i < totpoints; ++i) { + bGPDspoint *pt = &gps->points[i]; + MDeformVert *dvert = has_dverts ? &gps->dvert[i] : NULL; + tSamplePoint *sp = new_sample_point_from_gp_point(pt, dvert); + BLI_addtail(&points, sp); + } + + /* Iterate over edges and insert them into the heap. */ + for (tSamplePoint *pt = ((tSamplePoint *)points.first)->next; pt != NULL; pt = pt->next) { + tSampleEdge *se = new_sample_edge_from_sample_points(pt->prev, pt); + /* BLI_heap is a min-heap, but we need the largest key to be at the top, so we take the + * negative of the squared length. */ + BLI_heap_insert(edges, -(se->length_sq), se); + } + + if (is_cyclic) { + tSamplePoint *sp_first = points.first; + tSamplePoint *sp_last = points.last; + tSampleEdge *se = new_sample_edge_from_sample_points(sp_last, sp_first); + BLI_heap_insert(edges, -(se->length_sq), se); + } + + int num_points_needed = target_number - totpoints; + BLI_assert(num_points_needed > 0); + + while (num_points_needed > 0) { + tSampleEdge *se = BLI_heap_pop_min(edges); + tSamplePoint *sp = se->from; + tSamplePoint *sp_next = se->to; + + /* Subdivide the edge. */ + tSamplePoint *new_sp = MEM_callocN(sizeof(tSamplePoint), __func__); + interp_v3_v3v3(&new_sp->x, &sp->x, &sp_next->x, 0.5f); + new_sp->pressure = interpf(sp->pressure, sp_next->pressure, 0.5f); + new_sp->strength = interpf(sp->strength, sp_next->strength, 0.5f); + new_sp->time = interpf(sp->time, sp_next->time, 0.5f); + interp_v4_v4v4((float *)&new_sp->vertex_color, + (float *)&sp->vertex_color, + (float *)&sp_next->vertex_color, + 0.5f); + if (sp->dw && sp_next->dw) { + new_sp->totweight = MIN2(sp->totweight, sp_next->totweight); + new_sp->dw = MEM_callocN(sizeof(MDeformWeight) * new_sp->totweight, __func__); + for (uint32_t i = 0; i < new_sp->totweight; ++i) { + MDeformWeight *dw = &new_sp->dw[i]; + MDeformWeight *dw_from = &sp->dw[i]; + MDeformWeight *dw_to = &sp_next->dw[i]; + dw->def_nr = dw_from->def_nr; + dw->weight = interpf(dw_from->weight, dw_to->weight, 0.5f); + } + } + BLI_insertlinkafter(&points, sp, new_sp); + + tSampleEdge *se_prev = new_sample_edge_from_sample_points(sp, new_sp); + tSampleEdge *se_next = new_sample_edge_from_sample_points(new_sp, sp_next); + BLI_heap_insert(edges, -(se_prev->length_sq), se_prev); + BLI_heap_insert(edges, -(se_next->length_sq), se_next); + + MEM_freeN(se); + num_points_needed--; + } + + /* Edges are no longer needed. Heap is freed. */ + BLI_heap_free(edges, (HeapFreeFP)MEM_freeN); + + gps->totpoints = target_number; + gps->points = MEM_recallocN(gps->points, sizeof(bGPDspoint) * gps->totpoints); + if (has_dverts) { + gps->dvert = MEM_recallocN(gps->dvert, sizeof(MDeformVert) * gps->totpoints); + } + + /* Convert list back to stroke point array. */ + tSamplePoint *sp = points.first; + for (uint32_t i = 0; i < gps->totpoints && sp; ++i, sp = sp->next) { + bGPDspoint *pt = &gps->points[i]; + MDeformVert *dvert = &gps->dvert[i]; + + copy_v3_v3(&pt->x, &sp->x); + pt->pressure = sp->pressure; + pt->strength = sp->strength; + pt->time = sp->time; + copy_v4_v4((float *)&pt->vert_color, (float *)&sp->vertex_color); + + if (sp->dw) { + dvert->totweight = sp->totweight; + dvert->dw = MEM_callocN(sizeof(MDeformWeight) * dvert->totweight, __func__); + for (uint32_t j = 0; j < dvert->totweight; ++j) { + MDeformWeight *dw = &dvert->dw[j]; + MDeformWeight *dw_from = &sp->dw[j]; + dw->def_nr = dw_from->def_nr; + dw->weight = dw_from->weight; + } + } + if (select) { + pt->flag |= GP_SPOINT_SELECT; + } + } + + if (select) { + gps->flag |= GP_STROKE_SELECT; + } + + /* Free the sample points. Important to use the mutable loop here because we are erasing the list + * elements. */ + LISTBASE_FOREACH_MUTABLE (tSamplePoint *, temp, &points) { + if (temp->dw != NULL) { + MEM_freeN(temp->dw); + } + MEM_SAFE_FREE(temp); + } + + /* Update the geometry of the stroke. */ + BKE_gpencil_stroke_geometry_update(gpd, gps); +} + /** \} */ -- cgit v1.2.3 From 57f900e4efdaa0e4daba8e3c52684acb52a67a2e Mon Sep 17 00:00:00 2001 From: Antonio Vazquez Date: Sat, 12 Dec 2020 18:40:48 +0100 Subject: Fix T83705: GPencil - Duplicate strokes of destination layer when merge layer If the destination layer hadn't keyframe, a new keyframe was added and later the merge layer strokes were added, but this could change the animation because the new frame replaced the old drawings of the target layer. Now, before merge the layer, all keyframes are added in the target layer in order to keep the drawings. --- source/blender/editors/gpencil/gpencil_data.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/gpencil/gpencil_data.c b/source/blender/editors/gpencil/gpencil_data.c index 33a1469beab..203e86e9e15 100644 --- a/source/blender/editors/gpencil/gpencil_data.c +++ b/source/blender/editors/gpencil/gpencil_data.c @@ -1330,19 +1330,24 @@ static int gpencil_merge_layer_exec(bContext *C, wmOperator *op) BLI_ghash_insert(gh_frames_dst, POINTER_FROM_INT(gpf_dst->framenum), gpf_dst); } - /* Read all frames from merge layer and add any missing in destination layer. */ + /* Read all frames from merge layer and add any missing in destination layer, + * copying all previous strokes to keep the image equals. Need to do it in a separated + * loop to avoid strokes acumulation. */ LISTBASE_FOREACH (bGPDframe *, gpf_src, &gpl_src->frames) { /* Try to find frame in destination layer hash table. */ bGPDframe *gpf_dst = BLI_ghash_lookup(gh_frames_dst, POINTER_FROM_INT(gpf_src->framenum)); if (!gpf_dst) { - gpf_dst = BKE_gpencil_frame_addnew(gpl_dst, gpf_src->framenum); - /* Duplicate strokes into destination frame. */ - if (gpf_dst) { - BKE_gpencil_frame_copy_strokes(gpf_src, gpf_dst); - } + gpf_dst = BKE_gpencil_layer_frame_get(gpl_dst, gpf_src->framenum, GP_GETFRAME_ADD_COPY); + BLI_ghash_insert(gh_frames_dst, POINTER_FROM_INT(gpf_src->framenum), gpf_dst); } - else { - /* Add to tail all strokes. */ + } + + /* Read all frames from merge layer and add strokes. */ + LISTBASE_FOREACH (bGPDframe *, gpf_src, &gpl_src->frames) { + /* Try to find frame in destination layer hash table. */ + bGPDframe *gpf_dst = BLI_ghash_lookup(gh_frames_dst, POINTER_FROM_INT(gpf_src->framenum)); + /* Add to tail all strokes. */ + if (gpf_dst) { BLI_movelisttolist(&gpf_dst->strokes, &gpf_src->strokes); } } -- cgit v1.2.3 From c6075118d5d35657f9adcd6867b9655962e7386c Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Sun, 13 Dec 2020 09:27:37 -0600 Subject: Cleanup: Reduce variable scope in view_2d_ops.c --- source/blender/editors/interface/view2d_ops.c | 72 ++++++++++----------------- 1 file changed, 25 insertions(+), 47 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c index a5999962e09..7de0ec0255f 100644 --- a/source/blender/editors/interface/view2d_ops.c +++ b/source/blender/editors/interface/view2d_ops.c @@ -109,14 +109,13 @@ typedef struct v2dViewPanData { static bool view_pan_poll(bContext *C) { ARegion *region = CTX_wm_region(C); - View2D *v2d; /* check if there's a region in context to work with */ if (region == NULL) { return false; } - v2d = ®ion->v2d; + View2D *v2d = ®ion->v2d; /* check that 2d-view can pan */ if ((v2d->keepofs & V2D_LOCKOFS_X) && (v2d->keepofs & V2D_LOCKOFS_Y)) { @@ -191,10 +190,7 @@ static void view_pan_apply(bContext *C, wmOperator *op) /* cleanup temp customdata */ static void view_pan_exit(wmOperator *op) { - if (op->customdata) { - MEM_freeN(op->customdata); - op->customdata = NULL; - } + MEM_SAFE_FREE(op->customdata); } /** \} */ @@ -216,14 +212,12 @@ static int view_pan_exec(bContext *C, wmOperator *op) static int view_pan_invoke(bContext *C, wmOperator *op, const wmEvent *event) { wmWindow *window = CTX_wm_window(C); - v2dViewPanData *vpd; - View2D *v2d; /* set up customdata */ view_pan_init(C, op); - vpd = op->customdata; - v2d = vpd->v2d; + v2dViewPanData *vpd = op->customdata; + View2D *v2d = vpd->v2d; /* set initial settings */ vpd->startx = vpd->lastx = event->x; @@ -787,7 +781,6 @@ static void view_zoom_axis_lock_defaults(bContext *C, bool r_do_zoom_xy[2]) static bool view_zoom_poll(bContext *C) { ARegion *region = CTX_wm_region(C); - View2D *v2d; /* check if there's a region in context to work with */ if (region == NULL) { @@ -799,7 +792,7 @@ static bool view_zoom_poll(bContext *C) return false; } - v2d = ®ion->v2d; + View2D *v2d = ®ion->v2d; /* check that 2d-view is zoomable */ if ((v2d->keepzoom & V2D_LOCKZOOM_X) && (v2d->keepzoom & V2D_LOCKZOOM_Y)) { @@ -836,12 +829,12 @@ static void view_zoomstep_apply_ex(bContext *C, ARegion *region = CTX_wm_region(C); View2D *v2d = ®ion->v2d; const rctf cur_old = v2d->cur; - float dx, dy; const int snap_test = ED_region_snap_size_test(region); /* calculate amount to move view by, ensuring symmetry so the * old zoom level is restored after zooming back the same amount */ + float dx, dy; if (facx >= 0.0f) { dx = BLI_rctf_size_x(&v2d->cur) * facx; dy = BLI_rctf_size_y(&v2d->cur) * facy; @@ -955,10 +948,7 @@ static void view_zoomstep_exit(wmOperator *op) { UI_view2d_zoom_cache_reset(); - if (op->customdata) { - MEM_freeN(op->customdata); - op->customdata = NULL; - } + MEM_SAFE_FREE(op->customdata); } /* this operator only needs this single callback, where it calls the view_zoom_*() methods */ @@ -1107,15 +1097,14 @@ static void view_zoomdrag_apply(bContext *C, wmOperator *op) { v2dViewZoomData *vzd = op->customdata; View2D *v2d = vzd->v2d; - float dx, dy; const int snap_test = ED_region_snap_size_test(vzd->region); const bool use_cursor_init = RNA_boolean_get(op->ptr, "use_cursor_init"); const bool zoom_to_pos = use_cursor_init && vzd->zoom_to_mouse_pos; /* get amount to move view by */ - dx = RNA_float_get(op->ptr, "deltax") / U.dpi_fac; - dy = RNA_float_get(op->ptr, "deltay") / U.dpi_fac; + float dx = RNA_float_get(op->ptr, "deltax") / U.dpi_fac; + float dy = RNA_float_get(op->ptr, "deltay") / U.dpi_fac; if (U.uiflag & USER_ZOOM_INVERT) { dx *= -1; @@ -1223,14 +1212,12 @@ static int view_zoomdrag_exec(bContext *C, wmOperator *op) static int view_zoomdrag_invoke(bContext *C, wmOperator *op, const wmEvent *event) { wmWindow *window = CTX_wm_window(C); - v2dViewZoomData *vzd; - View2D *v2d; /* set up customdata */ view_zoomdrag_init(C, op); - vzd = op->customdata; - v2d = vzd->v2d; + v2dViewZoomData *vzd = op->customdata; + View2D *v2d = vzd->v2d; if (U.uiflag & USER_ZOOM_TO_MOUSEPOS) { ARegion *region = CTX_wm_region(C); @@ -1242,20 +1229,18 @@ static int view_zoomdrag_invoke(bContext *C, wmOperator *op, const wmEvent *even } if (ELEM(event->type, MOUSEZOOM, MOUSEPAN)) { - float dx, dy, fac; - vzd->lastx = event->prevx; vzd->lasty = event->prevy; /* As we have only 1D information (magnify value), feed both axes * with magnify information that is stored in x axis */ - fac = 0.01f * (event->prevx - event->x); - dx = fac * BLI_rctf_size_x(&v2d->cur) / 10.0f; + float fac = 0.01f * (event->prevx - event->x); + float dx = fac * BLI_rctf_size_x(&v2d->cur) / 10.0f; if (event->type == MOUSEPAN) { fac = 0.01f * (event->prevy - event->y); } - dy = fac * BLI_rctf_size_y(&v2d->cur) / 10.0f; + float dy = fac * BLI_rctf_size_y(&v2d->cur) / 10.0f; /* support trackpad zoom to always zoom entirely - the v2d code uses portrait or * landscape exceptions */ @@ -1491,11 +1476,11 @@ static int view_borderzoom_exec(bContext *C, wmOperator *op) { ARegion *region = CTX_wm_region(C); View2D *v2d = ®ion->v2d; - rctf rect; rctf cur_new = v2d->cur; const int smooth_viewtx = WM_operator_smooth_viewtx_get(op); /* convert coordinates of rect to 'tot' rect coordinates */ + rctf rect; WM_operator_properties_border_to_rctf(op, &rect); UI_view2d_region_to_view_rctf(v2d, &rect, &rect); @@ -1766,13 +1751,13 @@ static int view2d_smoothview_invoke(bContext *C, wmOperator *UNUSED(op), const w ARegion *region = CTX_wm_region(C); View2D *v2d = ®ion->v2d; struct SmoothView2DStore *sms = v2d->sms; - float step; /* escape if not our timer */ if (v2d->smooth_timer == NULL || v2d->smooth_timer != event->customdata) { return OPERATOR_PASS_THROUGH; } + float step; if (sms->time_allowed != 0.0) { step = (float)((v2d->smooth_timer->duration) / sms->time_allowed); } @@ -1978,15 +1963,11 @@ static void scroller_activate_init(bContext *C, const wmEvent *event, const char in_scroller) { - v2dScrollerMove *vsm; - View2DScrollers scrollers; ARegion *region = CTX_wm_region(C); View2D *v2d = ®ion->v2d; - rctf tot_cur_union; - float mask_size; /* set custom-data for operator */ - vsm = MEM_callocN(sizeof(v2dScrollerMove), "v2dScrollerMove"); + v2dScrollerMove *vsm = MEM_callocN(sizeof(v2dScrollerMove), "v2dScrollerMove"); op->customdata = vsm; /* set general data */ @@ -2000,16 +1981,17 @@ static void scroller_activate_init(bContext *C, /* 'zone' depends on where mouse is relative to bubble * - zooming must be allowed on this axis, otherwise, default to pan */ + View2DScrollers scrollers; UI_view2d_scrollers_calc(v2d, NULL, &scrollers); /* Use a union of 'cur' & 'tot' in case the current view is far outside 'tot'. In this cases * moving the scroll bars has far too little effect and the view can get stuck T31476. */ - tot_cur_union = v2d->tot; + rctf tot_cur_union = v2d->tot; BLI_rctf_union(&tot_cur_union, &v2d->cur); if (in_scroller == 'h') { /* horizontal scroller - calculate adjustment factor first */ - mask_size = (float)BLI_rcti_size_x(&v2d->hor); + float mask_size = (float)BLI_rcti_size_x(&v2d->hor); vsm->fac = BLI_rctf_size_x(&tot_cur_union) / mask_size; /* pixel rounding */ @@ -2029,7 +2011,7 @@ static void scroller_activate_init(bContext *C, } else { /* vertical scroller - calculate adjustment factor first */ - mask_size = (float)BLI_rcti_size_y(&v2d->vert); + float mask_size = (float)BLI_rcti_size_y(&v2d->vert); vsm->fac = BLI_rctf_size_y(&tot_cur_union) / mask_size; /* pixel rounding */ @@ -2076,10 +2058,9 @@ static void scroller_activate_apply(bContext *C, wmOperator *op) { v2dScrollerMove *vsm = op->customdata; View2D *v2d = vsm->v2d; - float temp; /* calculate amount to move view by */ - temp = vsm->fac * vsm->delta; + float temp = vsm->fac * vsm->delta; /* round to pixel */ temp = roundf(temp / vsm->fac_round) * vsm->fac_round; @@ -2219,11 +2200,9 @@ static int scroller_activate_invoke(bContext *C, wmOperator *op, const wmEvent * /* if in a scroller, init customdata then set modal handler which will * catch mouse-down to start doing useful stuff */ if (in_scroller) { - v2dScrollerMove *vsm; - /* initialize customdata */ scroller_activate_init(C, op, event, in_scroller); - vsm = (v2dScrollerMove *)op->customdata; + v2dScrollerMove *vsm = (v2dScrollerMove *)op->customdata; /* support for quick jump to location - gtk and qt do this on linux */ if (event->type == MIDDLEMOUSE) { @@ -2324,12 +2303,11 @@ static int reset_exec(bContext *C, wmOperator *UNUSED(op)) const uiStyle *style = UI_style_get(); ARegion *region = CTX_wm_region(C); View2D *v2d = ®ion->v2d; - int winx, winy; const int snap_test = ED_region_snap_size_test(region); /* zoom 1.0 */ - winx = (float)(BLI_rcti_size_x(&v2d->mask) + 1); - winy = (float)(BLI_rcti_size_y(&v2d->mask) + 1); + const int winx = (float)(BLI_rcti_size_x(&v2d->mask) + 1); + const int winy = (float)(BLI_rcti_size_y(&v2d->mask) + 1); v2d->cur.xmax = v2d->cur.xmin + winx; v2d->cur.ymax = v2d->cur.ymin + winy; -- cgit v1.2.3 From 9c0df8e27533657f49919e45d46c85c847048d8f Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Sun, 13 Dec 2020 21:41:08 +0300 Subject: Fix weird Swing+Twist decomposition with noncanonical quaternions. It turns out that after the fix to T83196 (rB814b2787cadd) the matrix to quaternion conversion can produce noncanonical results in large areas of the rotation space, when previously this was limited to way smaller areas. This in turn causes Swing+Twist math to produce angles beyond 180 degrees, e.g. outputting a -120..240 range. This fixes both issues, ensuring that conversion outputs a canonical result, and decomposition canonifies its input. This was reported in chat by @jpbouza. --- source/blender/blenlib/intern/math_rotation.c | 17 ++++++++++++++++- .../blender/blenlib/tests/BLI_math_rotation_test.cc | 20 ++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) (limited to 'source/blender') diff --git a/source/blender/blenlib/intern/math_rotation.c b/source/blender/blenlib/intern/math_rotation.c index a0ee16bee76..19828e69638 100644 --- a/source/blender/blenlib/intern/math_rotation.c +++ b/source/blender/blenlib/intern/math_rotation.c @@ -372,6 +372,11 @@ void mat3_normalized_to_quat(float q[4], const float mat[3][3]) q[1] = (mat[2][0] + mat[0][2]) * s; q[2] = (mat[2][1] + mat[1][2]) * s; } + + /* Make sure w is nonnegative for a canonical result. */ + if (q[0] < 0) { + negate_v4(q); + } } normalize_qt(q); @@ -556,10 +561,20 @@ void rotation_between_quats_to_quat(float q[4], const float q1[4], const float q * \param r_twist: if not NULL, receives the twist quaternion. * \returns twist angle. */ -float quat_split_swing_and_twist(const float q[4], int axis, float r_swing[4], float r_twist[4]) +float quat_split_swing_and_twist(const float q_in[4], int axis, float r_swing[4], float r_twist[4]) { BLI_assert(axis >= 0 && axis <= 2); + /* The calculation requires a canonical quaternion. */ + float q[4]; + + if (q_in[0] < 0) { + negate_v4_v4(q, q_in); + } + else { + copy_v4_v4(q, q_in); + } + /* Half-twist angle can be computed directly. */ float t = atan2f(q[axis + 1], q[0]); diff --git a/source/blender/blenlib/tests/BLI_math_rotation_test.cc b/source/blender/blenlib/tests/BLI_math_rotation_test.cc index 02257ba83dd..90fd4f8c2e6 100644 --- a/source/blender/blenlib/tests/BLI_math_rotation_test.cc +++ b/source/blender/blenlib/tests/BLI_math_rotation_test.cc @@ -71,6 +71,12 @@ TEST(math_rotation, quat_to_mat_to_quat_bad_T83196) test_quat_to_mat_to_quat(0.0149f, 0.9996f, -0.0212f, -0.0107f); } +TEST(math_rotation, quat_to_mat_to_quat_bad_negative) +{ + /* This shouldn't produce a negative q[0]. */ + test_quat_to_mat_to_quat(0.5f - 1e-6f, 0, -sqrtf(3) / 2 - 1e-6f, 0); +} + TEST(math_rotation, quat_to_mat_to_quat_near_1000) { test_quat_to_mat_to_quat(0.9999f, 0.01f, -0.001f, -0.01f); @@ -126,3 +132,17 @@ TEST(math_rotation, quat_to_mat_to_quat_near_0001) test_quat_to_mat_to_quat(0.25f, -0.025f, -0.25f, 0.97f); test_quat_to_mat_to_quat(0.30f, -0.030f, -0.30f, 0.95f); } + +TEST(math_rotation, quat_split_swing_and_twist_negative) +{ + const float input[4] = {-0.5f, 0, sqrtf(3) / 2, 0}; + const float expected_swing[4] = {1.0f, 0, 0, 0}; + const float expected_twist[4] = {0.5f, 0, -sqrtf(3) / 2, 0}; + float swing[4], twist[4]; + + float twist_angle = quat_split_swing_and_twist(input, 1, swing, twist); + + EXPECT_NEAR(twist_angle, -M_PI * 2 / 3, FLT_EPSILON); + EXPECT_V4_NEAR(swing, expected_swing, FLT_EPSILON); + EXPECT_V4_NEAR(twist, expected_twist, FLT_EPSILON); +} -- cgit v1.2.3 From bec583951d736776d2096368ef8d2b764287ac11 Mon Sep 17 00:00:00 2001 From: Yevgeny Makarov Date: Sun, 13 Dec 2020 12:28:01 -0800 Subject: UI: Remove Unused 'U.wheellinescroll' Property Remove 'U.wheellinescroll' preference, currently hidden and unused. Differential Revision: https://developer.blender.org/D9616 Reviewed by Brecht Van Lommel --- source/blender/blenloader/intern/versioning_userdef.c | 3 --- source/blender/editors/space_text/text_ops.c | 2 +- source/blender/makesdna/DNA_userdef_types.h | 3 +-- source/blender/makesrna/intern/rna_userdef.c | 6 ------ 4 files changed, 2 insertions(+), 12 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenloader/intern/versioning_userdef.c b/source/blender/blenloader/intern/versioning_userdef.c index 7bc11317bb4..cfcaeb03d77 100644 --- a/source/blender/blenloader/intern/versioning_userdef.c +++ b/source/blender/blenloader/intern/versioning_userdef.c @@ -328,9 +328,6 @@ void blo_do_versions_userdef(UserDef *userdef) #define USER_VERSION_ATLEAST(ver, subver) MAIN_VERSION_ATLEAST(userdef, ver, subver) /* the UserDef struct is not corrected with do_versions() .... ugh! */ - if (userdef->wheellinescroll == 0) { - userdef->wheellinescroll = 3; - } if (userdef->menuthreshold1 == 0) { userdef->menuthreshold1 = 5; userdef->menuthreshold2 = 2; diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c index f8b7c62686f..932bacfb8a0 100644 --- a/source/blender/editors/space_text/text_ops.c +++ b/source/blender/editors/space_text/text_ops.c @@ -2588,7 +2588,7 @@ static int text_scroll_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - txt_screen_skip(st, region, lines * U.wheellinescroll); + txt_screen_skip(st, region, lines * 3); ED_area_tag_redraw(CTX_wm_area(C)); diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index f5ac6ca4496..90944eb2b12 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -681,8 +681,7 @@ typedef struct UserDef { short versions; short dbl_click_time; - char _pad0[2]; - char wheellinescroll; + char _pad0[3]; char mini_axis_type; /** #eUserpref_UI_Flag. */ int uiflag; diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 2c659f06e90..f916c607fd9 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -5946,12 +5946,6 @@ static void rna_def_userdef_input(BlenderRNA *brna) prop = RNA_def_property(srna, "invert_zoom_wheel", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_WHEELZOOMDIR); RNA_def_property_ui_text(prop, "Wheel Invert Zoom", "Swap the Mouse Wheel zoom direction"); - - prop = RNA_def_property(srna, "wheel_scroll_lines", PROP_INT, PROP_NONE); - RNA_def_property_int_sdna(prop, NULL, "wheellinescroll"); - RNA_def_property_range(prop, 0, 32); - RNA_def_property_ui_text( - prop, "Wheel Scroll Lines", "Number of lines scrolled at a time with the mouse wheel"); } static void rna_def_userdef_keymap(BlenderRNA *brna) -- cgit v1.2.3 From 2e5d9a73f7b957114972185e996c0e36aadd4652 Mon Sep 17 00:00:00 2001 From: Yevgeny Makarov Date: Sun, 13 Dec 2020 12:39:28 -0800 Subject: UI: Improved Script Execution Warning New dialog box layout with large alert icon for the Python script execution warning popup. Differential Revision: https://developer.blender.org/D9390 Reviewed by Hans Goudey --- source/blender/windowmanager/intern/wm_files.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) (limited to 'source/blender') diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index 5b21b2397e7..d179cc456f4 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -2959,30 +2959,25 @@ static uiBlock *block_create_autorun_warning(struct bContext *C, void *UNUSED(arg1)) { wmWindowManager *wm = CTX_wm_manager(C); - const uiStyle *style = UI_style_get_dpi(); - const int text_points_max = MAX2(style->widget.points, style->widgetlabel.points); - const int dialog_width = text_points_max * 44 * U.dpi_fac; uiBlock *block = UI_block_begin(C, region, "autorun_warning_popup", UI_EMBOSS); - UI_block_flag_enable( block, UI_BLOCK_KEEP_OPEN | UI_BLOCK_LOOP | UI_BLOCK_NO_WIN_CLIP | UI_BLOCK_NUMSELECT); UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP); UI_block_emboss_set(block, UI_EMBOSS); - uiLayout *layout = UI_block_layout( - block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 10, 2, dialog_width, 0, 0, style); + uiLayout *layout = uiItemsAlertBox(block, 44, ALERT_ICON_ERROR); - /* Text and some vertical space */ + /* Title and explanation text. */ uiLayout *col = uiLayoutColumn(layout, true); uiItemL_ex(col, TIP_("For security reasons, automatic execution of Python scripts " "in this file was disabled:"), - ICON_ERROR, + ICON_NONE, true, false); - uiItemL_ex(col, G.autoexec_fail, ICON_BLANK1, false, true); - uiItemL(col, TIP_("This may lead to unexpected behavior"), ICON_BLANK1); + uiItemL_ex(col, G.autoexec_fail, ICON_NONE, false, true); + uiItemL(col, TIP_("This may lead to unexpected behavior"), ICON_NONE); uiItemS(layout); @@ -2995,7 +2990,7 @@ static uiBlock *block_create_autorun_warning(struct bContext *C, TIP_("Permanently allow execution of scripts"), ICON_NONE); - uiItemS(layout); + uiItemS_ex(layout, 3.0f); /* Buttons */ uiBut *but; -- cgit v1.2.3 From afeaac8b18b2f0d5db0aadae6009cf1d16218c65 Mon Sep 17 00:00:00 2001 From: Yevgeny Makarov Date: Sun, 13 Dec 2020 12:48:50 -0800 Subject: Fix cursor position on HighDPI in stereo side-by-side mode Could not select left quarter of the screen in stereo side-by-side mode on high dpi displays. Differential Revision: https://developer.blender.org/D9836 Reviewed by Julian Eisel --- source/blender/windowmanager/intern/wm_stereo.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source/blender') diff --git a/source/blender/windowmanager/intern/wm_stereo.c b/source/blender/windowmanager/intern/wm_stereo.c index fb9c71163c8..a620accab72 100644 --- a/source/blender/windowmanager/intern/wm_stereo.c +++ b/source/blender/windowmanager/intern/wm_stereo.c @@ -188,7 +188,7 @@ void wm_stereo3d_mouse_offset_apply(wmWindow *win, int *r_mouse_xy) } if (win->stereo3d_format->display_mode == S3D_DISPLAY_SIDEBYSIDE) { - const int half_x = win->sizex / 2; + const int half_x = WM_window_pixels_x(win) / 2; /* right half of the screen */ if (r_mouse_xy[0] > half_x) { r_mouse_xy[0] -= half_x; @@ -196,7 +196,7 @@ void wm_stereo3d_mouse_offset_apply(wmWindow *win, int *r_mouse_xy) r_mouse_xy[0] *= 2; } else if (win->stereo3d_format->display_mode == S3D_DISPLAY_TOPBOTTOM) { - const int half_y = win->sizey / 2; + const int half_y = WM_window_pixels_y(win) / 2; /* upper half of the screen */ if (r_mouse_xy[1] > half_y) { r_mouse_xy[1] -= half_y; -- cgit v1.2.3 From a2693ba43e8cfb12a286f87fd2e14659822a1fd2 Mon Sep 17 00:00:00 2001 From: Yevgeny Makarov Date: Sun, 13 Dec 2020 12:59:36 -0800 Subject: Cleanup: removing some uses of equal sign in descriptions Using 'is/means/equal' words in place of equal sign in descriptions. Differential Revision: https://developer.blender.org/D9799 Reviewed by Hans Goudey --- source/blender/editors/mesh/editmesh_select.c | 3 ++- source/blender/editors/space_action/action_edit.c | 2 +- source/blender/editors/space_graph/graph_edit.c | 4 ++-- source/blender/editors/space_outliner/outliner_dragdrop.c | 4 ++-- source/blender/makesrna/intern/rna_constraint.c | 2 +- source/blender/makesrna/intern/rna_nodetree.c | 10 +++++----- source/blender/makesrna/intern/rna_pose.c | 2 +- 7 files changed, 14 insertions(+), 13 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index a2fe949b6c5..d3eaa9048d3 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -4552,7 +4552,8 @@ void MESH_OT_select_non_manifold(wmOperatorType *ot) /* edges */ RNA_def_boolean(ot->srna, "use_wire", true, "Wire", "Wire edges"); RNA_def_boolean(ot->srna, "use_boundary", true, "Boundaries", "Boundary edges"); - RNA_def_boolean(ot->srna, "use_multi_face", true, "Multiple Faces", "Edges shared by 3+ faces"); + RNA_def_boolean( + ot->srna, "use_multi_face", true, "Multiple Faces", "Edges shared by more than two faces"); RNA_def_boolean(ot->srna, "use_non_contiguous", true, diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c index 167215b3813..d186cafb857 100644 --- a/source/blender/editors/space_action/action_edit.c +++ b/source/blender/editors/space_action/action_edit.c @@ -1827,7 +1827,7 @@ static const EnumPropertyItem prop_actkeys_mirror_types[] = { {ACTKEYS_MIRROR_XAXIS, "XAXIS", 0, - "By Values Over Value=0", + "By Values Over Zero Value", "Flip values of selected keyframes (i.e. negative values become positive, and vice versa)"}, {ACTKEYS_MIRROR_MARKER, "MARKER", diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c index c3e4eceef6e..e56d71913d6 100644 --- a/source/blender/editors/space_graph/graph_edit.c +++ b/source/blender/editors/space_graph/graph_edit.c @@ -2354,12 +2354,12 @@ static const EnumPropertyItem prop_graphkeys_mirror_types[] = { {GRAPHKEYS_MIRROR_YAXIS, "YAXIS", 0, - "By Times Over Time=0", + "By Times Over Zero Time", "Flip times of selected keyframes, effectively reversing the order they appear in"}, {GRAPHKEYS_MIRROR_XAXIS, "XAXIS", 0, - "By Values Over Value=0", + "By Values Over Zero Value", "Flip values of selected keyframes (i.e. negative values become positive, and vice versa)"}, {GRAPHKEYS_MIRROR_MARKER, "MARKER", diff --git a/source/blender/editors/space_outliner/outliner_dragdrop.c b/source/blender/editors/space_outliner/outliner_dragdrop.c index d3da7b80765..dcb8ef9c954 100644 --- a/source/blender/editors/space_outliner/outliner_dragdrop.c +++ b/source/blender/editors/space_outliner/outliner_dragdrop.c @@ -445,7 +445,7 @@ static int parent_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event) void OUTLINER_OT_parent_drop(wmOperatorType *ot) { /* identifiers */ - ot->name = "Drop to Set Parent [+Alt keeps transforms]"; + ot->name = "Drop to Set Parent (hold Alt to keep transforms)"; ot->description = "Drag to parent in Outliner"; ot->idname = "OUTLINER_OT_parent_drop"; @@ -531,7 +531,7 @@ static int parent_clear_invoke(bContext *C, wmOperator *UNUSED(op), const wmEven void OUTLINER_OT_parent_clear(wmOperatorType *ot) { /* identifiers */ - ot->name = "Drop to Clear Parent [+Alt keeps transforms]"; + ot->name = "Drop to Clear Parent (hold Alt to keep transforms)"; ot->description = "Drag to clear parent in Outliner"; ot->idname = "OUTLINER_OT_parent_clear"; diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c index 0f34ba47165..4f5828311d8 100644 --- a/source/blender/makesrna/intern/rna_constraint.c +++ b/source/blender/makesrna/intern/rna_constraint.c @@ -856,7 +856,7 @@ static void rna_def_constraint_headtail_common(StructRNA *srna) prop = RNA_def_property(srna, "head_tail", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, "bConstraint", "headtail"); - RNA_def_property_ui_text(prop, "Head/Tail", "Target along length of bone: Head=0, Tail=1"); + RNA_def_property_ui_text(prop, "Head/Tail", "Target along length of bone: Head is 0, Tail is 1"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); prop = RNA_def_property(srna, "use_bbone_shape", PROP_BOOLEAN, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 34d922fe2c8..4fc486eadac 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -6839,8 +6839,8 @@ static void def_cmp_defocus(StructRNA *srna) RNA_def_property_range(prop, 0.0f, 128.0f); RNA_def_property_ui_text( prop, - "F-stop", - "Amount of focal blur, 128=infinity=perfect focus, half the value doubles " + "F-Stop", + "Amount of focal blur, 128 (infinity) is perfect focus, half the value doubles " "the blur radius"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); @@ -6856,7 +6856,7 @@ static void def_cmp_defocus(StructRNA *srna) RNA_def_property_ui_text( prop, "Threshold", - "CoC radius threshold, prevents background bleed on in-focus midground, 0=off"); + "CoC radius threshold, prevents background bleed on in-focus midground, 0 is disabled"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); prop = RNA_def_property(srna, "use_preview", PROP_BOOLEAN, PROP_NONE); @@ -7642,8 +7642,8 @@ static void def_cmp_bokehblur(StructRNA *srna) RNA_def_property_range(prop, 0.0f, 128.0f); RNA_def_property_ui_text( prop, - "F-stop", - "Amount of focal blur, 128=infinity=perfect focus, half the value doubles " + "F-Stop", + "Amount of focal blur, 128 (infinity) is perfect focus, half the value doubles " "the blur radius"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); # endif diff --git a/source/blender/makesrna/intern/rna_pose.c b/source/blender/makesrna/intern/rna_pose.c index 5ffad122a5e..aad94f4729f 100644 --- a/source/blender/makesrna/intern/rna_pose.c +++ b/source/blender/makesrna/intern/rna_pose.c @@ -1383,7 +1383,7 @@ static void rna_def_pose_channel(BlenderRNA *brna) "rna_PoseChannel_bone_group_index_set", "rna_PoseChannel_bone_group_index_range"); RNA_def_property_ui_text( - prop, "Bone Group Index", "Bone Group this pose channel belongs to (0=no group)"); + prop, "Bone Group Index", "Bone group this pose channel belongs to (0 means no group)"); RNA_def_property_editable_func(prop, "rna_PoseChannel_proxy_editable"); RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_update"); -- cgit v1.2.3 From dd0520b93b747dfc996e86fb67a1b3bd352e0325 Mon Sep 17 00:00:00 2001 From: Howard Trickey Date: Sun, 13 Dec 2020 15:54:19 -0500 Subject: Fix T83725 Inconsistent vertex group between exact and fast boolean. This makes the exact boolean have zero weights for any vertex groups on any newly created vertices, which is what the fast solver does. The exact boolean solver was interpolating vertex data when interpolating loop data in newly created faces. Not sure why I chose that. The Fast boolean solver doesn't do that, so I stopped doing it too. --- source/blender/bmesh/tools/bmesh_boolean.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender') diff --git a/source/blender/bmesh/tools/bmesh_boolean.cc b/source/blender/bmesh/tools/bmesh_boolean.cc index bfb093c569f..ea5d66e195c 100644 --- a/source/blender/bmesh/tools/bmesh_boolean.cc +++ b/source/blender/bmesh/tools/bmesh_boolean.cc @@ -296,7 +296,7 @@ static bool apply_mesh_output_to_bmesh(BMesh *bm, IMesh &m_out, bool keep_hidden BMIter liter; BMLoop *l = static_cast(BM_iter_new(&liter, bm, BM_LOOPS_OF_FACE, bmf)); while (l != nullptr) { - BM_loop_interp_from_face(bm, l, orig_face, true, true); + BM_loop_interp_from_face(bm, l, orig_face, false, true); l = static_cast(BM_iter_step(&liter)); } } -- cgit v1.2.3 From 977ef04746d8a6a36a217330a02024cf768f636d Mon Sep 17 00:00:00 2001 From: Yevgeny Makarov Date: Sun, 13 Dec 2020 13:12:56 -0800 Subject: Cleanup: Fix capitalization in various places Approximately 33 changes of capitalization to conform to MLA title style. Differential Revision: https://developer.blender.org/D9796 Reviewed by Julian Eisel --- source/blender/editors/animation/anim_ops.c | 2 +- source/blender/editors/curve/editcurve.c | 2 +- source/blender/editors/mesh/editmesh_bevel.c | 2 +- source/blender/editors/mesh/editmesh_knife_project.c | 2 +- source/blender/editors/object/object_gpencil_modifier.c | 2 +- source/blender/editors/object/object_relations.c | 2 +- source/blender/editors/sculpt_paint/paint_image_proj.c | 2 +- source/blender/editors/sculpt_paint/sculpt.c | 2 +- source/blender/editors/sculpt_paint/sculpt_detail.c | 2 +- source/blender/editors/sculpt_paint/sculpt_filter_color.c | 4 ++-- source/blender/editors/sculpt_paint/sculpt_filter_mask.c | 4 ++-- source/blender/editors/sculpt_paint/sculpt_filter_mesh.c | 6 +++--- source/blender/editors/space_action/action_select.c | 4 ++-- source/blender/editors/space_graph/graph_select.c | 4 ++-- source/blender/editors/space_info/info_report.c | 2 +- source/blender/editors/space_node/node_view.c | 2 +- source/blender/editors/space_script/script_edit.c | 2 +- source/blender/editors/uvedit/uvedit_smart_stitch.c | 2 +- source/blender/makesrna/intern/rna_camera.c | 2 +- source/blender/makesrna/intern/rna_light.c | 2 +- source/blender/makesrna/intern/rna_material.c | 2 +- source/blender/makesrna/intern/rna_rna.c | 2 +- source/blender/makesrna/intern/rna_screen.c | 2 +- 23 files changed, 29 insertions(+), 29 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/animation/anim_ops.c b/source/blender/editors/animation/anim_ops.c index 9e622aea6ab..0db3e984b60 100644 --- a/source/blender/editors/animation/anim_ops.c +++ b/source/blender/editors/animation/anim_ops.c @@ -503,7 +503,7 @@ static void ANIM_OT_previewrange_clear(wmOperatorType *ot) /* identifiers */ ot->name = "Clear Preview Range"; ot->idname = "ANIM_OT_previewrange_clear"; - ot->description = "Clear Preview Range"; + ot->description = "Clear preview range"; /* api callbacks */ ot->exec = previewrange_clear_exec; diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c index db472c9ffa7..2b627971286 100644 --- a/source/blender/editors/curve/editcurve.c +++ b/source/blender/editors/curve/editcurve.c @@ -3838,7 +3838,7 @@ void CURVE_OT_subdivide(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - prop = RNA_def_int(ot->srna, "number_cuts", 1, 1, 1000, "Number of cuts", "", 1, 10); + prop = RNA_def_int(ot->srna, "number_cuts", 1, 1, 1000, "Number of Cuts", "", 1, 10); /* Avoid re-using last var because it can cause _very_ high poly meshes * and annoy users (or worse crash). */ RNA_def_property_flag(prop, PROP_SKIP_SAVE); diff --git a/source/blender/editors/mesh/editmesh_bevel.c b/source/blender/editors/mesh/editmesh_bevel.c index b8badd207fe..e788b28d3b4 100644 --- a/source/blender/editors/mesh/editmesh_bevel.c +++ b/source/blender/editors/mesh/editmesh_bevel.c @@ -1129,7 +1129,7 @@ void MESH_OT_bevel(wmOperatorType *ot) prop_affect_items, BEVEL_AFFECT_EDGES, "Affect", - "Affect Edges or Vertices"); + "Affect edges or vertices"); RNA_def_boolean(ot->srna, "clamp_overlap", diff --git a/source/blender/editors/mesh/editmesh_knife_project.c b/source/blender/editors/mesh/editmesh_knife_project.c index ef78d31a6bb..aa144dd3f3c 100644 --- a/source/blender/editors/mesh/editmesh_knife_project.c +++ b/source/blender/editors/mesh/editmesh_knife_project.c @@ -177,6 +177,6 @@ void MESH_OT_knife_project(wmOperatorType *ot) RNA_def_boolean(ot->srna, "cut_through", false, - "Cut through", + "Cut Through", "Cut through all faces, not just visible ones"); } diff --git a/source/blender/editors/object/object_gpencil_modifier.c b/source/blender/editors/object/object_gpencil_modifier.c index af95f5581bd..9ea67df6daf 100644 --- a/source/blender/editors/object/object_gpencil_modifier.c +++ b/source/blender/editors/object/object_gpencil_modifier.c @@ -789,7 +789,7 @@ void OBJECT_OT_gpencil_modifier_apply(wmOperatorType *ot) "apply_as", gpencil_modifier_apply_as_items, MODIFIER_APPLY_DATA, - "Apply as", + "Apply As", "How to apply the modifier to the geometry"); gpencil_edit_modifier_properties(ot); gpencil_edit_modifier_report_property(ot); diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index 3ad500d3d0d..8ec9f7af184 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -2556,7 +2556,7 @@ static int convert_proxy_to_override_exec(bContext *C, wmOperator *UNUSED(op)) void OBJECT_OT_convert_proxy_to_override(wmOperatorType *ot) { /* identifiers */ - ot->name = "Convert Proxy To Override"; + ot->name = "Convert Proxy to Override"; ot->description = "Convert a proxy to a local library override"; ot->idname = "OBJECT_OT_convert_proxy_to_override"; diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c index 98f4b4013cb..cca4ffd4d78 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.c +++ b/source/blender/editors/sculpt_paint/paint_image_proj.c @@ -6781,7 +6781,7 @@ static bool add_simple_uvs_poll(bContext *C) void PAINT_OT_add_simple_uvs(wmOperatorType *ot) { /* identifiers */ - ot->name = "Add simple UVs"; + ot->name = "Add Simple UVs"; ot->description = "Add cube map uvs on mesh"; ot->idname = "PAINT_OT_add_simple_uvs"; diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index fd7ec1da497..94f05560f79 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -8685,7 +8685,7 @@ static int sculpt_sample_color_invoke(bContext *C, static void SCULPT_OT_sample_color(wmOperatorType *ot) { /* identifiers */ - ot->name = "Sample color"; + ot->name = "Sample Color"; ot->idname = "SCULPT_OT_sample_color"; ot->description = "Sample the vertex color of the active vertex"; diff --git a/source/blender/editors/sculpt_paint/sculpt_detail.c b/source/blender/editors/sculpt_paint/sculpt_detail.c index ddf5b39f080..aa1d407dc24 100644 --- a/source/blender/editors/sculpt_paint/sculpt_detail.c +++ b/source/blender/editors/sculpt_paint/sculpt_detail.c @@ -363,7 +363,7 @@ void SCULPT_OT_sample_detail_size(wmOperatorType *ot) 0, SHRT_MAX, "Location", - "Screen Coordinates of sampling", + "Screen coordinates of sampling", 0, SHRT_MAX); RNA_def_enum(ot->srna, diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_color.c b/source/blender/editors/sculpt_paint/sculpt_filter_color.c index f3c07a86201..76a6b05cdff 100644 --- a/source/blender/editors/sculpt_paint/sculpt_filter_color.c +++ b/source/blender/editors/sculpt_paint/sculpt_filter_color.c @@ -328,9 +328,9 @@ void SCULPT_OT_color_filter(struct wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* rna */ - RNA_def_enum(ot->srna, "type", prop_color_filter_types, COLOR_FILTER_HUE, "Filter type", ""); + RNA_def_enum(ot->srna, "type", prop_color_filter_types, COLOR_FILTER_HUE, "Filter Type", ""); RNA_def_float( - ot->srna, "strength", 1.0f, -10.0f, 10.0f, "Strength", "Filter Strength", -10.0f, 10.0f); + ot->srna, "strength", 1.0f, -10.0f, 10.0f, "Strength", "Filter strength", -10.0f, 10.0f); PropertyRNA *prop = RNA_def_float_color( ot->srna, "fill_color", 3, NULL, 0.0f, FLT_MAX, "Fill Color", "", 0.0f, 1.0f); diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_mask.c b/source/blender/editors/sculpt_paint/sculpt_filter_mask.c index ddad6bef7fd..0297ed73dd4 100644 --- a/source/blender/editors/sculpt_paint/sculpt_filter_mask.c +++ b/source/blender/editors/sculpt_paint/sculpt_filter_mask.c @@ -80,12 +80,12 @@ static EnumPropertyItem prop_mask_filter_types[] = { {MASK_FILTER_CONTRAST_INCREASE, "CONTRAST_INCREASE", 0, - "Increase contrast", + "Increase Contrast", "Increase the contrast of the paint mask"}, {MASK_FILTER_CONTRAST_DECREASE, "CONTRAST_DECREASE", 0, - "Decrease contrast", + "Decrease Contrast", "Decrease the contrast of the paint mask"}, {0, NULL, 0, NULL, NULL}, }; diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c index 02d4be20e1b..e11894a8c01 100644 --- a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c +++ b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c @@ -771,15 +771,15 @@ void SCULPT_OT_mesh_filter(struct wmOperatorType *ot) "type", prop_mesh_filter_types, MESH_FILTER_INFLATE, - "Filter type", + "Filter Type", "Operation that is going to be applied to the mesh"); RNA_def_float( - ot->srna, "strength", 1.0f, -10.0f, 10.0f, "Strength", "Filter Strength", -10.0f, 10.0f); + ot->srna, "strength", 1.0f, -10.0f, 10.0f, "Strength", "Filter strength", -10.0f, 10.0f); RNA_def_enum_flag(ot->srna, "deform_axis", prop_mesh_filter_deform_axis_items, MESH_FILTER_DEFORM_X | MESH_FILTER_DEFORM_Y | MESH_FILTER_DEFORM_Z, - "Deform axis", + "Deform Axis", "Apply the deformation in the selected axis"); RNA_def_enum(ot->srna, "orientation", diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c index ab5f1e0ab22..98e39520e99 100644 --- a/source/blender/editors/space_action/action_select.c +++ b/source/blender/editors/space_action/action_select.c @@ -1325,8 +1325,8 @@ void ACTION_OT_select_less(wmOperatorType *ot) /* defines for left-right select tool */ static const EnumPropertyItem prop_actkeys_leftright_select_types[] = { {ACTKEYS_LRSEL_TEST, "CHECK", 0, "Check if Select Left or Right", ""}, - {ACTKEYS_LRSEL_LEFT, "LEFT", 0, "Before current frame", ""}, - {ACTKEYS_LRSEL_RIGHT, "RIGHT", 0, "After current frame", ""}, + {ACTKEYS_LRSEL_LEFT, "LEFT", 0, "Before Current Frame", ""}, + {ACTKEYS_LRSEL_RIGHT, "RIGHT", 0, "After Current Frame", ""}, {0, NULL, 0, NULL, NULL}, }; diff --git a/source/blender/editors/space_graph/graph_select.c b/source/blender/editors/space_graph/graph_select.c index 12035ab6b61..4ab4ef518fb 100644 --- a/source/blender/editors/space_graph/graph_select.c +++ b/source/blender/editors/space_graph/graph_select.c @@ -1288,8 +1288,8 @@ void GRAPH_OT_select_less(wmOperatorType *ot) /* defines for left-right select tool */ static const EnumPropertyItem prop_graphkeys_leftright_select_types[] = { {GRAPHKEYS_LRSEL_TEST, "CHECK", 0, "Check if Select Left or Right", ""}, - {GRAPHKEYS_LRSEL_LEFT, "LEFT", 0, "Before current frame", ""}, - {GRAPHKEYS_LRSEL_RIGHT, "RIGHT", 0, "After current frame", ""}, + {GRAPHKEYS_LRSEL_LEFT, "LEFT", 0, "Before Current Frame", ""}, + {GRAPHKEYS_LRSEL_RIGHT, "RIGHT", 0, "After Current Frame", ""}, {0, NULL, 0, NULL, NULL}, }; diff --git a/source/blender/editors/space_info/info_report.c b/source/blender/editors/space_info/info_report.c index 3ba088018c3..7dd8382c8ef 100644 --- a/source/blender/editors/space_info/info_report.c +++ b/source/blender/editors/space_info/info_report.c @@ -396,7 +396,7 @@ void INFO_OT_report_copy(wmOperatorType *ot) { /* identifiers */ ot->name = "Copy Reports to Clipboard"; - ot->description = "Copy selected reports to Clipboard"; + ot->description = "Copy selected reports to clipboard"; ot->idname = "INFO_OT_report_copy"; /* api callbacks */ diff --git a/source/blender/editors/space_node/node_view.c b/source/blender/editors/space_node/node_view.c index 3c861896d37..d2c88ed787c 100644 --- a/source/blender/editors/space_node/node_view.c +++ b/source/blender/editors/space_node/node_view.c @@ -283,7 +283,7 @@ void NODE_OT_backimage_move(wmOperatorType *ot) { /* identifiers */ ot->name = "Background Image Move"; - ot->description = "Move Node backdrop"; + ot->description = "Move node backdrop"; ot->idname = "NODE_OT_backimage_move"; /* api callbacks */ diff --git a/source/blender/editors/space_script/script_edit.c b/source/blender/editors/space_script/script_edit.c index bde7bdb77f1..50cfa2e71c7 100644 --- a/source/blender/editors/space_script/script_edit.c +++ b/source/blender/editors/space_script/script_edit.c @@ -152,7 +152,7 @@ void SCRIPT_OT_reload(wmOperatorType *ot) { /* identifiers */ ot->name = "Reload Scripts"; - ot->description = "Reload Scripts"; + ot->description = "Reload scripts"; ot->idname = "SCRIPT_OT_reload"; /* api callbacks */ diff --git a/source/blender/editors/uvedit/uvedit_smart_stitch.c b/source/blender/editors/uvedit/uvedit_smart_stitch.c index 6dac31794b4..c1d222c9368 100644 --- a/source/blender/editors/uvedit/uvedit_smart_stitch.c +++ b/source/blender/editors/uvedit/uvedit_smart_stitch.c @@ -2808,7 +2808,7 @@ void UV_OT_stitch(wmOperatorType *ot) RNA_def_boolean(ot->srna, "midpoint_snap", 0, - "Snap At Midpoint", + "Snap at Midpoint", "UVs are stitched at midpoint instead of at static island"); RNA_def_boolean(ot->srna, "clear_seams", 1, "Clear Seams", "Clear seams of stitched edges"); RNA_def_enum(ot->srna, diff --git a/source/blender/makesrna/intern/rna_camera.c b/source/blender/makesrna/intern/rna_camera.c index 1810cee5cee..df9f4674900 100644 --- a/source/blender/makesrna/intern/rna_camera.c +++ b/source/blender/makesrna/intern/rna_camera.c @@ -662,7 +662,7 @@ void RNA_def_camera(BlenderRNA *brna) prop = RNA_def_property(srna, "show_safe_center", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", CAM_SHOW_SAFE_CENTER); RNA_def_property_ui_text(prop, - "Show Center-cut safe areas", + "Show Center-Cut Safe Areas", "Show safe areas to fit content in a different aspect ratio"); RNA_def_property_update(prop, NC_CAMERA | ND_DRAW_RENDER_VIEWPORT, NULL); diff --git a/source/blender/makesrna/intern/rna_light.c b/source/blender/makesrna/intern/rna_light.c index e43079c967f..433d499b4c1 100644 --- a/source/blender/makesrna/intern/rna_light.c +++ b/source/blender/makesrna/intern/rna_light.c @@ -127,7 +127,7 @@ static void rna_def_light(BlenderRNA *brna) prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, rna_enum_light_type_items); - RNA_def_property_ui_text(prop, "Type", "Type of Light"); + RNA_def_property_ui_text(prop, "Type", "Type of light"); RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_LIGHT); RNA_def_property_update(prop, 0, "rna_Light_draw_update"); diff --git a/source/blender/makesrna/intern/rna_material.c b/source/blender/makesrna/intern/rna_material.c index 086a182e085..94b56e4f4e0 100644 --- a/source/blender/makesrna/intern/rna_material.c +++ b/source/blender/makesrna/intern/rna_material.c @@ -683,7 +683,7 @@ void RNA_def_material(BlenderRNA *brna) {MA_SPHERE, "SPHERE", ICON_MATSPHERE, "Sphere", "Sphere"}, {MA_CUBE, "CUBE", ICON_MATCUBE, "Cube", "Cube"}, {MA_HAIR, "HAIR", ICON_HAIR, "Hair", "Hair strands"}, - {MA_SHADERBALL, "SHADERBALL", ICON_MATSHADERBALL, "Shader Ball", "Shader Ball"}, + {MA_SHADERBALL, "SHADERBALL", ICON_MATSHADERBALL, "Shader Ball", "Shader ball"}, {MA_CLOTH, "CLOTH", ICON_MATCLOTH, "Cloth", "Cloth"}, {MA_FLUID, "FLUID", ICON_MATFLUID, "Fluid", "Fluid"}, {0, NULL, 0, NULL, NULL}, diff --git a/source/blender/makesrna/intern/rna_rna.c b/source/blender/makesrna/intern/rna_rna.c index 98ae7591062..e2001eacf4c 100644 --- a/source/blender/makesrna/intern/rna_rna.c +++ b/source/blender/makesrna/intern/rna_rna.c @@ -3076,7 +3076,7 @@ static void rna_def_string_property(StructRNA *srna) RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_string_funcs( prop, "rna_StringProperty_default_get", "rna_StringProperty_default_length", NULL); - RNA_def_property_ui_text(prop, "Default", "string default value"); + RNA_def_property_ui_text(prop, "Default", "String default value"); prop = RNA_def_property(srna, "length_max", PROP_INT, PROP_UNSIGNED); RNA_def_property_clear_flag(prop, PROP_EDITABLE); diff --git a/source/blender/makesrna/intern/rna_screen.c b/source/blender/makesrna/intern/rna_screen.c index ab84dcb0aba..e300fb1b31b 100644 --- a/source/blender/makesrna/intern/rna_screen.c +++ b/source/blender/makesrna/intern/rna_screen.c @@ -586,7 +586,7 @@ static void rna_def_screen(BlenderRNA *brna) prop = RNA_def_property(srna, "show_statusbar", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SCREEN_COLLAPSE_STATUSBAR); - RNA_def_property_ui_text(prop, "Show Status Bar", "Show Status Bar"); + RNA_def_property_ui_text(prop, "Show Status Bar", "Show status bar"); RNA_def_property_update(prop, 0, "rna_Screen_bar_update"); func = RNA_def_function(srna, "statusbar_info", "rna_Screen_statusbar_info_get"); -- cgit v1.2.3 From 260fca5d08e2f95e1b600a9c76a98dedd2541e10 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Sun, 13 Dec 2020 22:59:52 -0600 Subject: Fix T83673: Custom node trees selectable in nodes modifier Node tree types from addons were selectable in the modifier's drop-down. Obviously they didn't do anything, but it shouldn't be possible anyway. This was just caused by an unimplemented poll function. --- source/blender/makesrna/intern/rna_modifier.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'source/blender') diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index 80c2cbfb3ad..c32cc89aa30 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -1603,12 +1603,10 @@ static int rna_MeshSequenceCacheModifier_read_velocity_get(PointerRNA *ptr) # endif } -static bool rna_NodesModifier_node_group_poll(PointerRNA *ptr, PointerRNA value) +static bool rna_NodesModifier_node_group_poll(PointerRNA *UNUSED(ptr), PointerRNA value) { - NodesModifierData *nmd = ptr->data; bNodeTree *ntree = value.data; - UNUSED_VARS(nmd, ntree); - return true; + return ntree->type == NTREE_GEOMETRY; } static void rna_NodesModifier_node_group_update(Main *bmain, Scene *scene, PointerRNA *ptr) -- cgit v1.2.3 From fddbcb5757f6349ce1b11242fd760c1fb502a6a1 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Sun, 13 Dec 2020 23:49:14 -0600 Subject: UI: Click modifier icon to set active modifier This should be a final piece of the changes for the active modifier interface. Before, it was necessary to click on the blank space of a modifier panel to set it active (not the header), this commit allows clicking on the icon also. The spacing with the spacing with the expand button would ideally be a bit larger, but the layout system doesn't offer much flexibility here. --- source/blender/modifiers/intern/MOD_ui_common.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'source/blender') diff --git a/source/blender/modifiers/intern/MOD_ui_common.c b/source/blender/modifiers/intern/MOD_ui_common.c index fa5243c548f..55dbfdf478f 100644 --- a/source/blender/modifiers/intern/MOD_ui_common.c +++ b/source/blender/modifiers/intern/MOD_ui_common.c @@ -307,10 +307,16 @@ static void modifier_panel_header(const bContext *C, Panel *panel) /* Modifier Icon. */ sub = uiLayoutRow(layout, true); + uiLayoutSetEmboss(sub, UI_EMBOSS_NONE); if (mti->isDisabled && mti->isDisabled(scene, md, 0)) { uiLayoutSetRedAlert(sub, true); } - uiItemL(sub, "", RNA_struct_ui_icon(ptr->type)); + uiItemStringO(sub, + "", + RNA_struct_ui_icon(ptr->type), + "OBJECT_OT_modifier_set_active", + "modifier", + md->name); row = uiLayoutRow(layout, true); -- cgit v1.2.3 From 8f3a401975987c9b70f3ea0ea21977c70371b466 Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Mon, 14 Dec 2020 09:05:16 +0100 Subject: Eevee: Add Volume Transmittance to Color Render Passes. In Cycles the volume transmittance is already composited into the color passes. In Eevee the volume transmittance pass was separate and needed to be composited in the compositor. This patch adds the volume transmittance pass direct in the next render passes: * Diffuse Color * Specular Color * Emission * Environment This patch includes the removal of the volume transmittance render pass. It also renames the volume render passes to match Cycles. The setting themselves aren't unified. Maniphest Tasks: T81134 --- source/blender/blenloader/intern/versioning_290.c | 22 ++++++++ source/blender/draw/engines/eevee/eevee_private.h | 1 + source/blender/draw/engines/eevee/eevee_render.c | 26 +++------ .../draw/engines/eevee/eevee_renderpasses.c | 64 +++++++++++++++------- .../eevee/shaders/renderpass_postprocess_frag.glsl | 7 +++ source/blender/makesdna/DNA_layer_types.h | 4 +- source/blender/makesdna/DNA_scene_types.h | 3 +- source/blender/makesrna/intern/rna_scene.c | 12 +--- source/blender/makesrna/intern/rna_space.c | 7 +-- 9 files changed, 90 insertions(+), 56 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenloader/intern/versioning_290.c b/source/blender/blenloader/intern/versioning_290.c index f390f0b48d8..fe22558eb06 100644 --- a/source/blender/blenloader/intern/versioning_290.c +++ b/source/blender/blenloader/intern/versioning_290.c @@ -1258,5 +1258,27 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain) } } } + + /* EEVEE/Cycles Volumes consistency */ + for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) { + /* Remove Volume Transmittance render pass from each view layer. */ + LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) { + view_layer->eevee.render_passes &= ~EEVEE_RENDER_PASS_UNUSED_8; + } + + /* Rename Renderlayer Socket `VolumeScatterCol` to `VolumeDir` */ + if (scene->nodetree) { + LISTBASE_FOREACH (bNode *, node, &scene->nodetree->nodes) { + if (node->type == CMP_NODE_R_LAYERS) { + LISTBASE_FOREACH (bNodeSocket *, output_socket, &node->outputs) { + const static char *volume_scatter = "VolumeScatterCol"; + if (STREQLEN(output_socket->name, volume_scatter, MAX_NAME)) { + BLI_strncpy(output_socket->name, RE_PASSNAME_VOLUME_LIGHT, MAX_NAME); + } + } + } + } + } + } } } diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h index a6a480ca967..5bf8cab1b22 100644 --- a/source/blender/draw/engines/eevee/eevee_private.h +++ b/source/blender/draw/engines/eevee/eevee_private.h @@ -989,6 +989,7 @@ typedef struct EEVEE_PrivateData { GPUTexture *renderpass_input; GPUTexture *renderpass_col_input; GPUTexture *renderpass_light_input; + GPUTexture *renderpass_transmittance_input; /* Renderpass ubo reference used by material pass. */ struct GPUUniformBuf *renderpass_ubo; /** For rendering shadows. */ diff --git a/source/blender/draw/engines/eevee/eevee_render.c b/source/blender/draw/engines/eevee/eevee_render.c index 2b2ff2e5c90..2a01aeefce8 100644 --- a/source/blender/draw/engines/eevee/eevee_render.c +++ b/source/blender/draw/engines/eevee/eevee_render.c @@ -461,21 +461,13 @@ static void eevee_render_result_environment(RenderLayer *rl, EEVEE_RENDER_RESULT_MATERIAL_PASS(ENVIRONMENT, ENVIRONMENT) } -static void eevee_render_result_volume_scatter(RenderLayer *rl, - const char *viewname, - const rcti *rect, - EEVEE_Data *vedata, - EEVEE_ViewLayerData *sldata) -{ - EEVEE_RENDER_RESULT_MATERIAL_PASS(VOLUME_SCATTER, VOLUME_SCATTER) -} -static void eevee_render_result_volume_transmittance(RenderLayer *rl, - const char *viewname, - const rcti *rect, - EEVEE_Data *vedata, - EEVEE_ViewLayerData *sldata) +static void eevee_render_result_volume_light(RenderLayer *rl, + const char *viewname, + const rcti *rect, + EEVEE_Data *vedata, + EEVEE_ViewLayerData *sldata) { - EEVEE_RENDER_RESULT_MATERIAL_PASS(VOLUME_TRANSMITTANCE, VOLUME_TRANSMITTANCE) + EEVEE_RENDER_RESULT_MATERIAL_PASS(VOLUME_LIGHT, VOLUME_LIGHT) } static void eevee_render_result_aovs(RenderLayer *rl, @@ -696,8 +688,7 @@ void EEVEE_render_read_result(EEVEE_Data *vedata, eevee_render_result_emission(rl, viewname, rect, vedata, sldata); eevee_render_result_environment(rl, viewname, rect, vedata, sldata); eevee_render_result_bloom(rl, viewname, rect, vedata, sldata); - eevee_render_result_volume_scatter(rl, viewname, rect, vedata, sldata); - eevee_render_result_volume_transmittance(rl, viewname, rect, vedata, sldata); + eevee_render_result_volume_light(rl, viewname, rect, vedata, sldata); eevee_render_result_aovs(rl, viewname, rect, vedata, sldata); eevee_render_result_cryptomatte(rl, viewname, rect, vedata, sldata); } @@ -730,8 +721,7 @@ void EEVEE_render_update_passes(RenderEngine *engine, Scene *scene, ViewLayer *v CHECK_PASS_LEGACY(GLOSSY_DIRECT, SOCK_RGBA, 3, "RGB"); CHECK_PASS_LEGACY(EMIT, SOCK_RGBA, 3, "RGB"); CHECK_PASS_LEGACY(ENVIRONMENT, SOCK_RGBA, 3, "RGB"); - CHECK_PASS_EEVEE(VOLUME_SCATTER, SOCK_RGBA, 3, "RGB"); - CHECK_PASS_EEVEE(VOLUME_TRANSMITTANCE, SOCK_RGBA, 3, "RGB"); + CHECK_PASS_EEVEE(VOLUME_LIGHT, SOCK_RGBA, 3, "RGB"); CHECK_PASS_EEVEE(BLOOM, SOCK_RGBA, 3, "RGB"); LISTBASE_FOREACH (ViewLayerAOV *, aov, &view_layer->aovs) { diff --git a/source/blender/draw/engines/eevee/eevee_renderpasses.c b/source/blender/draw/engines/eevee/eevee_renderpasses.c index e7a03c678a8..6f87ff302f4 100644 --- a/source/blender/draw/engines/eevee/eevee_renderpasses.c +++ b/source/blender/draw/engines/eevee/eevee_renderpasses.c @@ -44,14 +44,14 @@ typedef enum eRenderPassPostProcessType { PASS_POST_AO = 6, PASS_POST_NORMAL = 7, PASS_POST_TWO_LIGHT_BUFFERS = 8, + PASS_POST_ACCUMULATED_TRANSMITTANCE_COLOR = 9, } eRenderPassPostProcessType; /* bitmask containing all renderpasses that need post-processing */ #define EEVEE_RENDERPASSES_WITH_POST_PROCESSING \ (EEVEE_RENDER_PASS_Z | EEVEE_RENDER_PASS_MIST | EEVEE_RENDER_PASS_NORMAL | \ - EEVEE_RENDER_PASS_AO | EEVEE_RENDER_PASS_BLOOM | EEVEE_RENDER_PASS_VOLUME_SCATTER | \ - EEVEE_RENDER_PASS_VOLUME_TRANSMITTANCE | EEVEE_RENDER_PASS_SHADOW | \ - EEVEE_RENDERPASSES_MATERIAL) + EEVEE_RENDER_PASS_AO | EEVEE_RENDER_PASS_BLOOM | EEVEE_RENDER_PASS_VOLUME_LIGHT | \ + EEVEE_RENDER_PASS_SHADOW | EEVEE_RENDERPASSES_MATERIAL) #define EEVEE_RENDERPASSES_ALL \ (EEVEE_RENDERPASSES_WITH_POST_PROCESSING | EEVEE_RENDER_PASS_COMBINED) @@ -64,7 +64,10 @@ typedef enum eRenderPassPostProcessType { EEVEE_RENDER_PASS_BLOOM) #define EEVEE_RENDERPASSES_LIGHT_PASS \ (EEVEE_RENDER_PASS_DIFFUSE_LIGHT | EEVEE_RENDER_PASS_SPECULAR_LIGHT) - +/* Render passes that uses volume transmittance when available */ +#define EEVEE_RENDERPASSES_USES_TRANSMITTANCE \ + (EEVEE_RENDER_PASS_DIFFUSE_COLOR | EEVEE_RENDER_PASS_SPECULAR_COLOR | EEVEE_RENDER_PASS_EMIT | \ + EEVEE_RENDER_PASS_ENVIRONMENT) bool EEVEE_renderpasses_only_first_sample_pass_active(EEVEE_Data *vedata) { EEVEE_StorageList *stl = vedata->stl; @@ -147,6 +150,18 @@ void EEVEE_renderpasses_init(EEVEE_Data *vedata) EEVEE_cryptomatte_renderpasses_init(vedata); } +BLI_INLINE bool eevee_renderpasses_volumetric_active(const EEVEE_EffectsInfo *effects, + const EEVEE_PrivateData *g_data) +{ + if (effects->enabled_effects & EFFECT_VOLUMETRIC) { + if (g_data->render_passes & + (EEVEE_RENDER_PASS_VOLUME_LIGHT | EEVEE_RENDERPASSES_USES_TRANSMITTANCE)) { + return true; + } + } + return false; +} + void EEVEE_renderpasses_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, uint tot_samples) @@ -189,8 +204,7 @@ void EEVEE_renderpasses_output_init(EEVEE_ViewLayerData *sldata, EEVEE_bloom_output_init(sldata, vedata, tot_samples); } - if ((g_data->render_passes & - (EEVEE_RENDER_PASS_VOLUME_TRANSMITTANCE | EEVEE_RENDER_PASS_VOLUME_SCATTER)) != 0) { + if (eevee_renderpasses_volumetric_active(effects, g_data)) { EEVEE_volumes_output_init(sldata, vedata, tot_samples); } @@ -198,6 +212,7 @@ void EEVEE_renderpasses_output_init(EEVEE_ViewLayerData *sldata, g_data->renderpass_input = txl->color; g_data->renderpass_col_input = txl->color; g_data->renderpass_light_input = txl->color; + g_data->renderpass_transmittance_input = txl->color; } else { /* Free unneeded memory */ @@ -227,6 +242,8 @@ void EEVEE_renderpasses_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *ve DRW_shgroup_uniform_texture_ref(grp, "inputColorBuffer", &g_data->renderpass_col_input); DRW_shgroup_uniform_texture_ref( grp, "inputSecondLightBuffer", &g_data->renderpass_light_input); + DRW_shgroup_uniform_texture_ref( + grp, "inputTransmittanceBuffer", &g_data->renderpass_transmittance_input); DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth); DRW_shgroup_uniform_block_ref(grp, "common_block", &sldata->common_ubo); DRW_shgroup_uniform_block_ref(grp, "renderpass_block", &sldata->renderpass_ubo.combined); @@ -265,6 +282,20 @@ void EEVEE_renderpasses_postprocess(EEVEE_ViewLayerData *UNUSED(sldata), g_data->renderpass_current_sample = current_sample; g_data->renderpass_type = renderpass_type; g_data->renderpass_postprocess = PASS_POST_UNDEFINED; + const bool volumetric_active = eevee_renderpasses_volumetric_active(effects, g_data); + eViewLayerEEVEEPassType default_color_pass_type = volumetric_active ? + PASS_POST_ACCUMULATED_TRANSMITTANCE_COLOR : + PASS_POST_ACCUMULATED_COLOR; + g_data->renderpass_transmittance_input = volumetric_active ? txl->volume_transmittance_accum : + txl->color; + + if (!volumetric_active && renderpass_type == EEVEE_RENDER_PASS_VOLUME_LIGHT) { + /* Early exit: Volumetric effect is off, but the volume light pass was requested. */ + static float clear_col[4] = {0.0f}; + GPU_framebuffer_bind(fbl->renderpass_fb); + GPU_framebuffer_clear_color(fbl->renderpass_fb, clear_col); + return; + } switch (renderpass_type) { case EEVEE_RENDER_PASS_Z: { @@ -286,38 +317,33 @@ void EEVEE_renderpasses_postprocess(EEVEE_ViewLayerData *UNUSED(sldata), g_data->renderpass_input = txl->mist_accum; break; } - case EEVEE_RENDER_PASS_VOLUME_SCATTER: { + case EEVEE_RENDER_PASS_VOLUME_LIGHT: { g_data->renderpass_postprocess = PASS_POST_ACCUMULATED_COLOR; g_data->renderpass_input = txl->volume_scatter_accum; break; } - case EEVEE_RENDER_PASS_VOLUME_TRANSMITTANCE: { - g_data->renderpass_postprocess = PASS_POST_ACCUMULATED_COLOR; - g_data->renderpass_input = txl->volume_transmittance_accum; - break; - } case EEVEE_RENDER_PASS_SHADOW: { g_data->renderpass_postprocess = PASS_POST_ACCUMULATED_VALUE; g_data->renderpass_input = txl->shadow_accum; break; } case EEVEE_RENDER_PASS_DIFFUSE_COLOR: { - g_data->renderpass_postprocess = PASS_POST_ACCUMULATED_COLOR; + g_data->renderpass_postprocess = default_color_pass_type; g_data->renderpass_input = txl->diff_color_accum; break; } case EEVEE_RENDER_PASS_SPECULAR_COLOR: { - g_data->renderpass_postprocess = PASS_POST_ACCUMULATED_COLOR; + g_data->renderpass_postprocess = default_color_pass_type; g_data->renderpass_input = txl->spec_color_accum; break; } case EEVEE_RENDER_PASS_ENVIRONMENT: { - g_data->renderpass_postprocess = PASS_POST_ACCUMULATED_COLOR; + g_data->renderpass_postprocess = default_color_pass_type; g_data->renderpass_input = txl->env_accum; break; } case EEVEE_RENDER_PASS_EMIT: { - g_data->renderpass_postprocess = PASS_POST_ACCUMULATED_COLOR; + g_data->renderpass_postprocess = default_color_pass_type; g_data->renderpass_input = txl->emit_accum; break; } @@ -372,7 +398,8 @@ void EEVEE_renderpasses_output_accumulate(EEVEE_ViewLayerData *sldata, { EEVEE_StorageList *stl = vedata->stl; EEVEE_EffectsInfo *effects = stl->effects; - eViewLayerEEVEEPassType render_pass = stl->g_data->render_passes; + EEVEE_PrivateData *g_data = stl->g_data; + eViewLayerEEVEEPassType render_pass = g_data->render_passes; if (!post_effect) { if ((render_pass & EEVEE_RENDER_PASS_MIST) != 0) { @@ -387,8 +414,7 @@ void EEVEE_renderpasses_output_accumulate(EEVEE_ViewLayerData *sldata, if ((render_pass & EEVEE_RENDERPASSES_MATERIAL) != 0) { EEVEE_material_output_accumulate(sldata, vedata); } - if ((render_pass & - (EEVEE_RENDER_PASS_VOLUME_TRANSMITTANCE | EEVEE_RENDER_PASS_VOLUME_SCATTER)) != 0) { + if (eevee_renderpasses_volumetric_active(effects, g_data)) { EEVEE_volumes_output_accumulate(sldata, vedata); } if ((render_pass & EEVEE_RENDER_PASS_CRYPTOMATTE) != 0) { diff --git a/source/blender/draw/engines/eevee/shaders/renderpass_postprocess_frag.glsl b/source/blender/draw/engines/eevee/shaders/renderpass_postprocess_frag.glsl index eb6ca4b9de8..0bbbe58c44a 100644 --- a/source/blender/draw/engines/eevee/shaders/renderpass_postprocess_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/renderpass_postprocess_frag.glsl @@ -11,6 +11,7 @@ #define PASS_POST_AO 6 #define PASS_POST_NORMAL 7 #define PASS_POST_TWO_LIGHT_BUFFERS 8 +#define PASS_POST_ACCUMULATED_TRANSMITTANCE_COLOR 9 uniform int postProcessType; uniform int currentSample; @@ -19,6 +20,7 @@ uniform sampler2D depthBuffer; uniform sampler2D inputBuffer; uniform sampler2D inputSecondLightBuffer; uniform sampler2D inputColorBuffer; +uniform sampler2D inputTransmittanceBuffer; out vec4 fragColor; @@ -99,6 +101,11 @@ void main() vec4 accumulated_color = texelFetch(inputBuffer, texel, 0); color = (accumulated_color / currentSample); } + else if (postProcessType == PASS_POST_ACCUMULATED_TRANSMITTANCE_COLOR) { + vec3 accumulated_color = texelFetch(inputBuffer, texel, 0).rgb; + vec3 transmittance = texelFetch(inputTransmittanceBuffer, texel, 0).rgb; + color.rgb = (accumulated_color / currentSample) * (transmittance / currentSample); + } else if (postProcessType == PASS_POST_ACCUMULATED_LIGHT) { vec3 accumulated_light = texelFetch(inputBuffer, texel, 0).rgb; vec3 accumulated_color = texelFetch(inputColorBuffer, texel, 0).rgb; diff --git a/source/blender/makesdna/DNA_layer_types.h b/source/blender/makesdna/DNA_layer_types.h index 6a91f4857b4..828c6ff2a51 100644 --- a/source/blender/makesdna/DNA_layer_types.h +++ b/source/blender/makesdna/DNA_layer_types.h @@ -40,8 +40,8 @@ typedef enum eViewLayerEEVEEPassType { EEVEE_RENDER_PASS_DIFFUSE_COLOR = (1 << 5), EEVEE_RENDER_PASS_SPECULAR_LIGHT = (1 << 6), EEVEE_RENDER_PASS_SPECULAR_COLOR = (1 << 7), - EEVEE_RENDER_PASS_VOLUME_TRANSMITTANCE = (1 << 8), - EEVEE_RENDER_PASS_VOLUME_SCATTER = (1 << 9), + EEVEE_RENDER_PASS_UNUSED_8 = (1 << 8), + EEVEE_RENDER_PASS_VOLUME_LIGHT = (1 << 9), EEVEE_RENDER_PASS_EMIT = (1 << 10), EEVEE_RENDER_PASS_ENVIRONMENT = (1 << 11), EEVEE_RENDER_PASS_SHADOW = (1 << 12), diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 85ec3dfdced..06f7f7aafb4 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -323,8 +323,7 @@ typedef enum eScenePassType { #define RE_PASSNAME_FREESTYLE "Freestyle" #define RE_PASSNAME_BLOOM "BloomCol" -#define RE_PASSNAME_VOLUME_TRANSMITTANCE "VolumeTransmCol" -#define RE_PASSNAME_VOLUME_SCATTER "VolumeScatterCol" +#define RE_PASSNAME_VOLUME_LIGHT "VolumeDir" /* View - MultiView */ typedef struct SceneRenderView { diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index d418614d7a0..72c6fda86cd 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -3995,15 +3995,9 @@ static void rna_def_view_layer_eevee(BlenderRNA *brna) srna = RNA_def_struct(brna, "ViewLayerEEVEE", NULL); RNA_def_struct_ui_text(srna, "Eevee Settings", "View layer settings for Eevee"); - prop = RNA_def_property(srna, "use_pass_volume_scatter", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "render_passes", EEVEE_RENDER_PASS_VOLUME_SCATTER); - RNA_def_property_ui_text(prop, "Volume Scatter", "Deliver volume scattering pass"); - RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_ViewLayer_pass_update"); - - prop = RNA_def_property(srna, "use_pass_volume_transmittance", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna( - prop, NULL, "render_passes", EEVEE_RENDER_PASS_VOLUME_TRANSMITTANCE); - RNA_def_property_ui_text(prop, "Volume Transmittance", "Deliver volume transmittance pass"); + prop = RNA_def_property(srna, "use_pass_volume_direct", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "render_passes", EEVEE_RENDER_PASS_VOLUME_LIGHT); + RNA_def_property_ui_text(prop, "Volume Light", "Deliver volume direct light pass"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_ViewLayer_pass_update"); prop = RNA_def_property(srna, "use_pass_bloom", PROP_BOOLEAN, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index d0afebe5465..36dbb1c78cc 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -412,12 +412,7 @@ static const EnumPropertyItem rna_enum_view3dshading_render_pass_type_items[] = {EEVEE_RENDER_PASS_DIFFUSE_COLOR, "DIFFUSE_COLOR", 0, "Diffuse Color", ""}, {EEVEE_RENDER_PASS_SPECULAR_LIGHT, "SPECULAR_LIGHT", 0, "Specular Light", ""}, {EEVEE_RENDER_PASS_SPECULAR_COLOR, "SPECULAR_COLOR", 0, "Specular Color", ""}, - {EEVEE_RENDER_PASS_VOLUME_TRANSMITTANCE, - "VOLUME_TRANSMITTANCE", - 0, - "Volume Transmittance", - ""}, - {EEVEE_RENDER_PASS_VOLUME_SCATTER, "VOLUME_SCATTER", 0, "Volume Scattering", ""}, + {EEVEE_RENDER_PASS_VOLUME_LIGHT, "VOLUME_LIGHT", 0, "Volume Light", ""}, {0, "", ICON_NONE, "Effects", ""}, {EEVEE_RENDER_PASS_BLOOM, "BLOOM", 0, "Bloom", ""}, -- cgit v1.2.3 From 6327771bc968c14440eb30f971916cc913e77977 Mon Sep 17 00:00:00 2001 From: Antonio Vazquez Date: Mon, 14 Dec 2020 10:25:37 +0100 Subject: Fix T83696: Add Additional menu to Effects panel This adds the missing options for the effects as it is done in modifiers. Reviewed By: HooglyBoogly Maniphest Tasks: T83696 Differential Revision: https://developer.blender.org/D9838 --- source/blender/editors/object/object_intern.h | 1 + source/blender/editors/object/object_ops.c | 1 + source/blender/editors/object/object_shader_fx.c | 54 +++++++++++++++++++++++ source/blender/shader_fx/intern/FX_ui_common.c | 56 ++++++++++++++++++++++++ 4 files changed, 112 insertions(+) (limited to 'source/blender') diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h index e6ef53a3d65..89ade5cc49d 100644 --- a/source/blender/editors/object/object_intern.h +++ b/source/blender/editors/object/object_intern.h @@ -206,6 +206,7 @@ void OBJECT_OT_gpencil_modifier_copy(struct wmOperatorType *ot); /* object_shader_fx.c */ void OBJECT_OT_shaderfx_add(struct wmOperatorType *ot); +void OBJECT_OT_shaderfx_copy(struct wmOperatorType *ot); void OBJECT_OT_shaderfx_remove(struct wmOperatorType *ot); void OBJECT_OT_shaderfx_move_up(struct wmOperatorType *ot); void OBJECT_OT_shaderfx_move_down(struct wmOperatorType *ot); diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c index 8ba0ce5fd08..2e5a75ffa7d 100644 --- a/source/blender/editors/object/object_ops.c +++ b/source/blender/editors/object/object_ops.c @@ -166,6 +166,7 @@ void ED_operatortypes_object(void) WM_operatortype_append(OBJECT_OT_shaderfx_move_up); WM_operatortype_append(OBJECT_OT_shaderfx_move_down); WM_operatortype_append(OBJECT_OT_shaderfx_move_to_index); + WM_operatortype_append(OBJECT_OT_shaderfx_copy); WM_operatortype_append(OBJECT_OT_correctivesmooth_bind); WM_operatortype_append(OBJECT_OT_meshdeform_bind); diff --git a/source/blender/editors/object/object_shader_fx.c b/source/blender/editors/object/object_shader_fx.c index c5caee5ba08..2b1ac08ec2e 100644 --- a/source/blender/editors/object/object_shader_fx.c +++ b/source/blender/editors/object/object_shader_fx.c @@ -640,3 +640,57 @@ void OBJECT_OT_shaderfx_move_to_index(wmOperatorType *ot) RNA_def_int( ot->srna, "index", 0, 0, INT_MAX, "Index", "The index to move the effect to", 0, INT_MAX); } + +/************************ copy shader operator *********************/ + +static int shaderfx_copy_exec(bContext *C, wmOperator *op) +{ + Object *ob = ED_object_active_context(C); + ShaderFxData *fx = edit_shaderfx_property_get(op, ob, 0); + + ShaderFxData *nfx = BKE_shaderfx_new(fx->type); + if (!nfx) { + return OPERATOR_CANCELLED; + } + + BLI_strncpy(nfx->name, fx->name, sizeof(nfx->name)); + /* Make sure effect data has unique name. */ + BKE_shaderfx_unique_name(&ob->shader_fx, nfx); + + BKE_shaderfx_copydata(fx, nfx); + BLI_insertlinkafter(&ob->shader_fx, fx, nfx); + + DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); + WM_main_add_notifier(NC_OBJECT | ND_SHADERFX, ob); + + return OPERATOR_FINISHED; +} + +static int shaderfx_copy_invoke(bContext *C, wmOperator *op, const wmEvent *event) +{ + int retval; + if (edit_shaderfx_invoke_properties(C, op, event, &retval)) { + return shaderfx_copy_exec(C, op); + } + return retval; +} + +static bool shaderfx_copy_poll(bContext *C) +{ + return edit_shaderfx_poll_generic(C, &RNA_ShaderFx, 0); +} + +void OBJECT_OT_shaderfx_copy(wmOperatorType *ot) +{ + ot->name = "Copy Effect"; + ot->description = "Duplicate effect at the same position in the stack"; + ot->idname = "OBJECT_OT_shaderfx_copy"; + + ot->invoke = shaderfx_copy_invoke; + ot->exec = shaderfx_copy_exec; + ot->poll = shaderfx_copy_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; + edit_shaderfx_properties(ot); +} diff --git a/source/blender/shader_fx/intern/FX_ui_common.c b/source/blender/shader_fx/intern/FX_ui_common.c index c1e3b2e21cd..9a86e1e96f5 100644 --- a/source/blender/shader_fx/intern/FX_ui_common.c +++ b/source/blender/shader_fx/intern/FX_ui_common.c @@ -124,6 +124,59 @@ PointerRNA *shaderfx_panel_get_property_pointers(Panel *panel, PointerRNA *r_ob_ #define ERROR_LIBDATA_MESSAGE TIP_("External library data") +static void gpencil_shaderfx_ops_extra_draw(bContext *C, uiLayout *layout, void *fx_v) +{ + PointerRNA op_ptr; + uiLayout *row; + ShaderFxData *fx = (ShaderFxData *)fx_v; + + PointerRNA ptr; + Object *ob = ED_object_active_context(C); + RNA_pointer_create(&ob->id, &RNA_ShaderFx, fx, &ptr); + uiLayoutSetContextPointer(layout, "shaderfx", &ptr); + uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT); + + uiLayoutSetUnitsX(layout, 4.0f); + + /* Duplicate. */ + uiItemO(layout, + CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Duplicate"), + ICON_DUPLICATE, + "OBJECT_OT_shaderfx_copy"); + + uiItemS(layout); + + /* Move to first. */ + row = uiLayoutColumn(layout, false); + uiItemFullO(row, + "OBJECT_OT_shaderfx_move_to_index", + IFACE_("Move to First"), + ICON_TRIA_UP, + NULL, + WM_OP_INVOKE_DEFAULT, + 0, + &op_ptr); + RNA_int_set(&op_ptr, "index", 0); + if (!fx->prev) { + uiLayoutSetEnabled(row, false); + } + + /* Move to last. */ + row = uiLayoutColumn(layout, false); + uiItemFullO(row, + "OBJECT_OT_shaderfx_move_to_index", + IFACE_("Move to Last"), + ICON_TRIA_DOWN, + NULL, + WM_OP_INVOKE_DEFAULT, + 0, + &op_ptr); + RNA_int_set(&op_ptr, "index", BLI_listbase_count(&ob->shader_fx) - 1); + if (!fx->next) { + uiLayoutSetEnabled(row, false); + } +} + static void shaderfx_panel_header(const bContext *UNUSED(C), Panel *panel) { uiLayout *layout = panel->layout; @@ -159,6 +212,9 @@ static void shaderfx_panel_header(const bContext *UNUSED(C), Panel *panel) uiItemR(row, ptr, "show_viewport", 0, "", ICON_NONE); uiItemR(row, ptr, "show_render", 0, "", ICON_NONE); + /* Extra operators. */ + uiItemMenuF(row, "", ICON_DOWNARROW_HLT, gpencil_shaderfx_ops_extra_draw, fx); + row = uiLayoutRow(row, false); uiLayoutSetEmboss(row, UI_EMBOSS_NONE); uiItemO(row, "", ICON_X, "OBJECT_OT_shaderfx_remove"); -- cgit v1.2.3 From 7d4536cacc82247da3b1c34eaea13986e151dd4b Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 14 Dec 2020 20:41:02 +1100 Subject: Fix enum-conversion, old-style-declaration warnings Introduced in 8f3a401975987c9b70f3ea0ea21977c70371b466 --- source/blender/blenloader/intern/versioning_290.c | 2 +- source/blender/draw/engines/eevee/eevee_renderpasses.c | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenloader/intern/versioning_290.c b/source/blender/blenloader/intern/versioning_290.c index fe22558eb06..4e642258899 100644 --- a/source/blender/blenloader/intern/versioning_290.c +++ b/source/blender/blenloader/intern/versioning_290.c @@ -1271,7 +1271,7 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain) LISTBASE_FOREACH (bNode *, node, &scene->nodetree->nodes) { if (node->type == CMP_NODE_R_LAYERS) { LISTBASE_FOREACH (bNodeSocket *, output_socket, &node->outputs) { - const static char *volume_scatter = "VolumeScatterCol"; + const char *volume_scatter = "VolumeScatterCol"; if (STREQLEN(output_socket->name, volume_scatter, MAX_NAME)) { BLI_strncpy(output_socket->name, RE_PASSNAME_VOLUME_LIGHT, MAX_NAME); } diff --git a/source/blender/draw/engines/eevee/eevee_renderpasses.c b/source/blender/draw/engines/eevee/eevee_renderpasses.c index 6f87ff302f4..dff3b437953 100644 --- a/source/blender/draw/engines/eevee/eevee_renderpasses.c +++ b/source/blender/draw/engines/eevee/eevee_renderpasses.c @@ -283,9 +283,8 @@ void EEVEE_renderpasses_postprocess(EEVEE_ViewLayerData *UNUSED(sldata), g_data->renderpass_type = renderpass_type; g_data->renderpass_postprocess = PASS_POST_UNDEFINED; const bool volumetric_active = eevee_renderpasses_volumetric_active(effects, g_data); - eViewLayerEEVEEPassType default_color_pass_type = volumetric_active ? - PASS_POST_ACCUMULATED_TRANSMITTANCE_COLOR : - PASS_POST_ACCUMULATED_COLOR; + eRenderPassPostProcessType default_color_pass_type = + volumetric_active ? PASS_POST_ACCUMULATED_TRANSMITTANCE_COLOR : PASS_POST_ACCUMULATED_COLOR; g_data->renderpass_transmittance_input = volumetric_active ? txl->volume_transmittance_accum : txl->color; -- cgit v1.2.3 From b8ae90263a9b480efd9da79968f6ce7b61a0808b Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 14 Dec 2020 18:16:53 +1100 Subject: Fix version patching sequence strip alpha from 2.4x files Regression in 4f5f868a523430aa41de8bd63f888878aaf63002 --- source/blender/blenkernel/intern/ipo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c index 6a852df95c6..2344adf7af9 100644 --- a/source/blender/blenkernel/intern/ipo.c +++ b/source/blender/blenkernel/intern/ipo.c @@ -1118,7 +1118,7 @@ static char *get_rna_access(ID *id, propname = "speed_fader"; break; case SEQ_FAC_OPACITY: - propname = "blend_opacity"; + propname = "blend_alpha"; break; } /* XXX this doesn't seem to be included anywhere in sequencer RNA... */ -- cgit v1.2.3 From 088df2bb03f3e8620cab9e466272850a03db5cc8 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 14 Dec 2020 18:44:04 +1100 Subject: Fix missing string escape for RNA path creation --- source/blender/blenkernel/intern/ipo.c | 23 +++++++++++++++++----- source/blender/blenkernel/intern/object.c | 21 ++++++++++++++------ source/blender/blenloader/intern/versioning_270.c | 4 +++- .../blender/blenloader/intern/versioning_cycles.c | 15 +++++++++----- source/blender/draw/intern/draw_instance_data.c | 10 +++++++--- source/blender/io/collada/AnimationImporter.cpp | 5 ++++- source/blender/io/collada/ArmatureImporter.cpp | 4 +++- source/blender/io/collada/collada_utils.cpp | 4 +++- source/blender/makesrna/intern/rna_gpencil.c | 10 +++++----- source/blender/makesrna/intern/rna_scene.c | 4 +++- source/blender/makesrna/intern/rna_sequencer.c | 5 ++++- source/blender/modifiers/intern/MOD_nodes.cc | 8 ++++++-- 12 files changed, 81 insertions(+), 32 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c index 2344adf7af9..0e611b21304 100644 --- a/source/blender/blenkernel/intern/ipo.c +++ b/source/blender/blenkernel/intern/ipo.c @@ -467,7 +467,9 @@ static char *shapekey_adrcodes_to_paths(ID *id, int adrcode, int *UNUSED(array_i /* setting that we alter is the "value" (i.e. keyblock.curval) */ if (kb) { /* Use the keyblock name, escaped, so that path lookups for this will work */ - BLI_snprintf(buf, sizeof(buf), "key_blocks[\"%s\"].value", kb->name); + char kb_name_esc[sizeof(kb->name) * 2]; + BLI_str_escape(kb_name_esc, kb->name, sizeof(kb_name_esc)); + BLI_snprintf(buf, sizeof(buf), "key_blocks[\"%s\"].value", kb_name_esc); } else { /* Fallback - Use the adrcode as index directly, so that this can be manually fixed */ @@ -1160,7 +1162,12 @@ static char *get_rna_access(ID *id, /* note, strings are not escapted and they should be! */ if ((actname && actname[0]) && (constname && constname[0])) { /* Constraint in Pose-Channel */ - BLI_snprintf(buf, sizeof(buf), "pose.bones[\"%s\"].constraints[\"%s\"]", actname, constname); + char actname_esc[sizeof(((bActionChannel *)NULL)->name) * 2]; + char constname_esc[sizeof(((bConstraint *)NULL)->name) * 2]; + BLI_str_escape(actname_esc, actname, sizeof(actname_esc)); + BLI_str_escape(constname_esc, constname, sizeof(constname_esc)); + BLI_snprintf( + buf, sizeof(buf), "pose.bones[\"%s\"].constraints[\"%s\"]", actname_esc, constname_esc); } else if (actname && actname[0]) { if ((blocktype == ID_OB) && STREQ(actname, "Object")) { @@ -1174,16 +1181,22 @@ static char *get_rna_access(ID *id, } else { /* Pose-Channel */ - BLI_snprintf(buf, sizeof(buf), "pose.bones[\"%s\"]", actname); + char actname_esc[sizeof(((bActionChannel *)NULL)->name) * 2]; + BLI_str_escape(actname_esc, actname, sizeof(actname_esc)); + BLI_snprintf(buf, sizeof(buf), "pose.bones[\"%s\"]", actname_esc); } } else if (constname && constname[0]) { /* Constraint in Object */ - BLI_snprintf(buf, sizeof(buf), "constraints[\"%s\"]", constname); + char constname_esc[sizeof(((bConstraint *)NULL)->name) * 2]; + BLI_str_escape(constname_esc, constname, sizeof(constname_esc)); + BLI_snprintf(buf, sizeof(buf), "constraints[\"%s\"]", constname_esc); } else if (seq) { /* Sequence names in Scene */ - BLI_snprintf(buf, sizeof(buf), "sequence_editor.sequences_all[\"%s\"]", seq->name + 2); + char seq_name_esc[(sizeof(seq->name) - 2) * 2]; + BLI_str_escape(seq_name_esc, seq->name + 2, sizeof(seq_name_esc)); + BLI_snprintf(buf, sizeof(buf), "sequence_editor.sequences_all[\"%s\"]", seq_name_esc); } else { buf[0] = '\0'; /* empty string */ diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 88a604a7b62..bdb907df1ac 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -5217,8 +5217,11 @@ bool BKE_object_modifier_use_time(Object *ob, ModifierData *md) AnimData *adt = ob->adt; FCurve *fcu; - char pattern[MAX_NAME + 16]; - BLI_snprintf(pattern, sizeof(pattern), "modifiers[\"%s\"]", md->name); + char md_name_esc[sizeof(md->name) * 2]; + BLI_str_escape(md_name_esc, md->name, sizeof(md_name_esc)); + + char pattern[sizeof(md_name_esc) + 16]; + BLI_snprintf(pattern, sizeof(pattern), "modifiers[\"%s\"]", md_name_esc); /* action - check for F-Curves with paths containing 'modifiers[' */ if (adt->action) { @@ -5260,8 +5263,11 @@ bool BKE_object_modifier_gpencil_use_time(Object *ob, GpencilModifierData *md) AnimData *adt = ob->adt; FCurve *fcu; - char pattern[MAX_NAME + 32]; - BLI_snprintf(pattern, sizeof(pattern), "grease_pencil_modifiers[\"%s\"]", md->name); + char md_name_esc[sizeof(md->name) * 2]; + BLI_str_escape(md_name_esc, md->name, sizeof(md_name_esc)); + + char pattern[sizeof(md_name_esc) + 32]; + BLI_snprintf(pattern, sizeof(pattern), "grease_pencil_modifiers[\"%s\"]", md_name_esc); /* action - check for F-Curves with paths containing 'grease_pencil_modifiers[' */ if (adt->action) { @@ -5295,8 +5301,11 @@ bool BKE_object_shaderfx_use_time(Object *ob, ShaderFxData *fx) AnimData *adt = ob->adt; FCurve *fcu; - char pattern[MAX_NAME + 32]; - BLI_snprintf(pattern, sizeof(pattern), "shader_effects[\"%s\"]", fx->name); + char fx_name_esc[sizeof(fx->name) * 2]; + BLI_str_escape(fx_name_esc, fx->name, sizeof(fx_name_esc)); + + char pattern[sizeof(fx_name_esc) + 32]; + BLI_snprintf(pattern, sizeof(pattern), "shader_effects[\"%s\"]", fx_name_esc); /* action - check for F-Curves with paths containing string[' */ if (adt->action) { diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c index adc2b55b350..b07d1ea66b1 100644 --- a/source/blender/blenloader/intern/versioning_270.c +++ b/source/blender/blenloader/intern/versioning_270.c @@ -301,7 +301,9 @@ static void do_version_hue_sat_node(bNodeTree *ntree, bNode *node) /* Take care of possible animation. */ AnimData *adt = BKE_animdata_from_id(&ntree->id); if (adt != NULL && adt->action != NULL) { - const char *prefix = BLI_sprintfN("nodes[\"%s\"]", node->name); + char node_name_esc[sizeof(node->name) * 2]; + BLI_str_escape(node_name_esc, node->name, sizeof(node_name_esc)); + const char *prefix = BLI_sprintfN("nodes[\"%s\"]", node_name_esc); for (FCurve *fcu = adt->action->curves.first; fcu != NULL; fcu = fcu->next) { if (STRPREFIX(fcu->rna_path, prefix)) { anim_change_prop_name(fcu, prefix, "color_hue", "inputs[1].default_value"); diff --git a/source/blender/blenloader/intern/versioning_cycles.c b/source/blender/blenloader/intern/versioning_cycles.c index 19e392734f0..631abe10ddc 100644 --- a/source/blender/blenloader/intern/versioning_cycles.c +++ b/source/blender/blenloader/intern/versioning_cycles.c @@ -840,12 +840,14 @@ static void update_mapping_node_fcurve_rna_path_callback(ID *UNUSED(id), fcurve->rna_path = BLI_sprintfN("%s.%s", data->nodePath, "inputs[3].default_value"); } else if (data->minimumNode && BLI_str_endswith(old_fcurve_rna_path, "max")) { - fcurve->rna_path = BLI_sprintfN( - "nodes[\"%s\"].%s", data->minimumNode->name, "inputs[1].default_value"); + char node_name_esc[sizeof(data->minimumNode->name) * 2]; + BLI_str_escape(node_name_esc, data->minimumNode->name, sizeof(node_name_esc)); + fcurve->rna_path = BLI_sprintfN("nodes[\"%s\"].%s", node_name_esc, "inputs[1].default_value"); } else if (data->maximumNode && BLI_str_endswith(old_fcurve_rna_path, "min")) { - fcurve->rna_path = BLI_sprintfN( - "nodes[\"%s\"].%s", data->maximumNode->name, "inputs[1].default_value"); + char node_name_esc[sizeof(data->maximumNode->name) * 2]; + BLI_str_escape(node_name_esc, data->maximumNode->name, sizeof(node_name_esc)); + fcurve->rna_path = BLI_sprintfN("nodes[\"%s\"].%s", node_name_esc, "inputs[1].default_value"); } if (fcurve->rna_path != old_fcurve_rna_path) { @@ -955,7 +957,10 @@ static void update_mapping_node_inputs_and_properties(bNodeTree *ntree) MEM_freeN(node->storage); node->storage = NULL; - char *nodePath = BLI_sprintfN("nodes[\"%s\"]", node->name); + char node_name_esc[sizeof(node->name) * 2]; + BLI_str_escape(node_name_esc, node->name, sizeof(node_name_esc)); + + char *nodePath = BLI_sprintfN("nodes[\"%s\"]", node_name_esc); MappingNodeFCurveCallbackData data = {nodePath, minimumNode, maximumNode}; BKE_fcurves_id_cb(&ntree->id, update_mapping_node_fcurve_rna_path_callback, &data); MEM_freeN(nodePath); diff --git a/source/blender/draw/intern/draw_instance_data.c b/source/blender/draw/intern/draw_instance_data.c index f1598ea2fff..ba03cee8149 100644 --- a/source/blender/draw/intern/draw_instance_data.c +++ b/source/blender/draw/intern/draw_instance_data.c @@ -669,10 +669,14 @@ static void drw_uniform_attribute_lookup(GPUUniformAttr *attr, DupliObject *dupli_source, float r_data[4]) { - char idprop_name[sizeof(attr->name) + 4]; - copy_v4_fl(r_data, 0); - sprintf(idprop_name, "[\"%s\"]", attr->name); + + char idprop_name[(sizeof(attr->name) * 2) + 4]; + { + char attr_name_esc[sizeof(attr->name) * 2]; + BLI_str_escape(attr_name_esc, attr->name, sizeof(attr_name_esc)); + SNPRINTF(idprop_name, "[\"%s\"]", attr_name_esc); + } /* If requesting instance data, check the parent particle system and object. */ if (attr->use_dupli) { diff --git a/source/blender/io/collada/AnimationImporter.cpp b/source/blender/io/collada/AnimationImporter.cpp index 77ccdeae28d..9f54bf2aa28 100644 --- a/source/blender/io/collada/AnimationImporter.cpp +++ b/source/blender/io/collada/AnimationImporter.cpp @@ -385,7 +385,10 @@ virtual void AnimationImporter::change_eul_to_quat(Object *ob, bAction *act) char joint_path[100]; char rna_path[100]; - BLI_snprintf(joint_path, sizeof(joint_path), "pose.bones[\"%s\"]", grp->name); + char grp_name_esc[sizeof(grp->name) * 2]; + BLI_str_escape(grp_name_esc, grp->name, sizeof(grp_name_esc)); + + BLI_snprintf(joint_path, sizeof(joint_path), "pose.bones[\"%s\"]", grp_name_esc); BLI_snprintf(rna_path, sizeof(rna_path), "%s.rotation_quaternion", joint_path); FCurve *quatcu[4] = { diff --git a/source/blender/io/collada/ArmatureImporter.cpp b/source/blender/io/collada/ArmatureImporter.cpp index 9533ca322f9..56716722b46 100644 --- a/source/blender/io/collada/ArmatureImporter.cpp +++ b/source/blender/io/collada/ArmatureImporter.cpp @@ -1037,7 +1037,9 @@ void ArmatureImporter::get_rna_path_for_joint(COLLADAFW::Node *node, char *joint_path, size_t count) { - BLI_snprintf(joint_path, count, "pose.bones[\"%s\"]", bc_get_joint_name(node)); + char bone_name_esc[sizeof(((Bone *)NULL)->name) * 2]; + BLI_str_escape(bone_name_esc, bc_get_joint_name(node), sizeof(bone_name_esc)); + BLI_snprintf(joint_path, count, "pose.bones[\"%s\"]", bone_name_esc); } /* gives a world-space mat */ diff --git a/source/blender/io/collada/collada_utils.cpp b/source/blender/io/collada/collada_utils.cpp index ad1cc1035fb..3c68de70248 100644 --- a/source/blender/io/collada/collada_utils.cpp +++ b/source/blender/io/collada/collada_utils.cpp @@ -832,7 +832,9 @@ void bc_enable_fcurves(bAction *act, char *bone_name) char prefix[200]; if (bone_name) { - BLI_snprintf(prefix, sizeof(prefix), "pose.bones[\"%s\"]", bone_name); + char bone_name_esc[sizeof(((Bone *)NULL)->name) * 2]; + BLI_str_escape(bone_name_esc, bone_name, sizeof(bone_name_esc)); + BLI_snprintf(prefix, sizeof(prefix), "pose.bones[\"%s\"]", bone_name_esc); } for (fcu = (FCurve *)act->curves.first; fcu; fcu = fcu->next) { diff --git a/source/blender/makesrna/intern/rna_gpencil.c b/source/blender/makesrna/intern/rna_gpencil.c index 7be9d14b1d1..72e11838fac 100644 --- a/source/blender/makesrna/intern/rna_gpencil.c +++ b/source/blender/makesrna/intern/rna_gpencil.c @@ -403,13 +403,13 @@ static char *rna_GPencilLayerMask_path(PointerRNA *ptr) bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd); bGPDlayer_Mask *mask = (bGPDlayer_Mask *)ptr->data; - char name_layer[sizeof(gpl->info) * 2]; - char name_mask[sizeof(mask->name) * 2]; + char gpl_info_esc[sizeof(gpl->info) * 2]; + char mask_name_esc[sizeof(mask->name) * 2]; - BLI_str_escape(name_layer, gpl->info, sizeof(name_layer)); - BLI_str_escape(name_mask, mask->name, sizeof(name_mask)); + BLI_str_escape(gpl_info_esc, gpl->info, sizeof(gpl_info_esc)); + BLI_str_escape(mask_name_esc, mask->name, sizeof(mask_name_esc)); - return BLI_sprintfN("layers[\"%s\"].mask_layers[\"%s\"]", name_layer, name_mask); + return BLI_sprintfN("layers[\"%s\"].mask_layers[\"%s\"]", gpl_info_esc, mask_name_esc); } static int rna_GPencil_active_mask_index_get(PointerRNA *ptr) diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 72c6fda86cd..e149bb4ecad 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -1812,7 +1812,9 @@ void rna_ViewLayer_pass_update(Main *bmain, Scene *activescene, PointerRNA *ptr) static char *rna_SceneRenderView_path(PointerRNA *ptr) { SceneRenderView *srv = (SceneRenderView *)ptr->data; - return BLI_sprintfN("render.views[\"%s\"]", srv->name); + char srv_name_esc[sizeof(srv->name) * 2]; + BLI_str_escape(srv_name_esc, srv->name, sizeof(srv_name_esc)); + return BLI_sprintfN("render.views[\"%s\"]", srv_name_esc); } static void rna_Scene_use_nodes_update(bContext *C, PointerRNA *ptr) diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c index 9e7fbf2f9a9..eea6fd88ec7 100644 --- a/source/blender/makesrna/intern/rna_sequencer.c +++ b/source/blender/makesrna/intern/rna_sequencer.c @@ -1201,8 +1201,11 @@ static void rna_SequenceModifier_name_set(PointerRNA *ptr, const char *value) if (adt) { char path[1024]; + char seq_name_esc[(sizeof(seq->name) - 2) * 2]; + BLI_str_escape(seq_name_esc, seq->name + 2, sizeof(seq_name_esc)); + BLI_snprintf( - path, sizeof(path), "sequence_editor.sequences_all[\"%s\"].modifiers", seq->name + 2); + path, sizeof(path), "sequence_editor.sequences_all[\"%s\"].modifiers", seq_name_esc); BKE_animdata_fix_paths_rename(&scene->id, adt, NULL, path, oldname, smd->name, 0, 0, 1); } } diff --git a/source/blender/modifiers/intern/MOD_nodes.cc b/source/blender/modifiers/intern/MOD_nodes.cc index 513e16e1a89..6730ce1c8a8 100644 --- a/source/blender/modifiers/intern/MOD_nodes.cc +++ b/source/blender/modifiers/intern/MOD_nodes.cc @@ -976,8 +976,12 @@ static void draw_property_for_socket(uiLayout *layout, /* IDProperties can be removed with python, so there could be a situation where * there isn't a property for a socket or it doesn't have the correct type. */ if (property != nullptr && property_type->is_correct_type(*property)) { - char rna_path[128]; - BLI_snprintf(rna_path, ARRAY_SIZE(rna_path), "[\"%s\"]", socket.identifier); + + char socket_id_esc[sizeof(socket.identifier) * 2]; + BLI_str_escape(socket_id_esc, socket.identifier, sizeof(socket_id_esc)); + + char rna_path[sizeof(socket_id_esc) + 4]; + BLI_snprintf(rna_path, ARRAY_SIZE(rna_path), "[\"%s\"]", socket_id_esc); uiItemR(layout, settings_ptr, rna_path, 0, socket.name, ICON_NONE); } } -- cgit v1.2.3 From 067046c26aaaf455c0c46470e81ac006671b8daa Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 14 Dec 2020 19:04:43 +1100 Subject: Cleanup: path_util.c comments --- source/blender/blenlib/intern/path_util.c | 79 +++++++++++++++---------------- 1 file changed, 39 insertions(+), 40 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c index 927318a923e..5636ffafb6a 100644 --- a/source/blender/blenlib/intern/path_util.c +++ b/source/blender/blenlib/intern/path_util.c @@ -288,7 +288,7 @@ void BLI_path_normalize_dir(const char *relabase, char *dir) * (good practice anyway). * REMOVED based on popular demand (see T45900). * Percent '%' char is a bit same case - not recommended to use it, - * but supported by all decent FS/OS around. + * but supported by all decent file-systems/operating-systems around. * * \note On Windows, it also ensures there is no '.' (dot char) at the end of the file, * this can lead to issues. @@ -513,8 +513,8 @@ void BLI_path_normalize_unc_16(wchar_t *path_16) #endif /** - * Replaces *file with a relative version (prefixed by "//") such that BLI_path_abs, given - * the same *relfile, will convert it back to its original value. + * Replaces `file` with a relative version (prefixed by "//") such that #BLI_path_abs, given + * the same `relfile`, will convert it back to its original value. */ void BLI_path_rel(char *file, const char *relfile) { @@ -664,7 +664,7 @@ void BLI_path_rel(char *file, const char *relfile) * \param maxlen: Maximum length of string * \param suffix: String to append to the original string * \param sep: Optional separator character - * \return true if succeeded + * \return true if succeeded */ bool BLI_path_suffix(char *string, size_t maxlen, const char *suffix, const char *sep) { @@ -703,7 +703,7 @@ bool BLI_path_suffix(char *string, size_t maxlen, const char *suffix, const char /** * Replaces path with the path of its parent directory, returning true if - * it was able to find a parent directory within the pathname. + * it was able to find a parent directory within the path. */ bool BLI_path_parent_dir(char *path) { @@ -722,7 +722,7 @@ bool BLI_path_parent_dir(char *path) } /** - * Strips off nonexistent (or non-accessible) subdirectories from the end of *dir, + * Strips off nonexistent (or non-accessible) sub-directories from the end of `dir`, * leaving the path of the lowest-level directory that does exist and we can read. */ bool BLI_path_parent_dir_until_exists(char *dir) @@ -737,9 +737,9 @@ bool BLI_path_parent_dir_until_exists(char *dir) } /** - * Looks for a sequence of "#" characters in the last slash-separated component of *path, + * Looks for a sequence of "#" characters in the last slash-separated component of `path`, * returning the indexes of the first and one past the last character in the sequence in - * *char_start and *char_end respectively. Returns true if such a sequence was found. + * `char_start` and `char_end` respectively. Returns true if such a sequence was found. */ static bool stringframe_chars(const char *path, int *char_start, int *char_end) { @@ -774,7 +774,7 @@ static bool stringframe_chars(const char *path, int *char_start, int *char_end) } /** - * Ensure *path contains at least one "#" character in its last slash-separated + * Ensure `path` contains at least one "#" character in its last slash-separated * component, appending one digits long if not. */ static void ensure_digits(char *path, int digits) @@ -796,7 +796,7 @@ static void ensure_digits(char *path, int digits) } /** - * Replaces "#" character sequence in last slash-separated component of *path + * Replaces "#" character sequence in last slash-separated component of `path` * with frame as decimal integer, with leading zeroes as necessary, to make digits digits. */ bool BLI_path_frame(char *path, int frame, int digits) @@ -818,7 +818,7 @@ bool BLI_path_frame(char *path, int frame, int digits) } /** - * Replaces "#" character sequence in last slash-separated component of *path + * Replaces "#" character sequence in last slash-separated component of `path` * with sta and end as decimal integers, with leading zeroes as necessary, to make digits * digits each, with a hyphen in-between. */ @@ -963,7 +963,7 @@ bool BLI_path_frame_check_chars(const char *path) /** * Creates a display string from path to be used menus and the user interface. - * Like bpy.path.display_name(). + * Like `bpy.path.display_name()`. */ void BLI_path_to_display_name(char *display_name, int maxlen, const char *name) { @@ -1004,7 +1004,7 @@ void BLI_path_to_display_name(char *display_name, int maxlen, const char *name) } /** - * If path begins with "//", strips that and replaces it with basepath directory. + * If path begins with "//", strips that and replaces it with `basepath` directory. * * \note Also converts drive-letter prefix to something more sensible * if this is a non-drive-letter-based system. @@ -1162,7 +1162,7 @@ bool BLI_path_abs_from_cwd(char *path, const size_t maxlen) #ifdef _WIN32 /** * Tries appending each of the semicolon-separated extensions in the PATHEXT - * environment variable (Windows-only) onto *name in turn until such a file is found. + * environment variable (Windows-only) onto `name` in turn until such a file is found. * Returns success/failure. */ bool BLI_path_program_extensions_add_win32(char *name, const size_t maxlen) @@ -1269,7 +1269,7 @@ bool BLI_path_program_search(char *fullname, const size_t maxlen, const char *na /** * Sets the specified environment variable to the specified value, - * and clears it if val == NULL. + * and clears it if `val == NULL`. */ void BLI_setenv(const char *env, const char *val) { @@ -1305,27 +1305,27 @@ void BLI_setenv_if_new(const char *env, const char *val) /** * Get an env var, result has to be used immediately. * - * On windows getenv gets its variables from a static copy of the environment variables taken at + * On windows #getenv gets its variables from a static copy of the environment variables taken at * process start-up, causing it to not pick up on environment variables created during runtime. * This function uses an alternative method to get environment variables that does pick up on * runtime environment variables. The result will be UTF-8 encoded. */ - const char *BLI_getenv(const char *env) { #ifdef _MSC_VER const char *result = NULL; - static wchar_t buffer[32768]; /* 32767 is the maximum size of the environment variable on - windows, reserve one more character for the zero terminator. */ + /* 32767 is the maximum size of the environment variable on windows, + * reserve one more character for the zero terminator. */ + static wchar_t buffer[32768]; wchar_t *env_16 = alloc_utf16_from_8(env, 0); if (env_16) { if (GetEnvironmentVariableW(env_16, buffer, ARRAY_SIZE(buffer))) { char *res_utf8 = alloc_utf_8_from_16(buffer, 0); - // make sure the result is valid, and will fit into our temporary storage buffer + /* Make sure the result is valid, and will fit into our temporary storage buffer. */ if (res_utf8) { if (strlen(res_utf8) + 1 < sizeof(buffer)) { - // We are re-using the utf16 buffer here, since allocating a second static buffer to - // contain the UTF-8 version to return would be wasteful. + /* We are re-using the utf16 buffer here, since allocating a second static buffer to + * contain the UTF-8 version to return would be wasteful. */ memcpy(buffer, res_utf8, strlen(res_utf8) + 1); result = (const char *)buffer; } @@ -1340,9 +1340,9 @@ const char *BLI_getenv(const char *env) } /** - * Ensures that the parent directory of *name exists. + * Ensures that the parent directory of `name` exists. * - * \return true on success (i.e. given path now exists on FS), false otherwise. + * \return true on success (i.e. given path now exists on file-system), false otherwise. */ bool BLI_make_existing_file(const char *name) { @@ -1354,13 +1354,13 @@ bool BLI_make_existing_file(const char *name) } /** - * Returns in *string the concatenation of *dir and *file (also with *relabase on the - * front if specified and *dir begins with "//"). Normalizes all occurrences of path - * separators, including ensuring there is exactly one between the copies of *dir and *file, - * and between the copies of *relabase and *dir. + * Returns in `string` the concatenation of `dir` and `file` (also with `relabase` on the + * front if specified and `dir` begins with "//"). Normalizes all occurrences of path + * separators, including ensuring there is exactly one between the copies of `dir` and `file`, + * and between the copies of `relabase` and `dir`. * - * \param relabase: Optional prefix to substitute for "//" on front of *dir - * \param string: Area to return result + * \param relabase: Optional prefix to substitute for "//" on front of `dir`. + * \param string: Area to return result. */ void BLI_make_file_string(const char *relabase, char *string, const char *dir, const char *file) { @@ -1500,9 +1500,8 @@ bool BLI_path_extension_check_array(const char *str, const char **ext_array) } /** - * Semicolon separated wildcards, eg: - * '*.zip;*.py;*.exe' - * does str match any of the semicolon-separated glob patterns in fnmatch. + * Semicolon separated wildcards, eg: `*.zip;*.py;*.exe` + * does str match any of the semicolon-separated glob patterns in #fnmatch. */ bool BLI_path_extension_check_glob(const char *str, const char *ext_fnmatch) { @@ -1535,7 +1534,7 @@ bool BLI_path_extension_check_glob(const char *str, const char *ext_fnmatch) * truncation. * * For now, only forbids last group to be a wildcard-only one, if there are more than one group - * (i.e. things like "*.txt;*.cpp;*" are changed to "*.txt;*.cpp;") + * (i.e. things like `*.txt;*.cpp;*` are changed to `*.txt;*.cpp;`) * * \returns true if it had to modify given \a ext_fnmatch pattern. */ @@ -1645,7 +1644,7 @@ bool BLI_path_filename_ensure(char *filepath, size_t maxlen, const char *filenam } /** - * Converts `/foo/bar.txt` to "/foo/" and `bar.txt` + * Converts `/foo/bar.txt` to `/foo/` and `bar.txt` * * - Wont change \a string. * - Wont create any directories. @@ -1678,7 +1677,7 @@ void BLI_split_dirfile( } /** - * Copies the parent directory part of string into *dir, max length dirlen. + * Copies the parent directory part of string into `dir`, max length `dirlen`. */ void BLI_split_dir_part(const char *string, char *dir, const size_t dirlen) { @@ -1686,7 +1685,7 @@ void BLI_split_dir_part(const char *string, char *dir, const size_t dirlen) } /** - * Copies the leaf filename part of string into *file, max length filelen. + * Copies the leaf filename part of string into `file`, max length `filelen`. */ void BLI_split_file_part(const char *string, char *file, const size_t filelen) { @@ -1733,7 +1732,7 @@ void BLI_path_append(char *__restrict dst, const size_t maxlen, const char *__re /** * Simple appending of filename to dir, does not check for valid path! - * Puts result into *dst, which may be same area as *dir. + * Puts result into `dst`, which may be same area as `dir`. */ void BLI_join_dirfile(char *__restrict dst, const size_t maxlen, @@ -1777,7 +1776,7 @@ void BLI_join_dirfile(char *__restrict dst, * Join multiple strings into a path, ensuring only a single path separator between each, * and trailing slash is kept. * - * \note If you want a trailing slash, add ``SEP_STR`` as the last path argument, + * \note If you want a trailing slash, add `SEP_STR` as the last path argument, * duplicate slashes will be cleaned up. */ size_t BLI_path_join(char *__restrict dst, const size_t dst_len, const char *path, ...) @@ -1861,7 +1860,7 @@ size_t BLI_path_join(char *__restrict dst, const size_t dst_len, const char *pat } /** - * like pythons os.path.basename() + * like Python's `os.path.basename()` * * \return The pointer into \a path string immediately after last slash, * or start of \a path if none found. -- cgit v1.2.3 From 45bf470ee9e94e62a038c9faac891744488a1b89 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Mon, 14 Dec 2020 10:46:19 +0100 Subject: Fix T83712: arctangent math node does not work in Eevee Caused by my refactoring of the math node. Somehow this operation slipped through my double checking procedure. --- source/blender/nodes/intern/math_functions.cc | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source/blender') diff --git a/source/blender/nodes/intern/math_functions.cc b/source/blender/nodes/intern/math_functions.cc index cc5e9547a96..5a6faa809f2 100644 --- a/source/blender/nodes/intern/math_functions.cc +++ b/source/blender/nodes/intern/math_functions.cc @@ -41,6 +41,8 @@ const FloatMathOperationInfo *get_float_math_operation_info(const int operation) RETURN_OPERATION_INFO("Sine", "math_sine"); case NODE_MATH_COSINE: RETURN_OPERATION_INFO("Cosine", "math_cosine"); + case NODE_MATH_TANGENT: + RETURN_OPERATION_INFO("Tangent", "math_tangent"); case NODE_MATH_ARCSINE: RETURN_OPERATION_INFO("Arc Sine", "math_arcsine"); case NODE_MATH_ARCCOSINE: -- cgit v1.2.3 From 53ed96641c60531e2ece17230879088df899f8a5 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Mon, 14 Dec 2020 10:48:11 +0100 Subject: Cleanup: clang tidy --- source/blender/io/collada/ArmatureImporter.cpp | 2 +- source/blender/io/collada/collada_utils.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'source/blender') diff --git a/source/blender/io/collada/ArmatureImporter.cpp b/source/blender/io/collada/ArmatureImporter.cpp index 56716722b46..7eef5c3f5fb 100644 --- a/source/blender/io/collada/ArmatureImporter.cpp +++ b/source/blender/io/collada/ArmatureImporter.cpp @@ -1037,7 +1037,7 @@ void ArmatureImporter::get_rna_path_for_joint(COLLADAFW::Node *node, char *joint_path, size_t count) { - char bone_name_esc[sizeof(((Bone *)NULL)->name) * 2]; + char bone_name_esc[sizeof(((Bone *)nullptr)->name) * 2]; BLI_str_escape(bone_name_esc, bc_get_joint_name(node), sizeof(bone_name_esc)); BLI_snprintf(joint_path, count, "pose.bones[\"%s\"]", bone_name_esc); } diff --git a/source/blender/io/collada/collada_utils.cpp b/source/blender/io/collada/collada_utils.cpp index 3c68de70248..bba50064879 100644 --- a/source/blender/io/collada/collada_utils.cpp +++ b/source/blender/io/collada/collada_utils.cpp @@ -832,7 +832,7 @@ void bc_enable_fcurves(bAction *act, char *bone_name) char prefix[200]; if (bone_name) { - char bone_name_esc[sizeof(((Bone *)NULL)->name) * 2]; + char bone_name_esc[sizeof(((Bone *)nullptr)->name) * 2]; BLI_str_escape(bone_name_esc, bone_name, sizeof(bone_name_esc)); BLI_snprintf(prefix, sizeof(prefix), "pose.bones[\"%s\"]", bone_name_esc); } -- cgit v1.2.3 From f5a019ed43ab07a7d265d81e8ce89d15aaff00ef Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Mon, 14 Dec 2020 11:28:08 +0100 Subject: LibOverride: Do not store some heavy data from override IDs. This commit removes geometry from meshes and shapekeys, and embedded files, from liboverride IDs. This data is never overrideable, there is no reason to store extra useless copies of it in production files. See T78944. Note that we may add more data to be skipped on write for liboverrides in the future, but this commit should address all the most important cases already. Reviewed By: brecht Differential Revision: https://developer.blender.org/D9810 --- source/blender/blenkernel/intern/font.c | 8 ++++- source/blender/blenkernel/intern/image.c | 17 +++++++--- source/blender/blenkernel/intern/key.c | 15 ++++++--- source/blender/blenkernel/intern/mesh.c | 51 +++++++++++++++++++++++------- source/blender/blenkernel/intern/sound.c | 8 ++++- source/blender/blenkernel/intern/volume.cc | 8 ++++- 6 files changed, 84 insertions(+), 23 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c index 9431915b4e4..df1dbaa905f 100644 --- a/source/blender/blenkernel/intern/font.c +++ b/source/blender/blenkernel/intern/font.c @@ -125,11 +125,17 @@ static void vfont_free_data(ID *id) static void vfont_blend_write(BlendWriter *writer, ID *id, const void *id_address) { VFont *vf = (VFont *)id; - if (vf->id.us > 0 || BLO_write_is_undo(writer)) { + const bool is_undo = BLO_write_is_undo(writer); + if (vf->id.us > 0 || is_undo) { /* Clean up, important in undo case to reduce false detection of changed datablocks. */ vf->data = NULL; vf->temp_pf = NULL; + /* Do not store packed files in case this is a library override ID. */ + if (ID_IS_OVERRIDE_LIBRARY(vf) && !is_undo) { + vf->packedfile = NULL; + } + /* write LibData */ BLO_write_id_struct(writer, VFont, id_address, &vf->id); BKE_id_blend_write(writer, &vf->id); diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index cd2ed32cd4f..f72cce8ba2e 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -225,14 +225,21 @@ static void image_foreach_cache(ID *id, static void image_blend_write(BlendWriter *writer, ID *id, const void *id_address) { Image *ima = (Image *)id; - if (ima->id.us > 0 || BLO_write_is_undo(writer)) { + const bool is_undo = BLO_write_is_undo(writer); + if (ima->id.us > 0 || is_undo) { ImagePackedFile *imapf; - /* Some trickery to keep forward compatibility of packed images. */ BLI_assert(ima->packedfile == NULL); - if (ima->packedfiles.first != NULL) { - imapf = ima->packedfiles.first; - ima->packedfile = imapf->packedfile; + /* Do not store packed files in case this is a library override ID. */ + if (ID_IS_OVERRIDE_LIBRARY(ima) && !is_undo) { + BLI_listbase_clear(&ima->packedfiles); + } + else { + /* Some trickery to keep forward compatibility of packed images. */ + if (ima->packedfiles.first != NULL) { + imapf = ima->packedfiles.first; + ima->packedfile = imapf->packedfile; + } } /* write LibData */ diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c index 7468112b40e..433d64a5927 100644 --- a/source/blender/blenkernel/intern/key.c +++ b/source/blender/blenkernel/intern/key.c @@ -108,7 +108,8 @@ static void shapekey_foreach_id(ID *id, LibraryForeachIDData *data) static void shapekey_blend_write(BlendWriter *writer, ID *id, const void *id_address) { Key *key = (Key *)id; - if (key->id.us > 0 || BLO_write_is_undo(writer)) { + const bool is_undo = BLO_write_is_undo(writer); + if (key->id.us > 0 || is_undo) { /* write LibData */ BLO_write_id_struct(writer, Key, id_address, &key->id); BKE_id_blend_write(writer, &key->id); @@ -119,9 +120,15 @@ static void shapekey_blend_write(BlendWriter *writer, ID *id, const void *id_add /* direct data */ LISTBASE_FOREACH (KeyBlock *, kb, &key->block) { - BLO_write_struct(writer, KeyBlock, kb); - if (kb->data) { - BLO_write_raw(writer, kb->totelem * key->elemsize, kb->data); + KeyBlock tmp_kb = *kb; + /* Do not store actual geometry data in case this is a library override ID. */ + if (ID_IS_OVERRIDE_LIBRARY(key) && !is_undo) { + tmp_kb.totelem = 0; + tmp_kb.data = NULL; + } + BLO_write_struct_at_address(writer, KeyBlock, kb, &tmp_kb); + if (tmp_kb.data != NULL) { + BLO_write_raw(writer, tmp_kb.totelem * key->elemsize, tmp_kb.data); } } } diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 9ccdf5189d1..53f2a85fdad 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -173,24 +173,53 @@ static void mesh_foreach_id(ID *id, LibraryForeachIDData *data) static void mesh_blend_write(BlendWriter *writer, ID *id, const void *id_address) { Mesh *mesh = (Mesh *)id; - if (mesh->id.us > 0 || BLO_write_is_undo(writer)) { - /* cache only - don't write */ - mesh->mface = NULL; - mesh->totface = 0; - memset(&mesh->fdata, 0, sizeof(mesh->fdata)); - memset(&mesh->runtime, 0, sizeof(mesh->runtime)); - + const bool is_undo = BLO_write_is_undo(writer); + if (mesh->id.us > 0 || is_undo) { CustomDataLayer *vlayers = NULL, vlayers_buff[CD_TEMP_CHUNK_SIZE]; CustomDataLayer *elayers = NULL, elayers_buff[CD_TEMP_CHUNK_SIZE]; CustomDataLayer *flayers = NULL, flayers_buff[CD_TEMP_CHUNK_SIZE]; CustomDataLayer *llayers = NULL, llayers_buff[CD_TEMP_CHUNK_SIZE]; CustomDataLayer *players = NULL, players_buff[CD_TEMP_CHUNK_SIZE]; - CustomData_blend_write_prepare(&mesh->vdata, &vlayers, vlayers_buff, ARRAY_SIZE(vlayers_buff)); - CustomData_blend_write_prepare(&mesh->edata, &elayers, elayers_buff, ARRAY_SIZE(elayers_buff)); + /* cache only - don't write */ + mesh->mface = NULL; + mesh->totface = 0; + memset(&mesh->fdata, 0, sizeof(mesh->fdata)); + memset(&mesh->runtime, 0, sizeof(mesh->runtime)); flayers = flayers_buff; - CustomData_blend_write_prepare(&mesh->ldata, &llayers, llayers_buff, ARRAY_SIZE(llayers_buff)); - CustomData_blend_write_prepare(&mesh->pdata, &players, players_buff, ARRAY_SIZE(players_buff)); + + /* Do not store actual geometry data in case this is a library override ID. */ + if (ID_IS_OVERRIDE_LIBRARY(mesh) && !is_undo) { + mesh->mvert = NULL; + mesh->totvert = 0; + memset(&mesh->vdata, 0, sizeof(mesh->vdata)); + vlayers = vlayers_buff; + + mesh->medge = NULL; + mesh->totedge = 0; + memset(&mesh->edata, 0, sizeof(mesh->edata)); + elayers = elayers_buff; + + mesh->mloop = NULL; + mesh->totloop = 0; + memset(&mesh->ldata, 0, sizeof(mesh->ldata)); + llayers = llayers_buff; + + mesh->mpoly = NULL; + mesh->totpoly = 0; + memset(&mesh->pdata, 0, sizeof(mesh->pdata)); + players = players_buff; + } + else { + CustomData_blend_write_prepare( + &mesh->vdata, &vlayers, vlayers_buff, ARRAY_SIZE(vlayers_buff)); + CustomData_blend_write_prepare( + &mesh->edata, &elayers, elayers_buff, ARRAY_SIZE(elayers_buff)); + CustomData_blend_write_prepare( + &mesh->ldata, &llayers, llayers_buff, ARRAY_SIZE(llayers_buff)); + CustomData_blend_write_prepare( + &mesh->pdata, &players, players_buff, ARRAY_SIZE(players_buff)); + } BLO_write_id_struct(writer, Mesh, id_address, &mesh->id); BKE_id_blend_write(writer, &mesh->id); diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c index 8b66b1fc628..5bcc1a9553a 100644 --- a/source/blender/blenkernel/intern/sound.c +++ b/source/blender/blenkernel/intern/sound.c @@ -135,13 +135,19 @@ static void sound_foreach_cache(ID *id, static void sound_blend_write(BlendWriter *writer, ID *id, const void *id_address) { bSound *sound = (bSound *)id; - if (sound->id.us > 0 || BLO_write_is_undo(writer)) { + const bool is_undo = BLO_write_is_undo(writer); + if (sound->id.us > 0 || is_undo) { /* Clean up, important in undo case to reduce false detection of changed datablocks. */ sound->tags = 0; sound->handle = NULL; sound->playback_handle = NULL; sound->spinlock = NULL; + /* Do not store packed files in case this is a library override ID. */ + if (ID_IS_OVERRIDE_LIBRARY(sound) && !is_undo) { + sound->packedfile = NULL; + } + /* write LibData */ BLO_write_id_struct(writer, bSound, id_address, &sound->id); BKE_id_blend_write(writer, &sound->id); diff --git a/source/blender/blenkernel/intern/volume.cc b/source/blender/blenkernel/intern/volume.cc index 11aa9597740..67727d87161 100644 --- a/source/blender/blenkernel/intern/volume.cc +++ b/source/blender/blenkernel/intern/volume.cc @@ -561,10 +561,16 @@ static void volume_foreach_cache(ID *id, static void volume_blend_write(BlendWriter *writer, ID *id, const void *id_address) { Volume *volume = (Volume *)id; - if (volume->id.us > 0 || BLO_write_is_undo(writer)) { + const bool is_undo = BLO_write_is_undo(writer); + if (volume->id.us > 0 || is_undo) { /* Clean up, important in undo case to reduce false detection of changed datablocks. */ volume->runtime.grids = nullptr; + /* Do not store packed files in case this is a library override ID. */ + if (ID_IS_OVERRIDE_LIBRARY(volume) && !is_undo) { + volume->packedfile = nullptr; + } + /* write LibData */ BLO_write_id_struct(writer, Volume, id_address, &volume->id); BKE_id_blend_write(writer, &volume->id); -- cgit v1.2.3 From 6f7ced77e3e8ecdf32d3345fcde7021e8a3dd56c Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Mon, 14 Dec 2020 14:09:18 +0300 Subject: Fix windows build. --- source/blender/blenlib/tests/BLI_math_rotation_test.cc | 1 + 1 file changed, 1 insertion(+) (limited to 'source/blender') diff --git a/source/blender/blenlib/tests/BLI_math_rotation_test.cc b/source/blender/blenlib/tests/BLI_math_rotation_test.cc index 90fd4f8c2e6..5a179bff3d6 100644 --- a/source/blender/blenlib/tests/BLI_math_rotation_test.cc +++ b/source/blender/blenlib/tests/BLI_math_rotation_test.cc @@ -2,6 +2,7 @@ #include "testing/testing.h" +#include "BLI_math_base.h" #include "BLI_math_rotation.h" #include -- cgit v1.2.3 From 812ea9184221a8ca5785528bebc3ef342a8ecfb4 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Fri, 11 Dec 2020 23:49:13 +0100 Subject: UI/Assets: Operator to load custom preview images for data-blocks No automatic preview generation will ever be good enough to cover all cases well. So custom preview images are a must for a preview driven data-block selection - like for asset browsing. The operator simply allows selecting an image file, which will then be read and copied into the data-blocks preview (resized if necessary). There's no UI for this currently and the operator won't be available in the search menu yet. It will later once the Asset Browser UI is merged. Reviewed as part of https://developer.blender.org/D9719. Reviewed by: Bastien Montagne, Brecht Van Lommel --- source/blender/blenkernel/BKE_icons.h | 6 +- source/blender/blenkernel/intern/icons.c | 77 +++++++++++++++++--------- source/blender/editors/include/ED_util.h | 1 + source/blender/editors/render/render_preview.c | 2 +- source/blender/editors/screen/screen_ops.c | 1 + source/blender/editors/util/ed_util.c | 72 ++++++++++++++++++++++++ 6 files changed, 132 insertions(+), 27 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/BKE_icons.h b/source/blender/blenkernel/BKE_icons.h index d6cf5eae323..534b24236e8 100644 --- a/source/blender/blenkernel/BKE_icons.h +++ b/source/blender/blenkernel/BKE_icons.h @@ -130,6 +130,9 @@ void BKE_previewimg_clear_single(struct PreviewImage *prv, enum eIconSizes size) /* get the preview from any pointer */ struct PreviewImage **BKE_previewimg_id_get_p(const struct ID *id); +/* Trigger deferred loading of a custom image file into the preview buffer. */ +void BKE_previewimg_id_custom_set(struct ID *id, const char *path); + /* free the preview image belonging to the id */ void BKE_previewimg_id_free(struct ID *id); @@ -156,7 +159,8 @@ struct PreviewImage *BKE_previewimg_cached_thumbnail_read(const char *name, bool force_update); void BKE_previewimg_cached_release(const char *name); -void BKE_previewimg_cached_release_pointer(struct PreviewImage *prv); + +void BKE_previewimg_deferred_release(struct PreviewImage *prv); void BKE_previewimg_blend_write(struct BlendWriter *writer, const struct PreviewImage *prv); void BKE_previewimg_blend_read(struct BlendDataReader *reader, struct PreviewImage *prv); diff --git a/source/blender/blenkernel/intern/icons.c b/source/blender/blenkernel/intern/icons.c index eec9013d067..58b4a8ce315 100644 --- a/source/blender/blenkernel/intern/icons.c +++ b/source/blender/blenkernel/intern/icons.c @@ -230,6 +230,20 @@ static PreviewImage *previewimg_create_ex(size_t deferred_data_size) return prv_img; } +static PreviewImage *previewimg_deferred_create(const char *path, int source) +{ + /* We pack needed data for lazy loading (source type, in a single char, and path). */ + const size_t deferred_data_size = strlen(path) + 2; + char *deferred_data; + + PreviewImage *prv = previewimg_create_ex(deferred_data_size); + deferred_data = (char *)PRV_DEFERRED_DATA(prv); + deferred_data[0] = source; + memcpy(&deferred_data[1], path, deferred_data_size - 1); + + return prv; +} + PreviewImage *BKE_previewimg_create(void) { return previewimg_create_ex(0); @@ -364,6 +378,42 @@ PreviewImage *BKE_previewimg_id_ensure(ID *id) return NULL; } +void BKE_previewimg_deferred_release(PreviewImage *prv) +{ + if (prv) { + if (prv->tag & PRV_TAG_DEFFERED_RENDERING) { + /* We cannot delete the preview while it is being loaded in another thread... */ + prv->tag |= PRV_TAG_DEFFERED_DELETE; + return; + } + if (prv->icon_id) { + BKE_icon_delete(prv->icon_id); + } + BKE_previewimg_freefunc(prv); + } +} + +void BKE_previewimg_id_custom_set(ID *id, const char *path) +{ + PreviewImage **prv = BKE_previewimg_id_get_p(id); + + /* Thumbnail previews must use the deferred pipeline. But we force them to be immediately + * generated here still. */ + + if (*prv) { + BKE_previewimg_deferred_release(*prv); + } + *prv = previewimg_deferred_create(path, THB_SOURCE_IMAGE); + + /* Can't lazy-render the preview on access. ID previews are saved to files and we want them to be + * there in time. Not only if something happened to have accessed it meanwhile. */ + for (int i = 0; i < NUM_ICON_SIZES; i++) { + BKE_previewimg_ensure(*prv, i); + /* Prevent auto-updates. */ + (*prv)->flag[i] |= PRV_USER_EDITED; + } +} + PreviewImage *BKE_previewimg_cached_get(const char *name) { return BLI_ghash_lookup(gCachedPreviews, name); @@ -417,15 +467,7 @@ PreviewImage *BKE_previewimg_cached_thumbnail_read(const char *name, } if (!prv) { - /* We pack needed data for lazy loading (source type, in a single char, and path). */ - const size_t deferred_data_size = strlen(path) + 2; - char *deferred_data; - - prv = previewimg_create_ex(deferred_data_size); - deferred_data = PRV_DEFERRED_DATA(prv); - deferred_data[0] = source; - memcpy(&deferred_data[1], path, deferred_data_size - 1); - + previewimg_deferred_create(path, source); force_update = true; } @@ -441,26 +483,11 @@ PreviewImage *BKE_previewimg_cached_thumbnail_read(const char *name, return prv; } -void BKE_previewimg_cached_release_pointer(PreviewImage *prv) -{ - if (prv) { - if (prv->tag & PRV_TAG_DEFFERED_RENDERING) { - /* We cannot delete the preview while it is being loaded in another thread... */ - prv->tag |= PRV_TAG_DEFFERED_DELETE; - return; - } - if (prv->icon_id) { - BKE_icon_delete(prv->icon_id); - } - BKE_previewimg_freefunc(prv); - } -} - void BKE_previewimg_cached_release(const char *name) { PreviewImage *prv = BLI_ghash_popkey(gCachedPreviews, name, MEM_freeN); - BKE_previewimg_cached_release_pointer(prv); + BKE_previewimg_deferred_release(prv); } /** diff --git a/source/blender/editors/include/ED_util.h b/source/blender/editors/include/ED_util.h index 68ae3589064..d74a80045f1 100644 --- a/source/blender/editors/include/ED_util.h +++ b/source/blender/editors/include/ED_util.h @@ -53,6 +53,7 @@ void ED_spacedata_id_remap(struct ScrArea *area, struct ID *new_id); void ED_OT_flush_edits(struct wmOperatorType *ot); +void ED_OT_lib_id_load_custom_preview(struct wmOperatorType *ot); /* ************** XXX OLD CRUFT WARNING ************* */ diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c index 095deccada0..d67113083a3 100644 --- a/source/blender/editors/render/render_preview.c +++ b/source/blender/editors/render/render_preview.c @@ -1304,7 +1304,7 @@ static void icon_preview_endjob(void *customdata) prv_img->tag &= ~PRV_TAG_DEFFERED_RENDERING; if (prv_img->tag & PRV_TAG_DEFFERED_DELETE) { BLI_assert(prv_img->tag & PRV_TAG_DEFFERED); - BKE_previewimg_cached_release_pointer(prv_img); + BKE_previewimg_deferred_release(prv_img); } } } diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 649279f8e08..a0c5762c73c 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -5510,6 +5510,7 @@ void ED_operatortypes_screen(void) WM_operatortype_append(ED_OT_undo_history); WM_operatortype_append(ED_OT_flush_edits); + WM_operatortype_append(ED_OT_lib_id_load_custom_preview); } /** \} */ diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c index 76c261c9cba..5e3f443ce9c 100644 --- a/source/blender/editors/util/ed_util.c +++ b/source/blender/editors/util/ed_util.c @@ -35,6 +35,7 @@ #include "DNA_screen_types.h" #include "DNA_space_types.h" +#include "BLI_fileops.h" #include "BLI_listbase.h" #include "BLI_path_util.h" #include "BLI_string.h" @@ -44,6 +45,7 @@ #include "BKE_context.h" #include "BKE_global.h" +#include "BKE_icons.h" #include "BKE_layer.h" #include "BKE_main.h" #include "BKE_material.h" @@ -51,6 +53,7 @@ #include "BKE_object.h" #include "BKE_packedFile.h" #include "BKE_paint.h" +#include "BKE_report.h" #include "BKE_screen.h" #include "BKE_undo_system.h" #include "BKE_workspace.h" @@ -501,3 +504,72 @@ void ED_OT_flush_edits(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_INTERNAL; } + +static bool lib_id_load_custom_preview_poll(bContext *C) +{ + const PointerRNA idptr = CTX_data_pointer_get(C, "active_id"); + BLI_assert(!idptr.data || RNA_struct_is_ID(idptr.type)); + + const ID *id = idptr.data; + if (!id) { + return false; + } + if (ID_IS_LINKED(id)) { + CTX_wm_operator_poll_msg_set(C, TIP_("Can't edit external library data")); + return false; + } + if (ID_IS_OVERRIDE_LIBRARY(id)) { + CTX_wm_operator_poll_msg_set(C, TIP_("Can't edit previews of overridden library data")); + return false; + } + if (!BKE_previewimg_id_get_p(id)) { + CTX_wm_operator_poll_msg_set(C, TIP_("Data-block does not support previews")); + return false; + } + + return true; +} + +static int lib_id_load_custom_preview_exec(bContext *C, wmOperator *op) +{ + char path[FILE_MAX]; + + RNA_string_get(op->ptr, "filepath", path); + + if (!BLI_is_file(path)) { + BKE_reportf(op->reports, RPT_ERROR, "File not found '%s'", path); + return OPERATOR_CANCELLED; + } + + PointerRNA idptr = CTX_data_pointer_get(C, "active_id"); + ID *id = idptr.data; + + BKE_previewimg_id_custom_set(id, path); + + // WM_event_add_notifier(C, NC_ASSET, NULL); + + return OPERATOR_FINISHED; +} + +void ED_OT_lib_id_load_custom_preview(wmOperatorType *ot) +{ + ot->name = "Load Custom Preview"; + ot->description = "Choose an image to help identify the data-block visually"; + ot->idname = "ED_OT_lib_id_load_custom_preview"; + + /* api callbacks */ + ot->poll = lib_id_load_custom_preview_poll; + ot->exec = lib_id_load_custom_preview_exec; + ot->invoke = WM_operator_filesel; + + /* flags */ + ot->flag = OPTYPE_INTERNAL; + + WM_operator_properties_filesel(ot, + FILE_TYPE_FOLDER | FILE_TYPE_IMAGE, + FILE_SPECIAL, + FILE_OPENFILE, + WM_FILESEL_FILEPATH, + FILE_DEFAULTDISPLAY, + FILE_SORT_DEFAULT); +} -- cgit v1.2.3 From 732d0b458b6f9024b285747a643cacb128888b8c Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Mon, 14 Dec 2020 13:00:28 +0100 Subject: Blenkernel: move DerivedMesh.c to c++ Required changes to make it compile with clang tidy: * Use c++ includes like (e.g. climits instead limits.h). * Insert type casts when casting from void* to something else. * Replace NULL with nullptr. * Insert casts from int to enum. * Replace designed initializers (not supported in C++ yet). * Use blender::Vector instead of BLI_array_staticdeclare (does not compile with C++). * Replace typedef statements. Ref T83357. --- source/blender/blenkernel/BKE_mesh.h | 2 +- source/blender/blenkernel/BKE_mesh_runtime.h | 4 +- source/blender/blenkernel/CMakeLists.txt | 2 +- source/blender/blenkernel/intern/DerivedMesh.c | 2391 ---------------------- source/blender/blenkernel/intern/DerivedMesh.cc | 2410 +++++++++++++++++++++++ source/blender/blenkernel/intern/mesh_convert.c | 2 +- source/blender/modifiers/intern/MOD_cloth.c | 2 +- 7 files changed, 2416 insertions(+), 2397 deletions(-) delete mode 100644 source/blender/blenkernel/intern/DerivedMesh.c create mode 100644 source/blender/blenkernel/intern/DerivedMesh.cc (limited to 'source/blender') diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index 807f13efe14..0f34549a3cd 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -678,7 +678,7 @@ void BKE_mesh_calc_edges_loose(struct Mesh *mesh); void BKE_mesh_calc_edges(struct Mesh *mesh, bool keep_existing_edges, const bool select_new_edges); void BKE_mesh_calc_edges_tessface(struct Mesh *mesh); -/* In DerivedMesh.c */ +/* In DerivedMesh.cc */ void BKE_mesh_wrapper_deferred_finalize(struct Mesh *me_eval, const CustomData_MeshMasks *cd_mask_finalize); diff --git a/source/blender/blenkernel/BKE_mesh_runtime.h b/source/blender/blenkernel/BKE_mesh_runtime.h index 87b55c581a2..67c87e96aff 100644 --- a/source/blender/blenkernel/BKE_mesh_runtime.h +++ b/source/blender/blenkernel/BKE_mesh_runtime.h @@ -57,9 +57,9 @@ void BKE_mesh_runtime_verttri_from_looptri(struct MVertTri *r_verttri, const struct MLoopTri *looptri, int looptri_num); -/* NOTE: the functions below are defined in DerivedMesh.c, and are intended to be moved +/* NOTE: the functions below are defined in DerivedMesh.cc, and are intended to be moved * to a more suitable location when that file is removed. - * They should also be renamed to use conventions from BKE, not old DerivedMesh.c. + * They should also be renamed to use conventions from BKE, not old DerivedMesh.cc. * For now keep the names similar to avoid confusion. */ struct Mesh *mesh_get_eval_final(struct Depsgraph *depsgraph, struct Scene *scene, diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index 65161317351..5b10f734d71 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -66,7 +66,7 @@ set(SRC intern/CCGSubSurf.c intern/CCGSubSurf_legacy.c intern/CCGSubSurf_util.c - intern/DerivedMesh.c + intern/DerivedMesh.cc intern/action.c intern/addon.c intern/anim_data.c diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c deleted file mode 100644 index eeff04788f9..00000000000 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ /dev/null @@ -1,2391 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2005 Blender Foundation. - * All rights reserved. - */ - -/** \file - * \ingroup bke - */ - -#include -#include - -#include "MEM_guardedalloc.h" - -#include "DNA_cloth_types.h" -#include "DNA_customdata_types.h" -#include "DNA_key_types.h" -#include "DNA_material_types.h" -#include "DNA_mesh_types.h" -#include "DNA_meshdata_types.h" -#include "DNA_object_types.h" -#include "DNA_scene_types.h" - -#include "BLI_array.h" -#include "BLI_bitmap.h" -#include "BLI_blenlib.h" -#include "BLI_linklist.h" -#include "BLI_math.h" -#include "BLI_task.h" -#include "BLI_utildefines.h" - -#include "BKE_DerivedMesh.h" -#include "BKE_bvhutils.h" -#include "BKE_colorband.h" -#include "BKE_deform.h" -#include "BKE_editmesh.h" -#include "BKE_key.h" -#include "BKE_layer.h" -#include "BKE_lib_id.h" -#include "BKE_material.h" -#include "BKE_mesh.h" -#include "BKE_mesh_iterators.h" -#include "BKE_mesh_mapping.h" -#include "BKE_mesh_runtime.h" -#include "BKE_mesh_tangent.h" -#include "BKE_mesh_wrapper.h" -#include "BKE_modifier.h" -#include "BKE_multires.h" -#include "BKE_object.h" -#include "BKE_object_deform.h" -#include "BKE_paint.h" - -#include "BLI_sys_types.h" /* for intptr_t support */ - -#include "BKE_shrinkwrap.h" -#include "DEG_depsgraph.h" -#include "DEG_depsgraph_query.h" - -#include "CLG_log.h" - -#ifdef WITH_OPENSUBDIV -# include "DNA_userdef_types.h" -#endif - -/* very slow! enable for testing only! */ -//#define USE_MODIFIER_VALIDATE - -#ifdef USE_MODIFIER_VALIDATE -# define ASSERT_IS_VALID_MESH(mesh) \ - (BLI_assert((mesh == NULL) || (BKE_mesh_is_valid(mesh) == true))) -#else -# define ASSERT_IS_VALID_MESH(mesh) -#endif - -static ThreadRWMutex loops_cache_lock = PTHREAD_RWLOCK_INITIALIZER; - -static void mesh_init_origspace(Mesh *mesh); -static void editbmesh_calc_modifier_final_normals(Mesh *mesh_final, - const CustomData_MeshMasks *final_datamask); - -/* -------------------------------------------------------------------- */ - -static MVert *dm_getVertArray(DerivedMesh *dm) -{ - MVert *mvert = CustomData_get_layer(&dm->vertData, CD_MVERT); - - if (!mvert) { - mvert = CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL, dm->getNumVerts(dm)); - CustomData_set_layer_flag(&dm->vertData, CD_MVERT, CD_FLAG_TEMPORARY); - dm->copyVertArray(dm, mvert); - } - - return mvert; -} - -static MEdge *dm_getEdgeArray(DerivedMesh *dm) -{ - MEdge *medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE); - - if (!medge) { - medge = CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_CALLOC, NULL, dm->getNumEdges(dm)); - CustomData_set_layer_flag(&dm->edgeData, CD_MEDGE, CD_FLAG_TEMPORARY); - dm->copyEdgeArray(dm, medge); - } - - return medge; -} - -static MFace *dm_getTessFaceArray(DerivedMesh *dm) -{ - MFace *mface = CustomData_get_layer(&dm->faceData, CD_MFACE); - - if (!mface) { - int numTessFaces = dm->getNumTessFaces(dm); - - if (!numTessFaces) { - /* Do not add layer if there's no elements in it, this leads to issues later when - * this layer is needed with non-zero size, but currently CD stuff does not check - * for requested layer size on creation and just returns layer which was previously - * added (sergey) */ - return NULL; - } - - mface = CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL, numTessFaces); - CustomData_set_layer_flag(&dm->faceData, CD_MFACE, CD_FLAG_TEMPORARY); - dm->copyTessFaceArray(dm, mface); - } - - return mface; -} - -static MLoop *dm_getLoopArray(DerivedMesh *dm) -{ - MLoop *mloop = CustomData_get_layer(&dm->loopData, CD_MLOOP); - - if (!mloop) { - mloop = CustomData_add_layer(&dm->loopData, CD_MLOOP, CD_CALLOC, NULL, dm->getNumLoops(dm)); - CustomData_set_layer_flag(&dm->loopData, CD_MLOOP, CD_FLAG_TEMPORARY); - dm->copyLoopArray(dm, mloop); - } - - return mloop; -} - -static MPoly *dm_getPolyArray(DerivedMesh *dm) -{ - MPoly *mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY); - - if (!mpoly) { - mpoly = CustomData_add_layer(&dm->polyData, CD_MPOLY, CD_CALLOC, NULL, dm->getNumPolys(dm)); - CustomData_set_layer_flag(&dm->polyData, CD_MPOLY, CD_FLAG_TEMPORARY); - dm->copyPolyArray(dm, mpoly); - } - - return mpoly; -} - -static MVert *dm_dupVertArray(DerivedMesh *dm) -{ - MVert *tmp = MEM_malloc_arrayN(dm->getNumVerts(dm), sizeof(*tmp), "dm_dupVertArray tmp"); - - if (tmp) { - dm->copyVertArray(dm, tmp); - } - - return tmp; -} - -static MEdge *dm_dupEdgeArray(DerivedMesh *dm) -{ - MEdge *tmp = MEM_malloc_arrayN(dm->getNumEdges(dm), sizeof(*tmp), "dm_dupEdgeArray tmp"); - - if (tmp) { - dm->copyEdgeArray(dm, tmp); - } - - return tmp; -} - -static MFace *dm_dupFaceArray(DerivedMesh *dm) -{ - MFace *tmp = MEM_malloc_arrayN(dm->getNumTessFaces(dm), sizeof(*tmp), "dm_dupFaceArray tmp"); - - if (tmp) { - dm->copyTessFaceArray(dm, tmp); - } - - return tmp; -} - -static MLoop *dm_dupLoopArray(DerivedMesh *dm) -{ - MLoop *tmp = MEM_malloc_arrayN(dm->getNumLoops(dm), sizeof(*tmp), "dm_dupLoopArray tmp"); - - if (tmp) { - dm->copyLoopArray(dm, tmp); - } - - return tmp; -} - -static MPoly *dm_dupPolyArray(DerivedMesh *dm) -{ - MPoly *tmp = MEM_malloc_arrayN(dm->getNumPolys(dm), sizeof(*tmp), "dm_dupPolyArray tmp"); - - if (tmp) { - dm->copyPolyArray(dm, tmp); - } - - return tmp; -} - -static int dm_getNumLoopTri(DerivedMesh *dm) -{ - const int numlooptris = poly_to_tri_count(dm->getNumPolys(dm), dm->getNumLoops(dm)); - BLI_assert(ELEM(dm->looptris.num, 0, numlooptris)); - return numlooptris; -} - -static const MLoopTri *dm_getLoopTriArray(DerivedMesh *dm) -{ - MLoopTri *looptri; - - BLI_rw_mutex_lock(&loops_cache_lock, THREAD_LOCK_READ); - looptri = dm->looptris.array; - BLI_rw_mutex_unlock(&loops_cache_lock); - - if (looptri != NULL) { - BLI_assert(dm->getNumLoopTri(dm) == dm->looptris.num); - } - else { - BLI_rw_mutex_lock(&loops_cache_lock, THREAD_LOCK_WRITE); - /* We need to ensure array is still NULL inside mutex-protected code, - * some other thread might have already recomputed those looptris. */ - if (dm->looptris.array == NULL) { - dm->recalcLoopTri(dm); - } - looptri = dm->looptris.array; - BLI_rw_mutex_unlock(&loops_cache_lock); - } - return looptri; -} - -static CustomData *dm_getVertCData(DerivedMesh *dm) -{ - return &dm->vertData; -} - -static CustomData *dm_getEdgeCData(DerivedMesh *dm) -{ - return &dm->edgeData; -} - -static CustomData *dm_getTessFaceCData(DerivedMesh *dm) -{ - return &dm->faceData; -} - -static CustomData *dm_getLoopCData(DerivedMesh *dm) -{ - return &dm->loopData; -} - -static CustomData *dm_getPolyCData(DerivedMesh *dm) -{ - return &dm->polyData; -} - -/** - * Utility function to initialize a DerivedMesh's function pointers to - * the default implementation (for those functions which have a default) - */ -void DM_init_funcs(DerivedMesh *dm) -{ - /* default function implementations */ - dm->getVertArray = dm_getVertArray; - dm->getEdgeArray = dm_getEdgeArray; - dm->getTessFaceArray = dm_getTessFaceArray; - dm->getLoopArray = dm_getLoopArray; - dm->getPolyArray = dm_getPolyArray; - dm->dupVertArray = dm_dupVertArray; - dm->dupEdgeArray = dm_dupEdgeArray; - dm->dupTessFaceArray = dm_dupFaceArray; - dm->dupLoopArray = dm_dupLoopArray; - dm->dupPolyArray = dm_dupPolyArray; - - dm->getLoopTriArray = dm_getLoopTriArray; - - /* subtypes handle getting actual data */ - dm->getNumLoopTri = dm_getNumLoopTri; - - dm->getVertDataLayout = dm_getVertCData; - dm->getEdgeDataLayout = dm_getEdgeCData; - dm->getTessFaceDataLayout = dm_getTessFaceCData; - dm->getLoopDataLayout = dm_getLoopCData; - dm->getPolyDataLayout = dm_getPolyCData; - - dm->getVertData = DM_get_vert_data; - dm->getEdgeData = DM_get_edge_data; - dm->getTessFaceData = DM_get_tessface_data; - dm->getPolyData = DM_get_poly_data; - dm->getVertDataArray = DM_get_vert_data_layer; - dm->getEdgeDataArray = DM_get_edge_data_layer; - dm->getTessFaceDataArray = DM_get_tessface_data_layer; - dm->getPolyDataArray = DM_get_poly_data_layer; - dm->getLoopDataArray = DM_get_loop_data_layer; -} - -/** - * Utility function to initialize a DerivedMesh for the desired number - * of vertices, edges and faces (doesn't allocate memory for them, just - * sets up the custom data layers) - */ -void DM_init(DerivedMesh *dm, - DerivedMeshType type, - int numVerts, - int numEdges, - int numTessFaces, - int numLoops, - int numPolys) -{ - dm->type = type; - dm->numVertData = numVerts; - dm->numEdgeData = numEdges; - dm->numTessFaceData = numTessFaces; - dm->numLoopData = numLoops; - dm->numPolyData = numPolys; - - DM_init_funcs(dm); - - dm->needsFree = 1; - dm->dirty = 0; - - /* don't use CustomData_reset(...); because we dont want to touch customdata */ - copy_vn_i(dm->vertData.typemap, CD_NUMTYPES, -1); - copy_vn_i(dm->edgeData.typemap, CD_NUMTYPES, -1); - copy_vn_i(dm->faceData.typemap, CD_NUMTYPES, -1); - copy_vn_i(dm->loopData.typemap, CD_NUMTYPES, -1); - copy_vn_i(dm->polyData.typemap, CD_NUMTYPES, -1); -} - -/** - * Utility function to initialize a DerivedMesh for the desired number - * of vertices, edges and faces, with a layer setup copied from source - */ -void DM_from_template_ex(DerivedMesh *dm, - DerivedMesh *source, - DerivedMeshType type, - int numVerts, - int numEdges, - int numTessFaces, - int numLoops, - int numPolys, - const CustomData_MeshMasks *mask) -{ - CustomData_copy(&source->vertData, &dm->vertData, mask->vmask, CD_CALLOC, numVerts); - CustomData_copy(&source->edgeData, &dm->edgeData, mask->emask, CD_CALLOC, numEdges); - CustomData_copy(&source->faceData, &dm->faceData, mask->fmask, CD_CALLOC, numTessFaces); - CustomData_copy(&source->loopData, &dm->loopData, mask->lmask, CD_CALLOC, numLoops); - CustomData_copy(&source->polyData, &dm->polyData, mask->pmask, CD_CALLOC, numPolys); - - dm->cd_flag = source->cd_flag; - - dm->type = type; - dm->numVertData = numVerts; - dm->numEdgeData = numEdges; - dm->numTessFaceData = numTessFaces; - dm->numLoopData = numLoops; - dm->numPolyData = numPolys; - - DM_init_funcs(dm); - - dm->needsFree = 1; - dm->dirty = 0; -} -void DM_from_template(DerivedMesh *dm, - DerivedMesh *source, - DerivedMeshType type, - int numVerts, - int numEdges, - int numTessFaces, - int numLoops, - int numPolys) -{ - DM_from_template_ex(dm, - source, - type, - numVerts, - numEdges, - numTessFaces, - numLoops, - numPolys, - &CD_MASK_DERIVEDMESH); -} - -bool DM_release(DerivedMesh *dm) -{ - if (dm->needsFree) { - CustomData_free(&dm->vertData, dm->numVertData); - CustomData_free(&dm->edgeData, dm->numEdgeData); - CustomData_free(&dm->faceData, dm->numTessFaceData); - CustomData_free(&dm->loopData, dm->numLoopData); - CustomData_free(&dm->polyData, dm->numPolyData); - - MEM_SAFE_FREE(dm->looptris.array); - dm->looptris.num = 0; - dm->looptris.num_alloc = 0; - - return true; - } - - CustomData_free_temporary(&dm->vertData, dm->numVertData); - CustomData_free_temporary(&dm->edgeData, dm->numEdgeData); - CustomData_free_temporary(&dm->faceData, dm->numTessFaceData); - CustomData_free_temporary(&dm->loopData, dm->numLoopData); - CustomData_free_temporary(&dm->polyData, dm->numPolyData); - - return false; -} - -void DM_DupPolys(DerivedMesh *source, DerivedMesh *target) -{ - CustomData_free(&target->loopData, source->numLoopData); - CustomData_free(&target->polyData, source->numPolyData); - - CustomData_copy(&source->loopData, - &target->loopData, - CD_MASK_DERIVEDMESH.lmask, - CD_DUPLICATE, - source->numLoopData); - CustomData_copy(&source->polyData, - &target->polyData, - CD_MASK_DERIVEDMESH.pmask, - CD_DUPLICATE, - source->numPolyData); - - target->numLoopData = source->numLoopData; - target->numPolyData = source->numPolyData; - - if (!CustomData_has_layer(&target->polyData, CD_MPOLY)) { - MPoly *mpoly; - MLoop *mloop; - - mloop = source->dupLoopArray(source); - mpoly = source->dupPolyArray(source); - CustomData_add_layer(&target->loopData, CD_MLOOP, CD_ASSIGN, mloop, source->numLoopData); - CustomData_add_layer(&target->polyData, CD_MPOLY, CD_ASSIGN, mpoly, source->numPolyData); - } -} - -void DM_ensure_normals(DerivedMesh *dm) -{ - if (dm->dirty & DM_DIRTY_NORMALS) { - dm->calcNormals(dm); - } - BLI_assert((dm->dirty & DM_DIRTY_NORMALS) == 0); -} - -/** - * Ensure the array is large enough - * - * \note This function must always be thread-protected by caller. - * It should only be used by internal code. - */ -void DM_ensure_looptri_data(DerivedMesh *dm) -{ - const unsigned int totpoly = dm->numPolyData; - const unsigned int totloop = dm->numLoopData; - const int looptris_num = poly_to_tri_count(totpoly, totloop); - - BLI_assert(dm->looptris.array_wip == NULL); - - SWAP(MLoopTri *, dm->looptris.array, dm->looptris.array_wip); - - if ((looptris_num > dm->looptris.num_alloc) || (looptris_num < dm->looptris.num_alloc * 2) || - (totpoly == 0)) { - MEM_SAFE_FREE(dm->looptris.array_wip); - dm->looptris.num_alloc = 0; - dm->looptris.num = 0; - } - - if (totpoly) { - if (dm->looptris.array_wip == NULL) { - dm->looptris.array_wip = MEM_malloc_arrayN( - looptris_num, sizeof(*dm->looptris.array_wip), __func__); - dm->looptris.num_alloc = looptris_num; - } - - dm->looptris.num = looptris_num; - } -} - -/** Utility function to convert an (evaluated) Mesh to a shape key block. */ -/* Just a shallow wrapper around BKE_keyblock_convert_from_mesh, - * that ensures both evaluated mesh and original one has same number of vertices. */ -void BKE_mesh_runtime_eval_to_meshkey(Mesh *me_deformed, Mesh *me, KeyBlock *kb) -{ - const int totvert = me_deformed->totvert; - - if (totvert == 0 || me->totvert == 0 || me->totvert != totvert) { - return; - } - - BKE_keyblock_convert_from_mesh(me_deformed, me->key, kb); -} - -/** - * set the CD_FLAG_NOCOPY flag in custom data layers where the mask is - * zero for the layer type, so only layer types specified by the mask - * will be copied - */ -void DM_set_only_copy(DerivedMesh *dm, const CustomData_MeshMasks *mask) -{ - CustomData_set_only_copy(&dm->vertData, mask->vmask); - CustomData_set_only_copy(&dm->edgeData, mask->emask); - CustomData_set_only_copy(&dm->faceData, mask->fmask); - /* this wasn't in 2.63 and is disabled for 2.64 because it gives problems with - * weight paint mode when there are modifiers applied, needs further investigation, - * see replies to r50969, Campbell */ -#if 0 - CustomData_set_only_copy(&dm->loopData, mask->lmask); - CustomData_set_only_copy(&dm->polyData, mask->pmask); -#endif -} - -static void mesh_set_only_copy(Mesh *mesh, const CustomData_MeshMasks *mask) -{ - CustomData_set_only_copy(&mesh->vdata, mask->vmask); - CustomData_set_only_copy(&mesh->edata, mask->emask); - CustomData_set_only_copy(&mesh->fdata, mask->fmask); - /* this wasn't in 2.63 and is disabled for 2.64 because it gives problems with - * weight paint mode when there are modifiers applied, needs further investigation, - * see replies to r50969, Campbell */ -#if 0 - CustomData_set_only_copy(&mesh->ldata, mask->lmask); - CustomData_set_only_copy(&mesh->pdata, mask->pmask); -#endif -} - -void DM_add_vert_layer(DerivedMesh *dm, int type, eCDAllocType alloctype, void *layer) -{ - CustomData_add_layer(&dm->vertData, type, alloctype, layer, dm->numVertData); -} - -void DM_add_edge_layer(DerivedMesh *dm, int type, eCDAllocType alloctype, void *layer) -{ - CustomData_add_layer(&dm->edgeData, type, alloctype, layer, dm->numEdgeData); -} - -void DM_add_tessface_layer(DerivedMesh *dm, int type, eCDAllocType alloctype, void *layer) -{ - CustomData_add_layer(&dm->faceData, type, alloctype, layer, dm->numTessFaceData); -} - -void DM_add_loop_layer(DerivedMesh *dm, int type, eCDAllocType alloctype, void *layer) -{ - CustomData_add_layer(&dm->loopData, type, alloctype, layer, dm->numLoopData); -} - -void DM_add_poly_layer(DerivedMesh *dm, int type, eCDAllocType alloctype, void *layer) -{ - CustomData_add_layer(&dm->polyData, type, alloctype, layer, dm->numPolyData); -} - -void *DM_get_vert_data(DerivedMesh *dm, int index, int type) -{ - BLI_assert(index >= 0 && index < dm->getNumVerts(dm)); - return CustomData_get(&dm->vertData, index, type); -} - -void *DM_get_edge_data(DerivedMesh *dm, int index, int type) -{ - BLI_assert(index >= 0 && index < dm->getNumEdges(dm)); - return CustomData_get(&dm->edgeData, index, type); -} - -void *DM_get_tessface_data(DerivedMesh *dm, int index, int type) -{ - BLI_assert(index >= 0 && index < dm->getNumTessFaces(dm)); - return CustomData_get(&dm->faceData, index, type); -} - -void *DM_get_poly_data(DerivedMesh *dm, int index, int type) -{ - BLI_assert(index >= 0 && index < dm->getNumPolys(dm)); - return CustomData_get(&dm->polyData, index, type); -} - -void *DM_get_vert_data_layer(DerivedMesh *dm, int type) -{ - if (type == CD_MVERT) { - return dm->getVertArray(dm); - } - - return CustomData_get_layer(&dm->vertData, type); -} - -void *DM_get_edge_data_layer(DerivedMesh *dm, int type) -{ - if (type == CD_MEDGE) { - return dm->getEdgeArray(dm); - } - - return CustomData_get_layer(&dm->edgeData, type); -} - -void *DM_get_tessface_data_layer(DerivedMesh *dm, int type) -{ - if (type == CD_MFACE) { - return dm->getTessFaceArray(dm); - } - - return CustomData_get_layer(&dm->faceData, type); -} - -void *DM_get_poly_data_layer(DerivedMesh *dm, int type) -{ - return CustomData_get_layer(&dm->polyData, type); -} - -void *DM_get_loop_data_layer(DerivedMesh *dm, int type) -{ - return CustomData_get_layer(&dm->loopData, type); -} - -void DM_copy_vert_data( - DerivedMesh *source, DerivedMesh *dest, int source_index, int dest_index, int count) -{ - CustomData_copy_data(&source->vertData, &dest->vertData, source_index, dest_index, count); -} - -/** - * interpolates vertex data from the vertices indexed by src_indices in the - * source mesh using the given weights and stores the result in the vertex - * indexed by dest_index in the dest mesh - */ -void DM_interp_vert_data(DerivedMesh *source, - DerivedMesh *dest, - int *src_indices, - float *weights, - int count, - int dest_index) -{ - CustomData_interp( - &source->vertData, &dest->vertData, src_indices, weights, NULL, count, dest_index); -} - -static float (*get_editbmesh_orco_verts(BMEditMesh *em))[3] -{ - BMIter iter; - BMVert *eve; - float(*orco)[3]; - int i; - - /* these may not really be the orco's, but it's only for preview. - * could be solver better once, but isn't simple */ - - orco = MEM_malloc_arrayN(em->bm->totvert, sizeof(float[3]), "BMEditMesh Orco"); - - BM_ITER_MESH_INDEX (eve, &iter, em->bm, BM_VERTS_OF_MESH, i) { - copy_v3_v3(orco[i], eve->co); - } - - return orco; -} - -/* orco custom data layer */ -static float (*get_orco_coords(Object *ob, BMEditMesh *em, int layer, int *free))[3] -{ - *free = 0; - - if (layer == CD_ORCO) { - /* get original coordinates */ - *free = 1; - - if (em) { - return get_editbmesh_orco_verts(em); - } - return BKE_mesh_orco_verts_get(ob); - } - if (layer == CD_CLOTH_ORCO) { - /* apply shape key for cloth, this should really be solved - * by a more flexible customdata system, but not simple */ - if (!em) { - ClothModifierData *clmd = (ClothModifierData *)BKE_modifiers_findby_type( - ob, eModifierType_Cloth); - KeyBlock *kb = BKE_keyblock_from_key(BKE_key_from_object(ob), - clmd->sim_parms->shapekey_rest); - - if (kb && kb->data) { - return kb->data; - } - } - - return NULL; - } - - return NULL; -} - -static Mesh *create_orco_mesh(Object *ob, Mesh *me, BMEditMesh *em, int layer) -{ - Mesh *mesh; - float(*orco)[3]; - int free; - - if (em) { - mesh = BKE_mesh_from_bmesh_for_eval_nomain(em->bm, NULL, me); - } - else { - mesh = BKE_mesh_copy_for_eval(me, true); - } - - orco = get_orco_coords(ob, em, layer, &free); - - if (orco) { - BKE_mesh_vert_coords_apply(mesh, orco); - if (free) { - MEM_freeN(orco); - } - } - - return mesh; -} - -static void add_orco_mesh(Object *ob, BMEditMesh *em, Mesh *mesh, Mesh *mesh_orco, int layer) -{ - float(*orco)[3], (*layerorco)[3]; - int totvert, free; - - totvert = mesh->totvert; - - if (mesh_orco) { - free = 1; - - if (mesh_orco->totvert == totvert) { - orco = BKE_mesh_vert_coords_alloc(mesh_orco, NULL); - } - else { - orco = BKE_mesh_vert_coords_alloc(mesh, NULL); - } - } - else { - /* TODO(sybren): totvert should potentially change here, as ob->data - * or em may have a different number of vertices than dm. */ - orco = get_orco_coords(ob, em, layer, &free); - } - - if (orco) { - if (layer == CD_ORCO) { - BKE_mesh_orco_verts_transform(ob->data, orco, totvert, 0); - } - - if (!(layerorco = CustomData_get_layer(&mesh->vdata, layer))) { - CustomData_add_layer(&mesh->vdata, layer, CD_CALLOC, NULL, mesh->totvert); - BKE_mesh_update_customdata_pointers(mesh, false); - - layerorco = CustomData_get_layer(&mesh->vdata, layer); - } - - memcpy(layerorco, orco, sizeof(float[3]) * totvert); - if (free) { - MEM_freeN(orco); - } - } -} - -static void mesh_calc_modifier_final_normals(const Mesh *mesh_input, - const CustomData_MeshMasks *final_datamask, - const bool sculpt_dyntopo, - Mesh *mesh_final) -{ - /* Compute normals. */ - const bool do_loop_normals = ((mesh_input->flag & ME_AUTOSMOOTH) != 0 || - (final_datamask->lmask & CD_MASK_NORMAL) != 0); - /* Some modifiers may need this info from their target (other) object, - * simpler to generate it here as well. - * Note that they will always be generated when no loop normals are computed, - * since they are needed by drawing code. */ - const bool do_poly_normals = ((final_datamask->pmask & CD_MASK_NORMAL) != 0); - - /* In case we also need poly normals, add the layer and compute them here - * (BKE_mesh_calc_normals_split() assumes that if that data exists, it is always valid). */ - if (do_poly_normals) { - if (!CustomData_has_layer(&mesh_final->pdata, CD_NORMAL)) { - float(*polynors)[3] = CustomData_add_layer( - &mesh_final->pdata, CD_NORMAL, CD_CALLOC, NULL, mesh_final->totpoly); - BKE_mesh_calc_normals_poly(mesh_final->mvert, - NULL, - mesh_final->totvert, - mesh_final->mloop, - mesh_final->mpoly, - mesh_final->totloop, - mesh_final->totpoly, - polynors, - false); - } - } - - if (do_loop_normals) { - /* Compute loop normals (note: will compute poly and vert normals as well, if needed!) */ - BKE_mesh_calc_normals_split(mesh_final); - BKE_mesh_tessface_clear(mesh_final); - } - - if (sculpt_dyntopo == false) { - /* watch this! after 2.75a we move to from tessface to looptri (by default) */ - if (final_datamask->fmask & CD_MASK_MFACE) { - BKE_mesh_tessface_ensure(mesh_final); - } - - /* without this, drawing ngon tri's faces will show ugly tessellated face - * normals and will also have to calculate normals on the fly, try avoid - * this where possible since calculating polygon normals isn't fast, - * note that this isn't a problem for subsurf (only quads) or editmode - * which deals with drawing differently. - * - * Only calc vertex normals if they are flagged as dirty. - * If using loop normals, poly nors have already been computed. - */ - if (!do_loop_normals) { - BKE_mesh_ensure_normals_for_display(mesh_final); - } - } - - /* Some modifiers, like data-transfer, may generate those data as temp layer, - * we do not want to keep them, as they are used by display code when available - * (i.e. even if autosmooth is disabled). */ - if (!do_loop_normals && CustomData_has_layer(&mesh_final->ldata, CD_NORMAL)) { - CustomData_free_layers(&mesh_final->ldata, CD_NORMAL, mesh_final->totloop); - } -} - -/* Does final touches to the final evaluated mesh, making sure it is perfectly usable. - * - * This is needed because certain information is not passed along intermediate meshes allocated - * during stack evaluation. - */ -static void mesh_calc_finalize(const Mesh *mesh_input, Mesh *mesh_eval) -{ - /* Make sure the name is the same. This is because mesh allocation from template does not - * take care of naming. */ - BLI_strncpy(mesh_eval->id.name, mesh_input->id.name, sizeof(mesh_eval->id.name)); - /* Make evaluated mesh to share same edit mesh pointer as original and copied meshes. */ - mesh_eval->edit_mesh = mesh_input->edit_mesh; -} - -void BKE_mesh_wrapper_deferred_finalize(Mesh *me_eval, - const CustomData_MeshMasks *cd_mask_finalize) -{ - if (me_eval->runtime.wrapper_type_finalize & (1 << ME_WRAPPER_TYPE_BMESH)) { - editbmesh_calc_modifier_final_normals(me_eval, cd_mask_finalize); - me_eval->runtime.wrapper_type_finalize &= ~(1 << ME_WRAPPER_TYPE_BMESH); - } - BLI_assert(me_eval->runtime.wrapper_type_finalize == 0); -} - -static void mesh_calc_modifiers(struct Depsgraph *depsgraph, - Scene *scene, - Object *ob, - int useDeform, - const bool need_mapping, - const CustomData_MeshMasks *dataMask, - const int index, - const bool use_cache, - const bool allow_shared_mesh, - /* return args */ - Mesh **r_deform, - Mesh **r_final) -{ - /* Input and final mesh. Final mesh is only created the moment the first - * constructive modifier is executed, or a deform modifier needs normals - * or certain data layers. */ - Mesh *mesh_input = ob->data; - Mesh *mesh_final = NULL; - Mesh *mesh_deform = NULL; - BLI_assert((mesh_input->id.tag & LIB_TAG_COPIED_ON_WRITE_EVAL_RESULT) == 0); - - /* Deformed vertex locations array. Deform only modifier need this type of - * float array rather than MVert*. Tracked along with mesh_final as an - * optimization to avoid copying coordinates back and forth if there are - * multiple sequential deform only modifiers. */ - float(*deformed_verts)[3] = NULL; - int num_deformed_verts = mesh_input->totvert; - bool isPrevDeform = false; - - /* Mesh with constructive modifiers but no deformation applied. Tracked - * along with final mesh if undeformed / orco coordinates are requested - * for texturing. */ - Mesh *mesh_orco = NULL; - Mesh *mesh_orco_cloth = NULL; - - /* Modifier evaluation modes. */ - const bool use_render = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER); - const int required_mode = use_render ? eModifierMode_Render : eModifierMode_Realtime; - - /* Sculpt can skip certain modifiers. */ - const bool has_multires = BKE_sculpt_multires_active(scene, ob) != NULL; - bool multires_applied = false; - const bool sculpt_mode = ob->mode & OB_MODE_SCULPT && ob->sculpt && !use_render; - const bool sculpt_dyntopo = (sculpt_mode && ob->sculpt->bm) && !use_render; - - /* Modifier evaluation contexts for different types of modifiers. */ - ModifierApplyFlag apply_render = use_render ? MOD_APPLY_RENDER : 0; - ModifierApplyFlag apply_cache = use_cache ? MOD_APPLY_USECACHE : 0; - const ModifierEvalContext mectx = {depsgraph, ob, apply_render | apply_cache}; - const ModifierEvalContext mectx_orco = {depsgraph, ob, apply_render | MOD_APPLY_ORCO}; - - /* Get effective list of modifiers to execute. Some effects like shape keys - * are added as virtual modifiers before the user created modifiers. */ - VirtualModifierData virtualModifierData; - ModifierData *firstmd = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData); - ModifierData *md = firstmd; - - /* Preview colors by modifiers such as dynamic paint, to show the results - * even if the resulting data is not used in a material. Only in object mode. - * TODO: this is broken, not drawn by the drawn manager. */ - const bool do_mod_mcol = (ob->mode == OB_MODE_OBJECT); - ModifierData *previewmd = NULL; - CustomData_MeshMasks previewmask = {0}; - if (do_mod_mcol) { - /* Find the last active modifier generating a preview, or NULL if none. */ - /* XXX Currently, DPaint modifier just ignores this. - * Needs a stupid hack... - * The whole "modifier preview" thing has to be (re?)designed, anyway! */ - previewmd = BKE_modifier_get_last_preview(scene, md, required_mode); - } - - /* Compute accumulated datamasks needed by each modifier. It helps to do - * this fine grained so that for example vertex groups are preserved up to - * an armature modifier, but not through a following subsurf modifier where - * subdividing them is expensive. */ - CustomData_MeshMasks final_datamask = *dataMask; - CDMaskLink *datamasks = BKE_modifier_calc_data_masks( - scene, ob, md, &final_datamask, required_mode, previewmd, &previewmask); - CDMaskLink *md_datamask = datamasks; - /* XXX Always copying POLYINDEX, else tessellated data are no more valid! */ - CustomData_MeshMasks append_mask = CD_MASK_BAREMESH_ORIGINDEX; - - /* Clear errors before evaluation. */ - BKE_modifiers_clear_errors(ob); - - /* Apply all leading deform modifiers. */ - if (useDeform) { - for (; md; md = md->next, md_datamask = md_datamask->next) { - const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); - - if (!BKE_modifier_is_enabled(scene, md, required_mode)) { - continue; - } - - if (useDeform < 0 && mti->dependsOnTime && mti->dependsOnTime(md)) { - continue; - } - - if (mti->type == eModifierTypeType_OnlyDeform && !sculpt_dyntopo) { - if (!deformed_verts) { - deformed_verts = BKE_mesh_vert_coords_alloc(mesh_input, &num_deformed_verts); - } - else if (isPrevDeform && mti->dependsOnNormals && mti->dependsOnNormals(md)) { - if (mesh_final == NULL) { - mesh_final = BKE_mesh_copy_for_eval(mesh_input, true); - ASSERT_IS_VALID_MESH(mesh_final); - } - BKE_mesh_vert_coords_apply(mesh_final, deformed_verts); - } - - BKE_modifier_deform_verts(md, &mectx, mesh_final, deformed_verts, num_deformed_verts); - - isPrevDeform = true; - } - else { - break; - } - - /* grab modifiers until index i */ - if ((index != -1) && (BLI_findindex(&ob->modifiers, md) >= index)) { - md = NULL; - break; - } - } - - /* Result of all leading deforming modifiers is cached for - * places that wish to use the original mesh but with deformed - * coordinates (like vertex paint). */ - if (r_deform) { - mesh_deform = BKE_mesh_copy_for_eval(mesh_input, true); - - if (deformed_verts) { - BKE_mesh_vert_coords_apply(mesh_deform, deformed_verts); - } - } - } - - /* Apply all remaining constructive and deforming modifiers. */ - bool have_non_onlydeform_modifiers_appled = false; - for (; md; md = md->next, md_datamask = md_datamask->next) { - const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); - - if (!BKE_modifier_is_enabled(scene, md, required_mode)) { - continue; - } - - if (mti->type == eModifierTypeType_OnlyDeform && !useDeform) { - continue; - } - - if ((mti->flags & eModifierTypeFlag_RequiresOriginalData) && - have_non_onlydeform_modifiers_appled) { - BKE_modifier_set_error(ob, md, "Modifier requires original data, bad stack position"); - continue; - } - - if (sculpt_mode && (!has_multires || multires_applied || sculpt_dyntopo)) { - bool unsupported = false; - - if (md->type == eModifierType_Multires && ((MultiresModifierData *)md)->sculptlvl == 0) { - /* If multires is on level 0 skip it silently without warning message. */ - if (!sculpt_dyntopo) { - continue; - } - } - - if (sculpt_dyntopo) { - unsupported = true; - } - - if (scene->toolsettings->sculpt->flags & SCULPT_ONLY_DEFORM) { - unsupported |= (mti->type != eModifierTypeType_OnlyDeform); - } - - unsupported |= multires_applied; - - if (unsupported) { - if (sculpt_dyntopo) { - BKE_modifier_set_error(ob, md, "Not supported in dyntopo"); - } - else { - BKE_modifier_set_error(ob, md, "Not supported in sculpt mode"); - } - continue; - } - } - - if (need_mapping && !BKE_modifier_supports_mapping(md)) { - continue; - } - - if (useDeform < 0 && mti->dependsOnTime && mti->dependsOnTime(md)) { - continue; - } - - /* Add orco mesh as layer if needed by this modifier. */ - if (mesh_final && mesh_orco && mti->requiredDataMask) { - CustomData_MeshMasks mask = {0}; - mti->requiredDataMask(ob, md, &mask); - if (mask.vmask & CD_MASK_ORCO) { - add_orco_mesh(ob, NULL, mesh_final, mesh_orco, CD_ORCO); - } - } - - /* How to apply modifier depends on (a) what we already have as - * a result of previous modifiers (could be a Mesh or just - * deformed vertices) and (b) what type the modifier is. */ - if (mti->type == eModifierTypeType_OnlyDeform) { - /* No existing verts to deform, need to build them. */ - if (!deformed_verts) { - if (mesh_final) { - /* Deforming a mesh, read the vertex locations - * out of the mesh and deform them. Once done with this - * run of deformers verts will be written back. */ - deformed_verts = BKE_mesh_vert_coords_alloc(mesh_final, &num_deformed_verts); - } - else { - deformed_verts = BKE_mesh_vert_coords_alloc(mesh_input, &num_deformed_verts); - } - } - /* if this is not the last modifier in the stack then recalculate the normals - * to avoid giving bogus normals to the next modifier see: T23673. */ - else if (isPrevDeform && mti->dependsOnNormals && mti->dependsOnNormals(md)) { - if (mesh_final == NULL) { - mesh_final = BKE_mesh_copy_for_eval(mesh_input, true); - ASSERT_IS_VALID_MESH(mesh_final); - } - BKE_mesh_vert_coords_apply(mesh_final, deformed_verts); - } - BKE_modifier_deform_verts(md, &mectx, mesh_final, deformed_verts, num_deformed_verts); - } - else { - bool check_for_needs_mapping = false; - /* apply vertex coordinates or build a Mesh as necessary */ - if (mesh_final != NULL) { - if (have_non_onlydeform_modifiers_appled == false) { - /* If we only deformed, we won't have initialized #CD_ORIGINDEX. - * as this is the only part of the function that initializes mapping. */ - check_for_needs_mapping = true; - } - } - else { - mesh_final = BKE_mesh_copy_for_eval(mesh_input, true); - ASSERT_IS_VALID_MESH(mesh_final); - check_for_needs_mapping = true; - } - - if (deformed_verts) { - BKE_mesh_vert_coords_apply(mesh_final, deformed_verts); - } - - have_non_onlydeform_modifiers_appled = true; - - /* determine which data layers are needed by following modifiers */ - CustomData_MeshMasks nextmask = md_datamask->next ? md_datamask->next->mask : final_datamask; - - if (check_for_needs_mapping) { - /* Initialize original indices the first time we evaluate a - * constructive modifier. Modifiers will then do mapping mostly - * automatic by copying them through CustomData_copy_data along - * with other data. - * - * These are created when either requested by evaluation, or if - * following modifiers requested them. */ - if (need_mapping || - ((nextmask.vmask | nextmask.emask | nextmask.pmask) & CD_MASK_ORIGINDEX)) { - /* calc */ - CustomData_add_layer( - &mesh_final->vdata, CD_ORIGINDEX, CD_CALLOC, NULL, mesh_final->totvert); - CustomData_add_layer( - &mesh_final->edata, CD_ORIGINDEX, CD_CALLOC, NULL, mesh_final->totedge); - CustomData_add_layer( - &mesh_final->pdata, CD_ORIGINDEX, CD_CALLOC, NULL, mesh_final->totpoly); - - /* Not worth parallelizing this, - * gives less than 0.1% overall speedup in best of best cases... */ - range_vn_i( - CustomData_get_layer(&mesh_final->vdata, CD_ORIGINDEX), mesh_final->totvert, 0); - range_vn_i( - CustomData_get_layer(&mesh_final->edata, CD_ORIGINDEX), mesh_final->totedge, 0); - range_vn_i( - CustomData_get_layer(&mesh_final->pdata, CD_ORIGINDEX), mesh_final->totpoly, 0); - } - } - - /* set the Mesh to only copy needed data */ - CustomData_MeshMasks mask = md_datamask->mask; - /* needMapping check here fixes bug T28112, otherwise it's - * possible that it won't be copied */ - CustomData_MeshMasks_update(&mask, &append_mask); - if (need_mapping) { - mask.vmask |= CD_MASK_ORIGINDEX; - mask.emask |= CD_MASK_ORIGINDEX; - mask.pmask |= CD_MASK_ORIGINDEX; - } - mesh_set_only_copy(mesh_final, &mask); - - /* add cloth rest shape key if needed */ - if (mask.vmask & CD_MASK_CLOTH_ORCO) { - add_orco_mesh(ob, NULL, mesh_final, mesh_orco, CD_CLOTH_ORCO); - } - - /* add an origspace layer if needed */ - if ((md_datamask->mask.lmask) & CD_MASK_ORIGSPACE_MLOOP) { - if (!CustomData_has_layer(&mesh_final->ldata, CD_ORIGSPACE_MLOOP)) { - CustomData_add_layer( - &mesh_final->ldata, CD_ORIGSPACE_MLOOP, CD_CALLOC, NULL, mesh_final->totloop); - mesh_init_origspace(mesh_final); - } - } - - Mesh *mesh_next = BKE_modifier_modify_mesh(md, &mectx, mesh_final); - ASSERT_IS_VALID_MESH(mesh_next); - - if (mesh_next) { - /* if the modifier returned a new mesh, release the old one */ - if (mesh_final != mesh_next) { - BLI_assert(mesh_final != mesh_input); - BKE_id_free(NULL, mesh_final); - } - mesh_final = mesh_next; - - if (deformed_verts) { - MEM_freeN(deformed_verts); - deformed_verts = NULL; - } - } - - /* create an orco mesh in parallel */ - if (nextmask.vmask & CD_MASK_ORCO) { - if (!mesh_orco) { - mesh_orco = create_orco_mesh(ob, mesh_input, NULL, CD_ORCO); - } - - nextmask.vmask &= ~CD_MASK_ORCO; - CustomData_MeshMasks temp_cddata_masks = { - .vmask = CD_MASK_ORIGINDEX, - .emask = CD_MASK_ORIGINDEX, - .fmask = CD_MASK_ORIGINDEX, - .pmask = CD_MASK_ORIGINDEX, - }; - if (mti->requiredDataMask != NULL) { - mti->requiredDataMask(ob, md, &temp_cddata_masks); - } - CustomData_MeshMasks_update(&temp_cddata_masks, &nextmask); - mesh_set_only_copy(mesh_orco, &temp_cddata_masks); - - mesh_next = BKE_modifier_modify_mesh(md, &mectx_orco, mesh_orco); - ASSERT_IS_VALID_MESH(mesh_next); - - if (mesh_next) { - /* if the modifier returned a new mesh, release the old one */ - if (mesh_orco != mesh_next) { - BLI_assert(mesh_orco != mesh_input); - BKE_id_free(NULL, mesh_orco); - } - - mesh_orco = mesh_next; - } - } - - /* create cloth orco mesh in parallel */ - if (nextmask.vmask & CD_MASK_CLOTH_ORCO) { - if (!mesh_orco_cloth) { - mesh_orco_cloth = create_orco_mesh(ob, mesh_input, NULL, CD_CLOTH_ORCO); - } - - nextmask.vmask &= ~CD_MASK_CLOTH_ORCO; - nextmask.vmask |= CD_MASK_ORIGINDEX; - nextmask.emask |= CD_MASK_ORIGINDEX; - nextmask.pmask |= CD_MASK_ORIGINDEX; - mesh_set_only_copy(mesh_orco_cloth, &nextmask); - - mesh_next = BKE_modifier_modify_mesh(md, &mectx_orco, mesh_orco_cloth); - ASSERT_IS_VALID_MESH(mesh_next); - - if (mesh_next) { - /* if the modifier returned a new mesh, release the old one */ - if (mesh_orco_cloth != mesh_next) { - BLI_assert(mesh_orco != mesh_input); - BKE_id_free(NULL, mesh_orco_cloth); - } - - mesh_orco_cloth = mesh_next; - } - } - - /* in case of dynamic paint, make sure preview mask remains for following modifiers */ - /* XXX Temp and hackish solution! */ - if (md->type == eModifierType_DynamicPaint) { - append_mask.lmask |= CD_MASK_PREVIEW_MLOOPCOL; - } - - mesh_final->runtime.deformed_only = false; - } - - isPrevDeform = (mti->type == eModifierTypeType_OnlyDeform); - - /* grab modifiers until index i */ - if ((index != -1) && (BLI_findindex(&ob->modifiers, md) >= index)) { - break; - } - - if (sculpt_mode && md->type == eModifierType_Multires) { - multires_applied = true; - } - } - - BLI_linklist_free((LinkNode *)datamasks, NULL); - - for (md = firstmd; md; md = md->next) { - BKE_modifier_free_temporary_data(md); - } - - /* Yay, we are done. If we have a Mesh and deformed vertices, - * we need to apply these back onto the Mesh. If we have no - * Mesh then we need to build one. */ - if (mesh_final == NULL) { - /* Note: this check on cdmask is a bit dodgy, it handles the issue at stake here (see T68211), - * but other cases might require similar handling? - * Could be a good idea to define a proper CustomData_MeshMask for that then. */ - if (deformed_verts == NULL && allow_shared_mesh && - (final_datamask.lmask & CD_MASK_NORMAL) == 0 && - (final_datamask.pmask & CD_MASK_NORMAL) == 0) { - mesh_final = mesh_input; - } - else { - mesh_final = BKE_mesh_copy_for_eval(mesh_input, true); - } - } - if (deformed_verts) { - BKE_mesh_vert_coords_apply(mesh_final, deformed_verts); - MEM_freeN(deformed_verts); - deformed_verts = NULL; - } - - /* Denotes whether the object which the modifier stack came from owns the mesh or whether the - * mesh is shared across multiple objects since there are no effective modifiers. */ - const bool is_own_mesh = (mesh_final != mesh_input); - - /* Add orco coordinates to final and deformed mesh if requested. */ - if (final_datamask.vmask & CD_MASK_ORCO) { - /* No need in ORCO layer if the mesh was not deformed or modified: undeformed mesh in this case - * matches input mesh. */ - if (is_own_mesh) { - add_orco_mesh(ob, NULL, mesh_final, mesh_orco, CD_ORCO); - } - - if (mesh_deform) { - add_orco_mesh(ob, NULL, mesh_deform, NULL, CD_ORCO); - } - } - - if (mesh_orco) { - BKE_id_free(NULL, mesh_orco); - } - if (mesh_orco_cloth) { - BKE_id_free(NULL, mesh_orco_cloth); - } - - /* Compute normals. */ - if (is_own_mesh) { - mesh_calc_modifier_final_normals(mesh_input, &final_datamask, sculpt_dyntopo, mesh_final); - } - else { - Mesh_Runtime *runtime = &mesh_input->runtime; - if (runtime->mesh_eval == NULL) { - BLI_assert(runtime->eval_mutex != NULL); - BLI_mutex_lock(runtime->eval_mutex); - if (runtime->mesh_eval == NULL) { - mesh_final = BKE_mesh_copy_for_eval(mesh_input, true); - mesh_calc_modifier_final_normals(mesh_input, &final_datamask, sculpt_dyntopo, mesh_final); - mesh_calc_finalize(mesh_input, mesh_final); - runtime->mesh_eval = mesh_final; - } - BLI_mutex_unlock(runtime->eval_mutex); - } - mesh_final = runtime->mesh_eval; - } - - if (is_own_mesh) { - mesh_calc_finalize(mesh_input, mesh_final); - } - - /* Return final mesh */ - *r_final = mesh_final; - if (r_deform) { - *r_deform = mesh_deform; - } -} - -float (*editbmesh_vert_coords_alloc(BMEditMesh *em, int *r_vert_len))[3] -{ - BMIter iter; - BMVert *eve; - float(*cos)[3]; - int i; - - *r_vert_len = em->bm->totvert; - - cos = MEM_malloc_arrayN(em->bm->totvert, sizeof(float[3]), "vertexcos"); - - BM_ITER_MESH_INDEX (eve, &iter, em->bm, BM_VERTS_OF_MESH, i) { - copy_v3_v3(cos[i], eve->co); - } - - return cos; -} - -bool editbmesh_modifier_is_enabled(Scene *scene, - const Object *ob, - ModifierData *md, - bool has_prev_mesh) -{ - const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); - const int required_mode = eModifierMode_Realtime | eModifierMode_Editmode; - - if (!BKE_modifier_is_enabled(scene, md, required_mode)) { - return false; - } - - if ((mti->flags & eModifierTypeFlag_RequiresOriginalData) && has_prev_mesh) { - BKE_modifier_set_error(ob, md, "Modifier requires original data, bad stack position"); - return false; - } - - return true; -} - -static void editbmesh_calc_modifier_final_normals(Mesh *mesh_final, - const CustomData_MeshMasks *final_datamask) -{ - if (mesh_final->runtime.wrapper_type != ME_WRAPPER_TYPE_MDATA) { - /* Generated at draw time. */ - mesh_final->runtime.wrapper_type_finalize = (1 << mesh_final->runtime.wrapper_type); - return; - } - - const bool do_loop_normals = ((mesh_final->flag & ME_AUTOSMOOTH) != 0 || - (final_datamask->lmask & CD_MASK_NORMAL) != 0); - /* Some modifiers may need this info from their target (other) object, - * simpler to generate it here as well. */ - const bool do_poly_normals = ((final_datamask->pmask & CD_MASK_NORMAL) != 0); - - /* In case we also need poly normals, add the layer and compute them here - * (BKE_mesh_calc_normals_split() assumes that if that data exists, it is always valid). */ - if (do_poly_normals) { - if (!CustomData_has_layer(&mesh_final->pdata, CD_NORMAL)) { - float(*polynors)[3] = CustomData_add_layer( - &mesh_final->pdata, CD_NORMAL, CD_CALLOC, NULL, mesh_final->totpoly); - BKE_mesh_calc_normals_poly(mesh_final->mvert, - NULL, - mesh_final->totvert, - mesh_final->mloop, - mesh_final->mpoly, - mesh_final->totloop, - mesh_final->totpoly, - polynors, - false); - } - } - - if (do_loop_normals) { - /* Compute loop normals */ - BKE_mesh_calc_normals_split(mesh_final); - BKE_mesh_tessface_clear(mesh_final); - } - - /* BMESH_ONLY, ensure tessface's used for drawing, - * but don't recalculate if the last modifier in the stack gives us tessfaces - * check if the derived meshes are DM_TYPE_EDITBMESH before calling, this isn't essential - * but quiets annoying error messages since tessfaces wont be created. */ - if (final_datamask->fmask & CD_MASK_MFACE) { - if (mesh_final->edit_mesh == NULL) { - BKE_mesh_tessface_ensure(mesh_final); - } - } - - /* same as mesh_calc_modifiers (if using loop normals, poly nors have already been computed). */ - if (!do_loop_normals) { - BKE_mesh_ensure_normals_for_display(mesh_final); - - /* Some modifiers, like data-transfer, may generate those data, we do not want to keep them, - * as they are used by display code when available (i.e. even if autosmooth is disabled). */ - if (CustomData_has_layer(&mesh_final->ldata, CD_NORMAL)) { - CustomData_free_layers(&mesh_final->ldata, CD_NORMAL, mesh_final->totloop); - } - } -} - -static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph, - Scene *scene, - Object *ob, - BMEditMesh *em_input, - const CustomData_MeshMasks *dataMask, - /* return args */ - Mesh **r_cage, - Mesh **r_final) -{ - /* Input and final mesh. Final mesh is only created the moment the first - * constructive modifier is executed, or a deform modifier needs normals - * or certain data layers. */ - Mesh *mesh_input = ob->data; - Mesh *mesh_final = NULL; - Mesh *mesh_cage = NULL; - - /* Deformed vertex locations array. Deform only modifier need this type of - * float array rather than MVert*. Tracked along with mesh_final as an - * optimization to avoid copying coordinates back and forth if there are - * multiple sequential deform only modifiers. */ - float(*deformed_verts)[3] = NULL; - int num_deformed_verts = 0; - bool isPrevDeform = false; - - /* Mesh with constructive modifiers but no deformation applied. Tracked - * along with final mesh if undeformed / orco coordinates are requested - * for texturing. */ - Mesh *mesh_orco = NULL; - - /* Modifier evaluation modes. */ - const int required_mode = eModifierMode_Realtime | eModifierMode_Editmode; - - const bool use_render = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER); - /* Modifier evaluation contexts for different types of modifiers. */ - ModifierApplyFlag apply_render = use_render ? MOD_APPLY_RENDER : 0; - const ModifierEvalContext mectx = {depsgraph, ob, MOD_APPLY_USECACHE | apply_render}; - const ModifierEvalContext mectx_orco = {depsgraph, ob, MOD_APPLY_ORCO}; - - /* Get effective list of modifiers to execute. Some effects like shape keys - * are added as virtual modifiers before the user created modifiers. */ - VirtualModifierData virtualModifierData; - ModifierData *md = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData); - - /* Compute accumulated datamasks needed by each modifier. It helps to do - * this fine grained so that for example vertex groups are preserved up to - * an armature modifier, but not through a following subsurf modifier where - * subdividing them is expensive. */ - CustomData_MeshMasks final_datamask = *dataMask; - CDMaskLink *datamasks = BKE_modifier_calc_data_masks( - scene, ob, md, &final_datamask, required_mode, NULL, NULL); - CDMaskLink *md_datamask = datamasks; - CustomData_MeshMasks append_mask = CD_MASK_BAREMESH; - - /* Evaluate modifiers up to certain index to get the mesh cage. */ - int cageIndex = BKE_modifiers_get_cage_index(scene, ob, NULL, 1); - if (r_cage && cageIndex == -1) { - mesh_cage = BKE_mesh_wrapper_from_editmesh_with_coords( - em_input, &final_datamask, NULL, mesh_input); - } - - /* Clear errors before evaluation. */ - BKE_modifiers_clear_errors(ob); - - for (int i = 0; md; i++, md = md->next, md_datamask = md_datamask->next) { - const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); - - if (!editbmesh_modifier_is_enabled(scene, ob, md, mesh_final != NULL)) { - continue; - } - - /* Add an orco mesh as layer if needed by this modifier. */ - if (mesh_final && mesh_orco && mti->requiredDataMask) { - CustomData_MeshMasks mask = {0}; - mti->requiredDataMask(ob, md, &mask); - if (mask.vmask & CD_MASK_ORCO) { - add_orco_mesh(ob, em_input, mesh_final, mesh_orco, CD_ORCO); - } - } - - /* How to apply modifier depends on (a) what we already have as - * a result of previous modifiers (could be a mesh or just - * deformed vertices) and (b) what type the modifier is. */ - if (mti->type == eModifierTypeType_OnlyDeform) { - /* No existing verts to deform, need to build them. */ - if (!deformed_verts) { - if (mesh_final) { - /* Deforming a derived mesh, read the vertex locations - * out of the mesh and deform them. Once done with this - * run of deformers verts will be written back. */ - deformed_verts = BKE_mesh_vert_coords_alloc(mesh_final, &num_deformed_verts); - } - else { - deformed_verts = editbmesh_vert_coords_alloc(em_input, &num_deformed_verts); - } - } - else if (isPrevDeform && mti->dependsOnNormals && mti->dependsOnNormals(md)) { - if (mesh_final == NULL) { - mesh_final = BKE_mesh_from_bmesh_for_eval_nomain(em_input->bm, NULL, mesh_input); - ASSERT_IS_VALID_MESH(mesh_final); - } - BLI_assert(deformed_verts != NULL); - BKE_mesh_vert_coords_apply(mesh_final, deformed_verts); - } - - if (mti->deformVertsEM) { - BKE_modifier_deform_vertsEM( - md, &mectx, em_input, mesh_final, deformed_verts, num_deformed_verts); - } - else { - BKE_modifier_deform_verts(md, &mectx, mesh_final, deformed_verts, num_deformed_verts); - } - } - else { - /* apply vertex coordinates or build a DerivedMesh as necessary */ - if (mesh_final) { - if (deformed_verts) { - Mesh *mesh_tmp = BKE_mesh_copy_for_eval(mesh_final, false); - if (mesh_final != mesh_cage) { - BKE_id_free(NULL, mesh_final); - } - mesh_final = mesh_tmp; - BKE_mesh_vert_coords_apply(mesh_final, deformed_verts); - } - else if (mesh_final == mesh_cage) { - /* 'me' may be changed by this modifier, so we need to copy it. */ - mesh_final = BKE_mesh_copy_for_eval(mesh_final, false); - } - } - else { - mesh_final = BKE_mesh_wrapper_from_editmesh_with_coords( - em_input, NULL, deformed_verts, mesh_input); - deformed_verts = NULL; - } - - /* create an orco derivedmesh in parallel */ - CustomData_MeshMasks mask = md_datamask->mask; - if (mask.vmask & CD_MASK_ORCO) { - if (!mesh_orco) { - mesh_orco = create_orco_mesh(ob, mesh_input, em_input, CD_ORCO); - } - - mask.vmask &= ~CD_MASK_ORCO; - mask.vmask |= CD_MASK_ORIGINDEX; - mask.emask |= CD_MASK_ORIGINDEX; - mask.pmask |= CD_MASK_ORIGINDEX; - mesh_set_only_copy(mesh_orco, &mask); - - Mesh *mesh_next = BKE_modifier_modify_mesh(md, &mectx_orco, mesh_orco); - ASSERT_IS_VALID_MESH(mesh_next); - - if (mesh_next) { - /* if the modifier returned a new dm, release the old one */ - if (mesh_orco && mesh_orco != mesh_next) { - BKE_id_free(NULL, mesh_orco); - } - mesh_orco = mesh_next; - } - } - - /* set the DerivedMesh to only copy needed data */ - CustomData_MeshMasks_update(&mask, &append_mask); - /* XXX WHAT? ovewrites mask ??? */ - /* CD_MASK_ORCO may have been cleared above */ - mask = md_datamask->mask; - mask.vmask |= CD_MASK_ORIGINDEX; - mask.emask |= CD_MASK_ORIGINDEX; - mask.pmask |= CD_MASK_ORIGINDEX; - - mesh_set_only_copy(mesh_final, &mask); - - if (mask.lmask & CD_MASK_ORIGSPACE_MLOOP) { - if (!CustomData_has_layer(&mesh_final->ldata, CD_ORIGSPACE_MLOOP)) { - CustomData_add_layer( - &mesh_final->ldata, CD_ORIGSPACE_MLOOP, CD_CALLOC, NULL, mesh_final->totloop); - mesh_init_origspace(mesh_final); - } - } - - Mesh *mesh_next = BKE_modifier_modify_mesh(md, &mectx, mesh_final); - ASSERT_IS_VALID_MESH(mesh_next); - - if (mesh_next) { - if (mesh_final && mesh_final != mesh_next) { - BKE_id_free(NULL, mesh_final); - } - mesh_final = mesh_next; - - if (deformed_verts) { - MEM_freeN(deformed_verts); - deformed_verts = NULL; - } - } - mesh_final->runtime.deformed_only = false; - } - - if (r_cage && i == cageIndex) { - if (mesh_final && deformed_verts) { - mesh_cage = BKE_mesh_copy_for_eval(mesh_final, false); - BKE_mesh_vert_coords_apply(mesh_cage, deformed_verts); - } - else if (mesh_final) { - mesh_cage = mesh_final; - } - else { - Mesh *me_orig = mesh_input; - if (me_orig->id.tag & LIB_TAG_COPIED_ON_WRITE) { - if (!BKE_mesh_runtime_ensure_edit_data(me_orig)) { - BKE_mesh_runtime_reset_edit_data(me_orig); - } - me_orig->runtime.edit_data->vertexCos = MEM_dupallocN(deformed_verts); - } - mesh_cage = BKE_mesh_wrapper_from_editmesh_with_coords( - em_input, - &final_datamask, - deformed_verts ? MEM_dupallocN(deformed_verts) : NULL, - mesh_input); - } - } - - isPrevDeform = (mti->type == eModifierTypeType_OnlyDeform); - } - - BLI_linklist_free((LinkNode *)datamasks, NULL); - - /* Yay, we are done. If we have a DerivedMesh and deformed vertices need - * to apply these back onto the DerivedMesh. If we have no DerivedMesh - * then we need to build one. */ - if (mesh_final) { - if (deformed_verts) { - Mesh *mesh_tmp = BKE_mesh_copy_for_eval(mesh_final, false); - if (mesh_final != mesh_cage) { - BKE_id_free(NULL, mesh_final); - } - mesh_final = mesh_tmp; - BKE_mesh_vert_coords_apply(mesh_final, deformed_verts); - } - } - else if (!deformed_verts && mesh_cage) { - /* cage should already have up to date normals */ - mesh_final = mesh_cage; - } - else { - /* this is just a copy of the editmesh, no need to calc normals */ - mesh_final = BKE_mesh_wrapper_from_editmesh_with_coords( - em_input, &final_datamask, deformed_verts, mesh_input); - deformed_verts = NULL; - } - - if (deformed_verts) { - MEM_freeN(deformed_verts); - } - - /* Add orco coordinates to final and deformed mesh if requested. */ - if (final_datamask.vmask & CD_MASK_ORCO) { - /* FIXME(Campbell): avoid the need to convert to mesh data just to add an orco layer. */ - BKE_mesh_wrapper_ensure_mdata(mesh_final); - - add_orco_mesh(ob, em_input, mesh_final, mesh_orco, CD_ORCO); - } - - if (mesh_orco) { - BKE_id_free(NULL, mesh_orco); - } - - /* Ensure normals calculation below is correct. */ - BLI_assert((mesh_input->flag & ME_AUTOSMOOTH) == (mesh_final->flag & ME_AUTOSMOOTH)); - BLI_assert(mesh_input->smoothresh == mesh_final->smoothresh); - BLI_assert(mesh_input->smoothresh == mesh_cage->smoothresh); - - /* Compute normals. */ - editbmesh_calc_modifier_final_normals(mesh_final, &final_datamask); - if (mesh_cage && (mesh_cage != mesh_final)) { - editbmesh_calc_modifier_final_normals(mesh_cage, &final_datamask); - } - - /* Return final mesh. */ - *r_final = mesh_final; - if (r_cage) { - *r_cage = mesh_cage; - } -} - -static void mesh_build_extra_data(struct Depsgraph *depsgraph, Object *ob, Mesh *mesh_eval) -{ - uint32_t eval_flags = DEG_get_eval_flags_for_id(depsgraph, &ob->id); - - if (eval_flags & DAG_EVAL_NEED_SHRINKWRAP_BOUNDARY) { - BKE_shrinkwrap_compute_boundary_data(mesh_eval); - } -} - -static void mesh_runtime_check_normals_valid(const Mesh *mesh) -{ - UNUSED_VARS_NDEBUG(mesh); - BLI_assert(!(mesh->runtime.cd_dirty_vert & CD_MASK_NORMAL)); - BLI_assert(!(mesh->runtime.cd_dirty_loop & CD_MASK_NORMAL)); - BLI_assert(!(mesh->runtime.cd_dirty_poly & CD_MASK_NORMAL)); -} - -static void mesh_build_data(struct Depsgraph *depsgraph, - Scene *scene, - Object *ob, - const CustomData_MeshMasks *dataMask, - const bool need_mapping) -{ - BLI_assert(ob->type == OB_MESH); - - /* Evaluated meshes aren't supposed to be created on original instances. If you do, - * they aren't cleaned up properly on mode switch, causing crashes, e.g T58150. */ - BLI_assert(ob->id.tag & LIB_TAG_COPIED_ON_WRITE); - - BKE_object_free_derived_caches(ob); - if (DEG_is_active(depsgraph)) { - BKE_sculpt_update_object_before_eval(ob); - } - -#if 0 /* XXX This is already taken care of in mesh_calc_modifiers()... */ - if (need_mapping) { - /* Also add the flag so that it is recorded in lastDataMask. */ - dataMask->vmask |= CD_MASK_ORIGINDEX; - dataMask->emask |= CD_MASK_ORIGINDEX; - dataMask->pmask |= CD_MASK_ORIGINDEX; - } -#endif - - Mesh *mesh_eval = NULL, *mesh_deform_eval = NULL; - mesh_calc_modifiers(depsgraph, - scene, - ob, - 1, - need_mapping, - dataMask, - -1, - true, - true, - &mesh_deform_eval, - &mesh_eval); - - /* The modifier stack evaluation is storing result in mesh->runtime.mesh_eval, but this result - * is not guaranteed to be owned by object. - * - * Check ownership now, since later on we can not go to a mesh owned by someone else via - * object's runtime: this could cause access freed data on depsgraph destruction (mesh who owns - * the final result might be freed prior to object). */ - Mesh *mesh = ob->data; - const bool is_mesh_eval_owned = (mesh_eval != mesh->runtime.mesh_eval); - BKE_object_eval_assign_data(ob, &mesh_eval->id, is_mesh_eval_owned); - - ob->runtime.mesh_deform_eval = mesh_deform_eval; - ob->runtime.last_data_mask = *dataMask; - ob->runtime.last_need_mapping = need_mapping; - - BKE_object_boundbox_calc_from_mesh(ob, mesh_eval); - - /* Make sure that drivers can target shapekey properties. - * Note that this causes a potential inconsistency, as the shapekey may have a - * different topology than the evaluated mesh. */ - BLI_assert(mesh->key == NULL || DEG_is_evaluated_id(&mesh->key->id)); - mesh_eval->key = mesh->key; - - if ((ob->mode & OB_MODE_ALL_SCULPT) && ob->sculpt) { - if (DEG_is_active(depsgraph)) { - BKE_sculpt_update_object_after_eval(depsgraph, ob); - } - } - - mesh_runtime_check_normals_valid(mesh_eval); - mesh_build_extra_data(depsgraph, ob, mesh_eval); -} - -static void editbmesh_build_data(struct Depsgraph *depsgraph, - Scene *scene, - Object *obedit, - BMEditMesh *em, - CustomData_MeshMasks *dataMask) -{ - BLI_assert(obedit->id.tag & LIB_TAG_COPIED_ON_WRITE); - - BKE_object_free_derived_caches(obedit); - if (DEG_is_active(depsgraph)) { - BKE_sculpt_update_object_before_eval(obedit); - } - - BKE_editmesh_free_derivedmesh(em); - - Mesh *me_cage; - Mesh *me_final; - - editbmesh_calc_modifiers(depsgraph, scene, obedit, em, dataMask, &me_cage, &me_final); - - em->mesh_eval_final = me_final; - em->mesh_eval_cage = me_cage; - - BKE_object_boundbox_calc_from_mesh(obedit, em->mesh_eval_final); - - em->lastDataMask = *dataMask; - - mesh_runtime_check_normals_valid(em->mesh_eval_final); -} - -static void object_get_datamask(const Depsgraph *depsgraph, - Object *ob, - CustomData_MeshMasks *r_mask, - bool *r_need_mapping) -{ - ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph); - - DEG_get_customdata_mask_for_object(depsgraph, ob, r_mask); - - if (r_need_mapping) { - *r_need_mapping = false; - } - - /* Must never access original objects when dependency graph is not active: it might be already - * freed. */ - if (!DEG_is_active(depsgraph)) { - return; - } - - Object *actob = view_layer->basact ? DEG_get_original_object(view_layer->basact->object) : NULL; - if (DEG_get_original_object(ob) == actob) { - bool editing = BKE_paint_select_face_test(actob); - - /* weight paint and face select need original indices because of selection buffer drawing */ - if (r_need_mapping) { - *r_need_mapping = (editing || (ob->mode & (OB_MODE_WEIGHT_PAINT | OB_MODE_VERTEX_PAINT))); - } - - /* check if we need tfaces & mcols due to face select or texture paint */ - if ((ob->mode & OB_MODE_TEXTURE_PAINT) || editing) { - r_mask->lmask |= CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL; - r_mask->fmask |= CD_MASK_MTFACE; - } - - /* check if we need mcols due to vertex paint or weightpaint */ - if (ob->mode & OB_MODE_VERTEX_PAINT) { - r_mask->lmask |= CD_MASK_MLOOPCOL; - } - - if (ob->mode & OB_MODE_WEIGHT_PAINT) { - r_mask->vmask |= CD_MASK_MDEFORMVERT; - } - - if (ob->mode & OB_MODE_EDIT) { - r_mask->vmask |= CD_MASK_MVERT_SKIN; - } - } -} - -void makeDerivedMesh(struct Depsgraph *depsgraph, - Scene *scene, - Object *ob, - BMEditMesh *em, - const CustomData_MeshMasks *dataMask) -{ - bool need_mapping; - CustomData_MeshMasks cddata_masks = *dataMask; - object_get_datamask(depsgraph, ob, &cddata_masks, &need_mapping); - - if (em) { - editbmesh_build_data(depsgraph, scene, ob, em, &cddata_masks); - } - else { - mesh_build_data(depsgraph, scene, ob, &cddata_masks, need_mapping); - } -} - -/***/ - -Mesh *mesh_get_eval_final(struct Depsgraph *depsgraph, - Scene *scene, - Object *ob, - const CustomData_MeshMasks *dataMask) -{ - /* This function isn't thread-safe and can't be used during evaluation. */ - BLI_assert(DEG_is_evaluating(depsgraph) == false); - - /* Evaluated meshes aren't supposed to be created on original instances. If you do, - * they aren't cleaned up properly on mode switch, causing crashes, e.g T58150. */ - BLI_assert(ob->id.tag & LIB_TAG_COPIED_ON_WRITE); - - /* if there's no evaluated mesh or the last data mask used doesn't include - * the data we need, rebuild the derived mesh - */ - bool need_mapping; - CustomData_MeshMasks cddata_masks = *dataMask; - object_get_datamask(depsgraph, ob, &cddata_masks, &need_mapping); - - Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob); - if ((mesh_eval == NULL) || - !CustomData_MeshMasks_are_matching(&(ob->runtime.last_data_mask), &cddata_masks) || - (need_mapping && !ob->runtime.last_need_mapping)) { - CustomData_MeshMasks_update(&cddata_masks, &ob->runtime.last_data_mask); - mesh_build_data( - depsgraph, scene, ob, &cddata_masks, need_mapping || ob->runtime.last_need_mapping); - mesh_eval = BKE_object_get_evaluated_mesh(ob); - } - - if (mesh_eval != NULL) { - BLI_assert(!(mesh_eval->runtime.cd_dirty_vert & CD_MASK_NORMAL)); - } - return mesh_eval; -} - -Mesh *mesh_get_eval_deform(struct Depsgraph *depsgraph, - Scene *scene, - Object *ob, - const CustomData_MeshMasks *dataMask) -{ - /* This function isn't thread-safe and can't be used during evaluation. */ - BLI_assert(DEG_is_evaluating(depsgraph) == false); - - /* Evaluated meshes aren't supposed to be created on original instances. If you do, - * they aren't cleaned up properly on mode switch, causing crashes, e.g T58150. */ - BLI_assert(ob->id.tag & LIB_TAG_COPIED_ON_WRITE); - - /* if there's no derived mesh or the last data mask used doesn't include - * the data we need, rebuild the derived mesh - */ - bool need_mapping; - - CustomData_MeshMasks cddata_masks = *dataMask; - object_get_datamask(depsgraph, ob, &cddata_masks, &need_mapping); - - if (!ob->runtime.mesh_deform_eval || - !CustomData_MeshMasks_are_matching(&(ob->runtime.last_data_mask), &cddata_masks) || - (need_mapping && !ob->runtime.last_need_mapping)) { - CustomData_MeshMasks_update(&cddata_masks, &ob->runtime.last_data_mask); - mesh_build_data( - depsgraph, scene, ob, &cddata_masks, need_mapping || ob->runtime.last_need_mapping); - } - - return ob->runtime.mesh_deform_eval; -} - -Mesh *mesh_create_eval_final(Depsgraph *depsgraph, - Scene *scene, - Object *ob, - const CustomData_MeshMasks *dataMask) -{ - Mesh *final; - - mesh_calc_modifiers(depsgraph, scene, ob, 1, false, dataMask, -1, false, false, NULL, &final); - - return final; -} - -Mesh *mesh_create_eval_final_index_render(Depsgraph *depsgraph, - Scene *scene, - Object *ob, - const CustomData_MeshMasks *dataMask, - int index) -{ - Mesh *final; - - mesh_calc_modifiers(depsgraph, scene, ob, 1, false, dataMask, index, false, false, NULL, &final); - - return final; -} - -Mesh *mesh_create_eval_no_deform(Depsgraph *depsgraph, - Scene *scene, - Object *ob, - const CustomData_MeshMasks *dataMask) -{ - Mesh *final; - - mesh_calc_modifiers(depsgraph, scene, ob, 0, false, dataMask, -1, false, false, NULL, &final); - - return final; -} - -Mesh *mesh_create_eval_no_deform_render(Depsgraph *depsgraph, - Scene *scene, - Object *ob, - const CustomData_MeshMasks *dataMask) -{ - Mesh *final; - - mesh_calc_modifiers(depsgraph, scene, ob, 0, false, dataMask, -1, false, false, NULL, &final); - - return final; -} - -/***/ - -Mesh *editbmesh_get_eval_cage_and_final(Depsgraph *depsgraph, - Scene *scene, - Object *obedit, - BMEditMesh *em, - const CustomData_MeshMasks *dataMask, - /* return args */ - Mesh **r_final) -{ - CustomData_MeshMasks cddata_masks = *dataMask; - - /* if there's no derived mesh or the last data mask used doesn't include - * the data we need, rebuild the derived mesh - */ - object_get_datamask(depsgraph, obedit, &cddata_masks, NULL); - - if (!em->mesh_eval_cage || - !CustomData_MeshMasks_are_matching(&(em->lastDataMask), &cddata_masks)) { - editbmesh_build_data(depsgraph, scene, obedit, em, &cddata_masks); - } - - *r_final = em->mesh_eval_final; - if (em->mesh_eval_final) { - BLI_assert(!(em->mesh_eval_final->runtime.cd_dirty_vert & DM_DIRTY_NORMALS)); - } - return em->mesh_eval_cage; -} - -Mesh *editbmesh_get_eval_cage(struct Depsgraph *depsgraph, - Scene *scene, - Object *obedit, - BMEditMesh *em, - const CustomData_MeshMasks *dataMask) -{ - CustomData_MeshMasks cddata_masks = *dataMask; - - /* if there's no derived mesh or the last data mask used doesn't include - * the data we need, rebuild the derived mesh - */ - object_get_datamask(depsgraph, obedit, &cddata_masks, NULL); - - if (!em->mesh_eval_cage || - !CustomData_MeshMasks_are_matching(&(em->lastDataMask), &cddata_masks)) { - editbmesh_build_data(depsgraph, scene, obedit, em, &cddata_masks); - } - - return em->mesh_eval_cage; -} - -Mesh *editbmesh_get_eval_cage_from_orig(struct Depsgraph *depsgraph, - Scene *scene, - Object *obedit, - const CustomData_MeshMasks *dataMask) -{ - BLI_assert((obedit->id.tag & LIB_TAG_COPIED_ON_WRITE) == 0); - Scene *scene_eval = (Scene *)DEG_get_evaluated_id(depsgraph, &scene->id); - Object *obedit_eval = (Object *)DEG_get_evaluated_id(depsgraph, &obedit->id); - BMEditMesh *em_eval = BKE_editmesh_from_object(obedit_eval); - return editbmesh_get_eval_cage(depsgraph, scene_eval, obedit_eval, em_eval, dataMask); -} - -/***/ - -/* same as above but for vert coords */ -typedef struct { - float (*vertexcos)[3]; - BLI_bitmap *vertex_visit; -} MappedUserData; - -static void make_vertexcos__mapFunc(void *userData, - int index, - const float co[3], - const float UNUSED(no_f[3]), - const short UNUSED(no_s[3])) -{ - MappedUserData *mappedData = (MappedUserData *)userData; - - if (BLI_BITMAP_TEST(mappedData->vertex_visit, index) == 0) { - /* we need coord from prototype vertex, not from copies, - * assume they stored in the beginning of vertex array stored in DM - * (mirror modifier for eg does this) */ - copy_v3_v3(mappedData->vertexcos[index], co); - BLI_BITMAP_ENABLE(mappedData->vertex_visit, index); - } -} - -void mesh_get_mapped_verts_coords(Mesh *me_eval, float (*r_cos)[3], const int totcos) -{ - if (me_eval->runtime.deformed_only == false) { - MappedUserData userData; - memset(r_cos, 0, sizeof(*r_cos) * totcos); - userData.vertexcos = r_cos; - userData.vertex_visit = BLI_BITMAP_NEW(totcos, "vertexcos flags"); - BKE_mesh_foreach_mapped_vert(me_eval, make_vertexcos__mapFunc, &userData, MESH_FOREACH_NOP); - MEM_freeN(userData.vertex_visit); - } - else { - MVert *mv = me_eval->mvert; - for (int i = 0; i < totcos; i++, mv++) { - copy_v3_v3(r_cos[i], mv->co); - } - } -} - -void DM_calc_loop_tangents(DerivedMesh *dm, - bool calc_active_tangent, - const char (*tangent_names)[MAX_NAME], - int tangent_names_len) -{ - BKE_mesh_calc_loop_tangent_ex(dm->getVertArray(dm), - dm->getPolyArray(dm), - dm->getNumPolys(dm), - dm->getLoopArray(dm), - dm->getLoopTriArray(dm), - dm->getNumLoopTri(dm), - &dm->loopData, - calc_active_tangent, - tangent_names, - tangent_names_len, - CustomData_get_layer(&dm->polyData, CD_NORMAL), - dm->getLoopDataArray(dm, CD_NORMAL), - dm->getVertDataArray(dm, CD_ORCO), /* may be NULL */ - /* result */ - &dm->loopData, - dm->getNumLoops(dm), - &dm->tangent_mask); -} - -static void mesh_init_origspace(Mesh *mesh) -{ - const float default_osf[4][2] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}}; - - OrigSpaceLoop *lof_array = CustomData_get_layer(&mesh->ldata, CD_ORIGSPACE_MLOOP); - const int numpoly = mesh->totpoly; - // const int numloop = mesh->totloop; - MVert *mv = mesh->mvert; - MLoop *ml = mesh->mloop; - MPoly *mp = mesh->mpoly; - int i, j, k; - - float(*vcos_2d)[2] = NULL; - BLI_array_staticdeclare(vcos_2d, 64); - - for (i = 0; i < numpoly; i++, mp++) { - OrigSpaceLoop *lof = lof_array + mp->loopstart; - - if (ELEM(mp->totloop, 3, 4)) { - for (j = 0; j < mp->totloop; j++, lof++) { - copy_v2_v2(lof->uv, default_osf[j]); - } - } - else { - MLoop *l = &ml[mp->loopstart]; - float p_nor[3], co[3]; - float mat[3][3]; - - float min[2] = {FLT_MAX, FLT_MAX}, max[2] = {-FLT_MAX, -FLT_MAX}; - float translate[2], scale[2]; - - BKE_mesh_calc_poly_normal(mp, l, mv, p_nor); - axis_dominant_v3_to_m3(mat, p_nor); - - BLI_array_clear(vcos_2d); - BLI_array_reserve(vcos_2d, mp->totloop); - for (j = 0; j < mp->totloop; j++, l++) { - mul_v3_m3v3(co, mat, mv[l->v].co); - copy_v2_v2(vcos_2d[j], co); - - for (k = 0; k < 2; k++) { - if (co[k] > max[k]) { - max[k] = co[k]; - } - else if (co[k] < min[k]) { - min[k] = co[k]; - } - } - } - - /* Brings min to (0, 0). */ - negate_v2_v2(translate, min); - - /* Scale will bring max to (1, 1). */ - sub_v2_v2v2(scale, max, min); - if (scale[0] == 0.0f) { - scale[0] = 1e-9f; - } - if (scale[1] == 0.0f) { - scale[1] = 1e-9f; - } - invert_v2(scale); - - /* Finally, transform all vcos_2d into ((0, 0), (1, 1)) - * square and assign them as origspace. */ - for (j = 0; j < mp->totloop; j++, lof++) { - add_v2_v2v2(lof->uv, vcos_2d[j], translate); - mul_v2_v2(lof->uv, scale); - } - } - } - - BKE_mesh_tessface_clear(mesh); - BLI_array_free(vcos_2d); -} - -/* derivedmesh info printing function, - * to help track down differences DM output */ - -#ifndef NDEBUG -# include "BLI_dynstr.h" - -static void dm_debug_info_layers(DynStr *dynstr, - DerivedMesh *dm, - CustomData *cd, - void *(*getElemDataArray)(DerivedMesh *, int)) -{ - int type; - - for (type = 0; type < CD_NUMTYPES; type++) { - if (CustomData_has_layer(cd, type)) { - /* note: doesn't account for multiple layers */ - const char *name = CustomData_layertype_name(type); - const int size = CustomData_sizeof(type); - const void *pt = getElemDataArray(dm, type); - const int pt_size = pt ? (int)(MEM_allocN_len(pt) / size) : 0; - const char *structname; - int structnum; - CustomData_file_write_info(type, &structname, &structnum); - BLI_dynstr_appendf( - dynstr, - " dict(name='%s', struct='%s', type=%d, ptr='%p', elem=%d, length=%d),\n", - name, - structname, - type, - (const void *)pt, - size, - pt_size); - } - } -} - -char *DM_debug_info(DerivedMesh *dm) -{ - DynStr *dynstr = BLI_dynstr_new(); - char *ret; - const char *tstr; - - BLI_dynstr_append(dynstr, "{\n"); - BLI_dynstr_appendf(dynstr, " 'ptr': '%p',\n", (void *)dm); - switch (dm->type) { - case DM_TYPE_CDDM: - tstr = "DM_TYPE_CDDM"; - break; - case DM_TYPE_CCGDM: - tstr = "DM_TYPE_CCGDM"; - break; - default: - tstr = "UNKNOWN"; - break; - } - BLI_dynstr_appendf(dynstr, " 'type': '%s',\n", tstr); - BLI_dynstr_appendf(dynstr, " 'numVertData': %d,\n", dm->numVertData); - BLI_dynstr_appendf(dynstr, " 'numEdgeData': %d,\n", dm->numEdgeData); - BLI_dynstr_appendf(dynstr, " 'numTessFaceData': %d,\n", dm->numTessFaceData); - BLI_dynstr_appendf(dynstr, " 'numPolyData': %d,\n", dm->numPolyData); - BLI_dynstr_appendf(dynstr, " 'deformedOnly': %d,\n", dm->deformedOnly); - - BLI_dynstr_append(dynstr, " 'vertexLayers': (\n"); - dm_debug_info_layers(dynstr, dm, &dm->vertData, dm->getVertDataArray); - BLI_dynstr_append(dynstr, " ),\n"); - - BLI_dynstr_append(dynstr, " 'edgeLayers': (\n"); - dm_debug_info_layers(dynstr, dm, &dm->edgeData, dm->getEdgeDataArray); - BLI_dynstr_append(dynstr, " ),\n"); - - BLI_dynstr_append(dynstr, " 'loopLayers': (\n"); - dm_debug_info_layers(dynstr, dm, &dm->loopData, dm->getLoopDataArray); - BLI_dynstr_append(dynstr, " ),\n"); - - BLI_dynstr_append(dynstr, " 'polyLayers': (\n"); - dm_debug_info_layers(dynstr, dm, &dm->polyData, dm->getPolyDataArray); - BLI_dynstr_append(dynstr, " ),\n"); - - BLI_dynstr_append(dynstr, " 'tessFaceLayers': (\n"); - dm_debug_info_layers(dynstr, dm, &dm->faceData, dm->getTessFaceDataArray); - BLI_dynstr_append(dynstr, " ),\n"); - - BLI_dynstr_append(dynstr, "}\n"); - - ret = BLI_dynstr_get_cstring(dynstr); - BLI_dynstr_free(dynstr); - return ret; -} - -void DM_debug_print(DerivedMesh *dm) -{ - char *str = DM_debug_info(dm); - puts(str); - fflush(stdout); - MEM_freeN(str); -} - -bool DM_is_valid(DerivedMesh *dm) -{ - const bool do_verbose = true; - const bool do_fixes = false; - - bool is_valid = true; - bool changed = true; - - is_valid &= BKE_mesh_validate_all_customdata( - dm->getVertDataLayout(dm), - dm->getNumVerts(dm), - dm->getEdgeDataLayout(dm), - dm->getNumEdges(dm), - dm->getLoopDataLayout(dm), - dm->getNumLoops(dm), - dm->getPolyDataLayout(dm), - dm->getNumPolys(dm), - false, /* setting mask here isn't useful, gives false positives */ - do_verbose, - do_fixes, - &changed); - - is_valid &= BKE_mesh_validate_arrays(NULL, - dm->getVertArray(dm), - dm->getNumVerts(dm), - dm->getEdgeArray(dm), - dm->getNumEdges(dm), - dm->getTessFaceArray(dm), - dm->getNumTessFaces(dm), - dm->getLoopArray(dm), - dm->getNumLoops(dm), - dm->getPolyArray(dm), - dm->getNumPolys(dm), - dm->getVertDataArray(dm, CD_MDEFORMVERT), - do_verbose, - do_fixes, - &changed); - - BLI_assert(changed == false); - - return is_valid; -} - -#endif /* NDEBUG */ diff --git a/source/blender/blenkernel/intern/DerivedMesh.cc b/source/blender/blenkernel/intern/DerivedMesh.cc new file mode 100644 index 00000000000..78d4ad6fe19 --- /dev/null +++ b/source/blender/blenkernel/intern/DerivedMesh.cc @@ -0,0 +1,2410 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup bke + */ + +#include +#include + +#include "MEM_guardedalloc.h" + +#include "DNA_cloth_types.h" +#include "DNA_customdata_types.h" +#include "DNA_key_types.h" +#include "DNA_material_types.h" +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" + +#include "BLI_array.h" +#include "BLI_bitmap.h" +#include "BLI_blenlib.h" +#include "BLI_float2.hh" +#include "BLI_linklist.h" +#include "BLI_math.h" +#include "BLI_task.h" +#include "BLI_utildefines.h" +#include "BLI_vector.hh" + +#include "BKE_DerivedMesh.h" +#include "BKE_bvhutils.h" +#include "BKE_colorband.h" +#include "BKE_deform.h" +#include "BKE_editmesh.h" +#include "BKE_key.h" +#include "BKE_layer.h" +#include "BKE_lib_id.h" +#include "BKE_material.h" +#include "BKE_mesh.h" +#include "BKE_mesh_iterators.h" +#include "BKE_mesh_mapping.h" +#include "BKE_mesh_runtime.h" +#include "BKE_mesh_tangent.h" +#include "BKE_mesh_wrapper.h" +#include "BKE_modifier.h" +#include "BKE_multires.h" +#include "BKE_object.h" +#include "BKE_object_deform.h" +#include "BKE_paint.h" + +#include "BLI_sys_types.h" /* for intptr_t support */ + +#include "BKE_shrinkwrap.h" +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" + +#include "CLG_log.h" + +#ifdef WITH_OPENSUBDIV +# include "DNA_userdef_types.h" +#endif + +/* very slow! enable for testing only! */ +//#define USE_MODIFIER_VALIDATE + +#ifdef USE_MODIFIER_VALIDATE +# define ASSERT_IS_VALID_MESH(mesh) \ + (BLI_assert((mesh == nullptr) || (BKE_mesh_is_valid(mesh) == true))) +#else +# define ASSERT_IS_VALID_MESH(mesh) +#endif + +static ThreadRWMutex loops_cache_lock = PTHREAD_RWLOCK_INITIALIZER; + +static void mesh_init_origspace(Mesh *mesh); +static void editbmesh_calc_modifier_final_normals(Mesh *mesh_final, + const CustomData_MeshMasks *final_datamask); + +/* -------------------------------------------------------------------- */ + +static MVert *dm_getVertArray(DerivedMesh *dm) +{ + MVert *mvert = (MVert *)CustomData_get_layer(&dm->vertData, CD_MVERT); + + if (!mvert) { + mvert = (MVert *)CustomData_add_layer( + &dm->vertData, CD_MVERT, CD_CALLOC, nullptr, dm->getNumVerts(dm)); + CustomData_set_layer_flag(&dm->vertData, CD_MVERT, CD_FLAG_TEMPORARY); + dm->copyVertArray(dm, mvert); + } + + return mvert; +} + +static MEdge *dm_getEdgeArray(DerivedMesh *dm) +{ + MEdge *medge = (MEdge *)CustomData_get_layer(&dm->edgeData, CD_MEDGE); + + if (!medge) { + medge = (MEdge *)CustomData_add_layer( + &dm->edgeData, CD_MEDGE, CD_CALLOC, nullptr, dm->getNumEdges(dm)); + CustomData_set_layer_flag(&dm->edgeData, CD_MEDGE, CD_FLAG_TEMPORARY); + dm->copyEdgeArray(dm, medge); + } + + return medge; +} + +static MFace *dm_getTessFaceArray(DerivedMesh *dm) +{ + MFace *mface = (MFace *)CustomData_get_layer(&dm->faceData, CD_MFACE); + + if (!mface) { + int numTessFaces = dm->getNumTessFaces(dm); + + if (!numTessFaces) { + /* Do not add layer if there's no elements in it, this leads to issues later when + * this layer is needed with non-zero size, but currently CD stuff does not check + * for requested layer size on creation and just returns layer which was previously + * added (sergey) */ + return nullptr; + } + + mface = (MFace *)CustomData_add_layer( + &dm->faceData, CD_MFACE, CD_CALLOC, nullptr, numTessFaces); + CustomData_set_layer_flag(&dm->faceData, CD_MFACE, CD_FLAG_TEMPORARY); + dm->copyTessFaceArray(dm, mface); + } + + return mface; +} + +static MLoop *dm_getLoopArray(DerivedMesh *dm) +{ + MLoop *mloop = (MLoop *)CustomData_get_layer(&dm->loopData, CD_MLOOP); + + if (!mloop) { + mloop = (MLoop *)CustomData_add_layer( + &dm->loopData, CD_MLOOP, CD_CALLOC, nullptr, dm->getNumLoops(dm)); + CustomData_set_layer_flag(&dm->loopData, CD_MLOOP, CD_FLAG_TEMPORARY); + dm->copyLoopArray(dm, mloop); + } + + return mloop; +} + +static MPoly *dm_getPolyArray(DerivedMesh *dm) +{ + MPoly *mpoly = (MPoly *)CustomData_get_layer(&dm->polyData, CD_MPOLY); + + if (!mpoly) { + mpoly = (MPoly *)CustomData_add_layer( + &dm->polyData, CD_MPOLY, CD_CALLOC, nullptr, dm->getNumPolys(dm)); + CustomData_set_layer_flag(&dm->polyData, CD_MPOLY, CD_FLAG_TEMPORARY); + dm->copyPolyArray(dm, mpoly); + } + + return mpoly; +} + +static MVert *dm_dupVertArray(DerivedMesh *dm) +{ + MVert *tmp = (MVert *)MEM_malloc_arrayN( + dm->getNumVerts(dm), sizeof(*tmp), "dm_dupVertArray tmp"); + + if (tmp) { + dm->copyVertArray(dm, tmp); + } + + return tmp; +} + +static MEdge *dm_dupEdgeArray(DerivedMesh *dm) +{ + MEdge *tmp = (MEdge *)MEM_malloc_arrayN( + dm->getNumEdges(dm), sizeof(*tmp), "dm_dupEdgeArray tmp"); + + if (tmp) { + dm->copyEdgeArray(dm, tmp); + } + + return tmp; +} + +static MFace *dm_dupFaceArray(DerivedMesh *dm) +{ + MFace *tmp = (MFace *)MEM_malloc_arrayN( + dm->getNumTessFaces(dm), sizeof(*tmp), "dm_dupFaceArray tmp"); + + if (tmp) { + dm->copyTessFaceArray(dm, tmp); + } + + return tmp; +} + +static MLoop *dm_dupLoopArray(DerivedMesh *dm) +{ + MLoop *tmp = (MLoop *)MEM_malloc_arrayN( + dm->getNumLoops(dm), sizeof(*tmp), "dm_dupLoopArray tmp"); + + if (tmp) { + dm->copyLoopArray(dm, tmp); + } + + return tmp; +} + +static MPoly *dm_dupPolyArray(DerivedMesh *dm) +{ + MPoly *tmp = (MPoly *)MEM_malloc_arrayN( + dm->getNumPolys(dm), sizeof(*tmp), "dm_dupPolyArray tmp"); + + if (tmp) { + dm->copyPolyArray(dm, tmp); + } + + return tmp; +} + +static int dm_getNumLoopTri(DerivedMesh *dm) +{ + const int numlooptris = poly_to_tri_count(dm->getNumPolys(dm), dm->getNumLoops(dm)); + BLI_assert(ELEM(dm->looptris.num, 0, numlooptris)); + return numlooptris; +} + +static const MLoopTri *dm_getLoopTriArray(DerivedMesh *dm) +{ + MLoopTri *looptri; + + BLI_rw_mutex_lock(&loops_cache_lock, THREAD_LOCK_READ); + looptri = dm->looptris.array; + BLI_rw_mutex_unlock(&loops_cache_lock); + + if (looptri != nullptr) { + BLI_assert(dm->getNumLoopTri(dm) == dm->looptris.num); + } + else { + BLI_rw_mutex_lock(&loops_cache_lock, THREAD_LOCK_WRITE); + /* We need to ensure array is still nullptr inside mutex-protected code, + * some other thread might have already recomputed those looptris. */ + if (dm->looptris.array == nullptr) { + dm->recalcLoopTri(dm); + } + looptri = dm->looptris.array; + BLI_rw_mutex_unlock(&loops_cache_lock); + } + return looptri; +} + +static CustomData *dm_getVertCData(DerivedMesh *dm) +{ + return &dm->vertData; +} + +static CustomData *dm_getEdgeCData(DerivedMesh *dm) +{ + return &dm->edgeData; +} + +static CustomData *dm_getTessFaceCData(DerivedMesh *dm) +{ + return &dm->faceData; +} + +static CustomData *dm_getLoopCData(DerivedMesh *dm) +{ + return &dm->loopData; +} + +static CustomData *dm_getPolyCData(DerivedMesh *dm) +{ + return &dm->polyData; +} + +/** + * Utility function to initialize a DerivedMesh's function pointers to + * the default implementation (for those functions which have a default) + */ +void DM_init_funcs(DerivedMesh *dm) +{ + /* default function implementations */ + dm->getVertArray = dm_getVertArray; + dm->getEdgeArray = dm_getEdgeArray; + dm->getTessFaceArray = dm_getTessFaceArray; + dm->getLoopArray = dm_getLoopArray; + dm->getPolyArray = dm_getPolyArray; + dm->dupVertArray = dm_dupVertArray; + dm->dupEdgeArray = dm_dupEdgeArray; + dm->dupTessFaceArray = dm_dupFaceArray; + dm->dupLoopArray = dm_dupLoopArray; + dm->dupPolyArray = dm_dupPolyArray; + + dm->getLoopTriArray = dm_getLoopTriArray; + + /* subtypes handle getting actual data */ + dm->getNumLoopTri = dm_getNumLoopTri; + + dm->getVertDataLayout = dm_getVertCData; + dm->getEdgeDataLayout = dm_getEdgeCData; + dm->getTessFaceDataLayout = dm_getTessFaceCData; + dm->getLoopDataLayout = dm_getLoopCData; + dm->getPolyDataLayout = dm_getPolyCData; + + dm->getVertData = DM_get_vert_data; + dm->getEdgeData = DM_get_edge_data; + dm->getTessFaceData = DM_get_tessface_data; + dm->getPolyData = DM_get_poly_data; + dm->getVertDataArray = DM_get_vert_data_layer; + dm->getEdgeDataArray = DM_get_edge_data_layer; + dm->getTessFaceDataArray = DM_get_tessface_data_layer; + dm->getPolyDataArray = DM_get_poly_data_layer; + dm->getLoopDataArray = DM_get_loop_data_layer; +} + +/** + * Utility function to initialize a DerivedMesh for the desired number + * of vertices, edges and faces (doesn't allocate memory for them, just + * sets up the custom data layers) + */ +void DM_init(DerivedMesh *dm, + DerivedMeshType type, + int numVerts, + int numEdges, + int numTessFaces, + int numLoops, + int numPolys) +{ + dm->type = type; + dm->numVertData = numVerts; + dm->numEdgeData = numEdges; + dm->numTessFaceData = numTessFaces; + dm->numLoopData = numLoops; + dm->numPolyData = numPolys; + + DM_init_funcs(dm); + + dm->needsFree = 1; + dm->dirty = (DMDirtyFlag)0; + + /* don't use CustomData_reset(...); because we dont want to touch customdata */ + copy_vn_i(dm->vertData.typemap, CD_NUMTYPES, -1); + copy_vn_i(dm->edgeData.typemap, CD_NUMTYPES, -1); + copy_vn_i(dm->faceData.typemap, CD_NUMTYPES, -1); + copy_vn_i(dm->loopData.typemap, CD_NUMTYPES, -1); + copy_vn_i(dm->polyData.typemap, CD_NUMTYPES, -1); +} + +/** + * Utility function to initialize a DerivedMesh for the desired number + * of vertices, edges and faces, with a layer setup copied from source + */ +void DM_from_template_ex(DerivedMesh *dm, + DerivedMesh *source, + DerivedMeshType type, + int numVerts, + int numEdges, + int numTessFaces, + int numLoops, + int numPolys, + const CustomData_MeshMasks *mask) +{ + CustomData_copy(&source->vertData, &dm->vertData, mask->vmask, CD_CALLOC, numVerts); + CustomData_copy(&source->edgeData, &dm->edgeData, mask->emask, CD_CALLOC, numEdges); + CustomData_copy(&source->faceData, &dm->faceData, mask->fmask, CD_CALLOC, numTessFaces); + CustomData_copy(&source->loopData, &dm->loopData, mask->lmask, CD_CALLOC, numLoops); + CustomData_copy(&source->polyData, &dm->polyData, mask->pmask, CD_CALLOC, numPolys); + + dm->cd_flag = source->cd_flag; + + dm->type = type; + dm->numVertData = numVerts; + dm->numEdgeData = numEdges; + dm->numTessFaceData = numTessFaces; + dm->numLoopData = numLoops; + dm->numPolyData = numPolys; + + DM_init_funcs(dm); + + dm->needsFree = 1; + dm->dirty = (DMDirtyFlag)0; +} +void DM_from_template(DerivedMesh *dm, + DerivedMesh *source, + DerivedMeshType type, + int numVerts, + int numEdges, + int numTessFaces, + int numLoops, + int numPolys) +{ + DM_from_template_ex(dm, + source, + type, + numVerts, + numEdges, + numTessFaces, + numLoops, + numPolys, + &CD_MASK_DERIVEDMESH); +} + +bool DM_release(DerivedMesh *dm) +{ + if (dm->needsFree) { + CustomData_free(&dm->vertData, dm->numVertData); + CustomData_free(&dm->edgeData, dm->numEdgeData); + CustomData_free(&dm->faceData, dm->numTessFaceData); + CustomData_free(&dm->loopData, dm->numLoopData); + CustomData_free(&dm->polyData, dm->numPolyData); + + MEM_SAFE_FREE(dm->looptris.array); + dm->looptris.num = 0; + dm->looptris.num_alloc = 0; + + return true; + } + + CustomData_free_temporary(&dm->vertData, dm->numVertData); + CustomData_free_temporary(&dm->edgeData, dm->numEdgeData); + CustomData_free_temporary(&dm->faceData, dm->numTessFaceData); + CustomData_free_temporary(&dm->loopData, dm->numLoopData); + CustomData_free_temporary(&dm->polyData, dm->numPolyData); + + return false; +} + +void DM_DupPolys(DerivedMesh *source, DerivedMesh *target) +{ + CustomData_free(&target->loopData, source->numLoopData); + CustomData_free(&target->polyData, source->numPolyData); + + CustomData_copy(&source->loopData, + &target->loopData, + CD_MASK_DERIVEDMESH.lmask, + CD_DUPLICATE, + source->numLoopData); + CustomData_copy(&source->polyData, + &target->polyData, + CD_MASK_DERIVEDMESH.pmask, + CD_DUPLICATE, + source->numPolyData); + + target->numLoopData = source->numLoopData; + target->numPolyData = source->numPolyData; + + if (!CustomData_has_layer(&target->polyData, CD_MPOLY)) { + MPoly *mpoly; + MLoop *mloop; + + mloop = source->dupLoopArray(source); + mpoly = source->dupPolyArray(source); + CustomData_add_layer(&target->loopData, CD_MLOOP, CD_ASSIGN, mloop, source->numLoopData); + CustomData_add_layer(&target->polyData, CD_MPOLY, CD_ASSIGN, mpoly, source->numPolyData); + } +} + +void DM_ensure_normals(DerivedMesh *dm) +{ + if (dm->dirty & DM_DIRTY_NORMALS) { + dm->calcNormals(dm); + } + BLI_assert((dm->dirty & DM_DIRTY_NORMALS) == 0); +} + +/** + * Ensure the array is large enough + * + * \note This function must always be thread-protected by caller. + * It should only be used by internal code. + */ +void DM_ensure_looptri_data(DerivedMesh *dm) +{ + const unsigned int totpoly = dm->numPolyData; + const unsigned int totloop = dm->numLoopData; + const int looptris_num = poly_to_tri_count(totpoly, totloop); + + BLI_assert(dm->looptris.array_wip == nullptr); + + SWAP(MLoopTri *, dm->looptris.array, dm->looptris.array_wip); + + if ((looptris_num > dm->looptris.num_alloc) || (looptris_num < dm->looptris.num_alloc * 2) || + (totpoly == 0)) { + MEM_SAFE_FREE(dm->looptris.array_wip); + dm->looptris.num_alloc = 0; + dm->looptris.num = 0; + } + + if (totpoly) { + if (dm->looptris.array_wip == nullptr) { + dm->looptris.array_wip = (MLoopTri *)MEM_malloc_arrayN( + looptris_num, sizeof(*dm->looptris.array_wip), __func__); + dm->looptris.num_alloc = looptris_num; + } + + dm->looptris.num = looptris_num; + } +} + +/** Utility function to convert an (evaluated) Mesh to a shape key block. */ +/* Just a shallow wrapper around BKE_keyblock_convert_from_mesh, + * that ensures both evaluated mesh and original one has same number of vertices. */ +void BKE_mesh_runtime_eval_to_meshkey(Mesh *me_deformed, Mesh *me, KeyBlock *kb) +{ + const int totvert = me_deformed->totvert; + + if (totvert == 0 || me->totvert == 0 || me->totvert != totvert) { + return; + } + + BKE_keyblock_convert_from_mesh(me_deformed, me->key, kb); +} + +/** + * set the CD_FLAG_NOCOPY flag in custom data layers where the mask is + * zero for the layer type, so only layer types specified by the mask + * will be copied + */ +void DM_set_only_copy(DerivedMesh *dm, const CustomData_MeshMasks *mask) +{ + CustomData_set_only_copy(&dm->vertData, mask->vmask); + CustomData_set_only_copy(&dm->edgeData, mask->emask); + CustomData_set_only_copy(&dm->faceData, mask->fmask); + /* this wasn't in 2.63 and is disabled for 2.64 because it gives problems with + * weight paint mode when there are modifiers applied, needs further investigation, + * see replies to r50969, Campbell */ +#if 0 + CustomData_set_only_copy(&dm->loopData, mask->lmask); + CustomData_set_only_copy(&dm->polyData, mask->pmask); +#endif +} + +static void mesh_set_only_copy(Mesh *mesh, const CustomData_MeshMasks *mask) +{ + CustomData_set_only_copy(&mesh->vdata, mask->vmask); + CustomData_set_only_copy(&mesh->edata, mask->emask); + CustomData_set_only_copy(&mesh->fdata, mask->fmask); + /* this wasn't in 2.63 and is disabled for 2.64 because it gives problems with + * weight paint mode when there are modifiers applied, needs further investigation, + * see replies to r50969, Campbell */ +#if 0 + CustomData_set_only_copy(&mesh->ldata, mask->lmask); + CustomData_set_only_copy(&mesh->pdata, mask->pmask); +#endif +} + +void DM_add_vert_layer(DerivedMesh *dm, int type, eCDAllocType alloctype, void *layer) +{ + CustomData_add_layer(&dm->vertData, type, alloctype, layer, dm->numVertData); +} + +void DM_add_edge_layer(DerivedMesh *dm, int type, eCDAllocType alloctype, void *layer) +{ + CustomData_add_layer(&dm->edgeData, type, alloctype, layer, dm->numEdgeData); +} + +void DM_add_tessface_layer(DerivedMesh *dm, int type, eCDAllocType alloctype, void *layer) +{ + CustomData_add_layer(&dm->faceData, type, alloctype, layer, dm->numTessFaceData); +} + +void DM_add_loop_layer(DerivedMesh *dm, int type, eCDAllocType alloctype, void *layer) +{ + CustomData_add_layer(&dm->loopData, type, alloctype, layer, dm->numLoopData); +} + +void DM_add_poly_layer(DerivedMesh *dm, int type, eCDAllocType alloctype, void *layer) +{ + CustomData_add_layer(&dm->polyData, type, alloctype, layer, dm->numPolyData); +} + +void *DM_get_vert_data(DerivedMesh *dm, int index, int type) +{ + BLI_assert(index >= 0 && index < dm->getNumVerts(dm)); + return CustomData_get(&dm->vertData, index, type); +} + +void *DM_get_edge_data(DerivedMesh *dm, int index, int type) +{ + BLI_assert(index >= 0 && index < dm->getNumEdges(dm)); + return CustomData_get(&dm->edgeData, index, type); +} + +void *DM_get_tessface_data(DerivedMesh *dm, int index, int type) +{ + BLI_assert(index >= 0 && index < dm->getNumTessFaces(dm)); + return CustomData_get(&dm->faceData, index, type); +} + +void *DM_get_poly_data(DerivedMesh *dm, int index, int type) +{ + BLI_assert(index >= 0 && index < dm->getNumPolys(dm)); + return CustomData_get(&dm->polyData, index, type); +} + +void *DM_get_vert_data_layer(DerivedMesh *dm, int type) +{ + if (type == CD_MVERT) { + return dm->getVertArray(dm); + } + + return CustomData_get_layer(&dm->vertData, type); +} + +void *DM_get_edge_data_layer(DerivedMesh *dm, int type) +{ + if (type == CD_MEDGE) { + return dm->getEdgeArray(dm); + } + + return CustomData_get_layer(&dm->edgeData, type); +} + +void *DM_get_tessface_data_layer(DerivedMesh *dm, int type) +{ + if (type == CD_MFACE) { + return dm->getTessFaceArray(dm); + } + + return CustomData_get_layer(&dm->faceData, type); +} + +void *DM_get_poly_data_layer(DerivedMesh *dm, int type) +{ + return CustomData_get_layer(&dm->polyData, type); +} + +void *DM_get_loop_data_layer(DerivedMesh *dm, int type) +{ + return CustomData_get_layer(&dm->loopData, type); +} + +void DM_copy_vert_data( + DerivedMesh *source, DerivedMesh *dest, int source_index, int dest_index, int count) +{ + CustomData_copy_data(&source->vertData, &dest->vertData, source_index, dest_index, count); +} + +/** + * interpolates vertex data from the vertices indexed by src_indices in the + * source mesh using the given weights and stores the result in the vertex + * indexed by dest_index in the dest mesh + */ +void DM_interp_vert_data(DerivedMesh *source, + DerivedMesh *dest, + int *src_indices, + float *weights, + int count, + int dest_index) +{ + CustomData_interp( + &source->vertData, &dest->vertData, src_indices, weights, nullptr, count, dest_index); +} + +static float (*get_editbmesh_orco_verts(BMEditMesh *em))[3] +{ + BMIter iter; + BMVert *eve; + float(*orco)[3]; + int i; + + /* these may not really be the orco's, but it's only for preview. + * could be solver better once, but isn't simple */ + + orco = (float(*)[3])MEM_malloc_arrayN(em->bm->totvert, sizeof(float[3]), "BMEditMesh Orco"); + + BM_ITER_MESH_INDEX (eve, &iter, em->bm, BM_VERTS_OF_MESH, i) { + copy_v3_v3(orco[i], eve->co); + } + + return orco; +} + +/* orco custom data layer */ +static float (*get_orco_coords(Object *ob, BMEditMesh *em, int layer, int *free))[3] +{ + *free = 0; + + if (layer == CD_ORCO) { + /* get original coordinates */ + *free = 1; + + if (em) { + return get_editbmesh_orco_verts(em); + } + return BKE_mesh_orco_verts_get(ob); + } + if (layer == CD_CLOTH_ORCO) { + /* apply shape key for cloth, this should really be solved + * by a more flexible customdata system, but not simple */ + if (!em) { + ClothModifierData *clmd = (ClothModifierData *)BKE_modifiers_findby_type( + ob, eModifierType_Cloth); + KeyBlock *kb = BKE_keyblock_from_key(BKE_key_from_object(ob), + clmd->sim_parms->shapekey_rest); + + if (kb && kb->data) { + return (float(*)[3])kb->data; + } + } + + return nullptr; + } + + return nullptr; +} + +static Mesh *create_orco_mesh(Object *ob, Mesh *me, BMEditMesh *em, int layer) +{ + Mesh *mesh; + float(*orco)[3]; + int free; + + if (em) { + mesh = BKE_mesh_from_bmesh_for_eval_nomain(em->bm, nullptr, me); + } + else { + mesh = BKE_mesh_copy_for_eval(me, true); + } + + orco = get_orco_coords(ob, em, layer, &free); + + if (orco) { + BKE_mesh_vert_coords_apply(mesh, orco); + if (free) { + MEM_freeN(orco); + } + } + + return mesh; +} + +static void add_orco_mesh(Object *ob, BMEditMesh *em, Mesh *mesh, Mesh *mesh_orco, int layer) +{ + float(*orco)[3], (*layerorco)[3]; + int totvert, free; + + totvert = mesh->totvert; + + if (mesh_orco) { + free = 1; + + if (mesh_orco->totvert == totvert) { + orco = BKE_mesh_vert_coords_alloc(mesh_orco, nullptr); + } + else { + orco = BKE_mesh_vert_coords_alloc(mesh, nullptr); + } + } + else { + /* TODO(sybren): totvert should potentially change here, as ob->data + * or em may have a different number of vertices than dm. */ + orco = get_orco_coords(ob, em, layer, &free); + } + + if (orco) { + if (layer == CD_ORCO) { + BKE_mesh_orco_verts_transform((Mesh *)ob->data, orco, totvert, 0); + } + + if (!(layerorco = (float(*)[3])CustomData_get_layer(&mesh->vdata, layer))) { + CustomData_add_layer(&mesh->vdata, layer, CD_CALLOC, nullptr, mesh->totvert); + BKE_mesh_update_customdata_pointers(mesh, false); + + layerorco = (float(*)[3])CustomData_get_layer(&mesh->vdata, layer); + } + + memcpy(layerorco, orco, sizeof(float[3]) * totvert); + if (free) { + MEM_freeN(orco); + } + } +} + +static void mesh_calc_modifier_final_normals(const Mesh *mesh_input, + const CustomData_MeshMasks *final_datamask, + const bool sculpt_dyntopo, + Mesh *mesh_final) +{ + /* Compute normals. */ + const bool do_loop_normals = ((mesh_input->flag & ME_AUTOSMOOTH) != 0 || + (final_datamask->lmask & CD_MASK_NORMAL) != 0); + /* Some modifiers may need this info from their target (other) object, + * simpler to generate it here as well. + * Note that they will always be generated when no loop normals are computed, + * since they are needed by drawing code. */ + const bool do_poly_normals = ((final_datamask->pmask & CD_MASK_NORMAL) != 0); + + /* In case we also need poly normals, add the layer and compute them here + * (BKE_mesh_calc_normals_split() assumes that if that data exists, it is always valid). */ + if (do_poly_normals) { + if (!CustomData_has_layer(&mesh_final->pdata, CD_NORMAL)) { + float(*polynors)[3] = (float(*)[3])CustomData_add_layer( + &mesh_final->pdata, CD_NORMAL, CD_CALLOC, nullptr, mesh_final->totpoly); + BKE_mesh_calc_normals_poly(mesh_final->mvert, + nullptr, + mesh_final->totvert, + mesh_final->mloop, + mesh_final->mpoly, + mesh_final->totloop, + mesh_final->totpoly, + polynors, + false); + } + } + + if (do_loop_normals) { + /* Compute loop normals (note: will compute poly and vert normals as well, if needed!) */ + BKE_mesh_calc_normals_split(mesh_final); + BKE_mesh_tessface_clear(mesh_final); + } + + if (sculpt_dyntopo == false) { + /* watch this! after 2.75a we move to from tessface to looptri (by default) */ + if (final_datamask->fmask & CD_MASK_MFACE) { + BKE_mesh_tessface_ensure(mesh_final); + } + + /* without this, drawing ngon tri's faces will show ugly tessellated face + * normals and will also have to calculate normals on the fly, try avoid + * this where possible since calculating polygon normals isn't fast, + * note that this isn't a problem for subsurf (only quads) or editmode + * which deals with drawing differently. + * + * Only calc vertex normals if they are flagged as dirty. + * If using loop normals, poly nors have already been computed. + */ + if (!do_loop_normals) { + BKE_mesh_ensure_normals_for_display(mesh_final); + } + } + + /* Some modifiers, like data-transfer, may generate those data as temp layer, + * we do not want to keep them, as they are used by display code when available + * (i.e. even if autosmooth is disabled). */ + if (!do_loop_normals && CustomData_has_layer(&mesh_final->ldata, CD_NORMAL)) { + CustomData_free_layers(&mesh_final->ldata, CD_NORMAL, mesh_final->totloop); + } +} + +/* Does final touches to the final evaluated mesh, making sure it is perfectly usable. + * + * This is needed because certain information is not passed along intermediate meshes allocated + * during stack evaluation. + */ +static void mesh_calc_finalize(const Mesh *mesh_input, Mesh *mesh_eval) +{ + /* Make sure the name is the same. This is because mesh allocation from template does not + * take care of naming. */ + BLI_strncpy(mesh_eval->id.name, mesh_input->id.name, sizeof(mesh_eval->id.name)); + /* Make evaluated mesh to share same edit mesh pointer as original and copied meshes. */ + mesh_eval->edit_mesh = mesh_input->edit_mesh; +} + +void BKE_mesh_wrapper_deferred_finalize(Mesh *me_eval, + const CustomData_MeshMasks *cd_mask_finalize) +{ + if (me_eval->runtime.wrapper_type_finalize & (1 << ME_WRAPPER_TYPE_BMESH)) { + editbmesh_calc_modifier_final_normals(me_eval, cd_mask_finalize); + me_eval->runtime.wrapper_type_finalize &= ~(1 << ME_WRAPPER_TYPE_BMESH); + } + BLI_assert(me_eval->runtime.wrapper_type_finalize == 0); +} + +static void mesh_calc_modifiers(struct Depsgraph *depsgraph, + Scene *scene, + Object *ob, + int useDeform, + const bool need_mapping, + const CustomData_MeshMasks *dataMask, + const int index, + const bool use_cache, + const bool allow_shared_mesh, + /* return args */ + Mesh **r_deform, + Mesh **r_final) +{ + /* Input and final mesh. Final mesh is only created the moment the first + * constructive modifier is executed, or a deform modifier needs normals + * or certain data layers. */ + Mesh *mesh_input = (Mesh *)ob->data; + Mesh *mesh_final = nullptr; + Mesh *mesh_deform = nullptr; + BLI_assert((mesh_input->id.tag & LIB_TAG_COPIED_ON_WRITE_EVAL_RESULT) == 0); + + /* Deformed vertex locations array. Deform only modifier need this type of + * float array rather than MVert*. Tracked along with mesh_final as an + * optimization to avoid copying coordinates back and forth if there are + * multiple sequential deform only modifiers. */ + float(*deformed_verts)[3] = nullptr; + int num_deformed_verts = mesh_input->totvert; + bool isPrevDeform = false; + + /* Mesh with constructive modifiers but no deformation applied. Tracked + * along with final mesh if undeformed / orco coordinates are requested + * for texturing. */ + Mesh *mesh_orco = nullptr; + Mesh *mesh_orco_cloth = nullptr; + + /* Modifier evaluation modes. */ + const bool use_render = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER); + const int required_mode = use_render ? eModifierMode_Render : eModifierMode_Realtime; + + /* Sculpt can skip certain modifiers. */ + const bool has_multires = BKE_sculpt_multires_active(scene, ob) != nullptr; + bool multires_applied = false; + const bool sculpt_mode = ob->mode & OB_MODE_SCULPT && ob->sculpt && !use_render; + const bool sculpt_dyntopo = (sculpt_mode && ob->sculpt->bm) && !use_render; + + /* Modifier evaluation contexts for different types of modifiers. */ + ModifierApplyFlag apply_render = use_render ? MOD_APPLY_RENDER : (ModifierApplyFlag)0; + ModifierApplyFlag apply_cache = use_cache ? MOD_APPLY_USECACHE : (ModifierApplyFlag)0; + const ModifierEvalContext mectx = { + depsgraph, ob, (ModifierApplyFlag)(apply_render | apply_cache)}; + const ModifierEvalContext mectx_orco = { + depsgraph, ob, (ModifierApplyFlag)(apply_render | MOD_APPLY_ORCO)}; + + /* Get effective list of modifiers to execute. Some effects like shape keys + * are added as virtual modifiers before the user created modifiers. */ + VirtualModifierData virtualModifierData; + ModifierData *firstmd = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData); + ModifierData *md = firstmd; + + /* Preview colors by modifiers such as dynamic paint, to show the results + * even if the resulting data is not used in a material. Only in object mode. + * TODO: this is broken, not drawn by the drawn manager. */ + const bool do_mod_mcol = (ob->mode == OB_MODE_OBJECT); + ModifierData *previewmd = nullptr; + CustomData_MeshMasks previewmask = {0}; + if (do_mod_mcol) { + /* Find the last active modifier generating a preview, or nullptr if none. */ + /* XXX Currently, DPaint modifier just ignores this. + * Needs a stupid hack... + * The whole "modifier preview" thing has to be (re?)designed, anyway! */ + previewmd = BKE_modifier_get_last_preview(scene, md, required_mode); + } + + /* Compute accumulated datamasks needed by each modifier. It helps to do + * this fine grained so that for example vertex groups are preserved up to + * an armature modifier, but not through a following subsurf modifier where + * subdividing them is expensive. */ + CustomData_MeshMasks final_datamask = *dataMask; + CDMaskLink *datamasks = BKE_modifier_calc_data_masks( + scene, ob, md, &final_datamask, required_mode, previewmd, &previewmask); + CDMaskLink *md_datamask = datamasks; + /* XXX Always copying POLYINDEX, else tessellated data are no more valid! */ + CustomData_MeshMasks append_mask = CD_MASK_BAREMESH_ORIGINDEX; + + /* Clear errors before evaluation. */ + BKE_modifiers_clear_errors(ob); + + /* Apply all leading deform modifiers. */ + if (useDeform) { + for (; md; md = md->next, md_datamask = md_datamask->next) { + const ModifierTypeInfo *mti = BKE_modifier_get_info((ModifierType)md->type); + + if (!BKE_modifier_is_enabled(scene, md, required_mode)) { + continue; + } + + if (useDeform < 0 && mti->dependsOnTime && mti->dependsOnTime(md)) { + continue; + } + + if (mti->type == eModifierTypeType_OnlyDeform && !sculpt_dyntopo) { + if (!deformed_verts) { + deformed_verts = BKE_mesh_vert_coords_alloc(mesh_input, &num_deformed_verts); + } + else if (isPrevDeform && mti->dependsOnNormals && mti->dependsOnNormals(md)) { + if (mesh_final == nullptr) { + mesh_final = BKE_mesh_copy_for_eval(mesh_input, true); + ASSERT_IS_VALID_MESH(mesh_final); + } + BKE_mesh_vert_coords_apply(mesh_final, deformed_verts); + } + + BKE_modifier_deform_verts(md, &mectx, mesh_final, deformed_verts, num_deformed_verts); + + isPrevDeform = true; + } + else { + break; + } + + /* grab modifiers until index i */ + if ((index != -1) && (BLI_findindex(&ob->modifiers, md) >= index)) { + md = nullptr; + break; + } + } + + /* Result of all leading deforming modifiers is cached for + * places that wish to use the original mesh but with deformed + * coordinates (like vertex paint). */ + if (r_deform) { + mesh_deform = BKE_mesh_copy_for_eval(mesh_input, true); + + if (deformed_verts) { + BKE_mesh_vert_coords_apply(mesh_deform, deformed_verts); + } + } + } + + /* Apply all remaining constructive and deforming modifiers. */ + bool have_non_onlydeform_modifiers_appled = false; + for (; md; md = md->next, md_datamask = md_datamask->next) { + const ModifierTypeInfo *mti = BKE_modifier_get_info((ModifierType)md->type); + + if (!BKE_modifier_is_enabled(scene, md, required_mode)) { + continue; + } + + if (mti->type == eModifierTypeType_OnlyDeform && !useDeform) { + continue; + } + + if ((mti->flags & eModifierTypeFlag_RequiresOriginalData) && + have_non_onlydeform_modifiers_appled) { + BKE_modifier_set_error(ob, md, "Modifier requires original data, bad stack position"); + continue; + } + + if (sculpt_mode && (!has_multires || multires_applied || sculpt_dyntopo)) { + bool unsupported = false; + + if (md->type == eModifierType_Multires && ((MultiresModifierData *)md)->sculptlvl == 0) { + /* If multires is on level 0 skip it silently without warning message. */ + if (!sculpt_dyntopo) { + continue; + } + } + + if (sculpt_dyntopo) { + unsupported = true; + } + + if (scene->toolsettings->sculpt->flags & SCULPT_ONLY_DEFORM) { + unsupported |= (mti->type != eModifierTypeType_OnlyDeform); + } + + unsupported |= multires_applied; + + if (unsupported) { + if (sculpt_dyntopo) { + BKE_modifier_set_error(ob, md, "Not supported in dyntopo"); + } + else { + BKE_modifier_set_error(ob, md, "Not supported in sculpt mode"); + } + continue; + } + } + + if (need_mapping && !BKE_modifier_supports_mapping(md)) { + continue; + } + + if (useDeform < 0 && mti->dependsOnTime && mti->dependsOnTime(md)) { + continue; + } + + /* Add orco mesh as layer if needed by this modifier. */ + if (mesh_final && mesh_orco && mti->requiredDataMask) { + CustomData_MeshMasks mask = {0}; + mti->requiredDataMask(ob, md, &mask); + if (mask.vmask & CD_MASK_ORCO) { + add_orco_mesh(ob, nullptr, mesh_final, mesh_orco, CD_ORCO); + } + } + + /* How to apply modifier depends on (a) what we already have as + * a result of previous modifiers (could be a Mesh or just + * deformed vertices) and (b) what type the modifier is. */ + if (mti->type == eModifierTypeType_OnlyDeform) { + /* No existing verts to deform, need to build them. */ + if (!deformed_verts) { + if (mesh_final) { + /* Deforming a mesh, read the vertex locations + * out of the mesh and deform them. Once done with this + * run of deformers verts will be written back. */ + deformed_verts = BKE_mesh_vert_coords_alloc(mesh_final, &num_deformed_verts); + } + else { + deformed_verts = BKE_mesh_vert_coords_alloc(mesh_input, &num_deformed_verts); + } + } + /* if this is not the last modifier in the stack then recalculate the normals + * to avoid giving bogus normals to the next modifier see: T23673. */ + else if (isPrevDeform && mti->dependsOnNormals && mti->dependsOnNormals(md)) { + if (mesh_final == nullptr) { + mesh_final = BKE_mesh_copy_for_eval(mesh_input, true); + ASSERT_IS_VALID_MESH(mesh_final); + } + BKE_mesh_vert_coords_apply(mesh_final, deformed_verts); + } + BKE_modifier_deform_verts(md, &mectx, mesh_final, deformed_verts, num_deformed_verts); + } + else { + bool check_for_needs_mapping = false; + /* apply vertex coordinates or build a Mesh as necessary */ + if (mesh_final != nullptr) { + if (have_non_onlydeform_modifiers_appled == false) { + /* If we only deformed, we won't have initialized #CD_ORIGINDEX. + * as this is the only part of the function that initializes mapping. */ + check_for_needs_mapping = true; + } + } + else { + mesh_final = BKE_mesh_copy_for_eval(mesh_input, true); + ASSERT_IS_VALID_MESH(mesh_final); + check_for_needs_mapping = true; + } + + if (deformed_verts) { + BKE_mesh_vert_coords_apply(mesh_final, deformed_verts); + } + + have_non_onlydeform_modifiers_appled = true; + + /* determine which data layers are needed by following modifiers */ + CustomData_MeshMasks nextmask = md_datamask->next ? md_datamask->next->mask : final_datamask; + + if (check_for_needs_mapping) { + /* Initialize original indices the first time we evaluate a + * constructive modifier. Modifiers will then do mapping mostly + * automatic by copying them through CustomData_copy_data along + * with other data. + * + * These are created when either requested by evaluation, or if + * following modifiers requested them. */ + if (need_mapping || + ((nextmask.vmask | nextmask.emask | nextmask.pmask) & CD_MASK_ORIGINDEX)) { + /* calc */ + CustomData_add_layer( + &mesh_final->vdata, CD_ORIGINDEX, CD_CALLOC, nullptr, mesh_final->totvert); + CustomData_add_layer( + &mesh_final->edata, CD_ORIGINDEX, CD_CALLOC, nullptr, mesh_final->totedge); + CustomData_add_layer( + &mesh_final->pdata, CD_ORIGINDEX, CD_CALLOC, nullptr, mesh_final->totpoly); + + /* Not worth parallelizing this, + * gives less than 0.1% overall speedup in best of best cases... */ + range_vn_i((int *)CustomData_get_layer(&mesh_final->vdata, CD_ORIGINDEX), + mesh_final->totvert, + 0); + range_vn_i((int *)CustomData_get_layer(&mesh_final->edata, CD_ORIGINDEX), + mesh_final->totedge, + 0); + range_vn_i((int *)CustomData_get_layer(&mesh_final->pdata, CD_ORIGINDEX), + mesh_final->totpoly, + 0); + } + } + + /* set the Mesh to only copy needed data */ + CustomData_MeshMasks mask = md_datamask->mask; + /* needMapping check here fixes bug T28112, otherwise it's + * possible that it won't be copied */ + CustomData_MeshMasks_update(&mask, &append_mask); + if (need_mapping) { + mask.vmask |= CD_MASK_ORIGINDEX; + mask.emask |= CD_MASK_ORIGINDEX; + mask.pmask |= CD_MASK_ORIGINDEX; + } + mesh_set_only_copy(mesh_final, &mask); + + /* add cloth rest shape key if needed */ + if (mask.vmask & CD_MASK_CLOTH_ORCO) { + add_orco_mesh(ob, nullptr, mesh_final, mesh_orco, CD_CLOTH_ORCO); + } + + /* add an origspace layer if needed */ + if ((md_datamask->mask.lmask) & CD_MASK_ORIGSPACE_MLOOP) { + if (!CustomData_has_layer(&mesh_final->ldata, CD_ORIGSPACE_MLOOP)) { + CustomData_add_layer( + &mesh_final->ldata, CD_ORIGSPACE_MLOOP, CD_CALLOC, nullptr, mesh_final->totloop); + mesh_init_origspace(mesh_final); + } + } + + Mesh *mesh_next = BKE_modifier_modify_mesh(md, &mectx, mesh_final); + ASSERT_IS_VALID_MESH(mesh_next); + + if (mesh_next) { + /* if the modifier returned a new mesh, release the old one */ + if (mesh_final != mesh_next) { + BLI_assert(mesh_final != mesh_input); + BKE_id_free(nullptr, mesh_final); + } + mesh_final = mesh_next; + + if (deformed_verts) { + MEM_freeN(deformed_verts); + deformed_verts = nullptr; + } + } + + /* create an orco mesh in parallel */ + if (nextmask.vmask & CD_MASK_ORCO) { + if (!mesh_orco) { + mesh_orco = create_orco_mesh(ob, mesh_input, nullptr, CD_ORCO); + } + + nextmask.vmask &= ~CD_MASK_ORCO; + CustomData_MeshMasks temp_cddata_masks = {0}; + temp_cddata_masks.vmask = CD_MASK_ORIGINDEX; + temp_cddata_masks.emask = CD_MASK_ORIGINDEX; + temp_cddata_masks.fmask = CD_MASK_ORIGINDEX; + temp_cddata_masks.pmask = CD_MASK_ORIGINDEX; + + if (mti->requiredDataMask != nullptr) { + mti->requiredDataMask(ob, md, &temp_cddata_masks); + } + CustomData_MeshMasks_update(&temp_cddata_masks, &nextmask); + mesh_set_only_copy(mesh_orco, &temp_cddata_masks); + + mesh_next = BKE_modifier_modify_mesh(md, &mectx_orco, mesh_orco); + ASSERT_IS_VALID_MESH(mesh_next); + + if (mesh_next) { + /* if the modifier returned a new mesh, release the old one */ + if (mesh_orco != mesh_next) { + BLI_assert(mesh_orco != mesh_input); + BKE_id_free(nullptr, mesh_orco); + } + + mesh_orco = mesh_next; + } + } + + /* create cloth orco mesh in parallel */ + if (nextmask.vmask & CD_MASK_CLOTH_ORCO) { + if (!mesh_orco_cloth) { + mesh_orco_cloth = create_orco_mesh(ob, mesh_input, nullptr, CD_CLOTH_ORCO); + } + + nextmask.vmask &= ~CD_MASK_CLOTH_ORCO; + nextmask.vmask |= CD_MASK_ORIGINDEX; + nextmask.emask |= CD_MASK_ORIGINDEX; + nextmask.pmask |= CD_MASK_ORIGINDEX; + mesh_set_only_copy(mesh_orco_cloth, &nextmask); + + mesh_next = BKE_modifier_modify_mesh(md, &mectx_orco, mesh_orco_cloth); + ASSERT_IS_VALID_MESH(mesh_next); + + if (mesh_next) { + /* if the modifier returned a new mesh, release the old one */ + if (mesh_orco_cloth != mesh_next) { + BLI_assert(mesh_orco != mesh_input); + BKE_id_free(nullptr, mesh_orco_cloth); + } + + mesh_orco_cloth = mesh_next; + } + } + + /* in case of dynamic paint, make sure preview mask remains for following modifiers */ + /* XXX Temp and hackish solution! */ + if (md->type == eModifierType_DynamicPaint) { + append_mask.lmask |= CD_MASK_PREVIEW_MLOOPCOL; + } + + mesh_final->runtime.deformed_only = false; + } + + isPrevDeform = (mti->type == eModifierTypeType_OnlyDeform); + + /* grab modifiers until index i */ + if ((index != -1) && (BLI_findindex(&ob->modifiers, md) >= index)) { + break; + } + + if (sculpt_mode && md->type == eModifierType_Multires) { + multires_applied = true; + } + } + + BLI_linklist_free((LinkNode *)datamasks, nullptr); + + for (md = firstmd; md; md = md->next) { + BKE_modifier_free_temporary_data(md); + } + + /* Yay, we are done. If we have a Mesh and deformed vertices, + * we need to apply these back onto the Mesh. If we have no + * Mesh then we need to build one. */ + if (mesh_final == nullptr) { + /* Note: this check on cdmask is a bit dodgy, it handles the issue at stake here (see T68211), + * but other cases might require similar handling? + * Could be a good idea to define a proper CustomData_MeshMask for that then. */ + if (deformed_verts == nullptr && allow_shared_mesh && + (final_datamask.lmask & CD_MASK_NORMAL) == 0 && + (final_datamask.pmask & CD_MASK_NORMAL) == 0) { + mesh_final = mesh_input; + } + else { + mesh_final = BKE_mesh_copy_for_eval(mesh_input, true); + } + } + if (deformed_verts) { + BKE_mesh_vert_coords_apply(mesh_final, deformed_verts); + MEM_freeN(deformed_verts); + deformed_verts = nullptr; + } + + /* Denotes whether the object which the modifier stack came from owns the mesh or whether the + * mesh is shared across multiple objects since there are no effective modifiers. */ + const bool is_own_mesh = (mesh_final != mesh_input); + + /* Add orco coordinates to final and deformed mesh if requested. */ + if (final_datamask.vmask & CD_MASK_ORCO) { + /* No need in ORCO layer if the mesh was not deformed or modified: undeformed mesh in this case + * matches input mesh. */ + if (is_own_mesh) { + add_orco_mesh(ob, nullptr, mesh_final, mesh_orco, CD_ORCO); + } + + if (mesh_deform) { + add_orco_mesh(ob, nullptr, mesh_deform, nullptr, CD_ORCO); + } + } + + if (mesh_orco) { + BKE_id_free(nullptr, mesh_orco); + } + if (mesh_orco_cloth) { + BKE_id_free(nullptr, mesh_orco_cloth); + } + + /* Compute normals. */ + if (is_own_mesh) { + mesh_calc_modifier_final_normals(mesh_input, &final_datamask, sculpt_dyntopo, mesh_final); + } + else { + Mesh_Runtime *runtime = &mesh_input->runtime; + if (runtime->mesh_eval == nullptr) { + BLI_assert(runtime->eval_mutex != nullptr); + BLI_mutex_lock((ThreadMutex *)runtime->eval_mutex); + if (runtime->mesh_eval == nullptr) { + mesh_final = BKE_mesh_copy_for_eval(mesh_input, true); + mesh_calc_modifier_final_normals(mesh_input, &final_datamask, sculpt_dyntopo, mesh_final); + mesh_calc_finalize(mesh_input, mesh_final); + runtime->mesh_eval = mesh_final; + } + BLI_mutex_unlock((ThreadMutex *)runtime->eval_mutex); + } + mesh_final = runtime->mesh_eval; + } + + if (is_own_mesh) { + mesh_calc_finalize(mesh_input, mesh_final); + } + + /* Return final mesh */ + *r_final = mesh_final; + if (r_deform) { + *r_deform = mesh_deform; + } +} + +float (*editbmesh_vert_coords_alloc(BMEditMesh *em, int *r_vert_len))[3] +{ + BMIter iter; + BMVert *eve; + float(*cos)[3]; + int i; + + *r_vert_len = em->bm->totvert; + + cos = (float(*)[3])MEM_malloc_arrayN(em->bm->totvert, sizeof(float[3]), "vertexcos"); + + BM_ITER_MESH_INDEX (eve, &iter, em->bm, BM_VERTS_OF_MESH, i) { + copy_v3_v3(cos[i], eve->co); + } + + return cos; +} + +bool editbmesh_modifier_is_enabled(Scene *scene, + const Object *ob, + ModifierData *md, + bool has_prev_mesh) +{ + const ModifierTypeInfo *mti = BKE_modifier_get_info((ModifierType)md->type); + const int required_mode = eModifierMode_Realtime | eModifierMode_Editmode; + + if (!BKE_modifier_is_enabled(scene, md, required_mode)) { + return false; + } + + if ((mti->flags & eModifierTypeFlag_RequiresOriginalData) && has_prev_mesh) { + BKE_modifier_set_error(ob, md, "Modifier requires original data, bad stack position"); + return false; + } + + return true; +} + +static void editbmesh_calc_modifier_final_normals(Mesh *mesh_final, + const CustomData_MeshMasks *final_datamask) +{ + if (mesh_final->runtime.wrapper_type != ME_WRAPPER_TYPE_MDATA) { + /* Generated at draw time. */ + mesh_final->runtime.wrapper_type_finalize = (1 << mesh_final->runtime.wrapper_type); + return; + } + + const bool do_loop_normals = ((mesh_final->flag & ME_AUTOSMOOTH) != 0 || + (final_datamask->lmask & CD_MASK_NORMAL) != 0); + /* Some modifiers may need this info from their target (other) object, + * simpler to generate it here as well. */ + const bool do_poly_normals = ((final_datamask->pmask & CD_MASK_NORMAL) != 0); + + /* In case we also need poly normals, add the layer and compute them here + * (BKE_mesh_calc_normals_split() assumes that if that data exists, it is always valid). */ + if (do_poly_normals) { + if (!CustomData_has_layer(&mesh_final->pdata, CD_NORMAL)) { + float(*polynors)[3] = (float(*)[3])CustomData_add_layer( + &mesh_final->pdata, CD_NORMAL, CD_CALLOC, nullptr, mesh_final->totpoly); + BKE_mesh_calc_normals_poly(mesh_final->mvert, + nullptr, + mesh_final->totvert, + mesh_final->mloop, + mesh_final->mpoly, + mesh_final->totloop, + mesh_final->totpoly, + polynors, + false); + } + } + + if (do_loop_normals) { + /* Compute loop normals */ + BKE_mesh_calc_normals_split(mesh_final); + BKE_mesh_tessface_clear(mesh_final); + } + + /* BMESH_ONLY, ensure tessface's used for drawing, + * but don't recalculate if the last modifier in the stack gives us tessfaces + * check if the derived meshes are DM_TYPE_EDITBMESH before calling, this isn't essential + * but quiets annoying error messages since tessfaces wont be created. */ + if (final_datamask->fmask & CD_MASK_MFACE) { + if (mesh_final->edit_mesh == nullptr) { + BKE_mesh_tessface_ensure(mesh_final); + } + } + + /* same as mesh_calc_modifiers (if using loop normals, poly nors have already been computed). */ + if (!do_loop_normals) { + BKE_mesh_ensure_normals_for_display(mesh_final); + + /* Some modifiers, like data-transfer, may generate those data, we do not want to keep them, + * as they are used by display code when available (i.e. even if autosmooth is disabled). */ + if (CustomData_has_layer(&mesh_final->ldata, CD_NORMAL)) { + CustomData_free_layers(&mesh_final->ldata, CD_NORMAL, mesh_final->totloop); + } + } +} + +static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph, + Scene *scene, + Object *ob, + BMEditMesh *em_input, + const CustomData_MeshMasks *dataMask, + /* return args */ + Mesh **r_cage, + Mesh **r_final) +{ + /* Input and final mesh. Final mesh is only created the moment the first + * constructive modifier is executed, or a deform modifier needs normals + * or certain data layers. */ + Mesh *mesh_input = (Mesh *)ob->data; + Mesh *mesh_final = nullptr; + Mesh *mesh_cage = nullptr; + + /* Deformed vertex locations array. Deform only modifier need this type of + * float array rather than MVert*. Tracked along with mesh_final as an + * optimization to avoid copying coordinates back and forth if there are + * multiple sequential deform only modifiers. */ + float(*deformed_verts)[3] = nullptr; + int num_deformed_verts = 0; + bool isPrevDeform = false; + + /* Mesh with constructive modifiers but no deformation applied. Tracked + * along with final mesh if undeformed / orco coordinates are requested + * for texturing. */ + Mesh *mesh_orco = nullptr; + + /* Modifier evaluation modes. */ + const int required_mode = eModifierMode_Realtime | eModifierMode_Editmode; + + const bool use_render = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER); + /* Modifier evaluation contexts for different types of modifiers. */ + ModifierApplyFlag apply_render = use_render ? MOD_APPLY_RENDER : (ModifierApplyFlag)0; + const ModifierEvalContext mectx = { + depsgraph, ob, (ModifierApplyFlag)(MOD_APPLY_USECACHE | apply_render)}; + const ModifierEvalContext mectx_orco = {depsgraph, ob, MOD_APPLY_ORCO}; + + /* Get effective list of modifiers to execute. Some effects like shape keys + * are added as virtual modifiers before the user created modifiers. */ + VirtualModifierData virtualModifierData; + ModifierData *md = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData); + + /* Compute accumulated datamasks needed by each modifier. It helps to do + * this fine grained so that for example vertex groups are preserved up to + * an armature modifier, but not through a following subsurf modifier where + * subdividing them is expensive. */ + CustomData_MeshMasks final_datamask = *dataMask; + CDMaskLink *datamasks = BKE_modifier_calc_data_masks( + scene, ob, md, &final_datamask, required_mode, nullptr, nullptr); + CDMaskLink *md_datamask = datamasks; + CustomData_MeshMasks append_mask = CD_MASK_BAREMESH; + + /* Evaluate modifiers up to certain index to get the mesh cage. */ + int cageIndex = BKE_modifiers_get_cage_index(scene, ob, nullptr, true); + if (r_cage && cageIndex == -1) { + mesh_cage = BKE_mesh_wrapper_from_editmesh_with_coords( + em_input, &final_datamask, nullptr, mesh_input); + } + + /* Clear errors before evaluation. */ + BKE_modifiers_clear_errors(ob); + + for (int i = 0; md; i++, md = md->next, md_datamask = md_datamask->next) { + const ModifierTypeInfo *mti = BKE_modifier_get_info((ModifierType)md->type); + + if (!editbmesh_modifier_is_enabled(scene, ob, md, mesh_final != nullptr)) { + continue; + } + + /* Add an orco mesh as layer if needed by this modifier. */ + if (mesh_final && mesh_orco && mti->requiredDataMask) { + CustomData_MeshMasks mask = {0}; + mti->requiredDataMask(ob, md, &mask); + if (mask.vmask & CD_MASK_ORCO) { + add_orco_mesh(ob, em_input, mesh_final, mesh_orco, CD_ORCO); + } + } + + /* How to apply modifier depends on (a) what we already have as + * a result of previous modifiers (could be a mesh or just + * deformed vertices) and (b) what type the modifier is. */ + if (mti->type == eModifierTypeType_OnlyDeform) { + /* No existing verts to deform, need to build them. */ + if (!deformed_verts) { + if (mesh_final) { + /* Deforming a derived mesh, read the vertex locations + * out of the mesh and deform them. Once done with this + * run of deformers verts will be written back. */ + deformed_verts = BKE_mesh_vert_coords_alloc(mesh_final, &num_deformed_verts); + } + else { + deformed_verts = editbmesh_vert_coords_alloc(em_input, &num_deformed_verts); + } + } + else if (isPrevDeform && mti->dependsOnNormals && mti->dependsOnNormals(md)) { + if (mesh_final == nullptr) { + mesh_final = BKE_mesh_from_bmesh_for_eval_nomain(em_input->bm, nullptr, mesh_input); + ASSERT_IS_VALID_MESH(mesh_final); + } + BLI_assert(deformed_verts != nullptr); + BKE_mesh_vert_coords_apply(mesh_final, deformed_verts); + } + + if (mti->deformVertsEM) { + BKE_modifier_deform_vertsEM( + md, &mectx, em_input, mesh_final, deformed_verts, num_deformed_verts); + } + else { + BKE_modifier_deform_verts(md, &mectx, mesh_final, deformed_verts, num_deformed_verts); + } + } + else { + /* apply vertex coordinates or build a DerivedMesh as necessary */ + if (mesh_final) { + if (deformed_verts) { + Mesh *mesh_tmp = BKE_mesh_copy_for_eval(mesh_final, false); + if (mesh_final != mesh_cage) { + BKE_id_free(nullptr, mesh_final); + } + mesh_final = mesh_tmp; + BKE_mesh_vert_coords_apply(mesh_final, deformed_verts); + } + else if (mesh_final == mesh_cage) { + /* 'me' may be changed by this modifier, so we need to copy it. */ + mesh_final = BKE_mesh_copy_for_eval(mesh_final, false); + } + } + else { + mesh_final = BKE_mesh_wrapper_from_editmesh_with_coords( + em_input, nullptr, deformed_verts, mesh_input); + deformed_verts = nullptr; + } + + /* create an orco derivedmesh in parallel */ + CustomData_MeshMasks mask = md_datamask->mask; + if (mask.vmask & CD_MASK_ORCO) { + if (!mesh_orco) { + mesh_orco = create_orco_mesh(ob, mesh_input, em_input, CD_ORCO); + } + + mask.vmask &= ~CD_MASK_ORCO; + mask.vmask |= CD_MASK_ORIGINDEX; + mask.emask |= CD_MASK_ORIGINDEX; + mask.pmask |= CD_MASK_ORIGINDEX; + mesh_set_only_copy(mesh_orco, &mask); + + Mesh *mesh_next = BKE_modifier_modify_mesh(md, &mectx_orco, mesh_orco); + ASSERT_IS_VALID_MESH(mesh_next); + + if (mesh_next) { + /* if the modifier returned a new dm, release the old one */ + if (mesh_orco && mesh_orco != mesh_next) { + BKE_id_free(nullptr, mesh_orco); + } + mesh_orco = mesh_next; + } + } + + /* set the DerivedMesh to only copy needed data */ + CustomData_MeshMasks_update(&mask, &append_mask); + /* XXX WHAT? ovewrites mask ??? */ + /* CD_MASK_ORCO may have been cleared above */ + mask = md_datamask->mask; + mask.vmask |= CD_MASK_ORIGINDEX; + mask.emask |= CD_MASK_ORIGINDEX; + mask.pmask |= CD_MASK_ORIGINDEX; + + mesh_set_only_copy(mesh_final, &mask); + + if (mask.lmask & CD_MASK_ORIGSPACE_MLOOP) { + if (!CustomData_has_layer(&mesh_final->ldata, CD_ORIGSPACE_MLOOP)) { + CustomData_add_layer( + &mesh_final->ldata, CD_ORIGSPACE_MLOOP, CD_CALLOC, nullptr, mesh_final->totloop); + mesh_init_origspace(mesh_final); + } + } + + Mesh *mesh_next = BKE_modifier_modify_mesh(md, &mectx, mesh_final); + ASSERT_IS_VALID_MESH(mesh_next); + + if (mesh_next) { + if (mesh_final && mesh_final != mesh_next) { + BKE_id_free(nullptr, mesh_final); + } + mesh_final = mesh_next; + + if (deformed_verts) { + MEM_freeN(deformed_verts); + deformed_verts = nullptr; + } + } + mesh_final->runtime.deformed_only = false; + } + + if (r_cage && i == cageIndex) { + if (mesh_final && deformed_verts) { + mesh_cage = BKE_mesh_copy_for_eval(mesh_final, false); + BKE_mesh_vert_coords_apply(mesh_cage, deformed_verts); + } + else if (mesh_final) { + mesh_cage = mesh_final; + } + else { + Mesh *me_orig = mesh_input; + if (me_orig->id.tag & LIB_TAG_COPIED_ON_WRITE) { + if (!BKE_mesh_runtime_ensure_edit_data(me_orig)) { + BKE_mesh_runtime_reset_edit_data(me_orig); + } + me_orig->runtime.edit_data->vertexCos = (float(*)[3])MEM_dupallocN(deformed_verts); + } + mesh_cage = BKE_mesh_wrapper_from_editmesh_with_coords( + em_input, + &final_datamask, + deformed_verts ? (float(*)[3])MEM_dupallocN(deformed_verts) : nullptr, + mesh_input); + } + } + + isPrevDeform = (mti->type == eModifierTypeType_OnlyDeform); + } + + BLI_linklist_free((LinkNode *)datamasks, nullptr); + + /* Yay, we are done. If we have a DerivedMesh and deformed vertices need + * to apply these back onto the DerivedMesh. If we have no DerivedMesh + * then we need to build one. */ + if (mesh_final) { + if (deformed_verts) { + Mesh *mesh_tmp = BKE_mesh_copy_for_eval(mesh_final, false); + if (mesh_final != mesh_cage) { + BKE_id_free(nullptr, mesh_final); + } + mesh_final = mesh_tmp; + BKE_mesh_vert_coords_apply(mesh_final, deformed_verts); + } + } + else if (!deformed_verts && mesh_cage) { + /* cage should already have up to date normals */ + mesh_final = mesh_cage; + } + else { + /* this is just a copy of the editmesh, no need to calc normals */ + mesh_final = BKE_mesh_wrapper_from_editmesh_with_coords( + em_input, &final_datamask, deformed_verts, mesh_input); + deformed_verts = nullptr; + } + + if (deformed_verts) { + MEM_freeN(deformed_verts); + } + + /* Add orco coordinates to final and deformed mesh if requested. */ + if (final_datamask.vmask & CD_MASK_ORCO) { + /* FIXME(Campbell): avoid the need to convert to mesh data just to add an orco layer. */ + BKE_mesh_wrapper_ensure_mdata(mesh_final); + + add_orco_mesh(ob, em_input, mesh_final, mesh_orco, CD_ORCO); + } + + if (mesh_orco) { + BKE_id_free(nullptr, mesh_orco); + } + + /* Ensure normals calculation below is correct. */ + BLI_assert((mesh_input->flag & ME_AUTOSMOOTH) == (mesh_final->flag & ME_AUTOSMOOTH)); + BLI_assert(mesh_input->smoothresh == mesh_final->smoothresh); + BLI_assert(mesh_input->smoothresh == mesh_cage->smoothresh); + + /* Compute normals. */ + editbmesh_calc_modifier_final_normals(mesh_final, &final_datamask); + if (mesh_cage && (mesh_cage != mesh_final)) { + editbmesh_calc_modifier_final_normals(mesh_cage, &final_datamask); + } + + /* Return final mesh. */ + *r_final = mesh_final; + if (r_cage) { + *r_cage = mesh_cage; + } +} + +static void mesh_build_extra_data(struct Depsgraph *depsgraph, Object *ob, Mesh *mesh_eval) +{ + uint32_t eval_flags = DEG_get_eval_flags_for_id(depsgraph, &ob->id); + + if (eval_flags & DAG_EVAL_NEED_SHRINKWRAP_BOUNDARY) { + BKE_shrinkwrap_compute_boundary_data(mesh_eval); + } +} + +static void mesh_runtime_check_normals_valid(const Mesh *mesh) +{ + UNUSED_VARS_NDEBUG(mesh); + BLI_assert(!(mesh->runtime.cd_dirty_vert & CD_MASK_NORMAL)); + BLI_assert(!(mesh->runtime.cd_dirty_loop & CD_MASK_NORMAL)); + BLI_assert(!(mesh->runtime.cd_dirty_poly & CD_MASK_NORMAL)); +} + +static void mesh_build_data(struct Depsgraph *depsgraph, + Scene *scene, + Object *ob, + const CustomData_MeshMasks *dataMask, + const bool need_mapping) +{ + BLI_assert(ob->type == OB_MESH); + + /* Evaluated meshes aren't supposed to be created on original instances. If you do, + * they aren't cleaned up properly on mode switch, causing crashes, e.g T58150. */ + BLI_assert(ob->id.tag & LIB_TAG_COPIED_ON_WRITE); + + BKE_object_free_derived_caches(ob); + if (DEG_is_active(depsgraph)) { + BKE_sculpt_update_object_before_eval(ob); + } + +#if 0 /* XXX This is already taken care of in mesh_calc_modifiers()... */ + if (need_mapping) { + /* Also add the flag so that it is recorded in lastDataMask. */ + dataMask->vmask |= CD_MASK_ORIGINDEX; + dataMask->emask |= CD_MASK_ORIGINDEX; + dataMask->pmask |= CD_MASK_ORIGINDEX; + } +#endif + + Mesh *mesh_eval = nullptr, *mesh_deform_eval = nullptr; + mesh_calc_modifiers(depsgraph, + scene, + ob, + 1, + need_mapping, + dataMask, + -1, + true, + true, + &mesh_deform_eval, + &mesh_eval); + + /* The modifier stack evaluation is storing result in mesh->runtime.mesh_eval, but this result + * is not guaranteed to be owned by object. + * + * Check ownership now, since later on we can not go to a mesh owned by someone else via + * object's runtime: this could cause access freed data on depsgraph destruction (mesh who owns + * the final result might be freed prior to object). */ + Mesh *mesh = (Mesh *)ob->data; + const bool is_mesh_eval_owned = (mesh_eval != mesh->runtime.mesh_eval); + BKE_object_eval_assign_data(ob, &mesh_eval->id, is_mesh_eval_owned); + + ob->runtime.mesh_deform_eval = mesh_deform_eval; + ob->runtime.last_data_mask = *dataMask; + ob->runtime.last_need_mapping = need_mapping; + + BKE_object_boundbox_calc_from_mesh(ob, mesh_eval); + + /* Make sure that drivers can target shapekey properties. + * Note that this causes a potential inconsistency, as the shapekey may have a + * different topology than the evaluated mesh. */ + BLI_assert(mesh->key == nullptr || DEG_is_evaluated_id(&mesh->key->id)); + mesh_eval->key = mesh->key; + + if ((ob->mode & OB_MODE_ALL_SCULPT) && ob->sculpt) { + if (DEG_is_active(depsgraph)) { + BKE_sculpt_update_object_after_eval(depsgraph, ob); + } + } + + mesh_runtime_check_normals_valid(mesh_eval); + mesh_build_extra_data(depsgraph, ob, mesh_eval); +} + +static void editbmesh_build_data(struct Depsgraph *depsgraph, + Scene *scene, + Object *obedit, + BMEditMesh *em, + CustomData_MeshMasks *dataMask) +{ + BLI_assert(obedit->id.tag & LIB_TAG_COPIED_ON_WRITE); + + BKE_object_free_derived_caches(obedit); + if (DEG_is_active(depsgraph)) { + BKE_sculpt_update_object_before_eval(obedit); + } + + BKE_editmesh_free_derivedmesh(em); + + Mesh *me_cage; + Mesh *me_final; + + editbmesh_calc_modifiers(depsgraph, scene, obedit, em, dataMask, &me_cage, &me_final); + + em->mesh_eval_final = me_final; + em->mesh_eval_cage = me_cage; + + BKE_object_boundbox_calc_from_mesh(obedit, em->mesh_eval_final); + + em->lastDataMask = *dataMask; + + mesh_runtime_check_normals_valid(em->mesh_eval_final); +} + +static void object_get_datamask(const Depsgraph *depsgraph, + Object *ob, + CustomData_MeshMasks *r_mask, + bool *r_need_mapping) +{ + ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph); + + DEG_get_customdata_mask_for_object(depsgraph, ob, r_mask); + + if (r_need_mapping) { + *r_need_mapping = false; + } + + /* Must never access original objects when dependency graph is not active: it might be already + * freed. */ + if (!DEG_is_active(depsgraph)) { + return; + } + + Object *actob = view_layer->basact ? DEG_get_original_object(view_layer->basact->object) : + nullptr; + if (DEG_get_original_object(ob) == actob) { + bool editing = BKE_paint_select_face_test(actob); + + /* weight paint and face select need original indices because of selection buffer drawing */ + if (r_need_mapping) { + *r_need_mapping = (editing || (ob->mode & (OB_MODE_WEIGHT_PAINT | OB_MODE_VERTEX_PAINT))); + } + + /* check if we need tfaces & mcols due to face select or texture paint */ + if ((ob->mode & OB_MODE_TEXTURE_PAINT) || editing) { + r_mask->lmask |= CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL; + r_mask->fmask |= CD_MASK_MTFACE; + } + + /* check if we need mcols due to vertex paint or weightpaint */ + if (ob->mode & OB_MODE_VERTEX_PAINT) { + r_mask->lmask |= CD_MASK_MLOOPCOL; + } + + if (ob->mode & OB_MODE_WEIGHT_PAINT) { + r_mask->vmask |= CD_MASK_MDEFORMVERT; + } + + if (ob->mode & OB_MODE_EDIT) { + r_mask->vmask |= CD_MASK_MVERT_SKIN; + } + } +} + +void makeDerivedMesh(struct Depsgraph *depsgraph, + Scene *scene, + Object *ob, + BMEditMesh *em, + const CustomData_MeshMasks *dataMask) +{ + bool need_mapping; + CustomData_MeshMasks cddata_masks = *dataMask; + object_get_datamask(depsgraph, ob, &cddata_masks, &need_mapping); + + if (em) { + editbmesh_build_data(depsgraph, scene, ob, em, &cddata_masks); + } + else { + mesh_build_data(depsgraph, scene, ob, &cddata_masks, need_mapping); + } +} + +/***/ + +Mesh *mesh_get_eval_final(struct Depsgraph *depsgraph, + Scene *scene, + Object *ob, + const CustomData_MeshMasks *dataMask) +{ + /* This function isn't thread-safe and can't be used during evaluation. */ + BLI_assert(DEG_is_evaluating(depsgraph) == false); + + /* Evaluated meshes aren't supposed to be created on original instances. If you do, + * they aren't cleaned up properly on mode switch, causing crashes, e.g T58150. */ + BLI_assert(ob->id.tag & LIB_TAG_COPIED_ON_WRITE); + + /* if there's no evaluated mesh or the last data mask used doesn't include + * the data we need, rebuild the derived mesh + */ + bool need_mapping; + CustomData_MeshMasks cddata_masks = *dataMask; + object_get_datamask(depsgraph, ob, &cddata_masks, &need_mapping); + + Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob); + if ((mesh_eval == nullptr) || + !CustomData_MeshMasks_are_matching(&(ob->runtime.last_data_mask), &cddata_masks) || + (need_mapping && !ob->runtime.last_need_mapping)) { + CustomData_MeshMasks_update(&cddata_masks, &ob->runtime.last_data_mask); + mesh_build_data( + depsgraph, scene, ob, &cddata_masks, need_mapping || ob->runtime.last_need_mapping); + mesh_eval = BKE_object_get_evaluated_mesh(ob); + } + + if (mesh_eval != nullptr) { + BLI_assert(!(mesh_eval->runtime.cd_dirty_vert & CD_MASK_NORMAL)); + } + return mesh_eval; +} + +Mesh *mesh_get_eval_deform(struct Depsgraph *depsgraph, + Scene *scene, + Object *ob, + const CustomData_MeshMasks *dataMask) +{ + /* This function isn't thread-safe and can't be used during evaluation. */ + BLI_assert(DEG_is_evaluating(depsgraph) == false); + + /* Evaluated meshes aren't supposed to be created on original instances. If you do, + * they aren't cleaned up properly on mode switch, causing crashes, e.g T58150. */ + BLI_assert(ob->id.tag & LIB_TAG_COPIED_ON_WRITE); + + /* if there's no derived mesh or the last data mask used doesn't include + * the data we need, rebuild the derived mesh + */ + bool need_mapping; + + CustomData_MeshMasks cddata_masks = *dataMask; + object_get_datamask(depsgraph, ob, &cddata_masks, &need_mapping); + + if (!ob->runtime.mesh_deform_eval || + !CustomData_MeshMasks_are_matching(&(ob->runtime.last_data_mask), &cddata_masks) || + (need_mapping && !ob->runtime.last_need_mapping)) { + CustomData_MeshMasks_update(&cddata_masks, &ob->runtime.last_data_mask); + mesh_build_data( + depsgraph, scene, ob, &cddata_masks, need_mapping || ob->runtime.last_need_mapping); + } + + return ob->runtime.mesh_deform_eval; +} + +Mesh *mesh_create_eval_final(Depsgraph *depsgraph, + Scene *scene, + Object *ob, + const CustomData_MeshMasks *dataMask) +{ + Mesh *final; + + mesh_calc_modifiers(depsgraph, scene, ob, 1, false, dataMask, -1, false, false, nullptr, &final); + + return final; +} + +Mesh *mesh_create_eval_final_index_render(Depsgraph *depsgraph, + Scene *scene, + Object *ob, + const CustomData_MeshMasks *dataMask, + int index) +{ + Mesh *final; + + mesh_calc_modifiers( + depsgraph, scene, ob, 1, false, dataMask, index, false, false, nullptr, &final); + + return final; +} + +Mesh *mesh_create_eval_no_deform(Depsgraph *depsgraph, + Scene *scene, + Object *ob, + const CustomData_MeshMasks *dataMask) +{ + Mesh *final; + + mesh_calc_modifiers(depsgraph, scene, ob, 0, false, dataMask, -1, false, false, nullptr, &final); + + return final; +} + +Mesh *mesh_create_eval_no_deform_render(Depsgraph *depsgraph, + Scene *scene, + Object *ob, + const CustomData_MeshMasks *dataMask) +{ + Mesh *final; + + mesh_calc_modifiers(depsgraph, scene, ob, 0, false, dataMask, -1, false, false, nullptr, &final); + + return final; +} + +/***/ + +Mesh *editbmesh_get_eval_cage_and_final(Depsgraph *depsgraph, + Scene *scene, + Object *obedit, + BMEditMesh *em, + const CustomData_MeshMasks *dataMask, + /* return args */ + Mesh **r_final) +{ + CustomData_MeshMasks cddata_masks = *dataMask; + + /* if there's no derived mesh or the last data mask used doesn't include + * the data we need, rebuild the derived mesh + */ + object_get_datamask(depsgraph, obedit, &cddata_masks, nullptr); + + if (!em->mesh_eval_cage || + !CustomData_MeshMasks_are_matching(&(em->lastDataMask), &cddata_masks)) { + editbmesh_build_data(depsgraph, scene, obedit, em, &cddata_masks); + } + + *r_final = em->mesh_eval_final; + if (em->mesh_eval_final) { + BLI_assert(!(em->mesh_eval_final->runtime.cd_dirty_vert & DM_DIRTY_NORMALS)); + } + return em->mesh_eval_cage; +} + +Mesh *editbmesh_get_eval_cage(struct Depsgraph *depsgraph, + Scene *scene, + Object *obedit, + BMEditMesh *em, + const CustomData_MeshMasks *dataMask) +{ + CustomData_MeshMasks cddata_masks = *dataMask; + + /* if there's no derived mesh or the last data mask used doesn't include + * the data we need, rebuild the derived mesh + */ + object_get_datamask(depsgraph, obedit, &cddata_masks, nullptr); + + if (!em->mesh_eval_cage || + !CustomData_MeshMasks_are_matching(&(em->lastDataMask), &cddata_masks)) { + editbmesh_build_data(depsgraph, scene, obedit, em, &cddata_masks); + } + + return em->mesh_eval_cage; +} + +Mesh *editbmesh_get_eval_cage_from_orig(struct Depsgraph *depsgraph, + Scene *scene, + Object *obedit, + const CustomData_MeshMasks *dataMask) +{ + BLI_assert((obedit->id.tag & LIB_TAG_COPIED_ON_WRITE) == 0); + Scene *scene_eval = (Scene *)DEG_get_evaluated_id(depsgraph, &scene->id); + Object *obedit_eval = (Object *)DEG_get_evaluated_id(depsgraph, &obedit->id); + BMEditMesh *em_eval = BKE_editmesh_from_object(obedit_eval); + return editbmesh_get_eval_cage(depsgraph, scene_eval, obedit_eval, em_eval, dataMask); +} + +/***/ + +/* same as above but for vert coords */ +struct MappedUserData { + float (*vertexcos)[3]; + BLI_bitmap *vertex_visit; +}; + +static void make_vertexcos__mapFunc(void *userData, + int index, + const float co[3], + const float UNUSED(no_f[3]), + const short UNUSED(no_s[3])) +{ + MappedUserData *mappedData = (MappedUserData *)userData; + + if (BLI_BITMAP_TEST(mappedData->vertex_visit, index) == 0) { + /* we need coord from prototype vertex, not from copies, + * assume they stored in the beginning of vertex array stored in DM + * (mirror modifier for eg does this) */ + copy_v3_v3(mappedData->vertexcos[index], co); + BLI_BITMAP_ENABLE(mappedData->vertex_visit, index); + } +} + +void mesh_get_mapped_verts_coords(Mesh *me_eval, float (*r_cos)[3], const int totcos) +{ + if (me_eval->runtime.deformed_only == false) { + MappedUserData userData; + memset(r_cos, 0, sizeof(*r_cos) * totcos); + userData.vertexcos = r_cos; + userData.vertex_visit = BLI_BITMAP_NEW(totcos, "vertexcos flags"); + BKE_mesh_foreach_mapped_vert(me_eval, make_vertexcos__mapFunc, &userData, MESH_FOREACH_NOP); + MEM_freeN(userData.vertex_visit); + } + else { + MVert *mv = me_eval->mvert; + for (int i = 0; i < totcos; i++, mv++) { + copy_v3_v3(r_cos[i], mv->co); + } + } +} + +void DM_calc_loop_tangents(DerivedMesh *dm, + bool calc_active_tangent, + const char (*tangent_names)[MAX_NAME], + int tangent_names_len) +{ + BKE_mesh_calc_loop_tangent_ex( + dm->getVertArray(dm), + dm->getPolyArray(dm), + dm->getNumPolys(dm), + dm->getLoopArray(dm), + dm->getLoopTriArray(dm), + dm->getNumLoopTri(dm), + &dm->loopData, + calc_active_tangent, + tangent_names, + tangent_names_len, + (float(*)[3])CustomData_get_layer(&dm->polyData, CD_NORMAL), + (float(*)[3])dm->getLoopDataArray(dm, CD_NORMAL), + (float(*)[3])dm->getVertDataArray(dm, CD_ORCO), /* may be nullptr */ + /* result */ + &dm->loopData, + dm->getNumLoops(dm), + &dm->tangent_mask); +} + +static void mesh_init_origspace(Mesh *mesh) +{ + const float default_osf[4][2] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}}; + + OrigSpaceLoop *lof_array = (OrigSpaceLoop *)CustomData_get_layer(&mesh->ldata, + CD_ORIGSPACE_MLOOP); + const int numpoly = mesh->totpoly; + // const int numloop = mesh->totloop; + MVert *mv = mesh->mvert; + MLoop *ml = mesh->mloop; + MPoly *mp = mesh->mpoly; + int i, j, k; + + blender::Vector vcos_2d; + + for (i = 0; i < numpoly; i++, mp++) { + OrigSpaceLoop *lof = lof_array + mp->loopstart; + + if (ELEM(mp->totloop, 3, 4)) { + for (j = 0; j < mp->totloop; j++, lof++) { + copy_v2_v2(lof->uv, default_osf[j]); + } + } + else { + MLoop *l = &ml[mp->loopstart]; + float p_nor[3], co[3]; + float mat[3][3]; + + float min[2] = {FLT_MAX, FLT_MAX}, max[2] = {-FLT_MAX, -FLT_MAX}; + float translate[2], scale[2]; + + BKE_mesh_calc_poly_normal(mp, l, mv, p_nor); + axis_dominant_v3_to_m3(mat, p_nor); + + vcos_2d.resize(mp->totloop); + for (j = 0; j < mp->totloop; j++, l++) { + mul_v3_m3v3(co, mat, mv[l->v].co); + copy_v2_v2(vcos_2d[j], co); + + for (k = 0; k < 2; k++) { + if (co[k] > max[k]) { + max[k] = co[k]; + } + else if (co[k] < min[k]) { + min[k] = co[k]; + } + } + } + + /* Brings min to (0, 0). */ + negate_v2_v2(translate, min); + + /* Scale will bring max to (1, 1). */ + sub_v2_v2v2(scale, max, min); + if (scale[0] == 0.0f) { + scale[0] = 1e-9f; + } + if (scale[1] == 0.0f) { + scale[1] = 1e-9f; + } + invert_v2(scale); + + /* Finally, transform all vcos_2d into ((0, 0), (1, 1)) + * square and assign them as origspace. */ + for (j = 0; j < mp->totloop; j++, lof++) { + add_v2_v2v2(lof->uv, vcos_2d[j], translate); + mul_v2_v2(lof->uv, scale); + } + } + } + + BKE_mesh_tessface_clear(mesh); +} + +/* derivedmesh info printing function, + * to help track down differences DM output */ + +#ifndef NDEBUG +# include "BLI_dynstr.h" + +static void dm_debug_info_layers(DynStr *dynstr, + DerivedMesh *dm, + CustomData *cd, + void *(*getElemDataArray)(DerivedMesh *, int)) +{ + int type; + + for (type = 0; type < CD_NUMTYPES; type++) { + if (CustomData_has_layer(cd, type)) { + /* note: doesn't account for multiple layers */ + const char *name = CustomData_layertype_name(type); + const int size = CustomData_sizeof(type); + const void *pt = getElemDataArray(dm, type); + const int pt_size = pt ? (int)(MEM_allocN_len(pt) / size) : 0; + const char *structname; + int structnum; + CustomData_file_write_info(type, &structname, &structnum); + BLI_dynstr_appendf( + dynstr, + " dict(name='%s', struct='%s', type=%d, ptr='%p', elem=%d, length=%d),\n", + name, + structname, + type, + (const void *)pt, + size, + pt_size); + } + } +} + +char *DM_debug_info(DerivedMesh *dm) +{ + DynStr *dynstr = BLI_dynstr_new(); + char *ret; + const char *tstr; + + BLI_dynstr_append(dynstr, "{\n"); + BLI_dynstr_appendf(dynstr, " 'ptr': '%p',\n", (void *)dm); + switch (dm->type) { + case DM_TYPE_CDDM: + tstr = "DM_TYPE_CDDM"; + break; + case DM_TYPE_CCGDM: + tstr = "DM_TYPE_CCGDM"; + break; + default: + tstr = "UNKNOWN"; + break; + } + BLI_dynstr_appendf(dynstr, " 'type': '%s',\n", tstr); + BLI_dynstr_appendf(dynstr, " 'numVertData': %d,\n", dm->numVertData); + BLI_dynstr_appendf(dynstr, " 'numEdgeData': %d,\n", dm->numEdgeData); + BLI_dynstr_appendf(dynstr, " 'numTessFaceData': %d,\n", dm->numTessFaceData); + BLI_dynstr_appendf(dynstr, " 'numPolyData': %d,\n", dm->numPolyData); + BLI_dynstr_appendf(dynstr, " 'deformedOnly': %d,\n", dm->deformedOnly); + + BLI_dynstr_append(dynstr, " 'vertexLayers': (\n"); + dm_debug_info_layers(dynstr, dm, &dm->vertData, dm->getVertDataArray); + BLI_dynstr_append(dynstr, " ),\n"); + + BLI_dynstr_append(dynstr, " 'edgeLayers': (\n"); + dm_debug_info_layers(dynstr, dm, &dm->edgeData, dm->getEdgeDataArray); + BLI_dynstr_append(dynstr, " ),\n"); + + BLI_dynstr_append(dynstr, " 'loopLayers': (\n"); + dm_debug_info_layers(dynstr, dm, &dm->loopData, dm->getLoopDataArray); + BLI_dynstr_append(dynstr, " ),\n"); + + BLI_dynstr_append(dynstr, " 'polyLayers': (\n"); + dm_debug_info_layers(dynstr, dm, &dm->polyData, dm->getPolyDataArray); + BLI_dynstr_append(dynstr, " ),\n"); + + BLI_dynstr_append(dynstr, " 'tessFaceLayers': (\n"); + dm_debug_info_layers(dynstr, dm, &dm->faceData, dm->getTessFaceDataArray); + BLI_dynstr_append(dynstr, " ),\n"); + + BLI_dynstr_append(dynstr, "}\n"); + + ret = BLI_dynstr_get_cstring(dynstr); + BLI_dynstr_free(dynstr); + return ret; +} + +void DM_debug_print(DerivedMesh *dm) +{ + char *str = DM_debug_info(dm); + puts(str); + fflush(stdout); + MEM_freeN(str); +} + +bool DM_is_valid(DerivedMesh *dm) +{ + const bool do_verbose = true; + const bool do_fixes = false; + + bool is_valid = true; + bool changed = true; + + is_valid &= BKE_mesh_validate_all_customdata( + dm->getVertDataLayout(dm), + dm->getNumVerts(dm), + dm->getEdgeDataLayout(dm), + dm->getNumEdges(dm), + dm->getLoopDataLayout(dm), + dm->getNumLoops(dm), + dm->getPolyDataLayout(dm), + dm->getNumPolys(dm), + false, /* setting mask here isn't useful, gives false positives */ + do_verbose, + do_fixes, + &changed); + + is_valid &= BKE_mesh_validate_arrays(nullptr, + dm->getVertArray(dm), + dm->getNumVerts(dm), + dm->getEdgeArray(dm), + dm->getNumEdges(dm), + dm->getTessFaceArray(dm), + dm->getNumTessFaces(dm), + dm->getLoopArray(dm), + dm->getNumLoops(dm), + dm->getPolyArray(dm), + dm->getNumPolys(dm), + (MDeformVert *)dm->getVertDataArray(dm, CD_MDEFORMVERT), + do_verbose, + do_fixes, + &changed); + + BLI_assert(changed == false); + + return is_valid; +} + +#endif /* NDEBUG */ diff --git a/source/blender/blenkernel/intern/mesh_convert.c b/source/blender/blenkernel/intern/mesh_convert.c index 8272bd07411..73883afe19e 100644 --- a/source/blender/blenkernel/intern/mesh_convert.c +++ b/source/blender/blenkernel/intern/mesh_convert.c @@ -1460,7 +1460,7 @@ Mesh *BKE_mesh_create_derived_for_modifier(struct Depsgraph *depsgraph, return result; } -/* This is a Mesh-based copy of the same function in DerivedMesh.c */ +/* This is a Mesh-based copy of the same function in DerivedMesh.cc */ static void shapekey_layers_to_keyblocks(Mesh *mesh_src, Mesh *mesh_dst, int actshape_uid) { KeyBlock *kb; diff --git a/source/blender/modifiers/intern/MOD_cloth.c b/source/blender/modifiers/intern/MOD_cloth.c index 4e15149083b..ac8f1ffed18 100644 --- a/source/blender/modifiers/intern/MOD_cloth.c +++ b/source/blender/modifiers/intern/MOD_cloth.c @@ -116,7 +116,7 @@ static void deformVerts(ModifierData *md, mesh_src = (Mesh *)BKE_id_copy_ex(NULL, (ID *)mesh, NULL, LIB_ID_COPY_LOCALIZE); } - /* TODO(sergey): For now it actually duplicates logic from DerivedMesh.c + /* TODO(sergey): For now it actually duplicates logic from DerivedMesh.cc * and needs some more generic solution. But starting experimenting with * this so close to the release is not that nice.. * -- cgit v1.2.3 From 4b0396695c622d1ac8669600fa820e80b1f0979f Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Mon, 14 Dec 2020 12:48:16 +0100 Subject: UI/Assets: Support generating object preview images Object previews are really helpful for visual data-block selection, like asset browsing. Having them be generative should also be quite handy and should work well enough in many, if not most cases. What this does is simple: * Place the object (actually a deep copy of it, for thread safety) in a virtual .blend into an empty scene/view-layer. * Add a camera, point it towards the front of the object, assuming that means pointing towards its +Y axis. * Use "Camera Fit Frame to Selected" logic to put the object into frame. * Create a threaded off-screen render. Of course, such an automatic preview will not work in all situations. E.g. it currently does a bad job capturing a single plane. We could add options for more advanced automatic previews, but probably custom previews is more important, which I committed already (812ea9184221). Part of the first Asset Browser milestone. Check the #asset_browser_milestone_1 project milestone on developer.blender.org. Reviewed as part of https://developer.blender.org/D9719. Reviewed by: Bastien Montagne, Brecht Van Lommel --- source/blender/blenkernel/intern/object.c | 4 +- source/blender/editors/include/ED_view3d.h | 5 + source/blender/editors/render/render_preview.c | 260 +++++++++++++++++---- source/blender/editors/space_view3d/view3d_utils.c | 35 +++ source/blender/editors/space_view3d/view3d_view.c | 28 +-- 5 files changed, 255 insertions(+), 77 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index bdb907df1ac..f11e7bc429d 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -2208,7 +2208,9 @@ ParticleSystem *BKE_object_copy_particlesystem(ParticleSystem *psys, const int f BLI_listbase_clear(&psysn->childcachebufs); if (flag & LIB_ID_CREATE_NO_MAIN) { - BLI_assert((psys->flag & PSYS_SHARED_CACHES) == 0); + /* XXX Disabled, fails when evaluating depsgraph after copying ID with no main for preview + * creation. */ + // BLI_assert((psys->flag & PSYS_SHARED_CACHES) == 0); psysn->flag |= PSYS_SHARED_CACHES; BLI_assert(psysn->pointcache != NULL); } diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index 596533406c3..13687bf0450 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -141,6 +141,11 @@ void ED_view3d_to_object(const struct Depsgraph *depsgraph, const float quat[4], const float dist); +bool ED_view3d_camera_to_view_selected(struct Main *bmain, + struct Depsgraph *depsgraph, + const struct Scene *scene, + struct Object *camera_ob); + void ED_view3d_lastview_store(struct RegionView3D *rv3d); /* Depth buffer */ diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c index d67113083a3..4466d9f434d 100644 --- a/source/blender/editors/render/render_preview.c +++ b/source/blender/editors/render/render_preview.c @@ -68,6 +68,7 @@ #include "BKE_main.h" #include "BKE_material.h" #include "BKE_node.h" +#include "BKE_object.h" #include "BKE_scene.h" #include "BKE_texture.h" #include "BKE_world.h" @@ -94,12 +95,16 @@ #include "ED_datafiles.h" #include "ED_render.h" #include "ED_screen.h" +#include "ED_view3d.h" +#include "ED_view3d_offscreen.h" #ifndef NDEBUG /* Used for database init assert(). */ # include "BLI_threads.h" #endif +static void icon_copy_rect(ImBuf *ibuf, uint w, uint h, uint *rect); + ImBuf *get_brush_icon(Brush *brush) { static const int flags = IB_rect | IB_multilayer | IB_metadata; @@ -336,7 +341,7 @@ static World *preview_get_localized_world(ShaderPreview *sp, World *world) return sp->worldcopy; } -static ID *duplicate_ids(ID *id) +static ID *duplicate_ids(ID *id, const bool allow_failure) { if (id == NULL) { /* Non-ID preview render. */ @@ -344,6 +349,7 @@ static ID *duplicate_ids(ID *id) } switch (GS(id->name)) { + case ID_OB: case ID_MA: case ID_TE: case ID_LA: @@ -357,7 +363,9 @@ static ID *duplicate_ids(ID *id) case ID_SCR: return NULL; default: - BLI_assert(!"ID type preview not supported."); + if (!allow_failure) { + BLI_assert(!"ID type preview not supported."); + } return NULL; } } @@ -698,6 +706,132 @@ void ED_preview_draw(const bContext *C, void *idp, void *parentp, void *slotp, r } } +/* **************************** Object preview ****************** */ + +struct ObjectPreviewData { + /* The main for the preview, not of the current file. */ + Main *pr_main; + /* Copy of the object to create the preview for. The copy is for thread safety (and to insert it + * into an own main). */ + Object *object; + int sizex; + int sizey; +}; + +static Object *object_preview_camera_create( + Main *preview_main, ViewLayer *view_layer, Object *preview_object, int sizex, int sizey) +{ + Object *camera = BKE_object_add(preview_main, view_layer, OB_CAMERA, "Preview Camera"); + + float rotmat[3][3]; + float dummyscale[3]; + mat4_to_loc_rot_size(camera->loc, rotmat, dummyscale, preview_object->obmat); + + /* Camera is Y up, so needs additional 90deg rotation around X to match object's Z up. */ + float drotmat[3][3]; + axis_angle_to_mat3_single(drotmat, 'X', M_PI_2); + mul_m3_m3_post(rotmat, drotmat); + + camera->rotmode = ROT_MODE_QUAT; + mat3_to_quat(camera->quat, rotmat); + + /* shader_preview_render() does this too. */ + if (sizex > sizey) { + ((Camera *)camera->data)->lens *= (float)sizey / (float)sizex; + } + + return camera; +} + +static Scene *object_preview_scene_create(const struct ObjectPreviewData *preview_data, + Depsgraph **r_depsgraph) +{ + Scene *scene = BKE_scene_add(preview_data->pr_main, "Object preview scene"); + ViewLayer *view_layer = scene->view_layers.first; + Depsgraph *depsgraph = DEG_graph_new( + preview_data->pr_main, scene, view_layer, DAG_EVAL_VIEWPORT); + + BLI_assert(preview_data->object != NULL); + BLI_addtail(&preview_data->pr_main->objects, preview_data->object); + + BKE_collection_object_add(preview_data->pr_main, scene->master_collection, preview_data->object); + + Object *camera_object = object_preview_camera_create(preview_data->pr_main, + view_layer, + preview_data->object, + preview_data->sizex, + preview_data->sizey); + + scene->camera = camera_object; + scene->r.xsch = preview_data->sizex; + scene->r.ysch = preview_data->sizey; + scene->r.size = 100; + + Base *preview_base = BKE_view_layer_base_find(view_layer, preview_data->object); + /* For 'view selected' below. */ + preview_base->flag |= BASE_SELECTED; + + DEG_graph_build_from_view_layer(depsgraph); + DEG_evaluate_on_refresh(depsgraph); + + ED_view3d_camera_to_view_selected(preview_data->pr_main, depsgraph, scene, camera_object); + + BKE_scene_graph_update_tagged(depsgraph, preview_data->pr_main); + + *r_depsgraph = depsgraph; + return scene; +} + +static void object_preview_render(IconPreview *preview, IconPreviewSize *preview_sized) +{ + Main *preview_main = BKE_main_new(); + const float pixelsize_old = U.pixelsize; + char err_out[256] = "unknown"; + + BLI_assert(preview->id_copy && (preview->id_copy != preview->id)); + + struct ObjectPreviewData preview_data = { + .pr_main = preview_main, + /* Act on a copy. */ + .object = (Object *)preview->id_copy, + .sizex = preview_sized->sizex, + .sizey = preview_sized->sizey, + }; + Depsgraph *depsgraph; + Scene *scene = object_preview_scene_create(&preview_data, &depsgraph); + + /* Ownership is now ours. */ + preview->id_copy = NULL; + + U.pixelsize = 2.0f; + + ImBuf *ibuf = ED_view3d_draw_offscreen_imbuf_simple( + depsgraph, + DEG_get_evaluated_scene(depsgraph), + NULL, + OB_SOLID, + DEG_get_evaluated_object(depsgraph, scene->camera), + preview_sized->sizex, + preview_sized->sizey, + IB_rect, + V3D_OFSDRAW_NONE, + R_ALPHAPREMUL, + NULL, + NULL, + err_out); + /* TODO color-management? */ + + U.pixelsize = pixelsize_old; + + if (ibuf) { + icon_copy_rect(ibuf, preview_sized->sizex, preview_sized->sizey, preview_sized->rect); + IMB_freeImBuf(ibuf); + } + + DEG_graph_free(depsgraph); + BKE_main_free(preview_main); +} + /* **************************** new shader preview system ****************** */ /* inside thread, called by renderer, sets job update value */ @@ -1188,27 +1322,54 @@ static void common_preview_startjob(void *customdata, } } -/* exported functions */ - -static void icon_preview_add_size(IconPreview *ip, uint *rect, int sizex, int sizey) +/** + * Some ID types already have their own, more focused rendering (only objects right now). This is + * for the other ones, which all share #ShaderPreview and some functions. + */ +static void other_id_types_preview_render(IconPreview *ip, + IconPreviewSize *cur_size, + const bool is_deferred, + short *stop, + short *do_update, + float *progress) { - IconPreviewSize *cur_size = ip->sizes.first, *new_size; + ShaderPreview *sp = MEM_callocN(sizeof(ShaderPreview), "Icon ShaderPreview"); + const bool is_render = !is_deferred; + + /* These types don't use the ShaderPreview mess, they have their own types and functions. */ + BLI_assert(!ELEM(GS(ip->id->name), ID_OB)); + + /* construct shader preview from image size and previewcustomdata */ + sp->scene = ip->scene; + sp->owner = ip->owner; + sp->sizex = cur_size->sizex; + sp->sizey = cur_size->sizey; + sp->pr_method = is_render ? PR_ICON_RENDER : PR_ICON_DEFERRED; + sp->pr_rect = cur_size->rect; + sp->id = ip->id; + sp->id_copy = ip->id_copy; + sp->bmain = ip->bmain; + sp->own_id_copy = false; + Material *ma = NULL; - while (cur_size) { - if (cur_size->sizex == sizex && cur_size->sizey == sizey) { - /* requested size is already in list, no need to add it again */ - return; + if (is_render) { + BLI_assert(ip->id); + + /* grease pencil use its own preview file */ + if (GS(ip->id->name) == ID_MA) { + ma = (Material *)ip->id; } - cur_size = cur_size->next; + if ((ma == NULL) || (ma->gp_style == NULL)) { + sp->pr_main = G_pr_main; + } + else { + sp->pr_main = G_pr_main_grease_pencil; + } } - new_size = MEM_callocN(sizeof(IconPreviewSize), "IconPreviewSize"); - new_size->sizex = sizex; - new_size->sizey = sizey; - new_size->rect = rect; - - BLI_addtail(&ip->sizes, new_size); + common_preview_startjob(sp, stop, do_update, progress); + shader_preview_free(sp); } static void icon_preview_startjob_all_sizes(void *customdata, @@ -1235,41 +1396,36 @@ static void icon_preview_startjob_all_sizes(void *customdata, continue; } - ShaderPreview *sp = MEM_callocN(sizeof(ShaderPreview), "Icon ShaderPreview"); - const bool is_render = !(prv->tag & PRV_TAG_DEFFERED); - - /* construct shader preview from image size and previewcustomdata */ - sp->scene = ip->scene; - sp->owner = ip->owner; - sp->sizex = cur_size->sizex; - sp->sizey = cur_size->sizey; - sp->pr_method = is_render ? PR_ICON_RENDER : PR_ICON_DEFERRED; - sp->pr_rect = cur_size->rect; - sp->id = ip->id; - sp->id_copy = ip->id_copy; - sp->bmain = ip->bmain; - sp->own_id_copy = false; - Material *ma = NULL; - - if (is_render) { - BLI_assert(ip->id); - - /* grease pencil use its own preview file */ - if (GS(ip->id->name) == ID_MA) { - ma = (Material *)ip->id; - } + if (ELEM(GS(ip->id->name), ID_OB)) { + /* Much simpler than the ShaderPreview mess used for other ID types. */ + object_preview_render(ip, cur_size); + } + else { + other_id_types_preview_render( + ip, cur_size, (prv->tag & PRV_TAG_DEFFERED), stop, do_update, progress); + } + } +} - if ((ma == NULL) || (ma->gp_style == NULL)) { - sp->pr_main = G_pr_main; - } - else { - sp->pr_main = G_pr_main_grease_pencil; - } +static void icon_preview_add_size(IconPreview *ip, uint *rect, int sizex, int sizey) +{ + IconPreviewSize *cur_size = ip->sizes.first, *new_size; + + while (cur_size) { + if (cur_size->sizex == sizex && cur_size->sizey == sizey) { + /* requested size is already in list, no need to add it again */ + return; } - common_preview_startjob(sp, stop, do_update, progress); - shader_preview_free(sp); + cur_size = cur_size->next; } + + new_size = MEM_callocN(sizeof(IconPreviewSize), "IconPreviewSize"); + new_size->sizex = sizex; + new_size->sizey = sizey; + new_size->rect = rect; + + BLI_addtail(&ip->sizes, new_size); } static void icon_preview_endjob(void *customdata) @@ -1333,7 +1489,9 @@ void ED_preview_icon_render(Main *bmain, Scene *scene, ID *id, uint *rect, int s ip.scene = scene; ip.owner = BKE_previewimg_id_ensure(id); ip.id = id; - ip.id_copy = duplicate_ids(id); + /* Control isn't given back to the caller until the preview is done. So we don't need to copy + * the ID to avoid thread races. */ + ip.id_copy = duplicate_ids(id, true); icon_preview_add_size(&ip, rect, sizex, sizey); @@ -1376,7 +1534,7 @@ void ED_preview_icon_job( ip->scene = CTX_data_scene(C); ip->owner = owner; ip->id = id; - ip->id_copy = duplicate_ids(id); + ip->id_copy = duplicate_ids(id, false); icon_preview_add_size(ip, rect, sizex, sizey); @@ -1445,7 +1603,7 @@ void ED_preview_shader_job(const bContext *C, sp->sizey = sizey; sp->pr_method = method; sp->id = id; - sp->id_copy = duplicate_ids(id); + sp->id_copy = duplicate_ids(id, false); sp->own_id_copy = true; sp->parent = parent; sp->slot = slot; diff --git a/source/blender/editors/space_view3d/view3d_utils.c b/source/blender/editors/space_view3d/view3d_utils.c index 1be9bd27c7a..2b7b8255068 100644 --- a/source/blender/editors/space_view3d/view3d_utils.c +++ b/source/blender/editors/space_view3d/view3d_utils.c @@ -1620,6 +1620,41 @@ void ED_view3d_to_object(const Depsgraph *depsgraph, BKE_object_apply_mat4_ex(ob, mat, ob_eval->parent, ob_eval->parentinv, true); } +bool ED_view3d_camera_to_view_selected(struct Main *bmain, + Depsgraph *depsgraph, + const Scene *scene, + Object *camera_ob) +{ + Object *camera_ob_eval = DEG_get_evaluated_object(depsgraph, camera_ob); + float co[3]; /* the new location to apply */ + float scale; /* only for ortho cameras */ + + if (BKE_camera_view_frame_fit_to_scene(depsgraph, scene, camera_ob_eval, co, &scale)) { + ObjectTfmProtectedChannels obtfm; + float obmat_new[4][4]; + + if ((camera_ob_eval->type == OB_CAMERA) && + (((Camera *)camera_ob_eval->data)->type == CAM_ORTHO)) { + ((Camera *)camera_ob->data)->ortho_scale = scale; + } + + copy_m4_m4(obmat_new, camera_ob_eval->obmat); + copy_v3_v3(obmat_new[3], co); + + /* only touch location */ + BKE_object_tfm_protected_backup(camera_ob, &obtfm); + BKE_object_apply_mat4(camera_ob, obmat_new, true, true); + BKE_object_tfm_protected_restore(camera_ob, &obtfm, OB_LOCK_SCALE | OB_LOCK_ROT4D); + + /* notifiers */ + DEG_id_tag_update_ex(bmain, &camera_ob->id, ID_RECALC_TRANSFORM); + + return true; + } + + return false; +} + /** \} */ /* -------------------------------------------------------------------- */ diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c index a24f59019f0..9d947384bf0 100644 --- a/source/blender/editors/space_view3d/view3d_view.c +++ b/source/blender/editors/space_view3d/view3d_view.c @@ -535,40 +535,18 @@ void VIEW3D_OT_camera_to_view(wmOperatorType *ot) * meant to take into account vertex/bone selection for eg. */ static int view3d_camera_to_view_selected_exec(bContext *C, wmOperator *op) { + Main *bmain = CTX_data_main(C); Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); Scene *scene = CTX_data_scene(C); View3D *v3d = CTX_wm_view3d(C); /* can be NULL */ Object *camera_ob = v3d ? v3d->camera : scene->camera; - Object *camera_ob_eval = DEG_get_evaluated_object(depsgraph, camera_ob); - - float r_co[3]; /* the new location to apply */ - float r_scale; /* only for ortho cameras */ - if (camera_ob_eval == NULL) { + if (camera_ob == NULL) { BKE_report(op->reports, RPT_ERROR, "No active camera"); return OPERATOR_CANCELLED; } - /* this function does all the important stuff */ - if (BKE_camera_view_frame_fit_to_scene(depsgraph, scene, camera_ob_eval, r_co, &r_scale)) { - ObjectTfmProtectedChannels obtfm; - float obmat_new[4][4]; - - if ((camera_ob_eval->type == OB_CAMERA) && - (((Camera *)camera_ob_eval->data)->type == CAM_ORTHO)) { - ((Camera *)camera_ob->data)->ortho_scale = r_scale; - } - - copy_m4_m4(obmat_new, camera_ob_eval->obmat); - copy_v3_v3(obmat_new[3], r_co); - - /* only touch location */ - BKE_object_tfm_protected_backup(camera_ob, &obtfm); - BKE_object_apply_mat4(camera_ob, obmat_new, true, true); - BKE_object_tfm_protected_restore(camera_ob, &obtfm, OB_LOCK_SCALE | OB_LOCK_ROT4D); - - /* notifiers */ - DEG_id_tag_update(&camera_ob->id, ID_RECALC_TRANSFORM); + if (ED_view3d_camera_to_view_selected(bmain, depsgraph, scene, camera_ob)) { WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, camera_ob); return OPERATOR_FINISHED; } -- cgit v1.2.3 From e3068f38c8c8df8cf198dc694aae9cc0c6e88633 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Mon, 14 Dec 2020 14:57:30 +0100 Subject: Fix memory leak and possible other issues with custom previews Mistake in 812ea9184221. Fixed that same one before in the branch, I may have brought it back when resolving merge conflicts. --- source/blender/blenkernel/intern/icons.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/intern/icons.c b/source/blender/blenkernel/intern/icons.c index 58b4a8ce315..ecafed5da31 100644 --- a/source/blender/blenkernel/intern/icons.c +++ b/source/blender/blenkernel/intern/icons.c @@ -467,7 +467,7 @@ PreviewImage *BKE_previewimg_cached_thumbnail_read(const char *name, } if (!prv) { - previewimg_deferred_create(path, source); + prv = previewimg_deferred_create(path, source); force_update = true; } -- cgit v1.2.3 From 6714b800d1716f7c7dec9a640d1c615bbf1a938f Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Mon, 14 Dec 2020 14:55:53 +0100 Subject: Cryptomatte: apply volume transmittance to Eevee. This patch will add volumetric transmittance to the cryptomatte coverage data of all samples when post processing the cryptomatte passes. It was discussed with Cycles that this is desired, but tricky to implement in Cycles. --- .../blender/draw/engines/eevee/eevee_cryptomatte.c | 63 ++++++++++++++++------ 1 file changed, 48 insertions(+), 15 deletions(-) (limited to 'source/blender') diff --git a/source/blender/draw/engines/eevee/eevee_cryptomatte.c b/source/blender/draw/engines/eevee/eevee_cryptomatte.c index 95f5aa8b628..9150de7184a 100644 --- a/source/blender/draw/engines/eevee/eevee_cryptomatte.c +++ b/source/blender/draw/engines/eevee/eevee_cryptomatte.c @@ -125,7 +125,7 @@ void EEVEE_cryptomatte_renderpasses_init(EEVEE_Data *vedata) return; } if (eevee_cryptomatte_active_layers(view_layer) != 0) { - g_data->render_passes |= EEVEE_RENDER_PASS_CRYPTOMATTE; + g_data->render_passes |= EEVEE_RENDER_PASS_CRYPTOMATTE | EEVEE_RENDER_PASS_VOLUME_LIGHT; g_data->cryptomatte_accurate_mode = (view_layer->cryptomatte_flag & VIEW_LAYER_CRYPTOMATTE_ACCURATE) != 0; } @@ -137,7 +137,8 @@ void EEVEE_cryptomatte_output_init(EEVEE_ViewLayerData *UNUSED(sldata), { EEVEE_FramebufferList *fbl = vedata->fbl; EEVEE_TextureList *txl = vedata->txl; - EEVEE_PrivateData *g_data = vedata->stl->g_data; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_PrivateData *g_data = stl->g_data; DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); const DRWContextState *draw_ctx = DRW_context_state_get(); @@ -469,6 +470,8 @@ static void eevee_cryptomatte_postprocess_weights(EEVEE_Data *vedata) { EEVEE_StorageList *stl = vedata->stl; EEVEE_PrivateData *g_data = stl->g_data; + EEVEE_EffectsInfo *effects = stl->effects; + EEVEE_TextureList *txl = vedata->txl; const DRWContextState *draw_ctx = DRW_context_state_get(); const ViewLayer *view_layer = draw_ctx->view_layer; const int num_cryptomatte_layers = eevee_cryptomatte_layers_count(view_layer); @@ -478,11 +481,25 @@ static void eevee_cryptomatte_postprocess_weights(EEVEE_Data *vedata) EEVEE_CryptomatteSample *accum_buffer = g_data->cryptomatte_accum_buffer; BLI_assert(accum_buffer); + float *volumetric_transmittance_buffer = NULL; + if ((effects->enabled_effects & EFFECT_VOLUMETRIC) != 0) { + volumetric_transmittance_buffer = GPU_texture_read( + txl->volume_transmittance_accum, GPU_DATA_FLOAT, 0); + } + const int num_samples = effects->taa_current_sample; + int accum_pixel_index = 0; int accum_pixel_stride = eevee_cryptomatte_pixel_stride(view_layer); for (int pixel_index = 0; pixel_index < buffer_size; pixel_index++, accum_pixel_index += accum_pixel_stride) { + float coverage = 1.0f; + if (volumetric_transmittance_buffer != NULL) { + coverage = (volumetric_transmittance_buffer[pixel_index * 4] + + volumetric_transmittance_buffer[pixel_index * 4 + 1] + + volumetric_transmittance_buffer[pixel_index * 4 + 2]) / + (3.0f * num_samples); + } for (int layer = 0; layer < num_cryptomatte_layers; layer++) { const int layer_offset = eevee_cryptomatte_layer_offset(view_layer, layer); /* Calculate the total weight of the sample. */ @@ -493,24 +510,40 @@ static void eevee_cryptomatte_postprocess_weights(EEVEE_Data *vedata) } BLI_assert(total_weight > 0.0f); - float total_weight_inv = 1.0f / total_weight; - for (int level = 0; level < num_levels; level++) { - EEVEE_CryptomatteSample *sample = &accum_buffer[accum_pixel_index + layer_offset + level]; - /* Remove background samples. These samples were used to determine the correct weight - * but won't be part of the final result. */ - if (sample->hash == 0.0f) { + float total_weight_inv = coverage / total_weight; + if (total_weight_inv > 0.0f) { + for (int level = 0; level < num_levels; level++) { + EEVEE_CryptomatteSample *sample = + &accum_buffer[accum_pixel_index + layer_offset + level]; + /* Remove background samples. These samples were used to determine the correct weight + * but won't be part of the final result. */ + if (sample->hash == 0.0f) { + sample->weight = 0.0f; + } + sample->weight *= total_weight_inv; + } + + /* Sort accum buffer by coverage of each sample. */ + qsort(&accum_buffer[accum_pixel_index + layer_offset], + num_levels, + sizeof(EEVEE_CryptomatteSample), + eevee_cryptomatte_sample_cmp_reverse); + } + else { + /* This pixel doesn't have any weight, so clear it fully. */ + for (int level = 0; level < num_levels; level++) { + EEVEE_CryptomatteSample *sample = + &accum_buffer[accum_pixel_index + layer_offset + level]; sample->weight = 0.0f; + sample->hash = 0.0f; } - sample->weight *= total_weight_inv; } - - /* Sort accum buffer by coverage of each sample. */ - qsort(&accum_buffer[accum_pixel_index + layer_offset], - num_levels, - sizeof(EEVEE_CryptomatteSample), - eevee_cryptomatte_sample_cmp_reverse); } } + + if (volumetric_transmittance_buffer) { + MEM_freeN(volumetric_transmittance_buffer); + } } /* Extract cryptomatte layer from the cryptomatte_accum_buffer to render passes. */ -- cgit v1.2.3 From 9ee7270e0acc6d60c8eac9e25cca00aa384c0879 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Mon, 14 Dec 2020 15:28:24 +0100 Subject: Geometry Nodes: require vertex groups data in nodes modifier Without this, the modifier evaluation code might remove any vertex groups from the mesh for performance reasons. We can't say for sure whether the node group will need the vertex groups, but it is quite likely. Ref T83357. --- source/blender/modifiers/intern/MOD_nodes.cc | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'source/blender') diff --git a/source/blender/modifiers/intern/MOD_nodes.cc b/source/blender/modifiers/intern/MOD_nodes.cc index 6730ce1c8a8..652558655ce 100644 --- a/source/blender/modifiers/intern/MOD_nodes.cc +++ b/source/blender/modifiers/intern/MOD_nodes.cc @@ -1063,6 +1063,15 @@ static void freeData(ModifierData *md) } } +static void requiredDataMask(Object *UNUSED(ob), + ModifierData *UNUSED(md), + CustomData_MeshMasks *r_cddata_masks) +{ + /* We don't know what the node tree will need. If there are vertex groups, it is likely that the + * node tree wants to access them. */ + r_cddata_masks->vmask |= CD_MASK_MDEFORMVERT; +} + ModifierTypeInfo modifierType_Nodes = { /* name */ "GeometryNodes", /* structName */ "NodesModifierData", @@ -1087,7 +1096,7 @@ ModifierTypeInfo modifierType_Nodes = { /* modifyVolume */ nullptr, /* initData */ initData, - /* requiredDataMask */ nullptr, + /* requiredDataMask */ requiredDataMask, /* freeData */ freeData, /* isDisabled */ isDisabled, /* updateDepsgraph */ updateDepsgraph, -- cgit v1.2.3 From 07ce9910f7ccaa48ae28c35049dec598b6214b36 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Mon, 14 Dec 2020 15:44:28 +0100 Subject: Geometry Nodes: enabled supports-mapping in nodes modifier Sometimes the geometry nodes modifier does support mapping and sometimes it does not. We have no infrastruture to determine this ahead of time currently. In order to support common use cases, it makes sense to add this flag to the modifier. One such common use case is to use the mesh as surface that other things are distributed on. Often, the distribution is controlled by vertex groups. Therefore, it would be helpful if the modifier is evaluated when the object is in vertex paint mode. This allows the user to see the distributed objects while painting. If the nodes modifier transforms the mesh in any way, vertex painting might not work as expected anymore, because the `deformMatrices` callback is not implemented. I'm not sure how this can be solved nicely, yet. --- source/blender/modifiers/intern/MOD_nodes.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source/blender') diff --git a/source/blender/modifiers/intern/MOD_nodes.cc b/source/blender/modifiers/intern/MOD_nodes.cc index 652558655ce..657fbb7e7f1 100644 --- a/source/blender/modifiers/intern/MOD_nodes.cc +++ b/source/blender/modifiers/intern/MOD_nodes.cc @@ -1079,9 +1079,9 @@ ModifierTypeInfo modifierType_Nodes = { /* srna */ &RNA_NodesModifier, /* type */ eModifierTypeType_Constructive, /* flags */ - static_cast(eModifierTypeFlag_AcceptsMesh | - eModifierTypeFlag_SupportsEditmode | - eModifierTypeFlag_EnableInEditmode), + static_cast( + eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsEditmode | + eModifierTypeFlag_EnableInEditmode | eModifierTypeFlag_SupportsMapping), /* icon */ ICON_NODETREE, /* copyData */ copyData, -- cgit v1.2.3 From f4df036bc497b134789b624efd9008c6f4b9c6c8 Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Mon, 14 Dec 2020 16:14:21 +0100 Subject: Cryptomatte: Data structure in compositor node This changes the way how the mattes are stored in the compositor node. This used to be a single string what was decoded/encoded when needed. The new data structure stores all entries in `CryptomatteEntry` and is converted to the old `matte_id` property on the fly. This is done for some future changes in the workflow where a more structured approach leads to less confusing and easier to read code. --- source/blender/blenkernel/BKE_cryptomatte.h | 10 ++ source/blender/blenkernel/CMakeLists.txt | 2 +- source/blender/blenkernel/intern/cryptomatte.c | 87 ---------- source/blender/blenkernel/intern/cryptomatte.cc | 190 +++++++++++++++++++++ source/blender/blenloader/intern/versioning_290.c | 20 +++ .../compositor/nodes/COM_CryptomatteNode.cpp | 53 +----- source/blender/makesdna/DNA_node_types.h | 12 +- source/blender/makesrna/RNA_access.h | 1 + source/blender/makesrna/intern/rna_nodetree.c | 44 +++-- .../composite/nodes/node_composite_cryptomatte.c | 178 ++----------------- 10 files changed, 288 insertions(+), 309 deletions(-) delete mode 100644 source/blender/blenkernel/intern/cryptomatte.c create mode 100644 source/blender/blenkernel/intern/cryptomatte.cc (limited to 'source/blender') diff --git a/source/blender/blenkernel/BKE_cryptomatte.h b/source/blender/blenkernel/BKE_cryptomatte.h index 929266d1b89..c3c17f72cae 100644 --- a/source/blender/blenkernel/BKE_cryptomatte.h +++ b/source/blender/blenkernel/BKE_cryptomatte.h @@ -25,18 +25,28 @@ #include "BLI_sys_types.h" +#include "DNA_layer_types.h" + #ifdef __cplusplus extern "C" { #endif struct Object; struct Material; +struct ID; +struct Main; +uint32_t BKE_cryptomatte_hash(const char *name, int name_len); uint32_t BKE_cryptomatte_object_hash(const struct Object *object); uint32_t BKE_cryptomatte_material_hash(const struct Material *material); uint32_t BKE_cryptomatte_asset_hash(const struct Object *object); float BKE_cryptomatte_hash_to_float(uint32_t cryptomatte_hash); +char *BKE_cryptomatte_entries_to_matte_id(struct NodeCryptomatte *node_storage); +void BKE_cryptomatte_matte_id_to_entries(const struct Main *bmain, + struct NodeCryptomatte *node_storage, + const char *matte_id); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index 5b10f734d71..d440d3e4d64 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -101,7 +101,7 @@ set(SRC intern/constraint.c intern/context.c intern/crazyspace.c - intern/cryptomatte.c + intern/cryptomatte.cc intern/curve.c intern/curve_bevel.c intern/curve_decimate.c diff --git a/source/blender/blenkernel/intern/cryptomatte.c b/source/blender/blenkernel/intern/cryptomatte.c deleted file mode 100644 index 6570ffce920..00000000000 --- a/source/blender/blenkernel/intern/cryptomatte.c +++ /dev/null @@ -1,87 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2008 Blender Foundation. - * All rights reserved. - */ - -/** \file - * \ingroup bke - */ - -#include "BKE_cryptomatte.h" - -#include "DNA_material_types.h" -#include "DNA_object_types.h" - -#include "BLI_compiler_attrs.h" -#include "BLI_hash_mm3.h" -#include "BLI_string.h" -#include - -static uint32_t cryptomatte_hash(const ID *id) -{ - const char *name = &id->name[2]; - const int len = BLI_strnlen(name, MAX_NAME - 2); - uint32_t cryptohash_int = BLI_hash_mm3((const unsigned char *)name, len, 0); - return cryptohash_int; -} - -uint32_t BKE_cryptomatte_object_hash(const Object *object) -{ - return cryptomatte_hash(&object->id); -} - -uint32_t BKE_cryptomatte_material_hash(const Material *material) -{ - if (material == NULL) { - return 0.0f; - } - return cryptomatte_hash(&material->id); -} - -uint32_t BKE_cryptomatte_asset_hash(const Object *object) -{ - const Object *asset_object = object; - while (asset_object->parent != NULL) { - asset_object = asset_object->parent; - } - return cryptomatte_hash(&asset_object->id); -} - -/* Convert a cryptomatte hash to a float. - * - * Cryptomatte hashes are stored in float textures and images. The conversion is taken from the - * cryptomatte specification. See Floating point conversion section in - * https://github.com/Psyop/Cryptomatte/blob/master/specification/cryptomatte_specification.pdf. - * - * The conversion uses as many 32 bit floating point values as possible to minimize hash - * collisions. Unfortunately not all 32 bits can be as NaN and Inf can be problematic. - * - * Note that this conversion assumes to be running on a L-endian system. */ -float BKE_cryptomatte_hash_to_float(uint32_t cryptomatte_hash) -{ - uint32_t mantissa = cryptomatte_hash & ((1 << 23) - 1); - uint32_t exponent = (cryptomatte_hash >> 23) & ((1 << 8) - 1); - exponent = MAX2(exponent, (uint32_t)1); - exponent = MIN2(exponent, (uint32_t)254); - exponent = exponent << 23; - uint32_t sign = (cryptomatte_hash >> 31); - sign = sign << 31; - uint32_t float_bits = sign | exponent | mantissa; - float f; - memcpy(&f, &float_bits, sizeof(uint32_t)); - return f; -} diff --git a/source/blender/blenkernel/intern/cryptomatte.cc b/source/blender/blenkernel/intern/cryptomatte.cc new file mode 100644 index 00000000000..4bbeb088628 --- /dev/null +++ b/source/blender/blenkernel/intern/cryptomatte.cc @@ -0,0 +1,190 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2020 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup bke + */ + +#include "BKE_cryptomatte.h" +#include "BKE_main.h" + +#include "DNA_material_types.h" +#include "DNA_node_types.h" +#include "DNA_object_types.h" + +#include "BLI_compiler_attrs.h" +#include "BLI_dynstr.h" +#include "BLI_hash_mm3.h" +#include "BLI_listbase.h" +#include "BLI_string.h" + +#include "MEM_guardedalloc.h" + +#include +#include +#include + +static uint32_t cryptomatte_hash(const ID *id) +{ + const char *name = &id->name[2]; + const int name_len = BLI_strnlen(name, MAX_NAME); + uint32_t cryptohash_int = BKE_cryptomatte_hash(name, name_len); + return cryptohash_int; +} + +uint32_t BKE_cryptomatte_hash(const char *name, int name_len) +{ + uint32_t cryptohash_int = BLI_hash_mm3((const unsigned char *)name, name_len, 0); + return cryptohash_int; +} + +uint32_t BKE_cryptomatte_object_hash(const Object *object) +{ + return cryptomatte_hash(&object->id); +} + +uint32_t BKE_cryptomatte_material_hash(const Material *material) +{ + if (material == nullptr) { + return 0.0f; + } + return cryptomatte_hash(&material->id); +} + +uint32_t BKE_cryptomatte_asset_hash(const Object *object) +{ + const Object *asset_object = object; + while (asset_object->parent != nullptr) { + asset_object = asset_object->parent; + } + return cryptomatte_hash(&asset_object->id); +} + +/* Convert a cryptomatte hash to a float. + * + * Cryptomatte hashes are stored in float textures and images. The conversion is taken from the + * cryptomatte specification. See Floating point conversion section in + * https://github.com/Psyop/Cryptomatte/blob/master/specification/cryptomatte_specification.pdf. + * + * The conversion uses as many 32 bit floating point values as possible to minimize hash + * collisions. Unfortunately not all 32 bits can be as NaN and Inf can be problematic. + * + * Note that this conversion assumes to be running on a L-endian system. */ +float BKE_cryptomatte_hash_to_float(uint32_t cryptomatte_hash) +{ + uint32_t mantissa = cryptomatte_hash & ((1 << 23) - 1); + uint32_t exponent = (cryptomatte_hash >> 23) & ((1 << 8) - 1); + exponent = MAX2(exponent, (uint32_t)1); + exponent = MIN2(exponent, (uint32_t)254); + exponent = exponent << 23; + uint32_t sign = (cryptomatte_hash >> 31); + sign = sign << 31; + uint32_t float_bits = sign | exponent | mantissa; + float f; + memcpy(&f, &float_bits, sizeof(uint32_t)); + return f; +} + +static ID *cryptomatte_find_id(const ListBase *ids, const float encoded_hash) +{ + LISTBASE_FOREACH (ID *, id, ids) { + uint32_t hash = BKE_cryptomatte_hash((id->name + 2), BLI_strnlen(id->name + 2, MAX_NAME)); + if (BKE_cryptomatte_hash_to_float(hash) == encoded_hash) { + return id; + } + } + return nullptr; +} + +/* Find an ID in the given main that matches the given encoded float. */ +static struct ID *BKE_cryptomatte_find_id(const Main *bmain, const float encoded_hash) +{ + ID *result; + result = cryptomatte_find_id(&bmain->objects, encoded_hash); + if (result == nullptr) { + result = cryptomatte_find_id(&bmain->materials, encoded_hash); + } + return result; +} + +char *BKE_cryptomatte_entries_to_matte_id(NodeCryptomatte *node_storage) +{ + DynStr *matte_id = BLI_dynstr_new(); + bool first = true; + LISTBASE_FOREACH (CryptomatteEntry *, entry, &node_storage->entries) { + if (!first) { + BLI_dynstr_append(matte_id, ","); + } + if (BLI_strnlen(entry->name, sizeof(entry->name)) != 0) { + BLI_dynstr_nappend(matte_id, entry->name, sizeof(entry->name)); + } + else { + BLI_dynstr_appendf(matte_id, "<%.9g>", entry->encoded_hash); + } + first = false; + } + char *result = BLI_dynstr_get_cstring(matte_id); + BLI_dynstr_free(matte_id); + return result; +} + +void BKE_cryptomatte_matte_id_to_entries(const Main *bmain, + NodeCryptomatte *node_storage, + const char *matte_id) +{ + BLI_freelistN(&node_storage->entries); + + std::istringstream ss(matte_id); + while (ss.good()) { + CryptomatteEntry *entry = nullptr; + std::string token; + getline(ss, token, ','); + /* Ignore empty tokens. */ + if (token.length() > 0) { + size_t first = token.find_first_not_of(' '); + size_t last = token.find_last_not_of(' '); + if (first == std::string::npos || last == std::string::npos) { + break; + } + token = token.substr(first, (last - first + 1)); + if (*token.begin() == '<' && *(--token.end()) == '>') { + float encoded_hash = atof(token.substr(1, token.length() - 2).c_str()); + entry = (CryptomatteEntry *)MEM_callocN(sizeof(CryptomatteEntry), __func__); + entry->encoded_hash = encoded_hash; + if (bmain) { + ID *id = BKE_cryptomatte_find_id(bmain, encoded_hash); + if (id != nullptr) { + BLI_strncpy(entry->name, id->name + 2, sizeof(entry->name)); + } + } + } + else { + const char *name = token.c_str(); + int name_len = token.length(); + entry = (CryptomatteEntry *)MEM_callocN(sizeof(CryptomatteEntry), __func__); + BLI_strncpy(entry->name, name, sizeof(entry->name)); + uint32_t hash = BKE_cryptomatte_hash(name, name_len); + entry->encoded_hash = BKE_cryptomatte_hash_to_float(hash); + } + } + if (entry != nullptr) { + BLI_addtail(&node_storage->entries, entry); + } + } +} \ No newline at end of file diff --git a/source/blender/blenloader/intern/versioning_290.c b/source/blender/blenloader/intern/versioning_290.c index 4e642258899..6f055186702 100644 --- a/source/blender/blenloader/intern/versioning_290.c +++ b/source/blender/blenloader/intern/versioning_290.c @@ -52,6 +52,7 @@ #include "BKE_armature.h" #include "BKE_collection.h" #include "BKE_colortools.h" +#include "BKE_cryptomatte.h" #include "BKE_fcurve.h" #include "BKE_gpencil.h" #include "BKE_lib_id.h" @@ -1280,5 +1281,24 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain) } } } + + /* Convert `NodeCryptomatte->storage->matte_id` to `NodeCryptomatte->storage->entries` */ + if (!DNA_struct_find(fd->filesdna, "CryptomatteEntry")) { + LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) { + if (scene->nodetree) { + LISTBASE_FOREACH (bNode *, node, &scene->nodetree->nodes) { + if (node->type == CMP_NODE_CRYPTOMATTE) { + NodeCryptomatte *storage = (NodeCryptomatte *)node->storage; + char *matte_id = storage->matte_id; + if (matte_id == NULL || strlen(storage->matte_id) == 0) { + continue; + } + BKE_cryptomatte_matte_id_to_entries(NULL, storage, storage->matte_id); + MEM_SAFE_FREE(storage->matte_id); + } + } + } + } + } } } diff --git a/source/blender/compositor/nodes/COM_CryptomatteNode.cpp b/source/blender/compositor/nodes/COM_CryptomatteNode.cpp index 8cc6b933759..7ca4e1f76fc 100644 --- a/source/blender/compositor/nodes/COM_CryptomatteNode.cpp +++ b/source/blender/compositor/nodes/COM_CryptomatteNode.cpp @@ -17,12 +17,15 @@ */ #include "COM_CryptomatteNode.h" -#include "BLI_assert.h" -#include "BLI_hash_mm3.h" -#include "BLI_string.h" #include "COM_ConvertOperation.h" #include "COM_CryptomatteOperation.h" #include "COM_SetAlphaOperation.h" + +#include "BLI_assert.h" +#include "BLI_hash_mm3.h" +#include "BLI_listbase.h" +#include "BLI_string.h" + #include CryptomatteNode::CryptomatteNode(bNode *editorNode) : Node(editorNode) @@ -30,24 +33,6 @@ CryptomatteNode::CryptomatteNode(bNode *editorNode) : Node(editorNode) /* pass */ } -/* This is taken from the Cryptomatte specification 1.0. */ -static inline float hash_to_float(uint32_t hash) -{ - uint32_t mantissa = hash & ((1 << 23) - 1); - uint32_t exponent = (hash >> 23) & ((1 << 8) - 1); - exponent = max(exponent, (uint32_t)1); - exponent = min(exponent, (uint32_t)254); - exponent = exponent << 23; - uint32_t sign = (hash >> 31); - sign = sign << 31; - uint32_t float_bits = sign | exponent | mantissa; - float f; - /* Bit casting relies on equal size for both types. */ - BLI_STATIC_ASSERT(sizeof(float) == sizeof(uint32_t), "float and uint32_t are not the same size") - ::memcpy(&f, &float_bits, sizeof(float)); - return f; -} - void CryptomatteNode::convertToOperations(NodeConverter &converter, const CompositorContext & /*context*/) const { @@ -61,30 +46,8 @@ void CryptomatteNode::convertToOperations(NodeConverter &converter, CryptomatteOperation *operation = new CryptomatteOperation(getNumberOfInputSockets() - 1); if (cryptoMatteSettings) { - if (cryptoMatteSettings->matte_id) { - /* Split the string by commas, ignoring white space. */ - std::string input = cryptoMatteSettings->matte_id; - std::istringstream ss(input); - while (ss.good()) { - std::string token; - getline(ss, token, ','); - /* Ignore empty tokens. */ - if (token.length() > 0) { - size_t first = token.find_first_not_of(' '); - size_t last = token.find_last_not_of(' '); - if (first == std::string::npos || last == std::string::npos) { - break; - } - token = token.substr(first, (last - first + 1)); - if (*token.begin() == '<' && *(--token.end()) == '>') { - operation->addObjectIndex(atof(token.substr(1, token.length() - 2).c_str())); - } - else { - uint32_t hash = BLI_hash_mm3((const unsigned char *)token.c_str(), token.length(), 0); - operation->addObjectIndex(hash_to_float(hash)); - } - } - } + LISTBASE_FOREACH (CryptomatteEntry *, cryptomatte_entry, &cryptoMatteSettings->entries) { + operation->addObjectIndex(cryptomatte_entry->encoded_hash); } } diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 8e463a8b406..f6ceb2b8e6a 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -1052,10 +1052,20 @@ typedef struct NodeSunBeams { float ray_length; } NodeSunBeams; +typedef struct CryptomatteEntry { + struct CryptomatteEntry *next, *prev; + float encoded_hash; + /** MAX_NAME. */ + char name[64]; + char _pad[4]; +} CryptomatteEntry; + typedef struct NodeCryptomatte { float add[3]; float remove[3]; - char *matte_id; + char *matte_id DNA_DEPRECATED; + /* Contains `CryptomatteEntry`. */ + ListBase entries; int num_inputs; char _pad[4]; } NodeCryptomatte; diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index a581edcb04b..4aeb9b9e5f7 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -202,6 +202,7 @@ extern StructRNA RNA_CopyRotationConstraint; extern StructRNA RNA_CopyScaleConstraint; extern StructRNA RNA_CopyTransformsConstraint; extern StructRNA RNA_CorrectiveSmoothModifier; +extern StructRNA RNA_CryptomatteEntry; extern StructRNA RNA_Curve; extern StructRNA RNA_CurveMap; extern StructRNA RNA_CurveMapPoint; diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 4fc486eadac..153e2aebd22 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -37,6 +37,7 @@ #include "BKE_animsys.h" #include "BKE_attribute.h" +#include "BKE_cryptomatte.h" #include "BKE_image.h" #include "BKE_node.h" #include "BKE_texture.h" @@ -3626,33 +3627,26 @@ static void rna_NodeCryptomatte_matte_get(PointerRNA *ptr, char *value) { bNode *node = (bNode *)ptr->data; NodeCryptomatte *nc = node->storage; - - strcpy(value, (nc->matte_id) ? nc->matte_id : ""); + char *matte_id = BKE_cryptomatte_entries_to_matte_id(nc); + strcpy(value, matte_id); + MEM_freeN(matte_id); } static int rna_NodeCryptomatte_matte_length(PointerRNA *ptr) { bNode *node = (bNode *)ptr->data; NodeCryptomatte *nc = node->storage; - - return (nc->matte_id) ? strlen(nc->matte_id) : 0; + char *matte_id = BKE_cryptomatte_entries_to_matte_id(nc); + int result = strlen(matte_id); + MEM_freeN(matte_id); + return result; } static void rna_NodeCryptomatte_matte_set(PointerRNA *ptr, const char *value) { bNode *node = (bNode *)ptr->data; NodeCryptomatte *nc = node->storage; - - if (nc->matte_id) { - MEM_freeN(nc->matte_id); - } - - if (value && value[0]) { - nc->matte_id = BLI_strdup(value); - } - else { - nc->matte_id = NULL; - } + BKE_cryptomatte_matte_id_to_entries(NULL, nc, value); } static void rna_NodeCryptomatte_update_add(Main *bmain, Scene *scene, PointerRNA *ptr) @@ -8205,6 +8199,24 @@ static void def_cmp_sunbeams(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); } +static void def_cmp_cryptomatte_entry(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "CryptomatteEntry", NULL); + RNA_def_struct_sdna(srna, "CryptomatteEntry"); + + prop = RNA_def_property(srna, "encoded_hash", PROP_FLOAT, PROP_NONE); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_float_sdna(prop, NULL, "encoded_hash"); + + prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Name", ""); + RNA_def_struct_name_property(srna, prop); +} + static void def_cmp_cryptomatte(StructRNA *srna) { PropertyRNA *prop; @@ -8494,6 +8506,8 @@ static void rna_def_compositor_node(BlenderRNA *brna) /* compositor node need_exec flag */ func = RNA_def_function(srna, "tag_need_exec", "rna_CompositorNode_tag_need_exec"); RNA_def_function_ui_description(func, "Tag the node for compositor update"); + + def_cmp_cryptomatte_entry(brna); } static void rna_def_texture_node(BlenderRNA *brna) diff --git a/source/blender/nodes/composite/nodes/node_composite_cryptomatte.c b/source/blender/nodes/composite/nodes/node_composite_cryptomatte.c index c8d2d993e75..f5308fe2671 100644 --- a/source/blender/nodes/composite/nodes/node_composite_cryptomatte.c +++ b/source/blender/nodes/composite/nodes/node_composite_cryptomatte.c @@ -27,172 +27,36 @@ #include "BLI_utildefines.h" #include "node_composite_util.h" -/* this is taken from the cryptomatte specification 1.0 */ - -BLI_INLINE float hash_to_float(uint32_t hash) +static CryptomatteEntry *cryptomatte_find(NodeCryptomatte *n, float encoded_hash) { - uint32_t mantissa = hash & ((1 << 23) - 1); - uint32_t exponent = (hash >> 23) & ((1 << 8) - 1); - exponent = MAX2(exponent, (uint32_t)1); - exponent = MIN2(exponent, (uint32_t)254); - exponent = exponent << 23; - uint32_t sign = (hash >> 31); - sign = sign << 31; - uint32_t float_bits = sign | exponent | mantissa; - float f; - /* Bit casting relies on equal size for both types. */ - BLI_STATIC_ASSERT(sizeof(float) == sizeof(uint32_t), "float and uint32_t are not the same size") - memcpy(&f, &float_bits, sizeof(float)); - return f; + LISTBASE_FOREACH (CryptomatteEntry *, entry, &n->entries) { + if (entry->encoded_hash == encoded_hash) { + return entry; + } + } + return NULL; } static void cryptomatte_add(NodeCryptomatte *n, float f) { - /* Turn the number into a string. */ - char number[32]; - BLI_snprintf(number, sizeof(number), "<%.9g>", f); - - /* Search if we already have the number. */ - if (n->matte_id && strlen(n->matte_id) != 0) { - size_t start = 0; - const size_t end = strlen(n->matte_id); - size_t token_len = 0; - while (start < end) { - /* Ignore leading whitespace. */ - while (start < end && n->matte_id[start] == ' ') { - start++; - } - - /* Find the next separator. */ - char *token_end = strchr(n->matte_id + start, ','); - if (ELEM(token_end, NULL, n->matte_id + start)) { - token_end = n->matte_id + end; - } - /* Be aware that token_len still contains any trailing white space. */ - token_len = token_end - (n->matte_id + start); - - /* If this has a leading bracket, - * assume a raw floating point number and look for the closing bracket. */ - if (n->matte_id[start] == '<') { - if (strncmp(n->matte_id + start, number, strlen(number)) == 0) { - /* This number is already there, so continue. */ - return; - } - } - else { - /* Remove trailing white space */ - size_t name_len = token_len; - while (n->matte_id[start + name_len] == ' ' && name_len > 0) { - name_len--; - } - /* Calculate the hash of the token and compare. */ - uint32_t hash = BLI_hash_mm3((const unsigned char *)(n->matte_id + start), name_len, 0); - if (f == hash_to_float(hash)) { - return; - } - } - start += token_len + 1; - } - } - - DynStr *new_matte = BLI_dynstr_new(); - if (!new_matte) { + /* Check if entry already exist. */ + if (cryptomatte_find(n, f) != NULL) { return; } - - if (n->matte_id) { - BLI_dynstr_append(new_matte, n->matte_id); - MEM_freeN(n->matte_id); - } - - if (BLI_dynstr_get_len(new_matte) > 0) { - BLI_dynstr_append(new_matte, ","); - } - BLI_dynstr_append(new_matte, number); - n->matte_id = BLI_dynstr_get_cstring(new_matte); - BLI_dynstr_free(new_matte); + CryptomatteEntry *entry = MEM_callocN(sizeof(CryptomatteEntry), __func__); + entry->encoded_hash = f; + BLI_addtail(&n->entries, entry); } static void cryptomatte_remove(NodeCryptomatte *n, float f) { - if (n->matte_id == NULL || strlen(n->matte_id) == 0) { - /* Empty string, nothing to remove. */ + CryptomatteEntry *entry = cryptomatte_find(n, f); + if (entry == NULL) { return; } - /* This will be the new string without the removed key. */ - DynStr *new_matte = BLI_dynstr_new(); - if (!new_matte) { - return; - } - - /* Turn the number into a string. */ - static char number[32]; - BLI_snprintf(number, sizeof(number), "<%.9g>", f); - - /* Search if we already have the number. */ - size_t start = 0; - const size_t end = strlen(n->matte_id); - size_t token_len = 0; - bool is_first = true; - while (start < end) { - bool skip = false; - /* Ignore leading whitespace or commas. */ - while (start < end && ((n->matte_id[start] == ' ') || (n->matte_id[start] == ','))) { - start++; - } - - /* Find the next separator. */ - char *token_end = strchr(n->matte_id + start + 1, ','); - if (ELEM(token_end, NULL, n->matte_id + start)) { - token_end = n->matte_id + end; - } - /* Be aware that token_len still contains any trailing white space. */ - token_len = token_end - (n->matte_id + start); - - if (token_len == 1) { - skip = true; - } - /* If this has a leading bracket, - * assume a raw floating point number and look for the closing bracket. */ - else if (n->matte_id[start] == '<') { - if (strncmp(n->matte_id + start, number, strlen(number)) == 0) { - /* This number is already there, so skip it. */ - skip = true; - } - } - else { - /* Remove trailing white space */ - size_t name_len = token_len; - while (n->matte_id[start + name_len] == ' ' && name_len > 0) { - name_len--; - } - /* Calculate the hash of the token and compare. */ - uint32_t hash = BLI_hash_mm3((const unsigned char *)(n->matte_id + start), name_len, 0); - if (f == hash_to_float(hash)) { - skip = true; - } - } - if (!skip) { - if (is_first) { - is_first = false; - } - else { - BLI_dynstr_append(new_matte, ", "); - } - BLI_dynstr_nappend(new_matte, n->matte_id + start, token_len); - } - start += token_len + 1; - } - - if (n->matte_id) { - MEM_freeN(n->matte_id); - n->matte_id = NULL; - } - if (BLI_dynstr_get_len(new_matte) > 0) { - n->matte_id = BLI_dynstr_get_cstring(new_matte); - } - BLI_dynstr_free(new_matte); + BLI_remlink(&n->entries, entry); + MEM_freeN(entry); } static bNodeSocketTemplate outputs[] = { @@ -265,10 +129,7 @@ static void node_free_cryptomatte(bNode *node) NodeCryptomatte *nc = node->storage; if (nc) { - if (nc->matte_id) { - MEM_freeN(nc->matte_id); - } - + BLI_freelistN(&nc->entries); MEM_freeN(nc); } } @@ -280,10 +141,7 @@ static void node_copy_cryptomatte(bNodeTree *UNUSED(dest_ntree), NodeCryptomatte *src_nc = src_node->storage; NodeCryptomatte *dest_nc = MEM_dupallocN(src_nc); - if (src_nc->matte_id) { - dest_nc->matte_id = MEM_dupallocN(src_nc->matte_id); - } - + BLI_duplicatelist(&dest_nc->entries, &src_nc->entries); dest_node->storage = dest_nc; } -- cgit v1.2.3 From 49ec3cef69bf183b488b680b7ab98105ce8acdd0 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Mon, 14 Dec 2020 11:43:46 -0600 Subject: Geometry Nodes: Input data type utility function This commit adds a simple utility function for getting the data type of an attribute or its "constant" socket counterparts. No functional changes. Differential Revision: https://developer.blender.org/D9819 --- source/blender/nodes/NOD_geometry_exec.hh | 11 +++++ source/blender/nodes/intern/node_geometry_exec.cc | 59 +++++++++++++++++++---- 2 files changed, 61 insertions(+), 9 deletions(-) (limited to 'source/blender') diff --git a/source/blender/nodes/NOD_geometry_exec.hh b/source/blender/nodes/NOD_geometry_exec.hh index a7df4bc3e1b..5fe554e0478 100644 --- a/source/blender/nodes/NOD_geometry_exec.hh +++ b/source/blender/nodes/NOD_geometry_exec.hh @@ -168,10 +168,21 @@ class GeoNodeExecParams { return this->get_input_attribute(name, component, domain, type, &default_value); } + /** + * Get the type of an input property or the associated constant socket types with the + * same names. Fall back to the default value if no attribute exists with the name. + */ + CustomDataType get_input_attribute_data_type(const StringRef name, + const GeometryComponent &component, + const CustomDataType default_type) const; + private: /* Utilities for detecting common errors at when using this class. */ void check_extract_input(StringRef identifier, const CPPType *requested_type = nullptr) const; void check_set_output(StringRef identifier, const CPPType &value_type) const; + + /* Find the active socket socket with the input name (not the identifier). */ + const bNodeSocket *find_available_socket(const StringRef name) const; }; } // namespace blender::nodes diff --git a/source/blender/nodes/intern/node_geometry_exec.cc b/source/blender/nodes/intern/node_geometry_exec.cc index a6d9115f01f..6a22adb25a7 100644 --- a/source/blender/nodes/intern/node_geometry_exec.cc +++ b/source/blender/nodes/intern/node_geometry_exec.cc @@ -19,23 +19,31 @@ namespace blender::nodes { -ReadAttributePtr GeoNodeExecParams::get_input_attribute(const StringRef name, - const GeometryComponent &component, - const AttributeDomain domain, - const CustomDataType type, - const void *default_value) const +const bNodeSocket *GeoNodeExecParams::find_available_socket(const StringRef name) const { - const bNodeSocket *found_socket = nullptr; LISTBASE_FOREACH (const bNodeSocket *, socket, &node_.inputs) { if ((socket->flag & SOCK_UNAVAIL) != 0) { continue; } if (name == socket->name) { - found_socket = socket; - break; + return socket; } } - BLI_assert(found_socket != nullptr); + + return nullptr; +} + +ReadAttributePtr GeoNodeExecParams::get_input_attribute(const StringRef name, + const GeometryComponent &component, + const AttributeDomain domain, + const CustomDataType type, + const void *default_value) const +{ + const bNodeSocket *found_socket = this->find_available_socket(name); + BLI_assert(found_socket != nullptr); /* There should always be available socket for the name. */ + if (found_socket == nullptr) { + return component.attribute_get_constant_for_read(domain, type, default_value); + } if (found_socket->type == SOCK_STRING) { const std::string name = this->get_input(found_socket->identifier); @@ -60,6 +68,39 @@ ReadAttributePtr GeoNodeExecParams::get_input_attribute(const StringRef name, return component.attribute_get_constant_for_read(domain, type, default_value); } +CustomDataType GeoNodeExecParams::get_input_attribute_data_type( + const StringRef name, + const GeometryComponent &component, + const CustomDataType default_type) const +{ + const bNodeSocket *found_socket = this->find_available_socket(name); + BLI_assert(found_socket != nullptr); /* There should always be available socket for the name. */ + if (found_socket == nullptr) { + return default_type; + } + + if (found_socket->type == SOCK_STRING) { + const std::string name = this->get_input(found_socket->identifier); + ReadAttributePtr attribute = component.attribute_try_get_for_read(name); + if (!attribute) { + return default_type; + } + return attribute->custom_data_type(); + } + if (found_socket->type == SOCK_FLOAT) { + return CD_PROP_FLOAT; + } + if (found_socket->type == SOCK_VECTOR) { + return CD_PROP_FLOAT3; + } + if (found_socket->type == SOCK_RGBA) { + return CD_PROP_COLOR; + } + + BLI_assert(false); + return default_type; +} + void GeoNodeExecParams::check_extract_input(StringRef identifier, const CPPType *requested_type) const { -- cgit v1.2.3 From 20bc1ab27578f1eec4962d0476de8380fed3e35a Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Mon, 14 Dec 2020 15:12:18 -0600 Subject: Fix incorrect RNA type warning Using the RNA type for regular modifiers instead of grease pencil modifiers caused a warning in context.c. --- source/blender/editors/object/object_gpencil_modifier.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender') diff --git a/source/blender/editors/object/object_gpencil_modifier.c b/source/blender/editors/object/object_gpencil_modifier.c index 9ea67df6daf..e5feb74df26 100644 --- a/source/blender/editors/object/object_gpencil_modifier.c +++ b/source/blender/editors/object/object_gpencil_modifier.c @@ -461,7 +461,7 @@ static bool gpencil_edit_modifier_poll(bContext *C) * (not only from added 'local' ones). */ static bool gpencil_edit_modifier_liboverride_allowed_poll(bContext *C) { - return gpencil_edit_modifier_poll_generic(C, &RNA_Modifier, 0, true); + return gpencil_edit_modifier_poll_generic(C, &RNA_GpencilModifier, 0, true); } static void gpencil_edit_modifier_properties(wmOperatorType *ot) -- cgit v1.2.3 From 04ca93ef9bcb3e2e0054c459f6b36ab43de24532 Mon Sep 17 00:00:00 2001 From: Wayde Moss Date: Mon, 14 Dec 2020 16:55:19 -0500 Subject: NLA: Fix context.selected_nla_strips PointerRNA The strips were given the wrong owner ID. This only caused issues for python based UI as far as I know. Property changes would not properly update the viewport. Reviewed By: lichtwerk Differential Revision: https://developer.blender.org/D9685 --- source/blender/editors/screen/screen_context.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender') diff --git a/source/blender/editors/screen/screen_context.c b/source/blender/editors/screen/screen_context.c index 244ebea5bbe..2061716f01f 100644 --- a/source/blender/editors/screen/screen_context.c +++ b/source/blender/editors/screen/screen_context.c @@ -663,7 +663,7 @@ static eContextResult screen_ctx_selected_nla_strips(const bContext *C, bContext NlaTrack *nlt = (NlaTrack *)ale->data; LISTBASE_FOREACH (NlaStrip *, strip, &nlt->strips) { if (strip->flag & NLASTRIP_FLAG_SELECT) { - CTX_data_list_add(result, &scene->id, &RNA_NlaStrip, strip); + CTX_data_list_add(result, ale->id, &RNA_NlaStrip, strip); } } } -- cgit v1.2.3 From fa6bf8f5b65edb0639c9a21be0886cc0ded76ef1 Mon Sep 17 00:00:00 2001 From: Wayde Moss Date: Mon, 14 Dec 2020 17:04:31 -0500 Subject: Nla Refactor: nlaevalchan_validate_index_ex() And removes redundant index local variable. Future patches {D8296} and {D8867} make use of this function. No functional changes. Split from {D9247} Reviewed By: sybren Differential Revision: https://developer.blender.org/D9693 --- source/blender/blenkernel/intern/anim_sys.c | 44 ++++++++++++++++++----------- 1 file changed, 27 insertions(+), 17 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 03c812b3b3d..fe449850be2 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -1201,6 +1201,28 @@ static int nlaevalchan_validate_index(NlaEvalChannel *nec, int index) return 0; } +static bool nlaevalchan_validate_index_ex(const NlaEvalChannel *nec, const int array_index) +{ + /** Although array_index comes from fcurve, that doesn't necessarily mean the property has that + * many elements. */ + const int index = nlaevalchan_validate_index(nec, array_index); + + if (index < 0) { + if (G.debug & G_DEBUG) { + ID *id = nec->key.ptr.owner_id; + CLOG_WARN(&LOG, + "Animation: Invalid array index. ID = '%s', '%s[%d]', array length is %d", + id ? (id->name + 2) : "", + nec->rna_path, + array_index, + nec->base_snapshot.length); + } + + return false; + } + return true; +} + /* Initialize default values for NlaEvalChannel from the property data. */ static void nlaevalchan_get_default_values(NlaEvalChannel *nec, float *r_values) { @@ -1612,19 +1634,7 @@ static bool nlaeval_blend_value(NlaBlendData *blend, return false; } - int index = nlaevalchan_validate_index(nec, array_index); - - if (index < 0) { - if (G.debug & G_DEBUG) { - ID *id = nec->key.ptr.owner_id; - CLOG_WARN(&LOG, - "Animato: Invalid array index. ID = '%s', '%s[%d]', array length is %d", - id ? (id->name + 2) : "", - nec->rna_path, - array_index, - nec->base_snapshot.length); - } - + if (!nlaevalchan_validate_index_ex(nec, array_index)) { return false; } @@ -1633,21 +1643,21 @@ static bool nlaeval_blend_value(NlaBlendData *blend, BLI_bitmap_set_all(nec->valid.ptr, true, 4); } else { - BLI_BITMAP_ENABLE(nec->valid.ptr, index); + BLI_BITMAP_ENABLE(nec->valid.ptr, array_index); } NlaEvalChannelSnapshot *nec_snapshot = nlaeval_snapshot_ensure_channel(blend->snapshot, nec); - float *p_value = &nec_snapshot->values[index]; + float *p_value = &nec_snapshot->values[array_index]; if (blend->mode == NLASTRIP_MODE_COMBINE) { /* Quaternion blending is deferred until all sub-channel values are known. */ if (nec->mix_mode == NEC_MIX_QUATERNION) { NlaEvalChannelSnapshot *blend_snapshot = nlaevalchan_queue_blend(blend, nec); - blend_snapshot->values[index] = value; + blend_snapshot->values[array_index] = value; } else { - float base_value = nec->base_snapshot.values[index]; + float base_value = nec->base_snapshot.values[array_index]; *p_value = nla_combine_value(nec->mix_mode, base_value, *p_value, value, blend->influence); } -- cgit v1.2.3 From 7f6ffe9195c105a2ed9776b907aa2e6e34ed4bf3 Mon Sep 17 00:00:00 2001 From: Wayde Moss Date: Mon, 14 Dec 2020 17:08:51 -0500 Subject: Nla Refactor: Blend functions explicit Div0 check It's an explicit check to prevent division by zero if caller hasn't done the check. Future patch {D8867} will not use the nla remap function and thus not do the check. This patch also replaces some float (==) equality checks with IS_EQF(). Split from {D9247} Reviewed By: sybren Differential Revision: https://developer.blender.org/D9694 --- source/blender/blenkernel/intern/anim_sys.c | 33 ++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 8 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index fe449850be2..0476fd1e244 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -1477,7 +1477,7 @@ static float nla_combine_value( return old_value + (value - base_value) * inf; case NEC_MIX_MULTIPLY: - if (base_value == 0.0f) { + if (IS_EQF(base_value, 0.0f)) { base_value = 1.0f; } return old_value * powf(value / base_value, inf); @@ -1493,6 +1493,11 @@ static float nla_combine_value( static bool nla_invert_blend_value( int blend_mode, float old_value, float target_value, float influence, float *r_value) { + /** No solution if strip had 0 influence. */ + if (IS_EQF(0, influence)) { + return false; + } + switch (blend_mode) { case NLASTRIP_MODE_ADD: *r_value = (target_value - old_value) / influence; @@ -1503,9 +1508,9 @@ static bool nla_invert_blend_value( return true; case NLASTRIP_MODE_MULTIPLY: - if (old_value == 0.0f) { + if (IS_EQF(old_value, 0.0f)) { /* Resolve 0/0 to 1. */ - if (target_value == 0.0f) { + if (IS_EQF(target_value, 0.0f)) { *r_value = 1.0f; return true; } @@ -1536,6 +1541,11 @@ static bool nla_invert_combine_value(int mix_mode, float influence, float *r_value) { + /* No solution if strip had no influence. */ + if (IS_EQF(influence, 0)) { + return false; + } + switch (mix_mode) { case NEC_MIX_ADD: case NEC_MIX_AXIS_ANGLE: @@ -1543,12 +1553,12 @@ static bool nla_invert_combine_value(int mix_mode, return true; case NEC_MIX_MULTIPLY: - if (base_value == 0.0f) { + if (IS_EQF(base_value, 0.0f)) { base_value = 1.0f; } - if (old_value == 0.0f) { + if (IS_EQF(old_value, 0.0f)) { /* Resolve 0/0 to 1. */ - if (target_value == 0.0f) { + if (IS_EQF(target_value, 0.0f)) { *r_value = base_value; return true; } @@ -1582,11 +1592,14 @@ static void nla_combine_quaternion(const float old_values[4], } /* invert accumulation of quaternion channels for Combine mode according to influence */ -static void nla_invert_combine_quaternion(const float old_values[4], +static bool nla_invert_combine_quaternion(const float old_values[4], const float values[4], float influence, float result[4]) { + if (IS_EQF(influence, 0)) { + return false; + } float tmp_old[4], tmp_new[4]; normalize_qt_qt(tmp_old, old_values); @@ -1595,6 +1608,8 @@ static void nla_invert_combine_quaternion(const float old_values[4], mul_qt_qtqt(result, tmp_old, tmp_new); pow_qt_fl_normalized(result, 1.0f / influence); + + return true; } /* Data about the current blend mode. */ @@ -2512,7 +2527,9 @@ bool BKE_animsys_nla_remap_keyframe_values(struct NlaKeyframingContext *context, *r_force_all = true; - nla_invert_combine_quaternion(old_values, values, influence, values); + if (!nla_invert_combine_quaternion(old_values, values, influence, values)) { + return false; + } } else { float *base_values = nec->base_snapshot.values; -- cgit v1.2.3 From 60746363875a67ae15278d8e4629f898d9562c47 Mon Sep 17 00:00:00 2001 From: Wayde Moss Date: Mon, 14 Dec 2020 17:23:04 -0500 Subject: NLA: Action Strip Defaults Sync Length On See T82309#1055564 {T63675} and their duplicates for how Default-off can cause confusion. This is just for convenience since it allows animators to keyframe outside of the strip's bounds by default. This was likely off by default before since Syncing Length would undesirably shift the whole animation after leaving tweak mode (fixed by {D7602}) and the animator wasn't able to keyframe outside the strip bounds anyways (fixed by {D7533}). Now it's better if the flag was on by default. While the animator is still roughly developing their animation NLA-wise they won't have to worry about strip bound keying failures. When they are more certain of the strip bounds, they can disable the flag to prevent affecting the rest of the NLA system. Reviewed By: sybren Differential Revision: https://developer.blender.org/D9661 --- source/blender/blenkernel/intern/nla.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index ebd9317fcf1..de0d67d386b 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -334,11 +334,8 @@ NlaStrip *BKE_nlastrip_new(bAction *act) /* generic settings * - selected flag to highlight this to the user * - (XXX) disabled Auto-Blends, as this was often causing some unwanted effects - * - (XXX) synchronization of strip-length in accordance with changes to action-length - * is not done though, since this should only really happens in editmode for strips now - * though this decision is still subject to further review... */ - strip->flag = NLASTRIP_FLAG_SELECT; + strip->flag = NLASTRIP_FLAG_SELECT | NLASTRIP_FLAG_SYNC_LENGTH; /* assign the action reference */ strip->act = act; -- cgit v1.2.3 From 7470c10601d0fa871cdf1917da3b58af36af3225 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Mon, 14 Dec 2020 17:19:43 -0600 Subject: Cleanup: Use LISTBASE_FOREACH macro, reduce variable scope --- source/blender/editors/space_node/node_edit.c | 344 ++++++++++---------------- 1 file changed, 136 insertions(+), 208 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c index 039ddad71ef..fdce5e3f30b 100644 --- a/source/blender/editors/space_node/node_edit.c +++ b/source/blender/editors/space_node/node_edit.c @@ -100,9 +100,7 @@ typedef struct CompoJob { static void compo_tag_output_nodes(bNodeTree *nodetree, int recalc_flags) { - bNode *node; - - for (node = nodetree->nodes.first; node; node = node->next) { + LISTBASE_FOREACH (bNode *, node, &nodetree->nodes) { if (node->type == CMP_NODE_COMPOSITE) { if (recalc_flags & COM_RECALC_COMPOSITE) { node->flag |= NODE_DO_OUTPUT_RECALC; @@ -124,14 +122,12 @@ static void compo_tag_output_nodes(bNodeTree *nodetree, int recalc_flags) static int compo_get_recalc_flags(const bContext *C) { wmWindowManager *wm = CTX_wm_manager(C); - wmWindow *win; int recalc_flags = 0; - for (win = wm->windows.first; win; win = win->next) { + LISTBASE_FOREACH (wmWindow *, win, &wm->windows) { const bScreen *screen = WM_window_get_active_screen(win); - ScrArea *area; - for (area = screen->areabase.first; area; area = area->next) { + LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { if (area->spacetype == SPACE_IMAGE) { SpaceImage *sima = area->spacedata.first; if (sima->image) { @@ -247,7 +243,6 @@ static void compo_startjob(void *cjv, CompoJob *cj = cjv; bNodeTree *ntree = cj->localtree; Scene *scene = cj->scene; - SceneRenderView *srv; if (scene->use_nodes == false) { return; @@ -280,7 +275,7 @@ static void compo_startjob(void *cjv, ""); } else { - for (srv = scene->r.views.first; srv; srv = srv->next) { + LISTBASE_FOREACH (SceneRenderView *, srv, &scene->r.views) { if (BKE_scene_multiview_is_render_view_active(&scene->r, srv) == false) { continue; } @@ -309,8 +304,6 @@ static void compo_startjob(void *cjv, */ void ED_node_composite_job(const bContext *C, struct bNodeTree *nodetree, Scene *scene_owner) { - wmJob *wm_job; - CompoJob *cj; Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); @@ -327,13 +320,13 @@ void ED_node_composite_job(const bContext *C, struct bNodeTree *nodetree, Scene BKE_image_backup_render( scene, BKE_image_ensure_viewer(bmain, IMA_TYPE_R_RESULT, "Render Result"), false); - wm_job = WM_jobs_get(CTX_wm_manager(C), - CTX_wm_window(C), - scene_owner, - "Compositing", - WM_JOB_EXCL_RENDER | WM_JOB_PROGRESS, - WM_JOB_TYPE_COMPOSITE); - cj = MEM_callocN(sizeof(CompoJob), "compo job"); + wmJob *wm_job = WM_jobs_get(CTX_wm_manager(C), + CTX_wm_window(C), + scene_owner, + "Compositing", + WM_JOB_EXCL_RENDER | WM_JOB_PROGRESS, + WM_JOB_TYPE_COMPOSITE); + CompoJob *cj = MEM_callocN(sizeof(CompoJob), "compo job"); /* customdata for preview thread */ cj->bmain = bmain; @@ -524,9 +517,6 @@ void ED_node_shader_default(const bContext *C, ID *id) /* called from shading buttons or header */ void ED_node_composit_default(const bContext *C, struct Scene *sce) { - bNode *in, *out; - bNodeSocket *fromsock, *tosock; - /* but lets check it anyway */ if (sce->nodetree) { if (G.debug & G_DEBUG) { @@ -541,18 +531,18 @@ void ED_node_composit_default(const bContext *C, struct Scene *sce) sce->nodetree->edit_quality = NTREE_QUALITY_HIGH; sce->nodetree->render_quality = NTREE_QUALITY_HIGH; - out = nodeAddStaticNode(C, sce->nodetree, CMP_NODE_COMPOSITE); + bNode *out = nodeAddStaticNode(C, sce->nodetree, CMP_NODE_COMPOSITE); out->locx = 300.0f; out->locy = 400.0f; - in = nodeAddStaticNode(C, sce->nodetree, CMP_NODE_R_LAYERS); + bNode *in = nodeAddStaticNode(C, sce->nodetree, CMP_NODE_R_LAYERS); in->locx = 10.0f; in->locy = 400.0f; nodeSetActive(sce->nodetree, in); /* links from color to color */ - fromsock = in->outputs.first; - tosock = out->inputs.first; + bNodeSocket *fromsock = in->outputs.first; + bNodeSocket *tosock = out->inputs.first; nodeAddLink(sce->nodetree, in, fromsock, out, tosock); ntreeUpdateTree(CTX_data_main(C), sce->nodetree); @@ -562,9 +552,6 @@ void ED_node_composit_default(const bContext *C, struct Scene *sce) /* called from shading buttons or header */ void ED_node_texture_default(const bContext *C, Tex *tex) { - bNode *in, *out; - bNodeSocket *fromsock, *tosock; - /* but lets check it anyway */ if (tex->nodetree) { if (G.debug & G_DEBUG) { @@ -575,17 +562,17 @@ void ED_node_texture_default(const bContext *C, Tex *tex) tex->nodetree = ntreeAddTree(NULL, "Texture Nodetree", ntreeType_Texture->idname); - out = nodeAddStaticNode(C, tex->nodetree, TEX_NODE_OUTPUT); + bNode *out = nodeAddStaticNode(C, tex->nodetree, TEX_NODE_OUTPUT); out->locx = 300.0f; out->locy = 300.0f; - in = nodeAddStaticNode(C, tex->nodetree, TEX_NODE_CHECKER); + bNode *in = nodeAddStaticNode(C, tex->nodetree, TEX_NODE_CHECKER); in->locx = 10.0f; in->locy = 300.0f; nodeSetActive(tex->nodetree, in); - fromsock = in->outputs.first; - tosock = out->inputs.first; + bNodeSocket *fromsock = in->outputs.first; + bNodeSocket *tosock = out->inputs.first; nodeAddLink(tex->nodetree, in, fromsock, out, tosock); ntreeUpdateTree(CTX_data_main(C), tex->nodetree); @@ -634,15 +621,13 @@ void snode_set_context(const bContext *C) void snode_update(SpaceNode *snode, bNode *node) { - bNodeTreePath *path; - /* XXX this only updates nodes in the current node space tree path. * The function supposedly should update any potential group node linking to changed tree, * this really requires a working depsgraph ... */ /* update all edited group nodes */ - path = snode->treepath.last; + bNodeTreePath *path = snode->treepath.last; if (path) { bNodeTree *ngroup = path->nodetree; for (path = path->prev; path; path = path->prev) { @@ -671,10 +656,9 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node, bool *r_acti /* generic node group output: set node as active output */ if (node->type == NODE_GROUP_OUTPUT) { - bNode *tnode; - for (tnode = ntree->nodes.first; tnode; tnode = tnode->next) { - if (tnode->type == NODE_GROUP_OUTPUT) { - tnode->flag &= ~NODE_DO_OUTPUT; + LISTBASE_FOREACH (bNode *, node_iter, &ntree->nodes) { + if (node_iter->type == NODE_GROUP_OUTPUT) { + node_iter->flag &= ~NODE_DO_OUTPUT; } } @@ -696,11 +680,9 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node, bool *r_acti SH_NODE_OUTPUT_WORLD, SH_NODE_OUTPUT_LIGHT, SH_NODE_OUTPUT_LINESTYLE)) { - bNode *tnode; - - for (tnode = ntree->nodes.first; tnode; tnode = tnode->next) { - if (tnode->type == node->type) { - tnode->flag &= ~NODE_DO_OUTPUT; + LISTBASE_FOREACH (bNode *, node_iter, &ntree->nodes) { + if (node_iter->type == node->type) { + node_iter->flag &= ~NODE_DO_OUTPUT; } } @@ -715,16 +697,13 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node, bool *r_acti /* if active texture changed, free glsl materials */ if ((node->flag & NODE_ACTIVE_TEXTURE) && !was_active_texture) { - Material *ma; - World *wo; - - for (ma = bmain->materials.first; ma; ma = ma->id.next) { + LISTBASE_FOREACH (Material *, ma, &bmain->materials) { if (ma->nodetree && ma->use_nodes && ntreeHasTree(ma->nodetree, ntree)) { GPU_material_free(&ma->gpumaterial); } } - for (wo = bmain->worlds.first; wo; wo = wo->id.next) { + LISTBASE_FOREACH (World *, wo, &bmain->materials) { if (wo->nodetree && wo->use_nodes && ntreeHasTree(wo->nodetree, ntree)) { GPU_material_free(&wo->gpumaterial); } @@ -742,11 +721,9 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node, bool *r_acti else if (ntree->type == NTREE_COMPOSIT) { /* make active viewer, currently only 1 supported... */ if (ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) { - bNode *tnode; - - for (tnode = ntree->nodes.first; tnode; tnode = tnode->next) { - if (ELEM(tnode->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) { - tnode->flag &= ~NODE_DO_OUTPUT; + LISTBASE_FOREACH (bNode *, node_iter, &ntree->nodes) { + if (ELEM(node_iter->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) { + node_iter->flag &= ~NODE_DO_OUTPUT; } } @@ -760,11 +737,9 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node, bool *r_acti } else if (node->type == CMP_NODE_COMPOSITE) { if (was_output == 0) { - bNode *tnode; - - for (tnode = ntree->nodes.first; tnode; tnode = tnode->next) { - if (tnode->type == CMP_NODE_COMPOSITE) { - tnode->flag &= ~NODE_DO_OUTPUT; + LISTBASE_FOREACH (bNode *, node_iter, &ntree->nodes) { + if (node_iter->type == CMP_NODE_COMPOSITE) { + node_iter->flag &= ~NODE_DO_OUTPUT; } } @@ -879,14 +854,12 @@ static void edit_node_properties_get( /* is rct in visible part of node? */ static bNode *visible_node(SpaceNode *snode, const rctf *rct) { - bNode *node; - - for (node = snode->edittree->nodes.last; node; node = node->prev) { + LISTBASE_FOREACH (bNode *, node, &snode->edittree->nodes) { if (BLI_rctf_isect(&node->totr, rct, NULL)) { - break; + return node; } } - return node; + return NULL; } /* ********************** size widget operator ******************** */ @@ -952,23 +925,19 @@ static int node_resize_modal(bContext *C, wmOperator *op, const wmEvent *event) ARegion *region = CTX_wm_region(C); bNode *node = nodeGetActive(snode->edittree); NodeSizeWidget *nsw = op->customdata; - float mx, my, dx, dy; switch (event->type) { - case MOUSEMOVE: - + case MOUSEMOVE: { + float mx, my; UI_view2d_region_to_view(®ion->v2d, event->mval[0], event->mval[1], &mx, &my); - dx = (mx - nsw->mxstart) / UI_DPI_FAC; - dy = (my - nsw->mystart) / UI_DPI_FAC; + float dx = (mx - nsw->mxstart) / UI_DPI_FAC; + float dy = (my - nsw->mystart) / UI_DPI_FAC; if (node) { - float *pwidth; - float oldwidth, widthmin, widthmax; - - pwidth = &node->width; - oldwidth = nsw->oldwidth; - widthmin = node->typeinfo->minwidth; - widthmax = node->typeinfo->maxwidth; + float *pwidth = &node->width; + float oldwidth = nsw->oldwidth; + float widthmin = node->typeinfo->minwidth; + float widthmax = node->typeinfo->maxwidth; { if (nsw->directions & NODE_RESIZE_RIGHT) { @@ -1026,23 +995,24 @@ static int node_resize_modal(bContext *C, wmOperator *op, const wmEvent *event) ED_region_tag_redraw(region); break; - + } case LEFTMOUSE: case MIDDLEMOUSE: - case RIGHTMOUSE: + case RIGHTMOUSE: { if (event->val == KM_RELEASE) { node_resize_exit(C, op, false); ED_node_post_apply_transform(C, snode->edittree); return OPERATOR_FINISHED; } - else if (event->val == KM_PRESS) { + if (event->val == KM_PRESS) { node_resize_exit(C, op, true); ED_region_tag_redraw(region); return OPERATOR_CANCELLED; } break; + } } return OPERATOR_RUNNING_MODAL; @@ -1095,14 +1065,12 @@ void NODE_OT_resize(wmOperatorType *ot) bool node_has_hidden_sockets(bNode *node) { - bNodeSocket *sock; - - for (sock = node->inputs.first; sock; sock = sock->next) { + LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) { if (sock->flag & SOCK_HIDDEN) { return true; } } - for (sock = node->outputs.first; sock; sock = sock->next) { + LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) { if (sock->flag & SOCK_HIDDEN) { return true; } @@ -1112,24 +1080,22 @@ bool node_has_hidden_sockets(bNode *node) void node_set_hidden_sockets(SpaceNode *snode, bNode *node, int set) { - bNodeSocket *sock; - if (set == 0) { - for (sock = node->inputs.first; sock; sock = sock->next) { + LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) { sock->flag &= ~SOCK_HIDDEN; } - for (sock = node->outputs.first; sock; sock = sock->next) { + LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) { sock->flag &= ~SOCK_HIDDEN; } } else { /* hide unused sockets */ - for (sock = node->inputs.first; sock; sock = sock->next) { + LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) { if (sock->link == NULL) { sock->flag |= SOCK_HIDDEN; } } - for (sock = node->outputs.first; sock; sock = sock->next) { + LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) { if (nodeCountSocketLinks(snode->edittree, sock) == 0) { sock->flag |= SOCK_HIDDEN; } @@ -1142,16 +1108,13 @@ void node_set_hidden_sockets(SpaceNode *snode, bNode *node, int set) int node_find_indicated_socket( SpaceNode *snode, bNode **nodep, bNodeSocket **sockp, float cursor[2], int in_out) { - bNode *node; - bNodeSocket *sock; rctf rect; *nodep = NULL; *sockp = NULL; /* check if we click in a socket */ - for (node = snode->edittree->nodes.first; node; node = node->next) { - + LISTBASE_FOREACH (bNode *, node, &snode->edittree->nodes) { BLI_rctf_init_pt_radius(&rect, cursor, NODE_SOCKSIZE + 4); if (!(node->flag & NODE_HIDDEN)) { @@ -1167,7 +1130,7 @@ int node_find_indicated_socket( } if (in_out & SOCK_IN) { - for (sock = node->inputs.first; sock; sock = sock->next) { + LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) { if (!nodeSocketIsHidden(sock)) { if (BLI_rctf_isect_pt(&rect, sock->locx, sock->locy)) { if (node == visible_node(snode, &rect)) { @@ -1180,7 +1143,7 @@ int node_find_indicated_socket( } } if (in_out & SOCK_OUT) { - for (sock = node->outputs.first; sock; sock = sock->next) { + LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) { if (!nodeSocketIsHidden(sock)) { if (BLI_rctf_isect_pt(&rect, sock->locx, sock->locy)) { if (node == visible_node(snode, &rect)) { @@ -1226,17 +1189,15 @@ static int node_duplicate_exec(bContext *C, wmOperator *op) Main *bmain = CTX_data_main(C); SpaceNode *snode = CTX_wm_space_node(C); bNodeTree *ntree = snode->edittree; - bNode *node, *newnode, *lastnode; - bNodeLink *link, *newlink, *lastlink; const bool keep_inputs = RNA_boolean_get(op->ptr, "keep_inputs"); bool do_tag_update = false; ED_preview_kill_jobs(CTX_wm_manager(C), bmain); - lastnode = ntree->nodes.last; - for (node = ntree->nodes.first; node; node = node->next) { + bNode *lastnode = ntree->nodes.last; + LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { if (node->flag & SELECT) { - newnode = BKE_node_copy_store_new_pointers(ntree, node, LIB_ID_COPY_DEFAULT); + BKE_node_copy_store_new_pointers(ntree, node, LIB_ID_COPY_DEFAULT); /* to ensure redraws or rerenders happen */ ED_node_tag_update_id(snode->id); @@ -1251,14 +1212,14 @@ static int node_duplicate_exec(bContext *C, wmOperator *op) /* copy links between selected nodes * NB: this depends on correct node->new_node and sock->new_sock pointers from above copy! */ - lastlink = ntree->links.last; - for (link = ntree->links.first; link; link = link->next) { + bNodeLink *lastlink = ntree->links.last; + LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) { /* This creates new links between copied nodes. * If keep_inputs is set, also copies input links from unselected (when fromnode==NULL)! */ if (link->tonode && (link->tonode->flag & NODE_SELECT) && (keep_inputs || (link->fromnode && (link->fromnode->flag & NODE_SELECT)))) { - newlink = MEM_callocN(sizeof(bNodeLink), "bNodeLink"); + bNodeLink *newlink = MEM_callocN(sizeof(bNodeLink), "bNodeLink"); newlink->flag = link->flag; newlink->tonode = link->tonode->new_node; newlink->tosock = link->tosock->new_sock; @@ -1282,11 +1243,11 @@ static int node_duplicate_exec(bContext *C, wmOperator *op) } /* clear flags for recursive depth-first iteration */ - for (node = ntree->nodes.first; node; node = node->next) { + LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { node->flag &= ~NODE_TEST; } /* reparent copied nodes */ - for (node = ntree->nodes.first; node; node = node->next) { + LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { if ((node->flag & SELECT) && !(node->flag & NODE_TEST)) { node_duplicate_reparent_recursive(node); } @@ -1298,10 +1259,10 @@ static int node_duplicate_exec(bContext *C, wmOperator *op) } /* deselect old nodes, select the copies instead */ - for (node = ntree->nodes.first; node; node = node->next) { + LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { if (node->flag & SELECT) { /* has been set during copy above */ - newnode = node->new_node; + bNode *newnode = node->new_node; nodeSetSelected(node, false); node->flag &= ~(NODE_ACTIVE | NODE_ACTIVE_TEXTURE); @@ -1389,17 +1350,16 @@ static int node_read_viewlayers_exec(bContext *C, wmOperator *UNUSED(op)) { Main *bmain = CTX_data_main(C); SpaceNode *snode = CTX_wm_space_node(C); - Scene *curscene = CTX_data_scene(C), *scene; - bNode *node; + Scene *curscene = CTX_data_scene(C); ED_preview_kill_jobs(CTX_wm_manager(C), bmain); /* first tag scenes unread */ - for (scene = bmain->scenes.first; scene; scene = scene->id.next) { + LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) { scene->id.tag |= LIB_TAG_DOIT; } - for (node = snode->edittree->nodes.first; node; node = node->next) { + LISTBASE_FOREACH (bNode *, node, &snode->edittree->nodes) { if (node->type == CMP_NODE_R_LAYERS) { ID *id = node->id; if (id->tag & LIB_TAG_DOIT) { @@ -1434,13 +1394,14 @@ void NODE_OT_read_viewlayers(wmOperatorType *ot) int node_render_changed_exec(bContext *C, wmOperator *UNUSED(op)) { Scene *sce = CTX_data_scene(C); - bNode *node; /* This is actually a test whether scene is used by the compositor or not. * All the nodes are using same render result, so there is no need to do * anything smart about check how exactly scene is used. */ - for (node = sce->nodetree->nodes.first; node; node = node->next) { - if (node->id == (ID *)sce) { + bNode *node = NULL; + LISTBASE_FOREACH (bNode *, node_iter, &sce->nodetree->nodes) { + if (node_iter->id == (ID *)sce) { + node = node_iter; break; } } @@ -1486,14 +1447,14 @@ void NODE_OT_render_changed(wmOperatorType *ot) static void node_flag_toggle_exec(SpaceNode *snode, int toggle_flag) { - bNode *node; int tot_eq = 0, tot_neq = 0; /* Toggles the flag on all selected nodes. * If the flag is set on all nodes it is unset. * If the flag is not set on all nodes, it is set. */ - for (node = snode->edittree->nodes.first; node; node = node->next) { + + LISTBASE_FOREACH (bNode *, node, &snode->edittree->nodes) { if (node->flag & SELECT) { if (toggle_flag == NODE_PREVIEW && (node->typeinfo->flag & NODE_PREVIEW) == 0) { @@ -1512,7 +1473,7 @@ static void node_flag_toggle_exec(SpaceNode *snode, int toggle_flag) } } } - for (node = snode->edittree->nodes.first; node; node = node->next) { + LISTBASE_FOREACH (bNode *, node, &snode->edittree->nodes) { if (node->flag & SELECT) { if (toggle_flag == NODE_PREVIEW && (node->typeinfo->flag & NODE_PREVIEW) == 0) { @@ -1631,8 +1592,6 @@ void NODE_OT_options_toggle(wmOperatorType *ot) static int node_socket_toggle_exec(bContext *C, wmOperator *UNUSED(op)) { SpaceNode *snode = CTX_wm_space_node(C); - bNode *node; - int hidden; /* sanity checking (poll callback checks this already) */ if ((snode == NULL) || (snode->edittree == NULL)) { @@ -1642,17 +1601,17 @@ static int node_socket_toggle_exec(bContext *C, wmOperator *UNUSED(op)) ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C)); /* Toggle for all selected nodes */ - hidden = 0; - for (node = snode->edittree->nodes.first; node; node = node->next) { + bool hidden = false; + LISTBASE_FOREACH (bNode *, node, &snode->edittree->nodes) { if (node->flag & SELECT) { if (node_has_hidden_sockets(node)) { - hidden = 1; + hidden = true; break; } } } - for (node = snode->edittree->nodes.first; node; node = node->next) { + LISTBASE_FOREACH (bNode *, node, &snode->edittree->nodes) { if (node->flag & SELECT) { node_set_hidden_sockets(snode, node, !hidden); } @@ -1686,12 +1645,11 @@ static int node_mute_exec(bContext *C, wmOperator *UNUSED(op)) { Main *bmain = CTX_data_main(C); SpaceNode *snode = CTX_wm_space_node(C); - bNode *node; bool do_tag_update = false; ED_preview_kill_jobs(CTX_wm_manager(C), bmain); - for (node = snode->edittree->nodes.first; node; node = node->next) { + LISTBASE_FOREACH (bNode *, node, &snode->edittree->nodes) { /* Only allow muting of nodes having a mute func! */ if ((node->flag & SELECT) && node->typeinfo->update_internal_links) { node->flag ^= NODE_MUTED; @@ -1731,13 +1689,11 @@ static int node_delete_exec(bContext *C, wmOperator *UNUSED(op)) { Main *bmain = CTX_data_main(C); SpaceNode *snode = CTX_wm_space_node(C); - bNode *node, *next; bool do_tag_update = false; ED_preview_kill_jobs(CTX_wm_manager(C), bmain); - for (node = snode->edittree->nodes.first; node; node = next) { - next = node->next; + LISTBASE_FOREACH_MUTABLE (bNode *, node, &snode->edittree->nodes) { if (node->flag & SELECT) { do_tag_update |= (do_tag_update || node_connected_to_output(bmain, snode->edittree, node)); nodeRemoveNode(bmain, snode->edittree, node, true); @@ -1787,10 +1743,8 @@ static bool node_switch_view_poll(bContext *C) static int node_switch_view_exec(bContext *C, wmOperator *UNUSED(op)) { SpaceNode *snode = CTX_wm_space_node(C); - bNode *node, *next; - for (node = snode->edittree->nodes.first; node; node = next) { - next = node->next; + LISTBASE_FOREACH_MUTABLE (bNode *, node, &snode->edittree->nodes) { if (node->flag & SELECT) { /* call the update function from the Switch View node */ node->update = NODE_UPDATE_OPERATOR; @@ -1825,12 +1779,10 @@ static int node_delete_reconnect_exec(bContext *C, wmOperator *UNUSED(op)) { Main *bmain = CTX_data_main(C); SpaceNode *snode = CTX_wm_space_node(C); - bNode *node, *next; ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C)); - for (node = snode->edittree->nodes.first; node; node = next) { - next = node->next; + LISTBASE_FOREACH_MUTABLE (bNode *, node, &snode->edittree->nodes) { if (node->flag & SELECT) { nodeInternalRelink(snode->edittree, node); nodeRemoveNode(bmain, snode->edittree, node, true); @@ -1963,9 +1915,6 @@ static int node_output_file_move_active_socket_exec(bContext *C, wmOperator *op) SpaceNode *snode = CTX_wm_space_node(C); PointerRNA ptr = CTX_data_pointer_get(C, "node"); bNode *node = NULL; - NodeImageMultiFile *nimf; - bNodeSocket *sock; - int direction; if (ptr.data) { node = ptr.data; @@ -1978,14 +1927,14 @@ static int node_output_file_move_active_socket_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - nimf = node->storage; + NodeImageMultiFile *nimf = node->storage; - sock = BLI_findlink(&node->inputs, nimf->active_input); + bNodeSocket *sock = BLI_findlink(&node->inputs, nimf->active_input); if (!sock) { return OPERATOR_CANCELLED; } - direction = RNA_enum_get(op->ptr, "direction"); + int direction = RNA_enum_get(op->ptr, "direction"); if (direction == 1) { bNodeSocket *before = sock->prev; @@ -2037,24 +1986,23 @@ static int node_copy_color_exec(bContext *C, wmOperator *UNUSED(op)) { SpaceNode *snode = CTX_wm_space_node(C); bNodeTree *ntree = snode->edittree; - bNode *node, *tnode; if (!ntree) { return OPERATOR_CANCELLED; } - node = nodeGetActive(ntree); + bNode *node = nodeGetActive(ntree); if (!node) { return OPERATOR_CANCELLED; } - for (tnode = ntree->nodes.first; tnode; tnode = tnode->next) { - if (tnode->flag & NODE_SELECT && tnode != node) { + LISTBASE_FOREACH (bNode *, node_iter, &ntree->nodes) { + if (node_iter->flag & NODE_SELECT && node_iter != node) { if (node->flag & NODE_CUSTOM_COLOR) { - tnode->flag |= NODE_CUSTOM_COLOR; - copy_v3_v3(tnode->color, node->color); + node_iter->flag |= NODE_CUSTOM_COLOR; + copy_v3_v3(node_iter->color, node->color); } else { - tnode->flag &= ~NODE_CUSTOM_COLOR; + node_iter->flag &= ~NODE_CUSTOM_COLOR; } } } @@ -2086,8 +2034,6 @@ static int node_clipboard_copy_exec(bContext *C, wmOperator *UNUSED(op)) { SpaceNode *snode = CTX_wm_space_node(C); bNodeTree *ntree = snode->edittree; - bNode *node; - bNodeLink *link, *newlink; ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C)); @@ -2095,7 +2041,7 @@ static int node_clipboard_copy_exec(bContext *C, wmOperator *UNUSED(op)) BKE_node_clipboard_clear(); BKE_node_clipboard_init(ntree); - for (node = ntree->nodes.first; node; node = node->next) { + LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { if (node->flag & SELECT) { /* No ID refcounting, this node is virtual, * detached from any actual Blender data currently. */ @@ -2105,7 +2051,7 @@ static int node_clipboard_copy_exec(bContext *C, wmOperator *UNUSED(op)) } } - for (node = ntree->nodes.first; node; node = node->next) { + LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { if (node->flag & SELECT) { bNode *new_node = node->new_node; @@ -2126,11 +2072,11 @@ static int node_clipboard_copy_exec(bContext *C, wmOperator *UNUSED(op)) /* copy links between selected nodes * NB: this depends on correct node->new_node and sock->new_sock pointers from above copy! */ - for (link = ntree->links.first; link; link = link->next) { + LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) { /* This creates new links between copied nodes. */ if (link->tonode && (link->tonode->flag & NODE_SELECT) && link->fromnode && (link->fromnode->flag & NODE_SELECT)) { - newlink = MEM_callocN(sizeof(bNodeLink), "bNodeLink"); + bNodeLink *newlink = MEM_callocN(sizeof(bNodeLink), "bNodeLink"); newlink->flag = link->flag; newlink->tonode = link->tonode->new_node; newlink->tosock = link->tosock->new_sock; @@ -2165,18 +2111,11 @@ static int node_clipboard_paste_exec(bContext *C, wmOperator *op) { SpaceNode *snode = CTX_wm_space_node(C); bNodeTree *ntree = snode->edittree; - const ListBase *clipboard_nodes_lb; - const ListBase *clipboard_links_lb; - bNode *node; - bNodeLink *link; - int num_nodes; - float center[2]; - bool is_clipboard_valid, all_nodes_valid; /* validate pointers in the clipboard */ - is_clipboard_valid = BKE_node_clipboard_validate(); - clipboard_nodes_lb = BKE_node_clipboard_get_nodes(); - clipboard_links_lb = BKE_node_clipboard_get_links(); + bool is_clipboard_valid = BKE_node_clipboard_validate(); + const ListBase *clipboard_nodes_lb = BKE_node_clipboard_get_nodes(); + const ListBase *clipboard_links_lb = BKE_node_clipboard_get_links(); if (BLI_listbase_is_empty(clipboard_nodes_lb)) { BKE_report(op->reports, RPT_ERROR, "Clipboard is empty"); @@ -2196,8 +2135,8 @@ static int node_clipboard_paste_exec(bContext *C, wmOperator *op) } /* make sure all clipboard nodes would be valid in the target tree */ - all_nodes_valid = true; - for (node = clipboard_nodes_lb->first; node; node = node->next) { + bool all_nodes_valid = true; + LISTBASE_FOREACH (bNode *, node, clipboard_nodes_lb) { if (!node->typeinfo->poll_instance || !node->typeinfo->poll_instance(node, ntree)) { all_nodes_valid = false; BKE_reportf(op->reports, @@ -2217,15 +2156,16 @@ static int node_clipboard_paste_exec(bContext *C, wmOperator *op) node_deselect_all(snode); /* calculate "barycenter" for placing on mouse cursor */ - zero_v2(center); - for (node = clipboard_nodes_lb->first, num_nodes = 0; node; node = node->next, num_nodes++) { + float center[2] = {0.0f, 0.0f}; + int num_nodes = 0; + LISTBASE_FOREACH_INDEX (bNode *, node, clipboard_nodes_lb, num_nodes) { center[0] += BLI_rctf_cent_x(&node->totr); center[1] += BLI_rctf_cent_y(&node->totr); } mul_v2_fl(center, 1.0 / num_nodes); /* copy nodes from clipboard */ - for (node = clipboard_nodes_lb->first; node; node = node->next) { + LISTBASE_FOREACH (bNode *, node, clipboard_nodes_lb) { bNode *new_node = BKE_node_copy_store_new_pointers(ntree, node, LIB_ID_COPY_DEFAULT); /* pasted nodes are selected */ @@ -2233,14 +2173,14 @@ static int node_clipboard_paste_exec(bContext *C, wmOperator *op) } /* reparent copied nodes */ - for (node = clipboard_nodes_lb->first; node; node = node->next) { + LISTBASE_FOREACH (bNode *, node, clipboard_nodes_lb) { bNode *new_node = node->new_node; if (new_node->parent) { new_node->parent = new_node->parent->new_node; } } - for (link = clipboard_links_lb->first; link; link = link->next) { + LISTBASE_FOREACH (bNodeLink *, link, clipboard_links_lb) { nodeAddLink(ntree, link->fromnode->new_node, link->fromsock->new_sock, @@ -2275,10 +2215,9 @@ void NODE_OT_clipboard_paste(wmOperatorType *ot) static bNodeSocket *ntree_get_active_interface_socket(ListBase *lb) { - bNodeSocket *sock; - for (sock = lb->first; sock; sock = sock->next) { - if (sock->flag & SELECT) { - return sock; + LISTBASE_FOREACH (bNodeSocket *, socket, lb) { + if (socket->flag & SELECT) { + return socket; } } return NULL; @@ -2289,12 +2228,12 @@ static int ntree_socket_add_exec(bContext *C, wmOperator *op) SpaceNode *snode = CTX_wm_space_node(C); bNodeTree *ntree = snode->edittree; int in_out = RNA_enum_get(op->ptr, "in_out"); - PointerRNA ntree_ptr; - bNodeSocket *sock, *tsock, *active_sock; - const char *default_name; + PointerRNA ntree_ptr; RNA_id_pointer_create((ID *)ntree, &ntree_ptr); + const char *default_name; + bNodeSocket *active_sock; if (in_out == SOCK_IN) { active_sock = ntree_get_active_interface_socket(&ntree->inputs); default_name = "Input"; @@ -2304,6 +2243,7 @@ static int ntree_socket_add_exec(bContext *C, wmOperator *op) default_name = "Output"; } + bNodeSocket *sock; if (active_sock) { /* insert a copy of the active socket right after it */ sock = ntreeInsertSocketInterface( @@ -2317,11 +2257,11 @@ static int ntree_socket_add_exec(bContext *C, wmOperator *op) } /* deactivate sockets (has to check both lists) */ - for (tsock = ntree->inputs.first; tsock; tsock = tsock->next) { - tsock->flag &= ~SELECT; + LISTBASE_FOREACH (bNodeSocket *, socket_iter, &ntree->inputs) { + socket_iter->flag &= ~SELECT; } - for (tsock = ntree->outputs.first; tsock; tsock = tsock->next) { - tsock->flag &= ~SELECT; + LISTBASE_FOREACH (bNodeSocket *, socket_iter, &ntree->outputs) { + socket_iter->flag &= ~SELECT; } /* make the new socket active */ sock->flag |= SELECT; @@ -2359,9 +2299,8 @@ static int ntree_socket_remove_exec(bContext *C, wmOperator *UNUSED(op)) { SpaceNode *snode = CTX_wm_space_node(C); bNodeTree *ntree = snode->edittree; - bNodeSocket *iosock, *active_sock; - iosock = ntree_get_active_interface_socket(&ntree->inputs); + bNodeSocket *iosock = ntree_get_active_interface_socket(&ntree->inputs); if (!iosock) { iosock = ntree_get_active_interface_socket(&ntree->outputs); } @@ -2370,7 +2309,7 @@ static int ntree_socket_remove_exec(bContext *C, wmOperator *UNUSED(op)) } /* preferably next socket becomes active, otherwise try previous socket */ - active_sock = (iosock->next ? iosock->next : iosock->prev); + bNodeSocket *active_sock = (iosock->next ? iosock->next : iosock->prev); ntreeRemoveSocketInterface(ntree, iosock); /* set active socket */ @@ -2416,11 +2355,9 @@ static int ntree_socket_move_exec(bContext *C, wmOperator *op) SpaceNode *snode = CTX_wm_space_node(C); bNodeTree *ntree = snode->edittree; int direction = RNA_enum_get(op->ptr, "direction"); - bNodeSocket *iosock; - ListBase *lb; - lb = &ntree->inputs; - iosock = ntree_get_active_interface_socket(lb); + ListBase *lb = &ntree->inputs; + bNodeSocket *iosock = ntree_get_active_interface_socket(lb); if (!iosock) { lb = &ntree->outputs; iosock = ntree_get_active_interface_socket(lb); @@ -2489,8 +2426,6 @@ static bool node_shader_script_update_poll(bContext *C) Scene *scene = CTX_data_scene(C); const RenderEngineType *type = RE_engines_find(scene->r.engine); SpaceNode *snode = CTX_wm_space_node(C); - bNode *node; - Text *text; /* test if we have a render engine that supports shaders scripts */ if (!(type && type->update_script_node)) { @@ -2498,7 +2433,7 @@ static bool node_shader_script_update_poll(bContext *C) } /* see if we have a shader script node in context */ - node = CTX_data_pointer_get_type(C, "node", &RNA_ShaderNodeScript).data; + bNode *node = CTX_data_pointer_get_type(C, "node", &RNA_ShaderNodeScript).data; if (!node && snode && snode->edittree) { node = nodeGetActive(snode->edittree); @@ -2513,7 +2448,7 @@ static bool node_shader_script_update_poll(bContext *C) } /* see if we have a text datablock in context */ - text = CTX_data_pointer_get_type(C, "edit_text", &RNA_Text).data; + Text *text = CTX_data_pointer_get_type(C, "edit_text", &RNA_Text).data; if (text) { return 1; } @@ -2530,12 +2465,11 @@ static bool node_shader_script_update_text_recursive(RenderEngine *engine, Text *text) { bool found = false; - bNode *node; ntree->done = true; /* update each script that is using this text datablock */ - for (node = ntree->nodes.first; node; node = node->next) { + LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { if (node->type == NODE_GROUP) { bNodeTree *ngroup = (bNodeTree *)node->id; if (ngroup && !ngroup->done) { @@ -2557,18 +2491,16 @@ static int node_shader_script_update_exec(bContext *C, wmOperator *op) Scene *scene = CTX_data_scene(C); SpaceNode *snode = CTX_wm_space_node(C); PointerRNA nodeptr = CTX_data_pointer_get_type(C, "node", &RNA_ShaderNodeScript); - bNodeTree *ntree_base = NULL; - bNode *node = NULL; - RenderEngine *engine; - RenderEngineType *type; bool found = false; /* setup render engine */ - type = RE_engines_find(scene->r.engine); - engine = RE_engine_create(type); + RenderEngineType *type = RE_engines_find(scene->r.engine); + RenderEngine *engine = RE_engine_create(type); engine->reports = op->reports; /* get node */ + bNodeTree *ntree_base = NULL; + bNode *node = NULL; if (nodeptr.data) { ntree_base = (bNodeTree *)nodeptr.owner_id; node = nodeptr.data; @@ -2643,10 +2575,8 @@ static void viewer_border_corner_to_backdrop(SpaceNode *snode, float *fx, float *fy) { - float bufx, bufy; - - bufx = backdrop_width * snode->zoom; - bufy = backdrop_height * snode->zoom; + float bufx = backdrop_width * snode->zoom; + float bufy = backdrop_height * snode->zoom; *fx = (bufx > 0.0f ? ((float)x - 0.5f * region->winx - snode->xof) / bufx + 0.5f : 0.0f); *fy = (bufy > 0.0f ? ((float)y - 0.5f * region->winy - snode->yof) / bufy + 0.5f : 0.0f); @@ -2655,14 +2585,12 @@ static void viewer_border_corner_to_backdrop(SpaceNode *snode, static int viewer_border_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); - Image *ima; void *lock; - ImBuf *ibuf; ED_preview_kill_jobs(CTX_wm_manager(C), bmain); - ima = BKE_image_ensure_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node"); - ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock); + Image *ima = BKE_image_ensure_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node"); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock); if (ibuf) { ARegion *region = CTX_wm_region(C); -- cgit v1.2.3 From 1e38e32cf6d6f24a0c9af27a0331c06037b68fd9 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 15 Dec 2020 10:23:12 +1100 Subject: Cleanup: type check failure, discarded-qualifiers warnings Caused by 7f6ffe9195c105a2ed9776b907aa2e6e34ed4bf3 --- source/blender/blenkernel/intern/anim_sys.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 0476fd1e244..ea41495d097 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -1189,7 +1189,7 @@ static void nlaeval_free(NlaEvalData *nlaeval) /* ---------------------- */ -static int nlaevalchan_validate_index(NlaEvalChannel *nec, int index) +static int nlaevalchan_validate_index(const NlaEvalChannel *nec, int index) { if (nec->is_array) { if (index >= 0 && index < nec->base_snapshot.length) { @@ -1494,7 +1494,7 @@ static bool nla_invert_blend_value( int blend_mode, float old_value, float target_value, float influence, float *r_value) { /** No solution if strip had 0 influence. */ - if (IS_EQF(0, influence)) { + if (IS_EQF(influence, 0.0f)) { return false; } @@ -1542,7 +1542,7 @@ static bool nla_invert_combine_value(int mix_mode, float *r_value) { /* No solution if strip had no influence. */ - if (IS_EQF(influence, 0)) { + if (IS_EQF(influence, 0.0f)) { return false; } @@ -1597,7 +1597,7 @@ static bool nla_invert_combine_quaternion(const float old_values[4], float influence, float result[4]) { - if (IS_EQF(influence, 0)) { + if (IS_EQF(influence, 0.0f)) { return false; } float tmp_old[4], tmp_new[4]; -- cgit v1.2.3 From 15f2f69694cb23d04989d3faea4853468a3b140a Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Mon, 14 Dec 2020 17:48:57 -0600 Subject: Cleanup: Reduce variable scope --- source/blender/editors/space_node/node_draw.c | 61 +++++++++++++-------------- 1 file changed, 29 insertions(+), 32 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c index fc7fa3a6caa..5a2eb0cc3a0 100644 --- a/source/blender/editors/space_node/node_draw.c +++ b/source/blender/editors/space_node/node_draw.c @@ -344,8 +344,6 @@ void node_from_view(struct bNode *node, float x, float y, float *rx, float *ry) /* based on settings in node, sets drawing rect info. each redraw! */ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node) { - uiLayout *layout, *row; - PointerRNA nodeptr; RNA_pointer_create(&ntree->id, &RNA_Node, node, &nodeptr); @@ -374,15 +372,15 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node) PointerRNA sockptr; RNA_pointer_create(&ntree->id, &RNA_NodeSocket, nsock, &sockptr); - layout = UI_block_layout(node->block, - UI_LAYOUT_VERTICAL, - UI_LAYOUT_PANEL, - locx + NODE_DYS, - dy, - NODE_WIDTH(node) - NODE_DY, - NODE_DY, - 0, - UI_style_get_dpi()); + uiLayout *layout = UI_block_layout(node->block, + UI_LAYOUT_VERTICAL, + UI_LAYOUT_PANEL, + locx + NODE_DYS, + dy, + NODE_WIDTH(node) - NODE_DY, + NODE_DY, + 0, + UI_style_get_dpi()); if (node->flag & NODE_MUTED) { uiLayoutSetActive(layout, false); @@ -393,7 +391,7 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node) uiLayoutSetContextPointer(layout, "socket", &sockptr); /* align output buttons to the right */ - row = uiLayoutRow(layout, 1); + uiLayout *row = uiLayoutRow(layout, true); uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_RIGHT); const char *socket_label = nodeSocketLabel(nsock); nsock->typeinfo->draw((bContext *)C, row, &sockptr, &nodeptr, IFACE_(socket_label)); @@ -469,15 +467,15 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node) node->butr.ymin = 0; node->butr.ymax = 0; - layout = UI_block_layout(node->block, - UI_LAYOUT_VERTICAL, - UI_LAYOUT_PANEL, - locx + NODE_DYS, - dy, - node->butr.xmax, - 0, - 0, - UI_style_get_dpi()); + uiLayout *layout = UI_block_layout(node->block, + UI_LAYOUT_VERTICAL, + UI_LAYOUT_PANEL, + locx + NODE_DYS, + dy, + node->butr.xmax, + 0, + 0, + UI_style_get_dpi()); if (node->flag & NODE_MUTED) { uiLayoutSetActive(layout, false); @@ -502,15 +500,15 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node) PointerRNA sockptr; RNA_pointer_create(&ntree->id, &RNA_NodeSocket, nsock, &sockptr); - layout = UI_block_layout(node->block, - UI_LAYOUT_VERTICAL, - UI_LAYOUT_PANEL, - locx + NODE_DYS, - dy, - NODE_WIDTH(node) - NODE_DY, - NODE_DY, - 0, - UI_style_get_dpi()); + uiLayout *layout = UI_block_layout(node->block, + UI_LAYOUT_VERTICAL, + UI_LAYOUT_PANEL, + locx + NODE_DYS, + dy, + NODE_WIDTH(node) - NODE_DY, + NODE_DY, + 0, + UI_style_get_dpi()); if (node->flag & NODE_MUTED) { uiLayoutSetActive(layout, false); @@ -520,7 +518,7 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node) uiLayoutSetContextPointer(layout, "node", &nodeptr); uiLayoutSetContextPointer(layout, "socket", &sockptr); - row = uiLayoutRow(layout, 1); + uiLayout *row = uiLayoutRow(layout, true); const char *socket_label = nodeSocketLabel(nsock); nsock->typeinfo->draw((bContext *)C, row, &sockptr, &nodeptr, IFACE_(socket_label)); @@ -771,7 +769,6 @@ void node_socket_color_get( bContext *C, bNodeTree *ntree, PointerRNA *node_ptr, bNodeSocket *sock, float r_color[4]) { PointerRNA ptr; - BLI_assert(RNA_struct_is_a(node_ptr->type, &RNA_Node)); RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr); -- cgit v1.2.3 From 525364be31aafa547f4b17b9947074ed5a5b2570 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 15 Dec 2020 10:47:58 +1100 Subject: Cleanup: reduce indirect DNA header inclusion Remove DNA headers, using forward declarations where possible. Also removed duplicate header, header including it's self and unnecessary inclusion of libc system headers from BKE header. --- source/blender/blenkernel/BKE_boids.h | 23 ++++--- source/blender/blenkernel/BKE_collision.h | 22 ++---- source/blender/blenkernel/BKE_cryptomatte.h | 2 - source/blender/blenkernel/BKE_curve.h | 8 ++- source/blender/blenkernel/BKE_effect.h | 4 +- source/blender/blenkernel/BKE_freestyle.h | 37 +++++----- source/blender/blenkernel/BKE_idprop.h | 78 +++++++++++----------- source/blender/blenkernel/BKE_layer.h | 21 +++--- source/blender/blenkernel/BKE_particle.h | 5 +- source/blender/blenkernel/BKE_pointcache.h | 11 ++- .../blender/blenkernel/BKE_sequencer_offscreen.h | 13 ++-- source/blender/blenkernel/BKE_shader_fx.h | 1 - source/blender/blenkernel/BKE_simulation.h | 3 +- source/blender/blenkernel/BKE_studiolight.h | 2 +- source/blender/blenkernel/BKE_text_suggestions.h | 6 +- source/blender/blenkernel/intern/anim_data.c | 1 + source/blender/blenkernel/intern/boids.c | 1 + source/blender/blenkernel/intern/brush.c | 1 + source/blender/blenkernel/intern/dynamicpaint.c | 1 + source/blender/blenkernel/intern/gpencil_curve.c | 3 + source/blender/blenkernel/intern/gpencil_geom.c | 1 + source/blender/blenkernel/intern/idprop_utils.c | 2 + source/blender/blenkernel/intern/idtype.c | 1 + source/blender/blenkernel/intern/image.c | 1 + source/blender/blenkernel/intern/lib_id.c | 1 + source/blender/blenkernel/intern/lib_remap.c | 1 + source/blender/blenkernel/intern/modifier.c | 1 + source/blender/blenkernel/intern/node.c | 1 + source/blender/blenkernel/intern/object.c | 1 + source/blender/blenkernel/intern/object_update.c | 1 + source/blender/blenkernel/intern/particle.c | 1 + source/blender/blenkernel/intern/particle_child.c | 1 + .../blenkernel/intern/particle_distribute.c | 1 + source/blender/blenkernel/intern/particle_system.c | 1 + source/blender/blenkernel/intern/scene.c | 2 + source/blender/blenkernel/intern/screen.c | 1 + source/blender/blenkernel/intern/softbody.c | 3 +- source/blender/blenkernel/particle_private.h | 4 +- source/blender/blenloader/intern/readfile.c | 2 + source/blender/blenloader/intern/versioning_250.c | 1 + source/blender/blenloader/intern/versioning_260.c | 2 + source/blender/blenloader/intern/versioning_270.c | 1 + source/blender/blenloader/intern/versioning_290.c | 1 + .../blenloader/intern/versioning_defaults.c | 1 + .../blender/blenloader/intern/versioning_legacy.c | 1 + .../blender/blenloader/intern/versioning_userdef.c | 1 + source/blender/blenloader/intern/writefile.c | 1 + .../intern/builder/deg_builder_nodes_view_layer.cc | 1 + .../intern/builder/deg_builder_relations.cc | 1 + .../builder/deg_builder_relations_view_layer.cc | 1 + .../draw/intern/draw_cache_impl_particles.c | 1 + .../blender/editors/armature/editarmature_undo.c | 2 + source/blender/editors/gpencil/drawgpencil.c | 1 + .../blender/editors/gpencil/gpencil_add_monkey.c | 1 + .../blender/editors/gpencil/gpencil_add_stroke.c | 1 + source/blender/editors/gpencil/gpencil_convert.c | 1 + source/blender/editors/gpencil/gpencil_data.c | 1 + source/blender/editors/gpencil/gpencil_edit.c | 1 + source/blender/editors/gpencil/gpencil_fill.c | 1 + source/blender/editors/gpencil/gpencil_merge.c | 1 + .../editors/gpencil/gpencil_ops_versioning.c | 1 + .../blender/editors/gpencil/gpencil_sculpt_paint.c | 1 + source/blender/editors/gpencil/gpencil_select.c | 1 + source/blender/editors/gpencil/gpencil_utils.c | 2 + .../blender/editors/gpencil/gpencil_vertex_ops.c | 1 + .../blender/editors/gpencil/gpencil_vertex_paint.c | 1 + source/blender/editors/include/ED_info.h | 8 ++- source/blender/editors/include/ED_uvedit.h | 8 ++- .../interface/interface_eyedropper_gpencil_color.c | 1 + .../blender/editors/mesh/editmesh_select_similar.c | 1 + source/blender/editors/mesh/editmesh_undo.c | 1 + source/blender/editors/metaball/editmball_undo.c | 2 + source/blender/editors/object/object_bake.c | 1 + .../blender/editors/physics/rigidbody_constraint.c | 1 + source/blender/editors/physics/rigidbody_object.c | 1 + source/blender/editors/sculpt_paint/paint_image.c | 1 + .../space_outliner/tree/tree_display_libraries.cc | 2 + .../space_outliner/tree/tree_display_view_layer.cc | 1 + source/blender/editors/undo/memfile_undo.c | 1 + .../intern/MOD_gpencil_ui_common.c | 1 + .../gpencil_modifiers/intern/MOD_gpencil_util.c | 1 + .../gpencil_modifiers/intern/MOD_gpencilcolor.c | 1 + .../gpencil_modifiers/intern/MOD_gpenciltint.c | 1 + source/blender/imbuf/intern/jpeg.c | 2 + source/blender/imbuf/intern/metadata.c | 2 + source/blender/imbuf/intern/png.c | 2 + .../blender/io/alembic/exporter/abc_writer_hair.cc | 1 + source/blender/io/alembic/intern/alembic_capi.cc | 1 + source/blender/makesdna/DNA_movieclip_types.h | 4 +- source/blender/makesdna/DNA_node_types.h | 19 +++--- source/blender/makesdna/DNA_scene_types.h | 23 +++---- source/blender/makesdna/DNA_sequence_types.h | 8 +-- source/blender/makesdna/DNA_windowmanager_types.h | 6 +- source/blender/makesdna/DNA_workspace_types.h | 2 +- source/blender/makesrna/intern/rna_access.c | 2 +- source/blender/makesrna/intern/rna_brush.c | 1 + source/blender/makesrna/intern/rna_object_force.c | 1 + source/blender/modifiers/intern/MOD_cloth.c | 1 + source/blender/modifiers/intern/MOD_collision.c | 2 + source/blender/modifiers/intern/MOD_nodes.cc | 1 + source/blender/modifiers/intern/MOD_shapekey.c | 1 + source/blender/modifiers/intern/MOD_smooth.c | 1 + source/blender/modifiers/intern/MOD_solidify.c | 1 + .../modifiers/intern/MOD_solidify_extrude.c | 1 + .../modifiers/intern/MOD_solidify_nonmanifold.c | 1 + .../nodes/geometry/nodes/node_geo_attribute_mix.cc | 2 + source/blender/nodes/intern/node_socket.cc | 2 + source/blender/python/generic/idprop_py_api.c | 2 + source/blender/python/intern/bpy_props.c | 2 + .../blender/render/intern/texture_pointdensity.c | 1 + source/blender/sequencer/intern/effects.c | 1 + source/blender/simulation/SIM_mass_spring.h | 2 +- source/blender/windowmanager/intern/wm_operators.c | 2 +- 113 files changed, 259 insertions(+), 171 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/BKE_boids.h b/source/blender/blenkernel/BKE_boids.h index c9e6f0e7346..71a4d35767f 100644 --- a/source/blender/blenkernel/BKE_boids.h +++ b/source/blender/blenkernel/BKE_boids.h @@ -23,13 +23,16 @@ * \ingroup bke */ -#include "DNA_boid_types.h" -#include "DNA_particle_types.h" - #ifdef __cplusplus extern "C" { #endif +struct BoidSettings; +struct BoidState; +struct Object; +struct ParticleData; +struct ParticleSettings; +struct ParticleSimulationData; struct RNG; typedef struct BoidBrainData { @@ -50,13 +53,13 @@ typedef struct BoidBrainData { void boids_precalc_rules(struct ParticleSettings *part, float cfra); void boid_brain(BoidBrainData *bbd, int p, struct ParticleData *pa); void boid_body(BoidBrainData *bbd, struct ParticleData *pa); -void boid_default_settings(BoidSettings *boids); -BoidRule *boid_new_rule(int type); -BoidState *boid_new_state(BoidSettings *boids); -BoidState *boid_duplicate_state(BoidSettings *boids, BoidState *state); -void boid_free_settings(BoidSettings *boids); -BoidSettings *boid_copy_settings(const BoidSettings *boids); -BoidState *boid_get_current_state(BoidSettings *boids); +void boid_default_settings(struct BoidSettings *boids); +struct BoidRule *boid_new_rule(int type); +struct BoidState *boid_new_state(struct BoidSettings *boids); +struct BoidState *boid_duplicate_state(struct BoidSettings *boids, struct BoidState *state); +void boid_free_settings(struct BoidSettings *boids); +struct BoidSettings *boid_copy_settings(const struct BoidSettings *boids); +struct BoidState *boid_get_current_state(struct BoidSettings *boids); #ifdef __cplusplus } diff --git a/source/blender/blenkernel/BKE_collision.h b/source/blender/blenkernel/BKE_collision.h index 3a5328a33e2..a10a4e3c7fd 100644 --- a/source/blender/blenkernel/BKE_collision.h +++ b/source/blender/blenkernel/BKE_collision.h @@ -22,23 +22,13 @@ * \ingroup bke */ -#include -#include -#include -#include - -/* types */ -#include "BKE_collision.h" -#include "DNA_cloth_types.h" - -#include "BLI_kdopbvh.h" - #ifdef __cplusplus extern "C" { #endif struct Collection; struct CollisionModifierData; +struct BVHTree; struct Depsgraph; struct MVert; struct MVertTri; @@ -113,11 +103,11 @@ typedef struct FaceCollPair { // used in modifier.c from collision.c ///////////////////////////////////////////////// -BVHTree *bvhtree_build_from_mvert(const struct MVert *mvert, - const struct MVertTri *tri, - int tri_num, - float epsilon); -void bvhtree_update_from_mvert(BVHTree *bvhtree, +struct BVHTree *bvhtree_build_from_mvert(const struct MVert *mvert, + const struct MVertTri *tri, + int tri_num, + float epsilon); +void bvhtree_update_from_mvert(struct BVHTree *bvhtree, const struct MVert *mvert, const struct MVert *mvert_moving, const struct MVertTri *tri, diff --git a/source/blender/blenkernel/BKE_cryptomatte.h b/source/blender/blenkernel/BKE_cryptomatte.h index c3c17f72cae..71b15e47203 100644 --- a/source/blender/blenkernel/BKE_cryptomatte.h +++ b/source/blender/blenkernel/BKE_cryptomatte.h @@ -25,8 +25,6 @@ #include "BLI_sys_types.h" -#include "DNA_layer_types.h" - #ifdef __cplusplus extern "C" { #endif diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h index dcb4a993da1..881b93fe709 100644 --- a/source/blender/blenkernel/BKE_curve.h +++ b/source/blender/blenkernel/BKE_curve.h @@ -22,7 +22,9 @@ * \ingroup bke */ -#include "DNA_scene_types.h" +#include "BLI_sys_types.h" + +#include "DNA_listBase.h" #ifdef __cplusplus extern "C" { @@ -318,8 +320,8 @@ void BKE_curve_deform_coords(const struct Object *ob_curve, const short flag, const short defaxis); -void BKE_curve_deform_coords_with_editmesh(const Object *ob_curve, - const Object *ob_target, +void BKE_curve_deform_coords_with_editmesh(const struct Object *ob_curve, + const struct Object *ob_target, float (*vert_coords)[3], const int vert_coords_len, const int defgrp_index, diff --git a/source/blender/blenkernel/BKE_effect.h b/source/blender/blenkernel/BKE_effect.h index 0585f67703c..3cba47afc46 100644 --- a/source/blender/blenkernel/BKE_effect.h +++ b/source/blender/blenkernel/BKE_effect.h @@ -22,8 +22,6 @@ * \ingroup bke */ -#include "DNA_modifier_types.h" - #include "BLI_utildefines.h" #ifdef __cplusplus @@ -147,7 +145,7 @@ float effector_falloff(struct EffectorCache *eff, struct EffectorData *efd, struct EffectedPoint *point, struct EffectorWeights *weights); -int closest_point_on_surface(SurfaceModifierData *surmd, +int closest_point_on_surface(struct SurfaceModifierData *surmd, const float co[3], float surface_co[3], float surface_nor[3], diff --git a/source/blender/blenkernel/BKE_freestyle.h b/source/blender/blenkernel/BKE_freestyle.h index 47f0b547d83..5e29665d728 100644 --- a/source/blender/blenkernel/BKE_freestyle.h +++ b/source/blender/blenkernel/BKE_freestyle.h @@ -23,8 +23,6 @@ * \ingroup bke */ -#include "DNA_scene_types.h" - #ifdef __cplusplus extern "C" { #endif @@ -39,28 +37,31 @@ typedef struct FreestyleModuleSettings FreestyleModuleSettings; typedef struct FreestyleSettings FreestyleSettings; /* FreestyleConfig */ -void BKE_freestyle_config_init(FreestyleConfig *config); -void BKE_freestyle_config_free(FreestyleConfig *config, const bool do_id_user); -void BKE_freestyle_config_copy(FreestyleConfig *new_config, - const FreestyleConfig *config, +void BKE_freestyle_config_init(struct FreestyleConfig *config); +void BKE_freestyle_config_free(struct FreestyleConfig *config, const bool do_id_user); +void BKE_freestyle_config_copy(struct FreestyleConfig *new_config, + const struct FreestyleConfig *config, const int flag); /* FreestyleConfig.modules */ -FreestyleModuleConfig *BKE_freestyle_module_add(FreestyleConfig *config); -bool BKE_freestyle_module_delete(FreestyleConfig *config, FreestyleModuleConfig *module_conf); -bool BKE_freestyle_module_move(FreestyleConfig *config, - FreestyleModuleConfig *module_conf, +struct FreestyleModuleConfig *BKE_freestyle_module_add(struct FreestyleConfig *config); +bool BKE_freestyle_module_delete(struct FreestyleConfig *config, + struct FreestyleModuleConfig *module_conf); +bool BKE_freestyle_module_move(struct FreestyleConfig *config, + struct FreestyleModuleConfig *module_conf, int direction); /* FreestyleConfig.linesets */ -FreestyleLineSet *BKE_freestyle_lineset_add(struct Main *bmain, - FreestyleConfig *config, - const char *name); -bool BKE_freestyle_lineset_delete(FreestyleConfig *config, FreestyleLineSet *lineset); -FreestyleLineSet *BKE_freestyle_lineset_get_active(FreestyleConfig *config); -short BKE_freestyle_lineset_get_active_index(FreestyleConfig *config); -void BKE_freestyle_lineset_set_active_index(FreestyleConfig *config, short index); -void BKE_freestyle_lineset_unique_name(FreestyleConfig *config, FreestyleLineSet *lineset); +struct FreestyleLineSet *BKE_freestyle_lineset_add(struct Main *bmain, + struct FreestyleConfig *config, + const char *name); +bool BKE_freestyle_lineset_delete(struct FreestyleConfig *config, + struct FreestyleLineSet *lineset); +struct FreestyleLineSet *BKE_freestyle_lineset_get_active(struct FreestyleConfig *config); +short BKE_freestyle_lineset_get_active_index(struct FreestyleConfig *config); +void BKE_freestyle_lineset_set_active_index(struct FreestyleConfig *config, short index); +void BKE_freestyle_lineset_unique_name(struct FreestyleConfig *config, + struct FreestyleLineSet *lineset); #ifdef __cplusplus } diff --git a/source/blender/blenkernel/BKE_idprop.h b/source/blender/blenkernel/BKE_idprop.h index 9c250240e5e..bcf35bf1197 100644 --- a/source/blender/blenkernel/BKE_idprop.h +++ b/source/blender/blenkernel/BKE_idprop.h @@ -20,8 +20,6 @@ * \ingroup bke */ -#include "DNA_ID.h" - #include "BLI_compiler_attrs.h" #ifdef __cplusplus @@ -57,9 +55,9 @@ typedef union IDPropertyTemplate { /* ----------- Property Array Type ---------- */ -IDProperty *IDP_NewIDPArray(const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -IDProperty *IDP_CopyIDPArray(const IDProperty *array, const int flag) ATTR_WARN_UNUSED_RESULT - ATTR_NONNULL(); +struct IDProperty *IDP_NewIDPArray(const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +struct IDProperty *IDP_CopyIDPArray(const struct IDProperty *array, + const int flag) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); /* shallow copies item */ void IDP_SetIndexArray(struct IDProperty *prop, int index, struct IDProperty *item) ATTR_NONNULL(); @@ -74,7 +72,9 @@ void IDP_ResizeArray(struct IDProperty *prop, int newlen); void IDP_FreeArray(struct IDProperty *prop); /* ---------- String Type ------------ */ -IDProperty *IDP_NewString(const char *st, const char *name, int maxlen) ATTR_WARN_UNUSED_RESULT +struct IDProperty *IDP_NewString(const char *st, + const char *name, + int maxlen) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(2 /* 'name 'arg */); /* maxlen excludes '\0' */ void IDP_AssignString(struct IDProperty *prop, const char *st, int maxlen) ATTR_NONNULL(); /* maxlen excludes '\0' */ @@ -84,9 +84,9 @@ void IDP_FreeString(struct IDProperty *prop) ATTR_NONNULL(); /*-------- ID Type -------*/ -typedef void (*IDPWalkFunc)(void *userData, IDProperty *idp); +typedef void (*IDPWalkFunc)(void *userData, struct IDProperty *idp); -void IDP_AssignID(IDProperty *prop, ID *id, const int flag); +void IDP_AssignID(struct IDProperty *prop, struct ID *id, const int flag); /*-------- Group Functions -------*/ @@ -100,10 +100,10 @@ void IDP_ReplaceInGroup(struct IDProperty *group, struct IDProperty *prop) ATTR_ void IDP_ReplaceInGroup_ex(struct IDProperty *group, struct IDProperty *prop, struct IDProperty *prop_exist); -void IDP_MergeGroup(IDProperty *dest, const IDProperty *src, const bool do_overwrite) +void IDP_MergeGroup(struct IDProperty *dest, const struct IDProperty *src, const bool do_overwrite) ATTR_NONNULL(); -void IDP_MergeGroup_ex(IDProperty *dest, - const IDProperty *src, +void IDP_MergeGroup_ex(struct IDProperty *dest, + const struct IDProperty *src, const bool do_overwrite, const int flag) ATTR_NONNULL(); bool IDP_AddToGroup(struct IDProperty *group, struct IDProperty *prop) ATTR_NONNULL(); @@ -113,11 +113,13 @@ bool IDP_InsertToGroup(struct IDProperty *group, void IDP_RemoveFromGroup(struct IDProperty *group, struct IDProperty *prop) ATTR_NONNULL(); void IDP_FreeFromGroup(struct IDProperty *group, struct IDProperty *prop) ATTR_NONNULL(); -IDProperty *IDP_GetPropertyFromGroup(const struct IDProperty *prop, - const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -IDProperty *IDP_GetPropertyTypeFromGroup(const struct IDProperty *prop, - const char *name, - const char type) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +struct IDProperty *IDP_GetPropertyFromGroup(const struct IDProperty *prop, + const char *name) ATTR_WARN_UNUSED_RESULT + ATTR_NONNULL(); +struct IDProperty *IDP_GetPropertyTypeFromGroup(const struct IDProperty *prop, + const char *name, + const char type) ATTR_WARN_UNUSED_RESULT + ATTR_NONNULL(); /*-------- Main Functions --------*/ struct IDProperty *IDP_GetProperties(struct ID *id, @@ -127,10 +129,10 @@ struct IDProperty *IDP_CopyProperty(const struct IDProperty *prop) ATTR_WARN_UNU ATTR_NONNULL(); struct IDProperty *IDP_CopyProperty_ex(const struct IDProperty *prop, const int flag) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -void IDP_CopyPropertyContent(IDProperty *dst, IDProperty *src) ATTR_NONNULL(); +void IDP_CopyPropertyContent(struct IDProperty *dst, struct IDProperty *src) ATTR_NONNULL(); -bool IDP_EqualsProperties_ex(IDProperty *prop1, - IDProperty *prop2, +bool IDP_EqualsProperties_ex(struct IDProperty *prop1, + struct IDProperty *prop2, const bool is_strict) ATTR_WARN_UNUSED_RESULT; bool IDP_EqualsProperties(struct IDProperty *prop1, @@ -142,12 +144,12 @@ struct IDProperty *IDP_New(const char type, void IDP_FreePropertyContent_ex(struct IDProperty *prop, const bool do_id_user); void IDP_FreePropertyContent(struct IDProperty *prop); -void IDP_FreeProperty_ex(IDProperty *prop, const bool do_id_user); +void IDP_FreeProperty_ex(struct IDProperty *prop, const bool do_id_user); void IDP_FreeProperty(struct IDProperty *prop); -void IDP_ClearProperty(IDProperty *prop); +void IDP_ClearProperty(struct IDProperty *prop); -void IDP_Reset(IDProperty *prop, const IDProperty *reference); +void IDP_Reset(struct IDProperty *prop, const struct IDProperty *reference); #define IDP_Int(prop) ((prop)->data.val) #define IDP_Array(prop) ((prop)->data.pointer) @@ -155,29 +157,29 @@ void IDP_Reset(IDProperty *prop, const IDProperty *reference); #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) # define IDP_Float(prop) \ _Generic((prop), \ - IDProperty *: (*(float *)&(prop)->data.val), \ - const IDProperty *: (*(const float *)&(prop)->data.val)) + struct IDProperty *: (*(float *)&(prop)->data.val), \ + const struct IDProperty *: (*(const float *)&(prop)->data.val)) # define IDP_Double(prop) \ _Generic((prop), \ - IDProperty *: (*(double *)&(prop)->data.val), \ - const IDProperty *: (*(const double *)&(prop)->data.val)) + struct IDProperty *: (*(double *)&(prop)->data.val), \ + const struct IDProperty *: (*(const double *)&(prop)->data.val)) # define IDP_String(prop) \ _Generic((prop), \ - IDProperty *: ((char *) (prop)->data.pointer), \ - const IDProperty *: ((const char *) (prop)->data.pointer)) + struct IDProperty *: ((char *) (prop)->data.pointer), \ + const struct IDProperty *: ((const char *) (prop)->data.pointer)) # define IDP_IDPArray(prop) \ _Generic((prop), \ - IDProperty *: ((IDProperty *) (prop)->data.pointer), \ - const IDProperty *: ((const IDProperty *) (prop)->data.pointer)) + struct IDProperty *: ((struct IDProperty *) (prop)->data.pointer), \ + const struct IDProperty *: ((const struct IDProperty *) (prop)->data.pointer)) # define IDP_Id(prop) \ _Generic((prop), \ - IDProperty *: ((ID *) (prop)->data.pointer), \ - const IDProperty *: ((const ID *) (prop)->data.pointer)) + struct IDProperty *: ((ID *) (prop)->data.pointer), \ + const struct IDProperty *: ((const ID *) (prop)->data.pointer)) #else # define IDP_Float(prop) (*(float *)&(prop)->data.val) # define IDP_Double(prop) (*(double *)&(prop)->data.val) # define IDP_String(prop) ((char *)(prop)->data.pointer) -# define IDP_IDPArray(prop) ((IDProperty *)(prop)->data.pointer) +# define IDP_IDPArray(prop) ((struct IDProperty *)(prop)->data.pointer) # define IDP_Id(prop) ((ID *)(prop)->data.pointer) #endif @@ -185,7 +187,7 @@ void IDP_Reset(IDProperty *prop, const IDProperty *reference); * Call a callback for each idproperty in the hierarchy under given root one (included). * */ -typedef void (*IDPForeachPropertyCallback)(IDProperty *id_property, void *user_data); +typedef void (*IDPForeachPropertyCallback)(struct IDProperty *id_property, void *user_data); void IDP_foreach_property(struct IDProperty *id_property_root, const int type_filter, @@ -194,18 +196,18 @@ void IDP_foreach_property(struct IDProperty *id_property_root, /* Format IDProperty as strings */ char *IDP_reprN(const struct IDProperty *prop, uint *r_len); -void IDP_repr_fn(const IDProperty *prop, +void IDP_repr_fn(const struct IDProperty *prop, void (*str_append_fn)(void *user_data, const char *str, uint str_len), void *user_data); void IDP_print(const struct IDProperty *prop); void IDP_BlendWrite(struct BlendWriter *writer, const struct IDProperty *prop); void IDP_BlendReadData_impl(struct BlendDataReader *reader, - IDProperty **prop, + struct IDProperty **prop, const char *caller_func_id); #define IDP_BlendDataRead(reader, prop) IDP_BlendReadData_impl(reader, prop, __func__) -void IDP_BlendReadLib(struct BlendLibReader *reader, IDProperty *prop); -void IDP_BlendReadExpand(struct BlendExpander *expander, IDProperty *prop); +void IDP_BlendReadLib(struct BlendLibReader *reader, struct IDProperty *prop); +void IDP_BlendReadExpand(struct BlendExpander *expander, struct IDProperty *prop); #ifdef __cplusplus } diff --git a/source/blender/blenkernel/BKE_layer.h b/source/blender/blenkernel/BKE_layer.h index e5fab35891c..aa95ac2a8cf 100644 --- a/source/blender/blenkernel/BKE_layer.h +++ b/source/blender/blenkernel/BKE_layer.h @@ -23,15 +23,14 @@ #include "BKE_collection.h" #include "DNA_listBase.h" -#include "DNA_scene_types.h" #ifdef __cplusplus extern "C" { #endif -#define TODO_LAYER_OVERRIDE /* CollectionOverride */ +#define TODO_LAYER_OVERRIDE /* CollectionOverride */ #define TODO_LAYER_OPERATORS /* collection mamanger and property panel operators */ -#define TODO_LAYER /* generic todo */ +#define TODO_LAYER /* generic todo */ struct Base; struct BlendDataReader; @@ -56,9 +55,9 @@ typedef enum eViewLayerCopyMethod { struct ViewLayer *BKE_view_layer_default_view(const struct Scene *scene); struct ViewLayer *BKE_view_layer_default_render(const struct Scene *scene); struct ViewLayer *BKE_view_layer_find(const struct Scene *scene, const char *layer_name); -struct ViewLayer *BKE_view_layer_add(Scene *scene, +struct ViewLayer *BKE_view_layer_add(struct Scene *scene, const char *name, - ViewLayer *view_layer_source, + struct ViewLayer *view_layer_source, const int type); /* DEPRECATED */ @@ -393,10 +392,11 @@ struct ObjectsInModeParams { void *filter_userdata; }; -Base **BKE_view_layer_array_from_bases_in_mode_params(struct ViewLayer *view_layer, - const struct View3D *v3d, - uint *r_len, - const struct ObjectsInModeParams *params); +struct Base **BKE_view_layer_array_from_bases_in_mode_params( + struct ViewLayer *view_layer, + const struct View3D *v3d, + uint *r_len, + const struct ObjectsInModeParams *params); struct Object **BKE_view_layer_array_from_objects_in_mode_params( struct ViewLayer *view_layer, @@ -452,7 +452,8 @@ void BKE_view_layer_verify_aov(struct RenderEngine *engine, struct Scene *scene, struct ViewLayer *view_layer); bool BKE_view_layer_has_valid_aov(struct ViewLayer *view_layer); -ViewLayer *BKE_view_layer_find_with_aov(struct Scene *scene, struct ViewLayerAOV *view_layer_aov); +struct ViewLayer *BKE_view_layer_find_with_aov(struct Scene *scene, + struct ViewLayerAOV *view_layer_aov); #ifdef __cplusplus } diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index 73815325594..2ac39be7eb3 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -29,11 +29,8 @@ #include "BLI_buffer.h" #include "BLI_utildefines.h" -#include "DNA_object_types.h" #include "DNA_particle_types.h" -#include "BKE_customdata.h" - #ifdef __cplusplus extern "C" { #endif @@ -302,7 +299,7 @@ int psys_get_tot_child(struct Scene *scene, struct ParticleSystem *psys_get_current(struct Object *ob); /* for rna */ short psys_get_current_num(struct Object *ob); -void psys_set_current_num(Object *ob, int index); +void psys_set_current_num(struct Object *ob, int index); /* UNUSED */ // struct Object *psys_find_object(struct Scene *scene, struct ParticleSystem *psys); diff --git a/source/blender/blenkernel/BKE_pointcache.h b/source/blender/blenkernel/BKE_pointcache.h index f2edebededc..d3ae043588d 100644 --- a/source/blender/blenkernel/BKE_pointcache.h +++ b/source/blender/blenkernel/BKE_pointcache.h @@ -23,12 +23,10 @@ * \ingroup bke */ -#include "DNA_ID.h" -#include "DNA_boid_types.h" -#include "DNA_dynamicpaint_types.h" -#include "DNA_object_force_types.h" -#include "DNA_pointcache_types.h" -#include /* for FILE */ +#include "DNA_boid_types.h" /* for #BoidData */ +#include "DNA_pointcache_types.h" /* for #BPHYS_TOT_DATA */ + +#include /* for #FILE */ #ifdef __cplusplus extern "C" { @@ -93,6 +91,7 @@ struct SoftBody; struct ViewLayer; struct BlendWriter; struct BlendDataReader; +struct DynamicPaintSurface; /* temp structure for read/write */ typedef struct PTCacheData { diff --git a/source/blender/blenkernel/BKE_sequencer_offscreen.h b/source/blender/blenkernel/BKE_sequencer_offscreen.h index f5f6067b06e..25a78fcfbad 100644 --- a/source/blender/blenkernel/BKE_sequencer_offscreen.h +++ b/source/blender/blenkernel/BKE_sequencer_offscreen.h @@ -23,26 +23,23 @@ * \ingroup bke */ -#include "DNA_object_enums.h" - -#include "DNA_view3d_types.h" - -#include "IMB_imbuf_types.h" - #ifdef __cplusplus extern "C" { #endif struct GPUOffScreen; +enum eDrawType; +enum eImBufFlags; + typedef struct ImBuf *(*SequencerDrawView)(struct Depsgraph *depsgraph, struct Scene *scene, struct View3DShading *shading_override, - eDrawType drawtype, + enum eDrawType drawtype, struct Object *camera, int width, int height, - eImBufFlags flag, + enum eImBufFlags flag, eV3DOffscreenDrawFlag draw_flags, int alpha_mode, const char *viewname, diff --git a/source/blender/blenkernel/BKE_shader_fx.h b/source/blender/blenkernel/BKE_shader_fx.h index 7c2d363be5c..b5b5f61a6a6 100644 --- a/source/blender/blenkernel/BKE_shader_fx.h +++ b/source/blender/blenkernel/BKE_shader_fx.h @@ -19,7 +19,6 @@ * \ingroup bke */ -#include "BKE_customdata.h" #include "BLI_compiler_attrs.h" #include "DNA_shader_fx_types.h" /* needed for all enum typdefs */ diff --git a/source/blender/blenkernel/BKE_simulation.h b/source/blender/blenkernel/BKE_simulation.h index 23735990079..37372036130 100644 --- a/source/blender/blenkernel/BKE_simulation.h +++ b/source/blender/blenkernel/BKE_simulation.h @@ -16,8 +16,6 @@ #pragma once -#include "DNA_simulation_types.h" - #ifdef __cplusplus extern "C" { #endif @@ -25,6 +23,7 @@ extern "C" { struct Depsgraph; struct Main; struct Scene; +struct Simulation; void *BKE_simulation_add(struct Main *bmain, const char *name); diff --git a/source/blender/blenkernel/BKE_studiolight.h b/source/blender/blenkernel/BKE_studiolight.h index 614523be123..70b8743bcd2 100644 --- a/source/blender/blenkernel/BKE_studiolight.h +++ b/source/blender/blenkernel/BKE_studiolight.h @@ -29,7 +29,7 @@ #include "BLI_path_util.h" -#include "DNA_userdef_types.h" +#include "DNA_userdef_types.h" /* for #SolidLight */ #ifdef __cplusplus extern "C" { diff --git a/source/blender/blenkernel/BKE_text_suggestions.h b/source/blender/blenkernel/BKE_text_suggestions.h index f54e45b6c2f..7561e1d1d08 100644 --- a/source/blender/blenkernel/BKE_text_suggestions.h +++ b/source/blender/blenkernel/BKE_text_suggestions.h @@ -22,8 +22,6 @@ * \ingroup bke */ -#include "DNA_text_types.h" - #ifdef __cplusplus extern "C" { #endif @@ -62,9 +60,9 @@ typedef struct SuggList { void free_texttools(void); /* Used to identify which Text object the current tools should appear against */ -void texttool_text_set_active(Text *text); +void texttool_text_set_active(struct Text *text); void texttool_text_clear(void); -short texttool_text_is_active(Text *text); +short texttool_text_is_active(struct Text *text); /* Suggestions */ void texttool_suggest_add(const char *name, char type); diff --git a/source/blender/blenkernel/intern/anim_data.c b/source/blender/blenkernel/intern/anim_data.c index 13abfa92032..633d6202222 100644 --- a/source/blender/blenkernel/intern/anim_data.c +++ b/source/blender/blenkernel/intern/anim_data.c @@ -42,6 +42,7 @@ #include "DNA_ID.h" #include "DNA_anim_types.h" #include "DNA_light_types.h" +#include "DNA_material_types.h" #include "DNA_node_types.h" #include "DNA_space_types.h" #include "DNA_windowmanager_types.h" diff --git a/source/blender/blenkernel/intern/boids.c b/source/blender/blenkernel/intern/boids.c index 96bf9fbe8d2..e69173cc1d5 100644 --- a/source/blender/blenkernel/intern/boids.c +++ b/source/blender/blenkernel/intern/boids.c @@ -39,6 +39,7 @@ #include "BKE_collision.h" #include "BKE_effect.h" #include "BKE_particle.h" +#include "BLI_kdopbvh.h" #include "BKE_modifier.h" diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index 96791aed2c3..33686cea4fc 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -23,6 +23,7 @@ #include "DNA_brush_types.h" #include "DNA_defaults.h" #include "DNA_gpencil_types.h" +#include "DNA_material_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c index b56a15b3d45..e18b2d87459 100644 --- a/source/blender/blenkernel/intern/dynamicpaint.c +++ b/source/blender/blenkernel/intern/dynamicpaint.c @@ -42,6 +42,7 @@ #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_modifier_types.h" +#include "DNA_object_force_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" #include "DNA_texture_types.h" diff --git a/source/blender/blenkernel/intern/gpencil_curve.c b/source/blender/blenkernel/intern/gpencil_curve.c index 8cc11468771..be14d74de7a 100644 --- a/source/blender/blenkernel/intern/gpencil_curve.c +++ b/source/blender/blenkernel/intern/gpencil_curve.c @@ -36,8 +36,11 @@ #include "BLT_translation.h" +#include "DNA_collection_types.h" #include "DNA_gpencil_types.h" +#include "DNA_material_types.h" #include "DNA_meshdata_types.h" +#include "DNA_scene_types.h" #include "BKE_collection.h" #include "BKE_context.h" diff --git a/source/blender/blenkernel/intern/gpencil_geom.c b/source/blender/blenkernel/intern/gpencil_geom.c index 85b02d2ba3b..df755e96216 100644 --- a/source/blender/blenkernel/intern/gpencil_geom.c +++ b/source/blender/blenkernel/intern/gpencil_geom.c @@ -42,6 +42,7 @@ #include "DNA_gpencil_modifier_types.h" #include "DNA_gpencil_types.h" +#include "DNA_material_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_scene_types.h" diff --git a/source/blender/blenkernel/intern/idprop_utils.c b/source/blender/blenkernel/intern/idprop_utils.c index f8a1113f69b..433f0e97844 100644 --- a/source/blender/blenkernel/intern/idprop_utils.c +++ b/source/blender/blenkernel/intern/idprop_utils.c @@ -26,6 +26,8 @@ #include "BLI_string.h" #include "BLI_utildefines.h" +#include "DNA_ID.h" + #include "BKE_idprop.h" #include "BKE_idtype.h" diff --git a/source/blender/blenkernel/intern/idtype.c b/source/blender/blenkernel/intern/idtype.c index 44bf8f0e4db..1889d1c4eb0 100644 --- a/source/blender/blenkernel/intern/idtype.c +++ b/source/blender/blenkernel/intern/idtype.c @@ -36,6 +36,7 @@ #include "BLT_translation.h" #include "DNA_ID.h" +#include "DNA_collection_types.h" #include "DNA_node_types.h" #include "DNA_scene_types.h" diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index f72cce8ba2e..228aed265cf 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -54,6 +54,7 @@ #include "DNA_camera_types.h" #include "DNA_defaults.h" #include "DNA_light_types.h" +#include "DNA_material_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_object_types.h" diff --git a/source/blender/blenkernel/intern/lib_id.c b/source/blender/blenkernel/intern/lib_id.c index 21a77e2b45a..8113417b55f 100644 --- a/source/blender/blenkernel/intern/lib_id.c +++ b/source/blender/blenkernel/intern/lib_id.c @@ -37,6 +37,7 @@ /* all types are needed here, in order to do memory operations */ #include "DNA_ID.h" #include "DNA_anim_types.h" +#include "DNA_collection_types.h" #include "DNA_gpencil_types.h" #include "DNA_key_types.h" #include "DNA_node_types.h" diff --git a/source/blender/blenkernel/intern/lib_remap.c b/source/blender/blenkernel/intern/lib_remap.c index f0031d4191d..56f7bb0be6f 100644 --- a/source/blender/blenkernel/intern/lib_remap.c +++ b/source/blender/blenkernel/intern/lib_remap.c @@ -24,6 +24,7 @@ #include "BLI_utildefines.h" +#include "DNA_collection_types.h" #include "DNA_object_types.h" #include "BKE_armature.h" diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 3496e05c6e5..418fe0a9502 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -38,6 +38,7 @@ #include "DNA_armature_types.h" #include "DNA_cloth_types.h" +#include "DNA_dynamicpaint_types.h" #include "DNA_fluid_types.h" #include "DNA_gpencil_modifier_types.h" #include "DNA_mesh_types.h" diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index a90d2ea36c9..a9a1740f4a8 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -35,6 +35,7 @@ #include "DNA_action_types.h" #include "DNA_anim_types.h" +#include "DNA_collection_types.h" #include "DNA_gpencil_types.h" #include "DNA_light_types.h" #include "DNA_linestyle_types.h" diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index f11e7bc429d..8764232e56b 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -38,6 +38,7 @@ #include "DNA_collection_types.h" #include "DNA_constraint_types.h" #include "DNA_defaults.h" +#include "DNA_dynamicpaint_types.h" #include "DNA_effect_types.h" #include "DNA_fluid_types.h" #include "DNA_gpencil_modifier_types.h" diff --git a/source/blender/blenkernel/intern/object_update.c b/source/blender/blenkernel/intern/object_update.c index 915ee56e2f7..1b4dc98252a 100644 --- a/source/blender/blenkernel/intern/object_update.c +++ b/source/blender/blenkernel/intern/object_update.c @@ -28,6 +28,7 @@ #include "DNA_key_types.h" #include "DNA_material_types.h" #include "DNA_mesh_types.h" +#include "DNA_modifier_types.h" #include "DNA_scene_types.h" #include "BLI_blenlib.h" diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index d516de535f9..dce45f44583 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -41,6 +41,7 @@ #include "DNA_material_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" +#include "DNA_object_force_types.h" #include "DNA_particle_types.h" #include "DNA_scene_types.h" diff --git a/source/blender/blenkernel/intern/particle_child.c b/source/blender/blenkernel/intern/particle_child.c index 98a55c3de95..6e0965650d3 100644 --- a/source/blender/blenkernel/intern/particle_child.c +++ b/source/blender/blenkernel/intern/particle_child.c @@ -25,6 +25,7 @@ #include "BLI_noise.h" #include "DNA_material_types.h" +#include "DNA_object_types.h" #include "BKE_colortools.h" #include "BKE_particle.h" diff --git a/source/blender/blenkernel/intern/particle_distribute.c b/source/blender/blenkernel/intern/particle_distribute.c index 194593be4ff..c3cc9136057 100644 --- a/source/blender/blenkernel/intern/particle_distribute.c +++ b/source/blender/blenkernel/intern/particle_distribute.c @@ -40,6 +40,7 @@ #include "DNA_particle_types.h" #include "DNA_scene_types.h" +#include "BKE_customdata.h" #include "BKE_global.h" #include "BKE_lib_id.h" #include "BKE_mesh.h" diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 79ce6769160..71df28c8b42 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -34,6 +34,7 @@ #include "DNA_anim_types.h" #include "DNA_boid_types.h" +#include "DNA_cloth_types.h" #include "DNA_curve_types.h" #include "DNA_listBase.h" #include "DNA_mesh_types.h" diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index bed10df5ace..f63d443d29f 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -37,6 +37,7 @@ #include "DNA_gpencil_types.h" #include "DNA_linestyle_types.h" #include "DNA_mask_types.h" +#include "DNA_material_types.h" #include "DNA_mesh_types.h" #include "DNA_node_types.h" #include "DNA_object_types.h" @@ -47,6 +48,7 @@ #include "DNA_sound_types.h" #include "DNA_space_types.h" #include "DNA_text_types.h" +#include "DNA_vfont_types.h" #include "DNA_view3d_types.h" #include "DNA_windowmanager_types.h" #include "DNA_workspace_types.h" diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c index 355db8f0d60..ae817c46931 100644 --- a/source/blender/blenkernel/intern/screen.c +++ b/source/blender/blenkernel/intern/screen.c @@ -34,6 +34,7 @@ #include "MEM_guardedalloc.h" +#include "DNA_collection_types.h" #include "DNA_defaults.h" #include "DNA_gpencil_types.h" #include "DNA_mask_types.h" diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c index 25d812884bc..cf02dd4d160 100644 --- a/source/blender/blenkernel/intern/softbody.c +++ b/source/blender/blenkernel/intern/softbody.c @@ -52,6 +52,7 @@ #include "DNA_lattice_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" +#include "DNA_object_force_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" @@ -149,7 +150,7 @@ typedef struct SB_thread_context { #define BSF_INTERSECT 1 /* edge intersects collider face */ /* private definitions for bodypoint states */ -#define SBF_DOFUZZY 1 /* Bodypoint do fuzzy */ +#define SBF_DOFUZZY 1 /* Bodypoint do fuzzy */ #define SBF_OUTOFCOLLISION 2 /* Bodypoint does not collide */ #define BFF_INTERSECT 1 /* collider edge intrudes face */ diff --git a/source/blender/blenkernel/particle_private.h b/source/blender/blenkernel/particle_private.h index 33277d1caac..1c183aab3b7 100644 --- a/source/blender/blenkernel/particle_private.h +++ b/source/blender/blenkernel/particle_private.h @@ -27,6 +27,8 @@ extern "C" { #endif +struct CurveMapping; + typedef struct ParticleChildModifierContext { ParticleThreadContext *thread_ctx; ParticleSimulationData *sim; @@ -62,7 +64,7 @@ float do_clump(ParticleKey *state, float pa_clump, bool use_clump_noise, float clump_noise_size, - CurveMapping *clumpcurve); + struct CurveMapping *clumpcurve); void do_child_modifiers(const ParticleChildModifierContext *modifier_ctx, float mat[4][4], ParticleKey *state, diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 9ce767b7ce1..fd10eac4302 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -45,6 +45,7 @@ #include "DNA_anim_types.h" #include "DNA_cachefile_types.h" +#include "DNA_collection_types.h" #include "DNA_fileglobal_types.h" #include "DNA_genfile.h" #include "DNA_key_types.h" @@ -53,6 +54,7 @@ #include "DNA_packedFile_types.h" #include "DNA_sdna_types.h" #include "DNA_sound_types.h" +#include "DNA_vfont_types.h" #include "DNA_volume_types.h" #include "DNA_workspace_types.h" diff --git a/source/blender/blenloader/intern/versioning_250.c b/source/blender/blenloader/intern/versioning_250.c index c86ad639216..b282a978e8a 100644 --- a/source/blender/blenloader/intern/versioning_250.c +++ b/source/blender/blenloader/intern/versioning_250.c @@ -46,6 +46,7 @@ #include "DNA_meshdata_types.h" #include "DNA_node_types.h" #include "DNA_object_fluidsim_types.h" +#include "DNA_object_force_types.h" #include "DNA_object_types.h" #include "DNA_screen_types.h" #include "DNA_sdna_types.h" diff --git a/source/blender/blenloader/intern/versioning_260.c b/source/blender/blenloader/intern/versioning_260.c index c33f2a8cad5..c336239ec59 100644 --- a/source/blender/blenloader/intern/versioning_260.c +++ b/source/blender/blenloader/intern/versioning_260.c @@ -28,11 +28,13 @@ #include "DNA_camera_types.h" #include "DNA_cloth_types.h" #include "DNA_constraint_types.h" +#include "DNA_dynamicpaint_types.h" #include "DNA_fluid_types.h" #include "DNA_genfile.h" #include "DNA_key_types.h" #include "DNA_light_types.h" #include "DNA_linestyle_types.h" +#include "DNA_material_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_object_fluidsim_types.h" diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c index b07d1ea66b1..046749e4691 100644 --- a/source/blender/blenloader/intern/versioning_270.c +++ b/source/blender/blenloader/intern/versioning_270.c @@ -64,6 +64,7 @@ #include "BKE_scene.h" #include "BKE_screen.h" #include "BKE_tracking.h" +#include "DNA_material_types.h" #include "SEQ_sequencer.h" diff --git a/source/blender/blenloader/intern/versioning_290.c b/source/blender/blenloader/intern/versioning_290.c index 6f055186702..d00c5225299 100644 --- a/source/blender/blenloader/intern/versioning_290.c +++ b/source/blender/blenloader/intern/versioning_290.c @@ -29,6 +29,7 @@ #include "DNA_anim_types.h" #include "DNA_brush_types.h" #include "DNA_cachefile_types.h" +#include "DNA_collection_types.h" #include "DNA_constraint_types.h" #include "DNA_fluid_types.h" #include "DNA_genfile.h" diff --git a/source/blender/blenloader/intern/versioning_defaults.c b/source/blender/blenloader/intern/versioning_defaults.c index 48a24755250..f89a5be27de 100644 --- a/source/blender/blenloader/intern/versioning_defaults.c +++ b/source/blender/blenloader/intern/versioning_defaults.c @@ -37,6 +37,7 @@ #include "DNA_curveprofile_types.h" #include "DNA_gpencil_types.h" #include "DNA_light_types.h" +#include "DNA_material_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_object_types.h" diff --git a/source/blender/blenloader/intern/versioning_legacy.c b/source/blender/blenloader/intern/versioning_legacy.c index d654a0e30bd..6f459339675 100644 --- a/source/blender/blenloader/intern/versioning_legacy.c +++ b/source/blender/blenloader/intern/versioning_legacy.c @@ -49,6 +49,7 @@ #include "DNA_nla_types.h" #include "DNA_node_types.h" #include "DNA_object_fluidsim_types.h" +#include "DNA_object_force_types.h" #include "DNA_object_types.h" #include "DNA_screen_types.h" #include "DNA_sdna_types.h" diff --git a/source/blender/blenloader/intern/versioning_userdef.c b/source/blender/blenloader/intern/versioning_userdef.c index cfcaeb03d77..5ed7ab55851 100644 --- a/source/blender/blenloader/intern/versioning_userdef.c +++ b/source/blender/blenloader/intern/versioning_userdef.c @@ -31,6 +31,7 @@ #endif #include "DNA_anim_types.h" +#include "DNA_collection_types.h" #include "DNA_curve_types.h" #include "DNA_scene_types.h" #include "DNA_space_types.h" diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 11fe240620a..c64a7dc1b9f 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -93,6 +93,7 @@ /* allow writefile to use deprecated functionality (for forward compatibility code) */ #define DNA_DEPRECATED_ALLOW +#include "DNA_collection_types.h" #include "DNA_fileglobal_types.h" #include "DNA_genfile.h" #include "DNA_sdna_types.h" diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc index c7669b9fecb..b1fd86f13bc 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc @@ -34,6 +34,7 @@ #include "BLI_string.h" #include "BLI_utildefines.h" +#include "DNA_collection_types.h" #include "DNA_freestyle_types.h" #include "DNA_layer_types.h" #include "DNA_linestyle_types.h" diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc index 04686823d62..de68ec6210e 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc @@ -39,6 +39,7 @@ #include "DNA_armature_types.h" #include "DNA_cachefile_types.h" #include "DNA_camera_types.h" +#include "DNA_cloth_types.h" #include "DNA_collection_types.h" #include "DNA_constraint_types.h" #include "DNA_curve_types.h" diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc index 8df8d4914c3..24876049942 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc @@ -34,6 +34,7 @@ #include "BLI_blenlib.h" #include "BLI_utildefines.h" +#include "DNA_collection_types.h" #include "DNA_linestyle_types.h" #include "DNA_node_types.h" #include "DNA_object_types.h" diff --git a/source/blender/draw/intern/draw_cache_impl_particles.c b/source/blender/draw/intern/draw_cache_impl_particles.c index 75685c7e2f0..a9febcedbf9 100644 --- a/source/blender/draw/intern/draw_cache_impl_particles.c +++ b/source/blender/draw/intern/draw_cache_impl_particles.c @@ -38,6 +38,7 @@ #include "DNA_modifier_types.h" #include "DNA_particle_types.h" +#include "BKE_customdata.h" #include "BKE_mesh.h" #include "BKE_particle.h" #include "BKE_pointcache.h" diff --git a/source/blender/editors/armature/editarmature_undo.c b/source/blender/editors/armature/editarmature_undo.c index c217b615db6..7c11c5e537e 100644 --- a/source/blender/editors/armature/editarmature_undo.c +++ b/source/blender/editors/armature/editarmature_undo.c @@ -26,7 +26,9 @@ #include "CLG_log.h" #include "DNA_armature_types.h" +#include "DNA_layer_types.h" #include "DNA_object_types.h" +#include "DNA_scene_types.h" #include "BLI_array_utils.h" #include "BLI_listbase.h" diff --git a/source/blender/editors/gpencil/drawgpencil.c b/source/blender/editors/gpencil/drawgpencil.c index 93767127cc7..4e2951c3571 100644 --- a/source/blender/editors/gpencil/drawgpencil.c +++ b/source/blender/editors/gpencil/drawgpencil.c @@ -41,6 +41,7 @@ #include "DNA_brush_types.h" #include "DNA_gpencil_types.h" +#include "DNA_material_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" diff --git a/source/blender/editors/gpencil/gpencil_add_monkey.c b/source/blender/editors/gpencil/gpencil_add_monkey.c index 315b3c281da..65141442237 100644 --- a/source/blender/editors/gpencil/gpencil_add_monkey.c +++ b/source/blender/editors/gpencil/gpencil_add_monkey.c @@ -25,6 +25,7 @@ #include "BLI_utildefines.h" #include "DNA_gpencil_types.h" +#include "DNA_material_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" diff --git a/source/blender/editors/gpencil/gpencil_add_stroke.c b/source/blender/editors/gpencil/gpencil_add_stroke.c index f26fd936d40..0c8cc621a3b 100644 --- a/source/blender/editors/gpencil/gpencil_add_stroke.c +++ b/source/blender/editors/gpencil/gpencil_add_stroke.c @@ -25,6 +25,7 @@ #include "BLI_utildefines.h" #include "DNA_gpencil_types.h" +#include "DNA_material_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" diff --git a/source/blender/editors/gpencil/gpencil_convert.c b/source/blender/editors/gpencil/gpencil_convert.c index 63aa242275a..09b57029350 100644 --- a/source/blender/editors/gpencil/gpencil_convert.c +++ b/source/blender/editors/gpencil/gpencil_convert.c @@ -41,6 +41,7 @@ #include "DNA_collection_types.h" #include "DNA_curve_types.h" #include "DNA_gpencil_types.h" +#include "DNA_material_types.h" #include "DNA_node_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" diff --git a/source/blender/editors/gpencil/gpencil_data.c b/source/blender/editors/gpencil/gpencil_data.c index 203e86e9e15..093f1fa89c7 100644 --- a/source/blender/editors/gpencil/gpencil_data.c +++ b/source/blender/editors/gpencil/gpencil_data.c @@ -42,6 +42,7 @@ #include "DNA_anim_types.h" #include "DNA_brush_types.h" #include "DNA_gpencil_types.h" +#include "DNA_material_types.h" #include "DNA_meshdata_types.h" #include "DNA_modifier_types.h" #include "DNA_object_types.h" diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c index 95c94f8cfed..36e383cf3c2 100644 --- a/source/blender/editors/gpencil/gpencil_edit.c +++ b/source/blender/editors/gpencil/gpencil_edit.c @@ -41,6 +41,7 @@ #include "DNA_gpencil_modifier_types.h" #include "DNA_gpencil_types.h" +#include "DNA_material_types.h" #include "DNA_meshdata_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" diff --git a/source/blender/editors/gpencil/gpencil_fill.c b/source/blender/editors/gpencil/gpencil_fill.c index 93941ea3766..39968aac9fa 100644 --- a/source/blender/editors/gpencil/gpencil_fill.c +++ b/source/blender/editors/gpencil/gpencil_fill.c @@ -35,6 +35,7 @@ #include "DNA_brush_types.h" #include "DNA_gpencil_types.h" #include "DNA_image_types.h" +#include "DNA_material_types.h" #include "DNA_meshdata_types.h" #include "DNA_object_types.h" #include "DNA_windowmanager_types.h" diff --git a/source/blender/editors/gpencil/gpencil_merge.c b/source/blender/editors/gpencil/gpencil_merge.c index 9f2bf3818a4..272dff56291 100644 --- a/source/blender/editors/gpencil/gpencil_merge.c +++ b/source/blender/editors/gpencil/gpencil_merge.c @@ -31,6 +31,7 @@ #include "BLI_math.h" #include "DNA_gpencil_types.h" +#include "DNA_material_types.h" #include "BKE_brush.h" #include "BKE_context.h" diff --git a/source/blender/editors/gpencil/gpencil_ops_versioning.c b/source/blender/editors/gpencil/gpencil_ops_versioning.c index 4721736489e..815bbbaa254 100644 --- a/source/blender/editors/gpencil/gpencil_ops_versioning.c +++ b/source/blender/editors/gpencil/gpencil_ops_versioning.c @@ -33,6 +33,7 @@ #include "BLI_math.h" #include "DNA_gpencil_types.h" +#include "DNA_material_types.h" #include "DNA_meshdata_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" diff --git a/source/blender/editors/gpencil/gpencil_sculpt_paint.c b/source/blender/editors/gpencil/gpencil_sculpt_paint.c index ed18c2eed5d..bb9dd8cac5d 100644 --- a/source/blender/editors/gpencil/gpencil_sculpt_paint.c +++ b/source/blender/editors/gpencil/gpencil_sculpt_paint.c @@ -41,6 +41,7 @@ #include "BLT_translation.h" #include "DNA_gpencil_types.h" +#include "DNA_material_types.h" #include "DNA_meshdata_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" diff --git a/source/blender/editors/gpencil/gpencil_select.c b/source/blender/editors/gpencil/gpencil_select.c index 2c0b9534141..281ab8c5adc 100644 --- a/source/blender/editors/gpencil/gpencil_select.c +++ b/source/blender/editors/gpencil/gpencil_select.c @@ -36,6 +36,7 @@ #include "BLI_utildefines.h" #include "DNA_gpencil_types.h" +#include "DNA_material_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c index e8e25a55796..c3ac33063af 100644 --- a/source/blender/editors/gpencil/gpencil_utils.c +++ b/source/blender/editors/gpencil/gpencil_utils.c @@ -40,7 +40,9 @@ #include "PIL_time.h" #include "DNA_brush_types.h" +#include "DNA_collection_types.h" #include "DNA_gpencil_types.h" +#include "DNA_material_types.h" #include "DNA_meshdata_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" diff --git a/source/blender/editors/gpencil/gpencil_vertex_ops.c b/source/blender/editors/gpencil/gpencil_vertex_ops.c index c3fd8d10b64..90b2c1c3895 100644 --- a/source/blender/editors/gpencil/gpencil_vertex_ops.c +++ b/source/blender/editors/gpencil/gpencil_vertex_ops.c @@ -32,6 +32,7 @@ #include "DNA_brush_types.h" #include "DNA_gpencil_types.h" +#include "DNA_material_types.h" #include "BKE_colortools.h" #include "BKE_context.h" diff --git a/source/blender/editors/gpencil/gpencil_vertex_paint.c b/source/blender/editors/gpencil/gpencil_vertex_paint.c index a4dc677f0dc..3afff897734 100644 --- a/source/blender/editors/gpencil/gpencil_vertex_paint.c +++ b/source/blender/editors/gpencil/gpencil_vertex_paint.c @@ -31,6 +31,7 @@ #include "DNA_brush_types.h" #include "DNA_gpencil_types.h" +#include "DNA_material_types.h" #include "BKE_brush.h" #include "BKE_colortools.h" diff --git a/source/blender/editors/include/ED_info.h b/source/blender/editors/include/ED_info.h index e3ce494e09a..9ac6b6c1085 100644 --- a/source/blender/editors/include/ED_info.h +++ b/source/blender/editors/include/ED_info.h @@ -38,8 +38,12 @@ const char *ED_info_statistics_string(struct Main *bmain, struct Scene *scene, struct ViewLayer *view_layer); -void ED_info_draw_stats( - struct Main *bmain, Scene *scene, ViewLayer *view_layer, int x, int *y, int height); +void ED_info_draw_stats(struct Main *bmain, + struct Scene *scene, + struct ViewLayer *view_layer, + int x, + int *y, + int height); #ifdef __cplusplus } diff --git a/source/blender/editors/include/ED_uvedit.h b/source/blender/editors/include/ED_uvedit.h index 2066d7da511..d08bc0b0b3d 100644 --- a/source/blender/editors/include/ED_uvedit.h +++ b/source/blender/editors/include/ED_uvedit.h @@ -217,8 +217,10 @@ struct BMLoop *ED_uvedit_active_vert_loop_get(struct BMesh *bm); void ED_uvedit_active_edge_loop_set(struct BMesh *bm, struct BMLoop *l); struct BMLoop *ED_uvedit_active_edge_loop_get(struct BMesh *bm); -char ED_uvedit_select_mode_get(const Scene *scene); -void ED_uvedit_select_sync_flush(const ToolSettings *ts, struct BMEditMesh *em, const bool select); +char ED_uvedit_select_mode_get(const struct Scene *scene); +void ED_uvedit_select_sync_flush(const struct ToolSettings *ts, + struct BMEditMesh *em, + const bool select); /* uvedit_unwrap_ops.c */ void ED_uvedit_live_unwrap_begin(struct Scene *scene, struct Object *obedit); @@ -244,7 +246,7 @@ struct UVPackIsland_Params { uint use_seams : 1; uint correct_aspect : 1; }; -void ED_uvedit_pack_islands_multi(const Scene *scene, +void ED_uvedit_pack_islands_multi(const struct Scene *scene, Object **objects, const uint objects_len, const struct UVPackIsland_Params *params); diff --git a/source/blender/editors/interface/interface_eyedropper_gpencil_color.c b/source/blender/editors/interface/interface_eyedropper_gpencil_color.c index 7f735a0e789..f2899fc0098 100644 --- a/source/blender/editors/interface/interface_eyedropper_gpencil_color.c +++ b/source/blender/editors/interface/interface_eyedropper_gpencil_color.c @@ -34,6 +34,7 @@ #include "BLT_translation.h" #include "DNA_gpencil_types.h" +#include "DNA_material_types.h" #include "DNA_space_types.h" #include "BKE_context.h" diff --git a/source/blender/editors/mesh/editmesh_select_similar.c b/source/blender/editors/mesh/editmesh_select_similar.c index 00349983c57..d762eede079 100644 --- a/source/blender/editors/mesh/editmesh_select_similar.c +++ b/source/blender/editors/mesh/editmesh_select_similar.c @@ -34,6 +34,7 @@ #include "BKE_material.h" #include "BKE_report.h" +#include "DNA_material_types.h" #include "DNA_meshdata_types.h" #include "WM_api.h" diff --git a/source/blender/editors/mesh/editmesh_undo.c b/source/blender/editors/mesh/editmesh_undo.c index 43cad2db185..cff5414da75 100644 --- a/source/blender/editors/mesh/editmesh_undo.c +++ b/source/blender/editors/mesh/editmesh_undo.c @@ -27,6 +27,7 @@ #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_object_types.h" +#include "DNA_scene_types.h" #include "BLI_array_utils.h" #include "BLI_listbase.h" diff --git a/source/blender/editors/metaball/editmball_undo.c b/source/blender/editors/metaball/editmball_undo.c index 552e459acb1..b4030ad269b 100644 --- a/source/blender/editors/metaball/editmball_undo.c +++ b/source/blender/editors/metaball/editmball_undo.c @@ -30,8 +30,10 @@ #include "BLI_utildefines.h" #include "DNA_defs.h" +#include "DNA_layer_types.h" #include "DNA_meta_types.h" #include "DNA_object_types.h" +#include "DNA_scene_types.h" #include "BKE_context.h" #include "BKE_layer.h" diff --git a/source/blender/editors/object/object_bake.c b/source/blender/editors/object/object_bake.c index 008498a1735..9618774eea8 100644 --- a/source/blender/editors/object/object_bake.c +++ b/source/blender/editors/object/object_bake.c @@ -25,6 +25,7 @@ #include "MEM_guardedalloc.h" +#include "DNA_material_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_object_types.h" diff --git a/source/blender/editors/physics/rigidbody_constraint.c b/source/blender/editors/physics/rigidbody_constraint.c index 4939bf0086b..cb7ca5bd5d1 100644 --- a/source/blender/editors/physics/rigidbody_constraint.c +++ b/source/blender/editors/physics/rigidbody_constraint.c @@ -25,6 +25,7 @@ #include #include +#include "DNA_collection_types.h" #include "DNA_object_types.h" #include "DNA_rigidbody_types.h" #include "DNA_scene_types.h" diff --git a/source/blender/editors/physics/rigidbody_object.c b/source/blender/editors/physics/rigidbody_object.c index cb25363d2b2..4fd304ea71d 100644 --- a/source/blender/editors/physics/rigidbody_object.c +++ b/source/blender/editors/physics/rigidbody_object.c @@ -25,6 +25,7 @@ #include #include +#include "DNA_collection_types.h" #include "DNA_object_types.h" #include "DNA_rigidbody_types.h" #include "DNA_scene_types.h" diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c index 999d364a3cd..324fd5d3075 100644 --- a/source/blender/editors/sculpt_paint/paint_image.c +++ b/source/blender/editors/sculpt_paint/paint_image.c @@ -40,6 +40,7 @@ #include "IMB_imbuf_types.h" #include "DNA_brush_types.h" +#include "DNA_material_types.h" #include "DNA_mesh_types.h" #include "DNA_node_types.h" #include "DNA_object_types.h" diff --git a/source/blender/editors/space_outliner/tree/tree_display_libraries.cc b/source/blender/editors/space_outliner/tree/tree_display_libraries.cc index bd0870c837c..cb5f42f08e1 100644 --- a/source/blender/editors/space_outliner/tree/tree_display_libraries.cc +++ b/source/blender/editors/space_outliner/tree/tree_display_libraries.cc @@ -24,6 +24,8 @@ #include "BKE_collection.h" #include "BKE_main.h" +#include "DNA_collection_types.h" + #include "BLT_translation.h" #include "../outliner_intern.h" diff --git a/source/blender/editors/space_outliner/tree/tree_display_view_layer.cc b/source/blender/editors/space_outliner/tree/tree_display_view_layer.cc index c88eb957dd1..f7740f4648f 100644 --- a/source/blender/editors/space_outliner/tree/tree_display_view_layer.cc +++ b/source/blender/editors/space_outliner/tree/tree_display_view_layer.cc @@ -20,6 +20,7 @@ #include +#include "DNA_collection_types.h" #include "DNA_scene_types.h" #include "BKE_layer.h" diff --git a/source/blender/editors/undo/memfile_undo.c b/source/blender/editors/undo/memfile_undo.c index 49417a54472..4fded419b5b 100644 --- a/source/blender/editors/undo/memfile_undo.c +++ b/source/blender/editors/undo/memfile_undo.c @@ -27,6 +27,7 @@ #include "BLI_listbase.h" #include "DNA_ID.h" +#include "DNA_collection_types.h" #include "DNA_node_types.h" #include "DNA_object_enums.h" #include "DNA_object_types.h" diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencil_ui_common.c b/source/blender/gpencil_modifiers/intern/MOD_gpencil_ui_common.c index 37cde3162a0..d3ba5bf8b37 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencil_ui_common.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencil_ui_common.c @@ -28,6 +28,7 @@ #include "BKE_object.h" #include "BKE_screen.h" +#include "DNA_material_types.h" #include "DNA_object_force_types.h" #include "DNA_object_types.h" #include "DNA_particle_types.h" diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c b/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c index 077a454db73..f5bfe66562b 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c @@ -33,6 +33,7 @@ #include "DNA_gpencil_modifier_types.h" #include "DNA_gpencil_types.h" +#include "DNA_material_types.h" #include "DNA_meshdata_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilcolor.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilcolor.c index 4e569099461..04405fed7d9 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilcolor.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilcolor.c @@ -34,6 +34,7 @@ #include "DNA_defaults.h" #include "DNA_gpencil_modifier_types.h" #include "DNA_gpencil_types.h" +#include "DNA_material_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c b/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c index 2ee148837cd..311d08238b9 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c @@ -33,6 +33,7 @@ #include "DNA_defaults.h" #include "DNA_gpencil_modifier_types.h" #include "DNA_gpencil_types.h" +#include "DNA_material_types.h" #include "DNA_meshdata_types.h" #include "DNA_modifier_types.h" #include "DNA_object_types.h" diff --git a/source/blender/imbuf/intern/jpeg.c b/source/blender/imbuf/intern/jpeg.c index 93cdbbb1407..7d4797def8f 100644 --- a/source/blender/imbuf/intern/jpeg.c +++ b/source/blender/imbuf/intern/jpeg.c @@ -33,6 +33,8 @@ #include "BKE_idprop.h" +#include "DNA_ID.h" /* ID property definitions. */ + #include "IMB_filetype.h" #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" diff --git a/source/blender/imbuf/intern/metadata.c b/source/blender/imbuf/intern/metadata.c index 28f09c38a96..d8abd3411cb 100644 --- a/source/blender/imbuf/intern/metadata.c +++ b/source/blender/imbuf/intern/metadata.c @@ -29,6 +29,8 @@ #include "BKE_idprop.h" +#include "DNA_ID.h" /* ID property definitions. */ + #include "MEM_guardedalloc.h" #include "IMB_imbuf.h" diff --git a/source/blender/imbuf/intern/png.c b/source/blender/imbuf/intern/png.c index 60fc2ac0867..561a833803d 100644 --- a/source/blender/imbuf/intern/png.c +++ b/source/blender/imbuf/intern/png.c @@ -32,6 +32,8 @@ #include "BKE_global.h" #include "BKE_idprop.h" +#include "DNA_ID.h" /* ID property definitions. */ + #include "MEM_guardedalloc.h" #include "IMB_imbuf.h" diff --git a/source/blender/io/alembic/exporter/abc_writer_hair.cc b/source/blender/io/alembic/exporter/abc_writer_hair.cc index f8d610a3659..80f2cadd08c 100644 --- a/source/blender/io/alembic/exporter/abc_writer_hair.cc +++ b/source/blender/io/alembic/exporter/abc_writer_hair.cc @@ -30,6 +30,7 @@ #include "BLI_math_geom.h" +#include "BKE_customdata.h" #include "BKE_mesh.h" #include "BKE_mesh_runtime.h" #include "BKE_particle.h" diff --git a/source/blender/io/alembic/intern/alembic_capi.cc b/source/blender/io/alembic/intern/alembic_capi.cc index c9eefbf9039..ad5a258f80c 100644 --- a/source/blender/io/alembic/intern/alembic_capi.cc +++ b/source/blender/io/alembic/intern/alembic_capi.cc @@ -35,6 +35,7 @@ #include "MEM_guardedalloc.h" #include "DNA_cachefile_types.h" +#include "DNA_collection_types.h" #include "DNA_curve_types.h" #include "DNA_modifier_types.h" #include "DNA_object_types.h" diff --git a/source/blender/makesdna/DNA_movieclip_types.h b/source/blender/makesdna/DNA_movieclip_types.h index 2b1fd546450..11cdb48edf0 100644 --- a/source/blender/makesdna/DNA_movieclip_types.h +++ b/source/blender/makesdna/DNA_movieclip_types.h @@ -24,8 +24,8 @@ #pragma once #include "DNA_ID.h" -#include "DNA_color_types.h" /* for color management */ -#include "DNA_tracking_types.h" +#include "DNA_color_types.h" /* for color management */ +#include "DNA_tracking_types.h" /* for #MovieTracking */ #ifdef __cplusplus extern "C" { diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index f6ceb2b8e6a..736ec8919b4 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -25,9 +25,8 @@ #include "DNA_ID.h" #include "DNA_listBase.h" -#include "DNA_scene_types.h" -#include "DNA_texture_types.h" -#include "DNA_vec_types.h" +#include "DNA_scene_types.h" /* for #ImageFormatData */ +#include "DNA_vec_types.h" /* for #rctf */ #ifdef __cplusplus extern "C" { @@ -352,8 +351,8 @@ typedef struct bNode { /* XXX NODE_UPDATE is a generic update flag. More fine-grained updates * might be used in the future, but currently all work the same way. */ -#define NODE_UPDATE 0xFFFF /* generic update flag (includes all others) */ -#define NODE_UPDATE_ID 1 /* associated id data block has changed */ +#define NODE_UPDATE 0xFFFF /* generic update flag (includes all others) */ +#define NODE_UPDATE_ID 1 /* associated id data block has changed */ #define NODE_UPDATE_OPERATOR 2 /* node update triggered from update operator */ /* Unique hash key for identifying node instances @@ -512,11 +511,11 @@ typedef struct bNodeTree { #define NTREE_TYPE_INIT 1 /* ntree->flag */ -#define NTREE_DS_EXPAND (1 << 0) /* for animation editors */ -#define NTREE_COM_OPENCL (1 << 1) /* use opencl */ -#define NTREE_TWO_PASS (1 << 2) /* two pass */ +#define NTREE_DS_EXPAND (1 << 0) /* for animation editors */ +#define NTREE_COM_OPENCL (1 << 1) /* use opencl */ +#define NTREE_TWO_PASS (1 << 2) /* two pass */ #define NTREE_COM_GROUPNODE_BUFFER (1 << 3) /* use groupnode buffers */ -#define NTREE_VIEWER_BORDER (1 << 4) /* use a border for viewer nodes */ +#define NTREE_VIEWER_BORDER (1 << 4) /* use a border for viewer nodes */ /* NOTE: DEPRECATED, use (id->tag & LIB_TAG_LOCALIZED) instead. */ /* tree is localized copy, free when deleting node groups */ @@ -1097,7 +1096,7 @@ typedef struct NodeAttributeMix { #define NODE_IES_EXTERNAL 1 /* frame node flags */ -#define NODE_FRAME_SHRINK 1 /* keep the bounding box minimal */ +#define NODE_FRAME_SHRINK 1 /* keep the bounding box minimal */ #define NODE_FRAME_RESIZEABLE 2 /* test flag, if frame can be resized by user */ /* proxy node flags */ diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 06f7f7aafb4..3d14cb4df96 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -33,15 +33,10 @@ #define USE_SETSCENE_CHECK #include "DNA_ID.h" -#include "DNA_collection_types.h" -#include "DNA_color_types.h" /* color management */ -#include "DNA_curveprofile_types.h" +#include "DNA_color_types.h" /* color management */ #include "DNA_customdata_types.h" /* Scene's runtime cddata masks. */ -#include "DNA_freestyle_types.h" #include "DNA_layer_types.h" #include "DNA_listBase.h" -#include "DNA_material_types.h" -#include "DNA_userdef_types.h" #include "DNA_vec_types.h" #include "DNA_view3d_types.h" @@ -487,7 +482,7 @@ typedef struct ImageFormatData { #define R_IMF_IMTYPE_INVALID 255 /* ImageFormatData.flag */ -#define R_IMF_FLAG_ZBUF (1 << 0) /* was R_OPENEXR_ZBUF */ +#define R_IMF_FLAG_ZBUF (1 << 0) /* was R_OPENEXR_ZBUF */ #define R_IMF_FLAG_PREVIEW_JPG (1 << 1) /* was R_PREVIEW_JPG */ /* return values from BKE_imtype_valid_depths, note this is depts per channel */ @@ -529,8 +524,8 @@ typedef enum eImageFormatDepth { /* ImageFormatData.jp2_flag */ #define R_IMF_JP2_FLAG_YCC (1 << 0) /* when disabled use RGB */ /* was R_JPEG2K_YCC */ -#define R_IMF_JP2_FLAG_CINE_PRESET (1 << 1) /* was R_JPEG2K_CINE_PRESET */ -#define R_IMF_JP2_FLAG_CINE_48 (1 << 2) /* was R_JPEG2K_CINE_48FPS */ +#define R_IMF_JP2_FLAG_CINE_PRESET (1 << 1) /* was R_JPEG2K_CINE_PRESET */ +#define R_IMF_JP2_FLAG_CINE_48 (1 << 2) /* was R_JPEG2K_CINE_48FPS */ /* ImageFormatData.jp2_codec */ #define R_IMF_JP2_CODEC_JP2 0 @@ -1782,7 +1777,7 @@ typedef struct Scene { ListBase view_layers; /* Not an actual datablock, but memory owned by scene. */ - Collection *master_collection; + struct Collection *master_collection; struct SceneCollection *collection DNA_DEPRECATED; /** Settings to be override by workspaces. */ @@ -1829,12 +1824,12 @@ typedef struct Scene { #define R_MODE_UNUSED_20 (1 << 20) /* cleared */ #define R_MODE_UNUSED_21 (1 << 21) /* cleared */ -#define R_NO_OVERWRITE (1 << 22) /* skip existing files */ -#define R_TOUCH (1 << 23) /* touch files before rendering */ +#define R_NO_OVERWRITE (1 << 22) /* skip existing files */ +#define R_TOUCH (1 << 23) /* touch files before rendering */ #define R_SIMPLIFY (1 << 24) -#define R_EDGE_FRS (1 << 25) /* R_EDGE reserved for Freestyle */ +#define R_EDGE_FRS (1 << 25) /* R_EDGE reserved for Freestyle */ #define R_PERSISTENT_DATA (1 << 26) /* keep data around for re-render */ -#define R_MODE_UNUSED_27 (1 << 27) /* cleared */ +#define R_MODE_UNUSED_27 (1 << 27) /* cleared */ /** #RenderData.seq_flag */ enum { diff --git a/source/blender/makesdna/DNA_sequence_types.h b/source/blender/makesdna/DNA_sequence_types.h index e21f3e1e706..59e5e9df9ee 100644 --- a/source/blender/makesdna/DNA_sequence_types.h +++ b/source/blender/makesdna/DNA_sequence_types.h @@ -33,9 +33,8 @@ #include "DNA_color_types.h" #include "DNA_defs.h" #include "DNA_listBase.h" -#include "DNA_session_uuid_types.h" -#include "DNA_vec_types.h" -#include "DNA_vfont_types.h" +#include "DNA_session_uuid_types.h" /* for #SessionUUID */ +#include "DNA_vec_types.h" /* for #rctf */ #ifdef __cplusplus extern "C" { @@ -44,6 +43,7 @@ extern "C" { struct Ipo; struct MovieClip; struct Scene; +struct VFont; struct bSound; /* strlens; 256= FILE_MAXFILE, 768= FILE_MAXDIR */ @@ -338,7 +338,7 @@ typedef struct GaussianBlurVars { typedef struct TextVars { char text[512]; - VFont *text_font; + struct VFont *text_font; int text_blf_id; int text_size; float color[4], shadow_color[4], box_color[4]; diff --git a/source/blender/makesdna/DNA_windowmanager_types.h b/source/blender/makesdna/DNA_windowmanager_types.h index a7ad18d7cf3..f07af2c14a0 100644 --- a/source/blender/makesdna/DNA_windowmanager_types.h +++ b/source/blender/makesdna/DNA_windowmanager_types.h @@ -24,10 +24,8 @@ #pragma once #include "DNA_listBase.h" -#include "DNA_screen_types.h" -#include "DNA_userdef_types.h" -#include "DNA_vec_types.h" -#include "DNA_xr_types.h" +#include "DNA_screen_types.h" /* for #ScrAreaMap */ +#include "DNA_xr_types.h" /* for #XrSessionSettings */ #include "DNA_ID.h" diff --git a/source/blender/makesdna/DNA_workspace_types.h b/source/blender/makesdna/DNA_workspace_types.h index edca887639e..c5c2351c718 100644 --- a/source/blender/makesdna/DNA_workspace_types.h +++ b/source/blender/makesdna/DNA_workspace_types.h @@ -22,7 +22,7 @@ #pragma once -#include "DNA_scene_types.h" +#include "DNA_ID.h" #ifdef __cplusplus extern "C" { diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index b03df1a82f3..4262d5590c8 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -5808,7 +5808,7 @@ ID *RNA_find_real_ID_and_path(Main *bmain, ID *id, const char **r_path) if (r_path) { *r_path = "collection"; } - return (ID *)BKE_collection_master_scene_search(bmain, (Collection *)id); + return (ID *)BKE_collection_master_scene_search(bmain, (struct Collection *)id); default: return NULL; diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c index b5ce7976fd8..08c655d493c 100644 --- a/source/blender/makesrna/intern/rna_brush.c +++ b/source/blender/makesrna/intern/rna_brush.c @@ -22,6 +22,7 @@ #include "DNA_brush_types.h" #include "DNA_gpencil_types.h" +#include "DNA_material_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" #include "DNA_texture_types.h" diff --git a/source/blender/makesrna/intern/rna_object_force.c b/source/blender/makesrna/intern/rna_object_force.c index 58f0502ab34..12fd2b78d91 100644 --- a/source/blender/makesrna/intern/rna_object_force.c +++ b/source/blender/makesrna/intern/rna_object_force.c @@ -21,6 +21,7 @@ #include #include "DNA_cloth_types.h" +#include "DNA_dynamicpaint_types.h" #include "DNA_fluid_types.h" #include "DNA_object_force_types.h" #include "DNA_object_types.h" diff --git a/source/blender/modifiers/intern/MOD_cloth.c b/source/blender/modifiers/intern/MOD_cloth.c index ac8f1ffed18..a25d65347c5 100644 --- a/source/blender/modifiers/intern/MOD_cloth.c +++ b/source/blender/modifiers/intern/MOD_cloth.c @@ -33,6 +33,7 @@ #include "DNA_defaults.h" #include "DNA_key_types.h" #include "DNA_mesh_types.h" +#include "DNA_object_force_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" diff --git a/source/blender/modifiers/intern/MOD_collision.c b/source/blender/modifiers/intern/MOD_collision.c index 7db0706c706..a80bac7c6de 100644 --- a/source/blender/modifiers/intern/MOD_collision.c +++ b/source/blender/modifiers/intern/MOD_collision.c @@ -23,6 +23,7 @@ #include "BLI_utildefines.h" +#include "BLI_kdopbvh.h" #include "BLI_math.h" #include "BLT_translation.h" @@ -30,6 +31,7 @@ #include "DNA_defaults.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" +#include "DNA_object_force_types.h" #include "DNA_object_types.h" #include "DNA_screen_types.h" diff --git a/source/blender/modifiers/intern/MOD_nodes.cc b/source/blender/modifiers/intern/MOD_nodes.cc index 657fbb7e7f1..6bb747fa715 100644 --- a/source/blender/modifiers/intern/MOD_nodes.cc +++ b/source/blender/modifiers/intern/MOD_nodes.cc @@ -33,6 +33,7 @@ #include "BLI_string.h" #include "BLI_utildefines.h" +#include "DNA_collection_types.h" #include "DNA_defaults.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" diff --git a/source/blender/modifiers/intern/MOD_shapekey.c b/source/blender/modifiers/intern/MOD_shapekey.c index 5d2e19eb2d2..81a0ee72496 100644 --- a/source/blender/modifiers/intern/MOD_shapekey.c +++ b/source/blender/modifiers/intern/MOD_shapekey.c @@ -27,6 +27,7 @@ #include "DNA_key_types.h" #include "DNA_mesh_types.h" +#include "DNA_object_types.h" #include "BKE_key.h" #include "BKE_particle.h" diff --git a/source/blender/modifiers/intern/MOD_smooth.c b/source/blender/modifiers/intern/MOD_smooth.c index e76a2baf6b6..618ccc78279 100644 --- a/source/blender/modifiers/intern/MOD_smooth.c +++ b/source/blender/modifiers/intern/MOD_smooth.c @@ -32,6 +32,7 @@ #include "DNA_defaults.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" +#include "DNA_object_types.h" #include "DNA_screen_types.h" #include "BKE_context.h" diff --git a/source/blender/modifiers/intern/MOD_solidify.c b/source/blender/modifiers/intern/MOD_solidify.c index e501dc3210f..8e519a72df1 100644 --- a/source/blender/modifiers/intern/MOD_solidify.c +++ b/source/blender/modifiers/intern/MOD_solidify.c @@ -29,6 +29,7 @@ #include "DNA_defaults.h" #include "DNA_mesh_types.h" +#include "DNA_object_types.h" #include "DNA_screen_types.h" #include "BKE_context.h" diff --git a/source/blender/modifiers/intern/MOD_solidify_extrude.c b/source/blender/modifiers/intern/MOD_solidify_extrude.c index c8b357b34c8..99069919120 100644 --- a/source/blender/modifiers/intern/MOD_solidify_extrude.c +++ b/source/blender/modifiers/intern/MOD_solidify_extrude.c @@ -26,6 +26,7 @@ #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" +#include "DNA_object_types.h" #include "MEM_guardedalloc.h" diff --git a/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c b/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c index 8acf07f9181..f62980ec4fd 100644 --- a/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c +++ b/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c @@ -24,6 +24,7 @@ #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" +#include "DNA_object_types.h" #include "MEM_guardedalloc.h" diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_mix.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_mix.cc index f96bc9f9e15..2f2558a2d53 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_attribute_mix.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_mix.cc @@ -16,6 +16,8 @@ #include "BKE_material.h" +#include "DNA_material_types.h" + #include "node_geometry_util.hh" static bNodeSocketTemplate geo_node_attribute_mix_in[] = { diff --git a/source/blender/nodes/intern/node_socket.cc b/source/blender/nodes/intern/node_socket.cc index 06dd4b8c188..60c2d6c37e1 100644 --- a/source/blender/nodes/intern/node_socket.cc +++ b/source/blender/nodes/intern/node_socket.cc @@ -37,6 +37,8 @@ #include "BKE_node.h" #include "BKE_persistent_data_handle.hh" +#include "DNA_collection_types.h" + #include "RNA_access.h" #include "RNA_types.h" diff --git a/source/blender/python/generic/idprop_py_api.c b/source/blender/python/generic/idprop_py_api.c index 63fb685e66d..fd996c8a1a2 100644 --- a/source/blender/python/generic/idprop_py_api.c +++ b/source/blender/python/generic/idprop_py_api.c @@ -28,6 +28,8 @@ #include "BKE_idprop.h" +#include "DNA_ID.h" /* ID property definitions. */ + #define USE_STRING_COERCE #ifdef USE_STRING_COERCE diff --git a/source/blender/python/intern/bpy_props.c b/source/blender/python/intern/bpy_props.c index 9d69d91c8c8..354086ef4c3 100644 --- a/source/blender/python/intern/bpy_props.c +++ b/source/blender/python/intern/bpy_props.c @@ -43,6 +43,8 @@ #include "MEM_guardedalloc.h" +#include "DNA_ID.h" /* MAX_IDPROP_NAME */ + #include "../generic/py_capi_utils.h" /* initial definition of callback slots we'll probably have more than 1 */ diff --git a/source/blender/render/intern/texture_pointdensity.c b/source/blender/render/intern/texture_pointdensity.c index e2568e0a013..4254f6b0aa6 100644 --- a/source/blender/render/intern/texture_pointdensity.c +++ b/source/blender/render/intern/texture_pointdensity.c @@ -44,6 +44,7 @@ #include "BKE_colorband.h" #include "BKE_colortools.h" +#include "BKE_customdata.h" #include "BKE_deform.h" #include "BKE_lattice.h" #include "BKE_object.h" diff --git a/source/blender/sequencer/intern/effects.c b/source/blender/sequencer/intern/effects.c index ba16206ce97..8ffbc453517 100644 --- a/source/blender/sequencer/intern/effects.c +++ b/source/blender/sequencer/intern/effects.c @@ -42,6 +42,7 @@ #include "DNA_scene_types.h" #include "DNA_sequence_types.h" #include "DNA_space_types.h" +#include "DNA_vfont_types.h" #include "BKE_fcurve.h" #include "BKE_lib_id.h" diff --git a/source/blender/simulation/SIM_mass_spring.h b/source/blender/simulation/SIM_mass_spring.h index 42d7c86b539..43de8b155cf 100644 --- a/source/blender/simulation/SIM_mass_spring.h +++ b/source/blender/simulation/SIM_mass_spring.h @@ -52,7 +52,7 @@ int SIM_cloth_solve(struct Depsgraph *depsgraph, struct ClothModifierData *clmd, struct ListBase *effectors); void SIM_cloth_solver_set_positions(struct ClothModifierData *clmd); -void SIM_cloth_solver_set_volume(ClothModifierData *clmd); +void SIM_cloth_solver_set_volume(struct ClothModifierData *clmd); #ifdef __cplusplus } diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index a5d23365df3..a5b5f082c41 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -3998,7 +3998,7 @@ static const EnumPropertyItem *rna_id_itemf(bool *r_free, /* Show collection color tag icons in menus. */ if (id_type == ID_GR) { - item_tmp.icon = UI_icon_color_from_collection((Collection *)id); + item_tmp.icon = UI_icon_color_from_collection((struct Collection *)id); } RNA_enum_item_add(&item, &totitem, &item_tmp); -- cgit v1.2.3 From e995296acbd9587efbed0b7f2cbb7bde28ea00f1 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 15 Dec 2020 12:23:37 +1100 Subject: Cleanup: unused variables --- source/blender/editors/screen/screen_context.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/screen/screen_context.c b/source/blender/editors/screen/screen_context.c index 2061716f01f..fb7606d1fe5 100644 --- a/source/blender/editors/screen/screen_context.c +++ b/source/blender/editors/screen/screen_context.c @@ -649,8 +649,6 @@ static eContextResult screen_ctx_selected_editable_sequences(const bContext *C, } static eContextResult screen_ctx_selected_nla_strips(const bContext *C, bContextDataResult *result) { - wmWindow *win = CTX_wm_window(C); - Scene *scene = WM_window_get_active_scene(win); bAnimContext ac; if (ANIM_animdata_get_context(C, &ac) != 0) { ListBase anim_data = {NULL, NULL}; -- cgit v1.2.3 From 001f2c5d50b496708ef12de2c083686996b678d9 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 15 Dec 2020 12:27:16 +1100 Subject: Cleanup: spelling --- source/blender/blenkernel/intern/gpencil_geom.c | 4 ++-- source/blender/editors/gpencil/gpencil_data.c | 4 ++-- source/blender/editors/interface/interface_templates.c | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/intern/gpencil_geom.c b/source/blender/blenkernel/intern/gpencil_geom.c index df755e96216..981f5d50353 100644 --- a/source/blender/blenkernel/intern/gpencil_geom.c +++ b/source/blender/blenkernel/intern/gpencil_geom.c @@ -3282,8 +3282,8 @@ static tSampleEdge *new_sample_edge_from_sample_points(tSamplePoint *from, tSamp * Does not change the shape of the stroke. The new points will be distributed as * uniformly as possible by repeatedly subdividing the current longest edge. * - * \param gps: The stroke to be upsampled. - * \param target_number: The number of points the upsampled stroke should have. + * \param gps: The stroke to be up-sampled. + * \param target_number: The number of points the up-sampled stroke should have. * \param select: Select/Deselect the stroke. */ void BKE_gpencil_stroke_uniform_subdivide(bGPdata *gpd, diff --git a/source/blender/editors/gpencil/gpencil_data.c b/source/blender/editors/gpencil/gpencil_data.c index 093f1fa89c7..aff109eb98e 100644 --- a/source/blender/editors/gpencil/gpencil_data.c +++ b/source/blender/editors/gpencil/gpencil_data.c @@ -1332,8 +1332,8 @@ static int gpencil_merge_layer_exec(bContext *C, wmOperator *op) } /* Read all frames from merge layer and add any missing in destination layer, - * copying all previous strokes to keep the image equals. Need to do it in a separated - * loop to avoid strokes acumulation. */ + * copying all previous strokes to keep the image equals. + * Need to do it in a separated loop to avoid strokes accumulation. */ LISTBASE_FOREACH (bGPDframe *, gpf_src, &gpl_src->frames) { /* Try to find frame in destination layer hash table. */ bGPDframe *gpf_dst = BLI_ghash_lookup(gh_frames_dst, POINTER_FROM_INT(gpf_src->framenum)); diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 352afe72e76..dec2312b549 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -6173,7 +6173,7 @@ void uiTemplateList(uiLayout *layout, org_i, flt_flag); - /* Items should be able to set context pointers for the layout. But the listrow button + /* Items should be able to set context pointers for the layout. But the list-row button * swallows events, so it needs the context storage too for handlers to see it. */ but->context = uiLayoutGetContextStore(sub); -- cgit v1.2.3 From 612598acd7b8d6a75dfb60ed3487bf5342b4f586 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 15 Dec 2020 12:30:00 +1100 Subject: Cleanup: doxy comments (use colon after parameter name) Also remove colon after `\note`. --- source/blender/blenkernel/intern/armature.c | 2 +- source/blender/blenkernel/intern/constraint.c | 2 +- source/blender/blenkernel/intern/gpencil_modifier.c | 2 +- source/blender/blenkernel/intern/modifier.c | 2 +- source/blender/blenkernel/intern/nla.c | 2 +- source/blender/blenkernel/intern/text.c | 13 ++++++++----- source/blender/editors/interface/interface_templates.c | 2 +- source/blender/editors/space_outliner/outliner_tree.c | 6 +++--- 8 files changed, 17 insertions(+), 14 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index 92146082557..ced211b1926 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -2441,7 +2441,7 @@ static void pose_proxy_sync(Object *ob, Object *from, int layer_protected) } /** - * \param r_last_visited_bone_p the last bone handled by the last call to this function. + * \param r_last_visited_bone_p: The last bone handled by the last call to this function. */ static int rebuild_pose_bone( bPose *pose, Bone *bone, bPoseChannel *parchan, int counter, Bone **r_last_visited_bone_p) diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 1c17692ac36..b6f84dfc42f 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -5960,7 +5960,7 @@ static bConstraint *constraint_find_original_for_update(bConstraintOb *cob, bCon * Check whether given constraint is not local (i.e. from linked data) when the object is a library * override. * - * \param con May be NULL, in which case we consider it as a non-local constraint case. + * \param con: May be NULL, in which case we consider it as a non-local constraint case. */ bool BKE_constraint_is_nonlocal_in_liboverride(const Object *ob, const bConstraint *con) { diff --git a/source/blender/blenkernel/intern/gpencil_modifier.c b/source/blender/blenkernel/intern/gpencil_modifier.c index ac81e4a5470..1be2cba31b5 100644 --- a/source/blender/blenkernel/intern/gpencil_modifier.c +++ b/source/blender/blenkernel/intern/gpencil_modifier.c @@ -534,7 +534,7 @@ void BKE_gpencil_modifier_set_error(GpencilModifierData *md, const char *_format * Check whether given modifier is not local (i.e. from linked data) when the object is a library * override. * - * \param gmd May be NULL, in which case we consider it as a non-local modifier case. + * \param gmd: May be NULL, in which case we consider it as a non-local modifier case. */ bool BKE_gpencil_modifier_is_nonlocal_in_liboverride(const Object *ob, const GpencilModifierData *gmd) diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 418fe0a9502..ba0f59f6363 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -579,7 +579,7 @@ bool BKE_modifier_is_enabled(const struct Scene *scene, ModifierData *md, int re * Check whether given modifier is not local (i.e. from linked data) when the object is a library * override. * - * \param md May be NULL, in which case we consider it as a non-local modifier case. + * \param md: May be NULL, in which case we consider it as a non-local modifier case. */ bool BKE_modifier_is_nonlocal_in_liboverride(const Object *ob, const ModifierData *md) { diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index de0d67d386b..75230f9045c 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -1192,7 +1192,7 @@ bool BKE_nlatrack_get_bounds(NlaTrack *nlt, float bounds[2]) * Check whether given NLA track is not local (i.e. from linked data) when the object is a library * override. * - * \param nlt May be NULL, in which case we consider it as a non-local track case. + * \param nlt: May be NULL, in which case we consider it as a non-local track case. */ bool BKE_nlatrack_is_nonlocal_in_liboverride(const ID *id, const NlaTrack *nlt) { diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c index 93795af7cd7..9ef2e818293 100644 --- a/source/blender/blenkernel/intern/text.c +++ b/source/blender/blenkernel/intern/text.c @@ -459,12 +459,14 @@ bool BKE_text_reload(Text *text) return true; } -/** Load a text file. +/** + * Load a text file. * - * \param is_internal If \a true, this text data-block only exists in memory, not as a file on - * disk. + * \param is_internal: If \a true, this text data-block only exists in memory, + * not as a file on disk. * - * \note: text data-blocks have no user by default, only the 'real user' flag. */ + * \note text data-blocks have no user by default, only the 'real user' flag. + */ Text *BKE_text_load_ex(Main *bmain, const char *file, const char *relpath, const bool is_internal) { unsigned char *buffer; @@ -520,7 +522,8 @@ Text *BKE_text_load_ex(Main *bmain, const char *file, const char *relpath, const /** Load a text file. * - * \note: text data-blocks have no user by default, only the 'real user' flag. */ + * \note Text data-blocks have no user by default, only the 'real user' flag. + */ Text *BKE_text_load(Main *bmain, const char *file, const char *relpath) { return BKE_text_load_ex(bmain, file, relpath, false); diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index dec2312b549..b895f1702f4 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -2014,7 +2014,7 @@ static void set_constraint_expand_flag(const bContext *UNUSED(C), Panel *panel, /** * Function with void * argument for #uiListPanelIDFromDataFunc. * - * \note: Constraint panel types are assumed to be named with the struct name field + * \note Constraint panel types are assumed to be named with the struct name field * concatenated to the defined prefix. */ static void object_constraint_panel_id(void *md_link, char *r_name) diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c index 7308b161d18..56eedcd3748 100644 --- a/source/blender/editors/space_outliner/outliner_tree.c +++ b/source/blender/editors/space_outliner/outliner_tree.c @@ -908,9 +908,9 @@ static void outliner_add_id_contents(SpaceOutliner *space_outliner, /** * TODO: this function needs to be split up! It's getting a bit too large... * - * \note: "ID" is not always a real ID - * \note: If child items are only added to the tree if the item is open, the TSE_ type _must_ be - * added to #outliner_element_needs_rebuild_on_open_change(). + * \note "ID" is not always a real ID. + * \note If child items are only added to the tree if the item is open, + * the `TSE_` type _must_ be added to #outliner_element_needs_rebuild_on_open_change(). */ TreeElement *outliner_add_element(SpaceOutliner *space_outliner, ListBase *lb, -- cgit v1.2.3 From a05d98884a3b0dae46c934c92c336b0b5d210dce Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 15 Dec 2020 12:41:44 +1100 Subject: RNA: disallow negative fcurve data-path array index --- source/blender/makesdna/DNA_anim_types.h | 7 ++++++- source/blender/makesrna/intern/rna_fcurve.c | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'source/blender') diff --git a/source/blender/makesdna/DNA_anim_types.h b/source/blender/makesdna/DNA_anim_types.h index bfc72fdd45c..1eafa655195 100644 --- a/source/blender/makesdna/DNA_anim_types.h +++ b/source/blender/makesdna/DNA_anim_types.h @@ -612,7 +612,12 @@ typedef struct FCurve { char _pad[3]; /* RNA - data link */ - /** When the RNA property from `rna_path` is an array, use this to access the array index. */ + /** + * When the RNA property from `rna_path` is an array, use this to access the array index. + * + * \note This may be negative (as it wasn't prevented in 2.91 and older). + * Currently it silently fails to resolve the data-path in this case. + */ int array_index; /** * RNA-path to resolve data-access, see: #RNA_path_resolve_property. diff --git a/source/blender/makesrna/intern/rna_fcurve.c b/source/blender/makesrna/intern/rna_fcurve.c index 8734984d4e1..475b4d33936 100644 --- a/source/blender/makesrna/intern/rna_fcurve.c +++ b/source/blender/makesrna/intern/rna_fcurve.c @@ -2341,7 +2341,7 @@ static void rna_def_fcurve(BlenderRNA *brna) RNA_def_property_update(prop, NC_ANIMATION, "rna_FCurve_update_data_relations"); /* called 'index' when given as function arg */ - prop = RNA_def_property(srna, "array_index", PROP_INT, PROP_NONE); + prop = RNA_def_property(srna, "array_index", PROP_INT, PROP_UNSIGNED); RNA_def_property_ui_text( prop, "RNA Array Index", "Index to the specific property affected by F-Curve if applicable"); /* XXX need an update callback for this so that animation gets evaluated */ -- cgit v1.2.3 From e035d7301c8c6fc1bb42110054101b00d190d1f9 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 15 Dec 2020 16:11:41 +1100 Subject: Fix crash sliding effect sequence strips Off by one error in array access. --- source/blender/editors/space_sequencer/sequencer_edit.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c index 93b17830c0f..953a77d22a6 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.c +++ b/source/blender/editors/space_sequencer/sequencer_edit.c @@ -537,7 +537,7 @@ static int slip_add_sequences_recursive( for (seq = seqbasep->first; seq; seq = seq->next) { if (!do_trim || (!(seq->type & SEQ_TYPE_EFFECT) && (seq->flag & SELECT))) { seq_array[offset + num_items] = seq; - trim[offset + num_items] = do_trim; + trim[offset + num_items] = do_trim && ((seq->type & SEQ_TYPE_EFFECT) == 0); num_items++; if (seq->type == SEQ_TYPE_META) { @@ -545,9 +545,6 @@ static int slip_add_sequences_recursive( num_items += slip_add_sequences_recursive( &seq->seqbase, seq_array, trim, num_items + offset, false); } - else if (seq->type & SEQ_TYPE_EFFECT) { - trim[offset + num_items] = false; - } } } -- cgit v1.2.3 From 12792ee70cd87ce4495a62cb89fd37b95be11917 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 15 Dec 2020 18:07:12 +1100 Subject: Fix T83788: Topology mirror crashes for vertices aren't mirrored Caused by da8dc204bd062b2712869cf2709d2530915249b5 --- source/blender/editors/mesh/editmesh_utils.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c index 6467df0e87b..94f386e08d5 100644 --- a/source/blender/editors/mesh/editmesh_utils.c +++ b/source/blender/editors/mesh/editmesh_utils.c @@ -1139,8 +1139,10 @@ void EDBM_verts_mirror_cache_begin_ex(BMEditMesh *em, if (use_topology) { v_mirr = cache_mirr_intptr_as_bmvert(mesh_topo_store.index_lookup, i); - if (respecthide && BM_elem_flag_test(v_mirr, BM_ELEM_HIDDEN)) { - v_mirr = NULL; + if (v_mirr != NULL) { + if (respecthide && BM_elem_flag_test(v_mirr, BM_ELEM_HIDDEN)) { + v_mirr = NULL; + } } } else { -- cgit v1.2.3 From 35368e8bfc5f9811f3a519b2262124ebe9ccf9e0 Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Tue, 15 Dec 2020 11:15:01 +0100 Subject: Fix: mattes of cryptomatte node lost after write Fix an issue introduced by {f4df036bc497} where the read/write code missed to store and read the mattes from its new location. --- source/blender/blenkernel/intern/node.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source/blender') diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index a9a1740f4a8..75f2fca1096 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -494,6 +494,9 @@ void ntreeBlendWrite(BlendWriter *writer, bNodeTree *ntree) if (nc->matte_id) { BLO_write_string(writer, nc->matte_id); } + LISTBASE_FOREACH (CryptomatteEntry *, entry, &nc->entries) { + BLO_write_struct(writer, CryptomatteEntry, entry); + } BLO_write_struct_by_name(writer, node->typeinfo->storagename, node->storage); } else if (node->typeinfo != &NodeTypeUndefined) { @@ -646,6 +649,7 @@ void ntreeBlendReadData(BlendDataReader *reader, bNodeTree *ntree) case CMP_NODE_CRYPTOMATTE: { NodeCryptomatte *nc = (NodeCryptomatte *)node->storage; BLO_read_data_address(reader, &nc->matte_id); + BLO_read_list(reader, &nc->entries); break; } case TEX_NODE_IMAGE: { -- cgit v1.2.3 From 1b130f17c9b2b82177b02f64d7e9189ff175f28c Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Tue, 15 Dec 2020 12:01:45 +0100 Subject: Cleanup: make format --- source/blender/blenkernel/BKE_layer.h | 4 ++-- source/blender/blenkernel/intern/softbody.c | 2 +- source/blender/makesdna/DNA_node_types.h | 14 +++++++------- source/blender/makesdna/DNA_scene_types.h | 14 +++++++------- 4 files changed, 17 insertions(+), 17 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/BKE_layer.h b/source/blender/blenkernel/BKE_layer.h index aa95ac2a8cf..240d6cb18ec 100644 --- a/source/blender/blenkernel/BKE_layer.h +++ b/source/blender/blenkernel/BKE_layer.h @@ -28,9 +28,9 @@ extern "C" { #endif -#define TODO_LAYER_OVERRIDE /* CollectionOverride */ +#define TODO_LAYER_OVERRIDE /* CollectionOverride */ #define TODO_LAYER_OPERATORS /* collection mamanger and property panel operators */ -#define TODO_LAYER /* generic todo */ +#define TODO_LAYER /* generic todo */ struct Base; struct BlendDataReader; diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c index cf02dd4d160..736acd76dfd 100644 --- a/source/blender/blenkernel/intern/softbody.c +++ b/source/blender/blenkernel/intern/softbody.c @@ -150,7 +150,7 @@ typedef struct SB_thread_context { #define BSF_INTERSECT 1 /* edge intersects collider face */ /* private definitions for bodypoint states */ -#define SBF_DOFUZZY 1 /* Bodypoint do fuzzy */ +#define SBF_DOFUZZY 1 /* Bodypoint do fuzzy */ #define SBF_OUTOFCOLLISION 2 /* Bodypoint does not collide */ #define BFF_INTERSECT 1 /* collider edge intrudes face */ diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 736ec8919b4..d512d8ffe34 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -351,8 +351,8 @@ typedef struct bNode { /* XXX NODE_UPDATE is a generic update flag. More fine-grained updates * might be used in the future, but currently all work the same way. */ -#define NODE_UPDATE 0xFFFF /* generic update flag (includes all others) */ -#define NODE_UPDATE_ID 1 /* associated id data block has changed */ +#define NODE_UPDATE 0xFFFF /* generic update flag (includes all others) */ +#define NODE_UPDATE_ID 1 /* associated id data block has changed */ #define NODE_UPDATE_OPERATOR 2 /* node update triggered from update operator */ /* Unique hash key for identifying node instances @@ -511,11 +511,11 @@ typedef struct bNodeTree { #define NTREE_TYPE_INIT 1 /* ntree->flag */ -#define NTREE_DS_EXPAND (1 << 0) /* for animation editors */ -#define NTREE_COM_OPENCL (1 << 1) /* use opencl */ -#define NTREE_TWO_PASS (1 << 2) /* two pass */ +#define NTREE_DS_EXPAND (1 << 0) /* for animation editors */ +#define NTREE_COM_OPENCL (1 << 1) /* use opencl */ +#define NTREE_TWO_PASS (1 << 2) /* two pass */ #define NTREE_COM_GROUPNODE_BUFFER (1 << 3) /* use groupnode buffers */ -#define NTREE_VIEWER_BORDER (1 << 4) /* use a border for viewer nodes */ +#define NTREE_VIEWER_BORDER (1 << 4) /* use a border for viewer nodes */ /* NOTE: DEPRECATED, use (id->tag & LIB_TAG_LOCALIZED) instead. */ /* tree is localized copy, free when deleting node groups */ @@ -1096,7 +1096,7 @@ typedef struct NodeAttributeMix { #define NODE_IES_EXTERNAL 1 /* frame node flags */ -#define NODE_FRAME_SHRINK 1 /* keep the bounding box minimal */ +#define NODE_FRAME_SHRINK 1 /* keep the bounding box minimal */ #define NODE_FRAME_RESIZEABLE 2 /* test flag, if frame can be resized by user */ /* proxy node flags */ diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 3d14cb4df96..8d43483dfe4 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -482,7 +482,7 @@ typedef struct ImageFormatData { #define R_IMF_IMTYPE_INVALID 255 /* ImageFormatData.flag */ -#define R_IMF_FLAG_ZBUF (1 << 0) /* was R_OPENEXR_ZBUF */ +#define R_IMF_FLAG_ZBUF (1 << 0) /* was R_OPENEXR_ZBUF */ #define R_IMF_FLAG_PREVIEW_JPG (1 << 1) /* was R_PREVIEW_JPG */ /* return values from BKE_imtype_valid_depths, note this is depts per channel */ @@ -524,8 +524,8 @@ typedef enum eImageFormatDepth { /* ImageFormatData.jp2_flag */ #define R_IMF_JP2_FLAG_YCC (1 << 0) /* when disabled use RGB */ /* was R_JPEG2K_YCC */ -#define R_IMF_JP2_FLAG_CINE_PRESET (1 << 1) /* was R_JPEG2K_CINE_PRESET */ -#define R_IMF_JP2_FLAG_CINE_48 (1 << 2) /* was R_JPEG2K_CINE_48FPS */ +#define R_IMF_JP2_FLAG_CINE_PRESET (1 << 1) /* was R_JPEG2K_CINE_PRESET */ +#define R_IMF_JP2_FLAG_CINE_48 (1 << 2) /* was R_JPEG2K_CINE_48FPS */ /* ImageFormatData.jp2_codec */ #define R_IMF_JP2_CODEC_JP2 0 @@ -1824,12 +1824,12 @@ typedef struct Scene { #define R_MODE_UNUSED_20 (1 << 20) /* cleared */ #define R_MODE_UNUSED_21 (1 << 21) /* cleared */ -#define R_NO_OVERWRITE (1 << 22) /* skip existing files */ -#define R_TOUCH (1 << 23) /* touch files before rendering */ +#define R_NO_OVERWRITE (1 << 22) /* skip existing files */ +#define R_TOUCH (1 << 23) /* touch files before rendering */ #define R_SIMPLIFY (1 << 24) -#define R_EDGE_FRS (1 << 25) /* R_EDGE reserved for Freestyle */ +#define R_EDGE_FRS (1 << 25) /* R_EDGE reserved for Freestyle */ #define R_PERSISTENT_DATA (1 << 26) /* keep data around for re-render */ -#define R_MODE_UNUSED_27 (1 << 27) /* cleared */ +#define R_MODE_UNUSED_27 (1 << 27) /* cleared */ /** #RenderData.seq_flag */ enum { -- cgit v1.2.3 From ef2151d73de87b3e7be631b6712283a727f8d4a6 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Tue, 15 Dec 2020 12:02:22 +0100 Subject: Fix T83776: Crashes with add-on's icon preview in menus Apparently the ID pointer can be NULL, which most code here assumes is not the case. But it's very fragile & finicky, there is one code path were it's allowed to be NULL. Add necessary NULL-checks, an assert as sanity check and a comment to note the possibility of NULL. --- source/blender/editors/render/render_preview.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c index 4466d9f434d..3c103f28d93 100644 --- a/source/blender/editors/render/render_preview.c +++ b/source/blender/editors/render/render_preview.c @@ -189,7 +189,7 @@ typedef struct IconPreview { Main *bmain; Scene *scene; void *owner; - ID *id, *id_copy; + ID *id, *id_copy; /* May be NULL! (see ICON_TYPE_PREVIEW case in #ui_icon_ensure_deferred()) */ ListBase sizes; } IconPreview; @@ -1235,6 +1235,8 @@ static void icon_preview_startjob(void *customdata, short *stop, short *do_updat ID *id = sp->id; short idtype = GS(id->name); + BLI_assert(id != NULL); + if (idtype == ID_IM) { Image *ima = (Image *)id; ImBuf *ibuf = NULL; @@ -1337,7 +1339,7 @@ static void other_id_types_preview_render(IconPreview *ip, const bool is_render = !is_deferred; /* These types don't use the ShaderPreview mess, they have their own types and functions. */ - BLI_assert(!ELEM(GS(ip->id->name), ID_OB)); + BLI_assert(!ip->id || !ELEM(GS(ip->id->name), ID_OB)); /* construct shader preview from image size and previewcustomdata */ sp->scene = ip->scene; @@ -1396,7 +1398,7 @@ static void icon_preview_startjob_all_sizes(void *customdata, continue; } - if (ELEM(GS(ip->id->name), ID_OB)) { + if (ip->id && ELEM(GS(ip->id->name), ID_OB)) { /* Much simpler than the ShaderPreview mess used for other ID types. */ object_preview_render(ip, cur_size); } -- cgit v1.2.3 From d8db5cb6003c84594f5c2f6a85a02f60bafe72c1 Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Tue, 15 Dec 2020 12:17:31 +0100 Subject: Fix: upward compatibility of cryptomatte matte id. The matte_id is stored in a different structure in 2.92. This patch will write the old matte_id field so the files can be opened correctly in older versions. --- source/blender/blenkernel/intern/node.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'source/blender') diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 75f2fca1096..87997198334 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -60,6 +60,7 @@ #include "BKE_anim_data.h" #include "BKE_animsys.h" #include "BKE_colortools.h" +#include "BKE_cryptomatte.h" #include "BKE_global.h" #include "BKE_idprop.h" #include "BKE_idtype.h" @@ -491,6 +492,10 @@ void ntreeBlendWrite(BlendWriter *writer, bNodeTree *ntree) } else if ((ntree->type == NTREE_COMPOSIT) && (node->type == CMP_NODE_CRYPTOMATTE)) { NodeCryptomatte *nc = (NodeCryptomatte *)node->storage; + /* Update the matte_id so the files can be opened in versions that don't + * use `CryptomatteEntry`. */ + MEM_SAFE_FREE(nc->matte_id); + nc->matte_id = BKE_cryptomatte_entries_to_matte_id(nc); if (nc->matte_id) { BLO_write_string(writer, nc->matte_id); } @@ -498,6 +503,7 @@ void ntreeBlendWrite(BlendWriter *writer, bNodeTree *ntree) BLO_write_struct(writer, CryptomatteEntry, entry); } BLO_write_struct_by_name(writer, node->typeinfo->storagename, node->storage); + MEM_SAFE_FREE(nc->matte_id); } else if (node->typeinfo != &NodeTypeUndefined) { BLO_write_struct_by_name(writer, node->typeinfo->storagename, node->storage); -- cgit v1.2.3 From 0d58eabee620cc534fab075764a83f5a328100c1 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Tue, 15 Dec 2020 12:42:10 +0100 Subject: Geometry Nodes: support evaluating mesh object to geometry set This implements the design proposed in T83357. The goal is to allow the geometry nodes modifier on mesh objects to output instances and potentially other geometry types. Both problems are tackled by allowing mesh objects to evaluate to a geometry set, instead of just a single mesh id data block. The geometry set can contain a mesh but also other data like instances and a point cloud. I can't say that I'm sure that this commit won't introduce bugs. Mainly the temporary object creation during rendering seems a bit brittle. BUT, we can be reasonably sure that this commit will not introduce regressions (at least not ones, that are hard to fix). This is because the code has been written in a way that minimizes changes for existing functionality. Given that we intend to hide the point cloud object for the next release, we won't even have to worry about temporary object creation for now. An important part of the technical design is to make sure that `ObjectRuntime->data_eval` contains the same data before and after this patch. This helps to make sure, that existing code paths are impacted as little as possible. Instead of fully replacing `data_eval`, there is `geometry_set_eval`, which contains all the geometry components an object evaluated to (including the data referenced by `data_eval`). For now, not much code has to be aware of `geometry_set_eval`. Mainly the depsgraph object iterator and the instances system have to know about it. Reviewers: brecht Differential Revision: https://developer.blender.org/D9851 --- source/blender/blenkernel/intern/DerivedMesh.cc | 99 +++++++++++++++++++--- source/blender/blenkernel/intern/pointcloud.cc | 32 ++++++- .../depsgraph/intern/depsgraph_query_iter.cc | 22 ++++- source/blender/makesdna/DNA_object_types.h | 11 ++- 4 files changed, 143 insertions(+), 21 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/intern/DerivedMesh.cc b/source/blender/blenkernel/intern/DerivedMesh.cc index 78d4ad6fe19..b8219dcf7ac 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.cc +++ b/source/blender/blenkernel/intern/DerivedMesh.cc @@ -50,6 +50,7 @@ #include "BKE_colorband.h" #include "BKE_deform.h" #include "BKE_editmesh.h" +#include "BKE_geometry_set.hh" #include "BKE_key.h" #include "BKE_layer.h" #include "BKE_lib_id.h" @@ -881,6 +882,56 @@ void BKE_mesh_wrapper_deferred_finalize(Mesh *me_eval, BLI_assert(me_eval->runtime.wrapper_type_finalize == 0); } +/** + * Modifies the given mesh and geometry set. The geometry set is expect to have NO mesh component. + * After this function ends, the geometry set will still have NO mesh component. Instead, an input + * mesh is passed separately and is returned separately. + * + * The purpose of the geometry set is to store all non-mesh geometry components that are generated + * by modifiers. + */ +static Mesh *modifier_modify_mesh_and_geometry_set(ModifierData *md, + const ModifierEvalContext &mectx, + Object *ob, + Mesh *input_mesh, + GeometrySet &geometry_set) +{ + Mesh *mesh_output = nullptr; + const ModifierTypeInfo *mti = BKE_modifier_get_info((ModifierType)md->type); + if (mti->modifyGeometrySet == nullptr) { + mesh_output = BKE_modifier_modify_mesh(md, &mectx, input_mesh); + } + else { + /* For performance reasons, this should be called by the modifier and/or nodes themselves at + * some point. */ + BKE_mesh_wrapper_ensure_mdata(input_mesh); + + /* Adds a new mesh component to the geometry set based on the #input_mesh. */ + BLI_assert(!geometry_set.has()); + MeshComponent &mesh_component = geometry_set.get_component_for_write(); + mesh_component.replace(input_mesh, GeometryOwnershipType::Editable); + mesh_component.copy_vertex_group_names_from_object(*ob); + + /* Let the modifier change the geometry set. */ + mti->modifyGeometrySet(md, &mectx, &geometry_set); + + /* Release the mesh from the geometry set again. */ + if (geometry_set.has()) { + MeshComponent &mesh_component = geometry_set.get_component_for_write(); + mesh_output = mesh_component.release(); + geometry_set.remove(); + } + + /* Return an empty mesh instead of null. */ + if (mesh_output == nullptr) { + mesh_output = BKE_mesh_new_nomain(0, 0, 0, 0, 0); + BKE_mesh_copy_settings(mesh_output, input_mesh); + } + } + + return mesh_output; +} + static void mesh_calc_modifiers(struct Depsgraph *depsgraph, Scene *scene, Object *ob, @@ -892,7 +943,8 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph, const bool allow_shared_mesh, /* return args */ Mesh **r_deform, - Mesh **r_final) + Mesh **r_final, + GeometrySet **r_geometry_set) { /* Input and final mesh. Final mesh is only created the moment the first * constructive modifier is executed, or a deform modifier needs normals @@ -900,6 +952,8 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph, Mesh *mesh_input = (Mesh *)ob->data; Mesh *mesh_final = nullptr; Mesh *mesh_deform = nullptr; + /* This geometry set contains the non-mesh data that might be generated by modifiers. */ + GeometrySet geometry_set_final; BLI_assert((mesh_input->id.tag & LIB_TAG_COPIED_ON_WRITE_EVAL_RESULT) == 0); /* Deformed vertex locations array. Deform only modifier need this type of @@ -1197,7 +1251,8 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph, } } - Mesh *mesh_next = BKE_modifier_modify_mesh(md, &mectx, mesh_final); + Mesh *mesh_next = modifier_modify_mesh_and_geometry_set( + md, mectx, ob, mesh_final, geometry_set_final); ASSERT_IS_VALID_MESH(mesh_next); if (mesh_next) { @@ -1375,6 +1430,9 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph, if (r_deform) { *r_deform = mesh_deform; } + if (r_geometry_set) { + *r_geometry_set = new GeometrySet(std::move(geometry_set_final)); + } } float (*editbmesh_vert_coords_alloc(BMEditMesh *em, int *r_vert_len))[3] @@ -1483,7 +1541,8 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph, const CustomData_MeshMasks *dataMask, /* return args */ Mesh **r_cage, - Mesh **r_final) + Mesh **r_final, + GeometrySet **r_geometry_set) { /* Input and final mesh. Final mesh is only created the moment the first * constructive modifier is executed, or a deform modifier needs normals @@ -1491,6 +1550,8 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph, Mesh *mesh_input = (Mesh *)ob->data; Mesh *mesh_final = nullptr; Mesh *mesh_cage = nullptr; + /* This geometry set contains the non-mesh data that might be generated by modifiers. */ + GeometrySet geometry_set_final; /* Deformed vertex locations array. Deform only modifier need this type of * float array rather than MVert*. Tracked along with mesh_final as an @@ -1655,7 +1716,8 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph, } } - Mesh *mesh_next = BKE_modifier_modify_mesh(md, &mectx, mesh_final); + Mesh *mesh_next = modifier_modify_mesh_and_geometry_set( + md, mectx, ob, mesh_final, geometry_set_final); ASSERT_IS_VALID_MESH(mesh_next); if (mesh_next) { @@ -1757,6 +1819,9 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph, if (r_cage) { *r_cage = mesh_cage; } + if (r_geometry_set) { + *r_geometry_set = new GeometrySet(std::move(geometry_set_final)); + } } static void mesh_build_extra_data(struct Depsgraph *depsgraph, Object *ob, Mesh *mesh_eval) @@ -1803,6 +1868,7 @@ static void mesh_build_data(struct Depsgraph *depsgraph, #endif Mesh *mesh_eval = nullptr, *mesh_deform_eval = nullptr; + GeometrySet *geometry_set_eval = nullptr; mesh_calc_modifiers(depsgraph, scene, ob, @@ -1813,7 +1879,8 @@ static void mesh_build_data(struct Depsgraph *depsgraph, true, true, &mesh_deform_eval, - &mesh_eval); + &mesh_eval, + &geometry_set_eval); /* The modifier stack evaluation is storing result in mesh->runtime.mesh_eval, but this result * is not guaranteed to be owned by object. @@ -1825,6 +1892,12 @@ static void mesh_build_data(struct Depsgraph *depsgraph, const bool is_mesh_eval_owned = (mesh_eval != mesh->runtime.mesh_eval); BKE_object_eval_assign_data(ob, &mesh_eval->id, is_mesh_eval_owned); + /* Add the final mesh as read-only non-owning component to the geometry set. */ + BLI_assert(!geometry_set_eval->has()); + MeshComponent &mesh_component = geometry_set_eval->get_component_for_write(); + mesh_component.replace(mesh_eval, GeometryOwnershipType::ReadOnly); + ob->runtime.geometry_set_eval = geometry_set_eval; + ob->runtime.mesh_deform_eval = mesh_deform_eval; ob->runtime.last_data_mask = *dataMask; ob->runtime.last_need_mapping = need_mapping; @@ -1864,11 +1937,14 @@ static void editbmesh_build_data(struct Depsgraph *depsgraph, Mesh *me_cage; Mesh *me_final; + GeometrySet *non_mesh_components; - editbmesh_calc_modifiers(depsgraph, scene, obedit, em, dataMask, &me_cage, &me_final); + editbmesh_calc_modifiers( + depsgraph, scene, obedit, em, dataMask, &me_cage, &me_final, &non_mesh_components); em->mesh_eval_final = me_final; em->mesh_eval_cage = me_cage; + obedit->runtime.geometry_set_eval = non_mesh_components; BKE_object_boundbox_calc_from_mesh(obedit, em->mesh_eval_final); @@ -2020,7 +2096,8 @@ Mesh *mesh_create_eval_final(Depsgraph *depsgraph, { Mesh *final; - mesh_calc_modifiers(depsgraph, scene, ob, 1, false, dataMask, -1, false, false, nullptr, &final); + mesh_calc_modifiers( + depsgraph, scene, ob, 1, false, dataMask, -1, false, false, nullptr, &final, nullptr); return final; } @@ -2034,7 +2111,7 @@ Mesh *mesh_create_eval_final_index_render(Depsgraph *depsgraph, Mesh *final; mesh_calc_modifiers( - depsgraph, scene, ob, 1, false, dataMask, index, false, false, nullptr, &final); + depsgraph, scene, ob, 1, false, dataMask, index, false, false, nullptr, &final, nullptr); return final; } @@ -2046,7 +2123,8 @@ Mesh *mesh_create_eval_no_deform(Depsgraph *depsgraph, { Mesh *final; - mesh_calc_modifiers(depsgraph, scene, ob, 0, false, dataMask, -1, false, false, nullptr, &final); + mesh_calc_modifiers( + depsgraph, scene, ob, 0, false, dataMask, -1, false, false, nullptr, &final, nullptr); return final; } @@ -2058,7 +2136,8 @@ Mesh *mesh_create_eval_no_deform_render(Depsgraph *depsgraph, { Mesh *final; - mesh_calc_modifiers(depsgraph, scene, ob, 0, false, dataMask, -1, false, false, nullptr, &final); + mesh_calc_modifiers( + depsgraph, scene, ob, 0, false, dataMask, -1, false, false, nullptr, &final, nullptr); return final; } diff --git a/source/blender/blenkernel/intern/pointcloud.cc b/source/blender/blenkernel/intern/pointcloud.cc index b4a9ad73048..7bd14e80333 100644 --- a/source/blender/blenkernel/intern/pointcloud.cc +++ b/source/blender/blenkernel/intern/pointcloud.cc @@ -371,6 +371,25 @@ static void pointcloud_evaluate_modifiers(struct Depsgraph *depsgraph, } } +static PointCloud *take_pointcloud_ownership_from_geometry_set(GeometrySet &geometry_set) +{ + if (!geometry_set.has()) { + return nullptr; + } + PointCloudComponent &pointcloud_component = + geometry_set.get_component_for_write(); + PointCloud *pointcloud = pointcloud_component.release(); + if (pointcloud != nullptr) { + /* Add back, but as read-only non-owning component. */ + pointcloud_component.replace(pointcloud, GeometryOwnershipType::ReadOnly); + } + else { + /* The component was empty, we can also remove it. */ + geometry_set.remove(); + } + return pointcloud; +} + void BKE_pointcloud_data_update(struct Depsgraph *depsgraph, struct Scene *scene, Object *object) { /* Free any evaluated data and restore original data. */ @@ -382,10 +401,17 @@ void BKE_pointcloud_data_update(struct Depsgraph *depsgraph, struct Scene *scene GeometryOwnershipType::ReadOnly); pointcloud_evaluate_modifiers(depsgraph, scene, object, geometry_set); + PointCloud *pointcloud_eval = take_pointcloud_ownership_from_geometry_set(geometry_set); + + /* If the geometry set did not contain a point cloud, we still create an empty one. */ + if (pointcloud_eval == nullptr) { + pointcloud_eval = BKE_pointcloud_new_nomain(0); + } + /* Assign evaluated object. */ - PointCloud *dummy_pointcloud = BKE_pointcloud_new_nomain(0); - BKE_object_eval_assign_data(object, &dummy_pointcloud->id, true); - object->runtime.geometry_set_eval = new GeometrySet(geometry_set); + const bool eval_is_owned = pointcloud_eval != pointcloud; + BKE_object_eval_assign_data(object, &pointcloud_eval->id, eval_is_owned); + object->runtime.geometry_set_eval = new GeometrySet(std::move(geometry_set)); } /* Draw Cache */ diff --git a/source/blender/depsgraph/intern/depsgraph_query_iter.cc b/source/blender/depsgraph/intern/depsgraph_query_iter.cc index b92bf475f49..e472d82f2ee 100644 --- a/source/blender/depsgraph/intern/depsgraph_query_iter.cc +++ b/source/blender/depsgraph/intern/depsgraph_query_iter.cc @@ -136,8 +136,8 @@ bool deg_iterator_components_step(BLI_Iterator *iter) return false; } - if (data->geometry_component_owner->type != OB_POINTCLOUD) { - /* Only point clouds support multiple geometry components currently. */ + if (data->geometry_component_owner->runtime.geometry_set_eval == nullptr) { + /* Return the object itself, if it does not have a geometry set yet. */ iter->current = data->geometry_component_owner; data->geometry_component_owner = nullptr; return true; @@ -149,10 +149,16 @@ bool deg_iterator_components_step(BLI_Iterator *iter) return false; } + /* The mesh component. */ if (data->geometry_component_id == 0) { data->geometry_component_id++; - /* The mesh component. */ + /* Don't use a temporary object for this component, when the owner is a mesh object. */ + if (data->geometry_component_owner->type == OB_MESH) { + iter->current = data->geometry_component_owner; + return true; + } + const Mesh *mesh = geometry_set->get_mesh_for_read(); if (mesh != nullptr) { Object *temp_object = &data->temp_geometry_component_object; @@ -164,10 +170,17 @@ bool deg_iterator_components_step(BLI_Iterator *iter) return true; } } + + /* The pointcloud component. */ if (data->geometry_component_id == 1) { data->geometry_component_id++; - /* The pointcloud component. */ + /* Don't use a temporary object for this component, when the owner is a point cloud object. */ + if (data->geometry_component_owner->type == OB_POINTCLOUD) { + iter->current = data->geometry_component_owner; + return true; + } + const PointCloud *pointcloud = geometry_set->get_pointcloud_for_read(); if (pointcloud != nullptr) { Object *temp_object = &data->temp_geometry_component_object; @@ -179,6 +192,7 @@ bool deg_iterator_components_step(BLI_Iterator *iter) return true; } } + data->geometry_component_owner = nullptr; return false; } diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index 71f67d8a3b4..0a3a2cd0b64 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -150,14 +150,17 @@ typedef struct Object_Runtime { */ struct ID *data_orig; /** - * Object data structure created during object evaluation. - * It has all modifiers applied. + * Object data structure created during object evaluation. It has all modifiers applied. + * The type is determined by the type of the original object. For example, for mesh and curve + * objects, this is a mesh. For a volume object, this is a volume. */ struct ID *data_eval; /** - * Some objects support evaluating to a geometry set instead of a single ID. In those cases the - * evaluated geometry will be stored here instead of in #data_eval. + * Objects can evaluate to a geometry set instead of a single ID. In those cases, the evaluated + * geometry set will be stored here. An ID of the correct type is still stored in #data_eval. + * #geometry_set_eval might reference the ID pointed to by #data_eval as well, but does not own + * the data. */ struct GeometrySet *geometry_set_eval; -- cgit v1.2.3 From 82645ff739687e4d58715869778c8860e832513c Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Tue, 15 Dec 2020 13:07:02 +0100 Subject: Move Point Cloud object back to Experimental Features The geometry-nodes features no longer depend on the point cloud object. Therefore the point cloud object, although important in the future, can be postponed until we have render and edit mode fully working. This reverts commits: * ea74ed5a7a2031b614d401e394f2e0146fc90155. * dc614c68ef2c8ca8b076a000974b5a20a4145a42. --- source/blender/editors/object/CMakeLists.txt | 1 + source/blender/editors/object/object_add.c | 9 +++++++++ source/blender/editors/space_buttons/CMakeLists.txt | 1 + source/blender/editors/space_buttons/buttons_context.c | 6 ++++++ source/blender/makesdna/DNA_userdef_types.h | 2 ++ source/blender/makesrna/intern/CMakeLists.txt | 1 + source/blender/makesrna/intern/makesrna.c | 2 ++ source/blender/makesrna/intern/rna_ID.c | 6 ++++++ source/blender/makesrna/intern/rna_internal.h | 2 ++ source/blender/makesrna/intern/rna_main.c | 4 ++++ source/blender/makesrna/intern/rna_main_api.c | 6 ++++++ source/blender/makesrna/intern/rna_object.c | 4 ++++ source/blender/makesrna/intern/rna_userdef.c | 5 +++++ source/blender/modifiers/CMakeLists.txt | 1 + 14 files changed, 50 insertions(+) (limited to 'source/blender') diff --git a/source/blender/editors/object/CMakeLists.txt b/source/blender/editors/object/CMakeLists.txt index d872511ae03..77b5379ddd4 100644 --- a/source/blender/editors/object/CMakeLists.txt +++ b/source/blender/editors/object/CMakeLists.txt @@ -88,6 +88,7 @@ endif() if(WITH_EXPERIMENTAL_FEATURES) add_definitions(-DWITH_GEOMETRY_NODES) + add_definitions(-DWITH_POINT_CLOUD) add_definitions(-DWITH_HAIR_NODES) endif() diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index bbfdfb2532d..a64033bc63a 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -1714,6 +1714,9 @@ void OBJECT_OT_hair_add(wmOperatorType *ot) static bool object_pointcloud_add_poll(bContext *C) { + if (!U.experimental.use_new_point_cloud_type) { + return false; + } return ED_operator_objectmode(C); } @@ -2316,17 +2319,23 @@ static const EnumPropertyItem convert_target_items[] = { "MESH", ICON_OUTLINER_OB_MESH, "Mesh", +#ifdef WITH_POINT_CLOUD "Mesh from Curve, Surface, Metaball, Text, or Pointcloud objects"}, +#else + "Mesh from Curve, Surface, Metaball, or Text objects"}, +#endif {OB_GPENCIL, "GPENCIL", ICON_OUTLINER_OB_GREASEPENCIL, "Grease Pencil", "Grease Pencil from Curve or Mesh objects"}, +#ifdef WITH_POINT_CLOUD {OB_POINTCLOUD, "POINTCLOUD", ICON_OUTLINER_OB_POINTCLOUD, "Pointcloud", "Pointcloud from Mesh objects"}, +#endif {0, NULL, 0, NULL, NULL}, }; diff --git a/source/blender/editors/space_buttons/CMakeLists.txt b/source/blender/editors/space_buttons/CMakeLists.txt index fa3e6a51036..c71e5e49d8d 100644 --- a/source/blender/editors/space_buttons/CMakeLists.txt +++ b/source/blender/editors/space_buttons/CMakeLists.txt @@ -51,6 +51,7 @@ endif() if(WITH_EXPERIMENTAL_FEATURES) add_definitions(-DWITH_GEOMETRY_NODES) + add_definitions(-DWITH_POINT_CLOUD) add_definitions(-DWITH_HAIR_NODES) endif() diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c index 8b39995a5c9..3a2b8cf0115 100644 --- a/source/blender/editors/space_buttons/buttons_context.c +++ b/source/blender/editors/space_buttons/buttons_context.c @@ -246,9 +246,11 @@ static bool buttons_context_path_data(ButsContextPath *path, int type) return true; } #endif +#ifdef WITH_POINT_CLOUD if (RNA_struct_is_a(ptr->type, &RNA_PointCloud) && (type == -1 || type == OB_POINTCLOUD)) { return true; } +#endif if (RNA_struct_is_a(ptr->type, &RNA_Volume) && (type == -1 || type == OB_VOLUME)) { return true; } @@ -812,7 +814,9 @@ const char *buttons_context_dir[] = { #ifdef WITH_HAIR_NODES "hair", #endif +#ifdef WITH_POINT_CLOUD "pointcloud", +#endif "volume", NULL, }; @@ -899,10 +903,12 @@ int /*eContextResult*/ buttons_context(const bContext *C, return CTX_RESULT_OK; } #endif +#ifdef WITH_POINT_CLOUD if (CTX_data_equals(member, "pointcloud")) { set_pointer_type(path, result, &RNA_PointCloud); return CTX_RESULT_OK; } +#endif if (CTX_data_equals(member, "volume")) { set_pointer_type(path, result, &RNA_Volume); return CTX_RESULT_OK; diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index 90944eb2b12..8c4c43e4446 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -632,10 +632,12 @@ typedef struct UserDef_Experimental { /* The following options are automatically sanitized (set to 0) * when the release cycle is not alpha. */ char use_new_hair_type; + char use_new_point_cloud_type; char use_sculpt_vertex_colors; char use_switch_object_operator; char use_sculpt_tools_tilt; char use_object_add_tool; + char _pad[7]; /** `makesdna` does not allow empty structs. */ } UserDef_Experimental; diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt index 9aea5b26a54..3ebbb98934e 100644 --- a/source/blender/makesrna/intern/CMakeLists.txt +++ b/source/blender/makesrna/intern/CMakeLists.txt @@ -99,6 +99,7 @@ set(DEFSRC if(WITH_EXPERIMENTAL_FEATURES) add_definitions(-DWITH_GEOMETRY_NODES) + add_definitions(-DWITH_POINT_CLOUD) add_definitions(-DWITH_HAIR_NODES) list(APPEND DEFSRC rna_hair.c diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c index 9eed1fcf085..8b861d20e4e 100644 --- a/source/blender/makesrna/intern/makesrna.c +++ b/source/blender/makesrna/intern/makesrna.c @@ -4308,7 +4308,9 @@ static RNAProcessItem PROCESS_ITEMS[] = { {"rna_packedfile.c", NULL, RNA_def_packedfile}, {"rna_palette.c", NULL, RNA_def_palette}, {"rna_particle.c", NULL, RNA_def_particle}, +#ifdef WITH_POINT_CLOUD {"rna_pointcloud.c", NULL, RNA_def_pointcloud}, +#endif {"rna_pose.c", "rna_pose_api.c", RNA_def_pose}, {"rna_curveprofile.c", NULL, RNA_def_profile}, {"rna_lightprobe.c", NULL, RNA_def_lightprobe}, diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c index d0e0b69a8d5..f63cf0271b8 100644 --- a/source/blender/makesrna/intern/rna_ID.c +++ b/source/blender/makesrna/intern/rna_ID.c @@ -289,9 +289,11 @@ short RNA_type_to_ID_code(const StructRNA *type) if (base_type == &RNA_PaintCurve) { return ID_PC; } +# ifdef WITH_POINT_CLOUD if (base_type == &RNA_PointCloud) { return ID_PT; } +# endif if (base_type == &RNA_LightProbe) { return ID_LP; } @@ -397,7 +399,11 @@ StructRNA *ID_code_to_RNA_type(short idcode) case ID_PC: return &RNA_PaintCurve; case ID_PT: +# ifdef WITH_POINT_CLOUD return &RNA_PointCloud; +# else + return &RNA_ID; +# endif case ID_LP: return &RNA_LightProbe; case ID_SCE: diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h index 1c6f83efd65..d4fdac390b2 100644 --- a/source/blender/makesrna/intern/rna_internal.h +++ b/source/blender/makesrna/intern/rna_internal.h @@ -470,7 +470,9 @@ void RNA_def_main_lightprobes(BlenderRNA *brna, PropertyRNA *cprop); #ifdef WITH_HAIR_NODES void RNA_def_main_hairs(BlenderRNA *brna, PropertyRNA *cprop); #endif +#ifdef WITH_POINT_CLOUD void RNA_def_main_pointclouds(BlenderRNA *brna, PropertyRNA *cprop); +#endif void RNA_def_main_volumes(BlenderRNA *brna, PropertyRNA *cprop); #ifdef WITH_GEOMETRY_NODES void RNA_def_main_simulations(BlenderRNA *brna, PropertyRNA *cprop); diff --git a/source/blender/makesrna/intern/rna_main.c b/source/blender/makesrna/intern/rna_main.c index 0f17f8c44cd..aa22a4307d2 100644 --- a/source/blender/makesrna/intern/rna_main.c +++ b/source/blender/makesrna/intern/rna_main.c @@ -128,7 +128,9 @@ RNA_MAIN_LISTBASE_FUNCS_DEF(objects) RNA_MAIN_LISTBASE_FUNCS_DEF(paintcurves) RNA_MAIN_LISTBASE_FUNCS_DEF(palettes) RNA_MAIN_LISTBASE_FUNCS_DEF(particles) +# ifdef WITH_POINT_CLOUD RNA_MAIN_LISTBASE_FUNCS_DEF(pointclouds) +# endif RNA_MAIN_LISTBASE_FUNCS_DEF(scenes) RNA_MAIN_LISTBASE_FUNCS_DEF(screens) RNA_MAIN_LISTBASE_FUNCS_DEF(shapekeys) @@ -391,12 +393,14 @@ void RNA_def_main(BlenderRNA *brna) # ifdef WITH_HAIR_NODES {"hairs", "Hair", "rna_Main_hairs_begin", "Hairs", "Hair data-blocks", RNA_def_main_hairs}, # endif +# ifdef WITH_POINT_CLOUD {"pointclouds", "PointCloud", "rna_Main_pointclouds_begin", "Point Clouds", "Point cloud data-blocks", RNA_def_main_pointclouds}, +# endif {"volumes", "Volume", "rna_Main_volumes_begin", diff --git a/source/blender/makesrna/intern/rna_main_api.c b/source/blender/makesrna/intern/rna_main_api.c index 5fc2cce9bc6..21ff44ed253 100644 --- a/source/blender/makesrna/intern/rna_main_api.c +++ b/source/blender/makesrna/intern/rna_main_api.c @@ -678,6 +678,7 @@ static Hair *rna_Main_hairs_new(Main *bmain, const char *name) } # endif +# ifdef WITH_POINT_CLOUD static PointCloud *rna_Main_pointclouds_new(Main *bmain, const char *name) { char safe_name[MAX_ID_NAME - 2]; @@ -687,6 +688,7 @@ static PointCloud *rna_Main_pointclouds_new(Main *bmain, const char *name) id_us_min(&pointcloud->id); return pointcloud; } +# endif static Volume *rna_Main_volumes_new(Main *bmain, const char *name) { @@ -755,7 +757,9 @@ RNA_MAIN_ID_TAG_FUNCS_DEF(lightprobes, lightprobes, ID_LP) # ifdef WITH_HAIR_NODES RNA_MAIN_ID_TAG_FUNCS_DEF(hairs, hairs, ID_HA) # endif +# ifdef WITH_POINT_CLOUD RNA_MAIN_ID_TAG_FUNCS_DEF(pointclouds, pointclouds, ID_PT) +# endif RNA_MAIN_ID_TAG_FUNCS_DEF(volumes, volumes, ID_VO) # ifdef WITH_GEOMETRY_NODES RNA_MAIN_ID_TAG_FUNCS_DEF(simulations, simulations, ID_SIM) @@ -2206,6 +2210,7 @@ void RNA_def_main_hairs(BlenderRNA *brna, PropertyRNA *cprop) } # endif +# ifdef WITH_POINT_CLOUD void RNA_def_main_pointclouds(BlenderRNA *brna, PropertyRNA *cprop) { StructRNA *srna; @@ -2252,6 +2257,7 @@ void RNA_def_main_pointclouds(BlenderRNA *brna, PropertyRNA *cprop) parm = RNA_def_boolean(func, "value", 0, "Value", ""); RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); } +# endif void RNA_def_main_volumes(BlenderRNA *brna, PropertyRNA *cprop) { diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index 4e170599ee6..3e8d8e10b37 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -579,7 +579,11 @@ static StructRNA *rna_Object_data_typef(PointerRNA *ptr) return &RNA_ID; # endif case OB_POINTCLOUD: +# ifdef WITH_POINT_CLOUD return &RNA_PointCloud; +# else + return &RNA_ID; +# endif case OB_VOLUME: return &RNA_Volume; default: diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index f916c607fd9..115bc221ce1 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -6160,6 +6160,11 @@ static void rna_def_userdef_experimental(BlenderRNA *brna) "Undo Legacy", "Use legacy undo (slower than the new default one, but may be more stable in some cases)"); + prop = RNA_def_property(srna, "use_new_point_cloud_type", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "use_new_point_cloud_type", 1); + RNA_def_property_ui_text( + prop, "New Point Cloud Type", "Enable the new point cloud type in the ui"); + prop = RNA_def_property(srna, "use_new_hair_type", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "use_new_hair_type", 1); RNA_def_property_ui_text(prop, "New Hair Type", "Enable the new hair type in the ui"); diff --git a/source/blender/modifiers/CMakeLists.txt b/source/blender/modifiers/CMakeLists.txt index 60c102de515..3a7addcba94 100644 --- a/source/blender/modifiers/CMakeLists.txt +++ b/source/blender/modifiers/CMakeLists.txt @@ -199,6 +199,7 @@ endif() if(WITH_EXPERIMENTAL_FEATURES) add_definitions(-DWITH_GEOMETRY_NODES) + add_definitions(-DWITH_POINT_CLOUD) add_definitions(-DWITH_HAIR_NODES) endif() -- cgit v1.2.3 From b71eb3a105b8f7fb216a48082386215a6ea81cc4 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Fri, 11 Dec 2020 18:15:25 +0100 Subject: Asset System: Data-block asset metadata storage, reading and API Asset metadata is what turns a regular data-block into an asset. It is a small data-structure, but a key part of the technical design of the asset system. The design foresees that asset data-blocks store an `ID.asset_data` pointer of type `AssetMetaData`. This data **must not** have dependencies on other data-blocks or data-block data, it must be an independent unit. That way we can read asset-metadata from .blends without reading anything else from the file. The Asset Browser will use this metadata (together with the data-block name, preview and file path) to represent assets in the file list. Includes: * New `ID.asset_data` for asset metadata. * Asset tags, description and custom properties. * BKE code to manage asset meta-data and asset tags. * Code to read asset data from files, without reading IDs. * RNA for asset metadata (including tags) Part of the first Asset Browser milestone. Check the #asset_browser_milestone_1 project milestone on developer.blender.org. Differential Revision: https://developer.blender.org/D9716 Reviewed by: Bastien Montagne, Brecht Van Lommel --- source/blender/CMakeLists.txt | 1 + source/blender/blenkernel/BKE_asset.h | 56 ++++++ source/blender/blenkernel/CMakeLists.txt | 2 + source/blender/blenkernel/intern/asset.c | 143 ++++++++++++++ source/blender/blenkernel/intern/lib_id.c | 5 + source/blender/blenkernel/intern/lib_id_delete.c | 5 + source/blender/blenloader/BLO_readfile.h | 8 + source/blender/blenloader/intern/readblenentry.c | 45 +++++ source/blender/blenloader/intern/readfile.c | 41 +++- source/blender/blenloader/intern/readfile.h | 6 + source/blender/makesdna/DNA_ID.h | 6 + source/blender/makesdna/DNA_asset_defaults.h | 37 ++++ source/blender/makesdna/DNA_asset_types.h | 62 ++++++ source/blender/makesdna/intern/CMakeLists.txt | 1 + source/blender/makesdna/intern/dna_defaults.c | 10 +- source/blender/makesdna/intern/makesdna.c | 2 + source/blender/makesrna/RNA_access.h | 2 + source/blender/makesrna/intern/CMakeLists.txt | 1 + source/blender/makesrna/intern/makesrna.c | 1 + source/blender/makesrna/intern/rna_ID.c | 5 + source/blender/makesrna/intern/rna_asset.c | 228 +++++++++++++++++++++++ source/blender/makesrna/intern/rna_internal.h | 1 + 22 files changed, 666 insertions(+), 2 deletions(-) create mode 100644 source/blender/blenkernel/BKE_asset.h create mode 100644 source/blender/blenkernel/intern/asset.c create mode 100644 source/blender/makesdna/DNA_asset_defaults.h create mode 100644 source/blender/makesdna/DNA_asset_types.h create mode 100644 source/blender/makesrna/intern/rna_asset.c (limited to 'source/blender') diff --git a/source/blender/CMakeLists.txt b/source/blender/CMakeLists.txt index c38da14be96..efd30ba8509 100644 --- a/source/blender/CMakeLists.txt +++ b/source/blender/CMakeLists.txt @@ -23,6 +23,7 @@ set(SRC_DNA_INC ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_action_types.h ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_anim_types.h ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_armature_types.h + ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_asset_types.h ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_boid_types.h ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_brush_enums.h ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_brush_types.h diff --git a/source/blender/blenkernel/BKE_asset.h b/source/blender/blenkernel/BKE_asset.h new file mode 100644 index 00000000000..edd49dd9851 --- /dev/null +++ b/source/blender/blenkernel/BKE_asset.h @@ -0,0 +1,56 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __BKE_ASSET_H__ +#define __BKE_ASSET_H__ + +/** \file + * \ingroup bke + */ + +#include "BLI_utildefines.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct BlendWriter; +struct BlendDataReader; +struct ID; +struct PreviewImage; + +struct AssetMetaData *BKE_asset_metadata_create(void); +void BKE_asset_metadata_free(struct AssetMetaData **asset_data); + +struct AssetTagEnsureResult { + struct AssetTag *tag; + /* Set to false if a tag of this name was already present. */ + bool is_new; +}; + +struct AssetTag *BKE_asset_metadata_tag_add(struct AssetMetaData *asset_data, const char *name); +struct AssetTagEnsureResult BKE_asset_metadata_tag_ensure(struct AssetMetaData *asset_data, + const char *name); +void BKE_asset_metadata_tag_remove(struct AssetMetaData *asset_data, struct AssetTag *tag); + +void BKE_asset_metadata_write(struct BlendWriter *writer, struct AssetMetaData *asset_data); +void BKE_asset_metadata_read(struct BlendDataReader *reader, struct AssetMetaData *asset_data); + +#ifdef __cplusplus +} +#endif + +#endif /* __BKE_ASSET_H__ */ diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index d440d3e4d64..156d731d4a7 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -77,6 +77,7 @@ set(SRC intern/armature.c intern/armature_deform.c intern/armature_update.c + intern/asset.c intern/attribute.c intern/attribute_access.cc intern/autoexec.c @@ -271,6 +272,7 @@ set(SRC BKE_attribute.h BKE_attribute_access.hh BKE_autoexec.h + BKE_asset.h BKE_blender.h BKE_blender_copybuffer.h BKE_blender_undo.h diff --git a/source/blender/blenkernel/intern/asset.c b/source/blender/blenkernel/intern/asset.c new file mode 100644 index 00000000000..92400d10fe5 --- /dev/null +++ b/source/blender/blenkernel/intern/asset.c @@ -0,0 +1,143 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** \file + * \ingroup bke + */ + +#include + +#include "BLI_listbase.h" +#include "BLI_string.h" +#include "BLI_string_utils.h" +#include "BLI_utildefines.h" + +#include "BKE_asset.h" +#include "BKE_icons.h" +#include "BKE_idprop.h" + +#include "DNA_ID.h" +#include "DNA_asset_types.h" +#include "DNA_defaults.h" + +#include "BLO_read_write.h" + +#include "MEM_guardedalloc.h" + +AssetMetaData *BKE_asset_metadata_create(void) +{ + AssetMetaData *asset_data = MEM_callocN(sizeof(*asset_data), __func__); + memcpy(asset_data, DNA_struct_default_get(AssetMetaData), sizeof(*asset_data)); + return asset_data; +} + +void BKE_asset_metadata_free(AssetMetaData **asset_data) +{ + if ((*asset_data)->properties) { + IDP_FreeProperty((*asset_data)->properties); + } + MEM_SAFE_FREE((*asset_data)->description); + BLI_freelistN(&(*asset_data)->tags); + + MEM_SAFE_FREE(*asset_data); +} + +static AssetTag *asset_metadata_tag_add(AssetMetaData *asset_data, const char *const name) +{ + AssetTag *tag = MEM_callocN(sizeof(*tag), __func__); + BLI_strncpy(tag->name, name, sizeof(tag->name)); + + BLI_addtail(&asset_data->tags, tag); + asset_data->tot_tags++; + /* Invariant! */ + BLI_assert(BLI_listbase_count(&asset_data->tags) == asset_data->tot_tags); + + return tag; +} + +AssetTag *BKE_asset_metadata_tag_add(AssetMetaData *asset_data, const char *name) +{ + AssetTag *tag = asset_metadata_tag_add(asset_data, name); + BLI_uniquename(&asset_data->tags, tag, name, '.', offsetof(AssetTag, name), sizeof(tag->name)); + return tag; +} + +/** + * Make sure there is a tag with name \a name, create one if needed. + */ +struct AssetTagEnsureResult BKE_asset_metadata_tag_ensure(AssetMetaData *asset_data, + const char *name) +{ + struct AssetTagEnsureResult result = {.tag = NULL}; + if (!name[0]) { + return result; + } + + AssetTag *tag = BLI_findstring(&asset_data->tags, name, offsetof(AssetTag, name)); + + if (tag) { + result.tag = tag; + result.is_new = false; + return result; + } + + tag = asset_metadata_tag_add(asset_data, name); + + result.tag = tag; + result.is_new = true; + return result; +} + +void BKE_asset_metadata_tag_remove(AssetMetaData *asset_data, AssetTag *tag) +{ + BLI_assert(BLI_findindex(&asset_data->tags, tag) >= 0); + BLI_freelinkN(&asset_data->tags, tag); + asset_data->tot_tags--; + /* Invariant! */ + BLI_assert(BLI_listbase_count(&asset_data->tags) == asset_data->tot_tags); +} + +/* .blend file API -------------------------------------------- */ + +void BKE_asset_metadata_write(BlendWriter *writer, AssetMetaData *asset_data) +{ + BLO_write_struct(writer, AssetMetaData, asset_data); + + if (asset_data->properties) { + IDP_BlendWrite(writer, asset_data->properties); + } + + if (asset_data->description) { + BLO_write_string(writer, asset_data->description); + } + LISTBASE_FOREACH (AssetTag *, tag, &asset_data->tags) { + BLO_write_struct(writer, AssetTag, tag); + } +} + +void BKE_asset_metadata_read(BlendDataReader *reader, AssetMetaData *asset_data) +{ + /* asset_data itself has been read already. */ + + if (asset_data->properties) { + BLO_read_data_address(reader, &asset_data->properties); + IDP_BlendDataRead(reader, &asset_data->properties); + } + + BLO_read_data_address(reader, &asset_data->description); + BLO_read_list(reader, &asset_data->tags); + BLI_assert(BLI_listbase_count(&asset_data->tags) == asset_data->tot_tags); +} diff --git a/source/blender/blenkernel/intern/lib_id.c b/source/blender/blenkernel/intern/lib_id.c index 8113417b55f..61b5e6f85bb 100644 --- a/source/blender/blenkernel/intern/lib_id.c +++ b/source/blender/blenkernel/intern/lib_id.c @@ -56,6 +56,7 @@ #include "BKE_anim_data.h" #include "BKE_armature.h" +#include "BKE_asset.h" #include "BKE_bpath.h" #include "BKE_context.h" #include "BKE_global.h" @@ -2362,6 +2363,10 @@ void BKE_id_reorder(const ListBase *lb, ID *id, ID *relative, bool after) void BKE_id_blend_write(BlendWriter *writer, ID *id) { + if (id->asset_data) { + BKE_asset_metadata_write(writer, id->asset_data); + } + /* ID_WM's id->properties are considered runtime only, and never written in .blend file. */ if (id->properties && !ELEM(GS(id->name), ID_WM)) { IDP_BlendWrite(writer, id->properties); diff --git a/source/blender/blenkernel/intern/lib_id_delete.c b/source/blender/blenkernel/intern/lib_id_delete.c index 1e45a3c1163..7199bd0f13c 100644 --- a/source/blender/blenkernel/intern/lib_id_delete.c +++ b/source/blender/blenkernel/intern/lib_id_delete.c @@ -31,6 +31,7 @@ #include "BLI_listbase.h" #include "BKE_anim_data.h" +#include "BKE_asset.h" #include "BKE_idprop.h" #include "BKE_idtype.h" #include "BKE_key.h" @@ -64,6 +65,10 @@ void BKE_libblock_free_data(ID *id, const bool do_id_user) id->override_library = NULL; } + if (id->asset_data) { + BKE_asset_metadata_free(&id->asset_data); + } + BKE_animdata_free(id, do_id_user); } diff --git a/source/blender/blenloader/BLO_readfile.h b/source/blender/blenloader/BLO_readfile.h index 0ab9a5e9e14..1d7c5d8a1d3 100644 --- a/source/blender/blenloader/BLO_readfile.h +++ b/source/blender/blenloader/BLO_readfile.h @@ -119,12 +119,20 @@ void BLO_blendfiledata_free(BlendFileData *bfd); /** \name BLO Blend File Handle API * \{ */ +struct BLODataBlockInfo { + char name[64]; /* MAX_NAME */ + struct AssetMetaData *asset_data; +}; + BlendHandle *BLO_blendhandle_from_file(const char *filepath, struct ReportList *reports); BlendHandle *BLO_blendhandle_from_memory(const void *mem, int memsize); struct LinkNode *BLO_blendhandle_get_datablock_names(BlendHandle *bh, int ofblocktype, int *tot_names); +struct LinkNode *BLO_blendhandle_get_datablock_info(BlendHandle *bh, + int ofblocktype, + int *tot_info_items); struct LinkNode *BLO_blendhandle_get_previews(BlendHandle *bh, int ofblocktype, int *tot_prev); struct LinkNode *BLO_blendhandle_get_linkable_groups(BlendHandle *bh); diff --git a/source/blender/blenloader/intern/readblenentry.c b/source/blender/blenloader/intern/readblenentry.c index 1aecba5ba90..3a1ccbeda01 100644 --- a/source/blender/blenloader/intern/readblenentry.c +++ b/source/blender/blenloader/intern/readblenentry.c @@ -159,6 +159,51 @@ LinkNode *BLO_blendhandle_get_datablock_names(BlendHandle *bh, int ofblocktype, return names; } +/** + * Gets the names and asset-data (if ID is an asset) of all the data-blocks in a file of a certain + * type (e.g. all the scene names in a file). + * + * \param bh: The blendhandle to access. + * \param ofblocktype: The type of names to get. + * \param tot_info_items: The length of the returned list. + * \return A BLI_linklist of BLODataBlockInfo *. The links and #BLODataBlockInfo.asset_data should + * be freed with MEM_freeN. + */ +LinkNode *BLO_blendhandle_get_datablock_info(BlendHandle *bh, int ofblocktype, int *tot_info_items) +{ + FileData *fd = (FileData *)bh; + LinkNode *infos = NULL; + BHead *bhead; + int tot = 0; + + for (bhead = blo_bhead_first(fd); bhead; bhead = blo_bhead_next(fd, bhead)) { + if (bhead->code == ofblocktype) { + struct BLODataBlockInfo *info = MEM_mallocN(sizeof(*info), __func__); + const char *name = blo_bhead_id_name(fd, bhead) + 2; + + STRNCPY(info->name, name); + + /* Lastly, read asset data from the following blocks. */ + info->asset_data = blo_bhead_id_asset_data_address(fd, bhead); + if (info->asset_data) { + bhead = blo_read_asset_data_block(fd, bhead, &info->asset_data); + /* blo_read_asset_data_block() reads all DATA heads and already advances bhead to the next + * non-DATA one. Go back, so the loop doesn't skip the non-DATA head. */ + bhead = blo_bhead_prev(fd, bhead); + } + + BLI_linklist_prepend(&infos, info); + tot++; + } + else if (bhead->code == ENDB) { + break; + } + } + + *tot_info_items = tot; + return infos; +} + /** * Gets the previews of all the data-blocks in a file of a certain type * (e.g. all the scene previews in a file). diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index fd10eac4302..8dff1aa1ed0 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -44,6 +44,7 @@ #define DNA_DEPRECATED_ALLOW #include "DNA_anim_types.h" +#include "DNA_asset_types.h" #include "DNA_cachefile_types.h" #include "DNA_collection_types.h" #include "DNA_fileglobal_types.h" @@ -73,6 +74,7 @@ #include "BKE_anim_data.h" #include "BKE_animsys.h" +#include "BKE_asset.h" #include "BKE_collection.h" #include "BKE_global.h" /* for G */ #include "BKE_idprop.h" @@ -957,12 +959,21 @@ static BHead *blo_bhead_read_full(FileData *fd, BHead *thisblock) } #endif /* USE_BHEAD_READ_ON_DEMAND */ -/* Warning! Caller's responsibility to ensure given bhead **is** and ID one! */ +/* Warning! Caller's responsibility to ensure given bhead **is** an ID one! */ const char *blo_bhead_id_name(const FileData *fd, const BHead *bhead) { return (const char *)POINTER_OFFSET(bhead, sizeof(*bhead) + fd->id_name_offs); } +/* Warning! Caller's responsibility to ensure given bhead **is** an ID one! */ +AssetMetaData *blo_bhead_id_asset_data_address(const FileData *fd, const BHead *bhead) +{ + BLI_assert(BKE_idtype_idcode_is_valid(bhead->code)); + return (fd->id_asset_data_offs >= 0) ? + *(AssetMetaData **)POINTER_OFFSET(bhead, sizeof(*bhead) + fd->id_asset_data_offs) : + NULL; +} + static void decode_blender_header(FileData *fd) { char header[SIZEOFBLENDERHEADER], num[4]; @@ -1040,6 +1051,8 @@ static bool read_file_dna(FileData *fd, const char **r_error_message) /* used to retrieve ID names from (bhead+1) */ fd->id_name_offs = DNA_elem_offset(fd->filesdna, "ID", "char", "name[]"); BLI_assert(fd->id_name_offs != -1); + fd->id_asset_data_offs = DNA_elem_offset( + fd->filesdna, "ID", "AssetMetaData", "*asset_data"); return true; } @@ -2360,6 +2373,11 @@ static void direct_link_id_common( return; } + if (id->asset_data) { + BLO_read_data_address(reader, &id->asset_data); + BKE_asset_metadata_read(reader, id->asset_data); + } + /*link direct data of ID properties*/ if (id->properties) { BLO_read_data_address(reader, &id->properties); @@ -3607,6 +3625,27 @@ static BHead *read_libblock(FileData *fd, /** \} */ +/* -------------------------------------------------------------------- */ +/** \name Read Asset Data + * \{ */ + +BHead *blo_read_asset_data_block(FileData *fd, BHead *bhead, AssetMetaData **r_asset_data) +{ + BLI_assert(BKE_idtype_idcode_is_valid(bhead->code)); + + bhead = read_data_into_datamap(fd, bhead, "asset-data read"); + + BlendDataReader reader = {fd}; + BLO_read_data_address(&reader, r_asset_data); + BKE_asset_metadata_read(&reader, *r_asset_data); + + oldnewmap_clear(fd->datamap); + + return bhead; +} + +/** \} */ + /* -------------------------------------------------------------------- */ /** \name Read Global Data * \{ */ diff --git a/source/blender/blenloader/intern/readfile.h b/source/blender/blenloader/intern/readfile.h index fb950e37da8..3e7cdb30e1f 100644 --- a/source/blender/blenloader/intern/readfile.h +++ b/source/blender/blenloader/intern/readfile.h @@ -112,6 +112,9 @@ typedef struct FileData { int fileversion; /** Used to retrieve ID names from (bhead+1). */ int id_name_offs; + /** Used to retrieve asset data from (bhead+1). NOTE: This may not be available in old files, + * will be -1 then! */ + int id_asset_data_offs; /** For do_versions patching. */ int globalf, fileflags; @@ -159,6 +162,8 @@ void blo_end_packed_pointer_map(FileData *fd, struct Main *oldmain); void blo_add_library_pointer_map(ListBase *old_mainlist, FileData *fd); void blo_make_old_idmap_from_main(FileData *fd, struct Main *bmain); +BHead *blo_read_asset_data_block(FileData *fd, BHead *bhead, struct AssetMetaData **r_asset_data); + void blo_cache_storage_init(FileData *fd, struct Main *bmain); void blo_cache_storage_old_bmain_clear(FileData *fd, struct Main *bmain_old); void blo_cache_storage_end(FileData *fd); @@ -170,6 +175,7 @@ BHead *blo_bhead_next(FileData *fd, BHead *thisblock); BHead *blo_bhead_prev(FileData *fd, BHead *thisblock); const char *blo_bhead_id_name(const FileData *fd, const BHead *bhead); +struct AssetMetaData *blo_bhead_id_asset_data_address(const FileData *fd, const BHead *bhead); /* do versions stuff */ diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h index f2d860a2851..84757e313ed 100644 --- a/source/blender/makesdna/DNA_ID.h +++ b/source/blender/makesdna/DNA_ID.h @@ -264,7 +264,12 @@ typedef struct IDOverrideLibrary { typedef struct ID { void *next, *prev; struct ID *newid; + struct Library *lib; + + /** If the ID is an asset, this pointer is set. Owning pointer. */ + struct AssetMetaData *asset_data; + /** MAX_ID_NAME. */ char name[66]; /** @@ -310,6 +315,7 @@ typedef struct ID { struct ID *orig_id; void *py_instance; + void *_pad1; } ID; /** diff --git a/source/blender/makesdna/DNA_asset_defaults.h b/source/blender/makesdna/DNA_asset_defaults.h new file mode 100644 index 00000000000..ff00ba79cf0 --- /dev/null +++ b/source/blender/makesdna/DNA_asset_defaults.h @@ -0,0 +1,37 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** \file + * \ingroup DNA + */ + +#pragma once + +/* Struct members on own line. */ +/* clang-format off */ + +/* -------------------------------------------------------------------- */ +/** \name Asset Struct + * \{ */ + +#define _DNA_DEFAULT_AssetMetaData \ + { \ + 0 \ + } + +/** \} */ + +/* clang-format on */ diff --git a/source/blender/makesdna/DNA_asset_types.h b/source/blender/makesdna/DNA_asset_types.h new file mode 100644 index 00000000000..671012e54ef --- /dev/null +++ b/source/blender/makesdna/DNA_asset_types.h @@ -0,0 +1,62 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** \file + * \ingroup DNA + */ + +#ifndef __DNA_ASSET_TYPES_H__ +#define __DNA_ASSET_TYPES_H__ + +#include "DNA_listBase.h" + +/** + * \brief User defined tag. + * Currently only used by assets, could be used more often at some point. + * Maybe add a custom icon and color to these in future? + */ +typedef struct AssetTag { + struct AssetTag *next, *prev; + char name[64]; /* MAX_NAME */ +} AssetTag; + +/** + * \brief The meta-data of an asset. + * By creating and giving this for a data-block (#ID.asset_data), the data-block becomes an asset. + * + * \note This struct must be readable without having to read anything but blocks from the ID it is + * attached to! That way, asset information of a file can be read, without reading anything + * more than that from the file. So pointers to other IDs or ID data are strictly forbidden. + */ +typedef struct AssetMetaData { + /** Custom asset meta-data. Cannot store pointers to IDs (#STRUCT_NO_DATABLOCK_IDPROPERTIES)! */ + struct IDProperty *properties; + + /** Optional description of this asset for display in the UI. Dynamic length. */ + char *description; + /** User defined tags for this asset. The asset manager uses these for filtering, but how they + * function exactly (e.g. how they are registered to provide a list of searchable available tags) + * is up to the asset-engine. */ + ListBase tags; /* AssetTag */ + short active_tag; + /** Store the number of tags to avoid continuous counting. Could be turned into runtime data, we + * can always reliably reconstruct it from the list. */ + short tot_tags; + + char _pad[4]; +} AssetMetaData; + +#endif /* __DNA_ASSET_TYPES_H__ */ diff --git a/source/blender/makesdna/intern/CMakeLists.txt b/source/blender/makesdna/intern/CMakeLists.txt index 2051335dd7e..a7adaa7e258 100644 --- a/source/blender/makesdna/intern/CMakeLists.txt +++ b/source/blender/makesdna/intern/CMakeLists.txt @@ -138,6 +138,7 @@ set(SRC ../../blenlib/intern/hash_mm2a.c ../../blenlib/intern/listbase.c + ../DNA_asset_defaults.h ../DNA_brush_defaults.h ../DNA_cachefile_defaults.h ../DNA_camera_defaults.h diff --git a/source/blender/makesdna/intern/dna_defaults.c b/source/blender/makesdna/intern/dna_defaults.c index 1a8bd25215f..3e4d5d87fb0 100644 --- a/source/blender/makesdna/intern/dna_defaults.c +++ b/source/blender/makesdna/intern/dna_defaults.c @@ -85,6 +85,7 @@ #include "DNA_defaults.h" #include "DNA_armature_types.h" +#include "DNA_asset_types.h" #include "DNA_brush_types.h" #include "DNA_cachefile_types.h" #include "DNA_camera_types.h" @@ -117,6 +118,7 @@ #include "DNA_world_types.h" #include "DNA_armature_defaults.h" +#include "DNA_asset_defaults.h" #include "DNA_brush_defaults.h" #include "DNA_cachefile_defaults.h" #include "DNA_camera_defaults.h" @@ -148,6 +150,9 @@ #define SDNA_DEFAULT_DECL_STRUCT(struct_name) \ static const struct_name DNA_DEFAULT_##struct_name = _DNA_DEFAULT_##struct_name +/* DNA_asset_defaults.h */ +SDNA_DEFAULT_DECL_STRUCT(AssetMetaData); + /* DNA_armature_defaults.h */ SDNA_DEFAULT_DECL_STRUCT(bArmature); @@ -338,7 +343,10 @@ extern const bTheme U_theme_default; /** Keep headers sorted. */ const void *DNA_default_table[SDNA_TYPE_MAX] = { - /* DNA_arnature_defaults.h */ + /* DNA_asset_defaults.h */ + SDNA_DEFAULT_DECL(AssetMetaData), + + /* DNA_armature_defaults.h */ SDNA_DEFAULT_DECL(bArmature), /* DNA_brush_defaults.h */ diff --git a/source/blender/makesdna/intern/makesdna.c b/source/blender/makesdna/intern/makesdna.c index 81a7da7b4d8..54d2bc88d16 100644 --- a/source/blender/makesdna/intern/makesdna.c +++ b/source/blender/makesdna/intern/makesdna.c @@ -139,6 +139,7 @@ static const char *includefiles[] = { "DNA_volume_types.h", "DNA_simulation_types.h", "DNA_pointcache_types.h", + "DNA_asset_types.h", /* see comment above before editing! */ @@ -1533,6 +1534,7 @@ int main(int argc, char **argv) #include "DNA_action_types.h" #include "DNA_anim_types.h" #include "DNA_armature_types.h" +#include "DNA_asset_types.h" #include "DNA_boid_types.h" #include "DNA_brush_types.h" #include "DNA_cachefile_types.h" diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index 4aeb9b9e5f7..da15489370a 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -70,6 +70,8 @@ extern StructRNA RNA_ArrayGpencilModifier; extern StructRNA RNA_ArrayModifier; extern StructRNA RNA_Attribute; extern StructRNA RNA_AttributeGroup; +extern StructRNA RNA_AssetMetaData; +extern StructRNA RNA_AssetTag; extern StructRNA RNA_BackgroundImage; extern StructRNA RNA_BevelModifier; extern StructRNA RNA_BezierSplinePoint; diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt index 3ebbb98934e..2ce1acb0074 100644 --- a/source/blender/makesrna/intern/CMakeLists.txt +++ b/source/blender/makesrna/intern/CMakeLists.txt @@ -31,6 +31,7 @@ set(DEFSRC rna_animviz.c rna_armature.c rna_attribute.c + rna_asset.c rna_boid.c rna_brush.c rna_cachefile.c diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c index 8b861d20e4e..c2c95c59002 100644 --- a/source/blender/makesrna/intern/makesrna.c +++ b/source/blender/makesrna/intern/makesrna.c @@ -4270,6 +4270,7 @@ static RNAProcessItem PROCESS_ITEMS[] = { {"rna_animviz.c", NULL, RNA_def_animviz}, {"rna_armature.c", "rna_armature_api.c", RNA_def_armature}, {"rna_attribute.c", NULL, RNA_def_attribute}, + {"rna_asset.c", NULL, RNA_def_asset}, {"rna_boid.c", NULL, RNA_def_boid}, {"rna_brush.c", NULL, RNA_def_brush}, {"rna_cachefile.c", NULL, RNA_def_cachefile}, diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c index f63cf0271b8..7c67bfc360b 100644 --- a/source/blender/makesrna/intern/rna_ID.c +++ b/source/blender/makesrna/intern/rna_ID.c @@ -1528,6 +1528,11 @@ static void rna_def_ID(BlenderRNA *brna) RNA_def_property_override_flag(prop, PROPOVERRIDE_NO_COMPARISON); RNA_def_property_ui_text(prop, "Library", "Library file the data-block is linked from"); + prop = RNA_def_property(srna, "asset_data", PROP_POINTER, PROP_NONE); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_override_flag(prop, PROPOVERRIDE_NO_COMPARISON); + RNA_def_property_ui_text(prop, "Asset Data", "Additional data for an asset data-block"); + prop = RNA_def_pointer( srna, "override_library", "IDOverrideLibrary", "Library Override", "Library override data"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); diff --git a/source/blender/makesrna/intern/rna_asset.c b/source/blender/makesrna/intern/rna_asset.c new file mode 100644 index 00000000000..1af53e95cc9 --- /dev/null +++ b/source/blender/makesrna/intern/rna_asset.c @@ -0,0 +1,228 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** \file + * \ingroup RNA + */ + +#include + +#include "RNA_define.h" +#include "RNA_enum_types.h" + +#include "DNA_asset_types.h" +#include "DNA_defs.h" + +#include "rna_internal.h" + +#ifdef RNA_RUNTIME + +# include "BKE_asset.h" +# include "BKE_idprop.h" + +# include "BLI_listbase.h" + +# include "RNA_access.h" + +static AssetTag *rna_AssetMetaData_tag_new(AssetMetaData *asset_data, + ReportList *reports, + const char *name, + bool skip_if_exists) +{ + AssetTag *tag = NULL; + + if (skip_if_exists) { + struct AssetTagEnsureResult result = BKE_asset_metadata_tag_ensure(asset_data, name); + + if (!result.is_new) { + BKE_reportf( + reports, RPT_WARNING, "Tag '%s' already present for given asset", result.tag->name); + /* Report, but still return valid item. */ + } + tag = result.tag; + } + else { + tag = BKE_asset_metadata_tag_add(asset_data, name); + } + + return tag; +} + +static void rna_AssetMetaData_tag_remove(AssetMetaData *asset_data, + ReportList *reports, + PointerRNA *tag_ptr) +{ + AssetTag *tag = tag_ptr->data; + if (BLI_findindex(&asset_data->tags, tag) == -1) { + BKE_reportf(reports, RPT_ERROR, "Tag '%s' not found in given asset", tag->name); + return; + } + + BKE_asset_metadata_tag_remove(asset_data, tag); + RNA_POINTER_INVALIDATE(tag_ptr); +} + +static IDProperty *rna_AssetMetaData_idprops(PointerRNA *ptr, bool create) +{ + AssetMetaData *asset_data = ptr->data; + + if (create && !asset_data->properties) { + IDPropertyTemplate val = {0}; + asset_data->properties = IDP_New(IDP_GROUP, &val, "RNA_AssetMetaData group"); + } + + return asset_data->properties; +} + +static void rna_AssetMetaData_description_get(PointerRNA *ptr, char *value) +{ + AssetMetaData *asset_data = ptr->data; + + if (asset_data->description) { + strcpy(value, asset_data->description); + } + else { + value[0] = '\0'; + } +} + +static int rna_AssetMetaData_description_length(PointerRNA *ptr) +{ + AssetMetaData *asset_data = ptr->data; + return asset_data->description ? strlen(asset_data->description) : 0; +} + +static void rna_AssetMetaData_description_set(PointerRNA *ptr, const char *value) +{ + AssetMetaData *asset_data = ptr->data; + + if (asset_data->description) { + MEM_freeN(asset_data->description); + } + + if (value[0]) { + asset_data->description = BLI_strdup(value); + } + else { + asset_data->description = NULL; + } +} + +static void rna_AssetMetaData_active_tag_range( + PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax) +{ + const AssetMetaData *asset_data = ptr->data; + *min = *softmin = 0; + *max = *softmax = MAX2(asset_data->tot_tags - 1, 0); +} + +#else + +static void rna_def_asset_tag(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "AssetTag", NULL); + RNA_def_struct_ui_text(srna, "Asset Tag", "User defined tag (name token)"); + + prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); + RNA_def_property_string_maxlength(prop, MAX_NAME); + RNA_def_property_ui_text(prop, "Name", "The identifier that makes up this tag"); + RNA_def_struct_name_property(srna, prop); +} + +static void rna_def_asset_tags_api(BlenderRNA *brna, PropertyRNA *cprop) +{ + StructRNA *srna; + + FunctionRNA *func; + PropertyRNA *parm; + + RNA_def_property_srna(cprop, "AssetTags"); + srna = RNA_def_struct(brna, "AssetTags", NULL); + RNA_def_struct_sdna(srna, "AssetMetaData"); + RNA_def_struct_ui_text(srna, "Asset Tags", "Collection of custom asset tags"); + + /* Tag collection */ + func = RNA_def_function(srna, "new", "rna_AssetMetaData_tag_new"); + RNA_def_function_ui_description(func, "Add a new tag to this asset"); + RNA_def_function_flag(func, FUNC_USE_REPORTS); + parm = RNA_def_string(func, "name", NULL, MAX_NAME, "Name", ""); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_boolean(func, + "skip_if_exists", + false, + "Skip if Exists", + "Do not add a new tag if one of the same type already exists"); + /* return type */ + parm = RNA_def_pointer(func, "tag", "AssetTag", "", "New tag"); + RNA_def_function_return(func, parm); + + func = RNA_def_function(srna, "remove", "rna_AssetMetaData_tag_remove"); + RNA_def_function_ui_description(func, "Remove an existing tag from this asset"); + RNA_def_function_flag(func, FUNC_USE_REPORTS); + /* tag to remove */ + parm = RNA_def_pointer(func, "tag", "AssetTag", "", "Removed tag"); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR); + RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, 0); +} + +static void rna_def_asset_data(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "AssetMetaData", NULL); + RNA_def_struct_ui_text(srna, "Asset Data", "Additional data stored for an asset data-block"); + // RNA_def_struct_ui_icon(srna, ICON_ASSET); /* TODO: Icon doesn't exist!. */ + /* The struct has custom properties, but no pointer properties to other IDs! */ + RNA_def_struct_idprops_func(srna, "rna_AssetMetaData_idprops"); + RNA_def_struct_flag(srna, STRUCT_NO_DATABLOCK_IDPROPERTIES); /* Mandatory! */ + + prop = RNA_def_property(srna, "description", PROP_STRING, PROP_NONE); + RNA_def_property_string_funcs(prop, + "rna_AssetMetaData_description_get", + "rna_AssetMetaData_description_length", + "rna_AssetMetaData_description_set"); + RNA_def_property_ui_text( + prop, "Description", "A description of the asset to be displayed for the user"); + + prop = RNA_def_property(srna, "tags", PROP_COLLECTION, PROP_NONE); + RNA_def_property_struct_type(prop, "AssetTag"); + RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, + "Tags", + "Custom tags (name tokens) for the asset, used for filtering and " + "general asset management"); + rna_def_asset_tags_api(brna, prop); + + prop = RNA_def_property(srna, "active_tag", PROP_INT, PROP_NONE); + RNA_def_property_int_funcs(prop, NULL, NULL, "rna_AssetMetaData_active_tag_range"); + RNA_def_property_ui_text(prop, "Active Tag", "Index of the tag set for editing"); +} + +void RNA_def_asset(BlenderRNA *brna) +{ + RNA_define_animate_sdna(false); + + rna_def_asset_tag(brna); + rna_def_asset_data(brna); + + RNA_define_animate_sdna(true); +} + +#endif diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h index d4fdac390b2..76c3e17e128 100644 --- a/source/blender/makesrna/intern/rna_internal.h +++ b/source/blender/makesrna/intern/rna_internal.h @@ -152,6 +152,7 @@ void RNA_def_animation(struct BlenderRNA *brna); void RNA_def_animviz(struct BlenderRNA *brna); void RNA_def_armature(struct BlenderRNA *brna); void RNA_def_attribute(struct BlenderRNA *brna); +void RNA_def_asset(struct BlenderRNA *brna); void RNA_def_boid(struct BlenderRNA *brna); void RNA_def_brush(struct BlenderRNA *brna); void RNA_def_cachefile(struct BlenderRNA *brna); -- cgit v1.2.3 From c25e0310497f5228bd04992d6bcd84481d0b0c5b Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Fri, 11 Dec 2020 23:16:29 +0100 Subject: Asset System: "Mark Asset" & "Clear Asset" operators and UI integration This makes it possible to turn data-blocks into assets and back into normal data-blocks. A core design decision made for the asset system is that not every data-block should be an asset, because not every data-block is made for reuse. Users have to explicitly mark data-blocks as assets. Exposes "Mark Asset" and "Clear Asset" in Outliner context menus (currently ID Data submenu) and button context menus. We are still not too happy with the names, they may change. This uses the new context members to pass data-blocks to operators, added in af008f553293 and 0c1d4769235c. Part of the first Asset Browser milestone. Check the #asset_browser_milestone_1 project milestone on developer.blender.org. Differential Revision: https://developer.blender.org/D9717 Reviewed by: Brecht Van Lommel --- source/blender/blenkernel/BKE_asset.h | 3 + source/blender/blenkernel/BKE_icons.h | 2 + source/blender/blenkernel/BKE_lib_id.h | 2 + source/blender/blenkernel/intern/asset.c | 8 + source/blender/blenkernel/intern/icons.c | 8 +- source/blender/blenkernel/intern/lib_id.c | 6 + source/blender/editors/CMakeLists.txt | 1 + source/blender/editors/asset/CMakeLists.txt | 39 ++++ source/blender/editors/asset/asset_edit.c | 69 ++++++ source/blender/editors/asset/asset_ops.c | 238 +++++++++++++++++++++ source/blender/editors/include/ED_asset.h | 39 ++++ .../editors/interface/interface_context_menu.c | 17 ++ source/blender/editors/space_api/spacetypes.c | 2 + .../editors/space_outliner/outliner_tools.c | 12 ++ source/blender/editors/util/CMakeLists.txt | 1 + source/blender/makesrna/intern/CMakeLists.txt | 1 + source/blender/windowmanager/WM_types.h | 2 + 17 files changed, 449 insertions(+), 1 deletion(-) create mode 100644 source/blender/editors/asset/CMakeLists.txt create mode 100644 source/blender/editors/asset/asset_edit.c create mode 100644 source/blender/editors/asset/asset_ops.c create mode 100644 source/blender/editors/include/ED_asset.h (limited to 'source/blender') diff --git a/source/blender/blenkernel/BKE_asset.h b/source/blender/blenkernel/BKE_asset.h index edd49dd9851..20df6109c13 100644 --- a/source/blender/blenkernel/BKE_asset.h +++ b/source/blender/blenkernel/BKE_asset.h @@ -46,6 +46,9 @@ struct AssetTagEnsureResult BKE_asset_metadata_tag_ensure(struct AssetMetaData * const char *name); void BKE_asset_metadata_tag_remove(struct AssetMetaData *asset_data, struct AssetTag *tag); +struct PreviewImage *BKE_asset_metadata_preview_get_from_id(const struct AssetMetaData *asset_data, + const struct ID *owner_id); + void BKE_asset_metadata_write(struct BlendWriter *writer, struct AssetMetaData *asset_data); void BKE_asset_metadata_read(struct BlendDataReader *reader, struct AssetMetaData *asset_data); diff --git a/source/blender/blenkernel/BKE_icons.h b/source/blender/blenkernel/BKE_icons.h index 534b24236e8..cb2755d8706 100644 --- a/source/blender/blenkernel/BKE_icons.h +++ b/source/blender/blenkernel/BKE_icons.h @@ -129,6 +129,8 @@ void BKE_previewimg_clear_single(struct PreviewImage *prv, enum eIconSizes size) /* get the preview from any pointer */ struct PreviewImage **BKE_previewimg_id_get_p(const struct ID *id); +struct PreviewImage *BKE_previewimg_id_get(const struct ID *id); + /* Trigger deferred loading of a custom image file into the preview buffer. */ void BKE_previewimg_id_custom_set(struct ID *id, const char *path); diff --git a/source/blender/blenkernel/BKE_lib_id.h b/source/blender/blenkernel/BKE_lib_id.h index e54e2fb4b87..9f3536c9314 100644 --- a/source/blender/blenkernel/BKE_lib_id.h +++ b/source/blender/blenkernel/BKE_lib_id.h @@ -298,6 +298,8 @@ void BKE_id_tag_clear_atomic(struct ID *id, int tag); bool BKE_id_is_in_global_main(struct ID *id); +bool BKE_id_can_be_asset(const struct ID *id); + void BKE_id_ordered_list(struct ListBase *ordered_lb, const struct ListBase *lb); void BKE_id_reorder(const struct ListBase *lb, struct ID *id, struct ID *relative, bool after); diff --git a/source/blender/blenkernel/intern/asset.c b/source/blender/blenkernel/intern/asset.c index 92400d10fe5..7ccb0aa2b57 100644 --- a/source/blender/blenkernel/intern/asset.c +++ b/source/blender/blenkernel/intern/asset.c @@ -110,6 +110,14 @@ void BKE_asset_metadata_tag_remove(AssetMetaData *asset_data, AssetTag *tag) BLI_assert(BLI_listbase_count(&asset_data->tags) == asset_data->tot_tags); } +/* Queries -------------------------------------------- */ + +PreviewImage *BKE_asset_metadata_preview_get_from_id(const AssetMetaData *UNUSED(asset_data), + const ID *id) +{ + return BKE_previewimg_id_get(id); +} + /* .blend file API -------------------------------------------- */ void BKE_asset_metadata_write(BlendWriter *writer, AssetMetaData *asset_data) diff --git a/source/blender/blenkernel/intern/icons.c b/source/blender/blenkernel/intern/icons.c index ecafed5da31..0abf5d7279b 100644 --- a/source/blender/blenkernel/intern/icons.c +++ b/source/blender/blenkernel/intern/icons.c @@ -344,7 +344,7 @@ PreviewImage **BKE_previewimg_id_get_p(const ID *id) ID_PRV_CASE(ID_LA, Light); ID_PRV_CASE(ID_IM, Image); ID_PRV_CASE(ID_BR, Brush); - ID_PRV_CASE(ID_OB, Object); + // ID_PRV_CASE(ID_OB, Object); ID_PRV_CASE(ID_GR, Collection); ID_PRV_CASE(ID_SCE, Scene); ID_PRV_CASE(ID_SCR, bScreen); @@ -356,6 +356,12 @@ PreviewImage **BKE_previewimg_id_get_p(const ID *id) return NULL; } +PreviewImage *BKE_previewimg_id_get(const ID *id) +{ + PreviewImage **prv_p = BKE_previewimg_id_get_p(id); + return prv_p ? *prv_p : NULL; +} + void BKE_previewimg_id_free(ID *id) { PreviewImage **prv_p = BKE_previewimg_id_get_p(id); diff --git a/source/blender/blenkernel/intern/lib_id.c b/source/blender/blenkernel/intern/lib_id.c index 61b5e6f85bb..be7ce34f7e6 100644 --- a/source/blender/blenkernel/intern/lib_id.c +++ b/source/blender/blenkernel/intern/lib_id.c @@ -2266,6 +2266,12 @@ bool BKE_id_is_in_global_main(ID *id) return (id == NULL || BLI_findindex(which_libbase(G_MAIN, GS(id->name)), id) != -1); } +bool BKE_id_can_be_asset(const ID *id) +{ + return !ID_IS_LINKED(id) && !ID_IS_OVERRIDE_LIBRARY(id) && + BKE_idtype_idcode_is_linkable(GS(id->name)); +} + /************************* Datablock order in UI **************************/ static int *id_order_get(ID *id) diff --git a/source/blender/editors/CMakeLists.txt b/source/blender/editors/CMakeLists.txt index 1f5dc73f732..a2ae350ce4b 100644 --- a/source/blender/editors/CMakeLists.txt +++ b/source/blender/editors/CMakeLists.txt @@ -22,6 +22,7 @@ if(WITH_BLENDER) add_subdirectory(animation) add_subdirectory(armature) + add_subdirectory(asset) add_subdirectory(curve) add_subdirectory(geometry) add_subdirectory(gizmo_library) diff --git a/source/blender/editors/asset/CMakeLists.txt b/source/blender/editors/asset/CMakeLists.txt new file mode 100644 index 00000000000..63a1761b264 --- /dev/null +++ b/source/blender/editors/asset/CMakeLists.txt @@ -0,0 +1,39 @@ +# ***** BEGIN GPL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# ***** END GPL LICENSE BLOCK ***** + +set(INC + ../include + ../../blenlib + ../../blenkernel + ../../makesdna + ../../makesrna + ../../windowmanager + ../../../../intern/guardedalloc +) + +set(INC_SYS +) + +set(SRC + asset_edit.c + asset_ops.c +) + +set(LIB +) + +blender_add_lib(bf_editor_asset "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/source/blender/editors/asset/asset_edit.c b/source/blender/editors/asset/asset_edit.c new file mode 100644 index 00000000000..5333c08c66a --- /dev/null +++ b/source/blender/editors/asset/asset_edit.c @@ -0,0 +1,69 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** \file + * \ingroup edasset + */ + +#include "BKE_asset.h" +#include "BKE_context.h" +#include "BKE_idtype.h" +#include "BKE_lib_id.h" + +#include "DNA_ID.h" +#include "DNA_asset_types.h" + +#include "UI_interface_icons.h" + +#include "RNA_access.h" + +#include "ED_asset.h" + +bool ED_asset_mark_id(const bContext *C, ID *id) +{ + if (id->asset_data) { + return false; + } + if (!BKE_id_can_be_asset(id)) { + return false; + } + + id_fake_user_set(id); + + id->asset_data = BKE_asset_metadata_create(); + + UI_icon_render_id(C, NULL, id, true, true); + + return true; +} + +bool ED_asset_clear_id(ID *id) +{ + if (!id->asset_data) { + return false; + } + BKE_asset_metadata_free(&id->asset_data); + /* Don't clear fake user here, there's no guarantee that it was actually set by + * #ED_asset_mark_id(), it might have been something/someone else. */ + + return true; +} + +bool ED_asset_can_make_single_from_context(const bContext *C) +{ + /* Context needs a "id" pointer to be set for #ASSET_OT_mark()/#ASSET_OT_clear() to use. */ + return CTX_data_pointer_get_type_silent(C, "id", &RNA_ID).data != NULL; +} diff --git a/source/blender/editors/asset/asset_ops.c b/source/blender/editors/asset/asset_ops.c new file mode 100644 index 00000000000..929d49e19fa --- /dev/null +++ b/source/blender/editors/asset/asset_ops.c @@ -0,0 +1,238 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** \file + * \ingroup edasset + */ + +#include + +#include "BKE_asset.h" +#include "BKE_context.h" +#include "BKE_report.h" + +#include "BLI_listbase.h" +#include "BLI_string_utils.h" + +#include "DNA_asset_types.h" + +#include "ED_asset.h" + +#include "MEM_guardedalloc.h" + +#include "RNA_access.h" +#include "RNA_define.h" + +#include "WM_api.h" +#include "WM_types.h" + +/* -------------------------------------------------------------------- */ + +struct AssetMarkResultStats { + int tot_created; + int tot_already_asset; + ID *last_id; +}; + +/** + * Return the IDs to operate on as list of #CollectionPointerLink links. Needs freeing. + */ +static ListBase /* CollectionPointerLink */ asset_operation_get_ids_from_context(const bContext *C) +{ + ListBase list = {0}; + + PointerRNA idptr = CTX_data_pointer_get_type(C, "id", &RNA_ID); + + if (idptr.data) { + CollectionPointerLink *ctx_link = MEM_callocN(sizeof(*ctx_link), __func__); + ctx_link->ptr = idptr; + BLI_addtail(&list, ctx_link); + } + else { + CTX_data_selected_ids(C, &list); + } + + return list; +} + +static void asset_mark_for_idptr_list(const bContext *C, + const ListBase /* CollectionPointerLink */ *ids, + struct AssetMarkResultStats *r_stats) +{ + memset(r_stats, 0, sizeof(*r_stats)); + + LISTBASE_FOREACH (CollectionPointerLink *, ctx_id, ids) { + BLI_assert(RNA_struct_is_ID(ctx_id->ptr.type)); + + ID *id = ctx_id->ptr.data; + if (id->asset_data) { + r_stats->tot_already_asset++; + continue; + } + + if (ED_asset_mark_id(C, id)) { + r_stats->last_id = id; + r_stats->tot_created++; + } + } +} + +static bool asset_mark_results_report(const struct AssetMarkResultStats *stats, + ReportList *reports) +{ + /* User feedback on failure. */ + if ((stats->tot_created < 1) && (stats->tot_already_asset > 0)) { + BKE_report(reports, + RPT_ERROR, + "Selected data-blocks are already assets (or do not support use as assets)"); + return false; + } + if (stats->tot_created < 1) { + BKE_report(reports, + RPT_ERROR, + "No data-blocks to create assets for found (or do not support use as assets)"); + return false; + } + + /* User feedback on success. */ + if (stats->tot_created == 1) { + /* If only one data-block: Give more useful message by printing asset name. */ + BKE_reportf(reports, RPT_INFO, "Data-block '%s' is now an asset", stats->last_id->name + 2); + } + else { + BKE_reportf(reports, RPT_INFO, "%i data-blocks are now assets", stats->tot_created); + } + + return true; +} + +static int asset_mark_exec(bContext *C, wmOperator *op) +{ + ListBase ids = asset_operation_get_ids_from_context(C); + + struct AssetMarkResultStats stats; + asset_mark_for_idptr_list(C, &ids, &stats); + BLI_freelistN(&ids); + + if (!asset_mark_results_report(&stats, op->reports)) { + return OPERATOR_CANCELLED; + } + + WM_main_add_notifier(NC_ID | NA_EDITED, NULL); + WM_main_add_notifier(NC_ASSET | NA_ADDED, NULL); + + return OPERATOR_FINISHED; +} + +static void ASSET_OT_mark(wmOperatorType *ot) +{ + ot->name = "Mark Asset"; + ot->description = + "Enable easier reuse of selected data-blocks through the Asset Browser, with the help of " + "customizable metadata (like previews, descriptions and tags)"; + ot->idname = "ASSET_OT_mark"; + + ot->exec = asset_mark_exec; + + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +/* -------------------------------------------------------------------- */ + +struct AssetClearResultStats { + int tot_removed; + ID *last_id; +}; + +static void asset_clear_from_idptr_list(const ListBase /* CollectionPointerLink */ *ids, + struct AssetClearResultStats *r_stats) +{ + memset(r_stats, 0, sizeof(*r_stats)); + + LISTBASE_FOREACH (CollectionPointerLink *, ctx_id, ids) { + BLI_assert(RNA_struct_is_ID(ctx_id->ptr.type)); + + ID *id = ctx_id->ptr.data; + if (!id->asset_data) { + continue; + } + + if (ED_asset_clear_id(id)) { + r_stats->tot_removed++; + r_stats->last_id = id; + } + } +} + +static bool asset_clear_result_report(const struct AssetClearResultStats *stats, + ReportList *reports) + +{ + if (stats->tot_removed < 1) { + BKE_report(reports, RPT_ERROR, "No asset data-blocks selected/focused"); + return false; + } + + if (stats->tot_removed == 1) { + /* If only one data-block: Give more useful message by printing asset name. */ + BKE_reportf( + reports, RPT_INFO, "Data-block '%s' is no asset anymore", stats->last_id->name + 2); + } + else { + BKE_reportf(reports, RPT_INFO, "%i data-blocks are no assets anymore", stats->tot_removed); + } + + return true; +} + +static int asset_clear_exec(bContext *C, wmOperator *op) +{ + ListBase ids = asset_operation_get_ids_from_context(C); + + struct AssetClearResultStats stats; + asset_clear_from_idptr_list(&ids, &stats); + BLI_freelistN(&ids); + + if (!asset_clear_result_report(&stats, op->reports)) { + return OPERATOR_CANCELLED; + } + + WM_main_add_notifier(NC_ID | NA_EDITED, NULL); + WM_main_add_notifier(NC_ASSET | NA_REMOVED, NULL); + + return OPERATOR_FINISHED; +} + +static void ASSET_OT_clear(wmOperatorType *ot) +{ + ot->name = "Clear Asset"; + ot->description = + "Delete all asset metadata and turn the selected asset data-blocks back into normal " + "data-blocks"; + ot->idname = "ASSET_OT_clear"; + + ot->exec = asset_clear_exec; + + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +/* -------------------------------------------------------------------- */ + +void ED_operatortypes_asset(void) +{ + WM_operatortype_append(ASSET_OT_mark); + WM_operatortype_append(ASSET_OT_clear); +} diff --git a/source/blender/editors/include/ED_asset.h b/source/blender/editors/include/ED_asset.h new file mode 100644 index 00000000000..6fe50528cc5 --- /dev/null +++ b/source/blender/editors/include/ED_asset.h @@ -0,0 +1,39 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** \file + * \ingroup editors + */ + +#ifndef __ED_ASSET_H__ +#define __ED_ASSET_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +bool ED_asset_mark_id(const struct bContext *C, struct ID *id); +bool ED_asset_clear_id(struct ID *id); + +bool ED_asset_can_make_single_from_context(const struct bContext *C); + +void ED_operatortypes_asset(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __ED_ASSET_H__ */ diff --git a/source/blender/editors/interface/interface_context_menu.c b/source/blender/editors/interface/interface_context_menu.c index 3e76cd1cde4..870c3a2a13f 100644 --- a/source/blender/editors/interface/interface_context_menu.c +++ b/source/blender/editors/interface/interface_context_menu.c @@ -38,6 +38,7 @@ #include "BKE_idprop.h" #include "BKE_screen.h" +#include "ED_asset.h" #include "ED_keyframing.h" #include "ED_screen.h" @@ -952,6 +953,22 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but) } } + /* If the button reprents an id, it can set the "id" context pointer. */ + if (ED_asset_can_make_single_from_context(C)) { + ID *id = CTX_data_pointer_get_type(C, "id", &RNA_ID).data; + + /* Gray out items depending on if data-block is an asset. Preferably this could be done via + * operator poll, but that doesn't work since the operator also works with "selected_ids", + * which isn't cheap to check. */ + uiLayout *sub = uiLayoutColumn(layout, true); + uiLayoutSetEnabled(sub, !id->asset_data); + uiItemO(sub, NULL, ICON_NONE, "ASSET_OT_mark"); + sub = uiLayoutColumn(layout, true); + uiLayoutSetEnabled(sub, id->asset_data); + uiItemO(sub, NULL, ICON_NONE, "ASSET_OT_clear"); + uiItemS(layout); + } + /* Pointer properties and string properties with * prop_search support jumping to target object/bone. */ if (but->rnapoin.data && but->rnaprop) { diff --git a/source/blender/editors/space_api/spacetypes.c b/source/blender/editors/space_api/spacetypes.c index 10ce7b81954..0fe94ec382c 100644 --- a/source/blender/editors/space_api/spacetypes.c +++ b/source/blender/editors/space_api/spacetypes.c @@ -40,6 +40,7 @@ #include "ED_anim_api.h" #include "ED_armature.h" +#include "ED_asset.h" #include "ED_clip.h" #include "ED_curve.h" #include "ED_fileselect.h" @@ -105,6 +106,7 @@ void ED_spacetypes_init(void) ED_operatortypes_screen(); ED_operatortypes_anim(); ED_operatortypes_animchannels(); + ED_operatortypes_asset(); ED_operatortypes_gpencil(); ED_operatortypes_object(); ED_operatortypes_lattice(); diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c index 098a0edb614..e4c3ebfdff5 100644 --- a/source/blender/editors/space_outliner/outliner_tools.c +++ b/source/blender/editors/space_outliner/outliner_tools.c @@ -1685,6 +1685,8 @@ typedef enum eOutlinerIdOpTypes { OUTLINER_IDOP_INVALID = 0, OUTLINER_IDOP_UNLINK, + OUTLINER_IDOP_MARK_ASSET, + OUTLINER_IDOP_CLEAR_ASSET, OUTLINER_IDOP_LOCAL, OUTLINER_IDOP_OVERRIDE_LIBRARY_CREATE, OUTLINER_IDOP_OVERRIDE_LIBRARY_CREATE_HIERARCHY, @@ -1710,6 +1712,8 @@ typedef enum eOutlinerIdOpTypes { /* TODO: implement support for changing the ID-block used. */ static const EnumPropertyItem prop_id_op_types[] = { {OUTLINER_IDOP_UNLINK, "UNLINK", 0, "Unlink", ""}, + {OUTLINER_IDOP_MARK_ASSET, "MARK_ASSET", 0, "Mark Asset", ""}, + {OUTLINER_IDOP_CLEAR_ASSET, "CLEAR_ASSET", 0, "Clear Asset", ""}, {OUTLINER_IDOP_LOCAL, "LOCAL", 0, "Make Local", ""}, {OUTLINER_IDOP_SINGLE, "SINGLE", 0, "Make Single User", ""}, {OUTLINER_IDOP_DELETE, "DELETE", ICON_X, "Delete", ""}, @@ -1915,6 +1919,14 @@ static int outliner_id_operation_exec(bContext *C, wmOperator *op) } break; } + case OUTLINER_IDOP_MARK_ASSET: { + WM_operator_name_call(C, "ASSET_OT_mark", WM_OP_EXEC_DEFAULT, NULL); + break; + } + case OUTLINER_IDOP_CLEAR_ASSET: { + WM_operator_name_call(C, "ASSET_OT_clear", WM_OP_EXEC_DEFAULT, NULL); + break; + } case OUTLINER_IDOP_LOCAL: { /* make local */ outliner_do_libdata_operation( diff --git a/source/blender/editors/util/CMakeLists.txt b/source/blender/editors/util/CMakeLists.txt index c88169778f7..bbaf5d5475a 100644 --- a/source/blender/editors/util/CMakeLists.txt +++ b/source/blender/editors/util/CMakeLists.txt @@ -47,6 +47,7 @@ set(SRC ../include/BIF_glutil.h ../include/ED_anim_api.h ../include/ED_armature.h + ../include/ED_asset.h ../include/ED_buttons.h ../include/ED_clip.h ../include/ED_curve.h diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt index 2ce1acb0074..3db8909c8a7 100644 --- a/source/blender/makesrna/intern/CMakeLists.txt +++ b/source/blender/makesrna/intern/CMakeLists.txt @@ -428,6 +428,7 @@ set(LIB bf_editor_animation bf_editor_armature + bf_editor_asset bf_editor_curve bf_editor_gizmo_library bf_editor_gpencil diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index 7fa2851cbf3..77258ef5224 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -298,6 +298,8 @@ typedef struct wmNotifier { #define NC_LINESTYLE (23 << 24) #define NC_CAMERA (24 << 24) #define NC_LIGHTPROBE (25 << 24) +/* Changes to asset data in the current .blend. */ +#define NC_ASSET (26 << 24) /* data type, 256 entries is enough, it can overlap */ #define NOTE_DATA 0x00FF0000 -- cgit v1.2.3 From 9363132c8601ebca6d89168e09bb10f81d6cb03a Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Mon, 14 Dec 2020 13:21:58 +0100 Subject: Asset System: Various changes to previews in preparation for Asset Browser * Support defining (not necessarily rendering) icons in threads. Needed so the File Browser can expose file previews with an icon-id to scripts. ** For that, ported `icons.c` to C++, to be able to use scope based mutex locks (cleaner & safer code). Had to do some cleanups and minor refactoring for that. * Added support for ImBuf icons, as a decent way for icons to hold the file preview buffers. * Tag previews as "unfinished" while they render in a thread, for the File Browser to dynamically load previews as they get finished. * Better handle cases where threaded preview generation is requested, but the ID type doesn't support it (fallback to single threaded). This is for general sanity of the code (as in, safety and cleanness) * Enabled asset notifier for custom preview loading operator, was just disabled because `NC_ASSET` wasn't defined in master yet. Part of the first Asset Browser milestone. Check the #asset_browser_milestone_1 project milestone on developer.blender.org. Differential Revision: https://developer.blender.org/D9719 Reviewed by: Bastien Montagne, Brecht Van Lommel --- source/blender/blenkernel/BKE_icons.h | 25 +- source/blender/blenkernel/CMakeLists.txt | 2 +- source/blender/blenkernel/intern/icons.c | 946 ------------------ source/blender/blenkernel/intern/icons.cc | 1053 ++++++++++++++++++++ source/blender/blenloader/intern/readblenentry.c | 4 + source/blender/editors/interface/interface_icons.c | 45 +- source/blender/editors/render/render_preview.c | 37 +- source/blender/editors/util/ed_util.c | 2 +- source/blender/imbuf/intern/thumbs_blend.c | 10 +- source/blender/makesdna/DNA_ID.h | 1 + 10 files changed, 1150 insertions(+), 975 deletions(-) delete mode 100644 source/blender/blenkernel/intern/icons.c create mode 100644 source/blender/blenkernel/intern/icons.cc (limited to 'source/blender') diff --git a/source/blender/blenkernel/BKE_icons.h b/source/blender/blenkernel/BKE_icons.h index cb2755d8706..5ceba4c717f 100644 --- a/source/blender/blenkernel/BKE_icons.h +++ b/source/blender/blenkernel/BKE_icons.h @@ -23,17 +23,26 @@ * \ingroup bke * * Resizable Icons for Blender + * + * There is some thread safety for this API but it is rather weak. Registering or unregistering + * icons is thread safe, changing data of icons from multiple threads is not. Practically this + * should be fine since only the main thread modifies icons. Should that change, more locks or a + * different design need to be introduced. */ #ifdef __cplusplus extern "C" { #endif +#include "BLI_compiler_attrs.h" + typedef void (*DrawInfoFreeFP)(void *drawinfo); enum { /** ID preview: obj is #ID. */ ICON_DATA_ID = 0, + /** Arbitrary Image buffer: obj is #ImBuf */ + ICON_DATA_IMBUF, /** Preview: obj is #PreviewImage */ ICON_DATA_PREVIEW, /** 2D triangles: obj is #Icon_Geom */ @@ -44,6 +53,9 @@ enum { ICON_DATA_GPLAYER, }; +/** + * \note See comment at the top regarding thread safety. + */ struct Icon { void *drawinfo; /** @@ -93,6 +105,9 @@ int BKE_icon_gplayer_color_ensure(struct bGPDlayer *gpl); int BKE_icon_preview_ensure(struct ID *id, struct PreviewImage *preview); +int BKE_icon_imbuf_create(struct ImBuf *ibuf) ATTR_WARN_UNUSED_RESULT; +struct ImBuf *BKE_icon_imbuf_get_buffer(int icon_id) ATTR_WARN_UNUSED_RESULT; + /* retrieve icon for id */ struct Icon *BKE_icon_get(const int icon_id); @@ -131,6 +146,9 @@ void BKE_previewimg_clear_single(struct PreviewImage *prv, enum eIconSizes size) struct PreviewImage **BKE_previewimg_id_get_p(const struct ID *id); struct PreviewImage *BKE_previewimg_id_get(const struct ID *id); +void BKE_previewimg_id_custom_set(struct ID *id, const char *path); + +bool BKE_previewimg_id_supports_jobs(const struct ID *id); /* Trigger deferred loading of a custom image file into the preview buffer. */ void BKE_previewimg_id_custom_set(struct ID *id, const char *path); @@ -151,6 +169,11 @@ struct PreviewImage *BKE_previewimg_id_ensure(struct ID *id); void BKE_previewimg_ensure(struct PreviewImage *prv, const int size); +struct ImBuf *BKE_previewimg_to_imbuf(struct PreviewImage *prv, const int size); + +void BKE_previewimg_finish(struct PreviewImage *prv, const int size); +bool BKE_previewimg_is_finished(const struct PreviewImage *prv, const int size); + struct PreviewImage *BKE_previewimg_cached_get(const char *name); struct PreviewImage *BKE_previewimg_cached_ensure(const char *name); @@ -168,7 +191,7 @@ void BKE_previewimg_blend_write(struct BlendWriter *writer, const struct Preview void BKE_previewimg_blend_read(struct BlendDataReader *reader, struct PreviewImage *prv); int BKE_icon_geom_ensure(struct Icon_Geom *geom); -struct Icon_Geom *BKE_icon_geom_from_memory(const uchar *data, size_t data_len); +struct Icon_Geom *BKE_icon_geom_from_memory(uchar *data, size_t data_len); struct Icon_Geom *BKE_icon_geom_from_file(const char *filename); struct ImBuf *BKE_icon_geom_rasterize(const struct Icon_Geom *geom, diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index 156d731d4a7..23ba4eb4235 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -133,7 +133,7 @@ set(SRC intern/gpencil_geom.c intern/gpencil_modifier.c intern/hair.c - intern/icons.c + intern/icons.cc intern/icons_rasterize.c intern/idprop.c intern/idprop_utils.c diff --git a/source/blender/blenkernel/intern/icons.c b/source/blender/blenkernel/intern/icons.c deleted file mode 100644 index 0abf5d7279b..00000000000 --- a/source/blender/blenkernel/intern/icons.c +++ /dev/null @@ -1,946 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2006-2007 Blender Foundation. - * All rights reserved. - */ - -/** \file - * \ingroup bke - */ - -#include -#include -#include - -#include "CLG_log.h" - -#include "MEM_guardedalloc.h" - -#include "DNA_brush_types.h" -#include "DNA_collection_types.h" -#include "DNA_gpencil_types.h" -#include "DNA_light_types.h" -#include "DNA_material_types.h" -#include "DNA_object_types.h" -#include "DNA_scene_types.h" -#include "DNA_screen_types.h" -#include "DNA_texture_types.h" -#include "DNA_world_types.h" - -#include "BLI_fileops.h" -#include "BLI_ghash.h" -#include "BLI_linklist_lockfree.h" -#include "BLI_string.h" -#include "BLI_threads.h" -#include "BLI_utildefines.h" - -#include "BKE_global.h" /* only for G.background test */ -#include "BKE_icons.h" -#include "BKE_studiolight.h" - -#include "BLI_sys_types.h" /* for intptr_t support */ - -#include "GPU_texture.h" - -#include "IMB_imbuf.h" -#include "IMB_imbuf_types.h" -#include "IMB_thumbs.h" - -#include "BLO_read_write.h" - -/** - * Only allow non-managed icons to be removed (by Python for eg). - * Previews & ID's have their own functions to remove icons. - */ -enum { - ICON_FLAG_MANAGED = (1 << 0), -}; - -/* GLOBALS */ - -static CLG_LogRef LOG = {"bke.icons"}; - -static GHash *gIcons = NULL; - -static int gNextIconId = 1; - -static int gFirstIconId = 1; - -static GHash *gCachedPreviews = NULL; - -/* Queue of icons for deferred deletion. */ -typedef struct DeferredIconDeleteNode { - struct DeferredIconDeleteNode *next; - int icon_id; -} DeferredIconDeleteNode; -static LockfreeLinkList g_icon_delete_queue; - -static void icon_free(void *val) -{ - Icon *icon = val; - - if (icon) { - if (icon->obj_type == ICON_DATA_GEOM) { - struct Icon_Geom *obj = icon->obj; - if (obj->mem) { - /* coords & colors are part of this memory. */ - MEM_freeN((void *)obj->mem); - } - else { - MEM_freeN((void *)obj->coords); - MEM_freeN((void *)obj->colors); - } - MEM_freeN(icon->obj); - } - - if (icon->drawinfo_free) { - icon->drawinfo_free(icon->drawinfo); - } - else if (icon->drawinfo) { - MEM_freeN(icon->drawinfo); - } - MEM_freeN(icon); - } -} - -static void icon_free_data(int icon_id, Icon *icon) -{ - if (icon->obj_type == ICON_DATA_ID) { - ((ID *)(icon->obj))->icon_id = 0; - } - else if (icon->obj_type == ICON_DATA_PREVIEW) { - ((PreviewImage *)(icon->obj))->icon_id = 0; - } - else if (icon->obj_type == ICON_DATA_GPLAYER) { - ((bGPDlayer *)(icon->obj))->runtime.icon_id = 0; - } - else if (icon->obj_type == ICON_DATA_GEOM) { - ((struct Icon_Geom *)(icon->obj))->icon_id = 0; - } - else if (icon->obj_type == ICON_DATA_STUDIOLIGHT) { - StudioLight *sl = icon->obj; - if (sl != NULL) { - BKE_studiolight_unset_icon_id(sl, icon_id); - } - } - else { - BLI_assert(0); - } -} - -/* create an id for a new icon and make sure that ids from deleted icons get reused - * after the integer number range is used up */ -static int get_next_free_id(void) -{ - BLI_assert(BLI_thread_is_main()); - int startId = gFirstIconId; - - /* if we haven't used up the int number range, we just return the next int */ - if (gNextIconId >= gFirstIconId) { - return gNextIconId++; - } - - /* now we try to find the smallest icon id not stored in the gIcons hash */ - while (BLI_ghash_lookup(gIcons, POINTER_FROM_INT(startId)) && startId >= gFirstIconId) { - startId++; - } - - /* if we found a suitable one that isn't used yet, return it */ - if (startId >= gFirstIconId) { - return startId; - } - - /* fail */ - return 0; -} - -void BKE_icons_init(int first_dyn_id) -{ - BLI_assert(BLI_thread_is_main()); - - gNextIconId = first_dyn_id; - gFirstIconId = first_dyn_id; - - if (!gIcons) { - gIcons = BLI_ghash_int_new(__func__); - BLI_linklist_lockfree_init(&g_icon_delete_queue); - } - - if (!gCachedPreviews) { - gCachedPreviews = BLI_ghash_str_new(__func__); - } -} - -void BKE_icons_free(void) -{ - BLI_assert(BLI_thread_is_main()); - - if (gIcons) { - BLI_ghash_free(gIcons, NULL, icon_free); - gIcons = NULL; - } - - if (gCachedPreviews) { - BLI_ghash_free(gCachedPreviews, MEM_freeN, BKE_previewimg_freefunc); - gCachedPreviews = NULL; - } - - BLI_linklist_lockfree_free(&g_icon_delete_queue, MEM_freeN); -} - -void BKE_icons_deferred_free(void) -{ - BLI_assert(BLI_thread_is_main()); - - for (DeferredIconDeleteNode *node = - (DeferredIconDeleteNode *)BLI_linklist_lockfree_begin(&g_icon_delete_queue); - node != NULL; - node = node->next) { - BLI_ghash_remove(gIcons, POINTER_FROM_INT(node->icon_id), NULL, icon_free); - } - BLI_linklist_lockfree_clear(&g_icon_delete_queue, MEM_freeN); -} - -static PreviewImage *previewimg_create_ex(size_t deferred_data_size) -{ - PreviewImage *prv_img = MEM_mallocN(sizeof(PreviewImage) + deferred_data_size, "img_prv"); - memset(prv_img, 0, sizeof(*prv_img)); /* leave deferred data dirty */ - - if (deferred_data_size) { - prv_img->tag |= PRV_TAG_DEFFERED; - } - - for (int i = 0; i < NUM_ICON_SIZES; i++) { - prv_img->flag[i] |= PRV_CHANGED; - prv_img->changed_timestamp[i] = 0; - } - return prv_img; -} - -static PreviewImage *previewimg_deferred_create(const char *path, int source) -{ - /* We pack needed data for lazy loading (source type, in a single char, and path). */ - const size_t deferred_data_size = strlen(path) + 2; - char *deferred_data; - - PreviewImage *prv = previewimg_create_ex(deferred_data_size); - deferred_data = (char *)PRV_DEFERRED_DATA(prv); - deferred_data[0] = source; - memcpy(&deferred_data[1], path, deferred_data_size - 1); - - return prv; -} - -PreviewImage *BKE_previewimg_create(void) -{ - return previewimg_create_ex(0); -} - -void BKE_previewimg_freefunc(void *link) -{ - PreviewImage *prv = (PreviewImage *)link; - if (prv) { - for (int i = 0; i < NUM_ICON_SIZES; i++) { - if (prv->rect[i]) { - MEM_freeN(prv->rect[i]); - } - if (prv->gputexture[i]) { - GPU_texture_free(prv->gputexture[i]); - } - } - - MEM_freeN(prv); - } -} - -void BKE_previewimg_free(PreviewImage **prv) -{ - if (prv && (*prv)) { - BKE_previewimg_freefunc(*prv); - *prv = NULL; - } -} - -void BKE_previewimg_clear_single(struct PreviewImage *prv, enum eIconSizes size) -{ - MEM_SAFE_FREE(prv->rect[size]); - if (prv->gputexture[size]) { - GPU_texture_free(prv->gputexture[size]); - } - prv->h[size] = prv->w[size] = 0; - prv->flag[size] |= PRV_CHANGED; - prv->flag[size] &= ~PRV_USER_EDITED; - prv->changed_timestamp[size] = 0; -} - -void BKE_previewimg_clear(struct PreviewImage *prv) -{ - for (int i = 0; i < NUM_ICON_SIZES; i++) { - BKE_previewimg_clear_single(prv, i); - } -} - -PreviewImage *BKE_previewimg_copy(const PreviewImage *prv) -{ - PreviewImage *prv_img = NULL; - - if (prv) { - prv_img = MEM_dupallocN(prv); - for (int i = 0; i < NUM_ICON_SIZES; i++) { - if (prv->rect[i]) { - prv_img->rect[i] = MEM_dupallocN(prv->rect[i]); - } - prv_img->gputexture[i] = NULL; - } - } - return prv_img; -} - -/** - * Duplicate preview image from \a id and clear icon_id, - * to be used by datablock copy functions. - */ -void BKE_previewimg_id_copy(ID *new_id, const ID *old_id) -{ - PreviewImage **old_prv_p = BKE_previewimg_id_get_p(old_id); - PreviewImage **new_prv_p = BKE_previewimg_id_get_p(new_id); - - if (old_prv_p && *old_prv_p) { - BLI_assert(new_prv_p != NULL && ELEM(*new_prv_p, NULL, *old_prv_p)); - // const int new_icon_id = get_next_free_id(); - - // if (new_icon_id == 0) { - // return; /* Failure. */ - // } - *new_prv_p = BKE_previewimg_copy(*old_prv_p); - new_id->icon_id = (*new_prv_p)->icon_id = 0; - } -} - -PreviewImage **BKE_previewimg_id_get_p(const ID *id) -{ - switch (GS(id->name)) { -#define ID_PRV_CASE(id_code, id_struct) \ - case id_code: { \ - return &((id_struct *)id)->preview; \ - } \ - ((void)0) - ID_PRV_CASE(ID_MA, Material); - ID_PRV_CASE(ID_TE, Tex); - ID_PRV_CASE(ID_WO, World); - ID_PRV_CASE(ID_LA, Light); - ID_PRV_CASE(ID_IM, Image); - ID_PRV_CASE(ID_BR, Brush); - // ID_PRV_CASE(ID_OB, Object); - ID_PRV_CASE(ID_GR, Collection); - ID_PRV_CASE(ID_SCE, Scene); - ID_PRV_CASE(ID_SCR, bScreen); -#undef ID_PRV_CASE - default: - break; - } - - return NULL; -} - -PreviewImage *BKE_previewimg_id_get(const ID *id) -{ - PreviewImage **prv_p = BKE_previewimg_id_get_p(id); - return prv_p ? *prv_p : NULL; -} - -void BKE_previewimg_id_free(ID *id) -{ - PreviewImage **prv_p = BKE_previewimg_id_get_p(id); - if (prv_p) { - BKE_previewimg_free(prv_p); - } -} - -PreviewImage *BKE_previewimg_id_ensure(ID *id) -{ - PreviewImage **prv_p = BKE_previewimg_id_get_p(id); - - if (prv_p) { - if (*prv_p == NULL) { - *prv_p = BKE_previewimg_create(); - } - return *prv_p; - } - - return NULL; -} - -void BKE_previewimg_deferred_release(PreviewImage *prv) -{ - if (prv) { - if (prv->tag & PRV_TAG_DEFFERED_RENDERING) { - /* We cannot delete the preview while it is being loaded in another thread... */ - prv->tag |= PRV_TAG_DEFFERED_DELETE; - return; - } - if (prv->icon_id) { - BKE_icon_delete(prv->icon_id); - } - BKE_previewimg_freefunc(prv); - } -} - -void BKE_previewimg_id_custom_set(ID *id, const char *path) -{ - PreviewImage **prv = BKE_previewimg_id_get_p(id); - - /* Thumbnail previews must use the deferred pipeline. But we force them to be immediately - * generated here still. */ - - if (*prv) { - BKE_previewimg_deferred_release(*prv); - } - *prv = previewimg_deferred_create(path, THB_SOURCE_IMAGE); - - /* Can't lazy-render the preview on access. ID previews are saved to files and we want them to be - * there in time. Not only if something happened to have accessed it meanwhile. */ - for (int i = 0; i < NUM_ICON_SIZES; i++) { - BKE_previewimg_ensure(*prv, i); - /* Prevent auto-updates. */ - (*prv)->flag[i] |= PRV_USER_EDITED; - } -} - -PreviewImage *BKE_previewimg_cached_get(const char *name) -{ - return BLI_ghash_lookup(gCachedPreviews, name); -} - -/** - * Generate an empty PreviewImage, if not yet existing. - */ -PreviewImage *BKE_previewimg_cached_ensure(const char *name) -{ - PreviewImage *prv = NULL; - void **key_p, **prv_p; - - if (!BLI_ghash_ensure_p_ex(gCachedPreviews, name, &key_p, &prv_p)) { - *key_p = BLI_strdup(name); - *prv_p = BKE_previewimg_create(); - } - prv = *prv_p; - BLI_assert(prv); - - return prv; -} - -/** - * Generate a PreviewImage from given file path, using thumbnails management, if not yet existing. - */ -PreviewImage *BKE_previewimg_cached_thumbnail_read(const char *name, - const char *path, - const int source, - bool force_update) -{ - PreviewImage *prv = NULL; - void **prv_p; - - prv_p = BLI_ghash_lookup_p(gCachedPreviews, name); - - if (prv_p) { - prv = *prv_p; - BLI_assert(prv); - } - - if (prv && force_update) { - const char *prv_deferred_data = PRV_DEFERRED_DATA(prv); - if (((int)prv_deferred_data[0] == source) && STREQ(&prv_deferred_data[1], path)) { - /* If same path, no need to re-allocate preview, just clear it up. */ - BKE_previewimg_clear(prv); - } - else { - BKE_previewimg_free(&prv); - } - } - - if (!prv) { - prv = previewimg_deferred_create(path, source); - force_update = true; - } - - if (force_update) { - if (prv_p) { - *prv_p = prv; - } - else { - BLI_ghash_insert(gCachedPreviews, BLI_strdup(name), prv); - } - } - - return prv; -} - -void BKE_previewimg_cached_release(const char *name) -{ - PreviewImage *prv = BLI_ghash_popkey(gCachedPreviews, name, MEM_freeN); - - BKE_previewimg_deferred_release(prv); -} - -/** - * Handle deferred (lazy) loading/generation of preview image, if needed. - * For now, only used with file thumbnails. - */ -void BKE_previewimg_ensure(PreviewImage *prv, const int size) -{ - if ((prv->tag & PRV_TAG_DEFFERED) != 0) { - const bool do_icon = ((size == ICON_SIZE_ICON) && !prv->rect[ICON_SIZE_ICON]); - const bool do_preview = ((size == ICON_SIZE_PREVIEW) && !prv->rect[ICON_SIZE_PREVIEW]); - - if (do_icon || do_preview) { - ImBuf *thumb; - char *prv_deferred_data = PRV_DEFERRED_DATA(prv); - int source = prv_deferred_data[0]; - char *path = &prv_deferred_data[1]; - int icon_w, icon_h; - - thumb = IMB_thumb_manage(path, THB_LARGE, source); - - if (thumb) { - /* PreviewImage assumes premultiplied alhpa... */ - IMB_premultiply_alpha(thumb); - - if (do_preview) { - prv->w[ICON_SIZE_PREVIEW] = thumb->x; - prv->h[ICON_SIZE_PREVIEW] = thumb->y; - prv->rect[ICON_SIZE_PREVIEW] = MEM_dupallocN(thumb->rect); - prv->flag[ICON_SIZE_PREVIEW] &= ~(PRV_CHANGED | PRV_USER_EDITED); - } - if (do_icon) { - if (thumb->x > thumb->y) { - icon_w = ICON_RENDER_DEFAULT_HEIGHT; - icon_h = (thumb->y * icon_w) / thumb->x + 1; - } - else if (thumb->x < thumb->y) { - icon_h = ICON_RENDER_DEFAULT_HEIGHT; - icon_w = (thumb->x * icon_h) / thumb->y + 1; - } - else { - icon_w = icon_h = ICON_RENDER_DEFAULT_HEIGHT; - } - - IMB_scaleImBuf(thumb, icon_w, icon_h); - prv->w[ICON_SIZE_ICON] = icon_w; - prv->h[ICON_SIZE_ICON] = icon_h; - prv->rect[ICON_SIZE_ICON] = MEM_dupallocN(thumb->rect); - prv->flag[ICON_SIZE_ICON] &= ~(PRV_CHANGED | PRV_USER_EDITED); - } - IMB_freeImBuf(thumb); - } - } - } -} - -void BKE_previewimg_blend_write(BlendWriter *writer, const PreviewImage *prv) -{ - /* Note we write previews also for undo steps. It takes up some memory, - * but not doing so would causes all previews to be re-rendered after - * undo which is too expensive. */ - - if (prv == NULL) { - return; - } - - PreviewImage prv_copy = *prv; - /* don't write out large previews if not requested */ - if (!(U.flag & USER_SAVE_PREVIEWS)) { - prv_copy.w[1] = 0; - prv_copy.h[1] = 0; - prv_copy.rect[1] = NULL; - } - BLO_write_struct_at_address(writer, PreviewImage, prv, &prv_copy); - if (prv_copy.rect[0]) { - BLO_write_uint32_array(writer, prv_copy.w[0] * prv_copy.h[0], prv_copy.rect[0]); - } - if (prv_copy.rect[1]) { - BLO_write_uint32_array(writer, prv_copy.w[1] * prv_copy.h[1], prv_copy.rect[1]); - } -} - -void BKE_previewimg_blend_read(BlendDataReader *reader, PreviewImage *prv) -{ - if (prv == NULL) { - return; - } - - for (int i = 0; i < NUM_ICON_SIZES; i++) { - if (prv->rect[i]) { - BLO_read_data_address(reader, &prv->rect[i]); - } - prv->gputexture[i] = NULL; - } - prv->icon_id = 0; - prv->tag = 0; -} - -void BKE_icon_changed(const int icon_id) -{ - BLI_assert(BLI_thread_is_main()); - - Icon *icon = NULL; - - if (!icon_id || G.background) { - return; - } - - icon = BLI_ghash_lookup(gIcons, POINTER_FROM_INT(icon_id)); - - if (icon) { - /* We *only* expect ID-tied icons here, not non-ID icon/preview! */ - BLI_assert(icon->id_type != 0); - BLI_assert(icon->obj_type == ICON_DATA_ID); - - /* Do not enforce creation of previews for valid ID types using BKE_previewimg_id_ensure() - * here, we only want to ensure *existing* preview images are properly tagged as - * changed/invalid, that's all. */ - PreviewImage **p_prv = BKE_previewimg_id_get_p((ID *)icon->obj); - - /* If we have previews, they all are now invalid changed. */ - if (p_prv && *p_prv) { - for (int i = 0; i < NUM_ICON_SIZES; i++) { - (*p_prv)->flag[i] |= PRV_CHANGED; - (*p_prv)->changed_timestamp[i]++; - } - } - } -} - -static Icon *icon_create(int icon_id, int obj_type, void *obj) -{ - Icon *new_icon = MEM_mallocN(sizeof(Icon), __func__); - - new_icon->obj_type = obj_type; - new_icon->obj = obj; - new_icon->id_type = 0; - new_icon->flag = 0; - - /* next two lines make sure image gets created */ - new_icon->drawinfo = NULL; - new_icon->drawinfo_free = NULL; - - BLI_ghash_insert(gIcons, POINTER_FROM_INT(icon_id), new_icon); - - return new_icon; -} - -static int icon_id_ensure_create_icon(struct ID *id) -{ - BLI_assert(BLI_thread_is_main()); - - Icon *icon = icon_create(id->icon_id, ICON_DATA_ID, id); - icon->id_type = GS(id->name); - icon->flag = ICON_FLAG_MANAGED; - - return id->icon_id; -} - -int BKE_icon_id_ensure(struct ID *id) -{ - /* Never handle icons in non-main thread! */ - BLI_assert(BLI_thread_is_main()); - - if (!id || G.background) { - return 0; - } - - if (id->icon_id) { - return id->icon_id; - } - - id->icon_id = get_next_free_id(); - - if (!id->icon_id) { - CLOG_ERROR(&LOG, "not enough IDs"); - return 0; - } - - /* Ensure we synchronize ID icon_id with its previewimage if it has one. */ - PreviewImage **p_prv = BKE_previewimg_id_get_p(id); - if (p_prv && *p_prv) { - BLI_assert(ELEM((*p_prv)->icon_id, 0, id->icon_id)); - (*p_prv)->icon_id = id->icon_id; - } - - return icon_id_ensure_create_icon(id); -} - -static int icon_gplayer_color_ensure_create_icon(bGPDlayer *gpl) -{ - BLI_assert(BLI_thread_is_main()); - - /* NOTE: The color previews for GP Layers don't really need - * to be "rendered" to image per se (as it will just be a plain - * colored rectangle), we need to define icon data here so that - * we can store a pointer to the layer data in icon->obj. - */ - Icon *icon = icon_create(gpl->runtime.icon_id, ICON_DATA_GPLAYER, gpl); - icon->flag = ICON_FLAG_MANAGED; - - return gpl->runtime.icon_id; -} - -int BKE_icon_gplayer_color_ensure(bGPDlayer *gpl) -{ - /* Never handle icons in non-main thread! */ - BLI_assert(BLI_thread_is_main()); - - if (!gpl || G.background) { - return 0; - } - - if (gpl->runtime.icon_id) { - return gpl->runtime.icon_id; - } - - gpl->runtime.icon_id = get_next_free_id(); - - if (!gpl->runtime.icon_id) { - CLOG_ERROR(&LOG, "not enough IDs"); - return 0; - } - - return icon_gplayer_color_ensure_create_icon(gpl); -} - -/** - * Return icon id of given preview, or create new icon if not found. - */ -int BKE_icon_preview_ensure(ID *id, PreviewImage *preview) -{ - if (!preview || G.background) { - return 0; - } - - if (id) { - BLI_assert(BKE_previewimg_id_ensure(id) == preview); - } - - if (preview->icon_id) { - BLI_assert(!id || !id->icon_id || id->icon_id == preview->icon_id); - return preview->icon_id; - } - - if (id && id->icon_id) { - preview->icon_id = id->icon_id; - return preview->icon_id; - } - - preview->icon_id = get_next_free_id(); - - if (!preview->icon_id) { - CLOG_ERROR(&LOG, "not enough IDs"); - return 0; - } - - /* Ensure we synchronize ID icon_id with its previewimage if available, - * and generate suitable 'ID' icon. */ - if (id) { - id->icon_id = preview->icon_id; - return icon_id_ensure_create_icon(id); - } - - Icon *icon = icon_create(preview->icon_id, ICON_DATA_PREVIEW, preview); - icon->flag = ICON_FLAG_MANAGED; - - return preview->icon_id; -} - -Icon *BKE_icon_get(const int icon_id) -{ - BLI_assert(BLI_thread_is_main()); - - Icon *icon = NULL; - - icon = BLI_ghash_lookup(gIcons, POINTER_FROM_INT(icon_id)); - - if (!icon) { - CLOG_ERROR(&LOG, "no icon for icon ID: %d", icon_id); - return NULL; - } - - return icon; -} - -void BKE_icon_set(const int icon_id, struct Icon *icon) -{ - BLI_assert(BLI_thread_is_main()); - - void **val_p; - - if (BLI_ghash_ensure_p(gIcons, POINTER_FROM_INT(icon_id), &val_p)) { - CLOG_ERROR(&LOG, "icon already set: %d", icon_id); - return; - } - - *val_p = icon; -} - -static void icon_add_to_deferred_delete_queue(int icon_id) -{ - DeferredIconDeleteNode *node = MEM_mallocN(sizeof(DeferredIconDeleteNode), __func__); - node->icon_id = icon_id; - BLI_linklist_lockfree_insert(&g_icon_delete_queue, (LockfreeLinkNode *)node); -} - -void BKE_icon_id_delete(struct ID *id) -{ - const int icon_id = id->icon_id; - if (!icon_id) { - return; /* no icon defined for library object */ - } - id->icon_id = 0; - - if (!BLI_thread_is_main()) { - icon_add_to_deferred_delete_queue(icon_id); - return; - } - - BKE_icons_deferred_free(); - BLI_ghash_remove(gIcons, POINTER_FROM_INT(icon_id), NULL, icon_free); -} - -/** - * Remove icon and free data. - */ -bool BKE_icon_delete(const int icon_id) -{ - if (icon_id == 0) { - /* no icon defined for library object */ - return false; - } - - Icon *icon = BLI_ghash_popkey(gIcons, POINTER_FROM_INT(icon_id), NULL); - if (icon) { - icon_free_data(icon_id, icon); - icon_free(icon); - return true; - } - - return false; -} - -bool BKE_icon_delete_unmanaged(const int icon_id) -{ - if (icon_id == 0) { - /* no icon defined for library object */ - return false; - } - - Icon *icon = BLI_ghash_popkey(gIcons, POINTER_FROM_INT(icon_id), NULL); - if (icon) { - if (UNLIKELY(icon->flag & ICON_FLAG_MANAGED)) { - BLI_ghash_insert(gIcons, POINTER_FROM_INT(icon_id), icon); - return false; - } - - icon_free_data(icon_id, icon); - icon_free(icon); - return true; - } - - return false; -} - -/* -------------------------------------------------------------------- */ -/** \name Geometry Icon - * \{ */ - -int BKE_icon_geom_ensure(struct Icon_Geom *geom) -{ - BLI_assert(BLI_thread_is_main()); - - if (geom->icon_id) { - return geom->icon_id; - } - - geom->icon_id = get_next_free_id(); - - icon_create(geom->icon_id, ICON_DATA_GEOM, geom); - /* Not managed for now, we may want this to be configurable per icon). */ - - return geom->icon_id; -} - -struct Icon_Geom *BKE_icon_geom_from_memory(const uchar *data, size_t data_len) -{ - BLI_assert(BLI_thread_is_main()); - if (data_len <= 8) { - goto fail; - } - /* Skip the header. */ - data_len -= 8; - const int div = 3 * 2 * 3; - const int coords_len = data_len / div; - if (coords_len * div != data_len) { - goto fail; - } - - const uchar header[4] = {'V', 'C', 'O', 0}; - const uchar *p = data; - if (memcmp(p, header, ARRAY_SIZE(header)) != 0) { - goto fail; - } - p += 4; - - struct Icon_Geom *geom = MEM_mallocN(sizeof(*geom), __func__); - geom->coords_range[0] = (int)*p++; - geom->coords_range[1] = (int)*p++; - /* x, y ignored for now */ - p += 2; - - geom->coords_len = coords_len; - geom->coords = (void *)p; - geom->colors = (void *)(p + (data_len / 3)); - geom->icon_id = 0; - geom->mem = data; - return geom; - -fail: - MEM_freeN((void *)data); - return NULL; -} - -struct Icon_Geom *BKE_icon_geom_from_file(const char *filename) -{ - BLI_assert(BLI_thread_is_main()); - size_t data_len; - uchar *data = BLI_file_read_binary_as_mem(filename, 0, &data_len); - if (data == NULL) { - return NULL; - } - return BKE_icon_geom_from_memory(data, data_len); -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Studio Light Icon - * \{ */ - -int BKE_icon_ensure_studio_light(struct StudioLight *sl, int id_type) -{ - int icon_id = get_next_free_id(); - Icon *icon = icon_create(icon_id, ICON_DATA_STUDIOLIGHT, sl); - icon->id_type = id_type; - return icon_id; -} -/** \} */ diff --git a/source/blender/blenkernel/intern/icons.cc b/source/blender/blenkernel/intern/icons.cc new file mode 100644 index 00000000000..b92b2259eeb --- /dev/null +++ b/source/blender/blenkernel/intern/icons.cc @@ -0,0 +1,1053 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2006-2007 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup bke + */ + +#include +#include +#include +#include + +#include "CLG_log.h" + +#include "MEM_guardedalloc.h" + +#include "DNA_brush_types.h" +#include "DNA_collection_types.h" +#include "DNA_gpencil_types.h" +#include "DNA_light_types.h" +#include "DNA_material_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" +#include "DNA_screen_types.h" +#include "DNA_texture_types.h" +#include "DNA_world_types.h" + +#include "BLI_fileops.h" +#include "BLI_ghash.h" +#include "BLI_linklist_lockfree.h" +#include "BLI_string.h" +#include "BLI_threads.h" +#include "BLI_utildefines.h" +#include "BLI_vector.hh" + +#include "BKE_global.h" /* only for G.background test */ +#include "BKE_icons.h" +#include "BKE_studiolight.h" + +#include "BLI_sys_types.h" /* for intptr_t support */ + +#include "GPU_texture.h" + +#include "IMB_imbuf.h" +#include "IMB_imbuf_types.h" +#include "IMB_thumbs.h" + +#include "BLO_read_write.h" + +#include "atomic_ops.h" + +/** + * Only allow non-managed icons to be removed (by Python for eg). + * Previews & ID's have their own functions to remove icons. + */ +enum { + ICON_FLAG_MANAGED = (1 << 0), +}; + +/* GLOBALS */ + +static CLG_LogRef LOG = {"bke.icons"}; + +/* Protected by gIconMutex. */ +static GHash *gIcons = NULL; + +/* Protected by gIconMutex. */ +static int gNextIconId = 1; + +/* Protected by gIconMutex. */ +static int gFirstIconId = 1; + +std::mutex gIconMutex; + +/* Not mutex-protected! */ +static GHash *gCachedPreviews = NULL; + +/* Queue of icons for deferred deletion. */ +typedef struct DeferredIconDeleteNode { + struct DeferredIconDeleteNode *next; + int icon_id; +} DeferredIconDeleteNode; +/* Protected by gIconMutex. */ +static LockfreeLinkList g_icon_delete_queue; + +static void icon_free(void *val) +{ + Icon *icon = (Icon *)val; + + if (icon) { + if (icon->obj_type == ICON_DATA_GEOM) { + struct Icon_Geom *obj = (struct Icon_Geom *)icon->obj; + if (obj->mem) { + /* coords & colors are part of this memory. */ + MEM_freeN((void *)obj->mem); + } + else { + MEM_freeN((void *)obj->coords); + MEM_freeN((void *)obj->colors); + } + MEM_freeN(icon->obj); + } + + if (icon->drawinfo_free) { + icon->drawinfo_free(icon->drawinfo); + } + else if (icon->drawinfo) { + MEM_freeN(icon->drawinfo); + } + MEM_freeN(icon); + } +} + +static void icon_free_data(int icon_id, Icon *icon) +{ + if (icon->obj_type == ICON_DATA_ID) { + ((ID *)(icon->obj))->icon_id = 0; + } + else if (icon->obj_type == ICON_DATA_IMBUF) { + ImBuf *imbuf = (ImBuf *)icon->obj; + if (imbuf) { + IMB_freeImBuf(imbuf); + } + } + else if (icon->obj_type == ICON_DATA_PREVIEW) { + ((PreviewImage *)(icon->obj))->icon_id = 0; + } + else if (icon->obj_type == ICON_DATA_GPLAYER) { + ((bGPDlayer *)(icon->obj))->runtime.icon_id = 0; + } + else if (icon->obj_type == ICON_DATA_GEOM) { + ((struct Icon_Geom *)(icon->obj))->icon_id = 0; + } + else if (icon->obj_type == ICON_DATA_STUDIOLIGHT) { + StudioLight *sl = (StudioLight *)icon->obj; + if (sl != NULL) { + BKE_studiolight_unset_icon_id(sl, icon_id); + } + } + else { + BLI_assert(0); + } +} + +static Icon *icon_ghash_lookup(int icon_id) +{ + std::scoped_lock lock(gIconMutex); + return (Icon *)BLI_ghash_lookup(gIcons, POINTER_FROM_INT(icon_id)); +} + +/* create an id for a new icon and make sure that ids from deleted icons get reused + * after the integer number range is used up */ +static int get_next_free_id(void) +{ + std::scoped_lock lock(gIconMutex); + int startId = gFirstIconId; + + /* if we haven't used up the int number range, we just return the next int */ + if (gNextIconId >= gFirstIconId) { + int next_id = gNextIconId++; + return next_id; + } + + /* Now we try to find the smallest icon id not stored in the gIcons hash. + * Don't use icon_ghash_lookup here, it would lock recursively (dead-lock). */ + while (BLI_ghash_lookup(gIcons, POINTER_FROM_INT(startId)) && startId >= gFirstIconId) { + startId++; + } + + /* if we found a suitable one that isn't used yet, return it */ + if (startId >= gFirstIconId) { + return startId; + } + + /* fail */ + return 0; +} + +void BKE_icons_init(int first_dyn_id) +{ + BLI_assert(BLI_thread_is_main()); + + gNextIconId = first_dyn_id; + gFirstIconId = first_dyn_id; + + if (!gIcons) { + gIcons = BLI_ghash_int_new(__func__); + BLI_linklist_lockfree_init(&g_icon_delete_queue); + } + + if (!gCachedPreviews) { + gCachedPreviews = BLI_ghash_str_new(__func__); + } +} + +void BKE_icons_free(void) +{ + BLI_assert(BLI_thread_is_main()); + + if (gIcons) { + BLI_ghash_free(gIcons, NULL, icon_free); + gIcons = NULL; + } + + if (gCachedPreviews) { + BLI_ghash_free(gCachedPreviews, MEM_freeN, BKE_previewimg_freefunc); + gCachedPreviews = NULL; + } + + BLI_linklist_lockfree_free(&g_icon_delete_queue, MEM_freeN); +} + +void BKE_icons_deferred_free(void) +{ + std::scoped_lock lock(gIconMutex); + + for (DeferredIconDeleteNode *node = + (DeferredIconDeleteNode *)BLI_linklist_lockfree_begin(&g_icon_delete_queue); + node != NULL; + node = node->next) { + BLI_ghash_remove(gIcons, POINTER_FROM_INT(node->icon_id), NULL, icon_free); + } + BLI_linklist_lockfree_clear(&g_icon_delete_queue, MEM_freeN); +} + +static PreviewImage *previewimg_create_ex(size_t deferred_data_size) +{ + PreviewImage *prv_img = (PreviewImage *)MEM_mallocN(sizeof(PreviewImage) + deferred_data_size, + "img_prv"); + memset(prv_img, 0, sizeof(*prv_img)); /* leave deferred data dirty */ + + if (deferred_data_size) { + prv_img->tag |= PRV_TAG_DEFFERED; + } + + for (int i = 0; i < NUM_ICON_SIZES; i++) { + prv_img->flag[i] |= (PRV_CHANGED | PRV_UNFINISHED); + prv_img->changed_timestamp[i] = 0; + } + return prv_img; +} + +static PreviewImage *previewimg_deferred_create(const char *path, int source) +{ + /* We pack needed data for lazy loading (source type, in a single char, and path). */ + const size_t deferred_data_size = strlen(path) + 2; + char *deferred_data; + + PreviewImage *prv = previewimg_create_ex(deferred_data_size); + deferred_data = (char *)PRV_DEFERRED_DATA(prv); + deferred_data[0] = source; + memcpy(&deferred_data[1], path, deferred_data_size - 1); + + return prv; +} + +PreviewImage *BKE_previewimg_create(void) +{ + return previewimg_create_ex(0); +} + +void BKE_previewimg_freefunc(void *link) +{ + PreviewImage *prv = (PreviewImage *)link; + if (prv) { + for (int i = 0; i < NUM_ICON_SIZES; i++) { + if (prv->rect[i]) { + MEM_freeN(prv->rect[i]); + } + if (prv->gputexture[i]) { + GPU_texture_free(prv->gputexture[i]); + } + } + + MEM_freeN(prv); + } +} + +void BKE_previewimg_free(PreviewImage **prv) +{ + if (prv && (*prv)) { + BKE_previewimg_freefunc(*prv); + *prv = NULL; + } +} + +void BKE_previewimg_clear_single(struct PreviewImage *prv, enum eIconSizes size) +{ + MEM_SAFE_FREE(prv->rect[size]); + if (prv->gputexture[size]) { + GPU_texture_free(prv->gputexture[size]); + } + prv->h[size] = prv->w[size] = 0; + prv->flag[size] |= (PRV_CHANGED | PRV_UNFINISHED); + prv->flag[size] &= ~PRV_USER_EDITED; + prv->changed_timestamp[size] = 0; +} + +void BKE_previewimg_clear(struct PreviewImage *prv) +{ + for (int i = 0; i < NUM_ICON_SIZES; i++) { + BKE_previewimg_clear_single(prv, (eIconSizes)i); + } +} + +PreviewImage *BKE_previewimg_copy(const PreviewImage *prv) +{ + PreviewImage *prv_img = NULL; + + if (prv) { + prv_img = (PreviewImage *)MEM_dupallocN(prv); + for (int i = 0; i < NUM_ICON_SIZES; i++) { + if (prv->rect[i]) { + prv_img->rect[i] = (uint *)MEM_dupallocN(prv->rect[i]); + } + prv_img->gputexture[i] = NULL; + } + } + return prv_img; +} + +/** + * Duplicate preview image from \a id and clear icon_id, + * to be used by datablock copy functions. + */ +void BKE_previewimg_id_copy(ID *new_id, const ID *old_id) +{ + PreviewImage **old_prv_p = BKE_previewimg_id_get_p(old_id); + PreviewImage **new_prv_p = BKE_previewimg_id_get_p(new_id); + + if (old_prv_p && *old_prv_p) { + BLI_assert(new_prv_p != NULL && ELEM(*new_prv_p, NULL, *old_prv_p)); + // const int new_icon_id = get_next_free_id(); + + // if (new_icon_id == 0) { + // return; /* Failure. */ + // } + *new_prv_p = BKE_previewimg_copy(*old_prv_p); + new_id->icon_id = (*new_prv_p)->icon_id = 0; + } +} + +PreviewImage **BKE_previewimg_id_get_p(const ID *id) +{ + switch (GS(id->name)) { +#define ID_PRV_CASE(id_code, id_struct) \ + case id_code: { \ + return &((id_struct *)id)->preview; \ + } \ + ((void)0) + ID_PRV_CASE(ID_MA, Material); + ID_PRV_CASE(ID_TE, Tex); + ID_PRV_CASE(ID_WO, World); + ID_PRV_CASE(ID_LA, Light); + ID_PRV_CASE(ID_IM, Image); + ID_PRV_CASE(ID_BR, Brush); + ID_PRV_CASE(ID_OB, Object); + ID_PRV_CASE(ID_GR, Collection); + ID_PRV_CASE(ID_SCE, Scene); + ID_PRV_CASE(ID_SCR, bScreen); +#undef ID_PRV_CASE + default: + break; + } + + return NULL; +} + +PreviewImage *BKE_previewimg_id_get(const ID *id) +{ + PreviewImage **prv_p = BKE_previewimg_id_get_p(id); + return prv_p ? *prv_p : NULL; +} + +void BKE_previewimg_id_free(ID *id) +{ + PreviewImage **prv_p = BKE_previewimg_id_get_p(id); + if (prv_p) { + BKE_previewimg_free(prv_p); + } +} + +PreviewImage *BKE_previewimg_id_ensure(ID *id) +{ + PreviewImage **prv_p = BKE_previewimg_id_get_p(id); + + if (prv_p) { + if (*prv_p == NULL) { + *prv_p = BKE_previewimg_create(); + } + return *prv_p; + } + + return NULL; +} + +void BKE_previewimg_id_custom_set(ID *id, const char *path) +{ + PreviewImage **prv = BKE_previewimg_id_get_p(id); + + /* Thumbnail previews must use the deferred pipeline. But we force them to be immediately + * generated here still. */ + + if (*prv) { + BKE_previewimg_deferred_release(*prv); + } + *prv = previewimg_deferred_create(path, THB_SOURCE_IMAGE); + + /* Can't lazy-render the preview on access. ID previews are saved to files and we want them to be + * there in time. Not only if something happened to have accessed it meanwhile. */ + for (int i = 0; i < NUM_ICON_SIZES; i++) { + BKE_previewimg_ensure(*prv, i); + /* Prevent auto-updates. */ + (*prv)->flag[i] |= PRV_USER_EDITED; + } +} + +bool BKE_previewimg_id_supports_jobs(const ID *id) +{ + return ELEM(GS(id->name), ID_OB, ID_MA, ID_TE, ID_LA, ID_WO, ID_IM, ID_BR); +} + +void BKE_previewimg_deferred_release(PreviewImage *prv) +{ + if (prv) { + if (prv->tag & PRV_TAG_DEFFERED_RENDERING) { + /* We cannot delete the preview while it is being loaded in another thread... */ + prv->tag |= PRV_TAG_DEFFERED_DELETE; + return; + } + if (prv->icon_id) { + BKE_icon_delete(prv->icon_id); + } + BKE_previewimg_freefunc(prv); + } +} + +PreviewImage *BKE_previewimg_cached_get(const char *name) +{ + BLI_assert(BLI_thread_is_main()); + return (PreviewImage *)BLI_ghash_lookup(gCachedPreviews, name); +} + +/** + * Generate an empty PreviewImage, if not yet existing. + */ +PreviewImage *BKE_previewimg_cached_ensure(const char *name) +{ + BLI_assert(BLI_thread_is_main()); + + PreviewImage *prv = NULL; + void **key_p, **prv_p; + + if (!BLI_ghash_ensure_p_ex(gCachedPreviews, name, &key_p, &prv_p)) { + *key_p = BLI_strdup(name); + *prv_p = BKE_previewimg_create(); + } + prv = *(PreviewImage **)prv_p; + BLI_assert(prv); + + return prv; +} + +/** + * Generate a PreviewImage from given file path, using thumbnails management, if not yet existing. + * Does not actually generate the preview, #BKE_previewimg_ensure() must be called for that. + */ +PreviewImage *BKE_previewimg_cached_thumbnail_read(const char *name, + const char *path, + const int source, + bool force_update) +{ + BLI_assert(BLI_thread_is_main()); + + PreviewImage *prv = NULL; + void **prv_p; + + prv_p = BLI_ghash_lookup_p(gCachedPreviews, name); + + if (prv_p) { + prv = *(PreviewImage **)prv_p; + BLI_assert(prv); + } + + if (prv && force_update) { + const char *prv_deferred_data = (char *)PRV_DEFERRED_DATA(prv); + if (((int)prv_deferred_data[0] == source) && STREQ(&prv_deferred_data[1], path)) { + /* If same path, no need to re-allocate preview, just clear it up. */ + BKE_previewimg_clear(prv); + } + else { + BKE_previewimg_free(&prv); + } + } + + if (!prv) { + prv = previewimg_deferred_create(path, source); + force_update = true; + } + + if (force_update) { + if (prv_p) { + *prv_p = prv; + } + else { + BLI_ghash_insert(gCachedPreviews, BLI_strdup(name), prv); + } + } + + return prv; +} + +void BKE_previewimg_cached_release(const char *name) +{ + BLI_assert(BLI_thread_is_main()); + + PreviewImage *prv = (PreviewImage *)BLI_ghash_popkey(gCachedPreviews, name, MEM_freeN); + + BKE_previewimg_deferred_release(prv); +} + +/** + * Handle deferred (lazy) loading/generation of preview image, if needed. + * For now, only used with file thumbnails. + */ +void BKE_previewimg_ensure(PreviewImage *prv, const int size) +{ + if ((prv->tag & PRV_TAG_DEFFERED) != 0) { + const bool do_icon = ((size == ICON_SIZE_ICON) && !prv->rect[ICON_SIZE_ICON]); + const bool do_preview = ((size == ICON_SIZE_PREVIEW) && !prv->rect[ICON_SIZE_PREVIEW]); + + if (do_icon || do_preview) { + ImBuf *thumb; + char *prv_deferred_data = (char *)PRV_DEFERRED_DATA(prv); + int source = prv_deferred_data[0]; + char *path = &prv_deferred_data[1]; + int icon_w, icon_h; + + thumb = IMB_thumb_manage(path, THB_LARGE, (ThumbSource)source); + + if (thumb) { + /* PreviewImage assumes premultiplied alhpa... */ + IMB_premultiply_alpha(thumb); + + if (do_preview) { + prv->w[ICON_SIZE_PREVIEW] = thumb->x; + prv->h[ICON_SIZE_PREVIEW] = thumb->y; + prv->rect[ICON_SIZE_PREVIEW] = (uint *)MEM_dupallocN(thumb->rect); + prv->flag[ICON_SIZE_PREVIEW] &= ~(PRV_CHANGED | PRV_USER_EDITED | PRV_UNFINISHED); + } + if (do_icon) { + if (thumb->x > thumb->y) { + icon_w = ICON_RENDER_DEFAULT_HEIGHT; + icon_h = (thumb->y * icon_w) / thumb->x + 1; + } + else if (thumb->x < thumb->y) { + icon_h = ICON_RENDER_DEFAULT_HEIGHT; + icon_w = (thumb->x * icon_h) / thumb->y + 1; + } + else { + icon_w = icon_h = ICON_RENDER_DEFAULT_HEIGHT; + } + + IMB_scaleImBuf(thumb, icon_w, icon_h); + prv->w[ICON_SIZE_ICON] = icon_w; + prv->h[ICON_SIZE_ICON] = icon_h; + prv->rect[ICON_SIZE_ICON] = (uint *)MEM_dupallocN(thumb->rect); + prv->flag[ICON_SIZE_ICON] &= ~(PRV_CHANGED | PRV_USER_EDITED | PRV_UNFINISHED); + } + IMB_freeImBuf(thumb); + } + } + } +} + +/** + * Create an #ImBuf holding a copy of the preview image buffer in \a prv. + * \note The returned image buffer has to be free'd (#IMB_freeImBuf()). + */ +ImBuf *BKE_previewimg_to_imbuf(PreviewImage *prv, const int size) +{ + const unsigned int w = prv->w[size]; + const unsigned int h = prv->h[size]; + const unsigned int *rect = prv->rect[size]; + + ImBuf *ima = NULL; + + if (w > 0 && h > 0 && rect) { + /* first allocate imbuf for copying preview into it */ + ima = IMB_allocImBuf(w, h, 32, IB_rect); + memcpy(ima->rect, rect, w * h * sizeof(*ima->rect)); + } + + return ima; +} + +void BKE_previewimg_finish(PreviewImage *prv, const int size) +{ + /* Previews may be calculated on a thread. */ + atomic_fetch_and_and_int16(&prv->flag[size], ~PRV_UNFINISHED); +} + +bool BKE_previewimg_is_finished(const PreviewImage *prv, const int size) +{ + return (prv->flag[size] & PRV_UNFINISHED) == 0; +} + +void BKE_previewimg_blend_write(BlendWriter *writer, const PreviewImage *prv) +{ + /* Note we write previews also for undo steps. It takes up some memory, + * but not doing so would causes all previews to be re-rendered after + * undo which is too expensive. */ + + if (prv == NULL) { + return; + } + + PreviewImage prv_copy = *prv; + /* don't write out large previews if not requested */ + if (!(U.flag & USER_SAVE_PREVIEWS)) { + prv_copy.w[1] = 0; + prv_copy.h[1] = 0; + prv_copy.rect[1] = NULL; + } + BLO_write_struct_at_address(writer, PreviewImage, prv, &prv_copy); + if (prv_copy.rect[0]) { + BLO_write_uint32_array(writer, prv_copy.w[0] * prv_copy.h[0], prv_copy.rect[0]); + } + if (prv_copy.rect[1]) { + BLO_write_uint32_array(writer, prv_copy.w[1] * prv_copy.h[1], prv_copy.rect[1]); + } +} + +void BKE_previewimg_blend_read(BlendDataReader *reader, PreviewImage *prv) +{ + if (prv == NULL) { + return; + } + + for (int i = 0; i < NUM_ICON_SIZES; i++) { + if (prv->rect[i]) { + BLO_read_data_address(reader, &prv->rect[i]); + } + prv->gputexture[i] = NULL; + prv->flag[i] |= PRV_UNFINISHED; + } + prv->icon_id = 0; + prv->tag = 0; +} + +void BKE_icon_changed(const int icon_id) +{ + Icon *icon = NULL; + + if (!icon_id || G.background) { + return; + } + + icon = icon_ghash_lookup(icon_id); + + if (icon) { + /* We *only* expect ID-tied icons here, not non-ID icon/preview! */ + BLI_assert(icon->id_type != 0); + BLI_assert(icon->obj_type == ICON_DATA_ID); + + /* Do not enforce creation of previews for valid ID types using BKE_previewimg_id_ensure() + * here, we only want to ensure *existing* preview images are properly tagged as + * changed/invalid, that's all. */ + PreviewImage **p_prv = BKE_previewimg_id_get_p((ID *)icon->obj); + + /* If we have previews, they all are now invalid changed. */ + if (p_prv && *p_prv) { + for (int i = 0; i < NUM_ICON_SIZES; i++) { + (*p_prv)->flag[i] |= (PRV_CHANGED | PRV_UNFINISHED); + (*p_prv)->changed_timestamp[i]++; + } + } + } +} + +static Icon *icon_create(int icon_id, int obj_type, void *obj) +{ + Icon *new_icon = (Icon *)MEM_mallocN(sizeof(Icon), __func__); + + new_icon->obj_type = obj_type; + new_icon->obj = obj; + new_icon->id_type = 0; + new_icon->flag = 0; + + /* next two lines make sure image gets created */ + new_icon->drawinfo = NULL; + new_icon->drawinfo_free = NULL; + + { + std::scoped_lock lock(gIconMutex); + BLI_ghash_insert(gIcons, POINTER_FROM_INT(icon_id), new_icon); + } + + return new_icon; +} + +static int icon_id_ensure_create_icon(struct ID *id) +{ + BLI_assert(BLI_thread_is_main()); + + Icon *icon = icon_create(id->icon_id, ICON_DATA_ID, id); + icon->id_type = GS(id->name); + icon->flag = ICON_FLAG_MANAGED; + + return id->icon_id; +} + +int BKE_icon_id_ensure(struct ID *id) +{ + /* Never handle icons in non-main thread! */ + BLI_assert(BLI_thread_is_main()); + + if (!id || G.background) { + return 0; + } + + if (id->icon_id) { + return id->icon_id; + } + + id->icon_id = get_next_free_id(); + + if (!id->icon_id) { + CLOG_ERROR(&LOG, "not enough IDs"); + return 0; + } + + /* Ensure we synchronize ID icon_id with its previewimage if it has one. */ + PreviewImage **p_prv = BKE_previewimg_id_get_p(id); + if (p_prv && *p_prv) { + BLI_assert(ELEM((*p_prv)->icon_id, 0, id->icon_id)); + (*p_prv)->icon_id = id->icon_id; + } + + return icon_id_ensure_create_icon(id); +} + +static int icon_gplayer_color_ensure_create_icon(bGPDlayer *gpl) +{ + BLI_assert(BLI_thread_is_main()); + + /* NOTE: The color previews for GP Layers don't really need + * to be "rendered" to image per se (as it will just be a plain + * colored rectangle), we need to define icon data here so that + * we can store a pointer to the layer data in icon->obj. + */ + Icon *icon = icon_create(gpl->runtime.icon_id, ICON_DATA_GPLAYER, gpl); + icon->flag = ICON_FLAG_MANAGED; + + return gpl->runtime.icon_id; +} + +int BKE_icon_gplayer_color_ensure(bGPDlayer *gpl) +{ + /* Never handle icons in non-main thread! */ + BLI_assert(BLI_thread_is_main()); + + if (!gpl || G.background) { + return 0; + } + + if (gpl->runtime.icon_id) { + return gpl->runtime.icon_id; + } + + gpl->runtime.icon_id = get_next_free_id(); + + if (!gpl->runtime.icon_id) { + CLOG_ERROR(&LOG, "not enough IDs"); + return 0; + } + + return icon_gplayer_color_ensure_create_icon(gpl); +} + +/** + * Return icon id of given preview, or create new icon if not found. + */ +int BKE_icon_preview_ensure(ID *id, PreviewImage *preview) +{ + if (!preview || G.background) { + return 0; + } + + if (id) { + BLI_assert(BKE_previewimg_id_ensure(id) == preview); + } + + if (preview->icon_id) { + BLI_assert(!id || !id->icon_id || id->icon_id == preview->icon_id); + return preview->icon_id; + } + + if (id && id->icon_id) { + preview->icon_id = id->icon_id; + return preview->icon_id; + } + + preview->icon_id = get_next_free_id(); + + if (!preview->icon_id) { + CLOG_ERROR(&LOG, "not enough IDs"); + return 0; + } + + /* Ensure we synchronize ID icon_id with its previewimage if available, + * and generate suitable 'ID' icon. */ + if (id) { + id->icon_id = preview->icon_id; + return icon_id_ensure_create_icon(id); + } + + Icon *icon = icon_create(preview->icon_id, ICON_DATA_PREVIEW, preview); + icon->flag = ICON_FLAG_MANAGED; + + return preview->icon_id; +} + +/** + * Create an icon as owner or \a ibuf. The icon-ID is not stored in \a ibuf, it needs to be stored + * separately. + * \note Transforms ownership of \a ibuf to the newly created icon. + */ +int BKE_icon_imbuf_create(ImBuf *ibuf) +{ + int icon_id = get_next_free_id(); + + Icon *icon = icon_create(icon_id, ICON_DATA_IMBUF, ibuf); + icon->flag = ICON_FLAG_MANAGED; + + return icon_id; +} + +ImBuf *BKE_icon_imbuf_get_buffer(int icon_id) +{ + Icon *icon = icon_ghash_lookup(icon_id); + if (!icon) { + CLOG_ERROR(&LOG, "no icon for icon ID: %d", icon_id); + return NULL; + } + if (icon->obj_type != ICON_DATA_IMBUF) { + CLOG_ERROR(&LOG, "icon ID does not refer to an imbuf icon: %d", icon_id); + return NULL; + } + + return (ImBuf *)icon->obj; +} + +Icon *BKE_icon_get(const int icon_id) +{ + BLI_assert(BLI_thread_is_main()); + + Icon *icon = NULL; + + icon = icon_ghash_lookup(icon_id); + + if (!icon) { + CLOG_ERROR(&LOG, "no icon for icon ID: %d", icon_id); + return NULL; + } + + return icon; +} + +void BKE_icon_set(const int icon_id, struct Icon *icon) +{ + void **val_p; + + std::scoped_lock lock(gIconMutex); + if (BLI_ghash_ensure_p(gIcons, POINTER_FROM_INT(icon_id), &val_p)) { + CLOG_ERROR(&LOG, "icon already set: %d", icon_id); + return; + } + + *val_p = icon; +} + +static void icon_add_to_deferred_delete_queue(int icon_id) +{ + DeferredIconDeleteNode *node = (DeferredIconDeleteNode *)MEM_mallocN( + sizeof(DeferredIconDeleteNode), __func__); + node->icon_id = icon_id; + /* Doesn't need lock. */ + BLI_linklist_lockfree_insert(&g_icon_delete_queue, (LockfreeLinkNode *)node); +} + +void BKE_icon_id_delete(struct ID *id) +{ + const int icon_id = id->icon_id; + if (!icon_id) { + return; /* no icon defined for library object */ + } + id->icon_id = 0; + + if (!BLI_thread_is_main()) { + icon_add_to_deferred_delete_queue(icon_id); + return; + } + + BKE_icons_deferred_free(); + std::scoped_lock lock(gIconMutex); + BLI_ghash_remove(gIcons, POINTER_FROM_INT(icon_id), NULL, icon_free); +} + +/** + * Remove icon and free data. + */ +bool BKE_icon_delete(const int icon_id) +{ + if (icon_id == 0) { + /* no icon defined for library object */ + return false; + } + + std::scoped_lock lock(gIconMutex); + if (Icon *icon = (Icon *)BLI_ghash_popkey(gIcons, POINTER_FROM_INT(icon_id), NULL)) { + icon_free_data(icon_id, icon); + icon_free(icon); + return true; + } + + return false; +} + +bool BKE_icon_delete_unmanaged(const int icon_id) +{ + if (icon_id == 0) { + /* no icon defined for library object */ + return false; + } + + std::scoped_lock lock(gIconMutex); + + Icon *icon = (Icon *)BLI_ghash_popkey(gIcons, POINTER_FROM_INT(icon_id), NULL); + if (icon) { + if (UNLIKELY(icon->flag & ICON_FLAG_MANAGED)) { + BLI_ghash_insert(gIcons, POINTER_FROM_INT(icon_id), icon); + return false; + } + + icon_free_data(icon_id, icon); + icon_free(icon); + return true; + } + + return false; +} + +/* -------------------------------------------------------------------- */ +/** \name Geometry Icon + * \{ */ + +int BKE_icon_geom_ensure(struct Icon_Geom *geom) +{ + BLI_assert(BLI_thread_is_main()); + + if (geom->icon_id) { + return geom->icon_id; + } + + geom->icon_id = get_next_free_id(); + + icon_create(geom->icon_id, ICON_DATA_GEOM, geom); + /* Not managed for now, we may want this to be configurable per icon). */ + + return geom->icon_id; +} + +struct Icon_Geom *BKE_icon_geom_from_memory(uchar *data, size_t data_len) +{ + BLI_assert(BLI_thread_is_main()); + if (data_len <= 8) { + return nullptr; + } + /* Wrapper for RAII early exit cleanups. */ + std::unique_ptr data_wrapper(std::move(data)); + + /* Skip the header. */ + data_len -= 8; + const int div = 3 * 2 * 3; + const int coords_len = data_len / div; + if (coords_len * div != data_len) { + return nullptr; + } + + const uchar header[4] = {'V', 'C', 'O', 0}; + uchar *p = data_wrapper.get(); + if (memcmp(p, header, ARRAY_SIZE(header)) != 0) { + return nullptr; + } + p += 4; + + struct Icon_Geom *geom = (struct Icon_Geom *)MEM_mallocN(sizeof(*geom), __func__); + geom->coords_range[0] = (int)*p++; + geom->coords_range[1] = (int)*p++; + /* x, y ignored for now */ + p += 2; + + geom->coords_len = coords_len; + geom->coords = reinterpret_castcoords)>(p); + geom->colors = reinterpret_castcolors)>(p + (data_len / 3)); + geom->icon_id = 0; + /* Move buffer ownership to C buffer. */ + geom->mem = data_wrapper.release(); + return geom; +} + +struct Icon_Geom *BKE_icon_geom_from_file(const char *filename) +{ + BLI_assert(BLI_thread_is_main()); + size_t data_len; + uchar *data = (uchar *)BLI_file_read_binary_as_mem(filename, 0, &data_len); + if (data == NULL) { + return NULL; + } + return BKE_icon_geom_from_memory(data, data_len); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Studio Light Icon + * \{ */ + +int BKE_icon_ensure_studio_light(struct StudioLight *sl, int id_type) +{ + int icon_id = get_next_free_id(); + Icon *icon = icon_create(icon_id, ICON_DATA_STUDIOLIGHT, sl); + icon->id_type = id_type; + return icon_id; +} +/** \} */ diff --git a/source/blender/blenloader/intern/readblenentry.c b/source/blender/blenloader/intern/readblenentry.c index 3a1ccbeda01..296480fc2e4 100644 --- a/source/blender/blenloader/intern/readblenentry.c +++ b/source/blender/blenloader/intern/readblenentry.c @@ -40,6 +40,7 @@ #include "DNA_genfile.h" #include "DNA_sdna_types.h" +#include "BKE_icons.h" #include "BKE_idtype.h" #include "BKE_main.h" @@ -248,6 +249,7 @@ LinkNode *BLO_blendhandle_get_previews(BlendHandle *bh, int ofblocktype, int *to if (looking) { if (bhead->SDNAnr == DNA_struct_find_nr(fd->filesdna, "PreviewImage")) { prv = BLO_library_read_struct(fd, bhead, "PreviewImage"); + if (prv) { memcpy(new_prv, prv, sizeof(PreviewImage)); if (prv->rect[0] && prv->w[0] && prv->h[0]) { @@ -262,6 +264,7 @@ LinkNode *BLO_blendhandle_get_previews(BlendHandle *bh, int ofblocktype, int *to new_prv->rect[0] = NULL; new_prv->w[0] = new_prv->h[0] = 0; } + BKE_previewimg_finish(new_prv, 0); if (prv->rect[1] && prv->w[1] && prv->h[1]) { bhead = blo_bhead_next(fd, bhead); @@ -275,6 +278,7 @@ LinkNode *BLO_blendhandle_get_previews(BlendHandle *bh, int ofblocktype, int *to new_prv->rect[1] = NULL; new_prv->w[1] = new_prv->h[1] = 0; } + BKE_previewimg_finish(new_prv, 1); MEM_freeN(prv); } } diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index 90f5172f6ec..1c09dc6f4df 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -100,11 +100,12 @@ typedef void (*VectorDrawFunc)(int x, int y, int w, int h, float alpha); #define ICON_TYPE_COLOR_TEXTURE 1 #define ICON_TYPE_MONO_TEXTURE 2 #define ICON_TYPE_BUFFER 3 -#define ICON_TYPE_VECTOR 4 -#define ICON_TYPE_GEOM 5 -#define ICON_TYPE_EVENT 6 /* draw keymap entries using custom renderer. */ -#define ICON_TYPE_GPLAYER 7 -#define ICON_TYPE_BLANK 8 +#define ICON_TYPE_IMBUF 4 +#define ICON_TYPE_VECTOR 5 +#define ICON_TYPE_GEOM 6 +#define ICON_TYPE_EVENT 7 /* draw keymap entries using custom renderer. */ +#define ICON_TYPE_GPLAYER 8 +#define ICON_TYPE_BLANK 9 typedef struct DrawInfo { int type; @@ -1147,6 +1148,9 @@ static DrawInfo *icon_create_drawinfo(Icon *icon) if (ELEM(icon_data_type, ICON_DATA_ID, ICON_DATA_PREVIEW)) { di->type = ICON_TYPE_PREVIEW; } + else if (icon_data_type == ICON_DATA_IMBUF) { + di->type = ICON_TYPE_IMBUF; + } else if (icon_data_type == ICON_DATA_GEOM) { di->type = ICON_TYPE_GEOM; } @@ -1262,7 +1266,7 @@ static void icon_create_rect(struct PreviewImage *prv_img, enum eIconSizes size) else if (!prv_img->rect[size]) { prv_img->w[size] = render_size; prv_img->h[size] = render_size; - prv_img->flag[size] |= PRV_CHANGED; + prv_img->flag[size] |= (PRV_CHANGED | PRV_UNFINISHED); prv_img->changed_timestamp[size] = 0; prv_img->rect[size] = MEM_callocN(render_size * render_size * sizeof(uint), "prv_rect"); } @@ -1384,8 +1388,12 @@ void ui_icon_ensure_deferred(const bContext *C, const int icon_id, const bool bi } } -/* only called when icon has changed */ -/* only call with valid pointer from UI_icon_draw */ +/** + * * Only call with valid pointer from UI_icon_draw. + * * Only called when icon has changed. + * + * Note that if an ID doesn't support jobs for preview creation, \a use_job will be ignored. + */ static void icon_set_image(const bContext *C, Scene *scene, ID *id, @@ -1408,7 +1416,7 @@ static void icon_set_image(const bContext *C, const bool delay = prv_img->rect[size] != NULL; icon_create_rect(prv_img, size); - if (use_job) { + if (use_job && BKE_previewimg_id_supports_jobs(id)) { /* Job (background) version */ ED_preview_icon_job( C, prv_img, id, prv_img->rect[size], prv_img->w[size], prv_img->h[size], delay); @@ -1790,7 +1798,14 @@ static void icon_draw_size(float x, /* We need to flush widget base first to ensure correct ordering. */ UI_widgetbase_draw_cache_flush(); - if (di->type == ICON_TYPE_VECTOR) { + if (di->type == ICON_TYPE_IMBUF) { + ImBuf *ibuf = icon->obj; + + GPU_blend(GPU_BLEND_ALPHA_PREMULT); + icon_draw_rect(x, y, w, h, aspect, ibuf->x, ibuf->y, ibuf->rect, alpha, desaturate); + GPU_blend(GPU_BLEND_ALPHA); + } + else if (di->type == ICON_TYPE_VECTOR) { /* vector icons use the uiBlock transformation, they are not drawn * with untransformed coordinates like the other icons */ di->data.vector.func((int)x, (int)y, w, h, 1.0f); @@ -1937,6 +1952,9 @@ static void ui_id_preview_image_render_size( } } +/** + * Note that if an ID doesn't support jobs for preview creation, \a use_job will be ignored. + */ void UI_icon_render_id(const bContext *C, Scene *scene, ID *id, const bool big, const bool use_job) { PreviewImage *pi = BKE_previewimg_id_ensure(id); @@ -1964,12 +1982,7 @@ static void ui_id_icon_render(const bContext *C, ID *id, bool use_jobs) } for (enum eIconSizes i = 0; i < NUM_ICON_SIZES; i++) { - /* check if rect needs to be created; changed - * only set by dynamic icons */ - if (((pi->flag[i] & PRV_CHANGED) || !pi->rect[i])) { - icon_set_image(C, NULL, id, pi, i, use_jobs); - pi->flag[i] &= ~PRV_CHANGED; - } + ui_id_preview_image_render_size(C, NULL, id, pi, i, use_jobs); } } diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c index 3c103f28d93..579fd86077e 100644 --- a/source/blender/editors/render/render_preview.c +++ b/source/blender/editors/render/render_preview.c @@ -354,13 +354,15 @@ static ID *duplicate_ids(ID *id, const bool allow_failure) case ID_TE: case ID_LA: case ID_WO: { + BLI_assert(BKE_previewimg_id_supports_jobs(id)); ID *id_copy = BKE_id_copy_ex( NULL, id, NULL, LIB_ID_CREATE_LOCAL | LIB_ID_COPY_LOCALIZE | LIB_ID_COPY_NO_ANIMDATA); return id_copy; } + /* These support threading, but don't need duplicating. */ case ID_IM: case ID_BR: - case ID_SCR: + BLI_assert(BKE_previewimg_id_supports_jobs(id)); return NULL; default: if (!allow_failure) { @@ -1374,6 +1376,24 @@ static void other_id_types_preview_render(IconPreview *ip, shader_preview_free(sp); } +/* exported functions */ + +/** + * Find the index to map \a icon_size to data in \a preview_image. + */ +static int icon_previewimg_size_index_get(const IconPreviewSize *icon_size, + const PreviewImage *preview_image) +{ + for (int i = 0; i < NUM_ICON_SIZES; i++) { + if ((preview_image->w[i] == icon_size->sizex) && (preview_image->h[i] == icon_size->sizey)) { + return i; + } + } + + BLI_assert(!"The searched icon size does not match any in the preview image"); + return -1; +} + static void icon_preview_startjob_all_sizes(void *customdata, short *stop, short *do_update, @@ -1398,6 +1418,13 @@ static void icon_preview_startjob_all_sizes(void *customdata, continue; } +#ifndef NDEBUG + { + int size_index = icon_previewimg_size_index_get(cur_size, prv); + BLI_assert(!BKE_previewimg_is_finished(prv, size_index)); + } +#endif + if (ip->id && ELEM(GS(ip->id->name), ID_OB)) { /* Much simpler than the ShaderPreview mess used for other ID types. */ object_preview_render(ip, cur_size); @@ -1460,6 +1487,12 @@ static void icon_preview_endjob(void *customdata) if (ip->owner) { PreviewImage *prv_img = ip->owner; prv_img->tag &= ~PRV_TAG_DEFFERED_RENDERING; + + LISTBASE_FOREACH (IconPreviewSize *, icon_size, &ip->sizes) { + int size_index = icon_previewimg_size_index_get(icon_size, prv_img); + BKE_previewimg_finish(prv_img, size_index); + } + if (prv_img->tag & PRV_TAG_DEFFERED_DELETE) { BLI_assert(prv_img->tag & PRV_TAG_DEFFERED); BKE_previewimg_deferred_release(prv_img); @@ -1576,6 +1609,8 @@ void ED_preview_shader_job(const bContext *C, Scene *scene = CTX_data_scene(C); short id_type = GS(id->name); + BLI_assert(BKE_previewimg_id_supports_jobs(id)); + /* Use workspace render only for buttons Window, * since the other previews are related to the datablock. */ diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c index 5e3f443ce9c..6547e42f410 100644 --- a/source/blender/editors/util/ed_util.c +++ b/source/blender/editors/util/ed_util.c @@ -546,7 +546,7 @@ static int lib_id_load_custom_preview_exec(bContext *C, wmOperator *op) BKE_previewimg_id_custom_set(id, path); - // WM_event_add_notifier(C, NC_ASSET, NULL); + WM_event_add_notifier(C, NC_ASSET, NULL); return OPERATOR_FINISHED; } diff --git a/source/blender/imbuf/intern/thumbs_blend.c b/source/blender/imbuf/intern/thumbs_blend.c index d5ded02be62..486db07597f 100644 --- a/source/blender/imbuf/intern/thumbs_blend.c +++ b/source/blender/imbuf/intern/thumbs_blend.c @@ -78,15 +78,7 @@ ImBuf *IMB_thumb_load_blend(const char *blen_path, const char *blen_group, const if (STREQ(blockname, blen_id)) { if (img) { - unsigned int w = img->w[ICON_SIZE_PREVIEW]; - unsigned int h = img->h[ICON_SIZE_PREVIEW]; - unsigned int *rect = img->rect[ICON_SIZE_PREVIEW]; - - if (w > 0 && h > 0 && rect) { - /* first allocate imbuf for copying preview into it */ - ima = IMB_allocImBuf(w, h, 32, IB_rect); - memcpy(ima->rect, rect, w * h * sizeof(unsigned int)); - } + ima = BKE_previewimg_to_imbuf(img, ICON_SIZE_PREVIEW); } break; } diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h index 84757e313ed..af8e83a2c44 100644 --- a/source/blender/makesdna/DNA_ID.h +++ b/source/blender/makesdna/DNA_ID.h @@ -360,6 +360,7 @@ enum eIconSizes { enum ePreviewImage_Flag { PRV_CHANGED = (1 << 0), PRV_USER_EDITED = (1 << 1), /* if user-edited, do not auto-update this anymore! */ + PRV_UNFINISHED = (1 << 2), /* The preview is not done rendering yet. */ }; /* for PreviewImage->tag */ -- cgit v1.2.3 From b5d778a7d4072bfb091198a2094890157a6d017b Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Mon, 14 Dec 2020 13:31:55 +0100 Subject: Asset System: Support dragging assets and appending on drop For the Asset Browser, it needs to be possible to drag assets into various editors, which may not come from the current .blend file. In other words, the dragging needs to work with just the asset metadata, without direct access to the data-block itself. Idea is simple: When dragging an asset, store the source file-path and data-block name and when dropping, append the data-block. It uses existing drop operators, but the function to get the dropped data-block is replaced with one that returns the local data-block, or, in case of an external asset, appends the data-block first. The drop operators need to be adjusted to use this new function that respects assets. With this patch it only works for dragging assets into the 3D view. Note that I expect this to be a short-lived change. A refactor like D4071 is needed to make the drag & drop system more future proof for assets and other use cases. Part of the first Asset Browser milestone. Check the #asset_browser_milestone_1 project milestone on developer.blender.org. Differential Revision: https://developer.blender.org/D9721 Reviewed by: Bastien Montagne, Brecht Van Lommel --- source/blender/editors/include/UI_interface.h | 7 ++ source/blender/editors/interface/interface.c | 37 ++++++-- .../blender/editors/interface/interface_handlers.c | 5 +- .../blender/editors/space_console/space_console.c | 4 +- source/blender/editors/space_node/space_node.c | 8 +- .../editors/space_outliner/outliner_dragdrop.c | 18 ++-- source/blender/editors/space_text/space_text.c | 2 +- source/blender/editors/space_view3d/space_view3d.c | 26 ++++-- source/blender/windowmanager/WM_api.h | 10 +- source/blender/windowmanager/WM_types.h | 20 ++-- source/blender/windowmanager/intern/wm_dragdrop.c | 102 +++++++++++++++++---- 11 files changed, 181 insertions(+), 58 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 352c58032f5..83e94664c0b 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -727,6 +727,13 @@ void UI_block_translate(uiBlock *block, int x, int y); int UI_but_return_value_get(uiBut *but); void UI_but_drag_set_id(uiBut *but, struct ID *id); +void UI_but_drag_set_asset(uiBut *but, + const char *name, + const char *path, + int id_type, + int icon, + struct ImBuf *imb, + float scale); void UI_but_drag_set_rna(uiBut *but, struct PointerRNA *ptr); void UI_but_drag_set_path(uiBut *but, const char *path, const bool use_free); void UI_but_drag_set_name(uiBut *but, const char *name); diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index 254d0909367..c5c2f0e55c4 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -3352,7 +3352,7 @@ static void ui_but_free(const bContext *C, uiBut *but) } if (but->dragpoin && (but->dragflag & UI_BUT_DRAGPOIN_FREE)) { - MEM_freeN(but->dragpoin); + WM_drag_data_free(but->dragtype, but->dragpoin); } ui_but_extra_operator_icons_free(but); @@ -6098,17 +6098,42 @@ void UI_but_drag_set_id(uiBut *but, ID *id) { but->dragtype = WM_DRAG_ID; if ((but->dragflag & UI_BUT_DRAGPOIN_FREE)) { - MEM_SAFE_FREE(but->dragpoin); + WM_drag_data_free(but->dragtype, but->dragpoin); but->dragflag &= ~UI_BUT_DRAGPOIN_FREE; } but->dragpoin = (void *)id; } +void UI_but_drag_set_asset(uiBut *but, + const char *name, + const char *path, + int id_type, + int icon, + struct ImBuf *imb, + float scale) +{ + wmDragAsset *asset_drag = MEM_mallocN(sizeof(*asset_drag), "wmDragAsset"); + + BLI_strncpy(asset_drag->name, name, sizeof(asset_drag->name)); + asset_drag->path = path; + asset_drag->id_type = id_type; + + but->dragtype = WM_DRAG_ASSET; + ui_def_but_icon(but, icon, 0); /* no flag UI_HAS_ICON, so icon doesn't draw in button */ + if ((but->dragflag & UI_BUT_DRAGPOIN_FREE)) { + WM_drag_data_free(but->dragtype, but->dragpoin); + } + but->dragpoin = asset_drag; + but->dragflag |= UI_BUT_DRAGPOIN_FREE; + but->imb = imb; + but->imb_scale = scale; +} + void UI_but_drag_set_rna(uiBut *but, PointerRNA *ptr) { but->dragtype = WM_DRAG_RNA; if ((but->dragflag & UI_BUT_DRAGPOIN_FREE)) { - MEM_SAFE_FREE(but->dragpoin); + WM_drag_data_free(but->dragtype, but->dragpoin); but->dragflag &= ~UI_BUT_DRAGPOIN_FREE; } but->dragpoin = (void *)ptr; @@ -6118,7 +6143,7 @@ void UI_but_drag_set_path(uiBut *but, const char *path, const bool use_free) { but->dragtype = WM_DRAG_PATH; if ((but->dragflag & UI_BUT_DRAGPOIN_FREE)) { - MEM_SAFE_FREE(but->dragpoin); + WM_drag_data_free(but->dragtype, but->dragpoin); but->dragflag &= ~UI_BUT_DRAGPOIN_FREE; } but->dragpoin = (void *)path; @@ -6131,7 +6156,7 @@ void UI_but_drag_set_name(uiBut *but, const char *name) { but->dragtype = WM_DRAG_NAME; if ((but->dragflag & UI_BUT_DRAGPOIN_FREE)) { - MEM_SAFE_FREE(but->dragpoin); + WM_drag_data_free(but->dragtype, but->dragpoin); but->dragflag &= ~UI_BUT_DRAGPOIN_FREE; } but->dragpoin = (void *)name; @@ -6149,7 +6174,7 @@ void UI_but_drag_set_image( but->dragtype = WM_DRAG_PATH; ui_def_but_icon(but, icon, 0); /* no flag UI_HAS_ICON, so icon doesn't draw in button */ if ((but->dragflag & UI_BUT_DRAGPOIN_FREE)) { - MEM_SAFE_FREE(but->dragpoin); + WM_drag_data_free(but->dragtype, but->dragpoin); but->dragflag &= ~UI_BUT_DRAGPOIN_FREE; } but->dragpoin = (void *)path; diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index bcb79743b12..f39ad4c4ed5 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -1987,6 +1987,8 @@ static bool ui_but_drag_init(bContext *C, else { wmDrag *drag = WM_event_start_drag( C, but->icon, but->dragtype, but->dragpoin, ui_but_value_get(but), WM_DRAG_NOP); + /* wmDrag has ownership over dragpoin now, stop messing with it. */ + but->dragpoin = NULL; if (but->imb) { WM_event_drag_image(drag, @@ -2259,10 +2261,11 @@ static void ui_but_drop(bContext *C, const wmEvent *event, uiBut *but, uiHandleB ListBase *drags = event->customdata; /* drop event type has listbase customdata by default */ LISTBASE_FOREACH (wmDrag *, wmd, drags) { + /* TODO asset dropping. */ if (wmd->type == WM_DRAG_ID) { /* align these types with UI_but_active_drop_name */ if (ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) { - ID *id = WM_drag_ID(wmd, 0); + ID *id = WM_drag_get_local_ID(wmd, 0); button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING); diff --git a/source/blender/editors/space_console/space_console.c b/source/blender/editors/space_console/space_console.c index a54faa41122..9b8e9e0e871 100644 --- a/source/blender/editors/space_console/space_console.c +++ b/source/blender/editors/space_console/space_console.c @@ -164,12 +164,12 @@ static bool id_drop_poll(bContext *UNUSED(C), const wmEvent *UNUSED(event), const char **UNUSED(tooltip)) { - return WM_drag_ID(drag, 0) != NULL; + return WM_drag_get_local_ID(drag, 0) != NULL; } static void id_drop_copy(wmDrag *drag, wmDropBox *drop) { - ID *id = WM_drag_ID(drag, 0); + ID *id = WM_drag_get_local_ID(drag, 0); /* copy drag path to properties */ char *text = RNA_path_full_ID_py(G_MAIN, id); diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c index afc1a963f4f..ad7632377a3 100644 --- a/source/blender/editors/space_node/space_node.c +++ b/source/blender/editors/space_node/space_node.c @@ -645,7 +645,7 @@ static bool node_ima_drop_poll(bContext *UNUSED(C), /* rule might not work? */ return (ELEM(drag->icon, 0, ICON_FILE_IMAGE, ICON_FILE_MOVIE)); } - return WM_drag_ID(drag, ID_IM) != NULL; + return WM_drag_get_local_ID(drag, ID_IM) != NULL; } static bool node_mask_drop_poll(bContext *UNUSED(C), @@ -653,19 +653,19 @@ static bool node_mask_drop_poll(bContext *UNUSED(C), const wmEvent *UNUSED(event), const char **UNUSED(r_tooltip)) { - return WM_drag_ID(drag, ID_MSK) != NULL; + return WM_drag_get_local_ID(drag, ID_MSK) != NULL; } static void node_id_drop_copy(wmDrag *drag, wmDropBox *drop) { - ID *id = WM_drag_ID(drag, 0); + ID *id = WM_drag_get_local_ID(drag, 0); RNA_string_set(drop->ptr, "name", id->name + 2); } static void node_id_path_drop_copy(wmDrag *drag, wmDropBox *drop) { - ID *id = WM_drag_ID(drag, 0); + ID *id = WM_drag_get_local_ID(drag, 0); if (id) { RNA_string_set(drop->ptr, "name", id->name + 2); diff --git a/source/blender/editors/space_outliner/outliner_dragdrop.c b/source/blender/editors/space_outliner/outliner_dragdrop.c index dcb8ef9c954..152bbc96281 100644 --- a/source/blender/editors/space_outliner/outliner_dragdrop.c +++ b/source/blender/editors/space_outliner/outliner_dragdrop.c @@ -333,7 +333,7 @@ static bool parent_drop_poll(bContext *C, ED_region_tag_redraw_no_rebuild(CTX_wm_region(C)); } - Object *potential_child = (Object *)WM_drag_ID(drag, ID_OB); + Object *potential_child = (Object *)WM_drag_get_local_ID(drag, ID_OB); if (!potential_child) { return false; } @@ -421,7 +421,7 @@ static int parent_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event) } Object *par = (Object *)tselem->id; - Object *ob = (Object *)WM_drag_ID_from_event(event, ID_OB); + Object *ob = (Object *)WM_drag_get_local_ID_from_event(event, ID_OB); if (ELEM(NULL, ob, par)) { return OPERATOR_CANCELLED; @@ -473,7 +473,7 @@ static bool parent_clear_poll(bContext *C, } } - Object *ob = (Object *)WM_drag_ID(drag, ID_OB); + Object *ob = (Object *)WM_drag_get_local_ID(drag, ID_OB); if (!ob) { return false; } @@ -552,7 +552,7 @@ static bool scene_drop_poll(bContext *C, const char **UNUSED(r_tooltip)) { /* Ensure item under cursor is valid drop target */ - Object *ob = (Object *)WM_drag_ID(drag, ID_OB); + Object *ob = (Object *)WM_drag_get_local_ID(drag, ID_OB); return (ob && (outliner_ID_drop_find(C, event, ID_SCE) != NULL)); } @@ -560,7 +560,7 @@ static int scene_drop_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent { Main *bmain = CTX_data_main(C); Scene *scene = (Scene *)outliner_ID_drop_find(C, event, ID_SCE); - Object *ob = (Object *)WM_drag_ID_from_event(event, ID_OB); + Object *ob = (Object *)WM_drag_get_local_ID_from_event(event, ID_OB); if (ELEM(NULL, ob, scene) || ID_IS_LINKED(scene)) { return OPERATOR_CANCELLED; @@ -620,7 +620,7 @@ static bool material_drop_poll(bContext *C, const char **UNUSED(r_tooltip)) { /* Ensure item under cursor is valid drop target */ - Material *ma = (Material *)WM_drag_ID(drag, ID_MA); + Material *ma = (Material *)WM_drag_get_local_ID(drag, ID_MA); return (ma && (outliner_ID_drop_find(C, event, ID_OB) != NULL)); } @@ -628,7 +628,7 @@ static int material_drop_invoke(bContext *C, wmOperator *UNUSED(op), const wmEve { Main *bmain = CTX_data_main(C); Object *ob = (Object *)outliner_ID_drop_find(C, event, ID_OB); - Material *ma = (Material *)WM_drag_ID_from_event(event, ID_MA); + Material *ma = (Material *)WM_drag_get_local_ID_from_event(event, ID_MA); if (ELEM(NULL, ob, ma)) { return OPERATOR_CANCELLED; @@ -1461,14 +1461,14 @@ static int outliner_item_drag_drop_invoke(bContext *C, parent = scene->master_collection; } - WM_drag_add_ID(drag, id, &parent->id); + WM_drag_add_local_ID(drag, id, &parent->id); } BLI_freelistN(&selected.selected_array); } else { /* Add single ID. */ - WM_drag_add_ID(drag, data.drag_id, data.drag_parent); + WM_drag_add_local_ID(drag, data.drag_id, data.drag_parent); } ED_outliner_select_sync_from_outliner(C, space_outliner); diff --git a/source/blender/editors/space_text/space_text.c b/source/blender/editors/space_text/space_text.c index bb71a9b11be..0f5ac5abe1d 100644 --- a/source/blender/editors/space_text/space_text.c +++ b/source/blender/editors/space_text/space_text.c @@ -357,7 +357,7 @@ static bool text_drop_paste_poll(bContext *UNUSED(C), static void text_drop_paste(wmDrag *drag, wmDropBox *drop) { char *text; - ID *id = WM_drag_ID(drag, 0); + ID *id = WM_drag_get_local_ID(drag, 0); /* copy drag path to properties */ text = RNA_path_full_ID_py(G_MAIN, id); diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index 9f31e7a411d..3761f4ad7c6 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -461,6 +461,12 @@ static void view3d_main_region_exit(wmWindowManager *wm, ARegion *region) ED_view3d_stop_render_preview(wm, region); } +static bool view3d_drop_in_main_region_poll(bContext *C, const wmEvent *event) +{ + ScrArea *area = CTX_wm_area(C); + return ED_region_overlap_isect_any_xy(area, &event->x) == false; +} + static ID *view3d_drop_id_in_main_region_poll_id(bContext *C, wmDrag *drag, const wmEvent *event, @@ -470,7 +476,7 @@ static ID *view3d_drop_id_in_main_region_poll_id(bContext *C, if (ED_region_overlap_isect_any_xy(area, &event->x)) { return NULL; } - return WM_drag_ID(drag, id_type); + return view3d_drop_in_main_region_poll(C, event) ? WM_drag_get_local_ID(drag, id_type) : NULL; } static bool view3d_drop_id_in_main_region_poll(bContext *C, @@ -478,7 +484,11 @@ static bool view3d_drop_id_in_main_region_poll(bContext *C, const wmEvent *event, ID_Type id_type) { - return (view3d_drop_id_in_main_region_poll_id(C, drag, event, id_type) != NULL); + if (!view3d_drop_in_main_region_poll(C, event)) { + return false; + } + + return WM_drag_get_local_ID(drag, id_type) || WM_drag_get_asset_data(drag, id_type); } static bool view3d_ob_drop_poll(bContext *C, @@ -533,7 +543,7 @@ static bool view3d_ima_drop_poll(bContext *C, return (ELEM(drag->icon, 0, ICON_FILE_IMAGE, ICON_FILE_MOVIE)); } - return WM_drag_ID(drag, ID_IM) != NULL; + return WM_drag_get_local_ID(drag, ID_IM) || WM_drag_get_asset_data(drag, ID_IM); } static bool view3d_ima_bg_is_camera_view(bContext *C) @@ -596,14 +606,14 @@ static bool view3d_volume_drop_poll(bContext *UNUSED(C), static void view3d_ob_drop_copy(wmDrag *drag, wmDropBox *drop) { - ID *id = WM_drag_ID(drag, ID_OB); + ID *id = WM_drag_get_local_ID_or_import_from_asset(drag, ID_OB); RNA_string_set(drop->ptr, "name", id->name + 2); } static void view3d_collection_drop_copy(wmDrag *drag, wmDropBox *drop) { - ID *id = WM_drag_ID(drag, ID_GR); + ID *id = WM_drag_get_local_ID_or_import_from_asset(drag, ID_GR); drop->opcontext = WM_OP_EXEC_DEFAULT; RNA_string_set(drop->ptr, "name", id->name + 2); @@ -611,14 +621,14 @@ static void view3d_collection_drop_copy(wmDrag *drag, wmDropBox *drop) static void view3d_id_drop_copy(wmDrag *drag, wmDropBox *drop) { - ID *id = WM_drag_ID(drag, 0); + ID *id = WM_drag_get_local_ID_or_import_from_asset(drag, 0); RNA_string_set(drop->ptr, "name", id->name + 2); } static void view3d_id_drop_copy_with_type(wmDrag *drag, wmDropBox *drop) { - ID *id = WM_drag_ID(drag, 0); + ID *id = WM_drag_get_local_ID(drag, 0); RNA_string_set(drop->ptr, "name", id->name + 2); RNA_enum_set(drop->ptr, "type", GS(id->name)); @@ -626,7 +636,7 @@ static void view3d_id_drop_copy_with_type(wmDrag *drag, wmDropBox *drop) static void view3d_id_path_drop_copy(wmDrag *drag, wmDropBox *drop) { - ID *id = WM_drag_ID(drag, 0); + ID *id = WM_drag_get_local_ID_or_import_from_asset(drag, 0); if (id) { RNA_string_set(drop->ptr, "name", id->name + 2); diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index da2115e12fb..1f205a71338 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -671,6 +671,7 @@ struct wmDrag *WM_event_start_drag( struct bContext *C, int icon, int type, void *poin, double value, unsigned int flags); void WM_event_drag_image(struct wmDrag *, struct ImBuf *, float scale, int sx, int sy); void WM_drag_free(struct wmDrag *drag); +void WM_drag_data_free(int dragtype, void *poin); void WM_drag_free_list(struct ListBase *lb); struct wmDropBox *WM_dropbox_add( @@ -681,9 +682,12 @@ struct wmDropBox *WM_dropbox_add( ListBase *WM_dropboxmap_find(const char *idname, int spaceid, int regionid); /* ID drag and drop */ -void WM_drag_add_ID(struct wmDrag *drag, struct ID *id, struct ID *from_parent); -struct ID *WM_drag_ID(const struct wmDrag *drag, short idcode); -struct ID *WM_drag_ID_from_event(const struct wmEvent *event, short idcode); +void WM_drag_add_local_ID(struct wmDrag *drag, struct ID *id, struct ID *from_parent); +struct ID *WM_drag_get_local_ID(const struct wmDrag *drag, short idcode); +struct ID *WM_drag_get_local_ID_from_event(const struct wmEvent *event, short idcode); + +struct wmDragAsset *WM_drag_get_asset_data(const struct wmDrag *drag, int idcode); +struct ID *WM_drag_get_local_ID_or_import_from_asset(const struct wmDrag *drag, int idcode); /* Set OpenGL viewport and scissor */ void wmViewport(const struct rcti *winrct); diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index 77258ef5224..0ddd0f20c7a 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -836,12 +836,13 @@ typedef void (*wmPaintCursorDraw)(struct bContext *C, int, int, void *customdata /* *************** Drag and drop *************** */ #define WM_DRAG_ID 0 -#define WM_DRAG_RNA 1 -#define WM_DRAG_PATH 2 -#define WM_DRAG_NAME 3 -#define WM_DRAG_VALUE 4 -#define WM_DRAG_COLOR 5 -#define WM_DRAG_DATASTACK 6 +#define WM_DRAG_ASSET 1 +#define WM_DRAG_RNA 2 +#define WM_DRAG_PATH 3 +#define WM_DRAG_NAME 4 +#define WM_DRAG_VALUE 5 +#define WM_DRAG_COLOR 6 +#define WM_DRAG_DATASTACK 7 typedef enum wmDragFlags { WM_DRAG_NOP = 0, @@ -856,6 +857,13 @@ typedef struct wmDragID { struct ID *from_parent; } wmDragID; +typedef struct wmDragAsset { + char name[64]; /* MAX_NAME */ + /* Always freed. */ + const char *path; + int id_type; +} wmDragAsset; + typedef struct wmDrag { struct wmDrag *next, *prev; diff --git a/source/blender/windowmanager/intern/wm_dragdrop.c b/source/blender/windowmanager/intern/wm_dragdrop.c index 373360c7b92..fe2e2d92127 100644 --- a/source/blender/windowmanager/intern/wm_dragdrop.c +++ b/source/blender/windowmanager/intern/wm_dragdrop.c @@ -37,6 +37,7 @@ #include "BIF_glutil.h" #include "BKE_context.h" +#include "BKE_global.h" #include "BKE_idtype.h" #include "GPU_shader.h" @@ -146,16 +147,23 @@ wmDrag *WM_event_start_drag( drag->flags = flags; drag->icon = icon; drag->type = type; - if (type == WM_DRAG_PATH) { - BLI_strncpy(drag->path, poin, FILE_MAX); - } - else if (type == WM_DRAG_ID) { - if (poin) { - WM_drag_add_ID(drag, poin, NULL); - } - } - else { - drag->poin = poin; + switch (type) { + case WM_DRAG_PATH: + BLI_strncpy(drag->path, poin, FILE_MAX); + break; + case WM_DRAG_ID: + if (poin) { + WM_drag_add_local_ID(drag, poin, NULL); + } + break; + case WM_DRAG_ASSET: + /* Move ownership of poin to wmDrag. */ + drag->poin = poin; + drag->flags |= WM_DRAG_FREE_DATA; + break; + default: + drag->poin = poin; + break; } drag->value = value; @@ -170,12 +178,26 @@ void WM_event_drag_image(wmDrag *drag, ImBuf *imb, float scale, int sx, int sy) drag->sy = sy; } -void WM_drag_free(wmDrag *drag) +void WM_drag_data_free(int dragtype, void *poin) { - if ((drag->flags & WM_DRAG_FREE_DATA) && drag->poin) { - MEM_freeN(drag->poin); + /* Don't require all the callers to have a NULL-check, just allow passing NULL. */ + if (!poin) { + return; } + /* Not too nice, could become a callback. */ + if (dragtype == WM_DRAG_ASSET) { + wmDragAsset *asset_drag = poin; + MEM_freeN((void *)asset_drag->path); + } + MEM_freeN(poin); +} + +void WM_drag_free(wmDrag *drag) +{ + if (drag->flags & WM_DRAG_FREE_DATA) { + WM_drag_data_free(drag->type, drag->poin); + } BLI_freelistN(&drag->ids); MEM_freeN(drag); } @@ -279,7 +301,7 @@ void wm_drags_check_ops(bContext *C, const wmEvent *event) /* ************** IDs ***************** */ -void WM_drag_add_ID(wmDrag *drag, ID *id, ID *from_parent) +void WM_drag_add_local_ID(wmDrag *drag, ID *id, ID *from_parent) { /* Don't drag the same ID twice. */ LISTBASE_FOREACH (wmDragID *, drag_id, &drag->ids) { @@ -302,7 +324,7 @@ void WM_drag_add_ID(wmDrag *drag, ID *id, ID *from_parent) BLI_addtail(&drag->ids, drag_id); } -ID *WM_drag_ID(const wmDrag *drag, short idcode) +ID *WM_drag_get_local_ID(const wmDrag *drag, short idcode) { if (drag->type != WM_DRAG_ID) { return NULL; @@ -317,14 +339,54 @@ ID *WM_drag_ID(const wmDrag *drag, short idcode) return (idcode == 0 || GS(id->name) == idcode) ? id : NULL; } -ID *WM_drag_ID_from_event(const wmEvent *event, short idcode) +ID *WM_drag_get_local_ID_from_event(const wmEvent *event, short idcode) { if (event->custom != EVT_DATA_DRAGDROP) { return NULL; } ListBase *lb = event->customdata; - return WM_drag_ID(lb->first, idcode); + return WM_drag_get_local_ID(lb->first, idcode); +} + +wmDragAsset *WM_drag_get_asset_data(const wmDrag *drag, int idcode) +{ + if (drag->type != WM_DRAG_ASSET) { + return NULL; + } + + wmDragAsset *asset_drag = drag->poin; + return (idcode == 0 || asset_drag->id_type == idcode) ? asset_drag : NULL; +} + +static ID *wm_drag_asset_id_import(wmDragAsset *asset_drag) +{ + /* Append only for now, wmDragAsset could have a `link` bool. */ + return WM_file_append_datablock( + G_MAIN, NULL, NULL, NULL, asset_drag->path, asset_drag->id_type, asset_drag->name); +} + +/** + * When dragging a local ID, return that. Otherwise, if dragging an asset-handle, link or append + * that depending on what was chosen by the drag-box (currently append only in fact). + */ +ID *WM_drag_get_local_ID_or_import_from_asset(const wmDrag *drag, int idcode) +{ + if (!ELEM(drag->type, WM_DRAG_ASSET, WM_DRAG_ID)) { + return NULL; + } + + if (drag->type == WM_DRAG_ID) { + return WM_drag_get_local_ID(drag, idcode); + } + + wmDragAsset *asset_drag = WM_drag_get_asset_data(drag, idcode); + if (!asset_drag) { + return NULL; + } + + /* Link/append the asset. */ + return wm_drag_asset_id_import(asset_drag); } /* ************** draw ***************** */ @@ -342,7 +404,7 @@ static const char *wm_drag_name(wmDrag *drag) { switch (drag->type) { case WM_DRAG_ID: { - ID *id = WM_drag_ID(drag, 0); + ID *id = WM_drag_get_local_ID(drag, 0); bool single = (BLI_listbase_count_at_most(&drag->ids, 2) == 1); if (single) { @@ -353,6 +415,10 @@ static const char *wm_drag_name(wmDrag *drag) } break; } + case WM_DRAG_ASSET: { + const wmDragAsset *asset_drag = WM_drag_get_asset_data(drag, 0); + return asset_drag->name; + } case WM_DRAG_PATH: case WM_DRAG_NAME: return drag->path; -- cgit v1.2.3 From e413c80371c1714d80262034d0e83b4e10e6cbe5 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Mon, 14 Dec 2020 13:39:41 +0100 Subject: Asset System: Support custom asset library paths through Preferences One of the core design aspects of the Asset Browser is that users can "mount" custom asset libraries via the Preferences. Currently an asset library is just a directory with one or more .blend files in it. We could easily support a single .blend file as asset library as well (rather than a directory). It's just disabled currently. Note that in earlier designs, asset libraries were called repositories. Idea is simple: In Preferences > File Paths, you can create custom libraries, by setting a name and selecting a path. The name is ensured to be unique. If the name or path are empty, the Asset Browser will not show it in the list of available asset libraries. The library path is not checked for validity, the Asset Browser will allow selecting invalid libraries, but show a message instead of the file list, to help the user understand what's going on. Of course the actual Asset Browser UI is not part of this commit, it's in one of the following ones. {F9497950} Part of the first Asset Browser milestone. Check the #asset_browser_milestone_1 project milestone on developer.blender.org. Differential Revision: https://developer.blender.org/D9722 Reviewed by: Brecht Van Lommel, Hans Goudey --- source/blender/blenkernel/BKE_preferences.h | 56 ++++++++++ source/blender/blenkernel/CMakeLists.txt | 2 + source/blender/blenkernel/intern/blender.c | 1 + source/blender/blenkernel/intern/blendfile.c | 3 + source/blender/blenkernel/intern/preferences.c | 119 +++++++++++++++++++++ source/blender/blenloader/intern/readfile.c | 1 + .../blender/blenloader/intern/versioning_userdef.c | 4 + source/blender/blenloader/intern/writefile.c | 4 + .../blender/editors/interface/interface_handlers.c | 6 +- source/blender/editors/space_buttons/buttons_ops.c | 2 +- .../blender/editors/space_userpref/userpref_ops.c | 61 +++++++++++ source/blender/makesdna/DNA_userdef_types.h | 9 ++ source/blender/makesrna/RNA_access.h | 1 + source/blender/makesrna/intern/rna_userdef.c | 36 +++++++ 14 files changed, 303 insertions(+), 2 deletions(-) create mode 100644 source/blender/blenkernel/BKE_preferences.h create mode 100644 source/blender/blenkernel/intern/preferences.c (limited to 'source/blender') diff --git a/source/blender/blenkernel/BKE_preferences.h b/source/blender/blenkernel/BKE_preferences.h new file mode 100644 index 00000000000..04a41d425bb --- /dev/null +++ b/source/blender/blenkernel/BKE_preferences.h @@ -0,0 +1,56 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#pragma once + +/** \file + * \ingroup bke + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "BLI_compiler_attrs.h" + +struct UserDef; +struct bUserAssetLibrary; + +void BKE_preferences_asset_library_free(struct bUserAssetLibrary *library) ATTR_NONNULL(); + +struct bUserAssetLibrary *BKE_preferences_asset_library_add(struct UserDef *userdef, + const char *name, + const char *path) ATTR_NONNULL(1); +void BKE_preferences_asset_library_name_set(struct UserDef *userdef, + struct bUserAssetLibrary *library, + const char *name) ATTR_NONNULL(); + +void BKE_preferences_asset_library_remove(struct UserDef *userdef, + struct bUserAssetLibrary *library) ATTR_NONNULL(); + +struct bUserAssetLibrary *BKE_preferences_asset_library_find_from_index( + const struct UserDef *userdef, int index) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT; +struct bUserAssetLibrary *BKE_preferences_asset_library_find_from_name( + const struct UserDef *userdef, const char *name) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT; +int BKE_preferences_asset_library_get_index(const struct UserDef *userdef, + const struct bUserAssetLibrary *library) + ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT; + +void BKE_preferences_asset_library_default_add(struct UserDef *userdef) ATTR_NONNULL(); + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index 23ba4eb4235..0067e1c8209 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -215,6 +215,7 @@ set(SRC intern/pbvh_bmesh.c intern/pointcache.c intern/pointcloud.cc + intern/preferences.c intern/report.c intern/rigidbody.c intern/scene.c @@ -376,6 +377,7 @@ set(SRC BKE_persistent_data_handle.hh BKE_pointcache.h BKE_pointcloud.h + BKE_preferences.h BKE_report.h BKE_rigidbody.h BKE_scene.h diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index f4f25c3a153..5b5bd416ef2 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -296,6 +296,7 @@ void BKE_blender_userdef_data_free(UserDef *userdef, bool clear_fonts) } BLI_freelistN(&userdef->autoexec_paths); + BLI_freelistN(&userdef->asset_libraries); BLI_freelistN(&userdef->uistyles); BLI_freelistN(&userdef->uifonts); diff --git a/source/blender/blenkernel/intern/blendfile.c b/source/blender/blenkernel/intern/blendfile.c index 567773507cf..0855db1a943 100644 --- a/source/blender/blenkernel/intern/blendfile.c +++ b/source/blender/blenkernel/intern/blendfile.c @@ -52,6 +52,7 @@ #include "BKE_layer.h" #include "BKE_lib_id.h" #include "BKE_main.h" +#include "BKE_preferences.h" #include "BKE_report.h" #include "BKE_scene.h" #include "BKE_screen.h" @@ -645,6 +646,8 @@ UserDef *BKE_blendfile_userdef_from_defaults(void) /* Default studio light. */ BKE_studiolight_default(userdef->light_param, userdef->light_ambient); + BKE_preferences_asset_library_default_add(userdef); + return userdef; } diff --git a/source/blender/blenkernel/intern/preferences.c b/source/blender/blenkernel/intern/preferences.c new file mode 100644 index 00000000000..c263ff7100f --- /dev/null +++ b/source/blender/blenkernel/intern/preferences.c @@ -0,0 +1,119 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** \file + * \ingroup bke + * + * User defined asset library API. + */ + +#include + +#include "MEM_guardedalloc.h" + +#include "BLI_listbase.h" +#include "BLI_path_util.h" +#include "BLI_string.h" +#include "BLI_string_utf8.h" +#include "BLI_string_utils.h" + +#include "BKE_appdir.h" +#include "BKE_preferences.h" + +#include "BLT_translation.h" + +#include "DNA_userdef_types.h" + +#define U BLI_STATIC_ASSERT(false, "Global 'U' not allowed, only use arguments passed in!") + +/* -------------------------------------------------------------------- */ +/** \name Asset Libraries + * \{ */ + +bUserAssetLibrary *BKE_preferences_asset_library_add(UserDef *userdef, + const char *name, + const char *path) +{ + bUserAssetLibrary *library = MEM_callocN(sizeof(*library), "bUserAssetLibrary"); + + BLI_addtail(&userdef->asset_libraries, library); + + if (name) { + BKE_preferences_asset_library_name_set(userdef, library, name); + } + if (path) { + BLI_strncpy(library->path, path, sizeof(library->path)); + } + + return library; +} + +void BKE_preferences_asset_library_name_set(UserDef *userdef, + bUserAssetLibrary *library, + const char *name) +{ + BLI_strncpy_utf8(library->name, name, sizeof(library->name)); + BLI_uniquename(&userdef->asset_libraries, + library, + name, + '.', + offsetof(bUserAssetLibrary, name), + sizeof(library->name)); +} + +/** + * Unlink and free a library preference member. + * \note Free's \a library itself. + */ +void BKE_preferences_asset_library_remove(UserDef *userdef, bUserAssetLibrary *library) +{ + BLI_freelinkN(&userdef->asset_libraries, library); +} + +bUserAssetLibrary *BKE_preferences_asset_library_find_from_index(const UserDef *userdef, int index) +{ + return BLI_findlink(&userdef->asset_libraries, index); +} + +bUserAssetLibrary *BKE_preferences_asset_library_find_from_name(const UserDef *userdef, + const char *name) +{ + return BLI_findstring(&userdef->asset_libraries, name, offsetof(bUserAssetLibrary, name)); +} + +int BKE_preferences_asset_library_get_index(const UserDef *userdef, + const bUserAssetLibrary *library) +{ + return BLI_findindex(&userdef->asset_libraries, library); +} + +void BKE_preferences_asset_library_default_add(UserDef *userdef) +{ + const char *asset_blend_name = "assets.blend"; + const char *doc_path = BKE_appdir_folder_default(); + + /* No home or documents path found, not much we can do. */ + if (!doc_path || !doc_path[0]) { + return; + } + + /* Add new "Default" library under '[doc_path]/assets.blend'. */ + + bUserAssetLibrary *library = BKE_preferences_asset_library_add(userdef, DATA_("Default"), NULL); + BLI_join_dirfile(library->path, sizeof(library->path), doc_path, asset_blend_name); +} + +/** \} */ diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 8dff1aa1ed0..a3e793038f7 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -3904,6 +3904,7 @@ static BHead *read_userdef(BlendFileData *bfd, FileData *fd, BHead *bhead) BLO_read_list(reader, &user->user_menus); BLO_read_list(reader, &user->addons); BLO_read_list(reader, &user->autoexec_paths); + BLO_read_list(reader, &user->asset_libraries); LISTBASE_FOREACH (wmKeyMap *, keymap, &user->user_keymaps) { keymap->modal_items = NULL; diff --git a/source/blender/blenloader/intern/versioning_userdef.c b/source/blender/blenloader/intern/versioning_userdef.c index 5ed7ab55851..f1572c563bf 100644 --- a/source/blender/blenloader/intern/versioning_userdef.c +++ b/source/blender/blenloader/intern/versioning_userdef.c @@ -44,6 +44,7 @@ #include "BKE_idprop.h" #include "BKE_keyconfig.h" #include "BKE_main.h" +#include "BKE_preferences.h" #include "BLO_readfile.h" @@ -830,6 +831,9 @@ void blo_do_versions_userdef(UserDef *userdef) */ { /* Keep this block, even when empty. */ + if (BLI_listbase_is_empty(&userdef->asset_libraries)) { + BKE_preferences_asset_library_default_add(userdef); + } } LISTBASE_FOREACH (bTheme *, btheme, &userdef->themes) { diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index c64a7dc1b9f..e7d55538f7e 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -756,6 +756,10 @@ static void write_userdef(BlendWriter *writer, const UserDef *userdef) BLO_write_struct(writer, bPathCompare, path_cmp); } + LISTBASE_FOREACH (const bUserAssetLibrary *, asset_library, &userdef->asset_libraries) { + BLO_write_struct(writer, bUserAssetLibrary, asset_library); + } + LISTBASE_FOREACH (const uiStyle *, style, &userdef->uistyles) { BLO_write_struct(writer, uiStyle, style); } diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index f39ad4c4ed5..72ed2cc0933 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -626,7 +626,11 @@ static bool ui_rna_is_userdef(PointerRNA *ptr, PropertyRNA *prop) if (base == NULL) { base = ptr->type; } - if (ELEM(base, &RNA_AddonPreferences, &RNA_KeyConfigPreferences, &RNA_KeyMapItem)) { + if (ELEM(base, + &RNA_AddonPreferences, + &RNA_KeyConfigPreferences, + &RNA_KeyMapItem, + &RNA_UserAssetLibrary)) { tag = true; } } diff --git a/source/blender/editors/space_buttons/buttons_ops.c b/source/blender/editors/space_buttons/buttons_ops.c index 8bdc2ed993f..8f57abf83ae 100644 --- a/source/blender/editors/space_buttons/buttons_ops.c +++ b/source/blender/editors/space_buttons/buttons_ops.c @@ -338,7 +338,7 @@ static int file_browse_invoke(bContext *C, wmOperator *op, const wmEvent *event) is_relative = BLI_path_is_rel(str); } - if (UNLIKELY(ptr.data == &U)) { + if (UNLIKELY(ptr.data == &U || is_userdef)) { is_relative = false; } diff --git a/source/blender/editors/space_userpref/userpref_ops.c b/source/blender/editors/space_userpref/userpref_ops.c index d823530fd89..9cc8cc6ddaa 100644 --- a/source/blender/editors/space_userpref/userpref_ops.c +++ b/source/blender/editors/space_userpref/userpref_ops.c @@ -30,6 +30,7 @@ #include "BKE_context.h" #include "BKE_global.h" #include "BKE_main.h" +#include "BKE_preferences.h" #include "BKE_report.h" #include "RNA_access.h" @@ -133,9 +134,69 @@ static void PREFERENCES_OT_autoexec_path_remove(wmOperatorType *ot) /** \} */ +/* -------------------------------------------------------------------- */ +/** \name Add Asset Library Operator + * \{ */ + +static int preferences_asset_library_add_exec(bContext *UNUSED(C), wmOperator *UNUSED(op)) +{ + BKE_preferences_asset_library_add(&U, NULL, NULL); + U.runtime.is_dirty = true; + return OPERATOR_FINISHED; +} + +static void PREFERENCES_OT_asset_library_add(wmOperatorType *ot) +{ + ot->name = "Add Asset Library"; + ot->idname = "PREFERENCES_OT_asset_library_add"; + ot->description = + "Add a path to a .blend file to be used by the Asset Browser as source of assets"; + + ot->exec = preferences_asset_library_add_exec; + + ot->flag = OPTYPE_INTERNAL; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Remove Asset Library Operator + * \{ */ + +static int preferences_asset_library_remove_exec(bContext *UNUSED(C), wmOperator *op) +{ + const int index = RNA_int_get(op->ptr, "index"); + bUserAssetLibrary *library = BLI_findlink(&U.asset_libraries, index); + if (library) { + BKE_preferences_asset_library_remove(&U, library); + U.runtime.is_dirty = true; + } + return OPERATOR_FINISHED; +} + +static void PREFERENCES_OT_asset_library_remove(wmOperatorType *ot) +{ + ot->name = "Remove Asset Library"; + ot->idname = "PREFERENCES_OT_asset_library_remove"; + ot->description = + "Remove a path to a .blend file, so the Asset Browser will not attempt to show it anymore"; + + ot->exec = preferences_asset_library_remove_exec; + + ot->flag = OPTYPE_INTERNAL; + + RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "", 0, 1000); +} + +/** \} */ + void ED_operatortypes_userpref(void) { WM_operatortype_append(PREFERENCES_OT_reset_default_theme); + WM_operatortype_append(PREFERENCES_OT_autoexec_path_add); WM_operatortype_append(PREFERENCES_OT_autoexec_path_remove); + + WM_operatortype_append(PREFERENCES_OT_asset_library_add); + WM_operatortype_append(PREFERENCES_OT_asset_library_remove); } diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index 8c4c43e4446..1bd013c7d54 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -569,6 +569,13 @@ enum { USER_MENU_TYPE_PROP = 4, }; +typedef struct bUserAssetLibrary { + struct bUserAssetLibrary *next, *prev; + + char name[64]; /* MAX_NAME */ + char path[1024]; /* FILE_MAX */ +} bUserAssetLibrary; + typedef struct SolidLight { int flag; float smooth; @@ -740,6 +747,8 @@ typedef struct UserDef { struct ListBase autoexec_paths; /** #bUserMenu. */ struct ListBase user_menus; + /** #bUserAssetLibrary */ + struct ListBase asset_libraries; char keyconfigstr[64]; diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index da15489370a..0b0895f9db0 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -697,6 +697,7 @@ extern StructRNA RNA_UVProjector; extern StructRNA RNA_UVWarpModifier; extern StructRNA RNA_UnitSettings; extern StructRNA RNA_UnknownType; +extern StructRNA RNA_UserAssetLibrary; extern StructRNA RNA_UserSolidLight; extern StructRNA RNA_VertexcolorGpencilModifier; extern StructRNA RNA_VectorFont; diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 115bc221ce1..2175cddcd7f 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -184,6 +184,7 @@ static const EnumPropertyItem rna_enum_userdef_viewport_aa_items[] = { # include "BKE_mesh_runtime.h" # include "BKE_paint.h" # include "BKE_pbvh.h" +# include "BKE_preferences.h" # include "BKE_screen.h" # include "DEG_depsgraph.h" @@ -335,6 +336,12 @@ static void rna_userdef_language_update(Main *UNUSED(bmain), USERDEF_TAG_DIRTY; } +static void rna_userdef_asset_library_name_set(PointerRNA *ptr, const char *value) +{ + bUserAssetLibrary *library = (bUserAssetLibrary *)ptr->data; + BKE_preferences_asset_library_name_set(&U, library, value); +} + static void rna_userdef_script_autoexec_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) @@ -5968,6 +5975,29 @@ static void rna_def_userdef_keymap(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Key Config", "The name of the active key configuration"); } +static void rna_def_userdef_filepaths_asset_library(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "UserAssetLibrary", NULL); + RNA_def_struct_sdna(srna, "bUserAssetLibrary"); + RNA_def_struct_clear_flag(srna, STRUCT_UNDO); + RNA_def_struct_ui_text( + srna, "Asset Library", "Settings to define a reusable library for Asset Browsers to use"); + + prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); + RNA_def_property_ui_text( + prop, "Name", "Identifier (not necessarily unique) for the asset library"); + RNA_def_property_string_funcs(prop, NULL, NULL, "rna_userdef_asset_library_name_set"); + RNA_def_struct_name_property(srna, prop); + RNA_def_property_update(prop, 0, "rna_userdef_update"); + + prop = RNA_def_property(srna, "path", PROP_STRING, PROP_FILEPATH); + RNA_def_property_ui_text(prop, "Path", "Path to a .blend file to use as an asset library"); + RNA_def_property_update(prop, 0, "rna_userdef_update"); +} + static void rna_def_userdef_filepaths(BlenderRNA *brna) { PropertyRNA *prop; @@ -6140,6 +6170,12 @@ static void rna_def_userdef_filepaths(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Save Preview Images", "Enables automatic saving of preview images in the .blend file"); + + rna_def_userdef_filepaths_asset_library(brna); + + prop = RNA_def_property(srna, "asset_libraries", PROP_COLLECTION, PROP_NONE); + RNA_def_property_struct_type(prop, "UserAssetLibrary"); + RNA_def_property_ui_text(prop, "Asset Libraries", ""); } static void rna_def_userdef_experimental(BlenderRNA *brna) -- cgit v1.2.3 From 70474e1a7cc45a1b1cc08d39b3e472c88c8d3225 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Mon, 14 Dec 2020 13:50:36 +0100 Subject: Asset System: Prepare File Browser backend for the Asset Browser The Asset Browser will be a sub-editor of the File Browser. This prepares the File Browser code for that. **File-Lists** * Support loading assets with metadata read from external files into the file-list. * New main based file-list type, for the "Current File" asset library. * Refresh file-list when switching between browse modes or asset libraries. * Support empty file-lists (asset library with no assets). * Store file previews as icons, so scripts can reference them via icon-id. See previous commit. **Space Data** * Introduce "browse mode" to differeniate between file and asset browsing. * Add `FileAssetSelectParams` to `SpaceFile`, with `FileSelectParams` as base. Makes sure data is separated between asset and file browsing when switching between them. The active params can be obtained through `ED_fileselect_get_active_params()`. * `FileAssetSelectParams` stores the currently visible asset library ID. * Introduce file history abstraction so file and asset browsing can keep a separate history (previous and next directories). **General** * Option to only show asset data-blocks while file browsing (not exposed here). * Add "active_file" context member, so scripts can get and display info about the active file. * Add "active_id" context member, so `ED_OT_lib_id_load_custom_preview` can set a custom ID preview. (Only for "Current File" asset library) * Expose some of `FileDirEntry` in RNA as (non-editable). That way scripts can obtain name, preview icon and asset-data. Part of the first Asset Browser milestone. Check the #asset_browser_milestone_1 project milestone on developer.blender.org. Differential Revision: https://developer.blender.org/D9724 Reviewed by: Bastien Montagne --- source/blender/blenkernel/intern/screen.c | 11 +- source/blender/blenloader/intern/readfile.c | 1 + source/blender/editors/include/ED_fileselect.h | 7 +- source/blender/editors/space_file/file_intern.h | 1 + source/blender/editors/space_file/file_ops.c | 9 +- source/blender/editors/space_file/filelist.c | 655 ++++++++++++++++----- source/blender/editors/space_file/filelist.h | 19 +- source/blender/editors/space_file/filesel.c | 188 ++++-- source/blender/editors/space_file/space_file.c | 139 ++++- source/blender/makesdna/DNA_space_types.h | 125 +++- source/blender/makesrna/RNA_access.h | 2 + source/blender/makesrna/RNA_enum_types.h | 1 + source/blender/makesrna/intern/rna_space.c | 241 +++++++- .../windowmanager/intern/wm_operator_props.c | 2 + 14 files changed, 1159 insertions(+), 242 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c index ae817c46931..52c41c9fd05 100644 --- a/source/blender/blenkernel/intern/screen.c +++ b/source/blender/blenkernel/intern/screen.c @@ -1266,6 +1266,9 @@ static void write_area_regions(BlendWriter *writer, ScrArea *area) if (sfile->params) { BLO_write_struct(writer, FileSelectParams, sfile->params); } + if (sfile->asset_params) { + BLO_write_struct(writer, FileAssetSelectParams, sfile->asset_params); + } } else if (sl->spacetype == SPACE_SEQ) { BLO_write_struct(writer, SpaceSeq, sl); @@ -1663,11 +1666,14 @@ static void direct_link_area(BlendDataReader *reader, ScrArea *area) * plus, it isn't saved to files yet! */ sfile->folders_prev = sfile->folders_next = NULL; + BLI_listbase_clear(&sfile->folder_histories); sfile->files = NULL; sfile->layout = NULL; sfile->op = NULL; sfile->previews_timer = NULL; + sfile->tags = 0; BLO_read_data_address(reader, &sfile->params); + BLO_read_data_address(reader, &sfile->asset_params); } else if (sl->spacetype == SPACE_CLIP) { SpaceClip *sclip = (SpaceClip *)sl; @@ -1751,8 +1757,11 @@ void BKE_screen_area_blend_read_lib(BlendLibReader *reader, ID *parent_id, ScrAr } break; } - case SPACE_FILE: + case SPACE_FILE: { + SpaceFile *sfile = (SpaceFile *)sl; + sfile->tags |= FILE_TAG_REBUILD_MAIN_FILES; break; + } case SPACE_ACTION: { SpaceAction *saction = (SpaceAction *)sl; bDopeSheet *ads = &saction->ads; diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index a3e793038f7..bccc7150523 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -2751,6 +2751,7 @@ static void lib_link_workspace_layout_restore(struct IDNameLib_Map *id_map, SpaceFile *sfile = (SpaceFile *)sl; sfile->op = NULL; sfile->previews_timer = NULL; + sfile->tags = FILE_TAG_REBUILD_MAIN_FILES; } else if (sl->spacetype == SPACE_ACTION) { SpaceAction *saction = (SpaceAction *)sl; diff --git a/source/blender/editors/include/ED_fileselect.h b/source/blender/editors/include/ED_fileselect.h index a5a8df916d6..3288cf11cb0 100644 --- a/source/blender/editors/include/ED_fileselect.h +++ b/source/blender/editors/include/ED_fileselect.h @@ -29,6 +29,7 @@ extern "C" { struct ARegion; struct FileSelectParams; +struct FileAssetSelectParams; struct Scene; struct ScrArea; struct SpaceFile; @@ -103,14 +104,14 @@ struct rcti; struct FileSelectParams *ED_fileselect_ensure_active_params(struct SpaceFile *sfile); struct FileSelectParams *ED_fileselect_get_active_params(const struct SpaceFile *sfile); +struct FileSelectParams *ED_fileselect_get_file_params(const struct SpaceFile *sfile); +struct FileAssetSelectParams *ED_fileselect_get_asset_params(const struct SpaceFile *sfile); void ED_fileselect_set_params_from_userdef(struct SpaceFile *sfile); void ED_fileselect_params_to_userdef(struct SpaceFile *sfile, const int temp_win_size[], const bool is_maximized); -void ED_fileselect_reset_params(struct SpaceFile *sfile); - void ED_fileselect_init_layout(struct SpaceFile *sfile, struct ARegion *region); FileLayout *ED_fileselect_get_layout(struct SpaceFile *sfile, struct ARegion *region); @@ -142,6 +143,8 @@ void ED_fileselect_exit(struct wmWindowManager *wm, struct Scene *owner_scene, struct SpaceFile *sfile); +bool ED_fileselect_is_asset_browser(const struct SpaceFile *sfile); + void ED_fileselect_window_params_get(const struct wmWindow *win, int win_size[2], bool *is_maximized); diff --git a/source/blender/editors/space_file/file_intern.h b/source/blender/editors/space_file/file_intern.h index b459c02d9e5..a0e02681e0e 100644 --- a/source/blender/editors/space_file/file_intern.h +++ b/source/blender/editors/space_file/file_intern.h @@ -90,6 +90,7 @@ void file_sfile_to_operator(struct Main *bmain, struct wmOperator *op, struct Sp void file_operator_to_sfile(struct Main *bmain, struct SpaceFile *sfile, struct wmOperator *op); /* filesel.c */ +void fileselect_refresh_params(struct SpaceFile *sfile); void fileselect_file_set(SpaceFile *sfile, const int index); bool file_attribute_column_type_enabled(const FileSelectParams *params, FileAttributeColumnType column); diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c index b98348307f3..8af84f65ced 100644 --- a/source/blender/editors/space_file/file_ops.c +++ b/source/blender/editors/space_file/file_ops.c @@ -930,6 +930,7 @@ void FILE_OT_select_all(wmOperatorType *ot) /* Note we could get rid of this one, but it's used by some addon so... * Does not hurt keeping it around for now. */ +/* TODO disallow bookmark editing in assets mode? */ static int bookmark_select_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); @@ -1836,10 +1837,6 @@ static int file_previous_exec(bContext *C, wmOperator *UNUSED(op)) FileSelectParams *params = ED_fileselect_get_active_params(sfile); if (params) { - if (!sfile->folders_next) { - sfile->folders_next = folderlist_new(); - } - folderlist_pushdir(sfile->folders_next, params->dir); folderlist_popdir(sfile->folders_prev, params->dir); folderlist_pushdir(sfile->folders_next, params->dir); @@ -1874,10 +1871,6 @@ static int file_next_exec(bContext *C, wmOperator *UNUSED(unused)) SpaceFile *sfile = CTX_wm_space_file(C); FileSelectParams *params = ED_fileselect_get_active_params(sfile); if (params) { - if (!sfile->folders_next) { - sfile->folders_next = folderlist_new(); - } - folderlist_pushdir(sfile->folders_prev, params->dir); folderlist_popdir(sfile->folders_next, params->dir); diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c index e87142a7096..5dc5f741ac3 100644 --- a/source/blender/editors/space_file/filelist.c +++ b/source/blender/editors/space_file/filelist.c @@ -53,13 +53,17 @@ # include "BLI_winstuff.h" #endif +#include "BKE_asset.h" #include "BKE_context.h" #include "BKE_global.h" #include "BKE_icons.h" #include "BKE_idtype.h" +#include "BKE_lib_id.h" #include "BKE_main.h" +#include "BKE_main_idmap.h" #include "BLO_readfile.h" +#include "DNA_asset_types.h" #include "DNA_space_types.h" #include "ED_datafiles.h" @@ -82,6 +86,8 @@ #include "filelist.h" +#define FILEDIR_NBR_ENTRIES_UNSET -1 + /* ----------------- FOLDERLIST (previous/next) -------------- */ typedef struct FolderList { @@ -89,12 +95,6 @@ typedef struct FolderList { char *foldername; } FolderList; -ListBase *folderlist_new(void) -{ - ListBase *p = MEM_callocN(sizeof(*p), __func__); - return p; -} - void folderlist_popdir(struct ListBase *folderlist, char *dir) { const char *prev_dir; @@ -117,6 +117,10 @@ void folderlist_popdir(struct ListBase *folderlist, char *dir) void folderlist_pushdir(ListBase *folderlist, const char *dir) { + if (!dir[0]) { + return; + } + struct FolderList *folder, *previous_folder; previous_folder = folderlist->last; @@ -153,7 +157,7 @@ int folderlist_clear_next(struct SpaceFile *sfile) struct FolderList *folder; /* if there is no folder_next there is nothing we can clear */ - if (!sfile->folders_next) { + if (BLI_listbase_is_empty(sfile->folders_next)) { return 0; } @@ -180,23 +184,79 @@ void folderlist_free(ListBase *folderlist) } } -ListBase *folderlist_duplicate(ListBase *folderlist) +static ListBase folderlist_duplicate(ListBase *folderlist) { + ListBase folderlistn = {NULL}; - if (folderlist) { - ListBase *folderlistn = MEM_callocN(sizeof(*folderlistn), __func__); - FolderList *folder; + BLI_duplicatelist(&folderlistn, folderlist); + + for (FolderList *folder = folderlistn.first; folder; folder = folder->next) { + folder->foldername = MEM_dupallocN(folder->foldername); + } + return folderlistn; +} - BLI_duplicatelist(folderlistn, folderlist); +/* ----------------- Folder-History (wraps/owns file list above) -------------- */ - for (folder = folderlistn->first; folder; folder = folder->next) { - folder->foldername = MEM_dupallocN(folder->foldername); +static FileFolderHistory *folder_history_find(const SpaceFile *sfile, eFileBrowse_Mode browse_mode) +{ + LISTBASE_FOREACH (FileFolderHistory *, history, &sfile->folder_histories) { + if (history->browse_mode == browse_mode) { + return history; } - return folderlistn; } + return NULL; } +void folder_history_list_ensure_for_active_browse_mode(SpaceFile *sfile) +{ + FileFolderHistory *history = folder_history_find(sfile, sfile->browse_mode); + + if (!history) { + history = MEM_callocN(sizeof(*history), __func__); + history->browse_mode = sfile->browse_mode; + BLI_addtail(&sfile->folder_histories, history); + } + + sfile->folders_next = &history->folders_next; + sfile->folders_prev = &history->folders_prev; +} + +static void folder_history_entry_free(SpaceFile *sfile, FileFolderHistory *history) +{ + if (sfile->folders_prev == &history->folders_prev) { + sfile->folders_prev = NULL; + } + if (sfile->folders_next == &history->folders_next) { + sfile->folders_next = NULL; + } + folderlist_free(&history->folders_prev); + folderlist_free(&history->folders_next); + BLI_freelinkN(&sfile->folder_histories, history); +} + +void folder_history_list_free(SpaceFile *sfile) +{ + LISTBASE_FOREACH_MUTABLE (FileFolderHistory *, history, &sfile->folder_histories) { + folder_history_entry_free(sfile, history); + } +} + +ListBase folder_history_list_duplicate(ListBase *listbase) +{ + ListBase histories = {NULL}; + + LISTBASE_FOREACH (FileFolderHistory *, history, listbase) { + FileFolderHistory *history_new = MEM_dupallocN(history); + history_new->folders_prev = folderlist_duplicate(&history->folders_prev); + history_new->folders_next = folderlist_duplicate(&history->folders_next); + BLI_addtail(&histories, history_new); + } + + return histories; +} + /* ------------------FILELIST------------------------ */ typedef struct FileListInternEntry { @@ -216,6 +276,24 @@ typedef struct FileListInternEntry { /** not strictly needed, but used during sorting, avoids to have to recompute it there... */ char *name; + /** + * This is data from the current main, represented by this file. It's crucial that this is + * updated correctly on undo, redo and file reading (without UI). The space is responsible to + * take care of that. + */ + struct { + /** When showing local IDs (FILE_MAIN, FILE_MAIN_ASSET), the ID this file entry represents. */ + ID *id; + + /* For the few file types that have the preview already in memory. For others, there's delayed + * preview reading from disk. Non-owning pointer. */ + PreviewImage *preview_image; + } local_data; + + /** When the file represents an asset read from another file, it is stored here. + * Owning pointer. */ + AssetMetaData *imported_asset_data; + /** Defined in BLI_fileops.h */ eFileAttributes attributes; BLI_stat_t st; @@ -267,7 +345,11 @@ typedef struct FileListEntryPreview { char path[FILE_MAX]; uint flags; int index; - ImBuf *img; + /* Some file types load the memory from runtime data, not from disk. We just wait until it's done + * generating (BKE_previewimg_is_finished()). */ + PreviewImage *in_memory_preview; + + int icon_id; } FileListEntryPreview; /* Dummy wrapper around FileListEntryPreview to ensure we do not access freed memory when freeing @@ -290,11 +372,16 @@ enum { FLF_HIDE_DOT = 1 << 1, FLF_HIDE_PARENT = 1 << 2, FLF_HIDE_LIB_DIR = 1 << 3, + FLF_ASSETS_ONLY = 1 << 4, }; typedef struct FileList { FileDirEntryArr filelist; + eFileSelectType type; + /* The library this list was created for. Stored here so we know when to re-read. */ + FileSelectAssetLibraryUID *asset_library; + short flags; short sort; @@ -324,10 +411,13 @@ typedef struct FileList { bool (*checkdirf)(struct FileList *, char *, const bool); /* Fill filelist (to be called by read job). */ - void (*read_jobf)(struct FileList *, const char *, short *, short *, float *, ThreadMutex *); + void (*read_jobf)( + Main *, struct FileList *, const char *, short *, short *, float *, ThreadMutex *); /* Filter an entry of current filelist. */ bool (*filterf)(struct FileListInternEntry *, const char *, FileListFilter *); + + short tags; /* FileListTags */ } FileList; /* FileList.flags */ @@ -340,6 +430,14 @@ enum { FL_SORT_INVERT = 1 << 5, }; +/* FileList.tags */ +enum FileListTags { + /** The file list has references to main data (IDs) and needs special care. */ + FILELIST_TAGS_USES_MAIN_DATA = (1 << 0), + /** The file list type is not thread-safe. */ + FILELIST_TAGS_NO_THREADS = (1 << 2), +}; + #define SPECIAL_IMG_SIZE 256 #define SPECIAL_IMG_ROWS 1 #define SPECIAL_IMG_COLS 7 @@ -357,24 +455,34 @@ enum { static ImBuf *gSpecialFileImages[SPECIAL_IMG_MAX]; -static void filelist_readjob_main(FileList *filelist, +static void filelist_readjob_main(Main *current_main, + FileList *filelist, const char *main_name, short *stop, short *do_update, float *progress, ThreadMutex *lock); -static void filelist_readjob_lib(FileList *filelist, +static void filelist_readjob_lib(Main *current_main, + FileList *filelist, const char *main_name, short *stop, short *do_update, float *progress, ThreadMutex *lock); -static void filelist_readjob_dir(FileList *filelist, +static void filelist_readjob_dir(Main *current_main, + FileList *filelist, const char *main_name, short *stop, short *do_update, float *progress, ThreadMutex *lock); +static void filelist_readjob_main_assets(Main *current_main, + FileList *filelist, + const char *main_name, + short *stop, + short *do_update, + float *progress, + ThreadMutex *lock); /* helper, could probably go in BKE actually? */ static int groupname_to_code(const char *group); @@ -694,6 +802,11 @@ static bool is_filtered_hidden(const char *filename, return true; } #endif + /* For data-blocks (but not the group directories), check the asset-only filter. */ + if (!(file->typeflag & FILE_TYPE_DIR) && (file->typeflag & FILE_TYPE_BLENDERLIB) && + (filter->flags & FLF_ASSETS_ONLY) && !(file->typeflag & FILE_TYPE_ASSET)) { + return true; + } return false; } @@ -737,51 +850,61 @@ static bool is_filtered_file(FileListInternEntry *file, return is_filtered; } -static bool is_filtered_lib(FileListInternEntry *file, const char *root, FileListFilter *filter) +static bool is_filtered_id_file(const FileListInternEntry *file, + const char *id_group, + const char *name, + const FileListFilter *filter) { - bool is_filtered; - char path[FILE_MAX_LIBEXTRA], dir[FILE_MAX_LIBEXTRA], *group, *name; - - BLI_join_dirfile(path, sizeof(path), root, file->relpath); - - if (BLO_library_path_explode(path, dir, &group, &name)) { - is_filtered = !is_filtered_hidden(file->relpath, filter, file); - if (is_filtered && !FILENAME_IS_CURRPAR(file->relpath)) { - /* We only check for types if some type are enabled in filtering. */ - if ((filter->filter || filter->filter_id) && (filter->flags & FLF_DO_FILTER)) { - if (file->typeflag & FILE_TYPE_DIR) { - if (file->typeflag & - (FILE_TYPE_BLENDERLIB | FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) { - if (!(filter->filter & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP))) { - is_filtered = false; - } - } - else { - if (!(filter->filter & FILE_TYPE_FOLDER)) { - is_filtered = false; - } + bool is_filtered = !is_filtered_hidden(file->relpath, filter, file); + if (is_filtered && !FILENAME_IS_CURRPAR(file->relpath)) { + /* We only check for types if some type are enabled in filtering. */ + if ((filter->filter || filter->filter_id) && (filter->flags & FLF_DO_FILTER)) { + if (file->typeflag & FILE_TYPE_DIR) { + if (file->typeflag & + (FILE_TYPE_BLENDERLIB | FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) { + if (!(filter->filter & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP))) { + is_filtered = false; } } - if (is_filtered && group) { - if (!name && (filter->flags & FLF_HIDE_LIB_DIR)) { + else { + if (!(filter->filter & FILE_TYPE_FOLDER)) { is_filtered = false; } - else { - uint64_t filter_id = groupname_to_filter_id(group); - if (!(filter_id & filter->filter_id)) { - is_filtered = false; - } - } } } - /* If there's a filter string, apply it as filter even if FLF_DO_FILTER is not set. */ - if (is_filtered && (filter->filter_search[0] != '\0')) { - if (fnmatch(filter->filter_search, file->relpath, FNM_CASEFOLD) != 0) { + if (is_filtered && id_group) { + if (!name && (filter->flags & FLF_HIDE_LIB_DIR)) { is_filtered = false; } + else { + uint64_t filter_id = groupname_to_filter_id(id_group); + if (!(filter_id & filter->filter_id)) { + is_filtered = false; + } + } + } + } + /* If there's a filter string, apply it as filter even if FLF_DO_FILTER is not set. */ + if (is_filtered && (filter->filter_search[0] != '\0')) { + if (fnmatch(filter->filter_search, file->relpath, FNM_CASEFOLD) != 0) { + is_filtered = false; } } } + + return is_filtered; +} + +static bool is_filtered_lib(FileListInternEntry *file, const char *root, FileListFilter *filter) +{ + bool is_filtered; + char path[FILE_MAX_LIBEXTRA], dir[FILE_MAX_LIBEXTRA], *group, *name; + + BLI_join_dirfile(path, sizeof(path), root, file->relpath); + + if (BLO_library_path_explode(path, dir, &group, &name)) { + is_filtered = is_filtered_id_file(file, group, name, filter); + } else { is_filtered = is_filtered_file(file, root, filter); } @@ -796,6 +919,14 @@ static bool is_filtered_main(FileListInternEntry *file, return !is_filtered_hidden(file->relpath, filter, file); } +static bool is_filtered_main_assets(FileListInternEntry *file, + const char *UNUSED(dir), + FileListFilter *filter) +{ + /* "Filtered" means *not* being filtered out... So return true if the file should be visible. */ + return is_filtered_id_file(file, file->relpath, file->name, filter); +} + static void filelist_filter_clear(FileList *filelist) { filelist->flags |= FL_NEED_FILTERING; @@ -807,7 +938,7 @@ void filelist_filter(FileList *filelist) const int num_files = filelist->filelist.nbr_entries; FileListInternEntry **filtered_tmp, *file; - if (filelist->filelist.nbr_entries == 0) { + if (ELEM(filelist->filelist.nbr_entries, FILEDIR_NBR_ENTRIES_UNSET, 0)) { return; } @@ -858,6 +989,7 @@ void filelist_setfilter_options(FileList *filelist, const bool hide_parent, const uint64_t filter, const uint64_t filter_id, + const bool filter_assets_only, const char *filter_glob, const char *filter_search) { @@ -875,6 +1007,10 @@ void filelist_setfilter_options(FileList *filelist, filelist->filter_data.flags ^= FLF_HIDE_PARENT; update = true; } + if (((filelist->filter_data.flags & FLF_ASSETS_ONLY) != 0) != (filter_assets_only != 0)) { + filelist->filter_data.flags ^= FLF_ASSETS_ONLY; + update = true; + } if (filelist->filter_data.filter != filter) { filelist->filter_data.filter = filter; update = true; @@ -903,6 +1039,50 @@ void filelist_setfilter_options(FileList *filelist, } } +/** + * Checks two libraries for equality. + * \return True if the libraries match. + */ +static bool filelist_compare_asset_libraries(const FileSelectAssetLibraryUID *library_a, + const FileSelectAssetLibraryUID *library_b) +{ + if (library_a->type != library_b->type) { + return false; + } + if (library_a->type == FILE_ASSET_LIBRARY_CUSTOM) { + return STREQ(library_a->custom_library_identifier, library_b->custom_library_identifier); + } + + return true; +} + +/** + * \param asset_library: May be NULL to unset the library. + */ +void filelist_setlibrary(FileList *filelist, const FileSelectAssetLibraryUID *asset_library) +{ + /* Unset if needed. */ + if (!asset_library) { + if (filelist->asset_library) { + MEM_SAFE_FREE(filelist->asset_library); + filelist->flags |= FL_FORCE_RESET; + } + return; + } + + if (!filelist->asset_library) { + filelist->asset_library = MEM_mallocN(sizeof(*filelist->asset_library), + "filelist asset library"); + *filelist->asset_library = *asset_library; + + filelist->flags |= FL_FORCE_RESET; + } + else if (!filelist_compare_asset_libraries(filelist->asset_library, asset_library)) { + *filelist->asset_library = *asset_library; + filelist->flags |= FL_FORCE_RESET; + } +} + /* ********** Icon/image helpers ********** */ void filelist_init_icons(void) @@ -960,7 +1140,12 @@ ImBuf *filelist_getimage(struct FileList *filelist, const int index) { FileDirEntry *file = filelist_geticon_get_file(filelist, index); - return file->image; + return file->preview_icon_id ? BKE_icon_imbuf_get_buffer(file->preview_icon_id) : NULL; +} + +ImBuf *filelist_file_getimage(const FileDirEntry *file) +{ + return file->preview_icon_id ? BKE_icon_imbuf_get_buffer(file->preview_icon_id) : NULL; } static ImBuf *filelist_geticon_image_ex(FileDirEntry *file) @@ -993,7 +1178,7 @@ static int filelist_geticon_ex(FileDirEntry *file, const bool is_main, const bool ignore_libdir) { - const int typeflag = file->typeflag; + const eFileSel_File_Types typeflag = file->typeflag; if ((typeflag & FILE_TYPE_DIR) && !(ignore_libdir && (typeflag & (FILE_TYPE_BLENDERLIB | FILE_TYPE_BLENDER)))) { @@ -1160,6 +1345,14 @@ static bool filelist_checkdir_main(struct FileList *filelist, char *r_dir, const return filelist_checkdir_lib(filelist, r_dir, do_change); } +static bool filelist_checkdir_main_assets(struct FileList *UNUSED(filelist), + char *UNUSED(r_dir), + const bool UNUSED(do_change)) +{ + /* Main is always valid. */ + return true; +} + static void filelist_entry_clear(FileDirEntry *entry) { if (entry->name) { @@ -1174,8 +1367,9 @@ static void filelist_entry_clear(FileDirEntry *entry) if (entry->redirection_path) { MEM_freeN(entry->redirection_path); } - if (entry->image) { - IMB_freeImBuf(entry->image); + if (entry->preview_icon_id) { + BKE_icon_delete(entry->preview_icon_id); + entry->preview_icon_id = 0; } /* For now, consider FileDirEntryRevision::poin as not owned here, * so no need to do anything about it */ @@ -1232,8 +1426,8 @@ static void filelist_direntryarr_free(FileDirEntryArr *array) #else BLI_assert(BLI_listbase_is_empty(&array->entries)); #endif - array->nbr_entries = 0; - array->nbr_entries_filtered = -1; + array->nbr_entries = FILEDIR_NBR_ENTRIES_UNSET; + array->nbr_entries_filtered = FILEDIR_NBR_ENTRIES_UNSET; array->entry_idx_start = -1; array->entry_idx_end = -1; } @@ -1249,6 +1443,10 @@ static void filelist_intern_entry_free(FileListInternEntry *entry) if (entry->name) { MEM_freeN(entry->name); } + /* If we own the asset-data (it was generated from external file data), free it. */ + if (entry->imported_asset_data) { + BKE_asset_metadata_free(&entry->imported_asset_data); + } MEM_freeN(entry); } @@ -1272,37 +1470,52 @@ static void filelist_cache_preview_runf(TaskPool *__restrict pool, void *taskdat FileListEntryPreview *preview = preview_taskdata->preview; ThumbSource source = 0; + bool done = false; // printf("%s: Start (%d)...\n", __func__, threadid); - // printf("%s: %d - %s - %p\n", __func__, preview->index, preview->path, preview->img); - BLI_assert(preview->flags & - (FILE_TYPE_IMAGE | FILE_TYPE_MOVIE | FILE_TYPE_FTFONT | FILE_TYPE_BLENDER | - FILE_TYPE_BLENDER_BACKUP | FILE_TYPE_BLENDERLIB)); - - if (preview->flags & FILE_TYPE_IMAGE) { - source = THB_SOURCE_IMAGE; - } - else if (preview->flags & - (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP | FILE_TYPE_BLENDERLIB)) { - source = THB_SOURCE_BLEND; - } - else if (preview->flags & FILE_TYPE_MOVIE) { - source = THB_SOURCE_MOVIE; - } - else if (preview->flags & FILE_TYPE_FTFONT) { - source = THB_SOURCE_FONT; + if (preview->in_memory_preview) { + if (BKE_previewimg_is_finished(preview->in_memory_preview, ICON_SIZE_PREVIEW)) { + ImBuf *imbuf = BKE_previewimg_to_imbuf(preview->in_memory_preview, ICON_SIZE_PREVIEW); + preview->icon_id = BKE_icon_imbuf_create(imbuf); + done = true; + } } + else { + // printf("%s: %d - %s - %p\n", __func__, preview->index, preview->path, preview->img); + BLI_assert(preview->flags & + (FILE_TYPE_IMAGE | FILE_TYPE_MOVIE | FILE_TYPE_FTFONT | FILE_TYPE_BLENDER | + FILE_TYPE_BLENDER_BACKUP | FILE_TYPE_BLENDERLIB)); - IMB_thumb_path_lock(preview->path); - /* Always generate biggest preview size for now, it's simpler and avoids having to re-generate in - * case user switch to a bigger preview size. */ - preview->img = IMB_thumb_manage(preview->path, THB_LARGE, source); - IMB_thumb_path_unlock(preview->path); + if (preview->flags & FILE_TYPE_IMAGE) { + source = THB_SOURCE_IMAGE; + } + else if (preview->flags & + (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP | FILE_TYPE_BLENDERLIB)) { + source = THB_SOURCE_BLEND; + } + else if (preview->flags & FILE_TYPE_MOVIE) { + source = THB_SOURCE_MOVIE; + } + else if (preview->flags & FILE_TYPE_FTFONT) { + source = THB_SOURCE_FONT; + } + + IMB_thumb_path_lock(preview->path); + /* Always generate biggest preview size for now, it's simpler and avoids having to re-generate + * in case user switch to a bigger preview size. */ + ImBuf *imbuf = IMB_thumb_manage(preview->path, THB_LARGE, source); + IMB_thumb_path_unlock(preview->path); + preview->icon_id = BKE_icon_imbuf_create(imbuf); - /* That way task freeing function won't free th preview, since it does not own it anymore. */ - atomic_cas_ptr((void **)&preview_taskdata->preview, preview, NULL); - BLI_thread_queue_push(cache->previews_done, preview); + done = true; + } + + if (done) { + /* That way task freeing function won't free th preview, since it does not own it anymore. */ + atomic_cas_ptr((void **)&preview_taskdata->preview, preview, NULL); + BLI_thread_queue_push(cache->previews_done, preview); + } // printf("%s: End (%d)...\n", __func__, threadid); } @@ -1315,8 +1528,8 @@ static void filelist_cache_preview_freef(TaskPool *__restrict UNUSED(pool), void /* preview_taskdata->preview is atomically set to NULL once preview has been processed and sent * to previews_done queue. */ if (preview != NULL) { - if (preview->img) { - IMB_freeImBuf(preview->img); + if (preview->icon_id) { + BKE_icon_delete(preview->icon_id); } MEM_freeN(preview); } @@ -1342,8 +1555,8 @@ static void filelist_cache_previews_clear(FileListEntryCache *cache) while ((preview = BLI_thread_queue_pop_timeout(cache->previews_done, 0))) { // printf("%s: DONE %d - %s - %p\n", __func__, preview->index, preview->path, // preview->img); - if (preview->img) { - IMB_freeImBuf(preview->img); + if (preview->icon_id) { + BKE_icon_delete(preview->icon_id); } MEM_freeN(preview); } @@ -1374,10 +1587,11 @@ static void filelist_cache_previews_push(FileList *filelist, FileDirEntry *entry BLI_assert(cache->flags & FLC_PREVIEWS_ACTIVE); - if (!entry->image && !(entry->flags & FILE_ENTRY_INVALID_PREVIEW) && + if (!entry->preview_icon_id && !(entry->flags & FILE_ENTRY_INVALID_PREVIEW) && (entry->typeflag & (FILE_TYPE_IMAGE | FILE_TYPE_MOVIE | FILE_TYPE_FTFONT | FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP | FILE_TYPE_BLENDERLIB))) { FileListEntryPreview *preview = MEM_mallocN(sizeof(*preview), __func__); + FileListInternEntry *intern_entry = filelist->filelist_intern.filtered[index]; if (entry->redirection_path) { BLI_strncpy(preview->path, entry->redirection_path, FILE_MAXDIR); @@ -1389,7 +1603,8 @@ static void filelist_cache_previews_push(FileList *filelist, FileDirEntry *entry preview->index = index; preview->flags = entry->typeflag; - preview->img = NULL; + preview->in_memory_preview = intern_entry->local_data.preview_image; + preview->icon_id = 0; // printf("%s: %d - %s - %p\n", __func__, preview->index, preview->path, preview->img); filelist_cache_preview_ensure_running(cache); @@ -1497,25 +1712,45 @@ FileList *filelist_new(short type) p->selection_state = BLI_ghash_new( BLI_ghashutil_uinthash_v4_p, BLI_ghashutil_uinthash_v4_cmp, __func__); + p->filelist.nbr_entries = FILEDIR_NBR_ENTRIES_UNSET; + filelist_settype(p, type); - switch (type) { + return p; +} + +void filelist_settype(FileList *filelist, short type) +{ + if (filelist->type == type) { + return; + } + + filelist->type = type; + filelist->tags = 0; + switch (filelist->type) { case FILE_MAIN: - p->checkdirf = filelist_checkdir_main; - p->read_jobf = filelist_readjob_main; - p->filterf = is_filtered_main; + filelist->checkdirf = filelist_checkdir_main; + filelist->read_jobf = filelist_readjob_main; + filelist->filterf = is_filtered_main; break; case FILE_LOADLIB: - p->checkdirf = filelist_checkdir_lib; - p->read_jobf = filelist_readjob_lib; - p->filterf = is_filtered_lib; + filelist->checkdirf = filelist_checkdir_lib; + filelist->read_jobf = filelist_readjob_lib; + filelist->filterf = is_filtered_lib; + break; + case FILE_MAIN_ASSET: + filelist->checkdirf = filelist_checkdir_main_assets; + filelist->read_jobf = filelist_readjob_main_assets; + filelist->filterf = is_filtered_main_assets; + filelist->tags |= FILELIST_TAGS_USES_MAIN_DATA | FILELIST_TAGS_NO_THREADS; break; default: - p->checkdirf = filelist_checkdir_dir; - p->read_jobf = filelist_readjob_dir; - p->filterf = is_filtered_file; + filelist->checkdirf = filelist_checkdir_dir; + filelist->read_jobf = filelist_readjob_dir; + filelist->filterf = is_filtered_file; break; } - return p; + + filelist->flags |= FL_FORCE_RESET; } void filelist_clear_ex(struct FileList *filelist, const bool do_cache, const bool do_selection) @@ -1560,6 +1795,8 @@ void filelist_free(struct FileList *filelist) filelist->selection_state = NULL; } + MEM_SAFE_FREE(filelist->asset_library); + memset(&filelist->filter_data, 0, sizeof(filelist->filter_data)); filelist->flags &= ~(FL_NEED_SORTING | FL_NEED_FILTERING); @@ -1580,7 +1817,7 @@ BlendHandle *filelist_lib(struct FileList *filelist) static const char *fileentry_uiname(const char *root, const char *relpath, - const int typeflag, + const eFileSel_File_Types typeflag, char *buff) { char *name = NULL; @@ -1624,11 +1861,12 @@ bool filelist_is_dir(struct FileList *filelist, const char *path) */ void filelist_setdir(struct FileList *filelist, char *r_dir) { + const bool allow_invalid = filelist->asset_library != NULL; BLI_assert(strlen(r_dir) < FILE_MAX_LIBEXTRA); BLI_path_normalize_dir(BKE_main_blendfile_path_from_global(), r_dir); - const bool is_valid_path = filelist->checkdirf(filelist, r_dir, true); - BLI_assert(is_valid_path); + const bool is_valid_path = filelist->checkdirf(filelist, r_dir, !allow_invalid); + BLI_assert(is_valid_path || allow_invalid); UNUSED_VARS_NDEBUG(is_valid_path); if (!STREQ(filelist->filelist.root, r_dir)) { @@ -1645,11 +1883,16 @@ void filelist_setrecursion(struct FileList *filelist, const int recursion_level) } } -bool filelist_force_reset(struct FileList *filelist) +bool filelist_needs_force_reset(FileList *filelist) { return (filelist->flags & FL_FORCE_RESET) != 0; } +void filelist_tag_force_reset(FileList *filelist) +{ + filelist->flags |= FL_FORCE_RESET; +} + bool filelist_is_ready(struct FileList *filelist) { return (filelist->flags & FL_IS_READY) != 0; @@ -1660,6 +1903,11 @@ bool filelist_pending(struct FileList *filelist) return (filelist->flags & FL_IS_PENDING) != 0; } +bool filelist_needs_reset_on_main_changes(const FileList *filelist) +{ + return (filelist->tags & FILELIST_TAGS_USES_MAIN_DATA) != 0; +} + /** * Limited version of full update done by space_file's file_refresh(), * to be used by operators and such. @@ -1668,7 +1916,7 @@ bool filelist_pending(struct FileList *filelist) */ int filelist_files_ensure(FileList *filelist) { - if (!filelist_force_reset(filelist) || !filelist_empty(filelist)) { + if (!filelist_needs_force_reset(filelist) || !filelist_needs_reading(filelist)) { filelist_sort(filelist); filelist_filter(filelist); } @@ -1701,6 +1949,17 @@ static FileDirEntry *filelist_file_create_entry(FileList *filelist, const int in if (entry->redirection_path) { ret->redirection_path = BLI_strdup(entry->redirection_path); } + ret->id = entry->local_data.id; + ret->asset_data = entry->imported_asset_data ? entry->imported_asset_data : NULL; + if (ret->id && (ret->asset_data == NULL)) { + ret->asset_data = ret->id->asset_data; + } + /* For some file types the preview is already available. */ + if (entry->local_data.preview_image && + BKE_previewimg_is_finished(entry->local_data.preview_image, ICON_SIZE_PREVIEW)) { + ImBuf *ibuf = BKE_previewimg_to_imbuf(entry->local_data.preview_image, ICON_SIZE_PREVIEW); + ret->preview_icon_id = BKE_icon_imbuf_create(ibuf); + } BLI_addtail(&cache->cached_entries, ret); return ret; } @@ -1770,7 +2029,7 @@ int filelist_file_findpath(struct FileList *filelist, const char *filename) { int fidx = -1; - if (filelist->filelist.nbr_entries_filtered < 0) { + if (filelist->filelist.nbr_entries_filtered == FILEDIR_NBR_ENTRIES_UNSET) { return fidx; } @@ -1788,9 +2047,17 @@ int filelist_file_findpath(struct FileList *filelist, const char *filename) return -1; } +/** + * Get the ID a file represents (if any). For #FILE_MAIN, #FILE_MAIN_ASSET. + */ +ID *filelist_file_get_id(const FileDirEntry *file) +{ + return file->id; +} + FileDirEntry *filelist_entry_find_uuid(struct FileList *filelist, const int uuid[4]) { - if (filelist->filelist.nbr_entries_filtered < 0) { + if (filelist->filelist.nbr_entries_filtered == FILEDIR_NBR_ENTRIES_UNSET) { return NULL; } @@ -2147,15 +2414,17 @@ bool filelist_cache_previews_update(FileList *filelist) // printf("%s: %d - %s - %p\n", __func__, preview->index, preview->path, preview->img); - if (preview->img) { + if (preview->icon_id) { /* Due to asynchronous process, a preview for a given image may be generated several times, * i.e. entry->image may already be set at this point. */ - if (entry && !entry->image) { - entry->image = preview->img; + if (entry && !entry->preview_icon_id) { + /* Move ownership over icon. */ + entry->preview_icon_id = preview->icon_id; + preview->icon_id = 0; changed = true; } else { - IMB_freeImBuf(preview->img); + BKE_icon_delete(preview->icon_id); } } else if (entry) { @@ -2313,9 +2582,9 @@ int ED_file_extension_icon(const char *path) } } -int filelist_empty(struct FileList *filelist) +int filelist_needs_reading(struct FileList *filelist) { - return (filelist->filelist.nbr_entries == 0); + return (filelist->filelist.nbr_entries == FILEDIR_NBR_ENTRIES_UNSET); } uint filelist_entry_select_set(const FileList *filelist, @@ -2564,8 +2833,8 @@ static int filelist_readjob_list_dir(const char *root, static int filelist_readjob_list_lib(const char *root, ListBase *entries, const bool skip_currpar) { FileListInternEntry *entry; - LinkNode *ln, *names; - int i, nnames, idcode = 0, nbr_entries = 0; + LinkNode *ln, *names = NULL, *datablock_infos = NULL; + int i, nitems, idcode = 0, nbr_entries = 0; char dir[FILE_MAX_LIBEXTRA], *group; bool ok; @@ -2587,11 +2856,11 @@ static int filelist_readjob_list_lib(const char *root, ListBase *entries, const * and freed in filelist_entry_free. */ if (group) { idcode = groupname_to_code(group); - names = BLO_blendhandle_get_datablock_names(libfiledata, idcode, &nnames); + datablock_infos = BLO_blendhandle_get_datablock_info(libfiledata, idcode, &nitems); } else { names = BLO_blendhandle_get_linkable_groups(libfiledata); - nnames = BLI_linklist_count(names); + nitems = BLI_linklist_count(names); } BLO_blendhandle_close(libfiledata); @@ -2604,12 +2873,18 @@ static int filelist_readjob_list_lib(const char *root, ListBase *entries, const nbr_entries++; } - for (i = 0, ln = names; i < nnames; i++, ln = ln->next) { - const char *blockname = ln->link; + for (i = 0, ln = (datablock_infos ? datablock_infos : names); i < nitems; i++, ln = ln->next) { + struct BLODataBlockInfo *info = datablock_infos ? ln->link : NULL; + const char *blockname = info ? info->name : ln->link; entry = MEM_callocN(sizeof(*entry), __func__); entry->relpath = BLI_strdup(blockname); entry->typeflag |= FILE_TYPE_BLENDERLIB; + if (info && info->asset_data) { + entry->typeflag |= FILE_TYPE_ASSET; + /* Moves ownership! */ + entry->imported_asset_data = info->asset_data; + } if (!(group && idcode)) { entry->typeflag |= FILE_TYPE_DIR; entry->blentype = groupname_to_code(blockname); @@ -2621,7 +2896,7 @@ static int filelist_readjob_list_lib(const char *root, ListBase *entries, const nbr_entries++; } - BLI_linklist_freeN(names); + BLI_linklist_freeN(datablock_infos ? datablock_infos : names); return nbr_entries; } @@ -2820,7 +3095,10 @@ static void filelist_readjob_do(const bool do_lib, // BLI_assert(filelist->filtered == NULL); BLI_assert(BLI_listbase_is_empty(&filelist->filelist.entries) && - (filelist->filelist.nbr_entries == 0)); + (filelist->filelist.nbr_entries == FILEDIR_NBR_ENTRIES_UNSET)); + + /* A valid, but empty directory from now. */ + filelist->filelist.nbr_entries = 0; todo_dirs = BLI_stack_new(sizeof(*td_dir), __func__); td_dir = BLI_stack_push_r(todo_dirs); @@ -2932,7 +3210,8 @@ static void filelist_readjob_do(const bool do_lib, BLI_stack_free(todo_dirs); } -static void filelist_readjob_dir(FileList *filelist, +static void filelist_readjob_dir(Main *UNUSED(current_main), + FileList *filelist, const char *main_name, short *stop, short *do_update, @@ -2942,7 +3221,8 @@ static void filelist_readjob_dir(FileList *filelist, filelist_readjob_do(false, filelist, main_name, stop, do_update, progress, lock); } -static void filelist_readjob_lib(FileList *filelist, +static void filelist_readjob_lib(Main *UNUSED(current_main), + FileList *filelist, const char *main_name, short *stop, short *do_update, @@ -2952,7 +3232,8 @@ static void filelist_readjob_lib(FileList *filelist, filelist_readjob_do(true, filelist, main_name, stop, do_update, progress, lock); } -static void filelist_readjob_main(FileList *filelist, +static void filelist_readjob_main(Main *current_main, + FileList *filelist, const char *main_name, short *stop, short *do_update, @@ -2960,12 +3241,67 @@ static void filelist_readjob_main(FileList *filelist, ThreadMutex *lock) { /* TODO! */ - filelist_readjob_dir(filelist, main_name, stop, do_update, progress, lock); + filelist_readjob_dir(current_main, filelist, main_name, stop, do_update, progress, lock); +} + +/** + * \warning Acts on main, so NOT thread-safe! + */ +static void filelist_readjob_main_assets(Main *current_main, + FileList *filelist, + const char *UNUSED(main_name), + short *UNUSED(stop), + short *do_update, + float *UNUSED(progress), + ThreadMutex *UNUSED(lock)) +{ + BLI_assert(BLI_listbase_is_empty(&filelist->filelist.entries) && + (filelist->filelist.nbr_entries == FILEDIR_NBR_ENTRIES_UNSET)); + + /* A valid, but empty directory from now. */ + filelist->filelist.nbr_entries = 0; + + FileListInternEntry *entry; + ListBase tmp_entries = {0}; + ID *id_iter; + int nbr_entries = 0; + + FOREACH_MAIN_ID_BEGIN (current_main, id_iter) { + if (!id_iter->asset_data) { + continue; + } + + const char *id_code_name = BKE_idtype_idcode_to_name(GS(id_iter->name)); + + entry = MEM_callocN(sizeof(*entry), __func__); + entry->relpath = BLI_strdup(id_code_name); + entry->name = BLI_strdup(id_iter->name + 2); + entry->typeflag |= FILE_TYPE_BLENDERLIB | FILE_TYPE_ASSET; + entry->blentype = GS(id_iter->name); + *((uint32_t *)entry->uuid) = atomic_add_and_fetch_uint32( + (uint32_t *)filelist->filelist_intern.curr_uuid, 1); + entry->local_data.preview_image = BKE_asset_metadata_preview_get_from_id(id_iter->asset_data, + id_iter); + entry->local_data.id = id_iter; + nbr_entries++; + BLI_addtail(&tmp_entries, entry); + } + FOREACH_MAIN_ID_END; + + if (nbr_entries) { + *do_update = true; + + BLI_movelisttolist(&filelist->filelist.entries, &tmp_entries); + filelist->filelist.nbr_entries += nbr_entries; + filelist->filelist.nbr_entries_filtered = filelist->filelist.entry_idx_start = + filelist->filelist.entry_idx_end = -1; + } } typedef struct FileListReadJob { ThreadMutex lock; char main_name[FILE_MAX]; + Main *current_main; struct FileList *filelist; /** XXX We may use a simpler struct here... just a linked list and root path? */ struct FileList *tmp_filelist; @@ -2985,7 +3321,7 @@ static void filelist_readjob_startjob(void *flrjv, short *stop, short *do_update flrj->tmp_filelist = MEM_dupallocN(flrj->filelist); BLI_listbase_clear(&flrj->tmp_filelist->filelist.entries); - flrj->tmp_filelist->filelist.nbr_entries = 0; + flrj->tmp_filelist->filelist.nbr_entries = FILEDIR_NBR_ENTRIES_UNSET; flrj->tmp_filelist->filelist_intern.filtered = NULL; BLI_listbase_clear(&flrj->tmp_filelist->filelist_intern.entries); @@ -2996,11 +3332,17 @@ static void filelist_readjob_startjob(void *flrjv, short *stop, short *do_update flrj->tmp_filelist->libfiledata = NULL; memset(&flrj->tmp_filelist->filelist_cache, 0, sizeof(flrj->tmp_filelist->filelist_cache)); flrj->tmp_filelist->selection_state = NULL; + flrj->tmp_filelist->asset_library = NULL; BLI_mutex_unlock(&flrj->lock); - flrj->tmp_filelist->read_jobf( - flrj->tmp_filelist, flrj->main_name, stop, do_update, progress, &flrj->lock); + flrj->tmp_filelist->read_jobf(flrj->current_main, + flrj->tmp_filelist, + flrj->main_name, + stop, + do_update, + progress, + &flrj->lock); } static void filelist_readjob_update(void *flrjv) @@ -3015,7 +3357,7 @@ static void filelist_readjob_update(void *flrjv) BLI_mutex_lock(&flrj->lock); - if (flrj->tmp_filelist->filelist.nbr_entries) { + if (flrj->tmp_filelist->filelist.nbr_entries > 0) { /* We just move everything out of 'thread context' into final list. */ new_nbr_entries = flrj->tmp_filelist->filelist.nbr_entries; BLI_movelisttolist(&new_entries, &flrj->tmp_filelist->filelist.entries); @@ -3033,7 +3375,7 @@ static void filelist_readjob_update(void *flrjv) /* if no new_nbr_entries, this is NOP */ BLI_movelisttolist(&fl_intern->entries, &new_entries); - flrj->filelist->filelist.nbr_entries = nbr_entries + new_nbr_entries; + flrj->filelist->filelist.nbr_entries = MAX2(nbr_entries, 0) + new_nbr_entries; } static void filelist_readjob_endjob(void *flrjv) @@ -3074,30 +3416,51 @@ void filelist_readjob_start(FileList *filelist, const bContext *C) wmJob *wm_job; FileListReadJob *flrj; + if (!filelist_is_dir(filelist, filelist->filelist.root)) { + return; + } + /* prepare job data */ flrj = MEM_callocN(sizeof(*flrj), __func__); flrj->filelist = filelist; + flrj->current_main = bmain; BLI_strncpy(flrj->main_name, BKE_main_blendfile_path(bmain), sizeof(flrj->main_name)); filelist->flags &= ~(FL_FORCE_RESET | FL_IS_READY); filelist->flags |= FL_IS_PENDING; + /* Init even for single threaded execution. Called functions use it. */ BLI_mutex_init(&flrj->lock); - /* setup job */ - wm_job = WM_jobs_get(CTX_wm_manager(C), - CTX_wm_window(C), - CTX_data_scene(C), - "Listing Dirs...", - WM_JOB_PROGRESS, - WM_JOB_TYPE_FILESEL_READDIR); - WM_jobs_customdata_set(wm_job, flrj, filelist_readjob_free); - WM_jobs_timer(wm_job, 0.01, NC_SPACE | ND_SPACE_FILE_LIST, NC_SPACE | ND_SPACE_FILE_LIST); - WM_jobs_callbacks( - wm_job, filelist_readjob_startjob, NULL, filelist_readjob_update, filelist_readjob_endjob); - - /* start the job */ - WM_jobs_start(CTX_wm_manager(C), wm_job); + if (filelist->tags & FILELIST_TAGS_NO_THREADS) { + short dummy_stop = false; + short dummy_do_update = false; + float dummy_progress = 0.0f; + + /* Single threaded execution. Just directly call the callbacks. */ + filelist_readjob_startjob(flrj, &dummy_stop, &dummy_do_update, &dummy_progress); + filelist_readjob_endjob(flrj); + filelist_readjob_free(flrj); + + WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL); + return; + } + else { + /* setup job */ + wm_job = WM_jobs_get(CTX_wm_manager(C), + CTX_wm_window(C), + CTX_data_scene(C), + "Listing Dirs...", + WM_JOB_PROGRESS, + WM_JOB_TYPE_FILESEL_READDIR); + WM_jobs_customdata_set(wm_job, flrj, filelist_readjob_free); + WM_jobs_timer(wm_job, 0.01, NC_SPACE | ND_SPACE_FILE_LIST, NC_SPACE | ND_SPACE_FILE_LIST); + WM_jobs_callbacks( + wm_job, filelist_readjob_startjob, NULL, filelist_readjob_update, filelist_readjob_endjob); + + /* start the job */ + WM_jobs_start(CTX_wm_manager(C), wm_job); + } } void filelist_readjob_stop(wmWindowManager *wm, Scene *owner_scene) diff --git a/source/blender/editors/space_file/filelist.h b/source/blender/editors/space_file/filelist.h index 4b8cc052382..59bd5bb50d7 100644 --- a/source/blender/editors/space_file/filelist.h +++ b/source/blender/editors/space_file/filelist.h @@ -30,6 +30,7 @@ extern "C" { struct BlendHandle; struct FileList; struct FileSelection; +struct FileSelectAssetLibraryUID; struct wmWindowManager; struct FileDirEntry; @@ -46,14 +47,16 @@ typedef enum FileCheckType { CHECK_ALL = 3, } FileCheckType; -struct ListBase *folderlist_new(void); void folderlist_free(struct ListBase *folderlist); -struct ListBase *folderlist_duplicate(ListBase *folderlist); void folderlist_popdir(struct ListBase *folderlist, char *dir); void folderlist_pushdir(struct ListBase *folderlist, const char *dir); const char *folderlist_peeklastdir(struct ListBase *folderlist); int folderlist_clear_next(struct SpaceFile *sfile); +void folder_history_list_ensure_for_active_browse_mode(struct SpaceFile *sfile); +void folder_history_list_free(struct SpaceFile *sfile); +struct ListBase folder_history_list_duplicate(struct ListBase *listbase); + void filelist_setsorting(struct FileList *filelist, const short sort, bool invert_sort); void filelist_sort(struct FileList *filelist); @@ -63,17 +66,22 @@ void filelist_setfilter_options(struct FileList *filelist, const bool hide_parent, const uint64_t filter, const uint64_t filter_id, + const bool filter_assets_only, const char *filter_glob, const char *filter_search); void filelist_filter(struct FileList *filelist); +void filelist_setlibrary(struct FileList *filelist, + const struct FileSelectAssetLibraryUID *asset_library); void filelist_init_icons(void); void filelist_free_icons(void); struct ImBuf *filelist_getimage(struct FileList *filelist, const int index); +struct ImBuf *filelist_file_getimage(const FileDirEntry *file); struct ImBuf *filelist_geticon_image(struct FileList *filelist, const int index); int filelist_geticon(struct FileList *filelist, const int index, const bool is_main); struct FileList *filelist_new(short type); +void filelist_settype(struct FileList *filelist, short type); void filelist_clear(struct FileList *filelist); void filelist_clear_ex(struct FileList *filelist, const bool do_cache, const bool do_selection); void filelist_free(struct FileList *filelist); @@ -83,15 +91,18 @@ bool filelist_is_dir(struct FileList *filelist, const char *path); void filelist_setdir(struct FileList *filelist, char *r_dir); int filelist_files_ensure(struct FileList *filelist); -int filelist_empty(struct FileList *filelist); +int filelist_needs_reading(struct FileList *filelist); FileDirEntry *filelist_file(struct FileList *filelist, int index); int filelist_file_findpath(struct FileList *filelist, const char *file); +struct ID *filelist_file_get_id(const struct FileDirEntry *file); FileDirEntry *filelist_entry_find_uuid(struct FileList *filelist, const int uuid[4]); void filelist_file_cache_slidingwindow_set(struct FileList *filelist, size_t window_size); bool filelist_file_cache_block(struct FileList *filelist, const int index); -bool filelist_force_reset(struct FileList *filelist); +bool filelist_needs_force_reset(struct FileList *filelist); +void filelist_tag_force_reset(struct FileList *filelist); bool filelist_pending(struct FileList *filelist); +bool filelist_needs_reset_on_main_changes(const struct FileList *filelist); bool filelist_is_ready(struct FileList *filelist); unsigned int filelist_entry_select_set(const struct FileList *filelist, diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c index 6e933e53a8f..2c66bd39e0a 100644 --- a/source/blender/editors/space_file/filesel.c +++ b/source/blender/editors/space_file/filesel.c @@ -56,7 +56,9 @@ #include "BKE_appdir.h" #include "BKE_context.h" +#include "BKE_idtype.h" #include "BKE_main.h" +#include "BKE_preferences.h" #include "BLF_api.h" @@ -77,14 +79,66 @@ #define VERTLIST_MAJORCOLUMN_WIDTH (25 * UI_UNIT_X) -FileSelectParams *ED_fileselect_get_active_params(const SpaceFile *sfile) +static void fileselect_initialize_params_common(SpaceFile *sfile, FileSelectParams *params) { - if (!sfile) { - /* Sometimes called in poll before space type was checked. */ - return NULL; + const char *blendfile_path = BKE_main_blendfile_path_from_global(); + + /* operator has no setting for this */ + params->active_file = -1; + + if (!params->dir[0]) { + if (blendfile_path[0] != '\0') { + BLI_split_dir_part(blendfile_path, params->dir, sizeof(params->dir)); + } + else { + const char *doc_path = BKE_appdir_folder_default(); + if (doc_path) { + BLI_strncpy(params->dir, doc_path, sizeof(params->dir)); + } + } } - return sfile->params; + folder_history_list_ensure_for_active_browse_mode(sfile); + folderlist_pushdir(sfile->folders_prev, params->dir); + + /* Switching thumbnails needs to recalc layout T28809. */ + if (sfile->layout) { + sfile->layout->dirty = true; + } +} + +static void fileselect_ensure_updated_asset_params(SpaceFile *sfile) +{ + BLI_assert(sfile->browse_mode == FILE_BROWSE_MODE_ASSETS); + BLI_assert(sfile->op == NULL); + + FileAssetSelectParams *asset_params = sfile->asset_params; + + if (!asset_params) { + asset_params = sfile->asset_params = MEM_callocN(sizeof(*asset_params), + "FileAssetSelectParams"); + asset_params->base_params.details_flags = U_default.file_space_data.details_flags; + asset_params->asset_library.type = FILE_ASSET_LIBRARY_LOCAL; + } + + FileSelectParams *base_params = &asset_params->base_params; + base_params->file[0] = '\0'; + base_params->filter_glob[0] = '\0'; + /* TODO this way of using filters to form categories is notably slower than specifying a + * "group" to read. That's because all types are read and filtering is applied afterwards. Would + * be nice if we could lazy-read individual groups. */ + base_params->flag |= U_default.file_space_data.flag | FILE_ASSETS_ONLY | FILE_FILTER; + base_params->flag &= ~FILE_DIRSEL_ONLY; + base_params->filter |= FILE_TYPE_BLENDERLIB; + base_params->filter_id = FILTER_ID_OB | FILTER_ID_GR; + base_params->display = FILE_IMGDISPLAY; + base_params->sort = FILE_SORT_ALPHA; + base_params->recursion_level = 1; + /* 'SMALL' size by default. More reasonable since this is typically used as regular editor, + * space is more of an issue here. */ + base_params->thumbnail_size = 96; + + fileselect_initialize_params_common(sfile, base_params); } /** @@ -92,6 +146,8 @@ FileSelectParams *ED_fileselect_get_active_params(const SpaceFile *sfile) * the previously used settings to be used here rather than overriding them */ static FileSelectParams *fileselect_ensure_updated_file_params(SpaceFile *sfile) { + BLI_assert(sfile->browse_mode == FILE_BROWSE_MODE_FILES); + FileSelectParams *params; wmOperator *op = sfile->op; @@ -297,42 +353,102 @@ static FileSelectParams *fileselect_ensure_updated_file_params(SpaceFile *sfile) params->filter_glob[0] = '\0'; } - /* operator has no setting for this */ - params->active_file = -1; + fileselect_initialize_params_common(sfile, params); - /* initialize the list with previous folders */ - if (!sfile->folders_prev) { - sfile->folders_prev = folderlist_new(); - } + return params; +} - if (!params->dir[0]) { - if (blendfile_path[0] != '\0') { - BLI_split_dir_part(blendfile_path, params->dir, sizeof(params->dir)); - } - else { - const char *doc_path = BKE_appdir_folder_default(); - if (doc_path) { - BLI_strncpy(params->dir, doc_path, sizeof(params->dir)); +/** + * If needed, create and return the file select parameters for the active browse mode. + */ +FileSelectParams *ED_fileselect_ensure_active_params(SpaceFile *sfile) +{ + switch ((eFileBrowse_Mode)sfile->browse_mode) { + case FILE_BROWSE_MODE_FILES: + if (!sfile->params) { + fileselect_ensure_updated_file_params(sfile); } - } + return sfile->params; + case FILE_BROWSE_MODE_ASSETS: + if (!sfile->asset_params) { + fileselect_ensure_updated_asset_params(sfile); + } + return &sfile->asset_params->base_params; } - folderlist_pushdir(sfile->folders_prev, params->dir); + BLI_assert(!"Invalid browse mode set in file space."); + return NULL; +} - /* Switching thumbnails needs to recalc layout T28809. */ - if (sfile->layout) { - sfile->layout->dirty = true; +/** + * Get the file select parameters for the active browse mode. + */ +FileSelectParams *ED_fileselect_get_active_params(const SpaceFile *sfile) +{ + if (!sfile) { + /* Sometimes called in poll before space type was checked. */ + return NULL; } - return params; + switch ((eFileBrowse_Mode)sfile->browse_mode) { + case FILE_BROWSE_MODE_FILES: + return sfile->params; + case FILE_BROWSE_MODE_ASSETS: + return (FileSelectParams *)sfile->asset_params; + } + + BLI_assert(!"Invalid browse mode set in file space."); + return NULL; } -FileSelectParams *ED_fileselect_ensure_active_params(SpaceFile *sfile) +FileSelectParams *ED_fileselect_get_file_params(const SpaceFile *sfile) { - if (!sfile->params) { - fileselect_ensure_updated_file_params(sfile); + return (sfile->browse_mode == FILE_BROWSE_MODE_FILES) ? sfile->params : NULL; +} + +FileAssetSelectParams *ED_fileselect_get_asset_params(const SpaceFile *sfile) +{ + return (sfile->browse_mode == FILE_BROWSE_MODE_ASSETS) ? sfile->asset_params : NULL; +} + +static void fileselect_refresh_asset_params(FileAssetSelectParams *asset_params) +{ + FileSelectAssetLibraryUID *library = &asset_params->asset_library; + FileSelectParams *base_params = &asset_params->base_params; + bUserAssetLibrary *user_library = NULL; + + /* Ensure valid repo, or fall-back to local one. */ + if (library->type == FILE_ASSET_LIBRARY_CUSTOM) { + user_library = BKE_preferences_asset_library_find_from_name( + &U, library->custom_library_identifier); + if (!user_library) { + library->type = FILE_ASSET_LIBRARY_LOCAL; + } + } + + switch (library->type) { + case FILE_ASSET_LIBRARY_LOCAL: + base_params->dir[0] = '\0'; + break; + case FILE_ASSET_LIBRARY_CUSTOM: + BLI_assert(user_library); + BLI_strncpy(base_params->dir, user_library->path, sizeof(base_params->dir)); + break; } - return sfile->params; + base_params->type = (library->type == FILE_ASSET_LIBRARY_LOCAL) ? FILE_MAIN_ASSET : FILE_LOADLIB; +} + +void fileselect_refresh_params(SpaceFile *sfile) +{ + FileAssetSelectParams *asset_params = ED_fileselect_get_asset_params(sfile); + if (asset_params) { + fileselect_refresh_asset_params(asset_params); + } +} + +bool ED_fileselect_is_asset_browser(const SpaceFile *sfile) +{ + return (sfile->browse_mode == FILE_BROWSE_MODE_ASSETS); } /* The subset of FileSelectParams.flag items we store into preferences. Note that FILE_SORT_ALPHA @@ -371,6 +487,8 @@ void ED_fileselect_set_params_from_userdef(SpaceFile *sfile) wmOperator *op = sfile->op; UserDef_FileSpaceData *sfile_udata = &U.file_space_data; + BLI_assert(sfile->browse_mode == FILE_BROWSE_MODE_FILES); + FileSelectParams *params = fileselect_ensure_updated_file_params(sfile); if (!op) { return; @@ -438,15 +556,6 @@ void ED_fileselect_params_to_userdef(SpaceFile *sfile, } } -void ED_fileselect_reset_params(SpaceFile *sfile) -{ - FileSelectParams *params = ED_fileselect_get_active_params(sfile); - params->type = FILE_UNIX; - params->flag = 0; - params->title[0] = '\0'; - params->active_file = -1; -} - /** * Sets FileSelectParams->file (name of selected file) */ @@ -1046,8 +1155,7 @@ void ED_fileselect_exit(wmWindowManager *wm, Scene *owner_scene, SpaceFile *sfil sfile->op = NULL; } - folderlist_free(sfile->folders_prev); - folderlist_free(sfile->folders_next); + folder_history_list_free(sfile); if (sfile->files) { ED_fileselect_clear(wm, owner_scene, sfile); diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c index c72ca58abba..f1d72387791 100644 --- a/source/blender/editors/space_file/space_file.c +++ b/source/blender/editors/space_file/space_file.c @@ -35,6 +35,8 @@ #include "BKE_screen.h" #include "RNA_access.h" +#include "RNA_define.h" +#include "RNA_enum_types.h" #include "WM_api.h" #include "WM_message.h" @@ -149,22 +151,10 @@ static void file_free(SpaceLink *sl) sfile->files = NULL; } - if (sfile->folders_prev) { - folderlist_free(sfile->folders_prev); - MEM_freeN(sfile->folders_prev); - sfile->folders_prev = NULL; - } - - if (sfile->folders_next) { - folderlist_free(sfile->folders_next); - MEM_freeN(sfile->folders_next); - sfile->folders_next = NULL; - } + folder_history_list_free(sfile); - if (sfile->params) { - MEM_freeN(sfile->params); - sfile->params = NULL; - } + MEM_SAFE_FREE(sfile->params); + MEM_SAFE_FREE(sfile->asset_params); if (sfile->layout) { MEM_freeN(sfile->layout); @@ -205,19 +195,20 @@ static SpaceLink *file_duplicate(SpaceLink *sl) sfilen->previews_timer = NULL; sfilen->smoothscroll_timer = NULL; + FileSelectParams *active_params_old = ED_fileselect_get_active_params(sfileo); + if (active_params_old) { + sfilen->files = filelist_new(active_params_old->type); + filelist_setdir(sfilen->files, active_params_old->dir); + } + if (sfileo->params) { - sfilen->files = filelist_new(sfileo->params->type); sfilen->params = MEM_dupallocN(sfileo->params); - filelist_setdir(sfilen->files, sfilen->params->dir); } - - if (sfileo->folders_prev) { - sfilen->folders_prev = folderlist_duplicate(sfileo->folders_prev); + if (sfileo->asset_params) { + sfilen->asset_params = MEM_dupallocN(sfileo->asset_params); } - if (sfileo->folders_next) { - sfilen->folders_next = folderlist_duplicate(sfileo->folders_next); - } + sfilen->folder_histories = folder_history_list_duplicate(&sfileo->folder_histories); if (sfileo->layout) { sfilen->layout = MEM_dupallocN(sfileo->layout); @@ -265,24 +256,42 @@ static void file_ensure_valid_region_state(bContext *C, } } +/** + * Tag the space to recreate the file-list. + */ +static void file_tag_reset_list(ScrArea *area, SpaceFile *sfile) +{ + filelist_tag_force_reset(sfile->files); + ED_area_tag_refresh(area); +} + static void file_refresh(const bContext *C, ScrArea *area) { wmWindowManager *wm = CTX_wm_manager(C); wmWindow *win = CTX_wm_window(C); SpaceFile *sfile = CTX_wm_space_file(C); FileSelectParams *params = ED_fileselect_ensure_active_params(sfile); + FileAssetSelectParams *asset_params = ED_fileselect_get_asset_params(sfile); struct FSMenu *fsmenu = ED_fsmenu_get(); - if (!sfile->folders_prev) { - sfile->folders_prev = folderlist_new(); + fileselect_refresh_params(sfile); + folder_history_list_ensure_for_active_browse_mode(sfile); + + if (sfile->files && (sfile->tags & FILE_TAG_REBUILD_MAIN_FILES) && + filelist_needs_reset_on_main_changes(sfile->files)) { + filelist_tag_force_reset(sfile->files); } + sfile->tags &= ~FILE_TAG_REBUILD_MAIN_FILES; + if (!sfile->files) { sfile->files = filelist_new(params->type); params->highlight_file = -1; /* added this so it opens nicer (ton) */ } + filelist_settype(sfile->files, params->type); filelist_setdir(sfile->files, params->dir); filelist_setrecursion(sfile->files, params->recursion_level); filelist_setsorting(sfile->files, params->sort, params->flag & FILE_SORT_INVERT); + filelist_setlibrary(sfile->files, asset_params ? &asset_params->asset_library : NULL); filelist_setfilter_options( sfile->files, (params->flag & FILE_FILTER) != 0, @@ -290,6 +299,7 @@ static void file_refresh(const bContext *C, ScrArea *area) true, /* Just always hide parent, prefer to not add an extra user option for this. */ params->filter, params->filter_id, + (params->flag & FILE_ASSETS_ONLY) != 0, params->filter_glob, params->filter_search); @@ -300,12 +310,12 @@ static void file_refresh(const bContext *C, ScrArea *area) sfile->bookmarknr = fsmenu_get_active_indices(fsmenu, FS_CATEGORY_BOOKMARKS, params->dir); sfile->recentnr = fsmenu_get_active_indices(fsmenu, FS_CATEGORY_RECENT, params->dir); - if (filelist_force_reset(sfile->files)) { + if (filelist_needs_force_reset(sfile->files)) { filelist_readjob_stop(wm, CTX_data_scene(C)); filelist_clear(sfile->files); } - if (filelist_empty(sfile->files)) { + if (filelist_needs_reading(sfile->files)) { if (!filelist_pending(sfile->files)) { filelist_readjob_start(sfile->files, C); } @@ -365,6 +375,14 @@ static void file_listener(wmWindow *UNUSED(win), break; } break; + case NC_ASSET: { + if (sfile->files && filelist_needs_reset_on_main_changes(sfile->files)) { + /* Full refresh of the file list if local asset data was changed. Refreshing this view is + * cheap and users expect this to be updated immediately. */ + file_tag_reset_list(area, sfile); + } + break; + } } } @@ -442,6 +460,22 @@ static void file_main_region_message_subscribe(const struct bContext *UNUSED(C), } } +static bool file_main_region_needs_refresh_before_draw(SpaceFile *sfile) +{ + /* Needed, because filelist is not initialized on loading */ + if (!sfile->files || filelist_needs_reading(sfile->files)) { + return true; + } + + /* File reading tagged the space because main data changed that may require a filelist reset. */ + if (filelist_needs_reset_on_main_changes(sfile->files) && + (sfile->tags & FILE_TAG_REBUILD_MAIN_FILES)) { + return true; + } + + return false; +} + static void file_main_region_draw(const bContext *C, ARegion *region) { /* draw entirely, view changes should be handled here */ @@ -450,8 +484,7 @@ static void file_main_region_draw(const bContext *C, ARegion *region) View2D *v2d = ®ion->v2d; - /* Needed, because filelist is not initialized on loading */ - if (!sfile->files || filelist_empty(sfile->files)) { + if (file_main_region_needs_refresh_before_draw(sfile)) { file_refresh(C, NULL); } @@ -681,6 +714,52 @@ static void file_dropboxes(void) WM_dropbox_add(lb, "FILE_OT_filepath_drop", filepath_drop_poll, filepath_drop_copy); } +const char *file_context_dir[] = {"active_file", "active_id", NULL}; + +static int /*eContextResult*/ file_context(const bContext *C, + const char *member, + bContextDataResult *result) +{ + bScreen *screen = CTX_wm_screen(C); + SpaceFile *sfile = CTX_wm_space_file(C); + FileSelectParams *params = ED_fileselect_get_active_params(sfile); + + BLI_assert(!ED_area_is_global(CTX_wm_area(C))); + + if (CTX_data_dir(member)) { + CTX_data_dir_set(result, file_context_dir); + return CTX_RESULT_OK; + } + else if (CTX_data_equals(member, "active_file")) { + FileDirEntry *file = filelist_file(sfile->files, params->active_file); + CTX_data_pointer_set(result, &screen->id, &RNA_FileSelectEntry, file); + return CTX_RESULT_OK; + } + else if (CTX_data_equals(member, "active_id")) { + const FileDirEntry *file = filelist_file(sfile->files, params->active_file); + + ID *id = filelist_file_get_id(file); + if (id) { + CTX_data_id_pointer_set(result, id); + } + return CTX_RESULT_OK; + } + return CTX_RESULT_MEMBER_NOT_FOUND; +} + +static void file_id_remap(ScrArea *area, SpaceLink *sl, ID *UNUSED(old_id), ID *UNUSED(new_id)) +{ + SpaceFile *sfile = (SpaceFile *)sl; + + /* If the file shows main data (IDs), tag it for reset. */ + if (sfile->files && filelist_needs_reset_on_main_changes(sfile->files)) { + /* Full refresh of the file list if main data was changed, don't even attempt remap pointers. + * We could give file list types a id-remap callback, but it's probably not worth it. + * Refreshing local file lists is relatively cheap. */ + file_tag_reset_list(area, sfile); + } +} + /* only called once, from space/spacetypes.c */ void ED_spacetype_file(void) { @@ -700,6 +779,8 @@ void ED_spacetype_file(void) st->operatortypes = file_operatortypes; st->keymap = file_keymap; st->dropboxes = file_dropboxes; + st->context = file_context; + st->id_remap = file_id_remap; /* regions: main window */ art = MEM_callocN(sizeof(ARegionType), "spacetype file region"); diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index 6fd112628a1..e07f085d356 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -664,6 +664,23 @@ typedef enum eSpaceSeq_OverlayType { /** \name File Selector * \{ */ +/** + * Information to identify a asset library. May be either one of the predefined types (current + * 'Main', builtin library, project library), or a custom type as defined in the Preferences. + * + * If the type is set to #FILE_ASSET_LIBRARY_CUSTOM, idname must have the name to identify the + * custom library. Otherwise idname is not used. + */ +typedef struct FileSelectAssetLibraryUID { + short type; + char _pad[6]; + /** + * If showing a custom asset library (#FILE_ASSET_LIBRARY_CUSTOM), this name has to be set to + * define which. Can be empty otherwise. + */ + char custom_library_identifier[64]; /* MAX_NAME */ +} FileSelectAssetLibraryUID; + /* Config and Input for File Selector */ typedef struct FileSelectParams { /** Title, also used for the text of the execute button. */ @@ -708,6 +725,7 @@ typedef struct FileSelectParams { /** Details toggles (file size, creation date, etc.) */ char details_flags; char _pad2[3]; + /** Filter when (flags & FILE_FILTER) is true. */ int filter; @@ -723,6 +741,32 @@ typedef struct FileSelectParams { /* XXX --- end unused -- */ } FileSelectParams; +/** + * File selection parameters for asset browsing mode, with #FileSelectParams as base. + */ +typedef struct FileAssetSelectParams { + FileSelectParams base_params; + + FileSelectAssetLibraryUID asset_library; +} FileAssetSelectParams; + +/** + * A wrapper to store previous and next folder lists (#FolderList) for a specific browse mode + * (#eFileBrowse_Mode). + */ +typedef struct FileFolderHistory { + struct FileFolderLists *next, *prev; + + /** The browse mode this prev/next folder-lists are created for. */ + char browse_mode; /* eFileBrowse_Mode */ + char _pad[7]; + + /** Holds the list of previous directories to show. */ + ListBase folders_prev; + /** Holds the list of next directories (pushed from previous) to show. */ + ListBase folders_next; +} FileFolderHistory; + /* File Browser */ typedef struct SpaceFile { SpaceLink *next, *prev; @@ -733,20 +777,42 @@ typedef struct SpaceFile { char _pad0[6]; /* End 'SpaceLink' header. */ - char _pad1[4]; + /** Is this a File Browser or an Asset Browser? */ + char browse_mode; /* eFileBrowse_Mode */ + char _pad1[1]; + + short tags; + int scroll_offset; - /** Config and input for file select. */ - struct FileSelectParams *params; + /** Config and input for file select. One for each browse-mode, to keep them independent. */ + FileSelectParams *params; + FileAssetSelectParams *asset_params; - /** Holds the list of files to show. */ + void *_pad2; + + /** + * Holds the list of files to show. + * Currently recreated when browse-mode changes. Could be per browse-mode to avoid refreshes. + */ struct FileList *files; - /** Holds the list of previous directories to show. */ + /** + * Holds the list of previous directories to show. Owned by `folder_histories` below. + */ ListBase *folders_prev; - /** Holds the list of next directories (pushed from previous) to show. */ + /** + * Holds the list of next directories (pushed from previous) to show. Owned by + * `folder_histories` below. + */ ListBase *folders_next; + /** + * This actually owns the prev/next folder-lists above. On browse-mode change, the lists of the + * new mode get assigned to the above. + */ + ListBase folder_histories; /* FileFolderHistory */ + /* operator that is invoking fileselect * op->exec() will be called on the 'Load' button. * if operator provides op->cancel(), then this will be invoked @@ -763,6 +829,30 @@ typedef struct SpaceFile { short systemnr, system_bookmarknr; } SpaceFile; +/* SpaceFile.browse_mode (File Space Browsing Mode) */ +typedef enum eFileBrowse_Mode { + /* Regular Blender File Browser */ + FILE_BROWSE_MODE_FILES = 0, + /* Asset Browser */ + FILE_BROWSE_MODE_ASSETS = 1, +} eFileBrowse_Mode; + +typedef enum eFileAssetLibrary_Type { + /* For the future. Display assets bundled with Blender by default. */ + // FILE_ASSET_LIBRARY_BUNDLED = 0, + /** Display assets from the current session (current "Main"). */ + FILE_ASSET_LIBRARY_LOCAL = 1, + /* For the future. Display assets for the current project. */ + // FILE_ASSET_LIBRARY_PROJECT = 2, + + /** Display assets from custom asset libraries, as defined in the preferences + * (#bUserAssetLibrary). The name will be taken from #FileSelectParams.asset_library.idname + * then. + * In RNA, we add the index of the custom library to this to identify it by index. So keep + * this last! */ + FILE_ASSET_LIBRARY_CUSTOM = 100, +} eFileAssetLibrary_Type; + /* FileSelectParams.display */ enum eFileDisplayType { /** Internal (not exposed to users): Keep whatever display type was used during the last File @@ -792,6 +882,13 @@ enum eFileSortType { FILE_SORT_SIZE = 4, }; +/* SpaceFile.tags */ +enum eFileTags { + /** Tag the space as having to update files representing or containing main data. Must be set + * after file read and undo/redo. */ + FILE_TAG_REBUILD_MAIN_FILES = (1 << 0), +}; + /* FileSelectParams.details_flags */ enum eFileDetails { FILE_DETAILS_SIZE = (1 << 0), @@ -810,6 +907,7 @@ enum eFileDetails { typedef enum eFileSelectType { FILE_LOADLIB = 1, FILE_MAIN = 2, + FILE_MAIN_ASSET = 3, FILE_UNIX = 8, FILE_BLENDER = 8, /* don't display relative paths */ @@ -842,6 +940,7 @@ typedef enum eFileSel_Params_Flag { FILE_SORT_INVERT = (1 << 11), FILE_HIDE_TOOL_PROPS = (1 << 12), FILE_CHECK_EXISTING = (1 << 13), + FILE_ASSETS_ONLY = (1 << 14), } eFileSel_Params_Flag; /* sfile->params->rename_flag */ @@ -885,6 +984,7 @@ typedef enum eFileSel_File_Types { FILE_TYPE_USD = (1 << 18), FILE_TYPE_VOLUME = (1 << 19), + FILE_TYPE_ASSET = (1 << 28), /** An FS directory (i.e. S_ISDIR on its path is true). */ FILE_TYPE_DIR = (1 << 30), FILE_TYPE_BLENDERLIB = (1u << 31), @@ -985,9 +1085,16 @@ typedef struct FileDirEntry { /** Optional argument for shortcuts, aliases etc. */ char *redirection_path; - /** TODO: make this a real ID pointer? */ - void *poin; - struct ImBuf *image; + /** When showing local IDs (FILE_MAIN, FILE_MAIN_ASSET), ID this file represents. Note comment + * for FileListInternEntry.local_data, the same applies here! */ + ID *id; + /** If this file represents an asset, its asset data is here. Note that we may show assets of + * external files in which case this is set but not the id above. + * Note comment for FileListInternEntry.local_data, the same applies here! */ + struct AssetMetaData *asset_data; + + /* The icon_id for the preview image. */ + int preview_icon_id; /* Tags are for info only, most of filtering is done in asset engine. */ char **tags; diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index 0b0895f9db0..aaa948dbff6 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -253,7 +253,9 @@ extern StructRNA RNA_FModifierPython; extern StructRNA RNA_FModifierStepped; extern StructRNA RNA_FaceMap; extern StructRNA RNA_FieldSettings; +extern StructRNA RNA_FileAssetSelectParams; extern StructRNA RNA_FileBrowserFSMenuEntry; +extern StructRNA RNA_FileSelectEntry; extern StructRNA RNA_FileSelectParams; extern StructRNA RNA_FloatAttribute; extern StructRNA RNA_FloatAttributeValue; diff --git a/source/blender/makesrna/RNA_enum_types.h b/source/blender/makesrna/RNA_enum_types.h index a94466e30c2..69bd6142cad 100644 --- a/source/blender/makesrna/RNA_enum_types.h +++ b/source/blender/makesrna/RNA_enum_types.h @@ -56,6 +56,7 @@ extern const EnumPropertyItem rna_enum_mesh_select_mode_items[]; extern const EnumPropertyItem rna_enum_mesh_select_mode_uv_items[]; extern const EnumPropertyItem rna_enum_mesh_delimit_mode_items[]; extern const EnumPropertyItem rna_enum_space_graph_mode_items[]; +extern const EnumPropertyItem rna_enum_space_file_browse_mode_items[]; extern const EnumPropertyItem rna_enum_space_sequencer_view_type_items[]; extern const EnumPropertyItem rna_enum_space_type_items[]; extern const EnumPropertyItem rna_enum_space_image_mode_items[]; diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 36dbb1c78cc..4b39858026c 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -170,6 +170,12 @@ const EnumPropertyItem rna_enum_space_sequencer_view_type_items[] = { {0, NULL, 0, NULL, NULL}, }; +const EnumPropertyItem rna_enum_space_file_browse_mode_items[] = { + {FILE_BROWSE_MODE_FILES, "FILES", ICON_FILEBROWSER, "File Browser", ""}, + {FILE_BROWSE_MODE_ASSETS, "ASSETS", ICON_ASSET_MANAGER, "Asset Browser", ""}, + {0, NULL, 0, NULL, NULL}, +}; + #define SACT_ITEM_DOPESHEET \ { \ SACTCONT_DOPESHEET, "DOPESHEET", ICON_ACTION, "Dope Sheet", "Edit all keyframes in scene" \ @@ -504,6 +510,7 @@ static const EnumPropertyItem rna_enum_curve_display_handle_items[] = { # include "BKE_layer.h" # include "BKE_nla.h" # include "BKE_paint.h" +# include "BKE_preferences.h" # include "BKE_scene.h" # include "BKE_screen.h" # include "BKE_workspace.h" @@ -2462,13 +2469,159 @@ static PointerRNA rna_FileSelectParams_filter_id_get(PointerRNA *ptr) return rna_pointer_inherit_refine(ptr, &RNA_FileSelectIDFilter, ptr->data); } +static int rna_FileAssetSelectParams_asset_library_get(PointerRNA *ptr) +{ + FileAssetSelectParams *params = ptr->data; + /* Just an extra sanity check to ensure this isn't somehow called for RNA_FileSelectParams. */ + BLI_assert(ptr->type == &RNA_FileAssetSelectParams); + + /* Simple case: Predefined repo, just set the value. */ + if (params->asset_library.type < FILE_ASSET_LIBRARY_CUSTOM) { + return params->asset_library.type; + } + + /* Note that the path isn't checked for validity here. If an invalid library path is used, the + * Asset Browser can give a nice hint on what's wrong. */ + const bUserAssetLibrary *user_library = BKE_preferences_asset_library_find_from_name( + &U, params->asset_library.custom_library_identifier); + const int index = BKE_preferences_asset_library_get_index(&U, user_library); + if (index > -1) { + return FILE_ASSET_LIBRARY_CUSTOM + index; + } + + BLI_assert(0); + return FILE_ASSET_LIBRARY_LOCAL; +} + +static void rna_FileAssetSelectParams_asset_library_set(PointerRNA *ptr, int value) +{ + FileAssetSelectParams *params = ptr->data; + + /* Simple case: Predefined repo, just set the value. */ + if (value < FILE_ASSET_LIBRARY_CUSTOM) { + params->asset_library.type = value; + params->asset_library.custom_library_identifier[0] = '\0'; + BLI_assert(ELEM(value, FILE_ASSET_LIBRARY_LOCAL)); + return; + } + + const bUserAssetLibrary *user_library = BKE_preferences_asset_library_find_from_index( + &U, value - FILE_ASSET_LIBRARY_CUSTOM); + + /* Note that the path isn't checked for validity here. If an invalid library path is used, the + * Asset Browser can give a nice hint on what's wrong. */ + const bool is_valid = (user_library->name[0] && user_library->path[0]); + if (user_library && is_valid) { + BLI_strncpy(params->asset_library.custom_library_identifier, + user_library->name, + sizeof(params->asset_library.custom_library_identifier)); + params->asset_library.type = FILE_ASSET_LIBRARY_CUSTOM; + } +} + +static const EnumPropertyItem *rna_FileAssetSelectParams_asset_library_itemf( + bContext *UNUSED(C), PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free) +{ + const EnumPropertyItem predefined_items[] = { + /* For the future. */ + // {FILE_ASSET_REPO_BUNDLED, "BUNDLED", 0, "Bundled", "Show the default user assets"}, + {FILE_ASSET_LIBRARY_LOCAL, + "LOCAL", + ICON_BLENDER, + "Current File", + "Show the assets currently available in this Blender session"}, + {0, NULL, 0, NULL, NULL}, + }; + + EnumPropertyItem *item = NULL; + int totitem = 0; + + /* Add separator if needed. */ + if (!BLI_listbase_is_empty(&U.asset_libraries)) { + const EnumPropertyItem sepr = {0, "", 0, "Custom", NULL}; + RNA_enum_item_add(&item, &totitem, &sepr); + } + + int i = 0; + for (bUserAssetLibrary *user_library = U.asset_libraries.first; user_library; + user_library = user_library->next, i++) { + /* Note that the path itself isn't checked for validity here. If an invalid library path is + * used, the Asset Browser can give a nice hint on what's wrong. */ + const bool is_valid = (user_library->name[0] && user_library->path[0]); + if (!is_valid) { + continue; + } + + /* Use library path as description, it's a nice hint for users. */ + EnumPropertyItem tmp = {FILE_ASSET_LIBRARY_CUSTOM + i, + user_library->name, + ICON_NONE, + user_library->name, + user_library->path}; + RNA_enum_item_add(&item, &totitem, &tmp); + } + + if (totitem) { + const EnumPropertyItem sepr = {0, "", 0, "Built-in", NULL}; + RNA_enum_item_add(&item, &totitem, &sepr); + } + + /* Add predefined items. */ + RNA_enum_items_add(&item, &totitem, predefined_items); + + RNA_enum_item_end(&item, &totitem); + *r_free = true; + return item; +} + +static void rna_FileBrowser_FileSelectEntry_name_get(PointerRNA *ptr, char *value) +{ + const FileDirEntry *entry = ptr->data; + strcpy(value, entry->name); +} + +static int rna_FileBrowser_FileSelectEntry_name_length(PointerRNA *ptr) +{ + const FileDirEntry *entry = ptr->data; + return (int)strlen(entry->name); +} + +static int rna_FileBrowser_FileSelectEntry_preview_icon_id_get(PointerRNA *ptr) +{ + const FileDirEntry *entry = ptr->data; + return entry->preview_icon_id; +} + +static PointerRNA rna_FileBrowser_FileSelectEntry_asset_data_get(PointerRNA *ptr) +{ + const FileDirEntry *entry = ptr->data; + return rna_pointer_inherit_refine(ptr, &RNA_AssetMetaData, entry->asset_data); +} + +static StructRNA *rna_FileBrowser_params_typef(PointerRNA *ptr) +{ + SpaceFile *sfile = ptr->data; + FileSelectParams *params = ED_fileselect_get_active_params(sfile); + + if (params == ED_fileselect_get_file_params(sfile)) { + return &RNA_FileSelectParams; + } + if (params == (void *)ED_fileselect_get_asset_params(sfile)) { + return &RNA_FileAssetSelectParams; + } + + BLI_assert(!"Could not identify file select parameters"); + return NULL; +} + static PointerRNA rna_FileBrowser_params_get(PointerRNA *ptr) { SpaceFile *sfile = ptr->data; FileSelectParams *params = ED_fileselect_get_active_params(sfile); + StructRNA *params_struct = rna_FileBrowser_params_typef(ptr); - if (params) { - return rna_pointer_inherit_refine(ptr, &RNA_FileSelectParams, params); + if (params && params_struct) { + return rna_pointer_inherit_refine(ptr, params_struct, params); } return rna_pointer_inherit_refine(ptr, NULL, NULL); @@ -2784,6 +2937,14 @@ static void rna_FileBrowser_FSMenuRecent_active_range( rna_FileBrowser_FSMenu_active_range(ptr, min, max, softmin, softmax, FS_CATEGORY_RECENT); } +static void rna_SpaceFileBrowser_browse_mode_update(Main *UNUSED(bmain), + Scene *UNUSED(scene), + PointerRNA *ptr) +{ + ScrArea *area = rna_area_from_space(ptr); + ED_area_tag_refresh(area); +} + #else static const EnumPropertyItem dt_uv_items[] = { @@ -5794,6 +5955,44 @@ static void rna_def_fileselect_idfilter(BlenderRNA *brna) } } +static void rna_def_fileselect_entry(BlenderRNA *brna) +{ + PropertyRNA *prop; + StructRNA *srna = RNA_def_struct(brna, "FileSelectEntry", NULL); + RNA_def_struct_sdna(srna, "FileDirEntry"); + RNA_def_struct_ui_text(srna, "File Select Entry", "A file viewable in the File Browser"); + + prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); + RNA_def_property_string_funcs(prop, + "rna_FileBrowser_FileSelectEntry_name_get", + "rna_FileBrowser_FileSelectEntry_name_length", + NULL); + RNA_def_property_ui_text(prop, "Name", ""); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_struct_name_property(srna, prop); + + prop = RNA_def_int( + srna, + "preview_icon_id", + 0, + INT_MIN, + INT_MAX, + "Icon ID", + "Unique integer identifying the preview of this file as an icon (zero means invalid)", + INT_MIN, + INT_MAX); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_int_funcs( + prop, "rna_FileBrowser_FileSelectEntry_preview_icon_id_get", NULL, NULL); + + prop = RNA_def_property(srna, "asset_data", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "AssetMetaData"); + RNA_def_property_pointer_funcs( + prop, "rna_FileBrowser_FileSelectEntry_asset_data_get", NULL, NULL, NULL); + RNA_def_property_ui_text( + prop, "Asset Data", "Asset data, valid if the file represents an asset"); +} + static void rna_def_fileselect_params(BlenderRNA *brna) { StructRNA *srna; @@ -5966,6 +6165,12 @@ static void rna_def_fileselect_params(BlenderRNA *brna) RNA_def_property_ui_icon(prop, ICON_BLENDER, 0); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL); + prop = RNA_def_property(srna, "use_filter_asset_only", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", FILE_ASSETS_ONLY); + RNA_def_property_ui_text( + prop, "Only Assets", "Hide .blend files items that are not data-blocks with asset metadata"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL); + prop = RNA_def_property(srna, "filter_id", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_struct_type(prop, "FileSelectIDFilter"); @@ -5997,6 +6202,25 @@ static void rna_def_fileselect_params(BlenderRNA *brna) RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_LIST, NULL); } +static void rna_def_fileselect_asset_params(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "FileAssetSelectParams", "FileSelectParams"); + RNA_def_struct_ui_text( + srna, "Asset Select Parameters", "Settings for the file selection in Asset Browser mode"); + + prop = RNA_def_property(srna, "asset_library", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, DummyRNA_NULL_items); + RNA_def_property_enum_funcs(prop, + "rna_FileAssetSelectParams_asset_library_get", + "rna_FileAssetSelectParams_asset_library_set", + "rna_FileAssetSelectParams_asset_library_itemf"); + RNA_def_property_ui_text(prop, "Asset Library", ""); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL); +} + static void rna_def_filemenu_entry(BlenderRNA *brna) { StructRNA *srna; @@ -6050,9 +6274,18 @@ static void rna_def_space_filebrowser(BlenderRNA *brna) rna_def_space_generic_show_region_toggles(srna, (1 << RGN_TYPE_TOOLS) | (1 << RGN_TYPE_UI)); + prop = RNA_def_property(srna, "browse_mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, rna_enum_space_file_browse_mode_items); + RNA_def_property_ui_text( + prop, + "Browsing Mode", + "Type of the File Editor view (regular file browsing or asset browsing)"); + RNA_def_property_update(prop, 0, "rna_SpaceFileBrowser_browse_mode_update"); + prop = RNA_def_property(srna, "params", PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, "FileSelectParams"); - RNA_def_property_pointer_funcs(prop, "rna_FileBrowser_params_get", NULL, NULL, NULL); + RNA_def_property_pointer_funcs( + prop, "rna_FileBrowser_params_get", NULL, "rna_FileBrowser_params_typef", NULL); RNA_def_property_ui_text( prop, "Filebrowser Parameter", "Parameters and Settings for the Filebrowser"); @@ -6800,7 +7033,9 @@ void RNA_def_space(BlenderRNA *brna) rna_def_space_image(brna); rna_def_space_sequencer(brna); rna_def_space_text(brna); + rna_def_fileselect_entry(brna); rna_def_fileselect_params(brna); + rna_def_fileselect_asset_params(brna); rna_def_fileselect_idfilter(brna); rna_def_filemenu_entry(brna); rna_def_space_filebrowser(brna); diff --git a/source/blender/windowmanager/intern/wm_operator_props.c b/source/blender/windowmanager/intern/wm_operator_props.c index 631a4d23eb5..fa658a5cdec 100644 --- a/source/blender/windowmanager/intern/wm_operator_props.c +++ b/source/blender/windowmanager/intern/wm_operator_props.c @@ -198,6 +198,8 @@ void WM_operator_properties_filesel(wmOperatorType *ot, ot->srna, "filter_blenlib", (filter & FILE_TYPE_BLENDERLIB) != 0, "Filter Blender IDs", ""); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + /* TODO asset only filter? */ + prop = RNA_def_int( ot->srna, "filemode", -- cgit v1.2.3 From 2d6a69ae4e9905a19ac7228b97ed08fb4ea72e75 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Mon, 14 Dec 2020 14:07:42 +0100 Subject: Asset System: New Asset Browser editor This introduces the User Interface part of the Asset Browser, based on the design in T54642. Additions: * New Asset Browser (internally a sub-editor of the File Browser). * Navigation region showing asset categories. * Main region showing the assets of the selected asset library with previews. The assets may be stored over multiple .blends in the directory that's "mounted" as asset library in the Preferences. They will all be shown in this list. * Header with an asset library dropdown, allowing to choose the active asset library to show. Options are the "Current File" as asset library and all custom libraries. * Display popover, filter popover and search box (partially dummies, see T82680). * Sidebar showing the metadata of the currently active file (name, preview, description and tags), which can be edited for assets in the "Current File" asset library. (For others it will reset on reload.) * The sidebar includes a button to load a custom preview image from a file. * Make asset files draggable (with preview image). * If a library with invalid path is selected, a message is drawn in the main region to help the user understand what's wrong. * Operators to add and remove asset tags. Exposed in the sidebar. * "Only Assets" option for Link/Append. * Internal utilities for asset UI scripts. For screenshots or demo videos, please see D9725. Or the 2.92 release notes. Note that there are many things to be tweaked and polished in the Asset Browser UI still. For example, the filter and display popovers are mostly dummies. See T82680. Part of the first Asset Browser milestone. Check the #asset_browser_milestone_1 project milestone on developer.blender.org. Differential Revision: https://developer.blender.org/D9725 Reviewed by: Brecht Van Lommel, Hans Goudey --- source/blender/editors/interface/interface_style.c | 8 +- source/blender/editors/space_file/file_draw.c | 186 +++++++++++++++++++-- source/blender/editors/space_file/file_intern.h | 3 + source/blender/editors/space_file/file_ops.c | 28 +++- source/blender/editors/space_file/file_utils.c | 17 +- source/blender/editors/space_file/space_file.c | 87 ++++++++-- source/blender/makesrna/intern/rna_screen.c | 2 + source/blender/makesrna/intern/rna_space.c | 62 +++++++ source/blender/makesrna/intern/rna_userdef.c | 5 +- 9 files changed, 364 insertions(+), 34 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/interface/interface_style.c b/source/blender/editors/interface/interface_style.c index c3d528ad5c5..a37fb0dfde1 100644 --- a/source/blender/editors/interface/interface_style.c +++ b/source/blender/editors/interface/interface_style.c @@ -206,8 +206,12 @@ void UI_fontstyle_draw_ex(const uiFontStyle *fs, BLF_disable(fs->uifont_id, font_flag); - *r_xofs = xofs; - *r_yofs = yofs; + if (r_xofs) { + *r_xofs = xofs; + } + if (r_yofs) { + *r_yofs = yofs; + } } void UI_fontstyle_draw(const uiFontStyle *fs, diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c index e3bdda7c480..f2f7f9d82f9 100644 --- a/source/blender/editors/space_file/file_draw.c +++ b/source/blender/editors/space_file/file_draw.c @@ -25,6 +25,7 @@ #include #include +#include "BLI_alloca.h" #include "BLI_blenlib.h" #include "BLI_fileops_types.h" #include "BLI_math.h" @@ -134,6 +135,7 @@ static void draw_tile(int sx, int sy, int width, int height, int colorid, int sh } static void file_draw_icon(uiBlock *block, + const FileDirEntry *file, const char *path, int sx, int sy, @@ -157,8 +159,29 @@ static void file_draw_icon(uiBlock *block, UI_but_func_tooltip_set(but, file_draw_tooltip_func, BLI_strdup(path)); if (drag) { - /* path is no more static, cannot give it directly to but... */ - UI_but_drag_set_path(but, BLI_strdup(path), true); + /* TODO duplicated from file_draw_preview(). */ + ID *id; + + if ((id = filelist_file_get_id(file))) { + UI_but_drag_set_id(but, id); + } + else if (file->typeflag & FILE_TYPE_ASSET) { + ImBuf *preview_image = filelist_file_getimage(file); + char blend_path[FILE_MAX_LIBEXTRA]; + if (BLO_library_path_explode(path, blend_path, NULL, NULL)) { + UI_but_drag_set_asset(but, + file->name, + BLI_strdup(blend_path), + file->blentype, + icon, + preview_image, + UI_DPI_FAC); + } + } + else { + /* path is no more static, cannot give it directly to but... */ + UI_but_drag_set_path(but, BLI_strdup(path), true); + } } } @@ -200,6 +223,65 @@ static void file_draw_string(int sx, }); } +/** + * \param r_sx, r_sy: The lower right corner of the last line drawn. AKA the cursor position on + * completion. + */ +static void file_draw_string_multiline(int sx, + int sy, + const char *string, + int wrap_width, + int line_height, + const uchar text_col[4], + int *r_sx, + int *r_sy) +{ + rcti rect; + + if (string[0] == '\0' || wrap_width < 1) { + return; + } + + const uiStyle *style = UI_style_get(); + int font_id = style->widgetlabel.uifont_id; + int len = strlen(string); + + rctf textbox; + BLF_wordwrap(font_id, wrap_width); + BLF_enable(font_id, BLF_WORD_WRAP); + BLF_boundbox(font_id, string, len, &textbox); + BLF_disable(font_id, BLF_WORD_WRAP); + + /* no text clipping needed, UI_fontstyle_draw does it but is a bit too strict + * (for buttons it works) */ + rect.xmin = sx; + rect.xmax = sx + wrap_width; + /* Need to increase the clipping rect by one more line, since the #UI_fontstyle_draw_ex() will + * actually start drawing at (ymax - line-height). */ + rect.ymin = sy - round_fl_to_int(BLI_rctf_size_y(&textbox)) - line_height; + rect.ymax = sy; + + struct ResultBLF result; + UI_fontstyle_draw_ex(&style->widget, + &rect, + string, + text_col, + &(struct uiFontStyleDraw_Params){ + .align = UI_STYLE_TEXT_LEFT, + .word_wrap = true, + }, + len, + NULL, + NULL, + &result); + if (r_sx) { + *r_sx = result.width; + } + if (r_sy) { + *r_sy = rect.ymin + line_height; + } +} + void file_calc_previews(const bContext *C, ARegion *region) { SpaceFile *sfile = CTX_wm_space_file(C); @@ -210,6 +292,7 @@ void file_calc_previews(const bContext *C, ARegion *region) } static void file_draw_preview(uiBlock *block, + const FileDirEntry *file, const char *path, int sx, int sy, @@ -218,7 +301,6 @@ static void file_draw_preview(uiBlock *block, const int icon, FileLayout *layout, const bool is_icon, - const int typeflags, const bool drag, const bool dimmed, const bool is_link) @@ -232,7 +314,7 @@ static void file_draw_preview(uiBlock *block, float scale; int ex, ey; bool show_outline = !is_icon && - (typeflags & (FILE_TYPE_IMAGE | FILE_TYPE_MOVIE | FILE_TYPE_BLENDER)); + (file->typeflag & (FILE_TYPE_IMAGE | FILE_TYPE_MOVIE | FILE_TYPE_BLENDER)); BLI_assert(imb != NULL); @@ -273,14 +355,14 @@ static void file_draw_preview(uiBlock *block, float col[4] = {1.0f, 1.0f, 1.0f, 1.0f}; if (is_icon) { - if (typeflags & FILE_TYPE_DIR) { + if (file->typeflag & FILE_TYPE_DIR) { UI_GetThemeColor4fv(TH_ICON_FOLDER, col); } else { UI_GetThemeColor4fv(TH_TEXT, col); } } - else if (typeflags & FILE_TYPE_FTFONT) { + else if (file->typeflag & FILE_TYPE_FTFONT) { UI_GetThemeColor4fv(TH_TEXT, col); } @@ -288,7 +370,7 @@ static void file_draw_preview(uiBlock *block, col[3] *= 0.3f; } - if (!is_icon && typeflags & FILE_TYPE_BLENDERLIB) { + if (!is_icon && file->typeflag & FILE_TYPE_BLENDERLIB) { /* Datablock preview images use premultiplied alpha. */ GPU_blend(GPU_BLEND_ALPHA_PREMULT); } @@ -324,7 +406,7 @@ static void file_draw_preview(uiBlock *block, icon_color[2] = 255; } icon_x = xco + (ex / 2.0f) - (icon_size / 2.0f); - icon_y = yco + (ey / 2.0f) - (icon_size * ((typeflags & FILE_TYPE_DIR) ? 0.78f : 0.75f)); + icon_y = yco + (ey / 2.0f) - (icon_size * ((file->typeflag & FILE_TYPE_DIR) ? 0.78f : 0.75f)); UI_icon_draw_ex( icon_x, icon_y, icon, icon_aspect / U.dpi_fac, icon_opacity, 0.0f, icon_color, false); } @@ -346,13 +428,13 @@ static void file_draw_preview(uiBlock *block, /* Link to folder or non-previewed file. */ uchar icon_color[4]; UI_GetThemeColor4ubv(TH_BACK, icon_color); - icon_x = xco + ((typeflags & FILE_TYPE_DIR) ? 0.14f : 0.23f) * scaledx; - icon_y = yco + ((typeflags & FILE_TYPE_DIR) ? 0.24f : 0.14f) * scaledy; + icon_x = xco + ((file->typeflag & FILE_TYPE_DIR) ? 0.14f : 0.23f) * scaledx; + icon_y = yco + ((file->typeflag & FILE_TYPE_DIR) ? 0.24f : 0.14f) * scaledy; UI_icon_draw_ex( icon_x, icon_y, arrow, icon_aspect / U.dpi_fac * 1.8, 0.3f, 0.0f, icon_color, false); } } - else if (icon && !is_icon && !(typeflags & FILE_TYPE_FTFONT)) { + else if (icon && !is_icon && !(file->typeflag & FILE_TYPE_FTFONT)) { /* Smaller, fainter icon at bottom-left for preview image thumbnail, but not for fonts. */ float icon_x, icon_y; const uchar dark[4] = {0, 0, 0, 255}; @@ -385,8 +467,22 @@ static void file_draw_preview(uiBlock *block, /* dragregion */ if (drag) { + ID *id; + + if ((id = filelist_file_get_id(file))) { + UI_but_drag_set_id(but, id); + } /* path is no more static, cannot give it directly to but... */ - UI_but_drag_set_image(but, BLI_strdup(path), icon, imb, scale, true); + else if (file->typeflag & FILE_TYPE_ASSET) { + char blend_path[FILE_MAX_LIBEXTRA]; + if (BLO_library_path_explode(path, blend_path, NULL, NULL)) { + UI_but_drag_set_asset( + but, file->name, BLI_strdup(blend_path), file->blentype, icon, imb, scale); + } + } + else { + UI_but_drag_set_image(but, BLI_strdup(path), icon, imb, scale, true); + } } GPU_blend(GPU_BLEND_NONE); @@ -821,6 +917,7 @@ void file_draw_list(const bContext *C, ARegion *region) } file_draw_preview(block, + file, path, sx, sy, @@ -829,13 +926,13 @@ void file_draw_list(const bContext *C, ARegion *region) icon, layout, is_icon, - file->typeflag, do_drag, is_hidden, is_link); } else { file_draw_icon(block, + file, path, sx, sy - layout->tile_border_y, @@ -906,3 +1003,66 @@ void file_draw_list(const bContext *C, ARegion *region) layout->curr_size = params->thumbnail_size; } + +static void file_draw_invalid_library_hint(const SpaceFile *sfile, const ARegion *region) +{ + const FileAssetSelectParams *asset_params = ED_fileselect_get_asset_params(sfile); + + char library_ui_path[PATH_MAX]; + file_path_to_ui_path(asset_params->base_params.dir, library_ui_path, sizeof(library_ui_path)); + + uchar text_col[4]; + uchar text_alert_col[4]; + UI_GetThemeColor4ubv(TH_TEXT, text_col); + UI_GetThemeColor4ubv(TH_REDALERT, text_alert_col); + + const View2D *v2d = ®ion->v2d; + const int pad = sfile->layout->tile_border_x; + const int width = BLI_rctf_size_x(&v2d->tot) - (2 * pad); + const int line_height = sfile->layout->textheight; + int sx = v2d->tot.xmin + pad; + /* For some reason no padding needed. */ + int sy = v2d->tot.ymax; + + { + const char *message = TIP_("Library not found"); + const int draw_string_str_len = strlen(message) + 2 + sizeof(library_ui_path); + char *draw_string = alloca(draw_string_str_len); + BLI_snprintf(draw_string, draw_string_str_len, "%s: %s", message, library_ui_path); + file_draw_string_multiline(sx, sy, draw_string, width, line_height, text_alert_col, NULL, &sy); + } + + /* Next line, but separate it a bit further. */ + sy -= line_height; + + { + UI_icon_draw(sx, sy - UI_UNIT_Y, ICON_INFO); + + const char *suggestion = TIP_( + "Set up the library or edit libraries in the Preferences, File Paths section."); + file_draw_string_multiline( + sx + UI_UNIT_X, sy, suggestion, width - UI_UNIT_X, line_height, text_col, NULL, NULL); + } +} + +/** + * Draw a string hint if the file list is invalid. + * \return true if the list is invalid and a hint was drawn. + */ +bool file_draw_hint_if_invalid(const SpaceFile *sfile, const ARegion *region) +{ + FileAssetSelectParams *asset_params = ED_fileselect_get_asset_params(sfile); + /* Only for asset browser. */ + if (!ED_fileselect_is_asset_browser(sfile)) { + return false; + } + /* Check if the library exists. */ + if ((asset_params->asset_library.type == FILE_ASSET_LIBRARY_LOCAL) || + filelist_is_dir(sfile->files, asset_params->base_params.dir)) { + return false; + } + + file_draw_invalid_library_hint(sfile, region); + + return true; +} diff --git a/source/blender/editors/space_file/file_intern.h b/source/blender/editors/space_file/file_intern.h index a0e02681e0e..56fb588776e 100644 --- a/source/blender/editors/space_file/file_intern.h +++ b/source/blender/editors/space_file/file_intern.h @@ -38,6 +38,7 @@ struct View2D; void file_calc_previews(const bContext *C, ARegion *region); void file_draw_list(const bContext *C, ARegion *region); +bool file_draw_hint_if_invalid(const SpaceFile *sfile, const ARegion *region); void file_draw_check_ex(bContext *C, struct ScrArea *area); void file_draw_check(bContext *C); @@ -117,3 +118,5 @@ void file_execute_region_panels_register(struct ARegionType *art); /* file_utils.c */ void file_tile_boundbox(const ARegion *region, FileLayout *layout, const int file, rcti *r_bounds); + +void file_path_to_ui_path(const char *path, char *r_pathi, int max_size); diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c index 8af84f65ced..be4577bcba7 100644 --- a/source/blender/editors/space_file/file_ops.c +++ b/source/blender/editors/space_file/file_ops.c @@ -40,6 +40,7 @@ # include "BLI_winstuff.h" #endif +#include "ED_asset.h" #include "ED_fileselect.h" #include "ED_screen.h" #include "ED_select_utils.h" @@ -2695,6 +2696,29 @@ static bool file_delete_poll(bContext *C) return poll; } +static bool file_delete_single(const FileSelectParams *params, + FileDirEntry *file, + const char **r_error_message) +{ + if (file->typeflag & FILE_TYPE_ASSET) { + ID *id = filelist_file_get_id(file); + if (!id) { + *r_error_message = "File is not a local data-block asset."; + return false; + } + ED_asset_clear_id(id); + } + else { + char str[FILE_MAX]; + BLI_join_dirfile(str, sizeof(str), params->dir, file->relpath); + if (BLI_delete_soft(str, r_error_message) != 0 || BLI_exists(str)) { + return false; + } + } + + return true; +} + static int file_delete_exec(bContext *C, wmOperator *op) { wmWindowManager *wm = CTX_wm_manager(C); @@ -2708,9 +2732,7 @@ static int file_delete_exec(bContext *C, wmOperator *op) for (int i = 0; i < numfiles; i++) { if (filelist_entry_select_index_get(sfile->files, i, CHECK_ALL)) { FileDirEntry *file = filelist_file(sfile->files, i); - char str[FILE_MAX]; - BLI_join_dirfile(str, sizeof(str), params->dir, file->relpath); - if (BLI_delete_soft(str, &error_message) != 0 || BLI_exists(str)) { + if (!file_delete_single(params, file, &error_message)) { report_error = true; } } diff --git a/source/blender/editors/space_file/file_utils.c b/source/blender/editors/space_file/file_utils.c index 452f2f704cf..9d85996c559 100644 --- a/source/blender/editors/space_file/file_utils.c +++ b/source/blender/editors/space_file/file_utils.c @@ -18,12 +18,14 @@ * \ingroup spfile */ +#include "BLI_fileops.h" #include "BLI_listbase.h" +#include "BLI_path_util.h" #include "BLI_rect.h" - -#include "BLO_readfile.h" +#include "BLI_string.h" #include "BKE_context.h" +#include "BLO_readfile.h" #include "ED_fileselect.h" #include "ED_screen.h" @@ -44,3 +46,14 @@ void file_tile_boundbox(const ARegion *region, FileLayout *layout, const int fil ymax - layout->tile_h - layout->tile_border_y, ymax); } + +/** + * If \a path leads to a .blend, remove the trailing slash (if needed). + */ +void file_path_to_ui_path(const char *path, char *r_path, int max_size) +{ + char tmp_path[PATH_MAX]; + BLI_strncpy(tmp_path, path, sizeof(tmp_path)); + BLI_path_slash_rstrip(tmp_path); + BLI_strncpy(r_path, BLO_has_bfile_extension(tmp_path) ? tmp_path : path, max_size); +} diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c index f1d72387791..46ae52fd4cf 100644 --- a/source/blender/editors/space_file/space_file.c +++ b/source/blender/editors/space_file/space_file.c @@ -57,6 +57,23 @@ #include "filelist.h" #include "fsmenu.h" +static ARegion *file_ui_region_ensure(ScrArea *area, ARegion *region_prev) +{ + ARegion *region; + + if ((region = BKE_area_find_region_type(area, RGN_TYPE_UI)) != NULL) { + return region; + } + + region = MEM_callocN(sizeof(ARegion), "execute region for file"); + BLI_insertlinkafter(&area->regionbase, region_prev, region); + region->regiontype = RGN_TYPE_UI; + region->alignment = RGN_ALIGN_TOP; + region->flag = RGN_FLAG_DYNAMIC_SIZE; + + return region; +} + static ARegion *file_execute_region_ensure(ScrArea *area, ARegion *region_prev) { ARegion *region; @@ -223,15 +240,30 @@ static void file_ensure_valid_region_state(bContext *C, SpaceFile *sfile, FileSelectParams *params) { - ARegion *region_ui = BKE_area_find_region_type(area, RGN_TYPE_UI); - ARegion *region_props = BKE_area_find_region_type(area, RGN_TYPE_TOOL_PROPS); - ARegion *region_execute = BKE_area_find_region_type(area, RGN_TYPE_EXECUTE); + ARegion *region_tools = BKE_area_find_region_type(area, RGN_TYPE_TOOLS); bool needs_init = false; /* To avoid multiple ED_area_init() calls. */ + BLI_assert(region_tools); + + if (sfile->browse_mode == FILE_BROWSE_MODE_ASSETS) { + ARegion *region_execute = file_execute_region_ensure(area, region_tools); + ARegion *region_props = file_tool_props_region_ensure(area, region_execute); + + /* Hide specific regions by default. */ + region_props->flag |= RGN_FLAG_HIDDEN; + region_execute->flag |= RGN_FLAG_HIDDEN; + + ARegion *region_ui = BKE_area_find_region_type(area, RGN_TYPE_UI); + if (region_ui) { + ED_region_remove(C, area, region_ui); + needs_init = true; + } + } /* If there's an file-operation, ensure we have the option and execute region */ - if (sfile->op && (region_props == NULL)) { - region_execute = file_execute_region_ensure(area, region_ui); - region_props = file_tool_props_region_ensure(area, region_execute); + else if (sfile->op) { + ARegion *region_ui = file_ui_region_ensure(area, region_tools); + ARegion *region_execute = file_execute_region_ensure(area, region_ui); + ARegion *region_props = file_tool_props_region_ensure(area, region_execute); if (params->flag & FILE_HIDE_TOOL_PROPS) { region_props->flag |= RGN_FLAG_HIDDEN; @@ -243,12 +275,19 @@ static void file_ensure_valid_region_state(bContext *C, needs_init = true; } /* If there's _no_ file-operation, ensure we _don't_ have the option and execute region */ - else if ((sfile->op == NULL) && (region_props != NULL)) { - BLI_assert(region_execute != NULL); + else { + ARegion *region_props = BKE_area_find_region_type(area, RGN_TYPE_TOOL_PROPS); + ARegion *region_execute = BKE_area_find_region_type(area, RGN_TYPE_EXECUTE); + ARegion *region_ui = file_ui_region_ensure(area, region_tools); + UNUSED_VARS(region_ui); - ED_region_remove(C, area, region_props); - ED_region_remove(C, area, region_execute); - needs_init = true; + if (region_props) { + BLI_assert(region_execute); + + ED_region_remove(C, area, region_props); + ED_region_remove(C, area, region_execute); + needs_init = true; + } } if (needs_init) { @@ -530,7 +569,9 @@ static void file_main_region_draw(const bContext *C, ARegion *region) file_highlight_set(sfile, region, event->x, event->y); } - file_draw_list(C, region); + if (!file_draw_hint_if_invalid(sfile, region)) { + file_draw_list(C, region); + } /* reset view matrix */ UI_view2d_view_restore(C); @@ -714,6 +755,25 @@ static void file_dropboxes(void) WM_dropbox_add(lb, "FILE_OT_filepath_drop", filepath_drop_poll, filepath_drop_copy); } +static int file_space_subtype_get(ScrArea *area) +{ + SpaceFile *sfile = area->spacedata.first; + return sfile->browse_mode; +} + +static void file_space_subtype_set(ScrArea *area, int value) +{ + SpaceFile *sfile = area->spacedata.first; + sfile->browse_mode = value; +} + +static void file_space_subtype_item_extend(bContext *UNUSED(C), + EnumPropertyItem **item, + int *totitem) +{ + RNA_enum_items_add(item, totitem, rna_enum_space_file_browse_mode_items); +} + const char *file_context_dir[] = {"active_file", "active_id", NULL}; static int /*eContextResult*/ file_context(const bContext *C, @@ -779,6 +839,9 @@ void ED_spacetype_file(void) st->operatortypes = file_operatortypes; st->keymap = file_keymap; st->dropboxes = file_dropboxes; + st->space_subtype_item_extend = file_space_subtype_item_extend; + st->space_subtype_get = file_space_subtype_get; + st->space_subtype_set = file_space_subtype_set; st->context = file_context; st->id_remap = file_id_remap; diff --git a/source/blender/makesrna/intern/rna_screen.c b/source/blender/makesrna/intern/rna_screen.c index e300fb1b31b..784172b3ac9 100644 --- a/source/blender/makesrna/intern/rna_screen.c +++ b/source/blender/makesrna/intern/rna_screen.c @@ -270,6 +270,8 @@ static void rna_Area_ui_type_update(bContext *C, PointerRNA *ptr) st->space_subtype_set(area, area->butspacetype_subtype); } area->butspacetype_subtype = 0; + + ED_area_tag_refresh(area); } static void rna_View2D_region_to_view(struct View2D *v2d, float x, float y, float result[2]) diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 4b39858026c..59012ce4528 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -2574,6 +2574,18 @@ static const EnumPropertyItem *rna_FileAssetSelectParams_asset_library_itemf( return item; } +static void rna_FileAssetSelectParams_asset_category_set(PointerRNA *ptr, uint64_t value) +{ + FileSelectParams *params = ptr->data; + params->filter_id = value; +} + +static uint64_t rna_FileAssetSelectParams_asset_category_get(PointerRNA *ptr) +{ + FileSelectParams *params = ptr->data; + return params->filter_id; +} + static void rna_FileBrowser_FileSelectEntry_name_get(PointerRNA *ptr, char *value) { const FileDirEntry *entry = ptr->data; @@ -6207,6 +6219,47 @@ static void rna_def_fileselect_asset_params(BlenderRNA *brna) StructRNA *srna; PropertyRNA *prop; + /* XXX copied from rna_def_fileselect_idfilter. */ + static const EnumPropertyItem asset_category_items[] = { + {FILTER_ID_SCE, "SCENES", ICON_SCENE_DATA, "Scenes", "Show scenes"}, + {FILTER_ID_AC, "ANIMATIONS", ICON_ANIM_DATA, "Animations", "Show animation data"}, + {FILTER_ID_OB | FILTER_ID_GR, + "OBJECTS_AND_COLLECTIONS", + ICON_GROUP, + "Objects & Collections", + "Show objects and collections"}, + {FILTER_ID_AR | FILTER_ID_CU | FILTER_ID_LT | FILTER_ID_MB | FILTER_ID_ME + /* XXX avoid warning */ + // | FILTER_ID_HA | FILTER_ID_PT | FILTER_ID_VO + , + "GEOMETRY", + ICON_MESH_DATA, + "Geometry", + "Show meshes, curves, lattice, armatures and metaballs data"}, + {FILTER_ID_LS | FILTER_ID_MA | FILTER_ID_NT | FILTER_ID_TE, + "SHADING", + ICON_MATERIAL_DATA, + "Shading", + "Show materials, nodetrees, textures and Freestyle's linestyles"}, + {FILTER_ID_IM | FILTER_ID_MC | FILTER_ID_MSK | FILTER_ID_SO, + "IMAGES_AND_SOUNDS", + ICON_IMAGE_DATA, + "Images & Sounds", + "Show images, movie clips, sounds and masks"}, + {FILTER_ID_CA | FILTER_ID_LA | FILTER_ID_LP | FILTER_ID_SPK | FILTER_ID_WO | FILTER_ID_WS, + "ENVIRONMENTS", + ICON_WORLD_DATA, + "Environment", + "Show worlds, lights, cameras and speakers"}, + {FILTER_ID_BR | FILTER_ID_GD | FILTER_ID_PA | FILTER_ID_PAL | FILTER_ID_PC | FILTER_ID_TXT | + FILTER_ID_VF | FILTER_ID_CF, + "MISC", + ICON_GREASEPENCIL, + "Miscellaneous", + "Show other data types"}, + {0, NULL, 0, NULL, NULL}, + }; + srna = RNA_def_struct(brna, "FileAssetSelectParams", "FileSelectParams"); RNA_def_struct_ui_text( srna, "Asset Select Parameters", "Settings for the file selection in Asset Browser mode"); @@ -6219,6 +6272,15 @@ static void rna_def_fileselect_asset_params(BlenderRNA *brna) "rna_FileAssetSelectParams_asset_library_itemf"); RNA_def_property_ui_text(prop, "Asset Library", ""); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL); + + prop = RNA_def_property(srna, "asset_category", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, asset_category_items); + RNA_def_property_enum_funcs(prop, + "rna_FileAssetSelectParams_asset_category_get", + "rna_FileAssetSelectParams_asset_category_set", + NULL); + RNA_def_property_ui_text(prop, "Asset Category", "Determine which kind of assets to display"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_LIST, NULL); } static void rna_def_filemenu_entry(BlenderRNA *brna) diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 2175cddcd7f..7a285df235a 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -5993,8 +5993,9 @@ static void rna_def_userdef_filepaths_asset_library(BlenderRNA *brna) RNA_def_struct_name_property(srna, prop); RNA_def_property_update(prop, 0, "rna_userdef_update"); - prop = RNA_def_property(srna, "path", PROP_STRING, PROP_FILEPATH); - RNA_def_property_ui_text(prop, "Path", "Path to a .blend file to use as an asset library"); + prop = RNA_def_property(srna, "path", PROP_STRING, PROP_DIRPATH); + RNA_def_property_ui_text( + prop, "Path", "Path to a directory with .blend files to use as an asset library"); RNA_def_property_update(prop, 0, "rna_userdef_update"); } -- cgit v1.2.3 From 303aceb917b892e1144b88663225ee3b1e78eabe Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Mon, 14 Dec 2020 15:19:09 +0100 Subject: Fix asset previews not showing in "Current File" repository after reading Previews would be flagged as unfinished when reading. Instead clear the flag and always consider them finished upon reading. If we wouldn't do this, the File Browser would keep running the preview updating to wait for the preview to finish. It could be smarter and also check if there's actually a preview job running. Instead, I think it will just display an unfilled buffer for now. Up until today we wouldn't even know if a stored preview is finished or not, so it would always assume they are finished. We do the same now, but have the option to make it smarter. --- source/blender/blenkernel/intern/icons.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/intern/icons.cc b/source/blender/blenkernel/intern/icons.cc index b92b2259eeb..4bd850094f0 100644 --- a/source/blender/blenkernel/intern/icons.cc +++ b/source/blender/blenkernel/intern/icons.cc @@ -658,7 +658,9 @@ void BKE_previewimg_blend_read(BlendDataReader *reader, PreviewImage *prv) BLO_read_data_address(reader, &prv->rect[i]); } prv->gputexture[i] = NULL; - prv->flag[i] |= PRV_UNFINISHED; + /* For now consider previews read from file as finished to not confuse File Browser preview + * loading. That could be smarter and check if there's a preview job running instead. */ + prv->flag[i] &= ~PRV_UNFINISHED; } prv->icon_id = 0; prv->tag = 0; -- cgit v1.2.3 From 68e4a902409881ee1f29969c3135700cacfe1a66 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Mon, 14 Dec 2020 19:08:13 +0100 Subject: Assets: Better path for the default asset library In D9722 we agreed on using `[home-directory]/Documents/Blender/Assets` for the default asset library. I just forgot to do the change before committing. (The default repository is just a named path, it's *not* a default library with bundled assets.) --- source/blender/blenkernel/intern/preferences.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/intern/preferences.c b/source/blender/blenkernel/intern/preferences.c index c263ff7100f..8dcf6de164a 100644 --- a/source/blender/blenkernel/intern/preferences.c +++ b/source/blender/blenkernel/intern/preferences.c @@ -102,18 +102,18 @@ int BKE_preferences_asset_library_get_index(const UserDef *userdef, void BKE_preferences_asset_library_default_add(UserDef *userdef) { - const char *asset_blend_name = "assets.blend"; - const char *doc_path = BKE_appdir_folder_default(); + char documents_path[FILE_MAXDIR]; /* No home or documents path found, not much we can do. */ - if (!doc_path || !doc_path[0]) { + if (!BKE_appdir_folder_documents(documents_path) || !documents_path[0]) { return; } - /* Add new "Default" library under '[doc_path]/assets.blend'. */ - bUserAssetLibrary *library = BKE_preferences_asset_library_add(userdef, DATA_("Default"), NULL); - BLI_join_dirfile(library->path, sizeof(library->path), doc_path, asset_blend_name); + + /* Add new "Default" library under '[doc_path]/Blender/Assets'. */ + BLI_path_join( + library->path, sizeof(library->path), documents_path, N_("Blender"), N_("Assets"), NULL); } /** \} */ -- cgit v1.2.3 From 9caeb9dfc7dfe8dcd6507a6b8dce5b98651b40ca Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Mon, 14 Dec 2020 23:01:24 +0100 Subject: Fix Asset Browser crash with undo in "Current File" library with sidebar When the Asset Browser was showing the "Current File" repository and the sidebar was open, undoing could crash, because the context API returned freed data. Don't let context return anything if a refresh is pending due to data changes like undo/redo. --- source/blender/editors/space_file/space_file.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c index 46ae52fd4cf..8be02b952a8 100644 --- a/source/blender/editors/space_file/space_file.c +++ b/source/blender/editors/space_file/space_file.c @@ -790,12 +790,18 @@ static int /*eContextResult*/ file_context(const bContext *C, CTX_data_dir_set(result, file_context_dir); return CTX_RESULT_OK; } - else if (CTX_data_equals(member, "active_file")) { + + /* The following member checks return file-list data, check if that needs refreshing first. */ + if (file_main_region_needs_refresh_before_draw(sfile)) { + return CTX_RESULT_NO_DATA; + } + + if (CTX_data_equals(member, "active_file")) { FileDirEntry *file = filelist_file(sfile->files, params->active_file); CTX_data_pointer_set(result, &screen->id, &RNA_FileSelectEntry, file); return CTX_RESULT_OK; } - else if (CTX_data_equals(member, "active_id")) { + if (CTX_data_equals(member, "active_id")) { const FileDirEntry *file = filelist_file(sfile->files, params->active_file); ID *id = filelist_file_get_id(file); @@ -804,6 +810,7 @@ static int /*eContextResult*/ file_context(const bContext *C, } return CTX_RESULT_OK; } + return CTX_RESULT_MEMBER_NOT_FOUND; } -- cgit v1.2.3 From 7dc8db7cd135e7b26fccc1cc6728cac8b510de70 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Tue, 15 Dec 2020 12:56:02 +0100 Subject: Fix failing assert when generating material preview The `!BKE_previewimg_is_finished()` in `icon_preview_startjob_all_sizes()` would fail. Caused by 990bd9acf243ae. We have to be more picky about tagging previews as unfinished after file read. But we also have to consider files stored in old versions and set the unfinished tag as needed. --- source/blender/blenkernel/intern/icons.cc | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/intern/icons.cc b/source/blender/blenkernel/intern/icons.cc index 4bd850094f0..48f5e11778c 100644 --- a/source/blender/blenkernel/intern/icons.cc +++ b/source/blender/blenkernel/intern/icons.cc @@ -659,8 +659,16 @@ void BKE_previewimg_blend_read(BlendDataReader *reader, PreviewImage *prv) } prv->gputexture[i] = NULL; /* For now consider previews read from file as finished to not confuse File Browser preview - * loading. That could be smarter and check if there's a preview job running instead. */ - prv->flag[i] &= ~PRV_UNFINISHED; + * loading. That could be smarter and check if there's a preview job running instead. + * If the preview is tagged as changed, it needs to be updated anyway, so don't remove the tag. + */ + if ((prv->flag[i] & PRV_CHANGED) == 0) { + BKE_previewimg_finish(prv, i); + } + else { + /* Only for old files that didn't write the flag . */ + prv->flag[i] |= PRV_UNFINISHED; + } } prv->icon_id = 0; prv->tag = 0; -- cgit v1.2.3 From 990406e1ff9371a8c896b71171caa876cfdff2f6 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Tue, 15 Dec 2020 16:58:30 +0100 Subject: Fix crash when deleting/renaming asset library while it's visible Storing the asset library reference by name wasn't a good idea, I thought it would work with a careful fallback, but it's easier to just use the index instead. So change to using indices, make sure fallback methods work reliable and make sure the file list is updated when asset libraries are removed. I added a new notifier type for the latter, I prefer not using file notifiers in asset-library/preferences code. We have more than enough values for notifiers left. --- source/blender/editors/space_file/filelist.c | 7 +++++- source/blender/editors/space_file/filesel.c | 7 ++++-- source/blender/editors/space_file/space_file.c | 5 ++++ .../blender/editors/space_userpref/userpref_ops.c | 2 ++ source/blender/makesdna/DNA_space_types.h | 9 ++++--- source/blender/makesrna/intern/rna_space.c | 21 ++++++++-------- source/blender/windowmanager/WM_types.h | 29 +++++++++++----------- 7 files changed, 49 insertions(+), 31 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c index 5dc5f741ac3..afa1fa0edee 100644 --- a/source/blender/editors/space_file/filelist.c +++ b/source/blender/editors/space_file/filelist.c @@ -61,6 +61,7 @@ #include "BKE_lib_id.h" #include "BKE_main.h" #include "BKE_main_idmap.h" +#include "BKE_preferences.h" #include "BLO_readfile.h" #include "DNA_asset_types.h" @@ -1050,7 +1051,11 @@ static bool filelist_compare_asset_libraries(const FileSelectAssetLibraryUID *li return false; } if (library_a->type == FILE_ASSET_LIBRARY_CUSTOM) { - return STREQ(library_a->custom_library_identifier, library_b->custom_library_identifier); + /* Don't only check the index, also check that it's valid. */ + bUserAssetLibrary *library_ptr_a = BKE_preferences_asset_library_find_from_index( + &U, library_a->custom_library_index); + return (library_ptr_a != NULL) && + (library_a->custom_library_index == library_b->custom_library_index); } return true; diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c index 2c66bd39e0a..cd27b7b5773 100644 --- a/source/blender/editors/space_file/filesel.c +++ b/source/blender/editors/space_file/filesel.c @@ -119,6 +119,7 @@ static void fileselect_ensure_updated_asset_params(SpaceFile *sfile) "FileAssetSelectParams"); asset_params->base_params.details_flags = U_default.file_space_data.details_flags; asset_params->asset_library.type = FILE_ASSET_LIBRARY_LOCAL; + asset_params->asset_library.custom_library_index = -1; } FileSelectParams *base_params = &asset_params->base_params; @@ -419,8 +420,10 @@ static void fileselect_refresh_asset_params(FileAssetSelectParams *asset_params) /* Ensure valid repo, or fall-back to local one. */ if (library->type == FILE_ASSET_LIBRARY_CUSTOM) { - user_library = BKE_preferences_asset_library_find_from_name( - &U, library->custom_library_identifier); + BLI_assert(library->custom_library_index >= 0); + + user_library = BKE_preferences_asset_library_find_from_index(&U, + library->custom_library_index); if (!user_library) { library->type = FILE_ASSET_LIBRARY_LOCAL; } diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c index 8be02b952a8..09b7e5b348c 100644 --- a/source/blender/editors/space_file/space_file.c +++ b/source/blender/editors/space_file/space_file.c @@ -412,6 +412,11 @@ static void file_listener(wmWindow *UNUSED(win), ED_area_tag_refresh(area); } break; + case ND_SPACE_ASSET_PARAMS: + if (sfile->browse_mode == FILE_BROWSE_MODE_ASSETS) { + ED_area_tag_refresh(area); + } + break; } break; case NC_ASSET: { diff --git a/source/blender/editors/space_userpref/userpref_ops.c b/source/blender/editors/space_userpref/userpref_ops.c index 9cc8cc6ddaa..ee23cde78c2 100644 --- a/source/blender/editors/space_userpref/userpref_ops.c +++ b/source/blender/editors/space_userpref/userpref_ops.c @@ -170,6 +170,8 @@ static int preferences_asset_library_remove_exec(bContext *UNUSED(C), wmOperator if (library) { BKE_preferences_asset_library_remove(&U, library); U.runtime.is_dirty = true; + /* Trigger refresh for the Asset Browser. */ + WM_main_add_notifier(NC_SPACE | ND_SPACE_ASSET_PARAMS, NULL); } return OPERATOR_FINISHED; } diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index e07f085d356..4161faca386 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -673,12 +673,13 @@ typedef enum eSpaceSeq_OverlayType { */ typedef struct FileSelectAssetLibraryUID { short type; - char _pad[6]; + char _pad[2]; /** - * If showing a custom asset library (#FILE_ASSET_LIBRARY_CUSTOM), this name has to be set to - * define which. Can be empty otherwise. + * If showing a custom asset library (#FILE_ASSET_LIBRARY_CUSTOM), this is the index of the + * #bUserAssetLibrary within #UserDef.asset_libraries. + * Should be ignored otherwise (but better set to -1 then, for sanity and debugging). */ - char custom_library_identifier[64]; /* MAX_NAME */ + int custom_library_index; } FileSelectAssetLibraryUID; /* Config and Input for File Selector */ diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 59012ce4528..0e779c8cc97 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -2482,11 +2482,10 @@ static int rna_FileAssetSelectParams_asset_library_get(PointerRNA *ptr) /* Note that the path isn't checked for validity here. If an invalid library path is used, the * Asset Browser can give a nice hint on what's wrong. */ - const bUserAssetLibrary *user_library = BKE_preferences_asset_library_find_from_name( - &U, params->asset_library.custom_library_identifier); - const int index = BKE_preferences_asset_library_get_index(&U, user_library); - if (index > -1) { - return FILE_ASSET_LIBRARY_CUSTOM + index; + const bUserAssetLibrary *user_library = BKE_preferences_asset_library_find_from_index( + &U, params->asset_library.custom_library_index); + if (user_library) { + return FILE_ASSET_LIBRARY_CUSTOM + params->asset_library.custom_library_index; } BLI_assert(0); @@ -2500,7 +2499,7 @@ static void rna_FileAssetSelectParams_asset_library_set(PointerRNA *ptr, int val /* Simple case: Predefined repo, just set the value. */ if (value < FILE_ASSET_LIBRARY_CUSTOM) { params->asset_library.type = value; - params->asset_library.custom_library_identifier[0] = '\0'; + params->asset_library.custom_library_index = -1; BLI_assert(ELEM(value, FILE_ASSET_LIBRARY_LOCAL)); return; } @@ -2511,10 +2510,12 @@ static void rna_FileAssetSelectParams_asset_library_set(PointerRNA *ptr, int val /* Note that the path isn't checked for validity here. If an invalid library path is used, the * Asset Browser can give a nice hint on what's wrong. */ const bool is_valid = (user_library->name[0] && user_library->path[0]); - if (user_library && is_valid) { - BLI_strncpy(params->asset_library.custom_library_identifier, - user_library->name, - sizeof(params->asset_library.custom_library_identifier)); + if (!user_library) { + params->asset_library.type = FILE_ASSET_LIBRARY_LOCAL; + params->asset_library.custom_library_index = -1; + } + else if (user_library && is_valid) { + params->asset_library.custom_library_index = value - FILE_ASSET_LIBRARY_CUSTOM; params->asset_library.type = FILE_ASSET_LIBRARY_CUSTOM; } } diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index 0ddd0f20c7a..a2cc246e21e 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -410,20 +410,21 @@ typedef struct wmNotifier { #define ND_SPACE_IMAGE (4 << 16) #define ND_SPACE_FILE_PARAMS (5 << 16) #define ND_SPACE_FILE_LIST (6 << 16) -#define ND_SPACE_NODE (7 << 16) -#define ND_SPACE_OUTLINER (8 << 16) -#define ND_SPACE_VIEW3D (9 << 16) -#define ND_SPACE_PROPERTIES (10 << 16) -#define ND_SPACE_TEXT (11 << 16) -#define ND_SPACE_TIME (12 << 16) -#define ND_SPACE_GRAPH (13 << 16) -#define ND_SPACE_DOPESHEET (14 << 16) -#define ND_SPACE_NLA (15 << 16) -#define ND_SPACE_SEQUENCER (16 << 16) -#define ND_SPACE_NODE_VIEW (17 << 16) -#define ND_SPACE_CHANGED (18 << 16) /*sent to a new editor type after it's replaced an old one*/ -#define ND_SPACE_CLIP (19 << 16) -#define ND_SPACE_FILE_PREVIEW (20 << 16) +#define ND_SPACE_ASSET_PARAMS (7 << 16) +#define ND_SPACE_NODE (8 << 16) +#define ND_SPACE_OUTLINER (9 << 16) +#define ND_SPACE_VIEW3D (10 << 16) +#define ND_SPACE_PROPERTIES (11 << 16) +#define ND_SPACE_TEXT (12 << 16) +#define ND_SPACE_TIME (13 << 16) +#define ND_SPACE_GRAPH (14 << 16) +#define ND_SPACE_DOPESHEET (15 << 16) +#define ND_SPACE_NLA (16 << 16) +#define ND_SPACE_SEQUENCER (17 << 16) +#define ND_SPACE_NODE_VIEW (18 << 16) +#define ND_SPACE_CHANGED (19 << 16) /*sent to a new editor type after it's replaced an old one*/ +#define ND_SPACE_CLIP (20 << 16) +#define ND_SPACE_FILE_PREVIEW (21 << 16) /* subtype, 256 entries too */ #define NOTE_SUBTYPE 0x0000FF00 -- cgit v1.2.3 From c6692014cf604a698245158615b4d10b057f12da Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Tue, 15 Dec 2020 17:19:55 +0100 Subject: Fix redundant declaration warning Function was declared twice (caused by merge conflicts) which GCC would rightfully complain about. --- source/blender/blenkernel/BKE_icons.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/BKE_icons.h b/source/blender/blenkernel/BKE_icons.h index 5ceba4c717f..28a6f837f61 100644 --- a/source/blender/blenkernel/BKE_icons.h +++ b/source/blender/blenkernel/BKE_icons.h @@ -146,8 +146,6 @@ void BKE_previewimg_clear_single(struct PreviewImage *prv, enum eIconSizes size) struct PreviewImage **BKE_previewimg_id_get_p(const struct ID *id); struct PreviewImage *BKE_previewimg_id_get(const struct ID *id); -void BKE_previewimg_id_custom_set(struct ID *id, const char *path); - bool BKE_previewimg_id_supports_jobs(const struct ID *id); /* Trigger deferred loading of a custom image file into the preview buffer. */ -- cgit v1.2.3 From b24712a9ca6fa807660a02d6988269748daecdbf Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Tue, 15 Dec 2020 18:18:53 +0100 Subject: Fix (studio-reported) broken handling of relative font paths. `blf_dir_search` BLF util would not properly handle relative fonts not found in pre-defined 'system fonts' directoriesi stored in `global_font_dir` global variable. Now it rebases relative paths to current .blend file location as expected. Note: the fact that VSE is setting font ptaths relative by default is probably not actually desired, but this is another issue really. See `BKE_sequencer_text_font_load` code. --- source/blender/blenfont/intern/blf_dir.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenfont/intern/blf_dir.c b/source/blender/blenfont/intern/blf_dir.c index 51d3849aa48..25235097505 100644 --- a/source/blender/blenfont/intern/blf_dir.c +++ b/source/blender/blenfont/intern/blf_dir.c @@ -47,6 +47,9 @@ #include "blf_internal.h" #include "blf_internal_types.h" +#include "BKE_global.h" +#include "BKE_main.h" + static ListBase global_font_dir = {NULL, NULL}; static DirBLF *blf_dir_find(const char *path) @@ -137,9 +140,11 @@ char *blf_dir_search(const char *file) } if (!s) { - /* check the current directory, why not ? */ - if (BLI_exists(file)) { - s = BLI_strdup(file); + /* Assume file is either an abslute path, or a relative path to current directory. */ + BLI_strncpy(full_path, file, sizeof(full_path)); + BLI_path_abs(full_path, BKE_main_blendfile_path(G_MAIN)); + if (BLI_exists(full_path)) { + s = BLI_strdup(full_path); } } -- cgit v1.2.3 From ffe63b0440cb55dee7a0ec3c383cce99167b47a1 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Tue, 15 Dec 2020 18:49:56 +0100 Subject: Fix crash opening maximized File Browser from Asset Browser If Preferences > Interface > Temporary Editors > File Browser is set to "Maximized Area", opening a File Browser from an Asset Browser would cause the new maximized editor to be an Asset Browser. Exiting it again would crash. This fixes the wrong behavior and the crash. There's still an issue with exiting the editor again, it stays a File Browser then and doesn't go back to being an Asset Browser. That's to be fixed separately. --- source/blender/editors/screen/screen_edit.c | 1 + source/blender/editors/space_file/filesel.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'source/blender') diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c index 6be2fb8004b..c3dcaefab79 100644 --- a/source/blender/editors/screen/screen_edit.c +++ b/source/blender/editors/screen/screen_edit.c @@ -1369,6 +1369,7 @@ ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *area, const newa->full = oldscreen; ED_screen_change(C, screen); + ED_area_tag_refresh(newa); } /* XXX bad code: setscreen() ends with first area active. fullscreen render assumes this too */ diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c index cd27b7b5773..b919a30e6cd 100644 --- a/source/blender/editors/space_file/filesel.c +++ b/source/blender/editors/space_file/filesel.c @@ -490,7 +490,7 @@ void ED_fileselect_set_params_from_userdef(SpaceFile *sfile) wmOperator *op = sfile->op; UserDef_FileSpaceData *sfile_udata = &U.file_space_data; - BLI_assert(sfile->browse_mode == FILE_BROWSE_MODE_FILES); + sfile->browse_mode = FILE_BROWSE_MODE_FILES; FileSelectParams *params = fileselect_ensure_updated_file_params(sfile); if (!op) { -- cgit v1.2.3 From 3834dc2f7b38a8a29b8cd6dbcd55ac5be7890553 Mon Sep 17 00:00:00 2001 From: Philipp Oeser Date: Fri, 11 Dec 2020 12:04:30 +0100 Subject: Fix Adjust Last Operation popup for operators relying on button context This was reported for duplicating particle systems, then using F9 to enable the 'Duplicate Settings' option (see T83317). In this case, the operator gets the particle_system from (buttons) context and if none can get found will duplicate all settings instead. The reason why none gets found here is that buttons_context() doesnt have a valid path when called from F9/SCREEN_OT_redo_last, path is cleared when global undo does a file-read which clears the path (see lib_link_workspace_layout_restore). It can be recomputed though to be valid even from redo_last (at least when in the Properties Editor). This was likely causing other operators (relying on buttons context) from the Properties Editor to fail as well. Fixes T83317 Maniphest Tasks: T83317 Differential Revision: https://developer.blender.org/D9825 --- source/blender/editors/space_buttons/buttons_context.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source/blender') diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c index 3a2b8cf0115..c1f29231f96 100644 --- a/source/blender/editors/space_buttons/buttons_context.c +++ b/source/blender/editors/space_buttons/buttons_context.c @@ -826,6 +826,11 @@ int /*eContextResult*/ buttons_context(const bContext *C, bContextDataResult *result) { SpaceProperties *sbuts = CTX_wm_space_properties(C); + if (sbuts && sbuts->path == NULL) { + /* path is cleared for SCREEN_OT_redo_last, when global undo does a file-read which clears the + * path (see lib_link_workspace_layout_restore). */ + buttons_context_compute(C, sbuts); + } ButsContextPath *path = sbuts ? sbuts->path : NULL; if (!path) { -- cgit v1.2.3 From 8df167873a3b36f7b179266802699d4f935cd2f9 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Tue, 15 Dec 2020 12:39:27 -0600 Subject: Cleanup: Clang tidy else after return --- source/blender/editors/space_file/filelist.c | 31 ++++++++++++++-------------- 1 file changed, 15 insertions(+), 16 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c index afa1fa0edee..3ed7b5499db 100644 --- a/source/blender/editors/space_file/filelist.c +++ b/source/blender/editors/space_file/filelist.c @@ -3450,22 +3450,21 @@ void filelist_readjob_start(FileList *filelist, const bContext *C) WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL); return; } - else { - /* setup job */ - wm_job = WM_jobs_get(CTX_wm_manager(C), - CTX_wm_window(C), - CTX_data_scene(C), - "Listing Dirs...", - WM_JOB_PROGRESS, - WM_JOB_TYPE_FILESEL_READDIR); - WM_jobs_customdata_set(wm_job, flrj, filelist_readjob_free); - WM_jobs_timer(wm_job, 0.01, NC_SPACE | ND_SPACE_FILE_LIST, NC_SPACE | ND_SPACE_FILE_LIST); - WM_jobs_callbacks( - wm_job, filelist_readjob_startjob, NULL, filelist_readjob_update, filelist_readjob_endjob); - - /* start the job */ - WM_jobs_start(CTX_wm_manager(C), wm_job); - } + + /* setup job */ + wm_job = WM_jobs_get(CTX_wm_manager(C), + CTX_wm_window(C), + CTX_data_scene(C), + "Listing Dirs...", + WM_JOB_PROGRESS, + WM_JOB_TYPE_FILESEL_READDIR); + WM_jobs_customdata_set(wm_job, flrj, filelist_readjob_free); + WM_jobs_timer(wm_job, 0.01, NC_SPACE | ND_SPACE_FILE_LIST, NC_SPACE | ND_SPACE_FILE_LIST); + WM_jobs_callbacks( + wm_job, filelist_readjob_startjob, NULL, filelist_readjob_update, filelist_readjob_endjob); + + /* start the job */ + WM_jobs_start(CTX_wm_manager(C), wm_job); } void filelist_readjob_stop(wmWindowManager *wm, Scene *owner_scene) -- cgit v1.2.3 From d59e87acf0b8954390ce2691145613ea8585010f Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Tue, 15 Dec 2020 12:41:41 -0600 Subject: Cleanup: Use nullptr instead of NULL in C++ code --- source/blender/blenkernel/intern/icons.cc | 72 +++++++++++++++---------------- 1 file changed, 36 insertions(+), 36 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/intern/icons.cc b/source/blender/blenkernel/intern/icons.cc index 48f5e11778c..fbf69357478 100644 --- a/source/blender/blenkernel/intern/icons.cc +++ b/source/blender/blenkernel/intern/icons.cc @@ -78,7 +78,7 @@ enum { static CLG_LogRef LOG = {"bke.icons"}; /* Protected by gIconMutex. */ -static GHash *gIcons = NULL; +static GHash *gIcons = nullptr; /* Protected by gIconMutex. */ static int gNextIconId = 1; @@ -89,7 +89,7 @@ static int gFirstIconId = 1; std::mutex gIconMutex; /* Not mutex-protected! */ -static GHash *gCachedPreviews = NULL; +static GHash *gCachedPreviews = nullptr; /* Queue of icons for deferred deletion. */ typedef struct DeferredIconDeleteNode { @@ -149,7 +149,7 @@ static void icon_free_data(int icon_id, Icon *icon) } else if (icon->obj_type == ICON_DATA_STUDIOLIGHT) { StudioLight *sl = (StudioLight *)icon->obj; - if (sl != NULL) { + if (sl != nullptr) { BKE_studiolight_unset_icon_id(sl, icon_id); } } @@ -166,7 +166,7 @@ static Icon *icon_ghash_lookup(int icon_id) /* create an id for a new icon and make sure that ids from deleted icons get reused * after the integer number range is used up */ -static int get_next_free_id(void) +static int get_next_free_id() { std::scoped_lock lock(gIconMutex); int startId = gFirstIconId; @@ -214,13 +214,13 @@ void BKE_icons_free(void) BLI_assert(BLI_thread_is_main()); if (gIcons) { - BLI_ghash_free(gIcons, NULL, icon_free); - gIcons = NULL; + BLI_ghash_free(gIcons, nullptr, icon_free); + gIcons = nullptr; } if (gCachedPreviews) { BLI_ghash_free(gCachedPreviews, MEM_freeN, BKE_previewimg_freefunc); - gCachedPreviews = NULL; + gCachedPreviews = nullptr; } BLI_linklist_lockfree_free(&g_icon_delete_queue, MEM_freeN); @@ -232,9 +232,9 @@ void BKE_icons_deferred_free(void) for (DeferredIconDeleteNode *node = (DeferredIconDeleteNode *)BLI_linklist_lockfree_begin(&g_icon_delete_queue); - node != NULL; + node != nullptr; node = node->next) { - BLI_ghash_remove(gIcons, POINTER_FROM_INT(node->icon_id), NULL, icon_free); + BLI_ghash_remove(gIcons, POINTER_FROM_INT(node->icon_id), nullptr, icon_free); } BLI_linklist_lockfree_clear(&g_icon_delete_queue, MEM_freeN); } @@ -296,7 +296,7 @@ void BKE_previewimg_free(PreviewImage **prv) { if (prv && (*prv)) { BKE_previewimg_freefunc(*prv); - *prv = NULL; + *prv = nullptr; } } @@ -321,7 +321,7 @@ void BKE_previewimg_clear(struct PreviewImage *prv) PreviewImage *BKE_previewimg_copy(const PreviewImage *prv) { - PreviewImage *prv_img = NULL; + PreviewImage *prv_img = nullptr; if (prv) { prv_img = (PreviewImage *)MEM_dupallocN(prv); @@ -329,7 +329,7 @@ PreviewImage *BKE_previewimg_copy(const PreviewImage *prv) if (prv->rect[i]) { prv_img->rect[i] = (uint *)MEM_dupallocN(prv->rect[i]); } - prv_img->gputexture[i] = NULL; + prv_img->gputexture[i] = nullptr; } } return prv_img; @@ -345,7 +345,7 @@ void BKE_previewimg_id_copy(ID *new_id, const ID *old_id) PreviewImage **new_prv_p = BKE_previewimg_id_get_p(new_id); if (old_prv_p && *old_prv_p) { - BLI_assert(new_prv_p != NULL && ELEM(*new_prv_p, NULL, *old_prv_p)); + BLI_assert(new_prv_p != nullptr && ELEM(*new_prv_p, nullptr, *old_prv_p)); // const int new_icon_id = get_next_free_id(); // if (new_icon_id == 0) { @@ -379,13 +379,13 @@ PreviewImage **BKE_previewimg_id_get_p(const ID *id) break; } - return NULL; + return nullptr; } PreviewImage *BKE_previewimg_id_get(const ID *id) { PreviewImage **prv_p = BKE_previewimg_id_get_p(id); - return prv_p ? *prv_p : NULL; + return prv_p ? *prv_p : nullptr; } void BKE_previewimg_id_free(ID *id) @@ -401,13 +401,13 @@ PreviewImage *BKE_previewimg_id_ensure(ID *id) PreviewImage **prv_p = BKE_previewimg_id_get_p(id); if (prv_p) { - if (*prv_p == NULL) { + if (*prv_p == nullptr) { *prv_p = BKE_previewimg_create(); } return *prv_p; } - return NULL; + return nullptr; } void BKE_previewimg_id_custom_set(ID *id, const char *path) @@ -464,7 +464,7 @@ PreviewImage *BKE_previewimg_cached_ensure(const char *name) { BLI_assert(BLI_thread_is_main()); - PreviewImage *prv = NULL; + PreviewImage *prv = nullptr; void **key_p, **prv_p; if (!BLI_ghash_ensure_p_ex(gCachedPreviews, name, &key_p, &prv_p)) { @@ -488,7 +488,7 @@ PreviewImage *BKE_previewimg_cached_thumbnail_read(const char *name, { BLI_assert(BLI_thread_is_main()); - PreviewImage *prv = NULL; + PreviewImage *prv = nullptr; void **prv_p; prv_p = BLI_ghash_lookup_p(gCachedPreviews, name); @@ -599,7 +599,7 @@ ImBuf *BKE_previewimg_to_imbuf(PreviewImage *prv, const int size) const unsigned int h = prv->h[size]; const unsigned int *rect = prv->rect[size]; - ImBuf *ima = NULL; + ImBuf *ima = nullptr; if (w > 0 && h > 0 && rect) { /* first allocate imbuf for copying preview into it */ @@ -627,7 +627,7 @@ void BKE_previewimg_blend_write(BlendWriter *writer, const PreviewImage *prv) * but not doing so would causes all previews to be re-rendered after * undo which is too expensive. */ - if (prv == NULL) { + if (prv == nullptr) { return; } @@ -636,7 +636,7 @@ void BKE_previewimg_blend_write(BlendWriter *writer, const PreviewImage *prv) if (!(U.flag & USER_SAVE_PREVIEWS)) { prv_copy.w[1] = 0; prv_copy.h[1] = 0; - prv_copy.rect[1] = NULL; + prv_copy.rect[1] = nullptr; } BLO_write_struct_at_address(writer, PreviewImage, prv, &prv_copy); if (prv_copy.rect[0]) { @@ -649,7 +649,7 @@ void BKE_previewimg_blend_write(BlendWriter *writer, const PreviewImage *prv) void BKE_previewimg_blend_read(BlendDataReader *reader, PreviewImage *prv) { - if (prv == NULL) { + if (prv == nullptr) { return; } @@ -657,7 +657,7 @@ void BKE_previewimg_blend_read(BlendDataReader *reader, PreviewImage *prv) if (prv->rect[i]) { BLO_read_data_address(reader, &prv->rect[i]); } - prv->gputexture[i] = NULL; + prv->gputexture[i] = nullptr; /* For now consider previews read from file as finished to not confuse File Browser preview * loading. That could be smarter and check if there's a preview job running instead. * If the preview is tagged as changed, it needs to be updated anyway, so don't remove the tag. @@ -676,7 +676,7 @@ void BKE_previewimg_blend_read(BlendDataReader *reader, PreviewImage *prv) void BKE_icon_changed(const int icon_id) { - Icon *icon = NULL; + Icon *icon = nullptr; if (!icon_id || G.background) { return; @@ -714,8 +714,8 @@ static Icon *icon_create(int icon_id, int obj_type, void *obj) new_icon->flag = 0; /* next two lines make sure image gets created */ - new_icon->drawinfo = NULL; - new_icon->drawinfo_free = NULL; + new_icon->drawinfo = nullptr; + new_icon->drawinfo_free = nullptr; { std::scoped_lock lock(gIconMutex); @@ -867,11 +867,11 @@ ImBuf *BKE_icon_imbuf_get_buffer(int icon_id) Icon *icon = icon_ghash_lookup(icon_id); if (!icon) { CLOG_ERROR(&LOG, "no icon for icon ID: %d", icon_id); - return NULL; + return nullptr; } if (icon->obj_type != ICON_DATA_IMBUF) { CLOG_ERROR(&LOG, "icon ID does not refer to an imbuf icon: %d", icon_id); - return NULL; + return nullptr; } return (ImBuf *)icon->obj; @@ -881,13 +881,13 @@ Icon *BKE_icon_get(const int icon_id) { BLI_assert(BLI_thread_is_main()); - Icon *icon = NULL; + Icon *icon = nullptr; icon = icon_ghash_lookup(icon_id); if (!icon) { CLOG_ERROR(&LOG, "no icon for icon ID: %d", icon_id); - return NULL; + return nullptr; } return icon; @@ -930,7 +930,7 @@ void BKE_icon_id_delete(struct ID *id) BKE_icons_deferred_free(); std::scoped_lock lock(gIconMutex); - BLI_ghash_remove(gIcons, POINTER_FROM_INT(icon_id), NULL, icon_free); + BLI_ghash_remove(gIcons, POINTER_FROM_INT(icon_id), nullptr, icon_free); } /** @@ -944,7 +944,7 @@ bool BKE_icon_delete(const int icon_id) } std::scoped_lock lock(gIconMutex); - if (Icon *icon = (Icon *)BLI_ghash_popkey(gIcons, POINTER_FROM_INT(icon_id), NULL)) { + if (Icon *icon = (Icon *)BLI_ghash_popkey(gIcons, POINTER_FROM_INT(icon_id), nullptr)) { icon_free_data(icon_id, icon); icon_free(icon); return true; @@ -962,7 +962,7 @@ bool BKE_icon_delete_unmanaged(const int icon_id) std::scoped_lock lock(gIconMutex); - Icon *icon = (Icon *)BLI_ghash_popkey(gIcons, POINTER_FROM_INT(icon_id), NULL); + Icon *icon = (Icon *)BLI_ghash_popkey(gIcons, POINTER_FROM_INT(icon_id), nullptr); if (icon) { if (UNLIKELY(icon->flag & ICON_FLAG_MANAGED)) { BLI_ghash_insert(gIcons, POINTER_FROM_INT(icon_id), icon); @@ -1041,8 +1041,8 @@ struct Icon_Geom *BKE_icon_geom_from_file(const char *filename) BLI_assert(BLI_thread_is_main()); size_t data_len; uchar *data = (uchar *)BLI_file_read_binary_as_mem(filename, 0, &data_len); - if (data == NULL) { - return NULL; + if (data == nullptr) { + return nullptr; } return BKE_icon_geom_from_memory(data, data_len); } -- cgit v1.2.3 From 26e9c2147e2810d5238408b029195d427a78f80e Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Tue, 15 Dec 2020 12:43:21 -0600 Subject: Blenloader: Add utility function to write double array It makes sense to support writing double arrays just like floats. This is just split from a patch (D9697) to slim it down some. --- source/blender/blenloader/BLO_read_write.h | 1 + source/blender/blenloader/intern/writefile.c | 5 +++++ 2 files changed, 6 insertions(+) (limited to 'source/blender') diff --git a/source/blender/blenloader/BLO_read_write.h b/source/blender/blenloader/BLO_read_write.h index c4480e2c544..ea0532d884b 100644 --- a/source/blender/blenloader/BLO_read_write.h +++ b/source/blender/blenloader/BLO_read_write.h @@ -160,6 +160,7 @@ void BLO_write_raw(BlendWriter *writer, size_t size_in_bytes, const void *data_p void BLO_write_int32_array(BlendWriter *writer, uint num, const int32_t *data_ptr); void BLO_write_uint32_array(BlendWriter *writer, uint num, const uint32_t *data_ptr); void BLO_write_float_array(BlendWriter *writer, uint num, const float *data_ptr); +void BLO_write_double_array(BlendWriter *writer, uint num, const double *data_ptr); void BLO_write_float3_array(BlendWriter *writer, uint num, const float *data_ptr); void BLO_write_pointer_array(BlendWriter *writer, uint num, const void *data_ptr); void BLO_write_string(BlendWriter *writer, const char *data_ptr); diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index e7d55538f7e..0a4f2fde93f 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -1374,6 +1374,11 @@ void BLO_write_float_array(BlendWriter *writer, uint num, const float *data_ptr) BLO_write_raw(writer, sizeof(float) * (size_t)num, data_ptr); } +void BLO_write_double_array(BlendWriter *writer, uint num, const double *data_ptr) +{ + BLO_write_raw(writer, sizeof(double) * (size_t)num, data_ptr); +} + void BLO_write_pointer_array(BlendWriter *writer, uint num, const void *data_ptr) { BLO_write_raw(writer, sizeof(void *) * (size_t)num, data_ptr); -- cgit v1.2.3 From c9de65679bb0905e7f689b83931c9be9a8abfa02 Mon Sep 17 00:00:00 2001 From: Pablo Dobarro Date: Sun, 6 Dec 2020 23:11:33 +0100 Subject: Fix T83201: Cloth brush performance regression The if statement of the dynamic area mode branch should be an else if. When using local mode, this was running both the local and global code. I moved this code to sculpt_cloth and refactored it to use a switch case to prevent this from happening again. Reviewed By: mont29 Maniphest Tasks: T83201 Differential Revision: https://developer.blender.org/D9762 --- source/blender/editors/sculpt_paint/sculpt.c | 27 +--------------- source/blender/editors/sculpt_paint/sculpt_cloth.c | 37 ++++++++++++++++++++++ .../blender/editors/sculpt_paint/sculpt_intern.h | 4 +++ 3 files changed, 42 insertions(+), 26 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 94f05560f79..80a32682325 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -5742,32 +5742,7 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode); } else if (brush->sculpt_tool == SCULPT_TOOL_CLOTH) { - if (brush->cloth_simulation_area_type == BRUSH_CLOTH_SIMULATION_AREA_LOCAL) { - SculptSearchSphereData data = { - .ss = ss, - .sd = sd, - .radius_squared = square_f(ss->cache->initial_radius * (1.0 + brush->cloth_sim_limit)), - .original = false, - .ignore_fully_ineffective = false, - .center = ss->cache->initial_location, - }; - BKE_pbvh_search_gather(ss->pbvh, SCULPT_search_sphere_cb, &data, &nodes, &totnode); - } - if (brush->cloth_simulation_area_type == BRUSH_CLOTH_SIMULATION_AREA_DYNAMIC) { - SculptSearchSphereData data = { - .ss = ss, - .sd = sd, - .radius_squared = square_f(ss->cache->radius * (1.0 + brush->cloth_sim_limit)), - .original = false, - .ignore_fully_ineffective = false, - .center = ss->cache->location, - }; - BKE_pbvh_search_gather(ss->pbvh, SCULPT_search_sphere_cb, &data, &nodes, &totnode); - } - else { - /* Gobal simulation, get all nodes. */ - BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode); - } + nodes = SCULPT_cloth_brush_affected_nodes_gather(ss, brush, &totnode); } else { const bool use_original = sculpt_tool_needs_original(brush->sculpt_tool) ? true : diff --git a/source/blender/editors/sculpt_paint/sculpt_cloth.c b/source/blender/editors/sculpt_paint/sculpt_cloth.c index f8165890cc4..0ac0d796ca4 100644 --- a/source/blender/editors/sculpt_paint/sculpt_cloth.c +++ b/source/blender/editors/sculpt_paint/sculpt_cloth.c @@ -119,6 +119,43 @@ static void cloth_brush_simulation_location_get(SculptSession *ss, copy_v3_v3(r_location, ss->cache->location); } +PBVHNode **SCULPT_cloth_brush_affected_nodes_gather(SculptSession *ss, + Brush *brush, + int *r_totnode) +{ + BLI_assert(ss->cache); + BLI_assert(brush->sculpt_tool == SCULPT_TOOL_CLOTH); + PBVHNode **nodes = NULL; + + switch (brush->cloth_simulation_area_type) { + case BRUSH_CLOTH_SIMULATION_AREA_LOCAL: { + SculptSearchSphereData data = { + .ss = ss, + .radius_squared = square_f(ss->cache->initial_radius * (1.0 + brush->cloth_sim_limit)), + .original = false, + .ignore_fully_ineffective = false, + .center = ss->cache->initial_location, + }; + BKE_pbvh_search_gather(ss->pbvh, SCULPT_search_sphere_cb, &data, &nodes, r_totnode); + } break; + case BRUSH_CLOTH_SIMULATION_AREA_GLOBAL: + BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, r_totnode); + break; + case BRUSH_CLOTH_SIMULATION_AREA_DYNAMIC: { + SculptSearchSphereData data = { + .ss = ss, + .radius_squared = square_f(ss->cache->radius * (1.0 + brush->cloth_sim_limit)), + .original = false, + .ignore_fully_ineffective = false, + .center = ss->cache->location, + }; + BKE_pbvh_search_gather(ss->pbvh, SCULPT_search_sphere_cb, &data, &nodes, r_totnode); + } break; + } + + return nodes; +} + static float cloth_brush_simulation_falloff_get(const Brush *brush, const float radius, const float location[3], diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h index e0d413bc75f..bd5ba15b493 100644 --- a/source/blender/editors/sculpt_paint/sculpt_intern.h +++ b/source/blender/editors/sculpt_paint/sculpt_intern.h @@ -423,6 +423,10 @@ void SCULPT_cloth_plane_falloff_preview_draw(const uint gpuattr, const float outline_col[3], float outline_alpha); +PBVHNode **SCULPT_cloth_brush_affected_nodes_gather(SculptSession *ss, + Brush *brush, + int *r_totnode); + BLI_INLINE bool SCULPT_is_cloth_deform_brush(const Brush *brush) { return (brush->sculpt_tool == SCULPT_TOOL_CLOTH && ELEM(brush->cloth_deform_type, -- cgit v1.2.3 From 288f2efbd41f325c4127a0f42bf5d2c6682fd00e Mon Sep 17 00:00:00 2001 From: Pablo Dobarro Date: Mon, 7 Dec 2020 17:32:52 +0100 Subject: Fix T83504: Cancel trim operators when there is no geometry The boolean solver crashes when there is no geometry in the mesh. Also, using the trimming tools without a valid intersection in the PBVH will make the orientation and position functionality of the trimming shape not work, so this is the safer solution. Reviewed By: mont29 Maniphest Tasks: T83504 Differential Revision: https://developer.blender.org/D9777 --- source/blender/editors/sculpt_paint/paint_mask.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'source/blender') diff --git a/source/blender/editors/sculpt_paint/paint_mask.c b/source/blender/editors/sculpt_paint/paint_mask.c index 17690757fa5..92c78a674f0 100644 --- a/source/blender/editors/sculpt_paint/paint_mask.c +++ b/source/blender/editors/sculpt_paint/paint_mask.c @@ -1552,6 +1552,11 @@ static int sculpt_trim_gesture_box_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } + if (ss->totvert == 0) { + /* No geometry to trim or to detect a valid position for the trimming shape. */ + return OPERATOR_CANCELLED; + } + SculptGestureContext *sgcontext = sculpt_gesture_init_from_box(C, op); if (!sgcontext) { return OPERATOR_CANCELLED; @@ -1589,6 +1594,11 @@ static int sculpt_trim_gesture_lasso_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } + if (ss->totvert == 0) { + /* No geometry to trim or to detect a valid position for the trimming shape. */ + return OPERATOR_CANCELLED; + } + SculptGestureContext *sgcontext = sculpt_gesture_init_from_lasso(C, op); if (!sgcontext) { return OPERATOR_CANCELLED; -- cgit v1.2.3 From c9b4d75336271fd0427f47a43f3bf4cb525c5252 Mon Sep 17 00:00:00 2001 From: Pablo Dobarro Date: Mon, 14 Dec 2020 17:22:20 +0100 Subject: Sculpt: Fair Face Sets operation for Face Set Edit This implements a mesh fairing algorithm and implements the fair operations for Face Set edit. This edit operations create a smooth as possible geometry patch in the area of the selected Face Set. The mesh fairing algorithm is designed by Brett Fedack for the addon "Mesh Fairing": https://github.com/fedackb/mesh-fairing, with some modifications: - The main fairing function in BKE_mesh_fair.h does not triangulate the mesh. For the test I did in sculpt mode results are good enough without triangulating the topology. Depending on the use and the result quality needed for a particular tool, the mesh can be triangulate in the affected area before starting fairing. - Cotangents loop weights are not implemented yet. The idea is to also expose the vertex and loop weights in a different function in case a tool needs to set up custom weights. This algorithm will also be used to solve the limitations of line project and implement the Lasso Project and Polyline Project tools. It can also be used in tools in other areas of Blender, like Edit Mode or future retopology tools. Reviewed By: brecht Differential Revision: https://developer.blender.org/D9603 --- source/blender/blenkernel/BKE_mesh_fair.h | 56 +++ source/blender/blenkernel/CMakeLists.txt | 3 + source/blender/blenkernel/intern/mesh_fair.cc | 505 +++++++++++++++++++++ source/blender/editors/sculpt_paint/CMakeLists.txt | 1 + .../blender/editors/sculpt_paint/sculpt_face_set.c | 91 +++- 5 files changed, 655 insertions(+), 1 deletion(-) create mode 100644 source/blender/blenkernel/BKE_mesh_fair.h create mode 100644 source/blender/blenkernel/intern/mesh_fair.cc (limited to 'source/blender') diff --git a/source/blender/blenkernel/BKE_mesh_fair.h b/source/blender/blenkernel/BKE_mesh_fair.h new file mode 100644 index 00000000000..2d5c85d4129 --- /dev/null +++ b/source/blender/blenkernel/BKE_mesh_fair.h @@ -0,0 +1,56 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Mesh Fairing algorithm designed by Brett Fedack, used in the addon "Mesh Fairing": + * https://github.com/fedackb/mesh-fairing. + */ + +#pragma once + +/** \file + * \ingroup bke + */ + +#include "BLI_utildefines.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Mesh Fairing. */ +/* Creates a smooth as possible geometry patch in a defined area. Different values of depth allow + * to minimize changes in the vertex positions or tangency in the affected area. */ + +typedef enum eMeshFairingDepth { + MESH_FAIRING_DEPTH_POSITION = 1, + MESH_FAIRING_DEPTH_TANGENCY = 2, +} eMeshFairingDepth; + +/* affect_vertices is used to define the fairing area. Indexed by vertex index, set to true when + * the vertex should be modified by fairing. */ +void BKE_bmesh_prefair_and_fair_vertices(struct BMesh *bm, + bool *affect_vertices, + const eMeshFairingDepth depth); + +/* This function can optionally use the MVert coordinates of deform_mverts to read and write the + * fairing result. When NULL, the function will use mesh->mverts directly. */ +void BKE_mesh_prefair_and_fair_vertices(struct Mesh *mesh, + struct MVert *deform_mverts, + bool *affect_vertices, + const eMeshFairingDepth depth); + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index 0067e1c8209..ae0a180311c 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -42,6 +42,7 @@ set(INC ../simulation ../../../intern/ghost ../../../intern/glew-mx + ../../../intern/eigen ../../../intern/guardedalloc ../../../intern/iksolver/extern ../../../intern/atomic @@ -170,6 +171,7 @@ set(SRC intern/mesh.c intern/mesh_convert.c intern/mesh_evaluate.c + intern/mesh_fair.cc intern/mesh_iterators.c intern/mesh_mapping.c intern/mesh_merge.c @@ -353,6 +355,7 @@ set(SRC BKE_mball_tessellate.h BKE_mesh.h BKE_mesh_iterators.h + BKE_mesh_fair.h BKE_mesh_mapping.h BKE_mesh_mirror.h BKE_mesh_remap.h diff --git a/source/blender/blenkernel/intern/mesh_fair.cc b/source/blender/blenkernel/intern/mesh_fair.cc new file mode 100644 index 00000000000..527288d06cf --- /dev/null +++ b/source/blender/blenkernel/intern/mesh_fair.cc @@ -0,0 +1,505 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Mesh Fairing algorithm designed by Brett Fedack, used in the addon "Mesh Fairing": + * https://github.com/fedackb/mesh-fairing. + */ + +/** \file + * \ingroup bke + */ + +#include "BLI_map.hh" +#include "BLI_math.h" +#include "BLI_vector.hh" + +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_object_types.h" + +#include "BKE_lib_id.h" +#include "BKE_lib_query.h" +#include "BKE_mesh.h" +#include "BKE_mesh_fair.h" +#include "BKE_mesh_mapping.h" + +#include "bmesh.h" +#include "bmesh_tools.h" + +#include "MEM_guardedalloc.h" +#include "eigen_capi.h" + +using blender::Map; +using blender::Vector; +using std::array; + +class VertexWeight { + public: + virtual float weight_at_index(const int index) = 0; + virtual ~VertexWeight() = default; +}; + +class LoopWeight { + public: + virtual float weight_at_index(const int index) = 0; + virtual ~LoopWeight() = default; +}; + +class FairingContext { + public: + /* Get coordinates of vertices which are adjacent to the loop with specified index. */ + virtual void adjacents_coords_from_loop(const int loop, + float r_adj_next[3], + float r_adj_prev[3]) = 0; + + /* Get the other vertex index for a loop. */ + virtual int other_vertex_index_from_loop(const int loop, const unsigned int v) = 0; + + int vertex_count_get() + { + return totvert_; + } + + int loop_count_get() + { + return totvert_; + } + + MeshElemMap *vertex_loop_map_get(const int v) + { + return &vlmap_[v]; + } + + float *vertex_deformation_co_get(const int v) + { + return co_[v]; + } + + virtual ~FairingContext() = default; + + void fair_vertices(bool *affected, + const eMeshFairingDepth depth, + VertexWeight *vertex_weight, + LoopWeight *loop_weight) + { + + fair_vertices_ex(affected, (int)depth, vertex_weight, loop_weight); + } + + protected: + Vector co_; + + int totvert_; + int totloop_; + + MeshElemMap *vlmap_; + int *vlmap_mem_; + + private: + void fair_setup_fairing(const int v, + const int i, + LinearSolver *solver, + float multiplier, + const int depth, + Map &vert_col_map, + VertexWeight *vertex_weight, + LoopWeight *loop_weight) + { + if (depth == 0) { + if (vert_col_map.contains(v)) { + const int j = vert_col_map.lookup(v); + EIG_linear_solver_matrix_add(solver, i, j, -multiplier); + return; + } + for (int j = 0; j < 3; j++) { + EIG_linear_solver_right_hand_side_add(solver, j, i, multiplier * co_[v][j]); + } + return; + } + + float w_ij_sum = 0; + const float w_i = vertex_weight->weight_at_index(v); + MeshElemMap *vlmap_elem = &vlmap_[v]; + for (int l = 0; l < vlmap_elem->count; l++) { + const int l_index = vlmap_elem->indices[l]; + const int other_vert = other_vertex_index_from_loop(l_index, v); + const float w_ij = loop_weight->weight_at_index(l_index); + w_ij_sum += w_ij; + fair_setup_fairing(other_vert, + i, + solver, + w_i * w_ij * multiplier, + depth - 1, + vert_col_map, + vertex_weight, + loop_weight); + } + fair_setup_fairing(v, + i, + solver, + -1 * w_i * w_ij_sum * multiplier, + depth - 1, + vert_col_map, + vertex_weight, + loop_weight); + } + + void fair_vertices_ex(bool *affected, + const int order, + VertexWeight *vertex_weight, + LoopWeight *loop_weight) + { + Map vert_col_map; + int num_affected_vertices = 0; + for (int i = 0; i < totvert_; i++) { + if (!affected[i]) { + continue; + } + vert_col_map.add(i, num_affected_vertices); + num_affected_vertices++; + } + + /* Early return, nothing to do. */ + if (num_affected_vertices == 0 || num_affected_vertices == totvert_) { + return; + } + + /* Setup fairing matrices */ + LinearSolver *solver = EIG_linear_solver_new(num_affected_vertices, num_affected_vertices, 3); + for (auto item : vert_col_map.items()) { + const int v = item.key; + const int col = item.value; + fair_setup_fairing(v, col, solver, 1.0f, order, vert_col_map, vertex_weight, loop_weight); + } + + /* Solve linear system */ + EIG_linear_solver_solve(solver); + + /* Copy the result back to the mesh */ + for (auto item : vert_col_map.items()) { + const int v = item.key; + const int col = item.value; + for (int j = 0; j < 3; j++) { + co_[v][j] = EIG_linear_solver_variable_get(solver, j, col); + } + } + + /* Free solver data */ + EIG_linear_solver_delete(solver); + } +}; + +class MeshFairingContext : public FairingContext { + public: + MeshFairingContext(Mesh *mesh, MVert *deform_mverts) + { + totvert_ = mesh->totvert; + totloop_ = mesh->totloop; + + medge_ = mesh->medge; + mpoly_ = mesh->mpoly; + mloop_ = mesh->mloop; + BKE_mesh_vert_loop_map_create(&vlmap_, + &vlmap_mem_, + mesh->mpoly, + mesh->mloop, + mesh->totvert, + mesh->totpoly, + mesh->totloop); + + /* Deformation coords. */ + co_.reserve(mesh->totvert); + if (deform_mverts) { + for (int i = 0; i < mesh->totvert; i++) { + co_[i] = deform_mverts[i].co; + } + } + else { + for (int i = 0; i < mesh->totvert; i++) { + co_[i] = mesh->mvert[i].co; + } + } + + loop_to_poly_map_.reserve(mesh->totloop); + for (int i = 0; i < mesh->totpoly; i++) { + for (int l = 0; l < mesh->mpoly[i].totloop; l++) { + loop_to_poly_map_[l + mesh->mpoly[i].loopstart] = i; + } + } + } + + ~MeshFairingContext() + { + MEM_SAFE_FREE(vlmap_); + MEM_SAFE_FREE(vlmap_mem_); + } + + virtual void adjacents_coords_from_loop(const int loop, + float r_adj_next[3], + float r_adj_prev[3]) override + { + const int vert = mloop_[loop].v; + const MPoly *p = &mpoly_[loop_to_poly_map_[loop]]; + const int corner = poly_find_loop_from_vert(p, &mloop_[p->loopstart], vert); + copy_v3_v3(r_adj_next, co_[ME_POLY_LOOP_NEXT(mloop_, p, corner)->v]); + copy_v3_v3(r_adj_prev, co_[ME_POLY_LOOP_PREV(mloop_, p, corner)->v]); + } + + virtual int other_vertex_index_from_loop(const int loop, const unsigned int v) override + { + MEdge *e = &medge_[mloop_[loop].e]; + if (e->v1 == v) { + return e->v2; + } + return e->v1; + } + + protected: + Mesh *mesh_; + MLoop *mloop_; + MPoly *mpoly_; + MEdge *medge_; + Vector loop_to_poly_map_; +}; + +class BMeshFairingContext : public FairingContext { + public: + BMeshFairingContext(BMesh *bm) + { + this->bm = bm; + totvert_ = bm->totvert; + totloop_ = bm->totloop; + + BM_mesh_elem_table_ensure(bm, BM_VERT); + BM_mesh_elem_index_ensure(bm, BM_LOOP); + + /* Deformation coords. */ + co_.reserve(bm->totvert); + for (int i = 0; i < bm->totvert; i++) { + BMVert *v = BM_vert_at_index(bm, i); + co_[i] = v->co; + } + + bmloop_.reserve(bm->totloop); + vlmap_ = (MeshElemMap *)MEM_calloc_arrayN(sizeof(MeshElemMap), bm->totvert, "bmesh loop map"); + vlmap_mem_ = (int *)MEM_malloc_arrayN(sizeof(int), bm->totloop, "bmesh loop map mempool"); + + BMVert *v; + BMLoop *l; + BMIter iter; + BMIter loop_iter; + int index_iter = 0; + + /* This initializes both the bmloop and the vlmap for bmesh in a single loop. */ + BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + int loop_count = 0; + const int vert_index = BM_elem_index_get(v); + vlmap_[vert_index].indices = &vlmap_mem_[index_iter]; + BM_ITER_ELEM (l, &loop_iter, v, BM_LOOPS_OF_VERT) { + const int loop_index = BM_elem_index_get(l); + bmloop_[loop_index] = l; + vlmap_mem_[index_iter] = loop_index; + index_iter++; + loop_count++; + } + vlmap_[vert_index].count = loop_count; + } + } + + ~BMeshFairingContext() + { + MEM_SAFE_FREE(vlmap_); + MEM_SAFE_FREE(vlmap_mem_); + } + + virtual void adjacents_coords_from_loop(const int loop, + float r_adj_next[3], + float r_adj_prev[3]) override + { + copy_v3_v3(r_adj_next, bmloop_[loop]->next->v->co); + copy_v3_v3(r_adj_prev, bmloop_[loop]->prev->v->co); + } + + virtual int other_vertex_index_from_loop(const int loop, const unsigned int v) override + { + BMLoop *l = bmloop_[loop]; + BMVert *bmvert = BM_vert_at_index(bm, v); + BMVert *bm_other_vert = BM_edge_other_vert(l->e, bmvert); + return BM_elem_index_get(bm_other_vert); + } + + protected: + BMesh *bm; + Vector bmloop_; +}; + +class UniformVertexWeight : public VertexWeight { + public: + UniformVertexWeight(FairingContext *fairing_context) + { + const int totvert = fairing_context->vertex_count_get(); + vertex_weights_.reserve(totvert); + for (int i = 0; i < totvert; i++) { + const int tot_loop = fairing_context->vertex_loop_map_get(i)->count; + if (tot_loop != 0) { + vertex_weights_[i] = 1.0f / tot_loop; + } + else { + vertex_weights_[i] = FLT_MAX; + } + } + } + ~UniformVertexWeight() = default; + + float weight_at_index(const int index) override + { + return vertex_weights_[index]; + } + + private: + Vector vertex_weights_; +}; + +class VoronoiVertexWeight : public VertexWeight { + + public: + VoronoiVertexWeight(FairingContext *fairing_context) + { + + const int totvert = fairing_context->vertex_count_get(); + vertex_weights_.reserve(totvert); + for (int i = 0; i < totvert; i++) { + + float area = 0.0f; + float a[3]; + copy_v3_v3(a, fairing_context->vertex_deformation_co_get(i)); + const float acute_threshold = M_PI_2; + + MeshElemMap *vlmap_elem = fairing_context->vertex_loop_map_get(i); + for (int l = 0; l < vlmap_elem->count; l++) { + const int l_index = vlmap_elem->indices[l]; + + float b[3], c[3], d[3]; + fairing_context->adjacents_coords_from_loop(l_index, b, c); + + if (angle_v3v3v3(c, fairing_context->vertex_deformation_co_get(i), b) < acute_threshold) { + calc_circumcenter(d, a, b, c); + } + else { + add_v3_v3v3(d, b, c); + mul_v3_fl(d, 0.5f); + } + + float t[3]; + add_v3_v3v3(t, a, b); + mul_v3_fl(t, 0.5f); + area += area_tri_v3(a, t, d); + + add_v3_v3v3(t, a, c); + mul_v3_fl(t, 0.5f); + area += area_tri_v3(a, d, t); + } + + vertex_weights_[i] = area != 0.0f ? 1.0f / area : 1e12; + } + } + ~VoronoiVertexWeight() = default; + + float weight_at_index(const int index) override + { + return vertex_weights_[index]; + } + + private: + Vector vertex_weights_; + + void calc_circumcenter(float r[3], const float a[3], const float b[3], const float c[3]) + { + float ab[3]; + sub_v3_v3v3(ab, b, a); + + float ac[3]; + sub_v3_v3v3(ac, c, a); + + float ab_cross_ac[3]; + cross_v3_v3v3(ab_cross_ac, ab, ac); + + if (len_squared_v3(ab_cross_ac) > 0.0f) { + float d[3]; + cross_v3_v3v3(d, ab_cross_ac, ab); + mul_v3_fl(d, len_squared_v3(ac)); + + float t[3]; + cross_v3_v3v3(t, ac, ab_cross_ac); + mul_v3_fl(t, len_squared_v3(ab)); + + add_v3_v3(d, t); + + mul_v3_fl(d, 1.0f / (2.0f * len_squared_v3(ab_cross_ac))); + + add_v3_v3v3(r, a, d); + return; + } + copy_v3_v3(r, a); + } +}; + +class UniformLoopWeight : public LoopWeight { + public: + float weight_at_index(const int UNUSED(index)) override + { + return 1.0f; + } +}; + +static void prefair_and_fair_vertices(FairingContext *fairing_context, + bool *affected_vertices, + const eMeshFairingDepth depth) +{ + /* Prefair. */ + UniformVertexWeight *uniform_vertex_weights = new UniformVertexWeight(fairing_context); + UniformLoopWeight *uniform_loop_weights = new UniformLoopWeight(); + fairing_context->fair_vertices( + affected_vertices, depth, uniform_vertex_weights, uniform_loop_weights); + delete uniform_vertex_weights; + + /* Fair. */ + VoronoiVertexWeight *voronoi_vertex_weights = new VoronoiVertexWeight(fairing_context); + /* TODO: Implemente cotangent loop weights. */ + fairing_context->fair_vertices( + affected_vertices, depth, voronoi_vertex_weights, uniform_loop_weights); + + delete uniform_loop_weights; + delete voronoi_vertex_weights; +} + +void BKE_mesh_prefair_and_fair_vertices(struct Mesh *mesh, + struct MVert *deform_mverts, + bool *affect_vertices, + const eMeshFairingDepth depth) +{ + MeshFairingContext *fairing_context = new MeshFairingContext(mesh, deform_mverts); + prefair_and_fair_vertices(fairing_context, affect_vertices, depth); + delete fairing_context; +} + +void BKE_bmesh_prefair_and_fair_vertices(struct BMesh *bm, + bool *affect_vertices, + const eMeshFairingDepth depth) +{ + BMeshFairingContext *fairing_context = new BMeshFairingContext(bm); + prefair_and_fair_vertices(fairing_context, affect_vertices, depth); + delete fairing_context; +} diff --git a/source/blender/editors/sculpt_paint/CMakeLists.txt b/source/blender/editors/sculpt_paint/CMakeLists.txt index 9bf3d2610d8..fff8d27ef5b 100644 --- a/source/blender/editors/sculpt_paint/CMakeLists.txt +++ b/source/blender/editors/sculpt_paint/CMakeLists.txt @@ -32,6 +32,7 @@ set(INC ../../windowmanager ../../../../intern/atomic ../../../../intern/clog + ../../../../intern/eigen ../../../../intern/glew-mx ../../../../intern/guardedalloc ) diff --git a/source/blender/editors/sculpt_paint/sculpt_face_set.c b/source/blender/editors/sculpt_paint/sculpt_face_set.c index ad42750bb92..1fba958d695 100644 --- a/source/blender/editors/sculpt_paint/sculpt_face_set.c +++ b/source/blender/editors/sculpt_paint/sculpt_face_set.c @@ -41,6 +41,7 @@ #include "BKE_context.h" #include "BKE_customdata.h" #include "BKE_mesh.h" +#include "BKE_mesh_fair.h" #include "BKE_mesh_mapping.h" #include "BKE_multires.h" #include "BKE_node.h" @@ -1024,6 +1025,8 @@ typedef enum eSculptFaceSetEditMode { SCULPT_FACE_SET_EDIT_GROW = 0, SCULPT_FACE_SET_EDIT_SHRINK = 1, SCULPT_FACE_SET_EDIT_DELETE_GEOMETRY = 2, + SCULPT_FACE_SET_EDIT_FAIR_POSITIONS = 3, + SCULPT_FACE_SET_EDIT_FAIR_TANGENCY = 4, } eSculptFaceSetEditMode; static EnumPropertyItem prop_sculpt_face_sets_edit_types[] = { @@ -1048,6 +1051,22 @@ static EnumPropertyItem prop_sculpt_face_sets_edit_types[] = { "Delete Geometry", "Deletes the faces that are assigned to the Face Set", }, + { + SCULPT_FACE_SET_EDIT_FAIR_POSITIONS, + "FAIR_POSITIONS", + 0, + "Fair Positions", + "Creates a smooth as possible geometry patch from the Face Set minimizing changes in " + "vertex positions", + }, + { + SCULPT_FACE_SET_EDIT_FAIR_TANGENCY, + "FAIR_TANGENCY", + 0, + "Fair Tangency", + "Creates a smooth as possible geometry patch from the Face Set minimizing changes in " + "vertex tangents", + }, {0, NULL, 0, NULL, NULL}, }; @@ -1181,6 +1200,29 @@ static void sculpt_face_set_delete_geometry(Object *ob, BM_mesh_free(bm); } +static void sculpt_face_set_edit_fair_face_set(Object *ob, + const int active_face_set_id, + const int fair_order) +{ + SculptSession *ss = ob->sculpt; + const int totvert = SCULPT_vertex_count_get(ss); + + Mesh *mesh = ob->data; + bool *fair_vertices = MEM_malloc_arrayN(sizeof(bool), totvert, "fair vertices"); + + SCULPT_boundary_info_ensure(ob); + + for (int i = 0; i < totvert; i++) { + fair_vertices[i] = !SCULPT_vertex_is_boundary(ss, i) && + SCULPT_vertex_has_face_set(ss, i, active_face_set_id) && + SCULPT_vertex_has_unique_face_set(ss, i); + } + + MVert *mvert = SCULPT_mesh_deformed_mverts_get(ss); + BKE_mesh_prefair_and_fair_vertices(mesh, mvert, fair_vertices, fair_order); + MEM_freeN(fair_vertices); +} + static void sculpt_face_set_apply_edit(Object *ob, const int active_face_set_id, const int mode, @@ -1204,6 +1246,12 @@ static void sculpt_face_set_apply_edit(Object *ob, case SCULPT_FACE_SET_EDIT_DELETE_GEOMETRY: sculpt_face_set_delete_geometry(ob, ss, active_face_set_id, modify_hidden); break; + case SCULPT_FACE_SET_EDIT_FAIR_POSITIONS: + sculpt_face_set_edit_fair_face_set(ob, active_face_set_id, MESH_FAIRING_DEPTH_POSITION); + break; + case SCULPT_FACE_SET_EDIT_FAIR_TANGENCY: + sculpt_face_set_edit_fair_face_set(ob, active_face_set_id, MESH_FAIRING_DEPTH_TANGENCY); + break; } } @@ -1230,6 +1278,16 @@ static bool sculpt_face_set_edit_is_operation_valid(SculptSession *ss, return false; } } + + if (ELEM(mode, SCULPT_FACE_SET_EDIT_FAIR_POSITIONS, SCULPT_FACE_SET_EDIT_FAIR_TANGENCY)) { + if (BKE_pbvh_type(ss->pbvh) == PBVH_GRIDS) { + /* TODO: Multires topology representation using grids and duplicates can't be used directly + * by the fair algorithm. Multires topology needs to be exposed in a different way or + * converted to a mesh for this operation. */ + return false; + } + } + return true; } @@ -1287,11 +1345,38 @@ static void sculpt_face_set_edit_modify_face_sets(Object *ob, MEM_freeN(nodes); } +static void sculpt_face_set_edit_modify_coordinates(bContext *C, + Object *ob, + const int active_face_set, + const eSculptFaceSetEditMode mode) +{ + Sculpt *sd = CTX_data_tool_settings(C)->sculpt; + SculptSession *ss = ob->sculpt; + PBVH *pbvh = ss->pbvh; + PBVHNode **nodes; + int totnode; + BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode); + SCULPT_undo_push_begin(ob, "face set edit"); + for (int i = 0; i < totnode; i++) { + BKE_pbvh_node_mark_update(nodes[i]); + SCULPT_undo_push_node(ob, nodes[i], SCULPT_UNDO_COORDS); + } + sculpt_face_set_apply_edit(ob, abs(active_face_set), mode, false); + + if (ss->deform_modifiers_active || ss->shapekey_active) { + SCULPT_flush_stroke_deform(sd, ob, true); + } + SCULPT_flush_update_step(C, SCULPT_UPDATE_COORDS); + SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_COORDS); + SCULPT_undo_push_end(); + MEM_freeN(nodes); +} + static int sculpt_face_set_edit_invoke(bContext *C, wmOperator *op, const wmEvent *event) { Object *ob = CTX_data_active_object(C); SculptSession *ss = ob->sculpt; - Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); + Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); const int mode = RNA_enum_get(op->ptr, "mode"); const bool modify_hidden = RNA_boolean_get(op->ptr, "modify_hidden"); @@ -1320,6 +1405,10 @@ static int sculpt_face_set_edit_invoke(bContext *C, wmOperator *op, const wmEven case SCULPT_FACE_SET_EDIT_SHRINK: sculpt_face_set_edit_modify_face_sets(ob, active_face_set, mode, modify_hidden); break; + case SCULPT_FACE_SET_EDIT_FAIR_POSITIONS: + case SCULPT_FACE_SET_EDIT_FAIR_TANGENCY: + sculpt_face_set_edit_modify_coordinates(C, ob, active_face_set, mode); + break; } SCULPT_tag_update_overlays(C); -- cgit v1.2.3 From 1e799dd26ec1e8487d61f7cdfb592dc86881df18 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Tue, 15 Dec 2020 21:20:57 +0100 Subject: Fix various issues with temporary, maximized File Browsers If Preferences > Interface > Temporary Editors > File Browser is set to "Maximized Area", opening a File Browser from a File or Asset Browser as regular editor would cause some issues. For example after closing the temporary File Browser, the regular browser would take over the file path and display settings from the temporary one. This is because they used to share the same area data. Some similar issues may have happend with temporary image editors. Now, this commit finally separates the space data of temporary maximized editors from the regular ones. So the editor data is entirely independent now, as it should be. --- source/blender/editors/include/ED_screen.h | 1 + source/blender/editors/screen/screen_edit.c | 187 ++++++++++++++++------------ 2 files changed, 111 insertions(+), 77 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h index dc1c43c0337..20417634020 100644 --- a/source/blender/editors/include/ED_screen.h +++ b/source/blender/editors/include/ED_screen.h @@ -239,6 +239,7 @@ void ED_screen_restore_temp_type(struct bContext *C, ScrArea *area); ScrArea *ED_screen_full_newspace(struct bContext *C, ScrArea *area, int type); void ED_screen_full_prevspace(struct bContext *C, ScrArea *area); void ED_screen_full_restore(struct bContext *C, ScrArea *area); +ScrArea *ED_screen_state_maximized_create(struct bContext *C); struct ScrArea *ED_screen_state_toggle(struct bContext *C, struct wmWindow *win, struct ScrArea *area, diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c index c3dcaefab79..be52874ed0b 100644 --- a/source/blender/editors/screen/screen_edit.c +++ b/source/blender/editors/screen/screen_edit.c @@ -1133,12 +1133,11 @@ void ED_screen_scene_change(bContext *C, wmWindow *win, Scene *scene) ScrArea *ED_screen_full_newspace(bContext *C, ScrArea *area, int type) { - wmWindow *win = CTX_wm_window(C); ScrArea *newsa = NULL; SpaceLink *newsl; if (!area || area->full == NULL) { - newsa = ED_screen_state_toggle(C, win, area, SCREENMAXIMIZED); + newsa = ED_screen_state_maximized_create(C); } if (!newsa) { @@ -1149,11 +1148,11 @@ ScrArea *ED_screen_full_newspace(bContext *C, ScrArea *area, int type) newsl = newsa->spacedata.first; /* Tag the active space before changing, so we can identify it when user wants to go back. */ - if ((newsl->link_flag & SPACE_FLAG_TYPE_TEMPORARY) == 0) { + if (newsl && (newsl->link_flag & SPACE_FLAG_TYPE_TEMPORARY) == 0) { newsl->link_flag |= SPACE_FLAG_TYPE_WAS_ACTIVE; } - ED_area_newspace(C, newsa, type, newsl->link_flag & SPACE_FLAG_TYPE_TEMPORARY); + ED_area_newspace(C, newsa, type, (newsl && newsl->link_flag & SPACE_FLAG_TYPE_TEMPORARY)); return newsa; } @@ -1217,13 +1216,108 @@ void ED_screen_full_restore(bContext *C, ScrArea *area) } /** - * this function toggles: if area is maximized/full then the parent will be restored + * \param toggle_area: If this is set, its space data will be swapped with the one of the new emtpy + * area, when toggling back it can be swapped back again. + * \return The newly created screen with the non-normal area. + */ +static bScreen *screen_state_to_nonnormal(bContext *C, + wmWindow *win, + ScrArea *toggle_area, + int state) +{ + Main *bmain = CTX_data_main(C); + WorkSpace *workspace = WM_window_get_active_workspace(win); + + /* change from SCREENNORMAL to new state */ + WorkSpaceLayout *layout_new; + ScrArea *newa; + char newname[MAX_ID_NAME - 2]; + + BLI_assert(ELEM(state, SCREENMAXIMIZED, SCREENFULL)); + + bScreen *oldscreen = WM_window_get_active_screen(win); + + oldscreen->state = state; + BLI_snprintf(newname, sizeof(newname), "%s-%s", oldscreen->id.name + 2, "nonnormal"); + + layout_new = ED_workspace_layout_add(bmain, workspace, win, newname); + + bScreen *screen = BKE_workspace_layout_screen_get(layout_new); + screen->state = state; + screen->redraws_flag = oldscreen->redraws_flag; + screen->temp = oldscreen->temp; + screen->flag = oldscreen->flag; + + /* timer */ + screen->animtimer = oldscreen->animtimer; + oldscreen->animtimer = NULL; + + newa = (ScrArea *)screen->areabase.first; + + /* swap area */ + if (toggle_area) { + ED_area_data_swap(newa, toggle_area); + newa->flag = toggle_area->flag; /* mostly for AREA_FLAG_WASFULLSCREEN */ + } + + if (state == SCREENFULL) { + /* temporarily hide global areas */ + LISTBASE_FOREACH (ScrArea *, glob_area, &win->global_areas.areabase) { + glob_area->global->flag |= GLOBAL_AREA_IS_HIDDEN; + } + /* temporarily hide the side panels/header */ + LISTBASE_FOREACH (ARegion *, region, &newa->regionbase) { + region->flagfullscreen = region->flag; + + if (ELEM(region->regiontype, + RGN_TYPE_UI, + RGN_TYPE_HEADER, + RGN_TYPE_TOOL_HEADER, + RGN_TYPE_FOOTER, + RGN_TYPE_TOOLS, + RGN_TYPE_NAV_BAR, + RGN_TYPE_EXECUTE)) { + region->flag |= RGN_FLAG_HIDDEN; + } + } + } + + if (toggle_area) { + toggle_area->full = oldscreen; + } + newa->full = oldscreen; + + ED_screen_change(C, screen); + ED_area_tag_refresh(newa); + + return screen; +} + +/** + * Create a new temporary screen with a maximized, empty area. + * This can be closed with #ED_screen_state_toggle(). + * + * Use this to just create a new maximized screen/area, rather than maximizing an existing one. + * Otherwise, maximize with #ED_screen_state_toggle(). + */ +ScrArea *ED_screen_state_maximized_create(bContext *C) +{ + bScreen *screen = screen_state_to_nonnormal(C, CTX_wm_window(C), NULL, SCREENMAXIMIZED); + return screen->areabase.first; +} + +/** + * This function toggles: if area is maximized/full then the parent will be restored. + * + * Use #ED_screen_state_maximized_create() if you do not want the toggle behavior when changing to + * a maximized area. I.e. if you just want to open a new maximized screen/area, not maximize a + * specific area. In the former case, space data of the maximized and non-maximized area should be + * independent, in the latter it should be the same. * * \warning \a area may be freed. */ ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *area, const short state) { - Main *bmain = CTX_data_main(C); wmWindowManager *wm = CTX_wm_manager(C); WorkSpace *workspace = WM_window_get_active_workspace(win); @@ -1257,7 +1351,7 @@ ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *area, const screen->state = SCREENNORMAL; screen->flag = oldscreen->flag; - /* find old area to restore from */ + /* Find old area we may have swapped dummy space data to. It's swapped back here. */ ScrArea *fullsa = NULL; LISTBASE_FOREACH (ScrArea *, old, &screen->areabase) { /* area to restore from is always first */ @@ -1271,13 +1365,6 @@ ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *area, const area->full = NULL; - if (fullsa == NULL) { - if (G.debug & G_DEBUG) { - printf("%s: something wrong in areafullscreen\n", __func__); - } - return NULL; - } - if (state == SCREENFULL) { /* unhide global areas */ LISTBASE_FOREACH (ScrArea *, glob_area, &win->global_areas.areabase) { @@ -1289,14 +1376,16 @@ ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *area, const } } - ED_area_data_swap(fullsa, area); + if (fullsa) { + ED_area_data_swap(fullsa, area); + ED_area_tag_refresh(fullsa); + } /* animtimer back */ screen->animtimer = oldscreen->animtimer; oldscreen->animtimer = NULL; ED_screen_change(C, screen); - ED_area_tag_refresh(fullsa); BKE_workspace_layout_remove(CTX_data_main(C), workspace, layout_old); @@ -1307,69 +1396,16 @@ ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *area, const screen->skip_handling = true; } else { - /* change from SCREENNORMAL to new state */ - WorkSpaceLayout *layout_new; - ScrArea *newa; - char newname[MAX_ID_NAME - 2]; - - BLI_assert(ELEM(state, SCREENMAXIMIZED, SCREENFULL)); - - bScreen *oldscreen = WM_window_get_active_screen(win); - - oldscreen->state = state; - BLI_snprintf(newname, sizeof(newname), "%s-%s", oldscreen->id.name + 2, "nonnormal"); - - layout_new = ED_workspace_layout_add(bmain, workspace, win, newname); - - screen = BKE_workspace_layout_screen_get(layout_new); - screen->state = state; - screen->redraws_flag = oldscreen->redraws_flag; - screen->temp = oldscreen->temp; - screen->flag = oldscreen->flag; - - /* timer */ - screen->animtimer = oldscreen->animtimer; - oldscreen->animtimer = NULL; + ScrArea *toggle_area = area; /* use random area when we have no active one, e.g. when the * mouse is outside of the window and we open a file browser */ - if (!area || area->global) { - area = oldscreen->areabase.first; + if (!toggle_area || toggle_area->global) { + bScreen *oldscreen = WM_window_get_active_screen(win); + toggle_area = oldscreen->areabase.first; } - newa = (ScrArea *)screen->areabase.first; - - /* copy area */ - ED_area_data_swap(newa, area); - newa->flag = area->flag; /* mostly for AREA_FLAG_WASFULLSCREEN */ - - if (state == SCREENFULL) { - /* temporarily hide global areas */ - LISTBASE_FOREACH (ScrArea *, glob_area, &win->global_areas.areabase) { - glob_area->global->flag |= GLOBAL_AREA_IS_HIDDEN; - } - /* temporarily hide the side panels/header */ - LISTBASE_FOREACH (ARegion *, region, &newa->regionbase) { - region->flagfullscreen = region->flag; - - if (ELEM(region->regiontype, - RGN_TYPE_UI, - RGN_TYPE_HEADER, - RGN_TYPE_TOOL_HEADER, - RGN_TYPE_FOOTER, - RGN_TYPE_TOOLS, - RGN_TYPE_NAV_BAR, - RGN_TYPE_EXECUTE)) { - region->flag |= RGN_FLAG_HIDDEN; - } - } - } - - area->full = oldscreen; - newa->full = oldscreen; - - ED_screen_change(C, screen); - ED_area_tag_refresh(newa); + screen = screen_state_to_nonnormal(C, win, toggle_area, state); } /* XXX bad code: setscreen() ends with first area active. fullscreen render assumes this too */ @@ -1413,9 +1449,6 @@ ScrArea *ED_screen_temp_space_open(bContext *C, area->flag |= AREA_FLAG_STACKED_FULLSCREEN; ((SpaceLink *)area->spacedata.first)->link_flag |= SPACE_FLAG_TYPE_TEMPORARY; } - else if (ctx_area != NULL && ctx_area->spacetype == space_type) { - area = ED_screen_state_toggle(C, CTX_wm_window(C), ctx_area, SCREENMAXIMIZED); - } else { area = ED_screen_full_newspace(C, ctx_area, (int)space_type); ((SpaceLink *)area->spacedata.first)->link_flag |= SPACE_FLAG_TYPE_TEMPORARY; -- cgit v1.2.3 From 7e8f6985d89866197be8465a8aec57f9b4ef7b51 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Tue, 15 Dec 2020 21:27:59 +0100 Subject: Fix crash selecting custom asset preview from maximized File Browser If Preferences > Interface > Temporary Editors > File Browser is set to "Maximized Area", "Load Custom Preview" in the Asset Browser would crash after selecting the file. 1e799dd26ec1e848 was important to get this issue fixed. This commit just ensures the file-list is recreated correctly after closing the temporary File Browser, so the custom preview operator can execute on valid context. --- source/blender/windowmanager/intern/wm_event_system.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source/blender') diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index ac27862d507..61624ad9d7c 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -2293,6 +2293,11 @@ static int wm_handler_fileselect_do(bContext *C, } wm_handler_op_context(C, handler, ctx_win->eventstate); + ScrArea *handler_area = CTX_wm_area(C); + /* Make sure new context area is ready, the operator callback may operate on it. */ + if (handler_area) { + ED_area_do_refresh(C, handler_area); + } /* Needed for #UI_popup_menu_reports. */ -- cgit v1.2.3 From 9e4a4c2e996c3741c2beaf5ed5aadc8cb8801ac3 Mon Sep 17 00:00:00 2001 From: Richard Antalik Date: Tue, 15 Dec 2020 21:42:06 +0100 Subject: VSE: Move remove gaps operator logic to module code Logic was broken into finding gaps and ofsetting strips. Functions were modified so they work on explicitly defined seqbase, so they can be used as python API functions. Functional changes: - Improve performance by calculating gap length and offseting strips at once. Previously strips were offset by one frame. - Calculate gap from start frame. Previously gap was considered only inbetween strips. Reviewed By: sergey Differential Revision: https://developer.blender.org/D9730 --- .../editors/space_sequencer/sequencer_draw.c | 2 +- .../editors/space_sequencer/sequencer_edit.c | 116 ++------------------- .../editors/space_sequencer/sequencer_intern.h | 1 - .../editors/space_sequencer/sequencer_view.c | 8 +- source/blender/sequencer/SEQ_sequencer.h | 29 +++++- source/blender/sequencer/intern/render.c | 17 +-- source/blender/sequencer/intern/strip_edit.c | 35 +++++++ source/blender/sequencer/intern/strip_time.c | 84 +++++++++++++++ source/blender/sequencer/intern/strip_time.h | 12 +++ source/blender/sequencer/intern/strip_transform.c | 30 ++++++ 10 files changed, 212 insertions(+), 122 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index 081714991ff..e31fa3205ba 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -2292,7 +2292,7 @@ void draw_timeline_seq(const bContext *C, ARegion *region) UI_view2d_view_ortho(v2d); /* Get timeline bound-box, needed for the scroll-bars. */ - boundbox_seq(scene, &v2d->tot); + SEQ_timeline_boundbox(scene, ed->seqbasep, &v2d->tot); draw_seq_backdrop(v2d); UI_view2d_constant_grid_draw(v2d, FPS); diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c index 953a77d22a6..184f821d411 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.c +++ b/source/blender/editors/space_sequencer/sequencer_edit.c @@ -183,117 +183,13 @@ bool sequencer_view_strips_poll(bContext *C) /** \name Remove Gaps Operator * \{ */ -static bool sequence_offset_after_frame(Scene *scene, const int delta, const int timeline_frame) -{ - Sequence *seq; - Editing *ed = BKE_sequencer_editing_get(scene, false); - bool done = false; - TimeMarker *marker; - - /* All strips >= timeline_frame are shifted. */ - - if (ed == NULL) { - return 0; - } - - for (seq = ed->seqbasep->first; seq; seq = seq->next) { - if (seq->startdisp >= timeline_frame) { - BKE_sequence_translate(scene, seq, delta); - BKE_sequence_calc(scene, seq); - BKE_sequence_invalidate_cache_preprocessed(scene, seq); - done = true; - } - } - - if (!scene->toolsettings->lock_markers) { - for (marker = scene->markers.first; marker; marker = marker->next) { - if (marker->frame >= timeline_frame) { - marker->frame += delta; - } - } - } - - return done; -} - -void boundbox_seq(Scene *scene, rctf *rect) -{ - Sequence *seq; - Editing *ed = BKE_sequencer_editing_get(scene, false); - float min[2], max[2]; - - if (ed == NULL) { - return; - } - - min[0] = SFRA; - max[0] = EFRA + 1; - min[1] = 0.0; - max[1] = 8.0; - - seq = ed->seqbasep->first; - while (seq) { - - if (min[0] > seq->startdisp - 1) { - min[0] = seq->startdisp - 1; - } - if (max[0] < seq->enddisp + 1) { - max[0] = seq->enddisp + 1; - } - if (max[1] < seq->machine + 2) { - max[1] = seq->machine + 2; - } - - seq = seq->next; - } - - rect->xmin = min[0]; - rect->xmax = max[0]; - rect->ymin = min[1]; - rect->ymax = max[1]; -} - static int sequencer_gap_remove_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); - rctf rectf; - int timeline_frame, efra, sfra; - bool first = false, done; - bool do_all = RNA_boolean_get(op->ptr, "all"); - - /* Get first and last frame. */ - boundbox_seq(scene, &rectf); - sfra = (int)rectf.xmin; - efra = (int)rectf.xmax; - - /* Check if the current frame has a gap already. */ - for (timeline_frame = CFRA; timeline_frame >= sfra; timeline_frame--) { - if (SEQ_render_evaluate_frame(scene, timeline_frame)) { - first = true; - break; - } - } + const bool do_all = RNA_boolean_get(op->ptr, "all"); + const Editing *ed = BKE_sequencer_editing_get(scene, false); - for (; timeline_frame < efra; timeline_frame++) { - /* There's still no strip to remove a gap for. */ - if (first == false) { - if (SEQ_render_evaluate_frame(scene, timeline_frame)) { - first = true; - } - } - else if (SEQ_render_evaluate_frame(scene, timeline_frame) == 0) { - done = true; - while (SEQ_render_evaluate_frame(scene, timeline_frame) == 0) { - done = sequence_offset_after_frame(scene, -1, timeline_frame); - if (done == false) { - break; - } - } - if (done == false || do_all == false) { - break; - } - } - } + SEQ_edit_remove_gaps(scene, ed->seqbasep, CFRA, do_all); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS); @@ -330,9 +226,9 @@ void SEQUENCER_OT_gap_remove(struct wmOperatorType *ot) static int sequencer_gap_insert_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); - int frames = RNA_int_get(op->ptr, "frames"); - - sequence_offset_after_frame(scene, frames, CFRA); + const int frames = RNA_int_get(op->ptr, "frames"); + const Editing *ed = BKE_sequencer_editing_get(scene, false); + SEQ_offset_after_frame(scene, ed->seqbasep, frames, CFRA); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); diff --git a/source/blender/editors/space_sequencer/sequencer_intern.h b/source/blender/editors/space_sequencer/sequencer_intern.h index 1ea4fb05d53..6ccfd3a9045 100644 --- a/source/blender/editors/space_sequencer/sequencer_intern.h +++ b/source/blender/editors/space_sequencer/sequencer_intern.h @@ -71,7 +71,6 @@ struct ImBuf *sequencer_ibuf_get(struct Main *bmain, /* sequencer_edit.c */ struct View2D; void seq_rectf(struct Sequence *seq, struct rctf *rectf); -void boundbox_seq(struct Scene *scene, struct rctf *rect); struct Sequence *find_nearest_seq(struct Scene *scene, struct View2D *v2d, int *hand, diff --git a/source/blender/editors/space_sequencer/sequencer_view.c b/source/blender/editors/space_sequencer/sequencer_view.c index 75d92d5f00d..d2166705943 100644 --- a/source/blender/editors/space_sequencer/sequencer_view.c +++ b/source/blender/editors/space_sequencer/sequencer_view.c @@ -87,8 +87,14 @@ static int sequencer_view_all_exec(bContext *C, wmOperator *op) rctf box; const int smooth_viewtx = WM_operator_smooth_viewtx_get(op); + Scene *scene = CTX_data_scene(C); + const Editing *ed = BKE_sequencer_editing_get(scene, false); + + if (ed == NULL) { + return OPERATOR_FINISHED; + } - boundbox_seq(CTX_data_scene(C), &box); + SEQ_timeline_boundbox(scene, ed->seqbasep, &box); UI_view2d_smooth_view(C, region, &box, smooth_viewtx); return OPERATOR_FINISHED; } diff --git a/source/blender/sequencer/SEQ_sequencer.h b/source/blender/sequencer/SEQ_sequencer.h index 11e213d842d..a024d5e10d3 100644 --- a/source/blender/sequencer/SEQ_sequencer.h +++ b/source/blender/sequencer/SEQ_sequencer.h @@ -161,7 +161,7 @@ void SEQ_render_new_render_data(struct Main *bmain, int preview_render_size, int for_render, SeqRenderData *r_context); -int SEQ_render_evaluate_frame(struct Scene *scene, int timeline_frame); +int SEQ_render_evaluate_frame(struct ListBase *seqbase, int timeline_frame); struct StripElem *SEQ_render_give_stripelem(struct Sequence *seq, int timeline_frame); /* ********************************************************************** @@ -595,6 +595,33 @@ struct Sequence *SEQ_edit_strip_split(struct Main *bmain, struct Sequence *seq, const int timeline_frame, const eSeqSplitMethod method); +bool SEQ_edit_remove_gaps(struct Scene *scene, + struct ListBase *seqbase, + const int initial_frame, + const bool remove_all_gaps); + +/* ********************************************************************** + * strip_time.c + * + * Editing functions + * ********************************************************************** + */ + +void SEQ_timeline_boundbox(const struct Scene *scene, + const struct ListBase *seqbase, + struct rctf *rect); + +/* ********************************************************************** + * strip_transform.c + * + * Editing functions + * ********************************************************************** + */ + +void SEQ_offset_after_frame(struct Scene *scene, + struct ListBase *seqbase, + const int delta, + const int timeline_frame); #ifdef __cplusplus } diff --git a/source/blender/sequencer/intern/render.c b/source/blender/sequencer/intern/render.c index 008ea1cd3a0..155258dc2c3 100644 --- a/source/blender/sequencer/intern/render.c +++ b/source/blender/sequencer/intern/render.c @@ -337,16 +337,17 @@ static int evaluate_seq_frame_gen(Sequence **seq_arr, return totseq; } -int SEQ_render_evaluate_frame(Scene *scene, int timeline_frame) +/** + * Count number of strips in timeline at timeline_frame + * + * \param seqbase: ListBase in which strips are located + * \param timeline_frame: frame on timeline from where gaps are searched for + * \return number of strips + */ +int SEQ_render_evaluate_frame(ListBase *seqbase, int timeline_frame) { - Editing *ed = BKE_sequencer_editing_get(scene, false); Sequence *seq_arr[MAXSEQ + 1]; - - if (ed == NULL) { - return 0; - } - - return evaluate_seq_frame_gen(seq_arr, ed->seqbasep, timeline_frame, 0); + return evaluate_seq_frame_gen(seq_arr, seqbase, timeline_frame, 0); } static bool video_seq_is_rendered(Sequence *seq) diff --git a/source/blender/sequencer/intern/strip_edit.c b/source/blender/sequencer/intern/strip_edit.c index 3137a471470..a29810cc9ee 100644 --- a/source/blender/sequencer/intern/strip_edit.c +++ b/source/blender/sequencer/intern/strip_edit.c @@ -38,6 +38,8 @@ #include "BKE_scene.h" #include "BKE_sound.h" +#include "strip_time.h" + #include "SEQ_sequencer.h" int BKE_sequence_swap(Sequence *seq_a, Sequence *seq_b, const char **error_str) @@ -319,3 +321,36 @@ Sequence *SEQ_edit_strip_split(Main *bmain, BKE_sequence_calc(scene, right_seq); return right_seq; } + +/** + * Find gap after initial_frame and move strips on right side to close the gap + * + * \param scene: Scene in which strips are located + * \param seqbase: ListBase in which strips are located + * \param initial_frame: frame on timeline from where gaps are searched for + * \param remove_all_gaps: remove all gaps instead of one gap + * \return true if gap is removed, otherwise false + */ +bool SEQ_edit_remove_gaps(Scene *scene, + ListBase *seqbase, + const int initial_frame, + const bool remove_all_gaps) +{ + GapInfo gap_info = {0}; + seq_time_gap_info_get(scene, seqbase, initial_frame, &gap_info); + + if (!gap_info.gap_exists) { + return false; + } + + if (remove_all_gaps) { + while (gap_info.gap_exists) { + SEQ_offset_after_frame(scene, seqbase, -gap_info.gap_length, gap_info.gap_start_frame); + seq_time_gap_info_get(scene, seqbase, initial_frame, &gap_info); + } + } + else { + SEQ_offset_after_frame(scene, seqbase, -gap_info.gap_length, gap_info.gap_start_frame); + } + return true; +} diff --git a/source/blender/sequencer/intern/strip_time.c b/source/blender/sequencer/intern/strip_time.c index a0ae6d6f16d..015d81cc217 100644 --- a/source/blender/sequencer/intern/strip_time.c +++ b/source/blender/sequencer/intern/strip_time.c @@ -351,3 +351,87 @@ float BKE_sequence_get_fps(Scene *scene, Sequence *seq) } return 0.0f; } + +/** + * Define boundary rectangle of sequencer timeline and fill in rect data + * + * \param scene: Scene in which strips are located + * \param seqbase: ListBase in which strips are located + * \param rect: data structure describing rectangle, that will be filled in by this function + */ +void SEQ_timeline_boundbox(const Scene *scene, const ListBase *seqbase, rctf *rect) +{ + float min[2], max[2]; + min[0] = scene->r.sfra; + max[0] = scene->r.efra + 1; + min[1] = 0.0; + max[1] = 8.0; + + LISTBASE_FOREACH (Sequence *, seq, seqbase) { + if (min[0] > seq->startdisp - 1) { + min[0] = seq->startdisp - 1; + } + if (max[0] < seq->enddisp + 1) { + max[0] = seq->enddisp + 1; + } + if (max[1] < seq->machine + 2) { + max[1] = seq->machine + 2; + } + } + + rect->xmin = min[0]; + rect->xmax = max[0]; + rect->ymin = min[1]; + rect->ymax = max[1]; +} + +/** + * Find first gap between strips after initial_frame and describe it by filling data of r_gap_info + * + * \param scene: Scene in which strips are located + * \param seqbase: ListBase in which strips are located + * \param initial_frame: frame on timeline from where gaps are searched for + * \param r_gap_info: data structure describing gap, that will be filled in by this function + */ +void seq_time_gap_info_get(const Scene *scene, + ListBase *seqbase, + const int initial_frame, + GapInfo *r_gap_info) +{ + rctf rectf; + /* Get first and last frame. */ + SEQ_timeline_boundbox(scene, seqbase, &rectf); + const int sfra = (int)rectf.xmin; + const int efra = (int)rectf.xmax; + int timeline_frame = initial_frame; + r_gap_info->gap_exists = false; + + if (SEQ_render_evaluate_frame(seqbase, initial_frame) == 0) { + /* Search backward for gap_start_frame. */ + for (; timeline_frame >= sfra; timeline_frame--) { + if (SEQ_render_evaluate_frame(seqbase, timeline_frame) != 0) { + break; + } + } + r_gap_info->gap_start_frame = timeline_frame + 1; + timeline_frame = initial_frame; + } + else { + /* Search forward for gap_start_frame. */ + for (; timeline_frame <= efra; timeline_frame++) { + if (SEQ_render_evaluate_frame(seqbase, timeline_frame) == 0) { + r_gap_info->gap_start_frame = timeline_frame; + break; + } + } + } + /* Search forward for gap_end_frame. */ + for (; timeline_frame <= efra; timeline_frame++) { + if (SEQ_render_evaluate_frame(seqbase, timeline_frame) != 0) { + const int gap_end_frame = timeline_frame; + r_gap_info->gap_length = gap_end_frame - r_gap_info->gap_start_frame; + r_gap_info->gap_exists = true; + break; + } + } +} diff --git a/source/blender/sequencer/intern/strip_time.h b/source/blender/sequencer/intern/strip_time.h index e4fb7f1d2ec..e435ff1ec5d 100644 --- a/source/blender/sequencer/intern/strip_time.h +++ b/source/blender/sequencer/intern/strip_time.h @@ -29,10 +29,22 @@ extern "C" { struct Scene; struct Sequence; +struct ListBase; float seq_give_frame_index(struct Sequence *seq, float timeline_frame); void seq_update_sound_bounds_recursive(struct Scene *scene, struct Sequence *metaseq); +/* Describes gap between strips in timeline. */ +typedef struct GapInfo { + int gap_start_frame; /* Start frame of the gap. */ + int gap_length; /* Length of the gap. */ + bool gap_exists; /* False if there are no gaps. */ +} GapInfo; +void seq_time_gap_info_get(const struct Scene *scene, + struct ListBase *seqbase, + const int initial_frame, + struct GapInfo *r_gap_info); + #ifdef __cplusplus } #endif diff --git a/source/blender/sequencer/intern/strip_transform.c b/source/blender/sequencer/intern/strip_transform.c index 233f8e5b22e..4aabe87bce1 100644 --- a/source/blender/sequencer/intern/strip_transform.c +++ b/source/blender/sequencer/intern/strip_transform.c @@ -397,3 +397,33 @@ bool BKE_sequence_base_shuffle_time(ListBase *seqbasep, return offset ? false : true; } + +/** + * Move strips and markers (if not locked) that start after timeline_frame by delta frames + * + * \param scene: Scene in which strips are located + * \param seqbase: ListBase in which strips are located + * \param delta: offset in frames to be applied + * \param timeline_frame: frame on timeline from where strips are moved + */ +void SEQ_offset_after_frame(Scene *scene, + ListBase *seqbase, + const int delta, + const int timeline_frame) +{ + LISTBASE_FOREACH (Sequence *, seq, seqbase) { + if (seq->startdisp >= timeline_frame) { + BKE_sequence_translate(scene, seq, delta); + BKE_sequence_calc(scene, seq); + BKE_sequence_invalidate_cache_preprocessed(scene, seq); + } + } + + if (!scene->toolsettings->lock_markers) { + LISTBASE_FOREACH (TimeMarker *, marker, &scene->markers) { + if (marker->frame >= timeline_frame) { + marker->frame += delta; + } + } + } +} -- cgit v1.2.3 From 5535b0b8878a84325b0f99ad10260e95433facc7 Mon Sep 17 00:00:00 2001 From: Cody Winchester Date: Tue, 15 Dec 2020 22:14:05 +0100 Subject: GPencil Array - Add option for uniform random scaling This patch adds the option to make the random scaling from the grease pencil array modifier uniform. The current settings allow a separate value for each of the 3 scaling axis. The modifier also creates different seed values for each axis so there is no way to keep the random scaling uniform. This patch creates 1 random seed value and applies it to each of the scaling axis. Here is a demonstration of the previous behavior and the new optional behavior. {F9485973} {F9485981} {F9485798} Reviewed By: #grease_pencil, antoniov, pepeland Differential Revision: https://developer.blender.org/D9764 --- .../blender/gpencil_modifiers/intern/MOD_gpencilarray.c | 15 ++++++++++++--- source/blender/makesdna/DNA_gpencil_modifier_types.h | 1 + source/blender/makesrna/intern/rna_gpencil_modifier.c | 5 +++++ 3 files changed, 18 insertions(+), 3 deletions(-) (limited to 'source/blender') diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c index aa21bf192c4..0b8f150aba4 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c @@ -237,9 +237,17 @@ static void generate_geometry(GpencilModifierData *md, /* To ensure a nice distribution, we use halton sequence and offset using the seed. */ BLI_halton_3d(primes, offset, x, r); - for (int i = 0; i < 3; i++) { - rand[j][i] = fmodf(r[i] * 2.0 - 1.0 + rand_offset, 1.0f); - rand[j][i] = fmodf(sin(rand[j][i] * 12.9898 + j * 78.233) * 43758.5453, 1.0f); + if ((mmd->flag & GP_ARRAY_UNIFORM_RANDOM_SCALE) && j == 2) { + float rand_value; + rand_value = fmodf(r[0] * 2.0 - 1.0 + rand_offset, 1.0f); + rand_value = fmodf(sin(rand_value * 12.9898 + j * 78.233) * 43758.5453, 1.0f); + copy_v3_fl(rand[j] , rand_value); + } + else { + for (int i = 0; i < 3; i++) { + rand[j][i] = fmodf(r[i] * 2.0 - 1.0 + rand_offset, 1.0f); + rand[j][i] = fmodf(sin(rand[j][i] * 12.9898 + j * 78.233) * 43758.5453, 1.0f); + } } } /* Calculate Random matrix. */ @@ -425,6 +433,7 @@ static void random_panel_draw(const bContext *UNUSED(C), Panel *panel) uiItemR(layout, ptr, "random_offset", 0, IFACE_("Offset"), ICON_NONE); uiItemR(layout, ptr, "random_rotation", 0, IFACE_("Rotation"), ICON_NONE); uiItemR(layout, ptr, "random_scale", 0, IFACE_("Scale"), ICON_NONE); + uiItemR(layout, ptr, "use_uniform_random_scale", 0, NULL, ICON_NONE); uiItemR(layout, ptr, "seed", 0, NULL, ICON_NONE); } diff --git a/source/blender/makesdna/DNA_gpencil_modifier_types.h b/source/blender/makesdna/DNA_gpencil_modifier_types.h index bd5afc457ac..9ac40495887 100644 --- a/source/blender/makesdna/DNA_gpencil_modifier_types.h +++ b/source/blender/makesdna/DNA_gpencil_modifier_types.h @@ -351,6 +351,7 @@ typedef enum eArrayGpencil_Flag { GP_ARRAY_USE_OFFSET = (1 << 7), GP_ARRAY_USE_RELATIVE = (1 << 8), GP_ARRAY_USE_OB_OFFSET = (1 << 9), + GP_ARRAY_UNIFORM_RANDOM_SCALE = (1 << 10), } eArrayGpencil_Flag; typedef struct BuildGpencilModifierData { diff --git a/source/blender/makesrna/intern/rna_gpencil_modifier.c b/source/blender/makesrna/intern/rna_gpencil_modifier.c index 5f131de6a40..f0660392eaf 100644 --- a/source/blender/makesrna/intern/rna_gpencil_modifier.c +++ b/source/blender/makesrna/intern/rna_gpencil_modifier.c @@ -1560,6 +1560,11 @@ static void rna_def_modifier_gpencilarray(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_ARRAY_USE_RELATIVE); RNA_def_property_ui_text(prop, "Shift", "Enable shift"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "use_uniform_random_scale", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_ARRAY_UNIFORM_RANDOM_SCALE); + RNA_def_property_ui_text(prop, "Uniform Scale", "Use the same random seed for each scale axis for a uniform scale"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); } static void rna_def_modifier_gpencilbuild(BlenderRNA *brna) -- cgit v1.2.3 From 151e847b8709c44a731f3d07c9a50139d728e227 Mon Sep 17 00:00:00 2001 From: Falk David Date: Tue, 15 Dec 2020 22:28:28 +0100 Subject: GPencil: Improve interpolation of strokes with unequal lengths Use the BKE_gpencil_stroke_uniform_subdivide function to subdivide strokes before interpolation. When the target/source stroke is smaller than the other stroke, it is subdivided until the lengths match. This improves the overall quality of the interpolation of different sized strokes. Before/After video: {F9511779} Reviewed By: #grease_pencil, antoniov, pepeland, mendio Differential Revision: https://developer.blender.org/D9839 --- .../blender/editors/gpencil/gpencil_interpolate.c | 69 +++++++++++----------- 1 file changed, 34 insertions(+), 35 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/gpencil/gpencil_interpolate.c b/source/blender/editors/gpencil/gpencil_interpolate.c index 3617f20763e..9bca294cf30 100644 --- a/source/blender/editors/gpencil/gpencil_interpolate.c +++ b/source/blender/editors/gpencil/gpencil_interpolate.c @@ -283,8 +283,8 @@ static void gpencil_interpolate_set_points(bContext *C, tGPDinterpolate *tgpi) tgpil = MEM_callocN(sizeof(tGPDinterpolate_layer), "GPencil Interpolate Layer"); tgpil->gpl = gpl; - tgpil->prevFrame = gpl->actframe; - tgpil->nextFrame = gpl->actframe->next; + tgpil->prevFrame = BKE_gpencil_frame_duplicate(gpl->actframe); + tgpil->nextFrame = BKE_gpencil_frame_duplicate(gpl->actframe->next); BLI_addtail(&tgpi->ilayers, tgpil); @@ -326,24 +326,25 @@ static void gpencil_interpolate_set_points(bContext *C, tGPDinterpolate *tgpi) valid = false; } - /* create new stroke */ - new_stroke = BKE_gpencil_stroke_duplicate(gps_from, true, true); - if (valid) { /* if destination stroke is smaller, resize new_stroke to size of gps_to stroke */ if (gps_from->totpoints > gps_to->totpoints) { - new_stroke->points = MEM_recallocN(new_stroke->points, - sizeof(*new_stroke->points) * gps_to->totpoints); - if (new_stroke->dvert != NULL) { - new_stroke->dvert = MEM_recallocN(new_stroke->dvert, - sizeof(*new_stroke->dvert) * gps_to->totpoints); - } - new_stroke->totpoints = gps_to->totpoints; + BKE_gpencil_stroke_uniform_subdivide(gpd, gps_to, gps_from->totpoints, true); } - /* update points position */ + if (gps_to->totpoints > gps_from->totpoints) { + BKE_gpencil_stroke_uniform_subdivide(gpd, gps_from, gps_to->totpoints, true); + } + + /* Create new stroke. */ + new_stroke = BKE_gpencil_stroke_duplicate(gps_from, true, true); + + /* Update points position. */ gpencil_interpolate_update_points(gps_from, gps_to, new_stroke, tgpil->factor); } else { + /* Create new stroke. */ + new_stroke = BKE_gpencil_stroke_duplicate(gps_from, true, true); + /* need an empty stroke to keep index correct for lookup, but resize to smallest size */ new_stroke->totpoints = 0; new_stroke->points = MEM_recallocN(new_stroke->points, sizeof(*new_stroke->points)); @@ -443,12 +444,16 @@ static void gpencil_interpolate_exit(bContext *C, wmOperator *op) /* finally, free memory used by temp data */ LISTBASE_FOREACH (tGPDinterpolate_layer *, tgpil, &tgpi->ilayers) { + BKE_gpencil_free_strokes(tgpil->prevFrame); + BKE_gpencil_free_strokes(tgpil->nextFrame); BKE_gpencil_free_strokes(tgpil->interFrame); - MEM_freeN(tgpil->interFrame); + MEM_SAFE_FREE(tgpil->prevFrame); + MEM_SAFE_FREE(tgpil->nextFrame); + MEM_SAFE_FREE(tgpil->interFrame); } BLI_freelistN(&tgpi->ilayers); - MEM_freeN(tgpi); + MEM_SAFE_FREE(tgpi); } DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL); @@ -992,8 +997,8 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op) } /* store extremes */ - prevFrame = gpl->actframe; - nextFrame = gpl->actframe->next; + prevFrame = BKE_gpencil_frame_duplicate(gpl->actframe); + nextFrame = BKE_gpencil_frame_duplicate(gpl->actframe->next); /* Loop over intermediary frames and create the interpolation */ for (cframe = prevFrame->framenum + step; cframe < nextFrame->framenum; cframe += step) { @@ -1049,28 +1054,17 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op) interFrame->key_type = BEZT_KEYTYPE_BREAKDOWN; } - /* create new stroke */ - bGPDstroke *new_stroke = BKE_gpencil_stroke_duplicate(gps_from, true, true); - /* if destination stroke is smaller, resize new_stroke to size of gps_to stroke */ if (gps_from->totpoints > gps_to->totpoints) { - /* free weights of removed points */ - if (new_stroke->dvert != NULL) { - BKE_defvert_array_free_elems(new_stroke->dvert + gps_to->totpoints, - gps_from->totpoints - gps_to->totpoints); - } - - new_stroke->points = MEM_recallocN(new_stroke->points, - sizeof(*new_stroke->points) * gps_to->totpoints); - - if (new_stroke->dvert != NULL) { - new_stroke->dvert = MEM_recallocN(new_stroke->dvert, - sizeof(*new_stroke->dvert) * gps_to->totpoints); - } - - new_stroke->totpoints = gps_to->totpoints; + BKE_gpencil_stroke_uniform_subdivide(gpd, gps_to, gps_from->totpoints, true); + } + if (gps_to->totpoints > gps_from->totpoints) { + BKE_gpencil_stroke_uniform_subdivide(gpd, gps_from, gps_to->totpoints, true); } + /* create new stroke */ + bGPDstroke *new_stroke = BKE_gpencil_stroke_duplicate(gps_from, true, true); + /* update points position */ gpencil_interpolate_update_points(gps_from, gps_to, new_stroke, factor); @@ -1081,6 +1075,11 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op) BLI_addtail(&interFrame->strokes, new_stroke); } } + + BKE_gpencil_free_strokes(prevFrame); + BKE_gpencil_free_strokes(nextFrame); + MEM_SAFE_FREE(prevFrame); + MEM_SAFE_FREE(nextFrame); } /* notifiers */ -- cgit v1.2.3 From dd9d12bf45edac33fb414b9d7e4a0a716b2fa4d0 Mon Sep 17 00:00:00 2001 From: Peter Fog Date: Tue, 15 Dec 2020 22:01:58 +0100 Subject: VSE: Paste strips after playhead by default Paste copied strips after playhead, because this is more intuitive. Previous functionality is still available by enabling "Keep Offset" property, or under shortcut Ctrl+Shift+V. Reviewed By: ISS Differential Revision: https://developer.blender.org/D9734 --- .../editors/space_sequencer/sequencer_edit.c | 26 ++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c index 184f821d411..1e3529a9607 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.c +++ b/source/blender/editors/space_sequencer/sequencer_edit.c @@ -2527,7 +2527,7 @@ void ED_sequencer_deselect_all(Scene *scene) SEQ_CURRENT_END; } -static int sequencer_paste_exec(bContext *C, wmOperator *UNUSED(op)) +static int sequencer_paste_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); @@ -2536,8 +2536,25 @@ static int sequencer_paste_exec(bContext *C, wmOperator *UNUSED(op)) int ofs; Sequence *iseq, *iseq_first; + if (BLI_listbase_count(&seqbase_clipboard) == 0) { + BKE_report(op->reports, RPT_INFO, "No strips to paste"); + return OPERATOR_CANCELLED; + } + ED_sequencer_deselect_all(scene); - ofs = scene->r.cfra - seqbase_clipboard_frame; + if (RNA_boolean_get(op->ptr, "keep_offset")) { + ofs = scene->r.cfra - seqbase_clipboard_frame; + } + else { + int min_seq_startdisp = INT_MAX; + LISTBASE_FOREACH (Sequence *, seq, &seqbase_clipboard) { + if (seq->startdisp < min_seq_startdisp) { + min_seq_startdisp = seq->startdisp; + } + } + /* Paste strips after playhead. */ + ofs = scene->r.cfra - min_seq_startdisp; + } /* Copy strips, temporarily restoring pointers to actual data-blocks. This * must happen on the clipboard itself, so that copying does user counting @@ -2585,6 +2602,11 @@ void SEQUENCER_OT_paste(wmOperatorType *ot) /* Flags. */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* Properties. */ + PropertyRNA *prop = RNA_def_boolean( + ot->srna, "keep_offset", false, "Keep Offset", "Keep strip offset to playhead when pasting"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); } /** \} */ -- cgit v1.2.3 From fad80a95fd08ec87a37f30f0b94a7061d4e382f2 Mon Sep 17 00:00:00 2001 From: Peter Fog Date: Tue, 15 Dec 2020 23:15:32 +0100 Subject: VSE: Add Overlay popover panels Add panels with overlay settings for strips and preview and overlay enable/disable button. Entries from the View menus moved to the overlay panels, which will simplify cluttered View menus. Additional options have been added: - Strip Name - Strip Source(ex. path) - Strip Duration So users can now select what info they need to see on the strips. When No text is displayed, waveforms are drawn in full height. Reviewed By: ISS, HooglyBoogly, pablovazquez Differential Revision: https://developer.blender.org/D9751 --- source/blender/blenkernel/BKE_blender_version.h | 2 +- source/blender/blenloader/intern/versioning_290.c | 39 ++- .../blenloader/intern/versioning_defaults.c | 3 +- .../editors/space_sequencer/sequencer_draw.c | 288 +++++++++++---------- .../editors/space_sequencer/space_sequencer.c | 5 +- source/blender/makesdna/DNA_space_types.h | 4 + source/blender/makesrna/intern/rna_space.c | 22 +- 7 files changed, 210 insertions(+), 153 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index afb6112b954..ca95ca8bda0 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -39,7 +39,7 @@ extern "C" { /* Blender file format version. */ #define BLENDER_FILE_VERSION BLENDER_VERSION -#define BLENDER_FILE_SUBVERSION 6 +#define BLENDER_FILE_SUBVERSION 7 /* Minimum Blender version that supports reading file written with the current * version. Older Blender versions will test this and show a warning if the file diff --git a/source/blender/blenloader/intern/versioning_290.c b/source/blender/blenloader/intern/versioning_290.c index d00c5225299..685bb762f29 100644 --- a/source/blender/blenloader/intern/versioning_290.c +++ b/source/blender/blenloader/intern/versioning_290.c @@ -1234,18 +1234,7 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain) } } - /** - * Versioning code until next subversion bump goes here. - * - * \note Be sure to check when bumping the version: - * - "versioning_userdef.c", #blo_do_versions_userdef - * - "versioning_userdef.c", #do_versions_theme - * - * \note Keep this message at the bottom of the function. - */ - { - /* Keep this block, even when empty. */ - + if (!MAIN_VERSION_ATLEAST(bmain, 292, 7)) { /* Make all IDProperties used as interface of geometry node trees overridable. */ LISTBASE_FOREACH (Object *, ob, &bmain->objects) { LISTBASE_FOREACH (ModifierData *, md, &ob->modifiers) { @@ -1301,5 +1290,31 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain) } } } + + /* Overlay elements in the sequencer. */ + LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) { + LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { + LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) { + if (sl->spacetype == SPACE_SEQ) { + SpaceSeq *sseq = (SpaceSeq *)sl; + sseq->flag |= (SEQ_SHOW_STRIP_OVERLAY | SEQ_SHOW_STRIP_NAME | SEQ_SHOW_STRIP_SOURCE | + SEQ_SHOW_STRIP_DURATION); + } + } + } + } + } + + /** + * Versioning code until next subversion bump goes here. + * + * \note Be sure to check when bumping the version: + * - "versioning_userdef.c", #blo_do_versions_userdef + * - "versioning_userdef.c", #do_versions_theme + * + * \note Keep this message at the bottom of the function. + */ + { + /* Keep this block, even when empty. */ } } diff --git a/source/blender/blenloader/intern/versioning_defaults.c b/source/blender/blenloader/intern/versioning_defaults.c index f89a5be27de..2d75b046366 100644 --- a/source/blender/blenloader/intern/versioning_defaults.c +++ b/source/blender/blenloader/intern/versioning_defaults.c @@ -182,7 +182,8 @@ static void blo_update_defaults_screen(bScreen *screen, } else if (area->spacetype == SPACE_SEQ) { SpaceSeq *seq = area->spacedata.first; - seq->flag |= SEQ_SHOW_MARKERS | SEQ_SHOW_FCURVES | SEQ_ZOOM_TO_FIT; + seq->flag |= SEQ_SHOW_MARKERS | SEQ_SHOW_FCURVES | SEQ_ZOOM_TO_FIT | SEQ_SHOW_STRIP_OVERLAY | + SEQ_SHOW_STRIP_SOURCE | SEQ_SHOW_STRIP_NAME | SEQ_SHOW_STRIP_DURATION; } else if (area->spacetype == SPACE_TEXT) { /* Show syntax and line numbers in Script workspace text editor. */ diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index e31fa3205ba..ac1b9e6d0a0 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -227,16 +227,16 @@ void color3ubv_from_seq(Scene *curscene, Sequence *seq, uchar col[3]) * \param x1, x2, y1, y2: The starting and end X value to draw the wave, same for y1 and y2. * \param stepsize: The width of a pixel. */ -static void draw_seq_waveform(View2D *v2d, - const bContext *C, - SpaceSeq *sseq, - Scene *scene, - Sequence *seq, - float x1, - float y1, - float x2, - float y2, - float stepsize) +static void draw_seq_waveform_overlay(View2D *v2d, + const bContext *C, + SpaceSeq *sseq, + Scene *scene, + Sequence *seq, + float x1, + float y1, + float x2, + float y2, + float stepsize) { /* Offset x1 and x2 values, to match view min/max, if strip is out of bounds. */ int x1_offset = max_ff(v2d->cur.xmin, x1); @@ -603,121 +603,113 @@ static void draw_seq_outline(Sequence *seq, } } -/* Draw info text on a sequence strip. */ -static void draw_seq_text(View2D *v2d, - Sequence *seq, - SpaceSeq *sseq, - float x1, - float x2, - float y1, - float y2, - bool seq_active, - bool y_threshold) +const char *draw_seq_text_get_name(SpaceSeq *sseq, Sequence *seq) { - rctf rect; - char str[32 + FILE_MAX]; - size_t str_len; const char *name = seq->name + 2; - uchar col[4]; - - /* All strings should include name. */ if (name[0] == '\0') { name = BKE_sequence_give_name(seq); } + return name; +} - if (ELEM(seq->type, SEQ_TYPE_META, SEQ_TYPE_ADJUSTMENT)) { - str_len = BLI_snprintf(str, sizeof(str), "%s | %d", name, seq->len); +static void draw_seq_text_get_source(SpaceSeq *sseq, + Sequence *seq, + char *r_source, + size_t source_len) +{ + /* Set source for the most common types. */ + if (ELEM(seq->type, SEQ_TYPE_IMAGE, SEQ_TYPE_MOVIE)) { + BLI_snprintf(r_source, source_len, "%s%s", seq->strip->dir, seq->strip->stripdata->name); } - else if (seq->type == SEQ_TYPE_SCENE) { - if (seq->scene) { - if (seq->scene_camera) { - str_len = BLI_snprintf(str, - sizeof(str), - "%s: %s (%s) | %d", - name, - seq->scene->id.name + 2, - ((ID *)seq->scene_camera)->name + 2, - seq->len); - } - else { - str_len = BLI_snprintf( - str, sizeof(str), "%s: %s | %d", name, seq->scene->id.name + 2, seq->len); - } - } - else { - str_len = BLI_snprintf(str, sizeof(str), "%s | %d", name, seq->len); + else if (seq->type == SEQ_TYPE_SOUND_RAM) { + if (seq->sound) { + BLI_snprintf(r_source, source_len, "%s", seq->sound->filepath); } } - else if (seq->type == SEQ_TYPE_MOVIECLIP) { - if (seq->clip && !STREQ(name, seq->clip->id.name + 2)) { - str_len = BLI_snprintf( - str, sizeof(str), "%s: %s | %d", name, seq->clip->id.name + 2, seq->len); - } - else { - str_len = BLI_snprintf(str, sizeof(str), "%s | %d", name, seq->len); - } + else if (seq->type == SEQ_TYPE_MULTICAM) { + BLI_snprintf(r_source, source_len, "Channel: %d", seq->multicam_source); } - else if (seq->type == SEQ_TYPE_MASK) { - if (seq->mask && !STREQ(name, seq->mask->id.name + 2)) { - str_len = BLI_snprintf( - str, sizeof(str), "%s: %s | %d", name, seq->mask->id.name + 2, seq->len); + else if (seq->type == SEQ_TYPE_TEXT) { + TextVars *textdata = seq->effectdata; + BLI_snprintf(r_source, source_len, "%s", textdata->text); + } + else if (seq->type == SEQ_TYPE_SCENE) { + if (seq->scene_camera) { + BLI_snprintf(r_source, + source_len, + "%s (%s)", + seq->scene->id.name + 2, + ((ID *)seq->scene_camera)->name + 2); } else { - str_len = BLI_snprintf(str, sizeof(str), "%s | %d", name, seq->len); + BLI_snprintf(r_source, source_len, "%s", seq->scene->id.name + 2); } } - else if (seq->type == SEQ_TYPE_MULTICAM) { - str_len = BLI_snprintf(str, sizeof(str), "Cam %s: %d", name, seq->multicam_source); - } - else if (seq->type == SEQ_TYPE_IMAGE) { - str_len = BLI_snprintf(str, - sizeof(str), - "%s: %s%s | %d", - name, - seq->strip->dir, - seq->strip->stripdata->name, - seq->len); + else if (seq->type == SEQ_TYPE_MOVIECLIP) { + BLI_snprintf(r_source, source_len, "%s", seq->clip->id.name + 2); } - else if (seq->type == SEQ_TYPE_TEXT) { - TextVars *textdata = seq->effectdata; - str_len = BLI_snprintf(str, sizeof(str), "%s | %d", textdata->text, seq->startdisp); + else if (seq->type == SEQ_TYPE_MASK) { + BLI_snprintf(r_source, source_len, "%s", seq->mask->id.name + 2); } - else if (seq->type & SEQ_TYPE_EFFECT) { - str_len = BLI_snprintf(str, sizeof(str), "%s | %d", name, seq->len); + else { + *r_source = '\0'; } - else if (seq->type == SEQ_TYPE_SOUND_RAM) { - /* If a waveform is drawn, avoid to draw text when there is not enough vertical space. */ - if (!y_threshold && (sseq->flag & SEQ_NO_WAVEFORMS) == 0 && - ((sseq->flag & SEQ_ALL_WAVEFORMS) || (seq->flag & SEQ_AUDIO_DRAW_WAVEFORM))) { +} - str[0] = 0; - str_len = 0; - } - else if (seq->sound) { - str_len = BLI_snprintf( - str, sizeof(str), "%s: %s | %d", name, seq->sound->filepath, seq->len); +static size_t draw_seq_text_get_overlay_string(SpaceSeq *sseq, + Sequence *seq, + char *r_overlay_string, + size_t overlay_string_len) +{ + const char *name = draw_seq_text_get_name(sseq, seq); + char source[FILE_MAX]; + int strip_duration = seq->enddisp - seq->startdisp; + draw_seq_text_get_source(sseq, seq, source, sizeof(source)); + + bool show_name = sseq->flag & SEQ_SHOW_STRIP_NAME; + bool show_source = (sseq->flag & (SEQ_SHOW_STRIP_SOURCE)) && source[0] != '\0'; + bool show_duration = sseq->flag & SEQ_SHOW_STRIP_DURATION; + + size_t string_len = 0; + if (show_name) { + string_len = BLI_snprintf(r_overlay_string, overlay_string_len, "%s", name); + if (show_source || show_duration) { + string_len += BLI_snprintf(r_overlay_string + string_len, overlay_string_len, " | "); } - else { - str_len = BLI_snprintf(str, sizeof(str), "%s | %d", name, seq->len); + } + if (show_source) { + string_len += BLI_snprintf(r_overlay_string + string_len, overlay_string_len, "%s", source); + if (show_duration) { + string_len += BLI_snprintf(r_overlay_string + string_len, overlay_string_len, " | "); } } - else if (seq->type == SEQ_TYPE_MOVIE) { - str_len = BLI_snprintf(str, - sizeof(str), - "%s: %s%s | %d", - name, - seq->strip->dir, - seq->strip->stripdata->name, - seq->len); + if (show_duration) { + string_len += BLI_snprintf( + r_overlay_string + string_len, overlay_string_len, "%d", strip_duration); } - else { - /* Should never get here!, but might with files from future. */ - BLI_assert(0); + return string_len; +} + +/* Draw info text on a sequence strip. */ +static void draw_seq_text_overlay(View2D *v2d, + Sequence *seq, + SpaceSeq *sseq, + float x1, + float x2, + float y1, + float y2, + bool seq_active) +{ + char overlay_string[FILE_MAX]; + size_t overlay_string_len = draw_seq_text_get_overlay_string( + sseq, seq, overlay_string, sizeof(overlay_string)); - str_len = BLI_snprintf(str, sizeof(str), "%s | %d", name, seq->len); + if (overlay_string_len == 0) { + return; } /* White text for the active strip. */ + uchar col[4]; col[0] = col[1] = col[2] = seq_active ? 255 : 10; col[3] = 255; @@ -731,15 +723,16 @@ static void draw_seq_text(View2D *v2d, } } + rctf rect; rect.xmin = x1; rect.ymin = y1; rect.xmax = x2; rect.ymax = y2; - UI_view2d_text_cache_add_rectf(v2d, &rect, str, str_len, col); + UI_view2d_text_cache_add_rectf(v2d, &rect, overlay_string, overlay_string_len, col); } -static void draw_sequence_extensions(Scene *scene, Sequence *seq, uint pos, float pixely) +static void draw_sequence_extensions_overlay(Scene *scene, Sequence *seq, uint pos, float pixely) { float x1, x2, y1, y2; uchar col[4], blend_col[3]; @@ -988,7 +981,7 @@ static void fcurve_batch_add_verts(GPUVertBuf *vbo, * - Volume for sound strips. * - Opacity for the other types. */ -static void draw_seq_fcurve( +static void draw_seq_fcurve_overlay( Scene *scene, View2D *v2d, Sequence *seq, float x1, float y1, float x2, float y2, float pixelx) { FCurve *fcu; @@ -1085,11 +1078,21 @@ static void draw_seq_strip(const bContext *C, x2 = (seq->endstill) ? (seq->start + seq->len) : seq->enddisp; y2 = seq->machine + SEQ_STRIP_OFSTOP; - /* Calculate height needed for drawing text on strip. */ - float text_margin_y = y2 - min_ff(0.40f, 20 * U.dpi_fac * pixely); + float text_margin_y; + bool y_threshold; + if ((sseq->flag & SEQ_SHOW_STRIP_NAME) || (sseq->flag & SEQ_SHOW_STRIP_SOURCE) || + (sseq->flag & SEQ_SHOW_STRIP_DURATION)) { - /* Is there enough space for drawing something else than text? */ - bool y_threshold = ((y2 - y1) / pixely) > 20 * U.dpi_fac; + /* Calculate height needed for drawing text on strip. */ + text_margin_y = y2 - min_ff(0.40f, 20 * U.dpi_fac * pixely); + + /* Is there enough space for drawing something else than text? */ + y_threshold = ((y2 - y1) / pixely) > 20 * U.dpi_fac; + } + else { + text_margin_y = y2; + y_threshold = 1; + } uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); @@ -1102,12 +1105,13 @@ static void draw_seq_strip(const bContext *C, } /* Draw strip offsets when flag is enabled or during "solo preview". */ - if (!is_single_image && (seq->startofs || seq->endofs) && pixely > 0) { - if ((sseq->draw_flag & SEQ_DRAW_OFFSET_EXT) || (seq == special_seq_update)) { - draw_sequence_extensions(scene, seq, pos, pixely); + if ((sseq->flag & SEQ_SHOW_STRIP_OVERLAY)) { + if (!is_single_image && (seq->startofs || seq->endofs) && pixely > 0) { + if ((sseq->draw_flag & SEQ_DRAW_OFFSET_EXT) || (seq == special_seq_update)) { + draw_sequence_extensions_overlay(scene, seq, pos, pixely); + } } } - immUnbindProgram(); x1 = seq->startdisp; @@ -1118,24 +1122,24 @@ static void draw_seq_strip(const bContext *C, drawmeta_contents(scene, seq, x1, y1, x2, y2); } - if (sseq->flag & SEQ_SHOW_FCURVES) { - draw_seq_fcurve(scene, v2d, seq, x1, y1, x2, y2, pixelx); + if ((sseq->flag & SEQ_SHOW_STRIP_OVERLAY) && (sseq->flag & SEQ_SHOW_FCURVES)) { + draw_seq_fcurve_overlay(scene, v2d, seq, x1, y1, x2, y2, pixelx); } /* Draw sound strip waveform. */ - if ((seq->type == SEQ_TYPE_SOUND_RAM) && (sseq->flag & SEQ_NO_WAVEFORMS) == 0) { - draw_seq_waveform(v2d, - C, - sseq, - scene, - seq, - x1, - y_threshold ? y1 + 0.05f : y1, - x2, - y_threshold ? text_margin_y : y2, - BLI_rctf_size_x(®ion->v2d.cur) / region->winx); + if ((seq->type == SEQ_TYPE_SOUND_RAM) && ((sseq->flag & SEQ_SHOW_STRIP_OVERLAY)) && + (sseq->flag & SEQ_NO_WAVEFORMS) == 0) { + draw_seq_waveform_overlay(v2d, + C, + sseq, + scene, + seq, + x1, + y_threshold ? y1 + 0.05f : y1, + x2, + y_threshold ? text_margin_y : y2, + BLI_rctf_size_x(®ion->v2d.cur) / region->winx); } - /* Draw locked state. */ if (seq->flag & SEQ_LOCK) { draw_seq_locked(x1, y1, x2, y2); @@ -1162,11 +1166,21 @@ static void draw_seq_strip(const bContext *C, calculate_seq_text_offsets(v2d, seq, &x1, &x2, pixelx); - /* Don't draw strip if there is not enough vertical or horizontal space. */ - if (((x2 - x1) > 32 * pixelx * U.dpi_fac) && ((y2 - y1) > 8 * pixely * U.dpi_fac)) { - /* Depending on the vertical space, draw text on top or in the center of strip. */ - draw_seq_text( - v2d, seq, sseq, x1, x2, y_threshold ? text_margin_y : y1, y2, seq_active, y_threshold); + /* If a waveform is drawn, avoid drawing text when there is not enough vertical space. */ + if (seq->type == SEQ_TYPE_SOUND_RAM) { + if (!y_threshold && (sseq->flag & SEQ_NO_WAVEFORMS) == 0 && + ((sseq->flag & SEQ_ALL_WAVEFORMS) || (seq->flag & SEQ_AUDIO_DRAW_WAVEFORM))) { + return; + } + } + + if (sseq->flag & SEQ_SHOW_STRIP_OVERLAY) { + /* Don't draw strip if there is not enough vertical or horizontal space. */ + if (((x2 - x1) > 32 * pixelx * U.dpi_fac) && ((y2 - y1) > 8 * pixely * U.dpi_fac)) { + /* Depending on the vertical space, draw text on top or in the center of strip. */ + draw_seq_text_overlay( + v2d, seq, sseq, x1, x2, y_threshold ? text_margin_y : y1, y2, seq_active); + } } } @@ -1360,7 +1374,7 @@ static void sequencer_display_size(Scene *scene, float r_viewrect[2]) r_viewrect[0] *= scene->r.xasp / scene->r.yasp; } -static void sequencer_draw_gpencil(const bContext *C) +static void sequencer_draw_gpencil_overlay(const bContext *C) { /* Draw grease-pencil (image aligned). */ ED_annotation_draw_2dimage(C); @@ -1373,7 +1387,9 @@ static void sequencer_draw_gpencil(const bContext *C) } /* Draw content and safety borders borders. */ -static void sequencer_draw_borders(const SpaceSeq *sseq, const View2D *v2d, const Scene *scene) +static void sequencer_draw_borders_overlay(const SpaceSeq *sseq, + const View2D *v2d, + const Scene *scene) { float x1 = v2d->tot.xmin; float y1 = v2d->tot.ymin; @@ -1825,17 +1841,17 @@ void sequencer_draw_preview(const bContext *C, C, scene, region, sseq, ibuf, scope, draw_overlay, draw_backdrop); /* Draw over image. */ - if (sseq->flag & SEQ_SHOW_METADATA) { + if (sseq->flag & SEQ_SHOW_METADATA && sseq->flag & SEQ_SHOW_STRIP_OVERLAY) { ED_region_image_metadata_draw(0.0, 0.0, ibuf, &v2d->tot, 1.0, 1.0); } } - if (show_imbuf) { - sequencer_draw_borders(sseq, v2d, scene); + if (show_imbuf && (sseq->flag & SEQ_SHOW_STRIP_OVERLAY)) { + sequencer_draw_borders_overlay(sseq, v2d, scene); } - if (draw_gpencil && show_imbuf) { - sequencer_draw_gpencil(C); + if (draw_gpencil && show_imbuf && (sseq->flag & SEQ_SHOW_STRIP_OVERLAY)) { + sequencer_draw_gpencil_overlay(C); } #if 0 sequencer_draw_maskedit(C, scene, region, sseq); diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c index 45c7bac54f8..64b51b70a12 100644 --- a/source/blender/editors/space_sequencer/space_sequencer.c +++ b/source/blender/editors/space_sequencer/space_sequencer.c @@ -99,7 +99,8 @@ static SpaceLink *sequencer_create(const ScrArea *UNUSED(area), const Scene *sce sseq->view = SEQ_VIEW_SEQUENCE; sseq->mainb = SEQ_DRAW_IMG_IMBUF; sseq->flag = SEQ_SHOW_GPENCIL | SEQ_USE_ALPHA | SEQ_SHOW_MARKERS | SEQ_SHOW_FCURVES | - SEQ_ZOOM_TO_FIT; + SEQ_ZOOM_TO_FIT | SEQ_SHOW_STRIP_OVERLAY | SEQ_SHOW_STRIP_NAME | + SEQ_SHOW_STRIP_SOURCE | SEQ_SHOW_STRIP_DURATION; /* Tool header. */ region = MEM_callocN(sizeof(ARegion), "tool header for sequencer"); @@ -706,7 +707,7 @@ static void sequencer_preview_region_draw(const bContext *C, ARegion *region) SpaceSeq *sseq = area->spacedata.first; Scene *scene = CTX_data_scene(C); wmWindowManager *wm = CTX_wm_manager(C); - const bool draw_overlay = (scene->ed && (scene->ed->over_flag & SEQ_EDIT_OVERLAY_SHOW)); + const bool draw_overlay = (scene->ed && (scene->ed->over_flag & SEQ_EDIT_OVERLAY_SHOW) && (sseq->flag & SEQ_SHOW_STRIP_OVERLAY)); /* XXX temp fix for wrong setting in sseq->mainb */ if (sseq->mainb == SEQ_DRAW_SEQUENCE) { diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index 4161faca386..4276e8b568e 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -621,6 +621,10 @@ typedef enum eSpaceSeq_Flag { SEQ_SHOW_METADATA = (1 << 10), SEQ_SHOW_MARKERS = (1 << 11), /* show markers region */ SEQ_ZOOM_TO_FIT = (1 << 12), + SEQ_SHOW_STRIP_OVERLAY = (1 << 13), + SEQ_SHOW_STRIP_NAME = (1 << 14), + SEQ_SHOW_STRIP_SOURCE = (1 << 15), + SEQ_SHOW_STRIP_DURATION = (1 << 16), } eSpaceSeq_Flag; /* SpaceSeq.view */ diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 0e779c8cc97..ca12bbbbb7a 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -5176,7 +5176,7 @@ static void rna_def_space_sequencer(BlenderRNA *brna) prop = RNA_def_property(srna, "waveform_display_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag"); RNA_def_property_enum_items(prop, waveform_type_display_items); - RNA_def_property_ui_text(prop, "Waveform Displaying", "How Waveforms are drawn"); + RNA_def_property_ui_text(prop, "Waveform Display", "How Waveforms are drawn"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL); prop = RNA_def_property(srna, "use_zoom_to_fit", PROP_BOOLEAN, PROP_NONE); @@ -5229,6 +5229,26 @@ static void rna_def_space_sequencer(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_SHOW_FCURVES); RNA_def_property_ui_text(prop, "Show F-Curves", "Display strip opacity/volume curve"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL); + + prop = RNA_def_property(srna, "show_strip_overlay", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_SHOW_STRIP_OVERLAY); + RNA_def_property_ui_text(prop, "Show Overlay", ""); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL); + + prop = RNA_def_property(srna, "show_strip_name", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_SHOW_STRIP_NAME); + RNA_def_property_ui_text(prop, "Show Name", ""); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL); + + prop = RNA_def_property(srna, "show_strip_source", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_SHOW_STRIP_SOURCE); + RNA_def_property_ui_text(prop, "Show Source", "Display path to source file, or name of source datablock"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL); + + prop = RNA_def_property(srna, "show_strip_duration", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_SHOW_STRIP_DURATION); + RNA_def_property_ui_text(prop, "Show Duration", ""); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL); } static void rna_def_space_text(BlenderRNA *brna) -- cgit v1.2.3 From 977bd7937a07a5cbb269c1cda6e95ef0931a0704 Mon Sep 17 00:00:00 2001 From: Richard Antalik Date: Wed, 16 Dec 2020 00:20:20 +0100 Subject: Fix warnings introduced in previous commit --- source/blender/editors/space_sequencer/sequencer_draw.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index ac1b9e6d0a0..5ad1e2399f5 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -603,7 +603,7 @@ static void draw_seq_outline(Sequence *seq, } } -const char *draw_seq_text_get_name(SpaceSeq *sseq, Sequence *seq) +static const char *draw_seq_text_get_name(Sequence *seq) { const char *name = seq->name + 2; if (name[0] == '\0') { @@ -612,10 +612,7 @@ const char *draw_seq_text_get_name(SpaceSeq *sseq, Sequence *seq) return name; } -static void draw_seq_text_get_source(SpaceSeq *sseq, - Sequence *seq, - char *r_source, - size_t source_len) +static void draw_seq_text_get_source(Sequence *seq, char *r_source, size_t source_len) { /* Set source for the most common types. */ if (ELEM(seq->type, SEQ_TYPE_IMAGE, SEQ_TYPE_MOVIE)) { @@ -661,10 +658,10 @@ static size_t draw_seq_text_get_overlay_string(SpaceSeq *sseq, char *r_overlay_string, size_t overlay_string_len) { - const char *name = draw_seq_text_get_name(sseq, seq); + const char *name = draw_seq_text_get_name(seq); char source[FILE_MAX]; int strip_duration = seq->enddisp - seq->startdisp; - draw_seq_text_get_source(sseq, seq, source, sizeof(source)); + draw_seq_text_get_source(seq, source, sizeof(source)); bool show_name = sseq->flag & SEQ_SHOW_STRIP_NAME; bool show_source = (sseq->flag & (SEQ_SHOW_STRIP_SOURCE)) && source[0] != '\0'; -- cgit v1.2.3 From 87fdb714383326255fa656809d637403b9bb2adb Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 16 Dec 2020 16:12:50 +1100 Subject: Cleanup: use static declarations --- source/blender/editors/space_file/space_file.c | 2 +- source/blender/editors/space_outliner/outliner_context.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c index 09b7e5b348c..d4f6618e82a 100644 --- a/source/blender/editors/space_file/space_file.c +++ b/source/blender/editors/space_file/space_file.c @@ -779,7 +779,7 @@ static void file_space_subtype_item_extend(bContext *UNUSED(C), RNA_enum_items_add(item, totitem, rna_enum_space_file_browse_mode_items); } -const char *file_context_dir[] = {"active_file", "active_id", NULL}; +static const char *file_context_dir[] = {"active_file", "active_id", NULL}; static int /*eContextResult*/ file_context(const bContext *C, const char *member, diff --git a/source/blender/editors/space_outliner/outliner_context.c b/source/blender/editors/space_outliner/outliner_context.c index e7dc2780c37..a314a640e42 100644 --- a/source/blender/editors/space_outliner/outliner_context.c +++ b/source/blender/editors/space_outliner/outliner_context.c @@ -50,7 +50,7 @@ static void outliner_context_selected_ids(const SpaceOutliner *space_outliner, CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION); } -const char *outliner_context_dir[] = {"selected_ids", NULL}; +static const char *outliner_context_dir[] = {"selected_ids", NULL}; int /*eContextResult*/ outliner_context(const bContext *C, const char *member, -- cgit v1.2.3 From 588f107f1155817afe4316549c84ca649be16600 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 16 Dec 2020 16:13:05 +1100 Subject: Cleanup: clang-format --- source/blender/editors/space_sequencer/space_sequencer.c | 3 ++- source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c | 2 +- source/blender/makesrna/intern/rna_gpencil_modifier.c | 3 ++- source/blender/makesrna/intern/rna_space.c | 3 ++- 4 files changed, 7 insertions(+), 4 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c index 64b51b70a12..2bf4741e4f5 100644 --- a/source/blender/editors/space_sequencer/space_sequencer.c +++ b/source/blender/editors/space_sequencer/space_sequencer.c @@ -707,7 +707,8 @@ static void sequencer_preview_region_draw(const bContext *C, ARegion *region) SpaceSeq *sseq = area->spacedata.first; Scene *scene = CTX_data_scene(C); wmWindowManager *wm = CTX_wm_manager(C); - const bool draw_overlay = (scene->ed && (scene->ed->over_flag & SEQ_EDIT_OVERLAY_SHOW) && (sseq->flag & SEQ_SHOW_STRIP_OVERLAY)); + const bool draw_overlay = (scene->ed && (scene->ed->over_flag & SEQ_EDIT_OVERLAY_SHOW) && + (sseq->flag & SEQ_SHOW_STRIP_OVERLAY)); /* XXX temp fix for wrong setting in sseq->mainb */ if (sseq->mainb == SEQ_DRAW_SEQUENCE) { diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c index 0b8f150aba4..b8fa88327fc 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c @@ -241,7 +241,7 @@ static void generate_geometry(GpencilModifierData *md, float rand_value; rand_value = fmodf(r[0] * 2.0 - 1.0 + rand_offset, 1.0f); rand_value = fmodf(sin(rand_value * 12.9898 + j * 78.233) * 43758.5453, 1.0f); - copy_v3_fl(rand[j] , rand_value); + copy_v3_fl(rand[j], rand_value); } else { for (int i = 0; i < 3; i++) { diff --git a/source/blender/makesrna/intern/rna_gpencil_modifier.c b/source/blender/makesrna/intern/rna_gpencil_modifier.c index f0660392eaf..89eb989a442 100644 --- a/source/blender/makesrna/intern/rna_gpencil_modifier.c +++ b/source/blender/makesrna/intern/rna_gpencil_modifier.c @@ -1563,7 +1563,8 @@ static void rna_def_modifier_gpencilarray(BlenderRNA *brna) prop = RNA_def_property(srna, "use_uniform_random_scale", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_ARRAY_UNIFORM_RANDOM_SCALE); - RNA_def_property_ui_text(prop, "Uniform Scale", "Use the same random seed for each scale axis for a uniform scale"); + RNA_def_property_ui_text( + prop, "Uniform Scale", "Use the same random seed for each scale axis for a uniform scale"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); } diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index ca12bbbbb7a..7405bc541c9 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -5242,7 +5242,8 @@ static void rna_def_space_sequencer(BlenderRNA *brna) prop = RNA_def_property(srna, "show_strip_source", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_SHOW_STRIP_SOURCE); - RNA_def_property_ui_text(prop, "Show Source", "Display path to source file, or name of source datablock"); + RNA_def_property_ui_text( + prop, "Show Source", "Display path to source file, or name of source datablock"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL); prop = RNA_def_property(srna, "show_strip_duration", PROP_BOOLEAN, PROP_NONE); -- cgit v1.2.3 From b347c4e9ca896c7f1149502962add1163db1e82c Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 16 Dec 2020 16:19:04 +1100 Subject: Cleanup: remove redundant struct declarations --- source/blender/blenkernel/BKE_animsys.h | 2 -- source/blender/blenkernel/BKE_attribute.h | 1 - source/blender/blenkernel/BKE_attribute_access.hh | 2 -- source/blender/blenkernel/BKE_cryptomatte.h | 1 - source/blender/blenkernel/BKE_editmesh.h | 2 -- source/blender/blenkernel/BKE_gpencil.h | 2 -- source/blender/blenkernel/BKE_gpencil_geom.h | 1 - source/blender/blenkernel/BKE_ipo.h | 1 - source/blender/blenkernel/BKE_lattice.h | 1 - source/blender/blenkernel/BKE_lib_id.h | 1 - source/blender/blenkernel/BKE_lib_remap.h | 2 -- source/blender/blenkernel/BKE_mesh.h | 1 - source/blender/blenkernel/BKE_paint.h | 1 - source/blender/blenkernel/BKE_pbvh.h | 1 - source/blender/blenkernel/BKE_screen.h | 1 - source/blender/blenkernel/BKE_speaker.h | 1 - source/blender/blenkernel/intern/multires_unsubdivide.h | 2 -- source/blender/blenlib/BLI_threads.h | 1 - source/blender/blenloader/intern/readfile.h | 3 --- source/blender/depsgraph/DEG_depsgraph_build.h | 1 - source/blender/depsgraph/intern/builder/deg_builder_relations.h | 1 - source/blender/depsgraph/intern/eval/deg_eval_flush.h | 2 -- source/blender/draw/engines/gpencil/gpencil_engine.h | 3 --- source/blender/draw/engines/image/image_private.h | 2 -- source/blender/draw/intern/DRW_render.h | 1 - source/blender/draw/intern/draw_common.h | 2 -- source/blender/editors/include/ED_armature.h | 1 - source/blender/editors/include/ED_gpencil.h | 1 - source/blender/editors/include/ED_image.h | 2 -- source/blender/editors/include/ED_object.h | 1 - source/blender/editors/include/ED_transform.h | 2 -- source/blender/editors/include/ED_transform_snap_object_context.h | 1 - source/blender/editors/include/ED_util_imbuf.h | 1 - source/blender/editors/include/ED_uvedit.h | 1 - source/blender/editors/include/ED_view3d.h | 5 ----- source/blender/editors/include/UI_interface.h | 1 - source/blender/editors/sculpt_paint/paint_intern.h | 1 - source/blender/editors/sculpt_paint/sculpt_intern.h | 1 - source/blender/editors/space_buttons/buttons_intern.h | 1 - source/blender/editors/space_outliner/tree/tree_element_nla.hh | 1 - source/blender/editors/transform/transform.h | 2 +- source/blender/editors/transform/transform_convert.h | 3 --- source/blender/editors/transform/transform_snap.h | 2 -- source/blender/editors/uvedit/uvedit_intern.h | 1 - source/blender/gpencil_modifiers/intern/MOD_gpencil_util.h | 2 -- source/blender/gpu/GPU_shader.h | 2 -- source/blender/gpu/GPU_texture.h | 8 -------- source/blender/gpu/intern/gpu_codegen.h | 3 --- source/blender/gpu/intern/gpu_node_graph.h | 2 -- source/blender/gpu/intern/gpu_uniform_buffer_private.hh | 2 ++ source/blender/io/alembic/exporter/abc_hierarchy_iterator.h | 1 - source/blender/io/alembic/exporter/abc_writer_abstract.h | 1 - source/blender/io/alembic/exporter/abc_writer_hair.h | 3 --- source/blender/io/alembic/intern/abc_reader_archive.h | 1 - source/blender/io/common/IO_abstract_hierarchy_iterator.h | 2 -- source/blender/io/usd/intern/usd_exporter_context.h | 1 - source/blender/io/usd/intern/usd_hierarchy_iterator.h | 1 - source/blender/io/usd/intern/usd_writer_abstract.h | 1 - source/blender/io/usd/usd.h | 1 - source/blender/makesdna/DNA_mesh_types.h | 2 -- source/blender/makesdna/DNA_object_types.h | 2 -- source/blender/python/BPY_extern.h | 1 - source/blender/sequencer/intern/multiview.h | 7 ------- source/blender/sequencer/intern/prefetch.h | 2 -- source/blender/sequencer/intern/render.h | 1 - source/blender/sequencer/intern/utils.h | 1 - source/blender/windowmanager/wm.h | 1 - 67 files changed, 3 insertions(+), 112 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/BKE_animsys.h b/source/blender/blenkernel/BKE_animsys.h index e812d04c7d1..8d904bd6019 100644 --- a/source/blender/blenkernel/BKE_animsys.h +++ b/source/blender/blenkernel/BKE_animsys.h @@ -45,8 +45,6 @@ struct NlaKeyframingContext; struct PathResolvedRNA; struct PointerRNA; struct PropertyRNA; -struct ReportList; -struct Scene; struct bAction; struct bActionGroup; struct bContext; diff --git a/source/blender/blenkernel/BKE_attribute.h b/source/blender/blenkernel/BKE_attribute.h index 55a841d8fd1..574d9904dc4 100644 --- a/source/blender/blenkernel/BKE_attribute.h +++ b/source/blender/blenkernel/BKE_attribute.h @@ -35,7 +35,6 @@ extern "C" { struct CustomData; struct CustomDataLayer; struct ID; -struct PointerRNA; struct ReportList; /* Attribute.domain */ diff --git a/source/blender/blenkernel/BKE_attribute_access.hh b/source/blender/blenkernel/BKE_attribute_access.hh index c4a704ef385..564e912551a 100644 --- a/source/blender/blenkernel/BKE_attribute_access.hh +++ b/source/blender/blenkernel/BKE_attribute_access.hh @@ -26,8 +26,6 @@ #include "BLI_color.hh" #include "BLI_float3.hh" -struct Mesh; - namespace blender::bke { using fn::CPPType; diff --git a/source/blender/blenkernel/BKE_cryptomatte.h b/source/blender/blenkernel/BKE_cryptomatte.h index 71b15e47203..d984b3824b1 100644 --- a/source/blender/blenkernel/BKE_cryptomatte.h +++ b/source/blender/blenkernel/BKE_cryptomatte.h @@ -31,7 +31,6 @@ extern "C" { struct Object; struct Material; -struct ID; struct Main; uint32_t BKE_cryptomatte_hash(const char *name, int name_len); diff --git a/source/blender/blenkernel/BKE_editmesh.h b/source/blender/blenkernel/BKE_editmesh.h index 0c84ad70845..2fb713a4299 100644 --- a/source/blender/blenkernel/BKE_editmesh.h +++ b/source/blender/blenkernel/BKE_editmesh.h @@ -35,9 +35,7 @@ struct BMLoop; struct BMesh; struct BoundBox; struct Depsgraph; -struct EditMeshData; struct Mesh; -struct MeshStatVis; struct Object; struct Scene; diff --git a/source/blender/blenkernel/BKE_gpencil.h b/source/blender/blenkernel/BKE_gpencil.h index 6dc8d1ef06e..9177931cf9b 100644 --- a/source/blender/blenkernel/BKE_gpencil.h +++ b/source/blender/blenkernel/BKE_gpencil.h @@ -36,7 +36,6 @@ struct ListBase; struct MDeformVert; struct Main; struct Material; -struct MaterialGPencilStyle; struct Object; struct Scene; struct SpaceImage; @@ -46,7 +45,6 @@ struct bDeformGroup; struct bGPDframe; struct bGPDlayer; struct bGPDlayer_Mask; -struct bGPDspoint; struct bGPDstroke; struct bGPDcurve; struct bGPdata; diff --git a/source/blender/blenkernel/BKE_gpencil_geom.h b/source/blender/blenkernel/BKE_gpencil_geom.h index 111f9030463..8cb7137e1f0 100644 --- a/source/blender/blenkernel/BKE_gpencil_geom.h +++ b/source/blender/blenkernel/BKE_gpencil_geom.h @@ -33,7 +33,6 @@ struct Main; struct Object; struct Scene; struct bGPDframe; -struct bGPDlayer; struct bGPDspoint; struct bGPDstroke; struct bGPdata; diff --git a/source/blender/blenkernel/BKE_ipo.h b/source/blender/blenkernel/BKE_ipo.h index 40b9f738bfd..f4871c83caf 100644 --- a/source/blender/blenkernel/BKE_ipo.h +++ b/source/blender/blenkernel/BKE_ipo.h @@ -26,7 +26,6 @@ extern "C" { #endif -struct Ipo; struct Main; void do_versions_ipos_to_animato(struct Main *main); diff --git a/source/blender/blenkernel/BKE_lattice.h b/source/blender/blenkernel/BKE_lattice.h index f4c1a6fdcb4..02fa8b306d3 100644 --- a/source/blender/blenkernel/BKE_lattice.h +++ b/source/blender/blenkernel/BKE_lattice.h @@ -38,7 +38,6 @@ struct Main; struct Mesh; struct Object; struct Scene; -struct bGPDstroke; void BKE_lattice_resize(struct Lattice *lt, int u, int v, int w, struct Object *ltOb); struct Lattice *BKE_lattice_add(struct Main *bmain, const char *name); diff --git a/source/blender/blenkernel/BKE_lib_id.h b/source/blender/blenkernel/BKE_lib_id.h index 9f3536c9314..b0971278dc7 100644 --- a/source/blender/blenkernel/BKE_lib_id.h +++ b/source/blender/blenkernel/BKE_lib_id.h @@ -51,7 +51,6 @@ extern "C" { #endif -struct BlendDataReader; struct BlendWriter; struct GHash; struct ID; diff --git a/source/blender/blenkernel/BKE_lib_remap.h b/source/blender/blenkernel/BKE_lib_remap.h index fb14e340d8b..a8d75213d39 100644 --- a/source/blender/blenkernel/BKE_lib_remap.h +++ b/source/blender/blenkernel/BKE_lib_remap.h @@ -38,8 +38,6 @@ extern "C" { #endif -struct wmWindowManager; - /* BKE_libblock_free, delete are declared in BKE_lib_id.h for convenience. */ /* Also IDRemap->flag. */ diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index 0f34549a3cd..2d8dc852d7c 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -26,7 +26,6 @@ #include "BLI_utildefines.h" struct BLI_Stack; -struct BMEditMesh; struct BMesh; struct BMeshCreateParams; struct BMeshFromMeshParams; diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h index 0a50dde1874..f679533e1a9 100644 --- a/source/blender/blenkernel/BKE_paint.h +++ b/source/blender/blenkernel/BKE_paint.h @@ -55,7 +55,6 @@ struct Paint; struct PaintCurve; struct Palette; struct PaletteColor; -struct ReportList; struct Scene; struct StrokeCache; struct SubdivCCG; diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h index fd600a41796..0fa44067b16 100644 --- a/source/blender/blenkernel/BKE_pbvh.h +++ b/source/blender/blenkernel/BKE_pbvh.h @@ -48,7 +48,6 @@ struct PBVH; struct PBVHNode; struct SubdivCCG; struct TaskParallelSettings; -struct TaskParallelTLS; typedef struct PBVH PBVH; typedef struct PBVHNode PBVHNode; diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h index 473a684eaba..7b5df98d148 100644 --- a/source/blender/blenkernel/BKE_screen.h +++ b/source/blender/blenkernel/BKE_screen.h @@ -51,7 +51,6 @@ struct View3D; struct View3DShading; struct WorkSpace; struct bContext; -struct bContextDataResult; struct bScreen; struct uiLayout; struct uiList; diff --git a/source/blender/blenkernel/BKE_speaker.h b/source/blender/blenkernel/BKE_speaker.h index e288c9f3eb4..9defa887d3c 100644 --- a/source/blender/blenkernel/BKE_speaker.h +++ b/source/blender/blenkernel/BKE_speaker.h @@ -26,7 +26,6 @@ extern "C" { #endif struct Main; -struct Speaker; void *BKE_speaker_add(struct Main *bmain, const char *name); diff --git a/source/blender/blenkernel/intern/multires_unsubdivide.h b/source/blender/blenkernel/intern/multires_unsubdivide.h index 39c6da0b6c8..0a03387282f 100644 --- a/source/blender/blenkernel/intern/multires_unsubdivide.h +++ b/source/blender/blenkernel/intern/multires_unsubdivide.h @@ -26,10 +26,8 @@ #include "BLI_sys_types.h" struct BMesh; -struct Depsgraph; struct Mesh; struct MultiresModifierData; -struct Object; typedef struct MultiresUnsubdivideGrid { /* For sanity checks. */ diff --git a/source/blender/blenlib/BLI_threads.h b/source/blender/blenlib/BLI_threads.h index d19b5393aa7..eefde1afefb 100644 --- a/source/blender/blenlib/BLI_threads.h +++ b/source/blender/blenlib/BLI_threads.h @@ -35,7 +35,6 @@ extern "C" { #define BLENDER_MAX_THREADS 1024 struct ListBase; -struct TaskScheduler; /* Threading API */ diff --git a/source/blender/blenloader/intern/readfile.h b/source/blender/blenloader/intern/readfile.h index 3e7cdb30e1f..c724cc32051 100644 --- a/source/blender/blenloader/intern/readfile.h +++ b/source/blender/blenloader/intern/readfile.h @@ -34,16 +34,13 @@ #include "zlib.h" struct BLOCacheStorage; -struct GSet; struct IDNameLib_Map; struct Key; struct MemFile; struct Object; struct OldNewMap; -struct PartEff; struct ReportList; struct UserDef; -struct View3D; typedef struct IDNameLib_Map IDNameLib_Map; diff --git a/source/blender/depsgraph/DEG_depsgraph_build.h b/source/blender/depsgraph/DEG_depsgraph_build.h index f894bdabba4..4e618d8625d 100644 --- a/source/blender/depsgraph/DEG_depsgraph_build.h +++ b/source/blender/depsgraph/DEG_depsgraph_build.h @@ -39,7 +39,6 @@ struct Main; struct Object; struct Scene; struct Simulation; -struct ViewLayer; struct bNodeTree; #include "BLI_sys_types.h" diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.h b/source/blender/depsgraph/intern/builder/deg_builder_relations.h index cbfb51c59a6..5587379089c 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.h @@ -45,7 +45,6 @@ #include "intern/node/deg_node_id.h" #include "intern/node/deg_node_operation.h" -struct Base; struct CacheFile; struct Camera; struct Collection; diff --git a/source/blender/depsgraph/intern/eval/deg_eval_flush.h b/source/blender/depsgraph/intern/eval/deg_eval_flush.h index 1f58c54dbf4..ec661360fdf 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_flush.h +++ b/source/blender/depsgraph/intern/eval/deg_eval_flush.h @@ -25,8 +25,6 @@ #pragma once -struct Main; - namespace blender { namespace deg { diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.h b/source/blender/draw/engines/gpencil/gpencil_engine.h index 04128dc157e..d0bd56b42dd 100644 --- a/source/blender/draw/engines/gpencil/gpencil_engine.h +++ b/source/blender/draw/engines/gpencil/gpencil_engine.h @@ -39,10 +39,7 @@ extern DrawEngineType draw_engine_gpencil_type; struct GPENCIL_Data; struct GPENCIL_StorageList; struct GPUBatch; -struct GPUVertBuf; -struct GPUVertFormat; struct GpencilBatchCache; -struct MaterialGPencilStyle; struct Object; struct RenderEngine; struct RenderLayer; diff --git a/source/blender/draw/engines/image/image_private.h b/source/blender/draw/engines/image/image_private.h index d5821cc5d70..76a94e68da1 100644 --- a/source/blender/draw/engines/image/image_private.h +++ b/source/blender/draw/engines/image/image_private.h @@ -25,11 +25,9 @@ extern "C" { #endif /* Forward declarations */ -struct GPUBatch; struct GPUTexture; struct ImBuf; struct Image; -struct rcti; /* *********** LISTS *********** */ diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h index fbe71900915..4df2ba1e913 100644 --- a/source/blender/draw/intern/DRW_render.h +++ b/source/blender/draw/intern/DRW_render.h @@ -64,7 +64,6 @@ #include "DEG_depsgraph.h" struct GPUBatch; -struct GPUFrameBuffer; struct GPUMaterial; struct GPUShader; struct GPUTexture; diff --git a/source/blender/draw/intern/draw_common.h b/source/blender/draw/intern/draw_common.h index 23dd47d4ab5..a059ac32311 100644 --- a/source/blender/draw/intern/draw_common.h +++ b/source/blender/draw/intern/draw_common.h @@ -22,10 +22,8 @@ #pragma once -struct DRWPass; struct DRWShadingGroup; struct FluidModifierData; -struct GPUMaterial; struct ModifierData; struct Object; struct ParticleSystem; diff --git a/source/blender/editors/include/ED_armature.h b/source/blender/editors/include/ED_armature.h index 3501acd4fdf..0c4576096fb 100644 --- a/source/blender/editors/include/ED_armature.h +++ b/source/blender/editors/include/ED_armature.h @@ -31,7 +31,6 @@ struct Base; struct Bone; struct Depsgraph; struct EditBone; -struct IDProperty; struct ListBase; struct Main; struct Mesh; diff --git a/source/blender/editors/include/ED_gpencil.h b/source/blender/editors/include/ED_gpencil.h index be2f714dfe1..1b7caf27ecf 100644 --- a/source/blender/editors/include/ED_gpencil.h +++ b/source/blender/editors/include/ED_gpencil.h @@ -51,7 +51,6 @@ struct ScrArea; struct SnapObjectContext; struct ToolSettings; struct View3D; -struct ViewLayer; struct bContext; struct Material; diff --git a/source/blender/editors/include/ED_image.h b/source/blender/editors/include/ED_image.h index c1d3a17b9b6..b139b0765a3 100644 --- a/source/blender/editors/include/ED_image.h +++ b/source/blender/editors/include/ED_image.h @@ -34,12 +34,10 @@ struct ARegion; struct ImBuf; struct Image; struct ImageUser; -struct LinkNodePair; struct Main; struct ReportList; struct Scene; struct SpaceImage; -struct ViewLayer; struct bContext; struct wmOperator; struct wmWindowManager; diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h index 2e9b711c99a..f9358f62274 100644 --- a/source/blender/editors/include/ED_object.h +++ b/source/blender/editors/include/ED_object.h @@ -53,7 +53,6 @@ struct uiLayout; struct wmKeyConfig; struct wmOperator; struct wmOperatorType; -struct wmWindowManager; /* object_edit.c */ /* context.object */ diff --git a/source/blender/editors/include/ED_transform.h b/source/blender/editors/include/ED_transform.h index 0ea86e006e0..ca3e351a052 100644 --- a/source/blender/editors/include/ED_transform.h +++ b/source/blender/editors/include/ED_transform.h @@ -32,7 +32,6 @@ extern "C" { struct Object; struct bContext; struct wmKeyConfig; -struct wmMsgBus; struct wmOperatorType; void ED_keymap_transform(struct wmKeyConfig *keyconf); @@ -108,7 +107,6 @@ bool calculateTransformCenter(struct bContext *C, struct Object; struct Scene; -struct wmGizmoGroup; struct wmGizmoGroupType; /* UNUSED */ diff --git a/source/blender/editors/include/ED_transform_snap_object_context.h b/source/blender/editors/include/ED_transform_snap_object_context.h index ebaa32941f2..b7174964ef6 100644 --- a/source/blender/editors/include/ED_transform_snap_object_context.h +++ b/source/blender/editors/include/ED_transform_snap_object_context.h @@ -31,7 +31,6 @@ struct BMVert; struct ARegion; struct Depsgraph; struct ListBase; -struct Main; struct Object; struct Scene; struct View3D; diff --git a/source/blender/editors/include/ED_util_imbuf.h b/source/blender/editors/include/ED_util_imbuf.h index d142d3d6425..4bbaa68e849 100644 --- a/source/blender/editors/include/ED_util_imbuf.h +++ b/source/blender/editors/include/ED_util_imbuf.h @@ -31,7 +31,6 @@ extern "C" { #endif struct ARegion; -struct Main; struct bContext; struct wmEvent; struct wmOperator; diff --git a/source/blender/editors/include/ED_uvedit.h b/source/blender/editors/include/ED_uvedit.h index d08bc0b0b3d..4de97411059 100644 --- a/source/blender/editors/include/ED_uvedit.h +++ b/source/blender/editors/include/ED_uvedit.h @@ -33,7 +33,6 @@ struct BMEditMesh; struct BMFace; struct BMLoop; struct BMesh; -struct Depsgraph; struct Image; struct ImageUser; struct Main; diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index 13687bf0450..a4856845a65 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -41,8 +41,6 @@ struct Camera; struct CustomData_MeshMasks; struct Depsgraph; struct EditBone; -struct GPUOffScreen; -struct GPUViewport; struct ID; struct MVert; struct Main; @@ -55,7 +53,6 @@ struct RenderEngineType; struct Scene; struct ScrArea; struct View3D; -struct View3DShading; struct ViewContext; struct ViewLayer; struct bContext; @@ -64,8 +61,6 @@ struct bScreen; struct rctf; struct rcti; struct wmGizmo; -struct wmOperator; -struct wmOperatorType; struct wmWindow; struct wmWindowManager; diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 83e94664c0b..7c128cbf1e6 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -50,7 +50,6 @@ struct PointerRNA; struct PropertyRNA; struct ReportList; struct ResultBLF; -struct ScrArea; struct bContext; struct bContextStore; struct bNode; diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h index 175d98ba9aa..3ca0d853d6a 100644 --- a/source/blender/editors/sculpt_paint/paint_intern.h +++ b/source/blender/editors/sculpt_paint/paint_intern.h @@ -43,7 +43,6 @@ struct wmEvent; struct wmKeyConfig; struct wmOperator; struct wmOperatorType; -struct wmWindowManager; enum ePaintMode; enum ePaintSymmetryFlags; diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h index bd5ba15b493..853b221e92a 100644 --- a/source/blender/editors/sculpt_paint/sculpt_intern.h +++ b/source/blender/editors/sculpt_paint/sculpt_intern.h @@ -39,7 +39,6 @@ struct AutomaskingCache; struct KeyBlock; struct Object; -struct SculptPoseIKChainSegment; struct SculptUndoNode; struct bContext; diff --git a/source/blender/editors/space_buttons/buttons_intern.h b/source/blender/editors/space_buttons/buttons_intern.h index 0a0846cf216..74e7bc11c26 100644 --- a/source/blender/editors/space_buttons/buttons_intern.h +++ b/source/blender/editors/space_buttons/buttons_intern.h @@ -35,7 +35,6 @@ struct bContext; struct bContextDataResult; struct bNode; struct bNodeTree; -struct uiLayout; struct wmOperatorType; struct SpaceProperties_Runtime { diff --git a/source/blender/editors/space_outliner/tree/tree_element_nla.hh b/source/blender/editors/space_outliner/tree/tree_element_nla.hh index 3ca62b13bd8..c94287ce576 100644 --- a/source/blender/editors/space_outliner/tree/tree_element_nla.hh +++ b/source/blender/editors/space_outliner/tree/tree_element_nla.hh @@ -23,7 +23,6 @@ #include "tree_element.hh" struct NlaTrack; -struct NlaStrip; namespace blender::ed::outliner { diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index 227330e8524..91bf2bf8aac 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -52,12 +52,12 @@ struct SnapObjectContext; struct TransDataContainer; struct TransInfo; struct TransSnap; -struct TransformOrientation; struct ViewLayer; struct bContext; struct wmEvent; struct wmKeyConfig; struct wmKeyMap; +struct wmOperator; struct wmTimer; /** #TransInfo.redraw */ diff --git a/source/blender/editors/transform/transform_convert.h b/source/blender/editors/transform/transform_convert.h index b753572ea7b..59fcd016020 100644 --- a/source/blender/editors/transform/transform_convert.h +++ b/source/blender/editors/transform/transform_convert.h @@ -29,12 +29,9 @@ struct FCurve; struct ListBase; struct Object; struct TransData; -struct TransDataContainer; struct TransDataCurveHandleFlags; struct TransInfo; struct bContext; -struct bKinematicConstraint; -struct bPoseChannel; /* transform_convert.c */ void transform_autoik_update(TransInfo *t, short mode); diff --git a/source/blender/editors/transform/transform_snap.h b/source/blender/editors/transform/transform_snap.h index 5bee572c603..db8ec943bfd 100644 --- a/source/blender/editors/transform/transform_snap.h +++ b/source/blender/editors/transform/transform_snap.h @@ -25,8 +25,6 @@ /* For enum. */ #include "DNA_space_types.h" -struct SnapObjectParams; - bool peelObjectsTransform(struct TransInfo *t, const float mval[2], const bool use_peel_object, diff --git a/source/blender/editors/uvedit/uvedit_intern.h b/source/blender/editors/uvedit/uvedit_intern.h index 306f8a2c561..28567234fab 100644 --- a/source/blender/editors/uvedit/uvedit_intern.h +++ b/source/blender/editors/uvedit/uvedit_intern.h @@ -25,7 +25,6 @@ struct BMFace; struct BMLoop; -struct Image; struct Object; struct Scene; struct SpaceImage; diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.h b/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.h index e5a6d9e6a8f..30e54f44499 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.h +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.h @@ -23,9 +23,7 @@ #pragma once -struct GHash; struct MDeformVert; -struct Main; struct Material; struct Object; struct bGPDlayer; diff --git a/source/blender/gpu/GPU_shader.h b/source/blender/gpu/GPU_shader.h index 27a7ea1e6a5..55716b584c3 100644 --- a/source/blender/gpu/GPU_shader.h +++ b/source/blender/gpu/GPU_shader.h @@ -27,8 +27,6 @@ extern "C" { #endif -struct GPUTexture; -struct GPUUniformBuf; struct GPUVertBuf; /** Opaque type hidding blender::gpu::Shader */ diff --git a/source/blender/gpu/GPU_texture.h b/source/blender/gpu/GPU_texture.h index e9c081abd22..91119bd05a1 100644 --- a/source/blender/gpu/GPU_texture.h +++ b/source/blender/gpu/GPU_texture.h @@ -28,14 +28,6 @@ #include "GPU_state.h" struct GPUVertBuf; -struct ImBuf; -struct Image; -struct ImageUser; -struct MovieClip; -struct MovieClipUser; -struct PreviewImage; - -struct GPUFrameBuffer; /** Opaque type hiding blender::gpu::Texture. */ typedef struct GPUTexture GPUTexture; diff --git a/source/blender/gpu/intern/gpu_codegen.h b/source/blender/gpu/intern/gpu_codegen.h index 5d130d75d2c..f3d58a55814 100644 --- a/source/blender/gpu/intern/gpu_codegen.h +++ b/source/blender/gpu/intern/gpu_codegen.h @@ -31,10 +31,7 @@ extern "C" { struct GPUMaterial; struct GPUNodeGraph; -struct GPUOutput; struct GPUShader; -struct GSet; -struct ListBase; typedef struct GPUPass { struct GPUPass *next; diff --git a/source/blender/gpu/intern/gpu_node_graph.h b/source/blender/gpu/intern/gpu_node_graph.h index 0ef95d94c0d..929191cff73 100644 --- a/source/blender/gpu/intern/gpu_node_graph.h +++ b/source/blender/gpu/intern/gpu_node_graph.h @@ -33,8 +33,6 @@ struct GPUNode; struct GPUOutput; -struct GPUShader; -struct GPUVertAttrLayers; struct ListBase; typedef enum eGPUDataSource { diff --git a/source/blender/gpu/intern/gpu_uniform_buffer_private.hh b/source/blender/gpu/intern/gpu_uniform_buffer_private.hh index 00d10776864..18ea6d18caf 100644 --- a/source/blender/gpu/intern/gpu_uniform_buffer_private.hh +++ b/source/blender/gpu/intern/gpu_uniform_buffer_private.hh @@ -24,6 +24,8 @@ #include "BLI_sys_types.h" +struct GPUUniformBuf; + namespace blender { namespace gpu { diff --git a/source/blender/io/alembic/exporter/abc_hierarchy_iterator.h b/source/blender/io/alembic/exporter/abc_hierarchy_iterator.h index a0d9257b822..2098b8b2505 100644 --- a/source/blender/io/alembic/exporter/abc_hierarchy_iterator.h +++ b/source/blender/io/alembic/exporter/abc_hierarchy_iterator.h @@ -29,7 +29,6 @@ #include struct Depsgraph; -struct ID; struct Object; namespace blender::io::alembic { diff --git a/source/blender/io/alembic/exporter/abc_writer_abstract.h b/source/blender/io/alembic/exporter/abc_writer_abstract.h index d23e69cf73e..4997e498199 100644 --- a/source/blender/io/alembic/exporter/abc_writer_abstract.h +++ b/source/blender/io/alembic/exporter/abc_writer_abstract.h @@ -29,7 +29,6 @@ #include "DNA_material_types.h" struct IDProperty; -struct Material; struct Object; namespace blender::io::alembic { diff --git a/source/blender/io/alembic/exporter/abc_writer_hair.h b/source/blender/io/alembic/exporter/abc_writer_hair.h index 3759ffa4310..901fd70601f 100644 --- a/source/blender/io/alembic/exporter/abc_writer_hair.h +++ b/source/blender/io/alembic/exporter/abc_writer_hair.h @@ -23,9 +23,6 @@ #include #include -struct ParticleSettings; -struct ParticleSystem; - namespace blender::io::alembic { class ABCHairWriter : public ABCAbstractWriter { diff --git a/source/blender/io/alembic/intern/abc_reader_archive.h b/source/blender/io/alembic/intern/abc_reader_archive.h index 2a4fd6bd8fb..67000194aa1 100644 --- a/source/blender/io/alembic/intern/abc_reader_archive.h +++ b/source/blender/io/alembic/intern/abc_reader_archive.h @@ -28,7 +28,6 @@ #include struct Main; -struct Scene; namespace blender::io::alembic { diff --git a/source/blender/io/common/IO_abstract_hierarchy_iterator.h b/source/blender/io/common/IO_abstract_hierarchy_iterator.h index e066ca8ba8f..300c555ac8f 100644 --- a/source/blender/io/common/IO_abstract_hierarchy_iterator.h +++ b/source/blender/io/common/IO_abstract_hierarchy_iterator.h @@ -43,13 +43,11 @@ #include #include -struct Base; struct Depsgraph; struct DupliObject; struct ID; struct Object; struct ParticleSystem; -struct ViewLayer; namespace blender::io { diff --git a/source/blender/io/usd/intern/usd_exporter_context.h b/source/blender/io/usd/intern/usd_exporter_context.h index 41ff34b327e..66e87f0eed1 100644 --- a/source/blender/io/usd/intern/usd_exporter_context.h +++ b/source/blender/io/usd/intern/usd_exporter_context.h @@ -24,7 +24,6 @@ #include struct Depsgraph; -struct Object; namespace blender::io::usd { diff --git a/source/blender/io/usd/intern/usd_hierarchy_iterator.h b/source/blender/io/usd/intern/usd_hierarchy_iterator.h index 922ab761bd9..cd19becbb07 100644 --- a/source/blender/io/usd/intern/usd_hierarchy_iterator.h +++ b/source/blender/io/usd/intern/usd_hierarchy_iterator.h @@ -28,7 +28,6 @@ #include struct Depsgraph; -struct ID; struct Object; namespace blender::io::usd { diff --git a/source/blender/io/usd/intern/usd_writer_abstract.h b/source/blender/io/usd/intern/usd_writer_abstract.h index 6a3b8d515dc..2143164e3dd 100644 --- a/source/blender/io/usd/intern/usd_writer_abstract.h +++ b/source/blender/io/usd/intern/usd_writer_abstract.h @@ -33,7 +33,6 @@ #include "DNA_material_types.h" struct Material; -struct Object; namespace blender::io::usd { diff --git a/source/blender/io/usd/usd.h b/source/blender/io/usd/usd.h index b9ea90736ff..40e2d0d8674 100644 --- a/source/blender/io/usd/usd.h +++ b/source/blender/io/usd/usd.h @@ -25,7 +25,6 @@ extern "C" { #endif -struct Scene; struct bContext; struct USDExportParams { diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h index 04fbc030ed9..c2337b28e54 100644 --- a/source/blender/makesdna/DNA_mesh_types.h +++ b/source/blender/makesdna/DNA_mesh_types.h @@ -35,7 +35,6 @@ struct AnimData; struct BVHCache; struct Ipo; struct Key; -struct LinkNode; struct MCol; struct MEdge; struct MFace; @@ -44,7 +43,6 @@ struct MLoopCol; struct MLoopTri; struct MLoopUV; struct MPoly; -struct MPropCol; struct MVert; struct Material; struct Mesh; diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index 0a3a2cd0b64..25447d8f20a 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -38,9 +38,7 @@ extern "C" { struct AnimData; struct BoundBox; -struct DerivedMesh; struct FluidsimSettings; -struct GpencilBatchCache; struct Ipo; struct Material; struct Mesh; diff --git a/source/blender/python/BPY_extern.h b/source/blender/python/BPY_extern.h index 46b4dbc96d7..366d801a888 100644 --- a/source/blender/python/BPY_extern.h +++ b/source/blender/python/BPY_extern.h @@ -26,7 +26,6 @@ struct ID; /* DNA_ID.h */ struct ListBase; /* DNA_listBase.h */ struct Object; /* DNA_object_types.h */ struct PathResolvedRNA; -struct ReportList; struct Text; /* defined in DNA_text_types.h */ struct bConstraint; /* DNA_constraint_types.h */ struct bConstraintOb; /* DNA_constraint_types.h */ diff --git a/source/blender/sequencer/intern/multiview.h b/source/blender/sequencer/intern/multiview.h index e1f998d18e2..bbc66c6f84c 100644 --- a/source/blender/sequencer/intern/multiview.h +++ b/source/blender/sequencer/intern/multiview.h @@ -27,14 +27,7 @@ extern "C" { #endif -struct Editing; -struct ImBuf; -struct Main; -struct Mask; struct Scene; -struct Sequence; -struct StripColorBalance; -struct StripElem; /* ********************************************************************** * sequencer.c diff --git a/source/blender/sequencer/intern/prefetch.h b/source/blender/sequencer/intern/prefetch.h index aa47a9dbcfc..6b9d936133d 100644 --- a/source/blender/sequencer/intern/prefetch.h +++ b/source/blender/sequencer/intern/prefetch.h @@ -27,8 +27,6 @@ extern "C" { #endif -struct ImBuf; -struct Main; struct Scene; struct Sequence; struct SeqRenderData; diff --git a/source/blender/sequencer/intern/render.h b/source/blender/sequencer/intern/render.h index d5affeb547b..46748415187 100644 --- a/source/blender/sequencer/intern/render.h +++ b/source/blender/sequencer/intern/render.h @@ -27,7 +27,6 @@ extern "C" { #endif -struct Editing; struct ImBuf; struct ListBase; struct Scene; diff --git a/source/blender/sequencer/intern/utils.h b/source/blender/sequencer/intern/utils.h index fe6041ec5e8..f30ea753d37 100644 --- a/source/blender/sequencer/intern/utils.h +++ b/source/blender/sequencer/intern/utils.h @@ -28,7 +28,6 @@ extern "C" { #endif struct Scene; -struct anim; bool sequencer_seq_generates_image(struct Sequence *seq); void seq_open_anim_file(struct Scene *scene, struct Sequence *seq, bool openfile); diff --git a/source/blender/windowmanager/wm.h b/source/blender/windowmanager/wm.h index baa47098bd3..c26acfc9802 100644 --- a/source/blender/windowmanager/wm.h +++ b/source/blender/windowmanager/wm.h @@ -23,7 +23,6 @@ #pragma once -struct ARegion; struct ReportList; struct wmWindow; -- cgit v1.2.3 From a869a61c88e37ce8a16676162ef7db3c62449b46 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 16 Dec 2020 16:26:23 +1100 Subject: Cleanup: sort struct blocks --- source/blender/blenkernel/BKE_action.h | 4 ++-- source/blender/blenkernel/BKE_anim_visualization.h | 4 ++-- source/blender/blenkernel/BKE_asset.h | 2 +- source/blender/blenkernel/BKE_collision.h | 2 +- source/blender/blenkernel/BKE_constraint.h | 8 ++++---- source/blender/blenkernel/BKE_cryptomatte.h | 4 ++-- source/blender/blenkernel/BKE_geometry_set.h | 4 ++-- source/blender/blenkernel/BKE_geometry_set.hh | 4 ++-- source/blender/blenkernel/BKE_gpencil.h | 2 +- source/blender/blenkernel/BKE_gpencil_curve.h | 4 ++-- source/blender/blenkernel/BKE_gpencil_geom.h | 2 +- source/blender/blenkernel/BKE_gpencil_modifier.h | 6 +++--- source/blender/blenkernel/BKE_modifier.h | 2 +- source/blender/blenkernel/BKE_paint.h | 6 +++--- source/blender/blenkernel/BKE_particle.h | 2 +- source/blender/blenkernel/BKE_pointcache.h | 6 +++--- source/blender/blenkernel/BKE_shader_fx.h | 6 +++--- source/blender/draw/engines/eevee/eevee_lightcache.h | 4 ++-- source/blender/editors/include/ED_fileselect.h | 2 +- source/blender/editors/space_file/filelist.h | 2 +- source/blender/editors/space_outliner/outliner_intern.h | 2 +- source/blender/makesdna/DNA_gpencil_types.h | 2 +- source/blender/makesdna/DNA_node_types.h | 2 +- source/blender/makesdna/DNA_object_types.h | 2 +- source/blender/modifiers/MOD_nodes.h | 2 +- source/blender/sequencer/SEQ_sequencer.h | 6 +++--- source/blender/sequencer/intern/effects.h | 2 +- source/blender/sequencer/intern/image_cache.h | 2 +- source/blender/sequencer/intern/prefetch.h | 2 +- source/blender/sequencer/intern/proxy.h | 2 +- source/blender/sequencer/intern/strip_time.h | 2 +- 31 files changed, 51 insertions(+), 51 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h index d8605941974..717cfa607ad 100644 --- a/source/blender/blenkernel/BKE_action.h +++ b/source/blender/blenkernel/BKE_action.h @@ -30,10 +30,10 @@ extern "C" { #endif -struct BlendWriter; struct BlendDataReader; -struct BlendLibReader; struct BlendExpander; +struct BlendLibReader; +struct BlendWriter; struct bArmature; /* The following structures are defined in DNA_action_types.h, and DNA_anim_types.h */ diff --git a/source/blender/blenkernel/BKE_anim_visualization.h b/source/blender/blenkernel/BKE_anim_visualization.h index decb2e0b210..4e86abeed8d 100644 --- a/source/blender/blenkernel/BKE_anim_visualization.h +++ b/source/blender/blenkernel/BKE_anim_visualization.h @@ -26,14 +26,14 @@ extern "C" { #endif +struct BlendDataReader; +struct BlendWriter; struct Object; struct ReportList; struct Scene; struct bAnimVizSettings; struct bMotionPath; struct bPoseChannel; -struct BlendWriter; -struct BlendDataReader; /* ---------------------------------------------------- */ /* Animation Visualization */ diff --git a/source/blender/blenkernel/BKE_asset.h b/source/blender/blenkernel/BKE_asset.h index 20df6109c13..38cd5747343 100644 --- a/source/blender/blenkernel/BKE_asset.h +++ b/source/blender/blenkernel/BKE_asset.h @@ -27,8 +27,8 @@ extern "C" { #endif -struct BlendWriter; struct BlendDataReader; +struct BlendWriter; struct ID; struct PreviewImage; diff --git a/source/blender/blenkernel/BKE_collision.h b/source/blender/blenkernel/BKE_collision.h index a10a4e3c7fd..ff1bca896b1 100644 --- a/source/blender/blenkernel/BKE_collision.h +++ b/source/blender/blenkernel/BKE_collision.h @@ -26,9 +26,9 @@ extern "C" { #endif +struct BVHTree; struct Collection; struct CollisionModifierData; -struct BVHTree; struct Depsgraph; struct MVert; struct MVertTri; diff --git a/source/blender/blenkernel/BKE_constraint.h b/source/blender/blenkernel/BKE_constraint.h index 7a14787c191..afad1e26159 100644 --- a/source/blender/blenkernel/BKE_constraint.h +++ b/source/blender/blenkernel/BKE_constraint.h @@ -23,6 +23,10 @@ * \ingroup bke */ +struct BlendDataReader; +struct BlendExpander; +struct BlendLibReader; +struct BlendWriter; struct Depsgraph; struct ID; struct ListBase; @@ -31,10 +35,6 @@ struct Scene; struct bConstraint; struct bConstraintTarget; struct bPoseChannel; -struct BlendWriter; -struct BlendDataReader; -struct BlendLibReader; -struct BlendExpander; /* ---------------------------------------------------------------------------- */ #ifdef __cplusplus diff --git a/source/blender/blenkernel/BKE_cryptomatte.h b/source/blender/blenkernel/BKE_cryptomatte.h index d984b3824b1..433c25084ad 100644 --- a/source/blender/blenkernel/BKE_cryptomatte.h +++ b/source/blender/blenkernel/BKE_cryptomatte.h @@ -29,9 +29,9 @@ extern "C" { #endif -struct Object; -struct Material; struct Main; +struct Material; +struct Object; uint32_t BKE_cryptomatte_hash(const char *name, int name_len); uint32_t BKE_cryptomatte_object_hash(const struct Object *object); diff --git a/source/blender/blenkernel/BKE_geometry_set.h b/source/blender/blenkernel/BKE_geometry_set.h index 87bb96be145..37a3ed82bb8 100644 --- a/source/blender/blenkernel/BKE_geometry_set.h +++ b/source/blender/blenkernel/BKE_geometry_set.h @@ -24,9 +24,9 @@ extern "C" { #endif -struct Object; -struct GeometrySet; struct Collection; +struct GeometrySet; +struct Object; void BKE_geometry_set_free(struct GeometrySet *geometry_set); diff --git a/source/blender/blenkernel/BKE_geometry_set.hh b/source/blender/blenkernel/BKE_geometry_set.hh index 617e0c45ae4..90d444aa270 100644 --- a/source/blender/blenkernel/BKE_geometry_set.hh +++ b/source/blender/blenkernel/BKE_geometry_set.hh @@ -32,10 +32,10 @@ #include "BKE_attribute_access.hh" #include "BKE_geometry_set.h" +struct Collection; struct Mesh; -struct PointCloud; struct Object; -struct Collection; +struct PointCloud; /* Each geometry component has a specific type. The type determines what kind of data the component * stores. Functions modifying a geometry will usually just modify a subset of the component types. diff --git a/source/blender/blenkernel/BKE_gpencil.h b/source/blender/blenkernel/BKE_gpencil.h index 9177931cf9b..df5711f5120 100644 --- a/source/blender/blenkernel/BKE_gpencil.h +++ b/source/blender/blenkernel/BKE_gpencil.h @@ -42,11 +42,11 @@ struct SpaceImage; struct ToolSettings; struct ViewLayer; struct bDeformGroup; +struct bGPDcurve; struct bGPDframe; struct bGPDlayer; struct bGPDlayer_Mask; struct bGPDstroke; -struct bGPDcurve; struct bGPdata; #define GPENCIL_SIMPLIFY(scene) ((scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_ENABLE)) diff --git a/source/blender/blenkernel/BKE_gpencil_curve.h b/source/blender/blenkernel/BKE_gpencil_curve.h index 1821972469c..2d42bb36949 100644 --- a/source/blender/blenkernel/BKE_gpencil_curve.h +++ b/source/blender/blenkernel/BKE_gpencil_curve.h @@ -30,10 +30,10 @@ extern "C" { struct Main; struct Object; struct Scene; -struct bGPdata; +struct bGPDcurve; struct bGPDlayer; struct bGPDstroke; -struct bGPDcurve; +struct bGPdata; void BKE_gpencil_convert_curve(struct Main *bmain, struct Scene *scene, diff --git a/source/blender/blenkernel/BKE_gpencil_geom.h b/source/blender/blenkernel/BKE_gpencil_geom.h index 8cb7137e1f0..1c86df73d3c 100644 --- a/source/blender/blenkernel/BKE_gpencil_geom.h +++ b/source/blender/blenkernel/BKE_gpencil_geom.h @@ -32,11 +32,11 @@ struct Depsgraph; struct Main; struct Object; struct Scene; +struct bGPDcurve; struct bGPDframe; struct bGPDspoint; struct bGPDstroke; struct bGPdata; -struct bGPDcurve; /* Object boundbox. */ bool BKE_gpencil_data_minmax(const struct bGPdata *gpd, float r_min[3], float r_max[3]); diff --git a/source/blender/blenkernel/BKE_gpencil_modifier.h b/source/blender/blenkernel/BKE_gpencil_modifier.h index ccf65a585ef..61ccf3d60f6 100644 --- a/source/blender/blenkernel/BKE_gpencil_modifier.h +++ b/source/blender/blenkernel/BKE_gpencil_modifier.h @@ -27,6 +27,9 @@ extern "C" { #endif struct ARegionType; +struct BlendDataReader; +struct BlendLibReader; +struct BlendWriter; struct Depsgraph; struct GpencilModifierData; struct ID; @@ -35,9 +38,6 @@ struct Main; struct ModifierUpdateDepsgraphContext; struct Object; struct Scene; -struct BlendWriter; -struct BlendDataReader; -struct BlendLibReader; /* NOTE: bakeModifier() called from UI: * needs to create new data-blocks, hence the need for this. */ struct bGPDframe; diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h index 38b449cd92d..685a8ed98e2 100644 --- a/source/blender/blenkernel/BKE_modifier.h +++ b/source/blender/blenkernel/BKE_modifier.h @@ -35,6 +35,7 @@ struct BlendWriter; struct CustomData_MeshMasks; struct DepsNodeHandle; struct Depsgraph; +struct GeometrySet; struct ID; struct ListBase; struct Main; @@ -43,7 +44,6 @@ struct ModifierData; struct Object; struct Scene; struct bArmature; -struct GeometrySet; typedef enum { /* Should not be used, only for None modifier type */ diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h index f679533e1a9..aaed2649ad9 100644 --- a/source/blender/blenkernel/BKE_paint.h +++ b/source/blender/blenkernel/BKE_paint.h @@ -34,6 +34,9 @@ extern "C" { struct BMFace; struct BMesh; +struct BlendDataReader; +struct BlendLibReader; +struct BlendWriter; struct Brush; struct CurveMapping; struct Depsgraph; @@ -66,9 +69,6 @@ struct ViewLayer; struct bContext; struct bToolRef; struct tPaletteColorHSV; -struct BlendWriter; -struct BlendDataReader; -struct BlendLibReader; extern const char PAINT_CURSOR_SCULPT[3]; extern const char PAINT_CURSOR_VERTEX_PAINT[3]; diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index 2ac39be7eb3..3913ede9049 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -42,9 +42,9 @@ struct ParticleSystemModifierData; struct BVHTreeRay; struct BVHTreeRayHit; -struct BlendWriter; struct BlendDataReader; struct BlendLibReader; +struct BlendWriter; struct CustomData_MeshMasks; struct Depsgraph; struct EdgeHash; diff --git a/source/blender/blenkernel/BKE_pointcache.h b/source/blender/blenkernel/BKE_pointcache.h index d3ae043588d..170eb4ba662 100644 --- a/source/blender/blenkernel/BKE_pointcache.h +++ b/source/blender/blenkernel/BKE_pointcache.h @@ -77,7 +77,10 @@ extern "C" { #define PTCACHE_READ_OLD 3 /* Structs */ +struct BlendDataReader; +struct BlendWriter; struct ClothModifierData; +struct DynamicPaintSurface; struct FluidModifierData; struct ListBase; struct Main; @@ -89,9 +92,6 @@ struct RigidBodyWorld; struct Scene; struct SoftBody; struct ViewLayer; -struct BlendWriter; -struct BlendDataReader; -struct DynamicPaintSurface; /* temp structure for read/write */ typedef struct PTCacheData { diff --git a/source/blender/blenkernel/BKE_shader_fx.h b/source/blender/blenkernel/BKE_shader_fx.h index b5b5f61a6a6..23bd62c70bc 100644 --- a/source/blender/blenkernel/BKE_shader_fx.h +++ b/source/blender/blenkernel/BKE_shader_fx.h @@ -27,14 +27,14 @@ extern "C" { #endif struct ARegionType; +struct BlendDataReader; +struct BlendLibReader; +struct BlendWriter; struct ID; struct ListBase; struct ModifierUpdateDepsgraphContext; struct Object; struct ShaderFxData; -struct BlendWriter; -struct BlendDataReader; -struct BlendLibReader; #define SHADER_FX_ACTIVE(_fx, _is_render) \ ((((_fx)->mode & eShaderFxMode_Realtime) && (_is_render == false)) || \ diff --git a/source/blender/draw/engines/eevee/eevee_lightcache.h b/source/blender/draw/engines/eevee/eevee_lightcache.h index 17392c0de0b..fde0c80ab37 100644 --- a/source/blender/draw/engines/eevee/eevee_lightcache.h +++ b/source/blender/draw/engines/eevee/eevee_lightcache.h @@ -24,14 +24,14 @@ #include "BLI_sys_types.h" /* for bool */ +struct BlendDataReader; +struct BlendWriter; struct EEVEE_Data; struct EEVEE_ViewLayerData; struct LightCache; struct Scene; struct SceneEEVEE; struct ViewLayer; -struct BlendWriter; -struct BlendDataReader; /* Light Bake */ struct wmJob *EEVEE_lightbake_job_create(struct wmWindowManager *wm, diff --git a/source/blender/editors/include/ED_fileselect.h b/source/blender/editors/include/ED_fileselect.h index 3288cf11cb0..6c66a6162b8 100644 --- a/source/blender/editors/include/ED_fileselect.h +++ b/source/blender/editors/include/ED_fileselect.h @@ -28,8 +28,8 @@ extern "C" { #endif struct ARegion; -struct FileSelectParams; struct FileAssetSelectParams; +struct FileSelectParams; struct Scene; struct ScrArea; struct SpaceFile; diff --git a/source/blender/editors/space_file/filelist.h b/source/blender/editors/space_file/filelist.h index 59bd5bb50d7..16984bb6e43 100644 --- a/source/blender/editors/space_file/filelist.h +++ b/source/blender/editors/space_file/filelist.h @@ -29,8 +29,8 @@ extern "C" { struct BlendHandle; struct FileList; -struct FileSelection; struct FileSelectAssetLibraryUID; +struct FileSelection; struct wmWindowManager; struct FileDirEntry; diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h index ccb481197e4..339cc3068d0 100644 --- a/source/blender/editors/space_outliner/outliner_intern.h +++ b/source/blender/editors/space_outliner/outliner_intern.h @@ -32,7 +32,6 @@ extern "C" { /* internal exports only */ struct ARegion; -struct bContextDataResult; struct EditBone; struct ID; struct ListBase; @@ -43,6 +42,7 @@ struct TreeElement; struct TreeStoreElem; struct ViewLayer; struct bContext; +struct bContextDataResult; struct bPoseChannel; struct wmKeyConfig; struct wmOperatorType; diff --git a/source/blender/makesdna/DNA_gpencil_types.h b/source/blender/makesdna/DNA_gpencil_types.h index 212f0bfa1c9..949b0bb5bf5 100644 --- a/source/blender/makesdna/DNA_gpencil_types.h +++ b/source/blender/makesdna/DNA_gpencil_types.h @@ -32,8 +32,8 @@ extern "C" { #endif struct AnimData; -struct MDeformVert; struct Curve; +struct MDeformVert; #define GP_DEFAULT_PIX_FACTOR 1.0f #define GP_DEFAULT_GRID_LINES 4 diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index d512d8ffe34..9cf64743843 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -33,6 +33,7 @@ extern "C" { #endif struct AnimData; +struct Collection; struct ID; struct Image; struct ListBase; @@ -43,7 +44,6 @@ struct bNodePreview; struct bNodeTreeExec; struct bNodeType; struct uiBlock; -struct Collection; #define NODE_MAXSTR 64 diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index 25447d8f20a..8b13db8a012 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -39,6 +39,7 @@ extern "C" { struct AnimData; struct BoundBox; struct FluidsimSettings; +struct GeometrySet; struct Ipo; struct Material; struct Mesh; @@ -49,7 +50,6 @@ struct RigidBodyOb; struct SculptSession; struct SoftBody; struct bGPdata; -struct GeometrySet; /* Vertex Groups - Name Info */ typedef struct bDeformGroup { diff --git a/source/blender/modifiers/MOD_nodes.h b/source/blender/modifiers/MOD_nodes.h index 9c75e7e3416..907dbe9c5f4 100644 --- a/source/blender/modifiers/MOD_nodes.h +++ b/source/blender/modifiers/MOD_nodes.h @@ -17,8 +17,8 @@ #pragma once struct Main; -struct Object; struct NodesModifierData; +struct Object; #ifdef __cplusplus extern "C" { diff --git a/source/blender/sequencer/SEQ_sequencer.h b/source/blender/sequencer/SEQ_sequencer.h index a024d5e10d3..8c4863d98ed 100644 --- a/source/blender/sequencer/SEQ_sequencer.h +++ b/source/blender/sequencer/SEQ_sequencer.h @@ -27,6 +27,9 @@ extern "C" { #endif +struct BlendDataReader; +struct BlendLibReader; +struct BlendWriter; struct Depsgraph; struct Editing; struct GPUOffScreen; @@ -44,9 +47,6 @@ struct StripElem; struct TextVars; struct bContext; struct bSound; -struct BlendWriter; -struct BlendDataReader; -struct BlendLibReader; /* Wipe effect */ enum { diff --git a/source/blender/sequencer/intern/effects.h b/source/blender/sequencer/intern/effects.h index 58e0a97d4c5..6a94c0ea9d9 100644 --- a/source/blender/sequencer/intern/effects.h +++ b/source/blender/sequencer/intern/effects.h @@ -28,8 +28,8 @@ extern "C" { #endif struct Scene; -struct Sequence; struct SeqRenderData; +struct Sequence; /* ********************************************************************** * sequencer.c diff --git a/source/blender/sequencer/intern/image_cache.h b/source/blender/sequencer/intern/image_cache.h index 0fcf0548628..2cb35670a2c 100644 --- a/source/blender/sequencer/intern/image_cache.h +++ b/source/blender/sequencer/intern/image_cache.h @@ -30,8 +30,8 @@ extern "C" { struct ImBuf; struct Main; struct Scene; -struct Sequence; struct SeqRenderData; +struct Sequence; #ifdef __cplusplus } diff --git a/source/blender/sequencer/intern/prefetch.h b/source/blender/sequencer/intern/prefetch.h index 6b9d936133d..1633ee297f8 100644 --- a/source/blender/sequencer/intern/prefetch.h +++ b/source/blender/sequencer/intern/prefetch.h @@ -28,8 +28,8 @@ extern "C" { #endif struct Scene; -struct Sequence; struct SeqRenderData; +struct Sequence; #ifdef __cplusplus } diff --git a/source/blender/sequencer/intern/proxy.h b/source/blender/sequencer/intern/proxy.h index a362a318a5a..a65fdcd42fe 100644 --- a/source/blender/sequencer/intern/proxy.h +++ b/source/blender/sequencer/intern/proxy.h @@ -27,10 +27,10 @@ extern "C" { #endif -struct anim; struct ImBuf; struct SeqRenderData; struct Sequence; +struct anim; #define PROXY_MAXFILE (2 * FILE_MAXDIR + FILE_MAXFILE) struct ImBuf *seq_proxy_fetch(const struct SeqRenderData *context, diff --git a/source/blender/sequencer/intern/strip_time.h b/source/blender/sequencer/intern/strip_time.h index e435ff1ec5d..ca9a935bc96 100644 --- a/source/blender/sequencer/intern/strip_time.h +++ b/source/blender/sequencer/intern/strip_time.h @@ -27,9 +27,9 @@ extern "C" { #endif +struct ListBase; struct Scene; struct Sequence; -struct ListBase; float seq_give_frame_index(struct Sequence *seq, float timeline_frame); void seq_update_sound_bounds_recursive(struct Scene *scene, struct Sequence *metaseq); -- cgit v1.2.3 From d23a5b1d88df513aff1dc1ba09730221567f2857 Mon Sep 17 00:00:00 2001 From: Ankit Meel Date: Wed, 16 Dec 2020 13:02:28 +0530 Subject: BLI: constexpr Span, IndexRange, StringRef(Null/Base) Motivated by `std::string_view` being usable in const (compile-time) context. One functional change was needed for StringRef: `std::char_traits::length(str)` instead of `strlen`. Reviewed By: JacquesLucke, LazyDodo Differential Revision: https://developer.blender.org/D9788 --- source/blender/blenlib/BLI_index_range.hh | 45 ++++---- source/blender/blenlib/BLI_span.hh | 124 ++++++++++---------- source/blender/blenlib/BLI_string_ref.hh | 126 +++++++++++---------- .../blender/blenlib/tests/BLI_index_range_test.cc | 7 ++ source/blender/blenlib/tests/BLI_span_test.cc | 15 +++ .../blender/blenlib/tests/BLI_string_ref_test.cc | 8 ++ 6 files changed, 180 insertions(+), 145 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenlib/BLI_index_range.hh b/source/blender/blenlib/BLI_index_range.hh index 2b060c986cd..4121542c887 100644 --- a/source/blender/blenlib/BLI_index_range.hh +++ b/source/blender/blenlib/BLI_index_range.hh @@ -73,21 +73,22 @@ class IndexRange { int64_t size_ = 0; public: - IndexRange() = default; + constexpr IndexRange() = default; - explicit IndexRange(int64_t size) : start_(0), size_(size) + constexpr explicit IndexRange(int64_t size) : start_(0), size_(size) { BLI_assert(size >= 0); } - IndexRange(int64_t start, int64_t size) : start_(start), size_(size) + constexpr IndexRange(int64_t start, int64_t size) : start_(start), size_(size) { BLI_assert(start >= 0); BLI_assert(size >= 0); } template - IndexRange(const tbb::blocked_range &range) : start_(range.begin()), size_(range.size()) + constexpr IndexRange(const tbb::blocked_range &range) + : start_(range.begin()), size_(range.size()) { } @@ -96,33 +97,33 @@ class IndexRange { int64_t current_; public: - Iterator(int64_t current) : current_(current) + constexpr Iterator(int64_t current) : current_(current) { } - Iterator &operator++() + constexpr Iterator &operator++() { current_++; return *this; } - bool operator!=(const Iterator &iterator) const + constexpr bool operator!=(const Iterator &iterator) const { return current_ != iterator.current_; } - int64_t operator*() const + constexpr int64_t operator*() const { return current_; } }; - Iterator begin() const + constexpr Iterator begin() const { return Iterator(start_); } - Iterator end() const + constexpr Iterator end() const { return Iterator(start_ + size_); } @@ -130,7 +131,7 @@ class IndexRange { /** * Access an element in the range. */ - int64_t operator[](int64_t index) const + constexpr int64_t operator[](int64_t index) const { BLI_assert(index >= 0); BLI_assert(index < this->size()); @@ -140,7 +141,7 @@ class IndexRange { /** * Two ranges compare equal when they contain the same numbers. */ - friend bool operator==(IndexRange a, IndexRange b) + constexpr friend bool operator==(IndexRange a, IndexRange b) { return (a.size_ == b.size_) && (a.start_ == b.start_ || a.size_ == 0); } @@ -148,7 +149,7 @@ class IndexRange { /** * Get the amount of numbers in the range. */ - int64_t size() const + constexpr int64_t size() const { return size_; } @@ -156,7 +157,7 @@ class IndexRange { /** * Create a new range starting at the end of the current one. */ - IndexRange after(int64_t n) const + constexpr IndexRange after(int64_t n) const { BLI_assert(n >= 0); return IndexRange(start_ + size_, n); @@ -165,7 +166,7 @@ class IndexRange { /** * Create a new range that ends at the start of the current one. */ - IndexRange before(int64_t n) const + constexpr IndexRange before(int64_t n) const { BLI_assert(n >= 0); return IndexRange(start_ - n, n); @@ -175,7 +176,7 @@ class IndexRange { * Get the first element in the range. * Asserts when the range is empty. */ - int64_t first() const + constexpr int64_t first() const { BLI_assert(this->size() > 0); return start_; @@ -185,7 +186,7 @@ class IndexRange { * Get the last element in the range. * Asserts when the range is empty. */ - int64_t last() const + constexpr int64_t last() const { BLI_assert(this->size() > 0); return start_ + size_ - 1; @@ -194,7 +195,7 @@ class IndexRange { /** * Get the element one after the end. The returned value is undefined when the range is empty. */ - int64_t one_after_last() const + constexpr int64_t one_after_last() const { return start_ + size_; } @@ -202,7 +203,7 @@ class IndexRange { /** * Get the first element in the range. The returned value is undefined when the range is empty. */ - int64_t start() const + constexpr int64_t start() const { return start_; } @@ -210,7 +211,7 @@ class IndexRange { /** * Returns true when the range contains a certain number, otherwise false. */ - bool contains(int64_t value) const + constexpr bool contains(int64_t value) const { return value >= start_ && value < start_ + size_; } @@ -218,7 +219,7 @@ class IndexRange { /** * Returns a new range, that contains a sub-interval of the current one. */ - IndexRange slice(int64_t start, int64_t size) const + constexpr IndexRange slice(int64_t start, int64_t size) const { BLI_assert(start >= 0); BLI_assert(size >= 0); @@ -226,7 +227,7 @@ class IndexRange { BLI_assert(new_start + size <= start_ + size_ || size == 0); return IndexRange(new_start, size); } - IndexRange slice(IndexRange range) const + constexpr IndexRange slice(IndexRange range) const { return this->slice(range.start(), range.size()); } diff --git a/source/blender/blenlib/BLI_span.hh b/source/blender/blenlib/BLI_span.hh index 5b4d2769f57..3f410efe908 100644 --- a/source/blender/blenlib/BLI_span.hh +++ b/source/blender/blenlib/BLI_span.hh @@ -93,15 +93,15 @@ template class Span { /** * Create a reference to an empty array. */ - Span() = default; + constexpr Span() = default; - Span(const T *start, int64_t size) : data_(start), size_(size) + constexpr Span(const T *start, int64_t size) : data_(start), size_(size) { BLI_assert(size >= 0); } template> * = nullptr> - Span(const U *start, int64_t size) : data_(static_cast(start)), size_(size) + constexpr Span(const U *start, int64_t size) : data_(static_cast(start)), size_(size) { BLI_assert(size >= 0); } @@ -117,16 +117,17 @@ template class Span { * Span span = {1, 2, 3, 4}; * call_function_with_array(span); */ - Span(const std::initializer_list &list) + constexpr Span(const std::initializer_list &list) : Span(list.begin(), static_cast(list.size())) { } - Span(const std::vector &vector) : Span(vector.data(), static_cast(vector.size())) + constexpr Span(const std::vector &vector) + : Span(vector.data(), static_cast(vector.size())) { } - template Span(const std::array &array) : Span(array.data(), N) + template constexpr Span(const std::array &array) : Span(array.data(), N) { } @@ -135,7 +136,7 @@ template class Span { * Span -> Span */ template> * = nullptr> - Span(Span array) : data_(static_cast(array.data())), size_(array.size()) + constexpr Span(Span array) : data_(static_cast(array.data())), size_(array.size()) { } @@ -143,7 +144,7 @@ template class Span { * Returns a contiguous part of the array. This invokes undefined behavior when the slice does * not stay within the bounds of the array. */ - Span slice(int64_t start, int64_t size) const + constexpr Span slice(int64_t start, int64_t size) const { BLI_assert(start >= 0); BLI_assert(size >= 0); @@ -151,7 +152,7 @@ template class Span { return Span(data_ + start, size); } - Span slice(IndexRange range) const + constexpr Span slice(IndexRange range) const { return this->slice(range.start(), range.size()); } @@ -160,7 +161,7 @@ template class Span { * Returns a new Span with n elements removed from the beginning. This invokes undefined * behavior when the array is too small. */ - Span drop_front(int64_t n) const + constexpr Span drop_front(int64_t n) const { BLI_assert(n >= 0); BLI_assert(n <= this->size()); @@ -171,7 +172,7 @@ template class Span { * Returns a new Span with n elements removed from the beginning. This invokes undefined * behavior when the array is too small. */ - Span drop_back(int64_t n) const + constexpr Span drop_back(int64_t n) const { BLI_assert(n >= 0); BLI_assert(n <= this->size()); @@ -182,7 +183,7 @@ template class Span { * Returns a new Span that only contains the first n elements. This invokes undefined * behavior when the array is too small. */ - Span take_front(int64_t n) const + constexpr Span take_front(int64_t n) const { BLI_assert(n >= 0); BLI_assert(n <= this->size()); @@ -193,7 +194,7 @@ template class Span { * Returns a new Span that only contains the last n elements. This invokes undefined * behavior when the array is too small. */ - Span take_back(int64_t n) const + constexpr Span take_back(int64_t n) const { BLI_assert(n >= 0); BLI_assert(n <= this->size()); @@ -204,25 +205,25 @@ template class Span { * Returns the pointer to the beginning of the referenced array. This may be nullptr when the * size is zero. */ - const T *data() const + constexpr const T *data() const { return data_; } - const T *begin() const + constexpr const T *begin() const { return data_; } - const T *end() const + constexpr const T *end() const { return data_ + size_; } - std::reverse_iterator rbegin() const + constexpr std::reverse_iterator rbegin() const { return std::reverse_iterator(this->end()); } - std::reverse_iterator rend() const + constexpr std::reverse_iterator rend() const { return std::reverse_iterator(this->begin()); } @@ -231,7 +232,7 @@ template class Span { * Access an element in the array. This invokes undefined behavior when the index is out of * bounds. */ - const T &operator[](int64_t index) const + constexpr const T &operator[](int64_t index) const { BLI_assert(index >= 0); BLI_assert(index < size_); @@ -241,7 +242,7 @@ template class Span { /** * Returns the number of elements in the referenced array. */ - int64_t size() const + constexpr int64_t size() const { return size_; } @@ -249,7 +250,7 @@ template class Span { /** * Returns true if the size is zero. */ - bool is_empty() const + constexpr bool is_empty() const { return size_ == 0; } @@ -257,7 +258,7 @@ template class Span { /** * Returns the number of bytes referenced by this Span. */ - int64_t size_in_bytes() const + constexpr int64_t size_in_bytes() const { return sizeof(T) * size_; } @@ -266,7 +267,7 @@ template class Span { * Does a linear search to see of the value is in the array. * Returns true if it is, otherwise false. */ - bool contains(const T &value) const + constexpr bool contains(const T &value) const { for (const T &element : *this) { if (element == value) { @@ -280,7 +281,7 @@ template class Span { * Does a constant time check to see if the pointer points to a value in the referenced array. * Return true if it is, otherwise false. */ - bool contains_ptr(const T *ptr) const + constexpr bool contains_ptr(const T *ptr) const { return (this->begin() <= ptr) && (ptr < this->end()); } @@ -289,7 +290,7 @@ template class Span { * Does a linear search to count how often the value is in the array. * Returns the number of occurrences. */ - int64_t count(const T &value) const + constexpr int64_t count(const T &value) const { int64_t counter = 0; for (const T &element : *this) { @@ -304,7 +305,7 @@ template class Span { * Return a reference to the first element in the array. This invokes undefined behavior when the * array is empty. */ - const T &first() const + constexpr const T &first() const { BLI_assert(size_ > 0); return data_[0]; @@ -314,7 +315,7 @@ template class Span { * Returns a reference to the last element in the array. This invokes undefined behavior when the * array is empty. */ - const T &last() const + constexpr const T &last() const { BLI_assert(size_ > 0); return data_[size_ - 1]; @@ -324,7 +325,7 @@ template class Span { * Returns the element at the given index. If the index is out of range, return the fallback * value. */ - T get(int64_t index, const T &fallback) const + constexpr T get(int64_t index, const T &fallback) const { if (index < size_ && index >= 0) { return data_[index]; @@ -336,7 +337,7 @@ template class Span { * Check if the array contains duplicates. Does a linear search for every element. So the total * running time is O(n^2). Only use this for small arrays. */ - bool has_duplicates__linear_search() const + constexpr bool has_duplicates__linear_search() const { /* The size should really be smaller than that. If it is not, the calling code should be * changed. */ @@ -358,7 +359,7 @@ template class Span { * called on small arrays, because it has a running time of O(n*m) where n and m are the sizes of * the arrays. */ - bool intersects__linear_search(Span other) const + constexpr bool intersects__linear_search(Span other) const { /* The size should really be smaller than that. If it is not, the calling code should be * changed. */ @@ -377,7 +378,7 @@ template class Span { * Returns the index of the first occurrence of the given value. This invokes undefined behavior * when the value is not in the array. */ - int64_t first_index(const T &search_value) const + constexpr int64_t first_index(const T &search_value) const { const int64_t index = this->first_index_try(search_value); BLI_assert(index >= 0); @@ -387,7 +388,7 @@ template class Span { /** * Returns the index of the first occurrence of the given value or -1 if it does not exist. */ - int64_t first_index_try(const T &search_value) const + constexpr int64_t first_index_try(const T &search_value) const { for (int64_t i = 0; i < size_; i++) { if (data_[i] == search_value) { @@ -401,7 +402,7 @@ template class Span { * Utility to make it more convenient to iterate over all indices that can be used with this * array. */ - IndexRange index_range() const + constexpr IndexRange index_range() const { return IndexRange(size_); } @@ -409,7 +410,7 @@ template class Span { /** * Returns a new Span to the same underlying memory buffer. No conversions are done. */ - template Span cast() const + template Span constexpr cast() const { BLI_assert((size_ * sizeof(T)) % sizeof(NewT) == 0); int64_t new_size = size_ * sizeof(T) / sizeof(NewT); @@ -450,21 +451,22 @@ template class MutableSpan { int64_t size_; public: - MutableSpan() = default; + constexpr MutableSpan() = default; - MutableSpan(T *start, const int64_t size) : data_(start), size_(size) + constexpr MutableSpan(T *start, const int64_t size) : data_(start), size_(size) { } - MutableSpan(std::vector &vector) : MutableSpan(vector.data(), vector.size()) + constexpr MutableSpan(std::vector &vector) : MutableSpan(vector.data(), vector.size()) { } - template MutableSpan(std::array &array) : MutableSpan(array.data(), N) + template + constexpr MutableSpan(std::array &array) : MutableSpan(array.data(), N) { } - operator Span() const + constexpr operator Span() const { return Span(data_, size_); } @@ -472,7 +474,7 @@ template class MutableSpan { /** * Returns the number of elements in the array. */ - int64_t size() const + constexpr int64_t size() const { return size_; } @@ -480,7 +482,7 @@ template class MutableSpan { /** * Replace all elements in the referenced array with the given value. */ - void fill(const T &value) + constexpr void fill(const T &value) { initialized_fill_n(data_, size_, value); } @@ -489,7 +491,7 @@ template class MutableSpan { * Replace a subset of all elements with the given value. This invokes undefined behavior when * one of the indices is out of bounds. */ - void fill_indices(Span indices, const T &value) + constexpr void fill_indices(Span indices, const T &value) { for (int64_t i : indices) { BLI_assert(i < size_); @@ -501,30 +503,30 @@ template class MutableSpan { * Returns a pointer to the beginning of the referenced array. This may be nullptr, when the size * is zero. */ - T *data() const + constexpr T *data() const { return data_; } - T *begin() const + constexpr T *begin() const { return data_; } - T *end() const + constexpr T *end() const { return data_ + size_; } - std::reverse_iterator rbegin() const + constexpr std::reverse_iterator rbegin() const { return std::reverse_iterator(this->end()); } - std::reverse_iterator rend() const + constexpr std::reverse_iterator rend() const { return std::reverse_iterator(this->begin()); } - T &operator[](const int64_t index) const + constexpr T &operator[](const int64_t index) const { BLI_assert(index < this->size()); return data_[index]; @@ -534,7 +536,7 @@ template class MutableSpan { * Returns a contiguous part of the array. This invokes undefined behavior when the slice would * go out of bounds. */ - MutableSpan slice(const int64_t start, const int64_t length) const + constexpr MutableSpan slice(const int64_t start, const int64_t length) const { BLI_assert(start + length <= this->size()); return MutableSpan(data_ + start, length); @@ -544,7 +546,7 @@ template class MutableSpan { * Returns a new MutableSpan with n elements removed from the beginning. This invokes * undefined behavior when the array is too small. */ - MutableSpan drop_front(const int64_t n) const + constexpr MutableSpan drop_front(const int64_t n) const { BLI_assert(n <= this->size()); return this->slice(n, this->size() - n); @@ -554,7 +556,7 @@ template class MutableSpan { * Returns a new MutableSpan with n elements removed from the end. This invokes undefined * behavior when the array is too small. */ - MutableSpan drop_back(const int64_t n) const + constexpr MutableSpan drop_back(const int64_t n) const { BLI_assert(n <= this->size()); return this->slice(0, this->size() - n); @@ -564,7 +566,7 @@ template class MutableSpan { * Returns a new MutableSpan that only contains the first n elements. This invokes undefined * behavior when the array is too small. */ - MutableSpan take_front(const int64_t n) const + constexpr MutableSpan take_front(const int64_t n) const { BLI_assert(n <= this->size()); return this->slice(0, n); @@ -574,7 +576,7 @@ template class MutableSpan { * Return a new MutableSpan that only contains the last n elements. This invokes undefined * behavior when the array is too small. */ - MutableSpan take_back(const int64_t n) const + constexpr MutableSpan take_back(const int64_t n) const { BLI_assert(n <= this->size()); return this->slice(this->size() - n, n); @@ -584,7 +586,7 @@ template class MutableSpan { * Returns an (immutable) Span that references the same array. This is usually not needed, * due to implicit conversions. However, sometimes automatic type deduction needs some help. */ - Span as_span() const + constexpr Span as_span() const { return Span(data_, size_); } @@ -593,7 +595,7 @@ template class MutableSpan { * Utility to make it more convenient to iterate over all indices that can be used with this * array. */ - IndexRange index_range() const + constexpr IndexRange index_range() const { return IndexRange(size_); } @@ -602,7 +604,7 @@ template class MutableSpan { * Returns a reference to the last element. This invokes undefined behavior when the array is * empty. */ - T &last() const + constexpr T &last() const { BLI_assert(size_ > 0); return data_[size_ - 1]; @@ -612,7 +614,7 @@ template class MutableSpan { * Does a linear search to count how often the value is in the array. * Returns the number of occurrences. */ - int64_t count(const T &value) const + constexpr int64_t count(const T &value) const { int64_t counter = 0; for (const T &element : *this) { @@ -628,7 +630,7 @@ template class MutableSpan { * destination contains uninitialized data and T is not trivially copy constructible. * The size of both spans is expected to be the same. */ - void copy_from(Span values) + constexpr void copy_from(Span values) { BLI_assert(size_ == values.size()); initialized_copy_n(values.data(), size_, data_); @@ -637,7 +639,7 @@ template class MutableSpan { /** * Returns a new span to the same underlying memory buffer. No conversions are done. */ - template MutableSpan cast() const + template constexpr MutableSpan cast() const { BLI_assert((size_ * sizeof(T)) % sizeof(NewT) == 0); int64_t new_size = size_ * sizeof(T) / sizeof(NewT); @@ -648,7 +650,7 @@ template class MutableSpan { /** * Utilities to check that arrays have the same size in debug builds. */ -template void assert_same_size(const T1 &v1, const T2 &v2) +template constexpr void assert_same_size(const T1 &v1, const T2 &v2) { UNUSED_VARS_NDEBUG(v1, v2); #ifdef DEBUG @@ -659,7 +661,7 @@ template void assert_same_size(const T1 &v1, const T2 } template -void assert_same_size(const T1 &v1, const T2 &v2, const T3 &v3) +constexpr void assert_same_size(const T1 &v1, const T2 &v2, const T3 &v3) { UNUSED_VARS_NDEBUG(v1, v2, v3); #ifdef DEBUG diff --git a/source/blender/blenlib/BLI_string_ref.hh b/source/blender/blenlib/BLI_string_ref.hh index 8597e54d03b..a2562c6100a 100644 --- a/source/blender/blenlib/BLI_string_ref.hh +++ b/source/blender/blenlib/BLI_string_ref.hh @@ -64,7 +64,7 @@ class StringRefBase { const char *data_; int64_t size_; - StringRefBase(const char *data, const int64_t size) : data_(data), size_(size) + constexpr StringRefBase(const char *data, const int64_t size) : data_(data), size_(size) { } @@ -75,12 +75,12 @@ class StringRefBase { /** * Return the (byte-)length of the referenced string, without any null-terminator. */ - int64_t size() const + constexpr int64_t size() const { return size_; } - bool is_empty() const + constexpr bool is_empty() const { return size_ == 0; } @@ -88,12 +88,12 @@ class StringRefBase { /** * Return a pointer to the start of the string. */ - const char *data() const + constexpr const char *data() const { return data_; } - operator Span() const + constexpr operator Span() const { return Span(data_, size_); } @@ -107,22 +107,22 @@ class StringRefBase { return std::string(data_, static_cast(size_)); } - operator std::string_view() const + constexpr operator std::string_view() const { return std::string_view(data_, static_cast(size_)); } - const char *begin() const + constexpr const char *begin() const { return data_; } - const char *end() const + constexpr const char *end() const { return data_ + size_; } - IndexRange index_range() const + constexpr IndexRange index_range() const { return IndexRange(size_); } @@ -165,19 +165,19 @@ class StringRefBase { /** * Returns true when the string begins with the given prefix. Otherwise false. */ - bool startswith(StringRef prefix) const; + constexpr bool startswith(StringRef prefix) const; /** * Returns true when the string ends with the given suffix. Otherwise false. */ - bool endswith(StringRef suffix) const; + constexpr bool endswith(StringRef suffix) const; - StringRef substr(int64_t start, const int64_t size) const; + constexpr StringRef substr(int64_t start, const int64_t size) const; /** * Get the first char in the string. This invokes undefined behavior when the string is empty. */ - const char &front() const + constexpr const char &front() const { BLI_assert(size_ >= 1); return data_[0]; @@ -186,7 +186,7 @@ class StringRefBase { /** * Get the last char in the string. This invokes undefined behavior when the string is empty. */ - const char &back() const + constexpr const char &back() const { BLI_assert(size_ >= 1); return data_[size_ - 1]; @@ -196,18 +196,18 @@ class StringRefBase { * The behavior of those functions matches the standard library implementation of * std::string_view. */ - int64_t find(char c, int64_t pos = 0) const; - int64_t find(StringRef str, int64_t pos = 0) const; - int64_t rfind(char c, int64_t pos = INT64_MAX) const; - int64_t rfind(StringRef str, int64_t pos = INT64_MAX) const; - int64_t find_first_of(StringRef chars, int64_t pos = 0) const; - int64_t find_first_of(char c, int64_t pos = 0) const; - int64_t find_last_of(StringRef chars, int64_t pos = INT64_MAX) const; - int64_t find_last_of(char c, int64_t pos = INT64_MAX) const; - int64_t find_first_not_of(StringRef chars, int64_t pos = 0) const; - int64_t find_first_not_of(char c, int64_t pos = 0) const; - int64_t find_last_not_of(StringRef chars, int64_t pos = INT64_MAX) const; - int64_t find_last_not_of(char c, int64_t pos = INT64_MAX) const; + constexpr int64_t find(char c, int64_t pos = 0) const; + constexpr int64_t find(StringRef str, int64_t pos = 0) const; + constexpr int64_t rfind(char c, int64_t pos = INT64_MAX) const; + constexpr int64_t rfind(StringRef str, int64_t pos = INT64_MAX) const; + constexpr int64_t find_first_of(StringRef chars, int64_t pos = 0) const; + constexpr int64_t find_first_of(char c, int64_t pos = 0) const; + constexpr int64_t find_last_of(StringRef chars, int64_t pos = INT64_MAX) const; + constexpr int64_t find_last_of(char c, int64_t pos = INT64_MAX) const; + constexpr int64_t find_first_not_of(StringRef chars, int64_t pos = 0) const; + constexpr int64_t find_first_not_of(char c, int64_t pos = 0) const; + constexpr int64_t find_last_not_of(StringRef chars, int64_t pos = INT64_MAX) const; + constexpr int64_t find_last_not_of(char c, int64_t pos = INT64_MAX) const; }; /** @@ -216,7 +216,7 @@ class StringRefBase { class StringRefNull : public StringRefBase { public: - StringRefNull() : StringRefBase("", 0) + constexpr StringRefNull() : StringRefBase("", 0) { } @@ -226,7 +226,7 @@ class StringRefNull : public StringRefBase { */ StringRefNull(const char *str) : StringRefBase(str, static_cast(strlen(str))) { - BLI_assert(str != NULL); + BLI_assert(str != nullptr); BLI_assert(data_[size_] == '\0'); } @@ -234,7 +234,7 @@ class StringRefNull : public StringRefBase { * Construct a StringRefNull from a null terminated c-string. This invokes undefined behavior * when the given size is not the correct size of the string. */ - StringRefNull(const char *str, const int64_t size) : StringRefBase(str, size) + constexpr StringRefNull(const char *str, const int64_t size) : StringRefBase(str, size) { BLI_assert(static_cast(strlen(str)) == size); } @@ -250,7 +250,7 @@ class StringRefNull : public StringRefBase { /** * Get the char at the given index. */ - char operator[](const int64_t index) const + constexpr char operator[](const int64_t index) const { BLI_assert(index >= 0); /* Use '<=' instead of just '<', so that the null character can be accessed as well. */ @@ -263,7 +263,7 @@ class StringRefNull : public StringRefBase { * * This is like ->data(), but can only be called on a StringRefNull. */ - const char *c_str() const + constexpr const char *c_str() const { return data_; } @@ -274,25 +274,26 @@ class StringRefNull : public StringRefBase { */ class StringRef : public StringRefBase { public: - StringRef() : StringRefBase(nullptr, 0) + constexpr StringRef() : StringRefBase(nullptr, 0) { } /** * StringRefNull can be converted into StringRef, but not the other way around. */ - StringRef(StringRefNull other) : StringRefBase(other.data(), other.size()) + constexpr StringRef(StringRefNull other) : StringRefBase(other.data(), other.size()) { } /** * Create a StringRef from a null-terminated c-string. */ - StringRef(const char *str) : StringRefBase(str, str ? static_cast(strlen(str)) : 0) + constexpr StringRef(const char *str) + : StringRefBase(str, str ? static_cast(std::char_traits::length(str)) : 0) { } - StringRef(const char *str, const int64_t length) : StringRefBase(str, length) + constexpr StringRef(const char *str, const int64_t length) : StringRefBase(str, length) { } @@ -300,7 +301,7 @@ class StringRef : public StringRefBase { * Create a StringRef from a start and end pointer. This invokes undefined behavior when the * second point points to a smaller address than the first one. */ - StringRef(const char *begin, const char *one_after_end) + constexpr StringRef(const char *begin, const char *one_after_end) : StringRefBase(begin, static_cast(one_after_end - begin)) { BLI_assert(begin <= one_after_end); @@ -314,7 +315,8 @@ class StringRef : public StringRefBase { { } - StringRef(std::string_view view) : StringRefBase(view.data(), static_cast(view.size())) + constexpr StringRef(std::string_view view) + : StringRefBase(view.data(), static_cast(view.size())) { } @@ -323,7 +325,7 @@ class StringRef : public StringRefBase { * * This is similar to std::string_view::remove_prefix. */ - StringRef drop_prefix(const int64_t n) const + constexpr StringRef drop_prefix(const int64_t n) const { BLI_assert(n >= 0); BLI_assert(n <= size_); @@ -334,7 +336,7 @@ class StringRef : public StringRefBase { * Return a new StringRef with the given prefix being skipped. This invokes undefined behavior if * the string does not begin with the given prefix. */ - StringRef drop_prefix(StringRef prefix) const + constexpr StringRef drop_prefix(StringRef prefix) const { BLI_assert(this->startswith(prefix)); return this->drop_prefix(prefix.size()); @@ -345,7 +347,7 @@ class StringRef : public StringRefBase { * * This is similar to std::string_view::remove_suffix. */ - StringRef drop_suffix(const int64_t n) const + constexpr StringRef drop_suffix(const int64_t n) const { BLI_assert(n >= 0); BLI_assert(n <= size_); @@ -355,7 +357,7 @@ class StringRef : public StringRefBase { /** * Get the char at the given index. */ - char operator[](int64_t index) const + constexpr char operator[](int64_t index) const { BLI_assert(index >= 0); BLI_assert(index < size_); @@ -391,7 +393,7 @@ inline std::string operator+(StringRef a, StringRef b) * not a problem when std::string_view is only used at api boundaries. To compare a StringRef and a * std::string_view, one should convert the std::string_view to StringRef (which is very cheap). * Ideally, we only use StringRef in our code to avoid this problem altogether. */ -inline bool operator==(StringRef a, StringRef b) +constexpr inline bool operator==(StringRef a, StringRef b) { if (a.size() != b.size()) { return false; @@ -399,27 +401,27 @@ inline bool operator==(StringRef a, StringRef b) return STREQLEN(a.data(), b.data(), (size_t)a.size()); } -inline bool operator!=(StringRef a, StringRef b) +constexpr inline bool operator!=(StringRef a, StringRef b) { return !(a == b); } -inline bool operator<(StringRef a, StringRef b) +constexpr inline bool operator<(StringRef a, StringRef b) { return std::string_view(a) < std::string_view(b); } -inline bool operator>(StringRef a, StringRef b) +constexpr inline bool operator>(StringRef a, StringRef b) { return std::string_view(a) > std::string_view(b); } -inline bool operator<=(StringRef a, StringRef b) +constexpr inline bool operator<=(StringRef a, StringRef b) { return std::string_view(a) <= std::string_view(b); } -inline bool operator>=(StringRef a, StringRef b) +constexpr inline bool operator>=(StringRef a, StringRef b) { return std::string_view(a) >= std::string_view(b); } @@ -427,7 +429,7 @@ inline bool operator>=(StringRef a, StringRef b) /** * Return true when the string starts with the given prefix. */ -inline bool StringRefBase::startswith(StringRef prefix) const +constexpr inline bool StringRefBase::startswith(StringRef prefix) const { if (size_ < prefix.size_) { return false; @@ -443,7 +445,7 @@ inline bool StringRefBase::startswith(StringRef prefix) const /** * Return true when the string ends with the given suffix. */ -inline bool StringRefBase::endswith(StringRef suffix) const +constexpr inline bool StringRefBase::endswith(StringRef suffix) const { if (size_ < suffix.size_) { return false; @@ -460,8 +462,8 @@ inline bool StringRefBase::endswith(StringRef suffix) const /** * Return a new #StringRef containing only a sub-string of the original string. */ -inline StringRef StringRefBase::substr(const int64_t start, - const int64_t max_size = INT64_MAX) const +constexpr inline StringRef StringRefBase::substr(const int64_t start, + const int64_t max_size = INT64_MAX) const { BLI_assert(max_size >= 0); BLI_assert(start >= 0); @@ -469,7 +471,7 @@ inline StringRef StringRefBase::substr(const int64_t start, return StringRef(data_ + start, substr_size); } -inline int64_t index_or_npos_to_int64(size_t index) +constexpr inline int64_t index_or_npos_to_int64(size_t index) { /* The compiler will probably optimize this check away. */ if (index == std::string_view::npos) { @@ -478,62 +480,62 @@ inline int64_t index_or_npos_to_int64(size_t index) return static_cast(index); } -inline int64_t StringRefBase::find(char c, int64_t pos) const +constexpr inline int64_t StringRefBase::find(char c, int64_t pos) const { BLI_assert(pos >= 0); return index_or_npos_to_int64(std::string_view(*this).find(c, static_cast(pos))); } -inline int64_t StringRefBase::find(StringRef str, int64_t pos) const +constexpr inline int64_t StringRefBase::find(StringRef str, int64_t pos) const { BLI_assert(pos >= 0); return index_or_npos_to_int64(std::string_view(*this).find(str, static_cast(pos))); } -inline int64_t StringRefBase::find_first_of(StringRef chars, int64_t pos) const +constexpr inline int64_t StringRefBase::find_first_of(StringRef chars, int64_t pos) const { BLI_assert(pos >= 0); return index_or_npos_to_int64( std::string_view(*this).find_first_of(chars, static_cast(pos))); } -inline int64_t StringRefBase::find_first_of(char c, int64_t pos) const +constexpr inline int64_t StringRefBase::find_first_of(char c, int64_t pos) const { return this->find_first_of(StringRef(&c, 1), pos); } -inline int64_t StringRefBase::find_last_of(StringRef chars, int64_t pos) const +constexpr inline int64_t StringRefBase::find_last_of(StringRef chars, int64_t pos) const { BLI_assert(pos >= 0); return index_or_npos_to_int64( std::string_view(*this).find_last_of(chars, static_cast(pos))); } -inline int64_t StringRefBase::find_last_of(char c, int64_t pos) const +constexpr inline int64_t StringRefBase::find_last_of(char c, int64_t pos) const { return this->find_last_of(StringRef(&c, 1), pos); } -inline int64_t StringRefBase::find_first_not_of(StringRef chars, int64_t pos) const +constexpr inline int64_t StringRefBase::find_first_not_of(StringRef chars, int64_t pos) const { BLI_assert(pos >= 0); return index_or_npos_to_int64( std::string_view(*this).find_first_not_of(chars, static_cast(pos))); } -inline int64_t StringRefBase::find_first_not_of(char c, int64_t pos) const +constexpr inline int64_t StringRefBase::find_first_not_of(char c, int64_t pos) const { return this->find_first_not_of(StringRef(&c, 1), pos); } -inline int64_t StringRefBase::find_last_not_of(StringRef chars, int64_t pos) const +constexpr inline int64_t StringRefBase::find_last_not_of(StringRef chars, int64_t pos) const { BLI_assert(pos >= 0); return index_or_npos_to_int64( std::string_view(*this).find_last_not_of(chars, static_cast(pos))); } -inline int64_t StringRefBase::find_last_not_of(char c, int64_t pos) const +constexpr inline int64_t StringRefBase::find_last_not_of(char c, int64_t pos) const { return this->find_last_not_of(StringRef(&c, 1), pos); } diff --git a/source/blender/blenlib/tests/BLI_index_range_test.cc b/source/blender/blenlib/tests/BLI_index_range_test.cc index d472ded0f18..ddaa067f50e 100644 --- a/source/blender/blenlib/tests/BLI_index_range_test.cc +++ b/source/blender/blenlib/tests/BLI_index_range_test.cc @@ -140,4 +140,11 @@ TEST(index_range, AsSpan) EXPECT_EQ(span[3], 7); } +TEST(index_range, constexpr_) +{ + constexpr IndexRange range = IndexRange(1, 1); + std::array compiles = {1}; + BLI_STATIC_ASSERT(range.size() == 1, ""); + EXPECT_EQ(compiles[0], 1); +} } // namespace blender::tests diff --git a/source/blender/blenlib/tests/BLI_span_test.cc b/source/blender/blenlib/tests/BLI_span_test.cc index 9a8d9df7873..d1c9f312b97 100644 --- a/source/blender/blenlib/tests/BLI_span_test.cc +++ b/source/blender/blenlib/tests/BLI_span_test.cc @@ -337,4 +337,19 @@ TEST(span, MutableReverseIterator) EXPECT_EQ_ARRAY(src.data(), Span({14, 15, 16, 17}).data(), 4); } +TEST(span, constexpr_) +{ + static constexpr std::array src = {3, 2, 1}; + constexpr Span span(src); + BLI_STATIC_ASSERT(span[2] == 1, ""); + BLI_STATIC_ASSERT(span.size() == 3, ""); + BLI_STATIC_ASSERT(span.slice(1, 2).size() == 2, ""); + BLI_STATIC_ASSERT(span.has_duplicates__linear_search() == false, ""); + + std::integral_constant ic; + BLI_STATIC_ASSERT(ic.value, ""); + + EXPECT_EQ(span.slice(1, 2).size(), 2); +} + } // namespace blender::tests diff --git a/source/blender/blenlib/tests/BLI_string_ref_test.cc b/source/blender/blenlib/tests/BLI_string_ref_test.cc index 2d488feff71..401a7bc1118 100644 --- a/source/blender/blenlib/tests/BLI_string_ref_test.cc +++ b/source/blender/blenlib/tests/BLI_string_ref_test.cc @@ -298,4 +298,12 @@ TEST(string_ref, ToStringView) EXPECT_EQ(view, "hello"); } +TEST(string_ref, constexpr_) +{ + constexpr StringRef sref("World"); + BLI_STATIC_ASSERT(sref[2] == 'r', ""); + BLI_STATIC_ASSERT(sref.size() == 5, ""); + std::array(sref.find_first_of('o'))> compiles = {1}; + EXPECT_EQ(compiles[0], 1); +} } // namespace blender::tests -- cgit v1.2.3 From 055ef5df615632f81e30e39ae47b42a87af350ca Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Wed, 16 Dec 2020 01:05:46 +0100 Subject: Cleanup: Rename Asset Browser context member from "active_id" to "id" This is the same name we use elsewhere for the focused/active ID context member, so this should follow it. --- source/blender/editors/space_file/space_file.c | 2 +- source/blender/editors/util/ed_util.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c index d4f6618e82a..5bd7f6c17f6 100644 --- a/source/blender/editors/space_file/space_file.c +++ b/source/blender/editors/space_file/space_file.c @@ -806,7 +806,7 @@ static int /*eContextResult*/ file_context(const bContext *C, CTX_data_pointer_set(result, &screen->id, &RNA_FileSelectEntry, file); return CTX_RESULT_OK; } - if (CTX_data_equals(member, "active_id")) { + if (CTX_data_equals(member, "id")) { const FileDirEntry *file = filelist_file(sfile->files, params->active_file); ID *id = filelist_file_get_id(file); diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c index 6547e42f410..4740e4d8d33 100644 --- a/source/blender/editors/util/ed_util.c +++ b/source/blender/editors/util/ed_util.c @@ -507,7 +507,7 @@ void ED_OT_flush_edits(wmOperatorType *ot) static bool lib_id_load_custom_preview_poll(bContext *C) { - const PointerRNA idptr = CTX_data_pointer_get(C, "active_id"); + const PointerRNA idptr = CTX_data_pointer_get(C, "id"); BLI_assert(!idptr.data || RNA_struct_is_ID(idptr.type)); const ID *id = idptr.data; @@ -541,7 +541,7 @@ static int lib_id_load_custom_preview_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - PointerRNA idptr = CTX_data_pointer_get(C, "active_id"); + PointerRNA idptr = CTX_data_pointer_get(C, "id"); ID *id = idptr.data; BKE_previewimg_id_custom_set(id, path); -- cgit v1.2.3 From 58d818f8bebf8c08b528d1637c93f15d2559cca1 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Wed, 16 Dec 2020 11:44:22 +0100 Subject: Assets: Add operator & button to regenerate the automatic preview This makes it possible to trigger a refresh of the data-block preview, available next to the preview in the Asset Browser sidebar. The previews get easily outdated and automatically refreshing it all the time is not an option because it would be a consistently running, quite expensive process. So a button to cause a refresh should be reasonable. This button can also be used to switch back from a custom preview to a generated one. Although that may not be clear, and we should probably think of a way to explain that better. Addresses T82719. --- source/blender/editors/include/ED_util.h | 1 + source/blender/editors/screen/screen_ops.c | 1 + source/blender/editors/util/ed_util.c | 37 ++++++++++++++++++++++++++++-- 3 files changed, 37 insertions(+), 2 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/include/ED_util.h b/source/blender/editors/include/ED_util.h index d74a80045f1..ca6b4bdc618 100644 --- a/source/blender/editors/include/ED_util.h +++ b/source/blender/editors/include/ED_util.h @@ -54,6 +54,7 @@ void ED_spacedata_id_remap(struct ScrArea *area, void ED_OT_flush_edits(struct wmOperatorType *ot); void ED_OT_lib_id_load_custom_preview(struct wmOperatorType *ot); +void ED_OT_lib_id_generate_preview(struct wmOperatorType *ot); /* ************** XXX OLD CRUFT WARNING ************* */ diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index a0c5762c73c..51687d5de1d 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -5511,6 +5511,7 @@ void ED_operatortypes_screen(void) WM_operatortype_append(ED_OT_flush_edits); WM_operatortype_append(ED_OT_lib_id_load_custom_preview); + WM_operatortype_append(ED_OT_lib_id_generate_preview); } /** \} */ diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c index 4740e4d8d33..d78758dcc1c 100644 --- a/source/blender/editors/util/ed_util.c +++ b/source/blender/editors/util/ed_util.c @@ -67,6 +67,7 @@ #include "ED_object.h" #include "ED_outliner.h" #include "ED_paint.h" +#include "ED_render.h" #include "ED_space_api.h" #include "ED_util.h" @@ -505,7 +506,7 @@ void ED_OT_flush_edits(wmOperatorType *ot) ot->flag = OPTYPE_INTERNAL; } -static bool lib_id_load_custom_preview_poll(bContext *C) +static bool lib_id_preview_editing_poll(bContext *C) { const PointerRNA idptr = CTX_data_pointer_get(C, "id"); BLI_assert(!idptr.data || RNA_struct_is_ID(idptr.type)); @@ -558,7 +559,7 @@ void ED_OT_lib_id_load_custom_preview(wmOperatorType *ot) ot->idname = "ED_OT_lib_id_load_custom_preview"; /* api callbacks */ - ot->poll = lib_id_load_custom_preview_poll; + ot->poll = lib_id_preview_editing_poll; ot->exec = lib_id_load_custom_preview_exec; ot->invoke = WM_operator_filesel; @@ -573,3 +574,35 @@ void ED_OT_lib_id_load_custom_preview(wmOperatorType *ot) FILE_DEFAULTDISPLAY, FILE_SORT_DEFAULT); } + +static int lib_id_generate_preview_exec(bContext *C, wmOperator *UNUSED(op)) +{ + PointerRNA idptr = CTX_data_pointer_get(C, "id"); + ID *id = idptr.data; + + ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C)); + + PreviewImage *preview = BKE_previewimg_id_get(id); + if (preview) { + BKE_previewimg_clear(preview); + } + UI_icon_render_id(C, NULL, id, true, true); + + WM_event_add_notifier(C, NC_ASSET, NULL); + + return OPERATOR_FINISHED; +} + +void ED_OT_lib_id_generate_preview(wmOperatorType *ot) +{ + ot->name = "Generate Preview"; + ot->description = "Create an automatic preview for the selected data-block"; + ot->idname = "ED_OT_lib_id_generate_preview"; + + /* api callbacks */ + ot->poll = lib_id_preview_editing_poll; + ot->exec = lib_id_generate_preview_exec; + + /* flags */ + ot->flag = OPTYPE_INTERNAL; +} -- cgit v1.2.3 From 3fc9fc1cb46a49bbfa2da4443fb4edefcdc3b89d Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Wed, 16 Dec 2020 11:58:30 +0100 Subject: UI: Indicate asset data-blocks with an icon in Outliners & search menus It's useful to easily see which data-blocks are assets and which not. So just like we usually show the library linking/override icons, we show the asset icon there (these are mutually exclusive data-block states). Uses the `'MAT_SPHERE_SKY` icon, which wasn't used before (except by an add-on!) and is sorta fitting, but not quite. We should either change this one or add an own asset icon. Meanwhile this isn't too bad :) Also adds an internal macro to check if a data-block is an asset, consistent to how we do it for libraries and library overrides. --- source/blender/editors/interface/interface_icons.c | 3 +++ source/blender/makesdna/DNA_ID.h | 2 ++ 2 files changed, 5 insertions(+) (limited to 'source/blender') diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index 1c09dc6f4df..08e9ea31b53 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -2199,6 +2199,9 @@ int UI_icon_from_library(const ID *id) if (ID_IS_OVERRIDE_LIBRARY(id)) { return ICON_LIBRARY_DATA_OVERRIDE; } + if (ID_IS_ASSET(id)) { + return ICON_MAT_SPHERE_SKY; + } return ICON_NONE; } diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h index af8e83a2c44..265baa16cc5 100644 --- a/source/blender/makesdna/DNA_ID.h +++ b/source/blender/makesdna/DNA_ID.h @@ -509,6 +509,8 @@ typedef enum ID_Type { #define ID_IS_OVERRIDE_LIBRARY_TEMPLATE(_id) \ (((ID *)(_id))->override_library != NULL && ((ID *)(_id))->override_library->reference == NULL) +#define ID_IS_ASSET(_id) (((const ID *)(_id))->asset_data != NULL) + /* Check whether datablock type is covered by copy-on-write. */ #define ID_TYPE_IS_COW(_id_type) (!ELEM(_id_type, ID_BR, ID_PAL, ID_IM)) -- cgit v1.2.3 From 4f128269b2dcf453647e7293f68f35173d45486a Mon Sep 17 00:00:00 2001 From: Eric Cosky Date: Wed, 16 Dec 2020 12:12:06 +0100 Subject: Fix possible crash with custom (add-on defined) icons This change is a simple null check on the ID provided to icon_set_image() which appears to be a legitimate value for the ID when used by some addins (discovered with PowerSave shortly after syncing to main). Differential Revision: https://developer.blender.org/D9866 Reviewed by: Julian Eisel --- source/blender/editors/interface/interface_icons.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender') diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index 08e9ea31b53..899f4a6ddb1 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -1416,7 +1416,7 @@ static void icon_set_image(const bContext *C, const bool delay = prv_img->rect[size] != NULL; icon_create_rect(prv_img, size); - if (use_job && BKE_previewimg_id_supports_jobs(id)) { + if (use_job && (!id || BKE_previewimg_id_supports_jobs(id))) { /* Job (background) version */ ED_preview_icon_job( C, prv_img, id, prv_img->rect[size], prv_img->w[size], prv_img->h[size], delay); -- cgit v1.2.3 From 985d673374a48eef6af5e73b0b24d4462a911f4b Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Wed, 16 Dec 2020 12:19:17 +0100 Subject: BLI: add new InplacePriorityQueue data structure This data structure adds priority queue functionality to an existing array. The underlying array is not changed. Instead, the priority queue maintains indices into the original array. Changing priorities of elements dynamically is supported, but the priority queue has to be informed of such changes. This data structure is needed for D9787. --- .../blender/blenlib/BLI_inplace_priority_queue.hh | 304 +++++++++++++++++++++ source/blender/blenlib/CMakeLists.txt | 2 + .../tests/BLI_inplace_priority_queue_test.cc | 113 ++++++++ 3 files changed, 419 insertions(+) create mode 100644 source/blender/blenlib/BLI_inplace_priority_queue.hh create mode 100644 source/blender/blenlib/tests/BLI_inplace_priority_queue_test.cc (limited to 'source/blender') diff --git a/source/blender/blenlib/BLI_inplace_priority_queue.hh b/source/blender/blenlib/BLI_inplace_priority_queue.hh new file mode 100644 index 00000000000..e76cb8504a3 --- /dev/null +++ b/source/blender/blenlib/BLI_inplace_priority_queue.hh @@ -0,0 +1,304 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#pragma once + +#include "BLI_array.hh" +#include "BLI_dot_export.hh" + +namespace blender { + +/** + * An InplacePriorityQueue adds priority queue functionality to an existing array. The underlying + * array is not changed. Instead, the priority queue maintains indices into the original array. + * + * The priority queue provides efficient access to the element in order of their priorities. + * + * When a priority changes, the priority queue has to be informed using one of the following + * methods: #priority_decreased, #priority_increased or #priority_changed. + */ +template< + /* Type of the elements in the underlying array. */ + typename T, + /* Binary function that takes two `const T &` inputs and returns true, when the first input has + greater priority than the second. */ + typename FirstHasHigherPriority = std::greater> +class InplacePriorityQueue { + private: + /* Underlying array the priority queue is built upon. This is a span instead of a mutable span, + * because this data structure never changes the values itself. */ + Span data_; + /* Maps indices from the heap (binary tree in array format) to indices of the underlying/original + * array. */ + Array heap_to_orig_; + /* This is the inversion of the above mapping. */ + Array orig_to_heap_; + /* Number of elements that are currently in the priority queue. */ + int64_t heap_size_ = 0; + /* Function that can be changed to customize how the priority of two elements is compared. */ + FirstHasHigherPriority first_has_higher_priority_fn_; + + public: + /** + * Construct the priority queue on top of the data in the given span. + */ + InplacePriorityQueue(Span data) + : data_(data), heap_to_orig_(data_.size()), orig_to_heap_(data_.size()) + { + for (const int64_t i : IndexRange(data_.size())) { + heap_to_orig_[i] = i; + orig_to_heap_[i] = i; + } + + this->rebuild(); + } + + /** + * Rebuilds the priority queue from the array that has been passed to the constructor. + */ + void rebuild() + { + const int final_heap_size = data_.size(); + if (final_heap_size > 1) { + for (int64_t i = this->get_parent(final_heap_size - 1); i >= 0; i--) { + this->heapify(i, final_heap_size); + } + } + heap_size_ = final_heap_size; + } + + /** + * Returns the number of elements in the priority queue. + * This is less or equal than the size of the underlying array. + */ + int64_t size() const + { + return heap_size_; + } + + /** + * Returns true, when the priority queue contains no elements. If this returns true, #peek and + * #pop must not be used. + */ + bool is_empty() const + { + return heap_size_ == 0; + } + + /** + * Get the element with the highest priority in the priority queue. + * The returned reference is const, because the priority queue has read-only access to the + * underlying data. If you need a mutable reference, use #peek_index instead. + */ + const T &peek() const + { + return data_[this->peek_index()]; + } + + /** + * Get the element with the highest priority in the priority queue and remove it. + * The returned reference is const, because the priority queue has read-only access to the + * underlying data. If you need a mutable reference, use #pop_index instead. + */ + const T &pop() + { + return data_[this->pop_index()]; + } + + /** + * Get the index of the element with the highest priority in the priority queue. + */ + int64_t peek_index() const + { + BLI_assert(!this->is_empty()); + return heap_to_orig_[0]; + } + + /** + * Get the index of the element with the highest priority in the priority queue and remove it. + */ + int64_t pop_index() + { + BLI_assert(!this->is_empty()); + const int64_t top_index_orig = heap_to_orig_[0]; + heap_size_--; + if (heap_size_ > 1) { + this->swap_indices(0, heap_size_); + this->heapify(0, heap_size_); + } + return top_index_orig; + } + + /** + * Inform the priority queue that the priority of the element at the given index has been + * decreased. + */ + void priority_decreased(const int64_t index) + { + const int64_t heap_index = orig_to_heap_[index]; + if (heap_index >= heap_size_) { + /* This element is not in the queue currently. */ + return; + } + this->heapify(heap_index, heap_size_); + } + + /** + * Inform the priority queue that the priority of the element at the given index has been + * increased. + */ + void priority_increased(const int64_t index) + { + int64_t current = orig_to_heap_[index]; + if (current >= heap_size_) { + /* This element is not in the queue currently. */ + return; + } + while (true) { + if (current == 0) { + break; + } + const int64_t parent = this->get_parent(current); + if (this->first_has_higher_priority(parent, current)) { + break; + } + this->swap_indices(current, parent); + current = parent; + } + } + + /** + * Inform the priority queue that the priority of the element at the given index has been + * changed. + */ + void priority_changed(const int64_t index) + { + this->priority_increased(index); + this->priority_decreased(index); + } + + /** + * Returns the indices of all elements that are in the priority queue. + * There are no guarantees about the order of indices. + */ + Span active_indices() const + { + return heap_to_orig_.as_span().take_front(heap_size_); + } + + /** + * Returns the indices of all elements that are not in the priority queue. + * The indices are in reverse order of their removal from the queue. + * I.e. the index that has been removed last, comes first. + */ + Span inactive_indices() const + { + return heap_to_orig_.as_span().drop_front(heap_size_); + } + + /** + * Returns the concatenation of the active and inactive indices. + */ + Span all_indices() const + { + return heap_to_orig_; + } + + /** + * Return the heap used by the priority queue as dot graph string. + * This exists for debugging purposes. + */ + std::string to_dot() const + { + return this->partial_to_dot(heap_size_); + } + + private: + bool first_has_higher_priority(const int64_t a, const int64_t b) + { + const T &value_a = data_[heap_to_orig_[a]]; + const T &value_b = data_[heap_to_orig_[b]]; + return first_has_higher_priority_fn_(value_a, value_b); + } + + void swap_indices(const int64_t a, const int64_t b) + { + std::swap(heap_to_orig_[a], heap_to_orig_[b]); + orig_to_heap_[heap_to_orig_[a]] = a; + orig_to_heap_[heap_to_orig_[b]] = b; + } + + void heapify(const int64_t parent, const int64_t heap_size) + { + int64_t max_index = parent; + const int left = this->get_left(parent); + const int right = this->get_right(parent); + if (left < heap_size && this->first_has_higher_priority(left, max_index)) { + max_index = left; + } + if (right < heap_size && this->first_has_higher_priority(right, max_index)) { + max_index = right; + } + if (max_index != parent) { + this->swap_indices(parent, max_index); + this->heapify(max_index, heap_size); + } + if (left < heap_size) { + BLI_assert(!this->first_has_higher_priority(left, parent)); + } + if (right < heap_size) { + BLI_assert(!this->first_has_higher_priority(right, parent)); + } + } + + int64_t get_parent(const int64_t child) const + { + BLI_assert(child > 0); + return (child - 1) / 2; + } + + int64_t get_left(const int64_t parent) const + { + return parent * 2 + 1; + } + + int64_t get_right(const int64_t parent) const + { + return parent * 2 + 2; + } + + std::string partial_to_dot(const int size) const + { + dot::DirectedGraph digraph; + Array dot_nodes(size); + for (const int i : IndexRange(size)) { + std::stringstream ss; + ss << data_[heap_to_orig_[i]]; + const std::string name = ss.str(); + dot::Node &node = digraph.new_node(name); + node.set_shape(dot::Attr_shape::Rectangle); + node.attributes.set("ordering", "out"); + dot_nodes[i] = &node; + if (i > 0) { + const int64_t parent = this->get_parent(i); + digraph.new_edge(*dot_nodes[parent], node); + } + } + return digraph.to_dot_string(); + } +}; + +} // namespace blender diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt index 46a3ad87dfe..aa4c4efe7d4 100644 --- a/source/blender/blenlib/CMakeLists.txt +++ b/source/blender/blenlib/CMakeLists.txt @@ -203,6 +203,7 @@ set(SRC BLI_heap_simple.h BLI_index_mask.hh BLI_index_range.hh + BLI_inplace_priority_queue.hh BLI_iterator.h BLI_jitter_2d.h BLI_kdopbvh.h @@ -390,6 +391,7 @@ if(WITH_GTESTS) tests/BLI_heap_test.cc tests/BLI_index_mask_test.cc tests/BLI_index_range_test.cc + tests/BLI_inplace_priority_queue_test.cc tests/BLI_kdopbvh_test.cc tests/BLI_linear_allocator_test.cc tests/BLI_linklist_lockfree_test.cc diff --git a/source/blender/blenlib/tests/BLI_inplace_priority_queue_test.cc b/source/blender/blenlib/tests/BLI_inplace_priority_queue_test.cc new file mode 100644 index 00000000000..3adf12f36a7 --- /dev/null +++ b/source/blender/blenlib/tests/BLI_inplace_priority_queue_test.cc @@ -0,0 +1,113 @@ +/* Apache License, Version 2.0 */ + +#include "testing/testing.h" + +#include "BLI_inplace_priority_queue.hh" +#include "BLI_rand.hh" + +namespace blender::tests { + +TEST(inplace_priority_queue, BuildSmall) +{ + Array values = {1, 5, 2, 8, 5, 6, 5, 4, 3, 6, 7, 3}; + InplacePriorityQueue priority_queue{values}; + + EXPECT_EQ(priority_queue.peek(), 8); + EXPECT_EQ(priority_queue.pop(), 8); + EXPECT_EQ(priority_queue.peek(), 7); + EXPECT_EQ(priority_queue.pop(), 7); + EXPECT_EQ(priority_queue.pop(), 6); + EXPECT_EQ(priority_queue.pop(), 6); + EXPECT_EQ(priority_queue.pop(), 5); +} + +TEST(inplace_priority_queue, DecreasePriority) +{ + Array values = {5, 2, 7, 4}; + InplacePriorityQueue priority_queue(values); + + EXPECT_EQ(priority_queue.peek(), 7); + values[2] = 0; + EXPECT_EQ(priority_queue.peek(), 0); + priority_queue.priority_decreased(2); + EXPECT_EQ(priority_queue.peek(), 5); +} + +TEST(inplace_priority_queue, IncreasePriority) +{ + Array values = {5, 2, 7, 4}; + InplacePriorityQueue priority_queue(values); + + EXPECT_EQ(priority_queue.peek(), 7); + values[1] = 10; + EXPECT_EQ(priority_queue.peek(), 7); + priority_queue.priority_increased(1); + EXPECT_EQ(priority_queue.peek(), 10); +} + +TEST(inplace_priority_queue, PopAll) +{ + RandomNumberGenerator rng; + Vector values; + const int amount = 1000; + for (int i = 0; i < amount; i++) { + values.append(rng.get_int32() % amount); + } + + InplacePriorityQueue priority_queue(values); + + int last_value = amount; + while (!priority_queue.is_empty()) { + const int value = priority_queue.pop(); + EXPECT_LE(value, last_value); + last_value = value; + } +} + +TEST(inplace_priority_queue, ManyPriorityChanges) +{ + RandomNumberGenerator rng; + Vector values; + const int amount = 1000; + for (int i = 0; i < amount; i++) { + values.append(rng.get_int32() % amount); + } + + InplacePriorityQueue priority_queue(values); + + for (int i = 0; i < amount; i++) { + const int index = rng.get_int32() % amount; + const int new_priority = rng.get_int32() % amount; + values[index] = new_priority; + priority_queue.priority_changed(index); + } + + int last_value = amount; + while (!priority_queue.is_empty()) { + const int value = priority_queue.pop(); + EXPECT_LE(value, last_value); + last_value = value; + } +} + +TEST(inplace_priority_queue, IndicesAccess) +{ + Array values = {4, 6, 2, 4, 8, 1, 10, 2, 5}; + InplacePriorityQueue priority_queue(values); + + EXPECT_EQ(priority_queue.active_indices().size(), 9); + EXPECT_EQ(priority_queue.inactive_indices().size(), 0); + EXPECT_EQ(priority_queue.all_indices().size(), 9); + EXPECT_EQ(priority_queue.pop(), 10); + EXPECT_EQ(priority_queue.active_indices().size(), 8); + EXPECT_EQ(priority_queue.inactive_indices().size(), 1); + EXPECT_EQ(values[priority_queue.inactive_indices()[0]], 10); + EXPECT_EQ(priority_queue.all_indices().size(), 9); + EXPECT_EQ(priority_queue.pop(), 8); + EXPECT_EQ(priority_queue.inactive_indices().size(), 2); + EXPECT_EQ(values[priority_queue.inactive_indices()[0]], 8); + EXPECT_EQ(values[priority_queue.inactive_indices()[1]], 10); + EXPECT_EQ(priority_queue.all_indices().size(), 9); +} + +} // namespace blender::tests -- cgit v1.2.3 From 4c26dd430d5ec0867cd7b834e601fbaaf7e10e67 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Wed, 16 Dec 2020 13:31:56 +0100 Subject: Geometry Nodes: rename node to Attribute Randomize Previously, the node was called Random Attribute. For consistency reasons, we move the "Attribute" part of the name to the front. --- source/blender/blenkernel/BKE_node.h | 2 +- source/blender/blenkernel/intern/node.c | 2 +- source/blender/blenloader/intern/versioning_290.c | 8 + source/blender/editors/space_node/drawnode.c | 2 +- source/blender/makesrna/intern/rna_nodetree.c | 2 +- source/blender/nodes/CMakeLists.txt | 2 +- source/blender/nodes/NOD_geometry.h | 2 +- source/blender/nodes/NOD_static_types.h | 2 +- .../geometry/nodes/node_geo_attribute_randomize.cc | 162 +++++++++++++++++++++ .../geometry/nodes/node_geo_random_attribute.cc | 161 -------------------- 10 files changed, 177 insertions(+), 168 deletions(-) create mode 100644 source/blender/nodes/geometry/nodes/node_geo_attribute_randomize.cc delete mode 100644 source/blender/nodes/geometry/nodes/node_geo_random_attribute.cc (limited to 'source/blender') diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 77a1d3989b0..f8ce364d694 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -1347,7 +1347,7 @@ int ntreeTexExecTree(struct bNodeTree *ntree, #define GEO_NODE_POINT_INSTANCE 1005 #define GEO_NODE_SUBDIVISION_SURFACE 1006 #define GEO_NODE_OBJECT_INFO 1007 -#define GEO_NODE_RANDOM_ATTRIBUTE 1008 +#define GEO_NODE_ATTRIBUTE_RANDOMIZE 1008 #define GEO_NODE_ATTRIBUTE_MATH 1009 #define GEO_NODE_JOIN_GEOMETRY 1010 #define GEO_NODE_ATTRIBUTE_FILL 1011 diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 87997198334..06ff7c2e65c 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -4737,7 +4737,7 @@ static void registerGeometryNodes(void) register_node_type_geo_point_distribute(); register_node_type_geo_point_instance(); register_node_type_geo_object_info(); - register_node_type_geo_random_attribute(); + register_node_type_geo_attribute_randomize(); register_node_type_geo_attribute_math(); register_node_type_geo_join_geometry(); register_node_type_geo_attribute_mix(); diff --git a/source/blender/blenloader/intern/versioning_290.c b/source/blender/blenloader/intern/versioning_290.c index 685bb762f29..49e1b057b39 100644 --- a/source/blender/blenloader/intern/versioning_290.c +++ b/source/blender/blenloader/intern/versioning_290.c @@ -1316,5 +1316,13 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain) */ { /* Keep this block, even when empty. */ + + LISTBASE_FOREACH (bNodeTree *, ntree, &bmain->nodetrees) { + LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { + if (STREQ(node->idname, "GeometryNodeRandomAttribute")) { + STRNCPY(node->idname, "GeometryNodeAttributeRandomize"); + } + } + } } } diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index f8c71791054..421d645d7bd 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -3220,7 +3220,7 @@ static void node_geometry_set_butfunc(bNodeType *ntype) case GEO_NODE_TRIANGULATE: ntype->draw_buttons = node_geometry_buts_triangulate; break; - case GEO_NODE_RANDOM_ATTRIBUTE: + case GEO_NODE_ATTRIBUTE_RANDOMIZE: ntype->draw_buttons = node_geometry_buts_random_attribute; break; case GEO_NODE_ATTRIBUTE_MATH: diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 153e2aebd22..34f4d287d6e 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -8388,7 +8388,7 @@ static void def_geo_attribute_create_common(StructRNA *srna, RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); } -static void def_geo_random_attribute(StructRNA *srna) +static void def_geo_attribute_randomize(StructRNA *srna) { def_geo_attribute_create_common(srna, "rna_GeometryNodeAttributeRandom_type_itemf", diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index 11852f6f723..779680a5da7 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -140,6 +140,7 @@ set(SRC geometry/nodes/node_geo_attribute_fill.cc geometry/nodes/node_geo_attribute_math.cc + geometry/nodes/node_geo_attribute_randomize.cc geometry/nodes/node_geo_boolean.cc geometry/nodes/node_geo_common.cc geometry/nodes/node_geo_edge_split.cc @@ -148,7 +149,6 @@ set(SRC geometry/nodes/node_geo_object_info.cc geometry/nodes/node_geo_point_distribute.cc geometry/nodes/node_geo_point_instance.cc - geometry/nodes/node_geo_random_attribute.cc geometry/nodes/node_geo_subdivision_surface.cc geometry/nodes/node_geo_transform.cc geometry/nodes/node_geo_triangulate.cc diff --git a/source/blender/nodes/NOD_geometry.h b/source/blender/nodes/NOD_geometry.h index e3ec0451832..5ac4af9fc14 100644 --- a/source/blender/nodes/NOD_geometry.h +++ b/source/blender/nodes/NOD_geometry.h @@ -35,7 +35,7 @@ void register_node_type_geo_triangulate(void); void register_node_type_geo_point_distribute(void); void register_node_type_geo_point_instance(void); void register_node_type_geo_object_info(void); -void register_node_type_geo_random_attribute(void); +void register_node_type_geo_attribute_randomize(void); void register_node_type_geo_attribute_math(void); void register_node_type_geo_join_geometry(void); void register_node_type_geo_attribute_mix(void); diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h index 491f49cf425..681286ae5ab 100644 --- a/source/blender/nodes/NOD_static_types.h +++ b/source/blender/nodes/NOD_static_types.h @@ -274,7 +274,7 @@ DefNode(GeometryNode, GEO_NODE_BOOLEAN, def_geo_boolean, "BOOLEAN", Boolean, "Bo DefNode(GeometryNode, GEO_NODE_POINT_DISTRIBUTE, 0, "POINT_DISTRIBUTE", PointDistribute, "Point Distribute", "") DefNode(GeometryNode, GEO_NODE_POINT_INSTANCE, def_geo_point_instance, "POINT_INSTANCE", PointInstance, "Point Instance", "") DefNode(GeometryNode, GEO_NODE_OBJECT_INFO, 0, "OBJECT_INFO", ObjectInfo, "Object Info", "") -DefNode(GeometryNode, GEO_NODE_RANDOM_ATTRIBUTE, def_geo_random_attribute, "RANDOM_ATTRIBUTE", RandomAttribute, "Random Attribute", "") +DefNode(GeometryNode, GEO_NODE_ATTRIBUTE_RANDOMIZE, def_geo_attribute_randomize, "ATTRIBUTE_RANDOMIZE", AttributeRandomize, "Attribute Randomize", "") DefNode(GeometryNode, GEO_NODE_ATTRIBUTE_MATH, def_geo_attribute_math, "ATTRIBUTE_MATH", AttributeMath, "Attribute Math", "") DefNode(GeometryNode, GEO_NODE_JOIN_GEOMETRY, 0, "JOIN_GEOMETRY", JoinGeometry, "Join Geometry", "") DefNode(GeometryNode, GEO_NODE_ATTRIBUTE_FILL, def_geo_attribute_fill, "ATTRIBUTE_FILL", AttributeFill, "Attribute Fill", "") diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_randomize.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_randomize.cc new file mode 100644 index 00000000000..bde9a2a695e --- /dev/null +++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_randomize.cc @@ -0,0 +1,162 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "node_geometry_util.hh" + +#include "BLI_rand.hh" + +#include "DNA_mesh_types.h" +#include "DNA_pointcloud_types.h" + +static bNodeSocketTemplate geo_node_attribute_randomize_in[] = { + {SOCK_GEOMETRY, N_("Geometry")}, + {SOCK_STRING, N_("Attribute")}, + {SOCK_VECTOR, N_("Min"), 0.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX}, + {SOCK_VECTOR, N_("Max"), 1.0f, 1.0f, 1.0f, 0.0f, -FLT_MAX, FLT_MAX}, + {SOCK_FLOAT, N_("Min"), 0.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX}, + {SOCK_FLOAT, N_("Max"), 1.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX}, + {SOCK_INT, N_("Seed"), 0, 0, 0, 0, -10000, 10000}, + {-1, ""}, +}; + +static bNodeSocketTemplate geo_node_attribute_randomize_out[] = { + {SOCK_GEOMETRY, N_("Geometry")}, + {-1, ""}, +}; + +static void geo_node_attribute_randomize_init(bNodeTree *UNUSED(tree), bNode *node) +{ + node->custom1 = CD_PROP_FLOAT; +} + +static void geo_node_attribute_randomize_update(bNodeTree *UNUSED(ntree), bNode *node) +{ + bNodeSocket *sock_min_vector = (bNodeSocket *)BLI_findlink(&node->inputs, 2); + bNodeSocket *sock_max_vector = sock_min_vector->next; + bNodeSocket *sock_min_float = sock_max_vector->next; + bNodeSocket *sock_max_float = sock_min_float->next; + + const int data_type = node->custom1; + + nodeSetSocketAvailability(sock_min_vector, data_type == CD_PROP_FLOAT3); + nodeSetSocketAvailability(sock_max_vector, data_type == CD_PROP_FLOAT3); + nodeSetSocketAvailability(sock_min_float, data_type == CD_PROP_FLOAT); + nodeSetSocketAvailability(sock_max_float, data_type == CD_PROP_FLOAT); +} + +namespace blender::nodes { + +static void randomize_attribute(FloatWriteAttribute &attribute, + float min, + float max, + RandomNumberGenerator &rng) +{ + MutableSpan attribute_span = attribute.get_span(); + for (const int i : IndexRange(attribute.size())) { + const float value = rng.get_float() * (max - min) + min; + attribute_span[i] = value; + } + attribute.apply_span(); +} + +static void randomize_attribute(Float3WriteAttribute &attribute, + float3 min, + float3 max, + RandomNumberGenerator &rng) +{ + MutableSpan attribute_span = attribute.get_span(); + for (const int i : IndexRange(attribute.size())) { + const float x = rng.get_float(); + const float y = rng.get_float(); + const float z = rng.get_float(); + const float3 value = float3(x, y, z) * (max - min) + min; + attribute_span[i] = value; + } + attribute.apply_span(); +} + +static void randomize_attribute(GeometryComponent &component, + const GeoNodeExecParams ¶ms, + RandomNumberGenerator &rng) +{ + const bNode &node = params.node(); + const CustomDataType data_type = static_cast(node.custom1); + const AttributeDomain domain = static_cast(node.custom2); + const std::string attribute_name = params.get_input("Attribute"); + if (attribute_name.empty()) { + return; + } + + WriteAttributePtr attribute = component.attribute_try_ensure_for_write( + attribute_name, domain, data_type); + if (!attribute) { + return; + } + + switch (data_type) { + case CD_PROP_FLOAT: { + FloatWriteAttribute float_attribute = std::move(attribute); + const float min_value = params.get_input("Min_001"); + const float max_value = params.get_input("Max_001"); + randomize_attribute(float_attribute, min_value, max_value, rng); + break; + } + case CD_PROP_FLOAT3: { + Float3WriteAttribute float3_attribute = std::move(attribute); + const float3 min_value = params.get_input("Min"); + const float3 max_value = params.get_input("Max"); + randomize_attribute(float3_attribute, min_value, max_value, rng); + break; + } + default: + break; + } +} + +static void geo_node_random_attribute_exec(GeoNodeExecParams params) +{ + GeometrySet geometry_set = params.extract_input("Geometry"); + const int seed = params.get_input("Seed"); + + if (geometry_set.has()) { + RandomNumberGenerator rng; + rng.seed_random(seed); + randomize_attribute(geometry_set.get_component_for_write(), params, rng); + } + if (geometry_set.has()) { + RandomNumberGenerator rng; + rng.seed_random(seed + 3245231); + randomize_attribute(geometry_set.get_component_for_write(), params, rng); + } + + params.set_output("Geometry", geometry_set); +} + +} // namespace blender::nodes + +void register_node_type_geo_attribute_randomize() +{ + static bNodeType ntype; + + geo_node_type_base( + &ntype, GEO_NODE_ATTRIBUTE_RANDOMIZE, "Attribute Randomize", NODE_CLASS_ATTRIBUTE, 0); + node_type_socket_templates( + &ntype, geo_node_attribute_randomize_in, geo_node_attribute_randomize_out); + node_type_init(&ntype, geo_node_attribute_randomize_init); + node_type_update(&ntype, geo_node_attribute_randomize_update); + ntype.geometry_node_execute = blender::nodes::geo_node_random_attribute_exec; + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/geometry/nodes/node_geo_random_attribute.cc b/source/blender/nodes/geometry/nodes/node_geo_random_attribute.cc deleted file mode 100644 index 5cacb96412c..00000000000 --- a/source/blender/nodes/geometry/nodes/node_geo_random_attribute.cc +++ /dev/null @@ -1,161 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "node_geometry_util.hh" - -#include "BLI_rand.hh" - -#include "DNA_mesh_types.h" -#include "DNA_pointcloud_types.h" - -static bNodeSocketTemplate geo_node_random_attribute_in[] = { - {SOCK_GEOMETRY, N_("Geometry")}, - {SOCK_STRING, N_("Attribute")}, - {SOCK_VECTOR, N_("Min"), 0.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX}, - {SOCK_VECTOR, N_("Max"), 1.0f, 1.0f, 1.0f, 0.0f, -FLT_MAX, FLT_MAX}, - {SOCK_FLOAT, N_("Min"), 0.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX}, - {SOCK_FLOAT, N_("Max"), 1.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX}, - {SOCK_INT, N_("Seed"), 0, 0, 0, 0, -10000, 10000}, - {-1, ""}, -}; - -static bNodeSocketTemplate geo_node_random_attribute_out[] = { - {SOCK_GEOMETRY, N_("Geometry")}, - {-1, ""}, -}; - -static void geo_node_random_attribute_init(bNodeTree *UNUSED(tree), bNode *node) -{ - node->custom1 = CD_PROP_FLOAT; -} - -static void geo_node_random_attribute_update(bNodeTree *UNUSED(ntree), bNode *node) -{ - bNodeSocket *sock_min_vector = (bNodeSocket *)BLI_findlink(&node->inputs, 2); - bNodeSocket *sock_max_vector = sock_min_vector->next; - bNodeSocket *sock_min_float = sock_max_vector->next; - bNodeSocket *sock_max_float = sock_min_float->next; - - const int data_type = node->custom1; - - nodeSetSocketAvailability(sock_min_vector, data_type == CD_PROP_FLOAT3); - nodeSetSocketAvailability(sock_max_vector, data_type == CD_PROP_FLOAT3); - nodeSetSocketAvailability(sock_min_float, data_type == CD_PROP_FLOAT); - nodeSetSocketAvailability(sock_max_float, data_type == CD_PROP_FLOAT); -} - -namespace blender::nodes { - -static void randomize_attribute(FloatWriteAttribute &attribute, - float min, - float max, - RandomNumberGenerator &rng) -{ - MutableSpan attribute_span = attribute.get_span(); - for (const int i : IndexRange(attribute.size())) { - const float value = rng.get_float() * (max - min) + min; - attribute_span[i] = value; - } - attribute.apply_span(); -} - -static void randomize_attribute(Float3WriteAttribute &attribute, - float3 min, - float3 max, - RandomNumberGenerator &rng) -{ - MutableSpan attribute_span = attribute.get_span(); - for (const int i : IndexRange(attribute.size())) { - const float x = rng.get_float(); - const float y = rng.get_float(); - const float z = rng.get_float(); - const float3 value = float3(x, y, z) * (max - min) + min; - attribute_span[i] = value; - } - attribute.apply_span(); -} - -static void randomize_attribute(GeometryComponent &component, - const GeoNodeExecParams ¶ms, - RandomNumberGenerator &rng) -{ - const bNode &node = params.node(); - const CustomDataType data_type = static_cast(node.custom1); - const AttributeDomain domain = static_cast(node.custom2); - const std::string attribute_name = params.get_input("Attribute"); - if (attribute_name.empty()) { - return; - } - - WriteAttributePtr attribute = component.attribute_try_ensure_for_write( - attribute_name, domain, data_type); - if (!attribute) { - return; - } - - switch (data_type) { - case CD_PROP_FLOAT: { - FloatWriteAttribute float_attribute = std::move(attribute); - const float min_value = params.get_input("Min_001"); - const float max_value = params.get_input("Max_001"); - randomize_attribute(float_attribute, min_value, max_value, rng); - break; - } - case CD_PROP_FLOAT3: { - Float3WriteAttribute float3_attribute = std::move(attribute); - const float3 min_value = params.get_input("Min"); - const float3 max_value = params.get_input("Max"); - randomize_attribute(float3_attribute, min_value, max_value, rng); - break; - } - default: - break; - } -} - -static void geo_node_random_attribute_exec(GeoNodeExecParams params) -{ - GeometrySet geometry_set = params.extract_input("Geometry"); - const int seed = params.get_input("Seed"); - - if (geometry_set.has()) { - RandomNumberGenerator rng; - rng.seed_random(seed); - randomize_attribute(geometry_set.get_component_for_write(), params, rng); - } - if (geometry_set.has()) { - RandomNumberGenerator rng; - rng.seed_random(seed + 3245231); - randomize_attribute(geometry_set.get_component_for_write(), params, rng); - } - - params.set_output("Geometry", geometry_set); -} - -} // namespace blender::nodes - -void register_node_type_geo_random_attribute() -{ - static bNodeType ntype; - - geo_node_type_base( - &ntype, GEO_NODE_RANDOM_ATTRIBUTE, "Random Attribute", NODE_CLASS_ATTRIBUTE, 0); - node_type_socket_templates(&ntype, geo_node_random_attribute_in, geo_node_random_attribute_out); - node_type_init(&ntype, geo_node_random_attribute_init); - node_type_update(&ntype, geo_node_random_attribute_update); - ntype.geometry_node_execute = blender::nodes::geo_node_random_attribute_exec; - nodeRegisterType(&ntype); -} -- cgit v1.2.3 From 29f923b27c5c0a183791a2a97e80c5f469a4ef51 Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Wed, 16 Dec 2020 13:54:02 +0100 Subject: Fix T83557: Alpha blend + emissive colors renders white artifacts Issue was that not all code paths were taken to determine if the GPU Texture was premultiplied or not. In this case the result was set to unpremultiplied what is incorrect. This fixes broken test case image alpha blend from image_colorspace. --- source/blender/blenkernel/intern/image_gpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/intern/image_gpu.c b/source/blender/blenkernel/intern/image_gpu.c index 9ed233ab34c..50138b34fa3 100644 --- a/source/blender/blenkernel/intern/image_gpu.c +++ b/source/blender/blenkernel/intern/image_gpu.c @@ -62,7 +62,7 @@ bool BKE_image_has_gpu_texture_premultiplied_alpha(Image *image, ImBuf *ibuf) return ibuf->rect_float != NULL; } } - else if (ibuf) { + if (ibuf) { if (ibuf->rect_float) { return image ? (image->alpha_mode != IMA_ALPHA_STRAIGHT) : false; } -- cgit v1.2.3 From 69c3f4a46d4621300ca2aa3ab778b24cb1713e95 Mon Sep 17 00:00:00 2001 From: Valdemar Lindberg Date: Wed, 16 Dec 2020 14:21:38 +0100 Subject: Fix 3D View is red when using stereo Fix T83415: 3D View is red when using stereo The red view was caused by SRGB not being enabled for an SRGB texture attached to the framebuffer. Currently, when configuring a framebuffer, the first texture attachment needs to be an SRGB format in order for the framebuffer to be binded with SRGB enabled. Thus, simply changing the SRGB texture attachment as the first texture attachment removes the red color in the view. Reviewed By: #eevee_viewport, jbakker Maniphest Tasks: T83415 Differential Revision: https://developer.blender.org/D9845 --- source/blender/gpu/intern/gpu_viewport.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source/blender') diff --git a/source/blender/gpu/intern/gpu_viewport.c b/source/blender/gpu/intern/gpu_viewport.c index 188c8786665..a83654d31e7 100644 --- a/source/blender/gpu/intern/gpu_viewport.c +++ b/source/blender/gpu/intern/gpu_viewport.c @@ -616,8 +616,8 @@ void GPU_viewport_stereo_composite(GPUViewport *viewport, Stereo3dFormat *stereo GPU_framebuffer_ensure_config(&dfbl->stereo_comp_fb, { GPU_ATTACHMENT_NONE, - GPU_ATTACHMENT_TEXTURE(dtxl->color), GPU_ATTACHMENT_TEXTURE(dtxl->color_overlay), + GPU_ATTACHMENT_TEXTURE(dtxl->color), }); GPUVertFormat *vert_format = immVertexFormat(); @@ -628,8 +628,8 @@ void GPU_viewport_stereo_composite(GPUViewport *viewport, Stereo3dFormat *stereo GPU_matrix_identity_set(); GPU_matrix_identity_projection_set(); immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_OVERLAYS_STEREO_MERGE); - immUniform1i("imageTexture", 0); - immUniform1i("overlayTexture", 1); + immUniform1i("overlayTexture", 0); + immUniform1i("imageTexture", 1); int settings = stereo_format->display_mode; if (settings == S3D_DISPLAY_ANAGLYPH) { switch (stereo_format->anaglyph_type) { -- cgit v1.2.3 From 8da62a9a86d98676ff0bc4cffd389dcbed7e3071 Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Wed, 16 Dec 2020 15:01:25 +0100 Subject: Fix T83547: UV Editor stitching preview is gone. Issue was related that the draw manager didn't invoked the draw handlers for image editors. --- source/blender/draw/intern/draw_manager.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'source/blender') diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index 988975bd399..ffc565d0514 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -2073,7 +2073,6 @@ void DRW_draw_render_loop_2d_ex(struct Depsgraph *depsgraph, * for the image editor this is when showing UV's.*/ const bool do_populate_loop = (DST.draw_ctx.space_data->spacetype == SPACE_IMAGE); const bool do_annotations = drw_draw_show_annotation(); - const bool do_region_callbacks = (DST.draw_ctx.space_data->spacetype != SPACE_IMAGE); const bool do_draw_gizmos = (DST.draw_ctx.space_data->spacetype != SPACE_IMAGE); /* Get list of enabled engines */ @@ -2125,7 +2124,7 @@ void DRW_draw_render_loop_2d_ex(struct Depsgraph *depsgraph, /* Start Drawing */ DRW_state_reset(); - if (do_region_callbacks && DST.draw_ctx.evil_C) { + if (DST.draw_ctx.evil_C) { ED_region_draw_cb_draw(DST.draw_ctx.evil_C, DST.draw_ctx.region, REGION_DRAW_PRE_VIEW); } @@ -2147,10 +2146,8 @@ void DRW_draw_render_loop_2d_ex(struct Depsgraph *depsgraph, if (do_annotations) { ED_annotation_draw_view2d(DST.draw_ctx.evil_C, true); } - if (do_region_callbacks) { - GPU_depth_test(GPU_DEPTH_NONE); - ED_region_draw_cb_draw(DST.draw_ctx.evil_C, DST.draw_ctx.region, REGION_DRAW_POST_VIEW); - } + GPU_depth_test(GPU_DEPTH_NONE); + ED_region_draw_cb_draw(DST.draw_ctx.evil_C, DST.draw_ctx.region, REGION_DRAW_POST_VIEW); GPU_matrix_pop_projection(); /* Callback can be nasty and do whatever they want with the state. * Don't trust them! */ -- cgit v1.2.3 From 8d590e4b86287be22567d1adf8c6a7946bc7f63d Mon Sep 17 00:00:00 2001 From: Philipp Oeser Date: Wed, 16 Dec 2020 10:14:58 +0100 Subject: Fix T83801: UVEditor translation ignores "Pixel Coordinates" and aspect ratio Caused by rB4eda60c2d82d. T83801 reported not moving in pixel space, but even without that toggle above commit caused the translation to not take apsect ratio into account properly [a translation of 1 on the x axis for example on an image with non 1:1 aspect ration caused the UVs to not end up in the same place on the next 'tile'] Above commit removed 'removeAspectRatio()' [the counterpart of applyAspectRatio -- which does the pixel coord correction internally] from 'applyTranslation()'. This was also reported in T83352 [which was closed by rBf3b08af24c9f -- but that only solved the displax in header, not the actual transformation] Now bring back 'removeAspectRatio()'. Maniphest Tasks: T83801 Differential Revision: https://developer.blender.org/D9869 --- source/blender/editors/transform/transform_mode_translate.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source/blender') diff --git a/source/blender/editors/transform/transform_mode_translate.c b/source/blender/editors/transform/transform_mode_translate.c index 90c1f241338..8597c372537 100644 --- a/source/blender/editors/transform/transform_mode_translate.c +++ b/source/blender/editors/transform/transform_mode_translate.c @@ -377,6 +377,9 @@ static void applyTranslation(TransInfo *t, const int UNUSED(mval[2])) else { mul_v3_m3v3(global_dir, t->spacemtx, global_dir); } + if (t->flag & T_2D_EDIT) { + removeAspectRatio(t, global_dir); + } } else { copy_v3_v3(global_dir, t->values); -- cgit v1.2.3 From 25543e6983602b4d14f51d73396c652b2aa65aa0 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Wed, 16 Dec 2020 15:10:28 +0100 Subject: LibOverride: Better handling of missing linked data during resync. We do not generate overrides for missing data-blocks (aka placeholder ones) anymore, and properly delete the remaining old overrides of those during the resync process. This should prevent constant 'missing data-blocks' messages when opening blend files with overrides whose libraries have beed edited. Issue reported by @andy from Blender studio, thanks. --- source/blender/blenkernel/BKE_lib_override.h | 1 + source/blender/blenkernel/intern/lib_override.c | 32 ++++++++++++++++++------- 2 files changed, 25 insertions(+), 8 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/BKE_lib_override.h b/source/blender/blenkernel/BKE_lib_override.h index bf6b5cbccef..13edabd4cb7 100644 --- a/source/blender/blenkernel/BKE_lib_override.h +++ b/source/blender/blenkernel/BKE_lib_override.h @@ -72,6 +72,7 @@ void BKE_lib_override_library_dependencies_tag(struct Main *bmain, void BKE_lib_override_library_override_group_tag(struct Main *bmain, struct ID *id_root, const uint tag, + const uint missing_tag, const bool do_create_main_relashionships); bool BKE_lib_override_library_create(struct Main *bmain, struct Scene *scene, diff --git a/source/blender/blenkernel/intern/lib_override.c b/source/blender/blenkernel/intern/lib_override.c index d82315a0e7f..11544d83ba9 100644 --- a/source/blender/blenkernel/intern/lib_override.c +++ b/source/blender/blenkernel/intern/lib_override.c @@ -369,6 +369,7 @@ bool BKE_lib_override_library_create_from_tag(Main *bmain) static bool lib_override_hierarchy_recursive_tag(Main *bmain, ID *id, const uint tag, + const uint missing_tag, Library *override_group_lib_reference) { void **entry_vp = BLI_ghash_lookup_p(bmain->relations->id_user_to_used, id); @@ -377,9 +378,16 @@ static bool lib_override_hierarchy_recursive_tag(Main *bmain, return (id->tag & tag) != 0; } + /* Note: in case some reference ID is missing from linked data (and therefore its override uses + * a placeholder as reference), use `missing_tag` instead of `tag` for this override. */ if (override_group_lib_reference != NULL && ID_IS_OVERRIDE_LIBRARY_REAL(id) && id->override_library->reference->lib == override_group_lib_reference) { - id->tag |= tag; + if (id->override_library->reference->tag & LIB_TAG_MISSING) { + id->tag |= missing_tag; + } + else { + id->tag |= tag; + } } /* This way we won't process again that ID, should we encounter it again through another @@ -397,7 +405,7 @@ static bool lib_override_hierarchy_recursive_tag(Main *bmain, /* We only consider IDs from the same library. */ if (entry->id_pointer != NULL && (*entry->id_pointer)->lib == id->lib) { if (lib_override_hierarchy_recursive_tag( - bmain, *entry->id_pointer, tag, override_group_lib_reference) && + bmain, *entry->id_pointer, tag, missing_tag, override_group_lib_reference) && override_group_lib_reference == NULL) { id->tag |= tag; } @@ -430,7 +438,7 @@ void BKE_lib_override_library_dependencies_tag(Main *bmain, /* We tag all intermediary data-blocks in-between two overridden ones (e.g. if a shape-key * has a driver using an armature object's bone, we need to override the shape-key/obdata, * the objects using them, etc.) */ - lib_override_hierarchy_recursive_tag(bmain, id_root, tag, NULL); + lib_override_hierarchy_recursive_tag(bmain, id_root, tag, 0, NULL); BKE_main_relations_free(bmain); } @@ -447,6 +455,7 @@ void BKE_lib_override_library_dependencies_tag(Main *bmain, void BKE_lib_override_library_override_group_tag(Main *bmain, ID *id_root, const uint tag, + const uint missing_tag, const bool do_create_main_relashionships) { if (do_create_main_relashionships) { @@ -456,7 +465,7 @@ void BKE_lib_override_library_override_group_tag(Main *bmain, /* We tag all liboverride data-blocks from the same library as reference one, * being used by the root ID. */ lib_override_hierarchy_recursive_tag( - bmain, id_root, tag, id_root->override_library->reference->lib); + bmain, id_root, tag, missing_tag, id_root->override_library->reference->lib); BKE_main_relations_free(bmain); } @@ -492,8 +501,9 @@ static int lib_override_library_make_tag_ids_cb(LibraryIDLinkCallbackData *cb_da } /* We tag all collections and objects for override. And we also tag all other data-blocks which - * would use one of those. */ - if (ELEM(GS(id->name), ID_OB, ID_GR)) { + * would use one of those. + * Note: missing IDs (aka placeholders) are never overridden. */ + if (ELEM(GS(id->name), ID_OB, ID_GR) && !(id->tag & LIB_TAG_MISSING)) { id->tag |= LIB_TAG_DOIT; } @@ -725,7 +735,7 @@ bool BKE_lib_override_library_resync(Main *bmain, Scene *scene, ViewLayer *view_ /* Make a mapping 'linked reference IDs' -> 'Local override IDs' of existing overrides, and tag * linked reference ones to be overridden again. */ - BKE_lib_override_library_override_group_tag(bmain, id_root, LIB_TAG_DOIT, true); + BKE_lib_override_library_override_group_tag(bmain, id_root, LIB_TAG_DOIT, LIB_TAG_MISSING, true); GHash *linkedref_to_old_override = BLI_ghash_new( BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__); @@ -835,6 +845,12 @@ bool BKE_lib_override_library_resync(Main *bmain, Scene *scene, ViewLayer *view_ } id->tag &= ~LIB_TAG_DOIT; } + /* Also cleanup old overrides that went missing in new linked data. */ + else if (id->tag & LIB_TAG_MISSING && !ID_IS_LINKED(id)) { + BLI_assert(ID_IS_OVERRIDE_LIBRARY(id)); + id->tag |= LIB_TAG_DOIT; + id->tag &= ~LIB_TAG_MISSING; + } } FOREACH_MAIN_ID_END; BKE_id_multi_tagged_delete(bmain); @@ -876,7 +892,7 @@ void BKE_lib_override_library_delete(Main *bmain, ID *id_root) id_root->tag |= LIB_TAG_DOIT; /* Tag all library overrides in the chains of dependencies from the given root one. */ - BKE_lib_override_library_override_group_tag(bmain, id_root, LIB_TAG_DOIT, true); + BKE_lib_override_library_override_group_tag(bmain, id_root, LIB_TAG_DOIT, LIB_TAG_DOIT, true); ID *id; FOREACH_MAIN_ID_BEGIN (bmain, id) { -- cgit v1.2.3 From 684c771263db1a5a7dbf65cde97e672d94b57839 Mon Sep 17 00:00:00 2001 From: Ray Molenkamp Date: Wed, 16 Dec 2020 07:27:47 -0700 Subject: Fix: Python warning in windows debug builds When doing a debug build on windows, blender will start with the following warning: "Unable to find the python binary, the multiprocessing module may not be functional!" The root cause for this issue is: for a debug build the python binary is called python_d.exe rather than just python.exe This change fixes BKE_appdir_program_python_search to look for the _d suffix for debug builds on windows Differential Revision: https://developer.blender.org/D9775 Reviewed by: Campbell Barton --- source/blender/blenkernel/intern/appdir.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/intern/appdir.c b/source/blender/blenkernel/intern/appdir.c index a6b3985e80d..ae0c27635a6 100644 --- a/source/blender/blenkernel/intern/appdir.c +++ b/source/blender/blenkernel/intern/appdir.c @@ -906,14 +906,20 @@ bool BKE_appdir_program_python_search(char *fullpath, const char *python_build_def = STRINGIFY(PYTHON_EXECUTABLE_NAME); #endif const char *basename = "python"; +#if defined(WIN32) && !defined(NDEBUG) + const char *basename_debug = "python_d"; +#endif char python_version[16]; /* Check both possible names. */ const char *python_names[] = { #ifdef PYTHON_EXECUTABLE_NAME - python_build_def, + python_build_def, +#endif +#if defined(WIN32) && !defined(NDEBUG) + basename_debug, #endif - python_version, - basename, + python_version, + basename, }; bool is_found = false; -- cgit v1.2.3 From 4463087223983c40a6d67beab0513fba7cdb7538 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Wed, 16 Dec 2020 15:59:58 +0100 Subject: BLI: remove implicit casts between some span types Casting pointers from one type to another does change the value of the pointer in some cases. Therefore, casting a span that contains pointers of one type to a span that contains pointers of another type, is not generally safe. In practice, this issue mainly comes up when dealing with classes that have a vtable. There are some special cases that are still allowed. For example, adding const to the pointer does not change the address. Also, casting to a void pointer is fine. In cases where implicit conversion is disabled, but one is sure that the cast is valid, an explicit call of `span.cast()` can be used. --- source/blender/blenlib/BLI_array.hh | 4 ++-- source/blender/blenlib/BLI_memory_utils.hh | 19 +++++++++++++++++++ source/blender/blenlib/BLI_span.hh | 5 +++-- source/blender/blenlib/BLI_vector.hh | 4 ++-- source/blender/blenlib/tests/BLI_memory_utils_test.cc | 11 +++++++++++ 5 files changed, 37 insertions(+), 6 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenlib/BLI_array.hh b/source/blender/blenlib/BLI_array.hh index 8a7dcb7ffaa..284d62fb876 100644 --- a/source/blender/blenlib/BLI_array.hh +++ b/source/blender/blenlib/BLI_array.hh @@ -220,13 +220,13 @@ class Array { return MutableSpan(data_, size_); } - template> * = nullptr> + template> * = nullptr> operator Span() const { return Span(data_, size_); } - template> * = nullptr> + template> * = nullptr> operator MutableSpan() { return MutableSpan(data_, size_); diff --git a/source/blender/blenlib/BLI_memory_utils.hh b/source/blender/blenlib/BLI_memory_utils.hh index 49076bb1aae..b3b6855089e 100644 --- a/source/blender/blenlib/BLI_memory_utils.hh +++ b/source/blender/blenlib/BLI_memory_utils.hh @@ -427,6 +427,25 @@ template inline constexpr bool is_convertible_pointer_v = std::is_convertible_v &&std::is_pointer_v &&std::is_pointer_v; +/** + * Helper variable that checks if a Span can be converted to Span safely, whereby From + * and To are pointers. Adding const and casting to a void pointer is allowed. + * Casting up and down a class hierarchy generally is not allowed, because this might change the + * pointer under some circumstances. + */ +template +inline constexpr bool is_span_convertible_pointer_v = + /* Make sure we are working with pointers. */ + std::is_pointer_v &&std::is_pointer_v && + (/* No casting is necessary when both types are the same. */ + std::is_same_v || + /* Allow adding const to the underlying type. */ + std::is_same_v, std::remove_pointer_t> || + /* Allow casting non-const pointers to void pointers. */ + (!std::is_const_v> && std::is_same_v) || + /* Allow casting any pointer to const void pointers. */ + std::is_same_v); + /** * Inline buffers for small-object-optimization should be disable by default. Otherwise we might * get large unexpected allocations on the stack. diff --git a/source/blender/blenlib/BLI_span.hh b/source/blender/blenlib/BLI_span.hh index 3f410efe908..8011b2f9abc 100644 --- a/source/blender/blenlib/BLI_span.hh +++ b/source/blender/blenlib/BLI_span.hh @@ -100,7 +100,7 @@ template class Span { BLI_assert(size >= 0); } - template> * = nullptr> + template> * = nullptr> constexpr Span(const U *start, int64_t size) : data_(static_cast(start)), size_(size) { BLI_assert(size >= 0); @@ -135,7 +135,8 @@ template class Span { * Support implicit conversions like the ones below: * Span -> Span */ - template> * = nullptr> + + template> * = nullptr> constexpr Span(Span array) : data_(static_cast(array.data())), size_(array.size()) { } diff --git a/source/blender/blenlib/BLI_vector.hh b/source/blender/blenlib/BLI_vector.hh index 053dcb6faea..fe6d54ae9e5 100644 --- a/source/blender/blenlib/BLI_vector.hh +++ b/source/blender/blenlib/BLI_vector.hh @@ -315,13 +315,13 @@ class Vector { return MutableSpan(begin_, this->size()); } - template> * = nullptr> + template> * = nullptr> operator Span() const { return Span(begin_, this->size()); } - template> * = nullptr> + template> * = nullptr> operator MutableSpan() { return MutableSpan(begin_, this->size()); diff --git a/source/blender/blenlib/tests/BLI_memory_utils_test.cc b/source/blender/blenlib/tests/BLI_memory_utils_test.cc index fcef2f8688a..23415e69b04 100644 --- a/source/blender/blenlib/tests/BLI_memory_utils_test.cc +++ b/source/blender/blenlib/tests/BLI_memory_utils_test.cc @@ -158,4 +158,15 @@ static_assert(is_convertible_pointer_v); static_assert(is_convertible_pointer_v); static_assert(is_convertible_pointer_v); +static_assert(is_span_convertible_pointer_v); +static_assert(is_span_convertible_pointer_v); +static_assert(!is_span_convertible_pointer_v); +static_assert(is_span_convertible_pointer_v); +static_assert(is_span_convertible_pointer_v); +static_assert(!is_span_convertible_pointer_v); +static_assert(is_span_convertible_pointer_v); +static_assert(is_span_convertible_pointer_v); +static_assert(!is_span_convertible_pointer_v); +static_assert(!is_span_convertible_pointer_v); + } // namespace blender::tests -- cgit v1.2.3 From 7ed69bd672555f6bbedc598aacda56efb6eeafbb Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Wed, 16 Dec 2020 16:07:23 +0100 Subject: Fix T83843: Crash in Asset Browser sidebar with geometry asset selected No icon should be created if the preview doesn't exist. --- source/blender/editors/space_file/filelist.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source/blender') diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c index 3ed7b5499db..8202a87864d 100644 --- a/source/blender/editors/space_file/filelist.c +++ b/source/blender/editors/space_file/filelist.c @@ -1511,7 +1511,9 @@ static void filelist_cache_preview_runf(TaskPool *__restrict pool, void *taskdat * in case user switch to a bigger preview size. */ ImBuf *imbuf = IMB_thumb_manage(preview->path, THB_LARGE, source); IMB_thumb_path_unlock(preview->path); - preview->icon_id = BKE_icon_imbuf_create(imbuf); + if (imbuf) { + preview->icon_id = BKE_icon_imbuf_create(imbuf); + } done = true; } -- cgit v1.2.3 From 5c5550f7b821cb6c67009682fec85ce0929474a3 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Wed, 16 Dec 2020 16:10:53 +0100 Subject: Asset Browser: For assets without preview, show type icon in sidebar Otherwise it would just show empty space where the icon is supposed to be. Unfortunately this icon is upscaled quite a bit and doesn't look too great. Would be good to improve but not a high priority. --- source/blender/editors/include/ED_fileselect.h | 2 ++ source/blender/editors/space_file/filelist.c | 10 ++++++++-- source/blender/makesrna/intern/rna_space.c | 2 +- 3 files changed, 11 insertions(+), 3 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/include/ED_fileselect.h b/source/blender/editors/include/ED_fileselect.h index 6c66a6162b8..7b240e0569f 100644 --- a/source/blender/editors/include/ED_fileselect.h +++ b/source/blender/editors/include/ED_fileselect.h @@ -30,6 +30,7 @@ extern "C" { struct ARegion; struct FileAssetSelectParams; struct FileSelectParams; +struct FileDirEntry; struct Scene; struct ScrArea; struct SpaceFile; @@ -154,6 +155,7 @@ struct ScrArea *ED_fileselect_handler_area_find(const struct wmWindow *win, int ED_path_extension_type(const char *path); int ED_file_extension_icon(const char *path); +int ED_file_icon(const struct FileDirEntry *file); void ED_file_read_bookmarks(void); diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c index 8202a87864d..d66219c7549 100644 --- a/source/blender/editors/space_file/filelist.c +++ b/source/blender/editors/space_file/filelist.c @@ -1178,7 +1178,7 @@ ImBuf *filelist_geticon_image(struct FileList *filelist, const int index) return filelist_geticon_image_ex(file); } -static int filelist_geticon_ex(FileDirEntry *file, +static int filelist_geticon_ex(const FileDirEntry *file, const char *root, const bool is_main, const bool ignore_libdir) @@ -1217,7 +1217,7 @@ static int filelist_geticon_ex(FileDirEntry *file, if (file->redirection_path) { target = file->redirection_path; } - else { + else if (root) { BLI_join_dirfile(fullpath, sizeof(fullpath), root, file->relpath); BLI_path_slash_ensure(fullpath); } @@ -1301,6 +1301,12 @@ int filelist_geticon(struct FileList *filelist, const int index, const bool is_m return filelist_geticon_ex(file, filelist->filelist.root, is_main, false); } +int ED_file_icon(const FileDirEntry *file) +{ + return file->preview_icon_id ? file->preview_icon_id : + filelist_geticon_ex(file, NULL, false, false); +} + /* ********** Main ********** */ static void parent_dir_until_exists_or_default_root(char *dir) diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 7405bc541c9..2f821dad811 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -2602,7 +2602,7 @@ static int rna_FileBrowser_FileSelectEntry_name_length(PointerRNA *ptr) static int rna_FileBrowser_FileSelectEntry_preview_icon_id_get(PointerRNA *ptr) { const FileDirEntry *entry = ptr->data; - return entry->preview_icon_id; + return ED_file_icon(entry); } static PointerRNA rna_FileBrowser_FileSelectEntry_asset_data_get(PointerRNA *ptr) -- cgit v1.2.3 From f3ab123e33b87cfcf4d310323572c798f9953201 Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Wed, 16 Dec 2020 16:16:50 +0100 Subject: Cleanup: Remove unused crop field from RenderResult. The `crop` field was used by Blender Internal to do an overscan per tile and merge it back to the render result. --- source/blender/editors/render/render_internal.c | 18 +++++----- source/blender/render/RE_pipeline.h | 2 +- source/blender/render/intern/engine.c | 4 +-- source/blender/render/intern/pipeline.c | 6 ++-- source/blender/render/intern/render_result.c | 47 ++++++------------------- source/blender/render/intern/render_result.h | 1 - 6 files changed, 26 insertions(+), 52 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c index 3dbf70aa4bc..a035ee3e342 100644 --- a/source/blender/editors/render/render_internal.c +++ b/source/blender/editors/render/render_internal.c @@ -150,31 +150,31 @@ static void image_buffer_rect_update(RenderJob *rj, } /* xmin here is first subrect x coord, xmax defines subrect width */ - xmin = renrect->xmin + rr->crop; - xmax = renrect->xmax - xmin + rr->crop; + xmin = renrect->xmin; + xmax = renrect->xmax - xmin; if (xmax < 2) { return; } - ymin = renrect->ymin + rr->crop; - ymax = renrect->ymax - ymin + rr->crop; + ymin = renrect->ymin; + ymax = renrect->ymax - ymin; if (ymax < 2) { return; } renrect->ymin = renrect->ymax; } else { - xmin = ymin = rr->crop; - xmax = rr->rectx - 2 * rr->crop; - ymax = rr->recty - 2 * rr->crop; + xmin = ymin = 0; + xmax = rr->rectx; + ymax = rr->recty; } /* xmin ymin is in tile coords. transform to ibuf */ - rxmin = rr->tilerect.xmin + xmin; + rxmin = rr->tilerect.xmin; if (rxmin >= ibuf->x) { return; } - rymin = rr->tilerect.ymin + ymin; + rymin = rr->tilerect.ymin; if (rymin >= ibuf->y) { return; } diff --git a/source/blender/render/RE_pipeline.h b/source/blender/render/RE_pipeline.h index 4dd2b300700..3e73ac77fc6 100644 --- a/source/blender/render/RE_pipeline.h +++ b/source/blender/render/RE_pipeline.h @@ -114,7 +114,7 @@ typedef struct RenderResult { /* target image size */ int rectx, recty; - short crop, sample_nr; + short sample_nr; /* The following rect32, rectf and rectz buffers are for temporary storage only, * for RenderResult structs created in #RE_AcquireResultImage - which do not have RenderView */ diff --git a/source/blender/render/intern/engine.c b/source/blender/render/intern/engine.c index 769077c0e8c..5685911c42e 100644 --- a/source/blender/render/intern/engine.c +++ b/source/blender/render/intern/engine.c @@ -288,7 +288,7 @@ RenderResult *RE_engine_begin_result( disprect.ymin = y; disprect.ymax = y + h; - result = render_result_new(re, &disprect, 0, RR_USE_MEM, layername, viewname); + result = render_result_new(re, &disprect, RR_USE_MEM, layername, viewname); /* todo: make this thread safe */ @@ -846,7 +846,7 @@ int RE_engine_render(Render *re, int do_all) if ((type->flag & RE_USE_SAVE_BUFFERS) && (re->r.scemode & R_EXR_TILE_FILE)) { savebuffers = RR_USE_EXR; } - re->result = render_result_new(re, &re->disprect, 0, savebuffers, RR_ALL_LAYERS, RR_ALL_VIEWS); + re->result = render_result_new(re, &re->disprect, savebuffers, RR_ALL_LAYERS, RR_ALL_VIEWS); } BLI_rw_mutex_unlock(&re->resultmutex); diff --git a/source/blender/render/intern/pipeline.c b/source/blender/render/intern/pipeline.c index 3d19e5e6c15..6b55b82ac97 100644 --- a/source/blender/render/intern/pipeline.c +++ b/source/blender/render/intern/pipeline.c @@ -905,7 +905,7 @@ static void render_result_rescale(Render *re) if (src_rectf != NULL) { float *dst_rectf = NULL; - re->result = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS, ""); + re->result = render_result_new(re, &re->disprect, RR_USE_MEM, RR_ALL_LAYERS, ""); if (re->result != NULL) { dst_rectf = RE_RenderViewGetById(re->result, 0)->rectf; @@ -1162,7 +1162,7 @@ static void render_result_uncrop(Render *re) /* weak is: it chances disprect from border */ render_result_disprect_to_full_resolution(re); - rres = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS, RR_ALL_VIEWS); + rres = render_result_new(re, &re->disprect, RR_USE_MEM, RR_ALL_LAYERS, RR_ALL_VIEWS); rres->stamp_data = BKE_stamp_data_copy(re->result->stamp_data); render_result_clone_passes(re, rres, NULL); @@ -1358,7 +1358,7 @@ static void do_render_composite(Render *re) if ((re->r.mode & R_CROP) == 0) { render_result_disprect_to_full_resolution(re); } - re->result = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS, RR_ALL_VIEWS); + re->result = render_result_new(re, &re->disprect, RR_USE_MEM, RR_ALL_LAYERS, RR_ALL_VIEWS); BLI_rw_mutex_unlock(&re->resultmutex); diff --git a/source/blender/render/intern/render_result.c b/source/blender/render/intern/render_result.c index dfce51ec3ab..1ed894751ce 100644 --- a/source/blender/render/intern/render_result.c +++ b/source/blender/render/intern/render_result.c @@ -285,12 +285,8 @@ RenderPass *render_layer_add_pass(RenderResult *rr, /* will read info from Render *re to define layers */ /* called in threads */ /* re->winx,winy is coordinate space of entire image, partrct the part within */ -RenderResult *render_result_new(Render *re, - rcti *partrct, - int crop, - int savebuffers, - const char *layername, - const char *viewname) +RenderResult *render_result_new( + Render *re, rcti *partrct, int savebuffers, const char *layername, const char *viewname) { RenderResult *rr; RenderLayer *rl; @@ -308,9 +304,7 @@ RenderResult *render_result_new(Render *re, rr->rectx = rectx; rr->recty = recty; rr->renrect.xmin = 0; - rr->renrect.xmax = rectx - 2 * crop; - /* crop is one or two extra pixels rendered for filtering, is used for merging and display too */ - rr->crop = crop; + rr->renrect.xmax = rectx; /* tilerect is relative coordinates within render disprect. do not subtract crop yet */ rr->tilerect.xmin = partrct->xmin - re->disprect.xmin; @@ -827,20 +821,8 @@ static void do_merge_tile( copylen = tilex = rrpart->rectx; tiley = rrpart->recty; - if (rrpart->crop) { /* filters add pixel extra */ - tile += pixsize * (rrpart->crop + ((size_t)rrpart->crop) * tilex); - - copylen = tilex - 2 * rrpart->crop; - tiley -= 2 * rrpart->crop; - - ofs = (((size_t)rrpart->tilerect.ymin) + rrpart->crop) * rr->rectx + - (rrpart->tilerect.xmin + rrpart->crop); - target += pixsize * ofs; - } - else { - ofs = (((size_t)rrpart->tilerect.ymin) * rr->rectx + rrpart->tilerect.xmin); - target += pixsize * ofs; - } + ofs = (((size_t)rrpart->tilerect.ymin) * rr->rectx + rrpart->tilerect.xmin); + target += pixsize * ofs; copylen *= sizeof(float) * pixsize; tilex *= pixsize; @@ -1107,7 +1089,7 @@ static void save_render_result_tile(RenderResult *rr, RenderResult *rrpart, cons { RenderLayer *rlp, *rl; RenderPass *rpassp; - int offs, partx, party; + int partx, party; BLI_thread_lock(LOCK_IMAGE); @@ -1120,13 +1102,6 @@ static void save_render_result_tile(RenderResult *rr, RenderResult *rrpart, cons continue; } - if (rrpart->crop) { /* filters add pixel extra */ - offs = (rrpart->crop + rrpart->crop * rrpart->rectx); - } - else { - offs = 0; - } - /* passes are allocated in sync */ for (rpassp = rlp->passes.first; rpassp; rpassp = rpassp->next) { const int xstride = rpassp->channels; @@ -1141,13 +1116,13 @@ static void save_render_result_tile(RenderResult *rr, RenderResult *rrpart, cons fullname, xstride, xstride * rrpart->rectx, - rpassp->rect + a + xstride * offs); + rpassp->rect + a); } } } - party = rrpart->tilerect.ymin + rrpart->crop; - partx = rrpart->tilerect.xmin + rrpart->crop; + party = rrpart->tilerect.ymin; + partx = rrpart->tilerect.xmin; for (rlp = rrpart->layers.first; rlp; rlp = rlp->next) { rl = RE_GetRenderLayer(rr, rlp->name); @@ -1267,7 +1242,7 @@ void render_result_exr_file_end(Render *re, RenderEngine *engine) /* Create new render result in memory instead of on disk. */ BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); render_result_free_list(&re->fullresult, re->result); - re->result = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS, RR_ALL_VIEWS); + re->result = render_result_new(re, &re->disprect, RR_USE_MEM, RR_ALL_LAYERS, RR_ALL_VIEWS); BLI_rw_mutex_unlock(&re->resultmutex); LISTBASE_FOREACH (RenderLayer *, rl, &re->result->layers) { @@ -1429,7 +1404,7 @@ bool render_result_exr_file_cache_read(Render *re) char *root = U.render_cachedir; RE_FreeRenderResult(re->result); - re->result = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS, RR_ALL_VIEWS); + re->result = render_result_new(re, &re->disprect, RR_USE_MEM, RR_ALL_LAYERS, RR_ALL_VIEWS); /* First try cache. */ render_result_exr_file_cache_path(re->scene, root, str); diff --git a/source/blender/render/intern/render_result.h b/source/blender/render/intern/render_result.h index 5c487223e94..67edd075e24 100644 --- a/source/blender/render/intern/render_result.h +++ b/source/blender/render/intern/render_result.h @@ -51,7 +51,6 @@ extern "C" { struct RenderResult *render_result_new(struct Render *re, struct rcti *partrct, - int crop, int savebuffers, const char *layername, const char *viewname); -- cgit v1.2.3 From d23894d3ef3f019eeb88ef3da77e8416c6f70f29 Mon Sep 17 00:00:00 2001 From: Pablo Dobarro Date: Fri, 11 Dec 2020 22:49:49 +0100 Subject: Sculpt: Multires Displacement Smear This tool implements smearing for multires displacement over the limit surface, similar to how smearing for colors and topology slide works. When used the displacement values of the vertices "slide" over the topology, creating the effect of smearing the surface detail. As the brush just modifies displacement values instead of coordinates, the total displacement of the affected area doesn't change. This means that this smearing effect can be used multiple times over the same area without generating any artifacts in the topology. When the brush is used with the pinch or expand smear modes, displacement differences are pushed into the same area, creating hard surface effects without pinching the topology. As any other brush that relies on the limit surface (like displacement erasers), this will work better after using apply base. Reviewed By: sergey, JulienKaspar, dbystedt Differential Revision: https://developer.blender.org/D9659 --- source/blender/blenkernel/intern/brush.c | 9 ++ .../blenloader/intern/versioning_defaults.c | 8 ++ source/blender/editors/sculpt_paint/sculpt.c | 151 +++++++++++++++++++++ .../blender/editors/sculpt_paint/sculpt_intern.h | 4 + source/blender/makesdna/DNA_brush_enums.h | 1 + source/blender/makesdna/DNA_brush_types.h | 2 +- source/blender/makesrna/intern/rna_brush.c | 1 + 7 files changed, 175 insertions(+), 1 deletion(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index 33686cea4fc..9a954a89cad 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -1834,6 +1834,14 @@ void BKE_brush_sculpt_reset(Brush *br) br->flag &= ~BRUSH_SPACE_ATTEN; br->curve_preset = BRUSH_CURVE_SPHERE; break; + case SCULPT_TOOL_DISPLACEMENT_SMEAR: + br->alpha = 1.0f; + br->spacing = 5; + br->hardness = 0.7f; + br->flag &= ~BRUSH_ALPHA_PRESSURE; + br->flag &= ~BRUSH_SPACE_ATTEN; + br->curve_preset = BRUSH_CURVE_SMOOTHER; + break; default: break; } @@ -1898,6 +1906,7 @@ void BKE_brush_sculpt_reset(Brush *br) case SCULPT_TOOL_MASK: case SCULPT_TOOL_DRAW_FACE_SETS: case SCULPT_TOOL_DISPLACEMENT_ERASER: + case SCULPT_TOOL_DISPLACEMENT_SMEAR: br->add_col[0] = 0.75f; br->add_col[1] = 0.75f; br->add_col[2] = 0.75f; diff --git a/source/blender/blenloader/intern/versioning_defaults.c b/source/blender/blenloader/intern/versioning_defaults.c index 2d75b046366..198f65b9794 100644 --- a/source/blender/blenloader/intern/versioning_defaults.c +++ b/source/blender/blenloader/intern/versioning_defaults.c @@ -739,6 +739,14 @@ void BLO_update_defaults_startup_blend(Main *bmain, const char *app_template) brush->sculpt_tool = SCULPT_TOOL_DISPLACEMENT_ERASER; } + brush_name = "Multires Displacement Smear"; + brush = BLI_findstring(&bmain->brushes, brush_name, offsetof(ID, name) + 2); + if (!brush) { + brush = BKE_brush_add(bmain, brush_name, OB_MODE_SCULPT); + id_us_min(&brush->id); + brush->sculpt_tool = SCULPT_TOOL_DISPLACEMENT_SMEAR; + } + /* Use the same tool icon color in the brush cursor */ for (brush = bmain->brushes.first; brush; brush = brush->id.next) { if (brush->ob_mode & OB_MODE_SCULPT) { diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 80a32682325..26db2673335 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -1227,6 +1227,7 @@ static bool sculpt_tool_is_proxy_used(const char sculpt_tool) SCULPT_TOOL_SMOOTH, SCULPT_TOOL_LAYER, SCULPT_TOOL_POSE, + SCULPT_TOOL_DISPLACEMENT_SMEAR, SCULPT_TOOL_BOUNDARY, SCULPT_TOOL_CLOTH, SCULPT_TOOL_PAINT, @@ -2362,6 +2363,7 @@ static float brush_strength(const Sculpt *sd, final_pressure = pressure * pressure; return final_pressure * overlap * feather; case SCULPT_TOOL_SMEAR: + case SCULPT_TOOL_DISPLACEMENT_SMEAR: return alpha * pressure * overlap * feather; case SCULPT_TOOL_CLAY_STRIPS: /* Clay Strips needs less strength to compensate the curve. */ @@ -3103,6 +3105,147 @@ static void do_displacement_eraser_brush(Sculpt *sd, Object *ob, PBVHNode **node /** \} */ +/** \name Sculpt Multires Displacement Smear Brush + * \{ */ + +static void do_displacement_smear_brush_task_cb_ex(void *__restrict userdata, + const int n, + const TaskParallelTLS *__restrict tls) +{ + SculptThreadedTaskData *data = userdata; + SculptSession *ss = data->ob->sculpt; + const Brush *brush = data->brush; + const float bstrength = clamp_f(ss->cache->bstrength, 0.0f, 1.0f); + + SculptBrushTest test; + SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( + ss, &test, data->brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(tls); + + PBVHVertexIter vd; + BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) + { + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + + float current_disp[3]; + float current_disp_norm[3]; + float interp_limit_surface_disp[3]; + + copy_v3_v3(interp_limit_surface_disp, ss->cache->prev_displacement[vd.index]); + + switch (brush->smear_deform_type) { + case BRUSH_SMEAR_DEFORM_DRAG: + sub_v3_v3v3(current_disp, ss->cache->location, ss->cache->last_location); + break; + case BRUSH_SMEAR_DEFORM_PINCH: + sub_v3_v3v3(current_disp, ss->cache->location, vd.co); + break; + case BRUSH_SMEAR_DEFORM_EXPAND: + sub_v3_v3v3(current_disp, vd.co, ss->cache->location); + break; + } + + normalize_v3_v3(current_disp_norm, current_disp); + mul_v3_v3fl(current_disp, current_disp_norm, ss->cache->bstrength); + + float weights_accum = 1.0f; + + SculptVertexNeighborIter ni; + SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd.index, ni) { + float vertex_disp[3]; + float vertex_disp_norm[3]; + float neighbor_limit_co[3]; + SCULPT_vertex_limit_surface_get(ss, ni.index, neighbor_limit_co); + sub_v3_v3v3(vertex_disp, + ss->cache->limit_surface_co[ni.index], + ss->cache->limit_surface_co[vd.index]); + const float *neighbor_limit_surface_disp = ss->cache->prev_displacement[ni.index]; + normalize_v3_v3(vertex_disp_norm, vertex_disp); + if (dot_v3v3(current_disp_norm, vertex_disp_norm) < 0.0f) { + const float disp_interp = clamp_f( + -dot_v3v3(current_disp_norm, vertex_disp_norm), 0.0f, 1.0f); + madd_v3_v3fl(interp_limit_surface_disp, neighbor_limit_surface_disp, disp_interp); + weights_accum += disp_interp; + } + } + SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); + + mul_v3_fl(interp_limit_surface_disp, 1.0f / weights_accum); + + float new_co[3]; + add_v3_v3v3(new_co, ss->cache->limit_surface_co[vd.index], interp_limit_surface_disp); + interp_v3_v3v3(vd.co, vd.co, new_co, fade); + + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; + } + } + BKE_pbvh_vertex_iter_end; +} + +static void do_displacement_smear_store_prev_disp_task_cb_ex( + void *__restrict userdata, const int n, const TaskParallelTLS *__restrict UNUSED(tls)) +{ + SculptThreadedTaskData *data = userdata; + SculptSession *ss = data->ob->sculpt; + + PBVHVertexIter vd; + BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) + { + sub_v3_v3v3(ss->cache->prev_displacement[vd.index], + SCULPT_vertex_co_get(ss, vd.index), + ss->cache->limit_surface_co[vd.index]); + } + BKE_pbvh_vertex_iter_end; +} + +static void do_displacement_smear_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) +{ + Brush *brush = BKE_paint_brush(&sd->paint); + SculptSession *ss = ob->sculpt; + + BKE_curvemapping_init(brush->curve); + + const int totvert = SCULPT_vertex_count_get(ss); + if (!ss->cache->prev_displacement) { + ss->cache->prev_displacement = MEM_malloc_arrayN( + totvert, sizeof(float[3]), "prev displacement"); + ss->cache->limit_surface_co = MEM_malloc_arrayN(totvert, sizeof(float[3]), "limit surface co"); + for (int i = 0; i < totvert; i++) { + SCULPT_vertex_limit_surface_get(ss, i, ss->cache->limit_surface_co[i]); + sub_v3_v3v3(ss->cache->prev_displacement[i], + SCULPT_vertex_co_get(ss, i), + ss->cache->limit_surface_co[i]); + } + } + /* Threaded loop over nodes. */ + SculptThreadedTaskData data = { + .sd = sd, + .ob = ob, + .brush = brush, + .nodes = nodes, + }; + + TaskParallelSettings settings; + BKE_pbvh_parallel_range_settings(&settings, true, totnode); + BLI_task_parallel_range( + 0, totnode, &data, do_displacement_smear_store_prev_disp_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_displacement_smear_brush_task_cb_ex, &settings); +} + +/** \} */ + static void do_draw_brush_task_cb_ex(void *__restrict userdata, const int n, const TaskParallelTLS *__restrict tls) @@ -5927,6 +6070,9 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe case SCULPT_TOOL_DISPLACEMENT_ERASER: do_displacement_eraser_brush(sd, ob, nodes, totnode); break; + case SCULPT_TOOL_DISPLACEMENT_SMEAR: + do_displacement_smear_brush(sd, ob, nodes, totnode); + break; case SCULPT_TOOL_PAINT: SCULPT_do_paint_brush(sd, ob, nodes, totnode); break; @@ -6490,6 +6636,8 @@ static const char *sculpt_tool_name(Sculpt *sd) return "Draw Face Sets"; case SCULPT_TOOL_DISPLACEMENT_ERASER: return "Multires Displacement Eraser"; + case SCULPT_TOOL_DISPLACEMENT_SMEAR: + return "Multires Displacement Smear"; case SCULPT_TOOL_PAINT: return "Paint Brush"; case SCULPT_TOOL_SMEAR: @@ -6510,6 +6658,8 @@ void SCULPT_cache_free(StrokeCache *cache) MEM_SAFE_FREE(cache->layer_displacement_factor); MEM_SAFE_FREE(cache->prev_colors); MEM_SAFE_FREE(cache->detail_directions); + MEM_SAFE_FREE(cache->prev_displacement); + MEM_SAFE_FREE(cache->limit_surface_co); if (cache->pose_ik_chain) { SCULPT_pose_ik_chain_free(cache->pose_ik_chain); @@ -6681,6 +6831,7 @@ static void sculpt_update_cache_invariants( SCULPT_TOOL_MASK, SCULPT_TOOL_SMOOTH, SCULPT_TOOL_SIMPLIFY, + SCULPT_TOOL_DISPLACEMENT_SMEAR, SCULPT_TOOL_DISPLACEMENT_ERASER) && (sd->gravity_factor > 0.0f)); /* Get gravity vector in world space. */ diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h index 853b221e92a..d1e17c7e59b 100644 --- a/source/blender/editors/sculpt_paint/sculpt_intern.h +++ b/source/blender/editors/sculpt_paint/sculpt_intern.h @@ -926,6 +926,10 @@ typedef struct StrokeCache { float (*prev_colors)[4]; + /* Multires Displacement Smear. */ + float (*prev_displacement)[3]; + float (*limit_surface_co)[3]; + /* The rest is temporary storage that isn't saved as a property */ bool first_time; /* Beginning of stroke may do some things special */ diff --git a/source/blender/makesdna/DNA_brush_enums.h b/source/blender/makesdna/DNA_brush_enums.h index 96e870cff8e..f12934c9104 100644 --- a/source/blender/makesdna/DNA_brush_enums.h +++ b/source/blender/makesdna/DNA_brush_enums.h @@ -457,6 +457,7 @@ typedef enum eBrushSculptTool { SCULPT_TOOL_SMEAR = 29, SCULPT_TOOL_BOUNDARY = 30, SCULPT_TOOL_DISPLACEMENT_ERASER = 31, + SCULPT_TOOL_DISPLACEMENT_SMEAR = 32, } eBrushSculptTool; /* Brush.uv_sculpt_tool */ diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h index 4b020019062..1709ea5dc63 100644 --- a/source/blender/makesdna/DNA_brush_types.h +++ b/source/blender/makesdna/DNA_brush_types.h @@ -373,7 +373,7 @@ typedef struct Brush { typedef struct tPaletteColorHSV { float rgb[3]; float value; - float h; + float h; float s; float v; } tPaletteColorHSV; diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c index 08c655d493c..a361feba439 100644 --- a/source/blender/makesrna/intern/rna_brush.c +++ b/source/blender/makesrna/intern/rna_brush.c @@ -134,6 +134,7 @@ const EnumPropertyItem rna_enum_brush_sculpt_tool_items[] = { {SCULPT_TOOL_SIMPLIFY, "SIMPLIFY", ICON_BRUSH_DATA, "Simplify", ""}, {SCULPT_TOOL_MASK, "MASK", ICON_BRUSH_MASK, "Mask", ""}, {SCULPT_TOOL_DISPLACEMENT_ERASER, "DISPLACEMENT_ERASER", ICON_BRUSH_SCULPT_DRAW, "Multires Displacement Eraser", ""}, + {SCULPT_TOOL_DISPLACEMENT_SMEAR, "DISPLACEMENT_SMEAR", ICON_BRUSH_SCULPT_DRAW, "Multires Displacement Smear", ""}, {SCULPT_TOOL_PAINT, "PAINT", ICON_BRUSH_SCULPT_DRAW, "Paint", ""}, {SCULPT_TOOL_SMEAR, "SMEAR", ICON_BRUSH_SCULPT_DRAW, "Smear", ""}, {SCULPT_TOOL_DRAW_FACE_SETS, "DRAW_FACE_SETS", ICON_BRUSH_MASK, "Draw Face Sets", ""}, -- cgit v1.2.3 From a7628ec22abca8d1aaada75a8227638947168a3a Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Wed, 16 Dec 2020 16:59:30 +0100 Subject: Geometry Nodes: Poisson disk point distribution node/method This patch does two things: * Introduce a Seed to the random distribution method * Bring in a new distribution method for the point scattering node Patch Review: https://developer.blender.org/D9787 Note: This commit doesn't not handle doversion. Which means that users need to manually update their files that were using the Point Distribute node and reconnect inputs to the "Maximum Density" socket. Original patch by Sebastian Parborg, with changes to not rely on the cy libraries and overall cleanup. Patch review by Jacques Lucke, besides help with the new "heap" system that was required for this algorithm. Based on Cem Yuksel. 2015. Sample Elimination for Generating Poisson Disk Sample. Sets. Computer Graphics Forum 34, 2 (May 2015), 25-32 http://www.cemyuksel.com/research/sampleelimination/ --- source/blender/blenlib/BLI_kdopbvh.h | 1 + source/blender/blenlib/intern/BLI_kdopbvh.c | 19 ++ source/blender/editors/space_node/drawnode.c | 10 + source/blender/makesdna/DNA_node_types.h | 5 + source/blender/makesrna/intern/rna_nodetree.c | 26 ++ source/blender/nodes/CMakeLists.txt | 1 + source/blender/nodes/NOD_static_types.h | 2 +- .../blender/nodes/geometry/node_geometry_util.hh | 8 +- .../geometry/nodes/node_geo_point_distribute.cc | 178 ++++++++++++- .../node_geo_point_distribute_poisson_disk.cc | 280 +++++++++++++++++++++ 10 files changed, 521 insertions(+), 9 deletions(-) create mode 100644 source/blender/nodes/geometry/nodes/node_geo_point_distribute_poisson_disk.cc (limited to 'source/blender') diff --git a/source/blender/blenlib/BLI_kdopbvh.h b/source/blender/blenlib/BLI_kdopbvh.h index c34b71a60f9..5e0ea4f2a99 100644 --- a/source/blender/blenlib/BLI_kdopbvh.h +++ b/source/blender/blenlib/BLI_kdopbvh.h @@ -178,6 +178,7 @@ int *BLI_bvhtree_intersect_plane(BVHTree *tree, float plane[4], uint *r_intersec int BLI_bvhtree_get_len(const BVHTree *tree); int BLI_bvhtree_get_tree_type(const BVHTree *tree); float BLI_bvhtree_get_epsilon(const BVHTree *tree); +void BLI_bvhtree_get_bounding_box(BVHTree *tree, float r_bb_min[3], float r_bb_max[3]); /* find nearest node to the given coordinates * (if nearest is given it will only search nodes where diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index f126c5a977b..0f90ad3a490 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -1076,6 +1076,25 @@ float BLI_bvhtree_get_epsilon(const BVHTree *tree) return tree->epsilon; } +/** + * This function returns the bounding box of the BVH tree. + */ +void BLI_bvhtree_get_bounding_box(BVHTree *tree, float r_bb_min[3], float r_bb_max[3]) +{ + BVHNode *root = tree->nodes[tree->totleaf]; + if (root != NULL) { + const float bb_min[3] = {root->bv[0], root->bv[2], root->bv[4]}; + const float bb_max[3] = {root->bv[1], root->bv[3], root->bv[5]}; + copy_v3_v3(r_bb_min, bb_min); + copy_v3_v3(r_bb_max, bb_max); + } + else { + BLI_assert(false); + zero_v3(r_bb_min); + zero_v3(r_bb_max); + } +} + /** \} */ /* -------------------------------------------------------------------- */ diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 421d645d7bd..2857c08cad6 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -3208,6 +3208,13 @@ static void node_geometry_buts_attribute_mix(uiLayout *layout, uiItemR(col, ptr, "input_type_b", DEFAULT_FLAGS, IFACE_("B"), ICON_NONE); } +static void node_geometry_buts_attribute_point_distribute(uiLayout *layout, + bContext *UNUSED(C), + PointerRNA *ptr) +{ + uiItemR(layout, ptr, "distribute_method", DEFAULT_FLAGS, "", ICON_NONE); +} + static void node_geometry_set_butfunc(bNodeType *ntype) { switch (ntype->type) { @@ -3235,6 +3242,9 @@ static void node_geometry_set_butfunc(bNodeType *ntype) case GEO_NODE_ATTRIBUTE_MIX: ntype->draw_buttons = node_geometry_buts_attribute_mix; break; + case GEO_NODE_POINT_DISTRIBUTE: + ntype->draw_buttons = node_geometry_buts_attribute_point_distribute; + break; } } diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 9cf64743843..34a5372892c 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -1501,6 +1501,11 @@ typedef enum GeometryNodeAttributeInputMode { GEO_NODE_ATTRIBUTE_INPUT_COLOR = 3, } GeometryNodeAttributeInputMode; +typedef enum GeometryNodePointDistributeMethod { + GEO_NODE_POINT_DISTRIBUTE_RANDOM = 0, + GEO_NODE_POINT_DISTRIBUTE_POISSON = 1, +} GeometryNodePointDistributeMethod; + #ifdef __cplusplus } #endif diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 34f4d287d6e..1731a42583b 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -452,6 +452,20 @@ static const EnumPropertyItem rna_node_geometry_attribute_input_type_items[] = { {0, NULL, 0, NULL, NULL}, }; +static const EnumPropertyItem rna_node_geometry_point_distribute_method_items[] = { + {GEO_NODE_POINT_DISTRIBUTE_RANDOM, + "RANDOM", + 0, + "Random", + "Distribute points randomly on the surface"}, + {GEO_NODE_POINT_DISTRIBUTE_POISSON, + "POISSON", + 0, + "Poisson Disk", + "Project points on the surface evenly with a Poisson disk distribution"}, + {0, NULL, 0, NULL, NULL}, +}; + #endif #ifdef RNA_RUNTIME @@ -8481,6 +8495,18 @@ static void def_geo_attribute_mix(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); } +static void def_geo_point_distribute(StructRNA *srna) +{ + PropertyRNA *prop; + + prop = RNA_def_property(srna, "distribute_method", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "custom1"); + RNA_def_property_enum_items(prop, rna_node_geometry_point_distribute_method_items); + RNA_def_property_enum_default(prop, GEO_NODE_POINT_DISTRIBUTE_RANDOM); + RNA_def_property_ui_text(prop, "Distribution Method", "Method to use for scattering points"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); +} + /* -------------------------------------------------------------------------- */ static void rna_def_shader_node(BlenderRNA *brna) diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index 779680a5da7..46536903d55 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -148,6 +148,7 @@ set(SRC geometry/nodes/node_geo_attribute_mix.cc geometry/nodes/node_geo_object_info.cc geometry/nodes/node_geo_point_distribute.cc + geometry/nodes/node_geo_point_distribute_poisson_disk.cc geometry/nodes/node_geo_point_instance.cc geometry/nodes/node_geo_subdivision_surface.cc geometry/nodes/node_geo_transform.cc diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h index 681286ae5ab..68efb0806fd 100644 --- a/source/blender/nodes/NOD_static_types.h +++ b/source/blender/nodes/NOD_static_types.h @@ -271,7 +271,7 @@ DefNode(GeometryNode, GEO_NODE_EDGE_SPLIT, 0, "EDGE_SPLIT", EdgeSplit, "Edge Spl DefNode(GeometryNode, GEO_NODE_TRANSFORM, 0, "TRANSFORM", Transform, "Transform", "") DefNode(GeometryNode, GEO_NODE_SUBDIVISION_SURFACE, 0, "SUBDIVISION_SURFACE", SubdivisionSurface, "Subdivision Surface", "") DefNode(GeometryNode, GEO_NODE_BOOLEAN, def_geo_boolean, "BOOLEAN", Boolean, "Boolean", "") -DefNode(GeometryNode, GEO_NODE_POINT_DISTRIBUTE, 0, "POINT_DISTRIBUTE", PointDistribute, "Point Distribute", "") +DefNode(GeometryNode, GEO_NODE_POINT_DISTRIBUTE, def_geo_point_distribute, "POINT_DISTRIBUTE", PointDistribute, "Point Distribute", "") DefNode(GeometryNode, GEO_NODE_POINT_INSTANCE, def_geo_point_instance, "POINT_INSTANCE", PointInstance, "Point Instance", "") DefNode(GeometryNode, GEO_NODE_OBJECT_INFO, 0, "OBJECT_INFO", ObjectInfo, "Object Info", "") DefNode(GeometryNode, GEO_NODE_ATTRIBUTE_RANDOMIZE, def_geo_attribute_randomize, "ATTRIBUTE_RANDOMIZE", AttributeRandomize, "Attribute Randomize", "") diff --git a/source/blender/nodes/geometry/node_geometry_util.hh b/source/blender/nodes/geometry/node_geometry_util.hh index ec389961615..c97463cdc22 100644 --- a/source/blender/nodes/geometry/node_geometry_util.hh +++ b/source/blender/nodes/geometry/node_geometry_util.hh @@ -42,4 +42,10 @@ namespace blender::nodes { void update_attribute_input_socket_availabilities(bNode &node, const StringRef name, const GeometryNodeAttributeInputMode mode); -} + +void poisson_disk_point_elimination(Vector const *input_points, + Vector *output_points, + float maximum_distance, + float3 boundbox); + +} // namespace blender::nodes diff --git a/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc b/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc index 2f5f7e264bc..8be9636e14d 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc @@ -24,6 +24,7 @@ #include "DNA_meshdata_types.h" #include "DNA_pointcloud_types.h" +#include "BKE_bvhutils.h" #include "BKE_deform.h" #include "BKE_mesh.h" #include "BKE_mesh_runtime.h" @@ -33,8 +34,10 @@ static bNodeSocketTemplate geo_node_point_distribute_in[] = { {SOCK_GEOMETRY, N_("Geometry")}, - {SOCK_FLOAT, N_("Density"), 10.0f, 0.0f, 0.0f, 0.0f, 0.0f, 100000.0f, PROP_NONE}, + {SOCK_FLOAT, N_("Minimum Distance"), 0.1f, 0.0f, 0.0f, 0.0f, 0.0f, 100000.0f, PROP_NONE}, + {SOCK_FLOAT, N_("Maximum Density"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 100000.0f, PROP_NONE}, {SOCK_STRING, N_("Density Attribute")}, + {SOCK_INT, N_("Seed"), 0, 0, 0, 0, -10000, 10000}, {-1, ""}, }; @@ -43,11 +46,19 @@ static bNodeSocketTemplate geo_node_point_distribute_out[] = { {-1, ""}, }; +static void node_point_distribute_update(bNodeTree *UNUSED(ntree), bNode *node) +{ + bNodeSocket *sock_min_dist = (bNodeSocket *)BLI_findlink(&node->inputs, 1); + + nodeSetSocketAvailability(sock_min_dist, ELEM(node->custom1, GEO_NODE_POINT_DISTRIBUTE_POISSON)); +} + namespace blender::nodes { -static Vector scatter_points_from_mesh(const Mesh *mesh, - const float density, - const FloatReadAttribute &density_factors) +static Vector random_scatter_points_from_mesh(const Mesh *mesh, + const float density, + const FloatReadAttribute &density_factors, + const int seed) { /* This only updates a cache and can be considered to be logically const. */ const MLoopTri *looptris = BKE_mesh_runtime_looptri_ensure(const_cast(mesh)); @@ -71,7 +82,7 @@ static Vector scatter_points_from_mesh(const Mesh *mesh, 3.0f; const float area = area_tri_v3(v0_pos, v1_pos, v2_pos); - const int looptri_seed = BLI_hash_int(looptri_index); + const int looptri_seed = BLI_hash_int(looptri_index + seed); RandomNumberGenerator looptri_rng(looptri_seed); const float points_amount_fl = area * density * looptri_density_factor; @@ -90,17 +101,158 @@ static Vector scatter_points_from_mesh(const Mesh *mesh, return points; } +struct RayCastAll_Data { + void *bvhdata; + + BVHTree_RayCastCallback raycast_callback; + + const Mesh *mesh; + float base_weight; + FloatReadAttribute *density_factors; + Vector *projected_points; + float cur_point_weight; +}; + +static void project_2d_bvh_callback(void *userdata, + int index, + const BVHTreeRay *ray, + BVHTreeRayHit *hit) +{ + struct RayCastAll_Data *data = (RayCastAll_Data *)userdata; + data->raycast_callback(data->bvhdata, index, ray, hit); + if (hit->index != -1) { + /* This only updates a cache and can be considered to be logically const. */ + const MLoopTri *looptris = BKE_mesh_runtime_looptri_ensure(const_cast(data->mesh)); + const MVert *mvert = data->mesh->mvert; + + const MLoopTri &looptri = looptris[index]; + const FloatReadAttribute &density_factors = data->density_factors[0]; + + const int v0_index = data->mesh->mloop[looptri.tri[0]].v; + const int v1_index = data->mesh->mloop[looptri.tri[1]].v; + const int v2_index = data->mesh->mloop[looptri.tri[2]].v; + + const float v0_density_factor = std::max(0.0f, density_factors[v0_index]); + const float v1_density_factor = std::max(0.0f, density_factors[v1_index]); + const float v2_density_factor = std::max(0.0f, density_factors[v2_index]); + + /* Calculate barycentric weights for hit point. */ + float3 weights; + interp_weights_tri_v3( + weights, mvert[v0_index].co, mvert[v1_index].co, mvert[v2_index].co, hit->co); + + float point_weight = weights[0] * v0_density_factor + weights[1] * v1_density_factor + + weights[2] * v2_density_factor; + + point_weight *= data->base_weight; + + if (point_weight >= FLT_EPSILON && data->cur_point_weight <= point_weight) { + data->projected_points->append(hit->co); + } + } +} + +static Vector poisson_scatter_points_from_mesh(const Mesh *mesh, + const float density, + const float minimum_distance, + const FloatReadAttribute &density_factors, + const int seed) +{ + Vector points; + + if (minimum_distance <= FLT_EPSILON || density <= FLT_EPSILON) { + return points; + } + + /* Scatter points randomly on the mesh with higher density (5-7) times higher than desired for + * good quality possion disk distributions. */ + int quality = 5; + const int output_points_target = 1000; + points.resize(output_points_target * quality); + + const float required_area = output_points_target * + (2.0f * sqrtf(3.0f) * minimum_distance * minimum_distance); + const float point_scale_multiplier = sqrtf(required_area); + + { + const int rnd_seed = BLI_hash_int(seed); + RandomNumberGenerator point_rng(rnd_seed); + + for (int i = 0; i < points.size(); i++) { + points[i].x = point_rng.get_float() * point_scale_multiplier; + points[i].y = point_rng.get_float() * point_scale_multiplier; + points[i].z = 0.0f; + } + } + + /* Eliminate the scattered points until we get a possion distribution. */ + Vector output_points(output_points_target); + + const float3 bounds_max = float3(point_scale_multiplier, point_scale_multiplier, 0); + poisson_disk_point_elimination(&points, &output_points, 2.0f * minimum_distance, bounds_max); + Vector final_points; + final_points.reserve(output_points_target); + + /* Check if we have any points we should remove from the final possion distribition. */ + BVHTreeFromMesh treedata; + BKE_bvhtree_from_mesh_get(&treedata, const_cast(mesh), BVHTREE_FROM_LOOPTRI, 2); + + float3 bb_min, bb_max; + BLI_bvhtree_get_bounding_box(treedata.tree, bb_min, bb_max); + + struct RayCastAll_Data data; + data.bvhdata = &treedata; + data.raycast_callback = treedata.raycast_callback; + data.mesh = mesh; + data.projected_points = &final_points; + data.density_factors = const_cast(&density_factors); + data.base_weight = std::min( + 1.0f, density / (output_points.size() / (point_scale_multiplier * point_scale_multiplier))); + + const float max_dist = bb_max[2] - bb_min[2] + 2.0f; + const float3 dir = float3(0, 0, -1); + float3 raystart; + raystart.z = bb_max[2] + 1.0f; + + float tile_start_x_coord = bb_min[0]; + int tile_repeat_x = ceilf((bb_max[0] - bb_min[0]) / point_scale_multiplier); + + float tile_start_y_coord = bb_min[1]; + int tile_repeat_y = ceilf((bb_max[1] - bb_min[1]) / point_scale_multiplier); + + for (int x = 0; x < tile_repeat_x; x++) { + float tile_curr_x_coord = x * point_scale_multiplier + tile_start_x_coord; + for (int y = 0; y < tile_repeat_y; y++) { + float tile_curr_y_coord = y * point_scale_multiplier + tile_start_y_coord; + for (int idx = 0; idx < output_points.size(); idx++) { + raystart.x = output_points[idx].x + tile_curr_x_coord; + raystart.y = output_points[idx].y + tile_curr_y_coord; + + data.cur_point_weight = (float)idx / (float)output_points.size(); + + BLI_bvhtree_ray_cast_all( + treedata.tree, raystart, dir, 0.0f, max_dist, project_2d_bvh_callback, &data); + } + } + } + + return final_points; +} + static void geo_node_point_distribute_exec(GeoNodeExecParams params) { GeometrySet geometry_set = params.extract_input("Geometry"); GeometrySet geometry_set_out; + GeometryNodePointDistributeMethod distribute_method = + static_cast(params.node().custom1); + if (!geometry_set.has_mesh()) { params.set_output("Geometry", std::move(geometry_set_out)); return; } - const float density = params.extract_input("Density"); + const float density = params.extract_input("Maximum Density"); const std::string density_attribute = params.extract_input("Density Attribute"); if (density <= 0.0f) { @@ -113,8 +265,19 @@ static void geo_node_point_distribute_exec(GeoNodeExecParams params) const FloatReadAttribute density_factors = mesh_component.attribute_get_for_read( density_attribute, ATTR_DOMAIN_POINT, 1.0f); + const int seed = params.get_input("Seed"); - Vector points = scatter_points_from_mesh(mesh_in, density, density_factors); + Vector points; + + switch (distribute_method) { + case GEO_NODE_POINT_DISTRIBUTE_RANDOM: + points = random_scatter_points_from_mesh(mesh_in, density, density_factors, seed); + break; + case GEO_NODE_POINT_DISTRIBUTE_POISSON: + const float min_dist = params.extract_input("Minimum Distance"); + points = poisson_scatter_points_from_mesh(mesh_in, density, min_dist, density_factors, seed); + break; + } PointCloud *pointcloud = BKE_pointcloud_new_nomain(points.size()); memcpy(pointcloud->co, points.data(), sizeof(float3) * points.size()); @@ -135,6 +298,7 @@ void register_node_type_geo_point_distribute() geo_node_type_base( &ntype, GEO_NODE_POINT_DISTRIBUTE, "Point Distribute", NODE_CLASS_GEOMETRY, 0); node_type_socket_templates(&ntype, geo_node_point_distribute_in, geo_node_point_distribute_out); + node_type_update(&ntype, node_point_distribute_update); ntype.geometry_node_execute = blender::nodes::geo_node_point_distribute_exec; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_point_distribute_poisson_disk.cc b/source/blender/nodes/geometry/nodes/node_geo_point_distribute_poisson_disk.cc new file mode 100644 index 00000000000..5dfdfce0e68 --- /dev/null +++ b/source/blender/nodes/geometry/nodes/node_geo_point_distribute_poisson_disk.cc @@ -0,0 +1,280 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/* + * Based on Cem Yuksel. 2015. Sample Elimination for Generating Poisson Disk Sample + * ! Sets. Computer Graphics Forum 34, 2 (May 2015), 25-32. + * ! http://www.cemyuksel.com/research/sampleelimination/ + * Copyright (c) 2016, Cem Yuksel + * All rights reserved. + */ + +#include "BLI_inplace_priority_queue.hh" +#include "BLI_kdtree.h" + +#include "node_geometry_util.hh" + +#include + +namespace blender::nodes { + +static void tile_point(Vector *tiled_points, + Vector *indices, + const float maximum_distance, + const float3 boundbox, + float3 const &point, + size_t index, + int dimension = 0) +{ + for (int dimension_iter = dimension; dimension_iter < 3; dimension_iter++) { + if (boundbox[dimension_iter] - point[dimension_iter] < maximum_distance) { + float3 point_tiled = point; + point_tiled[dimension_iter] -= boundbox[dimension_iter]; + + tiled_points->append(point_tiled); + indices->append(index); + + tile_point(tiled_points, + indices, + maximum_distance, + boundbox, + point_tiled, + index, + dimension_iter + 1); + } + + if (point[dimension_iter] < maximum_distance) { + float3 point_tiled = point; + point_tiled[dimension_iter] += boundbox[dimension_iter]; + + tiled_points->append(point_tiled); + indices->append(index); + + tile_point(tiled_points, + indices, + maximum_distance, + boundbox, + point_tiled, + index, + dimension_iter + 1); + } + } +} + +/** + * Returns the weight the point gets based on the distance to another point. + */ +static float point_weight_influence_get(const float maximum_distance, + const float minimum_distance, + float distance) +{ + const float alpha = 8.0f; + + if (distance < minimum_distance) { + distance = minimum_distance; + } + + return std::pow(1.0f - distance / maximum_distance, alpha); +} + +/** + * Weight each point based on their proximity to its neighbors + * + * For each index in the weight array add a weight based on the proximity the + * corresponding point has with its neighboors. + **/ +static void points_distance_weight_calculate(Vector *weights, + const size_t point_id, + const float3 *input_points, + const void *kd_tree, + const float minimum_distance, + const float maximum_distance, + InplacePriorityQueue *heap) +{ + KDTreeNearest_3d *nearest_point = nullptr; + int neighbors = BLI_kdtree_3d_range_search( + (KDTree_3d *)kd_tree, input_points[point_id], &nearest_point, maximum_distance); + + for (int i = 0; i < neighbors; i++) { + size_t neighbor_point_id = nearest_point[i].index; + + if (neighbor_point_id >= weights->size()) { + continue; + } + + /* The point should not influence itself. */ + if (neighbor_point_id == point_id) { + continue; + } + + const float weight_influence = point_weight_influence_get( + maximum_distance, minimum_distance, nearest_point[i].dist); + + /* In the first pass we just the weights. */ + if (heap == nullptr) { + (*weights)[point_id] += weight_influence; + } + /* When we run again we need to update the weights and the heap. */ + else { + (*weights)[neighbor_point_id] -= weight_influence; + heap->priority_decreased(neighbor_point_id); + } + } + + if (nearest_point) { + MEM_freeN(nearest_point); + } +} + +/** + * Returns the minimum radius fraction used by the default weight function. + */ +static float weight_limit_fraction_get(const size_t input_size, const size_t output_size) +{ + const float beta = 0.65f; + const float gamma = 1.5f; + float ratio = float(output_size) / float(input_size); + return (1.0f - std::pow(ratio, gamma)) * beta; +} + +/** + * Tile the input points. + */ +static void points_tiling(const float3 *input_points, + const size_t input_size, + void **kd_tree, + const float maximum_distance, + const float3 boundbox) + +{ + Vector tiled_points(input_points, input_points + input_size); + Vector indices(input_size); + + for (size_t i = 0; i < input_size; i++) { + indices[i] = i; + } + + /* Tile the tree based on the boundbox. */ + for (size_t i = 0; i < input_size; i++) { + tile_point(&tiled_points, &indices, maximum_distance, boundbox, input_points[i], i); + } + + /* Build a new tree with the new indices and tiled points. */ + *kd_tree = BLI_kdtree_3d_new(tiled_points.size()); + for (size_t i = 0; i < tiled_points.size(); i++) { + BLI_kdtree_3d_insert(*(KDTree_3d **)kd_tree, indices[i], tiled_points[i]); + } + BLI_kdtree_3d_balance(*(KDTree_3d **)kd_tree); +} + +static void weighted_sample_elimination(const float3 *input_points, + const size_t input_size, + float3 *output_points, + const size_t output_size, + const float maximum_distance, + const float3 boundbox, + const bool do_copy_eliminated) +{ + const float minimum_distance = maximum_distance * + weight_limit_fraction_get(input_size, output_size); + + void *kd_tree = nullptr; + points_tiling(input_points, input_size, &kd_tree, maximum_distance, boundbox); + + /* Assign weights to each sample. */ + Vector weights(input_size, 0.0f); + for (size_t point_id = 0; point_id < weights.size(); point_id++) { + points_distance_weight_calculate( + &weights, point_id, input_points, kd_tree, minimum_distance, maximum_distance, nullptr); + } + + /* Remove the points based on their weight. */ + InplacePriorityQueue heap(weights); + + size_t sample_size = input_size; + while (sample_size > output_size) { + /* For each sample around it, remove its weight contribution and update the heap. */ + size_t point_id = heap.pop_index(); + points_distance_weight_calculate( + &weights, point_id, input_points, kd_tree, minimum_distance, maximum_distance, &heap); + sample_size--; + } + + /* Copy the samples to the output array. */ + size_t target_size = do_copy_eliminated ? input_size : output_size; + for (size_t i = 0; i < target_size; i++) { + size_t index = heap.all_indices()[i]; + output_points[i] = input_points[index]; + } + + /* Cleanup. */ + BLI_kdtree_3d_free((KDTree_3d *)kd_tree); +} + +static void progressive_sampling_reorder(Vector *output_points, + float maximum_density, + float3 boundbox) +{ + /* Re-order the points for progressive sampling. */ + Vector temporary_points(output_points->size()); + float3 *source_points = output_points->data(); + float3 *dest_points = temporary_points.data(); + size_t source_size = output_points->size(); + size_t dest_size = 0; + + while (source_size >= 3) { + dest_size = source_size * 0.5f; + + /* Changes the weight function radius using half of the number of samples. + * It is used for progressive sampling. */ + maximum_density *= std::sqrt(2.0f); + weighted_sample_elimination( + source_points, source_size, dest_points, dest_size, maximum_density, boundbox, true); + + if (dest_points != output_points->data()) { + mempcpy((*output_points)[dest_size], + dest_points[dest_size], + (source_size - dest_size) * sizeof(float3)); + } + + /* Swap the arrays around. */ + float3 *points_iter = source_points; + source_points = dest_points; + dest_points = points_iter; + source_size = dest_size; + } + if (source_points != output_points->data()) { + memcpy(output_points->data(), source_points, dest_size * sizeof(float3)); + } +} + +void poisson_disk_point_elimination(Vector const *input_points, + Vector *output_points, + float maximum_density, + float3 boundbox) +{ + weighted_sample_elimination(input_points->data(), + input_points->size(), + output_points->data(), + output_points->size(), + maximum_density, + boundbox, + false); + + progressive_sampling_reorder(output_points, maximum_density, boundbox); +} + +} // namespace blender::nodes -- cgit v1.2.3 From ebd8a703ccb6b8884b26e78771a9fec8ba919f9a Mon Sep 17 00:00:00 2001 From: Philipp Oeser Date: Wed, 16 Dec 2020 16:41:47 +0100 Subject: Fix T83851: Python: operator macros cause a crash Caused by rB7447eb7e7430. This is just a copy-paste error [previous LISTBASE_FOREACH substitution of marco loop in that file has a different starting point which is not appropriate here] Maniphest Tasks: T83851 Differential Revision: https://developer.blender.org/D9872 --- source/blender/windowmanager/intern/wm_event_system.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender') diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 61624ad9d7c..c1ae307eb55 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -1204,7 +1204,7 @@ static wmOperator *wm_operator_create(wmWindowManager *wm, RNA_STRUCT_END; } else { - LISTBASE_FOREACH (wmOperatorTypeMacro *, macro, &op->opm->type->macro) { + LISTBASE_FOREACH (wmOperatorTypeMacro *, macro, &ot->macro) { wmOperatorType *otm = WM_operatortype_find(macro->idname, 0); wmOperator *opm = wm_operator_create(wm, otm, macro->ptr, NULL); -- cgit v1.2.3 From c06c5d617a8b0e72acdeb60674172d748093bf24 Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Wed, 16 Dec 2020 17:48:05 +0100 Subject: Cleanup: Replace mempcpy with memcpy There is no need of using mempcpy here, memcpy is enough. Note: This also fix building in Windows which was broken since a7628ec22a. --- .../nodes/geometry/nodes/node_geo_point_distribute_poisson_disk.cc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'source/blender') diff --git a/source/blender/nodes/geometry/nodes/node_geo_point_distribute_poisson_disk.cc b/source/blender/nodes/geometry/nodes/node_geo_point_distribute_poisson_disk.cc index 5dfdfce0e68..47764efa15d 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_point_distribute_poisson_disk.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_point_distribute_poisson_disk.cc @@ -28,6 +28,7 @@ #include "node_geometry_util.hh" #include +#include namespace blender::nodes { @@ -245,9 +246,9 @@ static void progressive_sampling_reorder(Vector *output_points, source_points, source_size, dest_points, dest_size, maximum_density, boundbox, true); if (dest_points != output_points->data()) { - mempcpy((*output_points)[dest_size], - dest_points[dest_size], - (source_size - dest_size) * sizeof(float3)); + memcpy((*output_points)[dest_size], + dest_points[dest_size], + (source_size - dest_size) * sizeof(float3)); } /* Swap the arrays around. */ -- cgit v1.2.3 From c484b54453e6072399dd79daccf237bb4bd73b41 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Wed, 16 Dec 2020 12:33:13 -0600 Subject: Geometry Nodes: Boolean attribute type This adds a boolean attribute and custom data type, to be used in the point separate node. It also adds it as supported data types in the random attribute and attribute fill nodes. There are more clever ways of storing a boolean attribute that make more sense in certain situations-- sets, bitfields, and others, this commit keeps it simple, saving those changes for when there is a proper use case for them. In any case, we will still probably always want the idea of a boolean attribute. Differential Revision: https://developer.blender.org/D9818 --- source/blender/blenkernel/BKE_attribute_access.hh | 2 ++ .../blender/blenkernel/intern/attribute_access.cc | 21 +++++++++++++++++++-- source/blender/blenkernel/intern/customdata.c | 16 ++++++++++++++++ source/blender/makesdna/DNA_customdata_types.h | 8 +++++--- source/blender/makesrna/intern/rna_attribute.c | 1 + source/blender/makesrna/intern/rna_nodetree.c | 4 ++-- source/blender/nodes/NOD_geometry_exec.hh | 2 ++ .../nodes/geometry/nodes/node_geo_attribute_fill.cc | 11 +++++++++++ .../geometry/nodes/node_geo_attribute_randomize.cc | 15 +++++++++++++++ .../nodes/intern/node_tree_multi_function.cc | 4 ++++ 10 files changed, 77 insertions(+), 7 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/BKE_attribute_access.hh b/source/blender/blenkernel/BKE_attribute_access.hh index 564e912551a..eafd86d176b 100644 --- a/source/blender/blenkernel/BKE_attribute_access.hh +++ b/source/blender/blenkernel/BKE_attribute_access.hh @@ -264,9 +264,11 @@ template class TypedWriteAttribute { } }; +using BooleanReadAttribute = TypedReadAttribute; using FloatReadAttribute = TypedReadAttribute; using Float3ReadAttribute = TypedReadAttribute; using Color4fReadAttribute = TypedReadAttribute; +using BooleanWriteAttribute = TypedWriteAttribute; using FloatWriteAttribute = TypedWriteAttribute; using Float3WriteAttribute = TypedWriteAttribute; using Color4fWriteAttribute = TypedWriteAttribute; diff --git a/source/blender/blenkernel/intern/attribute_access.cc b/source/blender/blenkernel/intern/attribute_access.cc index 282e9bc2962..623335f65a1 100644 --- a/source/blender/blenkernel/intern/attribute_access.cc +++ b/source/blender/blenkernel/intern/attribute_access.cc @@ -392,6 +392,8 @@ const blender::fn::CPPType *custom_data_type_to_cpp_type(const CustomDataType ty return &CPPType::get(); case CD_PROP_COLOR: return &CPPType::get(); + case CD_PROP_BOOL: + return &CPPType::get(); default: return nullptr; } @@ -415,6 +417,9 @@ CustomDataType cpp_type_to_custom_data_type(const blender::fn::CPPType &type) if (type.is()) { return CD_PROP_COLOR; } + if (type.is()) { + return CD_PROP_BOOL; + } return static_cast(-1); } @@ -449,6 +454,9 @@ static ReadAttributePtr read_attribute_from_custom_data(const CustomData &custom case CD_PROP_COLOR: return std::make_unique>( domain, Span(static_cast(layer.data), size)); + case CD_PROP_BOOL: + return std::make_unique>( + domain, Span(static_cast(layer.data), size)); } } } @@ -490,6 +498,9 @@ static WriteAttributePtr write_attribute_from_custom_data( case CD_PROP_COLOR: return std::make_unique>( domain, MutableSpan(static_cast(layer.data), size)); + case CD_PROP_BOOL: + return std::make_unique>( + domain, MutableSpan(static_cast(layer.data), size)); } } } @@ -751,6 +762,7 @@ bool PointCloudComponent::attribute_domain_with_type_supported( const AttributeDomain domain, const CustomDataType data_type) const { return domain == ATTR_DOMAIN_POINT && ELEM(data_type, + CD_PROP_BOOL, CD_PROP_FLOAT, CD_PROP_FLOAT2, CD_PROP_FLOAT3, @@ -874,8 +886,13 @@ bool MeshComponent::attribute_domain_with_type_supported(const AttributeDomain d if (!this->attribute_domain_supported(domain)) { return false; } - return ELEM( - data_type, CD_PROP_FLOAT, CD_PROP_FLOAT2, CD_PROP_FLOAT3, CD_PROP_INT32, CD_PROP_COLOR); + return ELEM(data_type, + CD_PROP_BOOL, + CD_PROP_FLOAT, + CD_PROP_FLOAT2, + CD_PROP_FLOAT3, + CD_PROP_INT32, + CD_PROP_COLOR); } int MeshComponent::attribute_domain_size(const AttributeDomain domain) const diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index fdb3e246382..1e2bc570c65 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -1837,6 +1837,21 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { layerMultiply_propfloat2, NULL, layerAdd_propfloat2}, + /* 50: CD_PROP_POOL */ + {sizeof(bool), + "bool", + 1, + N_("Boolean"), + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL}, }; static const char *LAYERTYPENAMES[CD_NUMTYPES] = { @@ -1892,6 +1907,7 @@ static const char *LAYERTYPENAMES[CD_NUMTYPES] = { "CDPropCol", "CDPropFloat3", "CDPropFloat2", + "CDPropBoolean", }; const CustomData_MeshMasks CD_MASK_BAREMESH = { diff --git a/source/blender/makesdna/DNA_customdata_types.h b/source/blender/makesdna/DNA_customdata_types.h index ae0bb20e529..832d55ea151 100644 --- a/source/blender/makesdna/DNA_customdata_types.h +++ b/source/blender/makesdna/DNA_customdata_types.h @@ -75,8 +75,7 @@ typedef struct CustomData { * MUST be >= CD_NUMTYPES, but we cant use a define here. * Correct size is ensured in CustomData_update_typemap assert(). */ - int typemap[50]; - char _pad[4]; + int typemap[51]; /** Number of layers, size of layers array. */ int totlayer, maxlayer; /** In editmode, total size of all data layers. */ @@ -156,7 +155,9 @@ typedef enum CustomDataType { CD_PROP_FLOAT3 = 48, CD_PROP_FLOAT2 = 49, - CD_NUMTYPES = 50, + CD_PROP_BOOL = 50, + + CD_NUMTYPES = 51, } CustomDataType; /* Bits for CustomDataMask */ @@ -208,6 +209,7 @@ typedef enum CustomDataType { #define CD_MASK_PROP_COLOR (1ULL << CD_PROP_COLOR) #define CD_MASK_PROP_FLOAT3 (1ULL << CD_PROP_FLOAT3) #define CD_MASK_PROP_FLOAT2 (1ULL << CD_PROP_FLOAT2) +#define CD_MASK_PROP_BOOL (1ULL << CD_PROP_BOOL) /** Multires loop data. */ #define CD_MASK_MULTIRES_GRIDS (CD_MASK_MDISPS | CD_GRID_PAINT_MASK) diff --git a/source/blender/makesrna/intern/rna_attribute.c b/source/blender/makesrna/intern/rna_attribute.c index 95f6340174a..f98ca47d767 100644 --- a/source/blender/makesrna/intern/rna_attribute.c +++ b/source/blender/makesrna/intern/rna_attribute.c @@ -44,6 +44,7 @@ const EnumPropertyItem rna_enum_attribute_type_items[] = { {CD_PROP_COLOR, "FLOAT_COLOR", 0, "Float Color", "RGBA color with floating-point precisions"}, {CD_MLOOPCOL, "BYTE_COLOR", 0, "Byte Color", "RGBA color with 8-bit precision"}, {CD_PROP_STRING, "STRING", 0, "String", "Text string"}, + {CD_PROP_BOOL, "BOOLEAN", 0, "Boolean", "True or false"}, {0, NULL, 0, NULL, NULL}, }; diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 1731a42583b..4cd5b45ce78 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -1890,7 +1890,7 @@ static const EnumPropertyItem *itemf_function_check( static bool attribute_random_type_supported(const EnumPropertyItem *item) { - return ELEM(item->value, CD_PROP_FLOAT, CD_PROP_FLOAT3); + return ELEM(item->value, CD_PROP_FLOAT, CD_PROP_FLOAT3, CD_PROP_BOOL); } static const EnumPropertyItem *rna_GeometryNodeAttributeRandom_type_itemf( bContext *UNUSED(C), PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free) @@ -1912,7 +1912,7 @@ static const EnumPropertyItem *rna_GeometryNodeAttributeRandom_domain_itemf( static bool attribute_fill_type_supported(const EnumPropertyItem *item) { - return ELEM(item->value, CD_PROP_FLOAT, CD_PROP_FLOAT3, CD_PROP_COLOR); + return ELEM(item->value, CD_PROP_FLOAT, CD_PROP_FLOAT3, CD_PROP_COLOR, CD_PROP_BOOL); } static const EnumPropertyItem *rna_GeometryNodeAttributeFill_type_itemf(bContext *UNUSED(C), PointerRNA *UNUSED(ptr), diff --git a/source/blender/nodes/NOD_geometry_exec.hh b/source/blender/nodes/NOD_geometry_exec.hh index 5fe554e0478..445e1ed6af2 100644 --- a/source/blender/nodes/NOD_geometry_exec.hh +++ b/source/blender/nodes/NOD_geometry_exec.hh @@ -26,6 +26,8 @@ namespace blender::nodes { +using bke::BooleanReadAttribute; +using bke::BooleanWriteAttribute; using bke::Color4fReadAttribute; using bke::Color4fWriteAttribute; using bke::Float3ReadAttribute; diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_fill.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_fill.cc index d3c7e86b708..5cdbd18ecc8 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_attribute_fill.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_fill.cc @@ -27,6 +27,7 @@ static bNodeSocketTemplate geo_node_attribute_fill_in[] = { {SOCK_VECTOR, N_("Value"), 0.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX}, {SOCK_FLOAT, N_("Value"), 0.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX}, {SOCK_RGBA, N_("Value"), 0.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX}, + {SOCK_BOOLEAN, N_("Value"), 0.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX}, {-1, ""}, }; @@ -45,12 +46,14 @@ static void geo_node_attribute_fill_update(bNodeTree *UNUSED(ntree), bNode *node bNodeSocket *socket_value_vector = (bNodeSocket *)BLI_findlink(&node->inputs, 2); bNodeSocket *socket_value_float = socket_value_vector->next; bNodeSocket *socket_value_color4f = socket_value_float->next; + bNodeSocket *socket_value_boolean = socket_value_color4f->next; const CustomDataType data_type = static_cast(node->custom1); nodeSetSocketAvailability(socket_value_vector, data_type == CD_PROP_FLOAT3); nodeSetSocketAvailability(socket_value_float, data_type == CD_PROP_FLOAT); nodeSetSocketAvailability(socket_value_color4f, data_type == CD_PROP_COLOR); + nodeSetSocketAvailability(socket_value_boolean, data_type == CD_PROP_BOOL); } namespace blender::nodes { @@ -96,6 +99,14 @@ static void fill_attribute(GeometryComponent &component, const GeoNodeExecParams color4f_attribute.apply_span(); break; } + case CD_PROP_BOOL: { + BooleanWriteAttribute boolean_attribute = std::move(attribute); + const bool value = params.get_input("Value_003"); + MutableSpan attribute_span = boolean_attribute.get_span(); + attribute_span.fill(value); + boolean_attribute.apply_span(); + break; + } default: break; } diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_randomize.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_randomize.cc index bde9a2a695e..53df2e8c087 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_attribute_randomize.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_randomize.cc @@ -59,6 +59,16 @@ static void geo_node_attribute_randomize_update(bNodeTree *UNUSED(ntree), bNode namespace blender::nodes { +static void randomize_attribute(BooleanWriteAttribute &attribute, RandomNumberGenerator &rng) +{ + MutableSpan attribute_span = attribute.get_span(); + for (const int i : IndexRange(attribute.size())) { + const bool value = rng.get_float() > 0.5f; + attribute_span[i] = value; + } + attribute.apply_span(); +} + static void randomize_attribute(FloatWriteAttribute &attribute, float min, float max, @@ -121,6 +131,11 @@ static void randomize_attribute(GeometryComponent &component, randomize_attribute(float3_attribute, min_value, max_value, rng); break; } + case CD_PROP_BOOL: { + BooleanWriteAttribute boolean_attribute = std::move(attribute); + randomize_attribute(boolean_attribute, rng); + break; + } default: break; } diff --git a/source/blender/nodes/intern/node_tree_multi_function.cc b/source/blender/nodes/intern/node_tree_multi_function.cc index ec5527a2970..2e4196af156 100644 --- a/source/blender/nodes/intern/node_tree_multi_function.cc +++ b/source/blender/nodes/intern/node_tree_multi_function.cc @@ -208,6 +208,10 @@ static DataTypeConversions create_implicit_conversions() conversions, "float to Color4f", [](float a) { return Color4f(a, a, a, 1.0f); }); add_implicit_conversion( conversions, "Color4f to float", [](Color4f a) { return rgb_to_grayscale(a); }); + add_implicit_conversion( + conversions, "float3 to boolean", [](float3 a) { return a.length_squared() == 0.0f; }); + add_implicit_conversion( + conversions, "boolean to float3", [](bool a) { return (a) ? float3(1.0f) : float3(0.0f); }); return conversions; } -- cgit v1.2.3 From a8da70f70a1f581412982d1f858b7b9a96ab8c37 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Wed, 16 Dec 2020 12:50:45 -0600 Subject: Geometry Nodes: Add boolean attribute in utility function This follows up rBc484b54453e607, adding the boolean custom property data type in one more place that was missed. --- source/blender/nodes/intern/node_geometry_exec.cc | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source/blender') diff --git a/source/blender/nodes/intern/node_geometry_exec.cc b/source/blender/nodes/intern/node_geometry_exec.cc index 6a22adb25a7..eef2c6c9125 100644 --- a/source/blender/nodes/intern/node_geometry_exec.cc +++ b/source/blender/nodes/intern/node_geometry_exec.cc @@ -96,6 +96,9 @@ CustomDataType GeoNodeExecParams::get_input_attribute_data_type( if (found_socket->type == SOCK_RGBA) { return CD_PROP_COLOR; } + if (found_socket->type == SOCK_BOOLEAN) { + return CD_PROP_BOOL; + } BLI_assert(false); return default_type; -- cgit v1.2.3 From 571362642201a743168cdf4c827a59c09c40414b Mon Sep 17 00:00:00 2001 From: Richard Antalik Date: Wed, 16 Dec 2020 20:34:26 +0100 Subject: VSE: Improve motion-picture workflow This commit resolves problem introduced in e1665c3d3190 - it was difficult to import media at their original resolution. This is done by using original resolution as reference for scale. All crop and strip transform values and their animation is converted form old files. To make both workflows easy to use, sequencer tool settings have been created with preset for preffered scaling method. This setting is in sequencer timeline header and add image or movie strip operator properties. Two new operators have been added: `sequencer.strip_transform_fit` operator with 3 options: Scale To Fit, Scale to Fill and Stretch To Fill. Operator can fail if strip image or video is not loaded currently, this case should be either sanitized or data loaded on demand. `sequencer.strip_transform_clear` operator with 4 options: Clear position, scale, rotation and all (previous 3 options combined). Reviewed By: sergey, fsiddi Differential Revision: https://developer.blender.org/D9582 --- source/blender/blenkernel/BKE_blender_version.h | 2 +- source/blender/blenkernel/intern/scene.c | 12 ++ source/blender/blenloader/intern/versioning_290.c | 182 +++++++++++++++++---- .../editors/space_sequencer/sequencer_add.c | 29 +++- .../editors/space_sequencer/sequencer_edit.c | 145 ++++++++++++++++ .../editors/space_sequencer/sequencer_intern.h | 2 + .../editors/space_sequencer/sequencer_ops.c | 2 + source/blender/imbuf/IMB_imbuf.h | 2 + source/blender/imbuf/intern/anim_movie.c | 10 ++ source/blender/makesdna/DNA_scene_types.h | 15 ++ source/blender/makesrna/intern/rna_scene.c | 38 +++++ source/blender/sequencer/SEQ_sequencer.h | 27 +++ source/blender/sequencer/intern/render.c | 18 +- source/blender/sequencer/intern/sequencer.c | 33 ++++ source/blender/sequencer/intern/strip_add.c | 14 ++ source/blender/sequencer/intern/utils.c | 34 ++++ 16 files changed, 514 insertions(+), 51 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index ca95ca8bda0..1ed4d1183a1 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -39,7 +39,7 @@ extern "C" { /* Blender file format version. */ #define BLENDER_FILE_VERSION BLENDER_VERSION -#define BLENDER_FILE_SUBVERSION 7 +#define BLENDER_FILE_SUBVERSION 8 /* Minimum Blender version that supports reading file written with the current * version. Older Blender versions will test this and show a warning if the file diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index f63d443d29f..cc192c1c3c0 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -222,6 +222,7 @@ static void scene_init_data(ID *id) /* Curve Profile */ scene->toolsettings->custom_bevel_profile_preset = BKE_curveprofile_add(PROF_PRESET_LINE); + scene->toolsettings->sequencer_tool_settings = SEQ_tool_settings_init(); for (size_t i = 0; i < ARRAY_SIZE(scene->orientation_slots); i++) { scene->orientation_slots[i].index_custom = -1; @@ -862,6 +863,9 @@ static void scene_blend_write(BlendWriter *writer, ID *id, const void *id_addres if (tos->custom_bevel_profile_preset) { BKE_curveprofile_blend_write(writer, tos->custom_bevel_profile_preset); } + if (tos->sequencer_tool_settings) { + BLO_write_struct(writer, SequencerToolSettings, tos->sequencer_tool_settings); + } BKE_paint_blend_write(writer, &tos->imapaint.paint); @@ -1121,6 +1125,8 @@ static void scene_blend_read_data(BlendDataReader *reader, ID *id) if (sce->toolsettings->custom_bevel_profile_preset) { BKE_curveprofile_blend_read(reader, sce->toolsettings->custom_bevel_profile_preset); } + + BLO_read_data_address(reader, &sce->toolsettings->sequencer_tool_settings); } if (sce->ed) { @@ -1792,6 +1798,8 @@ ToolSettings *BKE_toolsettings_copy(ToolSettings *toolsettings, const int flag) ts->gp_sculpt.cur_primitive = BKE_curvemapping_copy(ts->gp_sculpt.cur_primitive); ts->custom_bevel_profile_preset = BKE_curveprofile_copy(ts->custom_bevel_profile_preset); + + ts->sequencer_tool_settings = SEQ_tool_settings_copy(ts->sequencer_tool_settings); return ts; } @@ -1850,6 +1858,10 @@ void BKE_toolsettings_free(ToolSettings *toolsettings) BKE_curveprofile_free(toolsettings->custom_bevel_profile_preset); } + if (toolsettings->sequencer_tool_settings) { + SEQ_tool_settings_free(toolsettings->sequencer_tool_settings); + } + MEM_freeN(toolsettings); } diff --git a/source/blender/blenloader/intern/versioning_290.c b/source/blender/blenloader/intern/versioning_290.c index 49e1b057b39..753cc861982 100644 --- a/source/blender/blenloader/intern/versioning_290.c +++ b/source/blender/blenloader/intern/versioning_290.c @@ -74,6 +74,29 @@ /* Make preferences read-only, use versioning_userdef.c. */ #define U (*((const UserDef *)&U)) +static eSpaceSeq_Proxy_RenderSize get_sequencer_render_size(Main *bmain) +{ + eSpaceSeq_Proxy_RenderSize render_size = 100; + + for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) { + LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { + LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) { + switch (sl->spacetype) { + case SPACE_SEQ: { + SpaceSeq *sseq = (SpaceSeq *)sl; + if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) { + render_size = sseq->render_size; + break; + } + } + } + } + } + } + + return render_size; +} + /* image_size is width or height depending what RNA property is converted - X or Y. */ static void seq_convert_transform_animation(const Scene *scene, const char *path, @@ -212,6 +235,90 @@ static void seq_convert_transform_crop_lb(const Scene *scene, } } +static void seq_convert_transform_animation_2(const Scene *scene, + const char *path, + const float scale_to_fit_factor) +{ + if (scene->adt == NULL || scene->adt->action == NULL) { + return; + } + + FCurve *fcu = BKE_fcurve_find(&scene->adt->action->curves, path, 0); + if (fcu != NULL && !BKE_fcurve_is_empty(fcu)) { + BezTriple *bezt = fcu->bezt; + for (int i = 0; i < fcu->totvert; i++, bezt++) { + /* Same math as with old_image_center_*, but simplified. */ + bezt->vec[1][1] *= scale_to_fit_factor; + } + } +} + +static void seq_convert_transform_crop_2(const Scene *scene, + Sequence *seq, + const eSpaceSeq_Proxy_RenderSize render_size) +{ + const StripElem *s_elem = SEQ_render_give_stripelem(seq, seq->start); + if (s_elem == NULL) { + return; + } + + StripCrop *c = seq->strip->crop; + StripTransform *t = seq->strip->transform; + int image_size_x = s_elem->orig_width; + int image_size_y = s_elem->orig_height; + + if (SEQ_can_use_proxy(seq, SEQ_rendersize_to_proxysize(render_size))) { + image_size_x /= SEQ_rendersize_to_scale_factor(render_size); + image_size_y /= SEQ_rendersize_to_scale_factor(render_size); + } + + /* Calculate scale factor, so image fits in preview area with original aspect ratio. */ + const float scale_to_fit_factor = MIN2((float)scene->r.xsch / (float)image_size_x, + (float)scene->r.ysch / (float)image_size_y); + t->scale_x *= scale_to_fit_factor; + t->scale_y *= scale_to_fit_factor; + c->top /= scale_to_fit_factor; + c->bottom /= scale_to_fit_factor; + c->left /= scale_to_fit_factor; + c->right /= scale_to_fit_factor; + + char name_esc[(sizeof(seq->name) - 2) * 2], *path; + BLI_str_escape(name_esc, seq->name + 2, sizeof(name_esc)); + path = BLI_sprintfN("sequence_editor.sequences_all[\"%s\"].transform.offset_x", name_esc); + seq_convert_transform_animation_2(scene, path, scale_to_fit_factor); + MEM_freeN(path); + path = BLI_sprintfN("sequence_editor.sequences_all[\"%s\"].transform.offset_y", name_esc); + seq_convert_transform_animation_2(scene, path, scale_to_fit_factor); + MEM_freeN(path); + path = BLI_sprintfN("sequence_editor.sequences_all[\"%s\"].crop.min_x", name_esc); + seq_convert_transform_animation_2(scene, path, 1 / scale_to_fit_factor); + MEM_freeN(path); + path = BLI_sprintfN("sequence_editor.sequences_all[\"%s\"].crop.max_x", name_esc); + seq_convert_transform_animation_2(scene, path, 1 / scale_to_fit_factor); + MEM_freeN(path); + path = BLI_sprintfN("sequence_editor.sequences_all[\"%s\"].crop.min_y", name_esc); + seq_convert_transform_animation_2(scene, path, 1 / scale_to_fit_factor); + MEM_freeN(path); + path = BLI_sprintfN("sequence_editor.sequences_all[\"%s\"].crop.max_x", name_esc); + seq_convert_transform_animation_2(scene, path, 1 / scale_to_fit_factor); + MEM_freeN(path); +} + +static void seq_convert_transform_crop_lb_2(const Scene *scene, + const ListBase *lb, + const eSpaceSeq_Proxy_RenderSize render_size) +{ + + LISTBASE_FOREACH (Sequence *, seq, lb) { + if (seq->type != SEQ_TYPE_SOUND_RAM) { + seq_convert_transform_crop_2(scene, seq, render_size); + } + if (seq->type == SEQ_TYPE_META) { + seq_convert_transform_crop_lb_2(scene, &seq->seqbase, render_size); + } + } +} + void do_versions_after_linking_290(Main *bmain, ReportList *UNUSED(reports)) { if (!MAIN_VERSION_ATLEAST(bmain, 290, 1)) { @@ -441,25 +548,35 @@ void do_versions_after_linking_290(Main *bmain, ReportList *UNUSED(reports)) if (!MAIN_VERSION_ATLEAST(bmain, 292, 2)) { - eSpaceSeq_Proxy_RenderSize render_size = 100; + eSpaceSeq_Proxy_RenderSize render_size = get_sequencer_render_size(bmain); - for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) { - LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { - LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) { - switch (sl->spacetype) { - case SPACE_SEQ: { - SpaceSeq *sseq = (SpaceSeq *)sl; - render_size = sseq->render_size; - break; - } - } - } + LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) { + if (scene->ed != NULL) { + seq_convert_transform_crop_lb(scene, &scene->ed->seqbase, render_size); } } + } + if (!MAIN_VERSION_ATLEAST(bmain, 292, 8)) { + /* Systematically rebuild posebones to ensure consistent ordering matching the one of bones in + * Armature obdata. */ + LISTBASE_FOREACH (Object *, ob, &bmain->objects) { + if (ob->type == OB_ARMATURE) { + BKE_pose_rebuild(bmain, ob, ob->data, true); + } + } + + /* Wet Paint Radius Factor */ + for (Brush *br = bmain->brushes.first; br; br = br->id.next) { + if (br->ob_mode & OB_MODE_SCULPT && br->wet_paint_radius_factor == 0.0f) { + br->wet_paint_radius_factor = 1.0f; + } + } + + eSpaceSeq_Proxy_RenderSize render_size = get_sequencer_render_size(bmain); LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) { if (scene->ed != NULL) { - seq_convert_transform_crop_lb(scene, &scene->ed->seqbase, render_size); + seq_convert_transform_crop_lb_2(scene, &scene->ed->seqbase, render_size); } } } @@ -476,21 +593,6 @@ void do_versions_after_linking_290(Main *bmain, ReportList *UNUSED(reports)) */ { /* Keep this block, even when empty. */ - - /* Systematically rebuild posebones to ensure consistent ordering matching the one of bones in - * Armature obdata. */ - LISTBASE_FOREACH (Object *, ob, &bmain->objects) { - if (ob->type == OB_ARMATURE) { - BKE_pose_rebuild(bmain, ob, ob->data, true); - } - } - } - - /* Wet Paint Radius Factor */ - for (Brush *br = bmain->brushes.first; br; br = br->id.next) { - if (br->ob_mode & OB_MODE_SCULPT && br->wet_paint_radius_factor == 0.0f) { - br->wet_paint_radius_factor = 1.0f; - } } } @@ -1305,6 +1407,22 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain) } } + if (!MAIN_VERSION_ATLEAST(bmain, 292, 8)) { + LISTBASE_FOREACH (bNodeTree *, ntree, &bmain->nodetrees) { + LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { + if (STREQ(node->idname, "GeometryNodeRandomAttribute")) { + STRNCPY(node->idname, "GeometryNodeAttributeRandomize"); + } + } + } + + LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) { + if (scene->ed != NULL) { + scene->toolsettings->sequencer_tool_settings = SEQ_tool_settings_init(); + } + } + } + /** * Versioning code until next subversion bump goes here. * @@ -1316,13 +1434,5 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain) */ { /* Keep this block, even when empty. */ - - LISTBASE_FOREACH (bNodeTree *, ntree, &bmain->nodetrees) { - LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { - if (STREQ(node->idname, "GeometryNodeRandomAttribute")) { - STRNCPY(node->idname, "GeometryNodeAttributeRandomize"); - } - } - } } } diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c index 37dfcdbc765..71433a6978a 100644 --- a/source/blender/editors/space_sequencer/sequencer_add.c +++ b/source/blender/editors/space_sequencer/sequencer_add.c @@ -81,9 +81,18 @@ typedef struct SequencerAddData { #define SEQPROP_ENDFRAME (1 << 1) #define SEQPROP_NOPATHS (1 << 2) #define SEQPROP_NOCHAN (1 << 3) +#define SEQPROP_FIT_METHOD (1 << 4) #define SELECT 1 +static const EnumPropertyItem scale_fit_methods[] = { + {SEQ_SCALE_TO_FIT, "FIT", 0, "Scale to Fit", "Scale image to fit within the canvas"}, + {SEQ_SCALE_TO_FILL, "FILL", 0, "Scale to Fill", "Scale image to completely fill the canvas"}, + {SEQ_STRETCH_TO_FILL, "STRETCH", 0, "Stretch to Fill", "Stretch image to fill the canvas"}, + {SEQ_USE_ORIGINAL_SIZE, "ORIGINAL", 0, "Use Original Size", "Keep image at its original size"}, + {0, NULL, 0, NULL, NULL}, +}; + static void sequencer_generic_props__internal(wmOperatorType *ot, int flag) { PropertyRNA *prop; @@ -123,6 +132,15 @@ static void sequencer_generic_props__internal(wmOperatorType *ot, int flag) prop = RNA_def_boolean( ot->srna, "overlap", 0, "Allow Overlap", "Don't correct overlap on new sequence strips"); RNA_def_property_flag(prop, PROP_HIDDEN); + + if (flag & SEQPROP_FIT_METHOD) { + ot->prop = RNA_def_enum(ot->srna, + "fit_method", + scale_fit_methods, + SEQ_SCALE_TO_FIT, + "Fit Method", + "Scale fit method"); + } } static void sequencer_generic_invoke_path__internal(bContext *C, @@ -206,6 +224,8 @@ static void seq_load_operator_info(SeqLoadInfo *seq_load, bContext *C, wmOperato seq_load->end_frame = seq_load->start_frame; seq_load->channel = RNA_int_get(op->ptr, "channel"); seq_load->len = 1; + seq_load->fit_method = RNA_enum_get(op->ptr, "fit_method"); + SEQ_tool_settings_fit_method_set(CTX_data_scene(C), seq_load->fit_method); if ((prop = RNA_struct_find_property(op->ptr, "filepath"))) { /* Full path, file is set by the caller. */ @@ -659,6 +679,7 @@ static int sequencer_add_movie_strip_invoke(bContext *C, if (ed && ed->seqbasep && ed->seqbasep->first) { RNA_boolean_set(op->ptr, "use_framerate", false); } + RNA_enum_set(op->ptr, "fit_method", SEQ_tool_settings_fit_method_get(scene)); /* This is for drag and drop. */ if ((RNA_struct_property_is_set(op->ptr, "files") && RNA_collection_length(op->ptr, "files")) || @@ -725,7 +746,7 @@ void SEQUENCER_OT_movie_strip_add(struct wmOperatorType *ot) WM_FILESEL_SHOW_PROPS | WM_FILESEL_DIRECTORY, FILE_DEFAULTDISPLAY, FILE_SORT_DEFAULT); - sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME); + sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME | SEQPROP_FIT_METHOD); RNA_def_boolean(ot->srna, "sound", true, "Sound", "Load sound with the movie"); RNA_def_boolean(ot->srna, "use_framerate", @@ -928,6 +949,9 @@ static int sequencer_add_image_strip_invoke(bContext *C, PropertyRNA *prop; Scene *scene = CTX_data_scene(C); + const SequencerToolSettings *tool_settings = scene->toolsettings->sequencer_tool_settings; + RNA_enum_set(op->ptr, "fit_method", tool_settings->fit_method); + /* Name set already by drag and drop. */ if (RNA_struct_property_is_set(op->ptr, "files") && RNA_collection_length(op->ptr, "files")) { sequencer_generic_invoke_xy__internal( @@ -972,7 +996,8 @@ void SEQUENCER_OT_image_strip_add(struct wmOperatorType *ot) WM_FILESEL_SHOW_PROPS | WM_FILESEL_DIRECTORY, FILE_DEFAULTDISPLAY, FILE_SORT_DEFAULT); - sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME | SEQPROP_ENDFRAME); + sequencer_generic_props__internal(ot, + SEQPROP_STARTFRAME | SEQPROP_ENDFRAME | SEQPROP_FIT_METHOD); RNA_def_boolean(ot->srna, "use_placeholders", diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c index 1e3529a9607..ddc9ba2e0f6 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.c +++ b/source/blender/editors/space_sequencer/sequencer_edit.c @@ -3414,3 +3414,148 @@ Sequence *find_nearest_seq(Scene *scene, View2D *v2d, int *hand, const int mval[ } /** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Clear Strip Transform Operator + * \{ */ + +enum { + STRIP_TRANSFORM_POSITION, + STRIP_TRANSFORM_SCALE, + STRIP_TRANSFORM_ROTATION, + STRIP_TRANSFORM_ALL, +}; + +static const EnumPropertyItem transform_reset_properties[] = { + {STRIP_TRANSFORM_POSITION, "POSITION", 0, "Position", "Reset strip transform location"}, + {STRIP_TRANSFORM_SCALE, "SCALE", 0, "Scale", "Reset strip transform scale"}, + {STRIP_TRANSFORM_ROTATION, "ROTATION", 0, "Rotation", "Reset strip transform rotation"}, + {STRIP_TRANSFORM_ALL, "ALL", 0, "All", "Reset strip transform location, scale and rotation"}, + {0, NULL, 0, NULL, NULL}, +}; + +static int sequencer_strip_transform_clear_exec(bContext *C, wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + const Editing *ed = BKE_sequencer_editing_get(scene, false); + Sequence *seq; + const int property = RNA_enum_get(op->ptr, "property"); + + for (seq = ed->seqbasep->first; seq; seq = seq->next) { + if (seq->flag & SELECT && seq->type != SEQ_TYPE_SOUND_RAM) { + StripTransform *transform = seq->strip->transform; + switch (property) { + case STRIP_TRANSFORM_POSITION: + transform->xofs = 0; + transform->yofs = 0; + break; + case STRIP_TRANSFORM_SCALE: + transform->scale_x = 1.0f; + transform->scale_y = 1.0f; + break; + case STRIP_TRANSFORM_ROTATION: + transform->rotation = 0.0f; + break; + case STRIP_TRANSFORM_ALL: + transform->xofs = 0; + transform->yofs = 0; + transform->scale_x = 1.0f; + transform->scale_y = 1.0f; + transform->rotation = 0.0f; + break; + } + BKE_sequence_invalidate_cache_preprocessed(scene, seq); + } + } + + WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); + return OPERATOR_FINISHED; +} + +void SEQUENCER_OT_strip_transform_clear(struct wmOperatorType *ot) +{ + /* Identifiers. */ + ot->name = "Clear Strip Transform"; + ot->idname = "SEQUENCER_OT_strip_transform_clear"; + ot->description = "Reset image transformation to default value"; + + /* Api callbacks. */ + ot->exec = sequencer_strip_transform_clear_exec; + ot->poll = sequencer_edit_poll; + + /* Flags. */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + ot->prop = RNA_def_enum(ot->srna, + "property", + transform_reset_properties, + STRIP_TRANSFORM_ALL, + "Property", + "Strip transform property to be reset"); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Transform Set Fit Operator + * \{ */ + +static const EnumPropertyItem scale_fit_methods[] = { + {SEQ_SCALE_TO_FIT, "FIT", 0, "Scale to Fit", "Scale image so fits in preview"}, + {SEQ_SCALE_TO_FILL, "FILL", 0, "Scale to Fill", "Scale image so it fills preview completely"}, + {SEQ_STRETCH_TO_FILL, "STRETCH", 0, "Stretch to Fill", "Stretch image so it fills preview"}, + {0, NULL, 0, NULL, NULL}, +}; + +static int sequencer_strip_transform_fit_exec(bContext *C, wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + const Editing *ed = BKE_sequencer_editing_get(scene, false); + Sequence *seq; + const eSeqImageFitMethod fit_method = RNA_enum_get(op->ptr, "fit_method"); + + for (seq = ed->seqbasep->first; seq; seq = seq->next) { + if (seq->flag & SELECT && seq->type != SEQ_TYPE_SOUND_RAM) { + const int timeline_frame = CFRA; + StripElem *strip_elem = SEQ_render_give_stripelem(seq, timeline_frame); + + if (strip_elem == NULL) { + continue; + } + + SEQ_set_scale_to_fit(seq, + strip_elem->orig_width, + strip_elem->orig_height, + scene->r.xsch, + scene->r.ysch, + fit_method); + BKE_sequence_invalidate_cache_preprocessed(scene, seq); + } + } + + WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); + return OPERATOR_FINISHED; +} + +void SEQUENCER_OT_strip_transform_fit(struct wmOperatorType *ot) +{ + /* Identifiers. */ + ot->name = "Strip Transform Set Fit"; + ot->idname = "SEQUENCER_OT_strip_transform_fit"; + + /* Api callbacks. */ + ot->exec = sequencer_strip_transform_fit_exec; + ot->poll = sequencer_edit_poll; + + /* Flags. */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + ot->prop = RNA_def_enum(ot->srna, + "fit_method", + scale_fit_methods, + SEQ_SCALE_TO_FIT, + "Fit Method", + "Scale fit fit_method"); +} + +/** \} */ diff --git a/source/blender/editors/space_sequencer/sequencer_intern.h b/source/blender/editors/space_sequencer/sequencer_intern.h index 6ccfd3a9045..4c942a83f2b 100644 --- a/source/blender/editors/space_sequencer/sequencer_intern.h +++ b/source/blender/editors/space_sequencer/sequencer_intern.h @@ -144,6 +144,8 @@ void SEQUENCER_OT_enable_proxies(struct wmOperatorType *ot); void SEQUENCER_OT_export_subtitles(struct wmOperatorType *ot); void SEQUENCER_OT_set_range_to_strips(struct wmOperatorType *ot); +void SEQUENCER_OT_strip_transform_clear(struct wmOperatorType *ot); +void SEQUENCER_OT_strip_transform_fit(struct wmOperatorType *ot); /* sequencer_select.c */ void SEQUENCER_OT_select_all(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_sequencer/sequencer_ops.c b/source/blender/editors/space_sequencer/sequencer_ops.c index bdf6e4ece7f..7bfc8600544 100644 --- a/source/blender/editors/space_sequencer/sequencer_ops.c +++ b/source/blender/editors/space_sequencer/sequencer_ops.c @@ -81,6 +81,8 @@ void sequencer_operatortypes(void) WM_operatortype_append(SEQUENCER_OT_change_path); WM_operatortype_append(SEQUENCER_OT_set_range_to_strips); + WM_operatortype_append(SEQUENCER_OT_strip_transform_clear); + WM_operatortype_append(SEQUENCER_OT_strip_transform_fit); /* sequencer_select.c */ WM_operatortype_append(SEQUENCER_OT_select_all); diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h index 957352595ed..58ddc918f61 100644 --- a/source/blender/imbuf/IMB_imbuf.h +++ b/source/blender/imbuf/IMB_imbuf.h @@ -382,6 +382,8 @@ bool IMB_anim_can_produce_frames(const struct anim *anim); int ismovie(const char *filepath); void IMB_anim_set_preseek(struct anim *anim, int preseek); int IMB_anim_get_preseek(struct anim *anim); +int IMB_anim_get_image_width(struct anim *anim); +int IMB_anim_get_image_height(struct anim *anim); /** * diff --git a/source/blender/imbuf/intern/anim_movie.c b/source/blender/imbuf/intern/anim_movie.c index d825b20f5f2..9b01ea0840f 100644 --- a/source/blender/imbuf/intern/anim_movie.c +++ b/source/blender/imbuf/intern/anim_movie.c @@ -1506,3 +1506,13 @@ int IMB_anim_get_preseek(struct anim *anim) { return anim->preseek; } + +int IMB_anim_get_image_width(struct anim *anim) +{ + return anim->x; +} + +int IMB_anim_get_image_height(struct anim *anim) +{ + return anim->y; +} diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 8d43483dfe4..f73f99eb4e7 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -1339,6 +1339,18 @@ typedef struct MeshStatVis { float sharp_min, sharp_max; } MeshStatVis; +typedef struct SequencerToolSettings { + /* eSeqImageFitMethod */ + int fit_method; +} SequencerToolSettings; + +typedef enum eSeqImageFitMethod { + SEQ_SCALE_TO_FIT, + SEQ_SCALE_TO_FILL, + SEQ_STRETCH_TO_FILL, + SEQ_USE_ORIGINAL_SIZE, +} eSeqImageFitMethod; + /* *************************************************************** */ /* Tool Settings */ @@ -1513,6 +1525,9 @@ typedef struct ToolSettings { * Temporary until there is a proper preset system that stores the profiles or maybe stores * entire bevel configurations. */ struct CurveProfile *custom_bevel_profile_preset; + + struct SequencerToolSettings *sequencer_tool_settings; + } ToolSettings; /* *************************************************************** */ diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index e149bb4ecad..7cae88d292b 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -2200,6 +2200,11 @@ static char *rna_CurvePaintSettings_path(PointerRNA *UNUSED(ptr)) return BLI_strdup("tool_settings.curve_paint_settings"); } +static char *rna_SequencerToolSettings_path(PointerRNA *UNUSED(ptr)) +{ + return BLI_strdup("tool_settings.sequencer_tool_settings"); +} + /* generic function to recalc geometry */ static void rna_EditMesh_update(bContext *C, PointerRNA *UNUSED(ptr)) { @@ -3584,6 +3589,38 @@ static void rna_def_tool_settings(BlenderRNA *brna) RNA_def_property_pointer_sdna(prop, NULL, "custom_bevel_profile_preset"); RNA_def_property_struct_type(prop, "CurveProfile"); RNA_def_property_ui_text(prop, "Curve Profile Widget", "Used for defining a profile's path"); + + /* Sequencer tool settings */ + prop = RNA_def_property(srna, "sequencer_tool_settings", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); + RNA_def_property_struct_type(prop, "SequencerToolSettings"); + RNA_def_property_ui_text(prop, "Sequencer Tool Settings", NULL); +} + +static void rna_def_sequencer_tool_settings(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + static const EnumPropertyItem scale_fit_methods[] = { + {SEQ_SCALE_TO_FIT, "FIT", 0, "Scale to Fit", "Scale image to fit within the canvas"}, + {SEQ_SCALE_TO_FILL, "FILL", 0, "Scale to Fill", "Scale image to completely fill the canvas"}, + {SEQ_STRETCH_TO_FILL, "STRETCH", 0, "Stretch to Fill", "Stretch image to fill the canvas"}, + {SEQ_USE_ORIGINAL_SIZE, + "ORIGINAL", + 0, + "Use Original Size", + "Keep image at its original size"}, + {0, NULL, 0, NULL, NULL}, + }; + + srna = RNA_def_struct(brna, "SequencerToolSettings", NULL); + RNA_def_struct_path_func(srna, "rna_SequencerToolSettings_path"); + RNA_def_struct_ui_text(srna, "Sequencer Tool Settings", ""); + + prop = RNA_def_property(srna, "fit_method", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, scale_fit_methods); + RNA_def_property_ui_text(prop, "Fit Method", "Scale fit method"); } static void rna_def_unified_paint_settings(BlenderRNA *brna) @@ -7968,6 +8005,7 @@ void RNA_def_scene(BlenderRNA *brna) rna_def_gpencil_interpolate(brna); rna_def_unified_paint_settings(brna); rna_def_curve_paint_settings(brna); + rna_def_sequencer_tool_settings(brna); rna_def_statvis(brna); rna_def_unit_settings(brna); rna_def_scene_image_format_data(brna); diff --git a/source/blender/sequencer/SEQ_sequencer.h b/source/blender/sequencer/SEQ_sequencer.h index 8c4863d98ed..9b4c88520b4 100644 --- a/source/blender/sequencer/SEQ_sequencer.h +++ b/source/blender/sequencer/SEQ_sequencer.h @@ -23,6 +23,8 @@ * \ingroup sequencer */ +#include "DNA_scene_types.h" + #ifdef __cplusplus extern "C" { #endif @@ -47,6 +49,10 @@ struct StripElem; struct TextVars; struct bContext; struct bSound; +struct BlendWriter; +struct BlendDataReader; +struct BlendLibReader; +struct SequencerToolSettings; /* Wipe effect */ enum { @@ -179,6 +185,12 @@ void SEQ_render_pixel_from_sequencer_space_v4(struct Scene *scene, float pixel[4 * Sequencer scene functions * ********************************************************************** */ +struct SequencerToolSettings *SEQ_tool_settings_init(void); +void SEQ_tool_settings_free(struct SequencerToolSettings *tool_settings); +eSeqImageFitMethod SEQ_tool_settings_fit_method_get(struct Scene *scene); +void SEQ_tool_settings_fit_method_set(struct Scene *scene, eSeqImageFitMethod fit_method); + +struct SequencerToolSettings *SEQ_tool_settings_copy(struct SequencerToolSettings *tool_settings); struct Editing *BKE_sequencer_editing_get(struct Scene *scene, bool alloc); struct Editing *BKE_sequencer_editing_ensure(struct Scene *scene); void BKE_sequencer_editing_free(struct Scene *scene, const bool do_id_user); @@ -360,6 +372,20 @@ void BKE_sequence_invalidate_cache_in_range(struct Scene *scene, int invalidate_types); void BKE_sequencer_all_free_anim_ibufs(struct Scene *scene, int timeline_frame); +/* ********************************************************************** + * util.c + * + * Add strips + * ********************************************************************** + */ + +void SEQ_set_scale_to_fit(const struct Sequence *seq, + const int image_width, + const int image_height, + const int preview_width, + const int preview_height, + const eSeqImageFitMethod fit_method); + /* ********************************************************************** * sequencer.c * @@ -376,6 +402,7 @@ typedef struct SeqLoadInfo { int type; int len; /* only for image strips */ char path[1024]; /* 1024 = FILE_MAX */ + eSeqImageFitMethod fit_method; /* multiview */ char views_format; diff --git a/source/blender/sequencer/intern/render.c b/source/blender/sequencer/intern/render.c index 155258dc2c3..2e757a06751 100644 --- a/source/blender/sequencer/intern/render.c +++ b/source/blender/sequencer/intern/render.c @@ -528,7 +528,6 @@ static void sequencer_image_transform_init(void *handle_v, handle->ibuf_source = init_data->ibuf_source; handle->ibuf_out = init_data->ibuf_out; handle->transform = init_data->transform; - handle->scale_to_fit = init_data->scale_to_fit; handle->image_scale_factor = init_data->image_scale_factor; handle->for_render = init_data->for_render; @@ -540,8 +539,8 @@ static void *sequencer_image_transform_do_thread(void *data_v) { const ImageTransformThreadData *data = (ImageTransformThreadData *)data_v; const StripTransform *transform = data->transform; - const float scale_x = transform->scale_x * data->scale_to_fit; - const float scale_y = transform->scale_y * data->scale_to_fit; + const float scale_x = transform->scale_x * data->image_scale_factor; + const float scale_y = transform->scale_y * data->image_scale_factor; const float scale_to_fit_offs_x = (data->ibuf_out->x - data->ibuf_source->x) / 2; const float scale_to_fit_offs_y = (data->ibuf_out->y - data->ibuf_source->y) / 2; const float translate_x = transform->xofs * data->image_scale_factor + scale_to_fit_offs_x; @@ -626,10 +625,6 @@ static ImBuf *input_preprocess(const SeqRenderData *context, IMB_filtery(preprocessed_ibuf); } - /* Calculate scale factor, so image fits in preview area with original aspect ratio. */ - const float scale_to_fit_factor = MIN2((float)context->rectx / (float)ibuf->x, - (float)context->recty / (float)ibuf->y); - /* Get scale factor if preview resolution doesn't match project resolution. */ float preview_scale_factor; if (context->preview_render_size == SEQ_RENDER_SIZE_SCENE) { @@ -648,10 +643,10 @@ static ImBuf *input_preprocess(const SeqRenderData *context, const int height = ibuf->y; const StripCrop *c = seq->strip->crop; - const int left = c->left / scale_to_fit_factor * preview_scale_factor; - const int right = c->right / scale_to_fit_factor * preview_scale_factor; - const int top = c->top / scale_to_fit_factor * preview_scale_factor; - const int bottom = c->bottom / scale_to_fit_factor * preview_scale_factor; + const int left = c->left; + const int right = c->right; + const int top = c->top; + const int bottom = c->bottom; const float col[4] = {0.0f, 0.0f, 0.0f, 0.0f}; /* Left. */ @@ -673,7 +668,6 @@ static ImBuf *input_preprocess(const SeqRenderData *context, init_data.ibuf_source = ibuf; init_data.ibuf_out = preprocessed_ibuf; init_data.transform = seq->strip->transform; - init_data.scale_to_fit = scale_to_fit_factor; init_data.image_scale_factor = preview_scale_factor; init_data.for_render = context->for_render; IMB_processor_apply_threaded(context->recty, diff --git a/source/blender/sequencer/intern/sequencer.c b/source/blender/sequencer/intern/sequencer.c index c998886626c..82971a30c31 100644 --- a/source/blender/sequencer/intern/sequencer.c +++ b/source/blender/sequencer/intern/sequencer.c @@ -301,6 +301,32 @@ static void seq_new_fix_links_recursive(Sequence *seq) } } } + +SequencerToolSettings *SEQ_tool_settings_init(void) +{ + SequencerToolSettings *tool_settings = MEM_callocN(sizeof(SequencerToolSettings), + "Sequencer tool settings"); + tool_settings->fit_method = SEQ_SCALE_TO_FIT; + return tool_settings; +} + +void SEQ_tool_settings_free(SequencerToolSettings *tool_settings) +{ + MEM_freeN(tool_settings); +} + +eSeqImageFitMethod SEQ_tool_settings_fit_method_get(Scene *scene) +{ + const SequencerToolSettings *tool_settings = scene->toolsettings->sequencer_tool_settings; + return tool_settings->fit_method; +} + +void SEQ_tool_settings_fit_method_set(Scene *scene, eSeqImageFitMethod fit_method) +{ + SequencerToolSettings *tool_settings = scene->toolsettings->sequencer_tool_settings; + tool_settings->fit_method = fit_method; +} + /** \} */ /* -------------------------------------------------------------------- */ @@ -609,4 +635,11 @@ static void seq_free_animdata(Scene *scene, Sequence *seq) } #undef SEQ_RNAPATH_MAXSTR + +SequencerToolSettings *SEQ_tool_settings_copy(SequencerToolSettings *tool_settings) +{ + SequencerToolSettings *tool_settings_copy = MEM_dupallocN(tool_settings); + return tool_settings_copy; +} + /** \} */ diff --git a/source/blender/sequencer/intern/strip_add.c b/source/blender/sequencer/intern/strip_add.c index d2e4025bdfc..9c9d51e9286 100644 --- a/source/blender/sequencer/intern/strip_add.c +++ b/source/blender/sequencer/intern/strip_add.c @@ -118,6 +118,15 @@ Sequence *BKE_sequencer_add_image_strip(bContext *C, ListBase *seqbasep, SeqLoad seq->flag |= seq_load->flag & SEQ_USE_VIEWS; seq_load_apply(CTX_data_main(C), scene, seq, seq_load); + + char file_path[FILE_MAX]; + BLI_join_dirfile(file_path, sizeof(file_path), seq_load->path, seq_load->name); + ImBuf *ibuf = IMB_loadiffname(file_path, IB_rect, seq->strip->colorspace_settings.name); + if (ibuf != NULL) { + SEQ_set_scale_to_fit(seq, ibuf->x, ibuf->y, scene->r.xsch, scene->r.ysch, seq_load->fit_method); + IMB_freeImBuf(ibuf); + } + BKE_sequence_invalidate_cache_composite(scene, seq); return seq; @@ -275,6 +284,11 @@ Sequence *BKE_sequencer_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoad IMB_anim_load_metadata(anim_arr[0]); seq->anim_preseek = IMB_anim_get_preseek(anim_arr[0]); + + const float width = IMB_anim_get_image_width(anim_arr[0]); + const float height = IMB_anim_get_image_height(anim_arr[0]); + SEQ_set_scale_to_fit(seq, width, height, scene->r.xsch, scene->r.ysch, seq_load->fit_method); + BLI_strncpy(seq->name + 2, "Movie", SEQ_NAME_MAXSTR - 2); BKE_sequence_base_unique_name_recursive(&scene->ed->seqbase, seq); diff --git a/source/blender/sequencer/intern/utils.c b/source/blender/sequencer/intern/utils.c index 2b1d36a7709..ab0b65dba7f 100644 --- a/source/blender/sequencer/intern/utils.c +++ b/source/blender/sequencer/intern/utils.c @@ -36,6 +36,7 @@ #include "BLI_listbase.h" #include "BLI_path_util.h" #include "BLI_string.h" +#include "BLI_utildefines.h" #include "BKE_image.h" #include "BKE_main.h" @@ -547,3 +548,36 @@ bool sequencer_seq_generates_image(Sequence *seq) } return false; } + +void SEQ_set_scale_to_fit(const Sequence *seq, + const int image_width, + const int image_height, + const int preview_width, + const int preview_height, + const eSeqImageFitMethod fit_method) +{ + StripTransform *transform = seq->strip->transform; + + switch (fit_method) { + case SEQ_SCALE_TO_FIT: + transform->scale_x = transform->scale_y = MIN2((float)preview_width / (float)image_width, + (float)preview_height / (float)image_height); + + break; + case SEQ_SCALE_TO_FILL: + + transform->scale_x = transform->scale_y = MAX2((float)preview_width / (float)image_width, + (float)preview_height / (float)image_height); + break; + case SEQ_STRETCH_TO_FILL: + transform->scale_x = (float)preview_width / (float)image_width; + transform->scale_y = (float)preview_height / (float)image_height; + break; + case SEQ_USE_ORIGINAL_SIZE: + transform->scale_x = 1.0f; + transform->scale_y = 1.0f; + break; + } + + return; +} -- cgit v1.2.3 From ad7682ffdb3db5d368fd5d16f1649da780cc069f Mon Sep 17 00:00:00 2001 From: Gaia Clary Date: Wed, 16 Dec 2020 20:37:29 +0100 Subject: Allow vertex tools to operate on weight groups when armature is in object mode Since a few versions (even before 2.79) we have an option that allows to restrict the vertex tools to operate only on deform groups. This was originally implemented for working with vertex groups for skeletal animation. In that case it is fortunate to have weight tools operate only on deforming vertext groups (vgroups assigned to bones) In previous versions of Blender (up to 2.79) we have been able to use this option in Mesh Edit mode regardless of the armature mode. The current implementation (since 2.80 as far as i know) enables this option only when the associated armature is in pose mode. this has a bad consequence: It is not at all intuitive that you have to put the armature into Pose mode before you can make use of the option in mesh edit mode. Besides this it is not even necessary in the case when the user wants to restrict the tool only to all pose bones. In that case the armature can safely be kept in Object mode. However, when the tool shall apply only to selected pose bones, then it actually makes sense to have the armature in pose mode (as it is implemented right now) I do not know why this feature has been restricted as described above. It must have got lost somewhere on the way to Blender 2.90 This patch fixes the issue as it allows to select the "restrict to pose bones" option when the armature is in any mode. I see no downsides of this change, actually this is a fix for a feature that once worked and apparently got forgotten in newer releases. Reviewed By: sybren, campbellbarton Differential Revision: https://developer.blender.org/D9658 --- source/blender/editors/object/object_vgroup.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source/blender') diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c index 3d6a6abfe0d..23f1718cb2e 100644 --- a/source/blender/editors/object/object_vgroup.c +++ b/source/blender/editors/object/object_vgroup.c @@ -741,6 +741,9 @@ const EnumPropertyItem *ED_object_vgroup_selection_itemf_helper(const bContext * RNA_enum_items_add_value( &item, &totitem, WT_vertex_group_select_item, WT_VGROUP_BONE_SELECT); } + } + + if (BKE_modifiers_is_deformed_by_armature(ob)) { if (selection_mask & (1 << WT_VGROUP_BONE_DEFORM)) { RNA_enum_items_add_value( &item, &totitem, WT_vertex_group_select_item, WT_VGROUP_BONE_DEFORM); -- cgit v1.2.3 From 247b10e6a25ba58e8a74c64d4890a4c4885e51d0 Mon Sep 17 00:00:00 2001 From: Richard Antalik Date: Wed, 16 Dec 2020 21:24:42 +0100 Subject: Fix sequencer transform test failing This was casued by incorrect versioning keyframe conversion in recent commit 571362642201. --- source/blender/blenloader/intern/versioning_290.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenloader/intern/versioning_290.c b/source/blender/blenloader/intern/versioning_290.c index 753cc861982..4df681002a0 100644 --- a/source/blender/blenloader/intern/versioning_290.c +++ b/source/blender/blenloader/intern/versioning_290.c @@ -284,12 +284,6 @@ static void seq_convert_transform_crop_2(const Scene *scene, char name_esc[(sizeof(seq->name) - 2) * 2], *path; BLI_str_escape(name_esc, seq->name + 2, sizeof(name_esc)); - path = BLI_sprintfN("sequence_editor.sequences_all[\"%s\"].transform.offset_x", name_esc); - seq_convert_transform_animation_2(scene, path, scale_to_fit_factor); - MEM_freeN(path); - path = BLI_sprintfN("sequence_editor.sequences_all[\"%s\"].transform.offset_y", name_esc); - seq_convert_transform_animation_2(scene, path, scale_to_fit_factor); - MEM_freeN(path); path = BLI_sprintfN("sequence_editor.sequences_all[\"%s\"].crop.min_x", name_esc); seq_convert_transform_animation_2(scene, path, 1 / scale_to_fit_factor); MEM_freeN(path); -- cgit v1.2.3 From 07c46154318e321fe76c818c357439b79ea982cc Mon Sep 17 00:00:00 2001 From: Philipp Oeser Date: Wed, 16 Dec 2020 19:00:12 +0100 Subject: Fix T83856: Sculpt: anchored brushes with spherical falloff ignore topology automasking Anchored brushes with spherical falloff start off with zero radius, thus we have no pbvh nodes on the first brush step. This would prevent initializing the automasking cache [which only happens on the first brush step]. Maniphest Tasks: T83856 Differential Revision: https://developer.blender.org/D9873 --- source/blender/editors/sculpt_paint/sculpt.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 26db2673335..38d2bed7d97 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -5923,6 +5923,17 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe } } + /* Initialize automasking cache. For anchored brushes with spherical falloff, we start off with + * zero radius, thus we have no pbvh nodes on the first brush step. */ + if (totnode || + ((brush->falloff_shape == PAINT_FALLOFF_SHAPE_SPHERE) && (brush->flag & BRUSH_ANCHORED))) { + if (SCULPT_stroke_is_first_brush_step(ss->cache)) { + if (SCULPT_is_automasking_enabled(sd, ss, brush)) { + ss->cache->automasking = SCULPT_automasking_cache_init(sd, brush, ob); + } + } + } + /* Only act if some verts are inside the brush area. */ if (totnode) { float location[3]; @@ -5946,12 +5957,6 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe update_brush_local_mat(sd, ob); } - if (SCULPT_stroke_is_first_brush_step(ss->cache)) { - if (SCULPT_is_automasking_enabled(sd, ss, brush)) { - ss->cache->automasking = SCULPT_automasking_cache_init(sd, brush, ob); - } - } - if (brush->sculpt_tool == SCULPT_TOOL_POSE && SCULPT_stroke_is_first_brush_step(ss->cache)) { SCULPT_pose_brush_init(sd, ob, ss, brush); } -- cgit v1.2.3 From d11b219d40d7c72156fd11c335fde27212997957 Mon Sep 17 00:00:00 2001 From: Richard Antalik Date: Thu, 17 Dec 2020 02:11:22 +0100 Subject: Fix T83869: Crash when creating Sequencer in new scene Crash on null dereference in `SEQ_timeline_boundbox()`. This function was generalized in rB9e4a4c2e996c to work on arbitrary `seqbase`. Fixed by refactoring `SEQ_timeline_boundbox()` functions to return default sane values if `seqbase` is `NULL` Reviewed By: HooglyBoogly Differential Revision: https://developer.blender.org/D9878 --- .../editors/space_sequencer/sequencer_draw.c | 2 +- .../editors/space_sequencer/sequencer_view.c | 6 +---- source/blender/sequencer/SEQ_sequencer.h | 1 + source/blender/sequencer/intern/sequencer.c | 14 ++++++++++ source/blender/sequencer/intern/strip_time.c | 30 ++++++++++------------ 5 files changed, 31 insertions(+), 22 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index 5ad1e2399f5..d7d601a3c76 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -2305,7 +2305,7 @@ void draw_timeline_seq(const bContext *C, ARegion *region) UI_view2d_view_ortho(v2d); /* Get timeline bound-box, needed for the scroll-bars. */ - SEQ_timeline_boundbox(scene, ed->seqbasep, &v2d->tot); + SEQ_timeline_boundbox(scene, SEQ_active_seqbase_get(ed), &v2d->tot); draw_seq_backdrop(v2d); UI_view2d_constant_grid_draw(v2d, FPS); diff --git a/source/blender/editors/space_sequencer/sequencer_view.c b/source/blender/editors/space_sequencer/sequencer_view.c index d2166705943..e12c43b7804 100644 --- a/source/blender/editors/space_sequencer/sequencer_view.c +++ b/source/blender/editors/space_sequencer/sequencer_view.c @@ -90,11 +90,7 @@ static int sequencer_view_all_exec(bContext *C, wmOperator *op) Scene *scene = CTX_data_scene(C); const Editing *ed = BKE_sequencer_editing_get(scene, false); - if (ed == NULL) { - return OPERATOR_FINISHED; - } - - SEQ_timeline_boundbox(scene, ed->seqbasep, &box); + SEQ_timeline_boundbox(scene, SEQ_active_seqbase_get(ed), &box); UI_view2d_smooth_view(C, region, &box, smooth_viewtx); return OPERATOR_FINISHED; } diff --git a/source/blender/sequencer/SEQ_sequencer.h b/source/blender/sequencer/SEQ_sequencer.h index 9b4c88520b4..3a9c23de5cc 100644 --- a/source/blender/sequencer/SEQ_sequencer.h +++ b/source/blender/sequencer/SEQ_sequencer.h @@ -194,6 +194,7 @@ struct SequencerToolSettings *SEQ_tool_settings_copy(struct SequencerToolSetting struct Editing *BKE_sequencer_editing_get(struct Scene *scene, bool alloc); struct Editing *BKE_sequencer_editing_ensure(struct Scene *scene); void BKE_sequencer_editing_free(struct Scene *scene, const bool do_id_user); +struct ListBase *SEQ_active_seqbase_get(const struct Editing *ed); void BKE_sequencer_sort(struct Scene *scene); struct Sequence *BKE_sequencer_from_elem(ListBase *seqbase, struct StripElem *se); struct Sequence *BKE_sequencer_active_get(struct Scene *scene); diff --git a/source/blender/sequencer/intern/sequencer.c b/source/blender/sequencer/intern/sequencer.c index 82971a30c31..87b608ef141 100644 --- a/source/blender/sequencer/intern/sequencer.c +++ b/source/blender/sequencer/intern/sequencer.c @@ -327,6 +327,20 @@ void SEQ_tool_settings_fit_method_set(Scene *scene, eSeqImageFitMethod fit_metho tool_settings->fit_method = fit_method; } +/** + * Get seqbase that is being viewed currently. This can be main seqbase or meta strip seqbase + * + * \param ed: sequence editor data + * \return pointer to active seqbase. returns NULL if ed is NULL + */ +ListBase *SEQ_active_seqbase_get(const Editing *ed) +{ + if (ed == NULL) { + return NULL; + } + + return ed->seqbasep; +} /** \} */ /* -------------------------------------------------------------------- */ diff --git a/source/blender/sequencer/intern/strip_time.c b/source/blender/sequencer/intern/strip_time.c index 015d81cc217..d9074b2a683 100644 --- a/source/blender/sequencer/intern/strip_time.c +++ b/source/blender/sequencer/intern/strip_time.c @@ -361,28 +361,26 @@ float BKE_sequence_get_fps(Scene *scene, Sequence *seq) */ void SEQ_timeline_boundbox(const Scene *scene, const ListBase *seqbase, rctf *rect) { - float min[2], max[2]; - min[0] = scene->r.sfra; - max[0] = scene->r.efra + 1; - min[1] = 0.0; - max[1] = 8.0; + rect->xmin = scene->r.sfra; + rect->xmax = scene->r.efra + 1; + rect->ymin = 0.0f; + rect->ymax = 8.0f; + + if (seqbase == NULL) { + return; + } LISTBASE_FOREACH (Sequence *, seq, seqbase) { - if (min[0] > seq->startdisp - 1) { - min[0] = seq->startdisp - 1; + if (rect->xmin > seq->startdisp - 1) { + rect->xmin = seq->startdisp - 1; } - if (max[0] < seq->enddisp + 1) { - max[0] = seq->enddisp + 1; + if (rect->xmax < seq->enddisp + 1) { + rect->xmax = seq->enddisp + 1; } - if (max[1] < seq->machine + 2) { - max[1] = seq->machine + 2; + if (rect->ymax < seq->machine + 2) { + rect->ymax = seq->machine + 2; } } - - rect->xmin = min[0]; - rect->xmax = max[0]; - rect->ymin = min[1]; - rect->ymax = max[1]; } /** -- cgit v1.2.3 From 8df6589585a19efb7c9515bc40b81a55d43b3c9a Mon Sep 17 00:00:00 2001 From: Richard Antalik Date: Thu, 17 Dec 2020 02:32:24 +0100 Subject: VSE: Fix crash when adding image strip Crash happens when using relative path to image in operator properties and checking image dimensions by loading image with `IMB_loadiffname()` Ensure path is absolute. --- source/blender/sequencer/intern/strip_add.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source/blender') diff --git a/source/blender/sequencer/intern/strip_add.c b/source/blender/sequencer/intern/strip_add.c index 9c9d51e9286..e56dcf888a7 100644 --- a/source/blender/sequencer/intern/strip_add.c +++ b/source/blender/sequencer/intern/strip_add.c @@ -121,6 +121,7 @@ Sequence *BKE_sequencer_add_image_strip(bContext *C, ListBase *seqbasep, SeqLoad char file_path[FILE_MAX]; BLI_join_dirfile(file_path, sizeof(file_path), seq_load->path, seq_load->name); + BLI_path_abs(file_path, BKE_main_blendfile_path(CTX_data_main(C))); ImBuf *ibuf = IMB_loadiffname(file_path, IB_rect, seq->strip->colorspace_settings.name); if (ibuf != NULL) { SEQ_set_scale_to_fit(seq, ibuf->x, ibuf->y, scene->r.xsch, scene->r.ysch, seq_load->fit_method); -- cgit v1.2.3 From 7e535499d5f691876a50aede97e52cbb07c3b636 Mon Sep 17 00:00:00 2001 From: Ray Molenkamp Date: Wed, 16 Dec 2020 21:03:42 -0700 Subject: Clean-up: Fix build warning with MSVC Callback function was using int while update_render_passes_cb_t was using eNodeSocketDatatype leading to a build warning about different argument types with MSVC. --- source/blender/blenkernel/intern/layer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/intern/layer.c b/source/blender/blenkernel/intern/layer.c index 8a699e31f37..fbad0d920ed 100644 --- a/source/blender/blenkernel/intern/layer.c +++ b/source/blender/blenkernel/intern/layer.c @@ -2054,7 +2054,7 @@ static void bke_view_layer_verify_aov_cb(void *userdata, const char *name, int UNUSED(channels), const char *UNUSED(chanid), - int UNUSED(type)) + eNodeSocketDatatype UNUSED(type)) { GHash *name_count = userdata; void **value_p; -- cgit v1.2.3 From 6203a3ee684d704f2270edde4df80e2549d1a38d Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Thu, 17 Dec 2020 11:20:12 +0100 Subject: Fix T83878: Crash right-clicking in Asset Browser with no asset active Data of the File Browser context callback needs to be validated and return `CTX_RESULT_NO_DATA` if the context member is valid but not set in the current context. --- source/blender/editors/space_file/space_file.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c index 5bd7f6c17f6..774dc54700c 100644 --- a/source/blender/editors/space_file/space_file.c +++ b/source/blender/editors/space_file/space_file.c @@ -803,16 +803,25 @@ static int /*eContextResult*/ file_context(const bContext *C, if (CTX_data_equals(member, "active_file")) { FileDirEntry *file = filelist_file(sfile->files, params->active_file); + if (file == NULL) { + return CTX_RESULT_NO_DATA; + } + CTX_data_pointer_set(result, &screen->id, &RNA_FileSelectEntry, file); return CTX_RESULT_OK; } if (CTX_data_equals(member, "id")) { const FileDirEntry *file = filelist_file(sfile->files, params->active_file); + if (file == NULL) { + return CTX_RESULT_NO_DATA; + } ID *id = filelist_file_get_id(file); - if (id) { - CTX_data_id_pointer_set(result, id); + if (id == NULL) { + return CTX_RESULT_NO_DATA; } + + CTX_data_id_pointer_set(result, id); return CTX_RESULT_OK; } -- cgit v1.2.3 From 0eedba328df3cbc326900c34cdfc39b8554ad5ec Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Thu, 17 Dec 2020 11:55:45 +0100 Subject: Geometry Nodes: add Attribute Color Ramp node Differential Revision: https://developer.blender.org/D9861 Ref T82585. --- source/blender/blenkernel/BKE_node.h | 1 + source/blender/blenkernel/intern/node.c | 1 + source/blender/editors/space_node/drawnode.c | 10 ++ source/blender/makesdna/DNA_node_types.h | 4 + source/blender/makesrna/intern/rna_nodetree.c | 12 +++ source/blender/nodes/CMakeLists.txt | 1 + source/blender/nodes/NOD_geometry.h | 1 + source/blender/nodes/NOD_static_types.h | 1 + .../nodes/node_geo_attribute_color_ramp.cc | 107 +++++++++++++++++++++ 9 files changed, 138 insertions(+) create mode 100644 source/blender/nodes/geometry/nodes/node_geo_attribute_color_ramp.cc (limited to 'source/blender') diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index f8ce364d694..5f69fc397e8 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -1352,6 +1352,7 @@ int ntreeTexExecTree(struct bNodeTree *ntree, #define GEO_NODE_JOIN_GEOMETRY 1010 #define GEO_NODE_ATTRIBUTE_FILL 1011 #define GEO_NODE_ATTRIBUTE_MIX 1012 +#define GEO_NODE_ATTRIBUTE_COLOR_RAMP 1013 /** \} */ diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 06ff7c2e65c..415eb14be66 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -4741,6 +4741,7 @@ static void registerGeometryNodes(void) register_node_type_geo_attribute_math(); register_node_type_geo_join_geometry(); register_node_type_geo_attribute_mix(); + register_node_type_geo_attribute_color_ramp(); } static void registerFunctionNodes(void) diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 2857c08cad6..45f3b6cf9c9 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -3215,6 +3215,13 @@ static void node_geometry_buts_attribute_point_distribute(uiLayout *layout, uiItemR(layout, ptr, "distribute_method", DEFAULT_FLAGS, "", ICON_NONE); } +static void node_geometry_buts_attribute_color_ramp(uiLayout *layout, + bContext *UNUSED(C), + PointerRNA *ptr) +{ + uiTemplateColorRamp(layout, ptr, "color_ramp", 0); +} + static void node_geometry_set_butfunc(bNodeType *ntype) { switch (ntype->type) { @@ -3245,6 +3252,9 @@ static void node_geometry_set_butfunc(bNodeType *ntype) case GEO_NODE_POINT_DISTRIBUTE: ntype->draw_buttons = node_geometry_buts_attribute_point_distribute; break; + case GEO_NODE_ATTRIBUTE_COLOR_RAMP: + ntype->draw_buttons = node_geometry_buts_attribute_color_ramp; + break; } } diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 34a5372892c..7ad339c66af 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -1084,6 +1084,10 @@ typedef struct NodeAttributeMix { uint8_t input_type_b; } NodeAttributeMix; +typedef struct NodeAttributeColorRamp { + ColorBand color_ramp; +} NodeAttributeColorRamp; + /* script node mode */ #define NODE_SCRIPT_INTERNAL 0 #define NODE_SCRIPT_EXTERNAL 1 diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 4cd5b45ce78..d4ac3d1b084 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -8507,6 +8507,18 @@ static void def_geo_point_distribute(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); } +static void def_geo_attribute_color_ramp(StructRNA *srna) +{ + PropertyRNA *prop; + + RNA_def_struct_sdna_from(srna, "NodeAttributeColorRamp", "storage"); + + prop = RNA_def_property(srna, "color_ramp", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "ColorRamp"); + RNA_def_property_ui_text(prop, "Color Ramp", ""); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); +} + /* -------------------------------------------------------------------------- */ static void rna_def_shader_node(BlenderRNA *brna) diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index 46536903d55..bc0e7972bcb 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -138,6 +138,7 @@ set(SRC function/nodes/node_fn_switch.cc function/node_function_util.cc + geometry/nodes/node_geo_attribute_color_ramp.cc geometry/nodes/node_geo_attribute_fill.cc geometry/nodes/node_geo_attribute_math.cc geometry/nodes/node_geo_attribute_randomize.cc diff --git a/source/blender/nodes/NOD_geometry.h b/source/blender/nodes/NOD_geometry.h index 5ac4af9fc14..f1cd55ce048 100644 --- a/source/blender/nodes/NOD_geometry.h +++ b/source/blender/nodes/NOD_geometry.h @@ -39,6 +39,7 @@ void register_node_type_geo_attribute_randomize(void); void register_node_type_geo_attribute_math(void); void register_node_type_geo_join_geometry(void); void register_node_type_geo_attribute_mix(void); +void register_node_type_geo_attribute_color_ramp(void); #ifdef __cplusplus } diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h index 68efb0806fd..662952abb59 100644 --- a/source/blender/nodes/NOD_static_types.h +++ b/source/blender/nodes/NOD_static_types.h @@ -279,6 +279,7 @@ DefNode(GeometryNode, GEO_NODE_ATTRIBUTE_MATH, def_geo_attribute_math, "ATTRIBUT DefNode(GeometryNode, GEO_NODE_JOIN_GEOMETRY, 0, "JOIN_GEOMETRY", JoinGeometry, "Join Geometry", "") DefNode(GeometryNode, GEO_NODE_ATTRIBUTE_FILL, def_geo_attribute_fill, "ATTRIBUTE_FILL", AttributeFill, "Attribute Fill", "") DefNode(GeometryNode, GEO_NODE_ATTRIBUTE_MIX, def_geo_attribute_mix, "ATTRIBUTE_MIX", AttributeMix, "Attribute Mix", "") +DefNode(GeometryNode, GEO_NODE_ATTRIBUTE_COLOR_RAMP, def_geo_attribute_color_ramp, "ATTRIBUTE_COLOR_RAMP", AttributeColorRamp, "Attribute Color Ramp", "") /* undefine macros */ #undef DefNode diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_color_ramp.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_color_ramp.cc new file mode 100644 index 00000000000..3f7023ba88f --- /dev/null +++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_color_ramp.cc @@ -0,0 +1,107 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "node_geometry_util.hh" + +#include "BKE_colorband.h" + +static bNodeSocketTemplate geo_node_attribute_color_ramp_in[] = { + {SOCK_GEOMETRY, N_("Geometry")}, + {SOCK_STRING, N_("Attribute")}, + {SOCK_STRING, N_("Result")}, + {-1, ""}, +}; + +static bNodeSocketTemplate geo_node_attribute_color_ramp_out[] = { + {SOCK_GEOMETRY, N_("Geometry")}, + {-1, ""}, +}; + +namespace blender::nodes { + +static void execute_on_component(const GeoNodeExecParams ¶ms, GeometryComponent &component) +{ + const bNode &bnode = params.node(); + NodeAttributeColorRamp *node_storage = (NodeAttributeColorRamp *)bnode.storage; + + const std::string result_name = params.get_input("Result"); + /* Once we support more domains at the user level, we have to decide how the result domain is + * choosen. */ + const AttributeDomain result_domain = ATTR_DOMAIN_POINT; + const CustomDataType result_type = CD_PROP_COLOR; + + WriteAttributePtr attribute_result = component.attribute_try_ensure_for_write( + result_name, result_domain, result_type); + if (!attribute_result) { + return; + } + + Color4fWriteAttribute attribute_out = std::move(attribute_result); + + const std::string input_name = params.get_input("Attribute"); + FloatReadAttribute attribute_in = component.attribute_get_for_read( + input_name, result_domain, 0.0f); + + Span data_in = attribute_in.get_span(); + MutableSpan data_out = attribute_out.get_span(); + + ColorBand *color_ramp = &node_storage->color_ramp; + for (const int i : data_in.index_range()) { + BKE_colorband_evaluate(color_ramp, data_in[i], data_out[i]); + } + + attribute_out.apply_span(); +} + +static void geo_node_attribute_color_ramp_exec(GeoNodeExecParams params) +{ + GeometrySet geometry_set = params.extract_input("Geometry"); + + if (geometry_set.has()) { + execute_on_component(params, geometry_set.get_component_for_write()); + } + if (geometry_set.has()) { + execute_on_component(params, geometry_set.get_component_for_write()); + } + + params.set_output("Geometry", std::move(geometry_set)); +} + +static void geo_node_attribute_color_ramp_init(bNodeTree *UNUSED(ntree), bNode *node) +{ + NodeAttributeColorRamp *node_storage = (NodeAttributeColorRamp *)MEM_callocN( + sizeof(NodeAttributeColorRamp), __func__); + BKE_colorband_init(&node_storage->color_ramp, true); + node->storage = node_storage; +} + +} // namespace blender::nodes + +void register_node_type_geo_attribute_color_ramp() +{ + static bNodeType ntype; + + geo_node_type_base( + &ntype, GEO_NODE_ATTRIBUTE_COLOR_RAMP, "Attribute Color Ramp", NODE_CLASS_ATTRIBUTE, 0); + node_type_socket_templates( + &ntype, geo_node_attribute_color_ramp_in, geo_node_attribute_color_ramp_out); + node_type_storage( + &ntype, "NodeAttributeColorRamp", node_free_standard_storage, node_copy_standard_storage); + node_type_init(&ntype, blender::nodes::geo_node_attribute_color_ramp_init); + node_type_size_preset(&ntype, NODE_SIZE_LARGE); + ntype.geometry_node_execute = blender::nodes::geo_node_attribute_color_ramp_exec; + nodeRegisterType(&ntype); +} -- cgit v1.2.3 From cf2ebaf27c78b3f8f79d9d014ca2261228f87e70 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Thu, 17 Dec 2020 12:03:34 +0100 Subject: Fix T83875: Converting Proxy to override crashes blender. Some weird proxies apparently can have a local collection instancing... Not sure this is even really valid for proxies, but in any case we cannot override that, just detect and properly cancel the operation then. Should be backported to 2.91.1 should we do it. --- source/blender/blenkernel/intern/lib_override.c | 6 ++++++ source/blender/editors/object/object_relations.c | 11 ++++++++++- source/blender/editors/space_outliner/outliner_tools.c | 13 ++++++++++--- 3 files changed, 26 insertions(+), 4 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/intern/lib_override.c b/source/blender/blenkernel/intern/lib_override.c index 11544d83ba9..cabc80d4024 100644 --- a/source/blender/blenkernel/intern/lib_override.c +++ b/source/blender/blenkernel/intern/lib_override.c @@ -702,6 +702,12 @@ bool BKE_lib_override_library_proxy_convert(Main *bmain, &ob_proxy->proxy->id; ID *id_reference = is_override_instancing_object ? &ob_proxy_group->id : &ob_proxy->id; + /* In some cases the instance collection of a proxy object may be local (see e.g. T83875). Not + * sure this is a valid state, but for now just abort the overriding process. */ + if (!ID_IS_OVERRIDABLE_LIBRARY(id_root)) { + return false; + } + /* We manually convert the proxy object into a library override, further override handling will * then be handled by `BKE_lib_override_library_create()` just as for a regular override * creation. diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index 8ec9f7af184..5caa7c71e83 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -2527,7 +2527,7 @@ static bool convert_proxy_to_override_poll(bContext *C) return obact != NULL && obact->proxy != NULL; } -static int convert_proxy_to_override_exec(bContext *C, wmOperator *UNUSED(op)) +static int convert_proxy_to_override_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); @@ -2541,6 +2541,15 @@ static int convert_proxy_to_override_exec(bContext *C, wmOperator *UNUSED(op)) const bool success = BKE_lib_override_library_proxy_convert(bmain, scene, view_layer, ob_proxy); + if (!success) { + BKE_reportf( + op->reports, + RPT_ERROR_INVALID_INPUT, + "Could not create a library override from proxy '%s' (might use already local data?)", + ob_proxy->id.name + 2); + return OPERATOR_CANCELLED; + } + /* Remove the instance empty from this scene, the items now have an overridden collection * instead. */ if (success && is_override_instancing_object) { diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c index e4c3ebfdff5..492fc5c23bc 100644 --- a/source/blender/editors/space_outliner/outliner_tools.c +++ b/source/blender/editors/space_outliner/outliner_tools.c @@ -737,7 +737,7 @@ static void id_local_fn(bContext *C, } static void object_proxy_to_override_convert_fn(bContext *C, - ReportList *UNUSED(reports), + ReportList *reports, Scene *UNUSED(scene), TreeElement *UNUSED(te), TreeStoreElem *UNUSED(tsep), @@ -754,8 +754,15 @@ static void object_proxy_to_override_convert_fn(bContext *C, return; } - BKE_lib_override_library_proxy_convert( - CTX_data_main(C), scene, CTX_data_view_layer(C), ob_proxy); + if (!BKE_lib_override_library_proxy_convert( + CTX_data_main(C), scene, CTX_data_view_layer(C), ob_proxy)) { + BKE_reportf( + reports, + RPT_ERROR_INVALID_INPUT, + "Could not create a library override from proxy '%s' (might use already local data?)", + ob_proxy->id.name + 2); + return; + } DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS | ID_RECALC_COPY_ON_WRITE); WM_event_add_notifier(C, NC_WINDOW, NULL); -- cgit v1.2.3 From a9edf2c869baf1b73d388796737c38a1eff06471 Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Thu, 17 Dec 2020 14:22:06 +0100 Subject: Geometry-Nodes: Point Distribute - Sockets Renaming The size of the nodes is not enough to give enough context to users what the sockets are about. Minimum Distance -> Distance Min Maximum Density -> Distance Min Note this does not handle doversion. That means users will have to manually. --- source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source/blender') diff --git a/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc b/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc index 8be9636e14d..50c9246fc9b 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc @@ -34,8 +34,8 @@ static bNodeSocketTemplate geo_node_point_distribute_in[] = { {SOCK_GEOMETRY, N_("Geometry")}, - {SOCK_FLOAT, N_("Minimum Distance"), 0.1f, 0.0f, 0.0f, 0.0f, 0.0f, 100000.0f, PROP_NONE}, - {SOCK_FLOAT, N_("Maximum Density"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 100000.0f, PROP_NONE}, + {SOCK_FLOAT, N_("Distance Min"), 0.1f, 0.0f, 0.0f, 0.0f, 0.0f, 100000.0f, PROP_NONE}, + {SOCK_FLOAT, N_("Density Max"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 100000.0f, PROP_NONE}, {SOCK_STRING, N_("Density Attribute")}, {SOCK_INT, N_("Seed"), 0, 0, 0, 0, -10000, 10000}, {-1, ""}, @@ -252,7 +252,7 @@ static void geo_node_point_distribute_exec(GeoNodeExecParams params) return; } - const float density = params.extract_input("Maximum Density"); + const float density = params.extract_input("Density Max"); const std::string density_attribute = params.extract_input("Density Attribute"); if (density <= 0.0f) { @@ -274,7 +274,7 @@ static void geo_node_point_distribute_exec(GeoNodeExecParams params) points = random_scatter_points_from_mesh(mesh_in, density, density_factors, seed); break; case GEO_NODE_POINT_DISTRIBUTE_POISSON: - const float min_dist = params.extract_input("Minimum Distance"); + const float min_dist = params.extract_input("Distance Min"); points = poisson_scatter_points_from_mesh(mesh_in, density, min_dist, density_factors, seed); break; } -- cgit v1.2.3 From c9f8f7915fd8f65d1c57cd971f8e8a31a662a912 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Thu, 17 Dec 2020 07:43:31 -0600 Subject: Geometry Nodes: Make random attribute node stable Currently, the random attribute node doesn't work well for most workflows because for any change in the input data it outputs completely different results. This patch adds an implicit seed attribute input to the node, referred to by "id". The attribute is hashed for each element using the CPPType system's hash method, meaning the attribute can have any data type. Supporting any data type is also important so any attribute can be copied into the "id" attribute and used as a seed. The "id" attribute is an example of a "reserved name" attribute, meaning attributes with this name can be used implicitly by nodes like the random attribute node. Although it makes it a bit more difficult to dig deeper, using the name implicitly rather than exposing it as an input should make the system more accessible and predictable. Differential Revision: https://developer.blender.org/D9832 --- source/blender/blenkernel/BKE_attribute_access.hh | 2 + source/blender/blenkernel/BKE_geometry_set.hh | 5 ++ .../blender/blenkernel/intern/attribute_access.cc | 22 ++++++ source/blender/blenlib/BLI_hash.h | 58 ++++++++++----- source/blender/nodes/NOD_geometry_exec.hh | 2 + .../geometry/nodes/node_geo_attribute_randomize.cc | 84 +++++++++++++++------- .../geometry/nodes/node_geo_point_distribute.cc | 34 +++++++-- 7 files changed, 162 insertions(+), 45 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/BKE_attribute_access.hh b/source/blender/blenkernel/BKE_attribute_access.hh index eafd86d176b..22e14e44bec 100644 --- a/source/blender/blenkernel/BKE_attribute_access.hh +++ b/source/blender/blenkernel/BKE_attribute_access.hh @@ -267,10 +267,12 @@ template class TypedWriteAttribute { using BooleanReadAttribute = TypedReadAttribute; using FloatReadAttribute = TypedReadAttribute; using Float3ReadAttribute = TypedReadAttribute; +using Int32ReadAttribute = TypedReadAttribute; using Color4fReadAttribute = TypedReadAttribute; using BooleanWriteAttribute = TypedWriteAttribute; using FloatWriteAttribute = TypedWriteAttribute; using Float3WriteAttribute = TypedWriteAttribute; +using Int32WriteAttribute = TypedWriteAttribute; using Color4fWriteAttribute = TypedWriteAttribute; } // namespace blender::bke diff --git a/source/blender/blenkernel/BKE_geometry_set.hh b/source/blender/blenkernel/BKE_geometry_set.hh index 90d444aa270..e4232a84a00 100644 --- a/source/blender/blenkernel/BKE_geometry_set.hh +++ b/source/blender/blenkernel/BKE_geometry_set.hh @@ -136,6 +136,11 @@ class GeometryComponent { const AttributeDomain domain, const CustomDataType data_type) const; + /* Get a read-only attribute interpolated to the input domain, leaving the data type unchanged. + * Returns null when the attribute does not exist. */ + blender::bke::ReadAttributePtr attribute_try_get_for_read( + const blender::StringRef attribute_name, const AttributeDomain domain) const; + /* Get a read-only attribute for the given domain and data type. * Returns a constant attribute based on the default value if the attribute does not exist. * Never returns null. */ diff --git a/source/blender/blenkernel/intern/attribute_access.cc b/source/blender/blenkernel/intern/attribute_access.cc index 623335f65a1..934beb8a848 100644 --- a/source/blender/blenkernel/intern/attribute_access.cc +++ b/source/blender/blenkernel/intern/attribute_access.cc @@ -660,6 +660,28 @@ ReadAttributePtr GeometryComponent::attribute_try_get_for_read( return attribute; } +ReadAttributePtr GeometryComponent::attribute_try_get_for_read(const StringRef attribute_name, + const AttributeDomain domain) const +{ + if (!this->attribute_domain_supported(domain)) { + return {}; + } + + ReadAttributePtr attribute = this->attribute_try_get_for_read(attribute_name); + if (!attribute) { + return {}; + } + + if (attribute->domain() != domain) { + attribute = this->attribute_try_adapt_domain(std::move(attribute), domain); + if (!attribute) { + return {}; + } + } + + return attribute; +} + ReadAttributePtr GeometryComponent::attribute_get_for_read(const StringRef attribute_name, const AttributeDomain domain, const CustomDataType data_type, diff --git a/source/blender/blenlib/BLI_hash.h b/source/blender/blenlib/BLI_hash.h index c2be416ef5f..d687e805323 100644 --- a/source/blender/blenlib/BLI_hash.h +++ b/source/blender/blenlib/BLI_hash.h @@ -26,35 +26,59 @@ extern "C" { #endif -BLI_INLINE unsigned int BLI_hash_int_2d(unsigned int kx, unsigned int ky) -{ +/** + * Jenkins Lookup3 Hash Functions. + * Source: http://burtleburtle.net/bob/c/lookup3.c + */ + #define rot(x, k) (((x) << (k)) | ((x) >> (32 - (k)))) +#define final(a, b, c) \ + { \ + c ^= b; \ + c -= rot(b, 14); \ + a ^= c; \ + a -= rot(c, 11); \ + b ^= a; \ + b -= rot(a, 25); \ + c ^= b; \ + c -= rot(b, 16); \ + a ^= c; \ + a -= rot(c, 4); \ + b ^= a; \ + b -= rot(a, 14); \ + c ^= b; \ + c -= rot(b, 24); \ + } \ + ((void)0) + +BLI_INLINE unsigned int BLI_hash_int_3d(unsigned int kx, unsigned int ky, unsigned int kz) +{ + unsigned int a, b, c; + a = b = c = 0xdeadbeef + (3 << 2) + 13; + + c += kz; + b += ky; + a += kx; + final(a, b, c); + + return c; +} +BLI_INLINE unsigned int BLI_hash_int_2d(unsigned int kx, unsigned int ky) +{ unsigned int a, b, c; a = b = c = 0xdeadbeef + (2 << 2) + 13; a += kx; b += ky; - c ^= b; - c -= rot(b, 14); - a ^= c; - a -= rot(c, 11); - b ^= a; - b -= rot(a, 25); - c ^= b; - c -= rot(b, 16); - a ^= c; - a -= rot(c, 4); - b ^= a; - b -= rot(a, 14); - c ^= b; - c -= rot(b, 24); + final(a, b, c); return c; +} +#undef final #undef rot -} BLI_INLINE unsigned int BLI_hash_string(const char *str) { diff --git a/source/blender/nodes/NOD_geometry_exec.hh b/source/blender/nodes/NOD_geometry_exec.hh index 445e1ed6af2..cac04e18fc7 100644 --- a/source/blender/nodes/NOD_geometry_exec.hh +++ b/source/blender/nodes/NOD_geometry_exec.hh @@ -34,6 +34,8 @@ using bke::Float3ReadAttribute; using bke::Float3WriteAttribute; using bke::FloatReadAttribute; using bke::FloatWriteAttribute; +using bke::Int32ReadAttribute; +using bke::Int32WriteAttribute; using bke::PersistentDataHandleMap; using bke::PersistentObjectHandle; using bke::ReadAttribute; diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_randomize.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_randomize.cc index 53df2e8c087..2c3acfc9735 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_attribute_randomize.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_randomize.cc @@ -16,6 +16,7 @@ #include "node_geometry_util.hh" +#include "BLI_hash.h" #include "BLI_rand.hh" #include "DNA_mesh_types.h" @@ -59,48 +60,85 @@ static void geo_node_attribute_randomize_update(bNodeTree *UNUSED(ntree), bNode namespace blender::nodes { -static void randomize_attribute(BooleanWriteAttribute &attribute, RandomNumberGenerator &rng) +/** Rehash to combine the seed with the "id" hash and a mutator for each dimension. */ +static float noise_from_index_and_mutator(const int seed, const int hash, const int mutator) +{ + const int combined_hash = BLI_hash_int_3d(seed, hash, mutator); + return BLI_hash_int_01(combined_hash); +} + +/** Rehash to combine the seed with the "id" hash. */ +static float noise_from_index(const int seed, const int hash) +{ + const int combined_hash = BLI_hash_int_2d(seed, hash); + return BLI_hash_int_01(combined_hash); +} + +static void randomize_attribute(BooleanWriteAttribute &attribute, Span hashes, const int seed) { MutableSpan attribute_span = attribute.get_span(); for (const int i : IndexRange(attribute.size())) { - const bool value = rng.get_float() > 0.5f; + const bool value = noise_from_index(seed, hashes[i]) > 0.5f; attribute_span[i] = value; } attribute.apply_span(); } -static void randomize_attribute(FloatWriteAttribute &attribute, - float min, - float max, - RandomNumberGenerator &rng) +static void randomize_attribute( + FloatWriteAttribute &attribute, float min, float max, Span hashes, const int seed) { MutableSpan attribute_span = attribute.get_span(); for (const int i : IndexRange(attribute.size())) { - const float value = rng.get_float() * (max - min) + min; + const float value = noise_from_index(seed, hashes[i]) * (max - min) + min; attribute_span[i] = value; } attribute.apply_span(); } -static void randomize_attribute(Float3WriteAttribute &attribute, - float3 min, - float3 max, - RandomNumberGenerator &rng) +static void randomize_attribute( + Float3WriteAttribute &attribute, float3 min, float3 max, Span hashes, const int seed) { MutableSpan attribute_span = attribute.get_span(); for (const int i : IndexRange(attribute.size())) { - const float x = rng.get_float(); - const float y = rng.get_float(); - const float z = rng.get_float(); + const float x = noise_from_index_and_mutator(seed, hashes[i], 47); + const float y = noise_from_index_and_mutator(seed, hashes[i], 8); + const float z = noise_from_index_and_mutator(seed, hashes[i], 64); const float3 value = float3(x, y, z) * (max - min) + min; attribute_span[i] = value; } attribute.apply_span(); } +static Array get_element_hashes(GeometryComponent &component, + const AttributeDomain domain, + const int attribute_size) +{ + /* Hash the reserved name attribute "id" as a (hopefully) stable seed for each point. */ + ReadAttributePtr hash_attribute = component.attribute_try_get_for_read("id", domain); + Array hashes(attribute_size); + if (hash_attribute) { + BLI_assert(hashes.size() == hash_attribute->size()); + const CPPType &cpp_type = hash_attribute->cpp_type(); + fn::GSpan items = hash_attribute->get_span(); + for (const int i : hashes.index_range()) { + hashes[i] = (int)cpp_type.hash(items[i]); + } + } + else { + /* If there is no "id" attribute for per-point variation, just create it here. */ + RandomNumberGenerator rng; + rng.seed(0); + for (const int i : hashes.index_range()) { + hashes[i] = rng.get_int32(); + } + } + + return hashes; +} + static void randomize_attribute(GeometryComponent &component, const GeoNodeExecParams ¶ms, - RandomNumberGenerator &rng) + const int seed) { const bNode &node = params.node(); const CustomDataType data_type = static_cast(node.custom1); @@ -116,24 +154,26 @@ static void randomize_attribute(GeometryComponent &component, return; } + Array hashes = get_element_hashes(component, domain, attribute->size()); + switch (data_type) { case CD_PROP_FLOAT: { FloatWriteAttribute float_attribute = std::move(attribute); const float min_value = params.get_input("Min_001"); const float max_value = params.get_input("Max_001"); - randomize_attribute(float_attribute, min_value, max_value, rng); + randomize_attribute(float_attribute, min_value, max_value, hashes, seed); break; } case CD_PROP_FLOAT3: { Float3WriteAttribute float3_attribute = std::move(attribute); const float3 min_value = params.get_input("Min"); const float3 max_value = params.get_input("Max"); - randomize_attribute(float3_attribute, min_value, max_value, rng); + randomize_attribute(float3_attribute, min_value, max_value, hashes, seed); break; } case CD_PROP_BOOL: { BooleanWriteAttribute boolean_attribute = std::move(attribute); - randomize_attribute(boolean_attribute, rng); + randomize_attribute(boolean_attribute, hashes, seed); break; } default: @@ -147,14 +187,10 @@ static void geo_node_random_attribute_exec(GeoNodeExecParams params) const int seed = params.get_input("Seed"); if (geometry_set.has()) { - RandomNumberGenerator rng; - rng.seed_random(seed); - randomize_attribute(geometry_set.get_component_for_write(), params, rng); + randomize_attribute(geometry_set.get_component_for_write(), params, seed); } if (geometry_set.has()) { - RandomNumberGenerator rng; - rng.seed_random(seed + 3245231); - randomize_attribute(geometry_set.get_component_for_write(), params, rng); + randomize_attribute(geometry_set.get_component_for_write(), params, seed); } params.set_output("Geometry", geometry_set); diff --git a/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc b/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc index 50c9246fc9b..1d3fbae5b2e 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc @@ -58,6 +58,7 @@ namespace blender::nodes { static Vector random_scatter_points_from_mesh(const Mesh *mesh, const float density, const FloatReadAttribute &density_factors, + Vector &r_ids, const int seed) { /* This only updates a cache and can be considered to be logically const. */ @@ -95,6 +96,9 @@ static Vector random_scatter_points_from_mesh(const Mesh *mesh, float3 point_pos; interp_v3_v3v3v3(point_pos, v0_pos, v1_pos, v2_pos, bary_coords); points.append(point_pos); + + /* Build a hash stable even when the mesh is deformed. */ + r_ids.append(((int)(bary_coords.hash()) + looptri_index)); } } @@ -106,10 +110,14 @@ struct RayCastAll_Data { BVHTree_RayCastCallback raycast_callback; + /** The original coordinate the result point was projected from. */ + float2 raystart; + const Mesh *mesh; float base_weight; FloatReadAttribute *density_factors; Vector *projected_points; + Vector *stable_ids; float cur_point_weight; }; @@ -148,6 +156,9 @@ static void project_2d_bvh_callback(void *userdata, if (point_weight >= FLT_EPSILON && data->cur_point_weight <= point_weight) { data->projected_points->append(hit->co); + + /* Build a hash stable even when the mesh is deformed. */ + data->stable_ids->append((int)data->raystart.hash()); } } } @@ -156,6 +167,7 @@ static Vector poisson_scatter_points_from_mesh(const Mesh *mesh, const float density, const float minimum_distance, const FloatReadAttribute &density_factors, + Vector &r_ids, const int seed) { Vector points; @@ -191,6 +203,7 @@ static Vector poisson_scatter_points_from_mesh(const Mesh *mesh, const float3 bounds_max = float3(point_scale_multiplier, point_scale_multiplier, 0); poisson_disk_point_elimination(&points, &output_points, 2.0f * minimum_distance, bounds_max); Vector final_points; + r_ids.reserve(output_points_target); final_points.reserve(output_points_target); /* Check if we have any points we should remove from the final possion distribition. */ @@ -205,6 +218,7 @@ static Vector poisson_scatter_points_from_mesh(const Mesh *mesh, data.raycast_callback = treedata.raycast_callback; data.mesh = mesh; data.projected_points = &final_points; + data.stable_ids = &r_ids; data.density_factors = const_cast(&density_factors); data.base_weight = std::min( 1.0f, density / (output_points.size() / (point_scale_multiplier * point_scale_multiplier))); @@ -229,6 +243,7 @@ static Vector poisson_scatter_points_from_mesh(const Mesh *mesh, raystart.y = output_points[idx].y + tile_curr_y_coord; data.cur_point_weight = (float)idx / (float)output_points.size(); + data.raystart = raystart; BLI_bvhtree_ray_cast_all( treedata.tree, raystart, dir, 0.0f, max_dist, project_2d_bvh_callback, &data); @@ -267,15 +282,17 @@ static void geo_node_point_distribute_exec(GeoNodeExecParams params) density_attribute, ATTR_DOMAIN_POINT, 1.0f); const int seed = params.get_input("Seed"); + Vector stable_ids; Vector points; - switch (distribute_method) { case GEO_NODE_POINT_DISTRIBUTE_RANDOM: - points = random_scatter_points_from_mesh(mesh_in, density, density_factors, seed); + points = random_scatter_points_from_mesh( + mesh_in, density, density_factors, stable_ids, seed); break; case GEO_NODE_POINT_DISTRIBUTE_POISSON: const float min_dist = params.extract_input("Distance Min"); - points = poisson_scatter_points_from_mesh(mesh_in, density, min_dist, density_factors, seed); + points = poisson_scatter_points_from_mesh( + mesh_in, density, min_dist, density_factors, stable_ids, seed); break; } @@ -286,7 +303,16 @@ static void geo_node_point_distribute_exec(GeoNodeExecParams params) pointcloud->radius[i] = 0.05f; } - geometry_set_out.replace_pointcloud(pointcloud); + PointCloudComponent &point_component = + geometry_set_out.get_component_for_write(); + point_component.replace(pointcloud); + + Int32WriteAttribute stable_id_attribute = point_component.attribute_try_ensure_for_write( + "id", ATTR_DOMAIN_POINT, CD_PROP_INT32); + MutableSpan stable_ids_span = stable_id_attribute.get_span(); + stable_ids_span.copy_from(stable_ids); + stable_id_attribute.apply_span(); + params.set_output("Geometry", std::move(geometry_set_out)); } } // namespace blender::nodes -- cgit v1.2.3 From 3fc07d1e7482a6472bf6e34616ebe7b616189274 Mon Sep 17 00:00:00 2001 From: Philipp Oeser Date: Thu, 17 Dec 2020 12:38:40 +0100 Subject: Fix T83886: Particle instance modifier broken Caused by Caused by rB83980506957c. Since above commit, the modifier was created with wrong initial values [amount was 0.0 and offset was 1.0 -- instead of the other way around]. Since there is no way to fix existing files in a reasonable way I guess, all we can do here is to make sure that from now on, the defaults are correct. Maniphest Tasks: T83886 Differential Revision: https://developer.blender.org/D9881 --- source/blender/makesdna/DNA_modifier_defaults.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source/blender') diff --git a/source/blender/makesdna/DNA_modifier_defaults.h b/source/blender/makesdna/DNA_modifier_defaults.h index e122d50cba8..fcb582ef837 100644 --- a/source/blender/makesdna/DNA_modifier_defaults.h +++ b/source/blender/makesdna/DNA_modifier_defaults.h @@ -503,8 +503,8 @@ .random_position = 0.0f, \ .rotation = 0.0f, \ .random_rotation = 0.0f, \ - .particle_offset = 1.0f, \ - .particle_amount = 0.0f, \ + .particle_offset = 0.0f, \ + .particle_amount = 1.0f, \ .index_layer_name = "", \ .value_layer_name = "", \ } -- cgit v1.2.3 From fed995ced5b0b963bb42de5aa3e93a3c5dc91aac Mon Sep 17 00:00:00 2001 From: Philipp Oeser Date: Thu, 17 Dec 2020 13:41:10 +0100 Subject: Fix T83888: Ctrl F in Asset Browser crashes blender In case of being in Asset browsing mode, the search field is located in the header (RGN_TYPE_HEADER not RGN_TYPE_UI as for file browsing mode). To be future proof, now iterate all regions and act if the "filter_search" can be activated. Maniphest Tasks: T83888 Differential Revision: https://developer.blender.org/D9882 --- source/blender/editors/space_file/file_ops.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c index be4577bcba7..3730174a6c7 100644 --- a/source/blender/editors/space_file/file_ops.c +++ b/source/blender/editors/space_file/file_ops.c @@ -2778,13 +2778,20 @@ void FILE_OT_delete(struct wmOperatorType *ot) static int file_start_filter_exec(bContext *C, wmOperator *UNUSED(op)) { ScrArea *area = CTX_wm_area(C); - ARegion *region = BKE_area_find_region_type(area, RGN_TYPE_UI); SpaceFile *sfile = CTX_wm_space_file(C); FileSelectParams *params = ED_fileselect_get_active_params(sfile); ARegion *region_ctx = CTX_wm_region(C); - CTX_wm_region_set(C, region); - UI_textbutton_activate_rna(C, region, params, "filter_search"); + + if (area) { + LISTBASE_FOREACH (ARegion *, region, &area->regionbase) { + CTX_wm_region_set(C, region); + if (UI_textbutton_activate_rna(C, region, params, "filter_search")) { + break; + } + } + } + CTX_wm_region_set(C, region_ctx); return OPERATOR_FINISHED; -- cgit v1.2.3 From 48ddb94a26611a27d24ec02c2275b4f1fe27f87f Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Thu, 17 Dec 2020 12:22:47 -0600 Subject: Geometry Nodes: Point separate and attribute compare nodes This patch adds two related nodes, a node for separating points and mesh vertices based on a boolean attribute input, and a node for creating boolean attributes with comparisons. See the differential for an example file and video. Point Separate (T83059) The output in both geometries is just point data, contained in the mesh and point cloud components, depending which components had data in the input geometry. Any points with the mask attribute set to true will be moved from the first geometry output to the second. This means that for meshes, all edge and face data will be removed. Any point domain attributes are moved to the correct output geometry as well. Attribute Compare (T83057) The attribute compare does the "Equal" and "Not Equal" operations by comparing vectors and colors based on their distance from each other. For other operations, the comparison is between the lengths of the vector inputs. In general, the highest complexity data type is used for the operation, and a new function to determine that is added. Differential Revision: https://developer.blender.org/D9876 --- source/blender/blenkernel/BKE_node.h | 2 + source/blender/blenkernel/intern/node.c | 2 + source/blender/editors/space_node/drawnode.c | 12 + source/blender/makesdna/DNA_customdata_types.h | 2 +- source/blender/makesdna/DNA_node_types.h | 16 +- source/blender/makesrna/intern/rna_nodetree.c | 81 ++++- source/blender/nodes/CMakeLists.txt | 2 + source/blender/nodes/NOD_geometry.h | 2 + source/blender/nodes/NOD_math_functions.hh | 34 ++ source/blender/nodes/NOD_static_types.h | 2 + .../blender/nodes/geometry/node_geometry_util.cc | 42 +++ .../blender/nodes/geometry/node_geometry_util.hh | 2 + .../geometry/nodes/node_geo_attribute_compare.cc | 362 +++++++++++++++++++++ .../geometry/nodes/node_geo_point_separate.cc | 212 ++++++++++++ source/blender/nodes/intern/math_functions.cc | 30 ++ 15 files changed, 788 insertions(+), 15 deletions(-) create mode 100644 source/blender/nodes/geometry/nodes/node_geo_attribute_compare.cc create mode 100644 source/blender/nodes/geometry/nodes/node_geo_point_separate.cc (limited to 'source/blender') diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 5f69fc397e8..5e360bcb074 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -1353,6 +1353,8 @@ int ntreeTexExecTree(struct bNodeTree *ntree, #define GEO_NODE_ATTRIBUTE_FILL 1011 #define GEO_NODE_ATTRIBUTE_MIX 1012 #define GEO_NODE_ATTRIBUTE_COLOR_RAMP 1013 +#define GEO_NODE_POINT_SEPARATE 1014 +#define GEO_NODE_ATTRIBUTE_COMPARE 1015 /** \} */ diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 415eb14be66..d5cea8b6d63 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -4728,6 +4728,7 @@ static void registerGeometryNodes(void) { register_node_type_geo_group(); + register_node_type_geo_attribute_compare(); register_node_type_geo_attribute_fill(); register_node_type_geo_triangulate(); register_node_type_geo_edge_split(); @@ -4736,6 +4737,7 @@ static void registerGeometryNodes(void) register_node_type_geo_boolean(); register_node_type_geo_point_distribute(); register_node_type_geo_point_instance(); + register_node_type_geo_point_separate(); register_node_type_geo_object_info(); register_node_type_geo_attribute_randomize(); register_node_type_geo_attribute_math(); diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 45f3b6cf9c9..c2951a9d7a8 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -3149,6 +3149,15 @@ static void node_geometry_buts_boolean_math(uiLayout *layout, bContext *UNUSED(C uiItemR(layout, ptr, "operation", DEFAULT_FLAGS, "", ICON_NONE); } +static void node_geometry_buts_attribute_compare(uiLayout *layout, + bContext *UNUSED(C), + PointerRNA *ptr) +{ + uiItemR(layout, ptr, "operation", DEFAULT_FLAGS, "", ICON_NONE); + uiItemR(layout, ptr, "input_type_a", DEFAULT_FLAGS, IFACE_("Type A"), ICON_NONE); + uiItemR(layout, ptr, "input_type_b", DEFAULT_FLAGS, IFACE_("Type B"), ICON_NONE); +} + static void node_geometry_buts_subdivision_surface(uiLayout *layout, bContext *UNUSED(C), PointerRNA *UNUSED(ptr)) @@ -3240,6 +3249,9 @@ static void node_geometry_set_butfunc(bNodeType *ntype) case GEO_NODE_ATTRIBUTE_MATH: ntype->draw_buttons = node_geometry_buts_attribute_math; break; + case GEO_NODE_ATTRIBUTE_COMPARE: + ntype->draw_buttons = node_geometry_buts_attribute_compare; + break; case GEO_NODE_POINT_INSTANCE: ntype->draw_buttons = node_geometry_buts_point_instance; break; diff --git a/source/blender/makesdna/DNA_customdata_types.h b/source/blender/makesdna/DNA_customdata_types.h index 832d55ea151..e3b5ecfac04 100644 --- a/source/blender/makesdna/DNA_customdata_types.h +++ b/source/blender/makesdna/DNA_customdata_types.h @@ -220,7 +220,7 @@ typedef enum CustomDataType { /* All generic attributes. */ #define CD_MASK_PROP_ALL \ (CD_MASK_PROP_FLOAT | CD_MASK_PROP_FLOAT2 | CD_MASK_PROP_FLOAT3 | CD_MASK_PROP_INT32 | \ - CD_MASK_PROP_COLOR | CD_MASK_PROP_STRING | CD_MASK_MLOOPCOL) + CD_MASK_PROP_COLOR | CD_MASK_PROP_STRING | CD_MASK_MLOOPCOL | CD_MASK_PROP_BOOL) typedef struct CustomData_MeshMasks { uint64_t vmask; diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 7ad339c66af..f33d40b1b5d 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -1074,6 +1074,17 @@ typedef struct NodeDenoise { char _pad[7]; } NodeDenoise; +typedef struct NodeAttributeCompare { + /* FloatCompareOperation. */ + uint8_t operation; + + /* GeometryNodeAttributeInputMode */ + uint8_t input_type_a; + uint8_t input_type_b; + + char _pad[5]; +} NodeAttributeCompare; + typedef struct NodeAttributeMix { /* e.g. MA_RAMP_BLEND. */ uint8_t blend_type; @@ -1365,14 +1376,14 @@ enum { }; /* Float compare node operations. */ -enum { +typedef enum FloatCompareOperation { NODE_FLOAT_COMPARE_LESS_THAN = 0, NODE_FLOAT_COMPARE_LESS_EQUAL = 1, NODE_FLOAT_COMPARE_GREATER_THAN = 2, NODE_FLOAT_COMPARE_GREATER_EQUAL = 3, NODE_FLOAT_COMPARE_EQUAL = 4, NODE_FLOAT_COMPARE_NOT_EQUAL = 5, -}; +} FloatCompareOperation; /* Clamp node types. */ enum { @@ -1503,6 +1514,7 @@ typedef enum GeometryNodeAttributeInputMode { GEO_NODE_ATTRIBUTE_INPUT_FLOAT = 1, GEO_NODE_ATTRIBUTE_INPUT_VECTOR = 2, GEO_NODE_ATTRIBUTE_INPUT_COLOR = 3, + GEO_NODE_ATTRIBUTE_INPUT_BOOLEAN = 4, } GeometryNodeAttributeInputMode; typedef enum GeometryNodePointDistributeMethod { diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index d4ac3d1b084..9a627ef6e70 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -438,20 +438,54 @@ static const EnumPropertyItem rna_node_geometry_attribute_input_b_items[] = { {0, NULL, 0, NULL, NULL}, }; -static const EnumPropertyItem rna_node_geometry_attribute_factor_input_type_items[] = { - {GEO_NODE_ATTRIBUTE_INPUT_ATTRIBUTE, "ATTRIBUTE", 0, "Attribute", ""}, - {GEO_NODE_ATTRIBUTE_INPUT_FLOAT, "FLOAT", 0, "Float", ""}, +# define ITEM_ATTRIBUTE \ + { \ + GEO_NODE_ATTRIBUTE_INPUT_ATTRIBUTE, "ATTRIBUTE", 0, "Attribute", "" \ + } +# define ITEM_FLOAT \ + { \ + GEO_NODE_ATTRIBUTE_INPUT_FLOAT, "FLOAT", 0, "Float", "" \ + } +# define ITEM_VECTOR \ + { \ + GEO_NODE_ATTRIBUTE_INPUT_VECTOR, "VECTOR", 0, "Vector", "" \ + } +# define ITEM_COLOR \ + { \ + GEO_NODE_ATTRIBUTE_INPUT_COLOR, "COLOR", 0, "Color", "" \ + } +# define ITEM_BOOLEAN \ + { \ + GEO_NODE_ATTRIBUTE_INPUT_BOOLEAN, "BOOLEAN", 0, "Boolean", "" \ + } + +static const EnumPropertyItem rna_node_geometry_attribute_input_type_items_float[] = { + ITEM_ATTRIBUTE, + ITEM_FLOAT, {0, NULL, 0, NULL, NULL}, }; - -static const EnumPropertyItem rna_node_geometry_attribute_input_type_items[] = { - {GEO_NODE_ATTRIBUTE_INPUT_ATTRIBUTE, "ATTRIBUTE", 0, "Attribute", ""}, - {GEO_NODE_ATTRIBUTE_INPUT_FLOAT, "FLOAT", 0, "Float", ""}, - {GEO_NODE_ATTRIBUTE_INPUT_VECTOR, "VECTOR", 0, "Vector", ""}, - {GEO_NODE_ATTRIBUTE_INPUT_COLOR, "COLOR", 0, "Color", ""}, +static const EnumPropertyItem rna_node_geometry_attribute_input_type_items_no_boolean[] = { + ITEM_ATTRIBUTE, + ITEM_FLOAT, + ITEM_VECTOR, + ITEM_COLOR, + {0, NULL, 0, NULL, NULL}, +}; +static const EnumPropertyItem rna_node_geometry_attribute_input_type_items_any[] = { + ITEM_ATTRIBUTE, + ITEM_FLOAT, + ITEM_VECTOR, + ITEM_COLOR, + ITEM_BOOLEAN, {0, NULL, 0, NULL, NULL}, }; +# undef ITEM_ATTRIBUTE +# undef ITEM_FLOAT +# undef ITEM_VECTOR +# undef ITEM_COLOR +# undef ITEM_BOOLEAN + static const EnumPropertyItem rna_node_geometry_point_distribute_method_items[] = { {GEO_NODE_POINT_DISTRIBUTE_RANDOM, "RANDOM", @@ -8480,17 +8514,40 @@ static void def_geo_attribute_mix(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); prop = RNA_def_property(srna, "input_type_factor", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, rna_node_geometry_attribute_factor_input_type_items); + RNA_def_property_enum_items(prop, rna_node_geometry_attribute_input_type_items_float); RNA_def_property_ui_text(prop, "Input Type Factor", ""); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); prop = RNA_def_property(srna, "input_type_a", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, rna_node_geometry_attribute_input_type_items); + RNA_def_property_enum_items(prop, rna_node_geometry_attribute_input_type_items_no_boolean); + RNA_def_property_ui_text(prop, "Input Type A", ""); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); + + prop = RNA_def_property(srna, "input_type_b", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, rna_node_geometry_attribute_input_type_items_no_boolean); + RNA_def_property_ui_text(prop, "Input Type B", ""); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); +} + +static void def_geo_attribute_attribute_compare(StructRNA *srna) +{ + PropertyRNA *prop; + + RNA_def_struct_sdna_from(srna, "NodeAttributeCompare", "storage"); + + prop = RNA_def_property(srna, "operation", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, rna_enum_node_float_compare_items); + RNA_def_property_enum_default(prop, NODE_MATH_ADD); + RNA_def_property_ui_text(prop, "Operation", ""); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); + + prop = RNA_def_property(srna, "input_type_a", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, rna_node_geometry_attribute_input_type_items_any); RNA_def_property_ui_text(prop, "Input Type A", ""); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); prop = RNA_def_property(srna, "input_type_b", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, rna_node_geometry_attribute_input_type_items); + RNA_def_property_enum_items(prop, rna_node_geometry_attribute_input_type_items_any); RNA_def_property_ui_text(prop, "Input Type B", ""); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); } diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index bc0e7972bcb..e152c50179e 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -139,6 +139,7 @@ set(SRC function/node_function_util.cc geometry/nodes/node_geo_attribute_color_ramp.cc + geometry/nodes/node_geo_attribute_compare.cc geometry/nodes/node_geo_attribute_fill.cc geometry/nodes/node_geo_attribute_math.cc geometry/nodes/node_geo_attribute_randomize.cc @@ -151,6 +152,7 @@ set(SRC geometry/nodes/node_geo_point_distribute.cc geometry/nodes/node_geo_point_distribute_poisson_disk.cc geometry/nodes/node_geo_point_instance.cc + geometry/nodes/node_geo_point_separate.cc geometry/nodes/node_geo_subdivision_surface.cc geometry/nodes/node_geo_transform.cc geometry/nodes/node_geo_triangulate.cc diff --git a/source/blender/nodes/NOD_geometry.h b/source/blender/nodes/NOD_geometry.h index f1cd55ce048..19a7acf2299 100644 --- a/source/blender/nodes/NOD_geometry.h +++ b/source/blender/nodes/NOD_geometry.h @@ -38,6 +38,8 @@ void register_node_type_geo_object_info(void); void register_node_type_geo_attribute_randomize(void); void register_node_type_geo_attribute_math(void); void register_node_type_geo_join_geometry(void); +void register_node_type_geo_point_separate(void); +void register_node_type_geo_attribute_compare(void); void register_node_type_geo_attribute_mix(void); void register_node_type_geo_attribute_color_ramp(void); diff --git a/source/blender/nodes/NOD_math_functions.hh b/source/blender/nodes/NOD_math_functions.hh index 70e4174a844..cc750f9595a 100644 --- a/source/blender/nodes/NOD_math_functions.hh +++ b/source/blender/nodes/NOD_math_functions.hh @@ -36,6 +36,7 @@ struct FloatMathOperationInfo { }; const FloatMathOperationInfo *get_float_math_operation_info(const int operation); +const FloatMathOperationInfo *get_float_compare_operation_info(const int operation); /** * This calls the `callback` with two arguments: @@ -197,4 +198,37 @@ inline bool try_dispatch_float_math_fl_fl_fl_to_fl(const int operation, Callback return false; } +/** + * This is similar to try_dispatch_float_math_fl_to_fl, just with a different callback signature. + */ +template +inline bool try_dispatch_float_math_fl_fl_to_bool(const FloatCompareOperation operation, + Callback &&callback) +{ + const FloatMathOperationInfo *info = get_float_compare_operation_info(operation); + if (info == nullptr) { + return false; + } + + /* This is just an utility function to keep the individual cases smaller. */ + auto dispatch = [&](auto math_function) -> bool { + callback(math_function, *info); + return true; + }; + + switch (operation) { + case NODE_FLOAT_COMPARE_LESS_THAN: + return dispatch([](float a, float b) { return a < b; }); + case NODE_FLOAT_COMPARE_LESS_EQUAL: + return dispatch([](float a, float b) { return a <= b; }); + case NODE_FLOAT_COMPARE_GREATER_THAN: + return dispatch([](float a, float b) { return a > b; }); + case NODE_FLOAT_COMPARE_GREATER_EQUAL: + return dispatch([](float a, float b) { return a >= b; }); + default: + return false; + } + return false; +} + } // namespace blender::nodes diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h index 662952abb59..1e323d23a53 100644 --- a/source/blender/nodes/NOD_static_types.h +++ b/source/blender/nodes/NOD_static_types.h @@ -280,6 +280,8 @@ DefNode(GeometryNode, GEO_NODE_JOIN_GEOMETRY, 0, "JOIN_GEOMETRY", JoinGeometry, DefNode(GeometryNode, GEO_NODE_ATTRIBUTE_FILL, def_geo_attribute_fill, "ATTRIBUTE_FILL", AttributeFill, "Attribute Fill", "") DefNode(GeometryNode, GEO_NODE_ATTRIBUTE_MIX, def_geo_attribute_mix, "ATTRIBUTE_MIX", AttributeMix, "Attribute Mix", "") DefNode(GeometryNode, GEO_NODE_ATTRIBUTE_COLOR_RAMP, def_geo_attribute_color_ramp, "ATTRIBUTE_COLOR_RAMP", AttributeColorRamp, "Attribute Color Ramp", "") +DefNode(GeometryNode, GEO_NODE_POINT_SEPARATE, 0, "POINT_SEPARATE", PointSeparate, "Point Separate", "") +DefNode(GeometryNode, GEO_NODE_ATTRIBUTE_COMPARE, def_geo_attribute_attribute_compare, "ATTRIBUTE_COMPARE", AttributeCompare, "Attribute Compare", "") /* undefine macros */ #undef DefNode diff --git a/source/blender/nodes/geometry/node_geometry_util.cc b/source/blender/nodes/geometry/node_geometry_util.cc index 34c7d224f03..bcebaa6a37b 100644 --- a/source/blender/nodes/geometry/node_geometry_util.cc +++ b/source/blender/nodes/geometry/node_geometry_util.cc @@ -36,6 +36,48 @@ void update_attribute_input_socket_availabilities(bNode &node, } } +static int attribute_data_type_complexity(const CustomDataType data_type) +{ + switch (data_type) { + case CD_PROP_BOOL: + return 0; + case CD_PROP_INT32: + return 1; + case CD_PROP_FLOAT: + return 2; + case CD_PROP_FLOAT3: + return 4; + case CD_PROP_COLOR: + return 5; +#if 0 /* Attribute types are not supported yet. */ + case CD_MLOOPCOL: + return 3; + case CD_PROP_STRING: + return 6; +#endif + default: + /* Only accept "generic" custom data types used by the attribute system. */ + BLI_assert(false); + return 0; + } +} + +CustomDataType attribute_domain_highest_complexity(Span data_types) +{ + int highest_complexity = INT_MIN; + CustomDataType most_complex_type = CD_PROP_COLOR; + + for (const CustomDataType data_type : data_types) { + const int complexity = attribute_data_type_complexity(data_type); + if (complexity > highest_complexity) { + highest_complexity = complexity; + most_complex_type = data_type; + } + } + + return most_complex_type; +} + } // namespace blender::nodes bool geo_node_poll_default(bNodeType *UNUSED(ntype), bNodeTree *ntree) diff --git a/source/blender/nodes/geometry/node_geometry_util.hh b/source/blender/nodes/geometry/node_geometry_util.hh index c97463cdc22..3102690d2ed 100644 --- a/source/blender/nodes/geometry/node_geometry_util.hh +++ b/source/blender/nodes/geometry/node_geometry_util.hh @@ -43,6 +43,8 @@ void update_attribute_input_socket_availabilities(bNode &node, const StringRef name, const GeometryNodeAttributeInputMode mode); +CustomDataType attribute_domain_highest_complexity(Span); + void poisson_disk_point_elimination(Vector const *input_points, Vector *output_points, float maximum_distance, diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_compare.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_compare.cc new file mode 100644 index 00000000000..a3d5abfb3f2 --- /dev/null +++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_compare.cc @@ -0,0 +1,362 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "node_geometry_util.hh" + +#include "BKE_attribute.h" +#include "BKE_attribute_access.hh" + +#include "BLI_array.hh" +#include "BLI_math_base_safe.h" +#include "BLI_rand.hh" + +#include "DNA_mesh_types.h" +#include "DNA_pointcloud_types.h" + +#include "NOD_math_functions.hh" + +static bNodeSocketTemplate geo_node_attribute_compare_in[] = { + {SOCK_GEOMETRY, N_("Geometry")}, + {SOCK_STRING, N_("A")}, + {SOCK_FLOAT, N_("A"), 0.0, 0.0, 0.0, 0.0, -FLT_MAX, FLT_MAX}, + {SOCK_VECTOR, N_("A"), 0.0, 0.0, 0.0, 0.0, -FLT_MAX, FLT_MAX}, + {SOCK_RGBA, N_("A"), 0.5, 0.5, 0.5, 1.0}, + {SOCK_STRING, N_("B")}, + {SOCK_FLOAT, N_("B"), 0.0, 0.0, 0.0, 0.0, -FLT_MAX, FLT_MAX}, + {SOCK_VECTOR, N_("B"), 0.0, 0.0, 0.0, 0.0, -FLT_MAX, FLT_MAX}, + {SOCK_RGBA, N_("B"), 0.5, 0.5, 0.5, 1.0}, + {SOCK_FLOAT, N_("Threshold"), 0.01f, 0.0f, 0.0f, 0.0f, 0.0f, FLT_MAX}, + {SOCK_STRING, N_("Result")}, + {-1, ""}, +}; + +static bNodeSocketTemplate geo_node_attribute_compare_out[] = { + {SOCK_GEOMETRY, N_("Geometry")}, + {-1, ""}, +}; + +static void geo_node_attribute_compare_init(bNodeTree *UNUSED(tree), bNode *node) +{ + NodeAttributeCompare *data = (NodeAttributeCompare *)MEM_callocN(sizeof(NodeAttributeCompare), + "attribute mix node"); + data->operation = NODE_FLOAT_COMPARE_GREATER_THAN; + data->input_type_a = GEO_NODE_ATTRIBUTE_INPUT_ATTRIBUTE; + data->input_type_b = GEO_NODE_ATTRIBUTE_INPUT_ATTRIBUTE; + node->storage = data; +} + +static bool operation_tests_equality(const NodeAttributeCompare &node_storage) +{ + return ELEM(node_storage.operation, NODE_FLOAT_COMPARE_EQUAL, NODE_FLOAT_COMPARE_NOT_EQUAL); +} + +namespace blender::nodes { + +static void geo_node_attribute_compare_update(bNodeTree *UNUSED(ntree), bNode *node) +{ + NodeAttributeCompare *node_storage = (NodeAttributeCompare *)node->storage; + update_attribute_input_socket_availabilities( + *node, "A", (GeometryNodeAttributeInputMode)node_storage->input_type_a); + update_attribute_input_socket_availabilities( + *node, "B", (GeometryNodeAttributeInputMode)node_storage->input_type_b); + + bNodeSocket *socket_threshold = (bNodeSocket *)BLI_findlink(&node->inputs, 9); + nodeSetSocketAvailability(socket_threshold, operation_tests_equality(*node_storage)); +} + +static void do_math_operation(const FloatReadAttribute &input_a, + const FloatReadAttribute &input_b, + const FloatCompareOperation operation, + MutableSpan span_result) +{ + const int size = input_a.size(); + + Span span_a = input_a.get_span(); + Span span_b = input_b.get_span(); + + if (try_dispatch_float_math_fl_fl_to_bool( + operation, [&](auto math_function, const FloatMathOperationInfo &UNUSED(info)) { + for (const int i : IndexRange(size)) { + const float a = span_a[i]; + const float b = span_b[i]; + const bool out = math_function(a, b); + span_result[i] = out; + } + })) { + return; + } + + /* The operation is not supported by this node currently. */ + BLI_assert(false); +} + +static void do_equal_operation(const FloatReadAttribute &input_a, + const FloatReadAttribute &input_b, + const float threshold, + MutableSpan span_result) +{ + const int size = input_a.size(); + for (const int i : IndexRange(size)) { + const float a = input_a[i]; + const float b = input_b[i]; + span_result[i] = compare_ff(a, b, threshold); + } +} + +static void do_equal_operation(const Float3ReadAttribute &input_a, + const Float3ReadAttribute &input_b, + const float threshold, + MutableSpan span_result) +{ + const float threshold_squared = pow2f(threshold); + const int size = input_a.size(); + for (const int i : IndexRange(size)) { + const float3 a = input_a[i]; + const float3 b = input_b[i]; + span_result[i] = len_squared_v3v3(a, b) < threshold_squared; + } +} + +static void do_equal_operation(const Color4fReadAttribute &input_a, + const Color4fReadAttribute &input_b, + const float threshold, + MutableSpan span_result) +{ + const float threshold_squared = pow2f(threshold); + const int size = input_a.size(); + for (const int i : IndexRange(size)) { + const Color4f a = input_a[i]; + const Color4f b = input_b[i]; + span_result[i] = len_squared_v4v4(a, b) < threshold_squared; + } +} + +static void do_equal_operation(const BooleanReadAttribute &input_a, + const BooleanReadAttribute &input_b, + const float UNUSED(threshold), + MutableSpan span_result) +{ + const int size = input_a.size(); + for (const int i : IndexRange(size)) { + const bool a = input_a[i]; + const bool b = input_b[i]; + span_result[i] = a == b; + } +} + +static void do_not_equal_operation(const FloatReadAttribute &input_a, + const FloatReadAttribute &input_b, + const float threshold, + MutableSpan span_result) +{ + const int size = input_a.size(); + for (const int i : IndexRange(size)) { + const float a = input_a[i]; + const float b = input_b[i]; + span_result[i] = !compare_ff(a, b, threshold); + } +} + +static void do_not_equal_operation(const Float3ReadAttribute &input_a, + const Float3ReadAttribute &input_b, + const float threshold, + MutableSpan span_result) +{ + const float threshold_squared = pow2f(threshold); + const int size = input_a.size(); + for (const int i : IndexRange(size)) { + const float3 a = input_a[i]; + const float3 b = input_b[i]; + span_result[i] = len_squared_v3v3(a, b) >= threshold_squared; + } +} + +static void do_not_equal_operation(const Color4fReadAttribute &input_a, + const Color4fReadAttribute &input_b, + const float threshold, + MutableSpan span_result) +{ + const float threshold_squared = pow2f(threshold); + const int size = input_a.size(); + for (const int i : IndexRange(size)) { + const Color4f a = input_a[i]; + const Color4f b = input_b[i]; + span_result[i] = len_squared_v4v4(a, b) >= threshold_squared; + } +} + +static void do_not_equal_operation(const BooleanReadAttribute &input_a, + const BooleanReadAttribute &input_b, + const float UNUSED(threshold), + MutableSpan span_result) +{ + const int size = input_a.size(); + for (const int i : IndexRange(size)) { + const bool a = input_a[i]; + const bool b = input_b[i]; + span_result[i] = a != b; + } +} + +static CustomDataType get_data_type(GeometryComponent &component, + const GeoNodeExecParams ¶ms, + const NodeAttributeCompare &node_storage) +{ + if (operation_tests_equality(node_storage)) { + CustomDataType data_type_a = params.get_input_attribute_data_type( + "A", component, CD_PROP_FLOAT); + CustomDataType data_type_b = params.get_input_attribute_data_type( + "B", component, CD_PROP_FLOAT); + + /* Convert the input attributes to the same data type for the equality tests. Use the higher + * complexity attribute type, otherwise information necessary to the comparison may be lost. */ + return attribute_domain_highest_complexity({data_type_a, data_type_b}); + } + + /* Use float compare for every operation besides equality. */ + return CD_PROP_FLOAT; +} + +static void attribute_compare_calc(GeometryComponent &component, const GeoNodeExecParams ¶ms) +{ + const bNode &node = params.node(); + NodeAttributeCompare *node_storage = (NodeAttributeCompare *)node.storage; + const FloatCompareOperation operation = static_cast( + node_storage->operation); + + /* The result type of this node is always float. */ + const CustomDataType result_type = CD_PROP_BOOL; + /* The result domain is always point for now. */ + const AttributeDomain result_domain = ATTR_DOMAIN_POINT; + + /* Get result attribute first, in case it has to overwrite one of the existing attributes. */ + const std::string result_name = params.get_input("Result"); + WriteAttributePtr attribute_result = component.attribute_try_ensure_for_write( + result_name, result_domain, result_type); + if (!attribute_result) { + return; + } + + const CustomDataType input_data_type = get_data_type(component, params, *node_storage); + + ReadAttributePtr attribute_a = params.get_input_attribute( + "A", component, result_domain, input_data_type, nullptr); + ReadAttributePtr attribute_b = params.get_input_attribute( + "B", component, result_domain, input_data_type, nullptr); + + if (!attribute_a || !attribute_b) { + /* Attribute wasn't found. */ + return; + } + + BooleanWriteAttribute attribute_result_bool = std::move(attribute_result); + MutableSpan result_span = attribute_result_bool.get_span(); + + /* Use specific types for correct equality operations, but for other operations we use implicit + * conversions and float comparison. In other words, the comparison is not element-wise. */ + if (operation_tests_equality(*node_storage)) { + const float threshold = params.get_input("Threshold"); + if (operation == NODE_FLOAT_COMPARE_EQUAL) { + if (input_data_type == CD_PROP_FLOAT) { + FloatReadAttribute attribute_a_float = std::move(attribute_a); + FloatReadAttribute attribute_b_float = std::move(attribute_b); + do_equal_operation( + std::move(attribute_a_float), std::move(attribute_b_float), threshold, result_span); + } + else if (input_data_type == CD_PROP_FLOAT3) { + Float3ReadAttribute attribute_a_float3 = std::move(attribute_a); + Float3ReadAttribute attribute_b_float3 = std::move(attribute_b); + do_equal_operation( + std::move(attribute_a_float3), std::move(attribute_b_float3), threshold, result_span); + } + else if (input_data_type == CD_PROP_COLOR) { + Color4fReadAttribute attribute_a_color = std::move(attribute_a); + Color4fReadAttribute attribute_b_color = std::move(attribute_b); + do_equal_operation( + std::move(attribute_a_color), std::move(attribute_b_color), threshold, result_span); + } + else if (input_data_type == CD_PROP_BOOL) { + BooleanReadAttribute attribute_a_bool = std::move(attribute_a); + BooleanReadAttribute attribute_b_bool = std::move(attribute_b); + do_equal_operation( + std::move(attribute_a_bool), std::move(attribute_b_bool), threshold, result_span); + } + } + else if (operation == NODE_FLOAT_COMPARE_NOT_EQUAL) { + if (input_data_type == CD_PROP_FLOAT) { + FloatReadAttribute attribute_a_float = std::move(attribute_a); + FloatReadAttribute attribute_b_float = std::move(attribute_b); + do_not_equal_operation( + std::move(attribute_a_float), std::move(attribute_b_float), threshold, result_span); + } + else if (input_data_type == CD_PROP_FLOAT3) { + Float3ReadAttribute attribute_a_float3 = std::move(attribute_a); + Float3ReadAttribute attribute_b_float3 = std::move(attribute_b); + do_not_equal_operation( + std::move(attribute_a_float3), std::move(attribute_b_float3), threshold, result_span); + } + else if (input_data_type == CD_PROP_COLOR) { + Color4fReadAttribute attribute_a_color = std::move(attribute_a); + Color4fReadAttribute attribute_b_color = std::move(attribute_b); + do_not_equal_operation( + std::move(attribute_a_color), std::move(attribute_b_color), threshold, result_span); + } + else if (input_data_type == CD_PROP_BOOL) { + BooleanReadAttribute attribute_a_bool = std::move(attribute_a); + BooleanReadAttribute attribute_b_bool = std::move(attribute_b); + do_not_equal_operation( + std::move(attribute_a_bool), std::move(attribute_b_bool), threshold, result_span); + } + } + } + else { + do_math_operation(std::move(attribute_a), std::move(attribute_b), operation, result_span); + } + + attribute_result_bool.apply_span(); +} + +static void geo_node_attribute_compare_exec(GeoNodeExecParams params) +{ + GeometrySet geometry_set = params.extract_input("Geometry"); + + if (geometry_set.has()) { + attribute_compare_calc(geometry_set.get_component_for_write(), params); + } + if (geometry_set.has()) { + attribute_compare_calc(geometry_set.get_component_for_write(), params); + } + + params.set_output("Geometry", geometry_set); +} + +} // namespace blender::nodes + +void register_node_type_geo_attribute_compare() +{ + static bNodeType ntype; + + geo_node_type_base( + &ntype, GEO_NODE_ATTRIBUTE_COMPARE, "Attribute Compare", NODE_CLASS_ATTRIBUTE, 0); + node_type_socket_templates( + &ntype, geo_node_attribute_compare_in, geo_node_attribute_compare_out); + ntype.geometry_node_execute = blender::nodes::geo_node_attribute_compare_exec; + node_type_update(&ntype, blender::nodes::geo_node_attribute_compare_update); + node_type_storage( + &ntype, "NodeAttributeCompare", node_free_standard_storage, node_copy_standard_storage); + node_type_init(&ntype, geo_node_attribute_compare_init); + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/geometry/nodes/node_geo_point_separate.cc b/source/blender/nodes/geometry/nodes/node_geo_point_separate.cc new file mode 100644 index 00000000000..3229d87e1b2 --- /dev/null +++ b/source/blender/nodes/geometry/nodes/node_geo_point_separate.cc @@ -0,0 +1,212 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "BKE_mesh.h" +#include "BKE_persistent_data_handle.hh" +#include "BKE_pointcloud.h" + +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_pointcloud_types.h" + +#include "node_geometry_util.hh" + +static bNodeSocketTemplate geo_node_point_instance_in[] = { + {SOCK_GEOMETRY, N_("Geometry")}, + {SOCK_STRING, N_("Mask")}, + {-1, ""}, +}; + +static bNodeSocketTemplate geo_node_point_instance_out[] = { + {SOCK_GEOMETRY, N_("Geometry 1")}, + {SOCK_GEOMETRY, N_("Geometry 2")}, + {-1, ""}, +}; + +namespace blender::nodes { + +static void fill_new_attribute_from_input(ReadAttributePtr input_attribute, + WriteAttributePtr out_attribute_a, + WriteAttributePtr out_attribute_b, + Span a_or_b) +{ + fn::GSpan in_span = input_attribute->get_span(); + int i_a = 0; + int i_b = 0; + for (int i_in = 0; i_in < in_span.size(); i_in++) { + const bool move_to_b = a_or_b[i_in]; + if (move_to_b) { + out_attribute_b->set(i_b, in_span[i_in]); + i_b++; + } + else { + out_attribute_a->set(i_a, in_span[i_in]); + i_a++; + } + } +} + +/** + * Move the original attribute values to the two output components. + * + * \note This assumes a consistent ordering of indices before and after the split, + * which is true for points and a simple vertex array. + */ +static void move_split_attributes(const GeometryComponent &in_component, + GeometryComponent &out_component_a, + GeometryComponent &out_component_b, + Span a_or_b) +{ + Set attribute_names = in_component.attribute_names(); + + for (const std::string &name : attribute_names) { + ReadAttributePtr attribute = in_component.attribute_try_get_for_read(name); + BLI_assert(attribute); + + /* Since this node only creates points and vertices, don't copy other attributes. */ + if (attribute->domain() != ATTR_DOMAIN_POINT) { + continue; + } + + const CustomDataType data_type = bke::cpp_type_to_custom_data_type(attribute->cpp_type()); + const AttributeDomain domain = attribute->domain(); + + /* Don't try to create the attribute on the new component if it already exists. Built-in + * attributes will already exist on new components by definition. It should always be possible + * to recreate the attribute on the same component type. Also, if one of the new components + * has the attribute the other one should have it too, but check independently to be safe. */ + if (!out_component_a.attribute_exists(name)) { + if (!out_component_a.attribute_try_create(name, domain, data_type)) { + BLI_assert(false); + continue; + } + } + if (!out_component_b.attribute_exists(name)) { + if (!out_component_b.attribute_try_create(name, domain, data_type)) { + BLI_assert(false); + continue; + } + } + + WriteAttributePtr out_attribute_a = out_component_a.attribute_try_get_for_write(name); + WriteAttributePtr out_attribute_b = out_component_b.attribute_try_get_for_write(name); + if (!out_attribute_a || !out_attribute_b) { + BLI_assert(false); + continue; + } + + fill_new_attribute_from_input( + std::move(attribute), std::move(out_attribute_a), std::move(out_attribute_b), a_or_b); + } +} + +/** + * Find total in each new set and find which of the output sets each point will belong to. + */ +static Array count_point_splits(const GeometryComponent &component, + const GeoNodeExecParams ¶ms, + int *r_a_total, + int *r_b_total) +{ + const BooleanReadAttribute mask_attribute = params.get_input_attribute( + "Mask", component, ATTR_DOMAIN_POINT, false); + Array masks = mask_attribute.get_span(); + const int in_total = masks.size(); + + *r_b_total = 0; + for (const bool mask : masks) { + if (mask) { + *r_b_total += 1; + } + } + *r_a_total = in_total - *r_b_total; + + return masks; +} + +static void separate_mesh(const MeshComponent &in_component, + const GeoNodeExecParams ¶ms, + MeshComponent &out_component_a, + MeshComponent &out_component_b) +{ + const int size = in_component.attribute_domain_size(ATTR_DOMAIN_POINT); + if (size == 0) { + return; + } + + int a_total; + int b_total; + Array a_or_b = count_point_splits(in_component, params, &a_total, &b_total); + + out_component_a.replace(BKE_mesh_new_nomain(a_total, 0, 0, 0, 0)); + out_component_b.replace(BKE_mesh_new_nomain(b_total, 0, 0, 0, 0)); + + move_split_attributes(in_component, out_component_a, out_component_b, a_or_b); +} + +static void separate_point_cloud(const PointCloudComponent &in_component, + const GeoNodeExecParams ¶ms, + PointCloudComponent &out_component_a, + PointCloudComponent &out_component_b) +{ + const int size = in_component.attribute_domain_size(ATTR_DOMAIN_POINT); + if (size == 0) { + return; + } + + int a_total; + int b_total; + Array a_or_b = count_point_splits(in_component, params, &a_total, &b_total); + + out_component_a.replace(BKE_pointcloud_new_nomain(a_total)); + out_component_b.replace(BKE_pointcloud_new_nomain(b_total)); + + move_split_attributes(in_component, out_component_a, out_component_b, a_or_b); +} + +static void geo_node_point_separate_exec(GeoNodeExecParams params) +{ + GeometrySet geometry_set = params.extract_input("Geometry"); + GeometrySet out_set_a(geometry_set); + GeometrySet out_set_b; + + if (geometry_set.has()) { + separate_point_cloud(*geometry_set.get_component_for_read(), + params, + out_set_a.get_component_for_write(), + out_set_b.get_component_for_write()); + } + if (geometry_set.has()) { + separate_mesh(*geometry_set.get_component_for_read(), + params, + out_set_a.get_component_for_write(), + out_set_b.get_component_for_write()); + } + + params.set_output("Geometry 1", std::move(out_set_a)); + params.set_output("Geometry 2", std::move(out_set_b)); +} +} // namespace blender::nodes + +void register_node_type_geo_point_separate() +{ + static bNodeType ntype; + + geo_node_type_base(&ntype, GEO_NODE_POINT_SEPARATE, "Point Separate", NODE_CLASS_GEOMETRY, 0); + node_type_socket_templates(&ntype, geo_node_point_instance_in, geo_node_point_instance_out); + ntype.geometry_node_execute = blender::nodes::geo_node_point_separate_exec; + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/intern/math_functions.cc b/source/blender/nodes/intern/math_functions.cc index 5a6faa809f2..32a18f1c193 100644 --- a/source/blender/nodes/intern/math_functions.cc +++ b/source/blender/nodes/intern/math_functions.cc @@ -116,4 +116,34 @@ const FloatMathOperationInfo *get_float_math_operation_info(const int operation) return nullptr; } +const FloatMathOperationInfo *get_float_compare_operation_info(const int operation) +{ + +#define RETURN_OPERATION_INFO(title_case_name, shader_name) \ + { \ + static const FloatMathOperationInfo info{title_case_name, shader_name}; \ + return &info; \ + } \ + ((void)0) + + switch (operation) { + case NODE_FLOAT_COMPARE_LESS_THAN: + RETURN_OPERATION_INFO("Less Than", "math_less_than"); + case NODE_FLOAT_COMPARE_LESS_EQUAL: + RETURN_OPERATION_INFO("Less Than or Equal", "math_less_equal"); + case NODE_FLOAT_COMPARE_GREATER_THAN: + RETURN_OPERATION_INFO("Greater Than", "math_greater_than"); + case NODE_FLOAT_COMPARE_GREATER_EQUAL: + RETURN_OPERATION_INFO("Greater Than or Equal", "math_greater_equal"); + case NODE_FLOAT_COMPARE_EQUAL: + RETURN_OPERATION_INFO("Equal", "math_equal"); + case NODE_FLOAT_COMPARE_NOT_EQUAL: + RETURN_OPERATION_INFO("Not Equal", "math_not_equal"); + } + +#undef RETURN_OPERATION_INFO + + return nullptr; +} + } // namespace blender::nodes -- cgit v1.2.3 From f193b1afb313bcb937a396f09da2b9903a0d2fc3 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Thu, 17 Dec 2020 19:29:39 +0100 Subject: Color Management: use scene linear HSV for number buttons in color pickers Previously these HSV values were in the color picking space, which meant the relation to the scene linear RGB values was confusing. The new situation: * RGB number buttons: scene linear color space * HSV number buttons: scene linear color space * Picker widgets: color picking color space * Hex: sRGB color space Fixes T69562, T83853, Ref T68926 --- .../blender/editors/interface/interface_intern.h | 13 ++++- .../interface/interface_region_color_picker.c | 66 ++++++++++------------ 2 files changed, 42 insertions(+), 37 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index 5c7cad4c8d5..8f894d0c4bb 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -378,11 +378,20 @@ typedef struct uiButExtraOpIcon { typedef struct ColorPicker { struct ColorPicker *next, *prev; - /** Color data, may be HSV or HSL. */ + + /** Color in HSV or HSL, in color picking color space. Used for HSV cube, + * circle and slider widgets. The color picking space is perceptually + * linear for intuitive editing. */ float color_data[3]; - /** Initial color data (detect changes). */ + /** Initial color data (to detect changes). */ float color_data_init[3]; bool is_init; + + /** HSV or HSL color in scene linear color space value used for number + * buttons. This is scene linear so that there is a clear correspondence + * to the scene linear RGB values. */ + float hsv[3]; + /** Cubic saturation for the color wheel. */ bool use_color_cubic; bool use_color_lock; diff --git a/source/blender/editors/interface/interface_region_color_picker.c b/source/blender/editors/interface/interface_region_color_picker.c index f9a9e7182d2..cbf3dbf393d 100644 --- a/source/blender/editors/interface/interface_region_color_picker.c +++ b/source/blender/editors/interface/interface_region_color_picker.c @@ -182,15 +182,16 @@ static void ui_update_color_picker_buts_rgb(uiBut *from_but, ColorPicker *cpicker, const float rgb[3]) { - float *hsv = cpicker->color_data; + /* Convert from RGB to HSV in scene linear space color for numeric editing. */ + ui_rgb_to_color_picker_compat_v(rgb, cpicker->hsv); - /* Convert from RGB to HSV in perceptually linear space. */ + /* Convert from RGB to HSV in perceptually linear space for picker widgets. */ float tmp[3]; copy_v3_v3(tmp, rgb); if (from_but) { ui_scene_linear_to_color_picker_space(from_but, tmp); } - ui_rgb_to_color_picker_compat_v(tmp, hsv); + ui_rgb_to_color_picker_compat_v(tmp, cpicker->color_data); /* this updates button strings, * is hackish... but button pointers are on stack of caller function */ @@ -235,16 +236,16 @@ static void ui_update_color_picker_buts_rgb(uiBut *from_but, ui_but_value_set(bt, rgb[2]); } else if (bt->str[0] == 'H') { - ui_but_value_set(bt, hsv[0]); + ui_but_value_set(bt, cpicker->hsv[0]); } else if (bt->str[0] == 'S') { - ui_but_value_set(bt, hsv[1]); + ui_but_value_set(bt, cpicker->hsv[1]); } else if (bt->str[0] == 'V') { - ui_but_value_set(bt, hsv[2]); + ui_but_value_set(bt, cpicker->hsv[2]); } else if (bt->str[0] == 'L') { - ui_but_value_set(bt, hsv[2]); + ui_but_value_set(bt, cpicker->hsv[2]); } } @@ -252,7 +253,7 @@ static void ui_update_color_picker_buts_rgb(uiBut *from_but, } } -static void ui_colorpicker_rna_cb(bContext *UNUSED(C), void *bt1, void *UNUSED(arg)) +static void ui_colorpicker_rgba_update_cb(bContext *UNUSED(C), void *bt1, void *UNUSED(arg)) { uiBut *but = (uiBut *)bt1; uiPopupBlockHandle *popup = but->block->handle; @@ -270,19 +271,14 @@ static void ui_colorpicker_rna_cb(bContext *UNUSED(C), void *bt1, void *UNUSED(a } } -static void ui_color_wheel_rna_cb(bContext *UNUSED(C), void *bt1, void *UNUSED(arg)) +static void ui_colorpicker_hsv_update_cb(bContext *UNUSED(C), void *bt1, void *UNUSED(arg)) { uiBut *but = (uiBut *)bt1; uiPopupBlockHandle *popup = but->block->handle; float rgb[3]; ColorPicker *cpicker = but->custom_data; - float *hsv = cpicker->color_data; - - ui_color_picker_to_rgb_v(hsv, rgb); - - /* hsv is saved in perceptually linear space so convert back */ - ui_color_picker_to_scene_linear_space(but, rgb); + ui_color_picker_to_rgb_v(cpicker->hsv, rgb); ui_update_color_picker_buts_rgb(but, but->block, cpicker, rgb); if (popup) { @@ -331,12 +327,12 @@ static void ui_colorpicker_hide_reveal(uiBlock *block, enum ePickerType colormod { /* tag buttons */ LISTBASE_FOREACH (uiBut *, bt, &block->buttons) { - if ((bt->func == ui_colorpicker_rna_cb) && (bt->type == UI_BTYPE_NUM_SLIDER) && + if ((bt->func == ui_colorpicker_rgba_update_cb) && (bt->type == UI_BTYPE_NUM_SLIDER) && (bt->rnaindex != 3)) { /* RGB sliders (color circle and alpha are always shown) */ SET_FLAG_FROM_TEST(bt->flag, (colormode != PICKER_TYPE_RGB), UI_HIDDEN); } - else if (bt->func == ui_color_wheel_rna_cb) { + else if (bt->func == ui_colorpicker_hsv_update_cb) { /* HSV sliders */ SET_FLAG_FROM_TEST(bt->flag, (colormode != PICKER_TYPE_HSV), UI_HIDDEN); } @@ -386,7 +382,7 @@ static void ui_colorpicker_circle(uiBlock *block, 0.0, 0, TIP_("Color")); - UI_but_func_set(bt, ui_colorpicker_rna_cb, bt, NULL); + UI_but_func_set(bt, ui_colorpicker_rgba_update_cb, bt, NULL); bt->custom_data = cpicker; /* value */ @@ -408,7 +404,7 @@ static void ui_colorpicker_circle(uiBlock *block, 0, "Lightness"); hsv_but->gradient_type = UI_GRAD_L_ALT; - UI_but_func_set(&hsv_but->but, ui_colorpicker_rna_cb, &hsv_but->but, NULL); + UI_but_func_set(&hsv_but->but, ui_colorpicker_rgba_update_cb, &hsv_but->but, NULL); } else { hsv_but = (uiButHSVCube *)uiDefButR_prop(block, @@ -428,7 +424,7 @@ static void ui_colorpicker_circle(uiBlock *block, 0, TIP_("Value")); hsv_but->gradient_type = UI_GRAD_V_ALT; - UI_but_func_set(&hsv_but->but, ui_colorpicker_rna_cb, &hsv_but->but, NULL); + UI_but_func_set(&hsv_but->but, ui_colorpicker_rgba_update_cb, &hsv_but->but, NULL); } hsv_but->but.custom_data = cpicker; } @@ -461,7 +457,7 @@ static void ui_colorpicker_square(uiBlock *block, 0, TIP_("Color")); hsv_but->gradient_type = type; - UI_but_func_set(&hsv_but->but, ui_colorpicker_rna_cb, &hsv_but->but, NULL); + UI_but_func_set(&hsv_but->but, ui_colorpicker_rgba_update_cb, &hsv_but->but, NULL); hsv_but->but.custom_data = cpicker; /* value */ @@ -482,7 +478,7 @@ static void ui_colorpicker_square(uiBlock *block, 0, TIP_("Value")); hsv_but->gradient_type = type + 3; - UI_but_func_set(&hsv_but->but, ui_colorpicker_rna_cb, &hsv_but->but, NULL); + UI_but_func_set(&hsv_but->but, ui_colorpicker_rgba_update_cb, &hsv_but->but, NULL); hsv_but->but.custom_data = cpicker; } @@ -497,7 +493,6 @@ static void ui_block_colorpicker(uiBlock *block, uiBut *from_but, float rgba[4], float softmin, softmax, hardmin, hardmax, step, precision; int yco; ColorPicker *cpicker = ui_block_colorpicker_create(block); - float *hsv = cpicker->color_data; PointerRNA *ptr = &from_but->rnapoin; PropertyRNA *prop = from_but->rnaprop; @@ -513,8 +508,9 @@ static void ui_block_colorpicker(uiBlock *block, uiBut *from_but, float rgba[4], float rgb_perceptual[3]; copy_v3_v3(rgb_perceptual, rgba); + ui_rgb_to_color_picker_v(rgba, cpicker->hsv); ui_scene_linear_to_color_picker_space(from_but, rgb_perceptual); - ui_rgb_to_color_picker_v(rgb_perceptual, hsv); + ui_rgb_to_color_picker_v(rgb_perceptual, cpicker->color_data); if (cpicker->is_init == false) { copy_v3_v3(cpicker->color_data_init, cpicker->color_data); cpicker->is_init = true; @@ -639,7 +635,7 @@ static void ui_block_colorpicker(uiBlock *block, uiBut *from_but, float rgba[4], 0, 3, TIP_("Red")); - UI_but_func_set(bt, ui_colorpicker_rna_cb, bt, NULL); + UI_but_func_set(bt, ui_colorpicker_rgba_update_cb, bt, NULL); bt->custom_data = cpicker; bt = uiDefButR_prop(block, UI_BTYPE_NUM_SLIDER, @@ -657,7 +653,7 @@ static void ui_block_colorpicker(uiBlock *block, uiBut *from_but, float rgba[4], 0, 3, TIP_("Green")); - UI_but_func_set(bt, ui_colorpicker_rna_cb, bt, NULL); + UI_but_func_set(bt, ui_colorpicker_rgba_update_cb, bt, NULL); bt->custom_data = cpicker; bt = uiDefButR_prop(block, UI_BTYPE_NUM_SLIDER, @@ -675,7 +671,7 @@ static void ui_block_colorpicker(uiBlock *block, uiBut *from_but, float rgba[4], 0, 3, TIP_("Blue")); - UI_but_func_set(bt, ui_colorpicker_rna_cb, bt, NULL); + UI_but_func_set(bt, ui_colorpicker_rgba_update_cb, bt, NULL); bt->custom_data = cpicker; /* Could use: @@ -693,14 +689,14 @@ static void ui_block_colorpicker(uiBlock *block, uiBut *from_but, float rgba[4], yco, butwidth, UI_UNIT_Y, - hsv, + cpicker->hsv, 0.0, 1.0, 10, 3, TIP_("Hue")); UI_but_flag_disable(bt, UI_BUT_UNDO); - UI_but_func_set(bt, ui_color_wheel_rna_cb, bt, hsv); + UI_but_func_set(bt, ui_colorpicker_hsv_update_cb, bt, NULL); bt->custom_data = cpicker; bt = uiDefButF(block, UI_BTYPE_NUM_SLIDER, @@ -710,14 +706,14 @@ static void ui_block_colorpicker(uiBlock *block, uiBut *from_but, float rgba[4], yco -= UI_UNIT_Y, butwidth, UI_UNIT_Y, - hsv + 1, + cpicker->hsv + 1, 0.0, 1.0, 10, 3, TIP_("Saturation")); UI_but_flag_disable(bt, UI_BUT_UNDO); - UI_but_func_set(bt, ui_color_wheel_rna_cb, bt, hsv); + UI_but_func_set(bt, ui_colorpicker_hsv_update_cb, bt, NULL); bt->custom_data = cpicker; if (U.color_picker_type == USER_CP_CIRCLE_HSL) { bt = uiDefButF(block, @@ -728,7 +724,7 @@ static void ui_block_colorpicker(uiBlock *block, uiBut *from_but, float rgba[4], yco -= UI_UNIT_Y, butwidth, UI_UNIT_Y, - hsv + 2, + cpicker->hsv + 2, 0.0, 1.0, 10, @@ -744,7 +740,7 @@ static void ui_block_colorpicker(uiBlock *block, uiBut *from_but, float rgba[4], yco -= UI_UNIT_Y, butwidth, UI_UNIT_Y, - hsv + 2, + cpicker->hsv + 2, 0.0, softmax, 10, @@ -754,7 +750,7 @@ static void ui_block_colorpicker(uiBlock *block, uiBut *from_but, float rgba[4], UI_but_flag_disable(bt, UI_BUT_UNDO); bt->hardmax = hardmax; /* not common but rgb may be over 1.0 */ - UI_but_func_set(bt, ui_color_wheel_rna_cb, bt, hsv); + UI_but_func_set(bt, ui_colorpicker_hsv_update_cb, bt, NULL); bt->custom_data = cpicker; UI_block_align_end(block); @@ -776,7 +772,7 @@ static void ui_block_colorpicker(uiBlock *block, uiBut *from_but, float rgba[4], 0, 3, TIP_("Alpha")); - UI_but_func_set(bt, ui_colorpicker_rna_cb, bt, NULL); + UI_but_func_set(bt, ui_colorpicker_rgba_update_cb, bt, NULL); bt->custom_data = cpicker; } else { -- cgit v1.2.3 From b10d8e330e529abb1cb017312b46a33ede24a8d0 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Thu, 17 Dec 2020 19:39:39 +0100 Subject: Cleanup: renaming and code deduplication for color space clarity in picker Ref T68926 --- .../blender/editors/interface/interface_handlers.c | 48 +++--- .../blender/editors/interface/interface_intern.h | 17 +-- .../interface/interface_region_color_picker.c | 161 +++++++++++---------- .../blender/editors/interface/interface_widgets.c | 26 ++-- 4 files changed, 129 insertions(+), 123 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 72ed2cc0933..08e71e0cfd0 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -5861,7 +5861,7 @@ static int ui_do_but_COLOR(bContext *C, uiBut *but, uiHandleButtonData *data, co if (ELEM(event->type, MOUSEPAN, WHEELDOWNMOUSE, WHEELUPMOUSE) && event->ctrl) { ColorPicker *cpicker = but->custom_data; float hsv_static[3] = {0.0f}; - float *hsv = cpicker ? cpicker->color_data : hsv_static; + float *hsv = cpicker ? cpicker->hsv_perceptual : hsv_static; float col[3]; ui_but_v3_get(but, col); @@ -6089,7 +6089,7 @@ static bool ui_numedit_but_HSVCUBE(uiBut *but, { const uiButHSVCube *hsv_but = (uiButHSVCube *)but; ColorPicker *cpicker = but->custom_data; - float *hsv = cpicker->color_data; + float *hsv = cpicker->hsv_perceptual; float rgb[3]; float x, y; float mx_fl, my_fl; @@ -6107,7 +6107,7 @@ static bool ui_numedit_but_HSVCUBE(uiBut *but, #endif ui_but_v3_get(but, rgb); - ui_scene_linear_to_color_picker_space(but, rgb); + ui_scene_linear_to_perceptual_space(but, rgb); ui_rgb_to_color_picker_HSVCUBE_compat_v(hsv_but, rgb, hsv); @@ -6120,7 +6120,7 @@ static bool ui_numedit_but_HSVCUBE(uiBut *but, /* calculate original hsv again */ copy_v3_v3(rgb, data->origvec); - ui_scene_linear_to_color_picker_space(but, rgb); + ui_scene_linear_to_perceptual_space(but, rgb); copy_v3_v3(hsvo, hsv); @@ -6183,7 +6183,7 @@ static bool ui_numedit_but_HSVCUBE(uiBut *but, } ui_color_picker_to_rgb_HSVCUBE_v(hsv_but, hsv, rgb); - ui_color_picker_to_scene_linear_space(but, rgb); + ui_perceptual_to_scene_linear_space(but, rgb); /* clamp because with color conversion we can exceed range T34295. */ if (hsv_but->gradient_type == UI_GRAD_V_ALT) { @@ -6206,13 +6206,13 @@ static void ui_ndofedit_but_HSVCUBE(uiButHSVCube *hsv_but, const bool shift) { ColorPicker *cpicker = hsv_but->but.custom_data; - float *hsv = cpicker->color_data; + float *hsv = cpicker->hsv_perceptual; const float hsv_v_max = max_ff(hsv[2], hsv_but->but.softmax); float rgb[3]; const float sensitivity = (shift ? 0.15f : 0.3f) * ndof->dt; ui_but_v3_get(&hsv_but->but, rgb); - ui_scene_linear_to_color_picker_space(&hsv_but->but, rgb); + ui_scene_linear_to_perceptual_space(&hsv_but->but, rgb); ui_rgb_to_color_picker_HSVCUBE_compat_v(hsv_but, rgb, hsv); switch (hsv_but->gradient_type) { @@ -6261,7 +6261,7 @@ static void ui_ndofedit_but_HSVCUBE(uiButHSVCube *hsv_but, hsv_clamp_v(hsv, hsv_v_max); ui_color_picker_to_rgb_HSVCUBE_v(hsv_but, hsv, rgb); - ui_color_picker_to_scene_linear_space(&hsv_but->but, rgb); + ui_perceptual_to_scene_linear_space(&hsv_but->but, rgb); copy_v3_v3(data->vec, rgb); ui_but_v3_set(&hsv_but->but, data->vec); @@ -6318,7 +6318,7 @@ static int ui_do_but_HSVCUBE( float rgb[3], def_hsv[3]; float def[4]; ColorPicker *cpicker = but->custom_data; - float *hsv = cpicker->color_data; + float *hsv = cpicker->hsv_perceptual; RNA_property_float_get_default_array(&but->rnapoin, but->rnaprop, def); ui_rgb_to_color_picker_HSVCUBE_v(hsv_but, def, def_hsv); @@ -6374,7 +6374,7 @@ static bool ui_numedit_but_HSVCIRCLE(uiBut *but, { const bool changed = true; ColorPicker *cpicker = but->custom_data; - float *hsv = cpicker->color_data; + float *hsv = cpicker->hsv_perceptual; float mx_fl, my_fl; ui_mouse_scale_warp(data, mx, my, &mx_fl, &my_fl, shift); @@ -6400,8 +6400,8 @@ static bool ui_numedit_but_HSVCIRCLE(uiBut *but, float rgb[3]; ui_but_v3_get(but, rgb); - ui_scene_linear_to_color_picker_space(but, rgb); - ui_rgb_to_color_picker_compat_v(rgb, hsv); + ui_scene_linear_to_perceptual_space(but, rgb); + ui_color_picker_rgb_to_hsv_compat(rgb, hsv); /* exception, when using color wheel in 'locked' value state: * allow choosing a hue for black values, by giving a tiny increment */ @@ -6428,8 +6428,8 @@ static bool ui_numedit_but_HSVCIRCLE(uiBut *but, /* calculate original hsv again */ copy_v3_v3(hsvo, hsv); copy_v3_v3(rgbo, data->origvec); - ui_scene_linear_to_color_picker_space(but, rgbo); - ui_rgb_to_color_picker_compat_v(rgbo, hsvo); + ui_scene_linear_to_perceptual_space(but, rgbo); + ui_color_picker_rgb_to_hsv_compat(rgbo, hsvo); /* and original position */ ui_hsvcircle_pos_from_vals(cpicker, &rect, hsvo, &xpos, &ypos); @@ -6448,7 +6448,7 @@ static bool ui_numedit_but_HSVCIRCLE(uiBut *but, ui_color_snap_hue(snap, &hsv[0]); } - ui_color_picker_to_rgb_v(hsv, rgb); + ui_color_picker_hsv_to_rgb(hsv, rgb); if ((cpicker->use_luminosity_lock)) { if (!is_zero_v3(rgb)) { @@ -6456,7 +6456,7 @@ static bool ui_numedit_but_HSVCIRCLE(uiBut *but, } } - ui_color_picker_to_scene_linear_space(but, rgb); + ui_perceptual_to_scene_linear_space(but, rgb); ui_but_v3_set(but, rgb); data->draglastx = mx; @@ -6473,14 +6473,14 @@ static void ui_ndofedit_but_HSVCIRCLE(uiBut *but, const bool shift) { ColorPicker *cpicker = but->custom_data; - float *hsv = cpicker->color_data; + float *hsv = cpicker->hsv_perceptual; float rgb[3]; float phi, r /*, sqr */ /* UNUSED */, v[2]; const float sensitivity = (shift ? 0.06f : 0.3f) * ndof->dt; ui_but_v3_get(but, rgb); - ui_scene_linear_to_color_picker_space(but, rgb); - ui_rgb_to_color_picker_compat_v(rgb, hsv); + ui_scene_linear_to_perceptual_space(but, rgb); + ui_color_picker_rgb_to_hsv_compat(rgb, hsv); /* Convert current color on hue/sat disc to circular coordinates phi, r */ phi = fmodf(hsv[0] + 0.25f, 1.0f) * -2.0f * (float)M_PI; @@ -6530,7 +6530,7 @@ static void ui_ndofedit_but_HSVCIRCLE(uiBut *but, hsv_clamp_v(hsv, FLT_MAX); - ui_color_picker_to_rgb_v(hsv, data->vec); + ui_color_picker_hsv_to_rgb(hsv, data->vec); if (cpicker->use_luminosity_lock) { if (!is_zero_v3(data->vec)) { @@ -6538,7 +6538,7 @@ static void ui_ndofedit_but_HSVCIRCLE(uiBut *but, } } - ui_color_picker_to_scene_linear_space(but, data->vec); + ui_perceptual_to_scene_linear_space(but, data->vec); ui_but_v3_set(but, data->vec); } #endif /* WITH_INPUT_NDOF */ @@ -6547,7 +6547,7 @@ static int ui_do_but_HSVCIRCLE( bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event) { ColorPicker *cpicker = but->custom_data; - float *hsv = cpicker->color_data; + float *hsv = cpicker->hsv_perceptual; int mx = event->x; int my = event->y; ui_window_to_block(data->region, block, &mx, &my); @@ -6594,10 +6594,10 @@ static int ui_do_but_HSVCIRCLE( def = MEM_callocN(sizeof(float) * len, "reset_defaults - float"); RNA_property_float_get_default_array(&but->rnapoin, but->rnaprop, def); - ui_color_picker_to_rgb_v(def, def_hsv); + ui_color_picker_hsv_to_rgb(def, def_hsv); ui_but_v3_get(but, rgb); - ui_rgb_to_color_picker_compat_v(rgb, hsv); + ui_color_picker_rgb_to_hsv_compat(rgb, hsv); def_hsv[0] = hsv[0]; def_hsv[2] = hsv[2]; diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index 8f894d0c4bb..a35d9d5d336 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -382,15 +382,15 @@ typedef struct ColorPicker { /** Color in HSV or HSL, in color picking color space. Used for HSV cube, * circle and slider widgets. The color picking space is perceptually * linear for intuitive editing. */ - float color_data[3]; + float hsv_perceptual[3]; /** Initial color data (to detect changes). */ - float color_data_init[3]; + float hsv_perceptual_init[3]; bool is_init; /** HSV or HSL color in scene linear color space value used for number * buttons. This is scene linear so that there is a clear correspondence * to the scene linear RGB values. */ - float hsv[3]; + float hsv_scene_linear[3]; /** Cubic saturation for the color wheel. */ bool use_color_cubic; @@ -743,15 +743,14 @@ struct uiPopupBlockHandle { /* exposed as public API in UI_interface.h */ /* interface_region_color_picker.c */ -void ui_rgb_to_color_picker_compat_v(const float rgb[3], float r_cp[3]); -void ui_rgb_to_color_picker_v(const float rgb[3], float r_cp[3]); -void ui_color_picker_to_rgb_v(const float r_cp[3], float rgb[3]); -void ui_color_picker_to_rgb(float r_cp0, float r_cp1, float r_cp2, float *r, float *g, float *b); +void ui_color_picker_rgb_to_hsv_compat(const float rgb[3], float r_cp[3]); +void ui_color_picker_rgb_to_hsv(const float rgb[3], float r_cp[3]); +void ui_color_picker_hsv_to_rgb(const float r_cp[3], float rgb[3]); bool ui_but_is_color_gamma(uiBut *but); -void ui_scene_linear_to_color_picker_space(uiBut *but, float rgb[3]); -void ui_color_picker_to_scene_linear_space(uiBut *but, float rgb[3]); +void ui_scene_linear_to_perceptual_space(uiBut *but, float rgb[3]); +void ui_perceptual_to_scene_linear_space(uiBut *but, float rgb[3]); uiBlock *ui_block_func_COLOR(struct bContext *C, uiPopupBlockHandle *handle, void *arg_but); ColorPicker *ui_block_colorpicker_create(struct uiBlock *block); diff --git a/source/blender/editors/interface/interface_region_color_picker.c b/source/blender/editors/interface/interface_region_color_picker.c index cbf3dbf393d..82028d4e595 100644 --- a/source/blender/editors/interface/interface_region_color_picker.c +++ b/source/blender/editors/interface/interface_region_color_picker.c @@ -77,8 +77,10 @@ static void ui_color_picker_rgb_round(float rgb[3]) } } -void ui_rgb_to_color_picker_compat_v(const float rgb[3], float r_cp[3]) +void ui_color_picker_rgb_to_hsv_compat(const float rgb[3], float r_cp[3]) { + /* Convert RGB to HSV, remaining as compatible as possible with the existing + * r_hsv value (for example when value goes to zero, preserve the hue). */ switch (U.color_picker_type) { case USER_CP_CIRCLE_HSL: rgb_to_hsl_compat_v(rgb, r_cp); @@ -89,7 +91,7 @@ void ui_rgb_to_color_picker_compat_v(const float rgb[3], float r_cp[3]) } } -void ui_rgb_to_color_picker_v(const float rgb[3], float r_cp[3]) +void ui_color_picker_rgb_to_hsv(const float rgb[3], float r_cp[3]) { switch (U.color_picker_type) { case USER_CP_CIRCLE_HSL: @@ -101,7 +103,7 @@ void ui_rgb_to_color_picker_v(const float rgb[3], float r_cp[3]) } } -void ui_color_picker_to_rgb_v(const float r_cp[3], float rgb[3]) +void ui_color_picker_hsv_to_rgb(const float r_cp[3], float rgb[3]) { switch (U.color_picker_type) { case USER_CP_CIRCLE_HSL: @@ -113,18 +115,6 @@ void ui_color_picker_to_rgb_v(const float r_cp[3], float rgb[3]) } } -void ui_color_picker_to_rgb(float r_cp0, float r_cp1, float r_cp2, float *r, float *g, float *b) -{ - switch (U.color_picker_type) { - case USER_CP_CIRCLE_HSL: - hsl_to_rgb(r_cp0, r_cp1, r_cp2, r, g, b); - break; - default: - hsv_to_rgb(r_cp0, r_cp1, r_cp2, r, g, b); - break; - } -} - /* Returns true if the button is for a color with gamma baked in, * or if it's a color picker for such a button. */ bool ui_but_is_color_gamma(uiBut *but) @@ -138,7 +128,7 @@ bool ui_but_is_color_gamma(uiBut *but) return but->block->is_color_gamma_picker; } -void ui_scene_linear_to_color_picker_space(uiBut *but, float rgb[3]) +void ui_scene_linear_to_perceptual_space(uiBut *but, float rgb[3]) { /* Map to color picking space for HSV values and HSV cube/circle, * assuming it is more perceptually linear than the scene linear @@ -149,7 +139,7 @@ void ui_scene_linear_to_color_picker_space(uiBut *but, float rgb[3]) } } -void ui_color_picker_to_scene_linear_space(uiBut *but, float rgb[3]) +void ui_perceptual_to_scene_linear_space(uiBut *but, float rgb[3]) { if (!ui_but_is_color_gamma(but)) { IMB_colormanagement_color_picking_to_scene_linear_v3(rgb); @@ -163,16 +153,46 @@ void ui_color_picker_to_scene_linear_space(uiBut *but, float rgb[3]) /** \name Color Picker * \{ */ +static void ui_color_picker_update_hsv(ColorPicker *cpicker, + uiBut *from_but, + const float rgb_scene_linear[3]) +{ + /* Convert from RGB to HSV in scene linear space color for number editing. */ + if (cpicker->is_init == false) { + ui_color_picker_rgb_to_hsv(rgb_scene_linear, cpicker->hsv_scene_linear); + } + else { + ui_color_picker_rgb_to_hsv_compat(rgb_scene_linear, cpicker->hsv_scene_linear); + } + + /* Convert from RGB to HSV in perceptually linear space for picker widgets. */ + float rgb_perceptual[3]; + copy_v3_v3(rgb_perceptual, rgb_scene_linear); + if (from_but) { + ui_scene_linear_to_perceptual_space(from_but, rgb_perceptual); + } + + if (cpicker->is_init == false) { + ui_color_picker_rgb_to_hsv(rgb_perceptual, cpicker->hsv_perceptual); + copy_v3_v3(cpicker->hsv_perceptual_init, cpicker->hsv_perceptual); + } + else { + ui_color_picker_rgb_to_hsv_compat(rgb_perceptual, cpicker->hsv_perceptual); + } + + cpicker->is_init = true; +} + /* for picker, while editing hsv */ void ui_but_hsv_set(uiBut *but) { - float col[3]; + float rgb_perceptual[3]; ColorPicker *cpicker = but->custom_data; - float *hsv = cpicker->color_data; + float *hsv_perceptual = cpicker->hsv_perceptual; - ui_color_picker_to_rgb_v(hsv, col); + ui_color_picker_hsv_to_rgb(hsv_perceptual, rgb_perceptual); - ui_but_v3_set(but, col); + ui_but_v3_set(but, rgb_perceptual); } /* Updates all buttons who share the same color picker as the one passed @@ -180,18 +200,9 @@ void ui_but_hsv_set(uiBut *but) static void ui_update_color_picker_buts_rgb(uiBut *from_but, uiBlock *block, ColorPicker *cpicker, - const float rgb[3]) + const float rgb_scene_linear[3]) { - /* Convert from RGB to HSV in scene linear space color for numeric editing. */ - ui_rgb_to_color_picker_compat_v(rgb, cpicker->hsv); - - /* Convert from RGB to HSV in perceptually linear space for picker widgets. */ - float tmp[3]; - copy_v3_v3(tmp, rgb); - if (from_but) { - ui_scene_linear_to_color_picker_space(from_but, tmp); - } - ui_rgb_to_color_picker_compat_v(tmp, cpicker->color_data); + ui_color_picker_update_hsv(cpicker, from_but, rgb_scene_linear); /* this updates button strings, * is hackish... but button pointers are on stack of caller function */ @@ -201,7 +212,7 @@ static void ui_update_color_picker_buts_rgb(uiBut *from_but, } if (bt->rnaprop) { - ui_but_v3_set(bt, rgb); + ui_but_v3_set(bt, rgb_scene_linear); /* original button that created the color picker already does undo * push, so disable it on RNA buttons in the color picker block */ @@ -214,7 +225,7 @@ static void ui_update_color_picker_buts_rgb(uiBut *from_but, /* Hex code is assumed to be in sRGB space * (coming from other applications, web, etc) */ - copy_v3_v3(rgb_hex, rgb); + copy_v3_v3(rgb_hex, rgb_scene_linear); if (from_but && !ui_but_is_color_gamma(from_but)) { IMB_colormanagement_scene_linear_to_srgb_v3(rgb_hex); ui_color_picker_rgb_round(rgb_hex); @@ -227,25 +238,25 @@ static void ui_update_color_picker_buts_rgb(uiBut *from_but, } else if (bt->str[1] == ' ') { if (bt->str[0] == 'R') { - ui_but_value_set(bt, rgb[0]); + ui_but_value_set(bt, rgb_scene_linear[0]); } else if (bt->str[0] == 'G') { - ui_but_value_set(bt, rgb[1]); + ui_but_value_set(bt, rgb_scene_linear[1]); } else if (bt->str[0] == 'B') { - ui_but_value_set(bt, rgb[2]); + ui_but_value_set(bt, rgb_scene_linear[2]); } else if (bt->str[0] == 'H') { - ui_but_value_set(bt, cpicker->hsv[0]); + ui_but_value_set(bt, cpicker->hsv_scene_linear[0]); } else if (bt->str[0] == 'S') { - ui_but_value_set(bt, cpicker->hsv[1]); + ui_but_value_set(bt, cpicker->hsv_scene_linear[1]); } else if (bt->str[0] == 'V') { - ui_but_value_set(bt, cpicker->hsv[2]); + ui_but_value_set(bt, cpicker->hsv_scene_linear[2]); } else if (bt->str[0] == 'L') { - ui_but_value_set(bt, cpicker->hsv[2]); + ui_but_value_set(bt, cpicker->hsv_scene_linear[2]); } } @@ -259,11 +270,11 @@ static void ui_colorpicker_rgba_update_cb(bContext *UNUSED(C), void *bt1, void * uiPopupBlockHandle *popup = but->block->handle; PropertyRNA *prop = but->rnaprop; PointerRNA ptr = but->rnapoin; - float rgb[4]; + float rgb_scene_linear[4]; if (prop) { - RNA_property_float_get_array(&ptr, prop, rgb); - ui_update_color_picker_buts_rgb(but, but->block, but->custom_data, rgb); + RNA_property_float_get_array(&ptr, prop, rgb_scene_linear); + ui_update_color_picker_buts_rgb(but, but->block, but->custom_data, rgb_scene_linear); } if (popup) { @@ -275,11 +286,11 @@ static void ui_colorpicker_hsv_update_cb(bContext *UNUSED(C), void *bt1, void *U { uiBut *but = (uiBut *)bt1; uiPopupBlockHandle *popup = but->block->handle; - float rgb[3]; + float rgb_scene_linear[3]; ColorPicker *cpicker = but->custom_data; - ui_color_picker_to_rgb_v(cpicker->hsv, rgb); - ui_update_color_picker_buts_rgb(but, but->block, cpicker, rgb); + ui_color_picker_hsv_to_rgb(cpicker->hsv_scene_linear, rgb_scene_linear); + ui_update_color_picker_buts_rgb(but, but->block, cpicker, rgb_scene_linear); if (popup) { popup->menuretval = UI_RETURN_UPDATE; @@ -317,7 +328,7 @@ static void ui_popup_close_cb(bContext *UNUSED(C), void *bt1, void *UNUSED(arg)) if (popup) { ColorPicker *cpicker = but->custom_data; BLI_assert(cpicker->is_init); - popup->menuretval = (equals_v3v3(cpicker->color_data, cpicker->color_data_init) ? + popup->menuretval = (equals_v3v3(cpicker->hsv_perceptual, cpicker->hsv_perceptual_init) ? UI_RETURN_CANCEL : UI_RETURN_OK); } @@ -483,7 +494,10 @@ static void ui_colorpicker_square(uiBlock *block, } /* a HS circle, V slider, rgb/hsv/hex sliders */ -static void ui_block_colorpicker(uiBlock *block, uiBut *from_but, float rgba[4], bool show_picker) +static void ui_block_colorpicker(uiBlock *block, + uiBut *from_but, + float rgba_scene_linear[4], + bool show_picker) { /* ePickerType */ static char colormode = 1; @@ -500,21 +514,13 @@ static void ui_block_colorpicker(uiBlock *block, uiBut *from_but, float rgba[4], butwidth = width - 1.5f * UI_UNIT_X; /* sneaky way to check for alpha */ - rgba[3] = FLT_MAX; + rgba_scene_linear[3] = FLT_MAX; RNA_property_float_ui_range(ptr, prop, &softmin, &softmax, &step, &precision); RNA_property_float_range(ptr, prop, &hardmin, &hardmax); - RNA_property_float_get_array(ptr, prop, rgba); + RNA_property_float_get_array(ptr, prop, rgba_scene_linear); - float rgb_perceptual[3]; - copy_v3_v3(rgb_perceptual, rgba); - ui_rgb_to_color_picker_v(rgba, cpicker->hsv); - ui_scene_linear_to_color_picker_space(from_but, rgb_perceptual); - ui_rgb_to_color_picker_v(rgb_perceptual, cpicker->color_data); - if (cpicker->is_init == false) { - copy_v3_v3(cpicker->color_data_init, cpicker->color_data); - cpicker->is_init = true; - } + ui_color_picker_update_hsv(cpicker, from_but, rgba_scene_linear); /* when the softmax isn't defined in the RNA, * using very large numbers causes sRGB/linear round trip to fail. */ @@ -689,7 +695,7 @@ static void ui_block_colorpicker(uiBlock *block, uiBut *from_but, float rgba[4], yco, butwidth, UI_UNIT_Y, - cpicker->hsv, + cpicker->hsv_scene_linear, 0.0, 1.0, 10, @@ -706,7 +712,7 @@ static void ui_block_colorpicker(uiBlock *block, uiBut *from_but, float rgba[4], yco -= UI_UNIT_Y, butwidth, UI_UNIT_Y, - cpicker->hsv + 1, + cpicker->hsv_scene_linear + 1, 0.0, 1.0, 10, @@ -724,7 +730,7 @@ static void ui_block_colorpicker(uiBlock *block, uiBut *from_but, float rgba[4], yco -= UI_UNIT_Y, butwidth, UI_UNIT_Y, - cpicker->hsv + 2, + cpicker->hsv_scene_linear + 2, 0.0, 1.0, 10, @@ -740,7 +746,7 @@ static void ui_block_colorpicker(uiBlock *block, uiBut *from_but, float rgba[4], yco -= UI_UNIT_Y, butwidth, UI_UNIT_Y, - cpicker->hsv + 2, + cpicker->hsv_scene_linear + 2, 0.0, softmax, 10, @@ -755,7 +761,7 @@ static void ui_block_colorpicker(uiBlock *block, uiBut *from_but, float rgba[4], UI_block_align_end(block); - if (rgba[3] != FLT_MAX) { + if (rgba_scene_linear[3] != FLT_MAX) { bt = uiDefButR_prop(block, UI_BTYPE_NUM_SLIDER, 0, @@ -776,14 +782,14 @@ static void ui_block_colorpicker(uiBlock *block, uiBut *from_but, float rgba[4], bt->custom_data = cpicker; } else { - rgba[3] = 1.0f; + rgba_scene_linear[3] = 1.0f; } /* Hex color is in sRGB space. */ float rgb_hex[3]; uchar rgb_hex_uchar[3]; - copy_v3_v3(rgb_hex, rgba); + copy_v3_v3(rgb_hex, rgba_scene_linear); if (!ui_but_is_color_gamma(from_but)) { IMB_colormanagement_scene_linear_to_srgb_v3(rgb_hex); @@ -846,21 +852,22 @@ static int ui_colorpicker_small_wheel_cb(const bContext *UNUSED(C), LISTBASE_FOREACH (uiBut *, but, &block->buttons) { if (but->type == UI_BTYPE_HSVCUBE && but->active == NULL) { uiPopupBlockHandle *popup = block->handle; - float rgb[3]; ColorPicker *cpicker = but->custom_data; - float *hsv = cpicker->color_data; + float *hsv_perceptual = cpicker->hsv_perceptual; - ui_but_v3_get(but, rgb); - ui_scene_linear_to_color_picker_space(but, rgb); - ui_rgb_to_color_picker_compat_v(rgb, hsv); + float rgb_perceptual[3]; + ui_but_v3_get(but, rgb_perceptual); + ui_scene_linear_to_perceptual_space(but, rgb_perceptual); + ui_color_picker_rgb_to_hsv_compat(rgb_perceptual, hsv_perceptual); - hsv[2] = clamp_f(hsv[2] + add, 0.0f, 1.0f); + hsv_perceptual[2] = clamp_f(hsv_perceptual[2] + add, 0.0f, 1.0f); - ui_color_picker_to_rgb_v(hsv, rgb); - ui_color_picker_to_scene_linear_space(but, rgb); - ui_but_v3_set(but, rgb); + float rgb_scene_linear[3]; + ui_color_picker_hsv_to_rgb(hsv_perceptual, rgb_scene_linear); + ui_perceptual_to_scene_linear_space(but, rgb_scene_linear); + ui_but_v3_set(but, rgb_scene_linear); - ui_update_color_picker_buts_rgb(but, block, cpicker, rgb); + ui_update_color_picker_buts_rgb(but, block, cpicker, rgb_scene_linear); if (popup) { popup->menuretval = UI_RETURN_UPDATE; } diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index 9c7b112855f..e92c32bb1bd 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -2906,12 +2906,12 @@ static void ui_draw_but_HSVCIRCLE(uiBut *but, const uiWidgetColors *wcol, const const bool is_color_gamma = ui_but_is_color_gamma(but); /* Initialize for compatibility. */ - copy_v3_v3(hsv, cpicker->color_data); + copy_v3_v3(hsv, cpicker->hsv_perceptual); /* Compute current hue. */ ui_but_v3_get(but, rgb); - ui_scene_linear_to_color_picker_space(but, rgb); - ui_rgb_to_color_picker_compat_v(rgb, hsv); + ui_scene_linear_to_perceptual_space(but, rgb); + ui_color_picker_rgb_to_hsv_compat(rgb, hsv); CLAMP(hsv[2], 0.0f, 1.0f); /* for display only */ @@ -2928,8 +2928,8 @@ static void ui_draw_but_HSVCIRCLE(uiBut *but, const uiWidgetColors *wcol, const } const float hsv_center[3] = {0.0f, 0.0f, hsv[2]}; - ui_color_picker_to_rgb_v(hsv_center, rgb_center); - ui_color_picker_to_scene_linear_space(but, rgb_center); + ui_color_picker_hsv_to_rgb(hsv_center, rgb_center); + ui_perceptual_to_scene_linear_space(but, rgb_center); if (!is_color_gamma) { ui_block_cm_to_display_space_v3(but->block, rgb_center); @@ -2956,8 +2956,8 @@ static void ui_draw_but_HSVCIRCLE(uiBut *but, const uiWidgetColors *wcol, const rect, centx + co * radius, centy + si * radius, hsv_ang, hsv_ang + 1); hsv_ang[2] = hsv[2]; - ui_color_picker_to_rgb_v(hsv_ang, rgb_ang); - ui_color_picker_to_scene_linear_space(but, rgb_ang); + ui_color_picker_hsv_to_rgb(hsv_ang, rgb_ang); + ui_perceptual_to_scene_linear_space(but, rgb_ang); if (!is_color_gamma) { ui_block_cm_to_display_space_v3(but->block, rgb_ang); @@ -2987,10 +2987,10 @@ static void ui_draw_but_HSVCIRCLE(uiBut *but, const uiWidgetColors *wcol, const GPU_line_smooth(false); /* cursor */ - copy_v3_v3(hsv, cpicker->color_data); + copy_v3_v3(hsv, cpicker->hsv_perceptual); ui_but_v3_get(but, rgb); - ui_scene_linear_to_color_picker_space(but, rgb); - ui_rgb_to_color_picker_compat_v(rgb, hsv); + ui_scene_linear_to_perceptual_space(but, rgb); + ui_color_picker_rgb_to_hsv_compat(rgb, hsv); float xpos, ypos; ui_hsvcircle_pos_from_vals(cpicker, rect, hsv, &xpos, &ypos); @@ -3212,14 +3212,14 @@ static void ui_draw_but_HSVCUBE(uiBut *but, const rcti *rect) float rgb[3]; float x = 0.0f, y = 0.0f; ColorPicker *cpicker = but->custom_data; - float *hsv = cpicker->color_data; + float *hsv = cpicker->hsv_perceptual; float hsv_n[3]; /* Initialize for compatibility. */ copy_v3_v3(hsv_n, hsv); ui_but_v3_get(but, rgb); - ui_scene_linear_to_color_picker_space(but, rgb); + ui_scene_linear_to_perceptual_space(but, rgb); rgb_to_hsv_compat_v(rgb, hsv_n); ui_draw_gradient(rect, hsv_n, hsv_but->gradient_type, 1.0f); @@ -3251,7 +3251,7 @@ static void ui_draw_but_HSV_v(uiBut *but, const rcti *rect) float rgb[3], hsv[3], v; ui_but_v3_get(but, rgb); - ui_scene_linear_to_color_picker_space(but, rgb); + ui_scene_linear_to_perceptual_space(but, rgb); if (hsv_but->gradient_type == UI_GRAD_L_ALT) { rgb_to_hsl_v(rgb, hsv); -- cgit v1.2.3 From 23233fcf056e42958972d129ba526c0a103cf179 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Thu, 17 Dec 2020 14:43:01 -0600 Subject: Cleanup: Use abstraction for attribute math node input Since creating the attribute node, a helper function has been added to automatically get the input attribute or a constant value, depending on the "input type" values for the node. This commit replaces the specific implementation of that behavior with the new helper function. The versioning is necessary since the node now has a "storage" struct. --- source/blender/blenloader/intern/versioning_290.c | 21 ++++++++ source/blender/makesdna/DNA_node_types.h | 16 ++++-- source/blender/makesrna/intern/rna_nodetree.c | 24 +++------ .../geometry/nodes/node_geo_attribute_math.cc | 57 +++++++++------------- 4 files changed, 62 insertions(+), 56 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenloader/intern/versioning_290.c b/source/blender/blenloader/intern/versioning_290.c index 4df681002a0..9aded9137ec 100644 --- a/source/blender/blenloader/intern/versioning_290.c +++ b/source/blender/blenloader/intern/versioning_290.c @@ -1428,5 +1428,26 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain) */ { /* Keep this block, even when empty. */ + + FOREACH_NODETREE_BEGIN (bmain, ntree, id) { + if (ntree->type == NTREE_GEOMETRY) { + LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { + if (node->type == GEO_NODE_ATTRIBUTE_MATH && node->storage == NULL) { + const int old_use_attibute_a = (1 << 0); + const int old_use_attibute_b = (1 << 1); + NodeAttributeMath *data = MEM_callocN(sizeof(NodeAttributeMath), "NodeAttributeMath"); + data->operation = NODE_MATH_ADD; + data->input_type_a = (node->custom2 & old_use_attibute_a) ? + GEO_NODE_ATTRIBUTE_INPUT_ATTRIBUTE : + GEO_NODE_ATTRIBUTE_INPUT_FLOAT; + data->input_type_b = (node->custom2 & old_use_attibute_b) ? + GEO_NODE_ATTRIBUTE_INPUT_ATTRIBUTE : + GEO_NODE_ATTRIBUTE_INPUT_FLOAT; + node->storage = data; + } + } + } + } + FOREACH_NODETREE_END; } } diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index f33d40b1b5d..af91ab4f257 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -1085,6 +1085,17 @@ typedef struct NodeAttributeCompare { char _pad[5]; } NodeAttributeCompare; +typedef struct NodeAttributeMath { + /* e.g. NODE_MATH_ADD. */ + uint8_t operation; + + /* GeometryNodeAttributeInputMode */ + uint8_t input_type_a; + uint8_t input_type_b; + + char _pad[5]; +} NodeAttributeMath; + typedef struct NodeAttributeMix { /* e.g. MA_RAMP_BLEND. */ uint8_t blend_type; @@ -1499,11 +1510,6 @@ typedef enum GeometryNodeTriangulateQuads { GEO_NODE_TRIANGULATE_QUAD_SHORTEDGE = 3, } GeometryNodeTriangulateQuads; -typedef enum GeometryNodeUseAttributeFlag { - GEO_NODE_USE_ATTRIBUTE_A = (1 << 0), - GEO_NODE_USE_ATTRIBUTE_B = (1 << 1), -} GeometryNodeUseAttributeFlag; - typedef enum GeometryNodePointInstanceType { GEO_NODE_POINT_INSTANCE_TYPE_OBJECT = 0, GEO_NODE_POINT_INSTANCE_TYPE_COLLECTION = 1, diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 9a627ef6e70..e474c610bf7 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -426,18 +426,6 @@ static const EnumPropertyItem rna_node_geometry_triangulate_ngon_method_items[] {0, NULL, 0, NULL, NULL}, }; -static const EnumPropertyItem rna_node_geometry_attribute_input_a_items[] = { - {0, "FLOAT", 0, "Float", ""}, - {GEO_NODE_USE_ATTRIBUTE_A, "ATTRIBUTE", 0, "Attribute", ""}, - {0, NULL, 0, NULL, NULL}, -}; - -static const EnumPropertyItem rna_node_geometry_attribute_input_b_items[] = { - {0, "FLOAT", 0, "Float", ""}, - {GEO_NODE_USE_ATTRIBUTE_B, "ATTRIBUTE", 0, "Attribute", ""}, - {0, NULL, 0, NULL, NULL}, -}; - # define ITEM_ATTRIBUTE \ { \ GEO_NODE_ATTRIBUTE_INPUT_ATTRIBUTE, "ATTRIBUTE", 0, "Attribute", "" \ @@ -8454,8 +8442,10 @@ static void def_geo_attribute_math(StructRNA *srna) { PropertyRNA *prop; + RNA_def_struct_sdna_from(srna, "NodeAttributeMath", "storage"); + prop = RNA_def_property(srna, "operation", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_sdna(prop, NULL, "custom1"); + RNA_def_property_enum_sdna(prop, NULL, "operation"); RNA_def_property_enum_items(prop, rna_enum_node_math_items); RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_GeometryNodeAttributeMath_operation_itemf"); RNA_def_property_enum_default(prop, NODE_MATH_ADD); @@ -8463,14 +8453,14 @@ static void def_geo_attribute_math(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); prop = RNA_def_property(srna, "input_type_a", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_bitflag_sdna(prop, NULL, "custom2"); - RNA_def_property_enum_items(prop, rna_node_geometry_attribute_input_a_items); + RNA_def_property_enum_bitflag_sdna(prop, NULL, "input_type_a"); + RNA_def_property_enum_items(prop, rna_node_geometry_attribute_input_type_items_float); RNA_def_property_ui_text(prop, "Input Type A", ""); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); prop = RNA_def_property(srna, "input_type_b", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_bitflag_sdna(prop, NULL, "custom2"); - RNA_def_property_enum_items(prop, rna_node_geometry_attribute_input_b_items); + RNA_def_property_enum_bitflag_sdna(prop, NULL, "input_type_b"); + RNA_def_property_enum_items(prop, rna_node_geometry_attribute_input_type_items_float); RNA_def_property_ui_text(prop, "Input Type B", ""); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_math.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_math.cc index 455b2a79394..a7b71fa614f 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_attribute_math.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_math.cc @@ -30,9 +30,9 @@ static bNodeSocketTemplate geo_node_attribute_math_in[] = { {SOCK_GEOMETRY, N_("Geometry")}, - {SOCK_STRING, N_("Attribute A")}, + {SOCK_STRING, N_("A")}, {SOCK_FLOAT, N_("A"), 0.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX}, - {SOCK_STRING, N_("Attribute B")}, + {SOCK_STRING, N_("B")}, {SOCK_FLOAT, N_("B"), 0.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX}, {SOCK_STRING, N_("Result")}, {-1, ""}, @@ -45,27 +45,27 @@ static bNodeSocketTemplate geo_node_attribute_math_out[] = { static void geo_node_attribute_math_init(bNodeTree *UNUSED(tree), bNode *node) { - node->custom1 = NODE_MATH_ADD; - node->custom2 = GEO_NODE_USE_ATTRIBUTE_A | GEO_NODE_USE_ATTRIBUTE_B; + NodeAttributeMath *data = (NodeAttributeMath *)MEM_callocN(sizeof(NodeAttributeMath), + "NodeAttributeMath"); + + data->operation = NODE_MATH_ADD; + data->input_type_a = GEO_NODE_ATTRIBUTE_INPUT_ATTRIBUTE; + data->input_type_b = GEO_NODE_ATTRIBUTE_INPUT_ATTRIBUTE; + node->storage = data; } +namespace blender::nodes { + static void geo_node_attribute_math_update(bNodeTree *UNUSED(ntree), bNode *node) { - bNodeSocket *sock_attribute_a = (bNodeSocket *)BLI_findlink(&node->inputs, 1); - bNodeSocket *sock_float_a = sock_attribute_a->next; - bNodeSocket *sock_attribute_b = sock_float_a->next; - bNodeSocket *sock_float_b = sock_attribute_b->next; + NodeAttributeMath *node_storage = (NodeAttributeMath *)node->storage; - GeometryNodeUseAttributeFlag flag = static_cast(node->custom2); - - nodeSetSocketAvailability(sock_attribute_a, flag & GEO_NODE_USE_ATTRIBUTE_A); - nodeSetSocketAvailability(sock_attribute_b, flag & GEO_NODE_USE_ATTRIBUTE_B); - nodeSetSocketAvailability(sock_float_a, !(flag & GEO_NODE_USE_ATTRIBUTE_A)); - nodeSetSocketAvailability(sock_float_b, !(flag & GEO_NODE_USE_ATTRIBUTE_B)); + update_attribute_input_socket_availabilities( + *node, "A", (GeometryNodeAttributeInputMode)node_storage->input_type_a); + update_attribute_input_socket_availabilities( + *node, "B", (GeometryNodeAttributeInputMode)node_storage->input_type_b); } -namespace blender::nodes { - static void do_math_operation(const FloatReadAttribute &input_a, const FloatReadAttribute &input_b, FloatWriteAttribute result, @@ -112,23 +112,10 @@ static void attribute_math_calc(GeometryComponent &component, const GeoNodeExecP return; } - GeometryNodeUseAttributeFlag flag = static_cast(node.custom2); - - auto get_input_attribute = [&](GeometryNodeUseAttributeFlag use_flag, - StringRef attribute_socket_identifier, - StringRef value_socket_identifier) { - if (flag & use_flag) { - const std::string attribute_name = params.get_input( - attribute_socket_identifier); - return component.attribute_try_get_for_read(attribute_name, result_domain, result_type); - } - const float value = params.get_input(value_socket_identifier); - return component.attribute_get_constant_for_read(result_domain, result_type, &value); - }; - - ReadAttributePtr attribute_a = get_input_attribute(GEO_NODE_USE_ATTRIBUTE_A, "Attribute A", "A"); - ReadAttributePtr attribute_b = get_input_attribute(GEO_NODE_USE_ATTRIBUTE_B, "Attribute B", "B"); - + ReadAttributePtr attribute_a = params.get_input_attribute( + "A", component, result_domain, result_type, nullptr); + ReadAttributePtr attribute_b = params.get_input_attribute( + "B", component, result_domain, result_type, nullptr); if (!attribute_a || !attribute_b) { /* Attribute wasn't found. */ return; @@ -161,7 +148,9 @@ void register_node_type_geo_attribute_math() geo_node_type_base(&ntype, GEO_NODE_ATTRIBUTE_MATH, "Attribute Math", NODE_CLASS_ATTRIBUTE, 0); node_type_socket_templates(&ntype, geo_node_attribute_math_in, geo_node_attribute_math_out); ntype.geometry_node_execute = blender::nodes::geo_node_attribute_math_exec; - node_type_update(&ntype, geo_node_attribute_math_update); + node_type_update(&ntype, blender::nodes::geo_node_attribute_math_update); node_type_init(&ntype, geo_node_attribute_math_init); + node_type_storage( + &ntype, "NodeAttributeCompare", node_free_standard_storage, node_copy_standard_storage); nodeRegisterType(&ntype); } -- cgit v1.2.3 From ef17fb2715a3f24cd5cddd6725bfef4858f87617 Mon Sep 17 00:00:00 2001 From: Yevgeny Makarov Date: Thu, 17 Dec 2020 19:06:21 -0600 Subject: UI: Don't use abbreviations in label text Expand abbreviations for words like "Bright" (instead of "Brightness"), "Premul", "Lib", "Dir", etc. Differential Revision: https://developer.blender.org/D9862 --- source/blender/editors/gpencil/gpencil_vertex_ops.c | 2 +- source/blender/editors/object/object_relations.c | 2 +- .../blender/editors/sculpt_paint/paint_vertex_color_ops.c | 2 +- source/blender/editors/space_file/file_ops.c | 2 +- source/blender/editors/space_userpref/userpref_ops.c | 4 ++-- source/blender/editors/space_view3d/view3d_edit.c | 2 +- source/blender/makesrna/intern/rna_nodetree.c | 12 ++++++------ source/blender/makesrna/intern/rna_particle.c | 14 +++++++------- source/blender/makesrna/intern/rna_scene.c | 2 +- source/blender/makesrna/intern/rna_userdef.c | 2 +- source/blender/windowmanager/intern/wm_operator_props.c | 2 +- 11 files changed, 23 insertions(+), 23 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/gpencil/gpencil_vertex_ops.c b/source/blender/editors/gpencil/gpencil_vertex_ops.c index 90b2c1c3895..b212872b607 100644 --- a/source/blender/editors/gpencil/gpencil_vertex_ops.c +++ b/source/blender/editors/gpencil/gpencil_vertex_ops.c @@ -237,7 +237,7 @@ void GPENCIL_OT_vertex_color_brightness_contrast(wmOperatorType *ot) PropertyRNA *prop; /* identifiers */ - ot->name = "Vertex Paint Bright/Contrast"; + ot->name = "Vertex Paint Brightness/Contrast"; ot->idname = "GPENCIL_OT_vertex_color_brightness_contrast"; ot->description = "Adjust vertex color brightness/contrast"; diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index 5caa7c71e83..ee9ef192d18 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -484,7 +484,7 @@ void OBJECT_OT_proxy_make(wmOperatorType *ot) DummyRNA_DEFAULT_items, 0, "Proxy Object", - "Name of lib-linked/collection object to make a proxy for"); + "Name of library-linked/collection object to make a proxy for"); RNA_def_enum_funcs(prop, proxy_collection_object_itemf); RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE); ot->prop = prop; diff --git a/source/blender/editors/sculpt_paint/paint_vertex_color_ops.c b/source/blender/editors/sculpt_paint/paint_vertex_color_ops.c index b831687ca67..96d22fe4a21 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex_color_ops.c +++ b/source/blender/editors/sculpt_paint/paint_vertex_color_ops.c @@ -401,7 +401,7 @@ void PAINT_OT_vertex_color_brightness_contrast(wmOperatorType *ot) PropertyRNA *prop; /* identifiers */ - ot->name = "Vertex Paint Bright/Contrast"; + ot->name = "Vertex Paint Brightness/Contrast"; ot->idname = "PAINT_OT_vertex_color_brightness_contrast"; ot->description = "Adjust vertex color brightness/contrast"; diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c index 3730174a6c7..88dd82bb9ea 100644 --- a/source/blender/editors/space_file/file_ops.c +++ b/source/blender/editors/space_file/file_ops.c @@ -967,7 +967,7 @@ void FILE_OT_select_bookmark(wmOperatorType *ot) ot->poll = ED_operator_file_active; /* properties */ - prop = RNA_def_string(ot->srna, "dir", NULL, FILE_MAXDIR, "Dir", ""); + prop = RNA_def_string(ot->srna, "dir", NULL, FILE_MAXDIR, "Directory", ""); RNA_def_property_flag(prop, PROP_SKIP_SAVE); } diff --git a/source/blender/editors/space_userpref/userpref_ops.c b/source/blender/editors/space_userpref/userpref_ops.c index ee23cde78c2..f05d6df9944 100644 --- a/source/blender/editors/space_userpref/userpref_ops.c +++ b/source/blender/editors/space_userpref/userpref_ops.c @@ -93,7 +93,7 @@ static int preferences_autoexec_add_exec(bContext *UNUSED(C), wmOperator *UNUSED static void PREFERENCES_OT_autoexec_path_add(wmOperatorType *ot) { - ot->name = "Add Autoexec Path"; + ot->name = "Add Auto-Execution Path"; ot->idname = "PREFERENCES_OT_autoexec_path_add"; ot->description = "Add path to exclude from auto-execution"; @@ -121,7 +121,7 @@ static int preferences_autoexec_remove_exec(bContext *UNUSED(C), wmOperator *op) static void PREFERENCES_OT_autoexec_path_remove(wmOperatorType *ot) { - ot->name = "Remove Autoexec Path"; + ot->name = "Remove Auto-Execution Path"; ot->idname = "PREFERENCES_OT_autoexec_path_remove"; ot->description = "Remove path to exclude from auto-execution"; diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 9429da342a6..ebfa4f6d9af 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -4708,7 +4708,7 @@ static int viewpersportho_exec(bContext *C, wmOperator *UNUSED(op)) void VIEW3D_OT_view_persportho(wmOperatorType *ot) { /* identifiers */ - ot->name = "View Persp/Ortho"; + ot->name = "View Perspective/Orthographic"; ot->description = "Switch the current view from perspective/orthographic projection"; ot->idname = "VIEW3D_OT_view_persportho"; diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index e474c610bf7..d624154ddc7 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -5798,7 +5798,7 @@ static void def_cmp_alpha_over(StructRNA *srna) /* XXX: Tooltip */ prop = RNA_def_property(srna, "use_premultiply", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "custom1", 1); - RNA_def_property_ui_text(prop, "Convert Premul", ""); + RNA_def_property_ui_text(prop, "Convert Premultiplied", ""); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); RNA_def_struct_sdna_from(srna, "NodeTwoFloats", "storage"); @@ -5806,7 +5806,7 @@ static void def_cmp_alpha_over(StructRNA *srna) prop = RNA_def_property(srna, "premul", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "x"); RNA_def_property_range(prop, 0.0f, 1.0f); - RNA_def_property_ui_text(prop, "Premul", "Mix Factor"); + RNA_def_property_ui_text(prop, "Premultiplied", "Mix Factor"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); } @@ -6622,7 +6622,7 @@ static void def_cmp_brightcontrast(StructRNA *srna) prop = RNA_def_property(srna, "use_premultiply", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "custom1", 1); - RNA_def_property_ui_text(prop, "Convert Premul", "Keep output image premultiplied alpha"); + RNA_def_property_ui_text(prop, "Convert Premultiplied", "Keep output image premultiplied alpha"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); } @@ -6682,7 +6682,7 @@ static void def_cmp_channel_matte(StructRNA *srna) static const EnumPropertyItem algorithm_items[] = { {0, "SINGLE", 0, "Single", "Limit by single channel"}, - {1, "MAX", 0, "Max", "Limit by max of other channels"}, + {1, "MAX", 0, "Max", "Limit by maximum of other channels"}, {0, NULL, 0, NULL, NULL}, }; @@ -7077,8 +7077,8 @@ static void def_cmp_premul_key(StructRNA *srna) PropertyRNA *prop; static const EnumPropertyItem type_items[] = { - {0, "STRAIGHT_TO_PREMUL", 0, "Straight to Premul", ""}, - {1, "PREMUL_TO_STRAIGHT", 0, "Premul to Straight", ""}, + {0, "STRAIGHT_TO_PREMUL", 0, "To Premultiplied", "Convert straight to premultiplied"}, + {1, "PREMUL_TO_STRAIGHT", 0, "To Straight", "Convert premultiplied to straight"}, {0, NULL, 0, NULL, NULL}, }; diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c index 5fa93ec3f04..3e40d382237 100644 --- a/source/blender/makesrna/intern/rna_particle.c +++ b/source/blender/makesrna/intern/rna_particle.c @@ -3298,48 +3298,48 @@ static void rna_def_particle_settings(BlenderRNA *brna) RNA_def_property_float_sdna(prop, NULL, "rough1"); RNA_def_property_range(prop, 0.0f, 100000.0f); RNA_def_property_ui_range(prop, 0.0f, 10.0f, 0.1, 3); - RNA_def_property_ui_text(prop, "Rough1", "Amount of location dependent rough"); + RNA_def_property_ui_text(prop, "Roughness 1", "Amount of location dependent roughness"); RNA_def_property_update(prop, 0, "rna_Particle_redo_child"); prop = RNA_def_property(srna, "roughness_1_size", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "rough1_size"); RNA_def_property_range(prop, 0.01f, 100000.0f); RNA_def_property_ui_range(prop, 0.01f, 10.0f, 0.1, 3); - RNA_def_property_ui_text(prop, "Size1", "Size of location dependent rough"); + RNA_def_property_ui_text(prop, "Size 1", "Size of location dependent roughness"); RNA_def_property_update(prop, 0, "rna_Particle_redo_child"); prop = RNA_def_property(srna, "roughness_2", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "rough2"); RNA_def_property_range(prop, 0.0f, 100000.0f); RNA_def_property_ui_range(prop, 0.0f, 10.0f, 0.1, 3); - RNA_def_property_ui_text(prop, "Rough2", "Amount of random rough"); + RNA_def_property_ui_text(prop, "Roughness 2", "Amount of random roughness"); RNA_def_property_update(prop, 0, "rna_Particle_redo_child"); prop = RNA_def_property(srna, "roughness_2_size", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "rough2_size"); RNA_def_property_range(prop, 0.01f, 100000.0f); RNA_def_property_ui_range(prop, 0.01f, 10.0f, 0.1, 3); - RNA_def_property_ui_text(prop, "Size2", "Size of random rough"); + RNA_def_property_ui_text(prop, "Size 2", "Size of random roughness"); RNA_def_property_update(prop, 0, "rna_Particle_redo_child"); prop = RNA_def_property(srna, "roughness_2_threshold", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "rough2_thres"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text( - prop, "Threshold", "Amount of particles left untouched by random rough"); + prop, "Threshold", "Amount of particles left untouched by random roughness"); RNA_def_property_update(prop, 0, "rna_Particle_redo_child"); prop = RNA_def_property(srna, "roughness_endpoint", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "rough_end"); RNA_def_property_range(prop, 0.0f, 100000.0f); RNA_def_property_ui_range(prop, 0.0f, 10.0f, 0.1, 3); - RNA_def_property_ui_text(prop, "Rough Endpoint", "Amount of end point rough"); + RNA_def_property_ui_text(prop, "Roughness Endpoint", "Amount of endpoint roughness"); RNA_def_property_update(prop, 0, "rna_Particle_redo_child"); prop = RNA_def_property(srna, "roughness_end_shape", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "rough_end_shape"); RNA_def_property_range(prop, 0.0f, 10.0f); - RNA_def_property_ui_text(prop, "Shape", "Shape of end point rough"); + RNA_def_property_ui_text(prop, "Shape", "Shape of endpoint roughness"); RNA_def_property_update(prop, 0, "rna_Particle_redo_child"); prop = RNA_def_property(srna, "use_roughness_curve", PROP_BOOLEAN, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 7cae88d292b..84222347425 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -4240,7 +4240,7 @@ void rna_def_view_layer_common(StructRNA *srna, const bool scene) prop = RNA_def_property(srna, "use_ztransp", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "layflag", SCE_LAY_ZTRA); RNA_def_property_ui_text( - prop, "ZTransp", "Render Z-Transparent faces in this Layer (on top of Solid and Halos)"); + prop, "Z-Transparent", "Render Z-transparent faces in this layer (on top of Solid and Halos)"); if (scene) { RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); } diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 7a285df235a..ebcff76aa36 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -6331,7 +6331,7 @@ void RNA_def_userdef(BlenderRNA *brna) prop = RNA_def_property(srna, "autoexec_paths", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "autoexec_paths", NULL); RNA_def_property_struct_type(prop, "PathCompare"); - RNA_def_property_ui_text(prop, "Autoexec Paths", ""); + RNA_def_property_ui_text(prop, "Auto-Execution Paths", ""); rna_def_userdef_autoexec_path_collection(brna, prop); /* nested structs */ diff --git a/source/blender/windowmanager/intern/wm_operator_props.c b/source/blender/windowmanager/intern/wm_operator_props.c index fa658a5cdec..8dfe26fbf79 100644 --- a/source/blender/windowmanager/intern/wm_operator_props.c +++ b/source/blender/windowmanager/intern/wm_operator_props.c @@ -434,7 +434,7 @@ void WM_operator_properties_select_operation_simple(wmOperatorType *ot) void WM_operator_properties_select_walk_direction(wmOperatorType *ot) { static const EnumPropertyItem direction_items[] = { - {UI_SELECT_WALK_UP, "UP", 0, "Prev", ""}, + {UI_SELECT_WALK_UP, "UP", 0, "Previous", ""}, {UI_SELECT_WALK_DOWN, "DOWN", 0, "Next", ""}, {UI_SELECT_WALK_LEFT, "LEFT", 0, "Left", ""}, {UI_SELECT_WALK_RIGHT, "RIGHT", 0, "Right", ""}, -- cgit v1.2.3 From 7cbcfb7f492d027d415326d3b100803e949ce84a Mon Sep 17 00:00:00 2001 From: Nathan Craddock Date: Thu, 17 Dec 2020 19:59:49 -0700 Subject: Cleanup: Use LISTBASE_FOREACH macro in outliner code No functional changes. --- source/blender/editors/space_outliner/outliner_draw.c | 4 +--- source/blender/editors/space_outliner/outliner_edit.c | 7 +++---- 2 files changed, 4 insertions(+), 7 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c index 6364fbc0a87..657ada874ea 100644 --- a/source/blender/editors/space_outliner/outliner_draw.c +++ b/source/blender/editors/space_outliner/outliner_draw.c @@ -2928,8 +2928,6 @@ static void outliner_draw_iconrow(bContext *C, /* closed tree element */ static void outliner_set_coord_tree_element(TreeElement *te, int startx, int starty) { - TreeElement *ten; - /* closed items may be displayed in row of parent, don't change their coordinate! */ if ((te->flag & TE_ICONROW) == 0 && (te->flag & TE_ICONROW_MERGED) == 0) { te->xs = 0; @@ -2937,7 +2935,7 @@ static void outliner_set_coord_tree_element(TreeElement *te, int startx, int sta te->xend = 0; } - for (ten = te->subtree.first; ten; ten = ten->next) { + LISTBASE_FOREACH (TreeElement *, ten, &te->subtree) { outliner_set_coord_tree_element(ten, startx + UI_UNIT_X, starty); } } diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c index a1ff6193cd0..1cb98e704f2 100644 --- a/source/blender/editors/space_outliner/outliner_edit.c +++ b/source/blender/editors/space_outliner/outliner_edit.c @@ -1253,8 +1253,7 @@ static void outliner_set_coordinates_element_recursive(SpaceOutliner *space_outl *starty -= UI_UNIT_Y; if (TSELEM_OPEN(tselem, space_outliner)) { - TreeElement *ten; - for (ten = te->subtree.first; ten; ten = ten->next) { + LISTBASE_FOREACH (TreeElement *, ten, &te->subtree) { outliner_set_coordinates_element_recursive(space_outliner, ten, startx + UI_UNIT_X, starty); } } @@ -1753,7 +1752,7 @@ static void tree_element_to_path(TreeElement *te, { ListBase hierarchy = {NULL, NULL}; LinkData *ld; - TreeElement *tem, *temnext, *temsub; + TreeElement *tem, *temnext; TreeStoreElem *tse /* , *tsenext */ /* UNUSED */; PointerRNA *ptr, *nextptr; PropertyRNA *prop; @@ -1823,7 +1822,7 @@ static void tree_element_to_path(TreeElement *te, /* otherwise use index */ int index = 0; - for (temsub = tem->subtree.first; temsub; temsub = temsub->next, index++) { + LISTBASE_FOREACH (TreeElement *, temsub, &tem->subtree) { if (temsub == temnext) { break; } -- cgit v1.2.3 From 7d25139eaf4ab11e69d6adb2f436489eca016b64 Mon Sep 17 00:00:00 2001 From: Nathan Craddock Date: Thu, 17 Dec 2020 16:28:24 -0700 Subject: Fix T82960: Inaccurate selection on collapsed outliner rows After rB15083d9e1 the outliner tree is not rebuilt after expanding or collapsing rows. Because the tree is no longer rebuilt the positions and flags of the elements are not cleared when collapsing a row. This caused hover highlights and selections on the collapsed child icons to be incorrect in many cases. For example, only the direct children of a collapsed element are drawn inline. If any grandchild elements had been previously icon row flagged they would continue to be evaluated as icon row elements despite being hidden. In this case the x coordinates of the child and grandchild would overlap causing selection to appear erratic. Now the flags for inline row icons are explicitly cleared, which was previously only done because the tree was rebuilt on collapsing rows. --- source/blender/editors/space_outliner/outliner_draw.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source/blender') diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c index 657ada874ea..d2381cf30db 100644 --- a/source/blender/editors/space_outliner/outliner_draw.c +++ b/source/blender/editors/space_outliner/outliner_draw.c @@ -2845,6 +2845,7 @@ static void outliner_draw_iconrow(bContext *C, LISTBASE_FOREACH (TreeElement *, te, lb) { TreeStoreElem *tselem = TREESTORE(te); + te->flag &= ~(TE_ICONROW | TE_ICONROW_MERGED); /* object hierarchy always, further constrained on level */ if (level < 1 || (tselem->type == 0 && te->idcode == ID_OB)) { -- cgit v1.2.3 From 9dbc014af7a257f347e746740e5276bdaa885e38 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Thu, 17 Dec 2020 22:53:47 -0600 Subject: Cleanup: Various clang tidy warnings There are more in the new mesh fairing code and in the poisson distribution code, this commit doesn't fix those. --- source/blender/blenkernel/intern/mesh_fair.cc | 22 +++++++++++----------- source/blender/blenloader/intern/versioning_290.c | 1 + .../node_geo_point_distribute_poisson_disk.cc | 2 +- source/blender/sequencer/intern/utils.c | 2 -- 4 files changed, 13 insertions(+), 14 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/intern/mesh_fair.cc b/source/blender/blenkernel/intern/mesh_fair.cc index 527288d06cf..ccd1434b60b 100644 --- a/source/blender/blenkernel/intern/mesh_fair.cc +++ b/source/blender/blenkernel/intern/mesh_fair.cc @@ -156,7 +156,7 @@ class FairingContext { loop_weight); } - void fair_vertices_ex(bool *affected, + void fair_vertices_ex(const bool *affected, const int order, VertexWeight *vertex_weight, LoopWeight *loop_weight) @@ -240,15 +240,15 @@ class MeshFairingContext : public FairingContext { } } - ~MeshFairingContext() + ~MeshFairingContext() override { MEM_SAFE_FREE(vlmap_); MEM_SAFE_FREE(vlmap_mem_); } - virtual void adjacents_coords_from_loop(const int loop, - float r_adj_next[3], - float r_adj_prev[3]) override + void adjacents_coords_from_loop(const int loop, + float r_adj_next[3], + float r_adj_prev[3]) override { const int vert = mloop_[loop].v; const MPoly *p = &mpoly_[loop_to_poly_map_[loop]]; @@ -257,7 +257,7 @@ class MeshFairingContext : public FairingContext { copy_v3_v3(r_adj_prev, co_[ME_POLY_LOOP_PREV(mloop_, p, corner)->v]); } - virtual int other_vertex_index_from_loop(const int loop, const unsigned int v) override + int other_vertex_index_from_loop(const int loop, const unsigned int v) override { MEdge *e = &medge_[mloop_[loop].e]; if (e->v1 == v) { @@ -318,21 +318,21 @@ class BMeshFairingContext : public FairingContext { } } - ~BMeshFairingContext() + ~BMeshFairingContext() override { MEM_SAFE_FREE(vlmap_); MEM_SAFE_FREE(vlmap_mem_); } - virtual void adjacents_coords_from_loop(const int loop, - float r_adj_next[3], - float r_adj_prev[3]) override + void adjacents_coords_from_loop(const int loop, + float r_adj_next[3], + float r_adj_prev[3]) override { copy_v3_v3(r_adj_next, bmloop_[loop]->next->v->co); copy_v3_v3(r_adj_prev, bmloop_[loop]->prev->v->co); } - virtual int other_vertex_index_from_loop(const int loop, const unsigned int v) override + int other_vertex_index_from_loop(const int loop, const unsigned int v) override { BMLoop *l = bmloop_[loop]; BMVert *bmvert = BM_vert_at_index(bm, v); diff --git a/source/blender/blenloader/intern/versioning_290.c b/source/blender/blenloader/intern/versioning_290.c index 9aded9137ec..86293f273b3 100644 --- a/source/blender/blenloader/intern/versioning_290.c +++ b/source/blender/blenloader/intern/versioning_290.c @@ -686,6 +686,7 @@ static void do_versions_291_fcurve_handles_limit(FCurve *fcu) } } +/* NOLINTNEXTLINE: readability-function-size */ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain) { UNUSED_VARS(fd); diff --git a/source/blender/nodes/geometry/nodes/node_geo_point_distribute_poisson_disk.cc b/source/blender/nodes/geometry/nodes/node_geo_point_distribute_poisson_disk.cc index 47764efa15d..e53157cb5f8 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_point_distribute_poisson_disk.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_point_distribute_poisson_disk.cc @@ -27,8 +27,8 @@ #include "node_geometry_util.hh" +#include #include -#include namespace blender::nodes { diff --git a/source/blender/sequencer/intern/utils.c b/source/blender/sequencer/intern/utils.c index ab0b65dba7f..a76cfb76e62 100644 --- a/source/blender/sequencer/intern/utils.c +++ b/source/blender/sequencer/intern/utils.c @@ -578,6 +578,4 @@ void SEQ_set_scale_to_fit(const Sequence *seq, transform->scale_y = 1.0f; break; } - - return; } -- cgit v1.2.3 From 095b69361403bacd322172d6293b0faeee40b44e Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Thu, 17 Dec 2020 23:35:05 -0600 Subject: Outliner: Set active modifier on click The outliner already expands the panel for the modifier you click on, this just extends that idea to also set it active, which is consistent with behavior of active and selected items elsewhere in Blender. --- source/blender/editors/space_outliner/outliner_select.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source/blender') diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c index fa8bce9df6a..658e6adbe33 100644 --- a/source/blender/editors/space_outliner/outliner_select.c +++ b/source/blender/editors/space_outliner/outliner_select.c @@ -1185,6 +1185,7 @@ static void outliner_set_properties_tab(bContext *C, TreeElement *te, TreeStoreE } else { ModifierData *md = (ModifierData *)te->directdata; + BKE_object_modifier_set_active(ob, md); switch ((ModifierType)md->type) { case eModifierType_ParticleSystem: -- cgit v1.2.3 From 4f9e21bdc9772603acc0ba6727da9dd67287ac0f Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Fri, 18 Dec 2020 09:15:55 +0100 Subject: Fix T82591: Performance regression when rendering at very high resolution This patch introduces a partial update of GPUTexture. When rendering a large image the GPUTexture could have been scaled. The old implementation would rescale the image on CPU and create a new GPUTexture. This resulted in flooding the PCI bus. The new solution would only scale and upload the parts of the GPUTexture that has been changed. It does this by keeping track of areas of 256x256 pixels. When something changes the tiles that cover that changes will be rescaled and uploaded the next time the GPUTexture is requested. Test situation: Default Cube, 4 samples, 19200x10800 tile size 512. Blender 2.83.9: 4m27s. Blender 2.91: 20+m (regression) This patch: 1m01s. There is still room for more optimizations: * Reduce the time that an image is locked. ** Use task scheduling to update the tiles of an image. ** Generic optimization of the ImBuf scale method. Maniphest Tasks: T82591 Differential Revision: https://developer.blender.org/D9591 --- source/blender/blenkernel/BKE_image.h | 2 + source/blender/blenkernel/intern/image.c | 4 + source/blender/blenkernel/intern/image_gpu.c | 146 ++++++++++++++++++++---- source/blender/editors/render/render_internal.c | 134 +++++++++++++--------- source/blender/editors/space_image/image_edit.c | 3 + source/blender/makesdna/DNA_image_types.h | 9 +- source/blender/makesrna/intern/rna_image.c | 2 + 7 files changed, 224 insertions(+), 76 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h index 303945dbf64..c51a5f7e5e1 100644 --- a/source/blender/blenkernel/BKE_image.h +++ b/source/blender/blenkernel/BKE_image.h @@ -382,6 +382,8 @@ struct GPUTexture *BKE_image_get_gpu_tilemap(struct Image *image, bool BKE_image_has_gpu_texture_premultiplied_alpha(struct Image *image, struct ImBuf *ibuf); void BKE_image_update_gputexture( struct Image *ima, struct ImageUser *iuser, int x, int y, int w, int h); +void BKE_image_update_gputexture_delayed( + struct Image *ima, struct ImBuf *ibuf, int x, int y, int w, int h); void BKE_image_paint_set_mipmap(struct Main *bmain, bool mipmap); /* Delayed free of OpenGL buffers by main thread */ diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 228aed265cf..d1c6b552d2e 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -190,6 +190,7 @@ static void image_free_data(ID *id) BKE_previewimg_free(&image->preview); BLI_freelistN(&image->tiles); + BLI_freelistN(&image->gpu_refresh_areas); } static void image_foreach_cache(ID *id, @@ -298,6 +299,8 @@ static void image_blend_read_data(BlendDataReader *reader, ID *id) LISTBASE_FOREACH (ImageTile *, tile, &ima->tiles) { tile->ok = IMA_OK; } + ima->gpuflag = 0; + BLI_listbase_clear(&ima->gpu_refresh_areas); } static void image_blend_read_lib(BlendLibReader *UNUSED(reader), ID *id) @@ -3897,6 +3900,7 @@ RenderResult *BKE_image_acquire_renderresult(Scene *scene, Image *ima) } else { rr = BKE_image_get_renderslot(ima, ima->render_slot)->render; + ima->gpuflag |= IMA_GPU_REFRESH; } /* set proper views */ diff --git a/source/blender/blenkernel/intern/image_gpu.c b/source/blender/blenkernel/intern/image_gpu.c index 50138b34fa3..05aa3c89a84 100644 --- a/source/blender/blenkernel/intern/image_gpu.c +++ b/source/blender/blenkernel/intern/image_gpu.c @@ -23,6 +23,7 @@ #include "MEM_guardedalloc.h" +#include "BLI_bitmap.h" #include "BLI_boxpack_2d.h" #include "BLI_linklist.h" #include "BLI_listbase.h" @@ -48,6 +49,16 @@ /* Prototypes. */ static void gpu_free_unused_buffers(void); static void image_free_gpu(Image *ima, const bool immediate); +static void image_update_gputexture_ex( + Image *ima, ImageTile *tile, ImBuf *ibuf, int x, int y, int w, int h); + +/* Internal structs. */ +#define IMA_PARTIAL_REFRESH_TILE_SIZE 256 +typedef struct ImagePartialRefresh { + struct ImagePartialRefresh *next, *prev; + int tile_x; + int tile_y; +} ImagePartialRefresh; /* Is the alpha of the `GPUTexture` for a given image/ibuf premultiplied. */ bool BKE_image_has_gpu_texture_premultiplied_alpha(Image *image, ImBuf *ibuf) @@ -299,19 +310,35 @@ static GPUTexture *image_get_gpu_texture(Image *ima, * the current `pass` and `layer` should be 0. */ short requested_pass = iuser ? iuser->pass : 0; short requested_layer = iuser ? iuser->layer : 0; - short requested_slot = ima->render_slot; - if (ima->gpu_pass != requested_pass || ima->gpu_layer != requested_layer || - ima->gpu_slot != requested_slot) { + if (ima->gpu_pass != requested_pass || ima->gpu_layer != requested_layer) { ima->gpu_pass = requested_pass; ima->gpu_layer = requested_layer; - ima->gpu_slot = requested_slot; ima->gpuflag |= IMA_GPU_REFRESH; } - /* currently, gpu refresh tagging is used by ima sequences */ - if (ima->gpuflag & IMA_GPU_REFRESH) { + /* Check if image has been updated and tagged to be updated (full or partial). */ + ImageTile *tile = BKE_image_get_tile(ima, 0); + if (((ima->gpuflag & IMA_GPU_REFRESH) != 0) || + ((ibuf == NULL || tile == NULL || !tile->ok) && + ((ima->gpuflag & IMA_GPU_PARTIAL_REFRESH) != 0))) { image_free_gpu(ima, true); - ima->gpuflag &= ~IMA_GPU_REFRESH; + BLI_freelistN(&ima->gpu_refresh_areas); + ima->gpuflag &= ~(IMA_GPU_REFRESH | IMA_GPU_PARTIAL_REFRESH); + } + else if (ima->gpuflag & IMA_GPU_PARTIAL_REFRESH) { + BLI_assert(ibuf); + BLI_assert(tile && tile->ok); + ImagePartialRefresh *refresh_area; + while ((refresh_area = BLI_pophead(&ima->gpu_refresh_areas))) { + const int tile_offset_x = refresh_area->tile_x * IMA_PARTIAL_REFRESH_TILE_SIZE; + const int tile_offset_y = refresh_area->tile_y * IMA_PARTIAL_REFRESH_TILE_SIZE; + const int tile_width = MIN2(IMA_PARTIAL_REFRESH_TILE_SIZE, ibuf->x - tile_offset_x); + const int tile_height = MIN2(IMA_PARTIAL_REFRESH_TILE_SIZE, ibuf->y - tile_offset_y); + image_update_gputexture_ex( + ima, tile, ibuf, tile_offset_x, tile_offset_y, tile_width, tile_height); + MEM_freeN(refresh_area); + } + ima->gpuflag &= ~IMA_GPU_PARTIAL_REFRESH; } /* Tag as in active use for garbage collector. */ @@ -328,7 +355,6 @@ static GPUTexture *image_get_gpu_texture(Image *ima, /* Check if we have a valid image. If not, we return a dummy * texture with zero bind-code so we don't keep trying. */ - ImageTile *tile = BKE_image_get_tile(ima, 0); if (tile == NULL || tile->ok == 0) { *tex = image_gpu_texture_error_create(textarget); return *tex; @@ -590,8 +616,8 @@ static void gpu_texture_update_scaled(GPUTexture *tex, } else { /* Partial update with scaling. */ - int limit_w = smaller_power_of_2_limit(full_w); - int limit_h = smaller_power_of_2_limit(full_h); + int limit_w = GPU_texture_width(tex); + int limit_h = GPU_texture_height(tex); ibuf = update_do_scale(rect, rect_float, &x, &y, &w, &h, limit_w, limit_h, full_w, full_h); } @@ -643,7 +669,7 @@ static void gpu_texture_update_from_ibuf( scaled = (ibuf->x != tilesize[0]) || (ibuf->y != tilesize[1]); } else { - scaled = is_over_resolution_limit(ibuf->x, ibuf->y); + scaled = (GPU_texture_width(tex) != ibuf->x) || (GPU_texture_height(tex) != ibuf->y); } if (scaled) { @@ -746,6 +772,22 @@ static void gpu_texture_update_from_ibuf( GPU_texture_unbind(tex); } +static void image_update_gputexture_ex( + Image *ima, ImageTile *tile, ImBuf *ibuf, int x, int y, int w, int h) +{ + GPUTexture *tex = ima->gputexture[TEXTARGET_2D][0]; + /* Check if we need to update the main gputexture. */ + if (tex != NULL && tile == ima->tiles.first) { + gpu_texture_update_from_ibuf(tex, ima, ibuf, NULL, x, y, w, h); + } + + /* Check if we need to update the array gputexture. */ + tex = ima->gputexture[TEXTARGET_2D_ARRAY][0]; + if (tex != NULL) { + gpu_texture_update_from_ibuf(tex, ima, ibuf, tile, x, y, w, h); + } +} + /* Partial update of texture for texture painting. This is often much * quicker than fully updating the texture for high resolution images. */ void BKE_image_update_gputexture(Image *ima, ImageUser *iuser, int x, int y, int w, int h) @@ -757,20 +799,84 @@ void BKE_image_update_gputexture(Image *ima, ImageUser *iuser, int x, int y, int /* Full reload of texture. */ BKE_image_free_gputextures(ima); } + image_update_gputexture_ex(ima, tile, ibuf, x, y, w, h); + BKE_image_release_ibuf(ima, ibuf, NULL); +} - GPUTexture *tex = ima->gputexture[TEXTARGET_2D][0]; - /* Check if we need to update the main gputexture. */ - if (tex != NULL && tile == ima->tiles.first) { - gpu_texture_update_from_ibuf(tex, ima, ibuf, NULL, x, y, w, h); +/* Mark areas on the GPUTexture that needs to be updated. The areas are marked in chunks. + * The next time the GPUTexture is used these tiles will be refreshes. This saves time + * when writing to the same place multiple times This happens for during foreground + * rendering. */ +void BKE_image_update_gputexture_delayed( + struct Image *ima, struct ImBuf *ibuf, int x, int y, int w, int h) +{ + /* Check for full refresh. */ + if (ibuf && x == 0 && y == 0 && w == ibuf->x && h == ibuf->y) { + ima->gpuflag |= IMA_GPU_REFRESH; + } + /* Check if we can promote partial refresh to a full refresh. */ + if ((ima->gpuflag & (IMA_GPU_REFRESH | IMA_GPU_PARTIAL_REFRESH)) == + (IMA_GPU_REFRESH | IMA_GPU_PARTIAL_REFRESH)) { + ima->gpuflag &= ~IMA_GPU_PARTIAL_REFRESH; + BLI_freelistN(&ima->gpu_refresh_areas); + } + /* Image is already marked for complete refresh. */ + if (ima->gpuflag & IMA_GPU_REFRESH) { + return; } - /* Check if we need to update the array gputexture. */ - tex = ima->gputexture[TEXTARGET_2D_ARRAY][0]; - if (tex != NULL) { - gpu_texture_update_from_ibuf(tex, ima, ibuf, tile, x, y, w, h); + /* Schedule the tiles that covers the requested area. */ + const int start_tile_x = x / IMA_PARTIAL_REFRESH_TILE_SIZE; + const int start_tile_y = y / IMA_PARTIAL_REFRESH_TILE_SIZE; + const int end_tile_x = (x + w) / IMA_PARTIAL_REFRESH_TILE_SIZE; + const int end_tile_y = (y + h) / IMA_PARTIAL_REFRESH_TILE_SIZE; + const int num_tiles_x = (end_tile_x + 1) - (start_tile_x); + const int num_tiles_y = (end_tile_y + 1) - (start_tile_y); + const int num_tiles = num_tiles_x * num_tiles_y; + const bool allocate_on_heap = BLI_BITMAP_SIZE(num_tiles) > 16; + BLI_bitmap *requested_tiles = NULL; + if (allocate_on_heap) { + requested_tiles = BLI_BITMAP_NEW(num_tiles, __func__); + } + else { + requested_tiles = BLI_BITMAP_NEW_ALLOCA(num_tiles); } - BKE_image_release_ibuf(ima, ibuf, NULL); + /* Mark the tiles that have already been requested. They don't need to be requested again. */ + int num_tiles_not_scheduled = num_tiles; + LISTBASE_FOREACH (ImagePartialRefresh *, area, &ima->gpu_refresh_areas) { + if (area->tile_x < start_tile_x || area->tile_x > end_tile_x || area->tile_y < start_tile_y || + area->tile_y > end_tile_y) { + continue; + } + int requested_tile_index = (area->tile_x - start_tile_x) + + (area->tile_y - start_tile_y) * num_tiles_x; + BLI_BITMAP_ENABLE(requested_tiles, requested_tile_index); + num_tiles_not_scheduled--; + if (num_tiles_not_scheduled == 0) { + break; + } + } + + /* Schedule the tiles that aren't requested yet. */ + if (num_tiles_not_scheduled) { + int tile_index = 0; + for (int tile_y = start_tile_y; tile_y <= end_tile_y; tile_y++) { + for (int tile_x = start_tile_x; tile_x <= end_tile_x; tile_x++) { + if (!BLI_BITMAP_TEST_BOOL(requested_tiles, tile_index)) { + ImagePartialRefresh *area = MEM_mallocN(sizeof(ImagePartialRefresh), __func__); + area->tile_x = tile_x; + area->tile_y = tile_y; + BLI_addtail(&ima->gpu_refresh_areas, area); + } + tile_index++; + } + } + ima->gpuflag |= IMA_GPU_PARTIAL_REFRESH; + } + if (allocate_on_heap) { + MEM_freeN(requested_tiles); + } } /* these two functions are called on entering and exiting texture paint mode, diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c index a035ee3e342..69c1e887392 100644 --- a/source/blender/editors/render/render_internal.c +++ b/source/blender/editors/render/render_internal.c @@ -29,6 +29,7 @@ #include "BLI_listbase.h" #include "BLI_math.h" +#include "BLI_rect.h" #include "BLI_threads.h" #include "BLI_timecode.h" #include "BLI_utildefines.h" @@ -121,72 +122,90 @@ typedef struct RenderJob { } RenderJob; /* called inside thread! */ -static void image_buffer_rect_update(RenderJob *rj, - RenderResult *rr, - ImBuf *ibuf, - ImageUser *iuser, - volatile rcti *renrect, - const char *viewname) +static bool image_buffer_calc_tile_rect(const RenderResult *rr, + const ImBuf *ibuf, + volatile rcti *renrect, + rcti *r_ibuf_rect, + int *r_offset_x, + int *r_offset_y) { - Scene *scene = rj->scene; - const float *rectf = NULL; - int ymin, ymax, xmin, xmax; - int rymin, rxmin; - int linear_stride, linear_offset_x, linear_offset_y; - ColorManagedViewSettings *view_settings; - ColorManagedDisplaySettings *display_settings; - - if (ibuf->userflags & IB_DISPLAY_BUFFER_INVALID) { - /* The whole image buffer it so be color managed again anyway. */ - return; - } + int tile_y, tile_height, tile_x, tile_width; /* if renrect argument, we only refresh scanlines */ if (renrect) { - /* if (ymax == recty), rendering of layer is ready, + /* if (tile_height == recty), rendering of layer is ready, * we should not draw, other things happen... */ if (rr->renlay == NULL || renrect->ymax >= rr->recty) { - return; + return false; } - /* xmin here is first subrect x coord, xmax defines subrect width */ - xmin = renrect->xmin; - xmax = renrect->xmax - xmin; - if (xmax < 2) { - return; + /* tile_x here is first subrect x coord, tile_width defines subrect width */ + tile_x = renrect->xmin; + tile_width = renrect->xmax - tile_x; + if (tile_width < 2) { + return false; } - ymin = renrect->ymin; - ymax = renrect->ymax - ymin; - if (ymax < 2) { - return; + tile_y = renrect->ymin; + tile_height = renrect->ymax - tile_y; + if (tile_height < 2) { + return false; } renrect->ymin = renrect->ymax; } else { - xmin = ymin = 0; - xmax = rr->rectx; - ymax = rr->recty; + tile_x = tile_y = 0; + tile_width = rr->rectx; + tile_height = rr->recty; } - /* xmin ymin is in tile coords. transform to ibuf */ - rxmin = rr->tilerect.xmin; - if (rxmin >= ibuf->x) { - return; + /* tile_x tile_y is in tile coords. transform to ibuf */ + int offset_x = rr->tilerect.xmin; + if (offset_x >= ibuf->x) { + return false; } - rymin = rr->tilerect.ymin; - if (rymin >= ibuf->y) { - return; + int offset_y = rr->tilerect.ymin; + if (offset_y >= ibuf->y) { + return false; } - if (rxmin + xmax > ibuf->x) { - xmax = ibuf->x - rxmin; + if (offset_x + tile_width > ibuf->x) { + tile_width = ibuf->x - offset_x; } - if (rymin + ymax > ibuf->y) { - ymax = ibuf->y - rymin; + if (offset_y + tile_height > ibuf->y) { + tile_height = ibuf->y - offset_y; } - if (xmax < 1 || ymax < 1) { + if (tile_width < 1 || tile_height < 1) { + return false; + } + + r_ibuf_rect->xmax = tile_x + tile_width; + r_ibuf_rect->ymax = tile_y + tile_height; + r_ibuf_rect->xmin = tile_x; + r_ibuf_rect->ymin = tile_y; + *r_offset_x = offset_x; + *r_offset_y = offset_y; + return true; +} + +static void image_buffer_rect_update(RenderJob *rj, + RenderResult *rr, + ImBuf *ibuf, + ImageUser *iuser, + const rcti *tile_rect, + int offset_x, + int offset_y, + const char *viewname) +{ + Scene *scene = rj->scene; + const float *rectf = NULL; + int linear_stride, linear_offset_x, linear_offset_y; + ColorManagedViewSettings *view_settings; + ColorManagedDisplaySettings *display_settings; + + if (ibuf->userflags & IB_DISPLAY_BUFFER_INVALID) { + /* The whole image buffer is to be color managed again anyway. */ return; } @@ -230,10 +249,10 @@ static void image_buffer_rect_update(RenderJob *rj, return; } - rectf += 4 * (rr->rectx * ymin + xmin); + rectf += 4 * (rr->rectx * tile_rect->ymin + tile_rect->xmin); linear_stride = rr->rectx; - linear_offset_x = rxmin; - linear_offset_y = rymin; + linear_offset_x = offset_x; + linear_offset_y = offset_y; } else { rectf = ibuf->rect_float; @@ -253,10 +272,10 @@ static void image_buffer_rect_update(RenderJob *rj, linear_offset_y, view_settings, display_settings, - rxmin, - rymin, - rxmin + xmax, - rymin + ymax); + offset_x, + offset_y, + offset_x + BLI_rcti_size_x(tile_rect), + offset_y + BLI_rcti_size_y(tile_rect)); } /* ****************************** render invoking ***************** */ @@ -578,8 +597,16 @@ static void image_rect_update(void *rjv, RenderResult *rr, volatile rcti *renrec /* update part of render */ render_image_update_pass_and_layer(rj, rr, &rj->iuser); + rcti tile_rect; + int offset_x; + int offset_y; ibuf = BKE_image_acquire_ibuf(ima, &rj->iuser, &lock); if (ibuf) { + if (!image_buffer_calc_tile_rect(rr, ibuf, renrect, &tile_rect, &offset_x, &offset_y)) { + BKE_image_release_ibuf(ima, ibuf, lock); + return; + } + /* Don't waste time on CPU side color management if * image will be displayed using GLSL. * @@ -589,9 +616,10 @@ static void image_rect_update(void *rjv, RenderResult *rr, volatile rcti *renrec */ if (!rj->supports_glsl_draw || ibuf->channels == 1 || ED_draw_imbuf_method(ibuf) != IMAGE_DRAW_METHOD_GLSL) { - image_buffer_rect_update(rj, rr, ibuf, &rj->iuser, renrect, viewname); + image_buffer_rect_update(rj, rr, ibuf, &rj->iuser, &tile_rect, offset_x, offset_y, viewname); } - ima->gpuflag |= IMA_GPU_REFRESH; + BKE_image_update_gputexture_delayed( + ima, ibuf, offset_x, offset_y, BLI_rcti_size_x(&tile_rect), BLI_rcti_size_y(&tile_rect)); /* make jobs timer to send notifier */ *(rj->do_update) = true; diff --git a/source/blender/editors/space_image/image_edit.c b/source/blender/editors/space_image/image_edit.c index 180f1fb183c..c26f92c5463 100644 --- a/source/blender/editors/space_image/image_edit.c +++ b/source/blender/editors/space_image/image_edit.c @@ -407,6 +407,9 @@ bool ED_image_slot_cycle(struct Image *image, int direction) image->render_slot = ((cur == 1) ? 0 : 1); } + if ((cur != image->render_slot)) { + image->gpuflag |= IMA_GPU_REFRESH; + } return (cur != image->render_slot); } diff --git a/source/blender/makesdna/DNA_image_types.h b/source/blender/makesdna/DNA_image_types.h index 4edf06f90f7..eb03e047c90 100644 --- a/source/blender/makesdna/DNA_image_types.h +++ b/source/blender/makesdna/DNA_image_types.h @@ -151,12 +151,13 @@ typedef struct Image { int lastframe; /* GPU texture flag. */ + /* Contains `ImagePartialRefresh`. */ + ListBase gpu_refresh_areas; int gpuframenr; short gpuflag; short gpu_pass; short gpu_layer; - short gpu_slot; - char _pad2[4]; + char _pad2[6]; /** Deprecated. */ struct PackedFile *packedfile DNA_DEPRECATED; @@ -223,8 +224,10 @@ enum { enum { /** GPU texture needs to be refreshed. */ IMA_GPU_REFRESH = (1 << 0), + /** GPU texture needs to be partially refreshed. */ + IMA_GPU_PARTIAL_REFRESH = (1 << 1), /** All mipmap levels in OpenGL texture set? */ - IMA_GPU_MIPMAP_COMPLETE = (1 << 1), + IMA_GPU_MIPMAP_COMPLETE = (1 << 2), }; /* Image.source, where the image comes from */ diff --git a/source/blender/makesrna/intern/rna_image.c b/source/blender/makesrna/intern/rna_image.c index 2373045d95a..cf4b343e2f7 100644 --- a/source/blender/makesrna/intern/rna_image.c +++ b/source/blender/makesrna/intern/rna_image.c @@ -598,6 +598,7 @@ static void rna_render_slots_active_set(PointerRNA *ptr, int index = BLI_findindex(&image->renderslots, slot); if (index != -1) { image->render_slot = index; + image->gpuflag |= IMA_GPU_REFRESH; } } } @@ -613,6 +614,7 @@ static void rna_render_slots_active_index_set(PointerRNA *ptr, int value) Image *image = (Image *)ptr->owner_id; int num_slots = BLI_listbase_count(&image->renderslots); image->render_slot = value; + image->gpuflag |= IMA_GPU_REFRESH; CLAMP(image->render_slot, 0, num_slots - 1); } -- cgit v1.2.3 From ffb6648a970e72a749c7de3c5645450ba7d8d858 Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Fri, 18 Dec 2020 09:56:28 +0100 Subject: Fix T83625: Shading attribute names cause compilation error. Some GPU platforms don't support having more than one underscore in sequence in an attribute name. This change will remove the underscore as a possible character when encoding to save names. --- source/blender/gpu/intern/gpu_vertex_format.cc | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'source/blender') diff --git a/source/blender/gpu/intern/gpu_vertex_format.cc b/source/blender/gpu/intern/gpu_vertex_format.cc index cd6d78a185d..014c70033fc 100644 --- a/source/blender/gpu/intern/gpu_vertex_format.cc +++ b/source/blender/gpu/intern/gpu_vertex_format.cc @@ -262,13 +262,12 @@ void GPU_vertformat_attr_rename(GPUVertFormat *format, int attr_id, const char * /* Encode 8 original bytes into 11 safe bytes. */ static void safe_bytes(char out[11], const char data[8]) { - char safe_chars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"; + char safe_chars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; uint64_t in = *(uint64_t *)data; for (int i = 0; i < 11; i++) { - /* Encoding in base63 */ - out[i] = safe_chars[in % 63lu]; - in /= 63lu; + out[i] = safe_chars[in % 62lu]; + in /= 62lu; } } -- cgit v1.2.3 From fe5d2448c6e1348be1f82f10a65d65b992f2477b Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Fri, 18 Dec 2020 10:26:02 +0100 Subject: Fix T83494: Eevee clamp node incorrect when min > max. In glsl the clamp function has undefined behavior when min > max. For the clamp node this resulted in differences between cycles and eevee. This patch adds the expected implementation for minmax. The old clamp function is still used in cases where we know for certain that the input values are correct (math node clamp option). GPU uses optimized code and silicon in these cases. --- source/blender/gpu/shaders/material/gpu_shader_material_clamp.glsl | 5 +++++ source/blender/nodes/shader/nodes/node_shader_clamp.cc | 5 +++-- 2 files changed, 8 insertions(+), 2 deletions(-) (limited to 'source/blender') diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_clamp.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_clamp.glsl index b196aed690f..f89608feff1 100644 --- a/source/blender/gpu/shaders/material/gpu_shader_material_clamp.glsl +++ b/source/blender/gpu/shaders/material/gpu_shader_material_clamp.glsl @@ -3,6 +3,11 @@ void clamp_value(float value, float min, float max, out float result) result = clamp(value, min, max); } +void clamp_minmax(float value, float min_allowed, float max_allowed, out float result) +{ + result = min(max(value, min_allowed), max_allowed); +} + void clamp_range(float value, float min, float max, out float result) { result = (max > min) ? clamp(value, min, max) : clamp(value, max, min); diff --git a/source/blender/nodes/shader/nodes/node_shader_clamp.cc b/source/blender/nodes/shader/nodes/node_shader_clamp.cc index d3a893e1d76..4f77421cfe0 100644 --- a/source/blender/nodes/shader/nodes/node_shader_clamp.cc +++ b/source/blender/nodes/shader/nodes/node_shader_clamp.cc @@ -46,8 +46,9 @@ static int gpu_shader_clamp(GPUMaterial *mat, GPUNodeStack *in, GPUNodeStack *out) { - return (node->custom1 == NODE_CLAMP_MINMAX) ? GPU_stack_link(mat, node, "clamp_value", in, out) : - GPU_stack_link(mat, node, "clamp_range", in, out); + return (node->custom1 == NODE_CLAMP_MINMAX) ? + GPU_stack_link(mat, node, "clamp_minmax", in, out) : + GPU_stack_link(mat, node, "clamp_range", in, out); } static void sh_node_clamp_expand_in_mf_network(blender::nodes::NodeMFNetworkBuilder &builder) -- cgit v1.2.3 From f43561eae6826eead2e5e78bc8792b3c15dda6ae Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Thu, 17 Dec 2020 18:37:04 +0100 Subject: Function Nodes: Input Vector Ref: T82651 Normally people use "Combine XYZ" to input a vector, but it is more interesting to have an explicit vector input. So this is basically "Combine XYZ" without any input sockets, the values are stored in the node itself. Differential Revision: https://developer.blender.org/D9885 --- source/blender/blenkernel/BKE_node.h | 1 + source/blender/blenkernel/intern/node.c | 1 + source/blender/editors/space_node/drawnode.c | 9 ++++ source/blender/makesdna/DNA_node_types.h | 4 ++ source/blender/makesrna/intern/rna_nodetree.c | 13 +++++ source/blender/nodes/CMakeLists.txt | 1 + source/blender/nodes/NOD_function.h | 1 + source/blender/nodes/NOD_static_types.h | 1 + .../nodes/function/nodes/node_fn_input_vector.cc | 55 ++++++++++++++++++++++ 9 files changed, 86 insertions(+) create mode 100644 source/blender/nodes/function/nodes/node_fn_input_vector.cc (limited to 'source/blender') diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 5e360bcb074..bc254b81afb 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -1369,6 +1369,7 @@ int ntreeTexExecTree(struct bNodeTree *ntree, #define FN_NODE_COMBINE_STRINGS 1204 #define FN_NODE_OBJECT_TRANSFORMS 1205 #define FN_NODE_RANDOM_FLOAT 1206 +#define FN_NODE_INPUT_VECTOR 1207 /** \} */ diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index d5cea8b6d63..5af49802868 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -4755,6 +4755,7 @@ static void registerFunctionNodes(void) register_node_type_fn_combine_strings(); register_node_type_fn_object_transforms(); register_node_type_fn_random_float(); + register_node_type_fn_input_vector(); } void BKE_node_system_init(void) diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index c2951a9d7a8..b6744719cad 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -3289,6 +3289,12 @@ static void node_function_buts_switch(uiLayout *layout, bContext *UNUSED(C), Poi uiItemR(layout, ptr, "data_type", DEFAULT_FLAGS, "", ICON_NONE); } +static void node_function_buts_input_vector(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiLayout *col = uiLayoutColumn(layout, true); + uiItemR(col, ptr, "vector", UI_ITEM_R_EXPAND, "", ICON_NONE); +} + static void node_function_set_butfunc(bNodeType *ntype) { switch (ntype->type) { @@ -3301,6 +3307,9 @@ static void node_function_set_butfunc(bNodeType *ntype) case FN_NODE_SWITCH: ntype->draw_buttons = node_function_buts_switch; break; + case FN_NODE_INPUT_VECTOR: + ntype->draw_buttons = node_function_buts_input_vector; + break; } } diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index af91ab4f257..d6b5e3ed493 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -1110,6 +1110,10 @@ typedef struct NodeAttributeColorRamp { ColorBand color_ramp; } NodeAttributeColorRamp; +typedef struct NodeInputVector { + float vector[3]; +} NodeInputVector; + /* script node mode */ #define NODE_SCRIPT_INTERNAL 0 #define NODE_SCRIPT_EXTERNAL 1 diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index d624154ddc7..25bfc70ef8f 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -4480,6 +4480,19 @@ static void def_texture(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); } +static void def_fn_input_vector(StructRNA *srna) +{ + PropertyRNA *prop; + + RNA_def_struct_sdna_from(srna, "NodeInputVector", "storage"); + + prop = RNA_def_property(srna, "vector", PROP_FLOAT, PROP_XYZ); + RNA_def_property_array(prop, 3); + RNA_def_property_float_sdna(prop, NULL, "vector"); + RNA_def_property_ui_text(prop, "Vector", ""); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); +} + /* -- Shader Nodes ---------------------------------------------------------- */ static void def_sh_output(StructRNA *srna) diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index e152c50179e..866cf74d35b 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -133,6 +133,7 @@ set(SRC function/nodes/node_fn_combine_strings.cc function/nodes/node_fn_float_compare.cc function/nodes/node_fn_group_instance_id.cc + function/nodes/node_fn_input_vector.cc function/nodes/node_fn_object_transforms.cc function/nodes/node_fn_random_float.cc function/nodes/node_fn_switch.cc diff --git a/source/blender/nodes/NOD_function.h b/source/blender/nodes/NOD_function.h index 58a968151ac..75dd8f89bc8 100644 --- a/source/blender/nodes/NOD_function.h +++ b/source/blender/nodes/NOD_function.h @@ -27,6 +27,7 @@ void register_node_type_fn_group_instance_id(void); void register_node_type_fn_combine_strings(void); void register_node_type_fn_object_transforms(void); void register_node_type_fn_random_float(void); +void register_node_type_fn_input_vector(void); #ifdef __cplusplus } diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h index 1e323d23a53..5b61594cca1 100644 --- a/source/blender/nodes/NOD_static_types.h +++ b/source/blender/nodes/NOD_static_types.h @@ -265,6 +265,7 @@ DefNode(FunctionNode, FN_NODE_GROUP_INSTANCE_ID, 0, "GROUP_INSTANCE_ DefNode(FunctionNode, FN_NODE_COMBINE_STRINGS, 0, "COMBINE_STRINGS", CombineStrings, "Combine Strings", "") DefNode(FunctionNode, FN_NODE_OBJECT_TRANSFORMS, 0, "OBJECT_TRANSFORMS", ObjectTransforms, "Object Transforms", "") DefNode(FunctionNode, FN_NODE_RANDOM_FLOAT, 0, "RANDOM_FLOAT", RandomFloat, "Random Float", "") +DefNode(FunctionNode, FN_NODE_INPUT_VECTOR, def_fn_input_vector, "INPUT_VECTOR", InputVector, "Vector", "") DefNode(GeometryNode, GEO_NODE_TRIANGULATE, def_geo_triangulate, "TRIANGULATE", Triangulate, "Triangulate", "") DefNode(GeometryNode, GEO_NODE_EDGE_SPLIT, 0, "EDGE_SPLIT", EdgeSplit, "Edge Split", "") diff --git a/source/blender/nodes/function/nodes/node_fn_input_vector.cc b/source/blender/nodes/function/nodes/node_fn_input_vector.cc new file mode 100644 index 00000000000..c2707f6307a --- /dev/null +++ b/source/blender/nodes/function/nodes/node_fn_input_vector.cc @@ -0,0 +1,55 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "node_function_util.hh" + +#include "BLI_hash.h" + +static bNodeSocketTemplate fn_node_input_vector_out[] = { + {SOCK_VECTOR, N_("Vector")}, + {-1, ""}, +}; + +static void fn_node_vector_input_expand_in_mf_network( + blender::nodes::NodeMFNetworkBuilder &builder) +{ + bNode &bnode = builder.bnode(); + NodeInputVector *node_storage = static_cast(bnode.storage); + blender::float3 vector(node_storage->vector); + + builder.construct_and_set_matching_fn>(vector); +} + +static void fn_node_input_vector_init(bNodeTree *UNUSED(ntree), bNode *node) +{ + NodeInputVector *data = (NodeInputVector *)MEM_callocN(sizeof(NodeInputVector), + "input vector node"); + node->storage = data; +} + +void register_node_type_fn_input_vector() +{ + static bNodeType ntype; + + fn_node_type_base(&ntype, FN_NODE_INPUT_VECTOR, "Vector", 0, 0); + node_type_socket_templates(&ntype, nullptr, fn_node_input_vector_out); + node_type_init(&ntype, fn_node_input_vector_init); + node_type_storage( + &ntype, "NodeInputVector", node_free_standard_storage, node_copy_standard_storage); + ntype.expand_in_mf_network = fn_node_vector_input_expand_in_mf_network; + + nodeRegisterType(&ntype); +} -- cgit v1.2.3 From 79d6bd9a227f9c07b2a1c3e55d9e06d8b8306f39 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Fri, 18 Dec 2020 13:26:08 +0100 Subject: Functions: add generic pointer class for const pointers This adds a GPointer class, which is mostly the same as GMutablePointer. The main difference is that GPointer references const data, while GMutablePointer references non-const data. --- source/blender/functions/FN_generic_pointer.hh | 55 +++++++++++++++++++++++- source/blender/functions/FN_generic_value_map.hh | 2 +- 2 files changed, 54 insertions(+), 3 deletions(-) (limited to 'source/blender') diff --git a/source/blender/functions/FN_generic_pointer.hh b/source/blender/functions/FN_generic_pointer.hh index 5c2b611c614..2bd66daa7fe 100644 --- a/source/blender/functions/FN_generic_pointer.hh +++ b/source/blender/functions/FN_generic_pointer.hh @@ -21,7 +21,7 @@ namespace blender::fn { /** - * A generic pointer whose type is only known at runtime. + * A generic non-const pointer whose type is only known at runtime. */ class GMutablePointer { private: @@ -58,7 +58,7 @@ class GMutablePointer { template T *get() const { BLI_assert(this->is_type()); - return reinterpret_cast(data_); + return static_cast(data_); } template bool is_type() const @@ -73,4 +73,55 @@ class GMutablePointer { } }; +/** + * A generic const pointer whose type is only known at runtime. + */ +class GPointer { + private: + const CPPType *type_ = nullptr; + const void *data_ = nullptr; + + public: + GPointer() = default; + + GPointer(GMutablePointer ptr) : type_(ptr.type()), data_(ptr.get()) + { + } + + GPointer(const CPPType *type, const void *data = nullptr) : type_(type), data_(data) + { + /* If there is data, there has to be a type. */ + BLI_assert(data_ == nullptr || type_ != nullptr); + } + + GPointer(const CPPType &type, const void *data = nullptr) : type_(&type), data_(data) + { + } + + template GPointer(T *data) : GPointer(&CPPType::get(), data) + { + } + + const void *get() const + { + return data_; + } + + const CPPType *type() const + { + return type_; + } + + template const T *get() const + { + BLI_assert(this->is_type()); + return static_cast(data_); + } + + template bool is_type() const + { + return type_ != nullptr && type_->is(); + } +}; + } // namespace blender::fn diff --git a/source/blender/functions/FN_generic_value_map.hh b/source/blender/functions/FN_generic_value_map.hh index 2c1b37c0461..a9f2dc8a868 100644 --- a/source/blender/functions/FN_generic_value_map.hh +++ b/source/blender/functions/FN_generic_value_map.hh @@ -66,7 +66,7 @@ template class GValueMap { /* Add a value to the container that is copy constructed from the given value. The caller remains * responsible for destructing and freeing the given value. */ - template void add_new_by_copy(ForwardKey &&key, GMutablePointer value) + template void add_new_by_copy(ForwardKey &&key, GPointer value) { const CPPType &type = *value.type(); void *buffer = allocator_.allocate(type.size(), type.alignment()); -- cgit v1.2.3 From c5569ba140382015c32bd638532097ea05168607 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Fri, 18 Dec 2020 13:28:43 +0100 Subject: Geometry Nodes: do not crash when there are undefined nodes Undefined geometry nodes will just output a default value now. --- source/blender/modifiers/intern/MOD_nodes.cc | 29 ++++++++++++++++++++++++++-- source/blender/nodes/NOD_geometry_exec.hh | 11 +++++++++++ 2 files changed, 38 insertions(+), 2 deletions(-) (limited to 'source/blender') diff --git a/source/blender/modifiers/intern/MOD_nodes.cc b/source/blender/modifiers/intern/MOD_nodes.cc index 6bb747fa715..bbf0c7601f5 100644 --- a/source/blender/modifiers/intern/MOD_nodes.cc +++ b/source/blender/modifiers/intern/MOD_nodes.cc @@ -300,13 +300,28 @@ class GeometryNodesEvaluator { void execute_node(const DNode &node, GeoNodeExecParams params) { const bNode &bnode = params.node(); + + /* Use the geometry-node-execute callback if it exists. */ if (bnode.typeinfo->geometry_node_execute != nullptr) { bnode.typeinfo->geometry_node_execute(params); return; } - /* Use the multi-function implementation of the node. */ - const MultiFunction &fn = *mf_by_node_.lookup(&node); + /* Use the multi-function implementation if it exists. */ + const MultiFunction *multi_function = mf_by_node_.lookup_default(&node, nullptr); + if (multi_function != nullptr) { + this->execute_multi_function_node(node, params, *multi_function); + return; + } + + /* Just output default values if no implementation exists. */ + this->execute_unknown_node(node, params); + } + + void execute_multi_function_node(const DNode &node, + GeoNodeExecParams params, + const MultiFunction &fn) + { MFContextBuilder fn_context; MFParamsBuilder fn_params{fn, 1}; Vector input_data; @@ -341,6 +356,16 @@ class GeometryNodesEvaluator { } } + void execute_unknown_node(const DNode &node, GeoNodeExecParams params) + { + for (const DOutputSocket *socket : node.outputs()) { + if (socket->is_available()) { + const CPPType &type = *blender::nodes::socket_cpp_type_get(*socket->typeinfo()); + params.set_output_by_copy(socket->identifier(), {type, type.default_value()}); + } + } + } + void forward_to_inputs(const DOutputSocket &from_socket, GMutablePointer value_to_forward) { Span to_sockets_all = from_socket.linked_sockets(); diff --git a/source/blender/nodes/NOD_geometry_exec.hh b/source/blender/nodes/NOD_geometry_exec.hh index cac04e18fc7..f278d6b4107 100644 --- a/source/blender/nodes/NOD_geometry_exec.hh +++ b/source/blender/nodes/NOD_geometry_exec.hh @@ -44,6 +44,7 @@ using bke::WriteAttribute; using bke::WriteAttributePtr; using fn::CPPType; using fn::GMutablePointer; +using fn::GPointer; using fn::GValueMap; class GeoNodeExecParams { @@ -123,6 +124,16 @@ class GeoNodeExecParams { output_values_.add_new_by_move(identifier, value); } + void set_output_by_copy(StringRef identifier, GPointer value) + { +#ifdef DEBUG + BLI_assert(value.type() != nullptr); + BLI_assert(value.get() != nullptr); + this->check_set_output(identifier, *value.type()); +#endif + output_values_.add_new_by_copy(identifier, value); + } + /** * Store the output value for the given socket identifier. */ -- cgit v1.2.3 From 95afc53604de148c0ed7cfbee88906ae09f6b807 Mon Sep 17 00:00:00 2001 From: Vincent Blankfield Date: Fri, 18 Dec 2020 14:04:58 +0100 Subject: Fix T83716: Dope Sheet, incorrect scaling of channel UI elements Change the top coordinate of the animation channel list UI elements to `rect->ymin` so they correctly span from `rect->ymin` to `channel_height`. Some buttons in the dope sheet channels didn't scale properly with the `Keyframe Scale Factor` preferences setting. This was caused by using the `ymid` value (`ymid = BLI_rctf_cent_y(rect) - 0.5f * ICON_WIDTH`) to position the buttons that supposed to fill all vertical space in the channel (with `channel_height` height). The `ymid` value is only appropriate for the UI elements that with `ICON_WIDTH` height. Maniphest Tasks: T83716 Reviewed by: sybren Differential Revision: https://developer.blender.org/D9841 --- source/blender/editors/animation/anim_channels_defines.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c index c70a86eab1d..6cb829d3a23 100644 --- a/source/blender/editors/animation/anim_channels_defines.c +++ b/source/blender/editors/animation/anim_channels_defines.c @@ -5353,7 +5353,7 @@ void ANIM_channel_draw_widgets(const bContext *C, "", ICON_NONE, offset, - ymid, + rect->ymin, SLIDER_WIDTH, channel_height); UI_but_func_set(but, achannel_setting_slider_nla_curve_cb, ale->id, ale->data); @@ -5411,7 +5411,7 @@ void ANIM_channel_draw_widgets(const bContext *C, "", icon, offset, - ymid, + rect->ymin, ICON_WIDTH, channel_height); } @@ -5437,7 +5437,7 @@ void ANIM_channel_draw_widgets(const bContext *C, "", icon, offset, - ymid, + rect->ymin, ICON_WIDTH, channel_height); } @@ -5457,7 +5457,7 @@ void ANIM_channel_draw_widgets(const bContext *C, "", ICON_NONE, offset, - ymid, + rect->ymin, width, channel_height); } @@ -5483,7 +5483,7 @@ void ANIM_channel_draw_widgets(const bContext *C, "", ICON_NONE, offset, - ymid, + rect->ymin, SLIDER_WIDTH, channel_height); -- cgit v1.2.3 From f3b50380f042b33db0d7973c5c3daa7a460f75aa Mon Sep 17 00:00:00 2001 From: Philipp Oeser Date: Fri, 18 Dec 2020 10:35:08 +0100 Subject: Fix T83916: Cannot drag link from socket if node is inside frame Caused by rB7470c10601d0 where iterating nodetree nodes was changed from backwards to forwards by mistake. Maniphest Tasks: T83916 Differential Revision: https://developer.blender.org/D9890 --- source/blender/editors/space_node/node_edit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender') diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c index fdce5e3f30b..e6f11f3eb83 100644 --- a/source/blender/editors/space_node/node_edit.c +++ b/source/blender/editors/space_node/node_edit.c @@ -854,7 +854,7 @@ static void edit_node_properties_get( /* is rct in visible part of node? */ static bNode *visible_node(SpaceNode *snode, const rctf *rct) { - LISTBASE_FOREACH (bNode *, node, &snode->edittree->nodes) { + LISTBASE_FOREACH_BACKWARD (bNode *, node, &snode->edittree->nodes) { if (BLI_rctf_isect(&node->totr, rct, NULL)) { return node; } -- cgit v1.2.3 From 1be465cccbf96c64e5a90962bd2c76cbc7675fb0 Mon Sep 17 00:00:00 2001 From: Antonio Vazquez Date: Fri, 18 Dec 2020 15:57:10 +0100 Subject: GPencil: Fix potential error in interpolate frame As now it is using a duplicated frame, the untag must be done before copying the frames. --- source/blender/editors/gpencil/gpencil_interpolate.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/gpencil/gpencil_interpolate.c b/source/blender/editors/gpencil/gpencil_interpolate.c index 9bca294cf30..1c967110198 100644 --- a/source/blender/editors/gpencil/gpencil_interpolate.c +++ b/source/blender/editors/gpencil/gpencil_interpolate.c @@ -483,14 +483,15 @@ static bool gpencil_interpolate_set_init_values(bContext *C, wmOperator *op, tGP /* set interpolation weight */ tgpi->shift = RNA_float_get(op->ptr, "shift"); - /* set layers */ - gpencil_interpolate_set_points(C, tgpi); /* Untag strokes to be sure nothing is pending due any canceled process. */ LISTBASE_FOREACH (bGPDlayer *, gpl, &tgpi->gpd->layers) { gpencil_interpolate_untag_strokes(gpl); } + /* Set layers */ + gpencil_interpolate_set_points(C, tgpi); + return 1; } -- cgit v1.2.3 From 3deb21055ad16618b80297b7a82bca46b7b9c1f9 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Fri, 18 Dec 2020 16:00:45 +0100 Subject: Geometry Nodes: support randomly picking instances from collection This uses the "id" attribute to randomly pick instances from a collection for each point. There is one issue. When the collection is updated (e.g. when an object is added to it), the nodes modifier is not automatically updated. It seems like we don't have the infrastructure to support this dependency yet. The same issue exists in the Boolean modifier and with collision collections. This should be solved separately soonish. When "Whole Collection" is disabled, one direct child of the input collection is instanced at each point. A direct child can be an object or a collection. Currently, all objects are picked approximately equally often. In the future, we will provide more control over which point gets which instance. Differential Revision: https://developer.blender.org/D9884 Ref T82372. --- source/blender/editors/space_node/drawnode.c | 3 + source/blender/makesrna/intern/rna_nodetree.c | 5 + source/blender/modifiers/intern/MOD_nodes.cc | 1 + .../blender/nodes/geometry/node_geometry_util.hh | 3 + .../geometry/nodes/node_geo_attribute_randomize.cc | 33 ++--- .../geometry/nodes/node_geo_point_instance.cc | 146 ++++++++++++++++----- 6 files changed, 141 insertions(+), 50 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index b6744719cad..652c70155ab 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -3196,6 +3196,9 @@ static void node_geometry_buts_point_instance(uiLayout *layout, PointerRNA *ptr) { uiItemR(layout, ptr, "instance_type", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); + if (RNA_enum_get(ptr, "instance_type") == GEO_NODE_POINT_INSTANCE_TYPE_COLLECTION) { + uiItemR(layout, ptr, "use_whole_collection", DEFAULT_FLAGS, NULL, ICON_NONE); + } } static void node_geometry_buts_attribute_fill(uiLayout *layout, diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 25bfc70ef8f..cbd677582a9 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -8502,6 +8502,11 @@ static void def_geo_point_instance(StructRNA *srna) RNA_def_property_enum_default(prop, GEO_NODE_POINT_INSTANCE_TYPE_OBJECT); RNA_def_property_ui_text(prop, "Instance Type", ""); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); + + prop = RNA_def_property(srna, "use_whole_collection", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_negative_sdna(prop, NULL, "custom2", 1); + RNA_def_property_ui_text(prop, "Whole Collection", "Instance entire collection on each point"); + RNA_def_property_update(prop, 0, "rna_Node_socket_update"); } static void def_geo_attribute_mix(StructRNA *srna) diff --git a/source/blender/modifiers/intern/MOD_nodes.cc b/source/blender/modifiers/intern/MOD_nodes.cc index bbf0c7601f5..9730f734a17 100644 --- a/source/blender/modifiers/intern/MOD_nodes.cc +++ b/source/blender/modifiers/intern/MOD_nodes.cc @@ -154,6 +154,7 @@ static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphConte } /* TODO: Add relations for IDs in settings. */ + /* TODO: Add dependency for collection changes. */ } static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData) diff --git a/source/blender/nodes/geometry/node_geometry_util.hh b/source/blender/nodes/geometry/node_geometry_util.hh index 3102690d2ed..7c12611a898 100644 --- a/source/blender/nodes/geometry/node_geometry_util.hh +++ b/source/blender/nodes/geometry/node_geometry_util.hh @@ -50,4 +50,7 @@ void poisson_disk_point_elimination(Vector const *input_points, float maximum_distance, float3 boundbox); +Array get_geometry_element_ids_as_uints(const GeometryComponent &component, + const AttributeDomain domain); + } // namespace blender::nodes diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_randomize.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_randomize.cc index 2c3acfc9735..b8b53a17ecc 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_attribute_randomize.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_randomize.cc @@ -74,54 +74,57 @@ static float noise_from_index(const int seed, const int hash) return BLI_hash_int_01(combined_hash); } -static void randomize_attribute(BooleanWriteAttribute &attribute, Span hashes, const int seed) +static void randomize_attribute(BooleanWriteAttribute &attribute, + Span hashes, + const int seed) { MutableSpan attribute_span = attribute.get_span(); for (const int i : IndexRange(attribute.size())) { - const bool value = noise_from_index(seed, hashes[i]) > 0.5f; + const bool value = noise_from_index(seed, (int)hashes[i]) > 0.5f; attribute_span[i] = value; } attribute.apply_span(); } static void randomize_attribute( - FloatWriteAttribute &attribute, float min, float max, Span hashes, const int seed) + FloatWriteAttribute &attribute, float min, float max, Span hashes, const int seed) { MutableSpan attribute_span = attribute.get_span(); for (const int i : IndexRange(attribute.size())) { - const float value = noise_from_index(seed, hashes[i]) * (max - min) + min; + const float value = noise_from_index(seed, (int)hashes[i]) * (max - min) + min; attribute_span[i] = value; } attribute.apply_span(); } static void randomize_attribute( - Float3WriteAttribute &attribute, float3 min, float3 max, Span hashes, const int seed) + Float3WriteAttribute &attribute, float3 min, float3 max, Span hashes, const int seed) { MutableSpan attribute_span = attribute.get_span(); for (const int i : IndexRange(attribute.size())) { - const float x = noise_from_index_and_mutator(seed, hashes[i], 47); - const float y = noise_from_index_and_mutator(seed, hashes[i], 8); - const float z = noise_from_index_and_mutator(seed, hashes[i], 64); + const float x = noise_from_index_and_mutator(seed, (int)hashes[i], 47); + const float y = noise_from_index_and_mutator(seed, (int)hashes[i], 8); + const float z = noise_from_index_and_mutator(seed, (int)hashes[i], 64); const float3 value = float3(x, y, z) * (max - min) + min; attribute_span[i] = value; } attribute.apply_span(); } -static Array get_element_hashes(GeometryComponent &component, - const AttributeDomain domain, - const int attribute_size) +Array get_geometry_element_ids_as_uints(const GeometryComponent &component, + const AttributeDomain domain) { + const int domain_size = component.attribute_domain_size(domain); + /* Hash the reserved name attribute "id" as a (hopefully) stable seed for each point. */ ReadAttributePtr hash_attribute = component.attribute_try_get_for_read("id", domain); - Array hashes(attribute_size); + Array hashes(domain_size); if (hash_attribute) { BLI_assert(hashes.size() == hash_attribute->size()); const CPPType &cpp_type = hash_attribute->cpp_type(); fn::GSpan items = hash_attribute->get_span(); for (const int i : hashes.index_range()) { - hashes[i] = (int)cpp_type.hash(items[i]); + hashes[i] = cpp_type.hash(items[i]); } } else { @@ -129,7 +132,7 @@ static Array get_element_hashes(GeometryComponent &component, RandomNumberGenerator rng; rng.seed(0); for (const int i : hashes.index_range()) { - hashes[i] = rng.get_int32(); + hashes[i] = rng.get_uint32(); } } @@ -154,7 +157,7 @@ static void randomize_attribute(GeometryComponent &component, return; } - Array hashes = get_element_hashes(component, domain, attribute->size()); + Array hashes = get_geometry_element_ids_as_uints(component, domain); switch (data_type) { case CD_PROP_FLOAT: { diff --git a/source/blender/nodes/geometry/nodes/node_geo_point_instance.cc b/source/blender/nodes/geometry/nodes/node_geo_point_instance.cc index e030bc3eec6..4274ded2024 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_point_instance.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_point_instance.cc @@ -16,16 +16,21 @@ #include "BKE_mesh.h" #include "BKE_persistent_data_handle.hh" + +#include "DNA_collection_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_pointcloud_types.h" +#include "BLI_hash.h" + #include "node_geometry_util.hh" static bNodeSocketTemplate geo_node_point_instance_in[] = { {SOCK_GEOMETRY, N_("Geometry")}, {SOCK_OBJECT, N_("Object")}, {SOCK_COLLECTION, N_("Collection")}, + {SOCK_INT, N_("Seed"), 0, 0, 0, 0, -10000, 10000}, {-1, ""}, }; @@ -40,70 +45,141 @@ static void geo_node_point_instance_update(bNodeTree *UNUSED(tree), bNode *node) { bNodeSocket *object_socket = (bNodeSocket *)BLI_findlink(&node->inputs, 1); bNodeSocket *collection_socket = object_socket->next; + bNodeSocket *seed_socket = collection_socket->next; GeometryNodePointInstanceType type = (GeometryNodePointInstanceType)node->custom1; + const bool use_whole_collection = node->custom2 == 0; nodeSetSocketAvailability(object_socket, type == GEO_NODE_POINT_INSTANCE_TYPE_OBJECT); nodeSetSocketAvailability(collection_socket, type == GEO_NODE_POINT_INSTANCE_TYPE_COLLECTION); + nodeSetSocketAvailability( + seed_socket, type == GEO_NODE_POINT_INSTANCE_TYPE_COLLECTION && !use_whole_collection); +} + +static void get_instanced_data__object(const GeoNodeExecParams ¶ms, + MutableSpan> r_instances_data) +{ + bke::PersistentObjectHandle object_handle = params.get_input( + "Object"); + Object *object = params.handle_map().lookup(object_handle); + if (object == params.self_object()) { + object = nullptr; + } + if (object != nullptr) { + InstancedData instance; + instance.type = INSTANCE_DATA_TYPE_OBJECT; + instance.data.object = object; + r_instances_data.fill(instance); + } +} + +static void get_instanced_data__collection( + const GeoNodeExecParams ¶ms, + const GeometryComponent &component, + MutableSpan> r_instances_data) +{ + const bNode &node = params.node(); + bke::PersistentCollectionHandle collection_handle = + params.get_input("Collection"); + Collection *collection = params.handle_map().lookup(collection_handle); + if (collection != nullptr) { + const bool use_whole_collection = node.custom2 == 0; + if (use_whole_collection) { + InstancedData instance; + instance.type = INSTANCE_DATA_TYPE_COLLECTION; + instance.data.collection = collection; + r_instances_data.fill(instance); + } + else { + Vector possible_instances; + /* Direct child objects are instanced as objects. */ + LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) { + Object *object = cob->ob; + InstancedData instance; + instance.type = INSTANCE_DATA_TYPE_OBJECT; + instance.data.object = object; + possible_instances.append(instance); + } + /* Direct child collections are instanced as collections. */ + LISTBASE_FOREACH (CollectionChild *, child, &collection->children) { + Collection *child_collection = child->collection; + InstancedData instance; + instance.type = INSTANCE_DATA_TYPE_COLLECTION; + instance.data.collection = child_collection; + possible_instances.append(instance); + } + + if (!possible_instances.is_empty()) { + const int seed = params.get_input("Seed"); + Array ids = get_geometry_element_ids_as_uints(component, ATTR_DOMAIN_POINT); + for (const int i : r_instances_data.index_range()) { + const int index = BLI_hash_int_2d(ids[i], seed) % possible_instances.size(); + r_instances_data[i] = possible_instances[index]; + } + } + } + } +} + +static Array> get_instanced_data(const GeoNodeExecParams ¶ms, + const GeometryComponent &component, + const int amount) +{ + const bNode &node = params.node(); + const GeometryNodePointInstanceType type = (GeometryNodePointInstanceType)node.custom1; + + Array> instances_data(amount); + + switch (type) { + case GEO_NODE_POINT_INSTANCE_TYPE_OBJECT: { + get_instanced_data__object(params, instances_data); + break; + } + case GEO_NODE_POINT_INSTANCE_TYPE_COLLECTION: { + get_instanced_data__collection(params, component, instances_data); + break; + } + } + return instances_data; } static void add_instances_from_geometry_component(InstancesComponent &instances, const GeometryComponent &src_geometry, - Object *object, - Collection *collection) + const GeoNodeExecParams ¶ms) { + const AttributeDomain domain = ATTR_DOMAIN_POINT; + + const int domain_size = src_geometry.attribute_domain_size(domain); + Array> instances_data = get_instanced_data( + params, src_geometry, domain_size); + Float3ReadAttribute positions = src_geometry.attribute_get_for_read( - "position", ATTR_DOMAIN_POINT, {0, 0, 0}); + "position", domain, {0, 0, 0}); Float3ReadAttribute rotations = src_geometry.attribute_get_for_read( - "rotation", ATTR_DOMAIN_POINT, {0, 0, 0}); + "rotation", domain, {0, 0, 0}); Float3ReadAttribute scales = src_geometry.attribute_get_for_read( - "scale", ATTR_DOMAIN_POINT, {1, 1, 1}); + "scale", domain, {1, 1, 1}); - for (const int i : IndexRange(positions.size())) { - if (object != nullptr) { - instances.add_instance(object, positions[i], rotations[i], scales[i]); - } - if (collection != nullptr) { - instances.add_instance(collection, positions[i], rotations[i], scales[i]); + for (const int i : IndexRange(domain_size)) { + if (instances_data[i].has_value()) { + instances.add_instance(*instances_data[i], positions[i], rotations[i], scales[i]); } } } static void geo_node_point_instance_exec(GeoNodeExecParams params) { - GeometryNodePointInstanceType type = (GeometryNodePointInstanceType)params.node().custom1; GeometrySet geometry_set = params.extract_input("Geometry"); GeometrySet geometry_set_out; - Object *object = nullptr; - Collection *collection = nullptr; - - if (type == GEO_NODE_POINT_INSTANCE_TYPE_OBJECT) { - bke::PersistentObjectHandle object_handle = params.extract_input( - "Object"); - object = params.handle_map().lookup(object_handle); - /* Avoid accidental recursion of instances. */ - if (object == params.self_object()) { - object = nullptr; - } - } - else if (type == GEO_NODE_POINT_INSTANCE_TYPE_COLLECTION) { - bke::PersistentCollectionHandle collection_handle = - params.extract_input("Collection"); - collection = params.handle_map().lookup(collection_handle); - } - InstancesComponent &instances = geometry_set_out.get_component_for_write(); if (geometry_set.has()) { add_instances_from_geometry_component( - instances, *geometry_set.get_component_for_read(), object, collection); + instances, *geometry_set.get_component_for_read(), params); } if (geometry_set.has()) { add_instances_from_geometry_component( - instances, - *geometry_set.get_component_for_read(), - object, - collection); + instances, *geometry_set.get_component_for_read(), params); } params.set_output("Geometry", std::move(geometry_set_out)); -- cgit v1.2.3 From 7bee1489c1d81ecf2634df96ba039549c64313c3 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Fri, 18 Dec 2020 09:34:21 -0600 Subject: UI: Rename "Float Color" attribute data type to "Color" Since "Float Color" is more commonly used than "Byte Color", which is not exposed in the interface yet anyway, it makes sense to drop the "Float" label on the color data type name. --- source/blender/makesrna/intern/rna_attribute.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender') diff --git a/source/blender/makesrna/intern/rna_attribute.c b/source/blender/makesrna/intern/rna_attribute.c index f98ca47d767..e9d258424d8 100644 --- a/source/blender/makesrna/intern/rna_attribute.c +++ b/source/blender/makesrna/intern/rna_attribute.c @@ -41,7 +41,7 @@ const EnumPropertyItem rna_enum_attribute_type_items[] = { {CD_PROP_FLOAT, "FLOAT", 0, "Float", "Floating-point value"}, {CD_PROP_INT32, "INT", 0, "Integer", "32-bit integer"}, {CD_PROP_FLOAT3, "FLOAT_VECTOR", 0, "Vector", "3D vector with floating-point values"}, - {CD_PROP_COLOR, "FLOAT_COLOR", 0, "Float Color", "RGBA color with floating-point precisions"}, + {CD_PROP_COLOR, "FLOAT_COLOR", 0, "Color", "RGBA color with floating-point precisions"}, {CD_MLOOPCOL, "BYTE_COLOR", 0, "Byte Color", "RGBA color with 8-bit precision"}, {CD_PROP_STRING, "STRING", 0, "String", "Text string"}, {CD_PROP_BOOL, "BOOLEAN", 0, "Boolean", "True or false"}, -- cgit v1.2.3 From 2250b5cefee7f7cce31e388cb83515543ffe60f0 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Fri, 18 Dec 2020 18:12:11 +0100 Subject: UI: Redesigned data-block selectors The previous design is rather old and has a couple of problems: * Scalability: The current solution of adding little icon buttons next to the data-block name field doesn't scale well. It only works if there's a small number of operations. We need to be able to place more items there for better data-block management. Especially with the introduction of library overrides. * Discoverability: It's not obvious what some of the icons do. They appear and disappear, but it's not obvious why some are available at times and others not. * Unclear Status: Currently their library status (linked, indirectly linked, broken link, library override) isn't really clear. * Unusual behavior: Some of the icon buttons allow Shift or Ctrl clicking to invoke alternative behaviors. This is not a usual pattern in Blender. This patch does the following changes: * Adds a menu to the right of the name button to access all kinds of operations (create, delete, unlink, user management, library overrides, etc). * Make good use of the "disabled hint" for tooltips, to explain why buttons are disabled. The UI team wants to establish this as a good practise. * Use superimposed icons for duplicate and unlink, rather than extra buttons (uses less space, looks less distracting and is a nice + consistent design language). * Remove fake user and user count button, they are available from the menu now. * Support tooltips for superimposed icons (committed mouse hover feedback to master already). * Slightly increase size of the name button - it was already a bit small before, and the move from real buttons to superimposed icons reduces usable space for the name itself. * More clearly differentiate between duplicate and creating a new data-block. The latter is only available in the menu. * Display library status icon on the left (linked, missing library, overridden, asset) * Disables "Make Single User" button - in review we weren't sure if there are good use-cases for it, so better to see if we can remove it. Note that I do expect some aspects of this design to change still. I think some changes are problematic, but others disagreed. I will open a feedback thread on devtalk to see what others think. Differential Revision: https://developer.blender.org/D8554 Reviewed by: Bastien Montagne Design discussed and agreed on with the UI team, also see T79959. --- source/blender/editors/include/ED_util.h | 3 +- source/blender/editors/include/UI_interface.h | 34 +- source/blender/editors/interface/interface.c | 143 ++- .../editors/interface/interface_context_menu.c | 2 +- .../blender/editors/interface/interface_handlers.c | 51 +- source/blender/editors/interface/interface_ops.c | 1 + .../editors/interface/interface_region_tooltip.c | 68 +- .../editors/interface/interface_templates.c | 1086 ++++++++++++-------- source/blender/editors/render/render_intern.h | 3 + source/blender/editors/render/render_ops.c | 3 + source/blender/editors/render/render_shading.c | 236 +++-- source/blender/editors/screen/screen_ops.c | 1 - source/blender/editors/space_action/action_data.c | 178 ++-- .../blender/editors/space_action/action_intern.h | 1 + source/blender/editors/space_action/action_ops.c | 2 + source/blender/editors/space_api/spacetypes.c | 2 + source/blender/editors/space_clip/clip_buttons.c | 1 + source/blender/editors/space_file/file_panels.c | 9 +- source/blender/editors/space_image/image_buttons.c | 3 +- source/blender/editors/space_nla/nla_buttons.c | 3 +- source/blender/editors/space_node/drawnode.c | 94 +- source/blender/editors/util/CMakeLists.txt | 1 + source/blender/editors/util/ed_util.c | 21 - source/blender/editors/util/ed_util_ops.c | 155 +++ source/blender/makesrna/intern/rna_ui_api.c | 9 +- source/blender/modifiers/intern/MOD_displace.c | 2 +- source/blender/modifiers/intern/MOD_nodes.cc | 1 + .../modifiers/intern/MOD_volume_displace.cc | 3 +- source/blender/modifiers/intern/MOD_warp.c | 12 +- source/blender/modifiers/intern/MOD_wave.c | 12 +- .../blender/modifiers/intern/MOD_weightvg_util.c | 1 + .../windowmanager/intern/wm_operator_type.c | 2 +- 32 files changed, 1463 insertions(+), 680 deletions(-) create mode 100644 source/blender/editors/util/ed_util_ops.c (limited to 'source/blender') diff --git a/source/blender/editors/include/ED_util.h b/source/blender/editors/include/ED_util.h index ca6b4bdc618..1e87a940a7d 100644 --- a/source/blender/editors/include/ED_util.h +++ b/source/blender/editors/include/ED_util.h @@ -52,10 +52,11 @@ void ED_spacedata_id_remap(struct ScrArea *area, struct ID *old_id, struct ID *new_id); -void ED_OT_flush_edits(struct wmOperatorType *ot); void ED_OT_lib_id_load_custom_preview(struct wmOperatorType *ot); void ED_OT_lib_id_generate_preview(struct wmOperatorType *ot); +void ED_operatortypes_edutils(void); + /* ************** XXX OLD CRUFT WARNING ************* */ void apply_keyb_grid( diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 7c128cbf1e6..ced411ef75f 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -76,6 +76,7 @@ struct wmWindow; typedef struct uiBlock uiBlock; typedef struct uiBut uiBut; +typedef struct uiButExtraOpIcon uiButExtraOpIcon; typedef struct uiLayout uiLayout; typedef struct uiPopupBlockHandle uiPopupBlockHandle; @@ -1381,13 +1382,16 @@ typedef struct uiStringInfo { /* Note: Expects pointers to uiStringInfo structs as parameters. * Will fill them with translated strings, when possible. * Strings in uiStringInfo must be MEM_freeN'ed by caller. */ -void UI_but_string_info_get(struct bContext *C, uiBut *but, ...) ATTR_SENTINEL(0); +void UI_but_string_info_get(struct bContext *C, uiBut *but, uiButExtraOpIcon *extra_icon, ...) + ATTR_SENTINEL(0); /* Edit i18n stuff. */ /* Name of the main py op from i18n addon. */ #define EDTSRC_I18N_OP_NAME "UI_OT_edittranslation" /** + * TODO This is old stuff, only used by templateID. Should be cleaned up. + * * Special Buttons * * Buttons with a more specific purpose: @@ -1405,14 +1409,16 @@ enum { UI_ID_ALONE = 1 << 4, UI_ID_OPEN = 1 << 3, UI_ID_DELETE = 1 << 5, - UI_ID_LOCAL = 1 << 6, - UI_ID_AUTO_NAME = 1 << 7, - UI_ID_FAKE_USER = 1 << 8, + UI_ID_MAKE_LOCAL = 1 << 6, + UI_ID_LIB_OVERRIDE_ADD = 1 << 7, + UI_ID_AUTO_NAME = 1 << 8, UI_ID_PIN = 1 << 9, UI_ID_PREVIEWS = 1 << 10, - UI_ID_OVERRIDE = 1 << 11, + UI_ID_LIB_OVERRIDE_REMOVE = 1 << 11, + UI_ID_LIB_OVERRIDE_RESET = 1 << 12, UI_ID_FULL = UI_ID_RENAME | UI_ID_BROWSE | UI_ID_ADD_NEW | UI_ID_OPEN | UI_ID_ALONE | - UI_ID_DELETE | UI_ID_LOCAL, + UI_ID_DELETE | UI_ID_MAKE_LOCAL | UI_ID_LIB_OVERRIDE_ADD | + UI_ID_LIB_OVERRIDE_REMOVE | UI_ID_LIB_OVERRIDE_RESET, }; /** @@ -1658,10 +1664,12 @@ void UI_but_func_hold_set(uiBut *but, uiButHandleHoldFunc func, void *argN); void UI_but_func_pushed_state_set(uiBut *but, uiButPushedStateFunc func, void *arg); -PointerRNA *UI_but_extra_operator_icon_add(uiBut *but, - const char *opname, - short opcontext, - int icon); +struct uiButExtraOpIcon *UI_but_extra_operator_icon_add(uiBut *but, + const char *opname, + short opcontext, + int icon); +struct wmOperatorType *UI_but_extra_operator_icon_optype_get(struct uiButExtraOpIcon *extra_icon); +PointerRNA *UI_but_extra_operator_icon_opptr_get(struct uiButExtraOpIcon *extra_icon); /* Autocomplete * @@ -1963,6 +1971,7 @@ void uiTemplateID(uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *newop, + const char *duplicateop, const char *openop, const char *unlinkop, int filter, @@ -2567,6 +2576,11 @@ struct ARegion *UI_tooltip_create_from_button(struct bContext *C, struct ARegion *butregion, uiBut *but, bool is_label); +struct ARegion *UI_tooltip_create_from_button_or_extra_icon(struct bContext *C, + struct ARegion *butregion, + uiBut *but, + uiButExtraOpIcon *extra_icon, + bool is_label); struct ARegion *UI_tooltip_create_from_gizmo(struct bContext *C, struct wmGizmo *gz); void UI_tooltip_free(struct bContext *C, struct bScreen *screen, struct ARegion *region); diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index c5c2f0e55c4..26fd75cc74c 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -1167,16 +1167,21 @@ void ui_but_add_shortcut(uiBut *but, const char *shortcut_str, const bool do_str * \{ */ static bool ui_but_event_operator_string_from_operator(const bContext *C, - uiBut *but, + wmOperatorCallParams *op_call_params, char *buf, const size_t buf_len) { - BLI_assert(but->optype != NULL); + BLI_assert(op_call_params->optype != NULL); bool found = false; - IDProperty *prop = (but->opptr) ? but->opptr->data : NULL; - - if (WM_key_event_operator_string( - C, but->optype->idname, but->opcontext, prop, true, buf, buf_len)) { + IDProperty *prop = (op_call_params->opptr) ? op_call_params->opptr->data : NULL; + + if (WM_key_event_operator_string(C, + op_call_params->optype->idname, + op_call_params->opcontext, + prop, + true, + buf, + buf_len)) { found = true; } return found; @@ -1253,15 +1258,22 @@ static bool ui_but_event_operator_string_from_panel(const bContext *C, return found; } -static bool ui_but_event_operator_string(const bContext *C, - uiBut *but, - char *buf, - const size_t buf_len) +static bool ui_but_event_operator_string( + const bContext *C, uiBut *but, uiButExtraOpIcon *extra_icon, char *buf, const size_t buf_len) { bool found = false; + wmOperatorType *extra_icon_optype = UI_but_extra_operator_icon_optype_get(extra_icon); - if (but->optype != NULL) { - found = ui_but_event_operator_string_from_operator(C, but, buf, buf_len); + if (extra_icon_optype) { + found = ui_but_event_operator_string_from_operator(C, extra_icon->optype_params, buf, buf_len); + } + else if (but->optype != NULL) { + found = ui_but_event_operator_string_from_operator( + C, + &(wmOperatorCallParams){ + .optype = but->optype, .opptr = but->opptr, .opcontext = but->opcontext}, + buf, + buf_len); } else if (UI_but_menutype_get(but) != NULL) { found = ui_but_event_operator_string_from_menu(C, but, buf, buf_len); @@ -1564,7 +1576,7 @@ static void ui_menu_block_set_keymaps(const bContext *C, uiBlock *block) continue; } - if (ui_but_event_operator_string(C, but, buf, sizeof(buf))) { + if (ui_but_event_operator_string(C, but, NULL, buf, sizeof(buf))) { ui_but_add_shortcut(but, buf, false); } else if (ui_but_event_property_operator_string(C, but, buf, sizeof(buf))) { @@ -1605,12 +1617,12 @@ typedef enum PredefinedExtraOpIconType { PREDEFINED_EXTRA_OP_ICON_EYEDROPPER, } PredefinedExtraOpIconType; -static PointerRNA *ui_but_extra_operator_icon_add_ptr(uiBut *but, - wmOperatorType *optype, - short opcontext, - int icon) +static uiButExtraOpIcon *ui_but_extra_operator_icon_add_ptr(uiBut *but, + wmOperatorType *optype, + short opcontext, + int icon) { - uiButExtraOpIcon *extra_op_icon = MEM_mallocN(sizeof(*extra_op_icon), __func__); + uiButExtraOpIcon *extra_op_icon = MEM_callocN(sizeof(*extra_op_icon), __func__); extra_op_icon->icon = (BIFIconID)icon; extra_op_icon->optype_params = MEM_callocN(sizeof(*extra_op_icon->optype_params), @@ -1625,13 +1637,15 @@ static PointerRNA *ui_but_extra_operator_icon_add_ptr(uiBut *but, BLI_addtail(&but->extra_op_icons, extra_op_icon); - return extra_op_icon->optype_params->opptr; + return extra_op_icon; } static void ui_but_extra_operator_icon_free(uiButExtraOpIcon *extra_icon) { - WM_operator_properties_free(extra_icon->optype_params->opptr); - MEM_freeN(extra_icon->optype_params->opptr); + if (extra_icon->optype_params->opptr) { + WM_operator_properties_free(extra_icon->optype_params->opptr); + MEM_freeN(extra_icon->optype_params->opptr); + } MEM_freeN(extra_icon->optype_params); MEM_freeN(extra_icon); } @@ -1644,18 +1658,25 @@ void ui_but_extra_operator_icons_free(uiBut *but) BLI_listbase_clear(&but->extra_op_icons); } -PointerRNA *UI_but_extra_operator_icon_add(uiBut *but, - const char *opname, - short opcontext, - int icon) +uiButExtraOpIcon *UI_but_extra_operator_icon_add(uiBut *but, + const char *opname, + short opcontext, + int icon) { wmOperatorType *optype = WM_operatortype_find(opname, false); - if (optype) { - return ui_but_extra_operator_icon_add_ptr(but, optype, opcontext, icon); - } + BLI_assert(optype); + return ui_but_extra_operator_icon_add_ptr(but, optype, opcontext, icon); +} - return NULL; +PointerRNA *UI_but_extra_operator_icon_opptr_get(uiButExtraOpIcon *extra_icon) +{ + return extra_icon->optype_params->opptr; +} + +wmOperatorType *UI_but_extra_operator_icon_optype_get(uiButExtraOpIcon *extra_icon) +{ + return extra_icon ? extra_icon->optype_params->optype : NULL; } static bool ui_but_icon_extra_is_visible_text_clear(const uiBut *but) @@ -6818,7 +6839,7 @@ void UI_but_func_hold_set(uiBut *but, uiButHandleHoldFunc func, void *argN) but->hold_argN = argN; } -void UI_but_string_info_get(bContext *C, uiBut *but, ...) +void UI_but_string_info_get(bContext *C, uiBut *but, uiButExtraOpIcon *extra_icon, ...) { va_list args; uiStringInfo *si; @@ -6827,13 +6848,19 @@ void UI_but_string_info_get(bContext *C, uiBut *but, ...) int totitems; bool free_items = false; - va_start(args, but); + wmOperatorType *extra_icon_optype = UI_but_extra_operator_icon_optype_get(extra_icon); + wmOperatorType *optype = extra_icon ? extra_icon_optype : but->optype; + + /* Don't query RNA data when the extra-icon overrides the button. */ + PropertyRNA *rnaprop = extra_icon ? NULL : but->rnaprop; + + va_start(args, extra_icon); while ((si = (uiStringInfo *)va_arg(args, void *))) { uiStringInfoType type = si->type; char *tmp = NULL; if (type == BUT_GET_LABEL) { - if (but->str && but->str[0]) { + if (but->str && but->str[0] && !extra_icon) { const char *str_sep; size_t str_len; @@ -6863,16 +6890,16 @@ void UI_but_string_info_get(bContext *C, uiBut *but, ...) } if (type == BUT_GET_RNAPROP_IDENTIFIER) { - if (but->rnaprop) { - tmp = BLI_strdup(RNA_property_identifier(but->rnaprop)); + if (rnaprop) { + tmp = BLI_strdup(RNA_property_identifier(rnaprop)); } } else if (type == BUT_GET_RNASTRUCT_IDENTIFIER) { - if (but->rnaprop && but->rnapoin.data) { + if (rnaprop && but->rnapoin.data) { tmp = BLI_strdup(RNA_struct_identifier(but->rnapoin.type)); } - else if (but->optype) { - tmp = BLI_strdup(but->optype->idname); + else if (optype) { + tmp = BLI_strdup(optype->idname); } else if (ELEM(but->type, UI_BTYPE_MENU, UI_BTYPE_PULLDOWN)) { MenuType *mt = UI_but_menutype_get(but); @@ -6888,23 +6915,25 @@ void UI_but_string_info_get(bContext *C, uiBut *but, ...) } } else if (ELEM(type, BUT_GET_RNA_LABEL, BUT_GET_RNA_TIP)) { - if (but->rnaprop) { + if (rnaprop) { if (type == BUT_GET_RNA_LABEL) { - tmp = BLI_strdup(RNA_property_ui_name(but->rnaprop)); + tmp = BLI_strdup(RNA_property_ui_name(rnaprop)); } else { - const char *t = RNA_property_ui_description(but->rnaprop); + const char *t = RNA_property_ui_description(rnaprop); if (t && t[0]) { tmp = BLI_strdup(t); } } } - else if (but->optype) { + else if (optype) { + PointerRNA *opptr = extra_icon_optype ? UI_but_extra_operator_icon_opptr_get(extra_icon) : + but->opptr; if (type == BUT_GET_RNA_LABEL) { - tmp = BLI_strdup(WM_operatortype_name(but->optype, but->opptr)); + tmp = BLI_strdup(WM_operatortype_name(optype, opptr)); } else { - tmp = WM_operatortype_description(C, but->optype, but->opptr); + tmp = WM_operatortype_description(C, optype, opptr); } } else if (ELEM(but->type, UI_BTYPE_MENU, UI_BTYPE_PULLDOWN, UI_BTYPE_POPOVER)) { @@ -6956,11 +6985,11 @@ void UI_but_string_info_get(bContext *C, uiBut *but, ...) } else if (type == BUT_GET_RNA_LABEL_CONTEXT) { const char *_tmp = BLT_I18NCONTEXT_DEFAULT; - if (but->rnaprop) { - _tmp = RNA_property_translation_context(but->rnaprop); + if (rnaprop) { + _tmp = RNA_property_translation_context(rnaprop); } - else if (but->optype) { - _tmp = RNA_struct_translation_context(but->optype->srna); + else if (optype) { + _tmp = RNA_struct_translation_context(optype->srna); } else if (ELEM(but->type, UI_BTYPE_MENU, UI_BTYPE_PULLDOWN)) { MenuType *mt = UI_but_menutype_get(but); @@ -6979,16 +7008,16 @@ void UI_but_string_info_get(bContext *C, uiBut *but, ...) int value = 0; /* get the enum property... */ - if (but->rnaprop && RNA_property_type(but->rnaprop) == PROP_ENUM) { + if (rnaprop && RNA_property_type(rnaprop) == PROP_ENUM) { /* enum property */ ptr = &but->rnapoin; - prop = but->rnaprop; + prop = rnaprop; value = (ELEM(but->type, UI_BTYPE_ROW, UI_BTYPE_TAB)) ? (int)but->hardmax : (int)ui_but_value_get(but); } - else if (but->optype) { - PointerRNA *opptr = UI_but_operator_ptr_get(but); - wmOperatorType *ot = but->optype; + else if (optype) { + PointerRNA *opptr = extra_icon_optype ? UI_but_extra_operator_icon_opptr_get(extra_icon) : + UI_but_operator_ptr_get(but); /* so the context is passed to itemf functions */ WM_operator_properties_sanitize(opptr, false); @@ -6998,11 +7027,11 @@ void UI_but_string_info_get(bContext *C, uiBut *but, ...) * operator menus in the Anim Editors will show tooltips for the different * operations instead of the meaningless generic operator tooltip */ - if (ot->prop && RNA_property_type(ot->prop) == PROP_ENUM) { - if (RNA_struct_contains_property(opptr, ot->prop)) { + if (optype->prop && RNA_property_type(optype->prop) == PROP_ENUM) { + if (RNA_struct_contains_property(opptr, optype->prop)) { ptr = opptr; - prop = ot->prop; - value = RNA_property_enum_get(opptr, ot->prop); + prop = optype->prop; + value = RNA_property_enum_get(opptr, optype->prop); } } } @@ -7035,7 +7064,7 @@ void UI_but_string_info_get(bContext *C, uiBut *but, ...) else if (type == BUT_GET_OP_KEYMAP) { if (!ui_block_is_menu(but->block)) { char buf[128]; - if (ui_but_event_operator_string(C, but, buf, sizeof(buf))) { + if (ui_but_event_operator_string(C, but, extra_icon, buf, sizeof(buf))) { tmp = BLI_strdup(buf); } } diff --git a/source/blender/editors/interface/interface_context_menu.c b/source/blender/editors/interface/interface_context_menu.c index 870c3a2a13f..fd3b00eec31 100644 --- a/source/blender/editors/interface/interface_context_menu.c +++ b/source/blender/editors/interface/interface_context_menu.c @@ -509,7 +509,7 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but) uiStringInfo label = {BUT_GET_LABEL, NULL}; /* highly unlikely getting the label ever fails */ - UI_but_string_info_get(C, but, &label, NULL); + UI_but_string_info_get(C, but, NULL, &label, NULL); pup = UI_popup_menu_begin(C, label.strinfo ? label.strinfo : "", ICON_NONE); layout = UI_popup_menu_layout(pup); diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 08e71e0cfd0..790c2cd5313 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -334,6 +334,7 @@ typedef struct uiHandleButtonData { int retval; /* booleans (could be made into flags) */ bool cancel, escapecancel; + bool skip_undo_push; bool applied, applied_interactive; bool changed_cursor; wmTimer *flashtimer; @@ -820,7 +821,9 @@ static void ui_apply_but_func(bContext *C, uiBut *but) /* typically call ui_apply_but_undo(), ui_apply_but_autokey() */ static void ui_apply_but_undo(uiBut *but) { - if (but->flag & UI_BUT_UNDO) { + const bool force_skip_undo = (but->active && but->active->skip_undo_push); + + if (but->flag & UI_BUT_UNDO && !force_skip_undo) { const char *str = NULL; size_t str_len_clip = SIZE_MAX - 1; bool skip_undo = false; @@ -2866,7 +2869,8 @@ void ui_but_active_string_clear_and_exit(bContext *C, uiBut *but) but->active->str[0] = 0; ui_apply_but_TEX(C, but, but->active); - button_activate_state(C, but, BUTTON_STATE_EXIT); + /* use onfree event so undo is handled by caller and apply is already done above */ + button_activate_exit((bContext *)C, but, but->active, false, true); } static void ui_textedit_string_ensure_max_length(uiBut *but, uiHandleButtonData *data, int maxlen) @@ -4011,16 +4015,38 @@ static void ui_numedit_apply(bContext *C, uiBlock *block, uiBut *but, uiHandleBu ED_region_tag_redraw(data->region); } -static void ui_but_extra_operator_icon_apply(bContext *C, uiBut *but, uiButExtraOpIcon *op_icon) +static void ui_but_extra_operator_icon_apply_func(uiBut *but, uiButExtraOpIcon *op_icon) { - if (but->active->interactive) { - ui_apply_but(C, but->block, but, but->active, true); + if (ui_afterfunc_check(but->block, but)) { + uiAfterFunc *after = ui_afterfunc_new(); + + after->optype = op_icon->optype_params->optype; + after->opcontext = op_icon->optype_params->opcontext; + after->opptr = op_icon->optype_params->opptr; + + if (but->context) { + after->context = CTX_store_copy(but->context); + } + + /* Ownership moved, don't let the UI code free it. */ + op_icon->optype_params->opptr = NULL; } +} + +static void ui_but_extra_operator_icon_apply(bContext *C, + uiBut *but, + uiHandleButtonData *data, + uiButExtraOpIcon *op_icon) +{ button_activate_state(C, but, BUTTON_STATE_EXIT); - WM_operator_name_call_ptr(C, - op_icon->optype_params->optype, - op_icon->optype_params->opcontext, - op_icon->optype_params->opptr); + ui_apply_but(C, but->block, but, data, true); + + data->postbut = but; + data->posttype = BUTTON_ACTIVATE_OVER; + /* Leave undo up to the operator. */ + data->skip_undo_push = true; + + ui_but_extra_operator_icon_apply_func(but, op_icon); /* Force recreation of extra operator icons (pseudo update). */ ui_but_extra_operator_icons_free(but); @@ -4219,7 +4245,7 @@ static bool ui_do_but_extra_operator_icon(bContext *C, ED_region_tag_redraw(data->region); button_tooltip_timer_reset(C, but); - ui_but_extra_operator_icon_apply(C, but, op_icon); + ui_but_extra_operator_icon_apply(C, but, data, op_icon); /* Note: 'but', 'data' may now be freed, don't access. */ return true; @@ -7854,7 +7880,10 @@ static ARegion *ui_but_tooltip_init( uiBut *but = UI_region_active_but_get(region); *r_exit_on_event = false; if (but) { - return UI_tooltip_create_from_button(C, region, but, is_label); + uiButExtraOpIcon *extra_icon = ui_but_extra_operator_icon_mouse_over_get( + but, but->active, CTX_wm_window(C)->eventstate); + + return UI_tooltip_create_from_button_or_extra_icon(C, region, but, extra_icon, is_label); } return NULL; } diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c index e5aa0665a16..2995cff8ed5 100644 --- a/source/blender/editors/interface/interface_ops.c +++ b/source/blender/editors/interface/interface_ops.c @@ -1521,6 +1521,7 @@ static int edittranslation_exec(bContext *C, wmOperator *op) UI_but_string_info_get(C, but, + NULL, &but_label, &rna_label, &enum_label, diff --git a/source/blender/editors/interface/interface_region_tooltip.c b/source/blender/editors/interface/interface_region_tooltip.c index 12f3ba609f0..89515608c5b 100644 --- a/source/blender/editors/interface/interface_region_tooltip.c +++ b/source/blender/editors/interface/interface_region_tooltip.c @@ -534,7 +534,7 @@ static uiTooltipData *ui_tooltip_data_from_tool(bContext *C, uiBut *but, bool is { uiStringInfo op_keymap = {BUT_GET_OP_KEYMAP, NULL}; - UI_but_string_info_get(C, but, &op_keymap, NULL); + UI_but_string_info_get(C, but, NULL, &op_keymap, NULL); shortcut = op_keymap.strinfo; } @@ -764,7 +764,9 @@ static uiTooltipData *ui_tooltip_data_from_tool(bContext *C, uiBut *but, bool is return data; } -static uiTooltipData *ui_tooltip_data_from_button(bContext *C, uiBut *but) +static uiTooltipData *ui_tooltip_data_from_button(bContext *C, + uiBut *but, + uiButExtraOpIcon *extra_icon) { uiStringInfo but_label = {BUT_GET_LABEL, NULL}; uiStringInfo but_tip = {BUT_GET_TIP, NULL}; @@ -777,20 +779,29 @@ static uiTooltipData *ui_tooltip_data_from_button(bContext *C, uiBut *but) char buf[512]; + wmOperatorType *extra_icon_optype = UI_but_extra_operator_icon_optype_get(extra_icon); + wmOperatorType *optype = extra_icon ? extra_icon_optype : but->optype; + /* create tooltip data */ uiTooltipData *data = MEM_callocN(sizeof(uiTooltipData), "uiTooltipData"); - UI_but_string_info_get(C, - but, - &but_label, - &but_tip, - &enum_label, - &enum_tip, - &op_keymap, - &prop_keymap, - &rna_struct, - &rna_prop, - NULL); + if (extra_icon) { + UI_but_string_info_get(C, but, extra_icon, &but_label, &but_tip, &op_keymap, NULL); + } + else { + UI_but_string_info_get(C, + but, + NULL, + &but_label, + &but_tip, + &enum_label, + &enum_tip, + &op_keymap, + &prop_keymap, + &rna_struct, + &rna_prop, + NULL); + } /* Tip Label (only for buttons not already showing the label). * Check prefix instead of comparing because the button may include the shortcut. */ @@ -923,15 +934,16 @@ static uiTooltipData *ui_tooltip_data_from_button(bContext *C, uiBut *but) } } } - else if (but->optype) { - PointerRNA *opptr; - char *str; - opptr = UI_but_operator_ptr_get(but); /* allocated when needed, the button owns it */ + else if (optype) { + PointerRNA *opptr = extra_icon_optype ? + UI_but_extra_operator_icon_opptr_get(extra_icon) : + UI_but_operator_ptr_get( + but); /* allocated when needed, the button owns it */ /* so the context is passed to fieldf functions (some py fieldf functions use it) */ WM_operator_properties_sanitize(opptr, false); - str = ui_tooltip_text_python_from_op(C, but->optype, opptr); + char *str = ui_tooltip_text_python_from_op(C, optype, opptr); /* operator info */ if (U.flag & USER_TOOLTIPS_PYTHON) { @@ -958,7 +970,7 @@ static uiTooltipData *ui_tooltip_data_from_button(bContext *C, uiBut *but) disabled_msg = CTX_wm_operator_poll_msg_get(C); } /* alternatively, buttons can store some reasoning too */ - else if (but->disabled_info) { + if (!disabled_msg && but->disabled_info) { disabled_msg = TIP_(but->disabled_info); } @@ -1398,11 +1410,8 @@ static ARegion *ui_tooltip_create_with_data(bContext *C, /** \name ToolTip Public API * \{ */ -/** - * \param is_label: When true, show a small tip that only shows the name, - * otherwise show the full tooltip. - */ -ARegion *UI_tooltip_create_from_button(bContext *C, ARegion *butregion, uiBut *but, bool is_label) +ARegion *UI_tooltip_create_from_button_or_extra_icon( + bContext *C, ARegion *butregion, uiBut *but, uiButExtraOpIcon *extra_icon, bool is_label) { wmWindow *win = CTX_wm_window(C); /* aspect values that shrink text are likely unreadable */ @@ -1419,7 +1428,7 @@ ARegion *UI_tooltip_create_from_button(bContext *C, ARegion *butregion, uiBut *b } if (data == NULL) { - data = ui_tooltip_data_from_button(C, but); + data = ui_tooltip_data_from_button(C, but, extra_icon); } if (data == NULL) { @@ -1457,6 +1466,15 @@ ARegion *UI_tooltip_create_from_button(bContext *C, ARegion *butregion, uiBut *b return region; } +/** + * \param is_label: When true, show a small tip that only shows the name, + * otherwise show the full tooltip. + */ +ARegion *UI_tooltip_create_from_button(bContext *C, ARegion *butregion, uiBut *but, bool is_label) +{ + return UI_tooltip_create_from_button_or_extra_icon(C, butregion, but, NULL, is_label); +} + ARegion *UI_tooltip_create_from_gizmo(bContext *C, wmGizmo *gz) { wmWindow *win = CTX_wm_window(C); diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index b895f1702f4..6e96704271f 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -102,9 +102,16 @@ // #define USE_OP_RESET_BUT /* defines for templateID/TemplateSearch */ -#define TEMPLATE_SEARCH_TEXTBUT_WIDTH (UI_UNIT_X * 6) +#define TEMPLATE_SEARCH_TEXTBUT_WIDTH (UI_UNIT_X * 8) #define TEMPLATE_SEARCH_TEXTBUT_HEIGHT UI_UNIT_Y +/* Add "Make Single User" button to templateID. Users can just manually duplicate an ID, it's + * unclear what the use-case of this specific button is. So for now disabling it, we can bring it + * back or remove it later. + * - Julian + */ +//#define USE_TEMPLATE_ID_MAKE_SINGLE_USER + void UI_template_fix_linking(void) { } @@ -308,6 +315,12 @@ typedef struct TemplateID { ListBase *idlb; short idcode; + + const char *new_op; + const char *duplicate_op; + const char *unlink_op; + const char *open_op; + short filter; int prv_rows, prv_cols; bool preview; @@ -564,80 +577,64 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event) memset(&idptr, 0, sizeof(idptr)); RNA_property_pointer_set(&template_ui->ptr, template_ui->prop, idptr, NULL); RNA_property_update(C, &template_ui->ptr, template_ui->prop); - - if (id && CTX_wm_window(C)->eventstate->shift) { - /* only way to force-remove data (on save) */ - id_us_clear_real(id); - id_fake_user_clear(id); - id->us = 0; - undo_push_label = "Delete Data-Block"; - } - break; - case UI_ID_FAKE_USER: + case UI_ID_MAKE_LOCAL: if (id) { - if (id->flag & LIB_FAKEUSER) { - id_us_plus(id); - } - else { - id_us_min(id); + Main *bmain = CTX_data_main(C); + if (BKE_lib_id_make_local(bmain, id, false, 0)) { + BKE_main_id_clear_newpoins(bmain); + + /* reassign to get get proper updates/notifiers */ + idptr = RNA_property_pointer_get(&template_ui->ptr, template_ui->prop); + RNA_property_pointer_set(&template_ui->ptr, template_ui->prop, idptr, NULL); + RNA_property_update(C, &template_ui->ptr, template_ui->prop); + undo_push_label = "Make Local"; } - undo_push_label = "Fake User"; - } - else { - return; } break; - case UI_ID_LOCAL: - if (id) { + case UI_ID_LIB_OVERRIDE_ADD: + if (id && ID_IS_OVERRIDABLE_LIBRARY(id)) { Main *bmain = CTX_data_main(C); - if (CTX_wm_window(C)->eventstate->shift) { - if (ID_IS_OVERRIDABLE_LIBRARY(id)) { - /* Only remap that specific ID usage to overriding local data-block. */ - ID *override_id = BKE_lib_override_library_create_from_id(bmain, id, false); - if (override_id != NULL) { - BKE_main_id_clear_newpoins(bmain); - - if (GS(override_id->name) == ID_OB) { - Scene *scene = CTX_data_scene(C); - if (!BKE_collection_has_object_recursive(scene->master_collection, - (Object *)override_id)) { - BKE_collection_object_add_from( - bmain, scene, (Object *)id, (Object *)override_id); - } - } - - /* Assign new pointer, takes care of updates/notifiers */ - RNA_id_pointer_create(override_id, &idptr); + /* Only remap that specific ID usage to overriding local data-block. */ + ID *override_id = BKE_lib_override_library_create_from_id(bmain, id, false); + if (override_id != NULL) { + BKE_main_id_clear_newpoins(bmain); + + if (GS(override_id->name) == ID_OB) { + Scene *scene = CTX_data_scene(C); + if (!BKE_collection_has_object_recursive(scene->master_collection, + (Object *)override_id)) { + BKE_collection_object_add_from(bmain, scene, (Object *)id, (Object *)override_id); } - undo_push_label = "Make Library Override"; } - } - else { - if (BKE_lib_id_make_local(bmain, id, false, 0)) { - BKE_main_id_clear_newpoins(bmain); - /* reassign to get get proper updates/notifiers */ - idptr = RNA_property_pointer_get(&template_ui->ptr, template_ui->prop); - undo_push_label = "Make Local"; - } - } - if (undo_push_label != NULL) { - RNA_property_pointer_set(&template_ui->ptr, template_ui->prop, idptr, NULL); - RNA_property_update(C, &template_ui->ptr, template_ui->prop); + /* Assign new pointer, takes care of updates/notifiers */ + RNA_id_pointer_create(override_id, &idptr); } + /* reassign to get get proper updates/notifiers */ + RNA_property_pointer_set(&template_ui->ptr, template_ui->prop, idptr, NULL); + RNA_property_update(C, &template_ui->ptr, template_ui->prop); + undo_push_label = "Make Library Override"; } break; - case UI_ID_OVERRIDE: + case UI_ID_LIB_OVERRIDE_RESET: + if (id && ID_IS_OVERRIDE_LIBRARY_REAL(id)) { + Main *bmain = CTX_data_main(C); + BKE_lib_override_library_id_reset(bmain, id); + undo_push_label = "Reset Library Override"; + } + break; + case UI_ID_LIB_OVERRIDE_REMOVE: if (id && ID_IS_OVERRIDE_LIBRARY(id)) { BKE_lib_override_library_free(&id->override_library, true); /* reassign to get get proper updates/notifiers */ idptr = RNA_property_pointer_get(&template_ui->ptr, template_ui->prop); RNA_property_pointer_set(&template_ui->ptr, template_ui->prop, idptr, NULL); RNA_property_update(C, &template_ui->ptr, template_ui->prop); - undo_push_label = "Override Data-Block"; + undo_push_label = "Remove Library Override"; } break; +#ifdef USE_TEMPLATE_ID_MAKE_SINGLE_USER case UI_ID_ALONE: if (id) { const bool do_scene_obj = ((GS(id->name) == ID_OB) && @@ -659,6 +656,7 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event) undo_push_label = "Make Single User"; } break; +#endif #if 0 case UI_ID_AUTO_NAME: break; @@ -772,17 +770,221 @@ static const char *template_id_context(StructRNA *type) # define template_id_context(type) 0 #endif -static uiBut *template_id_def_new_but(uiBlock *block, - const ID *id, - const TemplateID *template_ui, - StructRNA *type, - const char *const newop, - const bool editable, - const bool id_open, - const bool use_tab_but, - int but_height) -{ +static void template_id_linked_operation_button( + uiBlock *block, Main *bmain, ID *id, TemplateID *template_ui, int operation) +{ + BLI_assert(ELEM(operation, UI_ID_MAKE_LOCAL, UI_ID_LIB_OVERRIDE_ADD)); + + const char *label = (operation == UI_ID_MAKE_LOCAL) ? + CTX_N_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Make Local") : + CTX_N_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add Library Override"); + const char *tip = (operation == UI_ID_MAKE_LOCAL) ? + N_("Make library linked data-block local to this file") : + N_("Create a local override of this library linked data-block"); + BIFIconID icon = (operation == UI_ID_MAKE_LOCAL) ? ICON_BLANK1 : ICON_LIBRARY_DATA_OVERRIDE; + + uiBut *but = uiDefIconTextBut(block, + UI_BTYPE_BUT, + 0, + icon, + CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, label), + 0, + 0, + UI_UNIT_X, + UI_UNIT_Y, + NULL, + 0, + 0, + 0, + 0, + TIP_(tip)); + + bool disabled = false; + + if (!ID_IS_LINKED(id)) { + disabled = true; + but->disabled_info = TIP_("Data-block is not linked"); + } + else if (id->tag & LIB_TAG_INDIRECT) { + disabled = true; + but->disabled_info = TIP_("Indirect library data-block, cannot change"); + } + else if (!BKE_lib_id_make_local(bmain, id, true /* test */, 0)) { + disabled = true; + but->disabled_info = TIP_("Data-blocks of this type cannot be made local"); + } + else if (!RNA_property_editable_info( + &template_ui->ptr, template_ui->prop, &but->disabled_info)) { + disabled = true; + } + + if (disabled) { + UI_but_flag_enable(but, UI_BUT_DISABLED); + } + else { + UI_but_funcN_set(but, template_id_cb, MEM_dupallocN(template_ui), POINTER_FROM_INT(operation)); + } +} + +static void template_id_library_overridden_button(uiBlock *block, + ID *id, + TemplateID *template_ui, + int operation) +{ + BLI_assert(ELEM(operation, UI_ID_LIB_OVERRIDE_RESET, UI_ID_LIB_OVERRIDE_REMOVE) && + ID_IS_OVERRIDE_LIBRARY(id)); + + if (operation == UI_ID_LIB_OVERRIDE_RESET && ID_IS_OVERRIDE_LIBRARY_REAL(id)) { + uiBut *but = uiDefIconTextBut( + block, + UI_BTYPE_BUT, + 0, + ICON_BLANK1, + CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Reset Library Override"), + 0, + 0, + UI_UNIT_X, + UI_UNIT_Y, + NULL, + 0, + 0, + 0, + 0, + TIP_("Reset the local override to the state of " + "the overridden data-block")); + if (!ID_IS_OVERRIDE_LIBRARY_REAL(id)) { + but->disabled_info = TIP_("Data-block is a virtual, not a real override"); + UI_but_flag_enable(but, UI_BUT_DISABLED); + } + else { + UI_but_funcN_set(but, + template_id_cb, + MEM_dupallocN(template_ui), + POINTER_FROM_INT(UI_ID_LIB_OVERRIDE_RESET)); + } + } + else if (operation == UI_ID_LIB_OVERRIDE_REMOVE) { + uiBut *but = uiDefIconTextBut( + block, + UI_BTYPE_BUT, + 0, + ICON_BLANK1, + CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Make Local"), + 0, + 0, + UI_UNIT_X, + UI_UNIT_Y, + NULL, + 0, + 0, + 0, + 0, + TIP_("Remove library override and make the library linked data-block " + "fully local to this file")); + UI_but_funcN_set(but, + template_id_cb, + MEM_dupallocN(template_ui), + POINTER_FROM_INT(UI_ID_LIB_OVERRIDE_REMOVE)); + } +} + +#ifdef USE_TEMPLATE_ID_MAKE_SINGLE_USER +static uiBut *template_id_make_single_user_button(uiBlock *block, ID *id, TemplateID *template_ui) +{ + uiBut *but = uiDefIconTextBut( + block, + UI_BTYPE_BUT, + 0, + ICON_BLANK1, + CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Make Single-User Copy"), + 0, + 0, + UI_UNIT_X, + UI_UNIT_Y, + NULL, + 0, + 0, + 0, + 0, + TIP_("Duplicate the data-block and assign the newly created copy")); + + if (ID_REAL_USERS(id) <= 1) { + UI_but_flag_enable(but, UI_BUT_DISABLED); + but->disabled_info = TIP_("Data-block already is a single-user"); + /* No need for further setup. */ + return but; + } + + UI_but_funcN_set(but, template_id_cb, MEM_dupallocN(template_ui), POINTER_FROM_INT(UI_ID_ALONE)); + ID *idfrom = template_ui->ptr.owner_id; + bool disabled = false; + + if (!RNA_property_editable_info(&template_ui->ptr, template_ui->prop, &but->disabled_info)) { + disabled = true; + } + if (!BKE_id_copy_is_allowed(id)) { + but->disabled_info = TIP_("Data-blocks of this type cannot be copied"); + disabled = true; + } + /* object in editmode - don't change data */ + if (idfrom && GS(idfrom->name) == ID_OB && (((Object *)idfrom)->mode & OB_MODE_EDIT)) { + but->disabled_info = TIP_("Cannot change object data in Edit Mode"); + disabled = true; + } + + if (disabled) { + UI_but_flag_enable(but, UI_BUT_DISABLED); + } + + return but; +} +#endif + +static void template_id_use_fake_user_button(uiBlock *block, PointerRNA *idptr) +{ + const bool use_fake_user = ID_FAKE_USERS(idptr->data) > 0; + uiBut *but = uiDefIconTextButR( + block, + UI_BTYPE_ICON_TOGGLE, + 0, + ICON_FAKE_USER_OFF, + use_fake_user ? CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove Fake User") : + CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add Fake User"), + 0, + 0, + UI_UNIT_X, + UI_UNIT_Y, + idptr, + "use_fake_user", + -1, + 0, + 0, + -1, + -1, + TIP_("When set, ensures the data-block is kept when reloading the file, even if not used at " + "all")); + + if ((ELEM(GS(((ID *)idptr->data)->name), ID_GR, ID_SCE, ID_SCR, ID_TXT, ID_OB, ID_WS))) { + but->disabled_info = TIP_("Data-block type does not support fake user"); + UI_but_flag_enable(but, UI_BUT_DISABLED); + } +} + +enum TemplateIDCreateType { + TEMPLATE_ID_CREATE_NEW, + TEMPLATE_ID_CREATE_DUPLICATE, +}; + +static uiBut *template_id_new_button(uiBlock *block, + const ID *id, + TemplateID *template_ui, + enum TemplateIDCreateType create_type, + StructRNA *type, + const bool id_open, + const bool use_tab_but, + int but_height) +{ uiBut *but; const int w = id ? UI_UNIT_X : id_open ? UI_UNIT_X * 3 : UI_UNIT_X * 6; const int but_type = use_tab_but ? UI_BTYPE_TAB : UI_BTYPE_BUT; @@ -820,54 +1022,384 @@ static uiBut *template_id_def_new_but(uiBlock *block, BLT_I18NCONTEXT_ID_POINTCLOUD, BLT_I18NCONTEXT_ID_VOLUME, BLT_I18NCONTEXT_ID_SIMULATION, ); + BLT_I18N_MSGID_MULTI_CTXT("Duplicate", + BLT_I18NCONTEXT_DEFAULT, + BLT_I18NCONTEXT_ID_SCENE, + BLT_I18NCONTEXT_ID_OBJECT, + BLT_I18NCONTEXT_ID_MESH, + BLT_I18NCONTEXT_ID_CURVE, + BLT_I18NCONTEXT_ID_METABALL, + BLT_I18NCONTEXT_ID_MATERIAL, + BLT_I18NCONTEXT_ID_TEXTURE, + BLT_I18NCONTEXT_ID_IMAGE, + BLT_I18NCONTEXT_ID_LATTICE, + BLT_I18NCONTEXT_ID_LIGHT, + BLT_I18NCONTEXT_ID_CAMERA, + BLT_I18NCONTEXT_ID_WORLD, + BLT_I18NCONTEXT_ID_SCREEN, + BLT_I18NCONTEXT_ID_TEXT, ); + BLT_I18N_MSGID_MULTI_CTXT("Duplicate", + BLT_I18NCONTEXT_ID_SPEAKER, + BLT_I18NCONTEXT_ID_SOUND, + BLT_I18NCONTEXT_ID_ARMATURE, + BLT_I18NCONTEXT_ID_ACTION, + BLT_I18NCONTEXT_ID_NODETREE, + BLT_I18NCONTEXT_ID_BRUSH, + BLT_I18NCONTEXT_ID_PARTICLESETTINGS, + BLT_I18NCONTEXT_ID_GPENCIL, + BLT_I18NCONTEXT_ID_FREESTYLELINESTYLE, + BLT_I18NCONTEXT_ID_WORKSPACE, + BLT_I18NCONTEXT_ID_LIGHTPROBE, + BLT_I18NCONTEXT_ID_HAIR, + BLT_I18NCONTEXT_ID_POINTCLOUD, + BLT_I18NCONTEXT_ID_VOLUME, + BLT_I18NCONTEXT_ID_SIMULATION, ); /* Note: BLT_I18N_MSGID_MULTI_CTXT takes a maximum number of parameters, * check the definition to see if a new call must be added when the limit * is exceeded. */ - if (newop) { + const char *text; + const char *op; + BIFIconID icon; + + switch (create_type) { + case TEMPLATE_ID_CREATE_NEW: + icon = ICON_ADD; + text = CTX_IFACE_(template_id_context(type), "New"); + op = template_ui->new_op; + break; + case TEMPLATE_ID_CREATE_DUPLICATE: + icon = ICON_DUPLICATE; + text = CTX_IFACE_(template_id_context(type), "Duplicate"); + op = template_ui->duplicate_op; + break; + } + + const bool icon_only = use_tab_but; + if (icon_only) { + text = ""; + } + + if (op) { + but = uiDefIconTextButO( + block, but_type, op, WM_OP_INVOKE_DEFAULT, icon, text, 0, 0, w, but_height, NULL); + UI_but_funcN_set( + but, template_id_cb, MEM_dupallocN(template_ui), POINTER_FROM_INT(UI_ID_ADD_NEW)); + + if (!RNA_property_editable_info(&template_ui->ptr, template_ui->prop, &but->disabled_info)) { + UI_but_flag_enable(but, UI_BUT_DISABLED); + } + } + else { + but = uiDefIconTextBut(block, + but_type, + 0, + icon, + text, + 0, + 0, + w, + but_height, + NULL, + 0, + 0, + 0, + 0, + TIP_("Create a new data-block")); + but->disabled_info = TIP_("Creating a new data-block is not supported here"); + UI_but_flag_enable(but, UI_BUT_DISABLED); + } + if (icon_only) { + UI_but_drawflag_disable(but, UI_BUT_ICON_LEFT); + } + +#ifndef WITH_INTERNATIONAL + UNUSED_VARS(type); +#endif + + return but; +} + +static void template_id_unlink_button(uiBlock *block, + TemplateID *template_ui, + bool hide_if_disabled) +{ + const char *disable_info; + const bool is_menu = ui_block_is_menu(block); + const bool editable = RNA_property_editable_info( + &template_ui->ptr, template_ui->prop, &disable_info); + /* allow unlink if 'unlinkop' is passed, even when 'PROP_NEVER_UNLINK' is set */ + uiBut *but = NULL; + + if (hide_if_disabled && !editable) { + /* Add no button. */ + } + else if (template_ui->unlink_op) { + but = uiDefIconTextButO(block, + UI_BTYPE_BUT, + template_ui->unlink_op, + WM_OP_INVOKE_DEFAULT, + ICON_X, + is_menu ? NULL : "", + 0, + 0, + UI_UNIT_X, + UI_UNIT_Y, + NULL); + /* so we can access the template from operators, font unlinking needs this */ + UI_but_funcN_set(but, NULL, MEM_dupallocN(template_ui), NULL); + } + else { + const bool never_unlink = RNA_property_flag(template_ui->prop) & + (PROP_NEVER_UNLINK | PROP_NEVER_NULL); + + if (!never_unlink || !hide_if_disabled) { + but = uiDefIconTextBut(block, + UI_BTYPE_BUT, + 0, + ICON_X, + is_menu ? CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Unlink") : "", + 0, + 0, + UI_UNIT_X, + UI_UNIT_Y, + NULL, + 0, + 0, + 0, + 0, + TIP_("Remove this usage of the data-block")); + if (!never_unlink) { + UI_but_funcN_set( + but, template_id_cb, MEM_dupallocN(template_ui), POINTER_FROM_INT(UI_ID_DELETE)); + } + if (!is_menu) { + UI_but_drawflag_disable(but, UI_BUT_ICON_LEFT); + } + } + + if (but && never_unlink) { + but->disabled_info = TIP_("Property must never be in an unlinked state"); + UI_but_flag_enable(but, UI_BUT_DISABLED); + } + } + + if (but) { + if (!editable) { + but->disabled_info = disable_info; + UI_but_flag_enable(but, UI_BUT_DISABLED); + } + } +} + +static void template_id_open_button(uiBlock *block, + ID *id, + TemplateID *template_ui, + const bool compact) +{ + const bool is_menu = ui_block_is_menu(block); + const int w = compact ? UI_UNIT_X * 3 : UI_UNIT_X * 6; + char text[UI_MAX_NAME_STR] = ""; + const bool icon_only = !is_menu && id; + uiBut *but; + + if (!icon_only) { + BLI_snprintf(text, + sizeof(text), + "%s%s", + CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Open"), + is_menu ? "..." : ""); + } + + if (template_ui->open_op) { but = uiDefIconTextButO(block, - but_type, - newop, + UI_BTYPE_BUT, + template_ui->open_op, WM_OP_INVOKE_DEFAULT, - (id && !use_tab_but) ? ICON_DUPLICATE : ICON_ADD, - (id) ? "" : CTX_IFACE_(template_id_context(type), "New"), + ICON_FILEBROWSER, + text, 0, 0, w, - but_height, + UI_UNIT_Y, NULL); UI_but_funcN_set( - but, template_id_cb, MEM_dupallocN(template_ui), POINTER_FROM_INT(UI_ID_ADD_NEW)); + but, template_id_cb, MEM_dupallocN(template_ui), POINTER_FROM_INT(UI_ID_OPEN)); } else { but = uiDefIconTextBut(block, - but_type, + UI_BTYPE_BUT, 0, - (id && !use_tab_but) ? ICON_DUPLICATE : ICON_ADD, - (id) ? "" : CTX_IFACE_(template_id_context(type), "New"), + ICON_FILEBROWSER, + text, 0, 0, w, - but_height, + UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL); - UI_but_funcN_set( - but, template_id_cb, MEM_dupallocN(template_ui), POINTER_FROM_INT(UI_ID_ADD_NEW)); + but->disabled_info = TIP_("Browsing for a new data-block is not supported here"); + UI_but_flag_enable(but, UI_BUT_DISABLED); } - if ((idfrom && idfrom->lib) || !editable) { + if (!RNA_property_editable_info(&template_ui->ptr, template_ui->prop, &but->disabled_info)) { UI_but_flag_enable(but, UI_BUT_DISABLED); } +} -#ifndef WITH_INTERNATIONAL - UNUSED_VARS(type); +static void template_id_unpack_button(uiBlock *block, ID *id) +{ + wmOperatorType *optype = WM_operatortype_find("FILE_OT_unpack_item", false); + uiBut *but; + + but = uiDefIconTextButO_ptr(block, + UI_BTYPE_BUT, + optype, + WM_OP_INVOKE_REGION_WIN, + ICON_PACKAGE, + NULL, + 0, + 0, + UI_UNIT_X, + UI_UNIT_Y, + NULL); + + if (!BKE_packedfile_id_check(id)) { + but->disabled_info = TIP_("File is not packed"); + UI_but_flag_enable(but, UI_BUT_DISABLED); + } + UI_but_operator_ptr_get(but); + + RNA_string_set(but->opptr, "id_name", id->name + 2); + RNA_int_set(but->opptr, "id_type", GS(id->name)); +} + +static void template_id_user_count_label(uiLayout *layout, const ID *id) +{ + char numstr[UI_MAX_NAME_STR]; + BLI_snprintf(numstr, + sizeof(numstr), + "%d %s", + ID_REAL_USERS(id), + ID_REAL_USERS(id) > 1 ? IFACE_("Users") : IFACE_("User")); + uiItemL(layout, numstr, ICON_NONE); +} + +static void template_id_menu(bContext *C, uiLayout *layout, void *arg) +{ + /* Button that spawned the menu. */ + const uiBut *menu_parent_but = arg; + TemplateID *template_ui = menu_parent_but->func_argN; + PointerRNA idptr = RNA_property_pointer_get(&template_ui->ptr, template_ui->prop); + ID *id = idptr.data; + uiBlock *block = uiLayoutGetBlock(layout); + + BLI_assert(id); + + template_id_new_button( + block, id, template_ui, TEMPLATE_ID_CREATE_NEW, idptr.type, false, false, UI_UNIT_X); + template_id_new_button( + block, id, template_ui, TEMPLATE_ID_CREATE_DUPLICATE, idptr.type, false, false, UI_UNIT_X); + template_id_unlink_button(block, template_ui, false); + +#ifdef USE_TEMPLATE_ID_MAKE_SINGLE_USER + template_id_make_single_user_button(block, id, template_ui); #endif + template_id_use_fake_user_button(block, &idptr); - return but; + if (template_ui->open_op || BKE_packedfile_id_check(id)) { + uiItemS(layout); + + template_id_open_button(block, id, template_ui, false); + template_id_unpack_button(block, id); + } + + /* Library operators. */ + if (ID_IS_OVERRIDE_LIBRARY(id)) { + uiItemS(layout); + + template_id_library_overridden_button(block, id, template_ui, UI_ID_LIB_OVERRIDE_RESET); + template_id_library_overridden_button(block, id, template_ui, UI_ID_LIB_OVERRIDE_REMOVE); + } + else if (ID_IS_LINKED(id)) { + uiItemS(layout); + + Main *bmain = CTX_data_main(C); + template_id_linked_operation_button(block, bmain, id, template_ui, UI_ID_MAKE_LOCAL); + template_id_linked_operation_button(block, bmain, id, template_ui, UI_ID_LIB_OVERRIDE_ADD); + } + + uiItemS(layout); + template_id_user_count_label(layout, id); +} + +static void template_id_name_button( + uiBlock *block, StructRNA *type, TemplateID *template_ui, int flag, const bool hide_extras) +{ + PointerRNA idptr = RNA_property_pointer_get(&template_ui->ptr, template_ui->prop); + ID *id = idptr.data; + BIFIconID lib_icon = UI_icon_from_library(id); + + char name[UI_MAX_NAME_STR] = ""; + uiBut *but = uiDefIconTextButR(block, + UI_BTYPE_TEXT, + 0, + lib_icon, + name, + 0, + 0, + TEMPLATE_SEARCH_TEXTBUT_WIDTH, + TEMPLATE_SEARCH_TEXTBUT_HEIGHT, + &idptr, + "name", + -1, + 0, + 0, + 0, + 0, + RNA_struct_ui_description(type)); + /* Note: Also needed for the extra icons below (their operators access the TemplateID). */ + UI_but_funcN_set( + but, template_id_cb, MEM_dupallocN(template_ui), POINTER_FROM_INT(UI_ID_RENAME)); + + const bool user_alert = (id->us <= 0); + if (user_alert) { + UI_but_flag_enable(but, UI_BUT_REDALERT); + } + + if (hide_extras) { + return; + } + + if (template_ui->duplicate_op && (flag & UI_ID_ADD_NEW)) { + UI_but_extra_operator_icon_add( + but, template_ui->duplicate_op, WM_OP_INVOKE_DEFAULT, ICON_DUPLICATE); + } + + if (id && (flag & UI_ID_DELETE)) { + const bool never_unlink = RNA_property_flag(template_ui->prop) & + (PROP_NEVER_UNLINK | PROP_NEVER_NULL); + if (template_ui->unlink_op) { + UI_but_extra_operator_icon_add(but, template_ui->unlink_op, WM_OP_INVOKE_DEFAULT, ICON_X); + } + else if (!never_unlink) { + UI_but_extra_operator_icon_add(but, "ED_OT_lib_unlink", WM_OP_INVOKE_DEFAULT, ICON_X); + } + } + + /* Disable fake user icon for now, only have it in the menu. */ + const bool add_extra_fake_user_icon = false; + if (add_extra_fake_user_icon && id->lib == NULL && + !(ELEM(GS(id->name), ID_GR, ID_SCE, ID_SCR, ID_TXT, ID_OB, ID_WS))) { + UI_but_extra_operator_icon_add(but, + "ED_OT_lib_fake_user_toggle", + WM_OP_INVOKE_DEFAULT, + ID_FAKE_USERS(id) ? ICON_FAKE_USER_ON : ICON_FAKE_USER_OFF); + } } static void template_ID(const bContext *C, @@ -875,9 +1407,6 @@ static void template_ID(const bContext *C, TemplateID *template_ui, StructRNA *type, int flag, - const char *newop, - const char *openop, - const char *unlinkop, const char *text, const bool live_icon, const bool hide_buttons) @@ -885,15 +1414,12 @@ static void template_ID(const bContext *C, uiBut *but; uiBlock *block; PointerRNA idptr; - // ListBase *lb; // UNUSED - ID *id, *idfrom; + ID *id; const bool editable = RNA_property_editable(&template_ui->ptr, template_ui->prop); const bool use_previews = template_ui->preview = (flag & UI_ID_PREVIEWS) != 0; idptr = RNA_property_pointer_get(&template_ui->ptr, template_ui->prop); id = idptr.data; - idfrom = template_ui->ptr.owner_id; - // lb = template_ui->idlb; /* Allow opertators to take the ID from context. */ uiLayoutSetContextPointer(layout, "id", &idptr); @@ -926,277 +1452,39 @@ static void template_ID(const bContext *C, /* text button with name */ if (id) { - char name[UI_MAX_NAME_STR]; - const bool user_alert = (id->us <= 0); - - // text_idbutton(id, name); - name[0] = '\0'; - but = uiDefButR(block, - UI_BTYPE_TEXT, - 0, - name, - 0, - 0, - TEMPLATE_SEARCH_TEXTBUT_WIDTH, - TEMPLATE_SEARCH_TEXTBUT_HEIGHT, - &idptr, - "name", - -1, - 0, - 0, - -1, - -1, - RNA_struct_ui_description(type)); - UI_but_funcN_set( - but, template_id_cb, MEM_dupallocN(template_ui), POINTER_FROM_INT(UI_ID_RENAME)); - if (user_alert) { - UI_but_flag_enable(but, UI_BUT_REDALERT); - } - - if (id->lib) { - if (id->tag & LIB_TAG_INDIRECT) { - but = uiDefIconBut(block, - UI_BTYPE_BUT, - 0, - ICON_LIBRARY_DATA_INDIRECT, - 0, - 0, - UI_UNIT_X, - UI_UNIT_Y, - NULL, - 0, - 0, - 0, - 0, - TIP_("Indirect library data-block, cannot change")); - UI_but_flag_enable(but, UI_BUT_DISABLED); - } - else { - const bool disabled = (!BKE_lib_id_make_local(CTX_data_main(C), id, true /* test */, 0) || - (idfrom && idfrom->lib)); - but = uiDefIconBut(block, - UI_BTYPE_BUT, - 0, - ICON_LIBRARY_DATA_DIRECT, - 0, - 0, - UI_UNIT_X, - UI_UNIT_Y, - NULL, - 0, - 0, - 0, - 0, - TIP_("Direct linked library data-block, click to make local, " - "Shift + Click to create a library override")); - if (disabled) { - UI_but_flag_enable(but, UI_BUT_DISABLED); - } - else { - UI_but_funcN_set( - but, template_id_cb, MEM_dupallocN(template_ui), POINTER_FROM_INT(UI_ID_LOCAL)); - } - } - } - else if (ID_IS_OVERRIDE_LIBRARY(id)) { - but = uiDefIconBut(block, - UI_BTYPE_BUT, - 0, - ICON_LIBRARY_DATA_OVERRIDE, - 0, - 0, - UI_UNIT_X, - UI_UNIT_Y, - NULL, - 0, - 0, - 0, - 0, - TIP_("Library override of linked data-block, click to make fully local")); - UI_but_funcN_set( - but, template_id_cb, MEM_dupallocN(template_ui), POINTER_FROM_INT(UI_ID_OVERRIDE)); - } - - if ((ID_REAL_USERS(id) > 1) && (hide_buttons == false)) { - char numstr[32]; - short numstr_len; - - numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%d", ID_REAL_USERS(id)); - - but = uiDefBut( - block, - UI_BTYPE_BUT, - 0, - numstr, - 0, - 0, - numstr_len * 0.2f * UI_UNIT_X + UI_UNIT_X, - UI_UNIT_Y, - NULL, - 0, - 0, - 0, - 0, - TIP_("Display number of users of this data (click to make a single-user copy)")); - but->flag |= UI_BUT_UNDO; - - UI_but_funcN_set( - but, template_id_cb, MEM_dupallocN(template_ui), POINTER_FROM_INT(UI_ID_ALONE)); - if ((!BKE_id_copy_is_allowed(id)) || (idfrom && idfrom->lib) || (!editable) || - /* object in editmode - don't change data */ - (idfrom && GS(idfrom->name) == ID_OB && (((Object *)idfrom)->mode & OB_MODE_EDIT))) { - UI_but_flag_enable(but, UI_BUT_DISABLED); - } - } - - if (user_alert) { - UI_but_flag_enable(but, UI_BUT_REDALERT); - } - - if (id->lib == NULL && !(ELEM(GS(id->name), ID_GR, ID_SCE, ID_SCR, ID_TXT, ID_OB, ID_WS)) && - (hide_buttons == false)) { - uiDefIconButR(block, - UI_BTYPE_ICON_TOGGLE, - 0, - ICON_FAKE_USER_OFF, - 0, - 0, - UI_UNIT_X, - UI_UNIT_Y, - &idptr, - "use_fake_user", - -1, - 0, - 0, - -1, - -1, - NULL); - } + template_id_name_button(block, type, template_ui, flag, hide_buttons); } - - if ((flag & UI_ID_ADD_NEW) && (hide_buttons == false)) { - template_id_def_new_but( - block, id, template_ui, type, newop, editable, flag & UI_ID_OPEN, false, UI_UNIT_X); + /* If no ID is set, show a "new" button instead of a text button. */ + else if ((flag & UI_ID_ADD_NEW) && (hide_buttons == false)) { + template_id_new_button( + block, id, template_ui, TEMPLATE_ID_CREATE_NEW, type, flag & UI_ID_OPEN, false, UI_UNIT_X); } - /* Due to space limit in UI - skip the "open" icon for packed data, and allow to unpack. - * Only for images, sound and fonts */ - if (id && BKE_packedfile_id_check(id)) { - but = uiDefIconButO(block, - UI_BTYPE_BUT, - "FILE_OT_unpack_item", - WM_OP_INVOKE_REGION_WIN, - ICON_PACKAGE, - 0, - 0, - UI_UNIT_X, - UI_UNIT_Y, - TIP_("Packed File, click to unpack")); - UI_but_operator_ptr_get(but); - - RNA_string_set(but->opptr, "id_name", id->name + 2); - RNA_int_set(but->opptr, "id_type", GS(id->name)); + if ((flag & UI_ID_OPEN) && !id) { + template_id_open_button(block, id, template_ui, flag & UI_ID_ADD_NEW); } - else if (flag & UI_ID_OPEN) { - const int w = id ? UI_UNIT_X : (flag & UI_ID_ADD_NEW) ? UI_UNIT_X * 3 : UI_UNIT_X * 6; - - if (openop) { - but = uiDefIconTextButO(block, - UI_BTYPE_BUT, - openop, - WM_OP_INVOKE_DEFAULT, - ICON_FILEBROWSER, - (id) ? "" : IFACE_("Open"), - 0, - 0, - w, - UI_UNIT_Y, - NULL); - UI_but_funcN_set( - but, template_id_cb, MEM_dupallocN(template_ui), POINTER_FROM_INT(UI_ID_OPEN)); - } - else { - but = uiDefIconTextBut(block, - UI_BTYPE_BUT, - 0, - ICON_FILEBROWSER, - (id) ? "" : IFACE_("Open"), - 0, - 0, - w, - UI_UNIT_Y, - NULL, - 0, - 0, - 0, - 0, - NULL); - UI_but_funcN_set( - but, template_id_cb, MEM_dupallocN(template_ui), POINTER_FROM_INT(UI_ID_OPEN)); - } - if ((idfrom && idfrom->lib) || !editable) { - UI_but_flag_enable(but, UI_BUT_DISABLED); - } + if (template_ui->idcode == ID_TE) { + uiTemplateTextureShow(layout, C, &template_ui->ptr, template_ui->prop); } - /* delete button */ - /* don't use RNA_property_is_unlink here */ - if (id && (flag & UI_ID_DELETE) && (hide_buttons == false)) { - /* allow unlink if 'unlinkop' is passed, even when 'PROP_NEVER_UNLINK' is set */ - but = NULL; - - if (unlinkop) { - but = uiDefIconButO(block, - UI_BTYPE_BUT, - unlinkop, - WM_OP_INVOKE_DEFAULT, - ICON_X, - 0, - 0, - UI_UNIT_X, - UI_UNIT_Y, - NULL); - /* so we can access the template from operators, font unlinking needs this */ - UI_but_funcN_set(but, NULL, MEM_dupallocN(template_ui), NULL); - } - else { - if ((RNA_property_flag(template_ui->prop) & PROP_NEVER_UNLINK) == 0) { - but = uiDefIconBut( - block, - UI_BTYPE_BUT, - 0, - ICON_X, - 0, - 0, - UI_UNIT_X, - UI_UNIT_Y, - NULL, - 0, - 0, - 0, - 0, - TIP_("Unlink data-block " - "(Shift + Click to set users to zero, data will then not be saved)")); - UI_but_funcN_set( - but, template_id_cb, MEM_dupallocN(template_ui), POINTER_FROM_INT(UI_ID_DELETE)); - - if (RNA_property_flag(template_ui->prop) & PROP_NEVER_NULL) { - UI_but_flag_enable(but, UI_BUT_DISABLED); - } - } - } - - if (but) { - if ((idfrom && idfrom->lib) || !editable) { - UI_but_flag_enable(but, UI_BUT_DISABLED); - } - } + if (id && !hide_buttons) { + /* Additional operations menu ("Make Local", overrides, etc). */ + but = uiDefIconMenuBut(block, + template_id_menu, + NULL, + ICON_DOWNARROW_HLT, + 0, + 0, + UI_UNIT_X, + UI_UNIT_Y, + TIP_("Show more operations for the selected data-block")); + UI_but_type_set_menu_from_pulldown(but); + /* Same hack as ui_item_menu() to allow allocated arg. */ + but->poin = (char *)but; + but->func_argN = MEM_dupallocN(template_ui); } - if (template_ui->idcode == ID_TE) { - uiTemplateTextureShow(layout, C, &template_ui->ptr, template_ui->prop); - } UI_block_align_end(block); } @@ -1215,7 +1503,6 @@ static void template_ID_tabs(const bContext *C, TemplateID *template, StructRNA *type, int flag, - const char *newop, const char *menu) { const ARegion *region = CTX_wm_region(C); @@ -1263,22 +1550,20 @@ static void template_ID_tabs(const bContext *C, BLI_freelistN(&ordered); if (flag & UI_ID_ADD_NEW) { - const bool editable = RNA_property_editable(&template->ptr, template->prop); uiBut *but; if (active_ptr.type) { type = active_ptr.type; } - but = template_id_def_new_but(block, - active_ptr.data, - template, - type, - newop, - editable, - flag & UI_ID_OPEN, - true, - but_height); + but = template_id_new_button(block, + active_ptr.data, + template, + TEMPLATE_ID_CREATE_NEW, + type, + flag & UI_ID_OPEN, + true, + but_height); UI_but_drawflag_enable(but, but_align); } } @@ -1288,6 +1573,7 @@ static void ui_template_id(uiLayout *layout, PointerRNA *ptr, const char *propname, const char *newop, + const char *duplicateop, const char *openop, const char *unlinkop, /* Only respected by tabs (use_tabs). */ @@ -1317,6 +1603,10 @@ static void ui_template_id(uiLayout *layout, template_ui = MEM_callocN(sizeof(TemplateID), "TemplateID"); template_ui->ptr = *ptr; template_ui->prop = prop; + template_ui->new_op = newop; + template_ui->duplicate_op = duplicateop; + template_ui->unlink_op = unlinkop; + template_ui->open_op = openop; template_ui->prv_rows = prv_rows; template_ui->prv_cols = prv_cols; template_ui->scale = scale; @@ -1328,7 +1618,7 @@ static void ui_template_id(uiLayout *layout, template_ui->filter = 0; } - if (newop) { + if (newop || duplicateop) { flag |= UI_ID_ADD_NEW; } if (openop) { @@ -1346,21 +1636,11 @@ static void ui_template_id(uiLayout *layout, if (template_ui->idlb) { if (use_tabs) { layout = uiLayoutRow(layout, true); - template_ID_tabs(C, layout, template_ui, type, flag, newop, menu); + template_ID_tabs(C, layout, template_ui, type, flag, menu); } else { layout = uiLayoutRow(layout, true); - template_ID(C, - layout, - template_ui, - type, - flag, - newop, - openop, - unlinkop, - text, - live_icon, - hide_buttons); + template_ID(C, layout, template_ui, type, flag, text, live_icon, hide_buttons); } } @@ -1372,6 +1652,7 @@ void uiTemplateID(uiLayout *layout, PointerRNA *ptr, const char *propname, const char *newop, + const char *duplicateop, const char *openop, const char *unlinkop, int filter, @@ -1383,6 +1664,7 @@ void uiTemplateID(uiLayout *layout, ptr, propname, newop, + duplicateop, openop, unlinkop, NULL, @@ -1412,6 +1694,7 @@ void uiTemplateIDBrowse(uiLayout *layout, ptr, propname, newop, + NULL, openop, unlinkop, NULL, @@ -1443,6 +1726,7 @@ void uiTemplateIDPreview(uiLayout *layout, ptr, propname, newop, + NULL, openop, unlinkop, NULL, @@ -1475,6 +1759,7 @@ void uiTemplateGpencilColorPreview(uiLayout *layout, NULL, NULL, NULL, + NULL, UI_ID_BROWSE | UI_ID_PREVIEWS | UI_ID_DELETE, rows, cols, @@ -1503,6 +1788,7 @@ void uiTemplateIDTabs(uiLayout *layout, newop, NULL, NULL, + NULL, menu, NULL, UI_ID_BROWSE | UI_ID_RENAME, @@ -1662,35 +1948,25 @@ static void template_search_add_button_searchmenu(const bContext *C, static void template_search_add_button_name(uiBlock *block, PointerRNA *active_ptr, - const StructRNA *type) + const StructRNA *type, + const char *newop, + const char *unlinkop) { - uiDefAutoButR(block, - active_ptr, - RNA_struct_name_property(type), - 0, - "", - ICON_NONE, - 0, - 0, - TEMPLATE_SEARCH_TEXTBUT_WIDTH, - TEMPLATE_SEARCH_TEXTBUT_HEIGHT); -} - -static void template_search_add_button_operator(uiBlock *block, - const char *const operator_name, - const int opcontext, - const int icon, - const bool editable) -{ - if (!operator_name) { - return; + uiBut *but = uiDefAutoButR(block, + active_ptr, + RNA_struct_name_property(type), + 0, + "", + ICON_NONE, + 0, + 0, + TEMPLATE_SEARCH_TEXTBUT_WIDTH, + TEMPLATE_SEARCH_TEXTBUT_HEIGHT); + if (newop) { + UI_but_extra_operator_icon_add(but, newop, WM_OP_INVOKE_DEFAULT, ICON_DUPLICATE); } - - uiBut *but = uiDefIconButO( - block, UI_BTYPE_BUT, operator_name, opcontext, icon, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL); - - if (!editable) { - UI_but_drawflag_enable(but, UI_BUT_DISABLED); + if (unlinkop) { + UI_but_extra_operator_icon_add(but, unlinkop, WM_OP_INVOKE_REGION_WIN, ICON_X); } } @@ -1716,10 +1992,7 @@ static void template_search_buttons(const bContext *C, UI_block_align_begin(block); template_search_add_button_searchmenu(C, layout, block, template_search, editable, false); - template_search_add_button_name(block, &active_ptr, type); - template_search_add_button_operator( - block, newop, WM_OP_INVOKE_DEFAULT, ICON_DUPLICATE, editable); - template_search_add_button_operator(block, unlinkop, WM_OP_INVOKE_REGION_WIN, ICON_X, editable); + template_search_add_button_name(block, &active_ptr, type, newop, unlinkop); UI_block_align_end(block); } @@ -7191,6 +7464,7 @@ void uiTemplateCacheFile(uiLayout *layout, ptr, propname, NULL, + NULL, "CACHEFILE_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, diff --git a/source/blender/editors/render/render_intern.h b/source/blender/editors/render/render_intern.h index e1d03e6f3be..e60455667e9 100644 --- a/source/blender/editors/render/render_intern.h +++ b/source/blender/editors/render/render_intern.h @@ -38,8 +38,11 @@ void OBJECT_OT_material_slot_move(struct wmOperatorType *ot); void OBJECT_OT_material_slot_remove_unused(struct wmOperatorType *ot); void MATERIAL_OT_new(struct wmOperatorType *ot); +void MATERIAL_OT_duplicate(struct wmOperatorType *ot); void TEXTURE_OT_new(struct wmOperatorType *ot); +void TEXTURE_OT_duplicate(struct wmOperatorType *ot); void WORLD_OT_new(struct wmOperatorType *ot); +void WORLD_OT_duplicate(struct wmOperatorType *ot); void MATERIAL_OT_copy(struct wmOperatorType *ot); void MATERIAL_OT_paste(struct wmOperatorType *ot); diff --git a/source/blender/editors/render/render_ops.c b/source/blender/editors/render/render_ops.c index e0aa02b354d..48e894036d9 100644 --- a/source/blender/editors/render/render_ops.c +++ b/source/blender/editors/render/render_ops.c @@ -45,8 +45,11 @@ void ED_operatortypes_render(void) WM_operatortype_append(OBJECT_OT_material_slot_remove_unused); WM_operatortype_append(MATERIAL_OT_new); + WM_operatortype_append(MATERIAL_OT_duplicate); WM_operatortype_append(TEXTURE_OT_new); + WM_operatortype_append(TEXTURE_OT_duplicate); WM_operatortype_append(WORLD_OT_new); + WM_operatortype_append(WORLD_OT_duplicate); WM_operatortype_append(MATERIAL_OT_copy); WM_operatortype_append(MATERIAL_OT_paste); diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c index b69337b1621..cac01bdc048 100644 --- a/source/blender/editors/render/render_shading.c +++ b/source/blender/editors/render/render_shading.c @@ -735,45 +735,40 @@ void OBJECT_OT_material_slot_remove_unused(wmOperatorType *ot) /** \} */ /* -------------------------------------------------------------------- */ -/** \name New Material Operator +/** \name Create Material Operators * \{ */ -static int new_material_exec(bContext *C, wmOperator *UNUSED(op)) +struct MaterialCreationData { + Object *ob; + PropertyPointerRNA pprop; +}; + +static void material_creation_data_init_from_UI_context(bContext *C, + struct MaterialCreationData *r_create_data) { - Material *ma = CTX_data_pointer_get_type(C, "material", &RNA_Material).data; - Main *bmain = CTX_data_main(C); - PointerRNA ptr, idptr; + PointerRNA ptr; PropertyRNA *prop; /* hook into UI */ UI_context_active_but_prop_get_templateID(C, &ptr, &prop); - Object *ob = (prop && RNA_struct_is_a(ptr.type, &RNA_Object)) ? ptr.data : NULL; + r_create_data->ob = (prop && RNA_struct_is_a(ptr.type, &RNA_Object)) ? ptr.data : NULL; + r_create_data->pprop.ptr = ptr; + r_create_data->pprop.prop = prop; +} - /* add or copy material */ - if (ma) { - Material *new_ma = (Material *)BKE_id_copy_ex( - bmain, &ma->id, NULL, LIB_ID_COPY_DEFAULT | LIB_ID_COPY_ACTIONS); - ma = new_ma; - } - else { - const char *name = DATA_("Material"); - if (!(ob != NULL && ob->type == OB_GPENCIL)) { - ma = BKE_material_add(bmain, name); - } - else { - ma = BKE_gpencil_material_add(bmain, name); - } - ED_node_shader_default(C, &ma->id); - ma->use_nodes = true; - } +static void material_creation_assign(bContext *C, + Material *ma, + struct MaterialCreationData *create_data) +{ + Main *bmain = CTX_data_main(C); - if (prop) { - if (ob != NULL) { + if (create_data->pprop.prop) { + if (create_data->ob != NULL) { /* Add slot follows user-preferences for creating new slots, * RNA pointer assignment doesn't, see: T60014. */ - if (BKE_object_material_get_p(ob, ob->actcol) == NULL) { - BKE_object_material_slot_add(bmain, ob); + if (BKE_object_material_get_p(create_data->ob, create_data->ob->actcol) == NULL) { + BKE_object_material_slot_add(bmain, create_data->ob); } } @@ -781,10 +776,32 @@ static int new_material_exec(bContext *C, wmOperator *UNUSED(op)) * pointer use also increases user, so this compensates it */ id_us_min(&ma->id); + PointerRNA idptr; RNA_id_pointer_create(&ma->id, &idptr); - RNA_property_pointer_set(&ptr, prop, idptr, NULL); - RNA_property_update(C, &ptr, prop); + RNA_property_pointer_set(&create_data->pprop.ptr, create_data->pprop.prop, idptr, NULL); + RNA_property_update(C, &create_data->pprop.ptr, create_data->pprop.prop); + } +} + +static int new_material_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Main *bmain = CTX_data_main(C); + struct MaterialCreationData create_data; + + material_creation_data_init_from_UI_context(C, &create_data); + + const char *name = DATA_("Material"); + Material *ma; + if ((create_data.ob == NULL) || (create_data.ob->type != OB_GPENCIL)) { + ma = BKE_material_add(bmain, name); + } + else { + ma = BKE_gpencil_material_add(bmain, name); } + ED_node_shader_default(C, &ma->id); + ma->use_nodes = true; + + material_creation_assign(C, ma, &create_data); WM_event_add_notifier(C, NC_MATERIAL | NA_ADDED, ma); @@ -806,27 +823,57 @@ void MATERIAL_OT_new(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; } -/** \} */ +static int duplicate_material_exec(bContext *C, wmOperator *op) +{ + Material *old_ma = CTX_data_pointer_get_type(C, "material", &RNA_Material).data; + + if (!old_ma) { + BKE_report( + op->reports, + RPT_ERROR, + "Incorrect context for duplicating a material (did not find material to duplicate)"); + return OPERATOR_CANCELLED; + } + + Main *bmain = CTX_data_main(C); + struct MaterialCreationData create_data; + + material_creation_data_init_from_UI_context(C, &create_data); + + Material *new_ma = (Material *)BKE_id_copy_ex( + bmain, &old_ma->id, NULL, LIB_ID_COPY_DEFAULT | LIB_ID_COPY_ACTIONS); + + material_creation_assign(C, new_ma, &create_data); + + WM_event_add_notifier(C, NC_MATERIAL | NA_ADDED, new_ma); + + return OPERATOR_FINISHED; +} + +void MATERIAL_OT_duplicate(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Duplicate Material"; + ot->idname = "MATERIAL_OT_duplicate"; + ot->description = "Duplicate an existing material"; + + /* api callbacks */ + ot->exec = duplicate_material_exec; + ot->poll = object_materials_supported_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; +} /* -------------------------------------------------------------------- */ -/** \name New Texture Operator +/** \name Create Texture Operators * \{ */ -static int new_texture_exec(bContext *C, wmOperator *UNUSED(op)) +static void texture_creation_assign(bContext *C, Tex *tex) { - Tex *tex = CTX_data_pointer_get_type(C, "texture", &RNA_Texture).data; - Main *bmain = CTX_data_main(C); PointerRNA ptr, idptr; PropertyRNA *prop; - /* add or copy texture */ - if (tex) { - tex = (Tex *)BKE_id_copy(bmain, &tex->id); - } - else { - tex = BKE_texture_add(bmain, DATA_("Texture")); - } - /* hook into UI */ UI_context_active_but_prop_get_templateID(C, &ptr, &prop); @@ -839,6 +886,14 @@ static int new_texture_exec(bContext *C, wmOperator *UNUSED(op)) RNA_property_pointer_set(&ptr, prop, idptr, NULL); RNA_property_update(C, &ptr, prop); } +} + +static int new_texture_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Main *bmain = CTX_data_main(C); + Tex *tex = BKE_texture_add(bmain, DATA_("Texture")); + + texture_creation_assign(C, tex); WM_event_add_notifier(C, NC_TEXTURE | NA_ADDED, tex); @@ -859,31 +914,53 @@ void TEXTURE_OT_new(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; } +static int duplicate_texture_exec(bContext *C, wmOperator *op) +{ + Tex *tex = CTX_data_pointer_get_type(C, "texture", &RNA_Texture).data; + + if (!tex) { + BKE_report(op->reports, + RPT_ERROR, + "Incorrect context for duplicating a texture (did not find texture to duplicate)"); + return OPERATOR_CANCELLED; + } + + /* add or copy texture */ + Main *bmain = CTX_data_main(C); + tex = (Tex *)BKE_id_copy(bmain, &tex->id); + + texture_creation_assign(C, tex); + + WM_event_add_notifier(C, NC_TEXTURE | NA_ADDED, tex); + + return OPERATOR_FINISHED; +} + +void TEXTURE_OT_duplicate(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Duplicate Texture"; + ot->idname = "TEXTURE_OT_duplicate"; + ot->description = "Duplicate an existing texture"; + + /* api callbacks */ + ot->exec = duplicate_texture_exec; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; +} + /** \} */ /* -------------------------------------------------------------------- */ -/** \name new world operator +/** \name Create world operators * \{ */ -static int new_world_exec(bContext *C, wmOperator *UNUSED(op)) +static void world_creation_assign(bContext *C, World *wo) { - World *wo = CTX_data_pointer_get_type(C, "world", &RNA_World).data; - Main *bmain = CTX_data_main(C); PointerRNA ptr, idptr; PropertyRNA *prop; - /* add or copy world */ - if (wo) { - World *new_wo = (World *)BKE_id_copy_ex( - bmain, &wo->id, NULL, LIB_ID_COPY_DEFAULT | LIB_ID_COPY_ACTIONS); - wo = new_wo; - } - else { - wo = BKE_world_add(bmain, DATA_("World")); - ED_node_shader_default(C, &wo->id); - wo->use_nodes = true; - } - /* hook into UI */ UI_context_active_but_prop_get_templateID(C, &ptr, &prop); @@ -896,6 +973,17 @@ static int new_world_exec(bContext *C, wmOperator *UNUSED(op)) RNA_property_pointer_set(&ptr, prop, idptr, NULL); RNA_property_update(C, &ptr, prop); } +} + +static int new_world_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Main *bmain = CTX_data_main(C); + + World *wo = BKE_world_add(bmain, DATA_("World")); + ED_node_shader_default(C, &wo->id); + wo->use_nodes = true; + + world_creation_assign(C, wo); WM_event_add_notifier(C, NC_WORLD | NA_ADDED, wo); @@ -907,7 +995,7 @@ void WORLD_OT_new(wmOperatorType *ot) /* identifiers */ ot->name = "New World"; ot->idname = "WORLD_OT_new"; - ot->description = "Create a new world Data-Block"; + ot->description = "Create a new world data-block"; /* api callbacks */ ot->exec = new_world_exec; @@ -916,6 +1004,36 @@ void WORLD_OT_new(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; } +static int duplicate_world_exec(bContext *C, wmOperator *UNUSED(op)) +{ + World *wo = CTX_data_pointer_get_type(C, "world", &RNA_World).data; + + if (wo) { + Main *bmain = CTX_data_main(C); + wo = (World *)BKE_id_copy(bmain, &wo->id); + } + + world_creation_assign(C, wo); + + WM_event_add_notifier(C, NC_WORLD | NA_ADDED, wo); + + return OPERATOR_FINISHED; +} + +void WORLD_OT_duplicate(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Duplicate World"; + ot->idname = "WORLD_OT_duplicate"; + ot->description = "Duplicate an existing world data-block"; + + /* api callbacks */ + ot->exec = duplicate_world_exec; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; +} + /** \} */ /* -------------------------------------------------------------------- */ diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 51687d5de1d..8768404d74f 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -5509,7 +5509,6 @@ void ED_operatortypes_screen(void) WM_operatortype_append(ED_OT_undo_redo); WM_operatortype_append(ED_OT_undo_history); - WM_operatortype_append(ED_OT_flush_edits); WM_operatortype_append(ED_OT_lib_id_load_custom_preview); WM_operatortype_append(ED_OT_lib_id_generate_preview); } diff --git a/source/blender/editors/space_action/action_data.c b/source/blender/editors/space_action/action_data.c index 3a584a7f0cb..4d5a93f75e0 100644 --- a/source/blender/editors/space_action/action_data.c +++ b/source/blender/editors/space_action/action_data.c @@ -158,7 +158,78 @@ static void actedit_change_action(bContext *C, bAction *act) RNA_property_update(C, &ptr, prop); } -/* ******************** New Action Operator *********************** */ +/* ******************** New Action Operators *********************** */ + +static void action_creation_assign(bContext *C, + bAction *action, + PointerRNA *ptr, + PropertyRNA *prop) +{ + PointerRNA idptr; + /* Set the new action. + * NOTE: we can't use actedit_change_action, as this function is also called from the NLA. */ + RNA_id_pointer_create(&action->id, &idptr); + RNA_property_pointer_set(ptr, prop, idptr, NULL); + RNA_property_update(C, ptr, prop); +} + +/** + * Stash the previously active action to prevent it from being lost. + * \return The old action if any. + */ +static bAction *action_creation_stash_old(bContext *C, PointerRNA *ptr, PropertyRNA *prop) +{ + bAction *oldact = NULL; + AnimData *adt = NULL; + + if (prop) { + /* The operator was called from a button. */ + PointerRNA oldptr; + + oldptr = RNA_property_pointer_get(ptr, prop); + oldact = (bAction *)oldptr.owner_id; + + /* stash the old action to prevent it from being lost */ + if (ptr->type == &RNA_AnimData) { + adt = ptr->data; + } + else if (ptr->type == &RNA_SpaceDopeSheetEditor) { + adt = ED_actedit_animdata_from_context(C); + } + } + else { + adt = ED_actedit_animdata_from_context(C); + oldact = adt->action; + } + + if (!adt || !oldact) { + /* Found nothing to stash in current context. */ + return NULL; + } + + /* Perform stashing operation. */ + if (BKE_nla_action_stash(adt, ID_IS_OVERRIDE_LIBRARY(ptr->owner_id))) { + /* The stash operation will remove the user already + * (and unlink the action from the AnimData action slot). + * Hence, we must unset the ref to the action in the + * action editor too (if this is where we're being called from) + * first before setting the new action once it is created, + * or else the user gets decremented twice! + */ + if (ptr->type == &RNA_SpaceDopeSheetEditor) { + SpaceAction *saction = ptr->data; + saction->action = NULL; + } + } + else { +#if 0 + printf("WARNING: Failed to stash %s. It may already exist in the NLA stack though\n", + oldact->id.name); +#endif + } + + return oldact; +} /* Criteria: * 1) There must be an dopesheet/action editor, and it must be in a mode which uses actions... @@ -207,71 +278,17 @@ static bool action_new_poll(bContext *C) static int action_new_exec(bContext *C, wmOperator *UNUSED(op)) { - PointerRNA ptr, idptr; + PointerRNA ptr; PropertyRNA *prop; - bAction *oldact = NULL; - AnimData *adt = NULL; /* hook into UI */ UI_context_active_but_prop_get_templateID(C, &ptr, &prop); - if (prop) { - /* The operator was called from a button. */ - PointerRNA oldptr; - - oldptr = RNA_property_pointer_get(&ptr, prop); - oldact = (bAction *)oldptr.owner_id; - - /* stash the old action to prevent it from being lost */ - if (ptr.type == &RNA_AnimData) { - adt = ptr.data; - } - else if (ptr.type == &RNA_SpaceDopeSheetEditor) { - adt = ED_actedit_animdata_from_context(C); - } - } - else { - adt = ED_actedit_animdata_from_context(C); - oldact = adt->action; - } - { - bAction *action = NULL; - - /* Perform stashing operation - But only if there is an action */ - if (adt && oldact) { - /* stash the action */ - if (BKE_nla_action_stash(adt, ID_IS_OVERRIDE_LIBRARY(ptr.owner_id))) { - /* The stash operation will remove the user already - * (and unlink the action from the AnimData action slot). - * Hence, we must unset the ref to the action in the - * action editor too (if this is where we're being called from) - * first before setting the new action once it is created, - * or else the user gets decremented twice! - */ - if (ptr.type == &RNA_SpaceDopeSheetEditor) { - SpaceAction *saction = ptr.data; - saction->action = NULL; - } - } - else { -#if 0 - printf("WARNING: Failed to stash %s. It may already exist in the NLA stack though\n", - oldact->id.name); -#endif - } - } - - /* create action */ - action = action_create_new(C, oldact); + action_creation_stash_old(C, &ptr, prop); - if (prop) { - /* set this new action - * NOTE: we can't use actedit_change_action, as this function is also called from the NLA - */ - RNA_id_pointer_create(&action->id, &idptr); - RNA_property_pointer_set(&ptr, prop, idptr, NULL); - RNA_property_update(C, &ptr, prop); - } + bAction *action = action_create_new(C, NULL); + if (prop) { + action_creation_assign(C, action, &ptr, prop); } /* set notifier that keyframes have changed */ @@ -285,7 +302,7 @@ void ACTION_OT_new(wmOperatorType *ot) /* identifiers */ ot->name = "New Action"; ot->idname = "ACTION_OT_new"; - ot->description = "Create new action"; + ot->description = "Create a new action"; /* api callbacks */ ot->exec = action_new_exec; @@ -295,6 +312,45 @@ void ACTION_OT_new(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +static int action_duplicate_assign_exec(bContext *C, wmOperator *UNUSED(op)) +{ + PointerRNA ptr; + PropertyRNA *prop; + + /* hook into UI */ + UI_context_active_but_prop_get_templateID(C, &ptr, &prop); + + bAction *old_action = action_creation_stash_old(C, &ptr, prop); + + bAction *new_action = action_create_new(C, old_action); + if (prop) { + action_creation_assign(C, new_action, &ptr, prop); + } + + /* set notifier that keyframes have changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_ADDED, NULL); + + return OPERATOR_FINISHED; +} + +/** + * Duplicate an action assigned to a templateID and update it's assignment - based on UI context. + */ +void ACTION_OT_duplicate_assign(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Duplicate & Assign Action"; + ot->idname = "ACTION_OT_duplicate_assign"; + ot->description = "Create a copy of an existing action and assign it"; + + /* api callbacks */ + ot->exec = action_duplicate_assign_exec; + ot->poll = action_new_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; +} + /* ******************* Action Push-Down Operator ******************** */ /* Criteria: diff --git a/source/blender/editors/space_action/action_intern.h b/source/blender/editors/space_action/action_intern.h index ffe0606c98f..4bce6c62a1a 100644 --- a/source/blender/editors/space_action/action_intern.h +++ b/source/blender/editors/space_action/action_intern.h @@ -106,6 +106,7 @@ void ACTION_OT_snap(struct wmOperatorType *ot); void ACTION_OT_mirror(struct wmOperatorType *ot); void ACTION_OT_new(struct wmOperatorType *ot); +void ACTION_OT_duplicate_assign(struct wmOperatorType *ot); void ACTION_OT_unlink(struct wmOperatorType *ot); void ACTION_OT_push_down(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_action/action_ops.c b/source/blender/editors/space_action/action_ops.c index 7422c05511c..329c3a9f6f6 100644 --- a/source/blender/editors/space_action/action_ops.c +++ b/source/blender/editors/space_action/action_ops.c @@ -73,7 +73,9 @@ void action_operatortypes(void) WM_operatortype_append(ACTION_OT_copy); WM_operatortype_append(ACTION_OT_paste); + /* UI-context based operators. */ WM_operatortype_append(ACTION_OT_new); + WM_operatortype_append(ACTION_OT_duplicate_assign); WM_operatortype_append(ACTION_OT_unlink); WM_operatortype_append(ACTION_OT_push_down); diff --git a/source/blender/editors/space_api/spacetypes.c b/source/blender/editors/space_api/spacetypes.c index 0fe94ec382c..10fa2c19919 100644 --- a/source/blender/editors/space_api/spacetypes.c +++ b/source/blender/editors/space_api/spacetypes.c @@ -65,6 +65,7 @@ #include "ED_space_api.h" #include "ED_transform.h" #include "ED_userpref.h" +#include "ED_util.h" #include "ED_uvedit.h" #include "io_ops.h" @@ -124,6 +125,7 @@ void ED_spacetypes_init(void) ED_operatortypes_render(); ED_operatortypes_mask(); ED_operatortypes_io(); + ED_operatortypes_edutils(); ED_operatortypes_view2d(); ED_operatortypes_ui(); diff --git a/source/blender/editors/space_clip/clip_buttons.c b/source/blender/editors/space_clip/clip_buttons.c index a95d0e3ea88..e0f603eb3d1 100644 --- a/source/blender/editors/space_clip/clip_buttons.c +++ b/source/blender/editors/space_clip/clip_buttons.c @@ -140,6 +140,7 @@ void uiTemplateMovieClip( ptr, propname, NULL, + NULL, "CLIP_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, diff --git a/source/blender/editors/space_file/file_panels.c b/source/blender/editors/space_file/file_panels.c index afa85d183d8..411f99cc3b4 100644 --- a/source/blender/editors/space_file/file_panels.c +++ b/source/blender/editors/space_file/file_panels.c @@ -180,11 +180,16 @@ static void file_panel_execution_buttons_draw(const bContext *C, Panel *panel) UI_but_funcN_set(but, file_filename_enter_handle, NULL, but); if (params->flag & FILE_CHECK_EXISTING) { - but_extra_rna_ptr = UI_but_extra_operator_icon_add( + uiButExtraOpIcon *extra_icon; + + extra_icon = UI_but_extra_operator_icon_add( but, "FILE_OT_filenum", WM_OP_EXEC_REGION_WIN, ICON_REMOVE); + but_extra_rna_ptr = UI_but_extra_operator_icon_opptr_get(extra_icon); RNA_int_set(but_extra_rna_ptr, "increment", -1); - but_extra_rna_ptr = UI_but_extra_operator_icon_add( + + extra_icon = UI_but_extra_operator_icon_add( but, "FILE_OT_filenum", WM_OP_EXEC_REGION_WIN, ICON_ADD); + but_extra_rna_ptr = UI_but_extra_operator_icon_opptr_get(extra_icon); RNA_int_set(but_extra_rna_ptr, "increment", 1); } diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c index c0c0280959c..f8f25e399eb 100644 --- a/source/blender/editors/space_image/image_buttons.c +++ b/source/blender/editors/space_image/image_buttons.c @@ -806,7 +806,8 @@ void uiTemplateImage(uiLayout *layout, C, ptr, propname, - ima ? NULL : "IMAGE_OT_new", + "IMAGE_OT_new", + NULL, "IMAGE_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, diff --git a/source/blender/editors/space_nla/nla_buttons.c b/source/blender/editors/space_nla/nla_buttons.c index 083fd641dc1..1d7e5448b92 100644 --- a/source/blender/editors/space_nla/nla_buttons.c +++ b/source/blender/editors/space_nla/nla_buttons.c @@ -292,8 +292,9 @@ static void nla_panel_animdata(const bContext *C, Panel *panel) (bContext *)C, &adt_ptr, "action", - "ACTION_OT_new", NULL, + "ACTION_OT_new", + "ACTION_OT_duplicate_assign", "NLA_OT_action_unlink", UI_TEMPLATE_ID_FILTER_ALL, false, diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 652c70155ab..421e66604e4 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -771,6 +771,7 @@ static void node_shader_buts_tex_image(uiLayout *layout, bContext *C, PointerRNA ptr, "image", "IMAGE_OT_new", + NULL, "IMAGE_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, @@ -808,6 +809,7 @@ static void node_shader_buts_tex_environment(uiLayout *layout, bContext *C, Poin ptr, "image", "IMAGE_OT_new", + NULL, "IMAGE_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, @@ -1395,6 +1397,7 @@ static void node_composit_buts_image(uiLayout *layout, bContext *C, PointerRNA * ptr, "image", "IMAGE_OT_new", + NULL, "IMAGE_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, @@ -1426,7 +1429,8 @@ static void node_composit_buts_viewlayers(uiLayout *layout, bContext *C, Pointer bNode *node = ptr->data; uiLayout *col, *row; - uiTemplateID(layout, C, ptr, "scene", NULL, NULL, NULL, UI_TEMPLATE_ID_FILTER_ALL, false, NULL); + uiTemplateID( + layout, C, ptr, "scene", NULL, NULL, NULL, NULL, UI_TEMPLATE_ID_FILTER_ALL, false, NULL); if (!node->id) { return; @@ -1548,7 +1552,8 @@ static void node_composit_buts_defocus(uiLayout *layout, bContext *C, PointerRNA col = uiLayoutColumn(layout, false); uiItemR(col, ptr, "use_preview", DEFAULT_FLAGS, NULL, ICON_NONE); - uiTemplateID(layout, C, ptr, "scene", NULL, NULL, NULL, UI_TEMPLATE_ID_FILTER_ALL, false, NULL); + uiTemplateID( + layout, C, ptr, "scene", NULL, NULL, NULL, NULL, UI_TEMPLATE_ID_FILTER_ALL, false, NULL); col = uiLayoutColumn(layout, false); uiItemR(col, ptr, "use_zbuffer", DEFAULT_FLAGS, NULL, ICON_NONE); @@ -2163,8 +2168,17 @@ static void node_composit_buts_ycc(uiLayout *layout, bContext *UNUSED(C), Pointe static void node_composit_buts_movieclip(uiLayout *layout, bContext *C, PointerRNA *ptr) { - uiTemplateID( - layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false, NULL); + uiTemplateID(layout, + C, + ptr, + "clip", + NULL, + NULL, + "CLIP_OT_open", + NULL, + UI_TEMPLATE_ID_FILTER_ALL, + false, + NULL); } static void node_composit_buts_movieclip_ex(uiLayout *layout, bContext *C, PointerRNA *ptr) @@ -2172,8 +2186,17 @@ static void node_composit_buts_movieclip_ex(uiLayout *layout, bContext *C, Point bNode *node = ptr->data; PointerRNA clipptr; - uiTemplateID( - layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false, NULL); + uiTemplateID(layout, + C, + ptr, + "clip", + NULL, + NULL, + "CLIP_OT_open", + NULL, + UI_TEMPLATE_ID_FILTER_ALL, + false, + NULL); if (!node->id) { return; @@ -2188,8 +2211,17 @@ static void node_composit_buts_stabilize2d(uiLayout *layout, bContext *C, Pointe { bNode *node = ptr->data; - uiTemplateID( - layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false, NULL); + uiTemplateID(layout, + C, + ptr, + "clip", + NULL, + NULL, + "CLIP_OT_open", + NULL, + UI_TEMPLATE_ID_FILTER_ALL, + false, + NULL); if (!node->id) { return; @@ -2214,8 +2246,17 @@ static void node_composit_buts_moviedistortion(uiLayout *layout, bContext *C, Po { bNode *node = ptr->data; - uiTemplateID( - layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false, NULL); + uiTemplateID(layout, + C, + ptr, + "clip", + NULL, + NULL, + "CLIP_OT_open", + NULL, + UI_TEMPLATE_ID_FILTER_ALL, + false, + NULL); if (!node->id) { return; @@ -2538,7 +2579,8 @@ static void node_composit_buts_mask(uiLayout *layout, bContext *C, PointerRNA *p { bNode *node = ptr->data; - uiTemplateID(layout, C, ptr, "mask", NULL, NULL, NULL, UI_TEMPLATE_ID_FILTER_ALL, false, NULL); + uiTemplateID( + layout, C, ptr, "mask", NULL, NULL, NULL, NULL, UI_TEMPLATE_ID_FILTER_ALL, false, NULL); uiItemR(layout, ptr, "use_feather", DEFAULT_FLAGS, NULL, ICON_NONE); uiItemR(layout, ptr, "size_source", DEFAULT_FLAGS, "", ICON_NONE); @@ -2559,7 +2601,8 @@ static void node_composit_buts_keyingscreen(uiLayout *layout, bContext *C, Point { bNode *node = ptr->data; - uiTemplateID(layout, C, ptr, "clip", NULL, NULL, NULL, UI_TEMPLATE_ID_FILTER_ALL, false, NULL); + uiTemplateID( + layout, C, ptr, "clip", NULL, NULL, NULL, NULL, UI_TEMPLATE_ID_FILTER_ALL, false, NULL); if (node->id) { MovieClip *clip = (MovieClip *)node->id; @@ -2595,8 +2638,17 @@ static void node_composit_buts_trackpos(uiLayout *layout, bContext *C, PointerRN { bNode *node = ptr->data; - uiTemplateID( - layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false, NULL); + uiTemplateID(layout, + C, + ptr, + "clip", + NULL, + NULL, + "CLIP_OT_open", + NULL, + UI_TEMPLATE_ID_FILTER_ALL, + false, + NULL); if (node->id) { MovieClip *clip = (MovieClip *)node->id; @@ -2636,8 +2688,17 @@ static void node_composit_buts_planetrackdeform(uiLayout *layout, bContext *C, P bNode *node = ptr->data; NodePlaneTrackDeformData *data = node->storage; - uiTemplateID( - layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false, NULL); + uiTemplateID(layout, + C, + ptr, + "clip", + NULL, + NULL, + "CLIP_OT_open", + NULL, + UI_TEMPLATE_ID_FILTER_ALL, + false, + NULL); if (node->id) { MovieClip *clip = (MovieClip *)node->id; @@ -3072,6 +3133,7 @@ static void node_texture_buts_image(uiLayout *layout, bContext *C, PointerRNA *p ptr, "image", "IMAGE_OT_new", + NULL, "IMAGE_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, diff --git a/source/blender/editors/util/CMakeLists.txt b/source/blender/editors/util/CMakeLists.txt index bbaf5d5475a..0aab3810254 100644 --- a/source/blender/editors/util/CMakeLists.txt +++ b/source/blender/editors/util/CMakeLists.txt @@ -39,6 +39,7 @@ set(SRC ed_transverts.c ed_util.c ed_util_imbuf.c + ed_util_ops.c gizmo_utils.c numinput.c select_utils.c diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c index d78758dcc1c..5d2584c566d 100644 --- a/source/blender/editors/util/ed_util.c +++ b/source/blender/editors/util/ed_util.c @@ -485,27 +485,6 @@ void ED_spacedata_id_remap(struct ScrArea *area, struct SpaceLink *sl, ID *old_i } } -static int ed_flush_edits_exec(bContext *C, wmOperator *UNUSED(op)) -{ - Main *bmain = CTX_data_main(C); - ED_editors_flush_edits(bmain); - return OPERATOR_FINISHED; -} - -void ED_OT_flush_edits(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Flush Edits"; - ot->description = "Flush edit data from active editing modes"; - ot->idname = "ED_OT_flush_edits"; - - /* api callbacks */ - ot->exec = ed_flush_edits_exec; - - /* flags */ - ot->flag = OPTYPE_INTERNAL; -} - static bool lib_id_preview_editing_poll(bContext *C) { const PointerRNA idptr = CTX_data_pointer_get(C, "id"); diff --git a/source/blender/editors/util/ed_util_ops.c b/source/blender/editors/util/ed_util_ops.c new file mode 100644 index 00000000000..d8d1a64c1ee --- /dev/null +++ b/source/blender/editors/util/ed_util_ops.c @@ -0,0 +1,155 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** \file + * \ingroup edutil + * + * Utility operators for UI data or for the UI to use. + */ + +#include + +#include "BLI_utildefines.h" + +#include "BKE_context.h" +#include "BKE_lib_id.h" +#include "BKE_main.h" +#include "BKE_report.h" + +#include "DNA_windowmanager_types.h" + +#include "ED_util.h" + +#include "RNA_access.h" + +#include "UI_interface.h" + +#include "WM_api.h" +#include "WM_types.h" + +static int lib_fake_user_toggle_exec(bContext *C, wmOperator *op) +{ + PropertyPointerRNA pprop; + PointerRNA idptr = PointerRNA_NULL; + + UI_context_active_but_prop_get_templateID(C, &pprop.ptr, &pprop.prop); + + if (pprop.prop) { + idptr = RNA_property_pointer_get(&pprop.ptr, pprop.prop); + } + + if ((pprop.prop == NULL) || RNA_pointer_is_null(&idptr) || !RNA_struct_is_ID(idptr.type)) { + BKE_report( + op->reports, RPT_ERROR, "Incorrect context for running data-block fake user toggling"); + return OPERATOR_CANCELLED; + } + + ID *id = idptr.data; + + if ((id->lib != NULL) || (ELEM(GS(id->name), ID_GR, ID_SCE, ID_SCR, ID_TXT, ID_OB, ID_WS))) { + BKE_report(op->reports, RPT_ERROR, "Data-block type does not support fake user"); + return OPERATOR_CANCELLED; + } + + if (ID_FAKE_USERS(id)) { + id_fake_user_clear(id); + } + else { + id_fake_user_set(id); + } + + return OPERATOR_FINISHED; +} + +static void ED_OT_lib_fake_user_toggle(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Toggle Fake User"; + ot->description = "Save this data-block even if it has no users"; + ot->idname = "ED_OT_lib_fake_user_toggle"; + + /* api callbacks */ + ot->exec = lib_fake_user_toggle_exec; + + /* flags */ + ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL; +} + +static int lib_unlink_exec(bContext *C, wmOperator *op) +{ + PropertyPointerRNA pprop; + PointerRNA idptr; + + UI_context_active_but_prop_get_templateID(C, &pprop.ptr, &pprop.prop); + + if (pprop.prop) { + idptr = RNA_property_pointer_get(&pprop.ptr, pprop.prop); + } + + if ((pprop.prop == NULL) || RNA_pointer_is_null(&idptr) || !RNA_struct_is_ID(idptr.type)) { + BKE_report( + op->reports, RPT_ERROR, "Incorrect context for running data-block fake user toggling"); + return OPERATOR_CANCELLED; + } + + memset(&idptr, 0, sizeof(idptr)); + RNA_property_pointer_set(&pprop.ptr, pprop.prop, idptr, NULL); + RNA_property_update(C, &pprop.ptr, pprop.prop); + + return OPERATOR_FINISHED; +} + +static void ED_OT_lib_unlink(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Unlink Data-Block"; + ot->description = "Remove a usage of a data-block, clearing the assignment"; + ot->idname = "ED_OT_lib_unlink"; + + /* api callbacks */ + ot->exec = lib_unlink_exec; + + /* flags */ + ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL; +} + +static int ed_flush_edits_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Main *bmain = CTX_data_main(C); + ED_editors_flush_edits(bmain); + return OPERATOR_FINISHED; +} + +static void ED_OT_flush_edits(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Flush Edits"; + ot->description = "Flush edit data from active editing modes"; + ot->idname = "ED_OT_flush_edits"; + + /* api callbacks */ + ot->exec = ed_flush_edits_exec; + + /* flags */ + ot->flag = OPTYPE_INTERNAL; +} + +void ED_operatortypes_edutils(void) +{ + WM_operatortype_append(ED_OT_lib_fake_user_toggle); + WM_operatortype_append(ED_OT_lib_unlink); + WM_operatortype_append(ED_OT_flush_edits); +} diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c index 447f5b4210b..e26cc8d8d41 100644 --- a/source/blender/makesrna/intern/rna_ui_api.c +++ b/source/blender/makesrna/intern/rna_ui_api.c @@ -480,6 +480,7 @@ static void rna_uiTemplateID(uiLayout *layout, PointerRNA *ptr, const char *propname, const char *newop, + const char *duplicateop, const char *openop, const char *unlinkop, int filter, @@ -498,7 +499,8 @@ static void rna_uiTemplateID(uiLayout *layout, /* Get translated name (label). */ name = rna_translate_ui_text(name, text_ctxt, NULL, prop, translate); - uiTemplateID(layout, C, ptr, propname, newop, openop, unlinkop, filter, live_icon, name); + uiTemplateID( + layout, C, ptr, propname, newop, duplicateop, openop, unlinkop, filter, live_icon, name); } static void rna_uiTemplateAnyID(uiLayout *layout, @@ -1155,9 +1157,12 @@ void RNA_api_ui_layout(StructRNA *srna) RNA_def_function_flag(func, FUNC_USE_CONTEXT); api_ui_item_rna_common(func); RNA_def_string(func, "new", NULL, 0, "", "Operator identifier to create a new ID block"); + RNA_def_string( + func, "duplicate", NULL, 0, "", "Operator identifier to duplicate the selected ID block"); RNA_def_string( func, "open", NULL, 0, "", "Operator identifier to open a file for creating a new ID block"); - RNA_def_string(func, "unlink", NULL, 0, "", "Operator identifier to unlink the ID block"); + RNA_def_string( + func, "unlink", NULL, 0, "", "Operator identifier to unlink the selected ID block"); RNA_def_enum(func, "filter", id_template_filter_items, diff --git a/source/blender/modifiers/intern/MOD_displace.c b/source/blender/modifiers/intern/MOD_displace.c index abe78943508..5359736d9fc 100644 --- a/source/blender/modifiers/intern/MOD_displace.c +++ b/source/blender/modifiers/intern/MOD_displace.c @@ -437,7 +437,7 @@ static void panel_draw(const bContext *C, Panel *panel) uiLayoutSetPropSep(layout, true); - uiTemplateID(layout, C, ptr, "texture", "texture.new", NULL, NULL, 0, ICON_NONE, NULL); + uiTemplateID(layout, C, ptr, "texture", "texture.new", NULL, NULL, NULL, 0, ICON_NONE, NULL); col = uiLayoutColumn(layout, false); uiLayoutSetActive(col, has_texture); diff --git a/source/blender/modifiers/intern/MOD_nodes.cc b/source/blender/modifiers/intern/MOD_nodes.cc index 9730f734a17..133a19dde9e 100644 --- a/source/blender/modifiers/intern/MOD_nodes.cc +++ b/source/blender/modifiers/intern/MOD_nodes.cc @@ -1031,6 +1031,7 @@ static void panel_draw(const bContext *C, Panel *panel) "node.new_geometry_node_group_assign", nullptr, nullptr, + nullptr, 0, false, nullptr); diff --git a/source/blender/modifiers/intern/MOD_volume_displace.cc b/source/blender/modifiers/intern/MOD_volume_displace.cc index 745e089b8ff..a916eff6617 100644 --- a/source/blender/modifiers/intern/MOD_volume_displace.cc +++ b/source/blender/modifiers/intern/MOD_volume_displace.cc @@ -113,7 +113,8 @@ static void panel_draw(const bContext *C, Panel *panel) uiLayoutSetPropSep(layout, true); - uiTemplateID(layout, C, ptr, "texture", "texture.new", nullptr, nullptr, 0, ICON_NONE, nullptr); + uiTemplateID( + layout, C, ptr, "texture", "texture.new", nullptr, nullptr, nullptr, 0, ICON_NONE, nullptr); uiItemR(layout, ptr, "texture_map_mode", 0, "Texture Mapping", ICON_NONE); if (vdmd->texture_map_mode == MOD_VOLUME_DISPLACE_MAP_OBJECT) { diff --git a/source/blender/modifiers/intern/MOD_warp.c b/source/blender/modifiers/intern/MOD_warp.c index 9d3d5b0658c..8ad15edff93 100644 --- a/source/blender/modifiers/intern/MOD_warp.c +++ b/source/blender/modifiers/intern/MOD_warp.c @@ -466,7 +466,17 @@ static void texture_panel_draw(const bContext *C, Panel *panel) int texture_coords = RNA_enum_get(ptr, "texture_coords"); - uiTemplateID(layout, C, ptr, "texture", "texture.new", NULL, NULL, 0, ICON_NONE, NULL); + uiTemplateID(layout, + C, + ptr, + "texture", + "texture.new", + "texture.duplicate", + NULL, + NULL, + 0, + ICON_NONE, + NULL); uiLayoutSetPropSep(layout, true); diff --git a/source/blender/modifiers/intern/MOD_wave.c b/source/blender/modifiers/intern/MOD_wave.c index 863656b85a5..94d8a80f2b4 100644 --- a/source/blender/modifiers/intern/MOD_wave.c +++ b/source/blender/modifiers/intern/MOD_wave.c @@ -436,7 +436,17 @@ static void texture_panel_draw(const bContext *C, Panel *panel) int texture_coords = RNA_enum_get(ptr, "texture_coords"); - uiTemplateID(layout, C, ptr, "texture", "texture.new", NULL, NULL, 0, ICON_NONE, NULL); + uiTemplateID(layout, + C, + ptr, + "texture", + "texture.new", + "texture.duplicate", + NULL, + NULL, + 0, + ICON_NONE, + NULL); uiLayoutSetPropSep(layout, true); diff --git a/source/blender/modifiers/intern/MOD_weightvg_util.c b/source/blender/modifiers/intern/MOD_weightvg_util.c index c5e2ecb9660..26b29100d30 100644 --- a/source/blender/modifiers/intern/MOD_weightvg_util.c +++ b/source/blender/modifiers/intern/MOD_weightvg_util.c @@ -363,6 +363,7 @@ void weightvg_ui_common(const bContext *C, PointerRNA *ob_ptr, PointerRNA *ptr, ptr, "mask_texture", "texture.new", + "texture.duplicate", NULL, NULL, 0, diff --git a/source/blender/windowmanager/intern/wm_operator_type.c b/source/blender/windowmanager/intern/wm_operator_type.c index 4c4fd2b1a8e..f5cdd4490cb 100644 --- a/source/blender/windowmanager/intern/wm_operator_type.c +++ b/source/blender/windowmanager/intern/wm_operator_type.c @@ -596,7 +596,7 @@ char *WM_operatortype_description(struct bContext *C, struct wmOperatorType *ot, struct PointerRNA *properties) { - if (ot->get_description && properties) { + if (C && ot->get_description && properties) { char *description = ot->get_description(C, ot, properties); if (description) { -- cgit v1.2.3 From 6be9747b9622e9ea0bacdc7f94b4f575feb659aa Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Fri, 18 Dec 2020 12:12:32 -0600 Subject: Cleanup: Use bool instead of int --- source/blender/editors/interface/interface_layout.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index 4b19b8f97f4..b3c34b3fb43 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -5485,8 +5485,8 @@ uiLayout *UI_block_layout(uiBlock *block, layout->y = y; layout->root = root; layout->space = style->templatespace; - layout->active = 1; - layout->enabled = 1; + layout->active = true; + layout->enabled = true; layout->context = NULL; layout->emboss = UI_EMBOSS_UNDEFINED; -- cgit v1.2.3 From e2983392894e380203966e49b2caa3807a661eb9 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Fri, 18 Dec 2020 12:39:50 -0600 Subject: Cleanup: Declare variables where initialized Also decrease scope of some variable declarations. --- .../blender/editors/interface/interface_layout.c | 183 ++++++++------------- 1 file changed, 71 insertions(+), 112 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index b3c34b3fb43..3b366688e59 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -3457,8 +3457,6 @@ static void menu_item_enum_rna_menu(bContext *UNUSED(C), uiLayout *layout, void void uiItemMenuEnumR_prop( uiLayout *layout, struct PointerRNA *ptr, PropertyRNA *prop, const char *name, int icon) { - MenuItemLevel *lvl; - if (!name) { name = RNA_property_ui_name(prop); } @@ -3466,7 +3464,7 @@ void uiItemMenuEnumR_prop( icon = ICON_BLANK1; } - lvl = MEM_callocN(sizeof(MenuItemLevel), "MenuItemLevel"); + MenuItemLevel *lvl = MEM_callocN(sizeof(MenuItemLevel), "MenuItemLevel"); lvl->rnapoin = *ptr; BLI_strncpy(lvl->propname, RNA_property_identifier(prop), sizeof(lvl->propname)); lvl->opcontext = layout->root->opcontext; @@ -3550,15 +3548,15 @@ static int ui_litem_min_width(int itemw) static void ui_litem_layout_row(uiLayout *litem) { uiItem *last_free_item = NULL; - int x, y, w, tot, totw, neww, newtotw, itemw, minw, itemh, offset; - int fixedw, freew, fixedx, freex, flag = 0, lastw = 0; + int x, neww, newtotw, itemw, minw, itemh, offset; + int freew, fixedx, freex, flag = 0, lastw = 0; float extra_pixel; /* x = litem->x; */ /* UNUSED */ - y = litem->y; - w = litem->w; - totw = 0; - tot = 0; + int y = litem->y; + int w = litem->w; + int totw = 0; + int tot = 0; LISTBASE_FOREACH (uiItem *, item, &litem->items) { ui_item_size(item, &itemw, &itemh); @@ -3573,7 +3571,7 @@ static void ui_litem_layout_row(uiLayout *litem) if (w != 0) { w -= (tot - 1) * litem->space; } - fixedw = 0; + int fixedw = 0; /* keep clamping items to fixed minimum size until all are done */ do { @@ -3724,12 +3722,11 @@ static void ui_litem_estimate_column(uiLayout *litem, bool is_box) static void ui_litem_layout_column(uiLayout *litem, bool is_box, bool is_menu) { - int itemw, itemh, x, y; - - x = litem->x; - y = litem->y; + int x = litem->x; + int y = litem->y; LISTBASE_FOREACH (uiItem *, item, &litem->items) { + int itemw, itemh; ui_item_size(item, &itemw, &itemh); y -= itemh; @@ -3753,15 +3750,13 @@ static void ui_litem_layout_column(uiLayout *litem, bool is_box, bool is_menu) * stores a float vector in unit circle */ static RadialDirection ui_get_radialbut_vec(float vec[2], short itemnum) { - RadialDirection dir; - if (itemnum >= PIE_MAX_ITEMS) { itemnum %= PIE_MAX_ITEMS; printf("Warning: Pie menus with more than %i items are currently unsupported\n", PIE_MAX_ITEMS); } - dir = ui_radial_dir_order[itemnum]; + RadialDirection dir = ui_radial_dir_order[itemnum]; ui_but_pie_dir(dir, vec); return dir; @@ -3789,7 +3784,7 @@ static bool ui_item_is_radial_drawable(uiButtonItem *bitem) static void ui_litem_layout_radial(uiLayout *litem) { - int itemh, itemw, x, y; + int itemh, itemw; int itemnum = 0; int totitems = 0; @@ -3800,8 +3795,8 @@ static void ui_litem_layout_radial(uiLayout *litem) const int pie_radius = U.pie_menu_radius * UI_DPI_FAC; - x = litem->x; - y = litem->y; + int x = litem->x; + int y = litem->y; int minx = x, miny = y, maxx = x, maxy = y; @@ -3921,16 +3916,14 @@ static void ui_litem_layout_box(uiLayout *litem) { uiLayoutItemBx *box = (uiLayoutItemBx *)litem; const uiStyle *style = litem->root->style; - uiBut *but; - int w, h; int boxspace = style->boxspace; if (litem->root->type == UI_LAYOUT_HEADER) { boxspace = 0; } - w = litem->w; - h = litem->h; + int w = litem->w; + int h = litem->h; litem->x += boxspace; litem->y -= boxspace; @@ -3955,7 +3948,7 @@ static void ui_litem_layout_box(uiLayout *litem) } /* roundbox around the sublayout */ - but = box->roundbox; + uiBut *but = box->roundbox; but->rect.xmin = litem->x; but->rect.ymin = litem->y; but->rect.xmax = litem->x + litem->w; @@ -3967,12 +3960,11 @@ static void ui_litem_estimate_column_flow(uiLayout *litem) { const uiStyle *style = litem->root->style; uiLayoutItemFlow *flow = (uiLayoutItemFlow *)litem; - int col, x, y, emh, emy, miny, itemw, itemh, maxw = 0; - int toth, totitem; + int itemw, itemh, maxw = 0; /* compute max needed width and total height */ - toth = 0; - totitem = 0; + int toth = 0; + int totitem = 0; LISTBASE_FOREACH (uiItem *, item, &litem->items) { ui_item_size(item, &itemw, &itemh); maxw = MAX2(maxw, itemw); @@ -3995,16 +3987,16 @@ static void ui_litem_estimate_column_flow(uiLayout *litem) } /* compute sizes */ - x = 0; - y = 0; - emy = 0; - miny = 0; + int x = 0; + int y = 0; + int emy = 0; + int miny = 0; maxw = 0; - emh = toth / flow->totcol; + int emh = toth / flow->totcol; /* create column per column */ - col = 0; + int col = 0; LISTBASE_FOREACH (uiItem *, item, &litem->items) { ui_item_size(item, &itemw, &itemh); @@ -4031,12 +4023,11 @@ static void ui_litem_layout_column_flow(uiLayout *litem) { const uiStyle *style = litem->root->style; uiLayoutItemFlow *flow = (uiLayoutItemFlow *)litem; - int col, x, y, w, emh, emy, miny, itemw, itemh; - int toth, totitem; + int col, emh, itemw, itemh; /* compute max needed width and total height */ - toth = 0; - totitem = 0; + int toth = 0; + int totitem = 0; LISTBASE_FOREACH (uiItem *, item, &litem->items) { ui_item_size(item, &itemw, &itemh); toth += itemh; @@ -4044,12 +4035,12 @@ static void ui_litem_layout_column_flow(uiLayout *litem) } /* compute sizes */ - x = litem->x; - y = litem->y; - emy = 0; - miny = 0; + int x = litem->x; + int y = litem->y; + int emy = 0; + int miny = 0; - w = litem->w - (flow->totcol - 1) * style->columnspace; + int w = litem->w - (flow->totcol - 1) * style->columnspace; emh = toth / flow->totcol; /* create column per column */ @@ -4457,14 +4448,13 @@ static void ui_litem_layout_grid_flow(uiLayout *litem) /* free layout */ static void ui_litem_estimate_absolute(uiLayout *litem) { - int itemx, itemy, itemw, itemh, minx, miny; - - minx = 1e6; - miny = 1e6; + int minx = 1e6; + int miny = 1e6; litem->w = 0; litem->h = 0; LISTBASE_FOREACH (uiItem *, item, &litem->items) { + int itemx, itemy, itemw, itemh; ui_item_offset(item, &itemx, &itemy); ui_item_size(item, &itemw, &itemh); @@ -4482,12 +4472,12 @@ static void ui_litem_estimate_absolute(uiLayout *litem) static void ui_litem_layout_absolute(uiLayout *litem) { float scalex = 1.0f, scaley = 1.0f; - int x, y, newx, newy, itemx, itemy, itemh, itemw, minx, miny, totw, toth; + int x, y, newx, newy, itemx, itemy, itemh, itemw; - minx = 1e6; - miny = 1e6; - totw = 0; - toth = 0; + int minx = 1e6; + int miny = 1e6; + int totw = 0; + int toth = 0; LISTBASE_FOREACH (uiItem *, item, &litem->items) { ui_item_offset(item, &itemx, &itemy); @@ -4548,24 +4538,24 @@ static void ui_litem_estimate_split(uiLayout *litem) static void ui_litem_layout_split(uiLayout *litem) { uiLayoutItemSplit *split = (uiLayoutItemSplit *)litem; - float percentage, extra_pixel = 0.0f; + float extra_pixel = 0.0f; const int tot = BLI_listbase_count(&litem->items); - int itemh, x, y, w, colw = 0; if (tot == 0) { return; } - x = litem->x; - y = litem->y; + int x = litem->x; + int y = litem->y; - percentage = (split->percentage == 0.0f) ? 1.0f / (float)tot : split->percentage; + float percentage = (split->percentage == 0.0f) ? 1.0f / (float)tot : split->percentage; - w = (litem->w - (tot - 1) * litem->space); - colw = w * percentage; + int w = (litem->w - (tot - 1) * litem->space); + int colw = w * percentage; colw = MAX2(colw, 0); LISTBASE_FOREACH (uiItem *, item, &litem->items) { + int itemh; ui_item_size(item, NULL, &itemh); ui_item_position(item, x, y - itemh, colw, itemh); @@ -4590,12 +4580,11 @@ static void ui_litem_layout_split(uiLayout *litem) /* overlap layout */ static void ui_litem_estimate_overlap(uiLayout *litem) { - int itemw, itemh; - litem->w = 0; litem->h = 0; LISTBASE_FOREACH (uiItem *, item, &litem->items) { + int itemw, itemh; ui_item_size(item, &itemw, &itemh); litem->w = MAX2(itemw, litem->w); @@ -4605,12 +4594,12 @@ static void ui_litem_estimate_overlap(uiLayout *litem) static void ui_litem_layout_overlap(uiLayout *litem) { - int itemw, itemh, x, y; - x = litem->x; - y = litem->y; + int x = litem->x; + int y = litem->y; LISTBASE_FOREACH (uiItem *, item, &litem->items) { + int itemw, itemh; ui_item_size(item, &itemw, &itemh); ui_item_position(item, x, y - itemh, litem->w, itemh); @@ -4657,9 +4646,7 @@ static void ui_layout_heading_set(uiLayout *layout, const char *heading) /* layout create functions */ uiLayout *uiLayoutRow(uiLayout *layout, bool align) { - uiLayout *litem; - - litem = MEM_callocN(sizeof(uiLayout), "uiLayoutRow"); + uiLayout *litem = MEM_callocN(sizeof(uiLayout), "uiLayoutRow"); ui_litem_init_from_parent(litem, layout, align); litem->item.type = ITEM_LAYOUT_ROW; @@ -4682,9 +4669,7 @@ uiLayout *uiLayoutRowWithHeading(uiLayout *layout, bool align, const char *headi uiLayout *uiLayoutColumn(uiLayout *layout, bool align) { - uiLayout *litem; - - litem = MEM_callocN(sizeof(uiLayout), "uiLayoutColumn"); + uiLayout *litem = MEM_callocN(sizeof(uiLayout), "uiLayoutColumn"); ui_litem_init_from_parent(litem, layout, align); litem->item.type = ITEM_LAYOUT_COLUMN; @@ -4710,9 +4695,7 @@ uiLayout *uiLayoutColumnWithHeading(uiLayout *layout, bool align, const char *he uiLayout *uiLayoutColumnFlow(uiLayout *layout, int number, bool align) { - uiLayoutItemFlow *flow; - - flow = MEM_callocN(sizeof(uiLayoutItemFlow), "uiLayoutItemFlow"); + uiLayoutItemFlow *flow = MEM_callocN(sizeof(uiLayoutItemFlow), "uiLayoutItemFlow"); ui_litem_init_from_parent(&flow->litem, layout, align); flow->litem.item.type = ITEM_LAYOUT_COLUMN_FLOW; @@ -4731,9 +4714,7 @@ uiLayout *uiLayoutGridFlow(uiLayout *layout, bool even_rows, bool align) { - uiLayoutItemGridFlow *flow; - - flow = MEM_callocN(sizeof(uiLayoutItemGridFlow), __func__); + uiLayoutItemGridFlow *flow = MEM_callocN(sizeof(uiLayoutItemGridFlow), __func__); flow->litem.item.type = ITEM_LAYOUT_GRID_FLOW; ui_litem_init_from_parent(&flow->litem, layout, align); @@ -4750,9 +4731,7 @@ uiLayout *uiLayoutGridFlow(uiLayout *layout, static uiLayoutItemBx *ui_layout_box(uiLayout *layout, int type) { - uiLayoutItemBx *box; - - box = MEM_callocN(sizeof(uiLayoutItemBx), "uiLayoutItemBx"); + uiLayoutItemBx *box = MEM_callocN(sizeof(uiLayoutItemBx), "uiLayoutItemBx"); ui_litem_init_from_parent(&box->litem, layout, false); box->litem.item.type = ITEM_LAYOUT_BOX; @@ -4767,8 +4746,6 @@ static uiLayoutItemBx *ui_layout_box(uiLayout *layout, int type) uiLayout *uiLayoutRadial(uiLayout *layout) { - uiLayout *litem; - /* radial layouts are only valid for radial menus */ if (layout->root->type != UI_LAYOUT_PIEMENU) { return ui_item_local_sublayout(layout, layout, 0); @@ -4776,14 +4753,14 @@ uiLayout *uiLayoutRadial(uiLayout *layout) /* only one radial wheel per root layout is allowed, so check and return that, if it exists */ LISTBASE_FOREACH (uiItem *, item, &layout->root->layout->items) { - litem = (uiLayout *)item; + uiLayout *litem = (uiLayout *)item; if (litem->item.type == ITEM_LAYOUT_RADIAL) { UI_block_layout_set_current(layout->root->block, litem); return litem; } } - litem = MEM_callocN(sizeof(uiLayout), "uiLayoutRadial"); + uiLayout *litem = MEM_callocN(sizeof(uiLayout), "uiLayoutRadial"); ui_litem_init_from_parent(litem, layout, false); litem->item.type = ITEM_LAYOUT_RADIAL; @@ -4838,9 +4815,7 @@ uiLayout *uiLayoutListBox(uiLayout *layout, uiLayout *uiLayoutAbsolute(uiLayout *layout, bool align) { - uiLayout *litem; - - litem = MEM_callocN(sizeof(uiLayout), "uiLayoutAbsolute"); + uiLayout *litem = MEM_callocN(sizeof(uiLayout), "uiLayoutAbsolute"); ui_litem_init_from_parent(litem, layout, align); litem->item.type = ITEM_LAYOUT_ABSOLUTE; @@ -4852,9 +4827,7 @@ uiLayout *uiLayoutAbsolute(uiLayout *layout, bool align) uiBlock *uiLayoutAbsoluteBlock(uiLayout *layout) { - uiBlock *block; - - block = uiLayoutGetBlock(layout); + uiBlock *block = uiLayoutGetBlock(layout); uiLayoutAbsolute(layout, false); return block; @@ -4862,9 +4835,7 @@ uiBlock *uiLayoutAbsoluteBlock(uiLayout *layout) uiLayout *uiLayoutOverlap(uiLayout *layout) { - uiLayout *litem; - - litem = MEM_callocN(sizeof(uiLayout), "uiLayoutOverlap"); + uiLayout *litem = MEM_callocN(sizeof(uiLayout), "uiLayoutOverlap"); ui_litem_init_from_parent(litem, layout, false); litem->item.type = ITEM_LAYOUT_OVERLAP; @@ -4876,9 +4847,7 @@ uiLayout *uiLayoutOverlap(uiLayout *layout) uiLayout *uiLayoutSplit(uiLayout *layout, float percentage, bool align) { - uiLayoutItemSplit *split; - - split = MEM_callocN(sizeof(uiLayoutItemSplit), "uiLayoutItemSplit"); + uiLayoutItemSplit *split = MEM_callocN(sizeof(uiLayoutItemSplit), "uiLayoutItemSplit"); ui_litem_init_from_parent(&split->litem, layout, align); split->litem.item.type = ITEM_LAYOUT_SPLIT; @@ -5290,12 +5259,9 @@ static void ui_item_estimate(uiItem *item) static void ui_item_align(uiLayout *litem, short nr) { - uiButtonItem *bitem; - uiLayoutItemBx *box; - LISTBASE_FOREACH_BACKWARD (uiItem *, item, &litem->items) { if (item->type == ITEM_BUTTON) { - bitem = (uiButtonItem *)item; + uiButtonItem *bitem = (uiButtonItem *)item; #ifndef USE_UIBUT_SPATIAL_ALIGN if (ui_but_can_align(bitem->but)) #endif @@ -5312,7 +5278,7 @@ static void ui_item_align(uiLayout *litem, short nr) /* pass */ } else if (item->type == ITEM_LAYOUT_BOX) { - box = (uiLayoutItemBx *)item; + uiLayoutItemBx *box = (uiLayoutItemBx *)item; if (!box->roundbox->alignnr) { box->roundbox->alignnr = nr; } @@ -5325,11 +5291,9 @@ static void ui_item_align(uiLayout *litem, short nr) static void ui_item_flag(uiLayout *litem, int flag) { - uiButtonItem *bitem; - LISTBASE_FOREACH_BACKWARD (uiItem *, item, &litem->items) { if (item->type == ITEM_BUTTON) { - bitem = (uiButtonItem *)item; + uiButtonItem *bitem = (uiButtonItem *)item; bitem->but->flag |= flag; } else { @@ -5465,17 +5429,14 @@ uiLayout *UI_block_layout(uiBlock *block, int padding, const uiStyle *style) { - uiLayout *layout; - uiLayoutRoot *root; - - root = MEM_callocN(sizeof(uiLayoutRoot), "uiLayoutRoot"); + uiLayoutRoot *root = MEM_callocN(sizeof(uiLayoutRoot), "uiLayoutRoot"); root->type = type; root->style = style; root->block = block; root->padding = padding; root->opcontext = WM_OP_INVOKE_REGION_WIN; - layout = MEM_callocN(sizeof(uiLayout), "uiLayout"); + uiLayout *layout = MEM_callocN(sizeof(uiLayout), "uiLayout"); layout->item.type = (type == UI_LAYOUT_VERT_BAR) ? ITEM_LAYOUT_COLUMN : ITEM_LAYOUT_ROOT; /* Only used when 'UI_ITEM_PROP_SEP' is set. */ @@ -5529,9 +5490,7 @@ void UI_block_layout_set_current(uiBlock *block, uiLayout *layout) void ui_layout_add_but(uiLayout *layout, uiBut *but) { - uiButtonItem *bitem; - - bitem = MEM_callocN(sizeof(uiButtonItem), "uiButtonItem"); + uiButtonItem *bitem = MEM_callocN(sizeof(uiButtonItem), "uiButtonItem"); bitem->item.type = ITEM_BUTTON; bitem->but = but; -- cgit v1.2.3 From 6367bc716a9e902bf75b2164cfd75702e6f13acb Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Fri, 18 Dec 2020 15:12:15 -0600 Subject: Cleanup: Use true and false for booleans --- source/blender/windowmanager/intern/wm_event_system.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source/blender') diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index c1ae307eb55..82ca54db075 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -212,11 +212,11 @@ static bool wm_test_duplicate_notifier(const wmWindowManager *wm, uint type, voi LISTBASE_FOREACH (wmNotifier *, note, &wm->queue) { if ((note->category | note->data | note->subtype | note->action) == type && note->reference == reference) { - return 1; + return true; } } - return 0; + return false; } void WM_event_add_notifier_ex(wmWindowManager *wm, const wmWindow *win, uint type, void *reference) @@ -785,8 +785,8 @@ bool WM_operator_poll(bContext *C, wmOperatorType *ot) LISTBASE_FOREACH (wmOperatorTypeMacro *, macro, &ot->macro) { wmOperatorType *ot_macro = WM_operatortype_find(macro->idname, 0); - if (0 == WM_operator_poll(C, ot_macro)) { - return 0; + if (!WM_operator_poll(C, ot_macro)) { + return false; } } @@ -798,7 +798,7 @@ bool WM_operator_poll(bContext *C, wmOperatorType *ot) return ot->poll(C); } - return 1; + return true; } /* sets up the new context and calls 'wm_operator_invoke()' with poll_only */ -- cgit v1.2.3 From c106b07e233889323e501cc033ac2010b2799bdc Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Fri, 18 Dec 2020 17:04:52 -0600 Subject: Cleanup: Remove unused variables from the bNode struct In some cases the variables were set but never used anywhere. Differential Revision: https://developer.blender.org/D9889 --- source/blender/blenkernel/intern/node.c | 1 - source/blender/editors/space_node/drawnode.c | 36 --------------------------- source/blender/editors/space_node/node_draw.c | 2 -- source/blender/makesdna/DNA_node_types.h | 17 +++++-------- source/blender/nodes/intern/node_exec.c | 2 -- 5 files changed, 6 insertions(+), 52 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 5af49802868..511c16e9ff4 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -674,7 +674,6 @@ void ntreeBlendReadData(BlendDataReader *reader, bNodeTree *ntree) /* and we connect the rest */ LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { BLO_read_data_address(reader, &node->parent); - node->lasty = 0; LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) { direct_link_node_socket(reader, sock); diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 421e66604e4..0ce31707204 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -203,42 +203,6 @@ static void node_buts_normal(uiLayout *layout, bContext *UNUSED(C), PointerRNA * uiItemR(layout, &sockptr, "default_value", DEFAULT_FLAGS, "", ICON_NONE); } -#if 0 /* not used in 2.5x yet */ -static void node_browse_tex_cb(bContext *C, void *ntree_v, void *node_v) -{ - Main *bmain = CTX_data_main(C); - bNodeTree *ntree = ntree_v; - bNode *node = node_v; - Tex *tex; - - if (node->menunr < 1) { - return; - } - - if (node->id) { - id_us_min(node->id); - node->id = NULL; - } - tex = BLI_findlink(&bmain->tex, node->menunr - 1); - - node->id = &tex->id; - id_us_plus(node->id); - BLI_strncpy(node->name, node->id->name + 2, sizeof(node->name)); - - nodeSetActive(ntree, node); - - if (ntree->type == NTREE_TEXTURE) { - ntreeTexCheckCyclics(ntree); - } - - // allqueue(REDRAWBUTSSHADING, 0); - // allqueue(REDRAWNODE, 0); - NodeTagChanged(ntree, node); - - node->menunr = 0; -} -#endif - static void node_buts_texture(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { bNode *node = ptr->data; diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c index 5a2eb0cc3a0..d3fec7257f5 100644 --- a/source/blender/editors/space_node/node_draw.c +++ b/source/blender/editors/space_node/node_draw.c @@ -1620,7 +1620,6 @@ void node_draw_nodetree(const bContext *C, } bNodeInstanceKey key = BKE_node_instance_key(parent_key, ntree, node); - node->nr = a; /* index of node in list, used for exec event code */ node_draw(C, region, snode, ntree, node, key); } @@ -1643,7 +1642,6 @@ void node_draw_nodetree(const bContext *C, } bNodeInstanceKey key = BKE_node_instance_key(parent_key, ntree, node); - node->nr = a; /* index of node in list, used for exec event code */ node_draw(C, region, snode, ntree, node, key); } } diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index d6b5e3ed493..743850621bc 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -218,15 +218,14 @@ typedef struct bNode { char name[64]; int flag; short type; - char _pad[2]; /** Both for dependency and sorting. */ short done, level; - /** Lasty: check preview render status, menunr: browse ID blocks. */ - short lasty, menunr; - /** For groupnode, offset in global caller stack. */ - short stack_index; - /** Number of this node in list, used for UI exec events. */ - short nr; + + /** Used as a boolean for execution. */ + uint8_t need_exec; + + char _pad[1]; + /** Custom user-defined color. */ float color[3]; @@ -264,10 +263,6 @@ typedef struct bNode { short custom1, custom2; float custom3, custom4; - /** Need_exec is set as UI execution event, exec is flag during exec. */ - short need_exec, exec; - /** Optional extra storage for use in thread (read only then!). */ - void *threaddata; /** Entire boundbox (worldspace). */ rctf totr; /** Optional buttons area. */ diff --git a/source/blender/nodes/intern/node_exec.c b/source/blender/nodes/intern/node_exec.c index 85c408c40bb..0d46119ab60 100644 --- a/source/blender/nodes/intern/node_exec.c +++ b/source/blender/nodes/intern/node_exec.c @@ -186,8 +186,6 @@ bNodeTreeExec *ntree_exec_begin(bNodeExecContext *context, for (n = 0; n < totnodes; n++) { node = nodelist[n]; - node->stack_index = index; - /* init node socket stack indexes */ for (sock = node->inputs.first; sock; sock = sock->next) { node_init_input_index(sock, &index); -- cgit v1.2.3 From 002722bb800e5b5d5d7e1c54e92e7d66037cb891 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Fri, 18 Dec 2020 17:08:27 -0600 Subject: Fix build error after previous commit I tested building so many times while making this patch, but somehow the previous commit was missing a padding variable, I have no idea how. --- source/blender/makesdna/DNA_node_types.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source/blender') diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 743850621bc..64dd489b850 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -263,6 +263,8 @@ typedef struct bNode { short custom1, custom2; float custom3, custom4; + char _pad1[4]; + /** Entire boundbox (worldspace). */ rctf totr; /** Optional buttons area. */ -- cgit v1.2.3 From 6942dd9f49003ead61f9a0e52b398ebc74a5e3cb Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Fri, 18 Dec 2020 17:13:15 -0600 Subject: Fix T83868: Button animation states no longer visible without emboss This bug was caused by making it so that non-embossed modifier icon buttons could become an operator button and retain their red highlight for disabled modifiers. The icon button needs emboss turned off, but in earlier versions of Blender, `UI_EMBOSS_NONE` would be overridden by animation or red alert states. Instead of abusing "NONE" to mean "none unless there is animation or red alert", this commit adds a new emboss flag for that situation, `UI_EMBOSS_NONE_OR_STATUS`, which uses no emboss unless there is an animation state, or another status. There are only a few situations where this is necessary, so the change isn't too big. Differential Revision: https://developer.blender.org/D9902 --- source/blender/editors/include/UI_interface.h | 5 +++++ source/blender/editors/interface/interface_templates.c | 2 +- source/blender/editors/interface/interface_widgets.c | 17 ++++++++++++----- source/blender/editors/space_nla/nla_buttons.c | 2 +- source/blender/editors/space_outliner/outliner_draw.c | 6 +++--- source/blender/makesrna/intern/rna_ui.c | 5 +++++ 6 files changed, 27 insertions(+), 10 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index ced411ef75f..05bedd526ed 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -108,6 +108,11 @@ enum { UI_EMBOSS_NONE = 1, /* Nothing, only icon and/or text */ UI_EMBOSS_PULLDOWN = 2, /* Pulldown menu style */ UI_EMBOSS_RADIAL = 3, /* Pie Menu */ + /** + * The same as #UI_EMBOSS_NONE, unless the the button has + * a coloring status like an animation state or red alert. + */ + UI_EMBOSS_NONE_OR_STATUS = 4, UI_EMBOSS_UNDEFINED = 255, /* For layout engine, use emboss from block. */ }; diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 6e96704271f..404ae0df6a1 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -2915,7 +2915,7 @@ static void draw_constraint_header(uiLayout *layout, Object *ob, bConstraint *co } else { /* enabled */ - UI_block_emboss_set(block, UI_EMBOSS_NONE); + UI_block_emboss_set(block, UI_EMBOSS_NONE_OR_STATUS); uiItemR(layout, &ptr, "mute", 0, "", 0); UI_block_emboss_set(block, UI_EMBOSS); diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index e92c32bb1bd..7e883851876 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -2520,8 +2520,14 @@ static void widget_active_color(uiWidgetColors *wcol) static const uchar *widget_color_blend_from_flags(const uiWidgetStateColors *wcol_state, int state, - int drawflag) + int drawflag, + const char emboss) { + /* Explicitly require #UI_EMBOSS_NONE_OR_STATUS for color blending with no emboss. */ + if (emboss == UI_EMBOSS_NONE) { + return NULL; + } + if (drawflag & UI_BUT_ANIMATED_CHANGED) { return wcol_state->inner_changed_sel; } @@ -2557,7 +2563,7 @@ static void widget_state(uiWidgetType *wt, int state, int drawflag, char emboss) wt->wcol = *(wt->wcol_theme); - const uchar *color_blend = widget_color_blend_from_flags(wcol_state, state, drawflag); + const uchar *color_blend = widget_color_blend_from_flags(wcol_state, state, drawflag, emboss); if (state & UI_SELECT) { copy_v4_v4_uchar(wt->wcol.inner, wt->wcol.inner_sel); @@ -2626,7 +2632,7 @@ static void widget_state_numslider(uiWidgetType *wt, int state, int drawflag, ch /* call this for option button */ widget_state(wt, state, drawflag, emboss); - const uchar *color_blend = widget_color_blend_from_flags(wcol_state, state, drawflag); + const uchar *color_blend = widget_color_blend_from_flags(wcol_state, state, drawflag, emboss); if (color_blend != NULL) { /* Set the slider 'item' so that it reflects state settings too. * De-saturate so the color of the slider doesn't conflict with the blend color, @@ -4524,8 +4530,9 @@ void ui_draw_but(const bContext *C, struct ARegion *region, uiStyle *style, uiBu break; } } - else if (but->emboss == UI_EMBOSS_NONE) { - /* "nothing" */ + else if (ELEM(but->emboss, UI_EMBOSS_NONE, UI_EMBOSS_NONE_OR_STATUS)) { + /* Use the same widget types for both no emboss types. Later on, + * #UI_EMBOSS_NONE_OR_STATUS will blend state colors if they apply. */ switch (but->type) { case UI_BTYPE_LABEL: wt = widget_type(UI_WTYPE_ICON_LABEL); diff --git a/source/blender/editors/space_nla/nla_buttons.c b/source/blender/editors/space_nla/nla_buttons.c index 1d7e5448b92..218fc3b7141 100644 --- a/source/blender/editors/space_nla/nla_buttons.c +++ b/source/blender/editors/space_nla/nla_buttons.c @@ -346,7 +346,7 @@ static void nla_panel_stripname(const bContext *C, Panel *panel) uiItemR(row, &strip_ptr, "name", 0, "", ICON_NLA); - UI_block_emboss_set(block, UI_EMBOSS_NONE); + UI_block_emboss_set(block, UI_EMBOSS_NONE_OR_STATUS); uiItemR(row, &strip_ptr, "mute", 0, "", ICON_NONE); UI_block_emboss_set(block, UI_EMBOSS); } diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c index d2381cf30db..9223da136e1 100644 --- a/source/blender/editors/space_outliner/outliner_draw.c +++ b/source/blender/editors/space_outliner/outliner_draw.c @@ -1996,7 +1996,7 @@ static void outliner_draw_mode_column_toggle(uiBlock *block, "Change the object in the current mode\n" "* Ctrl to add to the current mode"); } - + UI_block_emboss_set(block, UI_EMBOSS_NONE_OR_STATUS); uiBut *but = uiDefIconBut(block, UI_BTYPE_ICON_TOGGLE, 0, @@ -3646,7 +3646,7 @@ void draw_outliner(const bContext *C) outliner_tree_dimensions(space_outliner, &tree_width, &tree_height); /* Default to no emboss for outliner UI. */ - UI_block_emboss_set(block, UI_EMBOSS_NONE); + UI_block_emboss_set(block, UI_EMBOSS_NONE_OR_STATUS); if (space_outliner->outlinevis == SO_DATA_API) { int buttons_start_x = outliner_data_api_buttons_start_x(tree_width); @@ -3655,7 +3655,7 @@ void draw_outliner(const bContext *C) UI_block_emboss_set(block, UI_EMBOSS); outliner_draw_rnabuts(block, region, space_outliner, buttons_start_x, &space_outliner->tree); - UI_block_emboss_set(block, UI_EMBOSS_NONE); + UI_block_emboss_set(block, UI_EMBOSS_NONE_OR_STATUS); } else if (space_outliner->outlinevis == SO_ID_ORPHANS) { /* draw user toggle columns */ diff --git a/source/blender/makesrna/intern/rna_ui.c b/source/blender/makesrna/intern/rna_ui.c index 51cc178ab15..b86f5b789da 100644 --- a/source/blender/makesrna/intern/rna_ui.c +++ b/source/blender/makesrna/intern/rna_ui.c @@ -1200,6 +1200,11 @@ static void rna_def_ui_layout(BlenderRNA *brna) {UI_EMBOSS_NONE, "NONE", 0, "None", "Draw only text and icons"}, {UI_EMBOSS_PULLDOWN, "PULLDOWN_MENU", 0, "Pulldown Menu", "Draw pulldown menu style"}, {UI_EMBOSS_RADIAL, "RADIAL_MENU", 0, "Radial Menu", "Draw radial menu style"}, + {UI_EMBOSS_NONE_OR_STATUS, + "UI_EMBOSS_NONE_OR_STATUS", + 0, + "None or Status", + "Draw with no emboss unless the button has a coloring status like an animation state"}, {0, NULL, 0, NULL, NULL}, }; -- cgit v1.2.3 From 046ca0749a9389ec52da90b29c8b2032f3225c51 Mon Sep 17 00:00:00 2001 From: Richard Antalik Date: Sat, 19 Dec 2020 05:57:27 +0100 Subject: Cleanup: Rename BKE_sequencer functions API functions get SEQ_ prefix. Intern functions get seq_ prefix Functions also have appropriate category included in name. --- source/blender/blenkernel/intern/image.c | 2 +- source/blender/blenkernel/intern/scene.c | 18 +- source/blender/blenkernel/intern/sound.c | 4 +- source/blender/blenloader/intern/readfile.c | 2 +- source/blender/blenloader/intern/versioning_260.c | 4 +- source/blender/blenloader/intern/versioning_270.c | 2 +- source/blender/blenloader/intern/versioning_280.c | 4 +- .../intern/eval/deg_eval_copy_on_write.cc | 2 +- source/blender/editors/animation/anim_deps.c | 4 +- source/blender/editors/animation/anim_filter.c | 6 +- source/blender/editors/animation/anim_ops.c | 2 +- source/blender/editors/render/render_internal.c | 6 +- source/blender/editors/screen/screen_context.c | 6 +- source/blender/editors/sound/sound_ops.c | 2 +- .../editors/space_outliner/outliner_select.c | 8 +- .../blender/editors/space_outliner/outliner_sync.c | 4 +- .../editors/space_outliner/outliner_tools.c | 2 +- .../space_outliner/tree/tree_display_sequencer.cc | 2 +- .../editors/space_sequencer/sequencer_add.c | 92 ++--- .../editors/space_sequencer/sequencer_draw.c | 28 +- .../editors/space_sequencer/sequencer_edit.c | 395 ++++++++++----------- .../editors/space_sequencer/sequencer_modifier.c | 34 +- .../editors/space_sequencer/sequencer_proxy.c | 12 +- .../editors/space_sequencer/sequencer_select.c | 37 +- .../editors/space_sequencer/sequencer_view.c | 6 +- .../editors/space_sequencer/space_sequencer.c | 2 +- .../transform/transform_convert_sequencer.c | 76 ++-- source/blender/editors/transform/transform_snap.c | 2 +- source/blender/editors/util/ed_util_imbuf.c | 2 +- source/blender/makesdna/DNA_sequence_types.h | 2 +- source/blender/makesrna/intern/rna_camera.c | 2 +- source/blender/makesrna/intern/rna_color.c | 10 +- source/blender/makesrna/intern/rna_movieclip.c | 4 +- source/blender/makesrna/intern/rna_scene.c | 6 +- source/blender/makesrna/intern/rna_scene_api.c | 4 +- source/blender/makesrna/intern/rna_sequencer.c | 200 +++++------ source/blender/makesrna/intern/rna_sequencer_api.c | 60 ++-- source/blender/makesrna/intern/rna_space.c | 2 +- source/blender/render/intern/pipeline.c | 4 +- source/blender/sequencer/SEQ_sequencer.h | 324 +++++++++-------- source/blender/sequencer/intern/clipboard.c | 18 +- source/blender/sequencer/intern/effects.c | 38 +- source/blender/sequencer/intern/effects.h | 12 +- source/blender/sequencer/intern/image_cache.c | 115 +++--- source/blender/sequencer/intern/image_cache.h | 58 +-- source/blender/sequencer/intern/iterator.c | 18 +- source/blender/sequencer/intern/modifier.c | 50 +-- source/blender/sequencer/intern/prefetch.c | 48 ++- source/blender/sequencer/intern/prefetch.h | 16 +- source/blender/sequencer/intern/proxy.c | 2 +- source/blender/sequencer/intern/render.c | 79 ++--- source/blender/sequencer/intern/sequencer.c | 60 ++-- source/blender/sequencer/intern/sound.c | 20 +- source/blender/sequencer/intern/strip_add.c | 65 ++-- source/blender/sequencer/intern/strip_edit.c | 41 +-- source/blender/sequencer/intern/strip_relations.c | 92 ++--- source/blender/sequencer/intern/strip_select.c | 14 +- source/blender/sequencer/intern/strip_time.c | 28 +- source/blender/sequencer/intern/strip_transform.c | 135 ++++--- source/blender/sequencer/intern/utils.c | 43 +-- source/blender/sequencer/intern/utils.h | 6 +- source/blender/windowmanager/intern/wm_init_exit.c | 2 +- source/blender/windowmanager/intern/wm_jobs.c | 2 +- 63 files changed, 1161 insertions(+), 1185 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index d1c6b552d2e..090ab571542 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -2057,7 +2057,7 @@ static void stampdata( } if (use_dynamic && scene->r.stamp & R_STAMP_SEQSTRIP) { - const Sequence *seq = BKE_sequencer_foreground_frame_get(scene, scene->r.cfra); + const Sequence *seq = SEQ_get_topmost_sequence(scene, scene->r.cfra); if (seq) { STRNCPY(text, seq->name + 2); diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index cc192c1c3c0..7acd54b6af1 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -340,7 +340,7 @@ static void scene_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int if (scene_src->ed) { scene_dst->ed = MEM_callocN(sizeof(*scene_dst->ed), __func__); scene_dst->ed->seqbasep = &scene_dst->ed->seqbase; - BKE_sequence_base_dupli_recursive(scene_src, + SEQ_sequence_base_dupli_recursive(scene_src, scene_dst, &scene_dst->ed->seqbase, &scene_src->ed->seqbase, @@ -375,7 +375,7 @@ static void scene_free_data(ID *id) Scene *scene = (Scene *)id; const bool do_id_user = false; - BKE_sequencer_editing_free(scene, do_id_user); + SEQ_editing_free(scene, do_id_user); BKE_keyingsets_free(&scene->keyingsets); @@ -948,7 +948,7 @@ static void scene_blend_write(BlendWriter *writer, ID *id, const void *id_addres IDP_BlendWrite(writer, seq->prop); } - BKE_sequence_modifier_blend_write(writer, &seq->modifiers); + SEQ_modifier_blend_write(writer, &seq->modifiers); } SEQ_ALL_END; @@ -1145,7 +1145,7 @@ static void scene_blend_read_data(BlendDataReader *reader, ID *id) Sequence *seq; SEQ_ALL_BEGIN (ed, seq) { /* Do as early as possible, so that other parts of reading can rely on valid session UUID. */ - BKE_sequence_session_uuid_generate(seq); + SEQ_relations_session_uuid_generate(seq); BLO_read_data_address(reader, &seq->seq1); BLO_read_data_address(reader, &seq->seq2); @@ -1204,7 +1204,7 @@ static void scene_blend_read_data(BlendDataReader *reader, ID *id) BLO_read_data_address(reader, &seq->strip->color_balance); } - BKE_sequence_modifier_blend_read_data(reader, &seq->modifiers); + SEQ_modifier_blend_read_data(reader, &seq->modifiers); } SEQ_ALL_END; @@ -1493,7 +1493,7 @@ static void scene_blend_read_lib(BlendLibReader *reader, ID *id) } BLI_listbase_clear(&seq->anims); - BKE_sequence_modifier_blend_read_lib(reader, sce, &seq->modifiers); + SEQ_modifier_blend_read_lib(reader, sce, &seq->modifiers); } SEQ_ALL_END; @@ -2013,7 +2013,7 @@ Scene *BKE_scene_duplicate(Main *bmain, Scene *sce, eSceneCopyMethod type) /* Remove sequencer if not full copy */ /* XXX Why in Hell? :/ */ remove_sequencer_fcurves(sce_copy); - BKE_sequencer_editing_free(sce_copy, true); + SEQ_editing_free(sce_copy, true); } return sce_copy; @@ -3733,6 +3733,6 @@ void BKE_scene_eval_sequencer_sequences(Depsgraph *depsgraph, Scene *scene) } } SEQ_ALL_END; - BKE_sequencer_update_muting(scene->ed); - BKE_sequencer_update_sound_bounds_all(scene); + SEQ_sound_update_muting(scene->ed); + SEQ_sound_update_bounds_all(scene); } diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c index 5bcc1a9553a..d167fc4e51f 100644 --- a/source/blender/blenkernel/intern/sound.c +++ b/source/blender/blenkernel/intern/sound.c @@ -683,7 +683,7 @@ void BKE_sound_update_fps(Main *bmain, Scene *scene) AUD_Sequence_setFPS(scene->sound_scene, FPS); } - BKE_sequencer_refresh_sound_length(bmain, scene); + SEQ_sound_update_length(bmain, scene); } void BKE_sound_update_scene_listener(Scene *scene) @@ -825,7 +825,7 @@ void BKE_sound_update_sequencer(Main *main, bSound *sound) Scene *scene; for (scene = main->scenes.first; scene; scene = scene->id.next) { - BKE_sequencer_update_sound(scene, sound); + SEQ_sound_update(scene, sound); } } diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index bccc7150523..73606db9a41 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -2603,7 +2603,7 @@ static int lib_link_seq_clipboard_cb(Sequence *seq, void *arg_pt) static void lib_link_clipboard_restore(struct IDNameLib_Map *id_map) { /* update IDs stored in sequencer clipboard */ - BKE_sequencer_base_recursive_apply(&seqbase_clipboard, lib_link_seq_clipboard_cb, id_map); + SEQ_iterator_seqbase_recursive_apply(&seqbase_clipboard, lib_link_seq_clipboard_cb, id_map); } static int lib_link_main_data_restore_cb(LibraryIDLinkCallbackData *cb_data) diff --git a/source/blender/blenloader/intern/versioning_260.c b/source/blender/blenloader/intern/versioning_260.c index c336239ec59..86085ddbc73 100644 --- a/source/blender/blenloader/intern/versioning_260.c +++ b/source/blender/blenloader/intern/versioning_260.c @@ -1499,7 +1499,7 @@ void blo_do_versions_260(FileData *fd, Library *UNUSED(lib), Main *bmain) SequenceModifierData *smd; ColorBalanceModifierData *cbmd; - smd = BKE_sequence_modifier_new(seq, NULL, seqModifierType_ColorBalance); + smd = SEQ_modifier_new(seq, NULL, seqModifierType_ColorBalance); cbmd = (ColorBalanceModifierData *)smd; cbmd->color_balance = *strip->color_balance; @@ -1813,7 +1813,7 @@ void blo_do_versions_260(FileData *fd, Library *UNUSED(lib), Main *bmain) seq->alpha_mode = SEQ_ALPHA_STRAIGHT; } else { - BKE_sequence_alpha_mode_from_extension(seq); + SEQ_alpha_mode_from_file_extension(seq); } } SEQ_ALL_END; diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c index 046749e4691..ee5efff7216 100644 --- a/source/blender/blenloader/intern/versioning_270.c +++ b/source/blender/blenloader/intern/versioning_270.c @@ -1224,7 +1224,7 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *bmain) } if (seq->effectdata == NULL) { - struct SeqEffectHandle effect_handle = BKE_sequence_get_effect(seq); + struct SeqEffectHandle effect_handle = SEQ_effect_handle_get(seq); effect_handle.init(seq); } diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c index c2bedc54690..f7ef7f74a42 100644 --- a/source/blender/blenloader/intern/versioning_280.c +++ b/source/blender/blenloader/intern/versioning_280.c @@ -963,7 +963,7 @@ static void do_version_curvemapping_walker(Main *bmain, void (*callback)(CurveMa if (scene->ed != NULL) { LISTBASE_FOREACH (Sequence *, seq, &scene->ed->seqbase) { LISTBASE_FOREACH (SequenceModifierData *, smd, &seq->modifiers) { - const SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(smd->type); + const SequenceModifierTypeInfo *smti = SEQ_modifier_type_info_get(smd->type); if (smti) { if (smd->type == seqModifierType_Curves) { @@ -1783,7 +1783,7 @@ void do_versions_after_linking_280(Main *bmain, ReportList *UNUSED(reports)) static void do_versions_seq_unique_name_all_strips(Scene *sce, ListBase *seqbasep) { for (Sequence *seq = seqbasep->first; seq != NULL; seq = seq->next) { - BKE_sequence_base_unique_name_recursive(&sce->ed->seqbase, seq); + SEQ_sequence_base_unique_name_recursive(&sce->ed->seqbase, seq); if (seq->seqbase.first != NULL) { do_versions_seq_unique_name_all_strips(sce, &seq->seqbase); } 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 cff7292abd4..5119de1ed9e 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 @@ -322,7 +322,7 @@ bool scene_copy_inplace_no_main(const Scene *scene, Scene *new_scene) const ID *id_for_copy = &scene->id; if (G.debug & G_DEBUG_DEPSGRAPH_UUID) { - BKE_sequencer_check_uuids_unique_and_report(scene); + SEQ_relations_check_uuids_unique_and_report(scene); } #ifdef NESTED_ID_NASTY_WORKAROUND diff --git a/source/blender/editors/animation/anim_deps.c b/source/blender/editors/animation/anim_deps.c index 32ce78e405e..fbd55592729 100644 --- a/source/blender/editors/animation/anim_deps.c +++ b/source/blender/editors/animation/anim_deps.c @@ -212,7 +212,7 @@ static void animchan_sync_fcurve_scene(bAnimListElem *ale) return; } - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); /* get strip name, and check if this strip is selected */ char *seq_name = BLI_str_quoted_substrN(fcu->rna_path, "sequences_all["); @@ -220,7 +220,7 @@ static void animchan_sync_fcurve_scene(bAnimListElem *ale) return; } - Sequence *seq = BKE_sequence_get_by_name(ed->seqbasep, seq_name, false); + Sequence *seq = SEQ_get_sequence_by_name(ed->seqbasep, seq_name, false); MEM_freeN(seq_name); if (seq == NULL) { diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index f4a487140ff..83665d7a053 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -225,7 +225,7 @@ static bool actedit_get_context(bAnimContext *ac, SpaceAction *saction) { /* TODO, other methods to get the mask */ #if 0 - Sequence *seq = BKE_sequencer_active_get(ac->scene); + Sequence *seq = SEQ_select_active_get(ac->scene); MovieClip *clip = ac->scene->clip; struct Mask *mask = seq ? seq->mask : NULL; #endif @@ -1103,14 +1103,14 @@ static bool skip_fcurve_selected_data(bDopeSheet *ads, FCurve *fcu, ID *owner_id /* only consider if F-Curve involves sequence_editor.sequences */ if ((fcu->rna_path) && strstr(fcu->rna_path, "sequences_all")) { - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); Sequence *seq = NULL; if (ed) { /* get strip name, and check if this strip is selected */ char *seq_name = BLI_str_quoted_substrN(fcu->rna_path, "sequences_all["); if (seq_name) { - seq = BKE_sequence_get_by_name(ed->seqbasep, seq_name, false); + seq = SEQ_get_sequence_by_name(ed->seqbasep, seq_name, false); MEM_freeN(seq_name); } } diff --git a/source/blender/editors/animation/anim_ops.c b/source/blender/editors/animation/anim_ops.c index 0db3e984b60..07601414fb0 100644 --- a/source/blender/editors/animation/anim_ops.c +++ b/source/blender/editors/animation/anim_ops.c @@ -93,7 +93,7 @@ static void change_frame_apply(bContext *C, wmOperator *op) if (do_snap) { if (CTX_wm_space_seq(C)) { - frame = BKE_sequencer_find_next_prev_edit(scene, frame, SEQ_SIDE_BOTH, true, false, false); + frame = SEQ_time_find_next_prev_edit(scene, frame, SEQ_SIDE_BOTH, true, false, false); } else { frame = BKE_scene_frame_snap_by_seconds(scene, 1.0, frame); diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c index 69c1e887392..46680f649cd 100644 --- a/source/blender/editors/render/render_internal.c +++ b/source/blender/editors/render/render_internal.c @@ -363,7 +363,7 @@ static int screen_render_exec(bContext *C, wmOperator *op) * otherwise, invalidated cache entries can make their way into * the output rendering. We can't put that into RE_RenderFrame, * since sequence rendering can call that recursively... (peter) */ - BKE_sequencer_cache_cleanup(scene); + SEQ_cache_cleanup(scene); RE_SetReports(re, op->reports); @@ -935,7 +935,7 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even /* Reports are done inside check function, and it will return false if there are other strips to * render. */ - if ((scene->r.scemode & R_DOSEQ) && BKE_sequencer_check_scene_recursion(scene, op->reports)) { + if ((scene->r.scemode & R_DOSEQ) && SEQ_relations_check_scene_recursion(scene, op->reports)) { return OPERATOR_CANCELLED; } @@ -957,7 +957,7 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even * otherwise, invalidated cache entries can make their way into * the output rendering. We can't put that into RE_RenderFrame, * since sequence rendering can call that recursively... (peter) */ - BKE_sequencer_cache_cleanup(scene); + SEQ_cache_cleanup(scene); /* store spare * get view3d layer, local layer, make this nice api call to render diff --git a/source/blender/editors/screen/screen_context.c b/source/blender/editors/screen/screen_context.c index fb7606d1fe5..1dfe606be78 100644 --- a/source/blender/editors/screen/screen_context.c +++ b/source/blender/editors/screen/screen_context.c @@ -604,7 +604,7 @@ static eContextResult screen_ctx_sequences(const bContext *C, bContextDataResult { wmWindow *win = CTX_wm_window(C); Scene *scene = WM_window_get_active_scene(win); - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); if (ed) { LISTBASE_FOREACH (Sequence *, seq, ed->seqbasep) { CTX_data_list_add(result, &scene->id, &RNA_Sequence, seq); @@ -618,7 +618,7 @@ static eContextResult screen_ctx_selected_sequences(const bContext *C, bContextD { wmWindow *win = CTX_wm_window(C); Scene *scene = WM_window_get_active_scene(win); - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); if (ed) { LISTBASE_FOREACH (Sequence *, seq, ed->seqbasep) { if (seq->flag & SELECT) { @@ -635,7 +635,7 @@ static eContextResult screen_ctx_selected_editable_sequences(const bContext *C, { wmWindow *win = CTX_wm_window(C); Scene *scene = WM_window_get_active_scene(win); - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); if (ed) { LISTBASE_FOREACH (Sequence *, seq, ed->seqbasep) { if (seq->flag & SELECT && !(seq->flag & SEQ_LOCK)) { diff --git a/source/blender/editors/sound/sound_ops.c b/source/blender/editors/sound/sound_ops.c index 8dac90c2346..5bc13ec1b75 100644 --- a/source/blender/editors/sound/sound_ops.c +++ b/source/blender/editors/sound/sound_ops.c @@ -259,7 +259,7 @@ static void sound_update_animation_flags(Scene *scene) scene->id.tag |= LIB_TAG_DOIT; SEQ_ALL_BEGIN (scene->ed, seq) { - BKE_sequencer_recursive_apply(seq, sound_update_animation_flags_fn, scene); + SEQ_iterator_recursive_apply(seq, sound_update_animation_flags_fn, scene); } SEQ_ALL_END; diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c index 658e6adbe33..a1df922b335 100644 --- a/source/blender/editors/space_outliner/outliner_select.c +++ b/source/blender/editors/space_outliner/outliner_select.c @@ -870,13 +870,13 @@ static eOLDrawState tree_element_active_sequence(bContext *C, const eOLSetState set) { Sequence *seq = (Sequence *)te->directdata; - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); if (set != OL_SETSEL_NONE) { /* only check on setting */ if (BLI_findindex(ed->seqbasep, seq) != -1) { if (set == OL_SETSEL_EXTEND) { - BKE_sequencer_active_set(scene, NULL); + SEQ_select_active_set(scene, NULL); } ED_sequencer_deselect_all(scene); @@ -885,7 +885,7 @@ static eOLDrawState tree_element_active_sequence(bContext *C, } else { seq->flag |= SELECT; - BKE_sequencer_active_set(scene, seq); + SEQ_select_active_set(scene, seq); } } @@ -905,7 +905,7 @@ static eOLDrawState tree_element_active_sequence_dup(Scene *scene, const eOLSetState set) { Sequence *seq, *p; - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); seq = (Sequence *)te->directdata; if (set == OL_SETSEL_NONE) { diff --git a/source/blender/editors/space_outliner/outliner_sync.c b/source/blender/editors/space_outliner/outliner_sync.c index 0f5c74a9168..b3e8761f60b 100644 --- a/source/blender/editors/space_outliner/outliner_sync.c +++ b/source/blender/editors/space_outliner/outliner_sync.c @@ -305,7 +305,7 @@ static void outliner_select_sync_to_sequence(Scene *scene, TreeStoreElem *tselem Sequence *seq = (Sequence *)tselem->id; if (tselem->flag & TSE_ACTIVE) { - BKE_sequencer_active_set(scene, seq); + SEQ_select_active_set(scene, seq); } if (tselem->flag & TSE_SELECTED) { @@ -542,7 +542,7 @@ static void get_sync_select_active_data(const bContext *C, SyncSelectActiveData active_data->object = OBACT(view_layer); active_data->edit_bone = CTX_data_active_bone(C); active_data->pose_channel = CTX_data_active_pose_bone(C); - active_data->sequence = BKE_sequencer_active_get(scene); + active_data->sequence = SEQ_select_active_get(scene); } /* If outliner is dirty sync selection from view layer and sequwncer */ diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c index 492fc5c23bc..d4784a509bf 100644 --- a/source/blender/editors/space_outliner/outliner_tools.c +++ b/source/blender/editors/space_outliner/outliner_tools.c @@ -1206,7 +1206,7 @@ static void sequence_fn(int event, TreeElement *te, TreeStoreElem *tselem, void Sequence *seq = (Sequence *)te->directdata; if (event == OL_DOP_SELECT) { Scene *scene = (Scene *)scene_ptr; - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); if (BLI_findindex(ed->seqbasep, seq) != -1) { ED_sequencer_select_sequence_single(scene, seq, true); } diff --git a/source/blender/editors/space_outliner/tree/tree_display_sequencer.cc b/source/blender/editors/space_outliner/tree/tree_display_sequencer.cc index 48f0322ccb9..40f329d72c3 100644 --- a/source/blender/editors/space_outliner/tree/tree_display_sequencer.cc +++ b/source/blender/editors/space_outliner/tree/tree_display_sequencer.cc @@ -43,7 +43,7 @@ ListBase TreeDisplaySequencer::buildTree(const TreeSourceData &source_data) { ListBase tree = {nullptr}; - Editing *ed = BKE_sequencer_editing_get(source_data.scene, false); + Editing *ed = SEQ_editing_get(source_data.scene, false); if (ed == nullptr) { return tree; } diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c index 71433a6978a..e40e9f5429d 100644 --- a/source/blender/editors/space_sequencer/sequencer_add.c +++ b/source/blender/editors/space_sequencer/sequencer_add.c @@ -149,7 +149,7 @@ static void sequencer_generic_invoke_path__internal(bContext *C, { if (RNA_struct_find_property(op->ptr, identifier)) { Scene *scene = CTX_data_scene(C); - Sequence *last_seq = BKE_sequencer_active_get(scene); + Sequence *last_seq = SEQ_select_active_get(scene); if (last_seq && last_seq->strip && SEQ_HAS_PATH(last_seq)) { Main *bmain = CTX_data_main(C); char path[FILE_MAX]; @@ -165,7 +165,7 @@ static int sequencer_generic_invoke_xy_guess_channel(bContext *C, int type) Sequence *tgt = NULL; Sequence *seq; Scene *scene = CTX_data_scene(C); - Editing *ed = BKE_sequencer_editing_get(scene, true); + Editing *ed = SEQ_editing_get(scene, true); int timeline_frame = (int)CFRA; int proximity = INT_MAX; @@ -306,11 +306,11 @@ static void seq_load_operator_info(SeqLoadInfo *seq_load, bContext *C, wmOperato static void sequencer_add_apply_overlap(bContext *C, wmOperator *op, Sequence *seq) { Scene *scene = CTX_data_scene(C); - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); if (RNA_boolean_get(op->ptr, "overlap") == false) { - if (BKE_sequence_test_overlap(ed->seqbasep, seq)) { - BKE_sequence_base_shuffle(ed->seqbasep, seq, scene); + if (SEQ_transform_test_overlap(ed->seqbasep, seq)) { + SEQ_transform_seqbase_shuffle(ed->seqbasep, seq, scene); } } } @@ -321,7 +321,7 @@ static void sequencer_add_apply_replace_sel(bContext *C, wmOperator *op, Sequenc if (RNA_boolean_get(op->ptr, "replace_sel")) { ED_sequencer_deselect_all(scene); - BKE_sequencer_active_set(scene, seq); + SEQ_select_active_set(scene, seq); seq->flag |= SELECT; } } @@ -334,7 +334,7 @@ static bool seq_effect_add_properties_poll(const bContext *UNUSED(C), int type = RNA_enum_get(op->ptr, "type"); /* Hide start/end frames for effect strips that are locked to their parents' location. */ - if (BKE_sequence_effect_get_num_inputs(type) != 0) { + if (SEQ_effect_get_num_inputs(type) != 0) { if (STR_ELEM(prop_id, "frame_start", "frame_end")) { return false; } @@ -350,7 +350,7 @@ static int sequencer_add_scene_strip_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); - Editing *ed = BKE_sequencer_editing_get(scene, true); + Editing *ed = SEQ_editing_get(scene, true); Scene *sce_seq; Sequence *seq; @@ -364,20 +364,20 @@ static int sequencer_add_scene_strip_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - seq = BKE_sequence_alloc(ed->seqbasep, start_frame, channel, SEQ_TYPE_SCENE); + seq = SEQ_sequence_alloc(ed->seqbasep, start_frame, channel, SEQ_TYPE_SCENE); seq->blend_mode = SEQ_TYPE_CROSS; seq->scene = sce_seq; seq->len = sce_seq->r.efra - sce_seq->r.sfra + 1; BLI_strncpy(seq->name + 2, sce_seq->id.name + 2, sizeof(seq->name) - 2); - BKE_sequence_base_unique_name_recursive(&ed->seqbase, seq); + SEQ_sequence_base_unique_name_recursive(&ed->seqbase, seq); - BKE_sequence_calc_disp(scene, seq); - BKE_sequencer_sort(scene); + SEQ_time_update_sequence_bounds(scene, seq); + SEQ_sort(scene); sequencer_add_apply_replace_sel(C, op, seq); sequencer_add_apply_overlap(C, op, seq); - BKE_sequence_invalidate_cache_composite(scene, seq); + SEQ_relations_invalidate_cache_composite(scene, seq); DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS); DEG_relations_tag_update(bmain); @@ -424,7 +424,7 @@ static int sequencer_add_movieclip_strip_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); - Editing *ed = BKE_sequencer_editing_get(scene, true); + Editing *ed = SEQ_editing_get(scene, true); MovieClip *clip; Sequence *seq; @@ -438,7 +438,7 @@ static int sequencer_add_movieclip_strip_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - seq = BKE_sequence_alloc(ed->seqbasep, start_frame, channel, SEQ_TYPE_MOVIECLIP); + seq = SEQ_sequence_alloc(ed->seqbasep, start_frame, channel, SEQ_TYPE_MOVIECLIP); seq->blend_mode = SEQ_TYPE_CROSS; seq->clip = clip; seq->len = BKE_movieclip_get_duration(clip); @@ -446,14 +446,14 @@ static int sequencer_add_movieclip_strip_exec(bContext *C, wmOperator *op) id_us_ensure_real(&seq->clip->id); BLI_strncpy(seq->name + 2, clip->id.name + 2, sizeof(seq->name) - 2); - BKE_sequence_base_unique_name_recursive(&ed->seqbase, seq); + SEQ_sequence_base_unique_name_recursive(&ed->seqbase, seq); - BKE_sequence_calc_disp(scene, seq); - BKE_sequencer_sort(scene); + SEQ_time_update_sequence_bounds(scene, seq); + SEQ_sort(scene); sequencer_add_apply_replace_sel(C, op, seq); sequencer_add_apply_overlap(C, op, seq); - BKE_sequence_invalidate_cache_composite(scene, seq); + SEQ_relations_invalidate_cache_composite(scene, seq); DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); @@ -500,7 +500,7 @@ static int sequencer_add_mask_strip_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); - Editing *ed = BKE_sequencer_editing_get(scene, true); + Editing *ed = SEQ_editing_get(scene, true); Mask *mask; Sequence *seq; @@ -514,7 +514,7 @@ static int sequencer_add_mask_strip_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - seq = BKE_sequence_alloc(ed->seqbasep, start_frame, channel, SEQ_TYPE_MASK); + seq = SEQ_sequence_alloc(ed->seqbasep, start_frame, channel, SEQ_TYPE_MASK); seq->blend_mode = SEQ_TYPE_CROSS; seq->mask = mask; seq->len = BKE_mask_get_duration(mask); @@ -522,14 +522,14 @@ static int sequencer_add_mask_strip_exec(bContext *C, wmOperator *op) id_us_ensure_real(&seq->mask->id); BLI_strncpy(seq->name + 2, mask->id.name + 2, sizeof(seq->name) - 2); - BKE_sequence_base_unique_name_recursive(&ed->seqbase, seq); + SEQ_sequence_base_unique_name_recursive(&ed->seqbase, seq); - BKE_sequence_calc_disp(scene, seq); - BKE_sequencer_sort(scene); + SEQ_time_update_sequence_bounds(scene, seq); + SEQ_sort(scene); sequencer_add_apply_replace_sel(C, op, seq); sequencer_add_apply_overlap(C, op, seq); - BKE_sequence_invalidate_cache_composite(scene, seq); + SEQ_relations_invalidate_cache_composite(scene, seq); DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); @@ -574,7 +574,7 @@ void SEQUENCER_OT_mask_strip_add(struct wmOperatorType *ot) static int sequencer_add_generic_strip_exec(bContext *C, wmOperator *op, SeqLoadFn seq_load_fn) { Scene *scene = CTX_data_scene(C); - Editing *ed = BKE_sequencer_editing_get(scene, true); + Editing *ed = SEQ_editing_get(scene, true); SeqLoadInfo seq_load; int tot_files; @@ -632,7 +632,7 @@ static int sequencer_add_generic_strip_exec(bContext *C, wmOperator *op, SeqLoad return OPERATOR_CANCELLED; } - BKE_sequencer_sort(scene); + SEQ_sort(scene); DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); @@ -664,7 +664,7 @@ static bool sequencer_add_draw_check_fn(PointerRNA *UNUSED(ptr), static int sequencer_add_movie_strip_exec(bContext *C, wmOperator *op) { - return sequencer_add_generic_strip_exec(C, op, BKE_sequencer_add_movie_strip); + return sequencer_add_generic_strip_exec(C, op, SEQ_add_movie_strip); } static int sequencer_add_movie_strip_invoke(bContext *C, @@ -673,7 +673,7 @@ static int sequencer_add_movie_strip_invoke(bContext *C, { PropertyRNA *prop; Scene *scene = CTX_data_scene(C); - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); /* Only enable "use_framerate" if there aren't any existing strips, unless overridden by user. */ if (ed && ed->seqbasep && ed->seqbasep->first) { @@ -757,7 +757,7 @@ void SEQUENCER_OT_movie_strip_add(struct wmOperatorType *ot) static int sequencer_add_sound_strip_exec(bContext *C, wmOperator *op) { - return sequencer_add_generic_strip_exec(C, op, BKE_sequencer_add_sound_strip); + return sequencer_add_generic_strip_exec(C, op, SEQ_add_sound_strip); } static int sequencer_add_sound_strip_invoke(bContext *C, @@ -871,7 +871,7 @@ static int sequencer_add_image_strip_exec(bContext *C, wmOperator *op) { int minframe, numdigits; Scene *scene = CTX_data_scene(C); - Editing *ed = BKE_sequencer_editing_get(scene, true); + Editing *ed = SEQ_editing_get(scene, true); SeqLoadInfo seq_load; Sequence *seq; Strip *strip; @@ -899,7 +899,7 @@ static int sequencer_add_image_strip_exec(bContext *C, wmOperator *op) } /* Main adding function. */ - seq = BKE_sequencer_add_image_strip(C, ed->seqbasep, &seq_load); + seq = SEQ_add_image_strip(C, ed->seqbasep, &seq_load); strip = seq->strip; se = strip->stripdata; seq->blend_mode = SEQ_TYPE_ALPHAOVER; @@ -924,8 +924,8 @@ static int sequencer_add_image_strip_exec(bContext *C, wmOperator *op) } SEQ_render_init_colorspace(seq); - BKE_sequence_calc_disp(scene, seq); - BKE_sequencer_sort(scene); + SEQ_time_update_sequence_bounds(scene, seq); + SEQ_sort(scene); /* Last active name. */ BLI_strncpy(ed->act_imagedir, strip->dir, sizeof(ed->act_imagedir)); @@ -935,7 +935,7 @@ static int sequencer_add_image_strip_exec(bContext *C, wmOperator *op) MEM_freeN(op->customdata); } - BKE_sequence_invalidate_cache_composite(scene, seq); + SEQ_relations_invalidate_cache_composite(scene, seq); DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); @@ -1009,7 +1009,7 @@ void SEQUENCER_OT_image_strip_add(struct wmOperatorType *ot) static int sequencer_add_effect_strip_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); - Editing *ed = BKE_sequencer_editing_get(scene, true); + Editing *ed = SEQ_editing_get(scene, true); Sequence *seq; struct SeqEffectHandle sh; Sequence *seq1, *seq2, *seq3; @@ -1032,11 +1032,11 @@ static int sequencer_add_effect_strip_exec(bContext *C, wmOperator *op) RNA_int_set(op->ptr, "frame_end", end_frame); } - seq = BKE_sequence_alloc(ed->seqbasep, start_frame, channel, type); - BLI_strncpy(seq->name + 2, BKE_sequence_give_name(seq), sizeof(seq->name) - 2); - BKE_sequence_base_unique_name_recursive(&ed->seqbase, seq); + seq = SEQ_sequence_alloc(ed->seqbasep, start_frame, channel, type); + BLI_strncpy(seq->name + 2, SEQ_sequence_give_name(seq), sizeof(seq->name) - 2); + SEQ_sequence_base_unique_name_recursive(&ed->seqbase, seq); - sh = BKE_sequence_get_effect(seq); + sh = SEQ_effect_handle_get(seq); sh.init(seq); seq->seq1 = seq1; seq->seq2 = seq2; @@ -1044,11 +1044,11 @@ static int sequencer_add_effect_strip_exec(bContext *C, wmOperator *op) if (!seq1) { seq->len = 1; /* Effect is generator, set non zero length. */ - BKE_sequence_tx_set_final_right(seq, end_frame); + SEQ_transform_set_right_handle_frame(seq, end_frame); } seq->flag |= SEQ_USE_EFFECT_DEFAULT_FADE; - BKE_sequence_calc(scene, seq); + SEQ_time_update_sequence(scene, seq); if (seq->type == SEQ_TYPE_COLOR) { SolidColorVars *colvars = (SolidColorVars *)seq->effectdata; @@ -1077,10 +1077,10 @@ static int sequencer_add_effect_strip_exec(bContext *C, wmOperator *op) sequencer_add_apply_replace_sel(C, op, seq); sequencer_add_apply_overlap(C, op, seq); - BKE_sequencer_update_changed_seq_and_deps(scene, seq, 1, 1); /* Runs BKE_sequence_calc. */ - BKE_sequencer_sort(scene); + SEQ_relations_update_changed_seq_and_deps(scene, seq, 1, 1); /* Runs SEQ_time_update_sequence. */ + SEQ_sort(scene); - BKE_sequence_invalidate_cache_composite(scene, seq); + SEQ_relations_invalidate_cache_composite(scene, seq); DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); @@ -1100,7 +1100,7 @@ static int sequencer_add_effect_strip_invoke(bContext *C, /* When invoking an effect strip which uses inputs, skip initializing the channel from the * mouse. */ - if (BKE_sequence_effect_get_num_inputs(type) != 0) { + if (SEQ_effect_get_num_inputs(type) != 0) { prop_flag |= SEQPROP_NOCHAN; } } diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index d7d601a3c76..2f146690416 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -371,7 +371,7 @@ static void drawmeta_contents(Scene *scene, Sequence *seqm, float x1, float y1, ListBase *seqbase; int offset; - seqbase = BKE_sequence_seqbase_get(seqm, &offset); + seqbase = SEQ_get_seqbase_from_sequence(seqm, &offset); if (!seqbase || BLI_listbase_is_empty(seqbase)) { return; } @@ -488,7 +488,7 @@ static void draw_seq_handle(View2D *v2d, whichsel = SEQ_RIGHTSEL; } - if (!(seq->type & SEQ_TYPE_EFFECT) || BKE_sequence_effect_get_num_inputs(seq->type) == 0) { + if (!(seq->type & SEQ_TYPE_EFFECT) || SEQ_effect_get_num_inputs(seq->type) == 0) { GPU_blend(GPU_BLEND_ALPHA); GPU_blend(GPU_BLEND_ALPHA); @@ -607,7 +607,7 @@ static const char *draw_seq_text_get_name(Sequence *seq) { const char *name = seq->name + 2; if (name[0] == '\0') { - name = BKE_sequence_give_name(seq); + name = SEQ_sequence_give_name(seq); } return name; } @@ -840,9 +840,9 @@ static void draw_seq_background(Scene *scene, /* Draw the main strip body. */ if (is_single_image) { immRectf(pos, - BKE_sequence_tx_get_final_left(seq, false), + SEQ_transform_get_left_handle_frame(seq, false), y1, - BKE_sequence_tx_get_final_right(seq, false), + SEQ_transform_get_right_handle_frame(seq, false), y2); } else { @@ -1067,7 +1067,7 @@ static void draw_seq_strip(const bContext *C, float pixely = BLI_rctf_size_y(&v2d->cur) / BLI_rcti_size_y(&v2d->mask); /* Check if we are doing "solo preview". */ - bool is_single_image = (char)BKE_sequence_single_check(seq); + bool is_single_image = (char)SEQ_transform_single_image_check(seq); /* Draw strip body. */ x1 = (seq->startstill) ? seq->start : seq->startdisp; @@ -1143,7 +1143,7 @@ static void draw_seq_strip(const bContext *C, } /* Draw Red line on the top of invalid strip (Missing media). */ - if (!BKE_sequence_is_valid_check(seq)) { + if (!SEQ_sequence_has_source(seq)) { draw_seq_invalid(x1, x2, y2, text_margin_y); } @@ -1441,7 +1441,7 @@ void sequencer_draw_maskedit(const bContext *C, Scene *scene, ARegion *region, S // if (sc->mode == SC_MODE_MASKEDIT) if (0 && sseq->mainb == SEQ_DRAW_IMG_IMBUF) { - Mask *mask = BKE_sequencer_mask_get(scene); + Mask *mask = SEQ_active_mask_get(scene); if (mask) { int width, height; @@ -1473,7 +1473,7 @@ void sequencer_draw_maskedit(const bContext *C, Scene *scene, ARegion *region, S /* Force redraw, when prefetching and using cache view. */ static void seq_prefetch_wm_notify(const bContext *C, Scene *scene) { - if (BKE_sequencer_prefetch_need_redraw(CTX_data_main(C), scene)) { + if (SEQ_prefetch_need_redraw(CTX_data_main(C), scene)) { WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, NULL); } } @@ -1913,7 +1913,7 @@ static void draw_seq_strips(const bContext *C, Editing *ed, ARegion *region) Scene *scene = CTX_data_scene(C); View2D *v2d = ®ion->v2d; SpaceSeq *sseq = CTX_wm_space_seq(C); - Sequence *last_seq = BKE_sequencer_active_get(scene); + Sequence *last_seq = SEQ_select_active_get(scene); int sel = 0, j; float pixelx = BLI_rctf_size_x(&v2d->cur) / BLI_rcti_size_x(&v2d->mask); @@ -1956,7 +1956,7 @@ static void draw_seq_strips(const bContext *C, Editing *ed, ARegion *region) draw_seq_strip(C, sseq, scene, region, last_seq, pixelx, true); /* When active strip is an effect, highlight its inputs. */ - if (BKE_sequence_effect_get_num_inputs(last_seq->type) > 0) { + if (SEQ_effect_get_num_inputs(last_seq->type) > 0) { draw_effect_inputs_highlight(last_seq); } /* When active is a Multi-cam strip, highlight its source channel. */ @@ -2000,7 +2000,7 @@ static void draw_seq_strips(const bContext *C, Editing *ed, ARegion *region) static void seq_draw_sfra_efra(Scene *scene, View2D *v2d) { - const Editing *ed = BKE_sequencer_editing_get(scene, false); + const Editing *ed = SEQ_editing_get(scene, false); const int frame_sta = scene->r.sfra; const int frame_end = scene->r.efra + 1; @@ -2265,7 +2265,7 @@ static void draw_cache_view(const bContext *C) userdata.composite_vbo = GPU_vertbuf_create_with_format(&format); userdata.final_out_vbo = GPU_vertbuf_create_with_format(&format); - BKE_sequencer_cache_iterate(scene, &userdata, draw_cache_view_init_fn, draw_cache_view_iter_fn); + SEQ_cache_iterate(scene, &userdata, draw_cache_view_init_fn, draw_cache_view_iter_fn); draw_cache_view_batch(userdata.raw_vbo, userdata.raw_vert_count, 1.0f, 0.1f, 0.02f, 0.4f); draw_cache_view_batch( @@ -2282,7 +2282,7 @@ static void draw_cache_view(const bContext *C) void draw_timeline_seq(const bContext *C, ARegion *region) { Scene *scene = CTX_data_scene(C); - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); SpaceSeq *sseq = CTX_wm_space_seq(C); View2D *v2d = ®ion->v2d; short cfra_flag = 0; diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c index ddc9ba2e0f6..f78b602ceda 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.c +++ b/source/blender/editors/space_sequencer/sequencer_edit.c @@ -96,7 +96,7 @@ bool ED_space_sequencer_maskedit_mask_poll(bContext *C) bool ED_space_sequencer_check_show_maskedit(SpaceSeq *sseq, Scene *scene) { if (sseq && sseq->mainb == SEQ_DRAW_IMG_IMBUF) { - return (BKE_sequencer_mask_get(scene) != NULL); + return (SEQ_active_mask_get(scene) != NULL); } return false; @@ -136,14 +136,14 @@ bool ED_space_sequencer_check_show_strip(SpaceSeq *sseq) /* Operator functions. */ bool sequencer_edit_poll(bContext *C) { - return (BKE_sequencer_editing_get(CTX_data_scene(C), false) != NULL); + return (SEQ_editing_get(CTX_data_scene(C), false) != NULL); } #if 0 /* UNUSED */ bool sequencer_strip_poll(bContext *C) { Editing *ed; - return (((ed = BKE_sequencer_editing_get(CTX_data_scene(C), false)) != NULL) && + return (((ed = SEQ_editing_get(CTX_data_scene(C), false)) != NULL) && (ed->act_seq != NULL)); } #endif @@ -152,14 +152,14 @@ bool sequencer_strip_has_path_poll(bContext *C) { Editing *ed; Sequence *seq; - return (((ed = BKE_sequencer_editing_get(CTX_data_scene(C), false)) != NULL) && + return (((ed = SEQ_editing_get(CTX_data_scene(C), false)) != NULL) && ((seq = ed->act_seq) != NULL) && (SEQ_HAS_PATH(seq))); } bool sequencer_view_preview_poll(bContext *C) { SpaceSeq *sseq = CTX_wm_space_seq(C); - Editing *ed = BKE_sequencer_editing_get(CTX_data_scene(C), false); + Editing *ed = SEQ_editing_get(CTX_data_scene(C), false); if (ed && sseq && (sseq->mainb == SEQ_DRAW_IMG_IMBUF)) { return 1; } @@ -187,7 +187,7 @@ static int sequencer_gap_remove_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); const bool do_all = RNA_boolean_get(op->ptr, "all"); - const Editing *ed = BKE_sequencer_editing_get(scene, false); + const Editing *ed = SEQ_editing_get(scene, false); SEQ_edit_remove_gaps(scene, ed->seqbasep, CFRA, do_all); @@ -227,8 +227,8 @@ static int sequencer_gap_insert_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); const int frames = RNA_int_get(op->ptr, "frames"); - const Editing *ed = BKE_sequencer_editing_get(scene, false); - SEQ_offset_after_frame(scene, ed->seqbasep, frames, CFRA); + const Editing *ed = SEQ_editing_get(scene, false); + SEQ_transform_offset_after_frame(scene, ed->seqbasep, frames, CFRA); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); @@ -273,7 +273,7 @@ static int sequencer_snap_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); Sequence *seq; int snap_frame; @@ -282,22 +282,22 @@ static int sequencer_snap_exec(bContext *C, wmOperator *op) /* Check metas. */ for (seq = ed->seqbasep->first; seq; seq = seq->next) { if (seq->flag & SELECT && !(seq->depth == 0 && seq->flag & SEQ_LOCK) && - BKE_sequence_tx_test(seq)) { + SEQ_transform_sequence_can_be_translated(seq)) { if ((seq->flag & (SEQ_LEFTSEL + SEQ_RIGHTSEL)) == 0) { - BKE_sequence_translate( + SEQ_transform_translate_sequence( scene, seq, (snap_frame - seq->startofs + seq->startstill) - seq->start); } else { if (seq->flag & SEQ_LEFTSEL) { - BKE_sequence_tx_set_final_left(seq, snap_frame); + SEQ_transform_set_left_handle_frame(seq, snap_frame); } else { /* SEQ_RIGHTSEL */ - BKE_sequence_tx_set_final_right(seq, snap_frame); + SEQ_transform_set_right_handle_frame(seq, snap_frame); } - BKE_sequence_tx_handle_xlimits(seq, seq->flag & SEQ_LEFTSEL, seq->flag & SEQ_RIGHTSEL); - BKE_sequence_single_fix(seq); + SEQ_transform_handle_xlimits(seq, seq->flag & SEQ_LEFTSEL, seq->flag & SEQ_RIGHTSEL); + SEQ_transform_fix_single_image_seq_offsets(seq); } - BKE_sequence_calc(scene, seq); + SEQ_time_update_sequence(scene, seq); } } @@ -306,8 +306,8 @@ static int sequencer_snap_exec(bContext *C, wmOperator *op) for (seq = ed->seqbasep->first; seq; seq = seq->next) { if (seq->flag & SELECT && !(seq->depth == 0 && seq->flag & SEQ_LOCK)) { seq->flag &= ~SEQ_OVERLAP; - if (BKE_sequence_test_overlap(ed->seqbasep, seq)) { - BKE_sequence_base_shuffle(ed->seqbasep, seq, scene); + if (SEQ_transform_test_overlap(ed->seqbasep, seq)) { + SEQ_transform_seqbase_shuffle(ed->seqbasep, seq, scene); } } } @@ -316,21 +316,21 @@ static int sequencer_snap_exec(bContext *C, wmOperator *op) for (seq = ed->seqbasep->first; seq; seq = seq->next) { if (seq->type & SEQ_TYPE_EFFECT) { if (seq->seq1 && (seq->seq1->flag & SELECT)) { - BKE_sequencer_offset_animdata(scene, seq, (snap_frame - seq->startdisp)); - BKE_sequence_calc(scene, seq); + SEQ_offset_animdata(scene, seq, (snap_frame - seq->startdisp)); + SEQ_time_update_sequence(scene, seq); } else if (seq->seq2 && (seq->seq2->flag & SELECT)) { - BKE_sequencer_offset_animdata(scene, seq, (snap_frame - seq->startdisp)); - BKE_sequence_calc(scene, seq); + SEQ_offset_animdata(scene, seq, (snap_frame - seq->startdisp)); + SEQ_time_update_sequence(scene, seq); } else if (seq->seq3 && (seq->seq3->flag & SELECT)) { - BKE_sequencer_offset_animdata(scene, seq, (snap_frame - seq->startdisp)); - BKE_sequence_calc(scene, seq); + SEQ_offset_animdata(scene, seq, (snap_frame - seq->startdisp)); + SEQ_time_update_sequence(scene, seq); } } } - BKE_sequencer_sort(scene); + SEQ_sort(scene); DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); @@ -470,7 +470,7 @@ static int sequencer_slip_invoke(bContext *C, wmOperator *op, const wmEvent *eve { SlipData *data; Scene *scene = CTX_data_scene(C); - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); float mouseloc[2]; int num_seq; View2D *v2d = UI_view2d_fromcontext(C); @@ -518,7 +518,7 @@ static int sequencer_slip_invoke(bContext *C, wmOperator *op, const wmEvent *eve static bool sequencer_slip_recursively(Scene *scene, SlipData *data, int offset) { /* Only data types supported for now. */ - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); bool changed = false; /* Iterate in reverse so meta-strips are iterated after their children. */ @@ -568,11 +568,11 @@ static bool sequencer_slip_recursively(Scene *scene, SlipData *data, int offset) * we can skip calculating for effects. * This way we can avoid an extra loop just for effects. */ if (!(seq->type & SEQ_TYPE_EFFECT)) { - BKE_sequence_calc(scene, seq); + SEQ_time_update_sequence(scene, seq); } } if (changed) { - BKE_sequencer_free_imbuf(scene, &ed->seqbase, false); + SEQ_relations_free_imbuf(scene, &ed->seqbase, false); } return changed; } @@ -602,7 +602,7 @@ static void sequencer_slip_apply_limits(SlipData *data, int *offset) static int sequencer_slip_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); int offset = RNA_int_get(op->ptr, "offset"); bool success = false; @@ -737,7 +737,7 @@ static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *even case EVT_ESCKEY: case RIGHTMOUSE: { - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); for (int i = 0; i < data->num_seq; i++) { transseq_restore(data->ts + i, data->seq_array[i]); @@ -745,8 +745,8 @@ static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *even for (int i = 0; i < data->num_seq; i++) { Sequence *seq = data->seq_array[i]; - BKE_sequence_reload_new_file(bmain, scene, seq, false); - BKE_sequence_calc(scene, seq); + SEQ_add_reload_new_file(bmain, scene, seq, false); + SEQ_time_update_sequence(scene, seq); } MEM_freeN(data->seq_array); @@ -757,7 +757,7 @@ static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *even WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); - BKE_sequencer_free_imbuf(scene, &ed->seqbase, false); + SEQ_relations_free_imbuf(scene, &ed->seqbase, false); if (area) { ED_area_status_text(area, NULL); @@ -839,7 +839,7 @@ void SEQUENCER_OT_slip(struct wmOperatorType *ot) static int sequencer_mute_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); Sequence *seq; bool selected; @@ -850,13 +850,13 @@ static int sequencer_mute_exec(bContext *C, wmOperator *op) if (selected) { if (seq->flag & SELECT) { seq->flag |= SEQ_MUTE; - BKE_sequence_invalidate_dependent(scene, seq); + SEQ_relations_invalidate_dependent(scene, seq); } } else { if ((seq->flag & SELECT) == 0) { seq->flag |= SEQ_MUTE; - BKE_sequence_invalidate_dependent(scene, seq); + SEQ_relations_invalidate_dependent(scene, seq); } } } @@ -895,7 +895,7 @@ void SEQUENCER_OT_mute(struct wmOperatorType *ot) static int sequencer_unmute_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); Sequence *seq; bool selected; @@ -906,13 +906,13 @@ static int sequencer_unmute_exec(bContext *C, wmOperator *op) if (selected) { if (seq->flag & SELECT) { seq->flag &= ~SEQ_MUTE; - BKE_sequence_invalidate_dependent(scene, seq); + SEQ_relations_invalidate_dependent(scene, seq); } } else { if ((seq->flag & SELECT) == 0) { seq->flag &= ~SEQ_MUTE; - BKE_sequence_invalidate_dependent(scene, seq); + SEQ_relations_invalidate_dependent(scene, seq); } } } @@ -951,7 +951,7 @@ void SEQUENCER_OT_unmute(struct wmOperatorType *ot) static int sequencer_lock_exec(bContext *C, wmOperator *UNUSED(op)) { Scene *scene = CTX_data_scene(C); - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); Sequence *seq; for (seq = ed->seqbasep->first; seq; seq = seq->next) { @@ -989,7 +989,7 @@ void SEQUENCER_OT_lock(struct wmOperatorType *ot) static int sequencer_unlock_exec(bContext *C, wmOperator *UNUSED(op)) { Scene *scene = CTX_data_scene(C); - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); Sequence *seq; for (seq = ed->seqbasep->first; seq; seq = seq->next) { @@ -1028,18 +1028,18 @@ static int sequencer_reload_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); Sequence *seq; const bool adjust_length = RNA_boolean_get(op->ptr, "adjust_length"); for (seq = ed->seqbasep->first; seq; seq = seq->next) { if (seq->flag & SELECT) { - BKE_sequencer_update_changed_seq_and_deps(scene, seq, 0, 1); - BKE_sequence_reload_new_file(bmain, scene, seq, !adjust_length); + SEQ_relations_update_changed_seq_and_deps(scene, seq, 0, 1); + SEQ_add_reload_new_file(bmain, scene, seq, !adjust_length); if (adjust_length) { - if (BKE_sequence_test_overlap(ed->seqbasep, seq)) { - BKE_sequence_base_shuffle(ed->seqbasep, seq, scene); + if (SEQ_transform_test_overlap(ed->seqbasep, seq)) { + SEQ_transform_seqbase_shuffle(ed->seqbasep, seq, scene); } } } @@ -1091,9 +1091,9 @@ static bool sequencer_refresh_all_poll(bContext *C) static int sequencer_refresh_all_exec(bContext *C, wmOperator *UNUSED(op)) { Scene *scene = CTX_data_scene(C); - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); - BKE_sequencer_free_imbuf(scene, &ed->seqbase, false); + SEQ_relations_free_imbuf(scene, &ed->seqbase, false); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); @@ -1126,18 +1126,18 @@ int seq_effect_find_selected(Scene *scene, Sequence **r_selseq3, const char **r_error_str) { - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); Sequence *seq1 = NULL, *seq2 = NULL, *seq3 = NULL, *seq; *r_error_str = NULL; if (!activeseq) { - seq2 = BKE_sequencer_active_get(scene); + seq2 = SEQ_select_active_get(scene); } for (seq = ed->seqbasep->first; seq; seq = seq->next) { if (seq->flag & SELECT) { - if (seq->type == SEQ_TYPE_SOUND_RAM && BKE_sequence_effect_get_num_inputs(type) != 0) { + if (seq->type == SEQ_TYPE_SOUND_RAM && SEQ_effect_get_num_inputs(type) != 0) { *r_error_str = N_("Cannot apply effects to audio sequence strips"); return 0; } @@ -1167,7 +1167,7 @@ int seq_effect_find_selected(Scene *scene, seq3 = tmp; } - switch (BKE_sequence_effect_get_num_inputs(type)) { + switch (SEQ_effect_get_num_inputs(type)) { case 0: *r_selseq1 = *r_selseq2 = *r_selseq3 = NULL; return 1; /* Success. */ @@ -1204,10 +1204,10 @@ int seq_effect_find_selected(Scene *scene, *r_selseq3 = seq3; /* TODO(Richard): This function needs some refactoring, this is just quick hack for T73828. */ - if (BKE_sequence_effect_get_num_inputs(type) < 3) { + if (SEQ_effect_get_num_inputs(type) < 3) { *r_selseq3 = NULL; } - if (BKE_sequence_effect_get_num_inputs(type) < 2) { + if (SEQ_effect_get_num_inputs(type) < 2) { *r_selseq2 = NULL; } @@ -1217,24 +1217,24 @@ int seq_effect_find_selected(Scene *scene, static int sequencer_reassign_inputs_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); - Sequence *seq1, *seq2, *seq3, *last_seq = BKE_sequencer_active_get(scene); + Sequence *seq1, *seq2, *seq3, *last_seq = SEQ_select_active_get(scene); const char *error_msg; - if (BKE_sequence_effect_get_num_inputs(last_seq->type) == 0) { + if (SEQ_effect_get_num_inputs(last_seq->type) == 0) { BKE_report(op->reports, RPT_ERROR, "Cannot reassign inputs: strip has no inputs"); return OPERATOR_CANCELLED; } if (!seq_effect_find_selected( scene, last_seq, last_seq->type, &seq1, &seq2, &seq3, &error_msg) || - BKE_sequence_effect_get_num_inputs(last_seq->type) == 0) { + SEQ_effect_get_num_inputs(last_seq->type) == 0) { BKE_report(op->reports, RPT_ERROR, error_msg); return OPERATOR_CANCELLED; } /* Check if reassigning would create recursivity. */ - if (BKE_sequencer_render_loop_check(seq1, last_seq) || - BKE_sequencer_render_loop_check(seq2, last_seq) || - BKE_sequencer_render_loop_check(seq3, last_seq)) { + if (SEQ_relations_render_loop_check(seq1, last_seq) || + SEQ_relations_render_loop_check(seq2, last_seq) || + SEQ_relations_render_loop_check(seq3, last_seq)) { BKE_report(op->reports, RPT_ERROR, "Cannot reassign inputs: recursion detected"); return OPERATOR_CANCELLED; } @@ -1243,7 +1243,7 @@ static int sequencer_reassign_inputs_exec(bContext *C, wmOperator *op) last_seq->seq2 = seq2; last_seq->seq3 = seq3; - BKE_sequencer_update_changed_seq_and_deps(scene, last_seq, 1, 1); + SEQ_relations_update_changed_seq_and_deps(scene, last_seq, 1, 1); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); @@ -1253,10 +1253,10 @@ static int sequencer_reassign_inputs_exec(bContext *C, wmOperator *op) static bool sequencer_effect_poll(bContext *C) { Scene *scene = CTX_data_scene(C); - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); if (ed) { - Sequence *last_seq = BKE_sequencer_active_get(scene); + Sequence *last_seq = SEQ_select_active_get(scene); if (last_seq && (last_seq->type & SEQ_TYPE_EFFECT)) { return 1; } @@ -1289,7 +1289,7 @@ void SEQUENCER_OT_reassign_inputs(struct wmOperatorType *ot) static int sequencer_swap_inputs_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); - Sequence *seq, *last_seq = BKE_sequencer_active_get(scene); + Sequence *seq, *last_seq = SEQ_select_active_get(scene); if (last_seq->seq1 == NULL || last_seq->seq2 == NULL) { BKE_report(op->reports, RPT_ERROR, "No valid inputs to swap"); @@ -1300,7 +1300,7 @@ static int sequencer_swap_inputs_exec(bContext *C, wmOperator *op) last_seq->seq1 = last_seq->seq2; last_seq->seq2 = seq; - BKE_sequencer_update_changed_seq_and_deps(scene, last_seq, 1, 1); + SEQ_relations_update_changed_seq_and_deps(scene, last_seq, 1, 1); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); @@ -1360,7 +1360,7 @@ static int sequencer_split_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); bool changed = false; bool seq_selected = false; @@ -1371,7 +1371,7 @@ static int sequencer_split_exec(bContext *C, wmOperator *op) const int split_side = RNA_enum_get(op->ptr, "side"); const bool ignore_selection = RNA_boolean_get(op->ptr, "ignore_selection"); - BKE_sequencer_prefetch_stop(scene); + SEQ_prefetch_stop(scene); LISTBASE_FOREACH_BACKWARD (Sequence *, seq, ed->seqbasep) { if (use_cursor_position && seq->machine != split_channel) { @@ -1423,7 +1423,7 @@ static int sequencer_split_exec(bContext *C, wmOperator *op) } } - BKE_sequencer_sort(scene); + SEQ_sort(scene); } if (changed) { WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); @@ -1566,15 +1566,15 @@ static int apply_unique_name_fn(Sequence *seq, void *arg_pt) char name[sizeof(seq->name) - 2]; BLI_strncpy_utf8(name, seq->name + 2, sizeof(name)); - BKE_sequence_base_unique_name_recursive(&scene->ed->seqbase, seq); - BKE_sequencer_dupe_animdata(scene, name, seq->name + 2); + SEQ_sequence_base_unique_name_recursive(&scene->ed->seqbase, seq); + SEQ_dupe_animdata(scene, name, seq->name + 2); return 1; } static int sequencer_add_duplicate_exec(bContext *C, wmOperator *UNUSED(op)) { Scene *scene = CTX_data_scene(C); - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); ListBase nseqbase = {NULL, NULL}; @@ -1582,16 +1582,16 @@ static int sequencer_add_duplicate_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_CANCELLED; } - BKE_sequence_base_dupli_recursive(scene, scene, &nseqbase, ed->seqbasep, SEQ_DUPE_CONTEXT, 0); + SEQ_sequence_base_dupli_recursive(scene, scene, &nseqbase, ed->seqbasep, SEQ_DUPE_CONTEXT, 0); if (nseqbase.first) { Sequence *seq = nseqbase.first; /* Rely on the nseqbase list being added at the end. - * Their UUIDs has been re-generated by the BKE_sequence_base_dupli_recursive(), */ + * Their UUIDs has been re-generated by the SEQ_sequence_base_dupli_recursive(), */ BLI_movelisttolist(ed->seqbasep, &nseqbase); for (; seq; seq = seq->next) { - BKE_sequencer_recursive_apply(seq, apply_unique_name_fn, scene); + SEQ_iterator_recursive_apply(seq, apply_unique_name_fn, scene); } WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); @@ -1626,18 +1626,18 @@ static int sequencer_delete_exec(bContext *C, wmOperator *UNUSED(op)) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); Sequence *seq; - BKE_sequencer_prefetch_stop(scene); + SEQ_prefetch_stop(scene); SEQ_CURRENT_BEGIN (scene->ed, seq) { if (seq->flag & SELECT) { - BKE_sequencer_flag_for_removal(scene, ed->seqbasep, seq); + SEQ_edit_flag_for_removal(scene, ed->seqbasep, seq); } } SEQ_CURRENT_END; - BKE_sequencer_remove_flagged_sequences(scene, ed->seqbasep); + SEQ_edit_remove_flagged_sequences(scene, ed->seqbasep); DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS); DEG_relations_tag_update(bmain); @@ -1687,7 +1687,7 @@ void SEQUENCER_OT_delete(wmOperatorType *ot) static int sequencer_offset_clear_exec(bContext *C, wmOperator *UNUSED(op)) { Scene *scene = CTX_data_scene(C); - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); Sequence *seq; /* For effects, try to find a replacement input. */ @@ -1700,14 +1700,14 @@ static int sequencer_offset_clear_exec(bContext *C, wmOperator *UNUSED(op)) /* Update lengths, etc. */ seq = ed->seqbasep->first; while (seq) { - BKE_sequence_calc(scene, seq); + SEQ_time_update_sequence(scene, seq); seq = seq->next; } for (seq = ed->seqbasep->first; seq; seq = seq->next) { if ((seq->type & SEQ_TYPE_EFFECT) == 0 && (seq->flag & SELECT)) { - if (BKE_sequence_test_overlap(ed->seqbasep, seq)) { - BKE_sequence_base_shuffle(ed->seqbasep, seq, scene); + if (SEQ_transform_test_overlap(ed->seqbasep, seq)) { + SEQ_transform_seqbase_shuffle(ed->seqbasep, seq, scene); } } } @@ -1742,7 +1742,7 @@ void SEQUENCER_OT_offset_clear(wmOperatorType *ot) static int sequencer_separate_images_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); Sequence *seq, *seq_new; Strip *strip_new; @@ -1752,7 +1752,7 @@ static int sequencer_separate_images_exec(bContext *C, wmOperator *op) seq = ed->seqbasep->first; /* Poll checks this is valid. */ - BKE_sequencer_prefetch_stop(scene); + SEQ_prefetch_stop(scene); while (seq) { if ((seq->flag & SELECT) && (seq->type == SEQ_TYPE_IMAGE) && (seq->len > 1)) { @@ -1764,14 +1764,14 @@ static int sequencer_separate_images_exec(bContext *C, wmOperator *op) /* if (seq->ipo) id_us_min(&seq->ipo->id); */ /* XXX, remove fcurve and assign to split image strips */ - start_ofs = timeline_frame = BKE_sequence_tx_get_final_left(seq, false); - frame_end = BKE_sequence_tx_get_final_right(seq, false); + start_ofs = timeline_frame = SEQ_transform_get_left_handle_frame(seq, false); + frame_end = SEQ_transform_get_right_handle_frame(seq, false); while (timeline_frame < frame_end) { /* New seq. */ se = SEQ_render_give_stripelem(seq, timeline_frame); - seq_new = BKE_sequence_dupli_recursive( + seq_new = SEQ_sequence_dupli_recursive( scene, scene, ed->seqbasep, seq, SEQ_DUPE_UNIQUE_NAME); seq_new->start = start_ofs; @@ -1790,12 +1790,12 @@ static int sequencer_separate_images_exec(bContext *C, wmOperator *op) BLI_strncpy(se_new->name, se->name, sizeof(se_new->name)); strip_new->stripdata = se_new; - BKE_sequence_calc(scene, seq_new); + SEQ_time_update_sequence(scene, seq_new); if (step > 1) { seq_new->flag &= ~SEQ_OVERLAP; - if (BKE_sequence_test_overlap(ed->seqbasep, seq_new)) { - BKE_sequence_base_shuffle(ed->seqbasep, seq_new, scene); + if (SEQ_transform_test_overlap(ed->seqbasep, seq_new)) { + SEQ_transform_seqbase_shuffle(ed->seqbasep, seq_new, scene); } } @@ -1806,7 +1806,7 @@ static int sequencer_separate_images_exec(bContext *C, wmOperator *op) } seq_next = seq->next; - BKE_sequence_free(scene, seq, true); + SEQ_sequence_free(scene, seq, true); seq = seq_next; } else { @@ -1814,7 +1814,7 @@ static int sequencer_separate_images_exec(bContext *C, wmOperator *op) } } - BKE_sequencer_sort(scene); + SEQ_sort(scene); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); @@ -1873,8 +1873,8 @@ void recurs_sel_seq(Sequence *seqm) static int sequencer_meta_toggle_exec(bContext *C, wmOperator *UNUSED(op)) { Scene *scene = CTX_data_scene(C); - Editing *ed = BKE_sequencer_editing_get(scene, false); - Sequence *last_seq = BKE_sequencer_active_get(scene); + Editing *ed = SEQ_editing_get(scene, false); + Sequence *last_seq = SEQ_select_active_get(scene); MetaStack *ms; if (last_seq && last_seq->type == SEQ_TYPE_META && last_seq->flag & SELECT) { @@ -1887,7 +1887,7 @@ static int sequencer_meta_toggle_exec(bContext *C, wmOperator *UNUSED(op)) ed->seqbasep = &last_seq->seqbase; - BKE_sequencer_active_set(scene, NULL); + SEQ_select_active_set(scene, NULL); } else { /* Exit metastrip if possible. */ @@ -1910,23 +1910,23 @@ static int sequencer_meta_toggle_exec(bContext *C, wmOperator *UNUSED(op)) /* Recalc all: the meta can have effects connected to it. */ for (seq = ed->seqbasep->first; seq; seq = seq->next) { - BKE_sequence_calc(scene, seq); + SEQ_time_update_sequence(scene, seq); } /* 2.73+, keeping endpoints is important! * Moving them around means you can't usefully use metas in a complex edit. */ #if 1 - BKE_sequence_tx_set_final_left(ms->parseq, ms->disp_range[0]); - BKE_sequence_tx_set_final_right(ms->parseq, ms->disp_range[1]); - BKE_sequence_single_fix(ms->parseq); - BKE_sequence_calc(scene, ms->parseq); + SEQ_transform_set_left_handle_frame(ms->parseq, ms->disp_range[0]); + SEQ_transform_set_right_handle_frame(ms->parseq, ms->disp_range[1]); + SEQ_transform_fix_single_image_seq_offsets(ms->parseq); + SEQ_time_update_sequence(scene, ms->parseq); #else - if (BKE_sequence_test_overlap(ed->seqbasep, ms->parseq)) { - BKE_sequence_base_shuffle(ed->seqbasep, ms->parseq, scene); + if (SEQ_transform_test_overlap(ed->seqbasep, ms->parseq)) { + SEQ_transform_seqbase_shuffle(ed->seqbasep, ms->parseq, scene); } #endif - BKE_sequencer_active_set(scene, ms->parseq); + SEQ_select_active_set(scene, ms->parseq); ms->parseq->flag |= SELECT; recurs_sel_seq(ms->parseq); @@ -1964,21 +1964,21 @@ void SEQUENCER_OT_meta_toggle(wmOperatorType *ot) static int sequencer_meta_make_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); - Sequence *seq, *seqm, *next, *last_seq = BKE_sequencer_active_get(scene); + Sequence *seq, *seqm, *next, *last_seq = SEQ_select_active_get(scene); int channel_max = 1; - if (BKE_sequence_base_isolated_sel_check(ed->seqbasep) == false) { + if (SEQ_transform_seqbase_isolated_sel_check(ed->seqbasep) == false) { BKE_report(op->reports, RPT_ERROR, "Please select all related strips"); return OPERATOR_CANCELLED; } - BKE_sequencer_prefetch_stop(scene); + SEQ_prefetch_stop(scene); /* Remove all selected from main list, and put in meta. */ - seqm = BKE_sequence_alloc(ed->seqbasep, 1, 1, SEQ_TYPE_META); /* Channel number set later. */ + seqm = SEQ_sequence_alloc(ed->seqbasep, 1, 1, SEQ_TYPE_META); /* Channel number set later. */ strcpy(seqm->name + 2, "MetaStrip"); seqm->flag = SELECT; @@ -1986,7 +1986,7 @@ static int sequencer_meta_make_exec(bContext *C, wmOperator *op) while (seq) { next = seq->next; if (seq != seqm && (seq->flag & SELECT)) { - BKE_sequence_invalidate_cache_composite(scene, seq); + SEQ_relations_invalidate_cache_composite(scene, seq); channel_max = max_ii(seq->machine, channel_max); /* Sequence is moved within the same edit, no need to re-generate the UUID. */ BLI_remlink(ed->seqbasep, seq); @@ -1995,18 +1995,18 @@ static int sequencer_meta_make_exec(bContext *C, wmOperator *op) seq = next; } seqm->machine = last_seq ? last_seq->machine : channel_max; - BKE_sequence_calc(scene, seqm); + SEQ_time_update_sequence(scene, seqm); - BKE_sequencer_active_set(scene, seqm); + SEQ_select_active_set(scene, seqm); - if (BKE_sequence_test_overlap(ed->seqbasep, seqm)) { - BKE_sequence_base_shuffle(ed->seqbasep, seqm, scene); + if (SEQ_transform_test_overlap(ed->seqbasep, seqm)) { + SEQ_transform_seqbase_shuffle(ed->seqbasep, seqm, scene); } DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS); - BKE_sequence_base_unique_name_recursive(&scene->ed->seqbase, seqm); - BKE_sequence_invalidate_cache_composite(scene, seqm); + SEQ_sequence_base_unique_name_recursive(&scene->ed->seqbase, seqm); + SEQ_relations_invalidate_cache_composite(scene, seqm); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); return OPERATOR_FINISHED; @@ -2053,7 +2053,7 @@ static int seq_depends_on_meta(Sequence *seq, Sequence *seqm) static void recurs_del_seq_flag(Scene *scene, ListBase *lb, short flag, short deleteall) { Sequence *seq, *seqn; - Sequence *last_seq = BKE_sequencer_active_get(scene); + Sequence *last_seq = SEQ_select_active_get(scene); seq = lb->first; while (seq) { @@ -2061,12 +2061,12 @@ static void recurs_del_seq_flag(Scene *scene, ListBase *lb, short flag, short de if ((seq->flag & flag) || deleteall) { BLI_remlink(lb, seq); if (seq == last_seq) { - BKE_sequencer_active_set(scene, NULL); + SEQ_select_active_set(scene, NULL); } if (seq->type == SEQ_TYPE_META) { recurs_del_seq_flag(scene, &seq->seqbase, flag, 1); } - BKE_sequence_free(scene, seq, true); + SEQ_sequence_free(scene, seq, true); } seq = seqn; } @@ -2075,18 +2075,18 @@ static void recurs_del_seq_flag(Scene *scene, ListBase *lb, short flag, short de static int sequencer_meta_separate_exec(bContext *C, wmOperator *UNUSED(op)) { Scene *scene = CTX_data_scene(C); - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); - Sequence *seq, *last_seq = BKE_sequencer_active_get(scene); /* last_seq checks (ed == NULL) */ + Sequence *seq, *last_seq = SEQ_select_active_get(scene); /* last_seq checks (ed == NULL) */ if (last_seq == NULL || last_seq->type != SEQ_TYPE_META) { return OPERATOR_CANCELLED; } - BKE_sequencer_prefetch_stop(scene); + SEQ_prefetch_stop(scene); for (seq = last_seq->seqbase.first; seq != NULL; seq = seq->next) { - BKE_sequence_invalidate_cache_composite(scene, seq); + SEQ_relations_invalidate_cache_composite(scene, seq); } /* This moves strips from meta to parent, sating within same edit and no new strips are @@ -2097,7 +2097,7 @@ static int sequencer_meta_separate_exec(bContext *C, wmOperator *UNUSED(op)) BLI_listbase_clear(&last_seq->seqbase); BLI_remlink(ed->seqbasep, last_seq); - BKE_sequence_free(scene, last_seq, true); + SEQ_sequence_free(scene, last_seq, true); /* Empty meta strip, delete all effects depending on it. */ for (seq = ed->seqbasep->first; seq; seq = seq->next) { @@ -2113,13 +2113,13 @@ static int sequencer_meta_separate_exec(bContext *C, wmOperator *UNUSED(op)) for (seq = ed->seqbasep->first; seq; seq = seq->next) { if (seq->flag & SELECT) { seq->flag &= ~SEQ_OVERLAP; - if (BKE_sequence_test_overlap(ed->seqbasep, seq)) { - BKE_sequence_base_shuffle(ed->seqbasep, seq, scene); + if (SEQ_transform_test_overlap(ed->seqbasep, seq)) { + SEQ_transform_seqbase_shuffle(ed->seqbasep, seq, scene); } } } - BKE_sequencer_sort(scene); + SEQ_sort(scene); DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); @@ -2155,7 +2155,7 @@ static bool strip_jump_internal(Scene *scene, { bool changed = false; int timeline_frame = CFRA; - int next_frame = BKE_sequencer_find_next_prev_edit( + int next_frame = SEQ_time_find_next_prev_edit( scene, timeline_frame, side, do_skip_mute, do_center, false); if (next_frame != timeline_frame) { @@ -2230,19 +2230,19 @@ static void swap_sequence(Scene *scene, Sequence *seqa, Sequence *seqb) int seq_b_start; seq_b_start = (seqb->start - seqb->startdisp) + seqa->startdisp; - BKE_sequence_translate(scene, seqb, seq_b_start - seqb->start); - BKE_sequence_calc(scene, seqb); + SEQ_transform_translate_sequence(scene, seqb, seq_b_start - seqb->start); + SEQ_time_update_sequence(scene, seqb); seq_a_start = (seqa->start - seqa->startdisp) + seqb->enddisp + gap; - BKE_sequence_translate(scene, seqa, seq_a_start - seqa->start); - BKE_sequence_calc(scene, seqa); + SEQ_transform_translate_sequence(scene, seqa, seq_a_start - seqa->start); + SEQ_time_update_sequence(scene, seqa); } static Sequence *find_next_prev_sequence(Scene *scene, Sequence *test, int lr, int sel) { /* sel: 0==unselected, 1==selected, -1==don't care. */ Sequence *seq, *best_seq = NULL; - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); int dist, best_dist; best_dist = MAXFRAME * 2; @@ -2292,8 +2292,8 @@ static bool seq_is_parent(Sequence *par, Sequence *seq) static int sequencer_swap_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); - Editing *ed = BKE_sequencer_editing_get(scene, false); - Sequence *active_seq = BKE_sequencer_active_get(scene); + Editing *ed = SEQ_editing_get(scene, false); + Sequence *active_seq = SEQ_select_active_get(scene); Sequence *seq, *iseq; int side = RNA_enum_get(op->ptr, "side"); @@ -2306,11 +2306,11 @@ static int sequencer_swap_exec(bContext *C, wmOperator *op) if (seq) { /* Disallow effect strips. */ - if (BKE_sequence_effect_get_num_inputs(seq->type) >= 1 && + if (SEQ_effect_get_num_inputs(seq->type) >= 1 && (seq->effectdata || seq->seq1 || seq->seq2 || seq->seq3)) { return OPERATOR_CANCELLED; } - if ((BKE_sequence_effect_get_num_inputs(active_seq->type) >= 1) && + if ((SEQ_effect_get_num_inputs(active_seq->type) >= 1) && (active_seq->effectdata || active_seq->seq1 || active_seq->seq2 || active_seq->seq3)) { return OPERATOR_CANCELLED; } @@ -2328,7 +2328,7 @@ static int sequencer_swap_exec(bContext *C, wmOperator *op) for (iseq = scene->ed->seqbasep->first; iseq; iseq = iseq->next) { if ((iseq->type & SEQ_TYPE_EFFECT) && (seq_is_parent(iseq, active_seq) || seq_is_parent(iseq, seq))) { - BKE_sequence_calc(scene, iseq); + SEQ_time_update_sequence(scene, iseq); } } @@ -2337,13 +2337,13 @@ static int sequencer_swap_exec(bContext *C, wmOperator *op) if ((iseq->type & SEQ_TYPE_EFFECT) && (seq_is_parent(iseq, active_seq) || seq_is_parent(iseq, seq))) { /* This may now overlap. */ - if (BKE_sequence_test_overlap(ed->seqbasep, iseq)) { - BKE_sequence_base_shuffle(ed->seqbasep, iseq, scene); + if (SEQ_transform_test_overlap(ed->seqbasep, iseq)) { + SEQ_transform_seqbase_shuffle(ed->seqbasep, iseq, scene); } } } - BKE_sequencer_sort(scene); + SEQ_sort(scene); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); @@ -2382,7 +2382,7 @@ static int sequencer_rendersize_exec(bContext *C, wmOperator *UNUSED(op)) { int retval = OPERATOR_CANCELLED; Scene *scene = CTX_data_scene(C); - Sequence *active_seq = BKE_sequencer_active_get(scene); + Sequence *active_seq = SEQ_select_active_get(scene); StripElem *se = NULL; if (active_seq == NULL) { @@ -2458,11 +2458,11 @@ static int sequencer_copy_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); - BKE_sequencer_free_clipboard(); + SEQ_clipboard_free(); - if (BKE_sequence_base_isolated_sel_check(ed->seqbasep) == false) { + if (SEQ_transform_seqbase_isolated_sel_check(ed->seqbasep) == false) { BKE_report(op->reports, RPT_ERROR, "Please select all related strips"); return OPERATOR_CANCELLED; } @@ -2470,7 +2470,7 @@ static int sequencer_copy_exec(bContext *C, wmOperator *op) /* NOTE: The UUID is re-generated on paste, so we can keep UUID in the clipboard since * nobody can reach them anyway. * This reduces chance or running out of UUIDs if a cat falls asleep on Ctrl-C. */ - BKE_sequence_base_dupli_recursive(scene, + SEQ_sequence_base_dupli_recursive(scene, scene, &seqbase_clipboard, ed->seqbasep, @@ -2486,7 +2486,7 @@ static int sequencer_copy_exec(bContext *C, wmOperator *op) /* Replace datablock pointers with copies, to keep things working in case * data-blocks get deleted or another .blend file is opened. */ - BKE_sequencer_base_clipboard_pointers_store(bmain, &seqbase_clipboard); + SEQ_clipboard_pointers_store(bmain, &seqbase_clipboard); return OPERATOR_FINISHED; } @@ -2515,7 +2515,7 @@ void SEQUENCER_OT_copy(wmOperatorType *ot) void ED_sequencer_deselect_all(Scene *scene) { Sequence *seq; - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); if (ed == NULL) { return; @@ -2531,7 +2531,7 @@ static int sequencer_paste_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); - Editing *ed = BKE_sequencer_editing_get(scene, true); /* Create if needed. */ + Editing *ed = SEQ_editing_get(scene, true); /* Create if needed. */ ListBase nseqbase = {NULL, NULL}; int ofs; Sequence *iseq, *iseq_first; @@ -2559,25 +2559,25 @@ static int sequencer_paste_exec(bContext *C, wmOperator *op) /* Copy strips, temporarily restoring pointers to actual data-blocks. This * must happen on the clipboard itself, so that copying does user counting * on the actual data-blocks. */ - BKE_sequencer_base_clipboard_pointers_restore(&seqbase_clipboard, bmain); - BKE_sequence_base_dupli_recursive(scene, scene, &nseqbase, &seqbase_clipboard, 0, 0); - BKE_sequencer_base_clipboard_pointers_store(bmain, &seqbase_clipboard); + SEQ_clipboard_pointers_restore(&seqbase_clipboard, bmain); + SEQ_sequence_base_dupli_recursive(scene, scene, &nseqbase, &seqbase_clipboard, 0, 0); + SEQ_clipboard_pointers_store(bmain, &seqbase_clipboard); iseq_first = nseqbase.first; - /* NOTE: BKE_sequence_base_dupli_recursive() takes care of generating new UUIDs for sequences + /* NOTE: SEQ_sequence_base_dupli_recursive() takes care of generating new UUIDs for sequences * in the new list. */ BLI_movelisttolist(ed->seqbasep, &nseqbase); for (iseq = iseq_first; iseq; iseq = iseq->next) { /* Make sure, that pasted strips have unique names. */ - BKE_sequencer_recursive_apply(iseq, apply_unique_name_fn, scene); + SEQ_iterator_recursive_apply(iseq, apply_unique_name_fn, scene); /* Translate after name has been changed, otherwise this will affect animdata of original * strip. */ - BKE_sequence_translate(scene, iseq, ofs); + SEQ_transform_translate_sequence(scene, iseq, ofs); /* Ensure, that pasted strips don't overlap. */ - if (BKE_sequence_test_overlap(ed->seqbasep, iseq)) { - BKE_sequence_base_shuffle(ed->seqbasep, iseq, scene); + if (SEQ_transform_test_overlap(ed->seqbasep, iseq)) { + SEQ_transform_seqbase_shuffle(ed->seqbasep, iseq, scene); } } @@ -2622,12 +2622,12 @@ static int sequencer_swap_data_exec(bContext *C, wmOperator *op) Sequence *seq_other; const char *error_msg; - if (BKE_sequencer_active_get_pair(scene, &seq_act, &seq_other) == 0) { + if (SEQ_select_active_get_pair(scene, &seq_act, &seq_other) == 0) { BKE_report(op->reports, RPT_ERROR, "Please select two strips"); return OPERATOR_CANCELLED; } - if (BKE_sequence_swap(seq_act, seq_other, &error_msg) == 0) { + if (SEQ_edit_sequence_swap(seq_act, seq_other, &error_msg) == 0) { BKE_report(op->reports, RPT_ERROR, error_msg); return OPERATOR_CANCELLED; } @@ -2643,8 +2643,8 @@ static int sequencer_swap_data_exec(bContext *C, wmOperator *op) seq_act->scene_sound = NULL; seq_other->scene_sound = NULL; - BKE_sequence_calc(scene, seq_act); - BKE_sequence_calc(scene, seq_other); + SEQ_time_update_sequence(scene, seq_act); + SEQ_time_update_sequence(scene, seq_other); if (seq_act->sound) { BKE_sound_add_scene_sound_defaults(scene, seq_act); @@ -2653,8 +2653,8 @@ static int sequencer_swap_data_exec(bContext *C, wmOperator *op) BKE_sound_add_scene_sound_defaults(scene, seq_other); } - BKE_sequence_invalidate_cache_raw(scene, seq_act); - BKE_sequence_invalidate_cache_raw(scene, seq_other); + SEQ_relations_invalidate_cache_raw(scene, seq_act); + SEQ_relations_invalidate_cache_raw(scene, seq_other); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); @@ -2692,8 +2692,8 @@ static const EnumPropertyItem prop_change_effect_input_types[] = { static int sequencer_change_effect_input_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); - Editing *ed = BKE_sequencer_editing_get(scene, false); - Sequence *seq = BKE_sequencer_active_get(scene); + Editing *ed = SEQ_editing_get(scene, false); + Sequence *seq = SEQ_select_active_get(scene); Sequence **seq_1, **seq_2; @@ -2719,10 +2719,10 @@ static int sequencer_change_effect_input_exec(bContext *C, wmOperator *op) SWAP(Sequence *, *seq_1, *seq_2); - BKE_sequencer_update_changed_seq_and_deps(scene, seq, 0, 1); + SEQ_relations_update_changed_seq_and_deps(scene, seq, 0, 1); /* Invalidate cache. */ - BKE_sequencer_free_imbuf(scene, &ed->seqbase, false); + SEQ_relations_free_imbuf(scene, &ed->seqbase, false); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); return OPERATOR_FINISHED; @@ -2776,8 +2776,8 @@ EnumPropertyItem sequencer_prop_effect_types[] = { static int sequencer_change_effect_type_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); - Editing *ed = BKE_sequencer_editing_get(scene, false); - Sequence *seq = BKE_sequencer_active_get(scene); + Editing *ed = SEQ_editing_get(scene, false); + Sequence *seq = SEQ_select_active_get(scene); const int new_type = RNA_enum_get(op->ptr, "type"); /* Free previous effect and init new effect. */ @@ -2789,23 +2789,22 @@ static int sequencer_change_effect_type_exec(bContext *C, wmOperator *op) /* Can someone explain the logic behind only allowing to increase this, * copied from 2.4x - campbell */ - if (BKE_sequence_effect_get_num_inputs(seq->type) < - BKE_sequence_effect_get_num_inputs(new_type)) { + if (SEQ_effect_get_num_inputs(seq->type) < SEQ_effect_get_num_inputs(new_type)) { BKE_report(op->reports, RPT_ERROR, "New effect needs more input strips"); return OPERATOR_CANCELLED; } - sh = BKE_sequence_get_effect(seq); + sh = SEQ_effect_handle_get(seq); sh.free(seq, true); seq->type = new_type; - sh = BKE_sequence_get_effect(seq); + sh = SEQ_effect_handle_get(seq); sh.init(seq); - BKE_sequencer_update_changed_seq_and_deps(scene, seq, 0, 1); + SEQ_relations_update_changed_seq_and_deps(scene, seq, 0, 1); /* Invalidate cache. */ - BKE_sequencer_free_imbuf(scene, &ed->seqbase, false); + SEQ_relations_free_imbuf(scene, &ed->seqbase, false); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); @@ -2843,8 +2842,8 @@ static int sequencer_change_path_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); - Editing *ed = BKE_sequencer_editing_get(scene, false); - Sequence *seq = BKE_sequencer_active_get(scene); + Editing *ed = SEQ_editing_get(scene, false); + Sequence *seq = SEQ_select_active_get(scene); const bool is_relative_path = RNA_boolean_get(op->ptr, "relative_path"); const bool use_placeholders = RNA_boolean_get(op->ptr, "use_placeholders"); int minext_frameme, numdigits; @@ -2897,12 +2896,12 @@ static int sequencer_change_path_exec(bContext *C, wmOperator *op) /* Correct start/end frames so we don't move. * Important not to set seq->len = len; allow the function to handle it. */ - BKE_sequence_reload_new_file(bmain, scene, seq, true); + SEQ_add_reload_new_file(bmain, scene, seq, true); - BKE_sequence_calc(scene, seq); + SEQ_time_update_sequence(scene, seq); /* Invalidate cache. */ - BKE_sequencer_free_imbuf(scene, &ed->seqbase, false); + SEQ_relations_free_imbuf(scene, &ed->seqbase, false); } else if (ELEM(seq->type, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SOUND_HD)) { bSound *sound = seq->sound; @@ -2936,7 +2935,7 @@ static int sequencer_change_path_exec(bContext *C, wmOperator *op) static int sequencer_change_path_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { Scene *scene = CTX_data_scene(C); - Sequence *seq = BKE_sequencer_active_get(scene); + Sequence *seq = SEQ_select_active_get(scene); char filepath[FILE_MAX]; BLI_join_dirfile(filepath, sizeof(filepath), seq->strip->dir, seq->strip->stripdata->name); @@ -3020,7 +3019,7 @@ static int sequencer_export_subtitles_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); Sequence *seq, *seq_next; - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); ListBase text_seq = {0}; int iter = 0; FILE *file; @@ -3059,7 +3058,7 @@ static int sequencer_export_subtitles_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - BLI_listbase_sort(&text_seq, BKE_sequencer_cmp_time_startdisp); + BLI_listbase_sort(&text_seq, SEQ_time_cmp_time_startdisp); /* Open and write file. */ file = BLI_fopen(filepath, "w"); @@ -3098,7 +3097,7 @@ static bool sequencer_strip_is_text_poll(bContext *C) { Editing *ed; Sequence *seq; - return (((ed = BKE_sequencer_editing_get(CTX_data_scene(C), false)) != NULL) && + return (((ed = SEQ_editing_get(CTX_data_scene(C), false)) != NULL) && ((seq = ed->act_seq) != NULL) && (seq->type == SEQ_TYPE_TEXT)); } @@ -3135,7 +3134,7 @@ void SEQUENCER_OT_export_subtitles(struct wmOperatorType *ot) static int sequencer_set_range_to_strips_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); Sequence *seq; int sfra = MAXFRAME; @@ -3206,7 +3205,7 @@ void SEQUENCER_OT_set_range_to_strips(struct wmOperatorType *ot) static void set_filter_seq(Scene *scene) { Sequence *seq; - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); if (ed == NULL) { return; @@ -3220,8 +3219,8 @@ static void set_filter_seq(Scene *scene) if (seq->flag & SELECT) { if (seq->type == SEQ_TYPE_MOVIE) { seq->flag |= SEQ_FILTERY; - BKE_sequence_reload_new_file(bmain, scene, seq, false); - BKE_sequence_calc(scene, seq); + SEQ_add_reload_new_file(bmain, scene, seq, false); + SEQ_time_update_sequence(scene, seq); } } } @@ -3230,8 +3229,8 @@ static void set_filter_seq(Scene *scene) static void UNUSED_FUNCTION(seq_remap_paths)(Scene *scene) { - Sequence *seq, *last_seq = BKE_sequencer_active_get(scene); - Editing *ed = BKE_sequencer_editing_get(scene, false); + Sequence *seq, *last_seq = SEQ_select_active_get(scene); + Editing *ed = SEQ_editing_get(scene, false); char from[FILE_MAX], to[FILE_MAX], stripped[FILE_MAX]; if (last_seq == NULL) { @@ -3270,7 +3269,7 @@ static void UNUSED_FUNCTION(seq_remap_paths)(Scene *scene) static Sequence *sequence_find_parent(Scene *scene, Sequence *child) { - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); Sequence *parent = NULL; Sequence *seq; @@ -3322,7 +3321,7 @@ Sequence *find_neighboring_sequence(Scene *scene, Sequence *test, int lr, int se { /* sel: 0==unselected, 1==selected, -1==don't care. */ Sequence *seq; - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); if (ed == NULL) { return NULL; @@ -3356,7 +3355,7 @@ Sequence *find_neighboring_sequence(Scene *scene, Sequence *test, int lr, int se Sequence *find_nearest_seq(Scene *scene, View2D *v2d, int *hand, const int mval[2]) { Sequence *seq; - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); float x, y; float pixelx; float handsize; @@ -3378,7 +3377,7 @@ Sequence *find_nearest_seq(Scene *scene, View2D *v2d, int *hand, const int mval[ /* Check for both normal strips, and strips that have been flipped horizontally. */ if (((seq->startdisp < seq->enddisp) && (seq->startdisp <= x && seq->enddisp >= x)) || ((seq->startdisp > seq->enddisp) && (seq->startdisp >= x && seq->enddisp <= x))) { - if (BKE_sequence_tx_test(seq)) { + if (SEQ_transform_sequence_can_be_translated(seq)) { /* Clamp handles to defined size in pixel space. */ handsize = 2.0f * sequence_handle_size_get_clamped(seq, pixelx); @@ -3437,7 +3436,7 @@ static const EnumPropertyItem transform_reset_properties[] = { static int sequencer_strip_transform_clear_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); - const Editing *ed = BKE_sequencer_editing_get(scene, false); + const Editing *ed = SEQ_editing_get(scene, false); Sequence *seq; const int property = RNA_enum_get(op->ptr, "property"); @@ -3464,7 +3463,7 @@ static int sequencer_strip_transform_clear_exec(bContext *C, wmOperator *op) transform->rotation = 0.0f; break; } - BKE_sequence_invalidate_cache_preprocessed(scene, seq); + SEQ_relations_invalidate_cache_preprocessed(scene, seq); } } @@ -3510,7 +3509,7 @@ static const EnumPropertyItem scale_fit_methods[] = { static int sequencer_strip_transform_fit_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); - const Editing *ed = BKE_sequencer_editing_get(scene, false); + const Editing *ed = SEQ_editing_get(scene, false); Sequence *seq; const eSeqImageFitMethod fit_method = RNA_enum_get(op->ptr, "fit_method"); @@ -3529,7 +3528,7 @@ static int sequencer_strip_transform_fit_exec(bContext *C, wmOperator *op) scene->r.xsch, scene->r.ysch, fit_method); - BKE_sequence_invalidate_cache_preprocessed(scene, seq); + SEQ_relations_invalidate_cache_preprocessed(scene, seq); } } diff --git a/source/blender/editors/space_sequencer/sequencer_modifier.c b/source/blender/editors/space_sequencer/sequencer_modifier.c index fb09afc6ca5..e8f4fac1920 100644 --- a/source/blender/editors/space_sequencer/sequencer_modifier.c +++ b/source/blender/editors/space_sequencer/sequencer_modifier.c @@ -44,13 +44,13 @@ static bool strip_modifier_active_poll(bContext *C) { Scene *scene = CTX_data_scene(C); - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); if (ed) { - Sequence *seq = BKE_sequencer_active_get(scene); + Sequence *seq = SEQ_select_active_get(scene); if (seq) { - return BKE_sequence_supports_modifiers(seq); + return SEQ_sequence_supports_modifiers(seq); } } @@ -60,12 +60,12 @@ static bool strip_modifier_active_poll(bContext *C) static int strip_modifier_add_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); - Sequence *seq = BKE_sequencer_active_get(scene); + Sequence *seq = SEQ_select_active_get(scene); int type = RNA_enum_get(op->ptr, "type"); - BKE_sequence_modifier_new(seq, NULL, type); + SEQ_modifier_new(seq, NULL, type); - BKE_sequence_invalidate_cache_preprocessed(scene, seq); + SEQ_relations_invalidate_cache_preprocessed(scene, seq); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); return OPERATOR_FINISHED; @@ -102,21 +102,21 @@ void SEQUENCER_OT_strip_modifier_add(wmOperatorType *ot) static int strip_modifier_remove_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); - Sequence *seq = BKE_sequencer_active_get(scene); + Sequence *seq = SEQ_select_active_get(scene); char name[MAX_NAME]; SequenceModifierData *smd; RNA_string_get(op->ptr, "name", name); - smd = BKE_sequence_modifier_find_by_name(seq, name); + smd = SEQ_modifier_find_by_name(seq, name); if (!smd) { return OPERATOR_CANCELLED; } BLI_remlink(&seq->modifiers, smd); - BKE_sequence_modifier_free(smd); + SEQ_modifier_free(smd); - BKE_sequence_invalidate_cache_preprocessed(scene, seq); + SEQ_relations_invalidate_cache_preprocessed(scene, seq); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); return OPERATOR_FINISHED; @@ -153,7 +153,7 @@ enum { static int strip_modifier_move_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); - Sequence *seq = BKE_sequencer_active_get(scene); + Sequence *seq = SEQ_select_active_get(scene); char name[MAX_NAME]; int direction; SequenceModifierData *smd; @@ -161,7 +161,7 @@ static int strip_modifier_move_exec(bContext *C, wmOperator *op) RNA_string_get(op->ptr, "name", name); direction = RNA_enum_get(op->ptr, "direction"); - smd = BKE_sequence_modifier_find_by_name(seq, name); + smd = SEQ_modifier_find_by_name(seq, name); if (!smd) { return OPERATOR_CANCELLED; } @@ -179,7 +179,7 @@ static int strip_modifier_move_exec(bContext *C, wmOperator *op) } } - BKE_sequence_invalidate_cache_preprocessed(scene, seq); + SEQ_relations_invalidate_cache_preprocessed(scene, seq); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); return OPERATOR_FINISHED; @@ -225,7 +225,7 @@ static int strip_modifier_copy_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); Editing *ed = scene->ed; - Sequence *seq = BKE_sequencer_active_get(scene); + Sequence *seq = SEQ_select_active_get(scene); Sequence *seq_iter; const int type = RNA_enum_get(op->ptr, "type"); @@ -245,19 +245,19 @@ static int strip_modifier_copy_exec(bContext *C, wmOperator *op) while (smd) { smd_tmp = smd->next; BLI_remlink(&seq_iter->modifiers, smd); - BKE_sequence_modifier_free(smd); + SEQ_modifier_free(smd); smd = smd_tmp; } BLI_listbase_clear(&seq_iter->modifiers); } } - BKE_sequence_modifier_list_copy(seq_iter, seq); + SEQ_modifier_list_copy(seq_iter, seq); } } SEQ_CURRENT_END; - BKE_sequence_invalidate_cache_preprocessed(scene, seq); + SEQ_relations_invalidate_cache_preprocessed(scene, seq); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); return OPERATOR_FINISHED; diff --git a/source/blender/editors/space_sequencer/sequencer_proxy.c b/source/blender/editors/space_sequencer/sequencer_proxy.c index 2d23520814a..032885c2719 100644 --- a/source/blender/editors/space_sequencer/sequencer_proxy.c +++ b/source/blender/editors/space_sequencer/sequencer_proxy.c @@ -90,14 +90,14 @@ static void proxy_startjob(void *pjv, short *stop, short *do_update, float *prog static void proxy_endjob(void *pjv) { ProxyJob *pj = pjv; - Editing *ed = BKE_sequencer_editing_get(pj->scene, false); + Editing *ed = SEQ_editing_get(pj->scene, false); LinkData *link; for (link = pj->queue.first; link; link = link->next) { SEQ_proxy_rebuild_finish(link->data, pj->stop); } - BKE_sequencer_free_imbuf(pj->scene, &ed->seqbase, false); + SEQ_relations_free_imbuf(pj->scene, &ed->seqbase, false); WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, pj->scene); } @@ -108,7 +108,7 @@ static void seq_proxy_build_job(const bContext *C, ReportList *reports) ProxyJob *pj; struct Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); Scene *scene = CTX_data_scene(C); - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); ScrArea *area = CTX_wm_area(C); Sequence *seq; GSet *file_list; @@ -201,7 +201,7 @@ static int sequencer_rebuild_proxy_exec(bContext *C, wmOperator *UNUSED(op)) Main *bmain = CTX_data_main(C); struct Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); Scene *scene = CTX_data_scene(C); - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); Sequence *seq; GSet *file_list; @@ -225,7 +225,7 @@ static int sequencer_rebuild_proxy_exec(bContext *C, wmOperator *UNUSED(op)) SEQ_proxy_rebuild(context, &stop, &do_update, &progress); SEQ_proxy_rebuild_finish(context, 0); } - BKE_sequencer_free_imbuf(scene, &ed->seqbase, false); + SEQ_relations_free_imbuf(scene, &ed->seqbase, false); } } SEQ_CURRENT_END; @@ -266,7 +266,7 @@ static int sequencer_enable_proxies_invoke(bContext *C, static int sequencer_enable_proxies_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); Sequence *seq; bool proxy_25 = RNA_boolean_get(op->ptr, "proxy_25"); bool proxy_50 = RNA_boolean_get(op->ptr, "proxy_50"); diff --git a/source/blender/editors/space_sequencer/sequencer_select.c b/source/blender/editors/space_sequencer/sequencer_select.c index a6b2d7feae3..6534a63f03e 100644 --- a/source/blender/editors/space_sequencer/sequencer_select.c +++ b/source/blender/editors/space_sequencer/sequencer_select.c @@ -198,13 +198,13 @@ void select_surround_from_last(Scene *scene) void ED_sequencer_select_sequence_single(Scene *scene, Sequence *seq, bool deselect_all) { - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); if (deselect_all) { ED_sequencer_deselect_all(scene); } - BKE_sequencer_active_set(scene, seq); + SEQ_select_active_set(scene, seq); if (ELEM(seq->type, SEQ_TYPE_IMAGE, SEQ_TYPE_MOVIE)) { if (seq->strip) { @@ -223,7 +223,7 @@ void ED_sequencer_select_sequence_single(Scene *scene, Sequence *seq, bool desel #if 0 static void select_neighbor_from_last(Scene *scene, int lr) { - Sequence *seq = BKE_sequencer_active_get(scene); + Sequence *seq = SEQ_select_active_get(scene); Sequence *neighbor; bool changed = false; if (seq) { @@ -264,7 +264,7 @@ static int sequencer_de_select_all_exec(bContext *C, wmOperator *op) int action = RNA_enum_get(op->ptr, "action"); Scene *scene = CTX_data_scene(C); - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); Sequence *seq; if (action == SEL_TOGGLE) { @@ -331,7 +331,7 @@ void SEQUENCER_OT_select_all(struct wmOperatorType *ot) static int sequencer_select_inverse_exec(bContext *C, wmOperator *UNUSED(op)) { Scene *scene = CTX_data_scene(C); - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); Sequence *seq; for (seq = ed->seqbasep->first; seq; seq = seq->next) { @@ -376,7 +376,7 @@ static int sequencer_select_exec(bContext *C, wmOperator *op) { View2D *v2d = UI_view2d_fromcontext(C); Scene *scene = CTX_data_scene(C); - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); const bool extend = RNA_boolean_get(op->ptr, "extend"); const bool deselect_all = RNA_boolean_get(op->ptr, "deselect_all"); const bool linked_handle = RNA_boolean_get(op->ptr, "linked_handle"); @@ -464,7 +464,7 @@ static int sequencer_select_exec(bContext *C, wmOperator *op) ret_value = OPERATOR_FINISHED; } - BKE_sequencer_active_set(scene, seq); + SEQ_select_active_set(scene, seq); if (ELEM(seq->type, SEQ_TYPE_IMAGE, SEQ_TYPE_MOVIE)) { if (seq->strip) { @@ -667,7 +667,7 @@ void SEQUENCER_OT_select(wmOperatorType *ot) /* Run recursively to select linked. */ static bool select_more_less_seq__internal(Scene *scene, bool sel, const bool linked) { - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); Sequence *seq, *neighbor; bool changed = false; int isel; @@ -903,7 +903,7 @@ void SEQUENCER_OT_select_linked(wmOperatorType *ot) static int sequencer_select_handles_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); Sequence *seq; int sel_side = RNA_enum_get(op->ptr, "side"); @@ -964,7 +964,7 @@ void SEQUENCER_OT_select_handles(wmOperatorType *ot) static int sequencer_select_side_of_frame_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); const bool extend = RNA_boolean_get(op->ptr, "extend"); const int side = RNA_enum_get(op->ptr, "side"); Sequence *seq; @@ -1038,7 +1038,7 @@ void SEQUENCER_OT_select_side_of_frame(wmOperatorType *ot) static int sequencer_select_side_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); const int sel_side = RNA_enum_get(op->ptr, "side"); const int frame_init = sel_side == SEQ_SIDE_LEFT ? INT_MIN : INT_MAX; @@ -1109,7 +1109,7 @@ static int sequencer_box_select_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); View2D *v2d = UI_view2d_fromcontext(C); - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); if (ed == NULL) { return OPERATOR_CANCELLED; @@ -1454,8 +1454,7 @@ static bool select_grouped_effect_link(Editing *ed, Sequence *actseq, const int actseq->tmp = POINTER_FROM_INT(true); - for (BKE_sequence_iterator_begin(ed, &iter, true); iter.valid; - BKE_sequence_iterator_next(&iter)) { + for (SEQ_iterator_begin(ed, &iter, true); iter.valid; SEQ_iterator_next(&iter)) { seq = iter.seq; /* Ignore all seqs already selected. */ @@ -1486,8 +1485,8 @@ static bool select_grouped_effect_link(Editing *ed, Sequence *actseq, const int changed = true; /* Unfortunately, we must restart checks from the beginning. */ - BKE_sequence_iterator_end(&iter); - BKE_sequence_iterator_begin(ed, &iter, true); + SEQ_iterator_end(&iter); + SEQ_iterator_begin(ed, &iter, true); } /* Video strips below active one, or any strip for audio (order doesn't matter here). */ @@ -1496,7 +1495,7 @@ static bool select_grouped_effect_link(Editing *ed, Sequence *actseq, const int changed = true; } } - BKE_sequence_iterator_end(&iter); + SEQ_iterator_end(&iter); return changed; } @@ -1508,8 +1507,8 @@ static bool select_grouped_effect_link(Editing *ed, Sequence *actseq, const int static int sequencer_select_grouped_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); - Editing *ed = BKE_sequencer_editing_get(scene, false); - Sequence *seq, *actseq = BKE_sequencer_active_get(scene); + Editing *ed = SEQ_editing_get(scene, false); + Sequence *seq, *actseq = SEQ_select_active_get(scene); if (actseq == NULL) { BKE_report(op->reports, RPT_ERROR, "No active sequence!"); diff --git a/source/blender/editors/space_sequencer/sequencer_view.c b/source/blender/editors/space_sequencer/sequencer_view.c index e12c43b7804..250a0afc717 100644 --- a/source/blender/editors/space_sequencer/sequencer_view.c +++ b/source/blender/editors/space_sequencer/sequencer_view.c @@ -88,7 +88,7 @@ static int sequencer_view_all_exec(bContext *C, wmOperator *op) const int smooth_viewtx = WM_operator_smooth_viewtx_get(op); Scene *scene = CTX_data_scene(C); - const Editing *ed = BKE_sequencer_editing_get(scene, false); + const Editing *ed = SEQ_editing_get(scene, false); SEQ_timeline_boundbox(scene, SEQ_active_seqbase_get(ed), &box); UI_view2d_smooth_view(C, region, &box, smooth_viewtx); @@ -272,8 +272,8 @@ static int sequencer_view_selected_exec(bContext *C, wmOperator *op) Scene *scene = CTX_data_scene(C); View2D *v2d = UI_view2d_fromcontext(C); ARegion *region = CTX_wm_region(C); - Editing *ed = BKE_sequencer_editing_get(scene, false); - Sequence *last_seq = BKE_sequencer_active_get(scene); + Editing *ed = SEQ_editing_get(scene, false); + Sequence *last_seq = SEQ_select_active_get(scene); Sequence *seq; rctf cur_new = v2d->cur; diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c index 2bf4741e4f5..19146db3719 100644 --- a/source/blender/editors/space_sequencer/space_sequencer.c +++ b/source/blender/editors/space_sequencer/space_sequencer.c @@ -471,7 +471,7 @@ static int /*eContextResult*/ sequencer_context(const bContext *C, return CTX_RESULT_OK; } if (CTX_data_equals(member, "edit_mask")) { - Mask *mask = BKE_sequencer_mask_get(scene); + Mask *mask = SEQ_active_mask_get(scene); if (mask) { CTX_data_id_pointer_set(result, &mask->id); } diff --git a/source/blender/editors/transform/transform_convert_sequencer.c b/source/blender/editors/transform/transform_convert_sequencer.c index 3f86ef3e81b..83e384010bd 100644 --- a/source/blender/editors/transform/transform_convert_sequencer.c +++ b/source/blender/editors/transform/transform_convert_sequencer.c @@ -84,8 +84,8 @@ static void SeqTransInfo(TransInfo *t, Sequence *seq, int *r_recursive, int *r_c Scene *scene = t->scene; int cfra = CFRA; - int left = BKE_sequence_tx_get_final_left(seq, true); - int right = BKE_sequence_tx_get_final_right(seq, true); + int left = SEQ_transform_get_left_handle_frame(seq, true); + int right = SEQ_transform_get_right_handle_frame(seq, true); if (seq->depth == 0 && ((seq->flag & SELECT) == 0 || (seq->flag & SEQ_LOCK))) { *r_recursive = false; @@ -186,7 +186,7 @@ static void SeqTransInfo(TransInfo *t, Sequence *seq, int *r_recursive, int *r_c /* Meta's can only directly be moved between channels since they * don't have their start and length set directly (children affect that) * since this Meta is nested we don't need any of its data in fact. - * BKE_sequence_calc() will update its settings when run on the top-level meta. */ + * SEQ_time_update_sequence() will update its settings when run on the top-level meta. */ *r_flag = 0; *r_count = 0; *r_recursive = true; @@ -235,16 +235,16 @@ static TransData *SeqToTransData( /* Use seq_tx_get_final_left() and an offset here * so transform has the left hand location of the strip. * tdsq->start_offset is used when flushing the tx data back */ - start_left = BKE_sequence_tx_get_final_left(seq, false); + start_left = SEQ_transform_get_left_handle_frame(seq, false); td2d->loc[0] = start_left; tdsq->start_offset = start_left - seq->start; /* use to apply the original location */ break; case SEQ_LEFTSEL: - start_left = BKE_sequence_tx_get_final_left(seq, false); + start_left = SEQ_transform_get_left_handle_frame(seq, false); td2d->loc[0] = start_left; break; case SEQ_RIGHTSEL: - td2d->loc[0] = BKE_sequence_tx_get_final_right(seq, false); + td2d->loc[0] = SEQ_transform_get_right_handle_frame(seq, false); break; } @@ -366,7 +366,7 @@ static void SeqTransDataBounds(TransInfo *t, ListBase *seqbase, TransSeq *ts) static void freeSeqData(TransInfo *t, TransDataContainer *tc, TransCustomData *custom_data) { - Editing *ed = BKE_sequencer_editing_get(t->scene, false); + Editing *ed = SEQ_editing_get(t->scene, false); if (ed != NULL) { @@ -388,7 +388,7 @@ static void freeSeqData(TransInfo *t, TransDataContainer *tc, TransCustomData *c for (a = 0; a < t->total; a++, td++) { if ((seq != seq_prev) && (seq->depth == 0) && (seq->flag & SEQ_OVERLAP)) { seq = ((TransDataSeq *)td->extra)->seq; - BKE_sequence_base_shuffle(seqbasep, seq, t->scene); + SEQ_transform_seqbase_shuffle(seqbasep, seq, t->scene); } seq_prev = seq; @@ -429,7 +429,7 @@ static void freeSeqData(TransInfo *t, TransDataContainer *tc, TransCustomData *c } else { /* Tag seq with a non zero value, used by - * BKE_sequence_base_shuffle_time to identify the ones to shuffle */ + * SEQ_transform_seqbase_shuffle_time to identify the ones to shuffle */ if (seq->depth == 0) { seq->tmp = (void *)1; } @@ -455,7 +455,7 @@ static void freeSeqData(TransInfo *t, TransDataContainer *tc, TransCustomData *c } } - BKE_sequence_base_shuffle_time(seqbasep, t->scene, markers, use_sync_markers); + SEQ_transform_seqbase_shuffle_time(seqbasep, t->scene, markers, use_sync_markers); for (seq = seqbasep->first; seq; seq = seq->next) { if (seq->machine >= MAXSEQ * 2) { @@ -467,10 +467,10 @@ static void freeSeqData(TransInfo *t, TransDataContainer *tc, TransCustomData *c } } - BKE_sequence_base_shuffle_time(seqbasep, t->scene, markers, use_sync_markers); + SEQ_transform_seqbase_shuffle_time(seqbasep, t->scene, markers, use_sync_markers); } else { - BKE_sequence_base_shuffle_time(seqbasep, t->scene, markers, use_sync_markers); + SEQ_transform_seqbase_shuffle_time(seqbasep, t->scene, markers, use_sync_markers); } if (has_effect_any) { @@ -480,7 +480,7 @@ static void freeSeqData(TransInfo *t, TransDataContainer *tc, TransCustomData *c seq = ((TransDataSeq *)td->extra)->seq; if ((seq != seq_prev)) { if ((seq->type & SEQ_TYPE_EFFECT) && seq->seq1) { - BKE_sequence_calc(t->scene, seq); + SEQ_time_update_sequence(t->scene, seq); } } } @@ -493,8 +493,8 @@ static void freeSeqData(TransInfo *t, TransDataContainer *tc, TransCustomData *c seq = ((TransDataSeq *)td->extra)->seq; if ((seq != seq_prev) && (seq->depth == 0)) { if ((seq->type & SEQ_TYPE_EFFECT) && seq->seq1) { - if (BKE_sequence_test_overlap(seqbasep, seq)) { - BKE_sequence_base_shuffle(seqbasep, seq, t->scene); + if (SEQ_transform_test_overlap(seqbasep, seq)) { + SEQ_transform_seqbase_shuffle(seqbasep, seq, t->scene); } } } @@ -509,18 +509,18 @@ static void freeSeqData(TransInfo *t, TransDataContainer *tc, TransCustomData *c /* We might want to build a list of effects that need to be updated during transform */ if (seq->type & SEQ_TYPE_EFFECT) { if (seq->seq1 && seq->seq1->flag & SELECT) { - BKE_sequence_calc(t->scene, seq); + SEQ_time_update_sequence(t->scene, seq); } else if (seq->seq2 && seq->seq2->flag & SELECT) { - BKE_sequence_calc(t->scene, seq); + SEQ_time_update_sequence(t->scene, seq); } else if (seq->seq3 && seq->seq3->flag & SELECT) { - BKE_sequence_calc(t->scene, seq); + SEQ_time_update_sequence(t->scene, seq); } } } - BKE_sequencer_sort(t->scene); + SEQ_sort(t->scene); } else { /* Canceled, need to update the strips display */ @@ -528,10 +528,10 @@ static void freeSeqData(TransInfo *t, TransDataContainer *tc, TransCustomData *c seq = ((TransDataSeq *)td->extra)->seq; if ((seq != seq_prev) && (seq->depth == 0)) { if (seq->flag & SEQ_OVERLAP) { - BKE_sequence_base_shuffle(seqbasep, seq, t->scene); + SEQ_transform_seqbase_shuffle(seqbasep, seq, t->scene); } - BKE_sequence_calc_disp(t->scene, seq); + SEQ_time_update_sequence_bounds(t->scene, seq); } seq_prev = seq; } @@ -553,7 +553,7 @@ void createTransSeqData(TransInfo *t) #define XXX_DURIAN_ANIM_TX_HACK Scene *scene = t->scene; - Editing *ed = BKE_sequencer_editing_get(t->scene, false); + Editing *ed = SEQ_editing_get(t->scene, false); TransData *td = NULL; TransData2D *td2d = NULL; TransDataSeq *tdsq = NULL; @@ -640,21 +640,21 @@ BLI_INLINE void trans_update_seq(Scene *sce, Sequence *seq, int old_start, int s /* Calculate this strip and all nested strips. * Children are ALWAYS transformed first so we don't need to do this in another loop. */ - BKE_sequence_calc(sce, seq); + SEQ_time_update_sequence(sce, seq); } else { - BKE_sequence_calc_disp(sce, seq); + SEQ_time_update_sequence_bounds(sce, seq); } if (sel_flag == SELECT) { - BKE_sequencer_offset_animdata(sce, seq, seq->start - old_start); + SEQ_offset_animdata(sce, seq, seq->start - old_start); } } static void flushTransSeq(TransInfo *t) { /* Editing null check already done */ - ListBase *seqbasep = BKE_sequencer_editing_get(t->scene, false)->seqbasep; + ListBase *seqbasep = SEQ_editing_get(t->scene, false)->seqbasep; int a, new_frame; TransData *td = NULL; @@ -681,7 +681,7 @@ static void flushTransSeq(TransInfo *t) switch (tdsq->sel_flag) { case SELECT: #ifdef SEQ_TX_NESTED_METAS - if ((seq->depth != 0 || BKE_sequence_tx_test(seq))) { + if ((seq->depth != 0 || SEQ_transform_sequence_can_be_translated(seq))) { /* for meta's, their children move */ seq->start = new_frame - tdsq->start_offset; } @@ -697,18 +697,18 @@ static void flushTransSeq(TransInfo *t) } break; case SEQ_LEFTSEL: /* no vertical transform */ - BKE_sequence_tx_set_final_left(seq, new_frame); - BKE_sequence_tx_handle_xlimits(seq, tdsq->flag & SEQ_LEFTSEL, tdsq->flag & SEQ_RIGHTSEL); + SEQ_transform_set_left_handle_frame(seq, new_frame); + SEQ_transform_handle_xlimits(seq, tdsq->flag & SEQ_LEFTSEL, tdsq->flag & SEQ_RIGHTSEL); /* todo - move this into aftertrans update? - old seq tx needed it anyway */ - BKE_sequence_single_fix(seq); + SEQ_transform_fix_single_image_seq_offsets(seq); break; case SEQ_RIGHTSEL: /* no vertical transform */ - BKE_sequence_tx_set_final_right(seq, new_frame); - BKE_sequence_tx_handle_xlimits(seq, tdsq->flag & SEQ_LEFTSEL, tdsq->flag & SEQ_RIGHTSEL); + SEQ_transform_set_right_handle_frame(seq, new_frame); + SEQ_transform_handle_xlimits(seq, tdsq->flag & SEQ_LEFTSEL, tdsq->flag & SEQ_RIGHTSEL); /* todo - move this into aftertrans update? - old seq tx needed it anyway */ - BKE_sequence_single_fix(seq); + SEQ_transform_fix_single_image_seq_offsets(seq); break; } @@ -743,12 +743,12 @@ static void flushTransSeq(TransInfo *t) /* calc all meta's then effects T27953. */ for (seq = seqbasep->first; seq; seq = seq->next) { if (seq->type == SEQ_TYPE_META && seq->flag & SELECT) { - BKE_sequence_calc(t->scene, seq); + SEQ_time_update_sequence(t->scene, seq); } } for (seq = seqbasep->first; seq; seq = seq->next) { if (seq->seq1 || seq->seq2 || seq->seq3) { - BKE_sequence_calc(t->scene, seq); + SEQ_time_update_sequence(t->scene, seq); } } @@ -759,7 +759,7 @@ static void flushTransSeq(TransInfo *t) seq = tdsq->seq; if ((seq != seq_prev) && (seq->depth != 0)) { if (seq->seq1 || seq->seq2 || seq->seq3) { - BKE_sequence_calc(t->scene, seq); + SEQ_time_update_sequence(t->scene, seq); } } } @@ -777,7 +777,7 @@ static void flushTransSeq(TransInfo *t) if (seq->depth == 0) { /* test overlap, displays red outline */ seq->flag &= ~SEQ_OVERLAP; - if (BKE_sequence_test_overlap(seqbasep, seq)) { + if (SEQ_transform_test_overlap(seqbasep, seq)) { seq->flag |= SEQ_OVERLAP; } } @@ -800,7 +800,7 @@ void recalcData_sequencer(TransInfo *t) Sequence *seq = tdsq->seq; if (seq != seq_prev) { - BKE_sequence_invalidate_cache_composite(t->scene, seq); + SEQ_relations_invalidate_cache_composite(t->scene, seq); } seq_prev = seq; diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index f1c4c243780..8d20f1686f2 100644 --- a/source/blender/editors/transform/transform_snap.c +++ b/source/blender/editors/transform/transform_snap.c @@ -1409,7 +1409,7 @@ void snapSequenceBounds(TransInfo *t, const int mval[2]) const int frame_curr = round_fl_to_int(xmouse); /* Now find the closest sequence. */ - const int frame_near = BKE_sequencer_find_next_prev_edit( + const int frame_near = SEQ_time_find_next_prev_edit( t->scene, frame_curr, SEQ_SIDE_BOTH, true, false, true); const int frame_snap = transform_convert_sequencer_get_snap_bound(t); diff --git a/source/blender/editors/util/ed_util_imbuf.c b/source/blender/editors/util/ed_util_imbuf.c index b832d9a1d86..ca97a7b21c3 100644 --- a/source/blender/editors/util/ed_util_imbuf.c +++ b/source/blender/editors/util/ed_util_imbuf.c @@ -564,7 +564,7 @@ bool ED_imbuf_sample_poll(bContext *C) return false; } - return sseq && BKE_sequencer_editing_get(CTX_data_scene(C), false) != NULL; + return sseq && SEQ_editing_get(CTX_data_scene(C), false) != NULL; } return false; diff --git a/source/blender/makesdna/DNA_sequence_types.h b/source/blender/makesdna/DNA_sequence_types.h index 59e5e9df9ee..1f16fa6d148 100644 --- a/source/blender/makesdna/DNA_sequence_types.h +++ b/source/blender/makesdna/DNA_sequence_types.h @@ -283,7 +283,7 @@ typedef struct Editing { struct PrefetchJob *prefetch_job; - /* Must be initialized only by BKE_sequencer_cache_create() */ + /* Must be initialized only by seq_cache_create() */ int64_t disk_cache_timestamp; } Editing; diff --git a/source/blender/makesrna/intern/rna_camera.c b/source/blender/makesrna/intern/rna_camera.c index df9f4674900..2ac8b50f381 100644 --- a/source/blender/makesrna/intern/rna_camera.c +++ b/source/blender/makesrna/intern/rna_camera.c @@ -127,7 +127,7 @@ static void rna_Camera_background_images_clear(Camera *cam) static void rna_Camera_dof_update(Main *bmain, Scene *scene, PointerRNA *UNUSED(ptr)) { - BKE_sequence_invalidate_scene_strips(bmain, scene); + SEQ_relations_invalidate_scene_strips(bmain, scene); WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, scene); } diff --git a/source/blender/makesrna/intern/rna_color.c b/source/blender/makesrna/intern/rna_color.c index ac47f434c3b..2293b892ddb 100644 --- a/source/blender/makesrna/intern/rna_color.c +++ b/source/blender/makesrna/intern/rna_color.c @@ -608,14 +608,14 @@ static void rna_ColorManagedColorspaceSettings_reload_update(Main *bmain, MovieClip *clip = (MovieClip *)id; DEG_id_tag_update(&clip->id, ID_RECALC_SOURCE); - BKE_sequence_invalidate_movieclip_strips(bmain, clip); + SEQ_relations_invalidate_movieclip_strips(bmain, clip); WM_main_add_notifier(NC_MOVIECLIP | ND_DISPLAY, &clip->id); WM_main_add_notifier(NC_MOVIECLIP | NA_EDITED, &clip->id); } else if (GS(id->name) == ID_SCE) { Scene *scene = (Scene *)id; - BKE_sequence_invalidate_scene_strips(bmain, scene); + SEQ_relations_invalidate_scene_strips(bmain, scene); if (scene->ed) { ColorManagedColorspaceSettings *colorspace_settings = (ColorManagedColorspaceSettings *) @@ -634,18 +634,18 @@ static void rna_ColorManagedColorspaceSettings_reload_update(Main *bmain, } if (seq_found) { - BKE_sequence_free_anim(seq); + SEQ_relations_sequence_free_anim(seq); if (seq->strip->proxy && seq->strip->proxy->anim) { IMB_free_anim(seq->strip->proxy->anim); seq->strip->proxy->anim = NULL; } - BKE_sequence_invalidate_cache_preprocessed(scene, seq); + SEQ_relations_invalidate_cache_preprocessed(scene, seq); } else { SEQ_ALL_BEGIN (scene->ed, seq) { - BKE_sequence_free_anim(seq); + SEQ_relations_sequence_free_anim(seq); } SEQ_ALL_END; } diff --git a/source/blender/makesrna/intern/rna_movieclip.c b/source/blender/makesrna/intern/rna_movieclip.c index d07a4b4fac7..e7f697b281d 100644 --- a/source/blender/makesrna/intern/rna_movieclip.c +++ b/source/blender/makesrna/intern/rna_movieclip.c @@ -76,7 +76,7 @@ static void rna_MovieClip_use_proxy_update(Main *bmain, Scene *UNUSED(scene), Po { MovieClip *clip = (MovieClip *)ptr->owner_id; BKE_movieclip_clear_cache(clip); - BKE_sequence_invalidate_movieclip_strips(bmain, clip); + SEQ_relations_invalidate_movieclip_strips(bmain, clip); } static void rna_MovieClipUser_proxy_render_settings_update(Main *bmain, @@ -105,7 +105,7 @@ static void rna_MovieClipUser_proxy_render_settings_update(Main *bmain, if (clip && (clip->flag & MCLIP_USE_PROXY)) { BKE_movieclip_clear_cache(clip); - BKE_sequence_invalidate_movieclip_strips(bmain, clip); + SEQ_relations_invalidate_movieclip_strips(bmain, clip); } break; diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 84222347425..bce10b42ea8 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -916,7 +916,7 @@ static void rna_Scene_fps_update(Main *bmain, Scene *scene, PointerRNA *UNUSED(p /* NOTE: Tag via dependency graph will take care of all the updates ion the evaluated domain, * however, changes in FPS actually modifies an original skip length, * so this we take care about here. */ - BKE_sequencer_refresh_sound_length(bmain, scene); + SEQ_sound_update_length(bmain, scene); } static void rna_Scene_listener_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr)) @@ -2250,7 +2250,7 @@ static void rna_SceneCamera_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Po Scene *scene = (Scene *)ptr->owner_id; Object *camera = scene->camera; - BKE_sequencer_cache_cleanup(scene); + SEQ_cache_cleanup(scene); if (camera && (camera->type == OB_CAMERA)) { DEG_id_tag_update(&camera->id, ID_RECALC_GEOMETRY); @@ -2259,7 +2259,7 @@ static void rna_SceneCamera_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Po static void rna_SceneSequencer_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr)) { - BKE_sequencer_cache_cleanup(scene); + SEQ_cache_cleanup(scene); } static char *rna_ToolSettings_path(PointerRNA *UNUSED(ptr)) diff --git a/source/blender/makesrna/intern/rna_scene_api.c b/source/blender/makesrna/intern/rna_scene_api.c index a57c1196f6a..0549fc8bab2 100644 --- a/source/blender/makesrna/intern/rna_scene_api.c +++ b/source/blender/makesrna/intern/rna_scene_api.c @@ -186,7 +186,7 @@ static void rna_Scene_ray_cast(Scene *scene, static void rna_Scene_sequencer_editing_free(Scene *scene) { - BKE_sequencer_editing_free(scene, true); + SEQ_editing_free(scene, true); } # ifdef WITH_ALEMBIC @@ -343,7 +343,7 @@ void RNA_api_scene(StructRNA *srna) RNA_def_function_output(func, parm); /* Sequencer. */ - func = RNA_def_function(srna, "sequence_editor_create", "BKE_sequencer_editing_ensure"); + func = RNA_def_function(srna, "sequence_editor_create", "SEQ_editing_ensure"); RNA_def_function_ui_description(func, "Ensure sequence editor is valid in this scene"); parm = RNA_def_pointer( func, "sequence_editor", "SequenceEditor", "", "New sequence editor data or NULL"); diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c index eea6fd88ec7..43d65a4380b 100644 --- a/source/blender/makesrna/intern/rna_sequencer.c +++ b/source/blender/makesrna/intern/rna_sequencer.c @@ -103,16 +103,16 @@ static void meta_tmp_ref(Sequence *seq_par, Sequence *seq) static void rna_SequenceElement_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { Scene *scene = (Scene *)ptr->owner_id; - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); if (ed) { StripElem *se = (StripElem *)ptr->data; Sequence *seq; /* slow but we can't avoid! */ - seq = BKE_sequencer_from_elem(&ed->seqbase, se); + seq = SEQ_sequence_from_strip_elem(&ed->seqbase, se); if (seq) { - BKE_sequence_invalidate_cache_raw(scene, seq); + SEQ_relations_invalidate_cache_raw(scene, seq); } } } @@ -122,12 +122,12 @@ static void rna_Sequence_invalidate_raw_update(Main *UNUSED(bmain), PointerRNA *ptr) { Scene *scene = (Scene *)ptr->owner_id; - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); if (ed) { Sequence *seq = (Sequence *)ptr->data; - BKE_sequence_invalidate_cache_raw(scene, seq); + SEQ_relations_invalidate_cache_raw(scene, seq); } } @@ -136,12 +136,12 @@ static void rna_Sequence_invalidate_preprocessed_update(Main *UNUSED(bmain), PointerRNA *ptr) { Scene *scene = (Scene *)ptr->owner_id; - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); if (ed) { Sequence *seq = (Sequence *)ptr->data; - BKE_sequence_invalidate_cache_preprocessed(scene, seq); + SEQ_relations_invalidate_cache_preprocessed(scene, seq); } } @@ -150,12 +150,12 @@ static void rna_Sequence_invalidate_composite_update(Main *UNUSED(bmain), PointerRNA *ptr) { Scene *scene = (Scene *)ptr->owner_id; - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); if (ed) { Sequence *seq = (Sequence *)ptr->data; - BKE_sequence_invalidate_cache_composite(scene, seq); + SEQ_relations_invalidate_cache_composite(scene, seq); } } @@ -172,7 +172,7 @@ static void rna_Sequence_use_sequence(Main *bmain, Scene *scene, PointerRNA *ptr rna_Sequence_invalidate_raw_update(bmain, scene, ptr); /* Changing recursion changes set of IDs which needs to be remapped by the copy-on-write. * the only way for this currently is to tag the ID for ID_RECALC_COPY_ON_WRITE. */ - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); if (ed) { Sequence *seq = (Sequence *)ptr->data; if (seq->scene != NULL) { @@ -189,7 +189,7 @@ static void rna_SequenceEditor_sequences_all_begin(CollectionPropertyIterator *i PointerRNA *ptr) { Scene *scene = (Scene *)ptr->owner_id; - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); meta_tmp_ref(NULL, ed->seqbase.first); @@ -202,8 +202,8 @@ static void rna_SequenceEditor_update_cache(Main *UNUSED(bmain), { Editing *ed = scene->ed; - BKE_sequencer_free_imbuf(scene, &ed->seqbase, false); - BKE_sequencer_cache_cleanup(scene); + SEQ_relations_free_imbuf(scene, &ed->seqbase, false); + SEQ_cache_cleanup(scene); } static void rna_SequenceEditor_sequences_all_next(CollectionPropertyIterator *iter) @@ -263,10 +263,10 @@ static void rna_Sequence_views_format_update(Main *bmain, Scene *scene, PointerR static void do_sequence_frame_change_update(Scene *scene, Sequence *seq) { - Editing *ed = BKE_sequencer_editing_get(scene, false); - ListBase *seqbase = BKE_sequence_seqbase(&ed->seqbase, seq); + Editing *ed = SEQ_editing_get(scene, false); + ListBase *seqbase = SEQ_get_seqbase_by_seq(&ed->seqbase, seq); Sequence *tseq; - BKE_sequence_calc_disp(scene, seq); + SEQ_time_update_sequence_bounds(scene, seq); /* ensure effects are always fit in length to their input */ @@ -275,14 +275,14 @@ static void do_sequence_frame_change_update(Scene *scene, Sequence *seq) */ for (tseq = seqbase->first; tseq; tseq = tseq->next) { if (tseq->seq1 || tseq->seq2 || tseq->seq3) { - BKE_sequence_calc(scene, tseq); + SEQ_time_update_sequence(scene, tseq); } } - if (BKE_sequence_test_overlap(seqbase, seq)) { - BKE_sequence_base_shuffle(seqbase, seq, scene); /* XXX - BROKEN!, uses context seqbasep */ + if (SEQ_transform_test_overlap(seqbase, seq)) { + SEQ_transform_seqbase_shuffle(seqbase, seq, scene); /* XXX - BROKEN!, uses context seqbasep */ } - BKE_sequencer_sort(scene); + SEQ_sort(scene); } /* A simple wrapper around above func, directly usable as prop update func. @@ -301,10 +301,10 @@ static void rna_Sequence_start_frame_set(PointerRNA *ptr, int value) Sequence *seq = (Sequence *)ptr->data; Scene *scene = (Scene *)ptr->owner_id; - BKE_sequence_invalidate_cache_composite(scene, seq); - BKE_sequence_translate(scene, seq, value - seq->start); + SEQ_relations_invalidate_cache_composite(scene, seq); + SEQ_transform_translate_sequence(scene, seq, value - seq->start); do_sequence_frame_change_update(scene, seq); - BKE_sequence_invalidate_cache_composite(scene, seq); + SEQ_relations_invalidate_cache_composite(scene, seq); } static void rna_Sequence_start_frame_final_set(PointerRNA *ptr, int value) @@ -312,11 +312,11 @@ static void rna_Sequence_start_frame_final_set(PointerRNA *ptr, int value) Sequence *seq = (Sequence *)ptr->data; Scene *scene = (Scene *)ptr->owner_id; - BKE_sequence_invalidate_cache_composite(scene, seq); - BKE_sequence_tx_set_final_left(seq, value); - BKE_sequence_single_fix(seq); + SEQ_relations_invalidate_cache_composite(scene, seq); + SEQ_transform_set_left_handle_frame(seq, value); + SEQ_transform_fix_single_image_seq_offsets(seq); do_sequence_frame_change_update(scene, seq); - BKE_sequence_invalidate_cache_composite(scene, seq); + SEQ_relations_invalidate_cache_composite(scene, seq); } static void rna_Sequence_end_frame_final_set(PointerRNA *ptr, int value) @@ -324,11 +324,11 @@ static void rna_Sequence_end_frame_final_set(PointerRNA *ptr, int value) Sequence *seq = (Sequence *)ptr->data; Scene *scene = (Scene *)ptr->owner_id; - BKE_sequence_invalidate_cache_composite(scene, seq); - BKE_sequence_tx_set_final_right(seq, value); - BKE_sequence_single_fix(seq); + SEQ_relations_invalidate_cache_composite(scene, seq); + SEQ_transform_set_right_handle_frame(seq, value); + SEQ_transform_fix_single_image_seq_offsets(seq); do_sequence_frame_change_update(scene, seq); - BKE_sequence_invalidate_cache_composite(scene, seq); + SEQ_relations_invalidate_cache_composite(scene, seq); } static void rna_Sequence_frame_offset_start_set(PointerRNA *ptr, int value) @@ -336,7 +336,7 @@ static void rna_Sequence_frame_offset_start_set(PointerRNA *ptr, int value) Sequence *seq = (Sequence *)ptr->data; Scene *scene = (Scene *)ptr->owner_id; - BKE_sequence_invalidate_cache_composite(scene, seq); + SEQ_relations_invalidate_cache_composite(scene, seq); seq->startofs = value; } @@ -345,7 +345,7 @@ static void rna_Sequence_frame_offset_end_set(PointerRNA *ptr, int value) Sequence *seq = (Sequence *)ptr->data; Scene *scene = (Scene *)ptr->owner_id; - BKE_sequence_invalidate_cache_composite(scene, seq); + SEQ_relations_invalidate_cache_composite(scene, seq); seq->endofs = value; } @@ -354,7 +354,7 @@ static void rna_Sequence_frame_still_start_set(PointerRNA *ptr, int value) Sequence *seq = (Sequence *)ptr->data; Scene *scene = (Scene *)ptr->owner_id; - BKE_sequence_invalidate_cache_composite(scene, seq); + SEQ_relations_invalidate_cache_composite(scene, seq); seq->startstill = value; } @@ -363,7 +363,7 @@ static void rna_Sequence_frame_still_end_set(PointerRNA *ptr, int value) Sequence *seq = (Sequence *)ptr->data; Scene *scene = (Scene *)ptr->owner_id; - BKE_sequence_invalidate_cache_composite(scene, seq); + SEQ_relations_invalidate_cache_composite(scene, seq); seq->endstill = value; } @@ -374,7 +374,7 @@ static void rna_Sequence_anim_startofs_final_set(PointerRNA *ptr, int value) seq->anim_startofs = MIN2(value, seq->len + seq->anim_startofs); - BKE_sequence_reload_new_file(G.main, scene, seq, false); + SEQ_add_reload_new_file(G.main, scene, seq, false); do_sequence_frame_change_update(scene, seq); } @@ -385,7 +385,7 @@ static void rna_Sequence_anim_endofs_final_set(PointerRNA *ptr, int value) seq->anim_endofs = MIN2(value, seq->len + seq->anim_endofs); - BKE_sequence_reload_new_file(G.main, scene, seq, false); + SEQ_add_reload_new_file(G.main, scene, seq, false); do_sequence_frame_change_update(scene, seq); } @@ -428,43 +428,45 @@ static void rna_Sequence_frame_length_set(PointerRNA *ptr, int value) Sequence *seq = (Sequence *)ptr->data; Scene *scene = (Scene *)ptr->owner_id; - BKE_sequence_invalidate_cache_composite(scene, seq); - BKE_sequence_tx_set_final_right(seq, BKE_sequence_tx_get_final_left(seq, false) + value); + SEQ_relations_invalidate_cache_composite(scene, seq); + SEQ_transform_set_right_handle_frame(seq, + SEQ_transform_get_left_handle_frame(seq, false) + value); do_sequence_frame_change_update(scene, seq); - BKE_sequence_invalidate_cache_composite(scene, seq); + SEQ_relations_invalidate_cache_composite(scene, seq); } static int rna_Sequence_frame_length_get(PointerRNA *ptr) { Sequence *seq = (Sequence *)ptr->data; - return BKE_sequence_tx_get_final_right(seq, false) - BKE_sequence_tx_get_final_left(seq, false); + return SEQ_transform_get_right_handle_frame(seq, false) - + SEQ_transform_get_left_handle_frame(seq, false); } static int rna_Sequence_frame_editable(PointerRNA *ptr, const char **UNUSED(r_info)) { Sequence *seq = (Sequence *)ptr->data; /* Effect sequences' start frame and length must be readonly! */ - return (BKE_sequence_effect_get_num_inputs(seq->type)) ? 0 : PROP_EDITABLE; + return (SEQ_effect_get_num_inputs(seq->type)) ? 0 : PROP_EDITABLE; } static void rna_Sequence_channel_set(PointerRNA *ptr, int value) { Sequence *seq = (Sequence *)ptr->data; Scene *scene = (Scene *)ptr->owner_id; - Editing *ed = BKE_sequencer_editing_get(scene, false); - ListBase *seqbase = BKE_sequence_seqbase(&ed->seqbase, seq); + Editing *ed = SEQ_editing_get(scene, false); + ListBase *seqbase = SEQ_get_seqbase_by_seq(&ed->seqbase, seq); - BKE_sequence_invalidate_cache_composite(scene, seq); + SEQ_relations_invalidate_cache_composite(scene, seq); /* check channel increment or decrement */ const int channel_delta = (value >= seq->machine) ? 1 : -1; seq->machine = value; - if (BKE_sequence_test_overlap(seqbase, seq)) { + if (SEQ_transform_test_overlap(seqbase, seq)) { /* XXX - BROKEN!, uses context seqbasep */ - BKE_sequence_base_shuffle_ex(seqbase, seq, scene, channel_delta); + SEQ_transform_seqbase_shuffle_ex(seqbase, seq, scene, channel_delta); } - BKE_sequencer_sort(scene); - BKE_sequence_invalidate_cache_composite(scene, seq); + SEQ_sort(scene); + SEQ_relations_invalidate_cache_composite(scene, seq); } static void rna_Sequence_use_proxy_set(PointerRNA *ptr, bool value) @@ -492,7 +494,7 @@ static Sequence *sequence_get_by_transform(Editing *ed, StripTransform *transfor data.data = transform; /* irritating we need to search for our sequence! */ - BKE_sequencer_base_recursive_apply(&ed->seqbase, transform_seq_cmp_fn, &data); + SEQ_iterator_seqbase_recursive_apply(&ed->seqbase, transform_seq_cmp_fn, &data); return data.seq; } @@ -500,7 +502,7 @@ static Sequence *sequence_get_by_transform(Editing *ed, StripTransform *transfor static char *rna_SequenceTransform_path(PointerRNA *ptr) { Scene *scene = (Scene *)ptr->owner_id; - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); Sequence *seq = sequence_get_by_transform(ed, ptr->data); if (seq && seq->name + 2) { @@ -519,10 +521,10 @@ static void rna_SequenceTransform_update(Main *UNUSED(bmain), PointerRNA *ptr) { Scene *scene = (Scene *)ptr->owner_id; - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); Sequence *seq = sequence_get_by_transform(ed, ptr->data); - BKE_sequence_invalidate_cache_preprocessed(scene, seq); + SEQ_relations_invalidate_cache_preprocessed(scene, seq); } static int crop_seq_cmp_fn(Sequence *seq, void *arg_pt) @@ -544,7 +546,7 @@ static Sequence *sequence_get_by_crop(Editing *ed, StripCrop *crop) data.data = crop; /* irritating we need to search for our sequence! */ - BKE_sequencer_base_recursive_apply(&ed->seqbase, crop_seq_cmp_fn, &data); + SEQ_iterator_seqbase_recursive_apply(&ed->seqbase, crop_seq_cmp_fn, &data); return data.seq; } @@ -552,7 +554,7 @@ static Sequence *sequence_get_by_crop(Editing *ed, StripCrop *crop) static char *rna_SequenceCrop_path(PointerRNA *ptr) { Scene *scene = (Scene *)ptr->owner_id; - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); Sequence *seq = sequence_get_by_crop(ed, ptr->data); if (seq && seq->name + 2) { @@ -569,10 +571,10 @@ static char *rna_SequenceCrop_path(PointerRNA *ptr) static void rna_SequenceCrop_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { Scene *scene = (Scene *)ptr->owner_id; - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); Sequence *seq = sequence_get_by_crop(ed, ptr->data); - BKE_sequence_invalidate_cache_preprocessed(scene, seq); + SEQ_relations_invalidate_cache_preprocessed(scene, seq); } static void rna_Sequence_text_font_set(PointerRNA *ptr, @@ -583,7 +585,7 @@ static void rna_Sequence_text_font_set(PointerRNA *ptr, TextVars *data = seq->effectdata; VFont *value = ptr_value.data; - BKE_sequencer_text_font_unload(data, true); + SEQ_effect_text_font_unload(data, true); id_us_plus(&value->id); data->text_blf_id = SEQ_FONT_NOT_LOADED; @@ -610,7 +612,7 @@ static void rna_Sequence_name_set(PointerRNA *ptr, const char *value) char oldname[sizeof(seq->name)]; AnimData *adt; - BKE_sequencer_prefetch_stop(scene); + SEQ_prefetch_stop(scene); /* make a copy of the old name first */ BLI_strncpy(oldname, seq->name + 2, sizeof(seq->name) - 2); @@ -619,7 +621,7 @@ static void rna_Sequence_name_set(PointerRNA *ptr, const char *value) BLI_strncpy_utf8(seq->name + 2, value, sizeof(seq->name) - 2); /* make sure the name is unique */ - BKE_sequence_base_unique_name_recursive(&scene->ed->seqbase, seq); + SEQ_sequence_base_unique_name_recursive(&scene->ed->seqbase, seq); /* fix all the animation data which may link to this */ @@ -730,11 +732,11 @@ static bool rna_MovieSequence_reload_if_needed(ID *scene_id, Sequence *seq, Main bool has_reloaded; bool can_produce_frames; - BKE_sequence_movie_reload_if_needed(bmain, scene, seq, &has_reloaded, &can_produce_frames); + SEQ_add_movie_reload_if_needed(bmain, scene, seq, &has_reloaded, &can_produce_frames); if (has_reloaded && can_produce_frames) { - BKE_sequence_calc(scene, seq); - BKE_sequence_invalidate_cache_raw(scene, seq); + SEQ_time_update_sequence(scene, seq); + SEQ_relations_invalidate_cache_raw(scene, seq); DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS); WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, scene); @@ -834,7 +836,7 @@ static int rna_Sequence_input_count_get(PointerRNA *ptr) { Sequence *seq = (Sequence *)(ptr->data); - return BKE_sequence_effect_get_num_inputs(seq->type); + return SEQ_effect_get_num_inputs(seq->type); } static void rna_Sequence_input_set(PointerRNA *ptr, @@ -846,7 +848,7 @@ static void rna_Sequence_input_set(PointerRNA *ptr, Sequence *seq = ptr->data; Sequence *input = ptr_value.data; - if (BKE_sequencer_render_loop_check(input, seq)) { + if (SEQ_relations_render_loop_check(input, seq)) { BKE_report(reports, RPT_ERROR, "Cannot reassign inputs: recursion detected"); return; } @@ -895,13 +897,13 @@ static void rna_SequenceElement_filename_set(PointerRNA *ptr, const char *value) static void rna_Sequence_reopen_files_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { Scene *scene = (Scene *)ptr->owner_id; - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); - BKE_sequencer_free_imbuf(scene, &ed->seqbase, false); + SEQ_relations_free_imbuf(scene, &ed->seqbase, false); rna_Sequence_invalidate_raw_update(bmain, scene, ptr); if (RNA_struct_is_a(ptr->type, &RNA_SoundSequence)) { - BKE_sequencer_update_sound_bounds(scene, ptr->data); + SEQ_sound_update_bounds(scene, ptr->data); } } @@ -909,8 +911,8 @@ static void rna_Sequence_filepath_update(Main *bmain, Scene *UNUSED(scene), Poin { Scene *scene = (Scene *)ptr->owner_id; Sequence *seq = (Sequence *)(ptr->data); - BKE_sequence_reload_new_file(bmain, scene, seq, true); - BKE_sequence_calc(scene, seq); + SEQ_add_reload_new_file(bmain, scene, seq, true); + SEQ_time_update_sequence(scene, seq); rna_Sequence_invalidate_raw_update(bmain, scene, ptr); } @@ -937,26 +939,26 @@ static Sequence *sequence_get_by_proxy(Editing *ed, StripProxy *proxy) data.seq = NULL; data.data = proxy; - BKE_sequencer_base_recursive_apply(&ed->seqbase, seqproxy_seq_cmp_fn, &data); + SEQ_iterator_seqbase_recursive_apply(&ed->seqbase, seqproxy_seq_cmp_fn, &data); return data.seq; } static void rna_Sequence_tcindex_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { Scene *scene = (Scene *)ptr->owner_id; - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); Sequence *seq = sequence_get_by_proxy(ed, ptr->data); - BKE_sequence_reload_new_file(bmain, scene, seq, false); + SEQ_add_reload_new_file(bmain, scene, seq, false); do_sequence_frame_change_update(scene, seq); } static void rna_SequenceProxy_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { Scene *scene = (Scene *)ptr->owner_id; - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); Sequence *seq = sequence_get_by_proxy(ed, ptr->data); - BKE_sequence_invalidate_cache_preprocessed(scene, seq); + SEQ_relations_invalidate_cache_preprocessed(scene, seq); } /* do_versions? */ @@ -1006,7 +1008,7 @@ static Sequence *sequence_get_by_colorbalance(Editing *ed, data.data = cb; /* irritating we need to search for our sequence! */ - BKE_sequencer_base_recursive_apply(&ed->seqbase, colbalance_seq_cmp_fn, &data); + SEQ_iterator_seqbase_recursive_apply(&ed->seqbase, colbalance_seq_cmp_fn, &data); *r_smd = data.smd; @@ -1017,7 +1019,7 @@ static char *rna_SequenceColorBalance_path(PointerRNA *ptr) { Scene *scene = (Scene *)ptr->owner_id; SequenceModifierData *smd; - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); Sequence *seq = sequence_get_by_colorbalance(ed, ptr->data, &smd); if (seq && seq->name + 2) { @@ -1049,17 +1051,17 @@ static void rna_SequenceColorBalance_update(Main *UNUSED(bmain), PointerRNA *ptr) { Scene *scene = (Scene *)ptr->owner_id; - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); SequenceModifierData *smd; Sequence *seq = sequence_get_by_colorbalance(ed, ptr->data, &smd); - BKE_sequence_invalidate_cache_preprocessed(scene, seq); + SEQ_relations_invalidate_cache_preprocessed(scene, seq); } static void rna_SequenceEditor_overlay_lock_set(PointerRNA *ptr, bool value) { Scene *scene = (Scene *)ptr->owner_id; - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); if (ed == NULL) { return; @@ -1079,7 +1081,7 @@ static void rna_SequenceEditor_overlay_lock_set(PointerRNA *ptr, bool value) static int rna_SequenceEditor_overlay_frame_get(PointerRNA *ptr) { Scene *scene = (Scene *)ptr->owner_id; - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); if (ed == NULL) { return scene->r.cfra; @@ -1096,7 +1098,7 @@ static int rna_SequenceEditor_overlay_frame_get(PointerRNA *ptr) static void rna_SequenceEditor_overlay_frame_set(PointerRNA *ptr, int value) { Scene *scene = (Scene *)ptr->owner_id; - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); if (ed == NULL) { return; @@ -1130,7 +1132,7 @@ static Sequence *sequence_get_by_modifier(Editing *ed, SequenceModifierData *smd data.data = smd; /* irritating we need to search for our sequence! */ - BKE_sequencer_base_recursive_apply(&ed->seqbase, modifier_seq_cmp_fn, &data); + SEQ_iterator_seqbase_recursive_apply(&ed->seqbase, modifier_seq_cmp_fn, &data); return data.seq; } @@ -1160,7 +1162,7 @@ static StructRNA *rna_SequenceModifier_refine(struct PointerRNA *ptr) static char *rna_SequenceModifier_path(PointerRNA *ptr) { Scene *scene = (Scene *)ptr->owner_id; - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); SequenceModifierData *smd = ptr->data; Sequence *seq = sequence_get_by_modifier(ed, smd); @@ -1182,7 +1184,7 @@ static void rna_SequenceModifier_name_set(PointerRNA *ptr, const char *value) { SequenceModifierData *smd = ptr->data; Scene *scene = (Scene *)ptr->owner_id; - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); Sequence *seq = sequence_get_by_modifier(ed, smd); AnimData *adt; char oldname[sizeof(smd->name)]; @@ -1194,7 +1196,7 @@ static void rna_SequenceModifier_name_set(PointerRNA *ptr, const char *value) BLI_strncpy_utf8(smd->name, value, sizeof(smd->name)); /* make sure the name is truly unique */ - BKE_sequence_modifier_unique_name(seq, smd); + SEQ_modifier_unique_name(seq, smd); /* fix all the animation data which may link to this */ adt = BKE_animdata_from_id(&scene->id); @@ -1214,16 +1216,16 @@ static void rna_SequenceModifier_update(Main *UNUSED(bmain), Scene *UNUSED(scene { /* strip from other scenes could be modified, so using active scene is not reliable */ Scene *scene = (Scene *)ptr->owner_id; - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); Sequence *seq = sequence_get_by_modifier(ed, ptr->data); - BKE_sequence_invalidate_cache_preprocessed(scene, seq); + SEQ_relations_invalidate_cache_preprocessed(scene, seq); } static bool rna_SequenceModifier_otherSequence_poll(PointerRNA *ptr, PointerRNA value) { Scene *scene = (Scene *)ptr->owner_id; - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); Sequence *seq = sequence_get_by_modifier(ed, ptr->data); Sequence *cur = (Sequence *)value.data; @@ -1237,7 +1239,7 @@ static bool rna_SequenceModifier_otherSequence_poll(PointerRNA *ptr, PointerRNA static SequenceModifierData *rna_Sequence_modifier_new( Sequence *seq, bContext *C, ReportList *reports, const char *name, int type) { - if (!BKE_sequence_supports_modifiers(seq)) { + if (!SEQ_sequence_supports_modifiers(seq)) { BKE_report(reports, RPT_ERROR, "Sequence type does not support modifiers"); return NULL; @@ -1246,9 +1248,9 @@ static SequenceModifierData *rna_Sequence_modifier_new( Scene *scene = CTX_data_scene(C); SequenceModifierData *smd; - smd = BKE_sequence_modifier_new(seq, name, type); + smd = SEQ_modifier_new(seq, name, type); - BKE_sequence_invalidate_cache_preprocessed(scene, seq); + SEQ_relations_invalidate_cache_preprocessed(scene, seq); WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, NULL); @@ -1264,13 +1266,13 @@ static void rna_Sequence_modifier_remove(Sequence *seq, SequenceModifierData *smd = smd_ptr->data; Scene *scene = CTX_data_scene(C); - if (BKE_sequence_modifier_remove(seq, smd) == false) { + if (SEQ_modifier_remove(seq, smd) == false) { BKE_report(reports, RPT_ERROR, "Modifier was not found in the stack"); return; } RNA_POINTER_INVALIDATE(smd_ptr); - BKE_sequence_invalidate_cache_preprocessed(scene, seq); + SEQ_relations_invalidate_cache_preprocessed(scene, seq); WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, NULL); } @@ -1279,9 +1281,9 @@ static void rna_Sequence_modifier_clear(Sequence *seq, bContext *C) { Scene *scene = CTX_data_scene(C); - BKE_sequence_modifier_clear(seq); + SEQ_modifier_clear(seq); - BKE_sequence_invalidate_cache_preprocessed(scene, seq); + SEQ_relations_invalidate_cache_preprocessed(scene, seq); WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, NULL); } @@ -1292,11 +1294,11 @@ static void rna_SequenceModifier_strip_set(PointerRNA *ptr, { SequenceModifierData *smd = ptr->data; Scene *scene = (Scene *)ptr->owner_id; - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); Sequence *seq = sequence_get_by_modifier(ed, smd); Sequence *target = (Sequence *)value.data; - if (target != NULL && BKE_sequencer_render_loop_check(target, seq)) { + if (target != NULL && SEQ_relations_render_loop_check(target, seq)) { BKE_report(reports, RPT_ERROR, "Recursion detected, can not use this strip"); return; } @@ -1308,7 +1310,7 @@ static float rna_Sequence_fps_get(PointerRNA *ptr) { Scene *scene = (Scene *)ptr->owner_id; Sequence *seq = (Sequence *)(ptr->data); - return BKE_sequence_get_fps(scene, seq); + return SEQ_time_sequence_get_fps(scene, seq); } #else diff --git a/source/blender/makesrna/intern/rna_sequencer_api.c b/source/blender/makesrna/intern/rna_sequencer_api.c index 6f97098900e..67497c2da2a 100644 --- a/source/blender/makesrna/intern/rna_sequencer_api.c +++ b/source/blender/makesrna/intern/rna_sequencer_api.c @@ -58,11 +58,11 @@ static void rna_Sequence_update_rnafunc(ID *id, Sequence *self, bool do_data) { if (do_data) { - BKE_sequencer_update_changed_seq_and_deps((Scene *)id, self, true, true); + SEQ_relations_update_changed_seq_and_deps((Scene *)id, self, true, true); // new_tstripdata(self); /* need 2.6x version of this. */ } - BKE_sequence_calc((Scene *)id, self); - BKE_sequence_calc_disp((Scene *)id, self); + SEQ_time_update_sequence((Scene *)id, self); + SEQ_time_update_sequence_bounds((Scene *)id, self); } static void rna_Sequence_swap_internal(Sequence *seq_self, @@ -71,7 +71,7 @@ static void rna_Sequence_swap_internal(Sequence *seq_self, { const char *error_msg; - if (BKE_sequence_swap(seq_self, seq_other, &error_msg) == 0) { + if (SEQ_edit_sequence_swap(seq_self, seq_other, &error_msg) == 0) { BKE_report(reports, RPT_ERROR, error_msg); } } @@ -82,10 +82,10 @@ static Sequence *alloc_generic_sequence( Sequence *seq; StripElem *se; - seq = BKE_sequence_alloc(seqbase, frame_start, channel, type); + seq = SEQ_sequence_alloc(seqbase, frame_start, channel, type); BLI_strncpy(seq->name + 2, name, sizeof(seq->name) - 2); - BKE_sequence_base_unique_name_recursive(seqbase, seq); + SEQ_sequence_base_unique_name_recursive(seqbase, seq); Strip *strip = seq->strip; @@ -121,7 +121,7 @@ static Sequence *rna_Sequences_new_clip(ID *id, seq->len = BKE_movieclip_get_duration(clip); id_us_plus((ID *)clip); - BKE_sequence_calc_disp(scene, seq); + SEQ_time_update_sequence_bounds(scene, seq); DEG_relations_tag_update(bmain); DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS); @@ -168,8 +168,8 @@ static Sequence *rna_Sequences_new_mask(ID *id, seq->len = BKE_mask_get_duration(mask); id_us_plus((ID *)mask); - BKE_sequence_calc_disp(scene, seq); - BKE_sequence_invalidate_cache_composite(scene, seq); + SEQ_time_update_sequence_bounds(scene, seq); + SEQ_relations_invalidate_cache_composite(scene, seq); DEG_relations_tag_update(bmain); DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS); @@ -205,8 +205,8 @@ static Sequence *rna_Sequences_new_scene(ID *id, seq->len = sce_seq->r.efra - sce_seq->r.sfra + 1; id_us_plus((ID *)sce_seq); - BKE_sequence_calc_disp(scene, seq); - BKE_sequence_invalidate_cache_composite(scene, seq); + SEQ_time_update_sequence_bounds(scene, seq); + SEQ_relations_invalidate_cache_composite(scene, seq); DEG_relations_tag_update(bmain); DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS); @@ -255,12 +255,12 @@ static Sequence *rna_Sequences_new_image(ID *id, if (seq->strip->stripdata->name[0] == '\0') { BKE_report(reports, RPT_ERROR, "Sequences.new_image: unable to open image file"); BLI_remlink(seqbase, seq); - BKE_sequence_free(scene, seq, true); + SEQ_sequence_free(scene, seq, true); return NULL; } - BKE_sequence_calc_disp(scene, seq); - BKE_sequence_invalidate_cache_composite(scene, seq); + SEQ_time_update_sequence_bounds(scene, seq); + SEQ_relations_invalidate_cache_composite(scene, seq); DEG_relations_tag_update(bmain); DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS); @@ -318,8 +318,8 @@ static Sequence *rna_Sequences_new_movie( seq->len = IMB_anim_get_duration(an, IMB_TC_RECORD_RUN); } - BKE_sequence_calc_disp(scene, seq); - BKE_sequence_invalidate_cache_composite(scene, seq); + SEQ_time_update_sequence_bounds(scene, seq); + SEQ_relations_invalidate_cache_composite(scene, seq); DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS); WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, scene); @@ -365,7 +365,7 @@ static Sequence *rna_Sequences_new_sound(ID *id, seq->sound = sound; seq->len = ceil((double)info.length * FPS); - BKE_sequence_calc_disp(scene, seq); + SEQ_time_update_sequence_bounds(scene, seq); DEG_relations_tag_update(bmain); DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS); @@ -429,7 +429,7 @@ static Sequence *rna_Sequences_new_effect(ID *id, Scene *scene = (Scene *)id; Sequence *seq; struct SeqEffectHandle sh; - int num_inputs = BKE_sequence_effect_get_num_inputs(type); + int num_inputs = SEQ_effect_get_num_inputs(type); switch (num_inputs) { case 0: @@ -467,7 +467,7 @@ static Sequence *rna_Sequences_new_effect(ID *id, seq = alloc_generic_sequence(seqbase, name, frame_start, channel, type, NULL); - sh = BKE_sequence_get_effect(seq); + sh = SEQ_effect_handle_get(seq); seq->seq1 = seq1; seq->seq2 = seq2; @@ -477,14 +477,14 @@ static Sequence *rna_Sequences_new_effect(ID *id, if (!seq1) { /* effect has no deps */ seq->len = 1; - BKE_sequence_tx_set_final_right(seq, frame_end); + SEQ_transform_set_right_handle_frame(seq, frame_end); } seq->flag |= SEQ_USE_EFFECT_DEFAULT_FADE; - BKE_sequence_calc(scene, seq); - BKE_sequence_calc_disp(scene, seq); - BKE_sequence_invalidate_cache_composite(scene, seq); + SEQ_time_update_sequence(scene, seq); + SEQ_time_update_sequence_bounds(scene, seq); + SEQ_relations_invalidate_cache_composite(scene, seq); DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS); WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, scene); @@ -536,8 +536,8 @@ static void rna_Sequences_remove( return; } - BKE_sequencer_flag_for_removal(scene, seqbase, seq); - BKE_sequencer_remove_flagged_sequences(scene, seqbase); + SEQ_edit_flag_for_removal(scene, seqbase, seq); + SEQ_edit_remove_flagged_sequences(scene, seqbase); RNA_POINTER_INVALIDATE(seq_ptr); DEG_relations_tag_update(bmain); @@ -568,7 +568,7 @@ static StripElem *rna_SequenceElements_append(ID *id, Sequence *seq, const char BLI_strncpy(se->name, filename, sizeof(se->name)); seq->len++; - BKE_sequence_calc_disp(scene, seq); + SEQ_time_update_sequence_bounds(scene, seq); WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, scene); return se; @@ -609,7 +609,7 @@ static void rna_SequenceElements_pop(ID *id, Sequence *seq, ReportList *reports, MEM_freeN(seq->strip->stripdata); seq->strip->stripdata = new_seq; - BKE_sequence_calc_disp(scene, seq); + SEQ_time_update_sequence_bounds(scene, seq); WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, scene); } @@ -618,13 +618,13 @@ static void rna_Sequence_invalidate_cache_rnafunc(ID *id, Sequence *self, int ty { switch (type) { case SEQ_CACHE_STORE_RAW: - BKE_sequence_invalidate_cache_raw((Scene *)id, self); + SEQ_relations_invalidate_cache_raw((Scene *)id, self); break; case SEQ_CACHE_STORE_PREPROCESSED: - BKE_sequence_invalidate_cache_preprocessed((Scene *)id, self); + SEQ_relations_invalidate_cache_preprocessed((Scene *)id, self); break; case SEQ_CACHE_STORE_COMPOSITE: - BKE_sequence_invalidate_cache_composite((Scene *)id, self); + SEQ_relations_invalidate_cache_composite((Scene *)id, self); break; } } diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 2f821dad811..5604ccd9655 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -2223,7 +2223,7 @@ static void rna_SequenceEditor_update_cache(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr)) { - BKE_sequencer_cache_cleanup(scene); + SEQ_cache_cleanup(scene); } static void rna_Sequencer_view_type_update(Main *UNUSED(bmain), diff --git a/source/blender/render/intern/pipeline.c b/source/blender/render/intern/pipeline.c index 6b55b82ac97..fc6ff51976d 100644 --- a/source/blender/render/intern/pipeline.c +++ b/source/blender/render/intern/pipeline.c @@ -1548,7 +1548,7 @@ static void do_render_seq(Render *re) if (recurs_depth == 0) { /* With nested scenes, only free on top-level. */ Editing *ed = re->pipeline_scene_eval->ed; if (ed) { - BKE_sequencer_free_imbuf(re->pipeline_scene_eval, &ed->seqbase, true); + SEQ_relations_free_imbuf(re->pipeline_scene_eval, &ed->seqbase, true); } } IMB_freeImBuf(ibuf_arr[view_id]); @@ -1596,7 +1596,7 @@ static void do_render_all_options(Render *re) /* ensure no images are in memory from previous animated sequences */ BKE_image_all_free_anim_ibufs(re->main, re->r.cfra); - BKE_sequencer_all_free_anim_ibufs(re->scene, re->r.cfra); + SEQ_relations_free_all_anim_ibufs(re->scene, re->r.cfra); if (RE_engine_render(re, 1)) { /* in this case external render overrides all */ diff --git a/source/blender/sequencer/SEQ_sequencer.h b/source/blender/sequencer/SEQ_sequencer.h index 3a9c23de5cc..b2068a0d690 100644 --- a/source/blender/sequencer/SEQ_sequencer.h +++ b/source/blender/sequencer/SEQ_sequencer.h @@ -92,30 +92,28 @@ typedef struct SeqIterator { #define SEQ_ALL_BEGIN(ed, _seq) \ { \ SeqIterator iter_macro; \ - for (BKE_sequence_iterator_begin(ed, &iter_macro, false); iter_macro.valid; \ - BKE_sequence_iterator_next(&iter_macro)) { \ + for (SEQ_iterator_begin(ed, &iter_macro, false); iter_macro.valid; \ + SEQ_iterator_next(&iter_macro)) { \ _seq = iter_macro.seq; #define SEQ_ALL_END \ } \ - BKE_sequence_iterator_end(&iter_macro); \ + SEQ_iterator_end(&iter_macro); \ } \ ((void)0) #define SEQ_CURRENT_BEGIN(_ed, _seq) \ { \ SeqIterator iter_macro; \ - for (BKE_sequence_iterator_begin(_ed, &iter_macro, true); iter_macro.valid; \ - BKE_sequence_iterator_next(&iter_macro)) { \ + for (SEQ_iterator_begin(_ed, &iter_macro, true); iter_macro.valid; \ + SEQ_iterator_next(&iter_macro)) { \ _seq = iter_macro.seq; #define SEQ_CURRENT_END SEQ_ALL_END -void BKE_sequence_iterator_begin(struct Editing *ed, - SeqIterator *iter, - const bool use_current_sequences); -void BKE_sequence_iterator_next(SeqIterator *iter); -void BKE_sequence_iterator_end(SeqIterator *iter); +void SEQ_iterator_begin(struct Editing *ed, SeqIterator *iter, const bool use_current_sequences); +void SEQ_iterator_next(SeqIterator *iter); +void SEQ_iterator_end(SeqIterator *iter); /* ********************************************************************** * render.c @@ -191,56 +189,56 @@ eSeqImageFitMethod SEQ_tool_settings_fit_method_get(struct Scene *scene); void SEQ_tool_settings_fit_method_set(struct Scene *scene, eSeqImageFitMethod fit_method); struct SequencerToolSettings *SEQ_tool_settings_copy(struct SequencerToolSettings *tool_settings); -struct Editing *BKE_sequencer_editing_get(struct Scene *scene, bool alloc); -struct Editing *BKE_sequencer_editing_ensure(struct Scene *scene); -void BKE_sequencer_editing_free(struct Scene *scene, const bool do_id_user); +struct Editing *SEQ_editing_get(struct Scene *scene, bool alloc); +struct Editing *SEQ_editing_ensure(struct Scene *scene); +void SEQ_editing_free(struct Scene *scene, const bool do_id_user); struct ListBase *SEQ_active_seqbase_get(const struct Editing *ed); -void BKE_sequencer_sort(struct Scene *scene); -struct Sequence *BKE_sequencer_from_elem(ListBase *seqbase, struct StripElem *se); -struct Sequence *BKE_sequencer_active_get(struct Scene *scene); -int BKE_sequencer_active_get_pair(struct Scene *scene, - struct Sequence **seq_act, - struct Sequence **seq_other); -void BKE_sequencer_active_set(struct Scene *scene, struct Sequence *seq); -struct Mask *BKE_sequencer_mask_get(struct Scene *scene); +void SEQ_sort(struct Scene *scene); +struct Sequence *SEQ_sequence_from_strip_elem(ListBase *seqbase, struct StripElem *se); +struct Sequence *SEQ_select_active_get(struct Scene *scene); +int SEQ_select_active_get_pair(struct Scene *scene, + struct Sequence **seq_act, + struct Sequence **seq_other); +void SEQ_select_active_set(struct Scene *scene, struct Sequence *seq); +struct Mask *SEQ_active_mask_get(struct Scene *scene); /* apply functions recursively */ -int BKE_sequencer_base_recursive_apply(struct ListBase *seqbase, - int (*apply_fn)(struct Sequence *seq, void *), - void *arg); -int BKE_sequencer_recursive_apply(struct Sequence *seq, - int (*apply_fn)(struct Sequence *, void *), - void *arg); -float BKE_sequence_get_fps(struct Scene *scene, struct Sequence *seq); -int BKE_sequencer_find_next_prev_edit(struct Scene *scene, - int timeline_frame, - const short side, - const bool do_skip_mute, - const bool do_center, - const bool do_unselected); +int SEQ_iterator_seqbase_recursive_apply(struct ListBase *seqbase, + int (*apply_fn)(struct Sequence *seq, void *), + void *arg); +int SEQ_iterator_recursive_apply(struct Sequence *seq, + int (*apply_fn)(struct Sequence *, void *), + void *arg); +float SEQ_time_sequence_get_fps(struct Scene *scene, struct Sequence *seq); +int SEQ_time_find_next_prev_edit(struct Scene *scene, + int timeline_frame, + const short side, + const bool do_skip_mute, + const bool do_center, + const bool do_unselected); /* maintenance functions, mostly for RNA */ -void BKE_sequence_free(struct Scene *scene, struct Sequence *seq, const bool do_clean_animdata); -void BKE_sequence_free_anim(struct Sequence *seq); -const char *BKE_sequence_give_name(struct Sequence *seq); -ListBase *BKE_sequence_seqbase_get(struct Sequence *seq, int *r_offset); -void BKE_sequence_calc(struct Scene *scene, struct Sequence *seq); -void BKE_sequence_calc_disp(struct Scene *scene, struct Sequence *seq); -void BKE_sequence_reload_new_file(struct Main *bmain, - struct Scene *scene, - struct Sequence *seq, - const bool lock_range); -void BKE_sequence_movie_reload_if_needed(struct Main *bmain, - struct Scene *scene, - struct Sequence *seq, - bool *r_was_reloaded, - bool *r_can_produce_frames); -void BKE_sequence_alpha_mode_from_extension(struct Sequence *seq); -void BKE_sequencer_update_changed_seq_and_deps(struct Scene *scene, +void SEQ_sequence_free(struct Scene *scene, struct Sequence *seq, const bool do_clean_animdata); +void SEQ_relations_sequence_free_anim(struct Sequence *seq); +const char *SEQ_sequence_give_name(struct Sequence *seq); +ListBase *SEQ_get_seqbase_from_sequence(struct Sequence *seq, int *r_offset); +void SEQ_time_update_sequence(struct Scene *scene, struct Sequence *seq); +void SEQ_time_update_sequence_bounds(struct Scene *scene, struct Sequence *seq); +void SEQ_add_reload_new_file(struct Main *bmain, + struct Scene *scene, + struct Sequence *seq, + const bool lock_range); +void SEQ_add_movie_reload_if_needed(struct Main *bmain, + struct Scene *scene, + struct Sequence *seq, + bool *r_was_reloaded, + bool *r_can_produce_frames); +void SEQ_alpha_mode_from_file_extension(struct Sequence *seq); +void SEQ_relations_update_changed_seq_and_deps(struct Scene *scene, struct Sequence *changed_seq, int len_change, int ibuf_change); -bool BKE_sequencer_check_scene_recursion(struct Scene *scene, struct ReportList *reports); -bool BKE_sequencer_render_loop_check(struct Sequence *seq_main, struct Sequence *seq); -int BKE_sequencer_cmp_time_startdisp(const void *a, const void *b); +bool SEQ_relations_check_scene_recursion(struct Scene *scene, struct ReportList *reports); +bool SEQ_relations_render_loop_check(struct Sequence *seq_main, struct Sequence *seq); +int SEQ_time_cmp_time_startdisp(const void *a, const void *b); /* ********************************************************************** * proxy.c @@ -270,15 +268,15 @@ double SEQ_rendersize_to_scale_factor(int size); * Sequencer memory cache management functions * ********************************************************************** */ -void BKE_sequencer_cache_cleanup(struct Scene *scene); -void BKE_sequencer_cache_iterate(struct Scene *scene, - void *userdata, - bool callback_init(void *userdata, size_t item_count), - bool callback_iter(void *userdata, - struct Sequence *seq, - int timeline_frame, - int cache_type, - float cost)); +void SEQ_cache_cleanup(struct Scene *scene); +void SEQ_cache_iterate(struct Scene *scene, + void *userdata, + bool callback_init(void *userdata, size_t item_count), + bool callback_iter(void *userdata, + struct Sequence *seq, + int timeline_frame, + int cache_type, + float cost)); /* ********************************************************************** * prefetch.c @@ -287,9 +285,9 @@ void BKE_sequencer_cache_iterate(struct Scene *scene, * ********************************************************************** */ #define SEQ_CACHE_COST_MAX 10.0f -void BKE_sequencer_prefetch_stop_all(void); -void BKE_sequencer_prefetch_stop(struct Scene *scene); -bool BKE_sequencer_prefetch_need_redraw(struct Main *bmain, struct Scene *scene); +void SEQ_prefetch_stop_all(void); +void SEQ_prefetch_stop(struct Scene *scene); +bool SEQ_prefetch_need_redraw(struct Main *bmain, struct Scene *scene); /* ********************************************************************** * sequencer.c @@ -299,60 +297,59 @@ bool BKE_sequencer_prefetch_need_redraw(struct Main *bmain, struct Scene *scene) */ /* for transform but also could use elsewhere */ -int BKE_sequence_tx_get_final_left(struct Sequence *seq, bool metaclip); -int BKE_sequence_tx_get_final_right(struct Sequence *seq, bool metaclip); -void BKE_sequence_tx_set_final_left(struct Sequence *seq, int val); -void BKE_sequence_tx_set_final_right(struct Sequence *seq, int val); -void BKE_sequence_tx_handle_xlimits(struct Sequence *seq, int leftflag, int rightflag); -bool BKE_sequence_tx_test(struct Sequence *seq); -bool BKE_sequence_tx_fullupdate_test(struct Sequence *seq); -bool BKE_sequence_single_check(struct Sequence *seq); -void BKE_sequence_single_fix(struct Sequence *seq); -bool BKE_sequence_test_overlap(struct ListBase *seqbasep, struct Sequence *test); -void BKE_sequence_translate(struct Scene *scene, struct Sequence *seq, int delta); -const struct Sequence *BKE_sequencer_foreground_frame_get(const struct Scene *scene, int frame); -struct ListBase *BKE_sequence_seqbase(struct ListBase *seqbase, struct Sequence *seq); -void BKE_sequencer_offset_animdata(struct Scene *scene, struct Sequence *seq, int ofs); -void BKE_sequencer_dupe_animdata(struct Scene *scene, const char *name_src, const char *name_dst); -bool BKE_sequence_base_shuffle_ex(struct ListBase *seqbasep, - struct Sequence *test, - struct Scene *evil_scene, - int channel_delta); -bool BKE_sequence_base_shuffle(struct ListBase *seqbasep, - struct Sequence *test, - struct Scene *evil_scene); -bool BKE_sequence_base_shuffle_time(ListBase *seqbasep, - struct Scene *evil_scene, - ListBase *markers, - const bool use_sync_markers); -bool BKE_sequence_base_isolated_sel_check(struct ListBase *seqbase); -void BKE_sequencer_free_imbuf(struct Scene *scene, struct ListBase *seqbasep, bool for_render); -struct Sequence *BKE_sequence_dupli_recursive(const struct Scene *scene_src, +int SEQ_transform_get_left_handle_frame(struct Sequence *seq, bool metaclip); +int SEQ_transform_get_right_handle_frame(struct Sequence *seq, bool metaclip); +void SEQ_transform_set_left_handle_frame(struct Sequence *seq, int val); +void SEQ_transform_set_right_handle_frame(struct Sequence *seq, int val); +void SEQ_transform_handle_xlimits(struct Sequence *seq, int leftflag, int rightflag); +bool SEQ_transform_sequence_can_be_translated(struct Sequence *seq); +bool SEQ_transform_single_image_check(struct Sequence *seq); +void SEQ_transform_fix_single_image_seq_offsets(struct Sequence *seq); +bool SEQ_transform_test_overlap(struct ListBase *seqbasep, struct Sequence *test); +void SEQ_transform_translate_sequence(struct Scene *scene, struct Sequence *seq, int delta); +const struct Sequence *SEQ_get_topmost_sequence(const struct Scene *scene, int frame); +struct ListBase *SEQ_get_seqbase_by_seq(struct ListBase *seqbase, struct Sequence *seq); +void SEQ_offset_animdata(struct Scene *scene, struct Sequence *seq, int ofs); +void SEQ_dupe_animdata(struct Scene *scene, const char *name_src, const char *name_dst); +bool SEQ_transform_seqbase_shuffle_ex(struct ListBase *seqbasep, + struct Sequence *test, + struct Scene *evil_scene, + int channel_delta); +bool SEQ_transform_seqbase_shuffle(struct ListBase *seqbasep, + struct Sequence *test, + struct Scene *evil_scene); +bool SEQ_transform_seqbase_shuffle_time(ListBase *seqbasep, + struct Scene *evil_scene, + ListBase *markers, + const bool use_sync_markers); +bool SEQ_transform_seqbase_isolated_sel_check(struct ListBase *seqbase); +void SEQ_relations_free_imbuf(struct Scene *scene, struct ListBase *seqbasep, bool for_render); +struct Sequence *SEQ_sequence_dupli_recursive(const struct Scene *scene_src, struct Scene *scene_dst, struct ListBase *new_seq_list, struct Sequence *seq, int dupe_flag); -int BKE_sequence_swap(struct Sequence *seq_a, struct Sequence *seq_b, const char **error_str); -void BKE_sequencer_update_sound_bounds_all(struct Scene *scene); -void BKE_sequencer_update_sound_bounds(struct Scene *scene, struct Sequence *seq); -void BKE_sequencer_update_muting(struct Editing *ed); -void BKE_sequencer_update_sound(struct Scene *scene, struct bSound *sound); -void BKE_sequencer_refresh_sound_length(struct Main *bmain, struct Scene *scene); -void BKE_sequence_base_unique_name_recursive(ListBase *seqbasep, struct Sequence *seq); -void BKE_sequence_base_dupli_recursive(const struct Scene *scene_src, +int SEQ_edit_sequence_swap(struct Sequence *seq_a, struct Sequence *seq_b, const char **error_str); +void SEQ_sound_update_bounds_all(struct Scene *scene); +void SEQ_sound_update_bounds(struct Scene *scene, struct Sequence *seq); +void SEQ_sound_update_muting(struct Editing *ed); +void SEQ_sound_update(struct Scene *scene, struct bSound *sound); +void SEQ_sound_update_length(struct Main *bmain, struct Scene *scene); +void SEQ_sequence_base_unique_name_recursive(ListBase *seqbasep, struct Sequence *seq); +void SEQ_sequence_base_dupli_recursive(const struct Scene *scene_src, struct Scene *scene_dst, struct ListBase *nseqbase, const struct ListBase *seqbase, int dupe_flag, const int flag); -bool BKE_sequence_is_valid_check(struct Sequence *seq); -struct Sequence *BKE_sequence_get_by_name(struct ListBase *seqbase, +bool SEQ_sequence_has_source(struct Sequence *seq); +struct Sequence *SEQ_get_sequence_by_name(struct ListBase *seqbase, const char *name, bool recursive); -void BKE_sequencer_flag_for_removal(struct Scene *scene, - struct ListBase *seqbase, - struct Sequence *seq); -void BKE_sequencer_remove_flagged_sequences(struct Scene *scene, struct ListBase *seqbase); +void SEQ_edit_flag_for_removal(struct Scene *scene, + struct ListBase *seqbase, + struct Sequence *seq); +void SEQ_edit_remove_flagged_sequences(struct Scene *scene, struct ListBase *seqbase); /* ********************************************************************** * sequencer.c @@ -361,17 +358,17 @@ void BKE_sequencer_remove_flagged_sequences(struct Scene *scene, struct ListBase * ********************************************************************** */ -void BKE_sequence_invalidate_cache_raw(struct Scene *scene, struct Sequence *seq); -void BKE_sequence_invalidate_cache_preprocessed(struct Scene *scene, struct Sequence *seq); -void BKE_sequence_invalidate_cache_composite(struct Scene *scene, struct Sequence *seq); -void BKE_sequence_invalidate_dependent(struct Scene *scene, struct Sequence *seq); -void BKE_sequence_invalidate_scene_strips(struct Main *bmain, struct Scene *scene_target); -void BKE_sequence_invalidate_movieclip_strips(struct Main *bmain, struct MovieClip *clip_target); -void BKE_sequence_invalidate_cache_in_range(struct Scene *scene, - struct Sequence *seq, - struct Sequence *range_mask, - int invalidate_types); -void BKE_sequencer_all_free_anim_ibufs(struct Scene *scene, int timeline_frame); +void SEQ_relations_invalidate_cache_raw(struct Scene *scene, struct Sequence *seq); +void SEQ_relations_invalidate_cache_preprocessed(struct Scene *scene, struct Sequence *seq); +void SEQ_relations_invalidate_cache_composite(struct Scene *scene, struct Sequence *seq); +void SEQ_relations_invalidate_dependent(struct Scene *scene, struct Sequence *seq); +void SEQ_relations_invalidate_scene_strips(struct Main *bmain, struct Scene *scene_target); +void SEQ_relations_invalidate_movieclip_strips(struct Main *bmain, struct MovieClip *clip_target); +void SEQ_relations_invalidate_cache_in_range(struct Scene *scene, + struct Sequence *seq, + struct Sequence *range_mask, + int invalidate_types); +void SEQ_relations_free_all_anim_ibufs(struct Scene *scene, int timeline_frame); /* ********************************************************************** * util.c @@ -434,16 +431,16 @@ typedef struct SeqLoadInfo { /* use as an api function */ typedef struct Sequence *(*SeqLoadFn)(struct bContext *, ListBase *, struct SeqLoadInfo *); -struct Sequence *BKE_sequence_alloc(ListBase *lb, int timeline_frame, int machine, int type); -struct Sequence *BKE_sequencer_add_image_strip(struct bContext *C, - ListBase *seqbasep, - struct SeqLoadInfo *seq_load); -struct Sequence *BKE_sequencer_add_sound_strip(struct bContext *C, - ListBase *seqbasep, - struct SeqLoadInfo *seq_load); -struct Sequence *BKE_sequencer_add_movie_strip(struct bContext *C, - ListBase *seqbasep, - struct SeqLoadInfo *seq_load); +struct Sequence *SEQ_sequence_alloc(ListBase *lb, int timeline_frame, int machine, int type); +struct Sequence *SEQ_add_image_strip(struct bContext *C, + ListBase *seqbasep, + struct SeqLoadInfo *seq_load); +struct Sequence *SEQ_add_sound_strip(struct bContext *C, + ListBase *seqbasep, + struct SeqLoadInfo *seq_load); +struct Sequence *SEQ_add_movie_strip(struct bContext *C, + ListBase *seqbasep, + struct SeqLoadInfo *seq_load); /* ********************************************************************** * modifier.c @@ -478,28 +475,25 @@ typedef struct SequenceModifierTypeInfo { void (*apply)(struct SequenceModifierData *smd, struct ImBuf *ibuf, struct ImBuf *mask); } SequenceModifierTypeInfo; -const struct SequenceModifierTypeInfo *BKE_sequence_modifier_type_info_get(int type); -struct SequenceModifierData *BKE_sequence_modifier_new(struct Sequence *seq, - const char *name, - int type); -bool BKE_sequence_modifier_remove(struct Sequence *seq, struct SequenceModifierData *smd); -void BKE_sequence_modifier_clear(struct Sequence *seq); -void BKE_sequence_modifier_free(struct SequenceModifierData *smd); -void BKE_sequence_modifier_unique_name(struct Sequence *seq, struct SequenceModifierData *smd); -struct SequenceModifierData *BKE_sequence_modifier_find_by_name(struct Sequence *seq, - const char *name); -struct ImBuf *BKE_sequence_modifier_apply_stack(const SeqRenderData *context, - struct Sequence *seq, - struct ImBuf *ibuf, - int timeline_frame); -void BKE_sequence_modifier_list_copy(struct Sequence *seqn, struct Sequence *seq); -int BKE_sequence_supports_modifiers(struct Sequence *seq); - -void BKE_sequence_modifier_blend_write(struct BlendWriter *writer, struct ListBase *modbase); -void BKE_sequence_modifier_blend_read_data(struct BlendDataReader *reader, struct ListBase *lb); -void BKE_sequence_modifier_blend_read_lib(struct BlendLibReader *reader, - struct Scene *scene, - struct ListBase *lb); +const struct SequenceModifierTypeInfo *SEQ_modifier_type_info_get(int type); +struct SequenceModifierData *SEQ_modifier_new(struct Sequence *seq, const char *name, int type); +bool SEQ_modifier_remove(struct Sequence *seq, struct SequenceModifierData *smd); +void SEQ_modifier_clear(struct Sequence *seq); +void SEQ_modifier_free(struct SequenceModifierData *smd); +void SEQ_modifier_unique_name(struct Sequence *seq, struct SequenceModifierData *smd); +struct SequenceModifierData *SEQ_modifier_find_by_name(struct Sequence *seq, const char *name); +struct ImBuf *SEQ_modifier_apply_stack(const SeqRenderData *context, + struct Sequence *seq, + struct ImBuf *ibuf, + int timeline_frame); +void SEQ_modifier_list_copy(struct Sequence *seqn, struct Sequence *seq); +int SEQ_sequence_supports_modifiers(struct Sequence *seq); + +void SEQ_modifier_blend_write(struct BlendWriter *writer, struct ListBase *modbase); +void SEQ_modifier_blend_read_data(struct BlendDataReader *reader, struct ListBase *lb); +void SEQ_modifier_blend_read_lib(struct BlendLibReader *reader, + struct Scene *scene, + struct ListBase *lb); /* ********************************************************************** * seqeffects.c @@ -574,10 +568,10 @@ struct SeqEffectHandle { struct ImBuf *out); }; -struct SeqEffectHandle BKE_sequence_get_effect(struct Sequence *seq); -int BKE_sequence_effect_get_num_inputs(int seq_type); -void BKE_sequencer_text_font_unload(struct TextVars *data, const bool do_id_user); -void BKE_sequencer_text_font_load(struct TextVars *data, const bool do_id_user); +struct SeqEffectHandle SEQ_effect_handle_get(struct Sequence *seq); +int SEQ_effect_get_num_inputs(int seq_type); +void SEQ_effect_text_font_unload(struct TextVars *data, const bool do_id_user); +void SEQ_effect_text_font_load(struct TextVars *data, const bool do_id_user); /* ********************************************************************** * sequencer.c @@ -588,9 +582,9 @@ void BKE_sequencer_text_font_load(struct TextVars *data, const bool do_id_user); extern ListBase seqbase_clipboard; extern int seqbase_clipboard_frame; -void BKE_sequencer_base_clipboard_pointers_store(struct Main *bmain, struct ListBase *seqbase); -void BKE_sequencer_base_clipboard_pointers_restore(struct ListBase *seqbase, struct Main *bmain); -void BKE_sequencer_free_clipboard(void); +void SEQ_clipboard_pointers_store(struct Main *bmain, struct ListBase *seqbase); +void SEQ_clipboard_pointers_restore(struct ListBase *seqbase, struct Main *bmain); +void SEQ_clipboard_free(void); /* ********************************************************************** * sequencer.c @@ -601,9 +595,9 @@ void BKE_sequencer_free_clipboard(void); /* A debug and development function which checks whether sequences have unique UUIDs. * Errors will be reported to the console. */ -void BKE_sequencer_check_uuids_unique_and_report(const struct Scene *scene); +void SEQ_relations_check_uuids_unique_and_report(const struct Scene *scene); /* Generate new UUID for the given sequence. */ -void BKE_sequence_session_uuid_generate(struct Sequence *sequence); +void SEQ_relations_session_uuid_generate(struct Sequence *sequence); /* ********************************************************************** * strip_edit.c @@ -646,10 +640,10 @@ void SEQ_timeline_boundbox(const struct Scene *scene, * ********************************************************************** */ -void SEQ_offset_after_frame(struct Scene *scene, - struct ListBase *seqbase, - const int delta, - const int timeline_frame); +void SEQ_transform_offset_after_frame(struct Scene *scene, + struct ListBase *seqbase, + const int delta, + const int timeline_frame); #ifdef __cplusplus } diff --git a/source/blender/sequencer/intern/clipboard.c b/source/blender/sequencer/intern/clipboard.c index 7d37dab93dd..7a9a06a744a 100644 --- a/source/blender/sequencer/intern/clipboard.c +++ b/source/blender/sequencer/intern/clipboard.c @@ -56,13 +56,13 @@ ListBase seqbase_clipboard; int seqbase_clipboard_frame; -void BKE_sequencer_base_clipboard_pointers_free(struct ListBase *seqbase); +void seq_clipboard_pointers_free(struct ListBase *seqbase); -void BKE_sequencer_free_clipboard(void) +void SEQ_clipboard_free(void) { Sequence *seq, *nseq; - BKE_sequencer_base_clipboard_pointers_free(&seqbase_clipboard); + seq_clipboard_pointers_free(&seqbase_clipboard); for (seq = seqbase_clipboard.first; seq; seq = nseq) { nseq = seq->next; @@ -153,27 +153,27 @@ static void sequence_clipboard_pointers(Main *bmain, } /* recursive versions of functions above */ -void BKE_sequencer_base_clipboard_pointers_free(ListBase *seqbase) +void seq_clipboard_pointers_free(ListBase *seqbase) { Sequence *seq; for (seq = seqbase->first; seq; seq = seq->next) { sequence_clipboard_pointers(NULL, seq, seqclipboard_ptr_free); - BKE_sequencer_base_clipboard_pointers_free(&seq->seqbase); + seq_clipboard_pointers_free(&seq->seqbase); } } -void BKE_sequencer_base_clipboard_pointers_store(Main *bmain, ListBase *seqbase) +void SEQ_clipboard_pointers_store(Main *bmain, ListBase *seqbase) { Sequence *seq; for (seq = seqbase->first; seq; seq = seq->next) { sequence_clipboard_pointers(bmain, seq, seqclipboard_ptr_store); - BKE_sequencer_base_clipboard_pointers_store(bmain, &seq->seqbase); + SEQ_clipboard_pointers_store(bmain, &seq->seqbase); } } -void BKE_sequencer_base_clipboard_pointers_restore(ListBase *seqbase, Main *bmain) +void SEQ_clipboard_pointers_restore(ListBase *seqbase, Main *bmain) { Sequence *seq; for (seq = seqbase->first; seq; seq = seq->next) { sequence_clipboard_pointers(bmain, seq, seqclipboard_ptr_restore); - BKE_sequencer_base_clipboard_pointers_restore(&seq->seqbase, bmain); + SEQ_clipboard_pointers_restore(&seq->seqbase, bmain); } } diff --git a/source/blender/sequencer/intern/effects.c b/source/blender/sequencer/intern/effects.c index 8ffbc453517..58dd6d6e048 100644 --- a/source/blender/sequencer/intern/effects.c +++ b/source/blender/sequencer/intern/effects.c @@ -2988,7 +2988,7 @@ static ImBuf *do_multicam(const SeqRenderData *context, if (!ed) { return NULL; } - seqbasep = BKE_sequence_seqbase(&ed->seqbase, seq); + seqbasep = SEQ_get_seqbase_by_seq(&ed->seqbase, seq); if (!seqbasep) { return NULL; } @@ -3019,7 +3019,7 @@ static ImBuf *do_adjustment_impl(const SeqRenderData *context, Sequence *seq, fl ed = context->scene->ed; - seqbasep = BKE_sequence_seqbase(&ed->seqbase, seq); + seqbasep = SEQ_get_seqbase_by_seq(&ed->seqbase, seq); if (seq->machine > 1) { i = seq_render_give_ibuf_seqbase(context, timeline_frame, seq->machine - 1, seqbasep); @@ -3033,7 +3033,7 @@ static ImBuf *do_adjustment_impl(const SeqRenderData *context, Sequence *seq, fl if (!i) { Sequence *meta; - meta = BKE_sequence_metastrip(&ed->seqbase, NULL, seq); + meta = seq_find_metastrip_by_sequence(&ed->seqbase, NULL, seq); if (meta) { i = do_adjustment_impl(context, meta, timeline_frame); @@ -3129,7 +3129,7 @@ static void store_icu_yrange_speed(Sequence *seq, short UNUSED(adrcode), float * SpeedControlVars *v = (SpeedControlVars *)seq->effectdata; /* if not already done, load / initialize data */ - BKE_sequence_get_effect(seq); + SEQ_effect_handle_get(seq); if ((v->flags & SEQ_SPEED_INTEGRATE) != 0) { *ymin = -100.0; @@ -3147,7 +3147,7 @@ static void store_icu_yrange_speed(Sequence *seq, short UNUSED(adrcode), float * } } -void BKE_sequence_effect_speed_rebuild_map(Scene *scene, Sequence *seq, bool force) +void seq_effect_speed_rebuild_map(Scene *scene, Sequence *seq, bool force) { int timeline_frame; float fallback_fac = 1.0f; @@ -3156,7 +3156,7 @@ void BKE_sequence_effect_speed_rebuild_map(Scene *scene, Sequence *seq, bool for int flags = v->flags; /* if not already done, load / initialize data */ - BKE_sequence_get_effect(seq); + SEQ_effect_handle_get(seq); if ((force == false) && (seq->len == v->length) && (v->frameMap != NULL)) { return; @@ -3252,14 +3252,14 @@ void BKE_sequence_effect_speed_rebuild_map(Scene *scene, Sequence *seq, bool for } /* Override timeline_frame when rendering speed effect input. */ -float BKE_sequencer_speed_effect_target_frame_get(const SeqRenderData *context, - Sequence *seq, - float timeline_frame, - int input) +float seq_speed_effect_target_frame_get(const SeqRenderData *context, + Sequence *seq, + float timeline_frame, + int input) { int frame_index = seq_give_frame_index(seq, timeline_frame); SpeedControlVars *s = (SpeedControlVars *)seq->effectdata; - BKE_sequence_effect_speed_rebuild_map(context->scene, seq, false); + seq_effect_speed_rebuild_map(context->scene, seq, false); /* No interpolation. */ if ((s->flags & SEQ_SPEED_USE_INTERPOLATION) == 0) { @@ -3804,7 +3804,7 @@ static void init_text_effect(Sequence *seq) data->align_y = SEQ_TEXT_ALIGN_Y_BOTTOM; } -void BKE_sequencer_text_font_unload(TextVars *data, const bool do_id_user) +void SEQ_effect_text_font_unload(TextVars *data, const bool do_id_user) { if (data) { /* Unlink the VFont */ @@ -3820,7 +3820,7 @@ void BKE_sequencer_text_font_unload(TextVars *data, const bool do_id_user) } } -void BKE_sequencer_text_font_load(TextVars *data, const bool do_id_user) +void SEQ_effect_text_font_load(TextVars *data, const bool do_id_user) { if (data->text_font != NULL) { if (do_id_user) { @@ -3839,7 +3839,7 @@ void BKE_sequencer_text_font_load(TextVars *data, const bool do_id_user) static void free_text_effect(Sequence *seq, const bool do_id_user) { TextVars *data = seq->effectdata; - BKE_sequencer_text_font_unload(data, do_id_user); + SEQ_effect_text_font_unload(data, do_id_user); if (data) { MEM_freeN(data); @@ -3850,7 +3850,7 @@ static void free_text_effect(Sequence *seq, const bool do_id_user) static void load_text_effect(Sequence *seq) { TextVars *data = seq->effectdata; - BKE_sequencer_text_font_load(data, false); + SEQ_effect_text_font_load(data, false); } static void copy_text_effect(Sequence *dst, Sequence *src, const int flag) @@ -3859,7 +3859,7 @@ static void copy_text_effect(Sequence *dst, Sequence *src, const int flag) TextVars *data = dst->effectdata; data->text_blf_id = -1; - BKE_sequencer_text_font_load(data, (flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0); + SEQ_effect_text_font_load(data, (flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0); } static int num_inputs_text(void) @@ -4275,7 +4275,7 @@ static struct SeqEffectHandle get_sequence_effect_impl(int seq_type) return rval; } -struct SeqEffectHandle BKE_sequence_get_effect(Sequence *seq) +struct SeqEffectHandle SEQ_effect_handle_get(Sequence *seq) { struct SeqEffectHandle rval = {false, false, NULL}; @@ -4290,7 +4290,7 @@ struct SeqEffectHandle BKE_sequence_get_effect(Sequence *seq) return rval; } -struct SeqEffectHandle BKE_sequence_get_blend(Sequence *seq) +struct SeqEffectHandle seq_effect_get_sequence_blend(Sequence *seq) { struct SeqEffectHandle rval = {false, false, NULL}; @@ -4312,7 +4312,7 @@ struct SeqEffectHandle BKE_sequence_get_blend(Sequence *seq) return rval; } -int BKE_sequence_effect_get_num_inputs(int seq_type) +int SEQ_effect_get_num_inputs(int seq_type) { struct SeqEffectHandle rval = get_sequence_effect_impl(seq_type); diff --git a/source/blender/sequencer/intern/effects.h b/source/blender/sequencer/intern/effects.h index 6a94c0ea9d9..1bce4f324c3 100644 --- a/source/blender/sequencer/intern/effects.h +++ b/source/blender/sequencer/intern/effects.h @@ -38,12 +38,12 @@ struct Sequence; * ********************************************************************** */ -struct SeqEffectHandle BKE_sequence_get_blend(struct Sequence *seq); -void BKE_sequence_effect_speed_rebuild_map(struct Scene *scene, struct Sequence *seq, bool force); -float BKE_sequencer_speed_effect_target_frame_get(const struct SeqRenderData *context, - struct Sequence *seq, - float timeline_frame, - int input); +struct SeqEffectHandle seq_effect_get_sequence_blend(struct Sequence *seq); +void seq_effect_speed_rebuild_map(struct Scene *scene, struct Sequence *seq, bool force); +float seq_speed_effect_target_frame_get(const struct SeqRenderData *context, + struct Sequence *seq, + float timeline_frame, + int input); #ifdef __cplusplus } diff --git a/source/blender/sequencer/intern/image_cache.c b/source/blender/sequencer/intern/image_cache.c index d515a13cdee..6eb12df7186 100644 --- a/source/blender/sequencer/intern/image_cache.c +++ b/source/blender/sequencer/intern/image_cache.c @@ -803,7 +803,7 @@ static void seq_cache_valfree(void *val) BLI_mempool_free(item->cache_owner->items_pool, item); } -static void seq_cache_put(SeqCache *cache, SeqCacheKey *key, ImBuf *ibuf) +static void seq_cache_put_ex(SeqCache *cache, SeqCacheKey *key, ImBuf *ibuf) { SeqCacheItem *item; item = BLI_mempool_alloc(cache->items_pool); @@ -817,7 +817,7 @@ static void seq_cache_put(SeqCache *cache, SeqCacheKey *key, ImBuf *ibuf) } } -static ImBuf *seq_cache_get(SeqCache *cache, SeqCacheKey *key) +static ImBuf *seq_cache_get_ex(SeqCache *cache, SeqCacheKey *key) { SeqCacheItem *item = BLI_ghash_lookup(cache->hash, key); @@ -856,10 +856,9 @@ static SeqCacheKey *seq_cache_choose_key(Scene *scene, SeqCacheKey *lkey, SeqCac * We could use temp cache as a shield and later make it a non-temporary entry, * but it is not worth of increasing system complexity. */ - if (scene->ed->cache_flag & SEQ_CACHE_PREFETCH_ENABLE && - BKE_sequencer_prefetch_job_is_running(scene)) { + if (scene->ed->cache_flag & SEQ_CACHE_PREFETCH_ENABLE && seq_prefetch_job_is_running(scene)) { int pfjob_start, pfjob_end; - BKE_sequencer_prefetch_get_time_range(scene, &pfjob_start, &pfjob_end); + seq_prefetch_get_time_range(scene, &pfjob_start, &pfjob_end); if (lkey) { if (lkey->timeline_frame < pfjob_start || lkey->timeline_frame > pfjob_end) { @@ -990,7 +989,7 @@ static SeqCacheKey *seq_cache_get_item_for_removal(Scene *scene) /* Find only "base" keys. * Sources(other types) for a frame must be freed all at once. */ -bool BKE_sequencer_cache_recycle_item(Scene *scene) +bool seq_cache_recycle_item(Scene *scene) { size_t memory_total = seq_cache_get_mem_total(); SeqCache *cache = seq_cache_get_from_scene(scene); @@ -1083,7 +1082,7 @@ static void seq_cache_create(Main *bmain, Scene *scene) /* ***************************** API ****************************** */ -void BKE_sequencer_cache_free_temp_cache(Scene *scene, short id, int timeline_frame) +void seq_cache_free_temp_cache(Scene *scene, short id, int timeline_frame) { SeqCache *cache = seq_cache_get_from_scene(scene); if (!cache) { @@ -1111,7 +1110,7 @@ void BKE_sequencer_cache_free_temp_cache(Scene *scene, short id, int timeline_fr seq_cache_unlock(scene); } -void BKE_sequencer_cache_destruct(Scene *scene) +void seq_cache_destruct(Scene *scene) { SeqCache *cache = seq_cache_get_from_scene(scene); if (!cache) { @@ -1133,15 +1132,15 @@ void BKE_sequencer_cache_destruct(Scene *scene) scene->ed->cache = NULL; } -void BKE_sequencer_cache_cleanup_all(Main *bmain) +void seq_cache_cleanup_all(Main *bmain) { for (Scene *scene = bmain->scenes.first; scene != NULL; scene = scene->id.next) { - BKE_sequencer_cache_cleanup(scene); + SEQ_cache_cleanup(scene); } } -void BKE_sequencer_cache_cleanup(Scene *scene) +void SEQ_cache_cleanup(Scene *scene) { - BKE_sequencer_prefetch_stop(scene); + SEQ_prefetch_stop(scene); SeqCache *cache = seq_cache_get_from_scene(scene); if (!cache) { @@ -1162,11 +1161,11 @@ void BKE_sequencer_cache_cleanup(Scene *scene) seq_cache_unlock(scene); } -void BKE_sequencer_cache_cleanup_sequence(Scene *scene, - Sequence *seq, - Sequence *seq_changed, - int invalidate_types, - bool force_seq_changed_range) +void seq_cache_cleanup_sequence(Scene *scene, + Sequence *seq, + Sequence *seq_changed, + int invalidate_types, + bool force_seq_changed_range) { SeqCache *cache = seq_cache_get_from_scene(scene); if (!cache) { @@ -1226,11 +1225,11 @@ void BKE_sequencer_cache_cleanup_sequence(Scene *scene, seq_cache_unlock(scene); } -struct ImBuf *BKE_sequencer_cache_get(const SeqRenderData *context, - Sequence *seq, - float timeline_frame, - int type, - bool skip_disk_cache) +struct ImBuf *seq_cache_get(const SeqRenderData *context, + Sequence *seq, + float timeline_frame, + int type, + bool skip_disk_cache) { if (context->skip_cache || context->is_proxy_render || !seq) { @@ -1240,9 +1239,9 @@ struct ImBuf *BKE_sequencer_cache_get(const SeqRenderData *context, Scene *scene = context->scene; if (context->is_prefetch_render) { - context = BKE_sequencer_prefetch_get_original_context(context); + context = seq_prefetch_get_original_context(context); scene = context->scene; - seq = BKE_sequencer_prefetch_get_original_sequence(seq, scene); + seq = seq_prefetch_get_original_sequence(seq, scene); } if (!seq) { @@ -1265,7 +1264,7 @@ struct ImBuf *BKE_sequencer_cache_get(const SeqRenderData *context, key.frame_index = seq_cache_timeline_frame_to_frame_index(seq, timeline_frame, type); key.type = type; - ibuf = seq_cache_get(cache, &key); + ibuf = seq_cache_get_ex(cache, &key); } seq_cache_unlock(scene); @@ -1284,10 +1283,10 @@ struct ImBuf *BKE_sequencer_cache_get(const SeqRenderData *context, BLI_mutex_unlock(&cache->disk_cache->read_write_mutex); if (ibuf) { if (key.type == SEQ_CACHE_STORE_FINAL_OUT) { - BKE_sequencer_cache_put_if_possible(context, seq, timeline_frame, type, ibuf, 0.0f, true); + seq_cache_put_if_possible(context, seq, timeline_frame, type, ibuf, 0.0f, true); } else { - BKE_sequencer_cache_put(context, seq, timeline_frame, type, ibuf, 0.0f, true); + seq_cache_put(context, seq, timeline_frame, type, ibuf, 0.0f, true); } } } @@ -1295,28 +1294,28 @@ struct ImBuf *BKE_sequencer_cache_get(const SeqRenderData *context, return ibuf; } -bool BKE_sequencer_cache_put_if_possible(const SeqRenderData *context, - Sequence *seq, - float timeline_frame, - int type, - ImBuf *ibuf, - float cost, - bool skip_disk_cache) +bool seq_cache_put_if_possible(const SeqRenderData *context, + Sequence *seq, + float timeline_frame, + int type, + ImBuf *ibuf, + float cost, + bool skip_disk_cache) { Scene *scene = context->scene; if (context->is_prefetch_render) { - context = BKE_sequencer_prefetch_get_original_context(context); + context = seq_prefetch_get_original_context(context); scene = context->scene; - seq = BKE_sequencer_prefetch_get_original_sequence(seq, scene); + seq = seq_prefetch_get_original_sequence(seq, scene); } if (!seq) { return false; } - if (BKE_sequencer_cache_recycle_item(scene)) { - BKE_sequencer_cache_put(context, seq, timeline_frame, type, ibuf, cost, skip_disk_cache); + if (seq_cache_recycle_item(scene)) { + seq_cache_put(context, seq, timeline_frame, type, ibuf, cost, skip_disk_cache); return true; } @@ -1325,13 +1324,13 @@ bool BKE_sequencer_cache_put_if_possible(const SeqRenderData *context, return false; } -void BKE_sequencer_cache_put(const SeqRenderData *context, - Sequence *seq, - float timeline_frame, - int type, - ImBuf *i, - float cost, - bool skip_disk_cache) +void seq_cache_put(const SeqRenderData *context, + Sequence *seq, + float timeline_frame, + int type, + ImBuf *i, + float cost, + bool skip_disk_cache) { if (i == NULL || context->skip_cache || context->is_proxy_render || !seq) { return; @@ -1340,14 +1339,14 @@ void BKE_sequencer_cache_put(const SeqRenderData *context, Scene *scene = context->scene; if (context->is_prefetch_render) { - context = BKE_sequencer_prefetch_get_original_context(context); + context = seq_prefetch_get_original_context(context); scene = context->scene; - seq = BKE_sequencer_prefetch_get_original_sequence(seq, scene); + seq = seq_prefetch_get_original_sequence(seq, scene); BLI_assert(seq != NULL); } /* Prevent reinserting, it breaks cache key linking. */ - ImBuf *test = BKE_sequencer_cache_get(context, seq, timeline_frame, type, true); + ImBuf *test = seq_cache_get(context, seq, timeline_frame, type, true); if (test) { IMB_freeImBuf(test); return; @@ -1398,7 +1397,7 @@ void BKE_sequencer_cache_put(const SeqRenderData *context, } SeqCacheKey *temp_last_key = cache->last_key; - seq_cache_put(cache, key, i); + seq_cache_put_ex(cache, key, i); /* Restore pointer to previous item as this one will be freed when stack is rendered. */ if (key->is_temp_cache) { @@ -1433,14 +1432,14 @@ void BKE_sequencer_cache_put(const SeqRenderData *context, } } -void BKE_sequencer_cache_iterate(struct Scene *scene, - void *userdata, - bool callback_init(void *userdata, size_t item_count), - bool callback_iter(void *userdata, - struct Sequence *seq, - int timeline_frame, - int cache_type, - float cost)) +void SEQ_cache_iterate(struct Scene *scene, + void *userdata, + bool callback_init(void *userdata, size_t item_count), + bool callback_iter(void *userdata, + struct Sequence *seq, + int timeline_frame, + int cache_type, + float cost)) { SeqCache *cache = seq_cache_get_from_scene(scene); if (!cache) { @@ -1464,7 +1463,7 @@ void BKE_sequencer_cache_iterate(struct Scene *scene, seq_cache_unlock(scene); } -bool BKE_sequencer_cache_is_full(Scene *scene) +bool seq_cache_is_full(Scene *scene) { size_t memory_total = seq_cache_get_mem_total(); SeqCache *cache = seq_cache_get_from_scene(scene); diff --git a/source/blender/sequencer/intern/image_cache.h b/source/blender/sequencer/intern/image_cache.h index 2cb35670a2c..ed2d5dee910 100644 --- a/source/blender/sequencer/intern/image_cache.h +++ b/source/blender/sequencer/intern/image_cache.h @@ -37,35 +37,35 @@ struct Sequence; } #endif -struct ImBuf *BKE_sequencer_cache_get(const struct SeqRenderData *context, - struct Sequence *seq, - float timeline_frame, - int type, - bool skip_disk_cache); -void BKE_sequencer_cache_put(const struct SeqRenderData *context, - struct Sequence *seq, - float timeline_frame, - int type, - struct ImBuf *i, - float cost, - bool skip_disk_cache); -bool BKE_sequencer_cache_put_if_possible(const struct SeqRenderData *context, - struct Sequence *seq, - float timeline_frame, - int type, - struct ImBuf *nval, - float cost, - bool skip_disk_cache); -bool BKE_sequencer_cache_recycle_item(struct Scene *scene); -void BKE_sequencer_cache_free_temp_cache(struct Scene *scene, short id, int timeline_frame); -void BKE_sequencer_cache_destruct(struct Scene *scene); -void BKE_sequencer_cache_cleanup_all(struct Main *bmain); -void BKE_sequencer_cache_cleanup_sequence(struct Scene *scene, - struct Sequence *seq, - struct Sequence *seq_changed, - int invalidate_types, - bool force_seq_changed_range); -bool BKE_sequencer_cache_is_full(struct Scene *scene); +struct ImBuf *seq_cache_get(const struct SeqRenderData *context, + struct Sequence *seq, + float timeline_frame, + int type, + bool skip_disk_cache); +void seq_cache_put(const struct SeqRenderData *context, + struct Sequence *seq, + float timeline_frame, + int type, + struct ImBuf *i, + float cost, + bool skip_disk_cache); +bool seq_cache_put_if_possible(const struct SeqRenderData *context, + struct Sequence *seq, + float timeline_frame, + int type, + struct ImBuf *nval, + float cost, + bool skip_disk_cache); +bool seq_cache_recycle_item(struct Scene *scene); +void seq_cache_free_temp_cache(struct Scene *scene, short id, int timeline_frame); +void seq_cache_destruct(struct Scene *scene); +void seq_cache_cleanup_all(struct Main *bmain); +void seq_cache_cleanup_sequence(struct Scene *scene, + struct Sequence *seq, + struct Sequence *seq_changed, + int invalidate_types, + bool force_seq_changed_range); +bool seq_cache_is_full(struct Scene *scene); #ifdef __cplusplus } diff --git a/source/blender/sequencer/intern/iterator.c b/source/blender/sequencer/intern/iterator.c index fe6f4184ab1..7d54795b150 100644 --- a/source/blender/sequencer/intern/iterator.c +++ b/source/blender/sequencer/intern/iterator.c @@ -108,7 +108,7 @@ static void seq_array(Editing *ed, } } -void BKE_sequence_iterator_begin(Editing *ed, SeqIterator *iter, const bool use_current_sequences) +void SEQ_iterator_begin(Editing *ed, SeqIterator *iter, const bool use_current_sequences) { memset(iter, 0, sizeof(*iter)); seq_array(ed, &iter->array, &iter->tot, use_current_sequences); @@ -120,7 +120,7 @@ void BKE_sequence_iterator_begin(Editing *ed, SeqIterator *iter, const bool use_ } } -void BKE_sequence_iterator_next(SeqIterator *iter) +void SEQ_iterator_next(SeqIterator *iter) { if (++iter->cur < iter->tot) { iter->seq = iter->array[iter->cur]; @@ -130,7 +130,7 @@ void BKE_sequence_iterator_next(SeqIterator *iter) } } -void BKE_sequence_iterator_end(SeqIterator *iter) +void SEQ_iterator_end(SeqIterator *iter) { if (iter->array) { MEM_freeN(iter->array); @@ -139,20 +139,20 @@ void BKE_sequence_iterator_end(SeqIterator *iter) iter->valid = 0; } -int BKE_sequencer_base_recursive_apply(ListBase *seqbase, - int (*apply_fn)(Sequence *seq, void *), - void *arg) +int SEQ_iterator_seqbase_recursive_apply(ListBase *seqbase, + int (*apply_fn)(Sequence *seq, void *), + void *arg) { Sequence *iseq; for (iseq = seqbase->first; iseq; iseq = iseq->next) { - if (BKE_sequencer_recursive_apply(iseq, apply_fn, arg) == -1) { + if (SEQ_iterator_recursive_apply(iseq, apply_fn, arg) == -1) { return -1; /* bail out */ } } return 1; } -int BKE_sequencer_recursive_apply(Sequence *seq, int (*apply_fn)(Sequence *, void *), void *arg) +int SEQ_iterator_recursive_apply(Sequence *seq, int (*apply_fn)(Sequence *, void *), void *arg) { int ret = apply_fn(seq, arg); @@ -161,7 +161,7 @@ int BKE_sequencer_recursive_apply(Sequence *seq, int (*apply_fn)(Sequence *, voi } if (ret && seq->seqbase.first) { - ret = BKE_sequencer_base_recursive_apply(&seq->seqbase, apply_fn, arg); + ret = SEQ_iterator_seqbase_recursive_apply(&seq->seqbase, apply_fn, arg); } return ret; diff --git a/source/blender/sequencer/intern/modifier.c b/source/blender/sequencer/intern/modifier.c index 2c37ecf1910..99fa228e7a5 100644 --- a/source/blender/sequencer/intern/modifier.c +++ b/source/blender/sequencer/intern/modifier.c @@ -1316,7 +1316,7 @@ static void sequence_modifier_type_info_init(void) #undef INIT_TYPE } -const SequenceModifierTypeInfo *BKE_sequence_modifier_type_info_get(int type) +const SequenceModifierTypeInfo *SEQ_modifier_type_info_get(int type) { if (!modifierTypesInit) { sequence_modifier_type_info_init(); @@ -1326,10 +1326,10 @@ const SequenceModifierTypeInfo *BKE_sequence_modifier_type_info_get(int type) return modifiersTypes[type]; } -SequenceModifierData *BKE_sequence_modifier_new(Sequence *seq, const char *name, int type) +SequenceModifierData *SEQ_modifier_new(Sequence *seq, const char *name, int type) { SequenceModifierData *smd; - const SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(type); + const SequenceModifierTypeInfo *smti = SEQ_modifier_type_info_get(type); smd = MEM_callocN(smti->struct_size, "sequence modifier"); @@ -1345,7 +1345,7 @@ SequenceModifierData *BKE_sequence_modifier_new(Sequence *seq, const char *name, BLI_addtail(&seq->modifiers, smd); - BKE_sequence_modifier_unique_name(seq, smd); + SEQ_modifier_unique_name(seq, smd); if (smti->init_data) { smti->init_data(smd); @@ -1354,33 +1354,33 @@ SequenceModifierData *BKE_sequence_modifier_new(Sequence *seq, const char *name, return smd; } -bool BKE_sequence_modifier_remove(Sequence *seq, SequenceModifierData *smd) +bool SEQ_modifier_remove(Sequence *seq, SequenceModifierData *smd) { if (BLI_findindex(&seq->modifiers, smd) == -1) { return false; } BLI_remlink(&seq->modifiers, smd); - BKE_sequence_modifier_free(smd); + SEQ_modifier_free(smd); return true; } -void BKE_sequence_modifier_clear(Sequence *seq) +void SEQ_modifier_clear(Sequence *seq) { SequenceModifierData *smd, *smd_next; for (smd = seq->modifiers.first; smd; smd = smd_next) { smd_next = smd->next; - BKE_sequence_modifier_free(smd); + SEQ_modifier_free(smd); } BLI_listbase_clear(&seq->modifiers); } -void BKE_sequence_modifier_free(SequenceModifierData *smd) +void SEQ_modifier_free(SequenceModifierData *smd) { - const SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(smd->type); + const SequenceModifierTypeInfo *smti = SEQ_modifier_type_info_get(smd->type); if (smti && smti->free_data) { smti->free_data(smd); @@ -1389,9 +1389,9 @@ void BKE_sequence_modifier_free(SequenceModifierData *smd) MEM_freeN(smd); } -void BKE_sequence_modifier_unique_name(Sequence *seq, SequenceModifierData *smd) +void SEQ_modifier_unique_name(Sequence *seq, SequenceModifierData *smd) { - const SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(smd->type); + const SequenceModifierTypeInfo *smti = SEQ_modifier_type_info_get(smd->type); BLI_uniquename(&seq->modifiers, smd, @@ -1401,15 +1401,15 @@ void BKE_sequence_modifier_unique_name(Sequence *seq, SequenceModifierData *smd) sizeof(smd->name)); } -SequenceModifierData *BKE_sequence_modifier_find_by_name(Sequence *seq, const char *name) +SequenceModifierData *SEQ_modifier_find_by_name(Sequence *seq, const char *name) { return BLI_findstring(&(seq->modifiers), name, offsetof(SequenceModifierData, name)); } -ImBuf *BKE_sequence_modifier_apply_stack(const SeqRenderData *context, - Sequence *seq, - ImBuf *ibuf, - int timeline_frame) +ImBuf *SEQ_modifier_apply_stack(const SeqRenderData *context, + Sequence *seq, + ImBuf *ibuf, + int timeline_frame) { SequenceModifierData *smd; ImBuf *processed_ibuf = ibuf; @@ -1420,7 +1420,7 @@ ImBuf *BKE_sequence_modifier_apply_stack(const SeqRenderData *context, } for (smd = seq->modifiers.first; smd; smd = smd->next) { - const SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(smd->type); + const SequenceModifierTypeInfo *smti = SEQ_modifier_type_info_get(smd->type); /* could happen if modifier is being removed or not exists in current version of blender */ if (!smti) { @@ -1463,13 +1463,13 @@ ImBuf *BKE_sequence_modifier_apply_stack(const SeqRenderData *context, return processed_ibuf; } -void BKE_sequence_modifier_list_copy(Sequence *seqn, Sequence *seq) +void SEQ_modifier_list_copy(Sequence *seqn, Sequence *seq) { SequenceModifierData *smd; for (smd = seq->modifiers.first; smd; smd = smd->next) { SequenceModifierData *smdn; - const SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(smd->type); + const SequenceModifierTypeInfo *smti = SEQ_modifier_type_info_get(smd->type); smdn = MEM_dupallocN(smd); @@ -1482,7 +1482,7 @@ void BKE_sequence_modifier_list_copy(Sequence *seqn, Sequence *seq) } } -int BKE_sequence_supports_modifiers(Sequence *seq) +int SEQ_sequence_supports_modifiers(Sequence *seq) { return !ELEM(seq->type, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SOUND_HD); } @@ -1493,10 +1493,10 @@ int BKE_sequence_supports_modifiers(Sequence *seq) /** \name .blend File I/O * \{ */ -void BKE_sequence_modifier_blend_write(BlendWriter *writer, ListBase *modbase) +void SEQ_modifier_blend_write(BlendWriter *writer, ListBase *modbase) { LISTBASE_FOREACH (SequenceModifierData *, smd, modbase) { - const SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(smd->type); + const SequenceModifierTypeInfo *smti = SEQ_modifier_type_info_get(smd->type); if (smti) { BLO_write_struct_by_name(writer, smti->struct_name, smd); @@ -1518,7 +1518,7 @@ void BKE_sequence_modifier_blend_write(BlendWriter *writer, ListBase *modbase) } } -void BKE_sequence_modifier_blend_read_data(BlendDataReader *reader, ListBase *lb) +void SEQ_modifier_blend_read_data(BlendDataReader *reader, ListBase *lb) { BLO_read_list(reader, lb); @@ -1540,7 +1540,7 @@ void BKE_sequence_modifier_blend_read_data(BlendDataReader *reader, ListBase *lb } } -void BKE_sequence_modifier_blend_read_lib(BlendLibReader *reader, Scene *scene, ListBase *lb) +void SEQ_modifier_blend_read_lib(BlendLibReader *reader, Scene *scene, ListBase *lb) { LISTBASE_FOREACH (SequenceModifierData *, smd, lb) { if (smd->mask_id) { diff --git a/source/blender/sequencer/intern/prefetch.c b/source/blender/sequencer/intern/prefetch.c index 98b83651ffc..5d769a18a19 100644 --- a/source/blender/sequencer/intern/prefetch.c +++ b/source/blender/sequencer/intern/prefetch.c @@ -118,7 +118,7 @@ static PrefetchJob *seq_prefetch_job_get(Scene *scene) return NULL; } -bool BKE_sequencer_prefetch_job_is_running(Scene *scene) +bool seq_prefetch_job_is_running(Scene *scene) { PrefetchJob *pfjob = seq_prefetch_job_get(scene); @@ -159,14 +159,14 @@ static Sequence *sequencer_prefetch_get_original_sequence(Sequence *seq, ListBas } /* for cache context swapping */ -Sequence *BKE_sequencer_prefetch_get_original_sequence(Sequence *seq, Scene *scene) +Sequence *seq_prefetch_get_original_sequence(Sequence *seq, Scene *scene) { Editing *ed = scene->ed; return sequencer_prefetch_get_original_sequence(seq, &ed->seqbase); } /* for cache context swapping */ -SeqRenderData *BKE_sequencer_prefetch_get_original_context(const SeqRenderData *context) +SeqRenderData *seq_prefetch_get_original_context(const SeqRenderData *context) { PrefetchJob *pfjob = seq_prefetch_job_get(context->scene); @@ -177,11 +177,11 @@ static bool seq_prefetch_is_cache_full(Scene *scene) { PrefetchJob *pfjob = seq_prefetch_job_get(scene); - if (!BKE_sequencer_cache_is_full(pfjob->scene)) { + if (!seq_cache_is_full(pfjob->scene)) { return false; } - return BKE_sequencer_cache_recycle_item(pfjob->scene) == false; + return seq_cache_recycle_item(pfjob->scene) == false; } static float seq_prefetch_cfra(PrefetchJob *pfjob) @@ -193,7 +193,7 @@ static AnimationEvalContext seq_prefetch_anim_eval_context(PrefetchJob *pfjob) return BKE_animsys_eval_context_construct(pfjob->depsgraph, seq_prefetch_cfra(pfjob)); } -void BKE_sequencer_prefetch_get_time_range(Scene *scene, int *start, int *end) +void seq_prefetch_get_time_range(Scene *scene, int *start, int *end) { PrefetchJob *pfjob = seq_prefetch_job_get(scene); @@ -256,18 +256,18 @@ static void seq_prefetch_update_area(PrefetchJob *pfjob) } } -void BKE_sequencer_prefetch_stop_all(void) +void SEQ_prefetch_stop_all(void) { /*TODO(Richard): Use wm_jobs for prefetch, or pass main. */ for (Scene *scene = G.main->scenes.first; scene; scene = scene->id.next) { - BKE_sequencer_prefetch_stop(scene); + SEQ_prefetch_stop(scene); } } /* Use also to update scene and context changes * This function should almost always be called by cache invalidation, not directly. */ -void BKE_sequencer_prefetch_stop(Scene *scene) +void SEQ_prefetch_stop(Scene *scene) { PrefetchJob *pfjob; pfjob = seq_prefetch_job_get(scene); @@ -338,14 +338,14 @@ static void seq_prefetch_resume(Scene *scene) } } -void BKE_sequencer_prefetch_free(Scene *scene) +void seq_prefetch_free(Scene *scene) { PrefetchJob *pfjob = seq_prefetch_job_get(scene); if (!pfjob) { return; } - BKE_sequencer_prefetch_stop(scene); + SEQ_prefetch_stop(scene); BLI_threadpool_remove(&pfjob->threads, pfjob); BLI_threadpool_end(&pfjob->threads); @@ -372,28 +372,28 @@ static bool seq_prefetch_do_skip_frame(Scene *scene) if (seq_arr[i]->type == SEQ_TYPE_SCENE && (seq_arr[i]->flag & SEQ_SCENE_STRIPS) == 0) { int cached_types = 0; - ibuf = BKE_sequencer_cache_get(ctx, seq_arr[i], cfra, SEQ_CACHE_STORE_FINAL_OUT, false); + ibuf = seq_cache_get(ctx, seq_arr[i], cfra, SEQ_CACHE_STORE_FINAL_OUT, false); if (ibuf != NULL) { cached_types |= SEQ_CACHE_STORE_FINAL_OUT; IMB_freeImBuf(ibuf); ibuf = NULL; } - ibuf = BKE_sequencer_cache_get(ctx, seq_arr[i], cfra, SEQ_CACHE_STORE_FINAL_OUT, false); + ibuf = seq_cache_get(ctx, seq_arr[i], cfra, SEQ_CACHE_STORE_FINAL_OUT, false); if (ibuf != NULL) { cached_types |= SEQ_CACHE_STORE_COMPOSITE; IMB_freeImBuf(ibuf); ibuf = NULL; } - ibuf = BKE_sequencer_cache_get(ctx, seq_arr[i], cfra, SEQ_CACHE_STORE_PREPROCESSED, false); + ibuf = seq_cache_get(ctx, seq_arr[i], cfra, SEQ_CACHE_STORE_PREPROCESSED, false); if (ibuf != NULL) { cached_types |= SEQ_CACHE_STORE_PREPROCESSED; IMB_freeImBuf(ibuf); ibuf = NULL; } - ibuf = BKE_sequencer_cache_get(ctx, seq_arr[i], cfra, SEQ_CACHE_STORE_RAW, false); + ibuf = seq_cache_get(ctx, seq_arr[i], cfra, SEQ_CACHE_STORE_RAW, false); if (ibuf != NULL) { cached_types |= SEQ_CACHE_STORE_RAW; IMB_freeImBuf(ibuf); @@ -463,8 +463,7 @@ static void *seq_prefetch_frames(void *job) } ImBuf *ibuf = SEQ_render_give_ibuf(&pfjob->context_cpy, seq_prefetch_cfra(pfjob), 0); - BKE_sequencer_cache_free_temp_cache( - pfjob->scene, pfjob->context.task_id, seq_prefetch_cfra(pfjob)); + seq_cache_free_temp_cache(pfjob->scene, pfjob->context.task_id, seq_prefetch_cfra(pfjob)); IMB_freeImBuf(ibuf); /* Suspend thread if there is nothing to be prefetched. */ @@ -484,15 +483,14 @@ static void *seq_prefetch_frames(void *job) pfjob->num_frames_prefetched++; } - BKE_sequencer_cache_free_temp_cache( - pfjob->scene, pfjob->context.task_id, seq_prefetch_cfra(pfjob)); + seq_cache_free_temp_cache(pfjob->scene, pfjob->context.task_id, seq_prefetch_cfra(pfjob)); pfjob->running = false; pfjob->scene_eval->ed->prefetch_job = NULL; return NULL; } -static PrefetchJob *seq_prefetch_start(const SeqRenderData *context, float cfra) +static PrefetchJob *seq_prefetch_start_ex(const SeqRenderData *context, float cfra) { PrefetchJob *pfjob = seq_prefetch_job_get(context->scene); @@ -529,7 +527,7 @@ static PrefetchJob *seq_prefetch_start(const SeqRenderData *context, float cfra) } /* Start or resume prefetching*/ -void BKE_sequencer_prefetch_start(const SeqRenderData *context, float timeline_frame, float cost) +void seq_prefetch_start(const SeqRenderData *context, float timeline_frame, float cost) { Scene *scene = context->scene; Editing *ed = scene->ed; @@ -538,7 +536,7 @@ void BKE_sequencer_prefetch_start(const SeqRenderData *context, float timeline_f if (!context->is_prefetch_render && !context->is_proxy_render) { bool playing = seq_prefetch_is_playing(context->bmain); bool scrubbing = seq_prefetch_is_scrubbing(context->bmain); - bool running = BKE_sequencer_prefetch_job_is_running(scene); + bool running = seq_prefetch_job_is_running(scene); seq_prefetch_resume(scene); /* conditions to start: * prefetch enabled, prefetch not running, not scrubbing, @@ -549,16 +547,16 @@ void BKE_sequencer_prefetch_start(const SeqRenderData *context, float timeline_f !(playing && cost > 0.9) && ed->cache_flag & SEQ_CACHE_ALL_TYPES && has_strips && !G.is_rendering && !G.moving) { - seq_prefetch_start(context, timeline_frame); + seq_prefetch_start_ex(context, timeline_frame); } } } -bool BKE_sequencer_prefetch_need_redraw(Main *bmain, Scene *scene) +bool SEQ_prefetch_need_redraw(Main *bmain, Scene *scene) { bool playing = seq_prefetch_is_playing(bmain); bool scrubbing = seq_prefetch_is_scrubbing(bmain); - bool running = BKE_sequencer_prefetch_job_is_running(scene); + bool running = seq_prefetch_job_is_running(scene); bool suspended = seq_prefetch_job_is_waiting(scene); /* force redraw, when prefetching and using cache view. */ diff --git a/source/blender/sequencer/intern/prefetch.h b/source/blender/sequencer/intern/prefetch.h index 1633ee297f8..44aedb537ae 100644 --- a/source/blender/sequencer/intern/prefetch.h +++ b/source/blender/sequencer/intern/prefetch.h @@ -35,16 +35,12 @@ struct Sequence; } #endif -void BKE_sequencer_prefetch_start(const struct SeqRenderData *context, - float timeline_frame, - float cost); -void BKE_sequencer_prefetch_free(struct Scene *scene); -bool BKE_sequencer_prefetch_job_is_running(struct Scene *scene); -void BKE_sequencer_prefetch_get_time_range(struct Scene *scene, int *start, int *end); -struct SeqRenderData *BKE_sequencer_prefetch_get_original_context( - const struct SeqRenderData *context); -struct Sequence *BKE_sequencer_prefetch_get_original_sequence(struct Sequence *seq, - struct Scene *scene); +void seq_prefetch_start(const struct SeqRenderData *context, float timeline_frame, float cost); +void seq_prefetch_free(struct Scene *scene); +bool seq_prefetch_job_is_running(struct Scene *scene); +void seq_prefetch_get_time_range(struct Scene *scene, int *start, int *end); +struct SeqRenderData *seq_prefetch_get_original_context(const struct SeqRenderData *context); +struct Sequence *seq_prefetch_get_original_sequence(struct Sequence *seq, struct Scene *scene); #ifdef __cplusplus } diff --git a/source/blender/sequencer/intern/proxy.c b/source/blender/sequencer/intern/proxy.c index ff65216d987..72dc9708ccb 100644 --- a/source/blender/sequencer/intern/proxy.c +++ b/source/blender/sequencer/intern/proxy.c @@ -422,7 +422,7 @@ bool SEQ_proxy_rebuild_context(Main *bmain, context = MEM_callocN(sizeof(SeqIndexBuildContext), "seq proxy rebuild context"); - nseq = BKE_sequence_dupli_recursive(scene, scene, NULL, seq, 0); + nseq = SEQ_sequence_dupli_recursive(scene, scene, NULL, seq, 0); context->tc_flags = nseq->strip->proxy->build_tc_flags; context->size_flags = nseq->strip->proxy->build_size_flags; diff --git a/source/blender/sequencer/intern/render.c b/source/blender/sequencer/intern/render.c index 2e757a06751..84f2a6df647 100644 --- a/source/blender/sequencer/intern/render.c +++ b/source/blender/sequencer/intern/render.c @@ -461,9 +461,9 @@ static bool sequencer_use_crop(const Sequence *seq) return false; } -static bool BKE_sequencer_input_have_to_preprocess(const SeqRenderData *context, - Sequence *seq, - float UNUSED(timeline_frame)) +static bool seq_input_have_to_preprocess(const SeqRenderData *context, + Sequence *seq, + float UNUSED(timeline_frame)) { float mul; @@ -717,8 +717,7 @@ static ImBuf *input_preprocess(const SeqRenderData *context, } if (seq->modifiers.first) { - ImBuf *ibuf_new = BKE_sequence_modifier_apply_stack( - context, seq, preprocessed_ibuf, timeline_frame); + ImBuf *ibuf_new = SEQ_modifier_apply_stack(context, seq, preprocessed_ibuf, timeline_frame); if (ibuf_new != preprocessed_ibuf) { IMB_metadata_copy(ibuf_new, preprocessed_ibuf); @@ -748,8 +747,7 @@ static ImBuf *seq_render_preprocess_ibuf(const SeqRenderData *context, /* Proxies are not stored in cache. */ if (!is_proxy_image) { - BKE_sequencer_cache_put( - context, seq, timeline_frame, SEQ_CACHE_STORE_RAW, ibuf, cost, false); + seq_cache_put(context, seq, timeline_frame, SEQ_CACHE_STORE_RAW, ibuf, cost, false); } /* Reset timer so we can get partial render time. */ @@ -758,8 +756,7 @@ static ImBuf *seq_render_preprocess_ibuf(const SeqRenderData *context, } float cost = seq_estimate_render_cost_end(context->scene, begin); - BKE_sequencer_cache_put( - context, seq, timeline_frame, SEQ_CACHE_STORE_PREPROCESSED, ibuf, cost, false); + seq_cache_put(context, seq, timeline_frame, SEQ_CACHE_STORE_PREPROCESSED, ibuf, cost, false); return ibuf; } @@ -868,7 +865,7 @@ static ImBuf *seq_render_effect_strip_impl(const SeqRenderData *context, float fac, facf; int early_out; int i; - struct SeqEffectHandle sh = BKE_sequence_get_effect(seq); + struct SeqEffectHandle sh = SEQ_effect_handle_get(seq); FCurve *fcu = NULL; ImBuf *ibuf[3]; Sequence *input[3]; @@ -910,8 +907,7 @@ static ImBuf *seq_render_effect_strip_impl(const SeqRenderData *context, for (i = 0; i < 3; i++) { /* Speed effect requires time remapping of `timeline_frame` for input(s). */ if (input[0] && seq->type == SEQ_TYPE_SPEED) { - float target_frame = BKE_sequencer_speed_effect_target_frame_get( - context, seq, timeline_frame, i); + float target_frame = seq_speed_effect_target_frame_get(context, seq, timeline_frame, i); ibuf[i] = seq_render_strip(context, state, input[0], target_frame); } else { /* Other effects. */ @@ -921,7 +917,7 @@ static ImBuf *seq_render_effect_strip_impl(const SeqRenderData *context, } } - if (ibuf[0] && (ibuf[1] || BKE_sequence_effect_get_num_inputs(seq->type) == 1)) { + if (ibuf[0] && (ibuf[1] || SEQ_effect_get_num_inputs(seq->type) == 1)) { if (sh.multithreaded) { out = seq_render_effect_execute_threaded( &sh, context, seq, timeline_frame, fac, facf, ibuf[0], ibuf[1], ibuf[2]); @@ -1628,7 +1624,7 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context, } if (view_id != context->view_id) { - BKE_sequencer_cache_put( + seq_cache_put( &localcontext, seq, timeline_frame, SEQ_CACHE_STORE_RAW, ibufs_arr[view_id], 0, false); } @@ -1677,7 +1673,7 @@ static ImBuf *do_render_strip_seqbase(const SeqRenderData *context, ListBase *seqbase = NULL; int offset; - seqbase = BKE_sequence_seqbase_get(seq, &offset); + seqbase = SEQ_get_seqbase_from_sequence(seq, &offset); if (seqbase && !BLI_listbase_is_empty(seqbase)) { @@ -1806,15 +1802,14 @@ ImBuf *seq_render_strip(const SeqRenderData *context, clock_t begin = seq_estimate_render_cost_begin(); - ibuf = BKE_sequencer_cache_get( - context, seq, timeline_frame, SEQ_CACHE_STORE_PREPROCESSED, false); + ibuf = seq_cache_get(context, seq, timeline_frame, SEQ_CACHE_STORE_PREPROCESSED, false); if (ibuf != NULL) { return ibuf; } /* Proxies are not stored in cache. */ if (!SEQ_can_use_proxy(seq, SEQ_rendersize_to_proxysize(context->preview_render_size))) { - ibuf = BKE_sequencer_cache_get(context, seq, timeline_frame, SEQ_CACHE_STORE_RAW, false); + ibuf = seq_cache_get(context, seq, timeline_frame, SEQ_CACHE_STORE_RAW, false); } if (ibuf == NULL) { @@ -1822,7 +1817,7 @@ ImBuf *seq_render_strip(const SeqRenderData *context, } if (ibuf) { - use_preprocess = BKE_sequencer_input_have_to_preprocess(context, seq, timeline_frame); + use_preprocess = seq_input_have_to_preprocess(context, seq, timeline_frame); ibuf = seq_render_preprocess_ibuf( context, seq, ibuf, timeline_frame, begin, use_preprocess, is_proxy_image); } @@ -1851,7 +1846,7 @@ static bool seq_must_swap_input_in_blend_mode(Sequence *seq) static int seq_get_early_out_for_blend_mode(Sequence *seq) { - struct SeqEffectHandle sh = BKE_sequence_get_blend(seq); + struct SeqEffectHandle sh = seq_effect_get_sequence_blend(seq); float facf = seq->blend_opacity / 100.0f; int early_out = sh.early_out(seq, facf, facf); @@ -1874,7 +1869,7 @@ static ImBuf *seq_render_strip_stack_apply_effect( const SeqRenderData *context, Sequence *seq, float timeline_frame, ImBuf *ibuf1, ImBuf *ibuf2) { ImBuf *out; - struct SeqEffectHandle sh = BKE_sequence_get_blend(seq); + struct SeqEffectHandle sh = seq_effect_get_sequence_blend(seq); float facf = seq->blend_opacity / 100.0f; int swap_input = seq_must_swap_input_in_blend_mode(seq); @@ -1922,7 +1917,7 @@ static ImBuf *seq_render_strip_stack(const SeqRenderData *context, int early_out; Sequence *seq = seq_arr[i]; - out = BKE_sequencer_cache_get(context, seq, timeline_frame, SEQ_CACHE_STORE_COMPOSITE, false); + out = seq_cache_get(context, seq, timeline_frame, SEQ_CACHE_STORE_COMPOSITE, false); if (out) { break; @@ -1954,7 +1949,7 @@ static ImBuf *seq_render_strip_stack(const SeqRenderData *context, out = seq_render_strip_stack_apply_effect(context, seq, timeline_frame, ibuf1, ibuf2); float cost = seq_estimate_render_cost_end(context->scene, begin); - BKE_sequencer_cache_put( + seq_cache_put( context, seq_arr[i], timeline_frame, SEQ_CACHE_STORE_COMPOSITE, out, cost, false); IMB_freeImBuf(ibuf1); @@ -1983,7 +1978,7 @@ static ImBuf *seq_render_strip_stack(const SeqRenderData *context, } float cost = seq_estimate_render_cost_end(context->scene, begin); - BKE_sequencer_cache_put( + seq_cache_put( context, seq_arr[i], timeline_frame, SEQ_CACHE_STORE_COMPOSITE, out, cost, false); } @@ -1998,7 +1993,7 @@ static ImBuf *seq_render_strip_stack(const SeqRenderData *context, ImBuf *SEQ_render_give_ibuf(const SeqRenderData *context, float timeline_frame, int chanshown) { Scene *scene = context->scene; - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); ListBase *seqbasep; if (ed == NULL) { @@ -2023,11 +2018,11 @@ ImBuf *SEQ_render_give_ibuf(const SeqRenderData *context, float timeline_frame, count = seq_get_shown_sequences(seqbasep, timeline_frame, chanshown, seq_arr); if (count) { - out = BKE_sequencer_cache_get( + out = seq_cache_get( context, seq_arr[count - 1], timeline_frame, SEQ_CACHE_STORE_FINAL_OUT, false); } - BKE_sequencer_cache_free_temp_cache(context->scene, context->task_id, timeline_frame); + seq_cache_free_temp_cache(context->scene, context->task_id, timeline_frame); clock_t begin = seq_estimate_render_cost_begin(); float cost = 0; @@ -2038,27 +2033,27 @@ ImBuf *SEQ_render_give_ibuf(const SeqRenderData *context, float timeline_frame, cost = seq_estimate_render_cost_end(context->scene, begin); if (context->is_prefetch_render) { - BKE_sequencer_cache_put(context, - seq_arr[count - 1], - timeline_frame, - SEQ_CACHE_STORE_FINAL_OUT, - out, - cost, - false); + seq_cache_put(context, + seq_arr[count - 1], + timeline_frame, + SEQ_CACHE_STORE_FINAL_OUT, + out, + cost, + false); } else { - BKE_sequencer_cache_put_if_possible(context, - seq_arr[count - 1], - timeline_frame, - SEQ_CACHE_STORE_FINAL_OUT, - out, - cost, - false); + seq_cache_put_if_possible(context, + seq_arr[count - 1], + timeline_frame, + SEQ_CACHE_STORE_FINAL_OUT, + out, + cost, + false); } BLI_mutex_unlock(&seq_render_mutex); } - BKE_sequencer_prefetch_start(context, timeline_frame, cost); + seq_prefetch_start(context, timeline_frame, cost); return out; } diff --git a/source/blender/sequencer/intern/sequencer.c b/source/blender/sequencer/intern/sequencer.c index 87b608ef141..51495e7bf02 100644 --- a/source/blender/sequencer/intern/sequencer.c +++ b/source/blender/sequencer/intern/sequencer.c @@ -104,7 +104,7 @@ static void seq_free_strip(Strip *strip) MEM_freeN(strip); } -Sequence *BKE_sequence_alloc(ListBase *lb, int timeline_frame, int machine, int type) +Sequence *SEQ_sequence_alloc(ListBase *lb, int timeline_frame, int machine, int type) { Sequence *seq; @@ -129,13 +129,13 @@ Sequence *BKE_sequence_alloc(ListBase *lb, int timeline_frame, int machine, int seq->stereo3d_format = MEM_callocN(sizeof(Stereo3dFormat), "Sequence Stereo Format"); seq->cache_flag = SEQ_CACHE_STORE_RAW | SEQ_CACHE_STORE_PREPROCESSED | SEQ_CACHE_STORE_COMPOSITE; - BKE_sequence_session_uuid_generate(seq); + SEQ_relations_session_uuid_generate(seq); return seq; } /* only give option to skip cache locally (static func) */ -static void BKE_sequence_free_ex(Scene *scene, +static void seq_sequence_free_ex(Scene *scene, Sequence *seq, const bool do_cache, const bool do_id_user, @@ -145,10 +145,10 @@ static void BKE_sequence_free_ex(Scene *scene, seq_free_strip(seq->strip); } - BKE_sequence_free_anim(seq); + SEQ_relations_sequence_free_anim(seq); if (seq->type & SEQ_TYPE_EFFECT) { - struct SeqEffectHandle sh = BKE_sequence_get_effect(seq); + struct SeqEffectHandle sh = SEQ_effect_handle_get(seq); sh.free(seq, do_id_user); } @@ -186,7 +186,7 @@ static void BKE_sequence_free_ex(Scene *scene, } /* free modifiers */ - BKE_sequence_modifier_clear(seq); + SEQ_modifier_clear(seq); /* free cached data used by this strip, * also invalidate cache for all dependent sequences @@ -194,20 +194,20 @@ static void BKE_sequence_free_ex(Scene *scene, * be _very_ careful here, invalidating cache loops over the scene sequences and * assumes the listbase is valid for all strips, * this may not be the case if lists are being freed. - * this is optional BKE_sequence_invalidate_cache + * this is optional SEQ_relations_invalidate_cache */ if (do_cache) { if (scene) { - BKE_sequence_invalidate_cache_raw(scene, seq); + SEQ_relations_invalidate_cache_raw(scene, seq); } } MEM_freeN(seq); } -void BKE_sequence_free(Scene *scene, Sequence *seq, const bool do_clean_animdata) +void SEQ_sequence_free(Scene *scene, Sequence *seq, const bool do_clean_animdata) { - BKE_sequence_free_ex(scene, seq, true, true, do_clean_animdata); + seq_sequence_free_ex(scene, seq, true, true, do_clean_animdata); } /* cache must be freed before calling this function @@ -221,18 +221,18 @@ void seq_free_sequence_recurse(Scene *scene, Sequence *seq, const bool do_id_use seq_free_sequence_recurse(scene, iseq, do_id_user); } - BKE_sequence_free_ex(scene, seq, false, do_id_user, true); + seq_sequence_free_ex(scene, seq, false, do_id_user, true); } -Editing *BKE_sequencer_editing_get(Scene *scene, bool alloc) +Editing *SEQ_editing_get(Scene *scene, bool alloc) { if (alloc) { - BKE_sequencer_editing_ensure(scene); + SEQ_editing_ensure(scene); } return scene->ed; } -Editing *BKE_sequencer_editing_ensure(Scene *scene) +Editing *SEQ_editing_ensure(Scene *scene) { if (scene->ed == NULL) { Editing *ed; @@ -249,7 +249,7 @@ Editing *BKE_sequencer_editing_ensure(Scene *scene) return scene->ed; } -void BKE_sequencer_editing_free(Scene *scene, const bool do_id_user) +void SEQ_editing_free(Scene *scene, const bool do_id_user) { Editing *ed = scene->ed; Sequence *seq; @@ -258,12 +258,12 @@ void BKE_sequencer_editing_free(Scene *scene, const bool do_id_user) return; } - BKE_sequencer_prefetch_free(scene); - BKE_sequencer_cache_destruct(scene); + seq_prefetch_free(scene); + seq_cache_destruct(scene); SEQ_ALL_BEGIN (ed, seq) { /* handle cache freeing above */ - BKE_sequence_free_ex(scene, seq, false, do_id_user, false); + seq_sequence_free_ex(scene, seq, false, do_id_user, false); } SEQ_ALL_END; @@ -356,7 +356,7 @@ static Sequence *seq_dupli(const Scene *scene_src, Sequence *seqn = MEM_dupallocN(seq); if ((flag & LIB_ID_CREATE_NO_MAIN) == 0) { - BKE_sequence_session_uuid_generate(seq); + SEQ_relations_session_uuid_generate(seq); } seq->tmp = seqn; @@ -386,7 +386,7 @@ static Sequence *seq_dupli(const Scene *scene_src, if (seqn->modifiers.first) { BLI_listbase_clear(&seqn->modifiers); - BKE_sequence_modifier_list_copy(seqn, seq); + SEQ_modifier_list_copy(seqn, seq); } if (seq->type == SEQ_TYPE_META) { @@ -424,7 +424,7 @@ static Sequence *seq_dupli(const Scene *scene_src, } else if (seq->type & SEQ_TYPE_EFFECT) { struct SeqEffectHandle sh; - sh = BKE_sequence_get_effect(seq); + sh = SEQ_effect_handle_get(seq); if (sh.copy) { sh.copy(seqn, seq, flag); } @@ -448,11 +448,11 @@ static Sequence *seq_dupli(const Scene *scene_src, if (scene_src == scene_dst) { if (dupe_flag & SEQ_DUPE_UNIQUE_NAME) { - BKE_sequence_base_unique_name_recursive(&scene_dst->ed->seqbase, seqn); + SEQ_sequence_base_unique_name_recursive(&scene_dst->ed->seqbase, seqn); } if (dupe_flag & SEQ_DUPE_ANIM) { - BKE_sequencer_dupe_animdata(scene_dst, seq->name + 2, seqn->name + 2); + SEQ_dupe_animdata(scene_dst, seq->name + 2, seqn->name + 2); } } @@ -479,7 +479,7 @@ static Sequence *sequence_dupli_recursive_do(const Scene *scene_src, return seqn; } -Sequence *BKE_sequence_dupli_recursive( +Sequence *SEQ_sequence_dupli_recursive( const Scene *scene_src, Scene *scene_dst, ListBase *new_seq_list, Sequence *seq, int dupe_flag) { Sequence *seqn = sequence_dupli_recursive_do(scene_src, scene_dst, new_seq_list, seq, dupe_flag); @@ -490,7 +490,7 @@ Sequence *BKE_sequence_dupli_recursive( return seqn; } -void BKE_sequence_base_dupli_recursive(const Scene *scene_src, +void SEQ_sequence_base_dupli_recursive(const Scene *scene_src, Scene *scene_dst, ListBase *nseqbase, const ListBase *seqbase, @@ -499,7 +499,7 @@ void BKE_sequence_base_dupli_recursive(const Scene *scene_src, { Sequence *seq; Sequence *seqn = NULL; - Sequence *last_seq = BKE_sequencer_active_get((Scene *)scene_src); + Sequence *last_seq = SEQ_select_active_get((Scene *)scene_src); /* always include meta's strips */ int dupe_flag_recursive = dupe_flag | SEQ_DUPE_ALL | SEQ_DUPE_IS_RECURSIVE_CALL; @@ -514,13 +514,13 @@ void BKE_sequence_base_dupli_recursive(const Scene *scene_src, } if (seq->type == SEQ_TYPE_META) { - BKE_sequence_base_dupli_recursive( + SEQ_sequence_base_dupli_recursive( scene_src, scene_dst, &seqn->seqbase, &seq->seqbase, dupe_flag_recursive, flag); } if (dupe_flag & SEQ_DUPE_CONTEXT) { if (seq == last_seq) { - BKE_sequencer_active_set(scene_dst, seqn); + SEQ_select_active_set(scene_dst, seqn); } } } @@ -551,7 +551,7 @@ static size_t sequencer_rna_path_prefix(char str[SEQ_RNAPATH_MAXSTR], const char } /* XXX - hackish function needed for transforming strips! TODO - have some better solution */ -void BKE_sequencer_offset_animdata(Scene *scene, Sequence *seq, int ofs) +void SEQ_offset_animdata(Scene *scene, Sequence *seq, int ofs) { char str[SEQ_RNAPATH_MAXSTR]; size_t str_len; @@ -586,7 +586,7 @@ void BKE_sequencer_offset_animdata(Scene *scene, Sequence *seq, int ofs) DEG_id_tag_update(&scene->adt->action->id, ID_RECALC_ANIMATION); } -void BKE_sequencer_dupe_animdata(Scene *scene, const char *name_src, const char *name_dst) +void SEQ_dupe_animdata(Scene *scene, const char *name_src, const char *name_dst) { char str_from[SEQ_RNAPATH_MAXSTR]; size_t str_from_len; diff --git a/source/blender/sequencer/intern/sound.c b/source/blender/sequencer/intern/sound.c index 9549938abee..f62142d0112 100644 --- a/source/blender/sequencer/intern/sound.c +++ b/source/blender/sequencer/intern/sound.c @@ -40,14 +40,12 @@ #include "strip_time.h" -void BKE_sequence_sound_init(Scene *scene, Sequence *seq); - -void BKE_sequence_sound_init(Scene *scene, Sequence *seq) +static void seq_sound_init(Scene *scene, Sequence *seq) { if (seq->type == SEQ_TYPE_META) { Sequence *seq_child; for (seq_child = seq->seqbase.first; seq_child; seq_child = seq_child->next) { - BKE_sequence_sound_init(scene, seq_child); + seq_sound_init(scene, seq_child); } } else { @@ -70,7 +68,7 @@ static bool sequencer_refresh_sound_length_recursive(Main *bmain, Scene *scene, for (seq = seqbase->first; seq; seq = seq->next) { if (seq->type == SEQ_TYPE_META) { if (sequencer_refresh_sound_length_recursive(bmain, scene, &seq->seqbase)) { - BKE_sequence_calc(scene, seq); + SEQ_time_update_sequence(scene, seq); changed = true; } } @@ -86,7 +84,7 @@ static bool sequencer_refresh_sound_length_recursive(Main *bmain, Scene *scene, seq->endofs *= fac; seq->start += (old - seq->startofs); /* So that visual/"real" start frame does not change! */ - BKE_sequence_calc(scene, seq); + SEQ_time_update_sequence(scene, seq); changed = true; } } @@ -94,7 +92,7 @@ static bool sequencer_refresh_sound_length_recursive(Main *bmain, Scene *scene, } #endif -void BKE_sequencer_refresh_sound_length(Main *bmain, Scene *scene) +void SEQ_sound_update_length(Main *bmain, Scene *scene) { #ifdef WITH_AUDASPACE if (scene->ed) { @@ -105,7 +103,7 @@ void BKE_sequencer_refresh_sound_length(Main *bmain, Scene *scene) #endif } -void BKE_sequencer_update_sound_bounds_all(Scene *scene) +void SEQ_sound_update_bounds_all(Scene *scene) { Editing *ed = scene->ed; @@ -117,13 +115,13 @@ void BKE_sequencer_update_sound_bounds_all(Scene *scene) seq_update_sound_bounds_recursive(scene, seq); } else if (ELEM(seq->type, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SCENE)) { - BKE_sequencer_update_sound_bounds(scene, seq); + SEQ_sound_update_bounds(scene, seq); } } } } -void BKE_sequencer_update_sound_bounds(Scene *scene, Sequence *seq) +void SEQ_sound_update_bounds(Scene *scene, Sequence *seq) { if (seq->type == SEQ_TYPE_SCENE) { if (seq->scene && seq->scene_sound) { @@ -155,7 +153,7 @@ static void seq_update_sound_recursive(Scene *scene, ListBase *seqbasep, bSound } } -void BKE_sequencer_update_sound(Scene *scene, bSound *sound) +void SEQ_sound_update(Scene *scene, bSound *sound) { if (scene->ed) { seq_update_sound_recursive(scene, &scene->ed->seqbase, sound); diff --git a/source/blender/sequencer/intern/strip_add.c b/source/blender/sequencer/intern/strip_add.c index e56dcf888a7..4fe02b7fdd2 100644 --- a/source/blender/sequencer/intern/strip_add.c +++ b/source/blender/sequencer/intern/strip_add.c @@ -64,7 +64,7 @@ static void seq_load_apply(Main *bmain, Scene *scene, Sequence *seq, SeqLoadInfo if (seq) { BLI_strncpy_utf8(seq->name + 2, seq_load->name, sizeof(seq->name) - 2); BLI_utf8_invalid_strip(seq->name + 2, strlen(seq->name + 2)); - BKE_sequence_base_unique_name_recursive(&scene->ed->seqbase, seq); + SEQ_sequence_base_unique_name_recursive(&scene->ed->seqbase, seq); if (seq_load->flag & SEQ_LOAD_FRAME_ADVANCE) { seq_load->start_frame += (seq->enddisp - seq->startdisp); @@ -72,7 +72,7 @@ static void seq_load_apply(Main *bmain, Scene *scene, Sequence *seq, SeqLoadInfo if (seq_load->flag & SEQ_LOAD_REPLACE_SEL) { seq_load->flag |= SELECT; - BKE_sequencer_active_set(scene, seq); + SEQ_select_active_set(scene, seq); } if (seq_load->flag & SEQ_LOAD_SOUND_MONO) { @@ -94,13 +94,13 @@ static void seq_load_apply(Main *bmain, Scene *scene, Sequence *seq, SeqLoadInfo } /* NOTE: this function doesn't fill in image names */ -Sequence *BKE_sequencer_add_image_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo *seq_load) +Sequence *SEQ_add_image_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo *seq_load) { Scene *scene = CTX_data_scene(C); /* only for active seq */ Sequence *seq; Strip *strip; - seq = BKE_sequence_alloc(seqbasep, seq_load->start_frame, seq_load->channel, SEQ_TYPE_IMAGE); + seq = SEQ_sequence_alloc(seqbasep, seq_load->start_frame, seq_load->channel, SEQ_TYPE_IMAGE); seq->blend_mode = SEQ_TYPE_CROSS; /* so alpha adjustment fade to the strip below */ /* basic defaults */ @@ -124,21 +124,22 @@ Sequence *BKE_sequencer_add_image_strip(bContext *C, ListBase *seqbasep, SeqLoad BLI_path_abs(file_path, BKE_main_blendfile_path(CTX_data_main(C))); ImBuf *ibuf = IMB_loadiffname(file_path, IB_rect, seq->strip->colorspace_settings.name); if (ibuf != NULL) { - SEQ_set_scale_to_fit(seq, ibuf->x, ibuf->y, scene->r.xsch, scene->r.ysch, seq_load->fit_method); + SEQ_set_scale_to_fit( + seq, ibuf->x, ibuf->y, scene->r.xsch, scene->r.ysch, seq_load->fit_method); IMB_freeImBuf(ibuf); } - BKE_sequence_invalidate_cache_composite(scene, seq); + SEQ_relations_invalidate_cache_composite(scene, seq); return seq; } #ifdef WITH_AUDASPACE -Sequence *BKE_sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo *seq_load) +Sequence *SEQ_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo *seq_load) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); /* only for sound */ - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); bSound *sound; Sequence *seq; /* generic strip vars */ @@ -158,10 +159,10 @@ Sequence *BKE_sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoad return NULL; } - seq = BKE_sequence_alloc(seqbasep, seq_load->start_frame, seq_load->channel, SEQ_TYPE_SOUND_RAM); + seq = SEQ_sequence_alloc(seqbasep, seq_load->start_frame, seq_load->channel, SEQ_TYPE_SOUND_RAM); seq->sound = sound; BLI_strncpy(seq->name + 2, "Sound", SEQ_NAME_MAXSTR - 2); - BKE_sequence_base_unique_name_recursive(&scene->ed->seqbase, seq); + SEQ_sequence_base_unique_name_recursive(&scene->ed->seqbase, seq); /* basic defaults */ /* We add a very small negative offset here, because @@ -176,7 +177,7 @@ Sequence *BKE_sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoad seq->scene_sound = NULL; - BKE_sequence_calc_disp(scene, seq); + SEQ_time_update_sequence_bounds(scene, seq); /* last active name */ BLI_strncpy(ed->act_sounddir, strip->dir, FILE_MAXDIR); @@ -189,7 +190,7 @@ Sequence *BKE_sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoad return seq; } #else // WITH_AUDASPACE -Sequence *BKE_sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo *seq_load) +Sequence *SEQ_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo *seq_load) { (void)C; (void)seqbasep; @@ -198,7 +199,7 @@ Sequence *BKE_sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoad } #endif // WITH_AUDASPACE -Sequence *BKE_sequencer_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo *seq_load) +Sequence *SEQ_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo *seq_load) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); /* only for sound */ @@ -259,7 +260,7 @@ Sequence *BKE_sequencer_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoad if (seq_load->flag & SEQ_LOAD_MOVIE_SOUND) { seq_load->channel++; } - seq = BKE_sequence_alloc(seqbasep, seq_load->start_frame, seq_load->channel, SEQ_TYPE_MOVIE); + seq = SEQ_sequence_alloc(seqbasep, seq_load->start_frame, seq_load->channel, SEQ_TYPE_MOVIE); /* multiview settings */ if (seq_load->stereo3d_format) { @@ -291,7 +292,7 @@ Sequence *BKE_sequencer_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoad SEQ_set_scale_to_fit(seq, width, height, scene->r.xsch, scene->r.ysch, seq_load->fit_method); BLI_strncpy(seq->name + 2, "Movie", SEQ_NAME_MAXSTR - 2); - BKE_sequence_base_unique_name_recursive(&scene->ed->seqbase, seq); + SEQ_sequence_base_unique_name_recursive(&scene->ed->seqbase, seq); /* adjust scene's frame rate settings to match */ if (seq_load->flag & SEQ_LOAD_SYNC_FPS) { @@ -311,7 +312,7 @@ Sequence *BKE_sequencer_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoad BLI_split_dirfile(seq_load->path, strip->dir, se->name, sizeof(strip->dir), sizeof(se->name)); - BKE_sequence_calc_disp(scene, seq); + SEQ_time_update_sequence_bounds(scene, seq); if (seq_load->name[0] == '\0') { BLI_strncpy(seq_load->name, se->name, sizeof(seq_load->name)); @@ -320,20 +321,20 @@ Sequence *BKE_sequencer_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoad if (seq_load->flag & SEQ_LOAD_MOVIE_SOUND) { int start_frame_back = seq_load->start_frame; seq_load->channel--; - seq_load->seq_sound = BKE_sequencer_add_sound_strip(C, seqbasep, seq_load); + seq_load->seq_sound = SEQ_add_sound_strip(C, seqbasep, seq_load); seq_load->start_frame = start_frame_back; } /* can be NULL */ seq_load_apply(CTX_data_main(C), scene, seq, seq_load); - BKE_sequence_invalidate_cache_composite(scene, seq); + SEQ_relations_invalidate_cache_composite(scene, seq); MEM_freeN(anim_arr); return seq; } -/* note: caller should run BKE_sequence_calc(scene, seq) after */ -void BKE_sequence_reload_new_file(Main *bmain, Scene *scene, Sequence *seq, const bool lock_range) +/* note: caller should run SEQ_time_update_sequence(scene, seq) after */ +void SEQ_add_reload_new_file(Main *bmain, Scene *scene, Sequence *seq, const bool lock_range) { char path[FILE_MAX]; int prev_startdisp = 0, prev_enddisp = 0; @@ -352,7 +353,7 @@ void BKE_sequence_reload_new_file(Main *bmain, Scene *scene, Sequence *seq, cons if (lock_range) { /* keep so we don't have to move the actual start and end points (only the data) */ - BKE_sequence_calc_disp(scene, seq); + SEQ_time_update_sequence_bounds(scene, seq); prev_startdisp = seq->startdisp; prev_enddisp = seq->enddisp; } @@ -379,7 +380,7 @@ void BKE_sequence_reload_new_file(Main *bmain, Scene *scene, Sequence *seq, cons BLI_join_dirfile(path, sizeof(path), seq->strip->dir, seq->strip->stripdata->name); BLI_path_abs(path, BKE_main_blendfile_path_from_global()); - BKE_sequence_free_anim(seq); + SEQ_relations_sequence_free_anim(seq); if (is_multiview && (seq->views_format == R_IMF_VIEWS_INDIVIDUAL)) { char prefix[FILE_MAX]; @@ -499,19 +500,19 @@ void BKE_sequence_reload_new_file(Main *bmain, Scene *scene, Sequence *seq, cons free_proxy_seq(seq); if (lock_range) { - BKE_sequence_tx_set_final_left(seq, prev_startdisp); - BKE_sequence_tx_set_final_right(seq, prev_enddisp); - BKE_sequence_single_fix(seq); + SEQ_transform_set_left_handle_frame(seq, prev_startdisp); + SEQ_transform_set_right_handle_frame(seq, prev_enddisp); + SEQ_transform_fix_single_image_seq_offsets(seq); } - BKE_sequence_calc(scene, seq); + SEQ_time_update_sequence(scene, seq); } -void BKE_sequence_movie_reload_if_needed(struct Main *bmain, - struct Scene *scene, - struct Sequence *seq, - bool *r_was_reloaded, - bool *r_can_produce_frames) +void SEQ_add_movie_reload_if_needed(struct Main *bmain, + struct Scene *scene, + struct Sequence *seq, + bool *r_was_reloaded, + bool *r_can_produce_frames) { BLI_assert(seq->type == SEQ_TYPE_MOVIE || !"This function is only implemented for movie strips."); @@ -543,7 +544,7 @@ void BKE_sequence_movie_reload_if_needed(struct Main *bmain, return; } - BKE_sequence_reload_new_file(bmain, scene, seq, true); + SEQ_add_reload_new_file(bmain, scene, seq, true); *r_was_reloaded = true; if (BLI_listbase_is_empty(&seq->anims)) { diff --git a/source/blender/sequencer/intern/strip_edit.c b/source/blender/sequencer/intern/strip_edit.c index a29810cc9ee..11f42c5de9d 100644 --- a/source/blender/sequencer/intern/strip_edit.c +++ b/source/blender/sequencer/intern/strip_edit.c @@ -42,7 +42,7 @@ #include "SEQ_sequencer.h" -int BKE_sequence_swap(Sequence *seq_a, Sequence *seq_b, const char **error_str) +int SEQ_edit_sequence_swap(Sequence *seq_a, Sequence *seq_b, const char **error_str) { char name[sizeof(seq_a->name)]; @@ -65,8 +65,7 @@ int BKE_sequence_swap(Sequence *seq_a, Sequence *seq_b, const char **error_str) } if ((seq_a->type & SEQ_TYPE_EFFECT) && (seq_b->type & SEQ_TYPE_EFFECT)) { - if (BKE_sequence_effect_get_num_inputs(seq_a->type) != - BKE_sequence_effect_get_num_inputs(seq_b->type)) { + if (SEQ_effect_get_num_inputs(seq_a->type) != SEQ_effect_get_num_inputs(seq_b->type)) { *error_str = N_("Strips must have the same number of inputs"); return 0; } @@ -125,7 +124,7 @@ static void seq_update_muting_recursive(ListBase *seqbasep, Sequence *metaseq, i } } -void BKE_sequencer_update_muting(Editing *ed) +void SEQ_sound_update_muting(Editing *ed) { if (ed) { /* mute all sounds up to current metastack list */ @@ -167,7 +166,7 @@ static void sequencer_flag_users_for_removal(Scene *scene, ListBase *seqbase, Se } /* Flag seq and its users (effects) for removal. */ -void BKE_sequencer_flag_for_removal(Scene *scene, ListBase *seqbase, Sequence *seq) +void SEQ_edit_flag_for_removal(Scene *scene, ListBase *seqbase, Sequence *seq) { if (seq == NULL || (seq->flag & SEQ_FLAG_DELETE) != 0) { return; @@ -176,7 +175,7 @@ void BKE_sequencer_flag_for_removal(Scene *scene, ListBase *seqbase, Sequence *s /* Flag and remove meta children. */ if (seq->type == SEQ_TYPE_META) { LISTBASE_FOREACH (Sequence *, meta_child, &seq->seqbase) { - BKE_sequencer_flag_for_removal(scene, &seq->seqbase, meta_child); + SEQ_edit_flag_for_removal(scene, &seq->seqbase, meta_child); } } @@ -185,15 +184,15 @@ void BKE_sequencer_flag_for_removal(Scene *scene, ListBase *seqbase, Sequence *s } /* Remove all flagged sequences, return true if sequence is removed. */ -void BKE_sequencer_remove_flagged_sequences(Scene *scene, ListBase *seqbase) +void SEQ_edit_remove_flagged_sequences(Scene *scene, ListBase *seqbase) { LISTBASE_FOREACH_MUTABLE (Sequence *, seq, seqbase) { if (seq->flag & SEQ_FLAG_DELETE) { if (seq->type == SEQ_TYPE_META) { - BKE_sequencer_remove_flagged_sequences(scene, &seq->seqbase); + SEQ_edit_remove_flagged_sequences(scene, &seq->seqbase); } BLI_remlink(seqbase, seq); - BKE_sequence_free(scene, seq, true); + SEQ_sequence_free(scene, seq, true); } } } @@ -254,7 +253,7 @@ static void seq_split_set_right_offset(Sequence *seq, int timeline_frame) else if ((seq->start + seq->len) < timeline_frame) { seq->endstill -= seq->enddisp - timeline_frame; } - BKE_sequence_tx_set_final_right(seq, timeline_frame); + SEQ_transform_set_right_handle_frame(seq, timeline_frame); } static void seq_split_set_left_offset(Sequence *seq, int timeline_frame) @@ -268,7 +267,7 @@ static void seq_split_set_left_offset(Sequence *seq, int timeline_frame) seq->start = timeline_frame - seq->len + 1; seq->endstill = seq->enddisp - timeline_frame - 1; } - BKE_sequence_tx_set_final_left(seq, timeline_frame); + SEQ_transform_set_left_handle_frame(seq, timeline_frame); } /** @@ -297,12 +296,12 @@ Sequence *SEQ_edit_strip_split(Main *bmain, /* Precaution, needed because the length saved on-disk may not match the length saved in the * blend file, or our code may have minor differences reading file length between versions. * This causes hard-split to fail, see: T47862. */ - BKE_sequence_reload_new_file(bmain, scene, seq, true); - BKE_sequence_calc(scene, seq); + SEQ_add_reload_new_file(bmain, scene, seq, true); + SEQ_time_update_sequence(scene, seq); } Sequence *left_seq = seq; - Sequence *right_seq = BKE_sequence_dupli_recursive( + Sequence *right_seq = SEQ_sequence_dupli_recursive( scene, scene, seqbase, seq, SEQ_DUPE_UNIQUE_NAME | SEQ_DUPE_ANIM); switch (method) { @@ -313,12 +312,12 @@ Sequence *SEQ_edit_strip_split(Main *bmain, case SEQ_SPLIT_HARD: seq_split_set_right_hold_offset(left_seq, timeline_frame); seq_split_set_left_hold_offset(right_seq, timeline_frame); - BKE_sequence_reload_new_file(bmain, scene, left_seq, false); - BKE_sequence_reload_new_file(bmain, scene, right_seq, false); + SEQ_add_reload_new_file(bmain, scene, left_seq, false); + SEQ_add_reload_new_file(bmain, scene, right_seq, false); break; } - BKE_sequence_calc(scene, left_seq); - BKE_sequence_calc(scene, right_seq); + SEQ_time_update_sequence(scene, left_seq); + SEQ_time_update_sequence(scene, right_seq); return right_seq; } @@ -345,12 +344,14 @@ bool SEQ_edit_remove_gaps(Scene *scene, if (remove_all_gaps) { while (gap_info.gap_exists) { - SEQ_offset_after_frame(scene, seqbase, -gap_info.gap_length, gap_info.gap_start_frame); + SEQ_transform_offset_after_frame( + scene, seqbase, -gap_info.gap_length, gap_info.gap_start_frame); seq_time_gap_info_get(scene, seqbase, initial_frame, &gap_info); } } else { - SEQ_offset_after_frame(scene, seqbase, -gap_info.gap_length, gap_info.gap_start_frame); + SEQ_transform_offset_after_frame( + scene, seqbase, -gap_info.gap_length, gap_info.gap_start_frame); } return true; } diff --git a/source/blender/sequencer/intern/strip_relations.c b/source/blender/sequencer/intern/strip_relations.c index d802ce22f21..939cafb09fd 100644 --- a/source/blender/sequencer/intern/strip_relations.c +++ b/source/blender/sequencer/intern/strip_relations.c @@ -47,7 +47,7 @@ #include "utils.h" /* check whether sequence cur depends on seq */ -static bool BKE_sequence_check_depend(Sequence *seq, Sequence *cur) +static bool seq_relations_check_depend(Sequence *seq, Sequence *cur) { if (cur->seq1 == seq || cur->seq2 == seq || cur->seq3 == seq) { return true; @@ -84,14 +84,14 @@ static void sequence_do_invalidate_dependent(Scene *scene, Sequence *seq, ListBa continue; } - if (BKE_sequence_check_depend(seq, cur)) { + if (seq_relations_check_depend(seq, cur)) { /* Effect must be invalidated completely if they depend on invalidated seq. */ if ((cur->type & SEQ_TYPE_EFFECT) != 0) { - BKE_sequencer_cache_cleanup_sequence(scene, cur, seq, SEQ_CACHE_ALL_TYPES, false); + seq_cache_cleanup_sequence(scene, cur, seq, SEQ_CACHE_ALL_TYPES, false); } else { /* In case of alpha over for example only invalidate composite image */ - BKE_sequencer_cache_cleanup_sequence( + seq_cache_cleanup_sequence( scene, cur, seq, SEQ_CACHE_STORE_COMPOSITE | SEQ_CACHE_STORE_FINAL_OUT, false); } } @@ -110,33 +110,33 @@ static void sequence_invalidate_cache(Scene *scene, Editing *ed = scene->ed; if (invalidate_self) { - BKE_sequence_free_anim(seq); - BKE_sequencer_cache_cleanup_sequence(scene, seq, seq, invalidate_types, false); + SEQ_relations_sequence_free_anim(seq); + seq_cache_cleanup_sequence(scene, seq, seq, invalidate_types, false); } if (seq->effectdata && seq->type == SEQ_TYPE_SPEED) { - BKE_sequence_effect_speed_rebuild_map(scene, seq, true); + seq_effect_speed_rebuild_map(scene, seq, true); } sequence_do_invalidate_dependent(scene, seq, &ed->seqbase); DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS); - BKE_sequencer_prefetch_stop(scene); + SEQ_prefetch_stop(scene); } -void BKE_sequence_invalidate_cache_in_range(Scene *scene, - Sequence *seq, - Sequence *range_mask, - int invalidate_types) +void SEQ_relations_invalidate_cache_in_range(Scene *scene, + Sequence *seq, + Sequence *range_mask, + int invalidate_types) { - BKE_sequencer_cache_cleanup_sequence(scene, seq, range_mask, invalidate_types, true); + seq_cache_cleanup_sequence(scene, seq, range_mask, invalidate_types, true); } -void BKE_sequence_invalidate_cache_raw(Scene *scene, Sequence *seq) +void SEQ_relations_invalidate_cache_raw(Scene *scene, Sequence *seq) { sequence_invalidate_cache(scene, seq, true, SEQ_CACHE_ALL_TYPES); } -void BKE_sequence_invalidate_cache_preprocessed(Scene *scene, Sequence *seq) +void SEQ_relations_invalidate_cache_preprocessed(Scene *scene, Sequence *seq) { sequence_invalidate_cache(scene, seq, @@ -145,7 +145,7 @@ void BKE_sequence_invalidate_cache_preprocessed(Scene *scene, Sequence *seq) SEQ_CACHE_STORE_FINAL_OUT); } -void BKE_sequence_invalidate_cache_composite(Scene *scene, Sequence *seq) +void SEQ_relations_invalidate_cache_composite(Scene *scene, Sequence *seq) { if (ELEM(seq->type, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SOUND_HD)) { return; @@ -155,7 +155,7 @@ void BKE_sequence_invalidate_cache_composite(Scene *scene, Sequence *seq) scene, seq, true, SEQ_CACHE_STORE_COMPOSITE | SEQ_CACHE_STORE_FINAL_OUT); } -void BKE_sequence_invalidate_dependent(Scene *scene, Sequence *seq) +void SEQ_relations_invalidate_dependent(Scene *scene, Sequence *seq) { if (ELEM(seq->type, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SOUND_HD)) { return; @@ -169,7 +169,7 @@ static void invalidate_scene_strips(Scene *scene, Scene *scene_target, ListBase { for (Sequence *seq = seqbase->first; seq != NULL; seq = seq->next) { if (seq->scene == scene_target) { - BKE_sequence_invalidate_cache_raw(scene, seq); + SEQ_relations_invalidate_cache_raw(scene, seq); } if (seq->seqbase.first != NULL) { @@ -178,7 +178,7 @@ static void invalidate_scene_strips(Scene *scene, Scene *scene_target, ListBase } } -void BKE_sequence_invalidate_scene_strips(Main *bmain, Scene *scene_target) +void SEQ_relations_invalidate_scene_strips(Main *bmain, Scene *scene_target) { for (Scene *scene = bmain->scenes.first; scene != NULL; scene = scene->id.next) { if (scene->ed != NULL) { @@ -191,7 +191,7 @@ static void invalidate_movieclip_strips(Scene *scene, MovieClip *clip_target, Li { for (Sequence *seq = seqbase->first; seq != NULL; seq = seq->next) { if (seq->clip == clip_target) { - BKE_sequence_invalidate_cache_raw(scene, seq); + SEQ_relations_invalidate_cache_raw(scene, seq); } if (seq->seqbase.first != NULL) { @@ -200,7 +200,7 @@ static void invalidate_movieclip_strips(Scene *scene, MovieClip *clip_target, Li } } -void BKE_sequence_invalidate_movieclip_strips(Main *bmain, MovieClip *clip_target) +void SEQ_relations_invalidate_movieclip_strips(Main *bmain, MovieClip *clip_target) { for (Scene *scene = bmain->scenes.first; scene != NULL; scene = scene->id.next) { if (scene->ed != NULL) { @@ -209,7 +209,7 @@ void BKE_sequence_invalidate_movieclip_strips(Main *bmain, MovieClip *clip_targe } } -void BKE_sequencer_free_imbuf(Scene *scene, ListBase *seqbase, bool for_render) +void SEQ_relations_free_imbuf(Scene *scene, ListBase *seqbase, bool for_render) { if (scene->ed == NULL) { return; @@ -217,8 +217,8 @@ void BKE_sequencer_free_imbuf(Scene *scene, ListBase *seqbase, bool for_render) Sequence *seq; - BKE_sequencer_cache_cleanup(scene); - BKE_sequencer_prefetch_stop(scene); + SEQ_cache_cleanup(scene); + SEQ_prefetch_stop(scene); for (seq = seqbase->first; seq; seq = seq->next) { if (for_render && CFRA >= seq->startdisp && CFRA <= seq->enddisp) { @@ -227,14 +227,14 @@ void BKE_sequencer_free_imbuf(Scene *scene, ListBase *seqbase, bool for_render) if (seq->strip) { if (seq->type == SEQ_TYPE_MOVIE) { - BKE_sequence_free_anim(seq); + SEQ_relations_sequence_free_anim(seq); } if (seq->type == SEQ_TYPE_SPEED) { - BKE_sequence_effect_speed_rebuild_map(scene, seq, true); + seq_effect_speed_rebuild_map(scene, seq, true); } } if (seq->type == SEQ_TYPE_META) { - BKE_sequencer_free_imbuf(scene, &seq->seqbase, for_render); + SEQ_relations_free_imbuf(scene, &seq->seqbase, for_render); } if (seq->type == SEQ_TYPE_SCENE) { /* FIXME: recurse downwards, @@ -284,27 +284,27 @@ static bool update_changed_seq_recurs( if (free_imbuf) { if (ibuf_change) { if (seq->type == SEQ_TYPE_MOVIE) { - BKE_sequence_free_anim(seq); + SEQ_relations_sequence_free_anim(seq); } else if (seq->type == SEQ_TYPE_SPEED) { - BKE_sequence_effect_speed_rebuild_map(scene, seq, true); + seq_effect_speed_rebuild_map(scene, seq, true); } } if (len_change) { - BKE_sequence_calc(scene, seq); + SEQ_time_update_sequence(scene, seq); } } return free_imbuf; } -void BKE_sequencer_update_changed_seq_and_deps(Scene *scene, +void SEQ_relations_update_changed_seq_and_deps(Scene *scene, Sequence *changed_seq, int len_change, int ibuf_change) { - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); Sequence *seq; if (ed == NULL) { @@ -321,7 +321,7 @@ static void sequencer_all_free_anim_ibufs(ListBase *seqbase, int timeline_frame) { for (Sequence *seq = seqbase->first; seq != NULL; seq = seq->next) { if (seq->enddisp < timeline_frame || seq->startdisp > timeline_frame) { - BKE_sequence_free_anim(seq); + SEQ_relations_sequence_free_anim(seq); } if (seq->type == SEQ_TYPE_META) { sequencer_all_free_anim_ibufs(&seq->seqbase, timeline_frame); @@ -330,14 +330,14 @@ static void sequencer_all_free_anim_ibufs(ListBase *seqbase, int timeline_frame) } /* Unused */ -void BKE_sequencer_all_free_anim_ibufs(Scene *scene, int timeline_frame) +void SEQ_relations_free_all_anim_ibufs(Scene *scene, int timeline_frame) { - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); if (ed == NULL) { return; } sequencer_all_free_anim_ibufs(&ed->seqbase, timeline_frame); - BKE_sequencer_cache_cleanup(scene); + SEQ_cache_cleanup(scene); } static Sequence *sequencer_check_scene_recursion(Scene *scene, ListBase *seqbase) @@ -361,9 +361,9 @@ static Sequence *sequencer_check_scene_recursion(Scene *scene, ListBase *seqbase return NULL; } -bool BKE_sequencer_check_scene_recursion(Scene *scene, ReportList *reports) +bool SEQ_relations_check_scene_recursion(Scene *scene, ReportList *reports) { - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); if (ed == NULL) { return false; } @@ -391,7 +391,7 @@ bool BKE_sequencer_check_scene_recursion(Scene *scene, ReportList *reports) } /* Check if "seq_main" (indirectly) uses strip "seq". */ -bool BKE_sequencer_render_loop_check(Sequence *seq_main, Sequence *seq) +bool SEQ_relations_render_loop_check(Sequence *seq_main, Sequence *seq) { if (seq_main == NULL || seq == NULL) { return false; @@ -401,15 +401,15 @@ bool BKE_sequencer_render_loop_check(Sequence *seq_main, Sequence *seq) return true; } - if ((seq_main->seq1 && BKE_sequencer_render_loop_check(seq_main->seq1, seq)) || - (seq_main->seq2 && BKE_sequencer_render_loop_check(seq_main->seq2, seq)) || - (seq_main->seq3 && BKE_sequencer_render_loop_check(seq_main->seq3, seq))) { + if ((seq_main->seq1 && SEQ_relations_render_loop_check(seq_main->seq1, seq)) || + (seq_main->seq2 && SEQ_relations_render_loop_check(seq_main->seq2, seq)) || + (seq_main->seq3 && SEQ_relations_render_loop_check(seq_main->seq3, seq))) { return true; } SequenceModifierData *smd; for (smd = seq_main->modifiers.first; smd; smd = smd->next) { - if (smd->mask_sequence && BKE_sequencer_render_loop_check(smd->mask_sequence, seq)) { + if (smd->mask_sequence && SEQ_relations_render_loop_check(smd->mask_sequence, seq)) { return true; } } @@ -418,7 +418,7 @@ bool BKE_sequencer_render_loop_check(Sequence *seq_main, Sequence *seq) } /* Function to free imbuf and anim data on changes */ -void BKE_sequence_free_anim(Sequence *seq) +void SEQ_relations_sequence_free_anim(Sequence *seq) { while (seq->anims.last) { StripAnim *sanim = seq->anims.last; @@ -433,12 +433,12 @@ void BKE_sequence_free_anim(Sequence *seq) BLI_listbase_clear(&seq->anims); } -void BKE_sequence_session_uuid_generate(struct Sequence *sequence) +void SEQ_relations_session_uuid_generate(struct Sequence *sequence) { sequence->runtime.session_uuid = BLI_session_uuid_generate(); } -void BKE_sequencer_check_uuids_unique_and_report(const Scene *scene) +void SEQ_relations_check_uuids_unique_and_report(const Scene *scene) { if (scene->ed == NULL) { return; diff --git a/source/blender/sequencer/intern/strip_select.c b/source/blender/sequencer/intern/strip_select.c index 478ae9be337..fbf28087825 100644 --- a/source/blender/sequencer/intern/strip_select.c +++ b/source/blender/sequencer/intern/strip_select.c @@ -31,9 +31,9 @@ #include "SEQ_sequencer.h" -Sequence *BKE_sequencer_active_get(Scene *scene) +Sequence *SEQ_select_active_get(Scene *scene) { - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); if (ed == NULL) { return NULL; @@ -42,9 +42,9 @@ Sequence *BKE_sequencer_active_get(Scene *scene) return ed->act_seq; } -void BKE_sequencer_active_set(Scene *scene, Sequence *seq) +void SEQ_select_active_set(Scene *scene, Sequence *seq) { - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); if (ed == NULL) { return; @@ -53,11 +53,11 @@ void BKE_sequencer_active_set(Scene *scene, Sequence *seq) ed->act_seq = seq; } -int BKE_sequencer_active_get_pair(Scene *scene, Sequence **seq_act, Sequence **seq_other) +int SEQ_select_active_get_pair(Scene *scene, Sequence **seq_act, Sequence **seq_other) { - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); - *seq_act = BKE_sequencer_active_get(scene); + *seq_act = SEQ_select_active_get(scene); if (*seq_act == NULL) { return 0; diff --git a/source/blender/sequencer/intern/strip_time.c b/source/blender/sequencer/intern/strip_time.c index d9074b2a683..a3b17a7c58c 100644 --- a/source/blender/sequencer/intern/strip_time.c +++ b/source/blender/sequencer/intern/strip_time.c @@ -142,7 +142,7 @@ void seq_update_sound_bounds_recursive(Scene *scene, Sequence *metaseq) scene, metaseq, metaseq_start(metaseq), metaseq_end(metaseq)); } -void BKE_sequence_calc_disp(Scene *scene, Sequence *seq) +void SEQ_time_update_sequence_bounds(Scene *scene, Sequence *seq) { if (seq->startofs && seq->startstill) { seq->startstill = 0; @@ -159,7 +159,7 @@ void BKE_sequence_calc_disp(Scene *scene, Sequence *seq) } } -void BKE_sequence_calc(Scene *scene, Sequence *seq) +void SEQ_time_update_sequence(Scene *scene, Sequence *seq) { Sequence *seqm; int min, max; @@ -168,7 +168,7 @@ void BKE_sequence_calc(Scene *scene, Sequence *seq) seqm = seq->seqbase.first; while (seqm) { if (seqm->seqbase.first) { - BKE_sequence_calc(scene, seqm); + SEQ_time_update_sequence(scene, seqm); } seqm = seqm->next; } @@ -206,7 +206,7 @@ void BKE_sequence_calc(Scene *scene, Sequence *seq) seq->len = seq->enddisp - seq->startdisp; } else { - BKE_sequence_calc_disp(scene, seq); + SEQ_time_update_sequence_bounds(scene, seq); } } else { @@ -231,12 +231,12 @@ void BKE_sequence_calc(Scene *scene, Sequence *seq) } seq_update_sound_bounds_recursive(scene, seq); } - BKE_sequence_calc_disp(scene, seq); + SEQ_time_update_sequence_bounds(scene, seq); } } /** Comparison function suitable to be used with BLI_listbase_sort()... */ -int BKE_sequencer_cmp_time_startdisp(const void *a, const void *b) +int SEQ_time_cmp_time_startdisp(const void *a, const void *b) { const Sequence *seq_a = a; const Sequence *seq_b = b; @@ -244,14 +244,14 @@ int BKE_sequencer_cmp_time_startdisp(const void *a, const void *b) return (seq_a->startdisp > seq_b->startdisp); } -int BKE_sequencer_find_next_prev_edit(Scene *scene, - int timeline_frame, - const short side, - const bool do_skip_mute, - const bool do_center, - const bool do_unselected) +int SEQ_time_find_next_prev_edit(Scene *scene, + int timeline_frame, + const short side, + const bool do_skip_mute, + const bool do_center, + const bool do_unselected) { - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); Sequence *seq; int dist, best_dist, best_frame = timeline_frame; @@ -319,7 +319,7 @@ int BKE_sequencer_find_next_prev_edit(Scene *scene, return best_frame; } -float BKE_sequence_get_fps(Scene *scene, Sequence *seq) +float SEQ_time_sequence_get_fps(Scene *scene, Sequence *seq) { switch (seq->type) { case SEQ_TYPE_MOVIE: { diff --git a/source/blender/sequencer/intern/strip_transform.c b/source/blender/sequencer/intern/strip_transform.c index 4aabe87bce1..0cf3940dc54 100644 --- a/source/blender/sequencer/intern/strip_transform.c +++ b/source/blender/sequencer/intern/strip_transform.c @@ -44,28 +44,28 @@ static int seq_tx_get_end(Sequence *seq) return seq->start + seq->len; } -int BKE_sequence_tx_get_final_left(Sequence *seq, bool metaclip) +int SEQ_transform_get_left_handle_frame(Sequence *seq, bool metaclip) { if (metaclip && seq->tmp) { /* return the range clipped by the parents range */ - return max_ii(BKE_sequence_tx_get_final_left(seq, false), - BKE_sequence_tx_get_final_left((Sequence *)seq->tmp, true)); + return max_ii(SEQ_transform_get_left_handle_frame(seq, false), + SEQ_transform_get_left_handle_frame((Sequence *)seq->tmp, true)); } return (seq->start - seq->startstill) + seq->startofs; } -int BKE_sequence_tx_get_final_right(Sequence *seq, bool metaclip) +int SEQ_transform_get_right_handle_frame(Sequence *seq, bool metaclip) { if (metaclip && seq->tmp) { /* return the range clipped by the parents range */ - return min_ii(BKE_sequence_tx_get_final_right(seq, false), - BKE_sequence_tx_get_final_right((Sequence *)seq->tmp, true)); + return min_ii(SEQ_transform_get_right_handle_frame(seq, false), + SEQ_transform_get_right_handle_frame((Sequence *)seq->tmp, true)); } return ((seq->start + seq->len) + seq->endstill) - seq->endofs; } -void BKE_sequence_tx_set_final_left(Sequence *seq, int val) +void SEQ_transform_set_left_handle_frame(Sequence *seq, int val) { if (val < (seq)->start) { seq->startstill = abs(val - (seq)->start); @@ -77,7 +77,7 @@ void BKE_sequence_tx_set_final_left(Sequence *seq, int val) } } -void BKE_sequence_tx_set_final_right(Sequence *seq, int val) +void SEQ_transform_set_right_handle_frame(Sequence *seq, int val) { if (val > (seq)->start + (seq)->len) { seq->endstill = abs(val - (seq->start + (seq)->len)); @@ -91,15 +91,15 @@ void BKE_sequence_tx_set_final_right(Sequence *seq, int val) /* used so we can do a quick check for single image seq * since they work a bit differently to normal image seq's (during transform) */ -bool BKE_sequence_single_check(Sequence *seq) +bool SEQ_transform_single_image_check(Sequence *seq) { return ((seq->len == 1) && (seq->type == SEQ_TYPE_IMAGE || - ((seq->type & SEQ_TYPE_EFFECT) && BKE_sequence_effect_get_num_inputs(seq->type) == 0))); + ((seq->type & SEQ_TYPE_EFFECT) && SEQ_effect_get_num_inputs(seq->type) == 0))); } /* check if the selected seq's reference unselected seq's */ -bool BKE_sequence_base_isolated_sel_check(ListBase *seqbase) +bool SEQ_transform_seqbase_isolated_sel_check(ListBase *seqbase) { Sequence *seq; /* is there more than 1 select */ @@ -144,17 +144,18 @@ bool BKE_sequence_base_isolated_sel_check(ListBase *seqbase) * Use to impose limits when dragging/extending - so impossible situations don't happen. * Cant use the #SEQ_LEFTSEL and #SEQ_LEFTSEL directly because the strip may be in a meta-strip. */ -void BKE_sequence_tx_handle_xlimits(Sequence *seq, int leftflag, int rightflag) +void SEQ_transform_handle_xlimits(Sequence *seq, int leftflag, int rightflag) { if (leftflag) { - if (BKE_sequence_tx_get_final_left(seq, false) >= - BKE_sequence_tx_get_final_right(seq, false)) { - BKE_sequence_tx_set_final_left(seq, BKE_sequence_tx_get_final_right(seq, false) - 1); + if (SEQ_transform_get_left_handle_frame(seq, false) >= + SEQ_transform_get_right_handle_frame(seq, false)) { + SEQ_transform_set_left_handle_frame(seq, + SEQ_transform_get_right_handle_frame(seq, false) - 1); } - if (BKE_sequence_single_check(seq) == 0) { - if (BKE_sequence_tx_get_final_left(seq, false) >= seq_tx_get_end(seq)) { - BKE_sequence_tx_set_final_left(seq, seq_tx_get_end(seq) - 1); + if (SEQ_transform_single_image_check(seq) == 0) { + if (SEQ_transform_get_left_handle_frame(seq, false) >= seq_tx_get_end(seq)) { + SEQ_transform_set_left_handle_frame(seq, seq_tx_get_end(seq) - 1); } /* doesn't work now - TODO */ @@ -170,14 +171,15 @@ void BKE_sequence_tx_handle_xlimits(Sequence *seq, int leftflag, int rightflag) } if (rightflag) { - if (BKE_sequence_tx_get_final_right(seq, false) <= - BKE_sequence_tx_get_final_left(seq, false)) { - BKE_sequence_tx_set_final_right(seq, BKE_sequence_tx_get_final_left(seq, false) + 1); + if (SEQ_transform_get_right_handle_frame(seq, false) <= + SEQ_transform_get_left_handle_frame(seq, false)) { + SEQ_transform_set_right_handle_frame(seq, + SEQ_transform_get_left_handle_frame(seq, false) + 1); } - if (BKE_sequence_single_check(seq) == 0) { - if (BKE_sequence_tx_get_final_right(seq, false) <= seq_tx_get_start(seq)) { - BKE_sequence_tx_set_final_right(seq, seq_tx_get_start(seq) + 1); + if (SEQ_transform_single_image_check(seq) == 0) { + if (SEQ_transform_get_right_handle_frame(seq, false) <= seq_tx_get_start(seq)) { + SEQ_transform_set_right_handle_frame(seq, seq_tx_get_start(seq) + 1); } } } @@ -189,39 +191,30 @@ void BKE_sequence_tx_handle_xlimits(Sequence *seq, int leftflag, int rightflag) } } -void BKE_sequence_single_fix(Sequence *seq) +void SEQ_transform_fix_single_image_seq_offsets(Sequence *seq) { int left, start, offset; - if (!BKE_sequence_single_check(seq)) { + if (!SEQ_transform_single_image_check(seq)) { return; } /* make sure the image is always at the start since there is only one, * adjusting its start should be ok */ - left = BKE_sequence_tx_get_final_left(seq, false); + left = SEQ_transform_get_left_handle_frame(seq, false); start = seq->start; if (start != left) { offset = left - start; - BKE_sequence_tx_set_final_left(seq, BKE_sequence_tx_get_final_left(seq, false) - offset); - BKE_sequence_tx_set_final_right(seq, BKE_sequence_tx_get_final_right(seq, false) - offset); + SEQ_transform_set_left_handle_frame(seq, + SEQ_transform_get_left_handle_frame(seq, false) - offset); + SEQ_transform_set_right_handle_frame( + seq, SEQ_transform_get_right_handle_frame(seq, false) - offset); seq->start += offset; } } -bool BKE_sequence_tx_test(Sequence *seq) +bool SEQ_transform_sequence_can_be_translated(Sequence *seq) { - return !(seq->type & SEQ_TYPE_EFFECT) || (BKE_sequence_effect_get_num_inputs(seq->type) == 0); -} - -/** - * Return \a true if given \a seq needs a complete cleanup of its cache when it is transformed. - * - * Some (effect) strip types need a complete re-cache of themselves when they are transformed, - * because they do not 'contain' anything and do not have any explicit relations to other strips. - */ -bool BKE_sequence_tx_fullupdate_test(Sequence *seq) -{ - return BKE_sequence_tx_test(seq) && ELEM(seq->type, SEQ_TYPE_ADJUSTMENT, SEQ_TYPE_MULTICAM); + return !(seq->type & SEQ_TYPE_EFFECT) || (SEQ_effect_get_num_inputs(seq->type) == 0); } static bool seq_overlap(Sequence *seq1, Sequence *seq2) @@ -230,7 +223,7 @@ static bool seq_overlap(Sequence *seq1, Sequence *seq2) ((seq1->enddisp <= seq2->startdisp) || (seq1->startdisp >= seq2->enddisp)) == 0); } -bool BKE_sequence_test_overlap(ListBase *seqbasep, Sequence *test) +bool SEQ_transform_test_overlap(ListBase *seqbasep, Sequence *test) { Sequence *seq; @@ -245,43 +238,43 @@ bool BKE_sequence_test_overlap(ListBase *seqbasep, Sequence *test) return false; } -void BKE_sequence_translate(Scene *evil_scene, Sequence *seq, int delta) +void SEQ_transform_translate_sequence(Scene *evil_scene, Sequence *seq, int delta) { if (delta == 0) { return; } - BKE_sequencer_offset_animdata(evil_scene, seq, delta); + SEQ_offset_animdata(evil_scene, seq, delta); seq->start += delta; if (seq->type == SEQ_TYPE_META) { Sequence *seq_child; for (seq_child = seq->seqbase.first; seq_child; seq_child = seq_child->next) { - BKE_sequence_translate(evil_scene, seq_child, delta); + SEQ_transform_translate_sequence(evil_scene, seq_child, delta); } } - BKE_sequence_calc_disp(evil_scene, seq); + SEQ_time_update_sequence_bounds(evil_scene, seq); } /* return 0 if there weren't enough space */ -bool BKE_sequence_base_shuffle_ex(ListBase *seqbasep, - Sequence *test, - Scene *evil_scene, - int channel_delta) +bool SEQ_transform_seqbase_shuffle_ex(ListBase *seqbasep, + Sequence *test, + Scene *evil_scene, + int channel_delta) { const int orig_machine = test->machine; BLI_assert(ELEM(channel_delta, -1, 1)); test->machine += channel_delta; - BKE_sequence_calc(evil_scene, test); - while (BKE_sequence_test_overlap(seqbasep, test)) { + SEQ_time_update_sequence(evil_scene, test); + while (SEQ_transform_test_overlap(seqbasep, test)) { if ((channel_delta > 0) ? (test->machine >= MAXSEQ) : (test->machine < 1)) { break; } test->machine += channel_delta; - BKE_sequence_calc( + SEQ_time_update_sequence( evil_scene, test); // XXX - I don't think this is needed since were only moving vertically, Campbell. } @@ -301,18 +294,18 @@ bool BKE_sequence_base_shuffle_ex(ListBase *seqbasep, test->machine = orig_machine; new_frame = new_frame + (test->start - test->startdisp); /* adjust by the startdisp */ - BKE_sequence_translate(evil_scene, test, new_frame - test->start); + SEQ_transform_translate_sequence(evil_scene, test, new_frame - test->start); - BKE_sequence_calc(evil_scene, test); + SEQ_time_update_sequence(evil_scene, test); return false; } return true; } -bool BKE_sequence_base_shuffle(ListBase *seqbasep, Sequence *test, Scene *evil_scene) +bool SEQ_transform_seqbase_shuffle(ListBase *seqbasep, Sequence *test, Scene *evil_scene) { - return BKE_sequence_base_shuffle_ex(seqbasep, test, evil_scene, 1); + return SEQ_transform_seqbase_shuffle_ex(seqbasep, test, evil_scene, 1); } static int shuffle_seq_time_offset_test(ListBase *seqbasep, char dir) @@ -356,17 +349,17 @@ static int shuffle_seq_time_offset(Scene *scene, ListBase *seqbasep, char dir) for (seq = seqbasep->first; seq; seq = seq->next) { if (seq->tmp) { - BKE_sequence_calc_disp(scene, seq); /* corrects dummy startdisp/enddisp values */ + SEQ_time_update_sequence_bounds(scene, seq); /* corrects dummy startdisp/enddisp values */ } } return tot_ofs; } -bool BKE_sequence_base_shuffle_time(ListBase *seqbasep, - Scene *evil_scene, - ListBase *markers, - const bool use_sync_markers) +bool SEQ_transform_seqbase_shuffle_time(ListBase *seqbasep, + Scene *evil_scene, + ListBase *markers, + const bool use_sync_markers) { /* note: seq->tmp is used to tag strips to move */ @@ -379,7 +372,7 @@ bool BKE_sequence_base_shuffle_time(ListBase *seqbasep, if (offset) { for (seq = seqbasep->first; seq; seq = seq->next) { if (seq->tmp) { - BKE_sequence_translate(evil_scene, seq, offset); + SEQ_transform_translate_sequence(evil_scene, seq, offset); seq->flag &= ~SEQ_OVERLAP; } } @@ -406,16 +399,16 @@ bool BKE_sequence_base_shuffle_time(ListBase *seqbasep, * \param delta: offset in frames to be applied * \param timeline_frame: frame on timeline from where strips are moved */ -void SEQ_offset_after_frame(Scene *scene, - ListBase *seqbase, - const int delta, - const int timeline_frame) +void SEQ_transform_offset_after_frame(Scene *scene, + ListBase *seqbase, + const int delta, + const int timeline_frame) { LISTBASE_FOREACH (Sequence *, seq, seqbase) { if (seq->startdisp >= timeline_frame) { - BKE_sequence_translate(scene, seq, delta); - BKE_sequence_calc(scene, seq); - BKE_sequence_invalidate_cache_preprocessed(scene, seq); + SEQ_transform_translate_sequence(scene, seq, delta); + SEQ_time_update_sequence(scene, seq); + SEQ_relations_invalidate_cache_preprocessed(scene, seq); } } diff --git a/source/blender/sequencer/intern/utils.c b/source/blender/sequencer/intern/utils.c index a76cfb76e62..40f2aca4714 100644 --- a/source/blender/sequencer/intern/utils.c +++ b/source/blender/sequencer/intern/utils.c @@ -51,11 +51,11 @@ #include "proxy.h" #include "utils.h" -void BKE_sequencer_sort(Scene *scene) +void SEQ_sort(Scene *scene) { /* all strips together per kind, and in order of y location ("machine") */ ListBase seqbase, effbase; - Editing *ed = BKE_sequencer_editing_get(scene, false); + Editing *ed = SEQ_editing_get(scene, false); Sequence *seq, *seqt; if (ed == NULL) { @@ -132,7 +132,7 @@ static int seqbase_unique_name_recursive_fn(Sequence *seq, void *arg_pt) return 1; } -void BKE_sequence_base_unique_name_recursive(ListBase *seqbasep, Sequence *seq) +void SEQ_sequence_base_unique_name_recursive(ListBase *seqbasep, Sequence *seq) { SeqUniqueInfo sui; char *dot; @@ -156,7 +156,7 @@ void BKE_sequence_base_unique_name_recursive(ListBase *seqbasep, Sequence *seq) while (sui.match) { sui.match = 0; seqbase_unique_name(seqbasep, &sui); - BKE_sequencer_base_recursive_apply(seqbasep, seqbase_unique_name_recursive_fn, &sui); + SEQ_iterator_seqbase_recursive_apply(seqbasep, seqbase_unique_name_recursive_fn, &sui); } BLI_strncpy(seq->name + 2, sui.name_dest, sizeof(seq->name) - 2); @@ -220,7 +220,7 @@ static const char *give_seqname_by_type(int type) } } -const char *BKE_sequence_give_name(Sequence *seq) +const char *SEQ_sequence_give_name(Sequence *seq) { const char *name = give_seqname_by_type(seq->type); @@ -234,7 +234,7 @@ const char *BKE_sequence_give_name(Sequence *seq) return name; } -ListBase *BKE_sequence_seqbase_get(Sequence *seq, int *r_offset) +ListBase *SEQ_get_seqbase_from_sequence(Sequence *seq, int *r_offset) { ListBase *seqbase = NULL; @@ -246,7 +246,7 @@ ListBase *BKE_sequence_seqbase_get(Sequence *seq, int *r_offset) } case SEQ_TYPE_SCENE: { if (seq->flag & SEQ_SCENE_STRIPS && seq->scene) { - Editing *ed = BKE_sequencer_editing_get(seq->scene, false); + Editing *ed = SEQ_editing_get(seq->scene, false); if (ed) { seqbase = &ed->seqbase; *r_offset = seq->scene->r.sfra; @@ -275,7 +275,7 @@ void seq_open_anim_file(Scene *scene, Sequence *seq, bool openfile) } /* reset all the previously created anims */ - BKE_sequence_free_anim(seq); + SEQ_relations_sequence_free_anim(seq); BLI_join_dirfile(name, sizeof(name), seq->strip->dir, seq->strip->stripdata->name); BLI_path_abs(name, BKE_main_blendfile_path_from_global()); @@ -388,7 +388,7 @@ void seq_open_anim_file(Scene *scene, Sequence *seq, bool openfile) } } -const Sequence *BKE_sequencer_foreground_frame_get(const Scene *scene, int frame) +const Sequence *SEQ_get_topmost_sequence(const Scene *scene, int frame) { const Editing *ed = scene->ed; const Sequence *seq, *best_seq = NULL; @@ -421,7 +421,7 @@ const Sequence *BKE_sequencer_foreground_frame_get(const Scene *scene, int frame } /* in cases where we done know the sequence's listbase */ -ListBase *BKE_sequence_seqbase(ListBase *seqbase, Sequence *seq) +ListBase *SEQ_get_seqbase_by_seq(ListBase *seqbase, Sequence *seq) { Sequence *iseq; ListBase *lb = NULL; @@ -430,7 +430,7 @@ ListBase *BKE_sequence_seqbase(ListBase *seqbase, Sequence *seq) if (seq == iseq) { return seqbase; } - if (iseq->seqbase.first && (lb = BKE_sequence_seqbase(&iseq->seqbase, seq))) { + if (iseq->seqbase.first && (lb = SEQ_get_seqbase_by_seq(&iseq->seqbase, seq))) { return lb; } } @@ -438,7 +438,7 @@ ListBase *BKE_sequence_seqbase(ListBase *seqbase, Sequence *seq) return NULL; } -Sequence *BKE_sequence_metastrip(ListBase *seqbase, Sequence *meta, Sequence *seq) +Sequence *seq_find_metastrip_by_sequence(ListBase *seqbase, Sequence *meta, Sequence *seq) { Sequence *iseq; @@ -448,7 +448,8 @@ Sequence *BKE_sequence_metastrip(ListBase *seqbase, Sequence *meta, Sequence *se if (seq == iseq) { return meta; } - if (iseq->seqbase.first && (rval = BKE_sequence_metastrip(&iseq->seqbase, iseq, seq))) { + if (iseq->seqbase.first && + (rval = seq_find_metastrip_by_sequence(&iseq->seqbase, iseq, seq))) { return rval; } } @@ -460,7 +461,7 @@ Sequence *BKE_sequence_metastrip(ListBase *seqbase, Sequence *meta, Sequence *se * Only use as last resort when the StripElem is available but no the Sequence. * (needed for RNA) */ -Sequence *BKE_sequencer_from_elem(ListBase *seqbase, StripElem *se) +Sequence *SEQ_sequence_from_strip_elem(ListBase *seqbase, StripElem *se) { Sequence *iseq; @@ -470,7 +471,7 @@ Sequence *BKE_sequencer_from_elem(ListBase *seqbase, StripElem *se) (ARRAY_HAS_ITEM(se, iseq->strip->stripdata, iseq->len))) { break; } - if ((seq_found = BKE_sequencer_from_elem(&iseq->seqbase, se))) { + if ((seq_found = SEQ_sequence_from_strip_elem(&iseq->seqbase, se))) { iseq = seq_found; break; } @@ -479,7 +480,7 @@ Sequence *BKE_sequencer_from_elem(ListBase *seqbase, StripElem *se) return iseq; } -Sequence *BKE_sequence_get_by_name(ListBase *seqbase, const char *name, bool recursive) +Sequence *SEQ_get_sequence_by_name(ListBase *seqbase, const char *name, bool recursive) { Sequence *iseq = NULL; Sequence *rseq = NULL; @@ -489,7 +490,7 @@ Sequence *BKE_sequence_get_by_name(ListBase *seqbase, const char *name, bool rec return iseq; } if (recursive && (iseq->seqbase.first) && - (rseq = BKE_sequence_get_by_name(&iseq->seqbase, name, 1))) { + (rseq = SEQ_get_sequence_by_name(&iseq->seqbase, name, 1))) { return rseq; } } @@ -497,9 +498,9 @@ Sequence *BKE_sequence_get_by_name(ListBase *seqbase, const char *name, bool rec return NULL; } -Mask *BKE_sequencer_mask_get(Scene *scene) +Mask *SEQ_active_mask_get(Scene *scene) { - Sequence *seq_act = BKE_sequencer_active_get(scene); + Sequence *seq_act = SEQ_select_active_get(scene); if (seq_act && seq_act->type == SEQ_TYPE_MASK) { return seq_act->mask; @@ -508,7 +509,7 @@ Mask *BKE_sequencer_mask_get(Scene *scene) return NULL; } -void BKE_sequence_alpha_mode_from_extension(Sequence *seq) +void SEQ_alpha_mode_from_file_extension(Sequence *seq) { if (seq->strip && seq->strip->stripdata) { const char *filename = seq->strip->stripdata->name; @@ -518,7 +519,7 @@ void BKE_sequence_alpha_mode_from_extension(Sequence *seq) /* called on draw, needs to be fast, * we could cache and use a flag if we want to make checks for file paths resolving for eg. */ -bool BKE_sequence_is_valid_check(Sequence *seq) +bool SEQ_sequence_has_source(Sequence *seq) { switch (seq->type) { case SEQ_TYPE_MASK: diff --git a/source/blender/sequencer/intern/utils.h b/source/blender/sequencer/intern/utils.h index f30ea753d37..97f33bb3ae0 100644 --- a/source/blender/sequencer/intern/utils.h +++ b/source/blender/sequencer/intern/utils.h @@ -31,9 +31,9 @@ struct Scene; bool sequencer_seq_generates_image(struct Sequence *seq); void seq_open_anim_file(struct Scene *scene, struct Sequence *seq, bool openfile); -struct Sequence *BKE_sequence_metastrip(ListBase *seqbase /* = ed->seqbase */, - struct Sequence *meta /* = NULL */, - struct Sequence *seq); +struct Sequence *seq_find_metastrip_by_sequence(ListBase *seqbase /* = ed->seqbase */, + struct Sequence *meta /* = NULL */, + struct Sequence *seq); #ifdef __cplusplus } diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index 7984c2fd879..be58575f99c 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -565,7 +565,7 @@ void WM_exit_ex(bContext *C, const bool do_python) wm_free_reports(wm); } - BKE_sequencer_free_clipboard(); /* sequencer.c */ + SEQ_clipboard_free(); /* sequencer.c */ BKE_tracking_clipboard_free(); BKE_mask_clipboard_free(); BKE_vfont_clipboard_free(); diff --git a/source/blender/windowmanager/intern/wm_jobs.c b/source/blender/windowmanager/intern/wm_jobs.c index 443a6fd1979..2e794940f26 100644 --- a/source/blender/windowmanager/intern/wm_jobs.c +++ b/source/blender/windowmanager/intern/wm_jobs.c @@ -556,7 +556,7 @@ void WM_jobs_kill_all(wmWindowManager *wm) } /* This job will be automatically restarted */ - BKE_sequencer_prefetch_stop_all(); + SEQ_prefetch_stop_all(); } /* wait until every job ended, except for one owner (used in undo to keep screen job alive) */ -- cgit v1.2.3 From a5a302bd18061e833c4d629fffd06f57e7447d39 Mon Sep 17 00:00:00 2001 From: Richard Antalik Date: Sat, 19 Dec 2020 06:44:57 +0100 Subject: Cleanup: Split SEQ_sequencer.h file --- source/blender/blenkernel/intern/bpath.c | 2 +- source/blender/blenkernel/intern/image.c | 2 +- source/blender/blenkernel/intern/ipo.c | 2 +- source/blender/blenkernel/intern/scene.c | 8 +- source/blender/blenkernel/intern/sound.c | 1 + source/blender/blenloader/intern/readfile.c | 3 + source/blender/blenloader/intern/versioning_250.c | 2 +- source/blender/blenloader/intern/versioning_260.c | 4 +- source/blender/blenloader/intern/versioning_270.c | 3 +- source/blender/blenloader/intern/versioning_280.c | 4 +- source/blender/blenloader/intern/versioning_290.c | 2 + .../blender/blenloader/intern/versioning_legacy.c | 2 +- .../depsgraph/intern/builder/deg_builder_nodes.cc | 2 +- .../intern/builder/deg_builder_relations.cc | 2 +- .../intern/eval/deg_eval_copy_on_write.cc | 2 +- .../eval/deg_eval_runtime_backup_sequencer.cc | 2 +- source/blender/editors/animation/anim_deps.c | 1 + source/blender/editors/animation/anim_filter.c | 1 + source/blender/editors/animation/anim_ops.c | 1 + source/blender/editors/render/render_internal.c | 2 +- source/blender/editors/render/render_opengl.c | 2 +- source/blender/editors/sound/sound_ops.c | 2 +- .../editors/space_outliner/outliner_select.c | 1 + .../blender/editors/space_outliner/outliner_sync.c | 2 +- .../editors/space_sequencer/sequencer_add.c | 8 + .../editors/space_sequencer/sequencer_draw.c | 9 + .../editors/space_sequencer/sequencer_edit.c | 12 + .../editors/space_sequencer/sequencer_modifier.c | 4 + .../editors/space_sequencer/sequencer_proxy.c | 3 + .../editors/space_sequencer/sequencer_select.c | 2 + .../editors/space_sequencer/sequencer_view.c | 2 + .../editors/space_sequencer/space_sequencer.c | 1 + .../transform/transform_convert_sequencer.c | 4 + source/blender/editors/transform/transform_snap.c | 1 + source/blender/editors/util/ed_util_imbuf.c | 1 + source/blender/imbuf/intern/colormanagement.c | 2 +- source/blender/makesrna/intern/rna_camera.c | 2 +- source/blender/makesrna/intern/rna_color.c | 3 +- source/blender/makesrna/intern/rna_movieclip.c | 2 +- source/blender/makesrna/intern/rna_scene.c | 2 + source/blender/makesrna/intern/rna_sequencer.c | 11 + source/blender/makesrna/intern/rna_sequencer_api.c | 4 + source/blender/makesrna/intern/rna_space.c | 2 +- source/blender/render/intern/pipeline.c | 3 +- source/blender/sequencer/CMakeLists.txt | 15 + source/blender/sequencer/SEQ_add.h | 89 ++++ source/blender/sequencer/SEQ_clipboard.h | 41 ++ source/blender/sequencer/SEQ_edit.h | 59 +++ source/blender/sequencer/SEQ_effects.h | 118 +++++ source/blender/sequencer/SEQ_iterator.h | 75 +++ source/blender/sequencer/SEQ_modifier.h | 88 ++++ source/blender/sequencer/SEQ_prefetch.h | 39 ++ source/blender/sequencer/SEQ_proxy.h | 57 +++ source/blender/sequencer/SEQ_relations.h | 73 +++ source/blender/sequencer/SEQ_render.h | 88 ++++ source/blender/sequencer/SEQ_select.h | 41 ++ source/blender/sequencer/SEQ_sequencer.h | 570 +-------------------- source/blender/sequencer/SEQ_sound.h | 44 ++ source/blender/sequencer/SEQ_time.h | 51 ++ source/blender/sequencer/SEQ_transform.h | 63 +++ source/blender/sequencer/SEQ_util.h | 58 +++ source/blender/sequencer/SEQ_utils.h | 60 +++ source/blender/sequencer/intern/clipboard.c | 2 +- source/blender/sequencer/intern/effects.c | 5 +- source/blender/sequencer/intern/image_cache.c | 3 + source/blender/sequencer/intern/iterator.c | 2 +- source/blender/sequencer/intern/modifier.c | 3 +- source/blender/sequencer/intern/prefetch.c | 3 +- source/blender/sequencer/intern/proxy.c | 2 + source/blender/sequencer/intern/render.c | 5 + source/blender/sequencer/intern/render.h | 3 +- source/blender/sequencer/intern/sequencer.c | 6 + source/blender/sequencer/intern/sound.c | 21 +- source/blender/sequencer/intern/strip_add.c | 6 + source/blender/sequencer/intern/strip_edit.c | 7 +- source/blender/sequencer/intern/strip_relations.c | 4 + source/blender/sequencer/intern/strip_select.c | 1 + source/blender/sequencer/intern/strip_time.c | 2 + source/blender/sequencer/intern/strip_transform.c | 4 + source/blender/sequencer/intern/utils.c | 4 + source/blender/windowmanager/intern/wm_init_exit.c | 2 +- source/blender/windowmanager/intern/wm_jobs.c | 2 +- 82 files changed, 1238 insertions(+), 611 deletions(-) create mode 100644 source/blender/sequencer/SEQ_add.h create mode 100644 source/blender/sequencer/SEQ_clipboard.h create mode 100644 source/blender/sequencer/SEQ_edit.h create mode 100644 source/blender/sequencer/SEQ_effects.h create mode 100644 source/blender/sequencer/SEQ_iterator.h create mode 100644 source/blender/sequencer/SEQ_modifier.h create mode 100644 source/blender/sequencer/SEQ_prefetch.h create mode 100644 source/blender/sequencer/SEQ_proxy.h create mode 100644 source/blender/sequencer/SEQ_relations.h create mode 100644 source/blender/sequencer/SEQ_render.h create mode 100644 source/blender/sequencer/SEQ_select.h create mode 100644 source/blender/sequencer/SEQ_sound.h create mode 100644 source/blender/sequencer/SEQ_time.h create mode 100644 source/blender/sequencer/SEQ_transform.h create mode 100644 source/blender/sequencer/SEQ_util.h create mode 100644 source/blender/sequencer/SEQ_utils.h (limited to 'source/blender') diff --git a/source/blender/blenkernel/intern/bpath.c b/source/blender/blenkernel/intern/bpath.c index f624d0ae057..762ced7dc5f 100644 --- a/source/blender/blenkernel/intern/bpath.c +++ b/source/blender/blenkernel/intern/bpath.c @@ -78,7 +78,7 @@ #include "CLG_log.h" -#include "SEQ_sequencer.h" +#include "SEQ_iterator.h" #ifndef _MSC_VER # include "BLI_strict_flags.h" diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 090ab571542..ab57d14d2cf 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -93,7 +93,7 @@ #include "RE_pipeline.h" -#include "SEQ_sequencer.h" /* seq_foreground_frame_get() */ +#include "SEQ_utils.h" /* SEQ_get_topmost_sequence() */ #include "GPU_texture.h" diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c index 0e611b21304..1ab6e61e20e 100644 --- a/source/blender/blenkernel/intern/ipo.c +++ b/source/blender/blenkernel/intern/ipo.c @@ -74,7 +74,7 @@ #include "MEM_guardedalloc.h" -#include "SEQ_sequencer.h" +#include "SEQ_iterator.h" #include "BLO_read_write.h" diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 7acd54b6af1..c099fdb0e19 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -109,7 +109,13 @@ #include "RE_engine.h" +#include "SEQ_edit.h" +#include "SEQ_iterator.h" +#include "SEQ_modifier.h" +#include "SEQ_proxy.h" +#include "SEQ_relations.h" #include "SEQ_sequencer.h" +#include "SEQ_sound.h" #include "BLO_read_write.h" @@ -3733,6 +3739,6 @@ void BKE_scene_eval_sequencer_sequences(Depsgraph *depsgraph, Scene *scene) } } SEQ_ALL_END; - SEQ_sound_update_muting(scene->ed); + SEQ_edit_update_muting(scene->ed); SEQ_sound_update_bounds_all(scene); } diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c index d167fc4e51f..78729fb9261 100644 --- a/source/blender/blenkernel/intern/sound.c +++ b/source/blender/blenkernel/intern/sound.c @@ -68,6 +68,7 @@ #include "BLO_read_write.h" #include "SEQ_sequencer.h" +#include "SEQ_sound.h" static void sound_free_audio(bSound *sound); diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 73606db9a41..b61abd4ed06 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -105,6 +105,9 @@ #include "BLO_readfile.h" #include "BLO_undofile.h" +#include "SEQ_clipboard.h" +#include "SEQ_iterator.h" +#include "SEQ_modifier.h" #include "SEQ_sequencer.h" #include "readfile.h" diff --git a/source/blender/blenloader/intern/versioning_250.c b/source/blender/blenloader/intern/versioning_250.c index b282a978e8a..23f46e15f51 100644 --- a/source/blender/blenloader/intern/versioning_250.c +++ b/source/blender/blenloader/intern/versioning_250.c @@ -77,7 +77,7 @@ #include "BKE_sound.h" #include "BKE_texture.h" -#include "SEQ_sequencer.h" +#include "SEQ_iterator.h" #include "NOD_socket.h" diff --git a/source/blender/blenloader/intern/versioning_260.c b/source/blender/blenloader/intern/versioning_260.c index 86085ddbc73..767f24cf175 100644 --- a/source/blender/blenloader/intern/versioning_260.c +++ b/source/blender/blenloader/intern/versioning_260.c @@ -67,7 +67,9 @@ #include "BKE_texture.h" #include "BKE_tracking.h" -#include "SEQ_sequencer.h" +#include "SEQ_iterator.h" +#include "SEQ_modifier.h" +#include "SEQ_utils.h" #ifdef WITH_FFMPEG # include "BKE_writeffmpeg.h" diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c index ee5efff7216..df9268f0da1 100644 --- a/source/blender/blenloader/intern/versioning_270.c +++ b/source/blender/blenloader/intern/versioning_270.c @@ -66,7 +66,8 @@ #include "BKE_tracking.h" #include "DNA_material_types.h" -#include "SEQ_sequencer.h" +#include "SEQ_effects.h" +#include "SEQ_iterator.h" #include "BLI_listbase.h" #include "BLI_math.h" diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c index f7ef7f74a42..88493de5076 100644 --- a/source/blender/blenloader/intern/versioning_280.c +++ b/source/blender/blenloader/intern/versioning_280.c @@ -97,7 +97,9 @@ #include "BKE_unit.h" #include "BKE_workspace.h" -#include "SEQ_sequencer.h" +#include "SEQ_iterator.h" +#include "SEQ_modifier.h" +#include "SEQ_utils.h" /* Only for IMB_BlendMode */ #include "IMB_imbuf.h" diff --git a/source/blender/blenloader/intern/versioning_290.c b/source/blender/blenloader/intern/versioning_290.c index 86293f273b3..b27e62c9218 100644 --- a/source/blender/blenloader/intern/versioning_290.c +++ b/source/blender/blenloader/intern/versioning_290.c @@ -66,6 +66,8 @@ #include "RNA_access.h" +#include "SEQ_proxy.h" +#include "SEQ_render.h" #include "SEQ_sequencer.h" #include "BLO_readfile.h" diff --git a/source/blender/blenloader/intern/versioning_legacy.c b/source/blender/blenloader/intern/versioning_legacy.c index 6f459339675..dc8f7a0305a 100644 --- a/source/blender/blenloader/intern/versioning_legacy.c +++ b/source/blender/blenloader/intern/versioning_legacy.c @@ -80,7 +80,7 @@ #include "BKE_particle.h" #include "BKE_pointcache.h" -#include "SEQ_sequencer.h" +#include "SEQ_iterator.h" #include "NOD_socket.h" diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc index e5301532ddc..eb20dfb69a2 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc @@ -109,7 +109,7 @@ #include "DEG_depsgraph.h" #include "DEG_depsgraph_build.h" -#include "SEQ_sequencer.h" +#include "SEQ_iterator.h" #include "intern/builder/deg_builder.h" #include "intern/depsgraph.h" diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc index de68ec6210e..df48cb91ce7 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc @@ -99,7 +99,7 @@ #include "RNA_access.h" #include "RNA_types.h" -#include "SEQ_sequencer.h" +#include "SEQ_iterator.h" #include "DEG_depsgraph.h" #include "DEG_depsgraph_build.h" 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 5119de1ed9e..2544bb1642c 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 @@ -92,7 +92,7 @@ #include "BKE_pointcache.h" #include "BKE_sound.h" -#include "SEQ_sequencer.h" +#include "SEQ_relations.h" #include "intern/builder/deg_builder.h" #include "intern/builder/deg_builder_nodes.h" diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sequencer.cc b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sequencer.cc index c0e284a930e..34c23740730 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sequencer.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sequencer.cc @@ -30,7 +30,7 @@ #include "BKE_sound.h" -#include "SEQ_sequencer.h" +#include "SEQ_iterator.h" namespace blender::deg { diff --git a/source/blender/editors/animation/anim_deps.c b/source/blender/editors/animation/anim_deps.c index fbd55592729..17251587d3b 100644 --- a/source/blender/editors/animation/anim_deps.c +++ b/source/blender/editors/animation/anim_deps.c @@ -50,6 +50,7 @@ #include "RNA_access.h" #include "SEQ_sequencer.h" +#include "SEQ_utils.h" #include "ED_anim_api.h" diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index 83665d7a053..f2022194ed5 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -101,6 +101,7 @@ #include "ED_markers.h" #include "SEQ_sequencer.h" +#include "SEQ_utils.h" #include "UI_resources.h" /* for TH_KEYFRAME_SCALE lookup */ diff --git a/source/blender/editors/animation/anim_ops.c b/source/blender/editors/animation/anim_ops.c index 07601414fb0..a5514f6517e 100644 --- a/source/blender/editors/animation/anim_ops.c +++ b/source/blender/editors/animation/anim_ops.c @@ -56,6 +56,7 @@ #include "DEG_depsgraph_query.h" #include "SEQ_sequencer.h" +#include "SEQ_time.h" #include "anim_intern.h" diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c index 46680f649cd..10cf4131584 100644 --- a/source/blender/editors/render/render_internal.c +++ b/source/blender/editors/render/render_internal.c @@ -83,7 +83,7 @@ #include "RNA_access.h" #include "RNA_define.h" -#include "SEQ_sequencer.h" +#include "SEQ_relations.h" #include "BLO_undofile.h" diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c index f7275b06804..1069f942a7a 100644 --- a/source/blender/editors/render/render_opengl.c +++ b/source/blender/editors/render/render_opengl.c @@ -77,7 +77,7 @@ #include "RNA_access.h" #include "RNA_define.h" -#include "SEQ_sequencer.h" +#include "SEQ_render.h" #include "GPU_framebuffer.h" #include "GPU_matrix.h" diff --git a/source/blender/editors/sound/sound_ops.c b/source/blender/editors/sound/sound_ops.c index 5bc13ec1b75..34617804888 100644 --- a/source/blender/editors/sound/sound_ops.c +++ b/source/blender/editors/sound/sound_ops.c @@ -52,7 +52,7 @@ #include "RNA_define.h" #include "RNA_enum_types.h" -#include "SEQ_sequencer.h" +#include "SEQ_iterator.h" #include "UI_interface.h" diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c index a1df922b335..6380bb9505e 100644 --- a/source/blender/editors/space_outliner/outliner_select.c +++ b/source/blender/editors/space_outliner/outliner_select.c @@ -72,6 +72,7 @@ #include "ED_sequencer.h" #include "ED_undo.h" +#include "SEQ_select.h" #include "SEQ_sequencer.h" #include "WM_api.h" diff --git a/source/blender/editors/space_outliner/outliner_sync.c b/source/blender/editors/space_outliner/outliner_sync.c index b3e8761f60b..0b2d1ce34ec 100644 --- a/source/blender/editors/space_outliner/outliner_sync.c +++ b/source/blender/editors/space_outliner/outliner_sync.c @@ -46,7 +46,7 @@ #include "ED_object.h" #include "ED_outliner.h" -#include "SEQ_sequencer.h" +#include "SEQ_select.h" #include "WM_api.h" #include "WM_types.h" diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c index e40e9f5429d..f9076145f2f 100644 --- a/source/blender/editors/space_sequencer/sequencer_add.c +++ b/source/blender/editors/space_sequencer/sequencer_add.c @@ -50,7 +50,15 @@ #include "RNA_define.h" #include "RNA_enum_types.h" +#include "SEQ_add.h" +#include "SEQ_effects.h" +#include "SEQ_relations.h" +#include "SEQ_render.h" +#include "SEQ_select.h" #include "SEQ_sequencer.h" +#include "SEQ_time.h" +#include "SEQ_transform.h" +#include "SEQ_utils.h" /* For menu, popup, icons, etc. */ #include "ED_screen.h" diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index 2f146690416..1b213746add 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -68,7 +68,16 @@ #include "BIF_glutil.h" +#include "SEQ_effects.h" +#include "SEQ_prefetch.h" +#include "SEQ_proxy.h" +#include "SEQ_relations.h" +#include "SEQ_render.h" +#include "SEQ_select.h" #include "SEQ_sequencer.h" +#include "SEQ_time.h" +#include "SEQ_transform.h" +#include "SEQ_utils.h" #include "UI_interface.h" #include "UI_resources.h" diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c index f78b602ceda..c3553ac88ad 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.c +++ b/source/blender/editors/space_sequencer/sequencer_edit.c @@ -45,7 +45,19 @@ #include "BKE_report.h" #include "BKE_sound.h" +#include "SEQ_add.h" +#include "SEQ_clipboard.h" +#include "SEQ_edit.h" +#include "SEQ_effects.h" +#include "SEQ_iterator.h" +#include "SEQ_prefetch.h" +#include "SEQ_relations.h" +#include "SEQ_render.h" +#include "SEQ_select.h" #include "SEQ_sequencer.h" +#include "SEQ_time.h" +#include "SEQ_transform.h" +#include "SEQ_utils.h" #include "WM_api.h" #include "WM_types.h" diff --git a/source/blender/editors/space_sequencer/sequencer_modifier.c b/source/blender/editors/space_sequencer/sequencer_modifier.c index e8f4fac1920..f11a879912c 100644 --- a/source/blender/editors/space_sequencer/sequencer_modifier.c +++ b/source/blender/editors/space_sequencer/sequencer_modifier.c @@ -34,6 +34,10 @@ #include "RNA_define.h" #include "RNA_enum_types.h" +#include "SEQ_iterator.h" +#include "SEQ_modifier.h" +#include "SEQ_relations.h" +#include "SEQ_select.h" #include "SEQ_sequencer.h" /* Own include. */ diff --git a/source/blender/editors/space_sequencer/sequencer_proxy.c b/source/blender/editors/space_sequencer/sequencer_proxy.c index 032885c2719..b04363a4f33 100644 --- a/source/blender/editors/space_sequencer/sequencer_proxy.c +++ b/source/blender/editors/space_sequencer/sequencer_proxy.c @@ -34,6 +34,9 @@ #include "BKE_main.h" #include "BKE_report.h" +#include "SEQ_iterator.h" +#include "SEQ_proxy.h" +#include "SEQ_relations.h" #include "SEQ_sequencer.h" #include "WM_api.h" diff --git a/source/blender/editors/space_sequencer/sequencer_select.c b/source/blender/editors/space_sequencer/sequencer_select.c index 6534a63f03e..a6027a2472c 100644 --- a/source/blender/editors/space_sequencer/sequencer_select.c +++ b/source/blender/editors/space_sequencer/sequencer_select.c @@ -39,6 +39,8 @@ #include "RNA_define.h" +#include "SEQ_iterator.h" +#include "SEQ_select.h" #include "SEQ_sequencer.h" /* For menu, popup, icons, etc. */ diff --git a/source/blender/editors/space_sequencer/sequencer_view.c b/source/blender/editors/space_sequencer/sequencer_view.c index 250a0afc717..8805d5af227 100644 --- a/source/blender/editors/space_sequencer/sequencer_view.c +++ b/source/blender/editors/space_sequencer/sequencer_view.c @@ -38,7 +38,9 @@ #include "RNA_define.h" +#include "SEQ_select.h" #include "SEQ_sequencer.h" +#include "SEQ_time.h" /* For menu, popup, icons, etc. */ #include "ED_anim_api.h" diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c index 19146db3719..b11e2a32b87 100644 --- a/source/blender/editors/space_sequencer/space_sequencer.c +++ b/source/blender/editors/space_sequencer/space_sequencer.c @@ -52,6 +52,7 @@ #include "RNA_access.h" #include "SEQ_sequencer.h" +#include "SEQ_utils.h" #include "UI_interface.h" #include "UI_resources.h" diff --git a/source/blender/editors/transform/transform_convert_sequencer.c b/source/blender/editors/transform/transform_convert_sequencer.c index 83e384010bd..ebb0b6823a3 100644 --- a/source/blender/editors/transform/transform_convert_sequencer.c +++ b/source/blender/editors/transform/transform_convert_sequencer.c @@ -32,7 +32,11 @@ #include "ED_markers.h" +#include "SEQ_relations.h" #include "SEQ_sequencer.h" +#include "SEQ_time.h" +#include "SEQ_transform.h" +#include "SEQ_utils.h" #include "UI_view2d.h" diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index 8d20f1686f2..d407cea0033 100644 --- a/source/blender/editors/transform/transform_snap.c +++ b/source/blender/editors/transform/transform_snap.c @@ -42,6 +42,7 @@ #include "RNA_access.h" #include "SEQ_sequencer.h" +#include "SEQ_time.h" #include "WM_types.h" diff --git a/source/blender/editors/util/ed_util_imbuf.c b/source/blender/editors/util/ed_util_imbuf.c index ca97a7b21c3..0f2e280251f 100644 --- a/source/blender/editors/util/ed_util_imbuf.c +++ b/source/blender/editors/util/ed_util_imbuf.c @@ -42,6 +42,7 @@ #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" +#include "SEQ_render.h" #include "SEQ_sequencer.h" #include "UI_view2d.h" diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index 2c95d49612f..046e233fd05 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -57,7 +57,7 @@ #include "RNA_define.h" -#include "SEQ_sequencer.h" +#include "SEQ_iterator.h" #include diff --git a/source/blender/makesrna/intern/rna_camera.c b/source/blender/makesrna/intern/rna_camera.c index 2ac8b50f381..9d0ee90de60 100644 --- a/source/blender/makesrna/intern/rna_camera.c +++ b/source/blender/makesrna/intern/rna_camera.c @@ -40,7 +40,7 @@ # include "DEG_depsgraph.h" # include "DEG_depsgraph_build.h" -# include "SEQ_sequencer.h" +# include "SEQ_relations.h" static float rna_Camera_angle_get(PointerRNA *ptr) { diff --git a/source/blender/makesrna/intern/rna_color.c b/source/blender/makesrna/intern/rna_color.c index 2293b892ddb..39aeeb430c2 100644 --- a/source/blender/makesrna/intern/rna_color.c +++ b/source/blender/makesrna/intern/rna_color.c @@ -60,7 +60,8 @@ # include "IMB_colormanagement.h" # include "IMB_imbuf.h" -# include "SEQ_sequencer.h" +# include "SEQ_iterator.h" +# include "SEQ_relations.h" static int rna_CurveMapping_curves_length(PointerRNA *ptr) { diff --git a/source/blender/makesrna/intern/rna_movieclip.c b/source/blender/makesrna/intern/rna_movieclip.c index e7f697b281d..d32872d1682 100644 --- a/source/blender/makesrna/intern/rna_movieclip.c +++ b/source/blender/makesrna/intern/rna_movieclip.c @@ -49,7 +49,7 @@ # include "DNA_screen_types.h" # include "DNA_space_types.h" -# include "SEQ_sequencer.h" +# include "SEQ_relations.h" static void rna_MovieClip_reload_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index bce10b42ea8..b93922e46f2 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -699,7 +699,9 @@ const EnumPropertyItem rna_enum_transform_orientation_items[] = { # include "DEG_depsgraph_build.h" # include "DEG_depsgraph_query.h" +# include "SEQ_relations.h" # include "SEQ_sequencer.h" +# include "SEQ_sound.h" # ifdef WITH_FREESTYLE # include "FRS_freestyle.h" diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c index 43d65a4380b..4ab32d54665 100644 --- a/source/blender/makesrna/intern/rna_sequencer.c +++ b/source/blender/makesrna/intern/rna_sequencer.c @@ -46,7 +46,18 @@ #include "rna_internal.h" +#include "SEQ_add.h" +#include "SEQ_effects.h" +#include "SEQ_iterator.h" +#include "SEQ_modifier.h" +#include "SEQ_prefetch.h" +#include "SEQ_proxy.h" +#include "SEQ_relations.h" #include "SEQ_sequencer.h" +#include "SEQ_sound.h" +#include "SEQ_time.h" +#include "SEQ_transform.h" +#include "SEQ_utils.h" #include "WM_types.h" diff --git a/source/blender/makesrna/intern/rna_sequencer_api.c b/source/blender/makesrna/intern/rna_sequencer_api.c index 67497c2da2a..070fb08c3b4 100644 --- a/source/blender/makesrna/intern/rna_sequencer_api.c +++ b/source/blender/makesrna/intern/rna_sequencer_api.c @@ -51,6 +51,10 @@ # include "IMB_imbuf.h" # include "IMB_imbuf_types.h" +# include "SEQ_add.h" +# include "SEQ_edit.h" +# include "SEQ_relations.h" +# include "SEQ_render.h" # include "SEQ_sequencer.h" # include "WM_api.h" diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 5604ccd9655..acfb317c616 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -53,7 +53,7 @@ #include "rna_internal.h" -#include "SEQ_sequencer.h" +#include "SEQ_relations.h" #include "WM_api.h" #include "WM_types.h" diff --git a/source/blender/render/intern/pipeline.c b/source/blender/render/intern/pipeline.c index fc6ff51976d..f484977d2b4 100644 --- a/source/blender/render/intern/pipeline.c +++ b/source/blender/render/intern/pipeline.c @@ -88,7 +88,8 @@ #include "RE_pipeline.h" #include "RE_texture.h" -#include "SEQ_sequencer.h" +#include "SEQ_relations.h" +#include "SEQ_render.h" #include "../../windowmanager/WM_api.h" /* XXX */ #include "../../windowmanager/wm_window.h" /* XXX */ diff --git a/source/blender/sequencer/CMakeLists.txt b/source/blender/sequencer/CMakeLists.txt index db46fe91718..82e303806b3 100644 --- a/source/blender/sequencer/CMakeLists.txt +++ b/source/blender/sequencer/CMakeLists.txt @@ -44,7 +44,22 @@ set(INC_SYS ) set(SRC + SEQ_add.h + SEQ_clipboard.h + SEQ_edit.h + SEQ_effects.h + SEQ_iterator.h + SEQ_modifier.h + SEQ_prefetch.h + SEQ_proxy.h + SEQ_relations.h + SEQ_render.h + SEQ_select.h SEQ_sequencer.h + SEQ_sound.h + SEQ_time.h + SEQ_transform.h + SEQ_utils.h intern/clipboard.c intern/effects.c diff --git a/source/blender/sequencer/SEQ_add.h b/source/blender/sequencer/SEQ_add.h new file mode 100644 index 00000000000..9ed617e6963 --- /dev/null +++ b/source/blender/sequencer/SEQ_add.h @@ -0,0 +1,89 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2004 Blender Foundation. + * All rights reserved. + */ + +#pragma once + +/** \file + * \ingroup sequencer + */ + +#ifdef __cplusplus +extern "C" { +#endif + +struct Scene; +struct Sequence; +struct ListBase; +struct bContext; + +/* api for adding new sequence strips */ +typedef struct SeqLoadInfo { + int start_frame; + int end_frame; + int channel; + int flag; /* use sound, replace sel */ + int type; + int len; /* only for image strips */ + char path[1024]; /* 1024 = FILE_MAX */ + eSeqImageFitMethod fit_method; + + /* multiview */ + char views_format; + struct Stereo3dFormat *stereo3d_format; + + /* return values */ + char name[64]; + struct Sequence *seq_sound; /* for movie's */ + int tot_success; + int tot_error; +} SeqLoadInfo; + +/* SeqLoadInfo.flag */ +#define SEQ_LOAD_REPLACE_SEL (1 << 0) +#define SEQ_LOAD_FRAME_ADVANCE (1 << 1) +#define SEQ_LOAD_MOVIE_SOUND (1 << 2) +#define SEQ_LOAD_SOUND_CACHE (1 << 3) +#define SEQ_LOAD_SYNC_FPS (1 << 4) +#define SEQ_LOAD_SOUND_MONO (1 << 5) + +/* use as an api function */ +typedef struct Sequence *(*SeqLoadFn)(struct bContext *, ListBase *, struct SeqLoadInfo *); + +struct Sequence *SEQ_add_image_strip(struct bContext *C, + ListBase *seqbasep, + struct SeqLoadInfo *seq_load); +struct Sequence *SEQ_add_sound_strip(struct bContext *C, + ListBase *seqbasep, + struct SeqLoadInfo *seq_load); +struct Sequence *SEQ_add_movie_strip(struct bContext *C, + ListBase *seqbasep, + struct SeqLoadInfo *seq_load); +void SEQ_add_reload_new_file(struct Main *bmain, + struct Scene *scene, + struct Sequence *seq, + const bool lock_range); +void SEQ_add_movie_reload_if_needed(struct Main *bmain, + struct Scene *scene, + struct Sequence *seq, + bool *r_was_reloaded, + bool *r_can_produce_frames); + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/sequencer/SEQ_clipboard.h b/source/blender/sequencer/SEQ_clipboard.h new file mode 100644 index 00000000000..4b2bf69a8ac --- /dev/null +++ b/source/blender/sequencer/SEQ_clipboard.h @@ -0,0 +1,41 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2004 Blender Foundation. + * All rights reserved. + */ + +#pragma once + +/** \file + * \ingroup sequencer + */ + +#ifdef __cplusplus +extern "C" { +#endif + +struct ListBase; +struct Main; + +extern struct ListBase seqbase_clipboard; +extern int seqbase_clipboard_frame; +void SEQ_clipboard_pointers_store(struct Main *bmain, struct ListBase *seqbase); +void SEQ_clipboard_pointers_restore(struct ListBase *seqbase, struct Main *bmain); +void SEQ_clipboard_free(void); + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/sequencer/SEQ_edit.h b/source/blender/sequencer/SEQ_edit.h new file mode 100644 index 00000000000..b0c5d46d713 --- /dev/null +++ b/source/blender/sequencer/SEQ_edit.h @@ -0,0 +1,59 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2004 Blender Foundation. + * All rights reserved. + */ + +#pragma once + +/** \file + * \ingroup sequencer + */ + +#ifdef __cplusplus +extern "C" { +#endif + +struct Scene; +struct Sequence; +struct Main; +struct ListBase; + +int SEQ_edit_sequence_swap(struct Sequence *seq_a, struct Sequence *seq_b, const char **error_str); +void SEQ_edit_flag_for_removal(struct Scene *scene, + struct ListBase *seqbase, + struct Sequence *seq); +void SEQ_edit_remove_flagged_sequences(struct Scene *scene, struct ListBase *seqbase); +void SEQ_edit_update_muting(struct Editing *ed); + +typedef enum eSeqSplitMethod { + SEQ_SPLIT_SOFT, + SEQ_SPLIT_HARD, +} eSeqSplitMethod; + +struct Sequence *SEQ_edit_strip_split(struct Main *bmain, + struct Scene *scene, + struct ListBase *seqbase, + struct Sequence *seq, + const int timeline_frame, + const eSeqSplitMethod method); +bool SEQ_edit_remove_gaps(struct Scene *scene, + struct ListBase *seqbase, + const int initial_frame, + const bool remove_all_gaps); +#ifdef __cplusplus +} +#endif diff --git a/source/blender/sequencer/SEQ_effects.h b/source/blender/sequencer/SEQ_effects.h new file mode 100644 index 00000000000..1258efd2694 --- /dev/null +++ b/source/blender/sequencer/SEQ_effects.h @@ -0,0 +1,118 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2004 Blender Foundation. + * All rights reserved. + */ + +#pragma once + +/** \file + * \ingroup sequencer + */ + +#ifdef __cplusplus +extern "C" { +#endif + +struct Sequence; +struct ImBuf; +struct SeqRenderData; +struct TextVars; + +/* Wipe effect */ +enum { + DO_SINGLE_WIPE, + DO_DOUBLE_WIPE, + /* DO_BOX_WIPE, */ /* UNUSED */ + /* DO_CROSS_WIPE, */ /* UNUSED */ + DO_IRIS_WIPE, + DO_CLOCK_WIPE, +}; + +struct SeqEffectHandle { + bool multithreaded; + bool supports_mask; + + /* constructors & destructor */ + /* init is _only_ called on first creation */ + void (*init)(struct Sequence *seq); + + /* number of input strips needed + * (called directly after construction) */ + int (*num_inputs)(void); + + /* load is called first time after readblenfile in + * get_sequence_effect automatically */ + void (*load)(struct Sequence *seqconst); + + /* duplicate */ + void (*copy)(struct Sequence *dst, struct Sequence *src, const int flag); + + /* destruct */ + void (*free)(struct Sequence *seq, const bool do_id_user); + + /* returns: -1: no input needed, + * 0: no early out, + * 1: out = ibuf1, + * 2: out = ibuf2 */ + int (*early_out)(struct Sequence *seq, float facf0, float facf1); + + /* stores the y-range of the effect IPO */ + void (*store_icu_yrange)(struct Sequence *seq, short adrcode, float *ymin, float *ymax); + + /* stores the default facf0 and facf1 if no IPO is present */ + void (*get_default_fac)(struct Sequence *seq, float timeline_frame, float *facf0, float *facf1); + + /* execute the effect + * sequence effects are only required to either support + * float-rects or byte-rects + * (mixed cases are handled one layer up...) */ + + struct ImBuf *(*execute)(const struct SeqRenderData *context, + struct Sequence *seq, + float timeline_frame, + float facf0, + float facf1, + struct ImBuf *ibuf1, + struct ImBuf *ibuf2, + struct ImBuf *ibuf3); + + struct ImBuf *(*init_execution)(const struct SeqRenderData *context, + struct ImBuf *ibuf1, + struct ImBuf *ibuf2, + struct ImBuf *ibuf3); + + void (*execute_slice)(const struct SeqRenderData *context, + struct Sequence *seq, + float timeline_frame, + float facf0, + float facf1, + struct ImBuf *ibuf1, + struct ImBuf *ibuf2, + struct ImBuf *ibuf3, + int start_line, + int total_lines, + struct ImBuf *out); +}; + +struct SeqEffectHandle SEQ_effect_handle_get(struct Sequence *seq); +int SEQ_effect_get_num_inputs(int seq_type); +void SEQ_effect_text_font_unload(struct TextVars *data, const bool do_id_user); +void SEQ_effect_text_font_load(struct TextVars *data, const bool do_id_user); + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/sequencer/SEQ_iterator.h b/source/blender/sequencer/SEQ_iterator.h new file mode 100644 index 00000000000..05fd706a8de --- /dev/null +++ b/source/blender/sequencer/SEQ_iterator.h @@ -0,0 +1,75 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2004 Blender Foundation. + * All rights reserved. + */ + +#pragma once + +/** \file + * \ingroup sequencer + */ + +#ifdef __cplusplus +extern "C" { +#endif + +struct Sequence; +struct Editing; + +typedef struct SeqIterator { + struct Sequence **array; + int tot, cur; + + struct Sequence *seq; + int valid; +} SeqIterator; + +#define SEQ_ALL_BEGIN(ed, _seq) \ + { \ + SeqIterator iter_macro; \ + for (SEQ_iterator_begin(ed, &iter_macro, false); iter_macro.valid; \ + SEQ_iterator_next(&iter_macro)) { \ + _seq = iter_macro.seq; + +#define SEQ_ALL_END \ + } \ + SEQ_iterator_end(&iter_macro); \ + } \ + ((void)0) + +#define SEQ_CURRENT_BEGIN(_ed, _seq) \ + { \ + SeqIterator iter_macro; \ + for (SEQ_iterator_begin(_ed, &iter_macro, true); iter_macro.valid; \ + SEQ_iterator_next(&iter_macro)) { \ + _seq = iter_macro.seq; + +#define SEQ_CURRENT_END SEQ_ALL_END + +void SEQ_iterator_begin(struct Editing *ed, SeqIterator *iter, const bool use_current_sequences); +void SEQ_iterator_next(SeqIterator *iter); +void SEQ_iterator_end(SeqIterator *iter); +int SEQ_iterator_seqbase_recursive_apply(struct ListBase *seqbase, + int (*apply_fn)(struct Sequence *seq, void *), + void *arg); +int SEQ_iterator_recursive_apply(struct Sequence *seq, + int (*apply_fn)(struct Sequence *, void *), + void *arg); + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/sequencer/SEQ_modifier.h b/source/blender/sequencer/SEQ_modifier.h new file mode 100644 index 00000000000..74948db24d4 --- /dev/null +++ b/source/blender/sequencer/SEQ_modifier.h @@ -0,0 +1,88 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2004 Blender Foundation. + * All rights reserved. + */ + +#pragma once + +/** \file + * \ingroup sequencer + */ + +#ifdef __cplusplus +extern "C" { +#endif + +struct Scene; +struct Sequence; +struct ListBase; +struct SequenceModifierData; +struct SeqRenderData; +struct ImBuf; +struct BlendDataReader; +struct BlendLibReader; +struct BlendWriter; + +typedef struct SequenceModifierTypeInfo { + /* default name for the modifier */ + char name[64]; /* MAX_NAME */ + + /* DNA structure name used on load/save filed */ + char struct_name[64]; /* MAX_NAME */ + + /* size of modifier data structure, used by allocation */ + int struct_size; + + /* data initialization */ + void (*init_data)(struct SequenceModifierData *smd); + + /* free data used by modifier, + * only modifier-specific data should be freed, modifier descriptor would + * be freed outside of this callback + */ + void (*free_data)(struct SequenceModifierData *smd); + + /* copy data from one modifier to another */ + void (*copy_data)(struct SequenceModifierData *smd, struct SequenceModifierData *target); + + /* apply modifier on a given image buffer */ + void (*apply)(struct SequenceModifierData *smd, struct ImBuf *ibuf, struct ImBuf *mask); +} SequenceModifierTypeInfo; + +const struct SequenceModifierTypeInfo *SEQ_modifier_type_info_get(int type); +struct SequenceModifierData *SEQ_modifier_new(struct Sequence *seq, const char *name, int type); +bool SEQ_modifier_remove(struct Sequence *seq, struct SequenceModifierData *smd); +void SEQ_modifier_clear(struct Sequence *seq); +void SEQ_modifier_free(struct SequenceModifierData *smd); +void SEQ_modifier_unique_name(struct Sequence *seq, struct SequenceModifierData *smd); +struct SequenceModifierData *SEQ_modifier_find_by_name(struct Sequence *seq, const char *name); +struct ImBuf *SEQ_modifier_apply_stack(const struct SeqRenderData *context, + struct Sequence *seq, + struct ImBuf *ibuf, + int timeline_frame); +void SEQ_modifier_list_copy(struct Sequence *seqn, struct Sequence *seq); +int SEQ_sequence_supports_modifiers(struct Sequence *seq); + +void SEQ_modifier_blend_write(struct BlendWriter *writer, struct ListBase *modbase); +void SEQ_modifier_blend_read_data(struct BlendDataReader *reader, struct ListBase *lb); +void SEQ_modifier_blend_read_lib(struct BlendLibReader *reader, + struct Scene *scene, + struct ListBase *lb); + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/sequencer/SEQ_prefetch.h b/source/blender/sequencer/SEQ_prefetch.h new file mode 100644 index 00000000000..2ec8d509a91 --- /dev/null +++ b/source/blender/sequencer/SEQ_prefetch.h @@ -0,0 +1,39 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2004 Blender Foundation. + * All rights reserved. + */ + +#pragma once + +/** \file + * \ingroup sequencer + */ + +#ifdef __cplusplus +extern "C" { +#endif + +struct Scene; +struct Main; + +void SEQ_prefetch_stop_all(void); +void SEQ_prefetch_stop(struct Scene *scene); +bool SEQ_prefetch_need_redraw(struct Main *bmain, struct Scene *scene); + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/sequencer/SEQ_proxy.h b/source/blender/sequencer/SEQ_proxy.h new file mode 100644 index 00000000000..b909ac7b02d --- /dev/null +++ b/source/blender/sequencer/SEQ_proxy.h @@ -0,0 +1,57 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2004 Blender Foundation. + * All rights reserved. + */ + +#pragma once + +/** \file + * \ingroup sequencer + */ + +#ifdef __cplusplus +extern "C" { +#endif + +struct Scene; +struct Main; +struct GSet; +struct Sequence; +struct ListBase; +struct Depsgraph; +struct SeqIndexBuildContext; +struct ListBase; + +bool SEQ_proxy_rebuild_context(struct Main *bmain, + struct Depsgraph *depsgraph, + struct Scene *scene, + struct Sequence *seq, + struct GSet *file_list, + struct ListBase *queue); +void SEQ_proxy_rebuild(struct SeqIndexBuildContext *context, + short *stop, + short *do_update, + float *progress); +void SEQ_proxy_rebuild_finish(struct SeqIndexBuildContext *context, bool stop); +void SEQ_proxy_set(struct Sequence *seq, bool value); +bool SEQ_can_use_proxy(struct Sequence *seq, int psize); +int SEQ_rendersize_to_proxysize(int render_size); +double SEQ_rendersize_to_scale_factor(int size); + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/sequencer/SEQ_relations.h b/source/blender/sequencer/SEQ_relations.h new file mode 100644 index 00000000000..d0c5d2a474b --- /dev/null +++ b/source/blender/sequencer/SEQ_relations.h @@ -0,0 +1,73 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2004 Blender Foundation. + * All rights reserved. + */ + +#pragma once + +/** \file + * \ingroup sequencer + */ + +#ifdef __cplusplus +extern "C" { +#endif + +struct Scene; +struct Sequence; +struct Main; +struct ListBase; +struct ReportList; +struct MovieClip; + +void SEQ_relations_sequence_free_anim(struct Sequence *seq); +void SEQ_relations_update_changed_seq_and_deps(struct Scene *scene, + struct Sequence *changed_seq, + int len_change, + int ibuf_change); +bool SEQ_relations_check_scene_recursion(struct Scene *scene, struct ReportList *reports); +bool SEQ_relations_render_loop_check(struct Sequence *seq_main, struct Sequence *seq); +void SEQ_relations_free_imbuf(struct Scene *scene, struct ListBase *seqbasep, bool for_render); +void SEQ_relations_invalidate_cache_raw(struct Scene *scene, struct Sequence *seq); +void SEQ_relations_invalidate_cache_preprocessed(struct Scene *scene, struct Sequence *seq); +void SEQ_relations_invalidate_cache_composite(struct Scene *scene, struct Sequence *seq); +void SEQ_relations_invalidate_dependent(struct Scene *scene, struct Sequence *seq); +void SEQ_relations_invalidate_scene_strips(struct Main *bmain, struct Scene *scene_target); +void SEQ_relations_invalidate_movieclip_strips(struct Main *bmain, struct MovieClip *clip_target); +void SEQ_relations_invalidate_cache_in_range(struct Scene *scene, + struct Sequence *seq, + struct Sequence *range_mask, + int invalidate_types); +void SEQ_relations_free_all_anim_ibufs(struct Scene *scene, int timeline_frame); +/* A debug and development function which checks whether sequences have unique UUIDs. + * Errors will be reported to the console. */ +void SEQ_relations_check_uuids_unique_and_report(const struct Scene *scene); +/* Generate new UUID for the given sequence. */ +void SEQ_relations_session_uuid_generate(struct Sequence *sequence); + +void SEQ_cache_cleanup(struct Scene *scene); +void SEQ_cache_iterate(struct Scene *scene, + void *userdata, + bool callback_init(void *userdata, size_t item_count), + bool callback_iter(void *userdata, + struct Sequence *seq, + int timeline_frame, + int cache_type, + float cost)); +#ifdef __cplusplus +} +#endif diff --git a/source/blender/sequencer/SEQ_render.h b/source/blender/sequencer/SEQ_render.h new file mode 100644 index 00000000000..fea68c14c7b --- /dev/null +++ b/source/blender/sequencer/SEQ_render.h @@ -0,0 +1,88 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2004 Blender Foundation. + * All rights reserved. + */ + +#pragma once + +/** \file + * \ingroup sequencer + */ + +#ifdef __cplusplus +extern "C" { +#endif + +struct Scene; +struct Editing; +struct Sequence; +struct bSound; +struct Main; +struct ListBase; + +typedef enum eSeqTaskId { + SEQ_TASK_MAIN_RENDER, + SEQ_TASK_PREFETCH_RENDER, +} eSeqTaskId; + +typedef struct SeqRenderData { + struct Main *bmain; + struct Depsgraph *depsgraph; + struct Scene *scene; + int rectx; + int recty; + int preview_render_size; + int for_render; + int motion_blur_samples; + float motion_blur_shutter; + bool skip_cache; + bool is_proxy_render; + bool is_prefetch_render; + int view_id; + /* ID of task for asigning temp cache entries to particular task(thread, etc.) */ + eSeqTaskId task_id; + + /* special case for OpenGL render */ + struct GPUOffScreen *gpu_offscreen; + // int gpu_samples; + // bool gpu_full_samples; +} SeqRenderData; + +struct ImBuf *SEQ_render_give_ibuf(const SeqRenderData *context, + float timeline_frame, + int chanshown); +struct ImBuf *SEQ_render_give_ibuf_direct(const SeqRenderData *context, + float timeline_frame, + struct Sequence *seq); +void SEQ_render_init_colorspace(struct Sequence *seq); +void SEQ_render_new_render_data(struct Main *bmain, + struct Depsgraph *depsgraph, + struct Scene *scene, + int rectx, + int recty, + int preview_render_size, + int for_render, + SeqRenderData *r_context); +int SEQ_render_evaluate_frame(struct ListBase *seqbase, int timeline_frame); +struct StripElem *SEQ_render_give_stripelem(struct Sequence *seq, int timeline_frame); + +void SEQ_render_imbuf_from_sequencer_space(struct Scene *scene, struct ImBuf *ibuf); +void SEQ_render_pixel_from_sequencer_space_v4(struct Scene *scene, float pixel[4]); + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/sequencer/SEQ_select.h b/source/blender/sequencer/SEQ_select.h new file mode 100644 index 00000000000..5a65f9c0d8c --- /dev/null +++ b/source/blender/sequencer/SEQ_select.h @@ -0,0 +1,41 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2004 Blender Foundation. + * All rights reserved. + */ + +#pragma once + +/** \file + * \ingroup sequencer + */ + +#ifdef __cplusplus +extern "C" { +#endif + +struct Scene; +struct Sequence; + +struct Sequence *SEQ_select_active_get(struct Scene *scene); +int SEQ_select_active_get_pair(struct Scene *scene, + struct Sequence **seq_act, + struct Sequence **seq_other); +void SEQ_select_active_set(struct Scene *scene, struct Sequence *seq); + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/sequencer/SEQ_sequencer.h b/source/blender/sequencer/SEQ_sequencer.h index b2068a0d690..37ad71b64bd 100644 --- a/source/blender/sequencer/SEQ_sequencer.h +++ b/source/blender/sequencer/SEQ_sequencer.h @@ -23,15 +23,12 @@ * \ingroup sequencer */ -#include "DNA_scene_types.h" - #ifdef __cplusplus extern "C" { #endif -struct BlendDataReader; -struct BlendLibReader; -struct BlendWriter; +#include "DNA_scene_types.h" + struct Depsgraph; struct Editing; struct GPUOffScreen; @@ -54,16 +51,6 @@ struct BlendDataReader; struct BlendLibReader; struct SequencerToolSettings; -/* Wipe effect */ -enum { - DO_SINGLE_WIPE, - DO_DOUBLE_WIPE, - /* DO_BOX_WIPE, */ /* UNUSED */ - /* DO_CROSS_WIPE, */ /* UNUSED */ - DO_IRIS_WIPE, - DO_CLOCK_WIPE, -}; - /* RNA enums, just to be more readable */ enum { SEQ_SIDE_MOUSE = -1, @@ -74,576 +61,39 @@ enum { SEQ_SIDE_NO_CHANGE, }; -/* ********************************************************************** - * sequencer.c - * - * Sequencer iterators - * ********************************************************************** - */ - -typedef struct SeqIterator { - struct Sequence **array; - int tot, cur; - - struct Sequence *seq; - int valid; -} SeqIterator; - -#define SEQ_ALL_BEGIN(ed, _seq) \ - { \ - SeqIterator iter_macro; \ - for (SEQ_iterator_begin(ed, &iter_macro, false); iter_macro.valid; \ - SEQ_iterator_next(&iter_macro)) { \ - _seq = iter_macro.seq; - -#define SEQ_ALL_END \ - } \ - SEQ_iterator_end(&iter_macro); \ - } \ - ((void)0) - -#define SEQ_CURRENT_BEGIN(_ed, _seq) \ - { \ - SeqIterator iter_macro; \ - for (SEQ_iterator_begin(_ed, &iter_macro, true); iter_macro.valid; \ - SEQ_iterator_next(&iter_macro)) { \ - _seq = iter_macro.seq; - -#define SEQ_CURRENT_END SEQ_ALL_END - -void SEQ_iterator_begin(struct Editing *ed, SeqIterator *iter, const bool use_current_sequences); -void SEQ_iterator_next(SeqIterator *iter); -void SEQ_iterator_end(SeqIterator *iter); - -/* ********************************************************************** - * render.c - * - * Sequencer render functions - * ********************************************************************** - */ - -typedef enum eSeqTaskId { - SEQ_TASK_MAIN_RENDER, - SEQ_TASK_PREFETCH_RENDER, -} eSeqTaskId; - -typedef struct SeqRenderData { - struct Main *bmain; - struct Depsgraph *depsgraph; - struct Scene *scene; - int rectx; - int recty; - int preview_render_size; - int for_render; - int motion_blur_samples; - float motion_blur_shutter; - bool skip_cache; - bool is_proxy_render; - bool is_prefetch_render; - int view_id; - /* ID of task for asigning temp cache entries to particular task(thread, etc.) */ - eSeqTaskId task_id; - - /* special case for OpenGL render */ - struct GPUOffScreen *gpu_offscreen; - // int gpu_samples; - // bool gpu_full_samples; -} SeqRenderData; - -struct ImBuf *SEQ_render_give_ibuf(const SeqRenderData *context, - float timeline_frame, - int chanshown); -struct ImBuf *SEQ_render_give_ibuf_direct(const SeqRenderData *context, - float timeline_frame, - struct Sequence *seq); -void SEQ_render_init_colorspace(struct Sequence *seq); -void SEQ_render_new_render_data(struct Main *bmain, - struct Depsgraph *depsgraph, - struct Scene *scene, - int rectx, - int recty, - int preview_render_size, - int for_render, - SeqRenderData *r_context); -int SEQ_render_evaluate_frame(struct ListBase *seqbase, int timeline_frame); -struct StripElem *SEQ_render_give_stripelem(struct Sequence *seq, int timeline_frame); - -/* ********************************************************************** - * render.c - * - * Sequencer color space functions - * ********************************************************************** */ - -void SEQ_render_imbuf_from_sequencer_space(struct Scene *scene, struct ImBuf *ibuf); -void SEQ_render_pixel_from_sequencer_space_v4(struct Scene *scene, float pixel[4]); +#define SEQ_CACHE_COST_MAX 10.0f -/* ********************************************************************** - * sequencer.c - * - * Sequencer scene functions - * ********************************************************************** */ +/* seq_dupli' flags */ +#define SEQ_DUPE_UNIQUE_NAME (1 << 0) +#define SEQ_DUPE_CONTEXT (1 << 1) +#define SEQ_DUPE_ANIM (1 << 2) +#define SEQ_DUPE_ALL (1 << 3) /* otherwise only selected are copied */ +#define SEQ_DUPE_IS_RECURSIVE_CALL (1 << 4) struct SequencerToolSettings *SEQ_tool_settings_init(void); void SEQ_tool_settings_free(struct SequencerToolSettings *tool_settings); eSeqImageFitMethod SEQ_tool_settings_fit_method_get(struct Scene *scene); void SEQ_tool_settings_fit_method_set(struct Scene *scene, eSeqImageFitMethod fit_method); - struct SequencerToolSettings *SEQ_tool_settings_copy(struct SequencerToolSettings *tool_settings); struct Editing *SEQ_editing_get(struct Scene *scene, bool alloc); struct Editing *SEQ_editing_ensure(struct Scene *scene); void SEQ_editing_free(struct Scene *scene, const bool do_id_user); struct ListBase *SEQ_active_seqbase_get(const struct Editing *ed); -void SEQ_sort(struct Scene *scene); -struct Sequence *SEQ_sequence_from_strip_elem(ListBase *seqbase, struct StripElem *se); -struct Sequence *SEQ_select_active_get(struct Scene *scene); -int SEQ_select_active_get_pair(struct Scene *scene, - struct Sequence **seq_act, - struct Sequence **seq_other); -void SEQ_select_active_set(struct Scene *scene, struct Sequence *seq); -struct Mask *SEQ_active_mask_get(struct Scene *scene); -/* apply functions recursively */ -int SEQ_iterator_seqbase_recursive_apply(struct ListBase *seqbase, - int (*apply_fn)(struct Sequence *seq, void *), - void *arg); -int SEQ_iterator_recursive_apply(struct Sequence *seq, - int (*apply_fn)(struct Sequence *, void *), - void *arg); -float SEQ_time_sequence_get_fps(struct Scene *scene, struct Sequence *seq); -int SEQ_time_find_next_prev_edit(struct Scene *scene, - int timeline_frame, - const short side, - const bool do_skip_mute, - const bool do_center, - const bool do_unselected); -/* maintenance functions, mostly for RNA */ +struct Sequence *SEQ_sequence_alloc(ListBase *lb, int timeline_frame, int machine, int type); void SEQ_sequence_free(struct Scene *scene, struct Sequence *seq, const bool do_clean_animdata); -void SEQ_relations_sequence_free_anim(struct Sequence *seq); -const char *SEQ_sequence_give_name(struct Sequence *seq); -ListBase *SEQ_get_seqbase_from_sequence(struct Sequence *seq, int *r_offset); -void SEQ_time_update_sequence(struct Scene *scene, struct Sequence *seq); -void SEQ_time_update_sequence_bounds(struct Scene *scene, struct Sequence *seq); -void SEQ_add_reload_new_file(struct Main *bmain, - struct Scene *scene, - struct Sequence *seq, - const bool lock_range); -void SEQ_add_movie_reload_if_needed(struct Main *bmain, - struct Scene *scene, - struct Sequence *seq, - bool *r_was_reloaded, - bool *r_can_produce_frames); -void SEQ_alpha_mode_from_file_extension(struct Sequence *seq); -void SEQ_relations_update_changed_seq_and_deps(struct Scene *scene, - struct Sequence *changed_seq, - int len_change, - int ibuf_change); -bool SEQ_relations_check_scene_recursion(struct Scene *scene, struct ReportList *reports); -bool SEQ_relations_render_loop_check(struct Sequence *seq_main, struct Sequence *seq); -int SEQ_time_cmp_time_startdisp(const void *a, const void *b); - -/* ********************************************************************** - * proxy.c - * - * Proxy functions - * ********************************************************************** */ - -bool SEQ_proxy_rebuild_context(struct Main *bmain, - struct Depsgraph *depsgraph, - struct Scene *scene, - struct Sequence *seq, - struct GSet *file_list, - ListBase *queue); -void SEQ_proxy_rebuild(struct SeqIndexBuildContext *context, - short *stop, - short *do_update, - float *progress); -void SEQ_proxy_rebuild_finish(struct SeqIndexBuildContext *context, bool stop); -void SEQ_proxy_set(struct Sequence *seq, bool value); -bool SEQ_can_use_proxy(struct Sequence *seq, int psize); -int SEQ_rendersize_to_proxysize(int render_size); -double SEQ_rendersize_to_scale_factor(int size); - -/* ********************************************************************** - * image_cache.c - * - * Sequencer memory cache management functions - * ********************************************************************** */ - -void SEQ_cache_cleanup(struct Scene *scene); -void SEQ_cache_iterate(struct Scene *scene, - void *userdata, - bool callback_init(void *userdata, size_t item_count), - bool callback_iter(void *userdata, - struct Sequence *seq, - int timeline_frame, - int cache_type, - float cost)); - -/* ********************************************************************** - * prefetch.c - * - * Sequencer frame prefetching - * ********************************************************************** */ - -#define SEQ_CACHE_COST_MAX 10.0f -void SEQ_prefetch_stop_all(void); -void SEQ_prefetch_stop(struct Scene *scene); -bool SEQ_prefetch_need_redraw(struct Main *bmain, struct Scene *scene); - -/* ********************************************************************** - * sequencer.c - * - * Sequencer editing functions - * ********************************************************************** - */ - -/* for transform but also could use elsewhere */ -int SEQ_transform_get_left_handle_frame(struct Sequence *seq, bool metaclip); -int SEQ_transform_get_right_handle_frame(struct Sequence *seq, bool metaclip); -void SEQ_transform_set_left_handle_frame(struct Sequence *seq, int val); -void SEQ_transform_set_right_handle_frame(struct Sequence *seq, int val); -void SEQ_transform_handle_xlimits(struct Sequence *seq, int leftflag, int rightflag); -bool SEQ_transform_sequence_can_be_translated(struct Sequence *seq); -bool SEQ_transform_single_image_check(struct Sequence *seq); -void SEQ_transform_fix_single_image_seq_offsets(struct Sequence *seq); -bool SEQ_transform_test_overlap(struct ListBase *seqbasep, struct Sequence *test); -void SEQ_transform_translate_sequence(struct Scene *scene, struct Sequence *seq, int delta); -const struct Sequence *SEQ_get_topmost_sequence(const struct Scene *scene, int frame); -struct ListBase *SEQ_get_seqbase_by_seq(struct ListBase *seqbase, struct Sequence *seq); void SEQ_offset_animdata(struct Scene *scene, struct Sequence *seq, int ofs); void SEQ_dupe_animdata(struct Scene *scene, const char *name_src, const char *name_dst); -bool SEQ_transform_seqbase_shuffle_ex(struct ListBase *seqbasep, - struct Sequence *test, - struct Scene *evil_scene, - int channel_delta); -bool SEQ_transform_seqbase_shuffle(struct ListBase *seqbasep, - struct Sequence *test, - struct Scene *evil_scene); -bool SEQ_transform_seqbase_shuffle_time(ListBase *seqbasep, - struct Scene *evil_scene, - ListBase *markers, - const bool use_sync_markers); -bool SEQ_transform_seqbase_isolated_sel_check(struct ListBase *seqbase); -void SEQ_relations_free_imbuf(struct Scene *scene, struct ListBase *seqbasep, bool for_render); struct Sequence *SEQ_sequence_dupli_recursive(const struct Scene *scene_src, struct Scene *scene_dst, struct ListBase *new_seq_list, struct Sequence *seq, int dupe_flag); -int SEQ_edit_sequence_swap(struct Sequence *seq_a, struct Sequence *seq_b, const char **error_str); -void SEQ_sound_update_bounds_all(struct Scene *scene); -void SEQ_sound_update_bounds(struct Scene *scene, struct Sequence *seq); -void SEQ_sound_update_muting(struct Editing *ed); -void SEQ_sound_update(struct Scene *scene, struct bSound *sound); -void SEQ_sound_update_length(struct Main *bmain, struct Scene *scene); -void SEQ_sequence_base_unique_name_recursive(ListBase *seqbasep, struct Sequence *seq); void SEQ_sequence_base_dupli_recursive(const struct Scene *scene_src, struct Scene *scene_dst, struct ListBase *nseqbase, const struct ListBase *seqbase, int dupe_flag, const int flag); -bool SEQ_sequence_has_source(struct Sequence *seq); -struct Sequence *SEQ_get_sequence_by_name(struct ListBase *seqbase, - const char *name, - bool recursive); -void SEQ_edit_flag_for_removal(struct Scene *scene, - struct ListBase *seqbase, - struct Sequence *seq); -void SEQ_edit_remove_flagged_sequences(struct Scene *scene, struct ListBase *seqbase); - -/* ********************************************************************** - * sequencer.c - * - * Cache invalidation - * ********************************************************************** - */ - -void SEQ_relations_invalidate_cache_raw(struct Scene *scene, struct Sequence *seq); -void SEQ_relations_invalidate_cache_preprocessed(struct Scene *scene, struct Sequence *seq); -void SEQ_relations_invalidate_cache_composite(struct Scene *scene, struct Sequence *seq); -void SEQ_relations_invalidate_dependent(struct Scene *scene, struct Sequence *seq); -void SEQ_relations_invalidate_scene_strips(struct Main *bmain, struct Scene *scene_target); -void SEQ_relations_invalidate_movieclip_strips(struct Main *bmain, struct MovieClip *clip_target); -void SEQ_relations_invalidate_cache_in_range(struct Scene *scene, - struct Sequence *seq, - struct Sequence *range_mask, - int invalidate_types); -void SEQ_relations_free_all_anim_ibufs(struct Scene *scene, int timeline_frame); - -/* ********************************************************************** - * util.c - * - * Add strips - * ********************************************************************** - */ - -void SEQ_set_scale_to_fit(const struct Sequence *seq, - const int image_width, - const int image_height, - const int preview_width, - const int preview_height, - const eSeqImageFitMethod fit_method); - -/* ********************************************************************** - * sequencer.c - * - * Add strips - * ********************************************************************** - */ - -/* api for adding new sequence strips */ -typedef struct SeqLoadInfo { - int start_frame; - int end_frame; - int channel; - int flag; /* use sound, replace sel */ - int type; - int len; /* only for image strips */ - char path[1024]; /* 1024 = FILE_MAX */ - eSeqImageFitMethod fit_method; - - /* multiview */ - char views_format; - struct Stereo3dFormat *stereo3d_format; - - /* return values */ - char name[64]; - struct Sequence *seq_sound; /* for movie's */ - int tot_success; - int tot_error; -} SeqLoadInfo; - -/* SeqLoadInfo.flag */ -#define SEQ_LOAD_REPLACE_SEL (1 << 0) -#define SEQ_LOAD_FRAME_ADVANCE (1 << 1) -#define SEQ_LOAD_MOVIE_SOUND (1 << 2) -#define SEQ_LOAD_SOUND_CACHE (1 << 3) -#define SEQ_LOAD_SYNC_FPS (1 << 4) -#define SEQ_LOAD_SOUND_MONO (1 << 5) - -/* seq_dupli' flags */ -#define SEQ_DUPE_UNIQUE_NAME (1 << 0) -#define SEQ_DUPE_CONTEXT (1 << 1) -#define SEQ_DUPE_ANIM (1 << 2) -#define SEQ_DUPE_ALL (1 << 3) /* otherwise only selected are copied */ -#define SEQ_DUPE_IS_RECURSIVE_CALL (1 << 4) - -/* use as an api function */ -typedef struct Sequence *(*SeqLoadFn)(struct bContext *, ListBase *, struct SeqLoadInfo *); - -struct Sequence *SEQ_sequence_alloc(ListBase *lb, int timeline_frame, int machine, int type); -struct Sequence *SEQ_add_image_strip(struct bContext *C, - ListBase *seqbasep, - struct SeqLoadInfo *seq_load); -struct Sequence *SEQ_add_sound_strip(struct bContext *C, - ListBase *seqbasep, - struct SeqLoadInfo *seq_load); -struct Sequence *SEQ_add_movie_strip(struct bContext *C, - ListBase *seqbasep, - struct SeqLoadInfo *seq_load); - -/* ********************************************************************** - * modifier.c - * - * Modifiers - * ********************************************************************** - */ - -typedef struct SequenceModifierTypeInfo { - /* default name for the modifier */ - char name[64]; /* MAX_NAME */ - - /* DNA structure name used on load/save filed */ - char struct_name[64]; /* MAX_NAME */ - - /* size of modifier data structure, used by allocation */ - int struct_size; - - /* data initialization */ - void (*init_data)(struct SequenceModifierData *smd); - - /* free data used by modifier, - * only modifier-specific data should be freed, modifier descriptor would - * be freed outside of this callback - */ - void (*free_data)(struct SequenceModifierData *smd); - - /* copy data from one modifier to another */ - void (*copy_data)(struct SequenceModifierData *smd, struct SequenceModifierData *target); - - /* apply modifier on a given image buffer */ - void (*apply)(struct SequenceModifierData *smd, struct ImBuf *ibuf, struct ImBuf *mask); -} SequenceModifierTypeInfo; - -const struct SequenceModifierTypeInfo *SEQ_modifier_type_info_get(int type); -struct SequenceModifierData *SEQ_modifier_new(struct Sequence *seq, const char *name, int type); -bool SEQ_modifier_remove(struct Sequence *seq, struct SequenceModifierData *smd); -void SEQ_modifier_clear(struct Sequence *seq); -void SEQ_modifier_free(struct SequenceModifierData *smd); -void SEQ_modifier_unique_name(struct Sequence *seq, struct SequenceModifierData *smd); -struct SequenceModifierData *SEQ_modifier_find_by_name(struct Sequence *seq, const char *name); -struct ImBuf *SEQ_modifier_apply_stack(const SeqRenderData *context, - struct Sequence *seq, - struct ImBuf *ibuf, - int timeline_frame); -void SEQ_modifier_list_copy(struct Sequence *seqn, struct Sequence *seq); -int SEQ_sequence_supports_modifiers(struct Sequence *seq); - -void SEQ_modifier_blend_write(struct BlendWriter *writer, struct ListBase *modbase); -void SEQ_modifier_blend_read_data(struct BlendDataReader *reader, struct ListBase *lb); -void SEQ_modifier_blend_read_lib(struct BlendLibReader *reader, - struct Scene *scene, - struct ListBase *lb); - -/* ********************************************************************** - * seqeffects.c - * - * Sequencer effect strip management functions - * ********************************************************************** - */ - -struct SeqEffectHandle { - bool multithreaded; - bool supports_mask; - - /* constructors & destructor */ - /* init is _only_ called on first creation */ - void (*init)(struct Sequence *seq); - - /* number of input strips needed - * (called directly after construction) */ - int (*num_inputs)(void); - - /* load is called first time after readblenfile in - * get_sequence_effect automatically */ - void (*load)(struct Sequence *seqconst); - - /* duplicate */ - void (*copy)(struct Sequence *dst, struct Sequence *src, const int flag); - - /* destruct */ - void (*free)(struct Sequence *seq, const bool do_id_user); - - /* returns: -1: no input needed, - * 0: no early out, - * 1: out = ibuf1, - * 2: out = ibuf2 */ - int (*early_out)(struct Sequence *seq, float facf0, float facf1); - - /* stores the y-range of the effect IPO */ - void (*store_icu_yrange)(struct Sequence *seq, short adrcode, float *ymin, float *ymax); - - /* stores the default facf0 and facf1 if no IPO is present */ - void (*get_default_fac)(struct Sequence *seq, float timeline_frame, float *facf0, float *facf1); - - /* execute the effect - * sequence effects are only required to either support - * float-rects or byte-rects - * (mixed cases are handled one layer up...) */ - - struct ImBuf *(*execute)(const SeqRenderData *context, - struct Sequence *seq, - float timeline_frame, - float facf0, - float facf1, - struct ImBuf *ibuf1, - struct ImBuf *ibuf2, - struct ImBuf *ibuf3); - - struct ImBuf *(*init_execution)(const SeqRenderData *context, - struct ImBuf *ibuf1, - struct ImBuf *ibuf2, - struct ImBuf *ibuf3); - - void (*execute_slice)(const SeqRenderData *context, - struct Sequence *seq, - float timeline_frame, - float facf0, - float facf1, - struct ImBuf *ibuf1, - struct ImBuf *ibuf2, - struct ImBuf *ibuf3, - int start_line, - int total_lines, - struct ImBuf *out); -}; - -struct SeqEffectHandle SEQ_effect_handle_get(struct Sequence *seq); -int SEQ_effect_get_num_inputs(int seq_type); -void SEQ_effect_text_font_unload(struct TextVars *data, const bool do_id_user); -void SEQ_effect_text_font_load(struct TextVars *data, const bool do_id_user); - -/* ********************************************************************** - * sequencer.c - * - * Clipboard - * ********************************************************************** - */ - -extern ListBase seqbase_clipboard; -extern int seqbase_clipboard_frame; -void SEQ_clipboard_pointers_store(struct Main *bmain, struct ListBase *seqbase); -void SEQ_clipboard_pointers_restore(struct ListBase *seqbase, struct Main *bmain); -void SEQ_clipboard_free(void); - -/* ********************************************************************** - * sequencer.c - * - * Depsgraph - * ********************************************************************** - */ - -/* A debug and development function which checks whether sequences have unique UUIDs. - * Errors will be reported to the console. */ -void SEQ_relations_check_uuids_unique_and_report(const struct Scene *scene); -/* Generate new UUID for the given sequence. */ -void SEQ_relations_session_uuid_generate(struct Sequence *sequence); - -/* ********************************************************************** - * strip_edit.c - * - * Editing functions - * ********************************************************************** - */ - -typedef enum eSeqSplitMethod { - SEQ_SPLIT_SOFT, - SEQ_SPLIT_HARD, -} eSeqSplitMethod; - -struct Sequence *SEQ_edit_strip_split(struct Main *bmain, - struct Scene *scene, - struct ListBase *seqbase, - struct Sequence *seq, - const int timeline_frame, - const eSeqSplitMethod method); -bool SEQ_edit_remove_gaps(struct Scene *scene, - struct ListBase *seqbase, - const int initial_frame, - const bool remove_all_gaps); - -/* ********************************************************************** - * strip_time.c - * - * Editing functions - * ********************************************************************** - */ - -void SEQ_timeline_boundbox(const struct Scene *scene, - const struct ListBase *seqbase, - struct rctf *rect); - -/* ********************************************************************** - * strip_transform.c - * - * Editing functions - * ********************************************************************** - */ - -void SEQ_transform_offset_after_frame(struct Scene *scene, - struct ListBase *seqbase, - const int delta, - const int timeline_frame); #ifdef __cplusplus } diff --git a/source/blender/sequencer/SEQ_sound.h b/source/blender/sequencer/SEQ_sound.h new file mode 100644 index 00000000000..d04aed259fb --- /dev/null +++ b/source/blender/sequencer/SEQ_sound.h @@ -0,0 +1,44 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2004 Blender Foundation. + * All rights reserved. + */ + +#pragma once + +/** \file + * \ingroup sequencer + */ + +#ifdef __cplusplus +extern "C" { +#endif + +struct Scene; +struct Editing; +struct Sequence; +struct bSound; +struct Main; +struct ListBase; + +void SEQ_sound_update_bounds_all(struct Scene *scene); +void SEQ_sound_update_bounds(struct Scene *scene, struct Sequence *seq); +void SEQ_sound_update(struct Scene *scene, struct bSound *sound); +void SEQ_sound_update_length(struct Main *bmain, struct Scene *scene); + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/sequencer/SEQ_time.h b/source/blender/sequencer/SEQ_time.h new file mode 100644 index 00000000000..7fb47d42354 --- /dev/null +++ b/source/blender/sequencer/SEQ_time.h @@ -0,0 +1,51 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2004 Blender Foundation. + * All rights reserved. + */ + +#pragma once + +/** \file + * \ingroup sequencer + */ + +#ifdef __cplusplus +extern "C" { +#endif + +struct Scene; +struct Sequence; +struct ListBase; +struct rctf; + +void SEQ_timeline_boundbox(const struct Scene *scene, + const struct ListBase *seqbase, + struct rctf *rect); +float SEQ_time_sequence_get_fps(struct Scene *scene, struct Sequence *seq); +int SEQ_time_find_next_prev_edit(struct Scene *scene, + int timeline_frame, + const short side, + const bool do_skip_mute, + const bool do_center, + const bool do_unselected); +void SEQ_time_update_sequence(struct Scene *scene, struct Sequence *seq); +void SEQ_time_update_sequence_bounds(struct Scene *scene, struct Sequence *seq); +int SEQ_time_cmp_time_startdisp(const void *a, const void *b); + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/sequencer/SEQ_transform.h b/source/blender/sequencer/SEQ_transform.h new file mode 100644 index 00000000000..10d9c781dcb --- /dev/null +++ b/source/blender/sequencer/SEQ_transform.h @@ -0,0 +1,63 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2004 Blender Foundation. + * All rights reserved. + */ + +#pragma once + +/** \file + * \ingroup sequencer + */ + +#ifdef __cplusplus +extern "C" { +#endif + +struct Scene; +struct Sequence; +struct ListBase; + +int SEQ_transform_get_left_handle_frame(struct Sequence *seq, bool metaclip); +int SEQ_transform_get_right_handle_frame(struct Sequence *seq, bool metaclip); +void SEQ_transform_set_left_handle_frame(struct Sequence *seq, int val); +void SEQ_transform_set_right_handle_frame(struct Sequence *seq, int val); +void SEQ_transform_handle_xlimits(struct Sequence *seq, int leftflag, int rightflag); +bool SEQ_transform_sequence_can_be_translated(struct Sequence *seq); +bool SEQ_transform_single_image_check(struct Sequence *seq); +void SEQ_transform_fix_single_image_seq_offsets(struct Sequence *seq); +bool SEQ_transform_test_overlap(struct ListBase *seqbasep, struct Sequence *test); +void SEQ_transform_translate_sequence(struct Scene *scene, struct Sequence *seq, int delta); +bool SEQ_transform_seqbase_shuffle_ex(struct ListBase *seqbasep, + struct Sequence *test, + struct Scene *evil_scene, + int channel_delta); +bool SEQ_transform_seqbase_shuffle(struct ListBase *seqbasep, + struct Sequence *test, + struct Scene *evil_scene); +bool SEQ_transform_seqbase_shuffle_time(struct ListBase *seqbasep, + struct Scene *evil_scene, + struct ListBase *markers, + const bool use_sync_markers); +bool SEQ_transform_seqbase_isolated_sel_check(struct ListBase *seqbase); +void SEQ_transform_offset_after_frame(struct Scene *scene, + struct ListBase *seqbase, + const int delta, + const int timeline_frame); + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/sequencer/SEQ_util.h b/source/blender/sequencer/SEQ_util.h new file mode 100644 index 00000000000..9dae0a25a37 --- /dev/null +++ b/source/blender/sequencer/SEQ_util.h @@ -0,0 +1,58 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2004 Blender Foundation. + * All rights reserved. + */ + +#pragma once + +/** \file + * \ingroup sequencer + */ + +#include "DNA_scene_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct Scene; +struct Sequence; +struct ListBase; + +void SEQ_set_scale_to_fit(const struct Sequence *seq, + const int image_width, + const int image_height, + const int preview_width, + const int preview_height, + const eSeqImageFitMethod fit_method); +void SEQ_sort(struct Scene *scene); +void SEQ_sequence_base_unique_name_recursive(ListBase *seqbasep, struct Sequence *seq); +const char *SEQ_sequence_give_name(struct Sequence *seq); +ListBase *SEQ_get_seqbase_from_sequence(struct Sequence *seq, int *r_offset); +const struct Sequence *SEQ_get_topmost_sequence(const struct Scene *scene, int frame); +struct ListBase *SEQ_get_seqbase_by_seq(struct ListBase *seqbase, struct Sequence *seq); +struct Sequence *SEQ_sequence_from_strip_elem(ListBase *seqbase, struct StripElem *se); +struct Sequence *SEQ_get_sequence_by_name(struct ListBase *seqbase, + const char *name, + bool recursive); +struct Mask *SEQ_active_mask_get(struct Scene *scene); +void SEQ_alpha_mode_from_file_extension(struct Sequence *seq); +bool SEQ_sequence_has_source(struct Sequence *seq); + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/sequencer/SEQ_utils.h b/source/blender/sequencer/SEQ_utils.h new file mode 100644 index 00000000000..417d257ddd7 --- /dev/null +++ b/source/blender/sequencer/SEQ_utils.h @@ -0,0 +1,60 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2004 Blender Foundation. + * All rights reserved. + */ + +#pragma once + +/** \file + * \ingroup sequencer + */ + +#include "DNA_scene_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct Scene; +struct Sequence; +struct ListBase; +struct Mask; +struct StripElem; + +void SEQ_sort(struct Scene *scene); +void SEQ_sequence_base_unique_name_recursive(struct ListBase *seqbasep, struct Sequence *seq); +const char *SEQ_sequence_give_name(struct Sequence *seq); +struct ListBase *SEQ_get_seqbase_from_sequence(struct Sequence *seq, int *r_offset); +const struct Sequence *SEQ_get_topmost_sequence(const struct Scene *scene, int frame); +struct ListBase *SEQ_get_seqbase_by_seq(struct ListBase *seqbase, struct Sequence *seq); +struct Sequence *SEQ_sequence_from_strip_elem(struct ListBase *seqbase, struct StripElem *se); +struct Sequence *SEQ_get_sequence_by_name(struct ListBase *seqbase, + const char *name, + bool recursive); +struct Mask *SEQ_active_mask_get(struct Scene *scene); +void SEQ_alpha_mode_from_file_extension(struct Sequence *seq); +bool SEQ_sequence_has_source(struct Sequence *seq); +void SEQ_set_scale_to_fit(const struct Sequence *seq, + const int image_width, + const int image_height, + const int preview_width, + const int preview_height, + const eSeqImageFitMethod fit_method); + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/sequencer/intern/clipboard.c b/source/blender/sequencer/intern/clipboard.c index 7a9a06a744a..29cb749bc99 100644 --- a/source/blender/sequencer/intern/clipboard.c +++ b/source/blender/sequencer/intern/clipboard.c @@ -37,7 +37,7 @@ #include "BKE_scene.h" #include "BKE_sound.h" -#include "SEQ_sequencer.h" +#include "SEQ_clipboard.h" #include "sequencer.h" diff --git a/source/blender/sequencer/intern/effects.c b/source/blender/sequencer/intern/effects.c index 58dd6d6e048..e8e80c8da83 100644 --- a/source/blender/sequencer/intern/effects.c +++ b/source/blender/sequencer/intern/effects.c @@ -59,7 +59,10 @@ #include "RE_pipeline.h" -#include "SEQ_sequencer.h" +#include "SEQ_effects.h" +#include "SEQ_proxy.h" +#include "SEQ_render.h" +#include "SEQ_utils.h" #include "BLF_api.h" diff --git a/source/blender/sequencer/intern/image_cache.c b/source/blender/sequencer/intern/image_cache.c index 6eb12df7186..2fe59f52bf4 100644 --- a/source/blender/sequencer/intern/image_cache.c +++ b/source/blender/sequencer/intern/image_cache.c @@ -48,6 +48,9 @@ #include "BKE_main.h" #include "BKE_scene.h" +#include "SEQ_prefetch.h" +#include "SEQ_relations.h" +#include "SEQ_render.h" #include "SEQ_sequencer.h" #include "image_cache.h" diff --git a/source/blender/sequencer/intern/iterator.c b/source/blender/sequencer/intern/iterator.c index 7d54795b150..bb4982d1468 100644 --- a/source/blender/sequencer/intern/iterator.c +++ b/source/blender/sequencer/intern/iterator.c @@ -35,7 +35,7 @@ #include "BKE_scene.h" -#include "SEQ_sequencer.h" +#include "SEQ_iterator.h" /* ************************* iterator ************************** */ /* *************** (replaces old WHILE_SEQ) ********************* */ diff --git a/source/blender/sequencer/intern/modifier.c b/source/blender/sequencer/intern/modifier.c index 99fa228e7a5..b6f56025e6b 100644 --- a/source/blender/sequencer/intern/modifier.c +++ b/source/blender/sequencer/intern/modifier.c @@ -44,7 +44,8 @@ #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" -#include "SEQ_sequencer.h" +#include "SEQ_modifier.h" +#include "SEQ_render.h" #include "BLO_read_write.h" diff --git a/source/blender/sequencer/intern/prefetch.c b/source/blender/sequencer/intern/prefetch.c index 5d769a18a19..5ffb2287e1c 100644 --- a/source/blender/sequencer/intern/prefetch.c +++ b/source/blender/sequencer/intern/prefetch.c @@ -53,7 +53,8 @@ #include "DEG_depsgraph_debug.h" #include "DEG_depsgraph_query.h" -#include "SEQ_sequencer.h" +#include "SEQ_prefetch.h" +#include "SEQ_render.h" #include "image_cache.h" #include "prefetch.h" diff --git a/source/blender/sequencer/intern/proxy.c b/source/blender/sequencer/intern/proxy.c index 72dc9708ccb..22d8daba696 100644 --- a/source/blender/sequencer/intern/proxy.c +++ b/source/blender/sequencer/intern/proxy.c @@ -54,6 +54,8 @@ #include "IMB_imbuf_types.h" #include "IMB_metadata.h" +#include "SEQ_proxy.h" +#include "SEQ_render.h" #include "SEQ_sequencer.h" #include "multiview.h" diff --git a/source/blender/sequencer/intern/render.c b/source/blender/sequencer/intern/render.c index 84f2a6df647..524bf7cd74c 100644 --- a/source/blender/sequencer/intern/render.c +++ b/source/blender/sequencer/intern/render.c @@ -64,7 +64,12 @@ #include "RE_engine.h" #include "RE_pipeline.h" +#include "SEQ_effects.h" +#include "SEQ_modifier.h" +#include "SEQ_proxy.h" +#include "SEQ_render.h" #include "SEQ_sequencer.h" +#include "SEQ_utils.h" #include "effects.h" #include "image_cache.h" diff --git a/source/blender/sequencer/intern/render.h b/source/blender/sequencer/intern/render.h index 46748415187..6875087df82 100644 --- a/source/blender/sequencer/intern/render.h +++ b/source/blender/sequencer/intern/render.h @@ -32,6 +32,7 @@ struct ListBase; struct Scene; struct SeqRenderData; struct Sequence; +struct SeqEffectHandle; #define EARLY_NO_INPUT -1 #define EARLY_DO_EFFECT 0 @@ -50,7 +51,7 @@ struct ImBuf *seq_render_give_ibuf_seqbase(const struct SeqRenderData *context, int chan_shown, struct ListBase *seqbasep); struct ImBuf *seq_render_effect_execute_threaded(struct SeqEffectHandle *sh, - const SeqRenderData *context, + const struct SeqRenderData *context, struct Sequence *seq, float timeline_frame, float facf0, diff --git a/source/blender/sequencer/intern/sequencer.c b/source/blender/sequencer/intern/sequencer.c index 51495e7bf02..79e8ba2f6c0 100644 --- a/source/blender/sequencer/intern/sequencer.c +++ b/source/blender/sequencer/intern/sequencer.c @@ -44,7 +44,13 @@ #include "IMB_colormanagement.h" #include "IMB_imbuf.h" +#include "SEQ_effects.h" +#include "SEQ_iterator.h" +#include "SEQ_modifier.h" +#include "SEQ_relations.h" +#include "SEQ_select.h" #include "SEQ_sequencer.h" +#include "SEQ_utils.h" #include "image_cache.h" #include "prefetch.h" diff --git a/source/blender/sequencer/intern/sound.c b/source/blender/sequencer/intern/sound.c index f62142d0112..1054dbeeba6 100644 --- a/source/blender/sequencer/intern/sound.c +++ b/source/blender/sequencer/intern/sound.c @@ -36,28 +36,11 @@ #include "BKE_scene.h" #include "BKE_sound.h" -#include "SEQ_sequencer.h" +#include "SEQ_sound.h" +#include "SEQ_time.h" #include "strip_time.h" -static void seq_sound_init(Scene *scene, Sequence *seq) -{ - if (seq->type == SEQ_TYPE_META) { - Sequence *seq_child; - for (seq_child = seq->seqbase.first; seq_child; seq_child = seq_child->next) { - seq_sound_init(scene, seq_child); - } - } - else { - if (seq->sound) { - seq->scene_sound = BKE_sound_add_scene_sound_defaults(scene, seq); - } - if (seq->scene) { - seq->scene_sound = BKE_sound_scene_add_scene_sound_defaults(scene, seq); - } - } -} - /* Unlike _update_sound_ funcs, these ones take info from audaspace to update sequence length! */ #ifdef WITH_AUDASPACE static bool sequencer_refresh_sound_length_recursive(Main *bmain, Scene *scene, ListBase *seqbase) diff --git a/source/blender/sequencer/intern/strip_add.c b/source/blender/sequencer/intern/strip_add.c index 4fe02b7fdd2..ba080a07879 100644 --- a/source/blender/sequencer/intern/strip_add.c +++ b/source/blender/sequencer/intern/strip_add.c @@ -53,7 +53,13 @@ #include "IMB_imbuf_types.h" #include "IMB_metadata.h" +#include "SEQ_add.h" +#include "SEQ_relations.h" +#include "SEQ_select.h" #include "SEQ_sequencer.h" +#include "SEQ_time.h" +#include "SEQ_transform.h" +#include "SEQ_utils.h" #include "multiview.h" #include "proxy.h" diff --git a/source/blender/sequencer/intern/strip_edit.c b/source/blender/sequencer/intern/strip_edit.c index 11f42c5de9d..bba026057d2 100644 --- a/source/blender/sequencer/intern/strip_edit.c +++ b/source/blender/sequencer/intern/strip_edit.c @@ -40,7 +40,12 @@ #include "strip_time.h" +#include "SEQ_add.h" +#include "SEQ_edit.h" +#include "SEQ_effects.h" #include "SEQ_sequencer.h" +#include "SEQ_time.h" +#include "SEQ_transform.h" int SEQ_edit_sequence_swap(Sequence *seq_a, Sequence *seq_b, const char **error_str) { @@ -124,7 +129,7 @@ static void seq_update_muting_recursive(ListBase *seqbasep, Sequence *metaseq, i } } -void SEQ_sound_update_muting(Editing *ed) +void SEQ_edit_update_muting(Editing *ed) { if (ed) { /* mute all sounds up to current metastack list */ diff --git a/source/blender/sequencer/intern/strip_relations.c b/source/blender/sequencer/intern/strip_relations.c index 939cafb09fd..18ae21e3a65 100644 --- a/source/blender/sequencer/intern/strip_relations.c +++ b/source/blender/sequencer/intern/strip_relations.c @@ -40,7 +40,11 @@ #include "IMB_imbuf.h" +#include "SEQ_iterator.h" +#include "SEQ_prefetch.h" +#include "SEQ_relations.h" #include "SEQ_sequencer.h" +#include "SEQ_time.h" #include "effects.h" #include "image_cache.h" diff --git a/source/blender/sequencer/intern/strip_select.c b/source/blender/sequencer/intern/strip_select.c index fbf28087825..58ae281ead1 100644 --- a/source/blender/sequencer/intern/strip_select.c +++ b/source/blender/sequencer/intern/strip_select.c @@ -29,6 +29,7 @@ #include "BKE_scene.h" +#include "SEQ_select.h" #include "SEQ_sequencer.h" Sequence *SEQ_select_active_get(Scene *scene) diff --git a/source/blender/sequencer/intern/strip_time.c b/source/blender/sequencer/intern/strip_time.c index a3b17a7c58c..c495ad6d8f1 100644 --- a/source/blender/sequencer/intern/strip_time.c +++ b/source/blender/sequencer/intern/strip_time.c @@ -36,7 +36,9 @@ #include "IMB_imbuf.h" +#include "SEQ_render.h" #include "SEQ_sequencer.h" +#include "SEQ_time.h" #include "strip_time.h" #include "utils.h" diff --git a/source/blender/sequencer/intern/strip_transform.c b/source/blender/sequencer/intern/strip_transform.c index 0cf3940dc54..3a0ba36b795 100644 --- a/source/blender/sequencer/intern/strip_transform.c +++ b/source/blender/sequencer/intern/strip_transform.c @@ -33,7 +33,11 @@ #include "BKE_scene.h" #include "BKE_sound.h" +#include "SEQ_effects.h" +#include "SEQ_relations.h" #include "SEQ_sequencer.h" +#include "SEQ_time.h" +#include "SEQ_transform.h" static int seq_tx_get_start(Sequence *seq) { diff --git a/source/blender/sequencer/intern/utils.c b/source/blender/sequencer/intern/utils.c index 40f2aca4714..a15465eb3c0 100644 --- a/source/blender/sequencer/intern/utils.c +++ b/source/blender/sequencer/intern/utils.c @@ -42,7 +42,11 @@ #include "BKE_main.h" #include "BKE_scene.h" +#include "SEQ_iterator.h" +#include "SEQ_relations.h" +#include "SEQ_select.h" #include "SEQ_sequencer.h" +#include "SEQ_utils.h" #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index be58575f99c..d513598cf19 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -80,7 +80,7 @@ #include "RE_engine.h" #include "RE_pipeline.h" /* RE_ free stuff */ -#include "SEQ_sequencer.h" /* free seq clipboard */ +#include "SEQ_clipboard.h" /* free seq clipboard */ #include "IMB_thumbs.h" diff --git a/source/blender/windowmanager/intern/wm_jobs.c b/source/blender/windowmanager/intern/wm_jobs.c index 2e794940f26..cf45d380c48 100644 --- a/source/blender/windowmanager/intern/wm_jobs.c +++ b/source/blender/windowmanager/intern/wm_jobs.c @@ -36,7 +36,7 @@ #include "BKE_context.h" #include "BKE_global.h" -#include "SEQ_sequencer.h" +#include "SEQ_prefetch.h" #include "WM_api.h" #include "WM_types.h" -- cgit v1.2.3 From 09be4a0917fbdb391341a6bfcc1e918fb75d0fd2 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Sat, 19 Dec 2020 10:07:13 -0600 Subject: Cleanup: Use typedef for UI emboss type enum Previously both `char` and `int` were used to represent this enum. Differential Revision: https://developer.blender.org/D9903 --- source/blender/editors/include/UI_interface.h | 12 +++++------ source/blender/editors/interface/interface.c | 4 ++-- .../blender/editors/interface/interface_intern.h | 8 ++++---- .../blender/editors/interface/interface_layout.c | 10 +++++----- .../blender/editors/interface/interface_widgets.c | 23 ++++++++++++---------- 5 files changed, 30 insertions(+), 27 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 05bedd526ed..2705dd27756 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -103,7 +103,7 @@ typedef struct uiPopupBlockHandle uiPopupBlockHandle; #define UI_SCREEN_MARGIN 10 /** #uiBlock.emboss and #uiBut.emboss */ -enum { +typedef enum eUIEmbossType { UI_EMBOSS = 0, /* use widget style for drawing */ UI_EMBOSS_NONE = 1, /* Nothing, only icon and/or text */ UI_EMBOSS_PULLDOWN = 2, /* Pulldown menu style */ @@ -115,7 +115,7 @@ enum { UI_EMBOSS_NONE_OR_STATUS = 4, UI_EMBOSS_UNDEFINED = 255, /* For layout engine, use emboss from block. */ -}; +} eUIEmbossType; /* uiBlock->direction */ enum { @@ -671,7 +671,7 @@ bool UI_popup_block_name_exists(const struct bScreen *screen, const char *name); uiBlock *UI_block_begin(const struct bContext *C, struct ARegion *region, const char *name, - char emboss); + eUIEmbossType emboss); void UI_block_end_ex(const struct bContext *C, uiBlock *block, const int xy[2], int r_xy[2]); void UI_block_end(const struct bContext *C, uiBlock *block); void UI_block_draw(const struct bContext *C, struct uiBlock *block); @@ -685,7 +685,7 @@ enum { }; void UI_block_theme_style_set(uiBlock *block, char theme_style); char UI_block_emboss_get(uiBlock *block); -void UI_block_emboss_set(uiBlock *block, char emboss); +void UI_block_emboss_set(uiBlock *block, eUIEmbossType emboss); bool UI_block_is_search_only(const uiBlock *block); void UI_block_set_search_only(uiBlock *block, bool search_only); @@ -1923,7 +1923,7 @@ void uiLayoutSetScaleX(uiLayout *layout, float scale); void uiLayoutSetScaleY(uiLayout *layout, float scale); void uiLayoutSetUnitsX(uiLayout *layout, float unit); void uiLayoutSetUnitsY(uiLayout *layout, float unit); -void uiLayoutSetEmboss(uiLayout *layout, char emboss); +void uiLayoutSetEmboss(uiLayout *layout, eUIEmbossType emboss); void uiLayoutSetPropSep(uiLayout *layout, bool is_sep); void uiLayoutSetPropDecorate(uiLayout *layout, bool is_sep); int uiLayoutGetLocalDir(const uiLayout *layout); @@ -1942,7 +1942,7 @@ float uiLayoutGetScaleX(uiLayout *layout); float uiLayoutGetScaleY(uiLayout *layout); float uiLayoutGetUnitsX(uiLayout *layout); float uiLayoutGetUnitsY(uiLayout *layout); -int uiLayoutGetEmboss(uiLayout *layout); +eUIEmbossType uiLayoutGetEmboss(uiLayout *layout); bool uiLayoutGetPropSep(uiLayout *layout); bool uiLayoutGetPropDecorate(uiLayout *layout); diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index 26fd75cc74c..7713efd1c78 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -3478,7 +3478,7 @@ void UI_block_region_set(uiBlock *block, ARegion *region) block->oldblock = oldblock; } -uiBlock *UI_block_begin(const bContext *C, ARegion *region, const char *name, char emboss) +uiBlock *UI_block_begin(const bContext *C, ARegion *region, const char *name, eUIEmbossType emboss) { wmWindow *window = CTX_wm_window(C); Scene *scene = CTX_data_scene(C); @@ -3529,7 +3529,7 @@ char UI_block_emboss_get(uiBlock *block) return block->emboss; } -void UI_block_emboss_set(uiBlock *block, char emboss) +void UI_block_emboss_set(uiBlock *block, eUIEmbossType emboss) { block->emboss = emboss; } diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index a35d9d5d336..c005b456b6a 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -220,8 +220,8 @@ struct uiBut { const char *disabled_info; BIFIconID icon; - /** emboss: UI_EMBOSS, UI_EMBOSS_NONE ... etc, copied from the #uiBlock.emboss */ - char emboss; + /** Copied from the #uiBlock.emboss */ + eUIEmbossType emboss; /** direction in a pie menu, used for collision detection (RadialDirection) */ signed char pie_dir; /** could be made into a single flag */ @@ -502,8 +502,8 @@ struct uiBlock { char direction; /** UI_BLOCK_THEME_STYLE_* */ char theme_style; - /** UI_EMBOSS, UI_EMBOSS_NONE ... etc, copied to #uiBut.emboss */ - char emboss; + /** Copied to #uiBut.emboss */ + eUIEmbossType emboss; bool auto_open; char _pad[5]; double auto_open_last; diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index 3b366688e59..3ea7a5f5973 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -172,7 +172,7 @@ struct uiLayout { /** For layouts inside gridflow, they and their items shall never have a fixed maximal size. */ bool variable_size; char alignment; - char emboss; + eUIEmbossType emboss; /** for fixed width or height to avoid UI size changes */ float units[2]; }; @@ -1189,7 +1189,7 @@ static uiBut *uiItemFullO_ptr_ex(uiLayout *layout, const int w = ui_text_icon_width(layout, name, icon, 0); - const int prev_emboss = layout->emboss; + const eUIEmbossType prev_emboss = layout->emboss; if (flag & UI_ITEM_R_NO_BG) { layout->emboss = UI_EMBOSS_NONE; } @@ -2120,7 +2120,7 @@ void uiItemFullR(uiLayout *layout, int w, h; ui_item_rna_size(layout, name, icon, ptr, prop, index, icon_only, compact, &w, &h); - const int prev_emboss = layout->emboss; + const eUIEmbossType prev_emboss = layout->emboss; if (no_bg) { layout->emboss = UI_EMBOSS_NONE; } @@ -4914,7 +4914,7 @@ void uiLayoutSetUnitsY(uiLayout *layout, float unit) layout->units[1] = unit; } -void uiLayoutSetEmboss(uiLayout *layout, char emboss) +void uiLayoutSetEmboss(uiLayout *layout, eUIEmbossType emboss) { layout->emboss = emboss; } @@ -4999,7 +4999,7 @@ float uiLayoutGetUnitsY(uiLayout *layout) return layout->units[1]; } -int uiLayoutGetEmboss(uiLayout *layout) +eUIEmbossType uiLayoutGetEmboss(uiLayout *layout) { if (layout->emboss == UI_EMBOSS_UNDEFINED) { return layout->root->block->emboss; diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index 7e883851876..4d81b1edf0c 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -264,7 +264,7 @@ typedef struct uiWidgetType { /* converted colors for state */ uiWidgetColors wcol; - void (*state)(struct uiWidgetType *, int state, int drawflag, char emboss); + void (*state)(struct uiWidgetType *, int state, int drawflag, eUIEmbossType emboss); void (*draw)(uiWidgetColors *, rcti *, int state, int roundboxalign); void (*custom)(uiBut *, uiWidgetColors *, rcti *, int state, int roundboxalign); void (*text)(const uiFontStyle *, const uiWidgetColors *, uiBut *, rcti *); @@ -2521,7 +2521,7 @@ static void widget_active_color(uiWidgetColors *wcol) static const uchar *widget_color_blend_from_flags(const uiWidgetStateColors *wcol_state, int state, int drawflag, - const char emboss) + const eUIEmbossType emboss) { /* Explicitly require #UI_EMBOSS_NONE_OR_STATUS for color blending with no emboss. */ if (emboss == UI_EMBOSS_NONE) { @@ -2547,7 +2547,7 @@ static const uchar *widget_color_blend_from_flags(const uiWidgetStateColors *wco } /* copy colors from theme, and set changes in it based on state */ -static void widget_state(uiWidgetType *wt, int state, int drawflag, char emboss) +static void widget_state(uiWidgetType *wt, int state, int drawflag, eUIEmbossType emboss) { uiWidgetStateColors *wcol_state = wt->wcol_state; @@ -2625,7 +2625,7 @@ static void widget_state(uiWidgetType *wt, int state, int drawflag, char emboss) * \{ */ /* sliders use special hack which sets 'item' as inner when drawing filling */ -static void widget_state_numslider(uiWidgetType *wt, int state, int drawflag, char emboss) +static void widget_state_numslider(uiWidgetType *wt, int state, int drawflag, eUIEmbossType emboss) { uiWidgetStateColors *wcol_state = wt->wcol_state; @@ -2648,7 +2648,10 @@ static void widget_state_numslider(uiWidgetType *wt, int state, int drawflag, ch } /* labels use theme colors for text */ -static void widget_state_option_menu(uiWidgetType *wt, int state, int drawflag, char emboss) +static void widget_state_option_menu(uiWidgetType *wt, + int state, + int drawflag, + eUIEmbossType emboss) { const bTheme *btheme = UI_GetTheme(); @@ -2668,7 +2671,7 @@ static void widget_state_option_menu(uiWidgetType *wt, int state, int drawflag, static void widget_state_nothing(uiWidgetType *wt, int UNUSED(state), int UNUSED(drawflag), - char UNUSED(emboss)) + eUIEmbossType UNUSED(emboss)) { wt->wcol = *(wt->wcol_theme); } @@ -2677,7 +2680,7 @@ static void widget_state_nothing(uiWidgetType *wt, static void widget_state_pulldown(uiWidgetType *wt, int UNUSED(state), int UNUSED(drawflag), - char UNUSED(emboss)) + eUIEmbossType UNUSED(emboss)) { wt->wcol = *(wt->wcol_theme); } @@ -2686,7 +2689,7 @@ static void widget_state_pulldown(uiWidgetType *wt, static void widget_state_pie_menu_item(uiWidgetType *wt, int state, int UNUSED(drawflag), - char UNUSED(emboss)) + eUIEmbossType UNUSED(emboss)) { wt->wcol = *(wt->wcol_theme); @@ -2721,7 +2724,7 @@ static void widget_state_pie_menu_item(uiWidgetType *wt, static void widget_state_menu_item(uiWidgetType *wt, int state, int UNUSED(drawflag), - char UNUSED(emboss)) + eUIEmbossType UNUSED(emboss)) { wt->wcol = *(wt->wcol_theme); @@ -4070,7 +4073,7 @@ static void widget_optionbut(uiWidgetColors *wcol, } /* labels use Editor theme colors for text */ -static void widget_state_label(uiWidgetType *wt, int state, int drawflag, char emboss) +static void widget_state_label(uiWidgetType *wt, int state, int drawflag, eUIEmbossType emboss) { if (state & UI_BUT_LIST_ITEM) { /* Override default label theme's colors. */ -- cgit v1.2.3 From 6538f1e600ad5e0ca04e8e166b848dd321023c4b Mon Sep 17 00:00:00 2001 From: Aaron Carlisle Date: Sat, 19 Dec 2020 14:40:31 -0500 Subject: Compositor: New Exposure Node This new node increases the radiance of an image by a scalar value. Previously, the only way to adjust the the exposure of an image was with math node or using the scene's color management. Reviewed By: jbakker Differential Revision: https://developer.blender.org/D9677 --- source/blender/blenkernel/BKE_node.h | 1 + source/blender/blenkernel/intern/node.c | 1 + source/blender/compositor/CMakeLists.txt | 4 ++ source/blender/compositor/intern/COM_Converter.cpp | 4 ++ .../compositor/nodes/COM_ColorExposureNode.cpp | 37 ++++++++++++++ .../compositor/nodes/COM_ColorExposureNode.h | 34 +++++++++++++ .../operations/COM_ColorExposureOperation.cpp | 57 ++++++++++++++++++++++ .../operations/COM_ColorExposureOperation.h | 49 +++++++++++++++++++ source/blender/makesrna/RNA_access.h | 1 + source/blender/nodes/CMakeLists.txt | 1 + source/blender/nodes/NOD_composite.h | 1 + source/blender/nodes/NOD_static_types.h | 1 + .../composite/nodes/node_composite_exposure.c | 46 +++++++++++++++++ 13 files changed, 237 insertions(+) create mode 100644 source/blender/compositor/nodes/COM_ColorExposureNode.cpp create mode 100644 source/blender/compositor/nodes/COM_ColorExposureNode.h create mode 100644 source/blender/compositor/operations/COM_ColorExposureOperation.cpp create mode 100644 source/blender/compositor/operations/COM_ColorExposureOperation.h create mode 100644 source/blender/nodes/composite/nodes/node_composite_exposure.c (limited to 'source/blender') diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index bc254b81afb..e18f46c9988 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -1204,6 +1204,7 @@ void ntreeGPUMaterialNodes(struct bNodeTree *localtree, #define CMP_NODE_SWITCH_VIEW 322 #define CMP_NODE_CRYPTOMATTE 323 #define CMP_NODE_DENOISE 324 +#define CMP_NODE_EXPOSURE 325 /* channel toggles */ #define CMP_CHAN_RGB 1 diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 511c16e9ff4..676d0bf9385 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -4496,6 +4496,7 @@ static void registerCompositNodes(void) register_node_type_cmp_hue_sat(); register_node_type_cmp_brightcontrast(); register_node_type_cmp_gamma(); + register_node_type_cmp_exposure(); register_node_type_cmp_invert(); register_node_type_cmp_alphaover(); register_node_type_cmp_zcombine(); diff --git a/source/blender/compositor/CMakeLists.txt b/source/blender/compositor/CMakeLists.txt index fec98f58261..26d29f72efb 100644 --- a/source/blender/compositor/CMakeLists.txt +++ b/source/blender/compositor/CMakeLists.txt @@ -213,6 +213,8 @@ set(SRC nodes/COM_ColorCorrectionNode.h nodes/COM_ColorCurveNode.cpp nodes/COM_ColorCurveNode.h + nodes/COM_ColorExposureNode.cpp + nodes/COM_ColorExposureNode.h nodes/COM_ColorRampNode.cpp nodes/COM_ColorRampNode.h nodes/COM_ColorToBWNode.cpp @@ -399,6 +401,8 @@ set(SRC operations/COM_ChromaMatteOperation.h operations/COM_ColorCurveOperation.cpp operations/COM_ColorCurveOperation.h + operations/COM_ColorExposureOperation.cpp + operations/COM_ColorExposureOperation.h operations/COM_ColorMatteOperation.cpp operations/COM_ColorMatteOperation.h operations/COM_ColorRampOperation.cpp diff --git a/source/blender/compositor/intern/COM_Converter.cpp b/source/blender/compositor/intern/COM_Converter.cpp index d8f67571ee5..08035940667 100644 --- a/source/blender/compositor/intern/COM_Converter.cpp +++ b/source/blender/compositor/intern/COM_Converter.cpp @@ -37,6 +37,7 @@ #include "COM_ColorBalanceNode.h" #include "COM_ColorCorrectionNode.h" #include "COM_ColorCurveNode.h" +#include "COM_ColorExposureNode.h" #include "COM_ColorMatteNode.h" #include "COM_ColorNode.h" #include "COM_ColorRampNode.h" @@ -411,6 +412,9 @@ Node *Converter::convert(bNode *b_node) case CMP_NODE_DENOISE: node = new DenoiseNode(b_node); break; + case CMP_NODE_EXPOSURE: + node = new ExposureNode(b_node); + break; } return node; } diff --git a/source/blender/compositor/nodes/COM_ColorExposureNode.cpp b/source/blender/compositor/nodes/COM_ColorExposureNode.cpp new file mode 100644 index 00000000000..10738fcfe47 --- /dev/null +++ b/source/blender/compositor/nodes/COM_ColorExposureNode.cpp @@ -0,0 +1,37 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright 2020, Blender Foundation. + */ + +#include "COM_ColorExposureNode.h" +#include "COM_ColorExposureOperation.h" +#include "COM_ExecutionSystem.h" + +ExposureNode::ExposureNode(bNode *editorNode) : Node(editorNode) +{ + /* pass */ +} + +void ExposureNode::convertToOperations(NodeConverter &converter, + const CompositorContext & /*context*/) const +{ + ExposureOperation *operation = new ExposureOperation(); + converter.addOperation(operation); + + converter.mapInputSocket(getInputSocket(0), operation->getInputSocket(0)); + converter.mapInputSocket(getInputSocket(1), operation->getInputSocket(1)); + converter.mapOutputSocket(getOutputSocket(0), operation->getOutputSocket(0)); +} diff --git a/source/blender/compositor/nodes/COM_ColorExposureNode.h b/source/blender/compositor/nodes/COM_ColorExposureNode.h new file mode 100644 index 00000000000..18aefb7eae4 --- /dev/null +++ b/source/blender/compositor/nodes/COM_ColorExposureNode.h @@ -0,0 +1,34 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright 2020, Blender Foundation. + */ + +#ifndef __COM_EXPOSURENODE_H__ +#define __COM_EXPOSURENODE_H__ + +#include "COM_Node.h" + +/** + * \brief ExposureNode + * \ingroup Node + */ +class ExposureNode : public Node { + public: + ExposureNode(bNode *editorNode); + void convertToOperations(NodeConverter &converter, const CompositorContext &context) const; +}; + +#endif diff --git a/source/blender/compositor/operations/COM_ColorExposureOperation.cpp b/source/blender/compositor/operations/COM_ColorExposureOperation.cpp new file mode 100644 index 00000000000..8a475432cc8 --- /dev/null +++ b/source/blender/compositor/operations/COM_ColorExposureOperation.cpp @@ -0,0 +1,57 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright 2020, Blender Foundation. + */ + +#include "COM_ColorExposureOperation.h" + +ExposureOperation::ExposureOperation() : NodeOperation() +{ + this->addInputSocket(COM_DT_COLOR); + this->addInputSocket(COM_DT_VALUE); + this->addOutputSocket(COM_DT_COLOR); + this->m_inputProgram = NULL; +} + +void ExposureOperation::initExecution() +{ + this->m_inputProgram = this->getInputSocketReader(0); + this->m_inputExposureProgram = this->getInputSocketReader(1); +} + +void ExposureOperation::executePixelSampled(float output[4], + float x, + float y, + PixelSampler sampler) +{ + float inputValue[4]; + float inputExposure[4]; + this->m_inputProgram->readSampled(inputValue, x, y, sampler); + this->m_inputExposureProgram->readSampled(inputExposure, x, y, sampler); + const float exposure = pow(2, inputExposure[0]); + + output[0] = inputValue[0] * exposure; + output[1] = inputValue[1] * exposure; + output[2] = inputValue[2] * exposure; + + output[3] = inputValue[3]; +} + +void ExposureOperation::deinitExecution() +{ + this->m_inputProgram = NULL; + this->m_inputExposureProgram = NULL; +} diff --git a/source/blender/compositor/operations/COM_ColorExposureOperation.h b/source/blender/compositor/operations/COM_ColorExposureOperation.h new file mode 100644 index 00000000000..a65d5acbe6c --- /dev/null +++ b/source/blender/compositor/operations/COM_ColorExposureOperation.h @@ -0,0 +1,49 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright 2020, Blender Foundation. + */ + +#ifndef __COM_COLOREXPOSUREOPERATION_H__ +#define __COM_COLOREXPOSUREOPERATION_H__ +#include "COM_NodeOperation.h" + +class ExposureOperation : public NodeOperation { + private: + /** + * Cached reference to the inputProgram + */ + SocketReader *m_inputProgram; + SocketReader *m_inputExposureProgram; + + public: + ExposureOperation(); + + /** + * the inner loop of this program + */ + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + + /** + * Initialize the execution + */ + void initExecution(); + + /** + * Deinitialize the execution + */ + void deinitExecution(); +}; +#endif diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index aaa948dbff6..2d2e8d1a686 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -149,6 +149,7 @@ extern StructRNA RNA_CompositorNodeDilateErode; extern StructRNA RNA_CompositorNodeDisplace; extern StructRNA RNA_CompositorNodeDistanceMatte; extern StructRNA RNA_CompositorNodeDoubleEdgeMask; +extern StructRNA RNA_CompositorNodeExposure; extern StructRNA RNA_CompositorNodeFilter; extern StructRNA RNA_CompositorNodeFlip; extern StructRNA RNA_CompositorNodeGamma; diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index 866cf74d35b..60d4ee8f7c4 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -73,6 +73,7 @@ set(SRC composite/nodes/node_composite_distanceMatte.c composite/nodes/node_composite_doubleEdgeMask.c composite/nodes/node_composite_ellipsemask.c + composite/nodes/node_composite_exposure.c composite/nodes/node_composite_filter.c composite/nodes/node_composite_flip.c composite/nodes/node_composite_gamma.c diff --git a/source/blender/nodes/NOD_composite.h b/source/blender/nodes/NOD_composite.h index 99bcb849ebd..6ad02986010 100644 --- a/source/blender/nodes/NOD_composite.h +++ b/source/blender/nodes/NOD_composite.h @@ -56,6 +56,7 @@ void register_node_type_cmp_mix_rgb(void); void register_node_type_cmp_hue_sat(void); void register_node_type_cmp_brightcontrast(void); void register_node_type_cmp_gamma(void); +void register_node_type_cmp_exposure(void); void register_node_type_cmp_invert(void); void register_node_type_cmp_alphaover(void); void register_node_type_cmp_zcombine(void); diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h index 5b61594cca1..5156bac0e73 100644 --- a/source/blender/nodes/NOD_static_types.h +++ b/source/blender/nodes/NOD_static_types.h @@ -222,6 +222,7 @@ DefNode(CompositorNode, CMP_NODE_CORNERPIN, 0, "CORNER DefNode(CompositorNode, CMP_NODE_SUNBEAMS, def_cmp_sunbeams, "SUNBEAMS", SunBeams, "Sun Beams", "" ) DefNode(CompositorNode, CMP_NODE_CRYPTOMATTE, def_cmp_cryptomatte, "CRYPTOMATTE", Cryptomatte, "Cryptomatte", "" ) DefNode(CompositorNode, CMP_NODE_DENOISE, def_cmp_denoise, "DENOISE", Denoise, "Denoise", "" ) +DefNode(CompositorNode, CMP_NODE_EXPOSURE, 0, "EXPOSURE", Exposure, "Exposure", "" ) DefNode(TextureNode, TEX_NODE_OUTPUT, def_tex_output, "OUTPUT", Output, "Output", "" ) DefNode(TextureNode, TEX_NODE_CHECKER, 0, "CHECKER", Checker, "Checker", "" ) diff --git a/source/blender/nodes/composite/nodes/node_composite_exposure.c b/source/blender/nodes/composite/nodes/node_composite_exposure.c new file mode 100644 index 00000000000..bd27e4a3d76 --- /dev/null +++ b/source/blender/nodes/composite/nodes/node_composite_exposure.c @@ -0,0 +1,46 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2020 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup cmpnodes + */ + +#include "node_composite_util.h" + +/* **************** Exposure ******************** */ + +static bNodeSocketTemplate cmp_node_exposure_in[] = { + {SOCK_RGBA, N_("Image"), 1.0f, 1.0f, 1.0f, 1.0f}, + {SOCK_FLOAT, N_("Exposure"), 0.0f, 0.0f, 0.0f, 0.0f, -10.0f, 10.0f, PROP_NONE}, + {-1, ""}, +}; +static bNodeSocketTemplate cmp_node_exposure_out[] = { + {SOCK_RGBA, N_("Image")}, + {-1, ""}, +}; + +void register_node_type_cmp_exposure(void) +{ + static bNodeType ntype; + + cmp_node_type_base(&ntype, CMP_NODE_EXPOSURE, "Exposure", NODE_CLASS_OP_COLOR, 0); + node_type_socket_templates(&ntype, cmp_node_exposure_in, cmp_node_exposure_out); + + nodeRegisterType(&ntype); +} -- cgit v1.2.3 From c4ff91aab76a9987ec109a733d39ff800ccbd15b Mon Sep 17 00:00:00 2001 From: Richard Antalik Date: Sun, 20 Dec 2020 01:51:23 +0100 Subject: VSE: Fix incorrect cache memory usage calculation If image is cached twice, it's size has been counted twice as well, but only image reference count is increased, not memory usage. Use `MEM_get_memory_in_use()` instead of size own tracking. --- source/blender/sequencer/intern/image_cache.c | 17 +++-------------- source/blender/sequencer/intern/image_cache.h | 2 +- 2 files changed, 4 insertions(+), 15 deletions(-) (limited to 'source/blender') diff --git a/source/blender/sequencer/intern/image_cache.c b/source/blender/sequencer/intern/image_cache.c index 2fe59f52bf4..2cc25ae8d38 100644 --- a/source/blender/sequencer/intern/image_cache.c +++ b/source/blender/sequencer/intern/image_cache.c @@ -147,7 +147,6 @@ typedef struct SeqCache { struct BLI_mempool *keys_pool; struct BLI_mempool *items_pool; struct SeqCacheKey *last_key; - size_t memory_used; SeqDiskCache *disk_cache; } SeqCache; @@ -796,10 +795,8 @@ static void seq_cache_keyfree(void *val) static void seq_cache_valfree(void *val) { SeqCacheItem *item = (SeqCacheItem *)val; - SeqCache *cache = item->cache_owner; if (item->ibuf) { - cache->memory_used -= IMB_get_size_in_memory(item->ibuf); IMB_freeImBuf(item->ibuf); } @@ -816,7 +813,6 @@ static void seq_cache_put_ex(SeqCache *cache, SeqCacheKey *key, ImBuf *ibuf) if (BLI_ghash_reinsert(cache->hash, key, item, seq_cache_keyfree, seq_cache_valfree)) { IMB_refImBuf(ibuf); cache->last_key = key; - cache->memory_used += IMB_get_size_in_memory(ibuf); } } @@ -994,7 +990,6 @@ static SeqCacheKey *seq_cache_get_item_for_removal(Scene *scene) */ bool seq_cache_recycle_item(Scene *scene) { - size_t memory_total = seq_cache_get_mem_total(); SeqCache *cache = seq_cache_get_from_scene(scene); if (!cache) { return false; @@ -1002,7 +997,7 @@ bool seq_cache_recycle_item(Scene *scene) seq_cache_lock(scene); - while (cache->memory_used > memory_total) { + while (seq_cache_is_full()) { SeqCacheKey *finalkey = seq_cache_get_item_for_removal(scene); if (finalkey) { @@ -1466,13 +1461,7 @@ void SEQ_cache_iterate(struct Scene *scene, seq_cache_unlock(scene); } -bool seq_cache_is_full(Scene *scene) +bool seq_cache_is_full(void) { - size_t memory_total = seq_cache_get_mem_total(); - SeqCache *cache = seq_cache_get_from_scene(scene); - if (!cache) { - return false; - } - - return memory_total < cache->memory_used; + return seq_cache_get_mem_total() < MEM_get_memory_in_use(); } diff --git a/source/blender/sequencer/intern/image_cache.h b/source/blender/sequencer/intern/image_cache.h index ed2d5dee910..ab28b1d3204 100644 --- a/source/blender/sequencer/intern/image_cache.h +++ b/source/blender/sequencer/intern/image_cache.h @@ -65,7 +65,7 @@ void seq_cache_cleanup_sequence(struct Scene *scene, struct Sequence *seq_changed, int invalidate_types, bool force_seq_changed_range); -bool seq_cache_is_full(struct Scene *scene); +bool seq_cache_is_full(void); #ifdef __cplusplus } -- cgit v1.2.3 From 38b77ef8b22173835b3bc80efc218c3e05b9e37d Mon Sep 17 00:00:00 2001 From: Richard Antalik Date: Sun, 20 Dec 2020 03:58:38 +0100 Subject: VSE: Remove cost calculation from cache This value was meant to be used for keeping images that are slowest to render in cache. Method of measurement was flawed, because it doesn't take UI overhead into consideration. Cache panel is to be removed because users should not have to tweak settings like this. It is not useful for development either, therefore it is removed completely. --- .../editors/space_sequencer/sequencer_draw.c | 6 +- source/blender/makesdna/DNA_sequence_types.h | 2 +- source/blender/makesrna/intern/rna_sequencer.c | 7 --- source/blender/sequencer/SEQ_relations.h | 13 ++-- source/blender/sequencer/intern/image_cache.c | 54 ++++++---------- source/blender/sequencer/intern/image_cache.h | 2 - source/blender/sequencer/intern/prefetch.c | 15 +++-- source/blender/sequencer/intern/prefetch.h | 2 +- source/blender/sequencer/intern/render.c | 73 ++++------------------ source/blender/sequencer/intern/sequencer.c | 1 - 10 files changed, 51 insertions(+), 124 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index 1b213746add..2ee0dcea5e5 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -2111,8 +2111,10 @@ static bool draw_cache_view_init_fn(void *userdata, size_t item_count) } /* Called as a callback */ -static bool draw_cache_view_iter_fn( - void *userdata, struct Sequence *seq, int timeline_frame, int cache_type, float UNUSED(cost)) +static bool draw_cache_view_iter_fn(void *userdata, + struct Sequence *seq, + int timeline_frame, + int cache_type) { CacheDrawData *drawdata = userdata; struct View2D *v2d = drawdata->v2d; diff --git a/source/blender/makesdna/DNA_sequence_types.h b/source/blender/makesdna/DNA_sequence_types.h index 1f16fa6d148..ef14a5c52d4 100644 --- a/source/blender/makesdna/DNA_sequence_types.h +++ b/source/blender/makesdna/DNA_sequence_types.h @@ -278,7 +278,7 @@ typedef struct Editing { struct SeqCache *cache; /* Cache control */ - float recycle_max_cost; + float recycle_max_cost; /* UNUSED only for versioning. */ int cache_flag; struct PrefetchJob *prefetch_job; diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c index 4ab32d54665..eed976c8df1 100644 --- a/source/blender/makesrna/intern/rna_sequencer.c +++ b/source/blender/makesrna/intern/rna_sequencer.c @@ -2101,13 +2101,6 @@ static void rna_def_editor(BlenderRNA *brna) "Prefetch Frames", "Render frames ahead of current frame in the background for faster playback"); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, NULL); - - prop = RNA_def_property(srna, "recycle_max_cost", PROP_FLOAT, PROP_NONE); - RNA_def_property_range(prop, 0.0f, SEQ_CACHE_COST_MAX); - RNA_def_property_ui_range(prop, 0.0f, SEQ_CACHE_COST_MAX, 0.1f, 1); - RNA_def_property_float_sdna(prop, NULL, "recycle_max_cost"); - RNA_def_property_ui_text( - prop, "Recycle Up to Cost", "Only frames with cost lower than this value will be recycled"); } static void rna_def_filter_video(StructRNA *srna) diff --git a/source/blender/sequencer/SEQ_relations.h b/source/blender/sequencer/SEQ_relations.h index d0c5d2a474b..b2e7ac9f007 100644 --- a/source/blender/sequencer/SEQ_relations.h +++ b/source/blender/sequencer/SEQ_relations.h @@ -60,14 +60,11 @@ void SEQ_relations_check_uuids_unique_and_report(const struct Scene *scene); void SEQ_relations_session_uuid_generate(struct Sequence *sequence); void SEQ_cache_cleanup(struct Scene *scene); -void SEQ_cache_iterate(struct Scene *scene, - void *userdata, - bool callback_init(void *userdata, size_t item_count), - bool callback_iter(void *userdata, - struct Sequence *seq, - int timeline_frame, - int cache_type, - float cost)); +void SEQ_cache_iterate( + struct Scene *scene, + void *userdata, + bool callback_init(void *userdata, size_t item_count), + bool callback_iter(void *userdata, struct Sequence *seq, int timeline_frame, int cache_type)); #ifdef __cplusplus } #endif diff --git a/source/blender/sequencer/intern/image_cache.c b/source/blender/sequencer/intern/image_cache.c index 2cc25ae8d38..40ad70cf9a0 100644 --- a/source/blender/sequencer/intern/image_cache.c +++ b/source/blender/sequencer/intern/image_cache.c @@ -938,7 +938,6 @@ static SeqCacheKey *seq_cache_get_item_for_removal(Scene *scene) GHashIterator gh_iter; BLI_ghashIterator_init(&gh_iter, cache->hash); int total_count = 0; - int cheap_count = 0; while (!BLI_ghashIterator_done(&gh_iter)) { key = BLI_ghashIterator_getKey(&gh_iter); @@ -959,25 +958,22 @@ static SeqCacheKey *seq_cache_get_item_for_removal(Scene *scene) total_count++; - if (key->cost <= scene->ed->recycle_max_cost) { - cheap_count++; - if (lkey) { - if (key->timeline_frame < lkey->timeline_frame) { - lkey = key; - } - } - else { + if (lkey) { + if (key->timeline_frame < lkey->timeline_frame) { lkey = key; } - if (rkey) { - if (key->timeline_frame > rkey->timeline_frame) { - rkey = key; - } - } - else { + } + else { + lkey = key; + } + if (rkey) { + if (key->timeline_frame > rkey->timeline_frame) { rkey = key; } } + else { + rkey = key; + } } finalkey = seq_cache_choose_key(scene, lkey, rkey); @@ -1281,10 +1277,10 @@ struct ImBuf *seq_cache_get(const SeqRenderData *context, BLI_mutex_unlock(&cache->disk_cache->read_write_mutex); if (ibuf) { if (key.type == SEQ_CACHE_STORE_FINAL_OUT) { - seq_cache_put_if_possible(context, seq, timeline_frame, type, ibuf, 0.0f, true); + seq_cache_put_if_possible(context, seq, timeline_frame, type, ibuf, true); } else { - seq_cache_put(context, seq, timeline_frame, type, ibuf, 0.0f, true); + seq_cache_put(context, seq, timeline_frame, type, ibuf, true); } } } @@ -1297,7 +1293,6 @@ bool seq_cache_put_if_possible(const SeqRenderData *context, float timeline_frame, int type, ImBuf *ibuf, - float cost, bool skip_disk_cache) { Scene *scene = context->scene; @@ -1313,7 +1308,7 @@ bool seq_cache_put_if_possible(const SeqRenderData *context, } if (seq_cache_recycle_item(scene)) { - seq_cache_put(context, seq, timeline_frame, type, ibuf, cost, skip_disk_cache); + seq_cache_put(context, seq, timeline_frame, type, ibuf, skip_disk_cache); return true; } @@ -1327,7 +1322,6 @@ void seq_cache_put(const SeqRenderData *context, float timeline_frame, int type, ImBuf *i, - float cost, bool skip_disk_cache) { if (i == NULL || context->skip_cache || context->is_proxy_render || !seq) { @@ -1370,10 +1364,6 @@ void seq_cache_put(const SeqRenderData *context, flag = scene->ed->cache_flag; } - if (cost > SEQ_CACHE_COST_MAX) { - cost = SEQ_CACHE_COST_MAX; - } - SeqCacheKey *key; key = BLI_mempool_alloc(cache->keys_pool); key->cache_owner = cache; @@ -1382,7 +1372,6 @@ void seq_cache_put(const SeqRenderData *context, key->frame_index = seq_cache_timeline_frame_to_frame_index(seq, timeline_frame, type); key->timeline_frame = timeline_frame; key->type = type; - key->cost = cost; key->link_prev = NULL; key->link_next = NULL; key->is_temp_cache = true; @@ -1430,14 +1419,11 @@ void seq_cache_put(const SeqRenderData *context, } } -void SEQ_cache_iterate(struct Scene *scene, - void *userdata, - bool callback_init(void *userdata, size_t item_count), - bool callback_iter(void *userdata, - struct Sequence *seq, - int timeline_frame, - int cache_type, - float cost)) +void SEQ_cache_iterate( + struct Scene *scene, + void *userdata, + bool callback_init(void *userdata, size_t item_count), + bool callback_iter(void *userdata, struct Sequence *seq, int timeline_frame, int cache_type)) { SeqCache *cache = seq_cache_get_from_scene(scene); if (!cache) { @@ -1454,7 +1440,7 @@ void SEQ_cache_iterate(struct Scene *scene, SeqCacheKey *key = BLI_ghashIterator_getKey(&gh_iter); BLI_ghashIterator_step(&gh_iter); - interrupt = callback_iter(userdata, key->seq, key->timeline_frame, key->type, key->cost); + interrupt = callback_iter(userdata, key->seq, key->timeline_frame, key->type); } cache->last_key = NULL; diff --git a/source/blender/sequencer/intern/image_cache.h b/source/blender/sequencer/intern/image_cache.h index ab28b1d3204..41e8c4d1d48 100644 --- a/source/blender/sequencer/intern/image_cache.h +++ b/source/blender/sequencer/intern/image_cache.h @@ -47,14 +47,12 @@ void seq_cache_put(const struct SeqRenderData *context, float timeline_frame, int type, struct ImBuf *i, - float cost, bool skip_disk_cache); bool seq_cache_put_if_possible(const struct SeqRenderData *context, struct Sequence *seq, float timeline_frame, int type, struct ImBuf *nval, - float cost, bool skip_disk_cache); bool seq_cache_recycle_item(struct Scene *scene); void seq_cache_free_temp_cache(struct Scene *scene, short id, int timeline_frame); diff --git a/source/blender/sequencer/intern/prefetch.c b/source/blender/sequencer/intern/prefetch.c index 5ffb2287e1c..55df17c01f9 100644 --- a/source/blender/sequencer/intern/prefetch.c +++ b/source/blender/sequencer/intern/prefetch.c @@ -178,7 +178,7 @@ static bool seq_prefetch_is_cache_full(Scene *scene) { PrefetchJob *pfjob = seq_prefetch_job_get(scene); - if (!seq_cache_is_full(pfjob->scene)) { + if (!seq_cache_is_full()) { return false; } @@ -528,7 +528,7 @@ static PrefetchJob *seq_prefetch_start_ex(const SeqRenderData *context, float cf } /* Start or resume prefetching*/ -void seq_prefetch_start(const SeqRenderData *context, float timeline_frame, float cost) +void seq_prefetch_start(const SeqRenderData *context, float timeline_frame) { Scene *scene = context->scene; Editing *ed = scene->ed; @@ -540,13 +540,12 @@ void seq_prefetch_start(const SeqRenderData *context, float timeline_frame, floa bool running = seq_prefetch_job_is_running(scene); seq_prefetch_resume(scene); /* conditions to start: - * prefetch enabled, prefetch not running, not scrubbing, - * not playing and rendering-expensive footage, cache storage enabled, has strips to render, - * not rendering, not doing modal transform - important, see D7820. + * prefetch enabled, prefetch not running, not scrubbing, not playing, + * cache storage enabled, has strips to render, not rendering, not doing modal transform - + * important, see D7820. */ - if ((ed->cache_flag & SEQ_CACHE_PREFETCH_ENABLE) && !running && !scrubbing && - !(playing && cost > 0.9) && ed->cache_flag & SEQ_CACHE_ALL_TYPES && has_strips && - !G.is_rendering && !G.moving) { + if ((ed->cache_flag & SEQ_CACHE_PREFETCH_ENABLE) && !running && !scrubbing && !playing && + ed->cache_flag & SEQ_CACHE_ALL_TYPES && has_strips && !G.is_rendering && !G.moving) { seq_prefetch_start_ex(context, timeline_frame); } diff --git a/source/blender/sequencer/intern/prefetch.h b/source/blender/sequencer/intern/prefetch.h index 44aedb537ae..8cfc6bf90bd 100644 --- a/source/blender/sequencer/intern/prefetch.h +++ b/source/blender/sequencer/intern/prefetch.h @@ -35,7 +35,7 @@ struct Sequence; } #endif -void seq_prefetch_start(const struct SeqRenderData *context, float timeline_frame, float cost); +void seq_prefetch_start(const struct SeqRenderData *context, float timeline_frame); void seq_prefetch_free(struct Scene *scene); bool seq_prefetch_job_is_running(struct Scene *scene); void seq_prefetch_get_time_range(struct Scene *scene, int *start, int *end); diff --git a/source/blender/sequencer/intern/render.c b/source/blender/sequencer/intern/render.c index 524bf7cd74c..8d6a61f3c5d 100644 --- a/source/blender/sequencer/intern/render.c +++ b/source/blender/sequencer/intern/render.c @@ -403,24 +403,6 @@ int seq_get_shown_sequences(ListBase *seqbasep, return cnt; } -/* Estimate time spent by the program rendering the strip */ -static clock_t seq_estimate_render_cost_begin(void) -{ - return clock(); -} - -static float seq_estimate_render_cost_end(Scene *scene, clock_t begin) -{ - clock_t end = clock(); - float time_spent = (float)(end - begin); - float time_max = (1.0f / scene->r.frs_sec) * CLOCKS_PER_SEC; - - if (time_max != 0) { - return time_spent / time_max; - } - - return 1; -} /** \} */ /* -------------------------------------------------------------------- */ @@ -738,7 +720,6 @@ static ImBuf *seq_render_preprocess_ibuf(const SeqRenderData *context, Sequence *seq, ImBuf *ibuf, float timeline_frame, - clock_t begin, bool use_preprocess, const bool is_proxy_image) { @@ -748,20 +729,15 @@ static ImBuf *seq_render_preprocess_ibuf(const SeqRenderData *context, } if (use_preprocess) { - float cost = seq_estimate_render_cost_end(context->scene, begin); - /* Proxies are not stored in cache. */ if (!is_proxy_image) { - seq_cache_put(context, seq, timeline_frame, SEQ_CACHE_STORE_RAW, ibuf, cost, false); + seq_cache_put(context, seq, timeline_frame, SEQ_CACHE_STORE_RAW, ibuf, false); } - /* Reset timer so we can get partial render time. */ - begin = seq_estimate_render_cost_begin(); ibuf = input_preprocess(context, seq, timeline_frame, ibuf); } - float cost = seq_estimate_render_cost_end(context->scene, begin); - seq_cache_put(context, seq, timeline_frame, SEQ_CACHE_STORE_PREPROCESSED, ibuf, cost, false); + seq_cache_put(context, seq, timeline_frame, SEQ_CACHE_STORE_PREPROCESSED, ibuf, false); return ibuf; } @@ -1073,7 +1049,7 @@ static ImBuf *seq_render_image_strip(const SeqRenderData *context, if (view_id != context->view_id) { ibufs_arr[view_id] = seq_render_preprocess_ibuf( - &localcontext, seq, ibufs_arr[view_id], timeline_frame, clock(), true, false); + &localcontext, seq, ibufs_arr[view_id], timeline_frame, true, false); } } @@ -1223,7 +1199,7 @@ static ImBuf *seq_render_movie_strip(const SeqRenderData *context, if (view_id != context->view_id) { ibuf_arr[view_id] = seq_render_preprocess_ibuf( - &localcontext, seq, ibuf_arr[view_id], timeline_frame, clock(), true, false); + &localcontext, seq, ibuf_arr[view_id], timeline_frame, true, false); } } @@ -1630,7 +1606,7 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context, if (view_id != context->view_id) { seq_cache_put( - &localcontext, seq, timeline_frame, SEQ_CACHE_STORE_RAW, ibufs_arr[view_id], 0, false); + &localcontext, seq, timeline_frame, SEQ_CACHE_STORE_RAW, ibufs_arr[view_id], false); } RE_ReleaseResultImage(re); @@ -1805,8 +1781,6 @@ ImBuf *seq_render_strip(const SeqRenderData *context, bool use_preprocess = false; bool is_proxy_image = false; - clock_t begin = seq_estimate_render_cost_begin(); - ibuf = seq_cache_get(context, seq, timeline_frame, SEQ_CACHE_STORE_PREPROCESSED, false); if (ibuf != NULL) { return ibuf; @@ -1824,7 +1798,7 @@ ImBuf *seq_render_strip(const SeqRenderData *context, if (ibuf) { use_preprocess = seq_input_have_to_preprocess(context, seq, timeline_frame); ibuf = seq_render_preprocess_ibuf( - context, seq, ibuf, timeline_frame, begin, use_preprocess, is_proxy_image); + context, seq, ibuf, timeline_frame, use_preprocess, is_proxy_image); } if (ibuf == NULL) { @@ -1910,7 +1884,6 @@ static ImBuf *seq_render_strip_stack(const SeqRenderData *context, int count; int i; ImBuf *out = NULL; - clock_t begin; count = seq_get_shown_sequences(seqbasep, timeline_frame, chanshown, (Sequence **)&seq_arr); @@ -1946,16 +1919,13 @@ static ImBuf *seq_render_strip_stack(const SeqRenderData *context, break; case EARLY_DO_EFFECT: if (i == 0) { - begin = seq_estimate_render_cost_begin(); - ImBuf *ibuf1 = IMB_allocImBuf(context->rectx, context->recty, 32, IB_rect); ImBuf *ibuf2 = seq_render_strip(context, state, seq, timeline_frame); out = seq_render_strip_stack_apply_effect(context, seq, timeline_frame, ibuf1, ibuf2); - float cost = seq_estimate_render_cost_end(context->scene, begin); seq_cache_put( - context, seq_arr[i], timeline_frame, SEQ_CACHE_STORE_COMPOSITE, out, cost, false); + context, seq_arr[i], timeline_frame, SEQ_CACHE_STORE_COMPOSITE, out, false); IMB_freeImBuf(ibuf1); IMB_freeImBuf(ibuf2); @@ -1969,7 +1939,6 @@ static ImBuf *seq_render_strip_stack(const SeqRenderData *context, i++; for (; i < count; i++) { - begin = seq_estimate_render_cost_begin(); Sequence *seq = seq_arr[i]; if (seq_get_early_out_for_blend_mode(seq) == EARLY_DO_EFFECT) { @@ -1982,9 +1951,7 @@ static ImBuf *seq_render_strip_stack(const SeqRenderData *context, IMB_freeImBuf(ibuf2); } - float cost = seq_estimate_render_cost_end(context->scene, begin); - seq_cache_put( - context, seq_arr[i], timeline_frame, SEQ_CACHE_STORE_COMPOSITE, out, cost, false); + seq_cache_put(context, seq_arr[i], timeline_frame, SEQ_CACHE_STORE_COMPOSITE, out, false); } return out; @@ -2029,36 +1996,22 @@ ImBuf *SEQ_render_give_ibuf(const SeqRenderData *context, float timeline_frame, seq_cache_free_temp_cache(context->scene, context->task_id, timeline_frame); - clock_t begin = seq_estimate_render_cost_begin(); - float cost = 0; - if (count && !out) { BLI_mutex_lock(&seq_render_mutex); out = seq_render_strip_stack(context, &state, seqbasep, timeline_frame, chanshown); - cost = seq_estimate_render_cost_end(context->scene, begin); if (context->is_prefetch_render) { - seq_cache_put(context, - seq_arr[count - 1], - timeline_frame, - SEQ_CACHE_STORE_FINAL_OUT, - out, - cost, - false); + seq_cache_put( + context, seq_arr[count - 1], timeline_frame, SEQ_CACHE_STORE_FINAL_OUT, out, false); } else { - seq_cache_put_if_possible(context, - seq_arr[count - 1], - timeline_frame, - SEQ_CACHE_STORE_FINAL_OUT, - out, - cost, - false); + seq_cache_put_if_possible( + context, seq_arr[count - 1], timeline_frame, SEQ_CACHE_STORE_FINAL_OUT, out, false); } BLI_mutex_unlock(&seq_render_mutex); } - seq_prefetch_start(context, timeline_frame, cost); + seq_prefetch_start(context, timeline_frame); return out; } diff --git a/source/blender/sequencer/intern/sequencer.c b/source/blender/sequencer/intern/sequencer.c index 79e8ba2f6c0..b589a75fa42 100644 --- a/source/blender/sequencer/intern/sequencer.c +++ b/source/blender/sequencer/intern/sequencer.c @@ -249,7 +249,6 @@ Editing *SEQ_editing_ensure(Scene *scene) ed->cache_flag = SEQ_CACHE_STORE_FINAL_OUT; ed->cache_flag |= SEQ_CACHE_VIEW_FINAL_OUT; ed->cache_flag |= SEQ_CACHE_VIEW_ENABLE; - ed->recycle_max_cost = 10.0f; } return scene->ed; -- cgit v1.2.3 From 864c8068639a1341220f5a97b683f6834928ad76 Mon Sep 17 00:00:00 2001 From: Yevgeny Makarov Date: Sat, 19 Dec 2020 21:52:45 -0600 Subject: UI: Reorder enums in render results image editor header The convention is to put the label at the bottom of the enum, or in the spot furthest away from the button. This commit reorders the items in the "Slot", "Layer", and "Pass" menus to be consistent with this convention. It also reorders the numbering so that higher numbers are lower. The original patch was by Adrian Newton (@TFS), with slight changes and additions. Differential Revision: https://developer.blender.org/D7142 --- source/blender/editors/space_image/image_buttons.c | 142 ++++++++++----------- 1 file changed, 68 insertions(+), 74 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c index f8f25e399eb..1996f05b36a 100644 --- a/source/blender/editors/space_image/image_buttons.c +++ b/source/blender/editors/space_image/image_buttons.c @@ -86,26 +86,9 @@ static void ui_imageuser_slot_menu(bContext *UNUSED(C), uiLayout *layout, void * { uiBlock *block = uiLayoutGetBlock(layout); Image *image = image_p; - int slot_id; - uiDefBut(block, - UI_BTYPE_LABEL, - 0, - IFACE_("Slot"), - 0, - 0, - UI_UNIT_X * 5, - UI_UNIT_Y, - NULL, - 0.0, - 0.0, - 0, - 0, - ""); - uiItemS(layout); - - slot_id = BLI_listbase_count(&image->renderslots) - 1; - for (RenderSlot *slot = image->renderslots.last; slot; slot = slot->prev) { + int slot_id; + LISTBASE_FOREACH_INDEX (RenderSlot *, slot, &image->renderslots, slot_id) { char str[64]; if (slot->name[0] != '\0') { BLI_strncpy(str, slot->name, sizeof(str)); @@ -127,8 +110,23 @@ static void ui_imageuser_slot_menu(bContext *UNUSED(C), uiLayout *layout, void * 0, -1, ""); - slot_id--; } + + uiItemS(layout); + uiDefBut(block, + UI_BTYPE_LABEL, + 0, + IFACE_("Slot"), + 0, + 0, + UI_UNIT_X * 5, + UI_UNIT_Y, + NULL, + 0.0, + 0.0, + 0, + 0, + ""); } static bool ui_imageuser_slot_menu_step(bContext *C, int direction, void *image_p) @@ -175,14 +173,9 @@ static void ui_imageuser_layer_menu(bContext *UNUSED(C), uiLayout *layout, void Image *image = rnd_data->image; ImageUser *iuser = rnd_data->iuser; Scene *scene = iuser->scene; - RenderResult *rr; - RenderLayer *rl; - RenderLayer rl_fake = {NULL}; - const char *fake_name; - int nr; - /* may have been freed since drawing */ - rr = BKE_image_acquire_renderresult(scene, image); + /* May have been freed since drawing. */ + RenderResult *rr = BKE_image_acquire_renderresult(scene, image); if (UNLIKELY(rr == NULL)) { return; } @@ -190,32 +183,26 @@ static void ui_imageuser_layer_menu(bContext *UNUSED(C), uiLayout *layout, void UI_block_layout_set_current(block, layout); uiLayoutColumn(layout, false); - uiDefBut(block, - UI_BTYPE_LABEL, - 0, - IFACE_("Layer"), - 0, - 0, - UI_UNIT_X * 5, - UI_UNIT_Y, - NULL, - 0.0, - 0.0, - 0, - 0, - ""); - uiItemS(layout); - - nr = BLI_listbase_count(&rr->layers) - 1; - fake_name = ui_imageuser_layer_fake_name(rr); - + const char *fake_name = ui_imageuser_layer_fake_name(rr); if (fake_name) { - BLI_strncpy(rl_fake.name, fake_name, sizeof(rl_fake.name)); - nr += 1; + uiDefButS(block, + UI_BTYPE_BUT_MENU, + B_NOP, + fake_name, + 0, + 0, + UI_UNIT_X * 5, + UI_UNIT_X, + &iuser->layer, + 0.0, + 0.0, + 0, + -1, + ""); } - for (rl = rr->layers.last; rl; rl = rl->prev, nr--) { - final: + int nr = fake_name ? 1 : 0; + for (RenderLayer *rl = rr->layers.first; rl; rl = rl->next, nr++) { uiDefButS(block, UI_BTYPE_BUT_MENU, B_NOP, @@ -232,13 +219,21 @@ static void ui_imageuser_layer_menu(bContext *UNUSED(C), uiLayout *layout, void ""); } - if (fake_name) { - fake_name = NULL; - rl = &rl_fake; - goto final; - } - - BLI_assert(nr == -1); + uiItemS(layout); + uiDefBut(block, + UI_BTYPE_LABEL, + 0, + IFACE_("Layer"), + 0, + 0, + UI_UNIT_X * 5, + UI_UNIT_Y, + NULL, + 0.0, + 0.0, + 0, + 0, + ""); BKE_image_release_renderresult(scene, image); } @@ -268,23 +263,6 @@ static void ui_imageuser_pass_menu(bContext *UNUSED(C), uiLayout *layout, void * UI_block_layout_set_current(block, layout); uiLayoutColumn(layout, false); - uiDefBut(block, - UI_BTYPE_LABEL, - 0, - IFACE_("Pass"), - 0, - 0, - UI_UNIT_X * 5, - UI_UNIT_Y, - NULL, - 0.0, - 0.0, - 0, - 0, - ""); - - uiItemS(layout); - nr = (rl == NULL) ? 1 : 0; ListBase added_passes; @@ -315,6 +293,22 @@ static void ui_imageuser_pass_menu(bContext *UNUSED(C), uiLayout *layout, void * ""); } + uiItemS(layout); + uiDefBut(block, + UI_BTYPE_LABEL, + 0, + IFACE_("Pass"), + 0, + 0, + UI_UNIT_X * 5, + UI_UNIT_Y, + NULL, + 0.0, + 0.0, + 0, + 0, + ""); + BLI_freelistN(&added_passes); BKE_image_release_renderresult(scene, image); -- cgit v1.2.3 From 5a69f707516e858bb177fc95e49a942384326538 Mon Sep 17 00:00:00 2001 From: Peter Fog Date: Sun, 20 Dec 2020 06:23:08 +0100 Subject: VSE: Add options to select neighboring handles Options added to `sequencer.select_handles()` operator. Reviewed By: ISS Differential Revision: https://developer.blender.org/D7707 --- .../editors/space_sequencer/sequencer_select.c | 67 ++++++++++++++++++++-- 1 file changed, 62 insertions(+), 5 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/space_sequencer/sequencer_select.c b/source/blender/editors/space_sequencer/sequencer_select.c index a6027a2472c..edbffa8f693 100644 --- a/source/blender/editors/space_sequencer/sequencer_select.c +++ b/source/blender/editors/space_sequencer/sequencer_select.c @@ -902,6 +902,25 @@ void SEQUENCER_OT_select_linked(wmOperatorType *ot) /** \name Select Handles Operator * \{ */ +enum { + SEQ_SELECT_HANDLES_SIDE_LEFT, + SEQ_SELECT_HANDLES_SIDE_RIGHT, + SEQ_SELECT_HANDLES_SIDE_BOTH, + SEQ_SELECT_HANDLES_SIDE_LEFT_NEIGHBOR, + SEQ_SELECT_HANDLES_SIDE_RIGHT_NEIGHBOR, + SEQ_SELECT_HANDLES_SIDE_BOTH_NEIGHBORS, +}; + +static const EnumPropertyItem prop_select_handles_side_types[] = { + {SEQ_SELECT_HANDLES_SIDE_LEFT, "LEFT", 0, "Left", ""}, + {SEQ_SELECT_HANDLES_SIDE_RIGHT, "RIGHT", 0, "Right", ""}, + {SEQ_SELECT_HANDLES_SIDE_BOTH, "BOTH", 0, "Both", ""}, + {SEQ_SELECT_HANDLES_SIDE_LEFT_NEIGHBOR, "LEFT_NEIGHBOR", 0, "Left Neighbor", ""}, + {SEQ_SELECT_HANDLES_SIDE_RIGHT_NEIGHBOR, "RIGHT_NEIGHBOR", 0, "Right Neighbor", ""}, + {SEQ_SELECT_HANDLES_SIDE_BOTH_NEIGHBORS, "BOTH_NEIGHBORS", 0, "Both Neighbors", ""}, + {0, NULL, 0, NULL, NULL}, +}; + static int sequencer_select_handles_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); @@ -911,18 +930,56 @@ static int sequencer_select_handles_exec(bContext *C, wmOperator *op) for (seq = ed->seqbasep->first; seq; seq = seq->next) { if (seq->flag & SELECT) { + Sequence *l_neighbor = find_neighboring_sequence(scene, seq, SEQ_SIDE_LEFT, -1); + Sequence *r_neighbor = find_neighboring_sequence(scene, seq, SEQ_SIDE_RIGHT, -1); + switch (sel_side) { - case SEQ_SIDE_LEFT: + case SEQ_SELECT_HANDLES_SIDE_LEFT: seq->flag &= ~SEQ_RIGHTSEL; seq->flag |= SEQ_LEFTSEL; break; - case SEQ_SIDE_RIGHT: + case SEQ_SELECT_HANDLES_SIDE_RIGHT: seq->flag &= ~SEQ_LEFTSEL; seq->flag |= SEQ_RIGHTSEL; break; - case SEQ_SIDE_BOTH: + case SEQ_SELECT_HANDLES_SIDE_BOTH: seq->flag |= SEQ_LEFTSEL | SEQ_RIGHTSEL; break; + case SEQ_SELECT_HANDLES_SIDE_LEFT_NEIGHBOR: + if (l_neighbor) { + if (!(l_neighbor->flag & SELECT)) { + l_neighbor->flag |= SEQ_RIGHTSEL; + } + } + break; + case SEQ_SELECT_HANDLES_SIDE_RIGHT_NEIGHBOR: + if (r_neighbor) { + if (!(r_neighbor->flag & SELECT)) { + r_neighbor->flag |= SEQ_LEFTSEL; + } + } + break; + case SEQ_SELECT_HANDLES_SIDE_BOTH_NEIGHBORS: + if (l_neighbor) { + if (!(l_neighbor->flag & SELECT)) { + l_neighbor->flag |= SEQ_RIGHTSEL; + } + } + if (r_neighbor) { + if (!(r_neighbor->flag & SELECT)) { + r_neighbor->flag |= SEQ_LEFTSEL; + } + break; + } + } + } + } + /* Select strips */ + for (seq = ed->seqbasep->first; seq; seq = seq->next) { + if ((seq->flag & SEQ_LEFTSEL) || (seq->flag & SEQ_RIGHTSEL)) { + if (!(seq->flag & SELECT)) { + seq->flag |= SELECT; + recurs_sel_seq(seq); } } } @@ -951,8 +1008,8 @@ void SEQUENCER_OT_select_handles(wmOperatorType *ot) /* Properties. */ RNA_def_enum(ot->srna, "side", - prop_side_types, - SEQ_SIDE_BOTH, + prop_select_handles_side_types, + SEQ_SELECT_HANDLES_SIDE_BOTH, "Side", "The side of the handle that is selected"); } -- cgit v1.2.3 From d283a093d6643fc63264d95bed46af0646788277 Mon Sep 17 00:00:00 2001 From: Gaia Clary Date: Sun, 20 Dec 2020 18:48:07 +0100 Subject: fix T83880: Added check for valid context object to avoid null pointer exception when no object in scene --- source/blender/editors/object/object_vgroup.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c index 23f1718cb2e..fc4969019b5 100644 --- a/source/blender/editors/object/object_vgroup.c +++ b/source/blender/editors/object/object_vgroup.c @@ -736,17 +736,19 @@ const EnumPropertyItem *ED_object_vgroup_selection_itemf_helper(const bContext * RNA_enum_items_add_value(&item, &totitem, WT_vertex_group_select_item, WT_VGROUP_ACTIVE); } - if (BKE_object_pose_armature_get(ob)) { - if (selection_mask & (1 << WT_VGROUP_BONE_SELECT)) { - RNA_enum_items_add_value( - &item, &totitem, WT_vertex_group_select_item, WT_VGROUP_BONE_SELECT); + if (ob) { + if (BKE_object_pose_armature_get(ob)) { + if (selection_mask & (1 << WT_VGROUP_BONE_SELECT)) { + RNA_enum_items_add_value( + &item, &totitem, WT_vertex_group_select_item, WT_VGROUP_BONE_SELECT); + } } - } - if (BKE_modifiers_is_deformed_by_armature(ob)) { - if (selection_mask & (1 << WT_VGROUP_BONE_DEFORM)) { - RNA_enum_items_add_value( - &item, &totitem, WT_vertex_group_select_item, WT_VGROUP_BONE_DEFORM); + if (BKE_modifiers_is_deformed_by_armature(ob)) { + if (selection_mask & (1 << WT_VGROUP_BONE_DEFORM)) { + RNA_enum_items_add_value( + &item, &totitem, WT_vertex_group_select_item, WT_VGROUP_BONE_DEFORM); + } } } -- cgit v1.2.3 From c229d9876b78460179adaea9b8ea1b71a5ad19b1 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Sun, 20 Dec 2020 18:42:35 -0600 Subject: Cleanup: Correct comment --- source/blender/makesdna/DNA_userdef_types.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender') diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index 1bd013c7d54..d9ee9a27294 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -375,7 +375,7 @@ typedef struct ThemeSpace { /** Two uses, for uvs with modifier applied on mesh and uvs during painting. */ unsigned char uv_shadow[4]; - /** Outliner - filter match. */ + /** Search filter match, used for property search and in the outliner. */ unsigned char match[4]; /** Outliner - selected item. */ unsigned char selected_highlight[4]; -- cgit v1.2.3 From 84cc00f3b68e12209e000008f992fad3ac48f757 Mon Sep 17 00:00:00 2001 From: "Garry R. Osgood" Date: Sun, 20 Dec 2020 18:46:24 -0600 Subject: Fix T83989: Attribute Math node ignores its operation setting T83989 observes that the Attribute Math node always adds its operands regardless of its operator setting. This was caused by an oversight committed in rB23233fcf056e42, which overlooked adjusting the exec function to use the new storage location. Differential Revision: https://developer.blender.org/D9909 --- source/blender/nodes/geometry/nodes/node_geo_attribute_math.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source/blender') diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_math.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_math.cc index a7b71fa614f..997b85c5e9d 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_attribute_math.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_math.cc @@ -97,7 +97,8 @@ static void do_math_operation(const FloatReadAttribute &input_a, static void attribute_math_calc(GeometryComponent &component, const GeoNodeExecParams ¶ms) { const bNode &node = params.node(); - const int operation = node.custom1; + const NodeAttributeMath *node_storage = (const NodeAttributeMath *)node.storage; + const int operation = node_storage->operation; /* The result type of this node is always float. */ const CustomDataType result_type = CD_PROP_FLOAT; -- cgit v1.2.3