Blender V4.3
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
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
30/* -------------------------------------------------------------------- */
35{
37
38 TransData *td = nullptr;
43 PTCacheEdit *edit = PE_get_current(t->depsgraph, t->scene, ob);
44 ParticleSystem *psys = nullptr;
46 PTCacheEditKey *key;
47 float mat[4][4];
48 int i, k, transformparticle;
49 int count = 0, hasselected = 0;
50 const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
51
52 if (edit == nullptr || t->settings->particle.selectmode == SCE_SELECT_PATH) {
53 return;
54 }
55
56 psys = edit->psys;
57
58 for (i = 0, point = edit->points; i < edit->totpoint; i++, point++) {
59 point->flag &= ~PEP_TRANSFORM;
60 transformparticle = 0;
61
62 if ((point->flag & PEP_HIDE) == 0) {
63 for (k = 0, key = point->keys; k < point->totkey; k++, key++) {
64 if ((key->flag & PEK_HIDE) == 0) {
65 if (key->flag & PEK_SELECT) {
66 hasselected = 1;
67 transformparticle = 1;
68 }
69 else if (is_prop_edit) {
70 transformparticle = 1;
71 }
72 }
73 }
74 }
75
76 if (transformparticle) {
77 count += point->totkey;
78 point->flag |= PEP_TRANSFORM;
79 }
80 }
81
82 /* NOTE: in prop mode we need at least 1 selected. */
83 if (hasselected == 0) {
84 return;
85 }
86
87 tc->data_len = count;
88 td = tc->data = static_cast<TransData *>(
89 MEM_callocN(tc->data_len * sizeof(TransData), "TransObData(Particle Mode)"));
90
91 if (t->mode == TFM_BAKE_TIME) {
92 tx = tc->data_ext = static_cast<TransDataExtension *>(
93 MEM_callocN(tc->data_len * sizeof(TransDataExtension), "Particle_TransExtension"));
94 }
95 else {
96 tx = tc->data_ext = nullptr;
97 }
98
99 unit_m4(mat);
100
101 invert_m4_m4(ob->runtime->world_to_object.ptr(), ob->object_to_world().ptr());
102
103 for (i = 0, point = edit->points; i < edit->totpoint; i++, point++) {
104 TransData *head, *tail;
105 head = tail = td;
106
107 if (!(point->flag & PEP_TRANSFORM)) {
108 continue;
109 }
110
111 if (psys && !(psys->flag & PSYS_GLOBAL_HAIR)) {
112 ParticleSystemModifierData *psmd_eval = edit->psmd_eval;
114 ob, psmd_eval->mesh_final, psys->part->from, psys->particles + i, mat);
115 }
116
117 for (k = 0, key = point->keys; k < point->totkey; k++, key++) {
118 if (key->flag & PEK_USE_WCO) {
119 copy_v3_v3(key->world_co, key->co);
120 mul_m4_v3(mat, key->world_co);
121 td->loc = key->world_co;
122 }
123 else {
124 td->loc = key->co;
125 }
126
127 copy_v3_v3(td->iloc, td->loc);
128 copy_v3_v3(td->center, td->loc);
129
130 if (key->flag & PEK_SELECT) {
131 td->flag |= TD_SELECTED;
132 }
133 else if (!is_prop_edit) {
134 td->flag |= TD_SKIP;
135 }
136
137 unit_m3(td->mtx);
138 unit_m3(td->smtx);
139
140 /* Don't allow moving roots. */
141 if (k == 0 && pset->flag & PE_LOCK_FIRST && (!psys || !(psys->flag & PSYS_GLOBAL_HAIR))) {
143 }
144
145 td->ob = ob;
146 td->ext = tx;
147 if (t->mode == TFM_BAKE_TIME) {
148 td->val = key->time;
149 td->ival = *(key->time);
150 /* Abuse size and quat for min/max values. */
151 td->flag |= TD_NO_EXT;
152 if (k == 0) {
153 tx->size = nullptr;
154 }
155 else {
156 tx->size = (key - 1)->time;
157 }
158
159 if (k == point->totkey - 1) {
160 tx->quat = nullptr;
161 }
162 else {
163 tx->quat = (key + 1)->time;
164 }
165 }
166
167 td++;
168 if (tx) {
169 tx++;
170 }
171 tail++;
172 }
173 if (is_prop_edit && head != tail) {
174 calc_distanceCurveVerts(head, tail - 1, false);
175 }
176 }
177 }
178}
179
182/* -------------------------------------------------------------------- */
187{
189 Scene *scene = t->scene;
190 ViewLayer *view_layer = t->view_layer;
191 BKE_view_layer_synced_ensure(scene, view_layer);
193 PTCacheEdit *edit = PE_get_current(t->depsgraph, scene, ob);
194 ParticleSystem *psys = edit->psys;
196 PTCacheEditKey *key;
197 TransData *td;
198 float mat[4][4], imat[4][4], co[3];
199 int i, k;
200 const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
201
202 /* We do transform in world space, so flush world space position
203 * back to particle local space (only for hair particles). */
204 td = tc->data;
205 for (i = 0, point = edit->points; i < edit->totpoint; i++, point++, td++) {
206 if (!(point->flag & PEP_TRANSFORM)) {
207 continue;
208 }
209
210 if (psys && !(psys->flag & PSYS_GLOBAL_HAIR)) {
211 ParticleSystemModifierData *psmd_eval = edit->psmd_eval;
213 ob, psmd_eval->mesh_final, psys->part->from, psys->particles + i, mat);
214 invert_m4_m4(imat, mat);
215
216 for (k = 0, key = point->keys; k < point->totkey; k++, key++) {
217 copy_v3_v3(co, key->world_co);
218 mul_m4_v3(imat, co);
219
220 /* Optimization for proportional edit. */
221 if (!is_prop_edit || !compare_v3v3(key->co, co, 0.0001f)) {
222 copy_v3_v3(key->co, co);
223 point->flag |= PEP_EDIT_RECALC;
224 }
225 }
226 }
227 else {
228 point->flag |= PEP_EDIT_RECALC;
229 }
230 }
231
232 PE_update_object(t->depsgraph, scene, ob, 1);
235 }
236}
237
240/* -------------------------------------------------------------------- */
251
255 /*flags*/ T_POINTS,
256 /*create_trans_data*/ createTransParticleVerts,
257 /*recalc_data*/ recalcData_particles,
258 /*special_aftertrans_update*/ nullptr,
259};
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:3907
void BKE_particle_batch_cache_dirty_tag(struct ParticleSystem *psys, int mode)
Definition particle.cc:5295
@ 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 unit_m4(float m[4][4])
Definition rct.c:1127
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])
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:1048
@ OB_LOCK_LOC
@ PSYS_GLOBAL_HAIR
@ SCE_SELECT_PATH
@ PE_LOCK_FIRST
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)
@ TFM_BAKE_TIME
Read Guarded memory(de)allocation.
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Gabor Generate Gabor noise Gradient Generate interpolated color and intensity values based on the input vector Magic Generate a psychedelic color texture Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a point
int count
void *(* MEM_callocN)(size_t len, const char *str)
Definition mallocn.cc:42
ObjectRuntimeHandle * runtime
PTCacheEditPoint * points
struct ParticleSystem * psys
struct ParticleSystemModifierData * psmd_eval
ParticleData * particles
ParticleSettings * part
struct ParticleEditSettings particle
float smtx[3][3]
float mtx[3][3]
TransDataExtension * ext
eTfmMode mode
Definition transform.hh:517
eTState state
Definition transform.hh:527
ToolSettings * settings
Definition transform.hh:656
Scene * scene
Definition transform.hh:654
ViewLayer * view_layer
Definition transform.hh:655
eTFlag flag
Definition transform.hh:523
Depsgraph * depsgraph
Definition transform.hh:653
@ T_PROP_EDIT
Definition transform.hh:98
@ T_POINTS
Definition transform.hh:93
@ TRANS_CANCEL
Definition transform.hh:210
#define FOREACH_TRANS_DATA_CONTAINER(t, th)
Definition transform.hh:854
void calc_distanceCurveVerts(TransData *head, TransData *tail, bool cyclic)
conversion and adaptation of different datablocks to a common struct.
static void createTransParticleVerts(bContext *, TransInfo *t)
static void recalcData_particles(TransInfo *t)
TransConvertTypeInfo TransConvertType_Particle
static void flushTransParticles(TransInfo *t)
@ TD_NO_EXT
@ TD_SELECTED
@ TD_SKIP
void transform_snap_project_individual_apply(TransInfo *t)