diff options
-rw-r--r-- | doc/python_api/sphinx_doc_gen.py | 28 | ||||
-rw-r--r-- | release/scripts/startup/bl_ui/space_outliner.py | 26 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_paint.h | 4 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/paint.c | 44 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/sculpt.c | 55 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/sculpt_face_set.c | 1 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/sculpt_filter_color.c | 6 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/sculpt_filter_mesh.c | 17 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/sculpt_smooth.c | 3 | ||||
-rw-r--r-- | source/blender/editors/space_outliner/outliner_draw.c | 4 | ||||
-rw-r--r-- | source/blender/gpencil_modifiers/intern/MOD_gpenciloffset.c | 8 | ||||
-rw-r--r-- | tests/gtests/runner/CMakeLists.txt | 21 |
12 files changed, 140 insertions, 77 deletions
diff --git a/doc/python_api/sphinx_doc_gen.py b/doc/python_api/sphinx_doc_gen.py index 8ad96a6e4f5..2c9445dce97 100644 --- a/doc/python_api/sphinx_doc_gen.py +++ b/doc/python_api/sphinx_doc_gen.py @@ -696,13 +696,11 @@ def py_descr2sphinx(ident, fw, descr, module_name, type_name, identifier): doc = undocumented_message(module_name, type_name, identifier) if type(descr) == GetSetDescriptorType: - fw(ident + ".. attribute:: %s\n" % identifier) - fw(ident + " :noindex:\n\n") + fw(ident + ".. attribute:: %s\n\n" % identifier) write_indented_lines(ident + " ", fw, doc, False) fw("\n") elif type(descr) == MemberDescriptorType: # same as above but use 'data' - fw(ident + ".. data:: %s\n" % identifier) - fw(ident + " :noindex:\n\n") + fw(ident + ".. data:: %s\n\n" % identifier) write_indented_lines(ident + " ", fw, doc, False) fw("\n") elif type(descr) in {MethodDescriptorType, ClassMethodDescriptorType}: @@ -742,14 +740,11 @@ def pyprop2sphinx(ident, fw, identifier, py_prop): ''' # readonly properties use "data" directive, variables use "attribute" directive if py_prop.fset is None: - fw(ident + ".. data:: %s\n" % identifier) - fw(ident + " :noindex:\n\n") + fw(ident + ".. data:: %s\n\n" % identifier) else: - fw(ident + ".. attribute:: %s\n" % identifier) - fw(ident + " :noindex:\n\n") + fw(ident + ".. attribute:: %s\n\n" % identifier) write_indented_lines(ident + " ", fw, py_prop.__doc__) if py_prop.fset is None: - fw("\n") fw(ident + " (readonly)\n\n") else: fw("\n") @@ -915,8 +910,7 @@ def pymodule2sphinx(basepath, module_name, module, title): elif issubclass(value_type, (bool, int, float, str, tuple)): # constant, not much fun we can do here except to list it. # TODO, figure out some way to document these! - fw(".. data:: %s\n" % attribute) - fw(" :noindex:\n\n") + fw(".. data:: %s\n\n" % attribute) write_indented_lines(" ", fw, "constant value %s" % repr(value), False) fw("\n") else: @@ -1126,8 +1120,7 @@ def pycontext2sphinx(basepath): type_descr = prop.get_type_description( class_fmt=":class:`bpy.types.%s`", collection_id=_BPY_PROP_COLLECTION_ID) - fw(".. data:: %s\n" % prop.identifier) - fw(" :noindex:\n\n") + fw(".. data:: %s\n\n" % prop.identifier) if prop.description: fw(" %s\n\n" % prop.description) @@ -1172,8 +1165,7 @@ def pycontext2sphinx(basepath): i = 0 while char_array[i] is not None: member = ctypes.string_at(char_array[i]).decode(encoding="ascii") - fw(".. data:: %s\n" % member) - fw(" :noindex:\n\n") + fw(".. data:: %s\n\n" % member) member_type, is_seq = context_type_map[member] fw(" :type: %s :class:`bpy.types.%s`\n\n" % ("sequence of " if is_seq else "", member_type)) unique.add(member) @@ -1379,11 +1371,9 @@ def pyrna2sphinx(basepath): type_descr = prop.get_type_description(class_fmt=":class:`%s`", collection_id=_BPY_PROP_COLLECTION_ID) # readonly properties use "data" directive, variables properties use "attribute" directive if 'readonly' in type_descr: - fw(" .. data:: %s\n" % prop.identifier) - fw(" :noindex:\n\n") + fw(" .. data:: %s\n\n" % prop.identifier) else: - fw(" .. attribute:: %s\n" % prop.identifier) - fw(" :noindex:\n\n") + fw(" .. attribute:: %s\n\n" % prop.identifier) if prop.description: fw(" %s\n\n" % prop.description) diff --git a/release/scripts/startup/bl_ui/space_outliner.py b/release/scripts/startup/bl_ui/space_outliner.py index aa4d0b94b7f..5a54d4ca2d8 100644 --- a/release/scripts/startup/bl_ui/space_outliner.py +++ b/release/scripts/startup/bl_ui/space_outliner.py @@ -107,6 +107,14 @@ class OUTLINER_MT_editor_menus(Menu): class OUTLINER_MT_context_menu(Menu): bl_label = "Outliner Context Menu" + @staticmethod + def draw_common_operators(layout): + layout.menu("OUTLINER_MT_context_menu_view") + + layout.separator() + + layout.menu("INFO_MT_area") + def draw(self, context): space = context.space_data @@ -116,11 +124,7 @@ class OUTLINER_MT_context_menu(Menu): OUTLINER_MT_collection_new.draw_without_context_menu(context, layout) layout.separator() - layout.menu("OUTLINER_MT_context_menu_view") - - layout.separator() - - layout.menu("INFO_MT_area") + OUTLINER_MT_context_menu.draw_common_operators(layout) class OUTLINER_MT_context_menu_view(Menu): @@ -242,7 +246,7 @@ class OUTLINER_MT_collection(Menu): layout.separator() - OUTLINER_MT_context_menu.draw(self, context) + OUTLINER_MT_context_menu.draw_common_operators(layout) class OUTLINER_MT_collection_new(Menu): @@ -250,7 +254,7 @@ class OUTLINER_MT_collection_new(Menu): @staticmethod def draw_without_context_menu(context, layout): - layout.operator("outliner.collection_new", text="New Collection").nested = False + layout.operator("outliner.collection_new", text="New Collection").nested = True layout.operator("outliner.id_paste", text="Paste Data-Blocks", icon='PASTEDOWN') def draw(self, context): @@ -260,7 +264,7 @@ class OUTLINER_MT_collection_new(Menu): layout.separator() - OUTLINER_MT_context_menu.draw(self, context) + OUTLINER_MT_context_menu.draw_common_operators(layout) class OUTLINER_MT_object(Menu): @@ -303,11 +307,15 @@ class OUTLINER_MT_object(Menu): layout.operator("outliner.id_operation", text="Unlink").type = 'UNLINK' layout.separator() + layout.operator("outliner.collection_new", text="New Collection").nested = True + + layout.separator() + layout.operator_menu_enum("outliner.id_operation", "type", text="ID Data") layout.separator() - OUTLINER_MT_context_menu.draw(self, context) + OUTLINER_MT_context_menu.draw_common_operators(layout) class OUTLINER_PT_filter(Panel): diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h index e3a6fb4ba2e..1c02aece06f 100644 --- a/source/blender/blenkernel/BKE_paint.h +++ b/source/blender/blenkernel/BKE_paint.h @@ -451,6 +451,10 @@ void BKE_sculptsession_free_vwpaint_data(struct SculptSession *ss); void BKE_sculptsession_bm_to_me(struct Object *ob, bool reorder); void BKE_sculptsession_bm_to_me_for_render(struct Object *object); +/* Create new color layer on object if it doesn't have one and if experimental feature set has + * sculpt vertex color enabled. Returns truth if new layer has been added, false otherwise. */ +void BKE_sculpt_color_layer_create_if_needed(struct Object *object); + void BKE_sculpt_update_object_for_edit(struct Depsgraph *depsgraph, struct Object *ob_orig, bool need_pmap, diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c index 50feb8e99c8..d6fbba74a89 100644 --- a/source/blender/blenkernel/intern/paint.c +++ b/source/blender/blenkernel/intern/paint.c @@ -1314,6 +1314,13 @@ static void sculptsession_free_pbvh(Object *object) MEM_SAFE_FREE(ss->preview_vert_index_list); ss->preview_vert_index_count = 0; + + MEM_SAFE_FREE(ss->preview_vert_index_list); + + MEM_SAFE_FREE(ss->vertex_info.connected_component); + MEM_SAFE_FREE(ss->vertex_info.boundary); + + MEM_SAFE_FREE(ss->fake_neighbors.fake_neighbor_index); } void BKE_sculptsession_bm_to_me_for_render(Object *object) @@ -1366,13 +1373,6 @@ void BKE_sculptsession_free(Object *ob) MEM_SAFE_FREE(ss->deform_cos); MEM_SAFE_FREE(ss->deform_imats); - MEM_SAFE_FREE(ss->preview_vert_index_list); - - MEM_SAFE_FREE(ss->vertex_info.connected_component); - MEM_SAFE_FREE(ss->vertex_info.boundary); - - MEM_SAFE_FREE(ss->fake_neighbors.fake_neighbor_index); - if (ss->pose_ik_chain_preview) { for (int i = 0; i < ss->pose_ik_chain_preview->tot_segments; i++) { MEM_SAFE_FREE(ss->pose_ik_chain_preview->segments[i].weights); @@ -1484,7 +1484,7 @@ static void sculpt_update_object(Depsgraph *depsgraph, Mesh *me_eval, bool need_pmap, bool need_mask, - bool need_colors) + bool UNUSED(need_colors)) { Scene *scene = DEG_get_input_scene(depsgraph); Sculpt *sd = scene->toolsettings->sculpt; @@ -1514,16 +1514,6 @@ static void sculpt_update_object(Depsgraph *depsgraph, } } - /* Add a color layer if a color tool is used. */ - Mesh *orig_me = BKE_object_get_original_mesh(ob); - if (need_colors && U.experimental.use_sculpt_vertex_colors) { - if (!CustomData_has_layer(&orig_me->vdata, CD_PROP_COLOR)) { - CustomData_add_layer(&orig_me->vdata, CD_PROP_COLOR, CD_DEFAULT, NULL, orig_me->totvert); - BKE_mesh_update_customdata_pointers(orig_me, true); - DEG_id_tag_update(&orig_me->id, ID_RECALC_GEOMETRY); - } - } - /* tessfaces aren't used and will become invalid */ BKE_mesh_tessface_clear(me); @@ -1684,10 +1674,26 @@ void BKE_sculpt_update_object_after_eval(Depsgraph *depsgraph, Object *ob_eval) Mesh *me_eval = BKE_object_get_evaluated_mesh(ob_eval); BLI_assert(me_eval != NULL); - sculpt_update_object(depsgraph, ob_orig, me_eval, false, false, false); } +void BKE_sculpt_color_layer_create_if_needed(struct Object *object) +{ + Mesh *orig_me = BKE_object_get_original_mesh(object); + if (!U.experimental.use_sculpt_vertex_colors) { + return; + } + + if (CustomData_has_layer(&orig_me->vdata, CD_PROP_COLOR)) { + return; + } + + CustomData_add_layer(&orig_me->vdata, CD_PROP_COLOR, CD_DEFAULT, NULL, orig_me->totvert); + BKE_mesh_update_customdata_pointers(orig_me, true); + DEG_id_tag_update(&orig_me->id, ID_RECALC_GEOMETRY); + return; +} + void BKE_sculpt_update_object_for_edit( Depsgraph *depsgraph, Object *ob_orig, bool need_pmap, bool need_mask, bool need_colors) { diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index da5d6588dc8..590d04bed3d 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -3147,21 +3147,49 @@ void SCULPT_relax_vertex(SculptSession *ss, { float smooth_pos[3]; float final_disp[3]; - int count = 0; + float boundary_normal[3]; + int avg_count = 0; + int neighbor_count = 0; zero_v3(smooth_pos); + zero_v3(boundary_normal); + const bool is_boundary = SCULPT_vertex_is_boundary(ss, vd->index); SculptVertexNeighborIter ni; SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd->index, ni) { + neighbor_count++; if (!filter_boundary_face_sets || (filter_boundary_face_sets && !SCULPT_vertex_has_unique_face_set(ss, ni.index))) { - add_v3_v3(smooth_pos, SCULPT_vertex_co_get(ss, ni.index)); - count++; + + /* When the vertex to relax is boundary, use only connected boundary vertices for the average + * position. */ + if (is_boundary) { + if (SCULPT_vertex_is_boundary(ss, ni.index)) { + add_v3_v3(smooth_pos, SCULPT_vertex_co_get(ss, ni.index)); + avg_count++; + + /* Calculate a normal for the constraint plane using the edges of the boundary. */ + float to_neighbor[3]; + sub_v3_v3v3(to_neighbor, SCULPT_vertex_co_get(ss, ni.index), vd->co); + normalize_v3(to_neighbor); + add_v3_v3(boundary_normal, to_neighbor); + } + } + else { + add_v3_v3(smooth_pos, SCULPT_vertex_co_get(ss, ni.index)); + avg_count++; + } } } SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); - if (count > 0) { - mul_v3_fl(smooth_pos, 1.0f / (float)count); + /* Don't modify corner vertices. */ + if (neighbor_count <= 2) { + copy_v3_v3(r_final_pos, vd->co); + return; + } + + if (avg_count > 0) { + mul_v3_fl(smooth_pos, 1.0f / (float)avg_count); } else { copy_v3_v3(r_final_pos, vd->co); @@ -3171,11 +3199,12 @@ void SCULPT_relax_vertex(SculptSession *ss, float plane[4]; float smooth_closest_plane[3]; float vno[3]; - if (vd->no) { - normal_short_to_float_v3(vno, vd->no); + + if (is_boundary && avg_count == 2) { + normalize_v3_v3(vno, boundary_normal); } else { - copy_v3_v3(vno, vd->fno); + SCULPT_vertex_normal_get(ss, vd->index, vno); } if (is_zero_v3(vno)) { @@ -3256,6 +3285,7 @@ static void do_slide_relax_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int t TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, true, totnode); if (ss->cache->alt_smooth) { + SCULPT_boundary_info_ensure(ob); for (int i = 0; i < 4; i++) { BLI_task_parallel_range(0, totnode, &data, do_topology_relax_task_cb_ex, &settings); } @@ -7140,7 +7170,6 @@ static void sculpt_brush_init_tex(const Scene *scene, Sculpt *sd, SculptSession static void sculpt_brush_stroke_init(bContext *C, wmOperator *op) { - Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); Scene *scene = CTX_data_scene(C); Object *ob = CTX_data_active_object(C); Sculpt *sd = CTX_data_tool_settings(C)->sculpt; @@ -7163,6 +7192,14 @@ static void sculpt_brush_stroke_init(bContext *C, wmOperator *op) is_smooth = sculpt_needs_connectivity_info(sd, brush, ss, mode); needs_colors = ELEM(brush->sculpt_tool, SCULPT_TOOL_PAINT, SCULPT_TOOL_SMEAR); + + if (needs_colors) { + BKE_sculpt_color_layer_create_if_needed(ob); + } + + /* CTX_data_ensure_evaluated_depsgraph should be used at the end to include the updates of + * earlier steps modifying the data. */ + Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); BKE_sculpt_update_object_for_edit(depsgraph, ob, is_smooth, need_mask, needs_colors); } diff --git a/source/blender/editors/sculpt_paint/sculpt_face_set.c b/source/blender/editors/sculpt_paint/sculpt_face_set.c index 031b4f8731d..1940b007cb0 100644 --- a/source/blender/editors/sculpt_paint/sculpt_face_set.c +++ b/source/blender/editors/sculpt_paint/sculpt_face_set.c @@ -205,6 +205,7 @@ void SCULPT_do_draw_face_sets_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, in TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, true, totnode); if (ss->cache->alt_smooth) { + SCULPT_boundary_info_ensure(ob); for (int i = 0; i < 4; i++) { BLI_task_parallel_range(0, totnode, &data, do_relax_face_sets_brush_task_cb_ex, &settings); } diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_color.c b/source/blender/editors/sculpt_paint/sculpt_filter_color.c index 556b73b0ea5..59d82825740 100644 --- a/source/blender/editors/sculpt_paint/sculpt_filter_color.c +++ b/source/blender/editors/sculpt_paint/sculpt_filter_color.c @@ -265,7 +265,6 @@ static int sculpt_color_filter_modal(bContext *C, wmOperator *op, const wmEvent static int sculpt_color_filter_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { Object *ob = CTX_data_active_object(C); - Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); Sculpt *sd = CTX_data_tool_settings(C)->sculpt; SculptSession *ss = ob->sculpt; int mode = RNA_enum_get(op->ptr, "type"); @@ -285,6 +284,11 @@ static int sculpt_color_filter_invoke(bContext *C, wmOperator *op, const wmEvent SCULPT_undo_push_begin("color filter"); + BKE_sculpt_color_layer_create_if_needed(ob); + + /* CTX_data_ensure_evaluated_depsgraph should be used at the end to include the updates of + * earlier steps modifying the data. */ + Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); bool needs_pmap = mode == COLOR_FILTER_SMOOTH; BKE_sculpt_update_object_for_edit(depsgraph, ob, needs_pmap, false, true); diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c index 9c9726ff3db..e9a98a17f8a 100644 --- a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c +++ b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c @@ -310,8 +310,7 @@ static void mesh_filter_task_cb(void *__restrict userdata, break; } case MESH_FILTER_RELAX: { - SCULPT_relax_vertex( - ss, &vd, clamp_f(fade * ss->filter_cache->automask[vd.index], 0.0f, 1.0f), false, val); + SCULPT_relax_vertex(ss, &vd, clamp_f(fade, 0.0f, 1.0f), false, val); sub_v3_v3v3(disp, val, vd.co); break; } @@ -543,6 +542,10 @@ static int sculpt_mesh_filter_invoke(bContext *C, wmOperator *op, const wmEvent SCULPT_undo_push_begin("Mesh filter"); + if (ELEM(filter_type, MESH_FILTER_RELAX, MESH_FILTER_RELAX_FACE_SETS)) { + SCULPT_boundary_info_ensure(ob); + } + SCULPT_filter_cache_init(ob, sd, SCULPT_UNDO_COORDS); if (use_face_sets) { @@ -572,16 +575,6 @@ static int sculpt_mesh_filter_invoke(bContext *C, wmOperator *op, const wmEvent ss->filter_cache->enabled_axis[1] = deform_axis & MESH_FILTER_DEFORM_Y; ss->filter_cache->enabled_axis[2] = deform_axis & MESH_FILTER_DEFORM_Z; - if (RNA_enum_get(op->ptr, "type") == MESH_FILTER_RELAX) { - ss->filter_cache->automask = MEM_mallocN(totvert * sizeof(float), - "Relax filter edge automask"); - for (int i = 0; i < totvert; i++) { - ss->filter_cache->automask[i] = 1.0f; - } - SCULPT_boundary_automasking_init( - ob, AUTOMASK_INIT_BOUNDARY_EDGES, 1, ss->filter_cache->automask); - } - WM_event_add_modal_handler(C, op); return OPERATOR_RUNNING_MODAL; } diff --git a/source/blender/editors/sculpt_paint/sculpt_smooth.c b/source/blender/editors/sculpt_paint/sculpt_smooth.c index 1a699c91e9b..7fbbcd1c896 100644 --- a/source/blender/editors/sculpt_paint/sculpt_smooth.c +++ b/source/blender/editors/sculpt_paint/sculpt_smooth.c @@ -242,6 +242,9 @@ static void do_smooth_brush_task_cb_ex(void *__restrict userdata, madd_v3_v3v3fl(val, vd.co, val, fade); SCULPT_clip(sd, ss, vd.co, val); } + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; + } } } BKE_pbvh_vertex_iter_end; diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c index 47215f3ccda..a45b415b629 100644 --- a/source/blender/editors/space_outliner/outliner_draw.c +++ b/source/blender/editors/space_outliner/outliner_draw.c @@ -1376,13 +1376,13 @@ static void outliner_draw_restrictbuts(uiBlock *block, ID *id = tselem->id; bGPDlayer *gpl = (bGPDlayer *)te->directdata; - if (soops->show_restrict_flags & SO_RESTRICT_VIEWPORT) { + if (soops->show_restrict_flags & SO_RESTRICT_HIDE) { bt = uiDefIconButBitS(block, UI_BTYPE_ICON_TOGGLE, GP_LAYER_HIDE, 0, ICON_HIDE_OFF, - (int)(region->v2d.cur.xmax - restrict_offsets.viewport), + (int)(region->v2d.cur.xmax - restrict_offsets.hide), te->ys, UI_UNIT_X, UI_UNIT_Y, diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpenciloffset.c b/source/blender/gpencil_modifiers/intern/MOD_gpenciloffset.c index 09131b7d673..00fc4035ada 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpenciloffset.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpenciloffset.c @@ -106,19 +106,23 @@ static void deformStroke(GpencilModifierData *md, bGPDspoint *pt = &gps->points[i]; MDeformVert *dvert = gps->dvert != NULL ? &gps->dvert[i] : NULL; - /* verify vertex group */ + /* Verify vertex group. */ const float weight = get_modifier_point_weight( dvert, (mmd->flag & GP_OFFSET_INVERT_VGROUP) != 0, def_nr); if (weight < 0.0f) { continue; } - /* calculate matrix */ + /* Calculate matrix. */ mul_v3_v3fl(loc, mmd->loc, weight); mul_v3_v3fl(rot, mmd->rot, weight); mul_v3_v3fl(scale, mmd->scale, weight); add_v3_fl(scale, 1.0); loc_eul_size_to_mat4(mat, loc, rot, scale); + /* Apply scale to thickness. */ + float unit_scale = (scale[0] + scale[1] + scale[2]) / 3.0f; + pt->pressure *= unit_scale; + mul_m4_v3(mat, &pt->x); } /* Calc geometry data. */ diff --git a/tests/gtests/runner/CMakeLists.txt b/tests/gtests/runner/CMakeLists.txt index 4da0bce09a4..59537aab571 100644 --- a/tests/gtests/runner/CMakeLists.txt +++ b/tests/gtests/runner/CMakeLists.txt @@ -36,7 +36,7 @@ endif() # directly referenced from other code. get_property(_test_libs GLOBAL PROPERTY BLENDER_TEST_LIBS) if(WIN32) - list(APPEND TEST_LIBS ${_test_libs}) + # Win32 is set using target_link_options after target creation. elseif(APPLE) list(APPEND TEST_LIBS "-Wl,-force_load" ${_test_libs}) elseif(UNIX) @@ -44,7 +44,6 @@ elseif(UNIX) else() message(FATAL_ERROR "Unknown how to link whole-archive with your compiler ${CMAKE_CXX_COMPILER_ID}") endif() -unset(_test_libs) # This builds `bin/tests/blender_test`, but does not add it as a single test. setup_libdirs() @@ -56,6 +55,18 @@ BLENDER_SRC_GTEST_EX( ) setup_liblinks(blender_test) +if(WIN32) + foreach(_lib ${_test_libs}) + # Both target_link_libraries and target_link_options are required here + # target_link_libraries will add any dependend libraries, while just setting + # the wholearchive flag in target link options will not. + target_link_libraries(blender_test ${_lib}) + target_link_options(blender_test PRIVATE /wholearchive:$<TARGET_FILE:${_lib}>) + endforeach() +endif() + +unset(_test_libs) + # This runs the blender_test executable with `--gtest_list_tests`, then # exposes those tests individually to the ctest runner. # See https://cmake.org/cmake/help/v3.18/module/GoogleTest.html @@ -66,8 +77,10 @@ set(_GOOGLETEST_DISCOVER_TESTS_SCRIPT ) gtest_discover_tests(blender_test - # So that unit tests know where to find files: +# So that the binary can find its shared libs on window. + WORKING_DIRECTORY "$<TARGET_FILE_DIR:blender>" +# So that unit tests know where to find files: EXTRA_ARGS --test-assets-dir "${CMAKE_SOURCE_DIR}/../lib/tests" - --test-release-dir "$<TARGET_FILE_DIR:blender>/${BLENDER_VERSION}" + --test-release-dir "${CMAKE_INSTALL_PREFIX}/${BLENDER_VERSION}" ) |