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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans Goudey <h.goudey@me.com>2021-04-02 08:16:01 +0300
committerHans Goudey <h.goudey@me.com>2021-04-02 08:16:23 +0300
commita0e1080428abb991c443a40b29d2ae3948eb4a56 (patch)
tree735c26798d07a07690ebe827d604ee438afcc3e9 /source/blender/modifiers/intern/MOD_boolean.c
parent77f685774090c18b8da7a9860861664ed0fdd81e (diff)
Cleanup: Remove unecessary C API for direct mesh boolean
The main goal here is to remove the need for a C API to the code in `mesh_boolean_convert.cc`. This is achieved by moving `MOD_boolean.c` to C++ and making the necessary changes for it to compile. On top of that there are some other slight simplifications possible to the direct mesh boolean code: it doesn't need to copy the material remaps, and the modifier code can use some other C++ types directly.
Diffstat (limited to 'source/blender/modifiers/intern/MOD_boolean.c')
-rw-r--r--source/blender/modifiers/intern/MOD_boolean.c728
1 files changed, 0 insertions, 728 deletions
diff --git a/source/blender/modifiers/intern/MOD_boolean.c b/source/blender/modifiers/intern/MOD_boolean.c
deleted file mode 100644
index d92f0d4219e..00000000000
--- a/source/blender/modifiers/intern/MOD_boolean.c
+++ /dev/null
@@ -1,728 +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 by the Blender Foundation.
- * All rights reserved.
- */
-
-/** \file
- * \ingroup modifiers
- */
-
-// #define DEBUG_TIME
-
-#include <stdio.h>
-
-#include "BLI_utildefines.h"
-
-#include "BLI_alloca.h"
-#include "BLI_array.h"
-#include "BLI_math_geom.h"
-#include "BLI_math_matrix.h"
-
-#include "BLT_translation.h"
-
-#include "DNA_collection_types.h"
-#include "DNA_defaults.h"
-#include "DNA_mesh_types.h"
-#include "DNA_meshdata_types.h"
-#include "DNA_object_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_screen_types.h"
-
-#include "BKE_collection.h"
-#include "BKE_context.h"
-#include "BKE_global.h" /* only to check G.debug */
-#include "BKE_lib_id.h"
-#include "BKE_lib_query.h"
-#include "BKE_material.h"
-#include "BKE_mesh.h"
-#include "BKE_mesh_boolean_convert.h"
-#include "BKE_mesh_wrapper.h"
-#include "BKE_modifier.h"
-#include "BKE_screen.h"
-
-#include "UI_interface.h"
-#include "UI_resources.h"
-
-#include "RNA_access.h"
-
-#include "MOD_ui_common.h"
-#include "MOD_util.h"
-
-#include "DEG_depsgraph_query.h"
-
-#include "MEM_guardedalloc.h"
-
-#include "bmesh.h"
-#include "bmesh_tools.h"
-#include "tools/bmesh_boolean.h"
-#include "tools/bmesh_intersect.h"
-
-#ifdef DEBUG_TIME
-# include "PIL_time.h"
-# include "PIL_time_utildefines.h"
-#endif
-
-static void initData(ModifierData *md)
-{
- BooleanModifierData *bmd = (BooleanModifierData *)md;
-
- BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(bmd, modifier));
-
- MEMCPY_STRUCT_AFTER(bmd, DNA_struct_default_get(BooleanModifierData), modifier);
-}
-
-static bool isDisabled(const struct Scene *UNUSED(scene),
- ModifierData *md,
- bool UNUSED(useRenderParams))
-{
- BooleanModifierData *bmd = (BooleanModifierData *)md;
- Collection *col = bmd->collection;
-
- if (bmd->flag & eBooleanModifierFlag_Object) {
- return !bmd->object || bmd->object->type != OB_MESH;
- }
- if (bmd->flag & eBooleanModifierFlag_Collection) {
- /* The Exact solver tolerates an empty collection. */
- return !col && bmd->solver != eBooleanModifierSolver_Exact;
- }
- return false;
-}
-
-static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData)
-{
- BooleanModifierData *bmd = (BooleanModifierData *)md;
-
- walk(userData, ob, (ID **)&bmd->collection, IDWALK_CB_NOP);
- walk(userData, ob, (ID **)&bmd->object, IDWALK_CB_NOP);
-}
-
-static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
-{
- BooleanModifierData *bmd = (BooleanModifierData *)md;
- if ((bmd->flag & eBooleanModifierFlag_Object) && bmd->object != NULL) {
- DEG_add_object_relation(ctx->node, bmd->object, DEG_OB_COMP_TRANSFORM, "Boolean Modifier");
- DEG_add_object_relation(ctx->node, bmd->object, DEG_OB_COMP_GEOMETRY, "Boolean Modifier");
- }
-
- Collection *col = bmd->collection;
-
- if ((bmd->flag & eBooleanModifierFlag_Collection) && col != NULL) {
- FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (col, operand_ob) {
- if (operand_ob->type == OB_MESH && operand_ob != ctx->object) {
- DEG_add_object_relation(ctx->node, operand_ob, DEG_OB_COMP_TRANSFORM, "Boolean Modifier");
- DEG_add_object_relation(ctx->node, operand_ob, DEG_OB_COMP_GEOMETRY, "Boolean Modifier");
- }
- }
- FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
- }
- /* We need own transformation as well. */
- DEG_add_modifier_to_transform_relation(ctx->node, "Boolean Modifier");
-}
-
-static Mesh *get_quick_mesh(
- Object *ob_self, Mesh *mesh_self, Object *ob_operand_ob, Mesh *mesh_operand_ob, int operation)
-{
- Mesh *result = NULL;
-
- if (mesh_self->totpoly == 0 || mesh_operand_ob->totpoly == 0) {
- switch (operation) {
- case eBooleanModifierOp_Intersect:
- result = BKE_mesh_new_nomain(0, 0, 0, 0, 0);
- break;
-
- case eBooleanModifierOp_Union:
- if (mesh_self->totpoly != 0) {
- result = mesh_self;
- }
- else {
- result = (Mesh *)BKE_id_copy_ex(NULL, &mesh_operand_ob->id, NULL, LIB_ID_COPY_LOCALIZE);
-
- float imat[4][4];
- float omat[4][4];
-
- invert_m4_m4(imat, ob_self->obmat);
- mul_m4_m4m4(omat, imat, ob_operand_ob->obmat);
-
- const int mverts_len = result->totvert;
- MVert *mv = result->mvert;
-
- for (int i = 0; i < mverts_len; i++, mv++) {
- mul_m4_v3(omat, mv->co);
- }
-
- result->runtime.cd_dirty_vert |= CD_MASK_NORMAL;
- }
-
- break;
-
- case eBooleanModifierOp_Difference:
- result = mesh_self;
- break;
- }
- }
-
- return result;
-}
-
-/* has no meaning for faces, do this so we can tell which face is which */
-#define BM_FACE_TAG BM_ELEM_DRAW
-
-/**
- * Compare selected/unselected.
- */
-static int bm_face_isect_pair(BMFace *f, void *UNUSED(user_data))
-{
- return BM_elem_flag_test(f, BM_FACE_TAG) ? 1 : 0;
-}
-
-static bool BMD_error_messages(const Object *ob, ModifierData *md, Collection *col)
-{
- BooleanModifierData *bmd = (BooleanModifierData *)md;
-
- bool error_returns_result = false;
-
- const bool operand_collection = (bmd->flag & eBooleanModifierFlag_Collection) != 0;
- const bool use_exact = bmd->solver == eBooleanModifierSolver_Exact;
- const bool operation_intersect = bmd->operation == eBooleanModifierOp_Intersect;
-
-#ifndef WITH_GMP
- /* If compiled without GMP, return a error. */
- if (use_exact) {
- BKE_modifier_set_error(ob, md, "Compiled without GMP, using fast solver");
- error_returns_result = false;
- }
-#endif
-
- /* If intersect is selected using fast solver, return a error. */
- if (operand_collection && operation_intersect && !use_exact) {
- BKE_modifier_set_error(ob, md, "Cannot execute, intersect only available using exact solver");
- error_returns_result = true;
- }
-
- /* If the selected collection is empty and using fast solver, return a error. */
- if (operand_collection) {
- if (!use_exact && BKE_collection_is_empty(col)) {
- BKE_modifier_set_error(ob, md, "Cannot execute, fast solver and empty collection");
- error_returns_result = true;
- }
-
- /* If the selected collection contain non mesh objects, return a error. */
- if (col) {
- FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (col, operand_ob) {
- if (operand_ob->type != OB_MESH) {
- BKE_modifier_set_error(
- ob, md, "Cannot execute, the selected collection contains non mesh objects");
- error_returns_result = true;
- }
- }
- FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
- }
- }
-
- return error_returns_result;
-}
-
-static BMesh *BMD_mesh_bm_create(
- Mesh *mesh, Object *object, Mesh *mesh_operand_ob, Object *operand_ob, bool *r_is_flip)
-{
- BMesh *bm;
-
- *r_is_flip = (is_negative_m4(object->obmat) != is_negative_m4(operand_ob->obmat));
-
- const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(mesh, mesh_operand_ob);
-
- bm = BM_mesh_create(&allocsize,
- &((struct BMeshCreateParams){
- .use_toolflags = false,
- }));
-
- BM_mesh_bm_from_me(bm,
- mesh_operand_ob,
- &((struct BMeshFromMeshParams){
- .calc_face_normal = true,
- }));
-
- if (UNLIKELY(*r_is_flip)) {
- const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS);
- BMIter iter;
- BMFace *efa;
- BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
- BM_face_normal_flip_ex(bm, efa, cd_loop_mdisp_offset, true);
- }
- }
-
- BM_mesh_bm_from_me(bm,
- mesh,
- &((struct BMeshFromMeshParams){
- .calc_face_normal = true,
- }));
-
- return bm;
-}
-
-static void BMD_mesh_intersection(BMesh *bm,
- ModifierData *md,
- const ModifierEvalContext *ctx,
- Mesh *mesh_operand_ob,
- Object *object,
- Object *operand_ob,
- bool is_flip)
-{
- BooleanModifierData *bmd = (BooleanModifierData *)md;
-
- /* main bmesh intersection setup */
- /* create tessface & intersect */
- const int looptris_tot = poly_to_tri_count(bm->totface, bm->totloop);
- int tottri;
- BMLoop *(*looptris)[3] = MEM_malloc_arrayN(looptris_tot, sizeof(*looptris), __func__);
-
- BM_mesh_calc_tessellation_beauty(bm, looptris, &tottri);
-
- /* postpone this until after tessellating
- * so we can use the original normals before the vertex are moved */
- {
- BMIter iter;
- int i;
- const int i_verts_end = mesh_operand_ob->totvert;
- const int i_faces_end = mesh_operand_ob->totpoly;
-
- float imat[4][4];
- float omat[4][4];
- invert_m4_m4(imat, object->obmat);
- mul_m4_m4m4(omat, imat, operand_ob->obmat);
-
- BMVert *eve;
- i = 0;
- BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
- mul_m4_v3(omat, eve->co);
- if (++i == i_verts_end) {
- break;
- }
- }
-
- /* we need face normals because of 'BM_face_split_edgenet'
- * we could calculate on the fly too (before calling split). */
- float nmat[3][3];
- copy_m3_m4(nmat, omat);
- invert_m3(nmat);
-
- if (UNLIKELY(is_flip)) {
- negate_m3(nmat);
- }
-
- const short ob_src_totcol = operand_ob->totcol;
- short *material_remap = BLI_array_alloca(material_remap, ob_src_totcol ? ob_src_totcol : 1);
-
- /* Using original (not evaluated) object here since we are writing to it. */
- /* XXX Pretty sure comment above is fully wrong now with CoW & co ? */
- BKE_object_material_remap_calc(ctx->object, operand_ob, material_remap);
-
- BMFace *efa;
- i = 0;
- BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
- mul_transposed_m3_v3(nmat, efa->no);
- normalize_v3(efa->no);
-
- /* Temp tag to test which side split faces are from. */
- BM_elem_flag_enable(efa, BM_FACE_TAG);
-
- /* remap material */
- if (LIKELY(efa->mat_nr < ob_src_totcol)) {
- efa->mat_nr = material_remap[efa->mat_nr];
- }
-
- if (++i == i_faces_end) {
- break;
- }
- }
- }
-
- /* not needed, but normals for 'dm' will be invalid,
- * currently this is ok for 'BM_mesh_intersect' */
- // BM_mesh_normals_update(bm);
-
- bool use_separate = false;
- bool use_dissolve = true;
- bool use_island_connect = true;
-
- /* change for testing */
- if (G.debug & G_DEBUG) {
- use_separate = (bmd->bm_flag & eBooleanModifierBMeshFlag_BMesh_Separate) != 0;
- use_dissolve = (bmd->bm_flag & eBooleanModifierBMeshFlag_BMesh_NoDissolve) == 0;
- use_island_connect = (bmd->bm_flag & eBooleanModifierBMeshFlag_BMesh_NoConnectRegions) == 0;
- }
-
- BM_mesh_intersect(bm,
- looptris,
- tottri,
- bm_face_isect_pair,
- NULL,
- false,
- use_separate,
- use_dissolve,
- use_island_connect,
- false,
- false,
- bmd->operation,
- bmd->double_threshold);
-
- MEM_freeN(looptris);
-}
-
-#ifdef WITH_GMP
-
-/* Get a mapping from material slot numbers in the src_ob to slot numbers in the dst_ob.
- * If a material doesn't exist in the dst_ob, the mapping just goes to the same slot
- * or to zero if there aren't enough slots in the destination.
- * Caller must MEM_freeN the returned array. */
-static short *get_material_remap(Object *dest_ob, Object *src_ob)
-{
- short *remap;
- int n = dest_ob->totcol;
- if (n <= 0) {
- n = 1;
- }
- remap = MEM_mallocN(n * sizeof(short), __func__);
- BKE_object_material_remap_calc(dest_ob, src_ob, remap);
- return remap;
-}
-
-/* New method: bypass trip through BMesh. */
-static Mesh *exact_boolean_mesh(BooleanModifierData *bmd,
- const ModifierEvalContext *ctx,
- Mesh *mesh)
-{
- Mesh *result;
- Mesh *mesh_operand;
- short *remap;
- Mesh **meshes = NULL;
- const float(**obmats)[4][4] = NULL;
- short **material_remaps = NULL;
- BLI_array_declare(meshes);
- BLI_array_declare(obmats);
- BLI_array_declare(material_remaps);
-
-# ifdef DEBUG_TIME
- TIMEIT_START(boolean_bmesh);
-# endif
-
- if ((bmd->flag & eBooleanModifierFlag_Object) && bmd->object == NULL) {
- return mesh;
- }
-
- BLI_array_append(meshes, mesh);
- BLI_array_append(obmats, &ctx->object->obmat);
- BLI_array_append(material_remaps, NULL);
- if (bmd->flag & eBooleanModifierFlag_Object) {
- mesh_operand = BKE_modifier_get_evaluated_mesh_from_evaluated_object(bmd->object, false);
- if (!mesh_operand) {
- return mesh;
- }
- BKE_mesh_wrapper_ensure_mdata(mesh_operand);
- BLI_array_append(meshes, mesh_operand);
- BLI_array_append(obmats, &bmd->object->obmat);
- remap = get_material_remap(ctx->object, bmd->object);
- BLI_array_append(material_remaps, remap);
- }
- else if (bmd->flag & eBooleanModifierFlag_Collection) {
- Collection *collection = bmd->collection;
- /* Allow collection to be empty: then target mesh will just removed self-intersections. */
- if (collection) {
- FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (collection, ob) {
- if (ob->type == OB_MESH && ob != ctx->object) {
- Mesh *collection_mesh = BKE_modifier_get_evaluated_mesh_from_evaluated_object(ob, false);
- if (!collection_mesh) {
- continue;
- }
- BKE_mesh_wrapper_ensure_mdata(collection_mesh);
- BLI_array_append(meshes, collection_mesh);
- BLI_array_append(obmats, &ob->obmat);
- remap = get_material_remap(ctx->object, ob);
- BLI_array_append(material_remaps, remap);
- }
- }
- FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
- }
- }
-
- const bool use_self = (bmd->flag & eBooleanModifierFlag_Self) != 0;
- const bool hole_tolerant = (bmd->flag & eBooleanModifierFlag_HoleTolerant) != 0;
- result = BKE_mesh_boolean((const Mesh **)meshes,
- (const float(**)[4][4])obmats,
- &ctx->object->obmat,
- (const short **)material_remaps,
- BLI_array_len(meshes),
- use_self,
- hole_tolerant,
- bmd->operation);
-
- BLI_array_free(meshes);
- BLI_array_free(obmats);
- for (int i = 0; i < BLI_array_len(material_remaps); i++) {
- remap = material_remaps[i];
- if (remap) {
- MEM_freeN(remap);
- }
- }
- BLI_array_free(material_remaps);
-
-# ifdef DEBUG_TIME
- TIMEIT_END(boolean_bmesh);
-# endif
-
- return result;
-}
-#endif
-
-static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh)
-{
- BooleanModifierData *bmd = (BooleanModifierData *)md;
- Object *object = ctx->object;
- Mesh *result = mesh;
- Mesh *mesh_operand_ob;
- BMesh *bm;
- Collection *collection = bmd->collection;
-
- bool is_flip = false;
- const bool confirm_return = true;
-#ifdef WITH_GMP
- if (bmd->solver == eBooleanModifierSolver_Exact) {
- return exact_boolean_mesh(bmd, ctx, mesh);
- }
-#endif
-
-#ifdef DEBUG_TIME
- TIMEIT_START(boolean_bmesh);
-#endif
-
- if (bmd->flag & eBooleanModifierFlag_Object) {
- if (bmd->object == NULL) {
- return result;
- }
-
- BMD_error_messages(ctx->object, md, NULL);
-
- Object *operand_ob = bmd->object;
-
-#ifdef DEBUG_TIME
- TIMEIT_BLOCK_INIT(operand_get_evaluated_mesh);
- TIMEIT_BLOCK_START(operand_get_evaluated_mesh);
-#endif
- mesh_operand_ob = BKE_modifier_get_evaluated_mesh_from_evaluated_object(operand_ob, false);
-#ifdef DEBUG_TIME
- TIMEIT_BLOCK_END(operand_get_evaluated_mesh);
- TIMEIT_BLOCK_STATS(operand_get_evaluated_mesh);
-#endif
-
- if (mesh_operand_ob) {
- /* XXX This is utterly non-optimal, we may go from a bmesh to a mesh back to a bmesh!
- * But for 2.90 better not try to be smart here. */
- BKE_mesh_wrapper_ensure_mdata(mesh_operand_ob);
- /* when one of objects is empty (has got no faces) we could speed up
- * calculation a bit returning one of objects' derived meshes (or empty one)
- * Returning mesh is depended on modifiers operation (sergey) */
- result = get_quick_mesh(object, mesh, operand_ob, mesh_operand_ob, bmd->operation);
-
- if (result == NULL) {
-#ifdef DEBUG_TIME
- TIMEIT_BLOCK_INIT(object_BMD_mesh_bm_create);
- TIMEIT_BLOCK_START(object_BMD_mesh_bm_create);
-#endif
- bm = BMD_mesh_bm_create(mesh, object, mesh_operand_ob, operand_ob, &is_flip);
-#ifdef DEBUG_TIME
- TIMEIT_BLOCK_END(object_BMD_mesh_bm_create);
- TIMEIT_BLOCK_STATS(object_BMD_mesh_bm_create);
-#endif
-
-#ifdef DEBUG_TIME
- TIMEIT_BLOCK_INIT(BMD_mesh_intersection);
- TIMEIT_BLOCK_START(BMD_mesh_intersection);
-#endif
- BMD_mesh_intersection(bm, md, ctx, mesh_operand_ob, object, operand_ob, is_flip);
-#ifdef DEBUG_TIME
- TIMEIT_BLOCK_END(BMD_mesh_intersection);
- TIMEIT_BLOCK_STATS(BMD_mesh_intersection);
-#endif
-
-#ifdef DEBUG_TIME
- TIMEIT_BLOCK_INIT(BKE_mesh_from_bmesh_for_eval_nomain);
- TIMEIT_BLOCK_START(BKE_mesh_from_bmesh_for_eval_nomain);
-#endif
- result = BKE_mesh_from_bmesh_for_eval_nomain(bm, NULL, mesh);
-#ifdef DEBUG_TIME
- TIMEIT_BLOCK_END(BKE_mesh_from_bmesh_for_eval_nomain);
- TIMEIT_BLOCK_STATS(BKE_mesh_from_bmesh_for_eval_nomain);
-#endif
- BM_mesh_free(bm);
- result->runtime.cd_dirty_vert |= CD_MASK_NORMAL;
- }
-
- /* if new mesh returned, return it; otherwise there was
- * an error, so delete the modifier object */
- if (result == NULL) {
- BKE_modifier_set_error(object, md, "Cannot execute boolean operation");
- }
- }
- }
- else {
- if (collection == NULL) {
- return result;
- }
-
- /* Return result for certain errors. */
- if (BMD_error_messages(ctx->object, md, collection) == confirm_return) {
- return result;
- }
-
- FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (collection, operand_ob) {
- if (operand_ob->type == OB_MESH && operand_ob != ctx->object) {
-
- mesh_operand_ob = BKE_modifier_get_evaluated_mesh_from_evaluated_object(operand_ob, false);
-
- if (mesh_operand_ob) {
- /* XXX This is utterly non-optimal, we may go from a bmesh to a mesh back to a bmesh!
- * But for 2.90 better not try to be smart here. */
- BKE_mesh_wrapper_ensure_mdata(mesh_operand_ob);
-
- bm = BMD_mesh_bm_create(mesh, object, mesh_operand_ob, operand_ob, &is_flip);
-
- BMD_mesh_intersection(bm, md, ctx, mesh_operand_ob, object, operand_ob, is_flip);
-
- /* Needed for multiple objects to work. */
- BM_mesh_bm_to_me(NULL,
- bm,
- mesh,
- (&(struct BMeshToMeshParams){
- .calc_object_remap = false,
- }));
-
- result = BKE_mesh_from_bmesh_for_eval_nomain(bm, NULL, mesh);
- BM_mesh_free(bm);
- result->runtime.cd_dirty_vert |= CD_MASK_NORMAL;
- }
- }
- }
- FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
- }
-
-#ifdef DEBUG_TIME
- TIMEIT_END(boolean_bmesh);
-#endif
-
- return result;
-}
-
-static void requiredDataMask(Object *UNUSED(ob),
- ModifierData *UNUSED(md),
- CustomData_MeshMasks *r_cddata_masks)
-{
- r_cddata_masks->vmask |= CD_MASK_MDEFORMVERT;
- r_cddata_masks->emask |= CD_MASK_MEDGE;
- r_cddata_masks->fmask |= CD_MASK_MTFACE;
-}
-
-static void panel_draw(const bContext *UNUSED(C), Panel *panel)
-{
- uiLayout *layout = panel->layout;
-
- PointerRNA *ptr = modifier_panel_get_property_pointers(panel, NULL);
-
- uiItemR(layout, ptr, "operation", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
-
- uiLayoutSetPropSep(layout, true);
-
- uiItemR(layout, ptr, "operand_type", 0, NULL, ICON_NONE);
- if (RNA_enum_get(ptr, "operand_type") == eBooleanModifierFlag_Object) {
- uiItemR(layout, ptr, "object", 0, NULL, ICON_NONE);
- }
- else {
- uiItemR(layout, ptr, "collection", 0, NULL, ICON_NONE);
- }
-
- uiItemR(layout, ptr, "solver", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
-
- modifier_panel_end(layout, ptr);
-}
-
-static void solver_options_panel_draw(const bContext *UNUSED(C), Panel *panel)
-{
- uiLayout *layout = panel->layout;
-
- PointerRNA *ptr = modifier_panel_get_property_pointers(panel, NULL);
-
- const bool use_exact = RNA_enum_get(ptr, "solver") == eBooleanModifierSolver_Exact;
-
- uiLayoutSetPropSep(layout, true);
-
- uiLayout *col = uiLayoutColumn(layout, true);
- if (use_exact) {
- /* When operand is collection, we always use_self. */
- if (RNA_enum_get(ptr, "operand_type") == eBooleanModifierFlag_Object) {
- uiItemR(col, ptr, "use_self", 0, NULL, ICON_NONE);
- }
- uiItemR(col, ptr, "use_hole_tolerant", 0, NULL, ICON_NONE);
- }
- else {
- uiItemR(col, ptr, "double_threshold", 0, NULL, ICON_NONE);
- }
-
- if (G.debug) {
- uiItemR(col, ptr, "debug_options", 0, NULL, ICON_NONE);
- }
-}
-
-static void panelRegister(ARegionType *region_type)
-{
- PanelType *panel = modifier_panel_register(region_type, eModifierType_Boolean, panel_draw);
- modifier_subpanel_register(
- region_type, "solver_options", "Solver Options", NULL, solver_options_panel_draw, panel);
-}
-
-ModifierTypeInfo modifierType_Boolean = {
- /* name */ "Boolean",
- /* structName */ "BooleanModifierData",
- /* structSize */ sizeof(BooleanModifierData),
- /* srna */ &RNA_BooleanModifier,
- /* type */ eModifierTypeType_Nonconstructive,
- /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsEditmode,
- /* icon */ ICON_MOD_BOOLEAN,
-
- /* copyData */ BKE_modifier_copydata_generic,
-
- /* deformVerts */ NULL,
- /* deformMatrices */ NULL,
- /* deformVertsEM */ NULL,
- /* deformMatricesEM */ NULL,
- /* modifyMesh */ modifyMesh,
- /* modifyHair */ NULL,
- /* modifyGeometrySet */ NULL,
- /* modifyVolume */ NULL,
-
- /* initData */ initData,
- /* requiredDataMask */ requiredDataMask,
- /* freeData */ NULL,
- /* isDisabled */ isDisabled,
- /* updateDepsgraph */ updateDepsgraph,
- /* dependsOnTime */ NULL,
- /* dependsOnNormals */ NULL,
- /* foreachIDLink */ foreachIDLink,
- /* foreachTexLink */ NULL,
- /* freeRuntimeData */ NULL,
- /* panelRegister */ panelRegister,
- /* blendWrite */ NULL,
- /* blendRead */ NULL,
-};