Blender V5.0
pointcloud/intern/separate.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2025 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include "BLI_index_mask.hh"
6#include "BLI_task.hh"
7#include "BLI_vector_set.hh"
8
9#include "BKE_context.hh"
10#include "BKE_layer.hh"
11#include "BKE_lib_id.hh"
12
13#include "BKE_pointcloud.hh"
14
16#include "ED_object.hh"
17#include "ED_pointcloud.hh"
18
19#include "DNA_layer_types.h"
21
22#include "DEG_depsgraph.hh"
23
24#include "WM_api.hh"
25
27
29{
30 Main *bmain = CTX_data_main(C);
31 Scene *scene = CTX_data_scene(C);
32 ViewLayer *view_layer = CTX_data_view_layer(C);
33
35 scene, view_layer, CTX_wm_view3d(C));
36
37 VectorSet<PointCloud *> src_pointclouds;
38 for (Base *base_src : bases) {
39 src_pointclouds.add(static_cast<PointCloud *>(base_src->object->data));
40 }
41
42 /* Modify new point clouds and generate new point clouds in parallel. */
43 Array<PointCloud *> dst_pointclouds(src_pointclouds.size());
44 threading::parallel_for(dst_pointclouds.index_range(), 1, [&](const IndexRange range) {
45 for (const int i : range) {
46 IndexMaskMemory memory;
47 const IndexMask selection = retrieve_selected_points(*src_pointclouds[i], memory);
48 if (selection.is_empty()) {
49 dst_pointclouds[i] = nullptr;
50 continue;
51 }
52 dst_pointclouds[i] = copy_selection(*src_pointclouds[i], selection);
53 const IndexMask inverse = selection.complement(IndexRange(src_pointclouds[i]->totpoint),
54 memory);
55 BKE_pointcloud_nomain_to_pointcloud(copy_selection(*src_pointclouds[i], inverse),
56 src_pointclouds[i]);
57 }
58 });
59
60 /* Move new point clouds into main data-base. */
61 for (const int i : dst_pointclouds.index_range()) {
62 if (PointCloud *dst = dst_pointclouds[i]) {
63 dst_pointclouds[i] = BKE_pointcloud_add(bmain, BKE_id_name(src_pointclouds[i]->id));
64 pointcloud_copy_parameters(*src_pointclouds[i], *dst_pointclouds[i]);
65 BKE_pointcloud_nomain_to_pointcloud(dst, dst_pointclouds[i]);
66 }
67 }
68
69 /* Skip processing objects with no selected elements. */
70 bases.remove_if([&](Base *base) {
71 PointCloud *pointcloud = static_cast<PointCloud *>(base->object->data);
72 return dst_pointclouds[src_pointclouds.index_of(pointcloud)] == nullptr;
73 });
74
75 if (bases.is_empty()) {
76 return OPERATOR_CANCELLED;
77 }
78
79 /* Add new objects for the new point clouds. */
80 for (Base *base_src : bases) {
81 PointCloud *src = static_cast<PointCloud *>(base_src->object->data);
82 PointCloud *dst = dst_pointclouds[src_pointclouds.index_of(src)];
83
84 Base *base_dst = object::add_duplicate(
85 bmain, scene, view_layer, base_src, eDupli_ID_Flags(U.dupflag) & USER_DUP_ACT);
86 Object *object_dst = base_dst->object;
87 object_dst->mode = OB_MODE_OBJECT;
88 object_dst->data = dst;
89
92 WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, base_src->object);
94 }
95
97 return OPERATOR_FINISHED;
98}
99
101{
102 ot->name = "Separate";
103 ot->idname = "POINTCLOUD_OT_separate";
104 ot->description = "Separate selected geometry into a new point cloud";
105
106 ot->exec = separate_exec;
108
110}
111
112} // namespace blender::ed::pointcloud
Scene * CTX_data_scene(const bContext *C)
Main * CTX_data_main(const bContext *C)
View3D * CTX_wm_view3d(const bContext *C)
ViewLayer * CTX_data_view_layer(const bContext *C)
blender::Vector< Base * > BKE_view_layer_array_from_bases_in_edit_mode(const Scene *scene, ViewLayer *view_layer, const View3D *v3d)
const char * BKE_id_name(const ID &id)
General operations for point clouds.
PointCloud * BKE_pointcloud_add(Main *bmain, const char *name)
void BKE_pointcloud_nomain_to_pointcloud(PointCloud *pointcloud_src, PointCloud *pointcloud_dst)
void pointcloud_copy_parameters(const PointCloud &src, PointCloud &dst)
void DEG_id_tag_update(ID *id, unsigned int flags)
void DEG_relations_tag_update(Main *bmain)
@ ID_RECALC_GEOMETRY
Definition DNA_ID.h:1074
struct Base Base
@ OB_MODE_OBJECT
struct Object Object
struct PointCloud PointCloud
eDupli_ID_Flags
@ USER_DUP_ACT
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
#define C
Definition RandGen.cpp:29
#define ND_DRAW
Definition WM_types.hh:461
@ OPTYPE_UNDO
Definition WM_types.hh:182
@ OPTYPE_REGISTER
Definition WM_types.hh:180
#define NC_OBJECT
Definition WM_types.hh:379
#define U
IndexRange index_range() const
Definition BLI_array.hh:360
bool add(const Key &key)
int64_t size() const
Base * add_duplicate(Main *bmain, Scene *scene, ViewLayer *view_layer, Base *base, eDupli_ID_Flags dupflag)
bool editable_pointcloud_in_edit_mode_poll(bContext *C)
Definition operators.cc:73
static wmOperatorStatus separate_exec(bContext *C, wmOperator *)
void POINTCLOUD_OT_separate(wmOperatorType *ot)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
Definition BLI_task.hh:93
struct Object * object
i
Definition text_draw.cc:230
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
wmOperatorType * ot
Definition wm_files.cc:4237