Blender V5.0
transform_convert_particle.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
10#include "DNA_particle_types.h"
11
12#include "MEM_guardedalloc.h"
13
14#include "BLI_math_matrix.h"
15#include "BLI_math_vector.h"
16
17#include "BKE_layer.hh"
18#include "BKE_object_types.hh"
19#include "BKE_particle.h"
20#include "BKE_pointcache.h"
21
22#include "ED_particle.hh"
23
24#include "transform.hh"
25#include "transform_snap.hh"
26
27/* Own include. */
28#include "transform_convert.hh"
29
30namespace blender::ed::transform {
31
32/* -------------------------------------------------------------------- */
35
37{
39
40 TransData *td = nullptr;
45 PTCacheEdit *edit = PE_get_current(t->depsgraph, t->scene, ob);
46 ParticleSystem *psys = nullptr;
47 PTCacheEditPoint *point;
48 PTCacheEditKey *key;
49 float mat[4][4];
50 int i, k, transformparticle;
51 int count = 0, hasselected = 0;
52 const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
53
54 if (edit == nullptr || t->settings->particle.selectmode == SCE_SELECT_PATH) {
55 return;
56 }
57
58 psys = edit->psys;
59
60 for (i = 0, point = edit->points; i < edit->totpoint; i++, point++) {
61 point->flag &= ~PEP_TRANSFORM;
62 transformparticle = 0;
63
64 if ((point->flag & PEP_HIDE) == 0) {
65 for (k = 0, key = point->keys; k < point->totkey; k++, key++) {
66 if ((key->flag & PEK_HIDE) == 0) {
67 if (key->flag & PEK_SELECT) {
68 hasselected = 1;
69 transformparticle = 1;
70 }
71 else if (is_prop_edit) {
72 transformparticle = 1;
73 }
74 }
75 }
76 }
77
78 if (transformparticle) {
79 count += point->totkey;
80 point->flag |= PEP_TRANSFORM;
81 }
82 }
83
84 /* NOTE: in prop mode we need at least 1 selected. */
85 if (hasselected == 0) {
86 return;
87 }
88
89 tc->data_len = count;
90 td = tc->data = MEM_calloc_arrayN<TransData>(tc->data_len, "TransObData(Particle Mode)");
91
92 if (t->mode == TFM_BAKE_TIME) {
93 tx = tc->data_ext = MEM_calloc_arrayN<TransDataExtension>(tc->data_len,
94 "Particle_TransExtension");
95 }
96 else {
97 tx = tc->data_ext = nullptr;
98 }
99
100 unit_m4(mat);
101
102 invert_m4_m4(ob->runtime->world_to_object.ptr(), ob->object_to_world().ptr());
103
104 for (i = 0, point = edit->points; i < edit->totpoint; i++, point++) {
105 TransData *head, *tail;
106 head = tail = td;
107
108 if (!(point->flag & PEP_TRANSFORM)) {
109 continue;
110 }
111
112 if (psys && !(psys->flag & PSYS_GLOBAL_HAIR)) {
113 ParticleSystemModifierData *psmd_eval = edit->psmd_eval;
115 ob, psmd_eval->mesh_final, psys->part->from, psys->particles + i, mat);
116 }
117
118 for (k = 0, key = point->keys; k < point->totkey; k++, key++) {
119 if (key->flag & PEK_USE_WCO) {
120 copy_v3_v3(key->world_co, key->co);
121 mul_m4_v3(mat, key->world_co);
122 td->loc = key->world_co;
123 }
124 else {
125 td->loc = key->co;
126 }
127
128 copy_v3_v3(td->iloc, td->loc);
129 copy_v3_v3(td->center, td->loc);
130
131 if (key->flag & PEK_SELECT) {
132 td->flag |= TD_SELECTED;
133 }
134 else if (!is_prop_edit) {
135 td->flag |= TD_SKIP;
136 }
137
138 unit_m3(td->mtx);
139 unit_m3(td->smtx);
140
141 /* Don't allow moving roots. */
142 if (k == 0 && pset->flag & PE_LOCK_FIRST && (!psys || !(psys->flag & PSYS_GLOBAL_HAIR))) {
144 }
145
146 if (t->mode == TFM_BAKE_TIME) {
147 td->val = key->time;
148 td->ival = *(key->time);
149 /* Abuse scale and quat for min/max values. */
150 td->flag |= TD_NO_EXT;
151 if (k == 0) {
152 tx->scale = nullptr;
153 }
154 else {
155 tx->scale = (key - 1)->time;
156 }
157
158 if (k == point->totkey - 1) {
159 tx->quat = nullptr;
160 }
161 else {
162 tx->quat = (key + 1)->time;
163 }
164 }
165
166 td++;
167 if (tx) {
168 tx++;
169 }
170 tail++;
171 }
172 if (is_prop_edit && head != tail) {
173 calc_distanceCurveVerts(head, tail - 1, false);
174 }
175 }
176 }
177}
178
180
181/* -------------------------------------------------------------------- */
184
186{
188 Scene *scene = t->scene;
189 ViewLayer *view_layer = t->view_layer;
190 BKE_view_layer_synced_ensure(scene, view_layer);
192 PTCacheEdit *edit = PE_get_current(t->depsgraph, scene, ob);
193 ParticleSystem *psys = edit->psys;
194 PTCacheEditPoint *point;
195 PTCacheEditKey *key;
196 TransData *td;
197 float mat[4][4], imat[4][4], co[3];
198 int i, k;
199 const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
200
201 /* We do transform in world space, so flush world space position
202 * back to particle local space (only for hair particles). */
203 td = tc->data;
204 for (i = 0, point = edit->points; i < edit->totpoint; i++, point++, td++) {
205 if (!(point->flag & PEP_TRANSFORM)) {
206 continue;
207 }
208
209 if (psys && !(psys->flag & PSYS_GLOBAL_HAIR)) {
210 ParticleSystemModifierData *psmd_eval = edit->psmd_eval;
212 ob, psmd_eval->mesh_final, psys->part->from, psys->particles + i, mat);
213 invert_m4_m4(imat, mat);
214
215 for (k = 0, key = point->keys; k < point->totkey; k++, key++) {
216 copy_v3_v3(co, key->world_co);
217 mul_m4_v3(imat, co);
218
219 /* Optimization for proportional edit. */
220 if (!is_prop_edit || !compare_v3v3(key->co, co, 0.0001f)) {
221 copy_v3_v3(key->co, co);
222 point->flag |= PEP_EDIT_RECALC;
223 }
224 }
225 }
226 else {
227 point->flag |= PEP_EDIT_RECALC;
228 }
229 }
230
231 PE_update_object(t->depsgraph, scene, ob, 1);
234 }
235}
236
238
239/* -------------------------------------------------------------------- */
242
250
252
254 /*flags*/ T_POINTS,
255 /*create_trans_data*/ createTransParticleVerts,
256 /*recalc_data*/ recalcData_particles,
257 /*special_aftertrans_update*/ nullptr,
258};
259
260} // namespace blender::ed::transform
void BKE_view_layer_synced_ensure(const Scene *scene, ViewLayer *view_layer)
Object * BKE_view_layer_active_object_get(const ViewLayer *view_layer)
void psys_mat_hair_to_global(struct Object *ob, struct Mesh *mesh, short from, struct ParticleData *pa, float hairmat[4][4])
Definition particle.cc:3900
void BKE_particle_batch_cache_dirty_tag(struct ParticleSystem *psys, int mode)
Definition particle.cc:5288
@ BKE_PARTICLE_BATCH_DIRTY_ALL
#define PEK_HIDE
#define PEP_EDIT_RECALC
#define PEP_TRANSFORM
#define PEP_HIDE
#define PEK_SELECT
#define PEK_USE_WCO
void unit_m3(float m[3][3])
void mul_m4_v3(const float M[4][4], float r[3])
bool invert_m4_m4(float inverse[4][4], const float mat[4][4])
void unit_m4(float m[4][4])
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE bool compare_v3v3(const float v1[3], const float v2[3], float limit) ATTR_WARN_UNUSED_RESULT
void DEG_id_tag_update(ID *id, unsigned int flags)
@ ID_RECALC_PSYS_REDO
Definition DNA_ID.h:1081
@ OB_LOCK_LOC
@ PSYS_GLOBAL_HAIR
@ PE_LOCK_FIRST
@ SCE_SELECT_PATH
void PE_update_object(Depsgraph *depsgraph, Scene *scene, Object *ob, int useflag)
ParticleEditSettings * PE_settings(Scene *scene)
PTCacheEdit * PE_get_current(Depsgraph *depsgraph, Scene *scene, Object *ob)
Read Guarded memory(de)allocation.
int count
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:123
void transform_snap_project_individual_apply(TransInfo *t)
static void recalcData_particles(TransInfo *t)
TransConvertTypeInfo TransConvertType_Particle
static void createTransParticleVerts(bContext *, TransInfo *t)
static void flushTransParticles(TransInfo *t)
void calc_distanceCurveVerts(TransData *head, TransData *tail, bool cyclic)
ObjectRuntimeHandle * runtime
struct PTCacheEditKey * keys
PTCacheEditPoint * points
struct ParticleSystem * psys
struct ParticleSystemModifierData * psmd_eval
ParticleData * particles
ParticleSettings * part
struct ParticleEditSettings particle
i
Definition text_draw.cc:230
#define FOREACH_TRANS_DATA_CONTAINER(t, th)
Definition transform.hh:42
conversion and adaptation of different datablocks to a common struct.