fix for crash when a register script sets material colors, also made some changes...
[blender.git] / source / blender / modifiers / intern / MOD_particlesystem.c
1 /*
2 * $Id$
3 *
4 * ***** BEGIN GPL LICENSE BLOCK *****
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software  Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 *
20 * The Original Code is Copyright (C) 2005 by the Blender Foundation.
21 * All rights reserved.
22 *
23 * Contributor(s): Daniel Dunbar
24 *                 Ton Roosendaal,
25 *                 Ben Batt,
26 *                 Brecht Van Lommel,
27 *                 Campbell Barton
28 *
29 * ***** END GPL LICENSE BLOCK *****
30 *
31 */
32
33 #include "stddef.h"
34
35 #include "DNA_material_types.h"
36
37 #include "BKE_cdderivedmesh.h"
38 #include "BKE_material.h"
39 #include "BKE_modifier.h"
40 #include "BKE_particle.h"
41
42 #include "MOD_util.h"
43
44
45 static void initData(ModifierData *md) 
46 {
47         ParticleSystemModifierData *psmd= (ParticleSystemModifierData*) md;
48         psmd->psys= 0;
49         psmd->dm=0;
50         psmd->totdmvert= psmd->totdmedge= psmd->totdmface= 0;
51 }
52 static void freeData(ModifierData *md)
53 {
54         ParticleSystemModifierData *psmd= (ParticleSystemModifierData*) md;
55
56         if(psmd->dm){
57                 psmd->dm->needsFree = 1;
58                 psmd->dm->release(psmd->dm);
59                 psmd->dm=0;
60         }
61
62         /* ED_object_modifier_remove may have freed this first before calling
63          * modifier_free (which calls this function) */
64         if(psmd->psys)
65                 psmd->psys->flag |= PSYS_DELETE;
66 }
67 static void copyData(ModifierData *md, ModifierData *target)
68 {
69         ParticleSystemModifierData *psmd= (ParticleSystemModifierData*) md;
70         ParticleSystemModifierData *tpsmd= (ParticleSystemModifierData*) target;
71
72         tpsmd->dm = 0;
73         tpsmd->totdmvert = tpsmd->totdmedge = tpsmd->totdmface = 0;
74         //tpsmd->facepa = 0;
75         tpsmd->flag = psmd->flag;
76         /* need to keep this to recognise a bit later in copy_object */
77         tpsmd->psys = psmd->psys;
78 }
79
80 static CustomDataMask requiredDataMask(Object *ob, ModifierData *md)
81 {
82         ParticleSystemModifierData *psmd= (ParticleSystemModifierData*) md;
83         CustomDataMask dataMask = 0;
84         Material *ma;
85         MTex *mtex;
86         int i;
87
88         if(!psmd->psys->part)
89                 return 0;
90
91         ma= give_current_material(ob, psmd->psys->part->omat);
92         if(ma) {
93                 for(i=0; i<MAX_MTEX; i++) {
94                         mtex=ma->mtex[i];
95                         if(mtex && (ma->septex & (1<<i))==0)
96                                 if(mtex->pmapto && (mtex->texco & TEXCO_UV))
97                                         dataMask |= (1 << CD_MTFACE);
98                 }
99         }
100
101         if(psmd->psys->part->tanfac!=0.0)
102                 dataMask |= (1 << CD_MTFACE);
103
104         /* ask for vertexgroups if we need them */
105         for(i=0; i<PSYS_TOT_VG; i++){
106                 if(psmd->psys->vgroup[i]){
107                         dataMask |= (1 << CD_MDEFORMVERT);
108                         break;
109                 }
110         }
111         
112         /* particles only need this if they are after a non deform modifier, and
113         * the modifier stack will only create them in that case. */
114         dataMask |= CD_MASK_ORIGSPACE;
115
116         dataMask |= CD_MASK_ORCO;
117         
118         return dataMask;
119 }
120
121 /* saves the current emitter state for a particle system and calculates particles */
122 static void deformVerts(
123                                                    ModifierData *md, Object *ob, DerivedMesh *derivedData,
124                 float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc)
125 {
126         DerivedMesh *dm = derivedData;
127         ParticleSystemModifierData *psmd= (ParticleSystemModifierData*) md;
128         ParticleSystem * psys=0;
129         int needsFree=0;
130
131         if(ob->particlesystem.first)
132                 psys=psmd->psys;
133         else
134                 return;
135         
136         if(!psys_check_enabled(ob, psys))
137                 return;
138
139         if(dm==0) {
140                 dm= get_dm(md->scene, ob, NULL, NULL, vertexCos, 1);
141
142                 if(!dm)
143                         return;
144
145                 needsFree= 1;
146         }
147
148         /* clear old dm */
149         if(psmd->dm){
150                 psmd->dm->needsFree = 1;
151                 psmd->dm->release(psmd->dm);
152         }
153
154         /* make new dm */
155         psmd->dm=CDDM_copy(dm);
156         CDDM_apply_vert_coords(psmd->dm, vertexCos);
157         CDDM_calc_normals(psmd->dm);
158
159         if(needsFree){
160                 dm->needsFree = 1;
161                 dm->release(dm);
162         }
163
164         /* protect dm */
165         psmd->dm->needsFree = 0;
166
167         /* report change in mesh structure */
168         if(psmd->dm->getNumVerts(psmd->dm)!=psmd->totdmvert ||
169                   psmd->dm->getNumEdges(psmd->dm)!=psmd->totdmedge ||
170                   psmd->dm->getNumFaces(psmd->dm)!=psmd->totdmface){
171                 /* in file read dm hasn't really changed but just wasn't saved in file */
172
173                 psys->recalc |= PSYS_RECALC_RESET;
174                 psmd->flag |= eParticleSystemFlag_DM_changed;
175
176                 psmd->totdmvert= psmd->dm->getNumVerts(psmd->dm);
177                 psmd->totdmedge= psmd->dm->getNumEdges(psmd->dm);
178                 psmd->totdmface= psmd->dm->getNumFaces(psmd->dm);
179         }
180
181         if(psys) {
182                 psmd->flag &= ~eParticleSystemFlag_psys_updated;
183                 particle_system_update(md->scene, ob, psys);
184                 psmd->flag |= eParticleSystemFlag_psys_updated;
185                 psmd->flag &= ~eParticleSystemFlag_DM_changed;
186         }
187 }
188
189 /* disabled particles in editmode for now, until support for proper derivedmesh
190  * updates is coded */
191 #if 0
192 static void deformVertsEM(
193                                 ModifierData *md, Object *ob, EditMesh *editData,
194                                 DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
195 {
196         DerivedMesh *dm = derivedData;
197
198         if(!derivedData) dm = CDDM_from_editmesh(editData, ob->data);
199
200         deformVerts(md, ob, dm, vertexCos, numVerts);
201
202         if(!derivedData) dm->release(dm);
203 }
204 #endif
205
206
207 ModifierTypeInfo modifierType_ParticleSystem = {
208         /* name */              "ParticleSystem",
209         /* structName */        "ParticleSystemModifierData",
210         /* structSize */        sizeof(ParticleSystemModifierData),
211         /* type */              eModifierTypeType_OnlyDeform,
212         /* flags */             eModifierTypeFlag_AcceptsMesh
213                                                         | eModifierTypeFlag_SupportsMapping
214                                                         | eModifierTypeFlag_UsesPointCache /*
215                                                         | eModifierTypeFlag_SupportsEditmode
216                                                         | eModifierTypeFlag_EnableInEditmode */,
217
218         /* copyData */          copyData,
219         /* deformVerts */       deformVerts,
220         /* deformVertsEM */     0 /* deformVertsEM */ ,
221         /* deformMatricesEM */  0,
222         /* applyModifier */     0,
223         /* applyModifierEM */   0,
224         /* initData */          initData,
225         /* requiredDataMask */  requiredDataMask,
226         /* freeData */          freeData,
227         /* isDisabled */        0,
228         /* updateDepgraph */    0,
229         /* dependsOnTime */     0,
230         /* foreachObjectLink */ 0,
231         /* foreachIDLink */     0,
232 };