Particles

=========

Merge of the famous particle patch by Janne Karhu, a full rewrite
of the Blender particle system. This includes:

- Emitter, Hair and Reactor particle types.
- Newtonian, Keyed and Boids physics.
- Various particle visualisation and rendering types.
- Vertex group and texture control for various properties.
- Interpolated child particles from parents.
- Hair editing with combing, growing, cutting, .. .
- Explode modifier.
- Harmonic, Magnetic fields, and multiple falloff types.

.. and lots of other things, some more info is here:

http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite
http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite_Doc

The new particle system cannot be backwards compatible. Old particle
systems are being converted to the new system, but will require
tweaking to get them looking the same as before.

Point Cache
===========

The new system to replace manual baking, based on automatic caching
on disk. This is currently used by softbodies and the particle system.

See the Cache API section on:
http://wiki.blender.org/index.php/BlenderDev/PhysicsSprint

Documentation
=============

These new features still need good docs for the release logs, help
for this is appreciated.
This commit is contained in:
Brecht Van Lommel 2007-11-26 22:09:57 +00:00
commit 7da56f4a9b
97 changed files with 34782 additions and 16218 deletions

@ -434,6 +434,15 @@
<File
RelativePath="..\..\..\source\blender\blenkernel\intern\packedFile.c">
</File>
<File
RelativePath="..\..\..\source\blender\blenkernel\intern\particle.c">
</File>
<File
RelativePath="..\..\..\source\blender\blenkernel\intern\particle_system.c">
</File>
<File
RelativePath="..\..\..\source\blender\blenkernel\intern\pointcache.c">
</File>
<File
RelativePath="..\..\..\source\blender\blenkernel\intern\property.c">
</File>
@ -624,6 +633,9 @@
<File
RelativePath="..\..\..\source\blender\blenkernel\BKE_plugin_types.h">
</File>
<File
RelativePath="..\..\..\source\blender\blenkernel\BKE_pointcache.h">
</File>
<File
RelativePath="..\..\..\source\blender\blenkernel\BKE_property.h">
</File>

@ -307,6 +307,9 @@
<File
RelativePath="..\..\..\source\blender\src\editoops.c">
</File>
<File
RelativePath="..\..\..\source\blender\src\editparticle.c">
</File>
<File
RelativePath="..\..\..\source\blender\src\editscreen.c">
</File>
@ -674,6 +677,9 @@
<File
RelativePath="..\..\..\source\blender\include\BIF_editoops.h">
</File>
<File
RelativePath="..\..\..\source\blender\include\BIF_editparticle.h">
</File>
<File
RelativePath="..\..\..\source\blender\include\BIF_editsca.h">
</File>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

@ -70,6 +70,7 @@ struct DerivedMesh {
CustomData vertData, edgeData, faceData;
int numVertData, numEdgeData, numFaceData;
int needsFree; /* checked on ->release, is set to 0 for cached results */
int deformedOnly; /* set by modifier stack if only deformed from original */
/* Misc. Queries */

@ -231,5 +231,12 @@ struct MeshDeformModifierData;
void harmonic_coordinates_bind(struct MeshDeformModifierData *mmd,
float (*vertexcos)[3], int totvert, float cagemat[][4]);
/* particle.c */
struct ParticleSystem;
void PE_free_particle_edit(struct ParticleSystem *psys);
void PE_get_colors(char sel[4], char nosel[4]);
void PE_recalc_world_cos(struct Object *ob, struct ParticleSystem *psys);
#endif

@ -44,7 +44,7 @@ struct ListBase;
struct MemFile;
#define BLENDER_VERSION 245
#define BLENDER_SUBVERSION 7
#define BLENDER_SUBVERSION 8
#define BLENDER_MINVERSION 240
#define BLENDER_MINSUBVERSION 0

@ -123,5 +123,7 @@ void filldisplist(struct ListBase *dispbase, struct ListBase *to);
void fastshade_free_render(void);
float calc_taper(struct Object *taperobj, int cur, int tot);
#endif

@ -187,6 +187,7 @@ typedef struct Global {
/*#endif*/
#define G_DRAWSHARP (1 << 28) /* draw edges with the sharp flag */
#define G_SCULPTMODE (1 << 29)
#define G_PARTICLEEDIT (1 << 30)
#define G_AUTOMATKEYS (1 << 30)
#define G_HIDDENHANDLES (1 << 31) /* used for curves only */
@ -243,9 +244,10 @@ typedef struct Global {
#define B_ENDIAN 0
/* G.moving, signals drawing in (3d) window to denote transform */
#define G_TRANSFORM_OBJ 1
#define G_TRANSFORM_EDIT 2
#define G_TRANSFORM_MANIP 4
#define G_TRANSFORM_OBJ 1
#define G_TRANSFORM_EDIT 2
#define G_TRANSFORM_MANIP 4
#define G_TRANSFORM_PARTICLE 8
/* G.special1 */

@ -78,6 +78,7 @@ typedef struct Main {
ListBase action;
ListBase nodetree;
ListBase brush;
ListBase particle;
} Main;

@ -59,6 +59,12 @@ typedef enum {
eModifierTypeType_Constructive,
eModifierTypeType_Nonconstructive,
/* both deformVerts & applyModifier are valid calls
* used for particles modifier that doesn't actually modify the object
* unless it's a mesh and can be exploded -> curve can also emit particles
*/
eModifierTypeType_DeformOrConstruct
} ModifierTypeType;
typedef enum {
@ -81,8 +87,8 @@ typedef enum {
eModifierTypeFlag_RequiresOriginalData = (1<<5),
} ModifierTypeFlag;
typedef void (*ObjectWalkFunc)(void *userData, Object *ob, Object **obpoin);
typedef void (*IDWalkFunc)(void *userData, Object *ob, ID **idpoin);
typedef void (*ObjectWalkFunc)(void *userData, struct Object *ob, struct Object **obpoin);
typedef void (*IDWalkFunc)(void *userData, struct Object *ob, struct ID **idpoin);
typedef struct ModifierTypeInfo {
/* The user visible name for this modifier */
@ -277,11 +283,14 @@ int modifiers_getCageIndex(struct Object *ob,
int *lastPossibleCageIndex_r);
int modifiers_isSoftbodyEnabled(struct Object *ob);
int modifiers_isParticleEnabled(struct Object *ob);
struct Object *modifiers_isDeformedByArmature(struct Object *ob);
struct Object *modifiers_isDeformedByLattice(struct Object *ob);
int modifiers_usesArmature(struct Object *ob, struct bArmature *arm);
int modifiers_isDeformed(struct Object *ob);
int modifiers_indexInObject(struct Object *ob, struct ModifierData *md);
/* Calculates and returns a linked list of CustomDataMasks indicating the
* data required by each modifier in the stack pointed to by md for correct
* evaluation, assuming the data indicated by dataMask is required at the

@ -0,0 +1,254 @@
/* BKE_particle.h
*
*
* $Id: BKE_particle.h $
*
* ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
*
* 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. The Blender
* Foundation also sells licenses for use in proprietary software under
* the Blender License. See http://www.blender.org/BL/ for information
* about this.
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The Original Code is Copyright (C) 2007 by Janne Karhu.
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): none yet.
*
* ***** END GPL/BL DUAL LICENSE BLOCK *****
*/
#ifndef BKE_PARTICLE_H
#define BKE_PARTICLE_H
#include "DNA_particle_types.h"
#include "DNA_object_types.h"
struct ParticleSystemModifierData;
struct ParticleSystem;
struct ParticleKey;
struct HairKey;
struct Main;
struct Group;
struct Object;
struct DerivedMesh;
struct ModifierData;
struct MTFace;
struct MFace;
struct MVert;
struct IpoCurve;
struct LinkNode;
struct KDTree;
typedef struct ParticleEffectorCache {
struct ParticleEffectorCache *next, *prev;
struct Object *ob;
/* precalculated variables for guides */
float firstloc[4], firstdir[3];
float *distances;
float *locations;
/* precalculated variables for deflection */
float ob_minmax[6];
float *face_minmax;
float *vert_cos;
/* precalculated variables for boids */
struct KDTree *tree;
short type, psys_nbr;
struct Object obcopy; /* for restoring transformation data */
} ParticleEffectorCache;
typedef struct ParticleReactEvent {
struct ParticleReactEvent *next, *prev;
int event, pa_num;
Object *ob;
struct ParticleSystem *psys;
struct ParticleKey state;
float time, size;
}ParticleReactEvent;
typedef struct ParticleTexture{
float ivel; /* used in reset */
float time, life, exist, size; /* used in init */
float pvel[3]; /* used in physics */
float length, clump, kink; /* used in path caching */
} ParticleTexture;
typedef struct BoidVecFunc{
void (*Addf)(float *v, float *v1, float *v2);
void (*Subf)(float *v, float *v1, float *v2);
void (*Mulf)(float *v, float f);
float (*Length)(float *v);
float (*Normalize)(float *v);
float (*Inpf)(float *v1, float *v2);
void (*Copyf)(float *v1, float *v2);
} BoidVecFunc;
typedef struct ParticleSeam{
float v0[3], v1[3];
float nor[3], dir[3], tan[3];
float length2;
} ParticleSeam;
typedef struct ParticleCacheKey{
float co[3];
float vel[3];
float rot[4];
float col[3];
int steps;
} ParticleCacheKey;
typedef struct ParticleEditKey{
float *co;
float *vel;
float *rot;
float *time;
float world_co[3];
float length;
short flag;
} ParticleEditKey;
typedef struct ParticleUndo {
struct ParticleUndo *next, *prev;
struct ParticleEditKey **keys;
struct KDTree *emitter_field;
struct ParticleData *particles;
float *emitter_cosnos;
int totpart, totkeys;
char name[64];
} ParticleUndo;
typedef struct ParticleEdit{
ListBase undo;
struct ParticleUndo *curundo;
struct KDTree *emitter_field;
ParticleEditKey **keys;
int *mirror_cache;
float *emitter_cosnos;
int totkeys;
} ParticleEdit;
/* ----------- functions needed outside particlesystem ---------------- */
/* particle.c */
int count_particles(struct ParticleSystem *psys);
int count_particles_mod(struct ParticleSystem *psys, int totgr, int cur);
int psys_count_keys(struct ParticleSystem *psys);
char *psys_menu_string(struct Object *ob, int for_sb);
struct ParticleSystem *psys_get_current(struct Object *ob);
short psys_get_current_num(struct Object *ob);
//struct ParticleSystem *psys_get(struct Object *ob, int index);
struct ParticleData *psys_get_selected_particle(struct ParticleSystem *psys, int *index);
struct ParticleKey *psys_get_selected_key(struct ParticleSystem *psys, int pa_index, int *key_index);
void psys_change_act(void *ob_v, void *act_v);
struct Object *psys_get_lattice(struct Object *ob, struct ParticleSystem *psys);
void psys_disable_all(struct Object *ob);
void psys_enable_all(struct Object *ob);
int psys_ob_has_hair(struct Object *ob);
int psys_in_edit_mode(struct ParticleSystem *psys);
void psys_free_settings(struct ParticleSettings *part);
void free_child_path_cache(struct ParticleSystem *psys);
void psys_free_path_cache(struct ParticleSystem *psys);
void free_hair(struct ParticleSystem *psys);
void free_keyed_keys(struct ParticleSystem *psys);
void psys_free(struct Object * ob, struct ParticleSystem * psys);
void clear_particles_from_cache(struct Object *ob, struct ParticleSystem *psys, int cfra);
//void psys_remove_from_particle_list(struct Object *ob, short nbr, struct ParticleSystem *psys);
void psys_interpolate_uvs(struct MTFace *tface, int quad, float *uv, float *uvco);
void copy_particle_key(struct ParticleKey *to, struct ParticleKey *from, int time);
void psys_particle_on_emitter(struct Object *ob, struct ParticleSystemModifierData *psmd, int distr, int index, int index_dmcache, float *fuv, float foffset, float *vec, float *nor, float *utan, float *vtan);
struct ParticleSystemModifierData *psys_get_modifier(struct Object *ob, struct ParticleSystem *psys);
struct ParticleSettings *psys_new_settings(char *name, struct Main *main);
struct ParticleSettings *psys_copy_settings(struct ParticleSettings *part);
void psys_flush_settings(struct ParticleSettings *part, int event, int hair_recalc);
void psys_find_parents(struct Object *ob, struct ParticleSystemModifierData *psmd, struct ParticleSystem *psys);
void psys_cache_paths(struct Object *ob, struct ParticleSystem *psys, float cfra, int editupdate);
void psys_cache_child_paths(struct Object *ob, struct ParticleSystem *psys, float cfra, int editupdate);
int do_guide(struct ParticleKey *state, int pa_num, float time, struct ListBase *lb);
float psys_get_size(struct Object *ob, struct Material *ma, struct ParticleSystemModifierData *psmd, struct IpoCurve *icu_size, struct ParticleSystem *psys, struct ParticleSettings *part, struct ParticleData *pa, float *vg_size);
float psys_get_timestep(struct ParticleSettings *part);
float psys_get_child_time(struct ParticleSystem *psys, int child_nbr, float cfra);
float psys_get_child_size(struct ParticleSystem *psys, int child_nbr, float cfra, float *pa_time);
void psys_get_particle_on_path(struct Object *ob, struct ParticleSystem *psys, int pa_num, struct ParticleKey *state, int vel);
int psys_get_particle_state(struct Object *ob, struct ParticleSystem *psys, int p, struct ParticleKey *state, int always);
/* particle_system.c */
int psys_count_keyed_targets(struct Object *ob, struct ParticleSystem *psys);
void psys_get_reactor_target(struct Object *ob, struct ParticleSystem *psys, struct Object **target_ob, struct ParticleSystem **target_psys);
void psys_init_effectors(struct Object *obsrc, struct Group *group, struct ParticleSystem *psys);
void psys_end_effectors(struct ParticleSystem *psys);
void particle_system_update(struct Object *ob, struct ParticleSystem *psys);
/* ----------- functions needed only inside particlesystem ------------ */
/* particle.c */
void psys_key_to_object(struct Object *ob, struct ParticleKey *key, float imat[][4]);
//void psys_key_to_geometry(struct DerivedMesh *dm, struct ParticleData *pa, struct ParticleKey *key);
//void psys_key_from_geometry(struct DerivedMesh *dm, struct ParticleData *pa, struct ParticleKey *key);
//void psys_face_mat(struct DerivedMesh *dm, struct ParticleData *pa, float mat[][4]);
void psys_vec_rot_to_face(struct DerivedMesh *dm, struct ParticleData *pa, float *vec);
//void psys_vec_rot_from_face(struct DerivedMesh *dm, struct ParticleData *pa, float *vec);
void psys_mat_hair_to_object(struct Object *ob, struct DerivedMesh *dm, short from, struct ParticleData *pa, float hairmat[][4]);
void psys_mat_hair_to_global(struct Object *ob, struct DerivedMesh *dm, short from, struct ParticleData *pa, float hairmat[][4]);
float *psys_cache_vgroup(struct DerivedMesh *dm, struct ParticleSystem *psys, int vgroup);
void psys_get_texture(struct Object *ob, struct Material *ma, struct ParticleSystemModifierData *psmd, struct ParticleSystem *psys, struct ParticleData *pa, struct ParticleTexture *ptex, int event);
void psys_interpolate_face(struct MVert *mvert, struct MFace *mface, struct MTFace *tface, float *uv, float *vec, float *nor, float *utan, float *vtan);
float psys_interpolate_value_from_verts(struct DerivedMesh *dm, short from, int index, float *fw, float *values);
void psys_get_from_key(struct ParticleKey *key, float *loc, float *vel, float *rot, float *time);
int psys_intersect_dm(struct Object *ob, struct DerivedMesh *dm, float *vert_cos, float *co1, float* co2, float *min_d, int *min_face, float *min_uv, float *face_minmax, float *pa_minmax, float radius, float *ipoint);
void psys_particle_on_dm(struct Object *ob, struct DerivedMesh *dm, int from, int index, int index_dmcache, float *fw, float foffset, float *vec, float *nor, float *utan, float *vtan);
/* particle_system.c */
void initialize_particle(struct ParticleData *pa, int p, struct Object *ob, struct ParticleSystem *psys, struct ParticleSystemModifierData *psmd);
void reset_particle(struct ParticleData *pa, struct ParticleSystem *psys, struct ParticleSystemModifierData *psmd, struct Object *ob, float dtime, float cfra, float *vg_vel, float *vg_tan, float *vg_rot);
int psys_particle_dm_face_lookup(struct Object *ob, struct DerivedMesh *dm, int index, float *fw, struct LinkNode *node);
/* ParticleEffectorCache->type */
#define PSYS_EC_EFFECTOR 1
#define PSYS_EC_DEFLECT 2
#define PSYS_EC_PARTICLE 4
#define PSYS_EC_REACTOR 8
/* ParticleEditKey->flag */
#define PEK_SELECT 1
#define PEK_TO_SELECT 2
#define PEK_TAG 4
#define PEK_HIDE 8
/* index_dmcache */
#define DMCACHE_NOTFOUND -1
#define DMCACHE_ISCHILD -2
#endif

@ -0,0 +1,48 @@
/*
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The Original Code is Copyright (C) 2006 Blender Foundation.
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): Campbell Barton <ideasman42@gmail.com>
*
* ***** END GPL LICENSE BLOCK *****
*/
#ifndef BKE_POINTCACHE_H
#define BKE_POINTCACHE_H
#include "DNA_ID.h"
/* options for clearing pointcache - used for BKE_ptcache_id_clear
Before and after are non inclusive (they wont remove the cfra) */
#define PTCACHE_CLEAR_ALL 0
#define PTCACHE_CLEAR_FRAME 1
#define PTCACHE_CLEAR_BEFORE 2
#define PTCACHE_CLEAR_AFTER 3
#define PTCACHE_EXT ".bphys"
#define PTCACHE_PATH "//pointcache/"
int BKE_ptcache_id_filename(struct ID *id, char *filename, int cfra, int stack_index, short do_path, short do_ext);
FILE * BKE_ptcache_id_fopen(struct ID *id, char mode, int cfra, int stack_index);
void BKE_ptcache_id_clear(struct ID *id, char mode, int cfra, int stack_index);
#endif

@ -37,12 +37,25 @@
struct Object;
struct SoftBody;
typedef struct BodyPoint {
float origS[3], origE[3], origT[3], pos[3], vec[3], force[3];
float goal;
float prevpos[3], prevvec[3], prevdx[3], prevdv[3]; /* used for Heun integration */
int nofsprings; int *springs;
float choke;
float colball;
short flag;
char octantflag;
} BodyPoint;
/* allocates and initializes general main data */
extern struct SoftBody *sbNew(void);
/* frees internal data and softbody itself */
extern void sbFree(struct SoftBody *sb);
extern void softbody_clear_cache(struct Object *ob, float framenr);
/* do one simul step, reading and writing vertex locs from given array */
extern void sbObjectStep(struct Object *ob, float framnr, float (*vertexCos)[3], int numVerts);

@ -59,6 +59,10 @@
#define ELEM8(a, b, c, d, e, f, g, h, i) ( ELEM4(a, b, c, d, e) || ELEM4(a, f, g, h, i) )
#define ELEM9(a, b, c, d, e, f, g, h, i, j) ( ELEM4(a, b, c, d, e) || ELEM5(a, f, g, h, i, j) )
/* shift around elements */
#define SHIFT3(type, a, b, c) { type tmp; tmp = a; a = c; c = b; b = tmp; }
#define SHIFT4(type, a, b, c, d) { type tmp; tmp = a; a = d; d = c; c = b; b = tmp; }
/* string compare */
#define STREQ(str, a) ( strcmp((str), (a))==0 )
#define STREQ2(str, a, b) ( STREQ(str, a) || STREQ(str, b) )

@ -246,6 +246,8 @@ void fluidsimSettingsCopy(struct FluidsimSettings* sb) {}
/*new render funcs */
int externtex(struct MTex *mtex, float *vec, float *tin, float *tr, float *tg, float *tb, float *ta) { return 0; }
void texture_rgb_blend(float *in, float *tex, float *out, float fact, float facg, int blendtype) {}
float texture_value_blend(float tex, float out, float fact, float facg, int blendtype, int flip) { return 0; }
void RE_FreeRenderResult(struct RenderResult *rr) {}
void RE_GetResultImage(struct Render *re, struct RenderResult *rr) {}
@ -339,3 +341,8 @@ Sequence *get_forground_frame_seq(int frame){return 0;};
void harmonic_coordinates_bind(struct MeshDeformModifierData *mmd,
float (*vertexcos)[3], int totvert, float cagemat[][4]) {}
/* particle.c */
void PE_free_particle_edit(struct ParticleSystem *psys) {}
void PE_get_colors(char sel[4], char nosel[4]) {}
void PE_recalc_world_cos(struct Object *ob, struct ParticleSystem *psys) {}

@ -55,6 +55,7 @@
#include "DNA_view3d_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
#include "DNA_particle_types.h"
#include "BLI_arithb.h"
#include "BLI_blenlib.h"
@ -77,6 +78,7 @@
#include "BKE_subsurf.h"
#include "BKE_texture.h"
#include "BKE_utildefines.h"
#include "BKE_particle.h"
#ifdef WITH_VERSE
#include "BKE_verse.h"
@ -1961,6 +1963,7 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3],
*/
if(mti->type == eModifierTypeType_OnlyDeform) {
/* No existing verts to deform, need to build them. */
if(!deformedVerts) {
if(dm) {
@ -2002,9 +2005,12 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3],
/* set the DerivedMesh to only copy needed data */
DM_set_only_copy(dm, (CustomDataMask)curr->link);
ndm = mti->applyModifier(md, ob, dm, useRenderParams,
!inputVertexCos);
if(((CustomDataMask)curr->link) & CD_MASK_ORIGSPACE)
if(!CustomData_has_layer(&dm->faceData, CD_ORIGSPACE))
CustomData_add_layer(&dm->faceData, CD_ORIGSPACE, CD_DEFAULT, NULL, dm->getNumFaces(dm));
ndm = mti->applyModifier(md, ob, dm, useRenderParams, !inputVertexCos);
if(ndm) {
/* if the modifier returned a new dm, release the old one */
@ -2182,6 +2188,10 @@ static void editmesh_calc_modifiers(DerivedMesh **cage_r,
/* set the DerivedMesh to only copy needed data */
DM_set_only_copy(dm, (CustomDataMask)curr->link);
if(((CustomDataMask)curr->link) & CD_MASK_ORIGSPACE)
if(!CustomData_has_layer(&dm->faceData, CD_ORIGSPACE))
CustomData_add_layer(&dm->faceData, CD_ORIGSPACE, CD_DEFAULT, NULL, dm->getNumFaces(dm));
ndm = mti->applyModifierEM(md, ob, em, dm);
if (ndm) {
@ -2360,7 +2370,7 @@ static void mesh_build_data(Object *ob, CustomDataMask dataMask)
if(ob!=G.obedit) {
Object *obact = G.scene->basact?G.scene->basact->object:NULL;
int editing = (FACESEL_PAINT_TEST);
int editing = (FACESEL_PAINT_TEST)|(G.f & G_PARTICLEEDIT);
int needMapping = editing && (ob==obact);
if( (G.f & G_WEIGHTPAINT) && ob==obact ) {

@ -38,6 +38,7 @@
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
#include "BLI_arithb.h"
#include "BLI_rand.h"
#include "DNA_listBase.h"
#include "DNA_curve_types.h"
@ -47,6 +48,7 @@
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
#include "DNA_particle_types.h"
#include "DNA_scene_types.h"
#include "DNA_view3d_types.h"
#include "DNA_vfont_types.h"
@ -60,8 +62,10 @@
#include "BKE_global.h"
#include "BKE_ipo.h"
#include "BKE_key.h"
#include "BKE_lattice.h"
#include "BKE_main.h"
#include "BKE_object.h"
#include "BKE_particle.h"
#include "BKE_utildefines.h"
#include "BKE_bad_level_calls.h"
@ -563,134 +567,143 @@ static void face_duplilist(ListBase *lb, Scene *sce, Object *par)
dm->release(dm);
}
static void particle_duplilist(ListBase *lb, Scene *sce, Object *par, PartEff *paf)
static void new_particle_duplilist(ListBase *lb, Scene *sce, Object *par, ParticleSystem *psys)
{
Object *ob, copyob;
Base *base;
Particle *pa;
float ctime, vec1[3];
float vec[3], tmat[4][4], mat[3][3];
float *q2;
int lay, a, counter; /* counter is used to find in render the indexed object */
pa= paf->keys;
if(pa==NULL || (G.rendering && paf->disp!=100)) {
build_particle_system(par);
pa= paf->keys;
if(pa==NULL) return;
}
ctime= bsystem_time(par, (float)G.scene->r.cfra, 0.0);
GroupObject *go;
Object *ob, **oblist=0;
ParticleSettings *part;
ParticleData *pa;
ParticleKey state;
float ctime, pa_time;
float tmat[4][4], mat[3][3], obrotmat[3][3], parotmat[3][3], size=0.0;
float xvec[3] = {-1.0, 0.0, 0.0}, *q;
int lay, a, k, step_nbr = 0, counter;
int totpart, totchild, totgroup=0, pa_num;
if(psys==0) return;
part=psys->part;
if(part==0) return;
ctime = bsystem_time(par, (float)G.scene->r.cfra, 0.0);
totpart = psys->totpart;
totchild = psys->totchild;
BLI_srandom(31415926 + psys->seed);
lay= G.scene->lay;
if((part->draw_as == PART_DRAW_OB && part->dup_ob) ||
(part->draw_as == PART_DRAW_GR && part->dup_group && part->dup_group->gobject.first)) {
for(base= sce->base.first; base; base= base->next) {
if(base->object->type>0 && (base->lay & lay) && G.obedit!=base->object) {
ob= base->object->parent;
while(ob) {
if(ob==par) {
ob= base->object;
/* temp copy, to have ipos etc to work OK */
copyob= *ob;
/* don't want parent animation to apply on past object positions */
if(!(paf->flag & PAF_STATIC))
ob->parent= NULL;
for(a=0, pa= paf->keys, counter=0; a<paf->totpart; a++, pa+=paf->totkey, counter++) {
if(paf->flag & PAF_STATIC) {
float mtime;
where_is_particle(paf, pa, pa->time, vec1);
mtime= pa->time+pa->lifetime;
for(ctime= pa->time; ctime<mtime; ctime+=paf->staticstep, counter++) {
/* make sure hair grows until the end.. */
if(ctime>pa->time+pa->lifetime) ctime= pa->time+pa->lifetime;
/* to give ipos in object correct offset */
where_is_object_time(ob, ctime-pa->time);
if(psys->flag & (PSYS_HAIR_DONE|PSYS_KEYED) && part->draw & PART_DRAW_KEYS)
step_nbr = part->keys_step;
else
step_nbr = 0;
where_is_particle(paf, pa, ctime, vec); // makes sure there's always a vec
Mat4MulVecfl(par->obmat, vec);
if(paf->stype==PAF_VECT) {
where_is_particle(paf, pa, ctime+1.0, vec1); // makes sure there's always a vec
Mat4MulVecfl(par->obmat, vec1);
psys->lattice = psys_get_lattice(par, psys);
VecSubf(vec1, vec1, vec);
q2= vectoquat(vec1, ob->trackflag, ob->upflag);
QuatToMat3(q2, mat);
Mat4CpyMat4(tmat, ob->obmat);
Mat4MulMat43(ob->obmat, tmat, mat);
}
VECCOPY(ob->obmat[3], vec);
/* put object back in original state, so it cam be restored OK */
Mat4CpyMat4(tmat, ob->obmat);
Mat4CpyMat4(ob->obmat, copyob.obmat);
new_dupli_object(lb, ob, tmat, par->lay, counter);
}
}
else { // non static particles
if((paf->flag & PAF_UNBORN)==0 && ctime < pa->time) continue;
if((paf->flag & PAF_DIED)==0 && ctime > pa->time+pa->lifetime) continue;
if(part->draw_as==PART_DRAW_GR) {
group_handle_recalc_and_update(par, part->dup_group);
//if(ctime < pa->time+pa->lifetime) {
go= part->dup_group->gobject.first;
while(go) {
go=go->next;
totgroup++;
}
/* to give ipos in object correct offset, ob->parent is NULLed */
where_is_object_time(ob, ctime-pa->time);
where_is_particle(paf, pa, ctime, vec);
if(paf->stype==PAF_VECT) {
/* if particle died, we use previous position */
if(ctime > pa->time+pa->lifetime) {
where_is_particle(paf, pa, pa->time+pa->lifetime-1.0f, vec1);
VecSubf(vec1, vec, vec1);
}
else {
where_is_particle(paf, pa, ctime+1.0f, vec1);
VecSubf(vec1, vec1, vec);
}
q2= vectoquat(vec1, ob->trackflag, ob->upflag);
QuatToMat3(q2, mat);
Mat4CpyMat4(tmat, ob->obmat);
Mat4MulMat43(ob->obmat, tmat, mat);
}
oblist= MEM_callocN(totgroup*sizeof(Object *), "dupgroup object list");
go= part->dup_group->gobject.first;
for(a=0; a<totgroup; a++, go=go->next)
oblist[a]=go->ob;
}
VECCOPY(ob->obmat[3], vec);
/* put object back in original state, so it can be restored OK */
Mat4CpyMat4(tmat, ob->obmat);
Mat4CpyMat4(ob->obmat, copyob.obmat);
new_dupli_object(lb, ob, tmat, par->lay, counter);
}
}
/* temp copy, to have ipos etc to work OK */
*ob= copyob;
break;
if(totchild==0 || part->draw & PART_DRAW_PARENT)
a=0;
else
a=totpart;
for(pa=psys->particles,counter=0; a<totpart+totchild; a++,pa++,counter++) {
if(a<totpart) {
if(pa->flag & (PARS_UNEXIST+PARS_NO_DISP)) continue;
pa_num=pa->num;
pa_time=pa->time;
size=pa->size;
}
else {
/* TODO: figure these two out */
pa_num = a;
pa_time = psys->particles[psys->child[a - totpart].parent].time;
size=psys_get_child_size(psys, a - totpart, ctime, 0);
}
if(part->draw_as==PART_DRAW_GR) {
if(part->draw&PART_DRAW_RAND_GR)
ob = oblist[BLI_rand() % totgroup];
else if(part->from==PART_FROM_PARTICLE)
ob = oblist[pa_num % totgroup];
else
ob = oblist[a % totgroup];
}
else
ob = part->dup_ob;
for(k=0; k<=step_nbr; k++, counter++) {
if(step_nbr) {
state.time = (float)k / (float)step_nbr;
psys_get_particle_on_path(par, psys, a, &state, 0);
}
else {
state.time = -1.0;
if(psys_get_particle_state(par, psys, a, &state, 0) == 0)
continue;
}
QuatToMat3(state.rot, parotmat);
if(part->draw_as==PART_DRAW_GR && psys->part->draw & PART_DRAW_WHOLE_GR) {
for(go= part->dup_group->gobject.first; go; go= go->next) {
Mat4CpyMat4(tmat, go->ob->obmat);
Mat4MulMat43(tmat, go->ob->obmat, parotmat);
Mat4MulFloat3((float *)tmat, size);
VECADD(tmat[3], go->ob->obmat[3], state.co);
new_dupli_object(lb, go->ob, tmat, par->lay, counter);
}
}
else {
/* to give ipos in object correct offset */
where_is_object_time(ob, ctime-pa_time);
q = vectoquat(xvec, ob->trackflag, ob->upflag);
QuatToMat3(q, obrotmat);
Mat3MulMat3(mat, parotmat, obrotmat);
Mat4CpyMat4(tmat, ob->obmat);
Mat4MulMat43(tmat, ob->obmat, mat);
Mat4MulFloat3((float *)tmat, size);
VECCOPY(tmat[3], state.co);
new_dupli_object(lb, ob, tmat, par->lay, counter);
}
ob= ob->parent;
}
}
}
if(G.rendering && paf->disp!=100) {
MEM_freeN(paf->keys);
paf->keys= NULL;
if(oblist)
MEM_freeN(oblist);
if(psys->lattice) {
end_latt_deform();
psys->lattice = 0;
}
}
static Object *find_family_object(Object **obar, char *family, char ch)
@ -771,13 +784,14 @@ ListBase *object_duplilist(Scene *sce, Object *ob)
duplilist->first= duplilist->last= NULL;
if(ob->transflag & OB_DUPLI) {
if(ob->transflag & OB_DUPLIVERTS) {
if(ob->transflag & OB_DUPLIPARTS) {
ParticleSystem *psys = ob->particlesystem.first;
for(; psys; psys=psys->next)
new_particle_duplilist(duplilist, sce, ob, psys);
}
else if(ob->transflag & OB_DUPLIVERTS) {
if(ob->type==OB_MESH) {
PartEff *paf;
if( (paf=give_parteff(ob)) )
particle_duplilist(duplilist, sce, ob, paf);
else
vertex_duplilist(duplilist, sce, ob);
vertex_duplilist(duplilist, sce, ob);
}
else if(ob->type==OB_FONT) {
font_duplilist(duplilist, ob);
@ -823,14 +837,18 @@ int count_duplilist(Object *ob)
if(ob->transflag & OB_DUPLIVERTS) {
if(ob->type==OB_MESH) {
if(ob->transflag & OB_DUPLIVERTS) {
PartEff *paf;
if( (paf=give_parteff(ob)) ) {
return paf->totpart;
}
else {
ParticleSystem *psys = ob->particlesystem.first;
int pdup=0;
for(; psys; psys=psys->next)
pdup += psys->totpart;
if(pdup==0){
Mesh *me= ob->data;
return me->totvert;
}
else
return pdup;
}
}
}

@ -266,7 +266,7 @@ static void clear_global(void)
free_vertexpaint();
G.f &= ~(G_WEIGHTPAINT + G_VERTEXPAINT + G_FACESELECT);
G.f &= ~(G_WEIGHTPAINT + G_VERTEXPAINT + G_FACESELECT + G_PARTICLEEDIT);
}
/* make sure path names are correct for OS */

@ -751,6 +751,7 @@ DerivedMesh *CDDM_from_mesh(Mesh *mesh, Object *ob)
/* this does a referenced copy, the only new layers being ORIGINDEX */
DM_init(dm, mesh->totvert, mesh->totedge, mesh->totface);
dm->deformedOnly = 1;
CustomData_merge(&mesh->vdata, &dm->vertData, CD_MASK_MESH, CD_REFERENCE,
mesh->totvert);
@ -798,6 +799,8 @@ DerivedMesh *CDDM_from_editmesh(EditMesh *em, Mesh *me)
MFace *mface = cddm->mface;
int i, *index;
dm->deformedOnly = 1;
CustomData_merge(&em->vdata, &dm->vertData, CD_MASK_DERIVEDMESH,
CD_CALLOC, dm->numVertData);
/* CustomData_merge(&em->edata, &dm->edgeData, CD_MASK_DERIVEDMESH,
@ -889,6 +892,7 @@ DerivedMesh *CDDM_copy(DerivedMesh *source)
/* this initializes dm, and copies all non mvert/medge/mface layers */
DM_from_template(dm, source, numVerts, numEdges, numFaces);
dm->deformedOnly = source->deformedOnly;
CustomData_copy_data(&source->vertData, &dm->vertData, 0, 0, numVerts);
CustomData_copy_data(&source->edgeData, &dm->edgeData, 0, 0, numEdges);

@ -271,7 +271,7 @@ static void layerSwap_tface(void *data, int *corner_indices)
static void layerDefault_tface(void *data, int count)
{
static MTFace default_tf = {{{0, 1}, {0, 0}, {1, 0}, {1, 1}}, NULL,
static MTFace default_tf = {{{0, 0}, {1, 0}, {1, 1}, {0, 1}}, NULL,
0, 0, TF_DYNAMIC, 0, 0};
MTFace *tf = (MTFace*)data;
int i;
@ -280,6 +280,83 @@ static void layerDefault_tface(void *data, int count)
tf[i] = default_tf;
}
static void layerCopy_origspace_face(const void *source, void *dest, int count)
{
const OrigSpaceFace *source_tf = (const OrigSpaceFace*)source;
OrigSpaceFace *dest_tf = (OrigSpaceFace*)dest;
int i;
for(i = 0; i < count; ++i)
dest_tf[i] = source_tf[i];
}
static void layerInterp_origspace_face(void **sources, float *weights,
float *sub_weights, int count, void *dest)
{
OrigSpaceFace *osf = dest;
int i, j, k;
float uv[4][2];
float *sub_weight;
if(count <= 0) return;
memset(uv, 0, sizeof(uv));
sub_weight = sub_weights;
for(i = 0; i < count; ++i) {
float weight = weights ? weights[i] : 1;
OrigSpaceFace *src = sources[i];
for(j = 0; j < 4; ++j) {
if(sub_weights) {
for(k = 0; k < 4; ++k, ++sub_weight) {
float w = (*sub_weight) * weight;
float *tmp_uv = src->uv[k];
uv[j][0] += tmp_uv[0] * w;
uv[j][1] += tmp_uv[1] * w;
}
} else {
uv[j][0] += src->uv[j][0] * weight;
uv[j][1] += src->uv[j][1] * weight;
}
}
}
*osf = *(OrigSpaceFace *)sources[0];
for(j = 0; j < 4; ++j) {
osf->uv[j][0] = uv[j][0];
osf->uv[j][1] = uv[j][1];
}
}
static void layerSwap_origspace_face(void *data, int *corner_indices)
{
OrigSpaceFace *osf = data;
float uv[4][2];
int j;
for(j = 0; j < 4; ++j) {
uv[j][0] = osf->uv[corner_indices[j]][0];
uv[j][1] = osf->uv[corner_indices[j]][1];
}
memcpy(osf->uv, uv, sizeof(osf->uv));
}
static void layerDefault_origspace_face(void *data, int count)
{
static OrigSpaceFace default_osf = {{{0, 0}, {1, 0}, {1, 1}, {0, 1}}};
OrigSpaceFace *osf = (OrigSpaceFace*)data;
int i;
for(i = 0; i < count; i++)
osf[i] = default_osf;
}
/* --------- */
static void layerInterp_mcol(void **sources, float *weights,
float *sub_weights, int count, void *dest)
{
@ -370,11 +447,13 @@ const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
{sizeof(MFloatProperty), "MFloatProperty",1,"Float",NULL,NULL,NULL,NULL},
{sizeof(MIntProperty), "MIntProperty",1,"Int",NULL,NULL,NULL,NULL},
{sizeof(MStringProperty), "MStringProperty",1,"String",NULL,NULL,NULL,NULL},
{sizeof(OrigSpaceFace), "OrigSpaceFace", 1, "UVTex", layerCopy_origspace_face, NULL,
layerInterp_origspace_face, layerSwap_origspace_face, layerDefault_origspace_face},
};
const char *LAYERTYPENAMES[CD_NUMTYPES] = {
"CDMVert", "CDMSticky", "CDMDeformVert", "CDMEdge", "CDMFace", "CDMTFace",
"CDMCol", "CDOrigIndex", "CDNormal", "CDFlags","CDMFloatProperty","CDMIntProperty","CDMStringProperty"};
"CDMCol", "CDOrigIndex", "CDNormal", "CDFlags","CDMFloatProperty","CDMIntProperty","CDMStringProperty", "CDOrigSpace"};
const CustomDataMask CD_MASK_BAREMESH =
CD_MASK_MVERT | CD_MASK_MEDGE | CD_MASK_MFACE;
@ -387,8 +466,8 @@ const CustomDataMask CD_MASK_EDITMESH =
CD_MASK_MCOL|CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR;
const CustomDataMask CD_MASK_DERIVEDMESH =
CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_MTFACE |
CD_MASK_MCOL | CD_MASK_ORIGINDEX|
CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR;
CD_MASK_MCOL | CD_MASK_ORIGINDEX |
CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR | CD_MASK_ORIGSPACE;
static const LayerTypeInfo *layerType_getInfo(int type)
{

@ -57,6 +57,7 @@
#include "DNA_object_force.h"
#include "DNA_object_fluidsim.h"
#include "DNA_oops_types.h"
#include "DNA_particle_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
@ -72,8 +73,9 @@
#include "BKE_mball.h"
#include "BKE_modifier.h"
#include "BKE_object.h"
#include "BKE_scene.h"
#include "BKE_particle.h"
#include "BKE_utildefines.h"
#include "BKE_scene.h"
#include "MEM_guardedalloc.h"
#include "blendef.h"
@ -353,6 +355,7 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Object *ob, int
DagNode * node2;
DagNode * node3;
Key *key;
ParticleSystem *psys;
int addtoroot= 1;
node = dag_get_node(dag, ob);
@ -586,6 +589,54 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Object *ob, int
}
}
}
psys= ob->particlesystem.first;
if(psys) {
ParticleEffectorCache *nec;
for(; psys; psys=psys->next) {
ParticleSettings *part= psys->part;
dag_add_relation(dag, node, node, DAG_RL_OB_DATA);
if(part->phystype==PART_PHYS_KEYED && psys->keyed_ob &&
BLI_findlink(&psys->keyed_ob->particlesystem,psys->keyed_psys-1)) {
node2 = dag_get_node(dag, psys->keyed_ob);
dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA);
}
if(psys->effectors.first)
psys_end_effectors(psys);
psys_init_effectors(ob,psys->part->eff_group,psys);
if(psys->effectors.first) {
for(nec= psys->effectors.first; nec; nec= nec->next) {
Object *ob1= nec->ob;
if(nec->type & PSYS_EC_EFFECTOR) {
node2 = dag_get_node(dag, ob1);
if(ob1->pd->forcefield==PFIELD_GUIDE)
dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA|DAG_RL_OB_DATA);
else
dag_add_relation(dag, node2, node, DAG_RL_OB_DATA);
}
else if(nec->type & PSYS_EC_DEFLECT) {
node2 = dag_get_node(dag, ob1);
dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA|DAG_RL_OB_DATA);
}
else if(nec->type & PSYS_EC_PARTICLE) {
node2 = dag_get_node(dag, ob1);
dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA);
}
if(nec->type & PSYS_EC_REACTOR) {
node2 = dag_get_node(dag, ob1);
dag_add_relation(dag, node, node2, DAG_RL_DATA_DATA);
}
}
}
}
}
for (con = ob->constraints.first; con; con=con->next) {
bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
@ -1813,6 +1864,8 @@ static void dag_object_time_update_flags(Object *ob)
ob->recalc |= OB_RECALC_DATA; // NT FSPARTICLE
}
}
if(ob->particlesystem.first)
ob->recalc |= OB_RECALC_DATA;
break;
case OB_CURVE:
case OB_SURF:
@ -1842,6 +1895,17 @@ static void dag_object_time_update_flags(Object *ob)
if(ob->transflag & OB_DUPLI) ob->recalc |= OB_RECALC_DATA;
break;
}
if(ob->particlesystem.first) {
ParticleSystem *psys= ob->particlesystem.first;
for(; psys; psys=psys->next) {
if(psys->flag & PSYS_ENABLED) {
ob->recalc |= OB_RECALC_DATA;
break;
}
}
}
}
}

@ -1098,7 +1098,7 @@ void curve_to_filledpoly(Curve *cu, ListBase *nurb, ListBase *dispbase)
- first point left, last point right
- based on subdivided points in original curve, not on points in taper curve (still)
*/
static float calc_taper(Object *taperobj, int cur, int tot)
float calc_taper(Object *taperobj, int cur, int tot)
{
Curve *cu;
DispList *dl;
@ -1256,7 +1256,7 @@ void curve_calc_modifiers_post(Object *ob, ListBase *nurb, ListBase *dispbase, i
if ((md->mode & required_mode) != required_mode) continue;
if (mti->isDisabled && mti->isDisabled(md)) continue;
if (mti->type!=eModifierTypeType_OnlyDeform) continue;
if (mti->type!=eModifierTypeType_OnlyDeform && mti->type!=eModifierTypeType_DeformOrConstruct) continue;
for (dl=dispbase->first; dl; dl=dl->next) {
mti->deformVerts(md, ob, NULL, (float(*)[3]) dl->verts, (dl->type==DL_INDEX3)?dl->nr:dl->parts*dl->nr);

@ -799,7 +799,7 @@ static int pdDoDeflection(RNG *rng, float opco[3], float npco[3], float opno[3],
// t= 0.5; // this is labda of line, can use it optimize quad intersection
// sorry but no .. see below (BM)
if( LineIntersectsTriangle(opco, npco, nv1, nv2, nv3, &t) ) {
if( LineIntersectsTriangle(opco, npco, nv1, nv2, nv3, &t, NULL) ) {
if (t < min_t) {
deflected = 1;
deflected_now = 1;
@ -810,7 +810,7 @@ static int pdDoDeflection(RNG *rng, float opco[3], float npco[3], float opno[3],
// it might give a smaller t on (close to) the edge .. this is numerics not esoteric maths :)
// note: the 2 triangles don't need to share a plane ! (BM)
if (mface->v4) {
if( LineIntersectsTriangle(opco, npco, nv1, nv3, nv4, &t2) ) {
if( LineIntersectsTriangle(opco, npco, nv1, nv3, nv4, &t2, NULL) ) {
if (t2 < min_t) {
deflected = 1;
deflected_now = 2;

@ -52,6 +52,7 @@
#include "DNA_mesh_types.h"
#include "DNA_object_types.h"
#include "DNA_object_force.h"
#include "DNA_particle_types.h"
#include "DNA_sequence_types.h"
#include "DNA_scene_types.h"
#include "DNA_sound_types.h"
@ -93,7 +94,7 @@ int ob_ar[OB_TOTIPO]= {
OB_ROT_X, OB_ROT_Y, OB_ROT_Z, OB_DROT_X, OB_DROT_Y, OB_DROT_Z,
OB_SIZE_X, OB_SIZE_Y, OB_SIZE_Z, OB_DSIZE_X, OB_DSIZE_Y, OB_DSIZE_Z,
OB_LAY, OB_TIME, OB_COL_R, OB_COL_G, OB_COL_B, OB_COL_A,
OB_PD_FSTR, OB_PD_FFALL, OB_PD_SDAMP, OB_PD_RDAMP, OB_PD_PERM
OB_PD_FSTR, OB_PD_FFALL, OB_PD_SDAMP, OB_PD_RDAMP, OB_PD_PERM, OB_PD_FMAXD
};
int ac_ar[AC_TOTIPO]= {
@ -180,6 +181,12 @@ int fluidsim_ar[FLUIDSIM_TOTIPO]= {
FLUIDSIM_ACTIVE
};
int part_ar[PART_TOTIPO]= {
PART_EMIT_FREQ, PART_EMIT_LIFE, PART_EMIT_VEL, PART_EMIT_AVE, PART_EMIT_SIZE,
PART_AVE, PART_SIZE, PART_DRAG, PART_BROWN, PART_DAMP, PART_LENGTH, PART_CLUMP,
PART_GRAV_X, PART_GRAV_Y, PART_GRAV_Z, PART_KINK_AMP, PART_KINK_FREQ, PART_KINK_SHAPE,
PART_BB_TILT
};
float frame_to_float(int cfra) /* see also bsystem_time in object.c */
@ -1231,6 +1238,7 @@ void *get_ipo_poin(ID *id, IpoCurve *icu, int *type)
Lamp *la;
Sequence *seq;
World *wo;
ParticleSettings *part;
*type= IPO_FLOAT;
@ -1308,6 +1316,9 @@ void *get_ipo_poin(ID *id, IpoCurve *icu, int *type)
case OB_PD_PERM:
if(ob->pd) poin= &(ob->pd->pdef_perm);
break;
case OB_PD_FMAXD:
if(ob->pd) poin= &(ob->pd->maxdist);
break;
}
}
else if( GS(id->name)==ID_MA) {
@ -1560,7 +1571,48 @@ void *get_ipo_poin(ID *id, IpoCurve *icu, int *type)
poin= &(snd->attenuation); break;
}
}
else if( GS(id->name)==ID_PA) {
part= (ParticleSettings *)id;
switch(icu->adrcode) {
case PART_EMIT_FREQ:
case PART_EMIT_LIFE:
case PART_EMIT_VEL:
case PART_EMIT_AVE:
case PART_EMIT_SIZE:
poin= NULL; break;
case PART_CLUMP:
poin= &(part->clumpfac); break;
case PART_AVE:
poin= &(part->avefac); break;
case PART_SIZE:
poin= &(part->size); break;
case PART_DRAG:
poin= &(part->dragfac); break;
case PART_BROWN:
poin= &(part->brownfac); break;
case PART_DAMP:
poin= &(part->dampfac); break;
case PART_LENGTH:
poin= &(part->length); break;
case PART_GRAV_X:
poin= &(part->acc[0]); break;
case PART_GRAV_Y:
poin= &(part->acc[1]); break;
case PART_GRAV_Z:
poin= &(part->acc[2]); break;
case PART_KINK_AMP:
poin= &(part->kink_amp); break;
case PART_KINK_FREQ:
poin= &(part->kink_freq); break;
case PART_KINK_SHAPE:
poin= &(part->kink_shape); break;
case PART_BB_TILT:
poin= &(part->bb_tilt); break;
}
}
return poin;
}
@ -1855,6 +1907,29 @@ void set_icu_vars(IpoCurve *icu)
break;
}
}
else if(icu->blocktype==ID_PA){
switch(icu->adrcode) {
case PART_EMIT_LIFE:
case PART_SIZE:
case PART_KINK_FREQ:
case PART_EMIT_VEL:
case PART_EMIT_AVE:
case PART_EMIT_SIZE:
icu->ymin= 0.0;
break;
case PART_CLUMP:
case PART_DRAG:
case PART_DAMP:
case PART_LENGTH:
icu->ymin= 0.0;
icu->ymax= 1.0;
break;
case PART_KINK_SHAPE:
icu->ymin= -0.999;
icu->ymax= 0.999;
}
}
else if(icu->blocktype==ID_CO) {
icu->ymin= 0.0;
icu->ymax= 1.0f;
@ -2325,6 +2400,7 @@ void make_cfra_list(Ipo *ipo, ListBase *elems)
case OB_PD_SDAMP:
case OB_PD_RDAMP:
case OB_PD_PERM:
case OB_PD_FMAXD:
bezt= icu->bezt;
if(bezt) {
a= icu->totvert;

@ -78,6 +78,8 @@
#include "DNA_nla_types.h"
#include "DNA_effect_types.h"
#include "DNA_brush_types.h"
#include "DNA_particle_types.h"
#include "BKE_particle.h"
#include "BLI_blenlib.h"
#include "BLI_dynstr.h"
@ -194,6 +196,8 @@ ListBase *wich_libbase(Main *mainlib, short type)
return &(mainlib->nodetree);
case ID_BR:
return &(mainlib->brush);
case ID_PA:
return &(mainlib->particle);
}
return 0;
}
@ -254,16 +258,17 @@ int set_listbasepointers(Main *main, ListBase **lb)
lb[18]= &(main->nodetree);
lb[19]= &(main->brush);
lb[20]= &(main->script);
lb[21]= &(main->particle);
lb[21]= &(main->world);
lb[22]= &(main->screen);
lb[23]= &(main->object);
lb[24]= &(main->scene);
lb[25]= &(main->library);
lb[22]= &(main->world);
lb[23]= &(main->screen);
lb[24]= &(main->object);
lb[25]= &(main->scene);
lb[26]= &(main->library);
lb[26]= NULL;
lb[27]= NULL;
return 26;
return 27;
}
/* *********** ALLOC AND FREE *****************
@ -359,6 +364,9 @@ static ID *alloc_libblock_notest(short type)
case ID_BR:
id = MEM_callocN(sizeof(Brush), "brush");
break;
case ID_PA:
id = MEM_callocN(sizeof(ParticleSettings), "ParticleSettings");
break;
}
return id;
}
@ -503,6 +511,9 @@ void free_libblock(ListBase *lb, void *idv)
case ID_BR:
free_brush((Brush *)id);
break;
case ID_PA:
psys_free_settings((ParticleSettings *)id);
break;
}
if (id->properties) {

File diff suppressed because it is too large Load Diff

@ -60,6 +60,7 @@
#include "DNA_object_force.h"
#include "DNA_object_fluidsim.h"
#include "DNA_oops_types.h"
#include "DNA_particle_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
@ -101,6 +102,7 @@
#include "BKE_mball.h"
#include "BKE_modifier.h"
#include "BKE_object.h"
#include "BKE_particle.h"
#include "BKE_property.h"
#include "BKE_sca.h"
#include "BKE_scene.h"
@ -164,6 +166,15 @@ void object_free_modifiers(Object *ob)
modifier_free(md);
}
/* particle modifiers were freed, so free the particlesystems as well */
while(ob->particlesystem.first){
ParticleSystem *psys = ob->particlesystem.first;
BLI_remlink(&ob->particlesystem,psys);
psys_free(ob,psys);
}
}
/* here we will collect all local displist stuff */
@ -235,7 +246,11 @@ void free_object(Object *ob)
BPY_free_scriptlink(&ob->scriptlink);
if(ob->pd) MEM_freeN(ob->pd);
if(ob->pd){
if(ob->pd->tex)
ob->pd->tex->id.us--;
MEM_freeN(ob->pd);
}
if(ob->soft) sbFree(ob->soft);
if(ob->fluidsimSettings) fluidsimSettingsFree(ob->fluidsimSettings);
}
@ -380,6 +395,47 @@ void unlink_object(Object *ob)
}
}
/* particle systems */
if(obt->particlesystem.first) {
ParticleSystem *tpsys= obt->particlesystem.first;
for(; tpsys; tpsys=tpsys->next) {
if(tpsys->keyed_ob==ob) {
ParticleSystem *psys= BLI_findlink(&ob->particlesystem,tpsys->keyed_psys-1);
if(psys && psys->keyed_ob) {
tpsys->keyed_ob= psys->keyed_ob;
tpsys->keyed_psys= psys->keyed_psys;
}
else
tpsys->keyed_ob= NULL;
obt->recalc |= OB_RECALC_DATA;
}
if(tpsys->target_ob==ob) {
tpsys->target_ob= NULL;
obt->recalc |= OB_RECALC_DATA;
}
if(tpsys->part->dup_ob==ob)
tpsys->part->dup_ob= NULL;
if(tpsys->part->flag&PART_STICKY) {
ParticleData *pa;
int p;
for(p=0,pa=tpsys->particles; p<tpsys->totpart; p++,pa++) {
if(pa->stick_ob==ob) {
pa->stick_ob= 0;
pa->flag &= ~PARS_STICKY;
}
}
}
}
if(ob->pd)
obt->recalc |= OB_RECALC_DATA;
}
obt= obt->id.next;
}
@ -946,6 +1002,22 @@ SoftBody *copy_softbody(SoftBody *sb)
return sbn;
}
ParticleSystem *copy_particlesystem(ParticleSystem *psys)
{
ParticleSystem *psysn;
psysn= MEM_dupallocN(psys);
psysn->particles= MEM_dupallocN(psys->particles);
psysn->child= MEM_dupallocN(psys->child);
psysn->effectors.first= psysn->effectors.last= 0;
id_us_plus((ID *)psysn->part);
return psysn;
}
static void copy_object_pose(Object *obn, Object *ob)
{
bPoseChannel *chan;
@ -981,6 +1053,7 @@ Object *copy_object(Object *ob)
{
Object *obn;
ModifierData *md;
ParticleSystem *psys;
int a;
obn= copy_libblock(ob);
@ -1031,7 +1104,11 @@ Object *copy_object(Object *ob)
obn->disp.first= obn->disp.last= NULL;
if(ob->pd) obn->pd= MEM_dupallocN(ob->pd);
if(ob->pd){
obn->pd= MEM_dupallocN(ob->pd);
if(obn->pd->tex)
id_us_plus(&(obn->pd->tex->id));
}
obn->soft= copy_softbody(ob->soft);
/* NT copy fluid sim setting memory */
@ -1042,6 +1119,23 @@ Object *copy_object(Object *ob)
obn->fluidsimSettings->orgMesh = (Mesh *)obn->data;
}
}
obn->particlesystem.first= obn->particlesystem.last= NULL;
for(psys=ob->particlesystem.first; psys; psys=psys->next) {
ParticleSystemModifierData *psmd;
ParticleSystem *npsys= copy_particlesystem(psys);
BLI_addtail(&obn->particlesystem, npsys);
/* need to update particle modifiers too */
for(md=obn->modifiers.first; md; md=md->next) {
if(md->type==eModifierType_ParticleSystem) {
psmd= (ParticleSystemModifierData*)md;
if(psmd->psys==psys)
psmd->psys= npsys;
}
}
}
obn->derivedDeform = NULL;
obn->derivedFinal = NULL;
@ -2077,8 +2171,28 @@ void object_handle_update(Object *ob)
where_is_pose(ob);
}
}
if(ob->particlesystem.first) {
ParticleSystem *tpsys, *psys;
psys= ob->particlesystem.first;
while(psys) {
if(psys->flag & PSYS_ENABLED) {
particle_system_update(ob, psys);
psys= psys->next;
}
else if(psys->flag & PSYS_DELETE) {
tpsys=psys->next;
BLI_remlink(&ob->particlesystem, psys);
psys_free(ob,psys);
psys= tpsys;
}
else
psys= psys->next;
}
}
}
/* the no-group proxy case, we call update */
if(ob->proxy && ob->proxy_group==NULL) {
/* set pointer in library proxy target, for copying, but restore it */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -0,0 +1,185 @@
/**
*
* ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
*
* 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. The Blender
* Foundation also sells licenses for use in proprietary software under
* the Blender License. See http://www.blender.org/BL/ for information
* about this.
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* Contributor(s): Campbell Barton <ideasman42@gmail.com>
*
* ***** END GPL/BL DUAL LICENSE BLOCK *****
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "BKE_pointcache.h"
#include "BKE_utildefines.h"
#include "BKE_global.h"
#include "BKE_library.h"
#include "BLI_blenlib.h"
#include "BKE_utildefines.h"
#include "blendef.h"
/* needed for directory lookup */
#ifndef WIN32
#include <dirent.h>
#else
#include "BLI_winstuff.h"
#endif
/* Takes an Object ID and returns a unique name
- id: object id
- cfra: frame for the cache, can be negative
- stack_index: index in the modifier stack. we can have cache for more then one stack_index
*/
static int ptcache_path(char *filename)
{
sprintf(filename, PTCACHE_PATH);
BLI_convertstringcode(filename, G.sce, 0);
return strlen(filename);
}
int BKE_ptcache_id_filename(struct ID *id, char *filename, int cfra, int stack_index, short do_path, short do_ext)
{
int len=0;
char *idname;
char *newname;
filename[0] = '\0';
newname = filename;
/* start with temp dir */
if (do_path) {
len = ptcache_path(filename);
newname += len;
}
idname = (id->name+2);
/* convert chars to hex so they are always a valid filename */
while('\0' != *idname) {
sprintf(newname, "%02X", (char)(*idname++));
newname+=2;
len += 2;
}
if (do_ext) {
sprintf(newname, "_%06d_%02d"PTCACHE_EXT, cfra, stack_index); /* always 6 chars */
len += 16;
}
return len; /* make sure the above string is always 16 chars */
}
/* youll need to close yourself after! */
FILE *BKE_ptcache_id_fopen(struct ID *id, char mode, int cfra, int stack_index)
{
/* mode is same as fopen's modes */
FILE *fp = NULL;
char filename[(FILE_MAXDIR+FILE_MAXFILE)*2];
BKE_ptcache_id_filename(id, filename, cfra, stack_index, 1, 1);
if (mode=='r') {
if (!BLI_exists(filename)) {
return NULL;
}
fp = fopen(filename, "rb");
} else if (mode=='w') {
BLI_make_existing_file(filename); /* will create the dir if needs be, same as //textures is created */
fp = fopen(filename, "wb");
}
if (!fp) {
return NULL;
}
return fp;
}
/* youll need to close yourself after!
* mode,
*/
void BKE_ptcache_id_clear(struct ID *id, char mode, int cfra, int stack_index)
{
int len; /* store the length of the string */
/* mode is same as fopen's modes */
DIR *dir;
struct dirent *de;
char path[FILE_MAX];
char filename[(FILE_MAXDIR+FILE_MAXFILE)*2];
char path_full[(FILE_MAXDIR+FILE_MAXFILE)*2];
/* clear all files in the temp dir with the prefix of the ID and the ".bphys" suffix */
switch (mode) {
case PTCACHE_CLEAR_ALL:
case PTCACHE_CLEAR_BEFORE:
case PTCACHE_CLEAR_AFTER:
ptcache_path(path);
len = BKE_ptcache_id_filename(id, filename, cfra, stack_index, 0, 0); /* no path */
dir = opendir(path);
if (dir==NULL)
return;
while ((de = readdir(dir)) != NULL) {
if (strstr(de->d_name, PTCACHE_EXT)) { /* do we have the right extension?*/
if (strncmp(filename, de->d_name, len ) == 0) { /* do we have the right prefix */
if (mode == PTCACHE_CLEAR_ALL) {
BLI_join_dirfile(path_full, path, de->d_name);
BLI_delete(path_full, 0, 0);
} else {
/* read the number of the file */
int frame, len2 = strlen(de->d_name);
char num[7];
if (len2 > 15) { /* could crash if trying to copy a string out of this range*/
strncpy(num, de->d_name + (strlen(de->d_name) - 15), 6);
frame = atoi(num);
if((mode==PTCACHE_CLEAR_BEFORE && frame < cfra) ||
(mode==PTCACHE_CLEAR_AFTER && frame > cfra) ) {
BLI_join_dirfile(path_full, path, de->d_name);
BLI_delete(path_full, 0, 0);
}
}
}
}
}
}
closedir(dir);
break;
case PTCACHE_CLEAR_FRAME:
len = BKE_ptcache_id_filename(id, filename, cfra, stack_index, 1, 1); /* no path */
BLI_delete(filename, 0, 0);
break;
}
return;
}

@ -174,6 +174,8 @@ void free_scene(Scene *sce)
Scene *add_scene(char *name)
{
Scene *sce;
ParticleEditSettings *pset;
int a;
sce= alloc_libblock(&G.main->scene, ID_SCE, name);
sce->lay= 1;
@ -232,6 +234,19 @@ Scene *add_scene(char *name)
sce->toolsettings->unwrapper = 1;
sce->toolsettings->select_thresh= 0.01f;
sce->toolsettings->jointrilimit = 0.8f;
pset= &sce->toolsettings->particle;
pset->flag= PE_KEEP_LENGTHS|PE_LOCK_FIRST|PE_DEFLECT_EMITTER;
pset->emitterdist= 0.25f;
pset->totrekey= 5;
pset->totaddkey= 5;
pset->brushtype= PE_BRUSH_NONE;
for(a=0; a<PE_TOT_BRUSH; a++) {
pset->brush[a].strength= 50;
pset->brush[a].size= 50;
pset->brush[a].step= 10;
}
pset->brush[PE_BRUSH_CUT].strength= 100;
sce->jumpframe = 10;
sce->audio.mixrate = 44100;

@ -61,9 +61,11 @@ variables on the UI for now
#include "DNA_curve_types.h"
#include "DNA_object_types.h"
#include "DNA_object_force.h" /* here is the softbody struct */
#include "DNA_particle_types.h"
#include "DNA_key_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_modifier_types.h"
#include "DNA_lattice_types.h"
#include "DNA_scene_types.h"
@ -75,9 +77,12 @@ variables on the UI for now
#include "BKE_global.h"
#include "BKE_key.h"
#include "BKE_object.h"
#include "BKE_particle.h"
#include "BKE_softbody.h"
#include "BKE_utildefines.h"
#include "BKE_DerivedMesh.h"
#include "BKE_pointcache.h"
#include "BKE_modifier.h"
#include "BIF_editdeform.h"
#include "BIF_graphics.h"
@ -90,18 +95,6 @@ static int (*SB_localInterruptCallBack)(void) = NULL;
/* ********** soft body engine ******* */
typedef struct BodyPoint {
float origS[3], origE[3], origT[3], pos[3], vec[3], force[3];
float goal;
float prevpos[3], prevvec[3], prevdx[3], prevdv[3]; /* used for Heun integration */
int nofsprings; int *springs;
float choke;
float colball;
short flag;
char octantflag;
} BodyPoint;
typedef struct BodySpring {
int v1, v2;
float len, strength, cf;
@ -480,21 +473,31 @@ void ccd_build_deflector_hache(Object *vertexowner,GHash *hash)
while (base) {
/*Only proceed for mesh object in same layer */
if(base->object->type==OB_MESH && (base->lay & vertexowner->lay)) {
int particles=0;
ob= base->object;
if((vertexowner) && (ob == vertexowner)){
/* if vertexowner is given we don't want to check collision with owner object */
base = base->next;
continue;
if((vertexowner) && (ob == vertexowner)) {
if(vertexowner->soft->particles){
particles=1;
}
else {
/* if vertexowner is given we don't want to check collision with owner object */
base = base->next;
continue;
}
}
/*+++ only with deflecting set */
if(ob->pd && ob->pd->deflect && BLI_ghash_lookup(hash, ob) == 0) {
DerivedMesh *dm= NULL;
if(ob->softflag & OB_SB_COLLFINAL) { /* so maybe someone wants overkill to collide with subsurfed */
dm = mesh_get_derived_final(ob, CD_MASK_BAREMESH);
} else {
dm = mesh_get_derived_deform(ob, CD_MASK_BAREMESH);
if(particles) {
dm = psys_get_modifier(ob,psys_get_current(ob))->dm;
}
else {
if(ob->softflag & OB_SB_COLLFINAL) /* so maybe someone wants overkill to collide with subsurfed */
dm = mesh_get_derived_final(ob, CD_MASK_BAREMESH);
else
dm = mesh_get_derived_deform(ob, CD_MASK_BAREMESH);
}
if(dm){
@ -852,10 +855,11 @@ static void renew_softbody(Object *ob, int totpoint, int totspring)
{
SoftBody *sb;
int i;
short softflag;
if(ob->soft==NULL) ob->soft= sbNew();
else free_softbody_intern(ob->soft);
sb= ob->soft;
softflag=ob->softflag;
if(totpoint) {
sb->totpoint= totpoint;
@ -869,8 +873,8 @@ static void renew_softbody(Object *ob, int totpoint, int totspring)
for (i=0; i<totpoint; i++) {
BodyPoint *bp = &sb->bpoint[i];
if(ob->softflag & OB_SB_GOAL) {
bp->goal= ob->soft->defgoal;
if(softflag & OB_SB_GOAL) {
bp->goal= sb->defgoal;
}
else {
bp->goal= 0.0f;
@ -900,7 +904,6 @@ static void free_softbody_baked(SoftBody *sb)
sb->keys= NULL;
sb->totkey= 0;
}
static void free_scratch(SoftBody *sb)
{
@ -1203,9 +1206,9 @@ int sb_detect_face_collisionCached(float face_v1[3],float face_v2[3],float face_
Crossf(d_nvect, edge2, edge1);
Normalize(d_nvect);
if (
LineIntersectsTriangle(nv1, nv2, face_v1, face_v2, face_v3, &t) ||
LineIntersectsTriangle(nv2, nv3, face_v1, face_v2, face_v3, &t) ||
LineIntersectsTriangle(nv3, nv1, face_v1, face_v2, face_v3, &t) ){
LineIntersectsTriangle(nv1, nv2, face_v1, face_v2, face_v3, &t, NULL) ||
LineIntersectsTriangle(nv2, nv3, face_v1, face_v2, face_v3, &t, NULL) ||
LineIntersectsTriangle(nv3, nv1, face_v1, face_v2, face_v3, &t, NULL) ){
Vec3PlusStVec(force,-1.0f,d_nvect);
*damp=ob->pd->pdef_sbdamp;
deflected = 2;
@ -1217,9 +1220,9 @@ int sb_detect_face_collisionCached(float face_v1[3],float face_v2[3],float face_
Crossf(d_nvect, edge2, edge1);
Normalize(d_nvect);
if (
LineIntersectsTriangle(nv1, nv3, face_v1, face_v2, face_v3, &t) ||
LineIntersectsTriangle(nv3, nv4, face_v1, face_v2, face_v3, &t) ||
LineIntersectsTriangle(nv4, nv1, face_v1, face_v2, face_v3, &t) ){
LineIntersectsTriangle(nv1, nv3, face_v1, face_v2, face_v3, &t, NULL) ||
LineIntersectsTriangle(nv3, nv4, face_v1, face_v2, face_v3, &t, NULL) ||
LineIntersectsTriangle(nv4, nv1, face_v1, face_v2, face_v3, &t, NULL) ){
Vec3PlusStVec(force,-1.0f,d_nvect);
*damp=ob->pd->pdef_sbdamp;
deflected = 2;
@ -1402,7 +1405,7 @@ int sb_detect_edge_collisionCached(float edge_v1[3],float edge_v2[3],float *damp
Crossf(d_nvect, edge2, edge1);
Normalize(d_nvect);
if ( LineIntersectsTriangle(edge_v1, edge_v2, nv1, nv2, nv3, &t)){
if ( LineIntersectsTriangle(edge_v1, edge_v2, nv1, nv2, nv3, &t, NULL)){
float v1[3],v2[3];
float intrusiondepth,i1,i2;
VECSUB(v1, edge_v1, nv2);
@ -1421,7 +1424,7 @@ int sb_detect_edge_collisionCached(float edge_v1[3],float edge_v2[3],float *damp
Crossf(d_nvect, edge2, edge1);
Normalize(d_nvect);
if (LineIntersectsTriangle( edge_v1, edge_v2,nv1, nv3, nv4, &t)){
if (LineIntersectsTriangle( edge_v1, edge_v2,nv1, nv3, nv4, &t, NULL)){
float v1[3],v2[3];
float intrusiondepth,i1,i2;
VECSUB(v1, edge_v1, nv4);
@ -1550,7 +1553,7 @@ int sb_detect_vertex_collisionCached(float opco[3], float facenormal[3], float *
Object *ob= NULL;
GHash *hash;
GHashIterator *ihash;
float nv1[3], nv2[3], nv3[3], nv4[3], edge1[3], edge2[3],d_nvect[3], dv1[3],ve[3],avel[3],
float nv1[3], nv2[3], nv3[3], nv4[3], edge1[3], edge2[3],d_nvect[3], dv1[3],ve[3],avel[3]={0.0,0.0,0.0},
vv1[3], vv2[3], vv3[3], vv4[3], coledge[3], mindistedge = 1000.0f,
outerforceaccu[3],innerforceaccu[3],
facedist,n_mag,force_mag_norm,minx,miny,minz,maxx,maxy,maxz,
@ -2953,6 +2956,103 @@ static void curve_surf_to_softbody(Object *ob)
}
static void springs_from_particles(Object *ob)
{
ParticleSystem *psys;
ParticleSystemModifierData *psmd=0;
ParticleData *pa=0;
HairKey *key=0;
SoftBody *sb;
BodyPoint *bp;
BodySpring *bs;
int a,k;
float hairmat[4][4];
psys= ob->soft->particles;
sb= ob->soft;
if(ob && sb && psys) {
psmd = psys_get_modifier(ob, psys);
bp= sb->bpoint;
for(a=0, pa=psys->particles; a<psys->totpart; a++, pa++) {
for(k=0, key=pa->hair; k<pa->totkey; k++, bp++, key++) {
VECCOPY(bp->origS, key->co);
psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat);
Mat4MulVecfl(hairmat, bp->origS);
}
}
for(a=0, bs=sb->bspring; a<sb->totspring; a++, bs++)
bs->len= VecLenf(sb->bpoint[bs->v1].origS, sb->bpoint[bs->v2].origS);
}
}
static void particles_to_softbody(Object *ob)
{
SoftBody *sb;
BodyPoint *bp;
BodySpring *bs;
ParticleData *pa;
HairKey *key;
ParticleSystem *psys= ob->soft->particles;
float goalfac;
int a, k, curpoint;
int totpoint= psys_count_keys(psys);
int totedge= totpoint-psys->totpart;
/* renew ends with ob->soft with points and edges, also checks & makes ob->soft */
renew_softbody(ob, totpoint, totedge);
psys->particles->bpi = 0;
for(a=1, pa=psys->particles+1; a<psys->totpart; a++, pa++)
pa->bpi = (pa-1)->bpi + pa->totkey;
/* we always make body points */
sb= ob->soft;
bp= sb->bpoint;
bs= sb->bspring;
goalfac= ABS(sb->maxgoal - sb->mingoal);
if((ob->softflag & OB_SB_GOAL)) {
for(a=0, pa=psys->particles; a<psys->totpart; a++, pa++) {
for(k=0, key=pa->hair; k<pa->totkey; k++,bp++,key++) {
if(k) {
bp->goal= key->weight;
bp->goal= sb->mingoal + bp->goal*goalfac;
bp->goal= (float)pow(bp->goal, 4.0f);
}
else{
/* hair roots are allways fixed fully to goal */
bp->goal= 1.0f;
}
}
}
}
bp= sb->bpoint;
curpoint=0;
for(a=0, pa=psys->particles; a<psys->totpart; a++, curpoint++, pa++) {
for(k=0; k<pa->totkey-1; k++,bs++,curpoint++) {
bs->v1=curpoint;
bs->v2=curpoint+1;
bs->strength= 1.0;
bs->order=1;
}
}
build_bps_springlist(ob); /* scan for springs attached to bodypoints ONCE */
/* insert *other second order* springs if desired */
if(sb->secondspring > 0.0000001f) {
add_2nd_order_springs(ob,sb->secondspring*10.0); /* exploits the the first run of build_bps_springlist(ob);*/
build_bps_springlist(ob); /* yes we need to do it again*/
}
springs_from_particles(ob); /* write the 'rest'-lenght of the springs */
if(ob->softflag & OB_SB_SELF)
calculate_collision_balls(ob);
}
/* copies softbody result back in object */
static void softbody_to_object(Object *ob, float (*vertexCos)[3], int numVerts, int local)
{
@ -2969,117 +3069,94 @@ static void softbody_to_object(Object *ob, float (*vertexCos)[3], int numVerts,
}
}
/* return 1 if succesfully baked and applied step */
static int softbody_baked_step(Object *ob, float framenr, float (*vertexCos)[3], int numVerts)
void softbody_clear_cache(Object *ob, float framenr)
{
SoftBody *sb= ob->soft;
SBVertex *key0, *key1, *key2, *key3;
BodyPoint *bp;
float data[4], sfra, efra, cfra, dfra, fac; /* start, end, current, delta */
int ofs1, a;
SoftBody *sb = ob->soft;
ModifierData *md = ob->modifiers.first;
int stack_index = -1;
int a;
/* precondition check */
if(sb==NULL || sb->keys==NULL || sb->totkey==0) return 0;
/* so we got keys, but no bodypoints... even without simul we need it for the bake */
if(sb->bpoint==NULL) sb->bpoint= MEM_callocN( sb->totpoint*sizeof(BodyPoint), "bodypoint");
/* convert cfra time to system time */
sfra= (float)sb->sfra;
cfra= bsystem_time(ob, framenr, 0.0);
efra= (float)sb->efra;
dfra= (float)sb->interval;
if(sb==NULL) return;
/* offset in keys array */
ofs1= (int)floor( (cfra-sfra)/dfra );
if(ofs1 < 0) {
key0=key1=key2=key3= *sb->keys;
}
else if(ofs1 >= sb->totkey-1) {
key0=key1=key2=key3= *(sb->keys+sb->totkey-1);
}
if(sb->particles)
stack_index = modifiers_indexInObject(ob,(ModifierData*)psys_get_modifier(ob,sb->particles));
else {
key1= *(sb->keys+ofs1);
key2= *(sb->keys+ofs1+1);
if(ofs1>0) key0= *(sb->keys+ofs1-1);
else key0= key1;
if(ofs1<sb->totkey-2) key3= *(sb->keys+ofs1+2);
else key3= key2;
}
sb->ctime= cfra; /* needed? */
/* timing */
fac= ((cfra-sfra)/dfra) - (float)ofs1;
CLAMP(fac, 0.0, 1.0);
set_four_ipo(fac, data, KEY_BSPLINE);
if (key0&&key1&&key2&&key3) // may be null because we SHIFT_ESCAPED
for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++, key0++, key1++, key2++, key3++) {
bp->pos[0]= data[0]*key0->vec[0] + data[1]*key1->vec[0] + data[2]*key2->vec[0] + data[3]*key3->vec[0];
bp->pos[1]= data[0]*key0->vec[1] + data[1]*key1->vec[1] + data[2]*key2->vec[1] + data[3]*key3->vec[1];
bp->pos[2]= data[0]*key0->vec[2] + data[1]*key1->vec[2] + data[2]*key2->vec[2] + data[3]*key3->vec[2];
}
softbody_to_object(ob, vertexCos, numVerts, sb->local);
return 1;
}
/* only gets called after succesfully doing softbody_step */
/* already checked for OB_SB_BAKE flag */
static void softbody_baked_add(Object *ob, float framenr)
{
SoftBody *sb= ob->soft;
SBVertex *key;
BodyPoint *bp;
float sfra, efra, cfra, dfra, fac1; /* start, end, current, delta */
int ofs1, a;
/* convert cfra time to system time */
sfra= (float)sb->sfra;
fac1= ob->sf; ob->sf= 0.0f; /* disable startframe */
cfra= bsystem_time(ob, framenr, 0.0);
ob->sf= fac1;
efra= (float)sb->efra;
dfra= (float)sb->interval;
if(sb->totkey==0) {
if(sb->sfra >= sb->efra) return; /* safety, UI or py setting allows */
if(sb->interval<1) sb->interval= 1; /* just be sure */
sb->totkey= 1 + (int)(ceil( (efra-sfra)/dfra ) );
sb->keys= MEM_callocN( sizeof(void *)*sb->totkey, "sb keys");
}
/* inverse matrix might not be uptodate... */
Mat4Invert(ob->imat, ob->obmat);
/* now find out if we have to store a key */
/* offset in keys array */
if(cfra>=(efra)) {
ofs1= sb->totkey-1;
fac1= 0.0;
}
else {
ofs1= (int)floor( (cfra-sfra)/dfra );
fac1= ((cfra-sfra)/dfra) - (float)ofs1;
}
if( fac1 < 1.0/dfra ) {
key= *(sb->keys+ofs1);
if(key == NULL) {
*(sb->keys+ofs1)= key= MEM_mallocN(sb->totpoint*sizeof(SBVertex), "softbody key");
for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++, key++) {
VECCOPY(key->vec, bp->pos);
if(sb->local)
Mat4MulVecfl(ob->imat, key->vec);
for(a=0; md; md=md->next, a++) {
if(md->type == eModifierType_Softbody) {
stack_index = a;
break;
}
}
}
BKE_ptcache_id_clear((ID *)ob, PTCACHE_CLEAR_ALL, framenr, stack_index);
}
static void softbody_write_cache(Object *ob, float framenr)
{
FILE *fp = NULL;
SoftBody *sb = ob->soft;
BodyPoint *bp;
ModifierData *md = ob->modifiers.first;
int stack_index = -1;
int a;
if(sb->totpoint == 0) return;
if(sb->particles)
stack_index = modifiers_indexInObject(ob,(ModifierData*)psys_get_modifier(ob,sb->particles));
else {
for(a=0; md; md=md->next, a++) {
if(md->type == eModifierType_Softbody) {
stack_index = a;
break;
}
}
}
fp = BKE_ptcache_id_fopen((ID *)ob, 'w', framenr, stack_index);
if(!fp) return;
for(a=0, bp=sb->bpoint; a<sb->totpoint; a++, bp++)
fwrite(&bp->pos, sizeof(float), 3, fp);
fclose(fp);
}
static int softbody_read_cache(Object *ob, float framenr)
{
FILE *fp = NULL;
SoftBody *sb = ob->soft;
BodyPoint *bp;
ModifierData *md = ob->modifiers.first;
int stack_index = -1;
int a, ret = 1;
if(sb->totpoint == 0) return 0;
if(sb->particles)
stack_index = modifiers_indexInObject(ob,(ModifierData*)psys_get_modifier(ob,sb->particles));
else {
for(a=0; md; md=md->next, a++) {
if(md->type == eModifierType_Softbody) {
stack_index = a;
break;
}
}
}
fp = BKE_ptcache_id_fopen((ID *)ob, 'r', framenr, stack_index);
if(!fp)
ret = 0;
else {
for(a=0, bp=sb->bpoint; a<sb->totpoint; a++, bp++)
if(fread(&bp->pos, sizeof(float), 3, fp) != 3) {
ret = 0;
break;
}
fclose(fp);
}
return ret;
}
/* +++ ************ maintaining scratch *************** */
void sb_new_scratch(SoftBody *sb)
@ -3175,15 +3252,14 @@ void sbSetInterruptCallBack(int (*f)(void))
/* simulates one step. framenr is in frames */
void sbObjectStep(Object *ob, float framenr, float (*vertexCos)[3], int numVerts)
{
ParticleSystemModifierData *psmd=0;
ParticleData *pa=0;
SoftBody *sb;
HairKey *key= NULL;
BodyPoint *bp;
int a;
float dtime,ctime,forcetime,err;
/* baking works with global time */
if(!(ob->softflag & OB_SB_BAKEDO) )
if(softbody_baked_step(ob, framenr, vertexCos, numVerts) ) return;
float hairmat[4][4];
/* This part only sets goals and springs, based on original mesh/curve/lattice data.
Copying coordinates happens in next chunk by setting softbody flag OB_SB_RESET */
@ -3194,7 +3270,13 @@ void sbObjectStep(Object *ob, float framenr, float (*vertexCos)[3], int numVerts
(numVerts!=ob->soft->totpoint) || /* should never happen, just to be safe */
((ob->softflag & OB_SB_EDGES) && !ob->soft->bspring && object_has_edges(ob))) /* happens when in UI edges was set */
{
switch(ob->type) {
if(ob->soft && ob->soft->bpoint) /* don't clear on file load */
softbody_clear_cache(ob, framenr);
if(ob->soft->particles){
particles_to_softbody(ob);
}
else switch(ob->type) {
case OB_MESH:
mesh_to_softbody(ob);
break;
@ -3220,6 +3302,10 @@ void sbObjectStep(Object *ob, float framenr, float (*vertexCos)[3], int numVerts
/* still no points? go away */
if(sb->totpoint==0) return;
if(sb->particles){
psmd=psys_get_modifier(ob,sb->particles);
pa=sb->particles->particles;
}
/* checking time: */
@ -3231,17 +3317,45 @@ void sbObjectStep(Object *ob, float framenr, float (*vertexCos)[3], int numVerts
dtime= ctime - sb->ctime;
}
if(softbody_read_cache(ob, framenr)) {
if(sb->particles==0)
softbody_to_object(ob, vertexCos, numVerts, sb->local);
sb->ctime = ctime;
return;
}
/* the simulator */
/* update the vertex locations */
if (dtime!=0.0) {
if(sb->particles) {
pa=sb->particles->particles;
key = pa->hair;
psys_mat_hair_to_global(ob, psmd->dm, sb->particles->part->from, pa, hairmat);
}
for(a=0,bp=sb->bpoint; a<numVerts; a++, bp++) {
/* store where goals are now */
VECCOPY(bp->origS, bp->origE);
/* copy the position of the goals at desired end time */
VECCOPY(bp->origE, vertexCos[a]);
/* vertexCos came from local world, go global */
Mat4MulVecfl(ob->obmat, bp->origE);
if(sb->particles) {
if(key == pa->hair + pa->totkey) {
pa++;
key = pa->hair;
psys_mat_hair_to_global(ob, psmd->dm, sb->particles->part->from, pa, hairmat);
}
VECCOPY(bp->origE, key->co);
Mat4MulVecfl(hairmat,bp->origE);
key++;
}
else{
VECCOPY(bp->origE, vertexCos[a]);
/* vertexCos came from local world, go global */
Mat4MulVecfl(ob->obmat, bp->origE);
}
/* just to be save give bp->origT a defined value
will be calulated in interpolate_exciter()*/
VECCOPY(bp->origT, bp->origE);
@ -3253,9 +3367,29 @@ void sbObjectStep(Object *ob, float framenr, float (*vertexCos)[3], int numVerts
(dtime>=9.9*G.scene->r.framelen) /* too far forward in time --> goals won't be accurate enough */
)
{
if(sb->particles) {
pa=sb->particles->particles;
key = pa->hair;
psys_mat_hair_to_global(ob, psmd->dm, sb->particles->part->from, pa, hairmat);
}
for(a=0,bp=sb->bpoint; a<numVerts; a++, bp++) {
VECCOPY(bp->pos, vertexCos[a]);
Mat4MulVecfl(ob->obmat, bp->pos); /* yep, sofbody is global coords*/
if(sb->particles) {
if(key == pa->hair + pa->totkey) {
pa++;
key = pa->hair;
psys_mat_hair_to_global(ob, psmd->dm, sb->particles->part->from, pa, hairmat);
}
VECCOPY(bp->pos, key->co);
Mat4MulVecfl(hairmat, bp->pos);
key++;
}
else {
VECCOPY(bp->pos, vertexCos[a]);
Mat4MulVecfl(ob->obmat, bp->pos); /* yep, sofbody is global coords*/
}
VECCOPY(bp->origS, bp->pos);
VECCOPY(bp->origE, bp->pos);
VECCOPY(bp->origT, bp->pos);
@ -3283,23 +3417,22 @@ void sbObjectStep(Object *ob, float framenr, float (*vertexCos)[3], int numVerts
sb_new_scratch(sb); /* make a new */
sb->scratch->needstobuildcollider=1;
/* copy some info to scratch */
switch(ob->type) {
case OB_MESH:
if (ob->softflag & OB_SB_FACECOLL) mesh_faces_to_scratch(ob);
break;
case OB_LATTICE:
break;
case OB_CURVE:
case OB_SURF:
break;
default:
break;
if((sb->particles)==0) {
/* copy some info to scratch */
switch(ob->type) {
case OB_MESH:
if (ob->softflag & OB_SB_FACECOLL) mesh_faces_to_scratch(ob);
break;
case OB_LATTICE:
break;
case OB_CURVE:
case OB_SURF:
break;
default:
break;
}
}
ob->softflag &= ~OB_SB_RESET;
}
else if(dtime>0.0) {
@ -3411,10 +3544,10 @@ void sbObjectStep(Object *ob, float framenr, float (*vertexCos)[3], int numVerts
}
}
softbody_to_object(ob, vertexCos, numVerts, 0);
if(sb->particles==0)
softbody_to_object(ob, vertexCos, numVerts, 0);
sb->ctime= ctime;
if(ob->softflag & OB_SB_BAKEDO) softbody_baked_add(ob, framenr);
softbody_write_cache(ob, framenr);
}

@ -248,6 +248,7 @@ void VecMidf(float *v, float *v1, float *v2);
void VecOrthoBasisf(float *v, float *v1, float *v2);
float Vec2Lenf(float *v1, float *v2);
float Vec2Length(float *v);
void Vec2Mulf(float *v1, float f);
void Vec2Addf(float *v, float *v1, float *v2);
void Vec2Subf(float *v, float *v1, float *v2);
@ -281,6 +282,11 @@ float AreaPoly3Dfl(int nr, float *verts, float *normal);
extern short IsectLL2Df(float *v1, float *v2, float *v3, float *v4);
extern short IsectLL2Ds(short *v1, short *v2, short *v3, short *v4);
/*point in tri, 0 no intersection, 1 intersect */
int IsectPT2Df(float pt[2], float v1[2], float v2[2], float v3[2]);
/* point in quad, 0 no intersection, 1 intersect */
int IsectPQ2Df(float pt[2], float v1[2], float v2[2], float v3[2], float v4[2]);
/* interpolation weights of point in a triangle or quad, v4 may be NULL */
void InterpWeightsQ3Dfl(float *v1, float *v2, float *v3, float *v4, float *co, float *w);
/* interpolation weights of point in a polygon with >= 3 vertices */
@ -358,7 +364,13 @@ void LocQuatSizeToMat4(float mat[][4], float loc[3], float quat[4], float size[3
void tubemap(float x, float y, float z, float *u, float *v);
void spheremap(float x, float y, float z, float *u, float *v);
int LineIntersectsTriangle(float p1[3], float p2[3], float v0[3], float v1[3], float v2[3], float *lambda);
int LineIntersectsTriangle(float p1[3], float p2[3], float v0[3], float v1[3], float v2[3], float *lambda, float *uv);
int SweepingSphereIntersectsTriangleUV(float p1[3], float p2[3], float radius, float v0[3], float v1[3], float v2[3], float *lambda, float *ipoint);
int AxialLineIntersectsTriangle(int axis, float co1[3], float co2[3], float v0[3], float v1[3], float v2[3], float *lambda);
int AabbIntersectAabb(float min1[3], float max1[3], float min2[3], float max2[3]);
void VecfCubicInterpol(float *x1, float *v1, float *x2, float *v2, float t, float *x, float *v);
void PointInQuad2DUV(float v0[2], float v1[2], float v2[2], float v3[2], float pt[2], float *uv);
void PointInFace2DUV(int isquad, float v0[2], float v1[2], float v2[2], float v3[2], float pt[2], float *uv);
int point_in_tri_prism(float p[3], float v1[3], float v2[3], float v3[3]);
float lambda_cp_line_ex(float p[3], float l1[3], float l2[3], float cp[3]);

@ -0,0 +1,63 @@
/**
* A kd-tree for nearest neighbour search.
*
* $Id$
*
* ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
*
* 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. The Blender
* Foundation also sells licenses for use in proprietary software under
* the Blender License. See http://www.blender.org/BL/ for information
* about this.
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* The Original Code is: none of this file.
*
* Contributor(s): Janne Karhu
* Brecht Van Lommel
*
* ***** END GPL/BL DUAL LICENSE BLOCK *****
*/
#ifndef BLI_KDTREE_H
#define BLI_KDTREE_H
struct KDTree;
typedef struct KDTree KDTree;
typedef struct KDTreeNearest {
int index;
float dist;
float co[3];
} KDTreeNearest;
/* Creates or free a kdtree */
KDTree* BLI_kdtree_new(int maxsize);
void BLI_kdtree_free(KDTree *tree);
/* Construction: first insert points, then call balance. Normal is optional. */
void BLI_kdtree_insert(KDTree *tree, int index, float *co, float *nor);
void BLI_kdtree_balance(KDTree *tree);
/* Find nearest returns index, and -1 if no node is found.
* Find n nearest returns number of points found, with results in nearest.
* Normal is optional. */
int BLI_kdtree_find_nearest(KDTree *tree, float *co, float *nor, KDTreeNearest *nearest);
int BLI_kdtree_find_n_nearest(KDTree *tree, int n, float *co, float *nor, KDTreeNearest *nearest);
#endif

@ -0,0 +1,327 @@
/**
* $Id$
*
* ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
*
* 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. The Blender
* Foundation also sells licenses for use in proprietary software under
* the Blender License. See http://www.blender.org/BL/ for information
* about this.
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* The Original Code is: none of this file.
*
* Contributor(s): Janne Karhu
* Brecht Van Lommel
*
* ***** END GPL/BL DUAL LICENSE BLOCK *****
*/
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "MEM_guardedalloc.h"
#include "BLI_arithb.h"
#include "BLI_kdtree.h"
#define SWAP(type, a, b) { type sw_ap; sw_ap=(a); (a)=(b); (b)=sw_ap; }
typedef struct KDTreeNode {
struct KDTreeNode *left, *right;
float co[3], nor[3];
int index;
short d;
} KDTreeNode;
struct KDTree {
KDTreeNode *nodes;
int totnode;
KDTreeNode *root;
};
KDTree *BLI_kdtree_new(int maxsize)
{
KDTree *tree;
tree= MEM_callocN(sizeof(KDTree), "KDTree");
tree->nodes= MEM_callocN(sizeof(KDTreeNode)*maxsize, "KDTreeNode");
tree->totnode= 0;
return tree;
}
void BLI_kdtree_free(KDTree *tree)
{
if(tree) {
MEM_freeN(tree->nodes);
MEM_freeN(tree);
}
}
void BLI_kdtree_insert(KDTree *tree, int index, float *co, float *nor)
{
KDTreeNode *node= &tree->nodes[tree->totnode++];
node->index= index;
VecCopyf(node->co, co);
if(nor) VecCopyf(node->nor, nor);
}
static KDTreeNode *kdtree_balance(KDTreeNode *nodes, int totnode, int axis)
{
KDTreeNode *node;
float co;
int left, right, median, i, j;
if(totnode <= 0)
return NULL;
else if(totnode == 1)
return nodes;
/* quicksort style sorting around median */
left= 0;
right= totnode-1;
median= totnode/2;
while(right > left) {
co= nodes[right].co[axis];
i= left-1;
j= right;
while(1) {
while(nodes[++i].co[axis] < co);
while(nodes[--j].co[axis] > co && j>left);
if(i >= j) break;
SWAP(KDTreeNode, nodes[i], nodes[j]);
}
SWAP(KDTreeNode, nodes[i], nodes[right]);
if(i >= median)
right= i-1;
if(i <= median)
left= i+1;
}
/* set node and sort subnodes */
node= &nodes[median];
node->d= axis;
node->left= kdtree_balance(nodes, median, (axis+1)%3);
node->right= kdtree_balance(nodes+median+1, (totnode-(median+1)), (axis+1)%3);
return node;
}
void BLI_kdtree_balance(KDTree *tree)
{
tree->root= kdtree_balance(tree->nodes, tree->totnode, 0);
}
static float squared_distance(float *v1, float *v2, float *n1, float *n2)
{
float d[3], dist;
d[0]= v2[0]-v1[0];
d[1]= v2[1]-v1[1];
d[2]= v2[2]-v1[2];
dist= d[0]*d[0] + d[1]*d[1] + d[2]*d[2];
if(n1 && n2 && n1[0]*n2[0] + n1[1]*n2[1] + n1[2]*n2[2] < 0.0f)
dist *= 10.0f;
return dist;
}
int BLI_kdtree_find_nearest(KDTree *tree, float *co, float *nor, KDTreeNearest *nearest)
{
KDTreeNode *root, *node, *min_node;
KDTreeNode **stack, *defaultstack[100];
float min_dist, cur_dist;
int totstack, cur=0;
if(!tree->root)
return -1;
stack= defaultstack;
totstack= 100;
root= tree->root;
min_node= root;
min_dist= squared_distance(root->co,co,root->nor,nor);
if(root->left)
stack[cur++]=root->left;
if(root->right)
stack[cur++]=root->right;
while(cur--){
node=stack[cur];
cur_dist = node->co[node->d] - co[node->d];
if(cur_dist<0.0){
cur_dist= -cur_dist*cur_dist;
if(-cur_dist<min_dist){
cur_dist=squared_distance(node->co,co,node->nor,nor);
if(cur_dist<min_dist){
min_dist=cur_dist;
min_node=node;
}
if(node->left)
stack[cur++]=node->left;
}
if(node->right)
stack[cur++]=node->right;
}
else{
cur_dist= cur_dist*cur_dist;
if(cur_dist<min_dist){
cur_dist=squared_distance(node->co,co,node->nor,nor);
if(cur_dist<min_dist){
min_dist=cur_dist;
min_node=node;
}
if(node->right)
stack[cur++]=node->right;
}
if(node->left)
stack[cur++]=node->left;
}
if(cur+3 > totstack){
KDTreeNode **temp=MEM_callocN((totstack+100)*sizeof(KDTreeNode*), "psys_treestack");
memcpy(temp,stack,totstack*sizeof(KDTreeNode*));
if(stack != defaultstack)
MEM_freeN(stack);
stack=temp;
totstack+=100;
}
}
if(nearest) {
nearest->index= min_node->index;
nearest->dist= sqrt(min_dist);
VecCopyf(nearest->co, min_node->co);
}
if(stack != defaultstack)
MEM_freeN(stack);
return min_node->index;
}
static void add_nearest(KDTreeNearest *ptn, int *found, int n, int index, float dist, float *co)
{
int i;
if(*found<n) (*found)++;
for(i=*found-1; i>0; i--) {
if(dist >= ptn[i-1].dist)
break;
else
ptn[i]= ptn[i-1];
}
ptn[i].index= index;
ptn[i].dist= dist;
VecCopyf(ptn[i].co, co);
}
/* finds the nearest n entries in tree to specified coordinates */
int BLI_kdtree_find_n_nearest(KDTree *tree, int n, float *co, float *nor, KDTreeNearest *nearest)
{
KDTreeNode *root, *node=0;
KDTreeNode **stack, *defaultstack[100];
float cur_dist;
int i, totstack, cur=0, found=0;
if(!tree->root)
return 0;
stack= defaultstack;
totstack= 100;
root= tree->root;
cur_dist= squared_distance(root->co,co,root->nor,nor);
add_nearest(nearest,&found,n,root->index,cur_dist,root->co);
if(root->left)
stack[cur++]=root->left;
if(root->right)
stack[cur++]=root->right;
while(cur--){
node=stack[cur];
cur_dist = node->co[node->d] - co[node->d];
if(cur_dist<0.0){
cur_dist= -cur_dist*cur_dist;
if(found<n || -cur_dist<nearest[found-1].dist){
cur_dist=squared_distance(node->co,co,node->nor,nor);
if(found<n || cur_dist<nearest[found-1].dist)
add_nearest(nearest,&found,n,node->index,cur_dist,node->co);
if(node->left)
stack[cur++]=node->left;
}
if(node->right)
stack[cur++]=node->right;
}
else{
cur_dist= cur_dist*cur_dist;
if(found<n || cur_dist<nearest[found-1].dist){
cur_dist=squared_distance(node->co,co,node->nor,nor);
if(found<n || cur_dist<nearest[found-1].dist)
add_nearest(nearest,&found,n,node->index,cur_dist,node->co);
if(node->right)
stack[cur++]=node->right;
}
if(node->left)
stack[cur++]=node->left;
}
if(cur+3 > totstack){
KDTreeNode **temp=MEM_callocN((totstack+100)*sizeof(KDTreeNode*), "psys_treestack");
memcpy(temp,stack,totstack*sizeof(KDTreeNode*));
if(stack != defaultstack)
MEM_freeN(stack);
stack=temp;
totstack+=100;
}
}
for(i=0; i<found; i++)
nearest[i].dist= sqrt(nearest[i].dist);
if(stack != defaultstack)
MEM_freeN(stack);
return found;
}

@ -2421,6 +2421,98 @@ short IsectLL2Df(float *v1, float *v2, float *v3, float *v4)
return 0;
}
/*
-1: colliniar
1: intersection
*/
short IsectLLPt2Df(float x0,float y0,float x1,float y1,
float x2,float y2,float x3,float y3, float *xi,float *yi)
{
/*
this function computes the intersection of the sent lines
and returns the intersection point, note that the function assumes
the lines intersect. the function can handle vertical as well
as horizontal lines. note the function isn't very clever, it simply
applies the math, but we don't need speed since this is a
pre-processing step
*/
float c1,c2, // constants of linear equations
det_inv, // the inverse of the determinant of the coefficient
m1,m2; // the slopes of each line
/*
compute slopes, note the cludge for infinity, however, this will
be close enough
*/
if ( fabs( x1-x0 ) > 0.000001 )
m1 = ( y1-y0 ) / ( x1-x0 );
else
return -1; /*m1 = ( float ) 1e+10;*/ // close enough to infinity
if ( fabs( x3-x2 ) > 0.000001 )
m2 = ( y3-y2 ) / ( x3-x2 );
else
return -1; /*m2 = ( float ) 1e+10;*/ // close enough to infinity
if (fabs(m1-m2) < 0.000001)
return -1; /* paralelle lines */
// compute constants
c1 = ( y0-m1*x0 );
c2 = ( y2-m2*x2 );
// compute the inverse of the determinate
det_inv = 1.0f / ( -m1 + m2 );
// use Kramers rule to compute xi and yi
*xi= ( ( -c2 + c1 ) *det_inv );
*yi= ( ( m2*c1 - m1*c2 ) *det_inv );
return 1;
} // end Intersect_Lines
#define SIDE_OF_LINE(pa,pb,pp) ((pa[0]-pp[0])*(pb[1]-pp[1]))-((pb[0]-pp[0])*(pa[1]-pp[1]))
#define ISECT_EPSILON 1e-6
/* point in tri */
int IsectPT2Df(float pt[2], float v1[2], float v2[2], float v3[2])
{
if ((SIDE_OF_LINE(v1,v2,pt)>=-ISECT_EPSILON) &&
(SIDE_OF_LINE(v2,v3,pt)>=-ISECT_EPSILON) &&
(SIDE_OF_LINE(v3,v1,pt)>=-ISECT_EPSILON))
return 1;
else {
return 0;
}
}
/* point in quad - only convex quads */
int IsectPQ2Df(float pt[2], float v1[2], float v2[2], float v3[2], float v4[2])
{
if ((SIDE_OF_LINE(v1,v2,pt)>=-ISECT_EPSILON) &&
(SIDE_OF_LINE(v2,v3,pt)>=-ISECT_EPSILON) &&
(SIDE_OF_LINE(v3,v4,pt)>=-ISECT_EPSILON) &&
(SIDE_OF_LINE(v4,v1,pt)>=-ISECT_EPSILON))
return 1;
else
return 0;
}
/* copied from Geometry.c - todo - move to arithb.c or some other generic place we can reuse */
#define SIDE_OF_LINE(pa,pb,pp) ((pa[0]-pp[0])*(pb[1]-pp[1]))-((pb[0]-pp[0])*(pa[1]-pp[1]))
#define POINT_IN_TRI(p0,p1,p2,p3) ((SIDE_OF_LINE(p1,p2,p0)>=0) && (SIDE_OF_LINE(p2,p3,p0)>=0) && (SIDE_OF_LINE(p3,p1,p0)>=0))
/**
*
* @param min
* @param max
* @param vec
*/
void MinMax3(float *min, float *max, float *vec)
{
if(min[0]>vec[0]) min[0]= vec[0];
@ -3035,6 +3127,11 @@ float Vec2Lenf(float *v1, float *v2)
return (float)sqrt(x*x+y*y);
}
float Vec2Length(float *v)
{
return (float)sqrt(v[0]*v[0] + v[1]*v[1]);
}
void Vec2Mulf(float *v1, float f)
{
v1[0]*= f;
@ -3501,7 +3598,7 @@ void mul_v3_v3m4(float *v1, float *v2, float mat[][4])
test if the line starting at p1 ending at p2 intersects the triangle v0..v2
return non zero if it does
*/
int LineIntersectsTriangle(float p1[3], float p2[3], float v0[3], float v1[3], float v2[3], float *lambda)
int LineIntersectsTriangle(float p1[3], float p2[3], float v0[3], float v1[3], float v2[3], float *lambda, float *uv)
{
float p[3], s[3], d[3], e1[3], e2[3], q[3];
@ -3527,15 +3624,318 @@ int LineIntersectsTriangle(float p1[3], float p2[3], float v0[3], float v1[3], f
v = f * Inpf(d, q);
if ((v < 0.0)||((u + v) > 1.0)) return 0;
if(uv) {
uv[0]= u;
uv[1]= v;
}
return 1;
}
/* Adapted from the paper by Kasper Fauerby */
/* "Improved Collision detection and Response" */
int SweepingSphereIntersectsTriangleUV(float p1[3], float p2[3], float radius, float v0[3], float v1[3], float v2[3], float *lambda, float *ipoint)
{
float e1[3], e2[3], e3[3], point[3], vel[3], /*dist[3],*/ nor[3], temp[3], bv[3];
float a, b, c, d, e, x, y, z, t, t0, t1, radius2=radius*radius;
float elen2,edotv,edotbv,nordotv,vel2;
int embedded_in_plane=0, found_by_sweep=0;
/*
find closest point to p on line through l1,l2
and return lambda, where (0 <= lambda <= 1) when cp is in the line segement l1,l2
*/
VecSubf(e1,v1,v0);
VecSubf(e2,v2,v0);
VecSubf(vel,p2,p1);
/*---test plane of tri---*/
Crossf(nor,e1,e2);
Normalize(nor);
/* flip normal */
if(Inpf(nor,vel)>0.0f) VecMulf(nor,-1.0f);
a=Inpf(p1,nor)-Inpf(v0,nor);
nordotv=Inpf(nor,vel);
if ((nordotv > -0.000001) && (nordotv < 0.000001)) {
if(fabs(a)>=1.0f)
return 0;
else{
embedded_in_plane=1;
t0=0.0f;
t1=1.0f;
}
}
else{
t0=(radius-a)/nordotv;
t1=(-radius-a)/nordotv;
/* make t0<t1 */
if(t0>t1){b=t1; t1=t0; t0=b;}
if(t0>1.0f || t1<0.0f) return 0;
/* clamp to [0,1] */
t0=(t0<0.0f)?0.0f:((t0>1.0f)?1.0:t0);
t1=(t1<0.0f)?0.0f:((t1>1.0f)?1.0:t1);
}
/*---test inside of tri---*/
if(embedded_in_plane==0){
/* plane intersection point */
VecCopyf(point,vel);
VecMulf(point,t0);
VecAddf(point,point,p1);
VecCopyf(temp,nor);
VecMulf(temp,radius);
VecSubf(point,point,temp);
/* is the point in the tri? */
a=Inpf(e1,e1);
b=Inpf(e1,e2);
c=Inpf(e2,e2);
VecSubf(temp,point,v0);
d=Inpf(temp,e1);
e=Inpf(temp,e2);
x=d*c-e*b;
y=e*a-d*b;
z=x+y-(a*c-b*b);
if(( ((unsigned int)z)& ~(((unsigned int)x)|((unsigned int)y)) ) & 0x80000000){
*lambda=t0;
VecCopyf(ipoint,point);
return 1;
}
}
*lambda=1.0f;
/*---test points---*/
a=vel2=Inpf(vel,vel);
/*v0*/
VecSubf(temp,p1,v0);
b=2.0f*Inpf(vel,temp);
c=Inpf(temp,temp)-radius2;
d=b*b-4*a*c;
if(d>=0.0f){
if(d==0.0f)
t=-b/2*a;
else{
z=sqrt(d);
x=(-b-z)*0.5/a;
y=(-b+z)*0.5/a;
t=x<y?x:y;
}
if(t>0.0 && t < *lambda){
*lambda=t;
VecCopyf(ipoint,v0);
found_by_sweep=1;
}
}
/*v1*/
VecSubf(temp,p1,v1);
b=2.0f*Inpf(vel,temp);
c=Inpf(temp,temp)-radius2;
d=b*b-4*a*c;
if(d>=0.0f){
if(d==0.0f)
t=-b/2*a;
else{
z=sqrt(d);
x=(-b-z)*0.5/a;
y=(-b+z)*0.5/a;
t=x<y?x:y;
}
if(t>0.0 && t < *lambda){
*lambda=t;
VecCopyf(ipoint,v1);
found_by_sweep=1;
}
}
/*v2*/
VecSubf(temp,p1,v2);
b=2.0f*Inpf(vel,temp);
c=Inpf(temp,temp)-radius2;
d=b*b-4*a*c;
if(d>=0.0f){
if(d==0.0f)
t=-b/2*a;
else{
z=sqrt(d);
x=(-b-z)*0.5/a;
y=(-b+z)*0.5/a;
t=x<y?x:y;
}
if(t>0.0 && t < *lambda){
*lambda=t;
VecCopyf(ipoint,v2);
found_by_sweep=1;
}
}
/*---test edges---*/
/*e1*/
VecSubf(bv,v0,p1);
elen2 = Inpf(e1,e1);
edotv = Inpf(e1,vel);
edotbv = Inpf(e1,bv);
a=elen2*(-Inpf(vel,vel))+edotv*edotv;
b=2.0f*(elen2*Inpf(vel,bv)-edotv*edotbv);
c=elen2*(radius2-Inpf(bv,bv))+edotbv*edotbv;
d=b*b-4*a*c;
if(d>=0.0f){
if(d==0.0f)
t=-b/2*a;
else{
z=sqrt(d);
x=(-b-z)*0.5/a;
y=(-b+z)*0.5/a;
t=x<y?x:y;
}
e=(edotv*t-edotbv)/elen2;
if((e>=0.0f) && (e<=1.0f)){
if(t>0.0 && t < *lambda){
*lambda=t;
VecCopyf(ipoint,e1);
VecMulf(ipoint,e);
VecAddf(ipoint,ipoint,v0);
found_by_sweep=1;
}
}
}
/*e2*/
/*bv is same*/
elen2 = Inpf(e2,e2);
edotv = Inpf(e2,vel);
edotbv = Inpf(e2,bv);
a=elen2*(-Inpf(vel,vel))+edotv*edotv;
b=2.0f*(elen2*Inpf(vel,bv)-edotv*edotbv);
c=elen2*(radius2-Inpf(bv,bv))+edotbv*edotbv;
d=b*b-4*a*c;
if(d>=0.0f){
if(d==0.0f)
t=-b/2*a;
else{
z=sqrt(d);
x=(-b-z)*0.5/a;
y=(-b+z)*0.5/a;
t=x<y?x:y;
}
e=(edotv*t-edotbv)/elen2;
if((e>=0.0f) && (e<=1.0f)){
if(t>0.0 && t < *lambda){
*lambda=t;
VecCopyf(ipoint,e2);
VecMulf(ipoint,e);
VecAddf(ipoint,ipoint,v0);
found_by_sweep=1;
}
}
}
/*e3*/
VecSubf(e3,v2,v1);
VecSubf(bv,v1,p1);
elen2 = Inpf(e3,e3);
edotv = Inpf(e3,vel);
edotbv = Inpf(e3,bv);
a=elen2*(-Inpf(vel,vel))+edotv*edotv;
b=2.0f*(elen2*Inpf(vel,bv)-edotv*edotbv);
c=elen2*(radius2-Inpf(bv,bv))+edotbv*edotbv;
d=b*b-4*a*c;
if(d>=0.0f){
if(d==0.0f)
t=-b/2*a;
else{
z=sqrt(d);
x=(-b-z)*0.5/a;
y=(-b+z)*0.5/a;
t=x<y?x:y;
}
e=(edotv*t-edotbv)/elen2;
if((e>=0.0f) && (e<=1.0f)){
if(t>0.0 && t < *lambda){
*lambda=t;
VecCopyf(ipoint,e3);
VecMulf(ipoint,e);
VecAddf(ipoint,ipoint,v1);
found_by_sweep=1;
}
}
}
return found_by_sweep;
}
int AxialLineIntersectsTriangle(int axis, float p1[3], float p2[3], float v0[3], float v1[3], float v2[3], float *lambda)
{
float p[3], e1[3], e2[3];
float u, v, f;
int a0=axis, a1=(axis+1)%3, a2=(axis+2)%3;
//return LineIntersectsTriangle(p1,p2,v0,v1,v2,lambda);
///* first a simple bounding box test */
//if(MIN3(v0[a1],v1[a1],v2[a1]) > p1[a1]) return 0;
//if(MIN3(v0[a2],v1[a2],v2[a2]) > p1[a2]) return 0;
//if(MAX3(v0[a1],v1[a1],v2[a1]) < p1[a1]) return 0;
//if(MAX3(v0[a2],v1[a2],v2[a2]) < p1[a2]) return 0;
///* then a full intersection test */
VecSubf(e1,v1,v0);
VecSubf(e2,v2,v0);
VecSubf(p,v0,p1);
f= (e2[a1]*e1[a2]-e2[a2]*e1[a1]);
if ((f > -0.000001) && (f < 0.000001)) return 0;
v= (p[a2]*e1[a1]-p[a1]*e1[a2])/f;
if ((v < 0.0)||(v > 1.0)) return 0;
f= e1[a1];
if((f > -0.000001) && (f < 0.000001)){
f= e1[a2];
if((f > -0.000001) && (f < 0.000001)) return 0;
u= (-p[a2]-v*e2[a2])/f;
}
else
u= (-p[a1]-v*e2[a1])/f;
if ((u < 0.0)||((u + v) > 1.0)) return 0;
*lambda = (p[a0]+u*e1[a0]+v*e2[a0])/(p2[a0]-p1[a0]);
if ((*lambda < 0.0)||(*lambda > 1.0)) return 0;
return 1;
}
int AabbIntersectAabb(float min1[3], float max1[3], float min2[3], float max2[3])
{
return (min1[0]<max2[0] && min1[1]<max2[1] && min1[2]<max2[2] &&
min2[0]<max1[0] && min2[1]<max1[1] && min2[2]<max1[2]);
}
/* find closest point to p on line through l1,l2 and return lambda,
* where (0 <= lambda <= 1) when cp is in the line segement l1,l2
*/
float lambda_cp_line_ex(float p[3], float l1[3], float l2[3], float cp[3])
{
float h[3],u[3],lambda;
@ -3547,6 +3947,7 @@ float lambda_cp_line_ex(float p[3], float l1[3], float l2[3], float cp[3])
cp[2] = l1[2] + u[2] * lambda;
return lambda;
}
/* little sister we only need to know lambda */
float lambda_cp_line(float p[3], float l1[3], float l2[3])
{
@ -3556,7 +3957,156 @@ float lambda_cp_line(float p[3], float l1[3], float l2[3])
return(Inpf(u,h)/Inpf(u,u));
}
/* Similar to LineIntersectsTriangleUV, except it operates on a quad and in 2d, assumes point is in quad */
void PointInQuad2DUV(float v0[2], float v1[2], float v2[2], float v3[2], float pt[2], float *uv)
{
float x0,y0, x1,y1, wtot, v2d[2], w1, w2;
/* used for paralelle lines */
float pt3d[3], l1[3], l2[3], pt_on_line[3];
/* compute 2 edges of the quad intersection point */
if (IsectLLPt2Df(v0[0],v0[1],v1[0],v1[1], v2[0],v2[1],v3[0],v3[1], &x0,&y0) == 1) {
/* the intersection point between the quad-edge intersection and the point in the quad we want the uv's for */
/* should never be paralle !! */
/*printf("\tnot paralelle 1\n");*/
IsectLLPt2Df(pt[0],pt[1],x0,y0, v0[0],v0[1],v3[0],v3[1], &x1,&y1);
/* Get the weights from the new intersection point, to each edge */
v2d[0] = x1-v0[0];
v2d[1] = y1-v0[1];
w1 = Vec2Length(v2d);
v2d[0] = x1-v3[0]; /* some but for the other vert */
v2d[1] = y1-v3[1];
w2 = Vec2Length(v2d);
wtot = w1+w2;
/*w1 = w1/wtot;*/
/*w2 = w2/wtot;*/
uv[0] = w1/wtot;
} else {
/* lines are paralelle, lambda_cp_line_ex is 3d grrr */
/*printf("\tparalelle1\n");*/
pt3d[0] = pt[0];
pt3d[1] = pt[1];
pt3d[2] = l1[2] = l2[2] = 0.0f;
l1[0] = v0[0]; l1[1] = v0[1];
l2[0] = v1[0]; l2[1] = v1[1];
lambda_cp_line_ex(pt3d, l1, l2, pt_on_line);
v2d[0] = pt[0]-pt_on_line[0]; /* same, for the other vert */
v2d[1] = pt[1]-pt_on_line[1];
w1 = Vec2Length(v2d);
l1[0] = v2[0]; l1[1] = v2[1];
l2[0] = v3[0]; l2[1] = v3[1];
lambda_cp_line_ex(pt3d, l1, l2, pt_on_line);
v2d[0] = pt[0]-pt_on_line[0]; /* same, for the other vert */
v2d[1] = pt[1]-pt_on_line[1];
w2 = Vec2Length(v2d);
wtot = w1+w2;
uv[0] = w1/wtot;
}
/* Same as above to calc the uv[1] value, alternate calculation */
if (IsectLLPt2Df(v0[0],v0[1],v3[0],v3[1], v1[0],v1[1],v2[0],v2[1], &x0,&y0) == 1) { /* was v0,v1 v2,v3 now v0,v3 v1,v2*/
/* never paralle if above was not */
/*printf("\tnot paralelle2\n");*/
IsectLLPt2Df(pt[0],pt[1],x0,y0, v0[0],v0[1],v1[0],v1[1], &x1,&y1);/* was v0,v3 now v0,v1*/
v2d[0] = x1-v0[0];
v2d[1] = y1-v0[1];
w1 = Vec2Length(v2d);
v2d[0] = x1-v1[0];
v2d[1] = y1-v1[1];
w2 = Vec2Length(v2d);
wtot = w1+w2;
uv[1] = w1/wtot;
} else {
/* lines are paralelle, lambda_cp_line_ex is 3d grrr */
/*printf("\tparalelle2\n");*/
pt3d[0] = pt[0];
pt3d[1] = pt[1];
pt3d[2] = l1[2] = l2[2] = 0.0f;
l1[0] = v0[0]; l1[1] = v0[1];
l2[0] = v3[0]; l2[1] = v3[1];
lambda_cp_line_ex(pt3d, l1, l2, pt_on_line);
v2d[0] = pt[0]-pt_on_line[0]; /* some but for the other vert */
v2d[1] = pt[1]-pt_on_line[1];
w1 = Vec2Length(v2d);
l1[0] = v1[0]; l1[1] = v1[1];
l2[0] = v2[0]; l2[1] = v2[1];
lambda_cp_line_ex(pt3d, l1, l2, pt_on_line);
v2d[0] = pt[0]-pt_on_line[0]; /* some but for the other vert */
v2d[1] = pt[1]-pt_on_line[1];
w2 = Vec2Length(v2d);
wtot = w1+w2;
uv[1] = w1/wtot;
}
/* may need to flip UV's here */
}
/* same as above but does tri's and quads, tri's are a bit of a hack */
void PointInFace2DUV(int isquad, float v0[2], float v1[2], float v2[2], float v3[2], float pt[2], float *uv)
{
if (isquad) {
PointInQuad2DUV(v0, v1, v2, v3, pt, uv);
}
else {
/* not for quads, use for our abuse of LineIntersectsTriangleUV */
float p1_3d[3], p2_3d[3], v0_3d[3], v1_3d[3], v2_3d[3], lambda;
p1_3d[0] = p2_3d[0] = uv[0];
p1_3d[1] = p2_3d[1] = uv[1];
p1_3d[2] = 1.0f;
p2_3d[2] = -1.0f;
v0_3d[2] = v1_3d[2] = v2_3d[2] = 0.0;
/* generate a new fuv, (this is possibly a non optimal solution,
* since we only need 2d calculation but use 3d func's)
*
* this method makes an imaginary triangle in 2d space using the UV's from the derived mesh face
* Then find new uv coords using the fuv and this face with LineIntersectsTriangleUV.
* This means the new values will be correct in relation to the derived meshes face.
*/
Vec2Copyf(v0_3d, v0);
Vec2Copyf(v1_3d, v1);
Vec2Copyf(v2_3d, v2);
/* Doing this in 3D is not nice */
LineIntersectsTriangle(p1_3d, p2_3d, v0_3d, v1_3d, v2_3d, &lambda, uv);
}
}
/* (x1,v1)(t1=0)------(x2,v2)(t2=1), 0<t<1 --> (x,v)(t) */
void VecfCubicInterpol(float *x1, float *v1, float *x2, float *v2, float t, float *x, float *v)
{
float a[3],b[3];
float t2= t*t;
float t3= t2*t;
/* cubic interpolation */
a[0]= v1[0] + v2[0] + 2*(x1[0] - x2[0]);
a[1]= v1[1] + v2[1] + 2*(x1[1] - x2[1]);
a[2]= v1[2] + v2[2] + 2*(x1[2] - x2[2]);
b[0]= -2*v1[0] - v2[0] - 3*(x1[0] - x2[0]);
b[1]= -2*v1[1] - v2[1] - 3*(x1[1] - x2[1]);
b[2]= -2*v1[2] - v2[2] - 3*(x1[2] - x2[2]);
x[0]= a[0]*t3 + b[0]*t2 + v1[0]*t + x1[0];
x[1]= a[1]*t3 + b[1]*t2 + v1[1]*t + x1[1];
x[2]= a[2]*t3 + b[2]*t2 + v1[2]*t + x1[2];
v[0]= 3*a[0]*t2 + 2*b[0]*t + v1[0];
v[1]= 3*a[1]*t2 + 2*b[1]*t + v1[1];
v[2]= 3*a[2]*t2 + 2*b[2]*t + v1[2];
}
int point_in_slice(float p[3], float v1[3], float l1[3], float l2[3])
{

@ -86,6 +86,7 @@
#include "DNA_oops_types.h"
#include "DNA_object_force.h"
#include "DNA_packedFile_types.h"
#include "DNA_particle_types.h"
#include "DNA_property_types.h"
#include "DNA_text_types.h"
#include "DNA_view3d_types.h"
@ -122,6 +123,7 @@
#include "BKE_global.h" // for G
#include "BKE_group.h"
#include "BKE_image.h"
#include "BKE_key.h" //void set_four_ipo
#include "BKE_lattice.h"
#include "BKE_library.h" // for wich_libbase
#include "BKE_main.h" // for Main
@ -129,6 +131,7 @@
#include "BKE_modifier.h"
#include "BKE_node.h" // for tree type defines
#include "BKE_object.h"
#include "BKE_particle.h"
#include "BKE_property.h" // for get_property
#include "BKE_sca.h" // for init_actuator
#include "BKE_scene.h"
@ -2451,6 +2454,79 @@ static void direct_link_material(FileData *fd, Material *ma)
ma->preview = direct_link_preview_image(fd, ma->preview);
}
/* ************ READ PARTICLE SETTINGS ***************** */
static void lib_link_particlesettings(FileData *fd, Main *main)
{
ParticleSettings *part;
part= main->particle.first;
while(part) {
if(part->id.flag & LIB_NEEDLINK) {
part->ipo= newlibadr_us(fd, part->id.lib, part->ipo);
part->dup_ob = newlibadr(fd, part->id.lib, part->dup_ob);
part->dup_group = newlibadr(fd, part->id.lib, part->dup_group);
part->eff_group = newlibadr(fd, part->id.lib, part->eff_group);
part->bb_ob = newlibadr(fd, part->id.lib, part->bb_ob);
part->id.flag -= LIB_NEEDLINK;
}
part= part->id.next;
}
}
static void direct_link_particlesettings(FileData *fd, ParticleSettings *part)
{
part->pd= newdataadr(fd, part->pd);
}
static void lib_link_particlesystems(FileData *fd, ID *id, ListBase *particles)
{
ParticleSystem *psys;
int a;
for(psys=particles->first; psys; psys=psys->next){
ParticleData *pa;
psys->part = newlibadr_us(fd, id->lib, psys->part);
psys->target_ob = newlibadr(fd, id->lib, psys->target_ob);
psys->keyed_ob = newlibadr(fd, id->lib, psys->keyed_ob);
for(a=0,pa=psys->particles; a<psys->totpart; a++,pa++){
pa->stick_ob=newlibadr(fd, id->lib, pa->stick_ob);
}
}
}
static void direct_link_particlesystems(FileData *fd, ListBase *particles)
{
ParticleSystem *psys;
int a;
for(psys=particles->first; psys; psys=psys->next) {
psys->particles=newdataadr(fd,psys->particles);
if(psys->particles && psys->particles->hair){
ParticleData *pa = psys->particles;
for(a=0; a<psys->totpart; a++, pa++)
pa->hair=newdataadr(fd,pa->hair);
}
psys->child=newdataadr(fd,psys->child);
psys->effectors.first=psys->effectors.last=0;
psys->soft= newdataadr(fd, psys->soft);
if(psys->soft) {
SoftBody *sb = psys->soft;
sb->particles = psys;
sb->bpoint= NULL; // init pointers so it gets rebuilt nicely
sb->bspring= NULL;
sb->scratch= NULL;
}
psys->edit = 0;
psys->pathcache = 0;
psys->childcache = 0;
psys->reactevents.first = psys->reactevents.last = 0;
}
return;
}
/* ************ READ MESH ***************** */
static void lib_link_mtface(FileData *fd, Mesh *me, MTFace *mtface, int totface)
@ -2830,8 +2906,14 @@ static void lib_link_object(FileData *fd, Main *main)
if(ob->fluidsimSettings) {
ob->fluidsimSettings->ipo = newlibadr_us(fd, ob->id.lib, ob->fluidsimSettings->ipo);
}
/* texture field */
if(ob->pd)
if(ob->pd->tex)
ob->pd->tex=newlibadr_us(fd, ob->id.lib, ob->pd->tex);
lib_link_scriptlink(fd, &ob->id, &ob->scriptlink);
lib_link_particlesystems(fd, &ob->id, &ob->particlesystem);
lib_link_modifiers(fd, ob);
}
ob= ob->id.next;
@ -2888,6 +2970,16 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb)
SWITCH_INT(hmd->indexar[a]);
}
}
} else if (md->type==eModifierType_ParticleSystem) {
ParticleSystemModifierData *psmd = (ParticleSystemModifierData*) md;
psmd->dm=0;
psmd->psys=newdataadr(fd, psmd->psys);
psmd->flag|=eParticleSystemFlag_Loaded;
} else if (md->type==eModifierType_Explode) {
ExplodeModifierData *psmd = (ExplodeModifierData*) md;
psmd->facepa=0;
}
else if (md->type==eModifierType_MeshDeform) {
MeshDeformModifierData *mmd = (MeshDeformModifierData*) md;
@ -3014,7 +3106,8 @@ static void direct_link_object(FileData *fd, Object *ob)
sb->bspring= NULL;
sb->scratch= NULL;
/* although not used anymore */
/* still have to be loaded to be compatible with old files */
sb->keys= newdataadr(fd, sb->keys);
test_pointer_array(fd, (void **)&sb->keys);
if(sb->keys) {
@ -3031,6 +3124,9 @@ static void direct_link_object(FileData *fd, Object *ob)
ob->fluidsimSettings->meshBB = NULL;
ob->fluidsimSettings->meshSurfNormals = NULL;
}
link_list(fd, &ob->particlesystem);
direct_link_particlesystems(fd,&ob->particlesystem);
link_list(fd, &ob->prop);
prop= ob->prop.first;
@ -3958,6 +4054,7 @@ static char *dataname(short id_code)
case ID_SO: return "Data from SO";
case ID_NT: return "Data from NT";
case ID_BR: return "Data from BR";
case ID_PA: return "Data from PA";
}
return "Data from Lib Block";
@ -4094,6 +4191,9 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, int flag, ID
case ID_BR:
direct_link_brush(fd, (Brush*)id);
break;
case ID_PA:
direct_link_particlesettings(fd, (ParticleSettings*)id);
break;
}
/*link direct data of ID properties*/
@ -6845,10 +6945,228 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
con->headtail = 1.0f;
}
}
if(ob->soft && ob->soft->keys) {
SoftBody *sb = ob->soft;
int k;
for(k=0; k<sb->totkey; k++) {
if(sb->keys[k])
MEM_freeN(sb->keys[k]);
}
MEM_freeN(sb->keys);
sb->keys = NULL;
sb->totkey = 0;
ob->softflag &= ~OB_SB_BAKESET;
}
}
}
if ((main->versionfile < 245) || (main->versionfile == 245 && main->subversionfile < 7)) {
Object *ob;
bPoseChannel *pchan;
bConstraint *con;
bConstraintTarget *ct;
for(ob = main->object.first; ob; ob= ob->id.next) {
if(ob->pose) {
for(pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) {
for(con=pchan->constraints.first; con; con=con->next) {
if(con->type==CONSTRAINT_TYPE_PYTHON) {
bPythonConstraint *data= (bPythonConstraint *)con->data;
if (data->tar) {
/* version patching needs to be done */
ct= MEM_callocN(sizeof(bConstraintTarget), "PyConTarget");
ct->tar = data->tar;
strcpy(ct->subtarget, data->subtarget);
ct->space = con->tarspace;
BLI_addtail(&data->targets, ct);
data->tarnum++;
/* clear old targets to avoid problems */
data->tar = NULL;
strcpy(data->subtarget, "");
}
}
}
}
}
for(con=ob->constraints.first; con; con=con->next) {
if(con->type==CONSTRAINT_TYPE_PYTHON) {
bPythonConstraint *data= (bPythonConstraint *)con->data;
if (data->tar) {
/* version patching needs to be done */
ct= MEM_callocN(sizeof(bConstraintTarget), "PyConTarget");
ct->tar = data->tar;
strcpy(ct->subtarget, data->subtarget);
ct->space = con->tarspace;
BLI_addtail(&data->targets, ct);
data->tarnum++;
/* clear old targets to avoid problems */
data->tar = NULL;
strcpy(data->subtarget, "");
}
}
}
}
}
if ((main->versionfile < 245) || (main->versionfile == 245 && main->subversionfile < 8)) {
Scene *sce;
Object *ob;
PartEff *paf=0;
for(ob = main->object.first; ob; ob= ob->id.next) {
if(ob->soft && ob->soft->keys) {
SoftBody *sb = ob->soft;
int k;
for(k=0; k<sb->totkey; k++) {
if(sb->keys[k])
MEM_freeN(sb->keys[k]);
}
MEM_freeN(sb->keys);
sb->keys = NULL;
sb->totkey = 0;
ob->softflag &= ~OB_SB_BAKESET;
}
/* convert old particles to new system */
if((paf = give_parteff(ob))) {
ParticleSystem *psys;
ModifierData *md;
ParticleSystemModifierData *psmd;
ParticleSettings *part;
/* create new particle system */
psys = MEM_callocN(sizeof(ParticleSystem), "particle_system");
part = psys->part = psys_new_settings("PSys", main);
/* needed for proper libdata lookup */
oldnewmap_insert(fd->libmap, psys->part, psys->part, 0);
part->id.us--;
psys->totpart=0;
psys->flag=PSYS_ENABLED|PSYS_CURRENT;
BLI_addtail(&ob->particlesystem, psys);
md= modifier_new(eModifierType_ParticleSystem);
sprintf(md->name, "ParticleSystem %i", BLI_countlist(&ob->particlesystem));
psmd= (ParticleSystemModifierData*) md;
psmd->psys=psys;
BLI_addtail(&ob->modifiers, md);
/* convert settings from old particle system */
/* general settings */
part->totpart = paf->totpart;
part->sta = paf->sta;
part->end = paf->end;
part->lifetime = paf->lifetime;
part->randlife = paf->randlife;
psys->seed = paf->seed;
part->disp = paf->disp;
part->omat = paf->mat[0];
part->hair_step = paf->totkey;
part->eff_group = paf->group;
/* physics */
part->normfac = paf->normfac * 25.0f;
part->obfac = paf->obfac;
part->randfac = paf->randfac * 25.0f;
part->dampfac = paf->damp;
VECCOPY(part->acc, paf->force);
/* flags */
if(paf->stype & PAF_VECT) {
if(paf->flag & PAF_STATIC) {
/* new hair lifetime is always 100.0f */
float fac = paf->lifetime / 100.0f;
part->draw_as = PART_DRAW_PATH;
part->type = PART_HAIR;
psys->recalc |= PSYS_RECALC_HAIR;
part->normfac *= fac;
part->randfac *= fac;
}
else {
part->draw_as = PART_DRAW_LINE;
part->draw |= PART_DRAW_VEL_LENGTH;
part->draw_line[1] = 0.04f;
}
}
part->rotmode = PART_ROT_VEL;
part->flag |= (paf->flag & PAF_BSPLINE) ? PART_HAIR_BSPLINE : 0;
part->flag |= (paf->flag & PAF_TRAND) ? PART_TRAND : 0;
part->flag |= (paf->flag & PAF_EDISTR) ? PART_EDISTR : 0;
part->flag |= (paf->flag & PAF_UNBORN) ? PART_UNBORN : 0;
part->flag |= (paf->flag & PAF_DIED) ? PART_DIED : 0;
part->from |= (paf->flag & PAF_FACE) ? PART_FROM_FACE : 0;
part->draw |= (paf->flag & PAF_SHOWE) ? PART_DRAW_EMITTER : 0;
psys->vgroup[PSYS_VG_DENSITY] = paf->vertgroup;
psys->vgroup[PSYS_VG_VEL] = paf->vertgroup_v;
psys->vgroup[PSYS_VG_LENGTH] = paf->vertgroup_v;
/* dupliobjects */
if(ob->transflag & OB_DUPLIVERTS) {
Object *dup = main->object.first;
for(; dup; dup= dup->id.next) {
if(ob == newlibadr(fd, lib, dup->parent)) {
part->dup_ob = dup;
ob->transflag |= OB_DUPLIPARTS;
ob->transflag &= ~OB_DUPLIVERTS;
part->draw_as = PART_DRAW_OB;
}
}
}
free_effects(&ob->effect);
printf("Old particle system converted to new system.\n");
}
}
for(sce= main->scene.first; sce; sce=sce->id.next) {
ParticleEditSettings *pset= &sce->toolsettings->particle;
int a;
if(pset->brush[0].size == 0) {
pset->flag= PE_KEEP_LENGTHS|PE_LOCK_FIRST|PE_DEFLECT_EMITTER;
pset->emitterdist= 0.25f;
pset->totrekey= 5;
pset->totaddkey= 5;
pset->brushtype= PE_BRUSH_NONE;
for(a=0; a<PE_TOT_BRUSH; a++) {
pset->brush[a].strength= 50;
pset->brush[a].size= 50;
pset->brush[a].step= 10;
}
pset->brush[PE_BRUSH_CUT].strength= 100;
}
}
}
/* WATCH IT!!!: pointers from libdata have not been converted yet here! */
/* WATCH IT 2!: Userdef struct init has to be in src/usiblender.c! */
@ -6882,6 +7200,7 @@ static void lib_link_all(FileData *fd, Main *main)
lib_link_screen_sequence_ipos(main);
lib_link_nodetree(fd, main); /* has to be done after scene/materials, this will verify group nodes */
lib_link_brush(fd, main);
lib_link_particlesettings(fd, main);
lib_link_mesh(fd, main); /* as last: tpage images with users at zero */
@ -7433,6 +7752,7 @@ static void expand_scriptlink(FileData *fd, Main *mainvar, ScriptLink *slink)
static void expand_object(FileData *fd, Main *mainvar, Object *ob)
{
ModifierData *md;
ParticleSystem *psys;
bSensor *sens;
bController *cont;
bActuator *act;
@ -7475,6 +7795,9 @@ static void expand_object(FileData *fd, Main *mainvar, Object *ob)
if(ob->proxy_group)
expand_doit(fd, mainvar, ob->proxy_group);
for(psys=ob->particlesystem.first; psys; psys=psys->next)
expand_doit(fd, mainvar, psys->part);
sens= ob->sensors.first;
while(sens) {
for(a=0; a<sens->totlinks; a++) {

@ -132,6 +132,7 @@ Important to know is that 'streaming' has been added to files, for Blender Publi
#include "DNA_object_force.h"
#include "DNA_oops_types.h"
#include "DNA_packedFile_types.h"
#include "DNA_particle_types.h"
#include "DNA_property_types.h"
#include "DNA_scene_types.h"
#include "DNA_sdna_types.h"
@ -526,6 +527,43 @@ static void write_effects(WriteData *wd, ListBase *lb)
}
}
static void write_particlesettings(WriteData *wd, ListBase *idbase)
{
ParticleSettings *part;
part= idbase->first;
while(part) {
if(part->id.us>0 || wd->current) {
/* write LibData */
writestruct(wd, ID_PA, "ParticleSettings", 1, part);
writestruct(wd, DATA, "PartDeflect", 1, part->pd);
}
part= part->id.next;
}
}
static void write_particlesystems(WriteData *wd, ListBase *particles)
{
ParticleSystem *psys= particles->first;
int a;
for(; psys; psys=psys->next) {
writestruct(wd, DATA, "ParticleSystem", 1, psys);
if(psys->particles) {
writestruct(wd, DATA, "ParticleData", psys->totpart ,psys->particles);
if(psys->particles->hair) {
ParticleData *pa = psys->particles;
for(a=0; a<psys->totpart; a++, pa++)
writedata(wd, DATA, MEM_allocN_len(pa->hair),pa->hair);
}
}
if(psys->child) writestruct(wd, DATA, "ChildParticle", psys->totchild ,psys->child);
writestruct(wd, DATA, "SoftBody", 1, psys->soft);
}
}
static void write_properties(WriteData *wd, ListBase *lb)
{
bProperty *prop;
@ -803,7 +841,6 @@ static void write_modifiers(WriteData *wd, ListBase *modbase)
static void write_objects(WriteData *wd, ListBase *idbase)
{
Object *ob;
int a;
ob= idbase->first;
while(ob) {
@ -839,17 +876,9 @@ static void write_objects(WriteData *wd, ListBase *idbase)
writestruct(wd, DATA, "PartDeflect", 1, ob->pd);
writestruct(wd, DATA, "SoftBody", 1, ob->soft);
if(ob->soft) {
SoftBody *sb= ob->soft;
if(sb->keys) {
writedata(wd, DATA, sizeof(void *)*sb->totkey, sb->keys);
for(a=0; a<sb->totkey; a++) {
writestruct(wd, DATA, "SBVertex", sb->totpoint, sb->keys[a]);
}
}
}
writestruct(wd, DATA, "FluidsimSettings", 1, ob->fluidsimSettings); // NT
write_particlesystems(wd, &ob->particlesystem);
write_modifiers(wd, &ob->modifiers);
}
ob= ob->id.next;
@ -1909,6 +1938,7 @@ static int write_file_handle(int handle, MemFile *compare, MemFile *current, int
write_materials(wd, &G.main->mat);
write_textures (wd, &G.main->tex);
write_meshs (wd, &G.main->mesh);
write_particlesettings(wd, &G.main->particle);
write_nodetrees(wd, &G.main->nodetree);
write_brushes (wd, &G.main->brush);
if(current==NULL)

@ -65,6 +65,8 @@ void exit_editmode(int flag);
void check_editmode(int type);
void enter_editmode(int wc);
void exit_paint_modes(void);
void docenter(int centermode);
void docenter_new(void);
void docenter_cursor(void);

@ -83,6 +83,7 @@ extern void validate_editbonebutton_cb(void *bonev, void *namev);
#define TAB_OBJECT_OBJECT 0
#define TAB_OBJECT_PHYSICS 1
#define TAB_OBJECT_PARTICLE 2
#define TAB_SCENE_RENDER 0
#define TAB_SCENE_WORLD 1

@ -0,0 +1,92 @@
/* BIF_editparticle.h
*
*
* $Id: BIF_editparticle.h $
*
* ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
*
* 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. The Blender
* Foundation also sells licenses for use in proprietary software under
* the Blender License. See http://www.blender.org/BL/ for information
* about this.
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The Original Code is Copyright (C) 2007 by Janne Karhu.
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): none yet.
*
* ***** END GPL/BL DUAL LICENSE BLOCK *****
*/
#ifndef BIF_EDITPARTICLE_H
#define BIF_EDITPARTICLE_H
struct Object;
struct ParticleSystem;
struct ParticleEditSettings;
/* particle edit mode */
void PE_set_particle_edit(void);
void PE_create_particle_edit(struct Object *ob, struct ParticleSystem *psys);
void PE_free_particle_edit(struct ParticleSystem *psys);
void PE_change_act(void *ob_v, void *act_v);
/* access */
struct ParticleSystem *PE_get_current(struct Object *ob);
short PE_get_current_num(struct Object *ob);
int PE_minmax(float *min, float *max);
void PE_get_colors(char sel[4], char nosel[4]);
struct ParticleEditSettings *PE_settings(void);
/* update calls */
void PE_hide_keys_time(struct ParticleSystem *psys, float cfra);
void PE_update_object(struct Object *ob, int useflag);
void PE_update_selection(struct Object *ob);
void PE_recalc_world_cos(struct Object *ob, struct ParticleSystem *psys);
/* selection tools */
void PE_select_root(void);
void PE_select_tip(void);
void PE_deselectall(void);
void PE_select_linked(void);
void PE_select_less(void);
void PE_select_more(void);
void PE_mouse_particles(void);
void PE_borderselect(void);
void PE_selectionCB(short selecting, struct Object *editobj, short *mval, float rad);
void PE_do_lasso_select(short mcords[][2], short moves, short select);
/* tools */
void PE_hide(int mode);
void PE_rekey(void);
void PE_subdivide(void);
int PE_brush_particles(void);
void PE_delete_particle(void);
void PE_remove_doubles(void);
void PE_mirror_x(int tagged);
/* undo */
void PE_undo_push(char *str);
void PE_undo_step(int step);
void PE_undo(void);
void PE_redo(void);
void PE_undo_menu(void);
#endif

@ -39,6 +39,7 @@ struct Camera;
struct View3D;
void arrows_move_cursor(unsigned short event);
int lasso_inside(short mcords[][2], short moves, short sx, short sy);
void borderselect(void);
void circle_select(void);
void deselectall(void);

@ -45,6 +45,7 @@ extern void objects_bake_render(short event);
extern long mesh_octree_table(struct Object *ob, float *co, char mode);
extern int mesh_get_x_mirror_vert(struct Object *ob, int index);
extern struct EditVert *editmesh_get_x_mirror_vert(struct Object *ob, float *co);
extern int *mesh_get_x_mirror_faces(struct Object *ob);
#endif

@ -66,7 +66,7 @@ typedef enum {
ICON_ORTHO,
ICON_PERSP,
ICON_CAMERA,
ICON_EFFECTS,
ICON_PARTICLES,
ICON_BBOX,
ICON_WIRE,
ICON_SOLID,
@ -268,7 +268,7 @@ typedef enum {
ICON_EYEDROPPER,
ICON_WINDOW_WINDOW,
ICON_PANEL_CLOSE,
ICON_BLANK35,
ICON_PHYSICS,
ICON_BLANK36,
ICON_BLANK37,
ICON_BLANK38,

@ -59,6 +59,7 @@
#define TFM_TIME_SLIDE 20
#define TFM_TIME_SCALE 21
#define TFM_TIME_EXTEND 22
#define TFM_BAKE_TIME 23
/* TRANSFORM CONTEXTS */
#define CTX_NONE 0

@ -60,6 +60,7 @@ char *getname_la_ei(int nr);
char *getname_cam_ei(int nr);
char *getname_snd_ei(int nr);
char *getname_fluidsim_ei(int nr);
char *getname_part_ei(int nr);
char *getname_ipocurve(struct IpoCurve *icu, struct Object *ob);
int geticon_ipo_blocktype(short blocktype);

@ -232,6 +232,9 @@
#define B_MAN_TRANS 161
#define B_MAN_ROT 162
#define B_MAN_SCALE 163
#define B_SEL_PATH 166
#define B_SEL_POINT 167
#define B_SEL_END 168
/* IPO: 200 */
#define B_IPOHOME 201

@ -68,6 +68,7 @@ extern void do_soundbuts(unsigned short event);
/* object */
extern void object_panels(void);
extern void physics_panels(void);
extern void particle_panels(void);
extern void do_object_panels(unsigned short event);
extern void do_constraintbuts(unsigned short event);
extern void object_panel_constraint(char *context);
@ -102,6 +103,7 @@ extern void do_cambuts(unsigned short event);
extern void do_armbuts(unsigned short event);
extern void do_uvcalculationbuts(unsigned short event);
extern void weight_paint_buttons(struct uiBlock *);
extern void particle_edit_buttons(struct uiBlock *);
extern char *get_vertexgroup_menustr(struct Object *ob); // used in object buttons
@ -212,6 +214,8 @@ void curvemap_buttons(struct uiBlock *block, struct CurveMapping *cumap, char la
/* world buttons: buttons-preview update, and redraw 3dview */
#define B_WORLDPRV2 1224
#define B_MAT_PARTICLE 1225
/* *********************** */
#define B_TEXBUTS 1400
@ -282,6 +286,8 @@ void curvemap_buttons(struct uiBlock *block, struct CurveMapping *cumap, char la
#define B_GROUP_RELINK 1460
#define B_OBJECT_IPOFLAG 1461
#define B_BAKEABLE_CHANGE 1470
/* *********************** */
#define B_WORLDBUTS 1600
@ -578,6 +584,14 @@ void curvemap_buttons(struct uiBlock *block, struct CurveMapping *cumap, char la
/* Sculptmode */
#define B_SCULPT_TEXBROWSE 2860
/* Particles */
#define B_BAKE_OLENGTH 2870
#define B_BAKE_APPLY_AV 2871
#define B_BAKE_KEYTIME 2872
#define B_BAKE_AV_CHANGE 2873
#define B_BAKE_REDRAWEDIT 2874
#define B_BAKE_RECACHE 2875
/* *********************** */
#define B_RADIOBUTS 3000
@ -700,6 +714,26 @@ enum {
#define B_FIELD_CHANGE 3415
#define B_PAF_SET_VG 3416
#define B_PAF_SET_VG1 3417
#define B_PARTBROWSE 3418
#define B_PARTDELETE 3419
#define B_PARTALONE 3420
#define B_PARTLOCAL 3421
#define B_PARTAUTONAME 3422
#define B_PART_ALLOC 3423
#define B_PART_DISTR 3424
#define B_PART_INIT 3425
#define B_PART_RECALC 3426
#define B_PART_REDRAW 3427
#define B_PARTTYPE 3428
#define B_PARTACT 3429
#define B_PARTTARGET 3430
#define B_PART_ALLOC_CHILD 3431
#define B_PART_DISTR_CHILD 3432
#define B_PART_INIT_CHILD 3433
#define B_PART_RECALC_CHILD 3434
#define B_PART_EDITABLE 3435
#define B_PART_REKEY 3436
#define B_MODIFIER_BUTS 3600

@ -270,6 +270,8 @@ typedef struct TransInfo {
#endif
#define TD_TIMEONLY 128
#define TD_NOCENTER 256
#define TD_NO_EXT 512 /* ext abused for particle key timing */
#define TD_SKIP 1024 /* don't transform this data */
/* transsnap->status */
#define SNAP_ON 1
@ -350,10 +352,14 @@ int TimeSlide(TransInfo *t, short mval[2]);
void initTimeScale(TransInfo *t);
int TimeScale(TransInfo *t, short mval[2]);
void initBakeTime(TransInfo *t);
int BakeTime(TransInfo *t, short mval[2]);
/*********************** transform_conversions.c ********** */
struct ListBase;
void flushTransIpoData(TransInfo *t);
void flushTransUVs(TransInfo *t);
void flushTransParticles(TransInfo *t);
int clipUVTransform(TransInfo *t, float *vec, int resize);
/*********************** exported from transform_manipulator.c ********** */

@ -183,6 +183,7 @@ typedef struct PreviewImage {
#define ID_SCRIPT MAKE_ID2('P', 'Y')
#define ID_NT MAKE_ID2('N', 'T')
#define ID_BR MAKE_ID2('B', 'R')
#define ID_PA MAKE_ID2('P', 'A')
/* NOTE! Fake IDs, needed for g.sipo->blocktype or outliner */
#define ID_SEQ MAKE_ID2('S', 'Q')

@ -67,7 +67,8 @@ typedef struct CustomData {
#define CD_PROP_FLT 10
#define CD_PROP_INT 11
#define CD_PROP_STR 12
#define CD_NUMTYPES 13
#define CD_ORIGSPACE 13 /* for modifier stack face location mapping */
#define CD_NUMTYPES 14
/* Bits for CustomDataMask */
#define CD_MASK_MVERT (1 << CD_MVERT)
@ -83,6 +84,7 @@ typedef struct CustomData {
#define CD_MASK_PROP_FLT (1 << CD_PROP_FLT)
#define CD_MASK_PROP_INT (1 << CD_PROP_INT)
#define CD_MASK_PROP_STR (1 << CD_PROP_STR)
#define CD_MASK_ORIGSPACE (1 << CD_ORIGSPACE)
/* CustomData.flag */

@ -69,8 +69,8 @@ typedef short IPO_Channel;
/* ******************** */
#define OB_TOTIPO 29
#define OB_TOTNAM 29
#define OB_TOTIPO 30
#define OB_TOTNAM 30
#define OB_LOC_X 1
#define OB_LOC_Y 2
@ -107,6 +107,7 @@ typedef short IPO_Channel;
#define OB_PD_SDAMP 27
#define OB_PD_RDAMP 28
#define OB_PD_PERM 29
#define OB_PD_FMAXD 30
/* exception: driver channel, for bone driver only */
#define OB_ROT_DIFF 100
@ -354,6 +355,35 @@ typedef short IPO_Channel;
#define FLUIDSIM_ACTIVE 9
/* ******************** */
/* particle ipos */
#define PART_TOTIPO 19
#define PART_TOTNAM 19
#define PART_EMIT_FREQ 1
#define PART_EMIT_LIFE 2
#define PART_EMIT_VEL 3
#define PART_EMIT_AVE 4
#define PART_EMIT_SIZE 5
#define PART_AVE 6
#define PART_SIZE 7
#define PART_DRAG 8
#define PART_BROWN 9
#define PART_DAMP 10
#define PART_LENGTH 11
#define PART_CLUMP 12
#define PART_GRAV_X 13
#define PART_GRAV_Y 14
#define PART_GRAV_Z 15
#define PART_KINK_AMP 16
#define PART_KINK_FREQ 17
#define PART_KINK_SHAPE 18
#define PART_BB_TILT 19
/* these are IpoCurve specific */
/* **************** IPO ********************* */

@ -85,6 +85,7 @@ typedef struct Material {
short flarec, starc, linec, ringc;
float hasize, flaresize, subsize, flareboost;
float strand_sta, strand_end, strand_ease;
char strand_uvname[32];
float sbias; /* shadow bias */
float shad_alpha, padf; /* in use for irregular shadowbuffer */
@ -189,8 +190,9 @@ typedef struct Material {
#define MA_NORMAP_TANG 0x8000000
#define MA_GROUP_NOLAY 0x10000000
#define MA_FACETEXTURE_ALPHA 0x20000000
#define MA_STR_B_UNITS 0x40000000
#define MA_MODE_MASK 0x1fffffff /* all valid mode bits */
#define MA_MODE_MASK 0x4fffffff /* all valid mode bits */
/* ray mirror fadeout */
#define MA_RAYMIR_FADETOSKY 0
@ -274,6 +276,30 @@ typedef struct Material {
#define MAP_WARP 8192
#define MAP_LAYER 16384
/* mapto for halo */
//#define MAP_HA_COL 1
//#define MAP_HA_ALPHA 128
//#define MAP_HA_HAR 256
//#define MAP_HA_SIZE 2
//#define MAP_HA_ADD 64
/* pmapto */
/* init */
#define MAP_PA_INIT 31
#define MAP_PA_TIME 1
#define MAP_PA_LIFE 2
#define MAP_PA_DENS 4
#define MAP_PA_SIZE 8
#define MAP_PA_LENGTH 16
/* reset */
#define MAP_PA_IVEL 32
/* physics */
#define MAP_PA_PVEL 64
/* path cache */
#define MAP_PA_CACHE 384
#define MAP_PA_CLUMP 128
#define MAP_PA_KINK 256
/* pr_type */
#define MA_FLAT 0
#define MA_SPHERE 1

@ -99,6 +99,9 @@ typedef struct MStringProperty{
char s[256];
} MStringProperty;
typedef struct OrigSpaceFace {
float uv[4][2];
} OrigSpaceFace;
/* Multiresolution modeling */
typedef struct MultiresCol {

@ -29,6 +29,9 @@ typedef enum ModifierType {
eModifierType_Smooth,
eModifierType_Cast,
eModifierType_MeshDeform,
eModifierType_ParticleSystem,
eModifierType_ParticleInstance,
eModifierType_Explode,
NUM_MODIFIER_TYPES
} ModifierType;
@ -385,4 +388,51 @@ typedef struct MeshDeformModifierData {
float bindmat[4][4]; /* matrix of cage at binding time */
} MeshDeformModifierData;
typedef enum {
eParticleSystemFlag_Loaded = (1<<0),
eParticleSystemFlag_Pars = (1<<1),
eParticleSystemFlag_FromCurve = (1<<2),
eParticleSystemFlag_DM_changed = (1<<3),
eParticleSystemFlag_Disabled = (1<<4),
eParticleSystemFlag_psys_updated = (1<<5),
} ParticleSystemModifierFlag;
typedef struct ParticleSystemModifierData {
ModifierData modifier;
struct ParticleSystem *psys;
struct DerivedMesh *dm;
short flag, rt[3];
} ParticleSystemModifierData;
typedef enum {
eParticleInstanceFlag_Parents = (1<<0),
eParticleInstanceFlag_Children = (1<<1),
eParticleInstanceFlag_Path = (1<<2),
eParticleInstanceFlag_Unborn = (1<<3),
eParticleInstanceFlag_Alive = (1<<4),
eParticleInstanceFlag_Dead = (1<<5),
} ParticleInstanceModifierFlag;
typedef struct ParticleInstanceModifierData {
ModifierData modifier;
struct Object *ob;
short psys, flag, rt[2];
} ParticleInstanceModifierData;
typedef enum {
eExplodeFlag_CalcFaces = (1<<0),
//eExplodeFlag_PaSize = (1<<1),
eExplodeFlag_EdgeSplit = (1<<2),
eExplodeFlag_Unborn = (1<<3),
eExplodeFlag_Alive = (1<<4),
eExplodeFlag_Dead = (1<<5),
} ExplodeModifierFlag;
typedef struct ExplodeModifierData {
ModifierData modifier;
int *facepa;
short flag, vgroup;
float protect;
} ExplodeModifierData;
#endif

@ -41,19 +41,35 @@ typedef struct PartDeflect {
short deflect; /* Deflection flag - does mesh deflect particles*/
short forcefield; /* Force field type, do the vertices attract / repel particles ? */
short flag; /* general settings flag */
short pad;
short falloff; /* fall-off type*/
float pdef_damp; /* Damping factor for particle deflection */
float pdef_rdamp; /* Random element of damping for deflection */
float pdef_perm; /* Chance of particle passing through mesh */
float pdef_frict; /* Friction factor for particle deflection */
float pdef_rfrict; /* Random element of friction for deflection */
float f_strength; /* The strength of the force (+ or - ) */
float f_power; /* The power law - real gravitation is 2 (square) */
float f_dist;
float f_damp; /* The dampening factor, currently only for harmonic force */
float maxdist; /* if indicated, use this maximum */
float mindist; /* if indicated, use this minimum */
float maxrad; /* radial versions of above */
float minrad;
float f_power_r; /* radial fall-off power*/
float pdef_sbdamp; /* Damping factor for softbody deflection */
float pdef_sbift; /* inner face thickness for softbody deflection */
float pdef_sboft; /* outer face thickness for softbody deflection */
/* variables for guide curve */
float clump_fac, clump_pow;
float kink_freq, kink_shape, kink_amp, free_end;
float tex_nabla;
short tex_mode, kink, kink_axis, rt2;
struct Tex *tex; /* Texture of the texture effector */
} PartDeflect;
@ -62,6 +78,8 @@ typedef struct SBVertex {
} SBVertex;
typedef struct SoftBody {
struct ParticleSystem *particles; /* particlesystem softbody */
/* dynamic data */
int totpoint, totspring;
struct BodyPoint *bpoint; /* not saved in file */
@ -96,8 +114,10 @@ typedef struct SoftBody {
int interval;
short local, solverflags; /* local==1: use local coords for baking */
/* -- these must be kept for backwards compatibility -- */
SBVertex **keys; /* array of size totpointkey */
int totpointkey, totkey; /* if totpointkey != totpoint or totkey!- (efra-sfra)/interval -> free keys */
/* ---------------------------------------------------- */
float secondspring;
/* self collision*/
@ -122,11 +142,36 @@ typedef struct SoftBody {
#define PFIELD_MAGNET 3
#define PFIELD_WIND 4
#define PFIELD_GUIDE 5
#define PFIELD_TEXTURE 6
#define PFIELD_HARMONIC 7
#define PFIELD_NUCLEAR 8
#define PFIELD_MDIPOLE 9
/* pd->flag: various settings */
#define PFIELD_USEMAX 1
#define PDEFLE_DEFORM 2
#define PFIELD_GUIDE_PATH_ADD 4
#define PFIELD_PLANAR 8
#define PDEFLE_KILL_PART 16
#define PFIELD_POSZ 32
#define PFIELD_TEX_OBJECT 64
#define PFIELD_TEX_2D 128
#define PFIELD_USEMIN 256
#define PFIELD_USEMAXR 512
#define PFIELD_USEMINR 1024
/* pd->falloff */
#define PFIELD_FALL_SPHERE 0
#define PFIELD_FALL_TUBE 1
#define PFIELD_FALL_CONE 2
//reserved for near future
//#define PFIELD_FALL_INSIDE 3
/* pd->tex_mode */
#define PFIELD_TEX_RGB 0
#define PFIELD_TEX_GRAD 1
#define PFIELD_TEX_CURL 2
/* ob->softflag */
#define OB_SB_ENABLE 1
@ -142,6 +187,7 @@ typedef struct SoftBody {
#define OB_SB_FACECOLL 1024
#define OB_SB_EDGECOLL 2048
#define OB_SB_COLLFINAL 4096
#define OB_SB_PROTECT_CACHE 8192
/* sb->solverflags */
#define SBSO_MONITOR 1

@ -54,6 +54,7 @@ struct bConstraintChannel;
struct PartDeflect;
struct SoftBody;
struct FluidsimSettings;
struct ParticleSystem;
struct DerivedMesh;
typedef struct bDeformGroup {
@ -181,6 +182,7 @@ typedef struct Object {
ListBase constraints;
ListBase nlastrips;
ListBase hooks;
ListBase particlesystem; /* particle systems */
struct PartDeflect *pd; /* particle deflector/attractor/collision data */
struct SoftBody *soft; /* if exists, saved in file */
@ -195,7 +197,7 @@ typedef struct Object {
short recalco, pad4; /* recalco for temp storage of ob->recalc, bad design warning */
struct FluidsimSettings *fluidsimSettings; /* if fluidsim enabled, store additional settings */
struct DerivedMesh *derivedDeform, *derivedFinal;
int lastDataMask; /* the custom data layer mask that was last used to calculate derivedDeform and derivedFinal */
int pad;
@ -266,7 +268,7 @@ extern Object workob;
#define OB_OFFS_LOCAL 1
#define OB_QUAT 2
#define OB_NEG_SCALE 4
#define OB_DUPLI (8+16+256+512)
#define OB_DUPLI (8+16+256+512+2048)
#define OB_DUPLIFRAMES 8
#define OB_DUPLIVERTS 16
#define OB_DUPLIROT 32
@ -275,6 +277,7 @@ extern Object workob;
#define OB_DUPLIGROUP 256
#define OB_DUPLIFACES 512
#define OB_DUPLIFACES_SCALE 1024
#define OB_DUPLIPARTS 2048
/* (short) ipoflag */
#define OB_DRAWKEY 1

@ -0,0 +1,432 @@
/* DNA_particle_types.h
*
*
* $Id: DNA_particle_types.h $
*
* ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
*
* 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. The Blender
* Foundation also sells licenses for use in proprietary software under
* the Blender License. See http://www.blender.org/BL/ for information
* about this.
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The Original Code is Copyright (C) 2007 by Janne Karhu.
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): none yet.
*
* ***** END GPL/BL DUAL LICENSE BLOCK *****
*/
#ifndef DNA_PARTICLE_TYPES_H
#define DNA_PARTICLE_TYPES_H
#include "DNA_ID.h"
typedef struct HairKey {
float co[3]; /* location of hair vertex */
float time; /* time along hair, default 0-100 */
float weight; /* softbody weight */
short editflag; /* saved particled edit mode flags */
short pad;
} HairKey;
typedef struct ParticleKey { /* when changed update size of struct to copy_particleKey()!! */
float co[3]; /* location */
float vel[3]; /* velocity */
float rot[4]; /* rotation quaternion */
float ave[3]; /* angular velocity */
float time; /* when this key happens */
} ParticleKey;
/* Child particles are created around or between parent particles */
typedef struct ChildParticle {
int num, parent; /* num is face index on the final derived mesh */
int pa[4]; /* nearest particles to the child, used for the interpolation */
float w[4]; /* interpolation weights for the above particles */
float fuv[4], foffset; /* face vertex weights and offset */
float rand[3];
} ChildParticle;
/* Everything that's non dynamic for a particle: */
typedef struct ParticleData {
struct Object *stick_ob;/* object that particle sticks to when dead */
ParticleKey state; /* normally current global coordinates or */
/* in sticky object space if dead & sticky */
HairKey *hair; /* hair vertices */
ParticleKey *keys; /* keyed states */
float i_rot[4],r_rot[4];/* initial & random values (i_rot should be removed as it's not used anymore)*/
float r_ave[3],r_ve[3];
float fuv[4], foffset; /* coordinates on face/edge number "num" and depth along*/
/* face normal for volume emission */
float time, lifetime; /* dietime is not nescessarily time+lifetime as */
float dietime; /* particles can die unnaturally (collision) */
float bank; /* banking angle for boids */
float size, sizemul; /* size and multiplier so that we can update size when ever */
int num; /* index to vert/edge/face */
int num_dmcache; /* index to derived mesh data (face) to avoid slow lookups */
int pad;
int totkey;
int bpi; /* softbody body point start index */
short flag;
short alive; /* the life state of a particle */
short loop; /* how many times particle life has looped */
short rt2;
} ParticleData;
typedef struct ParticleSettings {
ID id;
int flag;
short type, from, distr;
/* physics modes */
short phystype, rotmode, avemode, reactevent;
short draw, draw_as, draw_size, childtype;
/* number of path segments, power of 2 except */
short draw_step, ren_step;
short hair_step, keys_step;
/* adaptive path rendering */
short adapt_angle, adapt_pix;
short disp, omat, interpolation, rotfrom, integrator;
short kink, kink_axis, nbetween, boidneighbours;
/* billboards */
short bb_align, bb_uv_split, bb_anim, bb_split_offset;
float bb_tilt, bb_rand_tilt, bb_offset[2];
/* general values */
float sta, end, lifetime, randlife;
float timetweak, jitfac, keyed_time;
int totpart, userjit, grid_res;
/* initial velocity factors */
float normfac, obfac, randfac, partfac, tanfac, tanphase, reactfac;
float rotfac, avefac, phasefac;
/* physical properties */
float mass, size, randsize, reactshape;
/* global physical properties */
float acc[3], dragfac, brownfac, dampfac;
/* length */
float length, abslength, randlength;
/* children */
int child_nbr;
float parents, childsize, childrandsize;
float childrad, childflat, childspread;
/* clumping */
float clumpfac, clumppow;
/* kink */
float kink_amp, kink_freq, kink_shape;
/* rough */
float rough1, rough1_size;
float rough2, rough2_size, rough2_thres;
float rough_end, rough_end_shape;
/* branching */
float branch_thres;
/* drawing stuff */
float draw_line[2];
/* boids */
float max_vel, max_lat_acc, max_tan_acc;
float average_vel, banking, max_bank, groundz;
float boidfac[8];
char boidrule[8];
struct Group *dup_group;
struct Group *eff_group;
struct Object *dup_ob;
struct Object *bb_ob;
struct Ipo *ipo;
struct PartDeflect *pd;
} ParticleSettings;
typedef struct ParticleSystem{
struct ParticleSystem *next, *prev;
ParticleSettings *part;
ParticleData *particles;
ChildParticle *child;
struct ParticleEdit *edit;
struct ParticleCacheKey **pathcache;
struct ParticleCacheKey **childcache;
struct SoftBody *soft;
struct Object *target_ob;
struct Object *keyed_ob;
struct Object *lattice;
struct ListBase effectors, reactevents;
float imat[4][4]; /* used for duplicators */
float cfra;
int seed;
int flag, totpart, totchild, totcached, totchildcache, rt;
short recalc, target_psys, keyed_psys, totkeyed, softflag, bakespace;
char bb_uvname[3][32];
/* if you change these remember to update array lengths to PSYS_TOT_VG! */
short vgroup[11], vg_neg, rt3[2];
}ParticleSystem;
/* general particle maximums */
/* no special why's, just seem reasonable */
/* changing these (atleast upwards) should not cause any major problems */
#define MAX_PARTS 100000 /* real particles/system */
#define MAX_PART_CHILDREN 1000 /* child particles/real particles */
#define MAX_BOIDNEIGHBOURS 10 /* neigbours considered/boid */
/* part->type */
/* hair is allways baked static in object/geometry space */
/* other types (normal particles) are in global space and not static baked */
#define PART_EMITTER 0
#define PART_REACTOR 1
#define PART_HAIR 2
/* part->flag */
#define PART_REACT_STA_END 1
#define PART_REACT_MULTIPLE 2
#define PART_LOOP 4
#define PART_LOOP_INSTANT 8
#define PART_HAIR_GEOMETRY 16
#define PART_UNBORN 32 /*show unborn particles*/
#define PART_DIED 64 /*show died particles*/
#define PART_TRAND 128
#define PART_EDISTR 256 /* particle/face from face areas */
#define PART_STICKY 512 /*collided particles can stick to collider*/
#define PART_DIE_ON_COL (1<<12)
#define PART_SIZE_DEFL (1<<13) /* swept sphere deflections */
#define PART_ROT_DYN (1<<14) /* dynamic rotation */
#define PART_SIZEMASS (1<<16)
#define PART_ABS_LENGTH (1<<15)
#define PART_ABS_TIME (1<<17)
#define PART_GLOB_TIME (1<<18)
#define PART_BOIDS_2D (1<<19)
#define PART_BRANCHING (1<<20)
#define PART_ANIM_BRANCHING (1<<21)
#define PART_SYMM_BRANCHING (1<<24)
#define PART_HAIR_BSPLINE 1024
#define PART_GRID_INVERT (1<<26)
#define PART_CHILD_SEAMS (1<<28)
#define PART_CHILD_RENDER (1<<29)
#define PART_CHILD_GUIDE (1<<30)
/* part->rotfrom */
#define PART_ROT_KEYS 0 /* interpolate directly from keys */
#define PART_ROT_ZINCR 1 /* same as zdir but done incrementally from previous position */
#define PART_ROT_IINCR 2 /* same as idir but done incrementally from previous position */
/* part->from */
#define PART_FROM_VERT 0
#define PART_FROM_FACE 1
#define PART_FROM_VOLUME 2
#define PART_FROM_PARTICLE 3
#define PART_FROM_CHILD 4
/* part->distr */
#define PART_DISTR_JIT 0
#define PART_DISTR_RAND 1
#define PART_DISTR_GRID 2
/* part->phystype */
#define PART_PHYS_NO 0
#define PART_PHYS_NEWTON 1
#define PART_PHYS_KEYED 2
#define PART_PHYS_BOIDS 3
/* part->kink */
#define PART_KINK_NO 0
#define PART_KINK_CURL 1
#define PART_KINK_RADIAL 2
#define PART_KINK_WAVE 3
#define PART_KINK_BRAID 4
#define PART_KINK_ROT 5
#define PART_KINK_ROLL 6
/* part->draw */
#define PART_DRAW_VEL 1
#define PART_DRAW_ANG 2
#define PART_DRAW_SIZE 4
#define PART_DRAW_EMITTER 8 /* render emitter also */
#define PART_DRAW_KEYS 16
#define PART_DRAW_ADAPT 32
#define PART_DRAW_COS 64
#define PART_DRAW_BB_LOCK 128
#define PART_DRAW_PARENT 256
#define PART_DRAW_NUM 512
#define PART_DRAW_RAND_GR 1024
#define PART_DRAW_REN_ADAPT 2048
#define PART_DRAW_VEL_LENGTH (1<<12)
#define PART_DRAW_MAT_COL (1<<13)
#define PART_DRAW_WHOLE_GR (1<<14)
/* part->bb_align */
#define PART_BB_X 0
#define PART_BB_Y 1
#define PART_BB_Z 2
#define PART_BB_VIEW 3
#define PART_BB_VEL 4
/* part->bb_anim */
#define PART_BB_ANIM_NONE 0
#define PART_BB_ANIM_TIME 1
#define PART_BB_ANIM_ANGLE 2
#define PART_BB_ANIM_OFF_TIME 3
#define PART_BB_ANIM_OFF_ANGLE 4
/* part->bb_split_offset */
#define PART_BB_OFF_NONE 0
#define PART_BB_OFF_LINEAR 1
#define PART_BB_OFF_RANDOM 2
/* part->draw as */
#define PART_DRAW_NOT 0
#define PART_DRAW_DOT 1
#define PART_DRAW_CIRC 2
#define PART_DRAW_CROSS 3
#define PART_DRAW_AXIS 4
#define PART_DRAW_LINE 5
#define PART_DRAW_PATH 6
#define PART_DRAW_OB 7
#define PART_DRAW_GR 8
#define PART_DRAW_BB 9
/* part->integrator */
#define PART_INT_EULER 0
#define PART_INT_MIDPOINT 1
#define PART_INT_RK4 2
/* part->rotmode */
#define PART_ROT_NOR 1
#define PART_ROT_VEL 2
#define PART_ROT_RAND 3
/* part->avemode */
#define PART_AVE_SPIN 1
#define PART_AVE_RAND 2
#define PART_AVE_VEL 3
/* part->reactevent */
#define PART_EVENT_DEATH 0
#define PART_EVENT_COLLIDE 1
#define PART_EVENT_NEAR 2
/* part->childtype */
#define PART_CHILD_PARTICLES 1
#define PART_CHILD_FACES 2
/* psys->recalc */
#define PSYS_INIT 1
#define PSYS_DISTR 2
#define PSYS_ALLOC 4
#define PSYS_TYPE 8
#define PSYS_RECALC_HAIR 16
/* psys->flag */
#define PSYS_CURRENT 1
//#define PSYS_BAKING 2
//#define PSYS_BAKE_UI 4
#define PSYS_KEYED_TIME 8
#define PSYS_ENABLED 16
#define PSYS_FIRST_KEYED 32
#define PSYS_DRAWING 64
//#define PSYS_SOFT_BAKE 128
#define PSYS_DELETE 256 /* remove particlesystem as soon as possible */
#define PSYS_HAIR_DONE 512
#define PSYS_KEYED 1024
#define PSYS_EDITED 2048
#define PSYS_PROTECT_CACHE 4096
/* pars->flag */
#define PARS_UNEXIST 1
#define PARS_NO_DISP 2
#define PARS_STICKY 4
#define PARS_TRANSFORM 8
#define PARS_HIDE 16
#define PARS_TAG 32
#define PARS_REKEY 64
#define PARS_EDIT_RECALC 128
/* pars->alive */
#define PARS_KILLED 0
#define PARS_DEAD 1
#define PARS_UNBORN 2
#define PARS_ALIVE 3
/* psys->vg */
#define PSYS_TOT_VG 11
#define PSYS_VG_DENSITY 0
#define PSYS_VG_VEL 1
#define PSYS_VG_LENGTH 2
#define PSYS_VG_CLUMP 3
#define PSYS_VG_KINK 4
#define PSYS_VG_ROUGH1 5
#define PSYS_VG_ROUGH2 6
#define PSYS_VG_ROUGHE 7
#define PSYS_VG_SIZE 8
#define PSYS_VG_TAN 9
#define PSYS_VG_ROT 10
/* part->boidrules */
#define BOID_TOT_RULES 8
#define BOID_COLLIDE 0
#define BOID_AVOID 1
#define BOID_CROWD 2
#define BOID_CENTER 3
#define BOID_AV_VEL 4
#define BOID_VEL_MATCH 5
#define BOID_GOAL 6
#define BOID_LEVEL 7
//#define PSYS_INTER_CUBIC 0
//#define PSYS_INTER_LINEAR 1
//#define PSYS_INTER_CARDINAL 2
//#define PSYS_INTER_BSPLINE 3
#endif

@ -308,11 +308,28 @@ typedef struct TimeMarker {
unsigned int flag;
} TimeMarker;
struct ImagePaintSettings {
typedef struct ImagePaintSettings {
struct Brush *brush;
short flag, tool;
int pad3;
};
} ImagePaintSettings;
typedef struct ParticleBrushData {
short size, strength; /* commong settings */
short step, invert; /* for specific brushes only */
} ParticleBrushData;
typedef struct ParticleEditSettings {
short flag;
short totrekey;
short totaddkey;
short brushtype;
ParticleBrushData brush[7]; /* 7 = PE_TOT_BRUSH */
float emitterdist;
int draw_timed;
} ParticleEditSettings;
typedef struct ToolSettings {
/* Subdivide Settings */
@ -348,6 +365,9 @@ typedef struct ToolSettings {
/* Image Paint (8 byte aligned please!) */
struct ImagePaintSettings imapaint;
/* Particle Editing */
struct ParticleEditSettings particle;
/* Select Group Threshold */
float select_thresh;
@ -606,6 +626,11 @@ typedef struct Scene {
#define SCE_SELECT_EDGE 2
#define SCE_SELECT_FACE 4
/* sce->selectmode for particles */
#define SCE_SELECT_PATH 1
#define SCE_SELECT_POINT 2
#define SCE_SELECT_END 4
/* sce->recalc (now in use by previewrender) */
#define SCE_PRV_CHANGED 1
@ -658,6 +683,28 @@ typedef struct Scene {
#define IMAGEPAINT_DRAW_TOOL 2
#define IMAGEPAINT_DRAW_TOOL_DRAWING 4
/* toolsettings->particle flag */
#define PE_KEEP_LENGTHS 1
#define PE_LOCK_FIRST 2
#define PE_DEFLECT_EMITTER 4
#define PE_INTERPOLATE_ADDED 8
#define PE_SHOW_CHILD 16
#define PE_SHOW_TIME 32
#define PE_X_MIRROR 64
/* toolsetting->particle brushtype */
#define PE_BRUSH_NONE -1
#define PE_BRUSH_COMB 0
#define PE_BRUSH_CUT 1
#define PE_BRUSH_LENGTH 2
#define PE_BRUSH_PUFF 3
#define PE_BRUSH_ADD 4
#define PE_BRUSH_WEIGHT 5
#define PE_BRUSH_SMOOTH 6
/* this must equal ParticleEditSettings.brush array size */
#define PE_TOT_BRUSH 7
/* toolsettings->retopo_mode */
#define RETOPO 1
#define RETOPO_PAINT 2

@ -57,9 +57,9 @@ typedef struct MTex {
char projx, projy, projz, mapping;
float ofs[3], size[3];
short texflag, colormodel;
short texflag, colormodel, pmapto, pmaptoneg;
float r, g, b, k;
float def_var;
float def_var, rt;
float colfac, norfac, varfac;
float dispfac;

@ -127,6 +127,7 @@ char *includefiles[] = {
"DNA_color_types.h",
"DNA_brush_types.h",
"DNA_customdata_types.h",
"DNA_particle_types.h",
// if you add files here, please add them at the end
// of makesdna.c (this file) as well
@ -1146,4 +1147,5 @@ int main(int argc, char ** argv)
#include "DNA_color_types.h"
#include "DNA_brush_types.h"
#include "DNA_customdata_types.h"
#include "DNA_particle_types.h"
/* end of list */

@ -46,9 +46,13 @@ struct ImBuf;
void RE_zbufferall_radio(struct RadView *vw, struct RNode **rg_elem, int rg_totelem, struct Render *re);
/* effect.c, editmesh_modes.c and brush.c, returns 1 if rgb, 0 otherwise */
/* particle.c, effect.c, editmesh_modes.c and brush.c, returns 1 if rgb, 0 otherwise */
int externtex(struct MTex *mtex, float *vec, float *tin, float *tr, float *tg, float *tb, float *ta);
/* particle.c */
void texture_rgb_blend(float *in, float *tex, float *out, float fact, float facg, int blendtype);
float texture_value_blend(float tex, float out, float fact, float facg, int blendtype, int flip);
/* node_composite.c */
void ibuf_sample(struct ImBuf *ibuf, float fx, float fy, float dx, float dy, float *result);
void antialias_tagbuf(int xsize, int ysize, char *rectmove);

@ -84,6 +84,8 @@ struct VertRen *RE_findOrAddVert(struct Render *re, int nr);
struct HaloRen *RE_findOrAddHalo(struct Render *re, int nr);
struct HaloRen *RE_inithalo(struct Render *re, struct Material *ma, float *vec, float *vec1, float *orco, float hasize,
float vectsize, int seed);
struct HaloRen *RE_inithalo_particle(struct Render *re, struct DerivedMesh *dm, struct Material *ma, float *vec, float *vec1,
float *orco, float *uvco, float hasize, float vectsize, int seed);
void RE_addRenderObject(struct Render *re, struct Object *ob, struct Object *par, int index, int sve, int eve, int sfa, int efa);
float *RE_vertren_get_sticky(struct Render *re, struct VertRen *ver, int verify);

File diff suppressed because it is too large Load Diff

@ -71,6 +71,7 @@
#include "BKE_customdata.h"
#include "BKE_texture.h"
#include "BKE_DerivedMesh.h"
#include "RE_render_ext.h" /* externtex */
@ -723,6 +724,152 @@ HaloRen *RE_inithalo(Render *re, Material *ma, float *vec, float *vec1,
return har;
}
HaloRen *RE_inithalo_particle(Render *re, DerivedMesh *dm, Material *ma, float *vec, float *vec1,
float *orco, float *uvco, float hasize, float vectsize, int seed)
{
HaloRen *har;
MTex *mtex;
float tin, tr, tg, tb, ta;
float xn, yn, zn, texvec[3], hoco[4], hoco1[4], in[3],tex[3],out[3];
int i;
if(hasize==0.0) return NULL;
projectverto(vec, re->winmat, hoco);
if(hoco[3]==0.0) return NULL;
if(vec1) {
projectverto(vec1, re->winmat, hoco1);
if(hoco1[3]==0.0) return NULL;
}
har= RE_findOrAddHalo(re, re->tothalo++);
VECCOPY(har->co, vec);
har->hasize= hasize;
/* actual projectvert is done in function project_renderdata() because of parts/border/pano */
/* we do it here for sorting of halos */
zn= hoco[3];
har->xs= 0.5*re->winx*(hoco[0]/zn);
har->ys= 0.5*re->winy*(hoco[1]/zn);
har->zs= 0x7FFFFF*(hoco[2]/zn);
har->zBufDist = 0x7FFFFFFF*(hoco[2]/zn);
/* halovect */
if(vec1) {
har->type |= HA_VECT;
xn= har->xs - 0.5*re->winx*(hoco1[0]/hoco1[3]);
yn= har->ys - 0.5*re->winy*(hoco1[1]/hoco1[3]);
if(xn==0.0 || (xn==0.0 && yn==0.0)) zn= 0.0;
else zn= atan2(yn, xn);
har->sin= sin(zn);
har->cos= cos(zn);
zn= VecLenf(vec1, vec)*0.5;
har->hasize= vectsize*zn + (1.0-vectsize)*hasize;
VecSubf(har->no, vec, vec1);
Normalize(har->no);
}
if(ma->mode & MA_HALO_XALPHA) har->type |= HA_XALPHA;
har->alfa= ma->alpha;
har->r= ma->r;
har->g= ma->g;
har->b= ma->b;
har->add= (255.0*ma->add);
har->mat= ma;
har->hard= ma->har;
har->seed= seed % 256;
if(ma->mode & MA_STAR) har->starpoints= ma->starc;
if(ma->mode & MA_HALO_LINES) har->linec= ma->linec;
if(ma->mode & MA_HALO_RINGS) har->ringc= ma->ringc;
if(ma->mode & MA_HALO_FLARE) har->flarec= ma->flarec;
if((ma->mode & MA_HALOTEX) && ma->mtex[0]){
har->tex= 1;
i=1;
}
for(i=0; i<MAX_MTEX; i++)
if(ma->mtex[i] && (ma->septex & (1<<i))==0) {
mtex= ma->mtex[i];
VECCOPY(texvec, vec);
if(mtex->texco & TEXCO_NORM) {
;
}
else if(mtex->texco & TEXCO_OBJECT) {
if(mtex->object){
float imat[4][4];
/* imat should really be cached somewhere before this */
Mat4Invert(imat,mtex->object->obmat);
Mat4MulVecfl(imat,texvec);
}
/* texvec[0]+= imatbase->ivec[0]; */
/* texvec[1]+= imatbase->ivec[1]; */
/* texvec[2]+= imatbase->ivec[2]; */
/* Mat3MulVecfl(imatbase->imat, texvec); */
}
else if(mtex->texco & TEXCO_GLOB){
VECCOPY(texvec,vec);
}
else if(mtex->texco & TEXCO_UV && uvco){
int uv_index=CustomData_get_named_layer_index(&dm->faceData,CD_MTFACE,mtex->uvname);
if(uv_index<0)
uv_index=CustomData_get_active_layer_index(&dm->faceData,CD_MTFACE);
uv_index-=CustomData_get_layer_index(&dm->faceData,CD_MTFACE);
texvec[0]=2.0f*uvco[2*uv_index]-1.0f;
texvec[1]=2.0f*uvco[2*uv_index+1]-1.0f;
texvec[2]=0.0f;
}
else if(orco) {
VECCOPY(texvec, orco);
}
externtex(mtex, texvec, &tin, &tr, &tg, &tb, &ta);
//yn= tin*mtex->colfac;
//zn= tin*mtex->varfac;
if(mtex->mapto & MAP_COL) {
tex[0]=tr;
tex[1]=tg;
tex[2]=tb;
out[0]=har->r;
out[1]=har->g;
out[2]=har->b;
texture_rgb_blend(in,tex,out,tin,mtex->colfac,mtex->blendtype);
// zn= 1.0-yn;
//har->r= (yn*tr+ zn*ma->r);
//har->g= (yn*tg+ zn*ma->g);
//har->b= (yn*tb+ zn*ma->b);
har->r= in[0];
har->g= in[1];
har->b= in[2];
}
if(mtex->mapto & MAP_ALPHA)
har->alfa = texture_value_blend(mtex->def_var,har->alfa,tin,mtex->varfac,mtex->blendtype,mtex->maptoneg & MAP_ALPHA);
if(mtex->mapto & MAP_HAR)
har->hard = 1.0+126.0*texture_value_blend(mtex->def_var,((float)har->hard)/127.0,tin,mtex->varfac,mtex->blendtype,mtex->maptoneg & MAP_HAR);
if(mtex->mapto & MAP_RAYMIRR)
har->hasize = 100.0*texture_value_blend(mtex->def_var,har->hasize/100.0,tin,mtex->varfac,mtex->blendtype,mtex->maptoneg & MAP_RAYMIRR);
/* now what on earth is this good for?? */
//if(mtex->texco & 16) {
// har->alfa= tin;
//}
}
return har;
}
/* -------------------------- operations on entire database ----------------------- */
/* ugly function for halos in panorama */

@ -1242,7 +1242,7 @@ int multitex_ext(Tex *tex, float *texvec, float *dxt, float *dyt, int osatex, Te
/* in = destination, tex = texture, out = previous color */
/* fact = texture strength, facg = button strength value */
static void texture_rgb_blend(float *in, float *tex, float *out, float fact, float facg, int blendtype)
void texture_rgb_blend(float *in, float *tex, float *out, float fact, float facg, int blendtype)
{
float facm, col;
@ -1330,7 +1330,7 @@ static void texture_rgb_blend(float *in, float *tex, float *out, float fact, flo
}
static float texture_value_blend(float tex, float out, float fact, float facg, int blendtype, int flip)
float texture_value_blend(float tex, float out, float fact, float facg, int blendtype, int flip)
{
float in=0.0, facm, col;
@ -1406,7 +1406,7 @@ void do_material_tex(ShadeInput *shi)
tex= mtex->tex;
if(tex==0) continue;
/* which coords */
if(mtex->texco==TEXCO_ORCO) {
co= shi->lo; dx= shi->dxlo; dy= shi->dylo;
@ -1486,7 +1486,7 @@ void do_material_tex(ShadeInput *shi)
dy[1]= dy[2]= 0.0f;
}
else continue; // can happen when texco defines disappear and it renders old files
/* de pointer defines if bumping happens */
if(mtex->mapto & (MAP_NORM|MAP_DISPLACE|MAP_WARP)) {
texres.nor= norvec;

File diff suppressed because it is too large Load Diff

@ -738,6 +738,8 @@ void drawbutspace(ScrArea *sa, void *spacedata)
object_panels();
else if(tab==TAB_OBJECT_PHYSICS)
physics_panels();
else if(tab==TAB_OBJECT_PARTICLE)
particle_panels();
break;
case CONTEXT_SHADING:

@ -66,6 +66,7 @@
#include "DNA_nla_types.h"
#include "DNA_object_types.h"
#include "DNA_object_force.h"
#include "DNA_particle_types.h"
#include "DNA_radio_types.h"
#include "DNA_screen_types.h"
#include "DNA_texture_types.h"
@ -86,8 +87,10 @@
#include "BKE_key.h"
#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_mesh.h"
#include "BKE_modifier.h"
#include "BKE_packedFile.h"
#include "BKE_particle.h"
#include "BKE_scene.h"
#include "BLI_blenlib.h"
@ -105,6 +108,7 @@
#include "BIF_editfont.h"
#include "BIF_editkey.h"
#include "BIF_editmesh.h"
#include "BIF_editparticle.h"
#include "BIF_imasel.h"
#include "BIF_interface.h"
#include "BIF_meshtools.h"
@ -950,7 +954,7 @@ static uiBlock *modifiers_add_menu(void *ob_v)
ModifierTypeInfo *mti = modifierType_getInfo(i);
/* Only allow adding through appropriate other interfaces */
if(ELEM(i, eModifierType_Softbody, eModifierType_Hook)) continue;
if(ELEM3(i, eModifierType_Softbody, eModifierType_Hook, eModifierType_ParticleSystem)) continue;
if((mti->flags&eModifierTypeFlag_AcceptsCVs) ||
(ob->type==OB_MESH && (mti->flags&eModifierTypeFlag_AcceptsMesh))) {
@ -990,6 +994,12 @@ static void modifiers_del(void *ob_v, void *md_v)
if (!md)
return;
if(md->type==eModifierType_ParticleSystem){
ParticleSystemModifierData *psmd=(ParticleSystemModifierData*)md;
BLI_remlink(&ob->particlesystem, psmd->psys);
psys_free(ob,psmd->psys);
}
BLI_remlink(&ob->modifiers, md_v);
modifier_free(md_v);
@ -1201,7 +1211,93 @@ void autocomplete_meshob(char *str, void *arg_v)
autocomplete_end(autocpl, str);
}
}
static void modifiers_convertParticles(void *obv, void *mdv)
{
Object *obn;
ModifierData *md = mdv;
ParticleSystem *psys;
ParticleCacheKey *key, **cache;
Mesh *me;
MVert *mvert;
MFace *mface;
int a, k, kmax;
int totvert=0, totface=0, cvert=0;
int totpart=0, totchild=0;
if(md->type != eModifierType_ParticleSystem) return;
if(G.f & G_PARTICLEEDIT) return;
psys=((ParticleSystemModifierData *)md)->psys;
if(psys->part->draw_as != PART_DRAW_PATH || psys->pathcache == 0) return;
totpart= psys->totcached;
totchild= psys->totchildcache;
if(totchild && (psys->part->draw&PART_DRAW_PARENT)==0)
totpart= 0;
/* count */
cache= psys->pathcache;
for(a=0; a<totpart; a++) {
key= cache[a];
totvert+= (int)(key->col[3])+1;
totface+= (int)(key->col[3]);
}
cache= psys->childcache;
for(a=0; a<totchild; a++) {
key= cache[a];
totvert+= (int)(key->col[3])+1;
totface+= (int)(key->col[3]);
}
if(totvert==0) return;
/* add new mesh */
obn= add_object(OB_MESH);
me= obn->data;
me->totvert= totvert;
me->totface= totface;
me->mvert= CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, NULL, totvert);
me->mface= CustomData_add_layer(&me->fdata, CD_MFACE, CD_CALLOC, NULL, totface);
mvert= me->mvert;
mface= me->mface;
/* copy coordinates */
cache= psys->pathcache;
for(a=0; a<totpart; a++){
key= cache[a];
kmax= (int)(key->col[3]);
for(k=0; k<=kmax; k++,key++,cvert++,mvert++) {
VECCOPY(mvert->co,key->co);
if(k){
mface->v1= cvert-1;
mface->v2= cvert;
mface++;
}
}
}
cache=psys->childcache;
for(a=0; a<totchild; a++) {
key=cache[a];
kmax=(int)(key->col[3]);
for(k=0; k<=kmax; k++,key++,cvert++,mvert++) {
VECCOPY(mvert->co,key->co);
if(k){
mface->v1=cvert-1;
mface->v2=cvert;
mface++;
}
}
}
make_edges(me, 0);
}
static void modifiers_applyModifier(void *obv, void *mdv)
{
Object *ob = obv;
@ -1506,6 +1602,13 @@ static void modifiers_bindMeshDeform(void *ob_v, void *md_v)
}
}
void modifiers_explodeFacepa(void *arg1, void *arg2)
{
ExplodeModifierData *emd=arg1;
emd->flag |= eExplodeFlag_CalcFaces;
}
static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco, int *yco, int index, int cageIndex, int lastCageIndex)
{
ModifierTypeInfo *mti = modifierType_getInfo(md->type);
@ -1641,7 +1744,7 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco
if(hmd->indexar==NULL)
height += 20;
} else if (md->type==eModifierType_Softbody) {
height = 26;
height = 31;
} else if (md->type==eModifierType_Boolean) {
height = 48;
} else if (md->type==eModifierType_Array) {
@ -1649,8 +1752,14 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco
} else if (md->type==eModifierType_MeshDeform) {
MeshDeformModifierData *mmd= (MeshDeformModifierData*)md;
height = (mmd->bindcos)? 73: 93;
}
} else if (md->type==eModifierType_ParticleSystem) {
height = 31;
} else if (md->type==eModifierType_ParticleInstance) {
height = 94;
} else if (md->type==eModifierType_Explode) {
height = 94;
}
/* roundbox 4 free variables: corner-rounding, nop, roundbox type, shade */
uiDefBut(block, ROUNDBOX, 0, "", x-10, y-height-2, width, height-2, NULL, 5.0, 0.0, 12, 40, "");
@ -1658,9 +1767,16 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco
if (!isVirtual) {
uiBlockBeginAlign(block);
but = uiDefBut(block, BUT, B_MODIFIER_RECALC, "Apply", lx,(cy-=19),60,19, 0, 0, 0, 0, 0, "Apply the current modifier and remove from the stack");
uiButSetFunc(but, modifiers_applyModifier, ob, md);
if (md->type!=eModifierType_Softbody) {
if (md->type==eModifierType_ParticleSystem) {
but = uiDefBut(block, BUT, B_MODIFIER_RECALC, "Convert", lx,(cy-=19),60,19, 0, 0, 0, 0, 0, "Convert the current particles to a mesh object");
uiButSetFunc(but, modifiers_convertParticles, ob, md);
}
else{
but = uiDefBut(block, BUT, B_MODIFIER_RECALC, "Apply", lx,(cy-=19),60,19, 0, 0, 0, 0, 0, "Apply the current modifier and remove from the stack");
uiButSetFunc(but, modifiers_applyModifier, ob, md);
}
if (md->type!=eModifierType_Softbody && md->type!=eModifierType_ParticleSystem) {
but = uiDefBut(block, BUT, B_MODIFIER_RECALC, "Copy", lx,(cy-=19),60,19, 0, 0, 0, 0, 0, "Duplicate the current modifier at the same position in the stack");
uiButSetFunc(but, modifiers_copyModifier, ob, md);
}
@ -2159,6 +2275,39 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco
uiDefButBitS(block, TOG, MOD_MDEF_DYNAMIC_BIND, B_MODIFIER_RECALC, "Dynamic", lx+(buttonWidth+1)/2 + 20, (cy-=19), buttonWidth/2 - 20,19, &mmd->flag, 0.0, 31.0, 0, 0, "Invert vertex group influence");
}
uiBlockEndAlign(block);
} else if (md->type==eModifierType_ParticleSystem) {
uiDefBut(block, LABEL, 1, "See Particle buttons.", lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
} else if (md->type==eModifierType_ParticleInstance) {
ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData*) md;
uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy -= 19), buttonWidth, 19, &pimd->ob, "Object that has the particlesystem");
uiDefButS(block, NUM, B_MODIFIER_RECALC, "PSYS:", lx, (cy -= 19), buttonWidth, 19, &pimd->psys, 1, 10, 10, 3, "Particlesystem number in the object");
uiDefButBitS(block, TOG, eParticleInstanceFlag_Parents, B_MODIFIER_RECALC, "Normal", lx, (cy -= 19), buttonWidth/3,19, &pimd->flag, 0, 0, 0, 0, "Create instances from normal particles");
uiDefButBitS(block, TOG, eParticleInstanceFlag_Children, B_MODIFIER_RECALC, "Children", lx+buttonWidth/3, cy, buttonWidth/3,19, &pimd->flag, 0, 0, 0, 0, "Create instances from child particles");
uiDefButBitS(block, TOG, eParticleInstanceFlag_Path, B_MODIFIER_RECALC, "Path", lx+buttonWidth*2/3, cy, buttonWidth/3,19, &pimd->flag, 0, 0, 0, 0, "Create instances along particle paths");
uiDefButBitS(block, TOG, eParticleInstanceFlag_Unborn, B_MODIFIER_RECALC, "Unborn", lx, (cy -= 19), buttonWidth/3,19, &pimd->flag, 0, 0, 0, 0, "Show instances when particles are unborn");
uiDefButBitS(block, TOG, eParticleInstanceFlag_Alive, B_MODIFIER_RECALC, "Alive", lx+buttonWidth/3, cy, buttonWidth/3,19, &pimd->flag, 0, 0, 0, 0, "Show instances when particles are alive");
uiDefButBitS(block, TOG, eParticleInstanceFlag_Dead, B_MODIFIER_RECALC, "Dead", lx+buttonWidth*2/3, cy, buttonWidth/3,19, &pimd->flag, 0, 0, 0, 0, "Show instances when particles are dead");
} else if (md->type==eModifierType_Explode) {
ExplodeModifierData *emd = (ExplodeModifierData*) md;
uiBut *but;
char *menustr= get_vertexgroup_menustr(ob);
int defCount=BLI_countlist(&ob->defbase);
if(defCount==0) emd->vgroup=0;
but=uiDefButS(block, MENU, B_MODIFIER_RECALC, menustr, lx, (cy-=19), buttonWidth/2,19, &emd->vgroup, 0, defCount, 0, 0, "Protect this vertex group");
uiButSetFunc(but,modifiers_explodeFacepa,emd,0);
MEM_freeN(menustr);
but=uiDefButF(block, NUMSLI, B_MODIFIER_RECALC, "", lx+buttonWidth/2, cy, buttonWidth/2,19, &emd->protect, 0.0f, 1.0f, 0, 0, "Clean vertex group edges");
uiButSetFunc(but,modifiers_explodeFacepa,emd,0);
but=uiDefBut(block, BUT, B_MODIFIER_RECALC, "Refresh", lx, (cy-=19), buttonWidth/2,19, 0, 0, 0, 0, 0, "Recalculate faces assigned to particles");
uiButSetFunc(but,modifiers_explodeFacepa,emd,0);
uiDefButBitS(block, TOG, eExplodeFlag_EdgeSplit, B_MODIFIER_RECALC, "Split Edges", lx+buttonWidth/2, cy, buttonWidth/2,19, &emd->flag, 0, 0, 0, 0, "Split face edges for nicer shrapnel");
uiDefButBitS(block, TOG, eExplodeFlag_Unborn, B_MODIFIER_RECALC, "Unborn", lx, (cy-=19), buttonWidth/3,19, &emd->flag, 0, 0, 0, 0, "Show mesh when particles are unborn");
uiDefButBitS(block, TOG, eExplodeFlag_Alive, B_MODIFIER_RECALC, "Alive", lx+buttonWidth/3, cy, buttonWidth/3,19, &emd->flag, 0, 0, 0, 0, "Show mesh when particles are alive");
uiDefButBitS(block, TOG, eExplodeFlag_Dead, B_MODIFIER_RECALC, "Dead", lx+buttonWidth*2/3, cy, buttonWidth/3,19, &emd->flag, 0, 0, 0, 0, "Show mesh when particles are dead");
}
uiBlockEndAlign(block);
@ -2180,6 +2329,8 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco
uiDefBut(block, LABEL, B_NOP, str, x+15, y+15, width-35, 19, NULL, 0.0, 0.0, 0.0, 0.0, "");
}
uiClearButLock();
y -= 3+6;
*xco = x;
@ -4956,6 +5107,7 @@ void do_fpaintbuts(unsigned short event)
ToolSettings *settings= G.scene->toolsettings;
int nr= 1;
MTex *mtex;
ParticleSystem *psys;
ob= OBACT;
if(ob==NULL) return;
@ -5230,6 +5382,20 @@ void do_fpaintbuts(unsigned short event)
allqueue(REDRAWIMAGE, 0);
allqueue(REDRAWBUTSEDIT, 0);
break;
case B_BAKE_REDRAWEDIT:
allqueue(REDRAWVIEW3D, 0);
allqueue(REDRAWBUTSEDIT, 0);
break;
case B_BAKE_RECACHE:
psys=PE_get_current(ob);
PE_hide_keys_time(psys,CFRA);
psys_cache_paths(ob,psys,CFRA,0);
if(PE_settings()->flag & PE_SHOW_CHILD)
psys_cache_child_paths(ob,psys,CFRA,0);
allqueue(REDRAWVIEW3D, 0);
allqueue(REDRAWBUTSEDIT, 0);
break;
}
}
@ -5575,6 +5741,127 @@ void editing_panel_mesh_multires()
uiBlockEndAlign(block);
}
void particle_edit_buttons(uiBlock *block)
{
Object *ob=OBACT;
ParticleSystem *psys = PE_get_current(ob);
ParticleEditSettings *pset = PE_settings();
ParticleEdit *edit;
uiBut *but;
short butx=10,buty=150,butw=150,buth=20, lastbuty;
static short partact;
char *menustr;
if(psys==NULL) return;
menustr = psys_menu_string(ob, 0);
partact = PE_get_current_num(ob)+1;
but=uiDefButS(block, MENU, B_BAKE_REDRAWEDIT, menustr, 160,180,butw,buth, &partact, 14.0, 0.0, 0, 0, "Browse systems");
uiButSetFunc(but, PE_change_act, ob, &partact);
MEM_freeN(menustr);
if(psys->edit) {
edit= psys->edit;
/* brushes */
//uiDefBut(block, LABEL, 0, "Brush", butx,(buty-=buth),butw,buth, NULL, 0.0, 0, 0, 0, "");
uiBlockBeginAlign(block);
uiDefButS(block,ROW,B_BAKE_REDRAWEDIT,"None",butx,buty,75,19,&pset->brushtype,14.0,PE_BRUSH_NONE,0,0,"Disable brush");
uiDefButS(block,ROW,B_BAKE_REDRAWEDIT,"Comb",butx+75,buty,75,19,&pset->brushtype,14.0,PE_BRUSH_COMB,0,0,"Comb hairs");
uiDefButS(block,ROW,B_BAKE_REDRAWEDIT,"Smooth",butx+150,buty,75,19,&pset->brushtype,14.0,PE_BRUSH_SMOOTH,0,0,"Smooth hairs");
uiDefButS(block,ROW,B_BAKE_REDRAWEDIT,"Weight",butx+225,buty,75,19,&pset->brushtype,14,PE_BRUSH_WEIGHT,0,0,"Weight hairs");
buty-= buth;
uiDefButS(block,ROW,B_BAKE_REDRAWEDIT,"Add", butx,buty,75,19,&pset->brushtype,14,PE_BRUSH_ADD,0,0,"Add hairs");
uiDefButS(block,ROW,B_BAKE_REDRAWEDIT,"Length", butx+75,buty,75,19,&pset->brushtype,14, PE_BRUSH_LENGTH,0,0,"Make hairs longer or shorter");
uiDefButS(block,ROW,B_BAKE_REDRAWEDIT,"Puff", butx+150,buty,75,19,&pset->brushtype,14, PE_BRUSH_PUFF,0,0,"Make hairs stand up");
uiDefButS(block,ROW,B_BAKE_REDRAWEDIT,"Cut", butx+225,buty,75,19,&pset->brushtype,14, PE_BRUSH_CUT,0,0,"Cut hairs");
uiBlockEndAlign(block);
buty-= 10;
lastbuty= buty;
/* brush options */
if(pset->brushtype>=0) {
ParticleBrushData *brush= &pset->brush[pset->brushtype];
butw= 180;
uiBlockBeginAlign(block);
uiDefButS(block, NUMSLI, B_BAKE_REDRAWEDIT, "Size:", butx,(buty-=buth),butw,buth, &brush->size, 1.0, 100.0, 1, 1, "Brush size");
uiDefButS(block, NUMSLI, B_BAKE_REDRAWEDIT, "Strength:", butx,(buty-=buth),butw,buth, &brush->strength, 1.0, 100.0, 1, 1, "Brush strength");
if(ELEM(pset->brushtype, PE_BRUSH_LENGTH, PE_BRUSH_PUFF)) {
char *str1, *str2, *tip1, *tip2;
if(pset->brushtype == PE_BRUSH_LENGTH) {
str1= "Grow"; tip1= "Make hairs longer [Shift]";
str2= "Shrink"; tip2= "Make hairs shorter [Shift]";
}
else /*if(pset->brushtype == PE_BRUSH_PUFF)*/ {
str1= "Add"; tip1= "Make hair more puffy [Shift]";
str2= "Sub"; tip2= "Make hair less puffy [Shift]";
}
uiDefButS(block,ROW,B_NOP,str1, butx,(buty-=buth),butw/2,buth,&brush->invert,0.0,0.0,0, 0,tip1);
uiDefButS(block,ROW,B_NOP,str2, butx+butw/2,buty,butw/2,buth,&brush->invert,0.0,1.0,0, 0,tip2);
}
uiBlockEndAlign(block);
butx += butw+10;
buty= lastbuty;
butw= 110;
if(pset->brushtype==PE_BRUSH_ADD) {
uiBlockBeginAlign(block);
uiDefButBitS(block, TOG, PE_INTERPOLATE_ADDED, B_BAKE_REDRAWEDIT, "Interpolate", butx,(buty-=buth),butw,buth, &pset->flag, 0, 0, 0, 0, "Interpolate new particles from the existing ones");
uiDefButS(block, NUMSLI, B_BAKE_REDRAWEDIT, "Step:", butx,(buty-=buth),butw,buth, &brush->step, 1.0, 50.0, 1, 1, "Brush step");
uiDefButS(block, NUMSLI, B_BAKE_REDRAWEDIT, "Keys:", butx,(buty-=buth),butw,buth, &pset->totaddkey, 2.0, 20.0, 1, 1, "How many keys to make new particles with");
uiBlockEndAlign(block);
}
}
/* keep options */
butw= 150;
butx= 10;
buty= lastbuty - (buth*3 + 10);
lastbuty= buty;
uiDefBut(block, LABEL, 0, "Keep", butx,(buty-=buth),butw,buth, NULL, 0.0, 0, 0, 0, "");
uiBlockBeginAlign(block);
uiDefButBitS(block, TOG, PE_KEEP_LENGTHS, B_BAKE_REDRAWEDIT, "Lengths", butx,(buty-=buth),butw/2,buth, &pset->flag, 0, 0, 0, 0, "Keep path lengths constant");
uiDefButBitS(block, TOG, PE_LOCK_FIRST, B_BAKE_REDRAWEDIT, "Root", butx+butw/2,buty,butw/2,buth, &pset->flag, 0, 0, 0, 0, "Keep first keys unmodified");
uiBlockEndAlign(block);
buty -= 5;
uiBlockBeginAlign(block);
uiDefButBitS(block, TOG, PE_DEFLECT_EMITTER, B_BAKE_REDRAWEDIT, "Deflect Emitter", butx,(buty-=buth),butw,buth, &pset->flag, 0, 0, 0, 0, "Keep paths from intersecting the emitter");
uiDefButF(block, NUM, B_BAKE_REDRAWEDIT, "Dist:", butx,(buty-=buth),butw,buth, &pset->emitterdist, 0.0, 10.0, 1, 1, "Distance from emitter");
uiBlockEndAlign(block);
buty= lastbuty;
butx += butw+10;
butw -= 10;
uiDefBut(block, LABEL, 0, "Draw", butx,(buty-=buth),butw,buth, NULL, 0.0, 0, 0, 0, "");
uiBlockBeginAlign(block);
uiDefButS(block, NUMSLI, B_BAKE_RECACHE, "Steps:", butx,(buty-=buth),butw,buth, &psys->part->draw_step, 0.0, 10.0, 1, 1, "Drawing accuracy of paths");
uiBlockEndAlign(block);
buty -= 5;
uiBlockBeginAlign(block);
uiDefButBitS(block, TOG, PE_SHOW_TIME, B_BAKE_REDRAWEDIT, "Show Time", butx,(buty-=buth),butw,buth, &pset->flag, 0, 0, 0, 0, "Show time values of the baked keys");
uiDefButBitS(block, TOG, PE_SHOW_CHILD, B_BAKE_RECACHE, "Show Children", butx,(buty-=buth),butw,buth, &pset->flag, 0, 0, 0, 0, "Show child particles in particle mode");
uiBlockEndAlign(block);
}
else{
uiDefBut(block, LABEL, 0, "System isn't editable", butx,(buty-=buth),250,buth, NULL, 0.0, 0, 0, 0, "");
}
}
/* this is a mode context sensitive system */
void editing_panels()

File diff suppressed because it is too large Load Diff

@ -52,6 +52,7 @@
#include "DNA_object_types.h"
#include "DNA_node_types.h"
#include "DNA_packedFile_types.h"
#include "DNA_particle_types.h"
#include "DNA_radio_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
@ -62,6 +63,7 @@
#include "DNA_world_types.h"
#include "BKE_colortools.h"
#include "BKE_depsgraph.h"
#include "BKE_displist.h"
#include "BKE_effect.h"
#include "BKE_global.h"
@ -69,6 +71,7 @@
#include "BKE_main.h"
#include "BKE_node.h"
#include "BKE_material.h"
#include "BKE_particle.h"
#include "BKE_utildefines.h"
#include "BKE_texture.h"
@ -3040,16 +3043,65 @@ void do_matbuts(unsigned short event)
allqueue(REDRAWBUTSSHADING, 0);
}
break;
case B_MAT_PARTICLE:
if(ma) {
Base *base;
Object *ob;
ParticleSystem *psys;
base= G.scene->base.first;
while(base){
if(base->object->type==OB_MESH) {
ob=base->object;
for(psys=ob->particlesystem.first; psys; psys=psys->next) {
if(psys && ma==give_current_material(ob,psys->part->omat)) {
psys->flag |= PSYS_INIT;
DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
}
}
}
base = base->next;
}
allqueue(REDRAWVIEW3D, 0);
}
}
}
static void particle_recalc_material(void *ma_v, void *arg2)
{
Material *ma = ma_v;
Base *base;
Object *ob;
ParticleSystem *psys;
base= G.scene->base.first;
while(base){
if(base->object->type==OB_MESH){
ob=base->object;
for(psys=ob->particlesystem.first; psys; psys=psys->next){
if(psys && ma==give_current_material(ob,psys->part->omat)){
psys->recalc |= PSYS_INIT;
DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
}
}
}
base = base->next;
}
allqueue(REDRAWVIEW3D, 0);
}
/* if from nodes, hide options that are not available */
static void material_panel_map_to(Material *ma, int from_nodes)
static void material_panel_map_to(Object *ob, Material *ma, int from_nodes)
{
uiBlock *block;
uiBut *but;
MTex *mtex;
ParticleSystem *psys;
int psys_mapto=0;
static short pattr=0;
block= uiNewBlock(&curarea->uiblocks, "material_panel_map_to", UI_EMBOSS, UI_HELV, curarea->win);
uiNewPanelTabbed("Texture", "Material");
@ -3091,32 +3143,82 @@ static void material_panel_map_to(Material *ma, int from_nodes)
/* MAP TO */
uiBlockBeginAlign(block);
uiDefButBitS(block, TOG, MAP_COL, B_MATPRV, "Col", 10,180,40,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect basic color of the material");
uiDefButBitS(block, TOG3, MAP_NORM, B_MATPRV, "Nor", 50,180,40,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the rendered normal");
uiDefButBitS(block, TOG, MAP_COLSPEC, B_MATPRV, "Csp", 90,180,40,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the specularity color");
uiDefButBitS(block, TOG, MAP_COLMIR, B_MATPRV, "Cmir", 130,180,50,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the mirror color");
uiDefButBitS(block, TOG3, MAP_REF, B_MATPRV, "Ref", 180,180,40,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the value of the materials reflectivity");
uiDefButBitS(block, TOG3, MAP_SPEC, B_MATPRV, "Spec", 220,180,50,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the value of specularity");
uiDefButBitS(block, TOG3, MAP_AMB, B_MATPRV, "Amb", 270,180,40,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the value of ambient");
uiDefButBitS(block, TOG3, MAP_HAR, B_MATPRV, "Hard", 10,160,50,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the hardness value");
uiDefButBitS(block, TOG3, MAP_RAYMIRR, B_MATPRV, "RayMir", 60,160,50,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the ray-mirror value");
uiDefButBitS(block, TOG3, MAP_ALPHA, B_MATPRV, "Alpha", 110,160,50,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the alpha value");
uiDefButBitS(block, TOG3, MAP_EMIT, B_MATPRV, "Emit", 160,160,45,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the emit value");
uiDefButBitS(block, TOG3, MAP_TRANSLU, B_MATPRV, "TransLu", 205,160,60,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the layer blending value");
if(from_nodes==0)
uiDefButBitS(block, TOG3, MAP_DISPLACE, B_MATPRV, "Disp", 265,160,45,19, &(mtex->mapto), 0, 0, 0, 0, "Let the texture displace the surface");
/*check if material is being used by particles*/
for(psys=ob->particlesystem.first; psys; psys=psys->next)
if(psys->part->omat==ob->actcol)
psys_mapto=1;
if(psys_mapto && pattr) {
but=uiDefButBitS(block, TOG3, MAP_PA_TIME, B_MAT_PARTICLE, "Time", 10,180,60,19, &(mtex->pmapto), 0, 0, 0, 0, "Causes the texture to affect the emission time of particles");
//uiButSetFunc(but, particle_recalc_material, ma, NULL);
but=uiDefButBitS(block, TOG3, MAP_PA_LIFE, B_MAT_PARTICLE, "Life", 70,180,60,19, &(mtex->pmapto), 0, 0, 0, 0, "Causes the texture to affect the life time of particles");
//uiButSetFunc(but, particle_recalc_material, ma, NULL);
but=uiDefButBitS(block, TOG3, MAP_PA_DENS, B_MAT_PARTICLE, "Dens", 130,180,60,19, &(mtex->pmapto), 0, 0, 0, 0, "Causes the texture to affect the density of particles");
//uiButSetFunc(but, particle_recalc_material, ma, NULL);
uiDefButBitS(block, TOG3, MAP_PA_IVEL, B_MAT_PARTICLE, "IVel", 190,180,60,19, &(mtex->pmapto), 0, 0, 0, 0, "Causes the texture to affect the initial velocity of particles");
uiDefButBitS(block, TOG3, MAP_PA_PVEL, B_MAT_PARTICLE, "PVel", 250,180,60,19, &(mtex->pmapto), 0, 0, 0, 0, "Causes the texture to affect the velocity of particles");
but=uiDefButBitS(block, TOG3, MAP_PA_SIZE, B_MAT_PARTICLE, "Size", 10,160,60,19, &(mtex->pmapto), 0, 0, 0, 0, "Causes the texture to affect the size of particles");
//uiButSetFunc(but, particle_recalc_material, ma, NULL);
but=uiDefButBitS(block, TOG3, MAP_PA_KINK, B_MAT_PARTICLE, "Kink", 70,160,60,19, &(mtex->pmapto), 0, 0, 0, 0, "Causes the texture to affect the kink of child particles");
//uiButSetFunc(but, particle_recalc_material, ma, NULL);
but=uiDefButBitS(block, TOG3, MAP_PA_LENGTH, B_MAT_PARTICLE, "Length",130,160,60,19, &(mtex->pmapto), 0, 0, 0, 0, "Causes the texture to affect the length of particles");
//uiButSetFunc(but, particle_recalc_material, ma, NULL);
but=uiDefButBitS(block, TOG3, MAP_PA_CLUMP, B_MAT_PARTICLE, "Clump", 190,160,60,19, &(mtex->pmapto), 0, 0, 0, 0, "Causes the texture to affect the clump of child particles");
//uiButSetFunc(but, particle_recalc_material, ma, NULL);
uiBlockSetCol(block, TH_BUT_SETTING1);
uiDefButBitS(block, TOG, 1, B_MATPRV, "PAttr", 250,160,60,19, &pattr, 0, 0, 0, 0, "Display settings for particle attributes");
uiBlockSetCol(block, TH_AUTO);
}
else {
uiDefButBitS(block, TOG, MAP_COL, B_MATPRV, "Col", 10,180,40,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect basic colour of the material");
uiDefButBitS(block, TOG3, MAP_NORM, B_MATPRV, "Nor", 50,180,40,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the rendered normal");
uiDefButBitS(block, TOG, MAP_COLSPEC, B_MATPRV, "Csp", 90,180,40,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the specularity colour");
uiDefButBitS(block, TOG, MAP_COLMIR, B_MATPRV, "Cmir", 130,180,50,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the mirror colour");
uiDefButBitS(block, TOG3, MAP_REF, B_MATPRV, "Ref", 180,180,40,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the value of the materials reflectivity");
uiDefButBitS(block, TOG3, MAP_SPEC, B_MATPRV, "Spec", 220,180,50,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the value of specularity");
uiDefButBitS(block, TOG3, MAP_AMB, B_MATPRV, "Amb", 270,180,40,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the value of ambient");
if(psys_mapto) {
uiDefButBitS(block, TOG3, MAP_HAR, B_MATPRV, "Hard", 10,160,40,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the hardness value");
uiDefButBitS(block, TOG3, MAP_RAYMIRR, B_MATPRV, "RayMir", 50,160,40,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the ray-mirror value");
uiDefButBitS(block, TOG3, MAP_ALPHA, B_MATPRV, "Alpha", 90,160,40,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the alpha value");
uiDefButBitS(block, TOG3, MAP_EMIT, B_MATPRV, "Emit", 130,160,50,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the emit value");
uiDefButBitS(block, TOG3, MAP_TRANSLU, B_MATPRV, "TransLu", 180,160,40,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the layer blending value");
if(from_nodes==0)
uiDefButBitS(block, TOG3, MAP_DISPLACE, B_MATPRV, "Disp", 220,160,50,19, &(mtex->mapto), 0, 0, 0, 0, "Let the texture displace the surface");
uiBlockSetCol(block, TH_BUT_SETTING1);
uiDefButBitS(block, TOG, 1, B_MATPRV, "PAttr", 270,160,40,19, &pattr, 0, 0, 0, 0, "Display settings for particle attributes");
uiBlockSetCol(block, TH_AUTO);
}
else {
uiDefButBitS(block, TOG3, MAP_HAR, B_MATPRV, "Hard", 10,160,50,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the hardness value");
uiDefButBitS(block, TOG3, MAP_RAYMIRR, B_MATPRV, "RayMir", 60,160,50,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the ray-mirror value");
uiDefButBitS(block, TOG3, MAP_ALPHA, B_MATPRV, "Alpha", 110,160,50,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the alpha value");
uiDefButBitS(block, TOG3, MAP_EMIT, B_MATPRV, "Emit", 160,160,45,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the emit value");
uiDefButBitS(block, TOG3, MAP_TRANSLU, B_MATPRV, "TransLu", 205,160,60,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the layer blending value");
if(from_nodes==0)
uiDefButBitS(block, TOG3, MAP_DISPLACE, B_MATPRV, "Disp", 265,160,45,19, &(mtex->mapto), 0, 0, 0, 0, "Let the texture displace the surface");
}
}
uiBlockEndAlign(block);
uiBlockBeginAlign(block);
uiDefButS(block, MENU, B_MATPRV, mapto_blendtype_pup(),155,125,155,19, &(mtex->blendtype), 0, 0, 0, 0, "Texture blending mode");
but=uiDefButS(block, MENU, B_MATPRV, mapto_blendtype_pup(),155,125,155,19, &(mtex->blendtype), 0, 0, 0, 0, "Texture blending mode");
uiBlockEndAlign(block);
if(psys_mapto && mtex->pmapto & MAP_PA_INIT)
uiButSetFunc(but, particle_recalc_material, ma, NULL);
uiBlockBeginAlign(block);
uiDefButF(block, NUMSLI, B_MATPRV, "Col ", 155,100,155,19, &(mtex->colfac), 0.0, 1.0, 0, 0, "Sets the amount the texture affects color values");
/* newnoise: increased range to 25, the constant offset for bumpmapping quite often needs a higher nor setting */
uiDefButF(block, NUMSLI, B_MATPRV, "Nor ", 155,80,155,19, &(mtex->norfac), 0.0, 25.0, 0, 0, "Sets the amount the texture affects normal values");
uiDefButF(block, NUMSLI, B_MATPRV, "Var ", 155,60,155,19, &(mtex->varfac), 0.0, 1.0, 0, 0, "Sets the amount the texture affects other values");
but=uiDefButF(block, NUMSLI, B_MATPRV, "Var ", 155,60,155,19, &(mtex->varfac), 0.0, 1.0, 0, 0, "Sets the amount the texture affects other values");
if(psys_mapto && mtex->pmapto & MAP_PA_INIT)
uiButSetFunc(but, particle_recalc_material, ma, NULL);
uiDefButF(block, NUMSLI, B_MATPRV, "Disp ", 155,40,155,19, &(mtex->dispfac), 0.0, 1.0, 0, 0, "Sets the amount the texture displaces the surface");
uiBlockBeginAlign(block);
@ -3200,7 +3302,7 @@ static void material_panel_map_input(Object *ob, Material *ma)
uiDefButS(block, ROW, B_MATPRV, "UV", 630,160,40,18, &(mtex->texco), 4.0, (float)TEXCO_UV, 0, 0, "Uses UV coordinates for texture coordinates");
uiDefButS(block, ROW, B_MATPRV, "Orco", 670,160,55,18, &(mtex->texco), 4.0, (float)TEXCO_ORCO, 0, 0, "Uses the original undeformed coordinates of the object");
if( give_parteff(ob) )
if( ob->particlesystem.first )
uiDefButS(block, ROW, B_MATPRV, "Strand", 725,160,50,18, &(mtex->texco), 4.0, (float)TEXCO_STRAND, 0, 0, "Uses normalized strand texture coordinate (1D)");
else
uiDefButS(block, ROW, B_MATPRV, "Stick", 725,160,50,18, &(mtex->texco), 4.0, (float)TEXCO_STICKY, 0, 0, "Uses mesh's sticky coordinates for the texture coordinates");
@ -3244,12 +3346,14 @@ static void material_panel_map_input(Object *ob, Material *ma)
}
static void material_panel_texture(Material *ma)
static void material_panel_texture(Object *ob, Material *ma)
{
uiBlock *block;
uiBut *but;
MTex *mtex;
ID *id;
int loos;
ParticleSystem *psys;
int loos, psys_mapto=0;
int a;
char str[64], *strp;
@ -3257,6 +3361,11 @@ static void material_panel_texture(Material *ma)
if(uiNewPanel(curarea, block, "Texture", "Material", 960, 0, 318, 204)==0) return;
uiClearButLock();
/*check if material is being used by particles*/
for(psys=ob->particlesystem.first; psys; psys=psys->next)
if(psys->part->omat==ob->actcol)
psys_mapto=1;
/* TEX CHANNELS */
uiBlockSetCol(block, TH_BUT_NEUTRAL);
@ -3278,7 +3387,10 @@ static void material_panel_texture(Material *ma)
for(a= 0; a<MAX_MTEX; a++) {
mtex= ma->mtex[a];
if(mtex && mtex->tex) {
uiDefIconButBitS(block, ICONTOGN, 1<<a, B_MATPRV, ICON_CHECKBOX_HLT-1, -20, 180-18*a, 28, 20, &ma->septex, 0.0, 0.0, 0, 0, "Click to disable or enable this texture channel");
but=uiDefIconButBitS(block, ICONTOGN, 1<<a, B_MATPRV, ICON_CHECKBOX_HLT-1, -20, 180-18*a, 28, 20, &ma->septex, 0.0, 0.0, 0, 0, "Click to disable or enable this texture channel");
if(psys_mapto && ma->mtex[a]->mapto & MAP_PA_IVEL)
uiButSetFunc(but, particle_recalc_material, ma, NULL);
}
}
uiBlockBeginAlign(block);
@ -3740,14 +3852,22 @@ static uiBlock *strand_menu(void *mat_v)
block= uiNewBlock(&curarea->uiblocks, "strand menu", UI_EMBOSS, UI_HELV, curarea->win);
/* use this for a fake extra empy space around the buttons */
uiDefBut(block, LABEL, 0, "", 0, 0, 250, 100, NULL, 0, 0, 0, 0, "");
uiDefBut(block, LABEL, 0, "", 0, 0, 250, 120, NULL, 0, 0, 0, 0, "");
uiBlockBeginAlign(block);
/* event return 0, to prevent menu to close */
uiDefButBitI(block, TOG, MA_TANGENT_STR, 0, "Use Tangent Shading", 10,70,230,20, &(ma->mode), 0, 0, 0, 0, "Uses direction of strands as normal for tangent-shading");
uiDefButF(block, NUMSLI, 0, "Start ", 10, 50, 230,20, &ma->strand_sta, 0.25, 20.0, 2, 0, "Start size of strands in pixels");
uiDefButF(block, NUMSLI, 0, "End ", 10, 30, 230,20, &ma->strand_end, 0.25, 10.0, 2, 0, "End size of strands in pixels");
uiDefButF(block, NUMSLI, 0, "Shape ", 10, 10, 230,20, &ma->strand_ease, -0.9, 0.9, 2, 0, "Shape of strands, positive value makes it rounder, negative makes it spiky");
uiDefButBitI(block, TOG, MA_TANGENT_STR, 0, "Use Tangent Shading", 10,90,115,20, &(ma->mode), 0, 0, 0, 0, "Uses direction of strands as normal for tangent-shading");
uiDefButBitI(block, TOG, MA_STR_B_UNITS, 0, "Use Blender Units", 125,90,115,20, &(ma->mode), 0, 0, 0, 0, "Use actual Blender units for widths instead of pixels");
if(ma->mode & MA_STR_B_UNITS){
uiDefButF(block, NUMSLI, 0, "Start ", 10, 70, 230,20, &ma->strand_sta, 0.01, 20.0, 2, 0, "Start size of strands in Blender units");
uiDefButF(block, NUMSLI, 0, "End ", 10, 50, 230,20, &ma->strand_end, 0.01, 10.0, 2, 0, "End size of strands in Blender units");
}
else{
uiDefButF(block, NUMSLI, 0, "Start ", 10, 70, 230,20, &ma->strand_sta, 0.25, 20.0, 2, 0, "Start size of strands in pixels");
uiDefButF(block, NUMSLI, 0, "End ", 10, 50, 230,20, &ma->strand_end, 0.25, 10.0, 2, 0, "End size of strands in pixels");
}
uiDefButF(block, NUMSLI, 0, "Shape ", 10, 30, 230,20, &ma->strand_ease, -0.9, 0.9, 2, 0, "Shape of strands, positive value makes it rounder, negative makes it spiky");
uiDefBut(block, TEX, B_MATPRV, "UV:", 10,10,230,20, ma->strand_uvname, 0, 31, 0, 0, "Set name of UV layer to override");
uiBlockSetDirection(block, UI_TOP);
BIF_preview_changed(ID_MA);
@ -4045,12 +4165,12 @@ void material_panels()
}
material_panel_sss(ma);
material_panel_texture(ma);
material_panel_texture(ob, ma);
mtex= ma->mtex[ ma->texact ];
if(mtex && mtex->tex) {
material_panel_map_input(ob, ma);
material_panel_map_to(ma, from_nodes);
material_panel_map_to(ob, ma, from_nodes);
}
}
}

@ -61,6 +61,7 @@
#include "DNA_modifier_types.h"
#include "DNA_object_types.h"
#include "DNA_object_force.h"
#include "DNA_particle_types.h"
#include "DNA_space_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
@ -74,6 +75,7 @@
#include "BLI_arithb.h"
#include "BLI_editVert.h"
#include "BLI_edgehash.h"
#include "BLI_rand.h"
#include "BKE_utildefines.h"
#include "BKE_curve.h"
@ -93,6 +95,8 @@
#include "BKE_modifier.h"
#include "BKE_object.h"
#include "BKE_anim.h" //for the where_on_path function
#include "BKE_particle.h"
#include "BKE_utildefines.h"
#ifdef WITH_VERSE
#include "BKE_verse.h"
#endif
@ -100,6 +104,7 @@
#include "BIF_editarmature.h"
#include "BIF_editdeform.h"
#include "BIF_editmesh.h"
#include "BIF_editparticle.h"
#include "BIF_glutil.h"
#include "BIF_gl.h"
#include "BIF_glutil.h"
@ -108,6 +113,7 @@
#include "BIF_retopo.h"
#include "BIF_screen.h"
#include "BIF_space.h"
#include "BIF_toolbox.h"
#include "BDR_drawmesh.h"
#include "BDR_drawobject.h"
@ -2954,6 +2960,743 @@ static void draw_static_particle_system(Object *ob, PartEff *paf, int dt)
}
/* unified drawing of all new particle systems draw types except dupli ob & group */
/* mostly tries to use vertex arrays for speed */
/* 1. check that everything is ok & updated */
/* 2. start initialising things */
/* 3. initialize according to draw type */
/* 4. allocate drawing data arrays */
/* 5. start filling the arrays */
/* 6. draw the arrays */
/* 7. clean up */
static void draw_new_particle_system(Base *base, ParticleSystem *psys)
{
View3D *v3d= G.vd;
Object *ob=base->object;
ParticleSystemModifierData *psmd;
ParticleSettings *part;
ParticleData *pars, *pa;
ParticleKey state, *states=0;
ParticleCacheKey *cache=0;
Material *ma;
Object *bb_ob=0;
float vel[3], vec[3], vec2[3], imat[4][4], onevec[3]={0.0f,0.0f,0.0f}, bb_center[3];
float timestep, pixsize=1.0, pa_size, pa_time, r_tilt;
float cfra=bsystem_time(ob,(float)CFRA,0.0);
float *vdata=0, *vedata=0, *cdata=0, *ndata=0, *vd=0, *ved=0, *cd=0, *nd=0, xvec[3], yvec[3], zvec[3];
int a, k, k_max=0, totpart, totpoint=0, draw_as, path_nbr=0;
int path_possible=0, keys_possible=0, draw_keys=0, totchild=0;
int select=ob->flag&SELECT;
GLint polygonmode[2];
char val[32];
/* 1. */
if(psys==0)
return;
part=psys->part;
pars=psys->particles;
if(part==0 || (psys->flag & PSYS_ENABLED)==0)
return;
if(pars==0) return;
if(!G.obedit && psys_in_edit_mode(psys)
&& psys->flag & PSYS_HAIR_DONE && part->draw_as==PART_DRAW_PATH)
return;
if(part->draw_as==PART_DRAW_NOT) return;
/* 2. */
if(part->phystype==PART_PHYS_KEYED){
if(psys->flag & PSYS_FIRST_KEYED){
if(psys->flag&PSYS_KEYED){
select=psys_count_keyed_targets(ob,psys);
if(psys->totkeyed==0)
return;
}
}
else
return;
}
if(select){
select=0;
if(psys_get_current(ob)==psys)
select=1;
}
psys->flag|=PSYS_DRAWING;
if(part->flag&PART_CHILD_RENDER || !psys->childcache)
totchild=0;
else
totchild=psys->totchild*part->disp/100;
ma= give_current_material(ob,part->omat);
if(select)
cpack(0xFFFFFF);
else if(part->draw&PART_DRAW_MAT_COL)
glColor3f(ma->r,ma->g,ma->b);
else
cpack(0);
psmd= psys_get_modifier(ob,psys);
timestep= psys_get_timestep(part);
myloadmatrix(G.vd->viewmat);
if( (base->flag & OB_FROMDUPLI) && (ob->flag & OB_FROMGROUP) ) {
float mat[4][4];
Mat4MulMat4(mat, psys->imat, ob->obmat);
mymultmatrix(mat);
}
totpart=psys->totpart;
draw_as=part->draw_as;
if(part->flag&PART_ABS_TIME && part->ipo){
calc_ipo(part->ipo, cfra);
execute_ipo((ID *)part, part->ipo);
}
if(part->flag&PART_GLOB_TIME)
cfra=bsystem_time(0,(float)CFRA,0.0);
if(psys->pathcache){
path_possible=1;
keys_possible=1;
}
if(draw_as==PART_DRAW_PATH && path_possible==0)
draw_as=PART_DRAW_DOT;
if(draw_as!=PART_DRAW_PATH && keys_possible && part->draw&PART_DRAW_KEYS){
path_nbr=part->keys_step;
draw_keys=1;
}
/* 3. */
switch(draw_as){
case PART_DRAW_DOT:
if(part->draw_size)
glPointSize(part->draw_size);
else
glPointSize(2.0); /* default dot size */
break;
case PART_DRAW_CIRC:
/* calculate view aligned matrix: */
Mat4CpyMat4(imat, G.vd->viewinv);
Normalize(imat[0]);
Normalize(imat[1]);
/* no break! */
case PART_DRAW_CROSS:
case PART_DRAW_AXIS:
/* lets calculate the scale: */
pixsize= v3d->persmat[0][3]*ob->obmat[3][0]+ v3d->persmat[1][3]*ob->obmat[3][1]+ v3d->persmat[2][3]*ob->obmat[3][2]+ v3d->persmat[3][3];
pixsize*= v3d->pixsize;
if(part->draw_size==0.0)
pixsize*=2.0;
else
pixsize*=part->draw_size;
break;
case PART_DRAW_OB:
if(part->dup_ob==0)
draw_as=PART_DRAW_DOT;
else
draw_as=0;
break;
case PART_DRAW_GR:
if(part->dup_group==0)
draw_as=PART_DRAW_DOT;
else
draw_as=0;
break;
case PART_DRAW_BB:
if(G.vd->camera==0 && part->bb_ob==0){
error("Billboards need an active camera or a target object!");
draw_as=part->draw_as=PART_DRAW_DOT;
if(part->draw_size)
glPointSize(part->draw_size);
else
glPointSize(2.0); /* default dot size */
}
else if(part->bb_ob)
bb_ob=part->bb_ob;
else
bb_ob=G.vd->camera;
if(part->bb_align<PART_BB_VIEW)
onevec[part->bb_align]=1.0f;
break;
case PART_DRAW_PATH:
break;
}
if(part->draw & PART_DRAW_SIZE && part->draw_as!=PART_DRAW_CIRC){
Mat4CpyMat4(imat, G.vd->viewinv);
Normalize(imat[0]);
Normalize(imat[1]);
}
/* 4. */
if(draw_as && draw_as!=PART_DRAW_PATH){
if(draw_as!=PART_DRAW_CIRC){
switch(draw_as){
case PART_DRAW_AXIS:
cdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*6*3*sizeof(float), "particle_cdata");
/* no break! */
case PART_DRAW_CROSS:
vdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*6*3*sizeof(float), "particle_vdata");
break;
case PART_DRAW_LINE:
vdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*2*3*sizeof(float), "particle_vdata");
break;
case PART_DRAW_BB:
vdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*4*3*sizeof(float), "particle_vdata");
ndata=MEM_callocN((totpart+totchild)*(path_nbr+1)*4*3*sizeof(float), "particle_vdata");
break;
default:
vdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*3*sizeof(float), "particle_vdata");
}
}
if(part->draw&PART_DRAW_VEL && draw_as!=PART_DRAW_LINE)
vedata=MEM_callocN((totpart+totchild)*2*3*(path_nbr+1)*sizeof(float), "particle_vedata");
vd=vdata;
ved=vedata;
cd=cdata;
nd=ndata;
psys->lattice=psys_get_lattice(ob,psys);
}
if(draw_as){
/* 5. */
for(a=0,pa=pars; a<totpart+totchild; a++, pa++){
if(a<totpart){
if(totchild && (part->draw&PART_DRAW_PARENT)==0) continue;
if(pa->flag & PARS_NO_DISP || pa->flag & PARS_UNEXIST) continue;
pa_time=(cfra-pa->time)/pa->lifetime;
if((part->flag&PART_ABS_TIME)==0 && part->ipo){
calc_ipo(part->ipo, 100*pa_time);
execute_ipo((ID *)part, part->ipo);
}
pa_size=pa->size;
r_tilt=1.0f+pa->r_ave[0];
if(path_nbr){
cache=psys->pathcache[a];
k_max=(int)(cache->steps);
}
}
else{
pa_time=psys_get_child_time(psys,a-totpart,cfra);
if((part->flag&PART_ABS_TIME)==0 && part->ipo){
calc_ipo(part->ipo, 100*pa_time);
execute_ipo((ID *)part, part->ipo);
}
pa_size=psys_get_child_size(psys,a-totpart,cfra,0);
r_tilt=2.0f*psys->child[a-totpart].rand[2];
if(path_nbr){
cache=psys->childcache[a-totpart];
k_max=(int)(cache->steps);
}
}
if(draw_as!=PART_DRAW_PATH){
int next_pa=0;
for(k=0; k<=path_nbr; k++){
if(draw_keys){
state.time=(float)k/(float)path_nbr;
psys_get_particle_on_path(ob,psys,a,&state,1);
}
else if(path_nbr){
if(k<=k_max){
VECCOPY(state.co,(cache+k)->co);
VECCOPY(state.vel,(cache+k)->vel);
QUATCOPY(state.rot,(cache+k)->rot);
}
else
continue;
}
else{
state.time=cfra;
if(psys_get_particle_state(ob,psys,a,&state,0)==0){
next_pa=1;
break;
}
}
switch(draw_as){
case PART_DRAW_DOT:
if(vd){
VECCOPY(vd,state.co) vd+=3;
}
break;
case PART_DRAW_CROSS:
case PART_DRAW_AXIS:
vec[0]=2.0f*pixsize;
vec[1]=vec[2]=0.0;
QuatMulVecf(state.rot,vec);
if(draw_as==PART_DRAW_AXIS){
cd[1]=cd[2]=cd[4]=cd[5]=0.0;
cd[0]=cd[3]=1.0;
cd[6]=cd[8]=cd[9]=cd[11]=0.0;
cd[7]=cd[10]=1.0;
cd[13]=cd[12]=cd[15]=cd[16]=0.0;
cd[14]=cd[17]=1.0;
cd+=18;
VECCOPY(vec2,state.co);
}
else VECSUB(vec2,state.co,vec);
VECADD(vec,state.co,vec);
VECCOPY(vd,vec); vd+=3;
VECCOPY(vd,vec2); vd+=3;
vec[1]=2.0f*pixsize;
vec[0]=vec[2]=0.0;
QuatMulVecf(state.rot,vec);
if(draw_as==PART_DRAW_AXIS){
VECCOPY(vec2,state.co);
}
else VECSUB(vec2,state.co,vec);
VECADD(vec,state.co,vec);
VECCOPY(vd,vec); vd+=3;
VECCOPY(vd,vec2); vd+=3;
vec[2]=2.0f*pixsize;
vec[0]=vec[1]=0.0;
QuatMulVecf(state.rot,vec);
if(draw_as==PART_DRAW_AXIS){
VECCOPY(vec2,state.co);
}
else VECSUB(vec2,state.co,vec);
VECADD(vec,state.co,vec);
VECCOPY(vd,vec); vd+=3;
VECCOPY(vd,vec2); vd+=3;
break;
case PART_DRAW_LINE:
VECCOPY(vec,state.vel);
Normalize(vec);
if(part->draw & PART_DRAW_VEL_LENGTH)
VecMulf(vec,VecLength(state.vel));
VECADDFAC(vd,state.co,vec,-part->draw_line[0]); vd+=3;
VECADDFAC(vd,state.co,vec,part->draw_line[1]); vd+=3;
break;
case PART_DRAW_CIRC:
drawcircball(GL_LINE_LOOP, state.co, pixsize, imat);
break;
case PART_DRAW_BB:
if(part->draw&PART_DRAW_BB_LOCK && part->bb_align==PART_BB_VIEW){
VECCOPY(xvec,bb_ob->obmat[0]);
Normalize(xvec);
VECCOPY(yvec,bb_ob->obmat[1]);
Normalize(yvec);
VECCOPY(zvec,bb_ob->obmat[2]);
Normalize(zvec);
}
else if(part->bb_align==PART_BB_VEL){
float temp[3];
VECCOPY(temp,state.vel);
Normalize(temp);
VECSUB(zvec,bb_ob->obmat[3],state.co);
if(part->draw&PART_DRAW_BB_LOCK){
float fac=-Inpf(zvec,temp);
VECADDFAC(zvec,zvec,temp,fac);
}
Normalize(zvec);
Crossf(xvec,temp,zvec);
Normalize(xvec);
Crossf(yvec,zvec,xvec);
}
else{
VECSUB(zvec,bb_ob->obmat[3],state.co);
if(part->draw&PART_DRAW_BB_LOCK)
zvec[part->bb_align]=0.0f;
Normalize(zvec);
if(part->bb_align<PART_BB_VIEW)
Crossf(xvec,onevec,zvec);
else
Crossf(xvec,bb_ob->obmat[1],zvec);
Normalize(xvec);
Crossf(yvec,zvec,xvec);
}
VECCOPY(vec,xvec);
VECCOPY(vec2,yvec);
VecMulf(xvec,cos(part->bb_tilt*(1.0f-part->bb_rand_tilt*r_tilt)*(float)M_PI));
VecMulf(vec2,sin(part->bb_tilt*(1.0f-part->bb_rand_tilt*r_tilt)*(float)M_PI));
VECADD(xvec,xvec,vec2);
VecMulf(yvec,cos(part->bb_tilt*(1.0f-part->bb_rand_tilt*r_tilt)*(float)M_PI));
VecMulf(vec,-sin(part->bb_tilt*(1.0f-part->bb_rand_tilt*r_tilt)*(float)M_PI));
VECADD(yvec,yvec,vec);
VecMulf(xvec,pa_size);
VecMulf(yvec,pa_size);
VECADDFAC(bb_center,state.co,xvec,part->bb_offset[0]);
VECADDFAC(bb_center,bb_center,yvec,part->bb_offset[1]);
VECADD(vd,bb_center,xvec);
VECADD(vd,vd,yvec); vd+=3;
VECSUB(vd,bb_center,xvec);
VECADD(vd,vd,yvec); vd+=3;
VECSUB(vd,bb_center,xvec);
VECSUB(vd,vd,yvec); vd+=3;
VECADD(vd,bb_center,xvec);
VECSUB(vd,vd,yvec); vd+=3;
VECCOPY(nd, zvec); nd+=3;
VECCOPY(nd, zvec); nd+=3;
VECCOPY(nd, zvec); nd+=3;
VECCOPY(nd, zvec); nd+=3;
break;
}
if(vedata){
VECCOPY(ved,state.co);
ved+=3;
VECCOPY(vel,state.vel);
VecMulf(vel,timestep);
VECADD(ved,state.co,vel);
ved+=3;
}
if(part->draw & PART_DRAW_SIZE){
setlinestyle(3);
drawcircball(GL_LINE_LOOP, state.co, pa_size, imat);
setlinestyle(0);
}
totpoint++;
}
if(next_pa)
continue;
if(part->draw&PART_DRAW_NUM){
/* in path drawing state.co is the end point */
glRasterPos3f(state.co[0], state.co[1], state.co[2]);
sprintf(val," %i",a);
BMF_DrawString(G.font, val);
}
}
}
/* 6. */
glGetIntegerv(GL_POLYGON_MODE, polygonmode);
if(draw_as != PART_DRAW_CIRC){
glDisableClientState(GL_NORMAL_ARRAY);
if(draw_as==PART_DRAW_PATH){
ParticleCacheKey **cache, *path;
float *cd2=0,*cdata2=0;
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnable(GL_LIGHTING);
if(totchild && (part->draw&PART_DRAW_PARENT)==0)
totpart=0;
cache=psys->pathcache;
for(a=0, pa=psys->particles; a<totpart; a++, pa++){
path=cache[a];
glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->co);
glNormalPointer(GL_FLOAT, sizeof(ParticleCacheKey), path->vel);
glDrawArrays(GL_LINE_STRIP, 0, path->steps + 1);
}
cache=psys->childcache;
for(a=0; a<totchild; a++){
path=cache[a];
glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->co);
glNormalPointer(GL_FLOAT, sizeof(ParticleCacheKey), path->vel);
glDrawArrays(GL_LINE_STRIP, 0, path->steps + 1);
}
if(cdata2)
MEM_freeN(cdata2);
cd2=cdata2=0;
glLineWidth(1.0f);
/* draw particle edit mode key points*/
}
if(draw_as!=PART_DRAW_PATH){
glDisableClientState(GL_COLOR_ARRAY);
if(vdata){
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, vdata);
}
else
glDisableClientState(GL_VERTEX_ARRAY);
if(ndata && MIN2(G.vd->drawtype, ob->dt)>OB_WIRE){
glEnableClientState(GL_NORMAL_ARRAY);
glNormalPointer(GL_FLOAT, 0, ndata);
glEnable(GL_LIGHTING);
}
else{
glDisableClientState(GL_NORMAL_ARRAY);
glDisable(GL_LIGHTING);
}
switch(draw_as){
case PART_DRAW_AXIS:
case PART_DRAW_CROSS:
if(cdata){
glEnableClientState(GL_COLOR_ARRAY);
glColorPointer(3, GL_FLOAT, 0, cdata);
}
glDrawArrays(GL_LINES, 0, 6*totpoint);
break;
case PART_DRAW_LINE:
glDrawArrays(GL_LINES, 0, 2*totpoint);
break;
case PART_DRAW_BB:
if(MIN2(G.vd->drawtype, ob->dt)<=OB_WIRE)
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
glDrawArrays(GL_QUADS, 0, 4*totpoint);
break;
default:
glDrawArrays(GL_POINTS, 0, totpoint);
break;
}
}
}
if(vedata){
glDisableClientState(GL_COLOR_ARRAY);
cpack(0xC0C0C0);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, vedata);
glDrawArrays(GL_LINES, 0, 2*totpoint);
}
glPolygonMode(GL_FRONT, polygonmode[0]);
glPolygonMode(GL_BACK, polygonmode[1]);
}
/* 7. */
glDisable(GL_LIGHTING);
glDisableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnable(GL_DEPTH_TEST);
if(states)
MEM_freeN(states);
if(vdata)
MEM_freeN(vdata);
if(vedata)
MEM_freeN(vedata);
if(cdata)
MEM_freeN(cdata);
if(ndata)
MEM_freeN(ndata);
psys->flag &= ~PSYS_DRAWING;
if(psys->lattice){
end_latt_deform();
psys->lattice=0;
}
myloadmatrix(G.vd->viewmat);
mymultmatrix(ob->obmat); // bring back local matrix for dtx
}
static void draw_particle_edit(Object *ob, ParticleSystem *psys)
{
ParticleEdit *edit = psys->edit;
ParticleData *pa;
ParticleCacheKey **path;
ParticleEditKey *key;
ParticleEditSettings *pset = PE_settings();
/*Mesh *me= (Mesh*)ob->data;*/
Material *ma;
int i, k, totpart = psys->totpart, totchild=0, timed = pset->draw_timed;
char nosel[4], sel[4];
float sel_col[3];
float nosel_col[3];
char val[32];
if(psys->pathcache==0){
PE_hide_keys_time(psys,CFRA);
psys_cache_paths(ob,psys,CFRA,0);
}
if(pset->flag & PE_SHOW_CHILD && psys->part->draw_as == PART_DRAW_PATH) {
if(psys->childcache==0)
psys_cache_child_paths(ob, psys, CFRA, 0);
}
else if(psys->childcache)
free_child_path_cache(psys);
if((G.vd->flag & V3D_ZBUF_SELECT)==0)
glDisable(GL_DEPTH_TEST);
myloadmatrix(G.vd->viewmat);
BIF_GetThemeColor3ubv(TH_VERTEX_SELECT, sel);
BIF_GetThemeColor3ubv(TH_VERTEX, nosel);
sel_col[0]=(float)sel[0]/255.0f;
sel_col[1]=(float)sel[1]/255.0f;
sel_col[2]=(float)sel[2]/255.0f;
nosel_col[0]=(float)nosel[0]/255.0f;
nosel_col[1]=(float)nosel[1]/255.0f;
nosel_col[2]=(float)nosel[2]/255.0f;
if(psys->childcache)
totchild = psys->totchildcache;
/* draw paths */
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
if(timed)
glEnable(GL_BLEND);
if(pset->brushtype == PE_BRUSH_WEIGHT){
glLineWidth(2.0f);
glEnableClientState(GL_COLOR_ARRAY);
glDisable(GL_LIGHTING);
}
for(i=0, pa=psys->particles, path = psys->pathcache; i<totpart; i++, pa++, path++){
/*if(me->mface[pa->num].flag & ME_HIDE)
continue;*/
glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), (*path)->co);
glNormalPointer(GL_FLOAT, sizeof(ParticleCacheKey), (*path)->vel);
glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), (*path)->col);
glDrawArrays(GL_LINE_STRIP, 0, (int)(*path)->steps + 1);
}
if(psys->part->draw&PART_DRAW_MAT_COL) {
ma= give_current_material(ob,psys->part->omat);
glColor3f(ma->r,ma->g,ma->b);
glDisableClientState(GL_COLOR_ARRAY);
}
glEnable(GL_LIGHTING);
for(i=0, path=psys->childcache; i<totchild; i++,path++){
glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), (*path)->co);
glNormalPointer(GL_FLOAT, sizeof(ParticleCacheKey), (*path)->vel);
glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), (*path)->col);
glDrawArrays(GL_LINE_STRIP, 0, (int)(*path)->steps + 1);
}
/* draw edit vertices */
if(G.scene->selectmode!=SCE_SELECT_PATH){
glDisableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glDisable(GL_LIGHTING);
glPointSize(4.0f);
if(G.scene->selectmode==SCE_SELECT_POINT){
float *cd=0,*cdata=0;
cd=cdata=MEM_callocN(edit->totkeys*(timed?4:3)*sizeof(float), "particle edit color data");
for(i=0, pa=psys->particles; i<totpart; i++, pa++){
for(k=0, key=edit->keys[i]; k<pa->totkey; k++, key++){
if(key->flag&PEK_SELECT){
VECCOPY(cd,sel_col);
}
else{
VECCOPY(cd,nosel_col);
}
if(timed)
*(cd+3) = (key->flag&PEK_HIDE)?0.0f:1.0f;
cd += (timed?4:3);
}
}
cd=cdata;
for(i=0, pa=psys->particles; i<totpart; i++, pa++){
if((pa->flag & PARS_HIDE)==0){
glVertexPointer(3, GL_FLOAT, sizeof(ParticleEditKey), edit->keys[i]->world_co);
glColorPointer((timed?4:3), GL_FLOAT, (timed?4:3)*sizeof(float), cd);
glDrawArrays(GL_POINTS, 0, pa->totkey);
}
cd += (timed?4:3) * pa->totkey;
if(pset->flag&PE_SHOW_TIME && (pa->flag&PARS_HIDE)==0){
for(k=0, key=edit->keys[i]+k; k<pa->totkey; k++, key++){
if(key->flag & PEK_HIDE) continue;
glRasterPos3fv(key->world_co);
sprintf(val," %.1f",*key->time);
BMF_DrawString(G.font, val);
}
}
}
if(cdata)
MEM_freeN(cdata);
cd=cdata=0;
}
else if(G.scene->selectmode == SCE_SELECT_END){
for(i=0, pa=psys->particles; i<totpart; i++, pa++){
if((pa->flag & PARS_HIDE)==0){
key = edit->keys[i] + pa->totkey - 1;
if(key->flag & PEK_SELECT)
glColor3fv(sel_col);
else
glColor3fv(nosel_col);
/* has to be like this.. otherwise selection won't work, have try glArrayElement later..*/
glBegin(GL_POINTS);
glVertex3fv(key->world_co);
glEnd();
if(pset->flag & PE_SHOW_TIME){
glRasterPos3fv(key->world_co);
sprintf(val," %.1f",*key->time);
BMF_DrawString(G.font, val);
}
}
}
}
}
glDisable(GL_BLEND);
glDisable(GL_LIGHTING);
glDisableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnable(GL_DEPTH_TEST);
glLineWidth(1.0f);
mymultmatrix(ob->obmat); // bring back local matrix for dtx
}
unsigned int nurbcol[8]= {
0, 0x9090, 0x409030, 0x603080, 0, 0x40fff0, 0x40c033, 0xA090F0 };
@ -3367,7 +4110,49 @@ void drawcircball(int mode, float *cent, float rad, float tmat[][4])
}
glEnd();
}
/* needs fixing if non-identity matrice used */
static void drawtube(float *vec, float radius, float height, float tmat[][4])
{
float cur[3];
drawcircball(GL_LINE_LOOP, vec, radius, tmat);
VecCopyf(cur,vec);
cur[2]+=height;
drawcircball(GL_LINE_LOOP, cur, radius, tmat);
glBegin(GL_LINES);
glVertex3f(vec[0]+radius,vec[1],vec[2]);
glVertex3f(cur[0]+radius,cur[1],cur[2]);
glVertex3f(vec[0]-radius,vec[1],vec[2]);
glVertex3f(cur[0]-radius,cur[1],cur[2]);
glVertex3f(vec[0],vec[1]+radius,vec[2]);
glVertex3f(cur[0],cur[1]+radius,cur[2]);
glVertex3f(vec[0],vec[1]-radius,vec[2]);
glVertex3f(cur[0],cur[1]-radius,cur[2]);
glEnd();
}
/* needs fixing if non-identity matrice used */
static void drawcone(float *vec, float radius, float height, float tmat[][4])
{
float cur[3];
VecCopyf(cur,vec);
cur[2]+=height;
drawcircball(GL_LINE_LOOP, cur, radius, tmat);
glBegin(GL_LINES);
glVertex3f(vec[0],vec[1],vec[2]);
glVertex3f(cur[0]+radius,cur[1],cur[2]);
glVertex3f(vec[0],vec[1],vec[2]);
glVertex3f(cur[0]-radius,cur[1],cur[2]);
glVertex3f(vec[0],vec[1],vec[2]);
glVertex3f(cur[0],cur[1]+radius,cur[2]);
glVertex3f(vec[0],vec[1],vec[2]);
glVertex3f(cur[0],cur[1]-radius,cur[2]);
glEnd();
}
/* return 1 if nothing was drawn */
static int drawmball(Base *base, int dt)
{
@ -3497,7 +4282,7 @@ static void draw_forcefield(Object *ob)
else if (pd->forcefield == PFIELD_VORTEX) {
float ffall_val, force_val;
Mat4One(imat);
Mat4One(tmat);
if (has_ipo_code(ob->ipo, OB_PD_FFALL))
ffall_val = IPO_GetFloatValue(ob->ipo, OB_PD_FFALL, G.scene->r.cfra);
else
@ -3510,12 +4295,12 @@ static void draw_forcefield(Object *ob)
BIF_ThemeColorBlend(curcol, TH_BACK, 0.7);
if (force_val < 0) {
drawspiral(vec, size*1.0, imat, 1);
drawspiral(vec, size*1.0, imat, 16);
drawspiral(vec, size*1.0, tmat, 1);
drawspiral(vec, size*1.0, tmat, 16);
}
else {
drawspiral(vec, size*1.0, imat, -1);
drawspiral(vec, size*1.0, imat, -16);
drawspiral(vec, size*1.0, tmat, -1);
drawspiral(vec, size*1.0, tmat, -16);
}
}
else if (pd->forcefield == PFIELD_GUIDE && ob->type==OB_CURVE) {
@ -3543,14 +4328,66 @@ static void draw_forcefield(Object *ob)
VECCOPY(vec, guidevec1); /* max center */
}
}
/* as last, guide curve alters it */
if(pd->flag & PFIELD_USEMAX) {
setlinestyle(3);
BIF_ThemeColorBlend(curcol, TH_BACK, 0.5);
drawcircball(GL_LINE_LOOP, vec, pd->maxdist, imat);
setlinestyle(0);
setlinestyle(3);
BIF_ThemeColorBlend(curcol, TH_BACK, 0.5);
if(pd->falloff==PFIELD_FALL_SPHERE){
/* as last, guide curve alters it */
if(pd->flag & PFIELD_USEMAX)
drawcircball(GL_LINE_LOOP, vec, pd->maxdist, imat);
if(pd->flag & PFIELD_USEMIN)
drawcircball(GL_LINE_LOOP, vec, pd->mindist, imat);
}
else if(pd->falloff==PFIELD_FALL_TUBE){
float radius,distance;
Mat4One(tmat);
vec[0]=vec[1]=0.0f;
radius=(pd->flag&PFIELD_USEMAXR)?pd->maxrad:1.0f;
distance=(pd->flag&PFIELD_USEMAX)?pd->maxdist:0.0f;
vec[2]=distance;
distance=(pd->flag&PFIELD_POSZ)?-distance:-2.0f*distance;
if(pd->flag & (PFIELD_USEMAX|PFIELD_USEMAXR))
drawtube(vec,radius,distance,tmat);
radius=(pd->flag&PFIELD_USEMINR)?pd->minrad:1.0f;
distance=(pd->flag&PFIELD_USEMIN)?pd->mindist:0.0f;
vec[2]=distance;
distance=(pd->flag&PFIELD_POSZ)?-distance:-2.0f*distance;
if(pd->flag & (PFIELD_USEMIN|PFIELD_USEMINR))
drawtube(vec,radius,distance,tmat);
}
else if(pd->falloff==PFIELD_FALL_CONE){
float radius,distance;
Mat4One(tmat);
radius=(pd->flag&PFIELD_USEMAXR)?pd->maxrad:1.0f;
radius*=(float)M_PI/180.0f;
distance=(pd->flag&PFIELD_USEMAX)?pd->maxdist:0.0f;
if(pd->flag & (PFIELD_USEMAX|PFIELD_USEMAXR)){
drawcone(vec,distance*sin(radius),distance*cos(radius),tmat);
if((pd->flag & PFIELD_POSZ)==0)
drawcone(vec,distance*sin(radius),-distance*cos(radius),tmat);
}
radius=(pd->flag&PFIELD_USEMINR)?pd->minrad:1.0f;
radius*=(float)M_PI/180.0f;
distance=(pd->flag&PFIELD_USEMIN)?pd->mindist:0.0f;
if(pd->flag & (PFIELD_USEMIN|PFIELD_USEMINR)){
drawcone(vec,distance*sin(radius),distance*cos(radius),tmat);
if((pd->flag & PFIELD_POSZ)==0)
drawcone(vec,distance*sin(radius),-distance*cos(radius),tmat);
}
}
setlinestyle(0);
}
static void draw_box(float vec[8][3])
@ -4200,6 +5037,26 @@ void draw_object(Base *base, int flag)
}
if(ob->pd && ob->pd->forcefield) draw_forcefield(ob);
/* code for new particle system */
if(warning_recursive==0 && (flag & DRAW_PICKING)==0){
glDepthMask(GL_FALSE);
if(col || (ob->flag & SELECT)) cpack(0xFFFFFF); /* for visibility, also while wpaint */
if(ob->particlesystem.first) {
ParticleSystem *psys;
for(psys=ob->particlesystem.first; psys; psys=psys->next)
draw_new_particle_system(base, psys);
if(G.f & G_PARTICLEEDIT && ob==OBACT) {
psys= PE_get_current(ob);
if(psys && !G.obedit && psys_in_edit_mode(psys))
draw_particle_edit(ob, psys);
}
}
if(col) cpack(col);
glDepthMask(GL_TRUE);
}
{
bConstraint *con;
for(con=ob->constraints.first; con; con= con->next)

@ -74,14 +74,7 @@ void set_scene(Scene *sce) /* also see scene.c: set_scene_bg() */
if( G.obedit)
exit_editmode(EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR);
if(G.f & G_VERTEXPAINT)
set_vpaint();
if(G.f & G_TEXTUREPAINT)
set_texturepaint();
if(G.f & G_WEIGHTPAINT)
set_wpaint();
if(G.f & G_SCULPTMODE)
set_sculptmode();
exit_paint_modes();
G.scene= sce;

@ -71,6 +71,7 @@
#include "DNA_meshdata_types.h"
#include "DNA_meta_types.h"
#include "DNA_object_types.h"
#include "DNA_particle_types.h"
#include "DNA_screen_types.h"
#include "DNA_scene_types.h"
#include "DNA_space_types.h"
@ -101,6 +102,7 @@
#include "BKE_main.h"
#include "BKE_mesh.h"
#include "BKE_object.h"
#include "BKE_particle.h"
#include "BKE_scene.h"
#include "BKE_texture.h"
#include "BKE_utildefines.h"
@ -110,6 +112,7 @@
#include "BIF_editgroup.h"
#include "BIF_editarmature.h"
#include "BIF_editmesh.h"
#include "BIF_editparticle.h"
#include "BIF_gl.h"
#include "BIF_glutil.h"
#include "BIF_interface.h"
@ -2224,7 +2227,6 @@ void do_viewbuts(unsigned short event)
}
}
static void view3d_panel_object(short cntrl) // VIEW3D_HANDLER_OBJECT
{
uiBlock *block;
@ -2245,8 +2247,16 @@ static void view3d_panel_object(short cntrl) // VIEW3D_HANDLER_OBJECT
uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | cntrl);
uiSetPanelHandler(VIEW3D_HANDLER_OBJECT); // for close and esc
if(!uiNewPanel(curarea, block, "Transform Properties", "View3d", 10, 230, 318, 204))
return;
if((G.f & G_SCULPTMODE) && !G.obedit) {
if(!uiNewPanel(curarea, block, "Transform Properties", "View3d", 10, 230, 425, 234))
return;
} else if(G.f & G_PARTICLEEDIT && !G.obedit){
if(!uiNewPanel(curarea, block, "Transform Properties", "View3d", 10, 230, 318, 234))
return;
} else {
if(!uiNewPanel(curarea, block, "Transform Properties", "View3d", 10, 230, 318, 204))
return;
}
uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
@ -2262,16 +2272,18 @@ static void view3d_panel_object(short cntrl) // VIEW3D_HANDLER_OBJECT
uiButSetFunc(bt, test_idbutton_cb, ob->id.name, NULL);
#endif
uiBlockBeginAlign(block);
uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_OBJECTPANELPARENT, "Par:", 160, 180, 140, 20, &ob->parent, "Parent Object");
if((ob->parent) && (ob->partype == PARBONE)) {
bt= uiDefBut(block, TEX, B_OBJECTPANELPARENT, "ParBone:", 160, 160, 140, 20, ob->parsubstr, 0, 30, 0, 0, "");
uiButSetCompleteFunc(bt, autocomplete_bone, (void *)ob->parent);
if((G.f & G_PARTICLEEDIT)==0) {
uiBlockBeginAlign(block);
uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_OBJECTPANELPARENT, "Par:", 160, 180, 140, 20, &ob->parent, "Parent Object");
if((ob->parent) && (ob->partype == PARBONE)) {
bt= uiDefBut(block, TEX, B_OBJECTPANELPARENT, "ParBone:", 160, 160, 140, 20, ob->parsubstr, 0, 30, 0, 0, "");
uiButSetCompleteFunc(bt, autocomplete_bone, (void *)ob->parent);
}
else {
strcpy(ob->parsubstr, "");
}
uiBlockEndAlign(block);
}
else {
strcpy(ob->parsubstr, "");
}
uiBlockEndAlign(block);
}
lim= 10000.0f*MAX2(1.0, G.vd->grid);
@ -2305,6 +2317,9 @@ static void view3d_panel_object(short cntrl) // VIEW3D_HANDLER_OBJECT
else if(G.f & G_SCULPTMODE) {
uiNewPanelTitle(block, "Sculpt Properties");
sculptmode_draw_interface_tools(block,10,150);
} else if(G.f & G_PARTICLEEDIT){
uiNewPanelTitle(block, "Particle Edit Properties");
particle_edit_buttons(block);
} else {
BoundBox *bb = NULL;
@ -2771,6 +2786,7 @@ void drawview3dspace(ScrArea *sa, void *spacedata)
for(SETLOOPER(G.scene->set, base))
object_handle_update(base->object); // bke_object.h
}
for(base= G.scene->base.first; base; base= base->next)
object_handle_update(base->object); // bke_object.h
@ -2906,7 +2922,8 @@ void drawview3dspace(ScrArea *sa, void *spacedata)
if(G.moving) {
BIF_drawConstraint();
if(G.obedit) BIF_drawPropCircle(); // only editmode has proportional edit
if(G.obedit || (G.f & G_PARTICLEEDIT))
BIF_drawPropCircle(); // only editmode and particles have proportional edit
BIF_drawSnap();
}
@ -3008,6 +3025,17 @@ void drawview3dspace(ScrArea *sa, void *spacedata)
}
retopo_draw_paint_lines();
if(!G.obedit && OBACT && G.f&G_PARTICLEEDIT && area_is_active_area(v3d->area)){
ParticleSystem *psys = PE_get_current(OBACT);
ParticleEditSettings *pset = PE_settings();
short c[2];
if(psys && psys->edit && pset->brushtype>=0){
getmouseco_areawin(c);
fdrawXORcirc((float)c[0], (float)c[1], (float)pset->brush[pset->brushtype].size);
}
}
if(v3d->persp>1) drawviewborder();
if(v3d->flag2 & V3D_FLYMODE) drawviewborder_flymode();
if(!(G.f & G_PLAYANIM)) drawcursor(v3d);

@ -52,12 +52,14 @@
#include "DNA_action_types.h"
#include "DNA_armature_types.h"
#include "DNA_curve_types.h"
#include "DNA_group_types.h"
#include "DNA_ipo_types.h"
#include "DNA_lattice_types.h"
#include "DNA_meta_types.h"
#include "DNA_mesh_types.h"
#include "DNA_modifier_types.h"
#include "DNA_object_types.h"
#include "DNA_particle_types.h"
#include "DNA_screen_types.h"
#include "DNA_scene_types.h"
#include "DNA_space_types.h"
@ -81,6 +83,7 @@
#include "BKE_mesh.h"
#include "BKE_modifier.h"
#include "BKE_object.h"
#include "BKE_particle.h"
#include "BKE_utildefines.h"
#ifdef WITH_VERSE
@ -90,6 +93,7 @@
#include "BIF_editmesh.h"
#include "BIF_editview.h"
#include "BIF_editarmature.h"
#include "BIF_editparticle.h"
#include "BIF_gl.h"
#include "BIF_glutil.h"
#include "BIF_interface.h"
@ -425,6 +429,9 @@ int get_border(rcti *rect, short flag)
else if (FACESEL_PAINT_TEST) {
circle_selectCB(&obedit_selectionCB);
}
else if (G.f&G_PARTICLEEDIT) {
circle_selectCB(&PE_selectionCB);
}
return 0;
case SPACE_IMAGE: // brush select in UV editor
@ -477,7 +484,7 @@ void draw_sel_circle(short *mval, short *mvalo, float rad, float rado, int selec
void circle_selectCB(select_CBfunc callback)
{
static float rad= 40.0;
float rado;
float rado= rad;
int firsttime=1;
int escape= 0;
unsigned short event;
@ -495,8 +502,6 @@ void circle_selectCB(select_CBfunc callback)
draw_sel_circle(mval, NULL, rad, 0.0, selecting); // draws frontbuffer, but sets backbuf again
rado= rad;
while(TRUE) {
if(mval[0]!=mvalo[0] || mval[1]!=mvalo[1] || rado!=rad || firsttime) {
@ -787,8 +792,47 @@ void countall()
ob= base->object; /* warning, ob not is obact anymore */
if(base->flag & SELECT) G.totobjsel++;
if(ob->parent && (ob->parent->transflag & (OB_DUPLIVERTS|OB_DUPLIFACES))) {
if(ob->transflag & OB_DUPLIPARTS) {
ParticleSystem *psys;
ParticleSettings *part;
int step_nbr;
for(psys=ob->particlesystem.first; psys; psys=psys->next){
part=psys->part;
//if(psys->flag&PSYS_BAKED && part->draw&PART_DRAW_KEYS)
// step_nbr=part->keys_step;
//else
step_nbr=1;
if(part->draw_as==PART_DRAW_OB && part->dup_ob){
int tot=count_particles(psys);
count_object(part->dup_ob, 0, tot*step_nbr);
}
else if(part->draw_as==PART_DRAW_GR && part->dup_group){
GroupObject *go;
int tot, totgroup=0, cur=0;
go= part->dup_group->gobject.first;
while(go){
go=go->next;
totgroup++;
}
go= part->dup_group->gobject.first;
while(go){
tot=count_particles_mod(psys,totgroup,cur);
count_object(go->ob, 0, tot*step_nbr);
cur++;
go=go->next;
}
}
}
count_object(ob, base->flag & SELECT, 1);
G.totobj++;
}
else if(ob->parent && (ob->parent->transflag & (OB_DUPLIVERTS|OB_DUPLIFACES))) {
int tot= count_duplilist(ob->parent);
G.totobj+=tot;
count_object(ob, base->flag & SELECT, tot);
@ -1818,6 +1862,9 @@ void delete_context_selected(void)
else if(G.obedit->type==OB_MBALL) delete_mball();
else if (G.obedit->type==OB_ARMATURE) delete_armature();
}
else if(G.f & G_PARTICLEEDIT){
PE_delete_particle();
}
else delete_obj(0);
}
@ -1829,9 +1876,9 @@ void duplicate_context_selected(void)
else if(G.obedit->type==OB_MBALL) adduplicate_mball();
else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) adduplicate_nurb();
}
else {
else if(G.f & G_PARTICLEEDIT);
else
adduplicate(0, U.dupflag);
}
}
void toggle_shading(void)

@ -62,6 +62,7 @@
#include "DNA_material_types.h"
#include "DNA_object_types.h"
#include "DNA_object_fluidsim.h"
#include "DNA_particle_types.h"
#include "DNA_screen_types.h"
#include "DNA_scene_types.h"
#include "DNA_space_types.h"
@ -82,6 +83,7 @@
#include "BKE_ipo.h"
#include "BKE_key.h"
#include "BKE_material.h"
#include "BKE_particle.h"
#include "BKE_texture.h"
#include "BKE_utildefines.h"
@ -131,6 +133,7 @@ extern int ac_ar[];
extern int co_ar[];
extern int te_ar[];
extern int fluidsim_ar[]; // NT
extern int part_ar[];
/* forwards */
#define IPOTHRESH 0.9
@ -344,6 +347,22 @@ void editipo_changed(SpaceIpo *si, int doredraw)
DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA);
allqueue(REDRAWVIEW3D, 0);
}
else if(si->blocktype==ID_PA){
Object *ob=OBACT;
ParticleSystem *psys = ob->particlesystem.first;
/* find out if we need to initialize particles */
for(; psys; psys=psys->next) {
if(psys->part->ipo==si->ipo) {
ei= si->editipo;
for(a=0; a<si->totipo; a++, ei++)
if(ei->icu && ELEM3(ei->icu->adrcode,PART_EMIT_FREQ,PART_EMIT_LIFE,PART_EMIT_SIZE))
psys_flush_settings(psys->part,PSYS_INIT,1);
}
}
DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA);
allqueue(REDRAWVIEW3D, 0);
}
}
if(si->showkey) make_ipokey();
@ -436,6 +455,49 @@ static void make_ob_editipo(Object *ob, SpaceIpo *si)
//fprintf(stderr,"FSIMAKE_OPBJ call %d \n", si->totipo);
}
static void make_part_editipo(SpaceIpo *si)
{
EditIpo *ei;
int a;
char *name;
if(si->from==0) return;
ei= si->editipo= MEM_callocN(PART_TOTIPO*sizeof(EditIpo), "editipo");
si->totipo= PART_TOTIPO;
for(a=0; a<PART_TOTIPO; a++) {
name = getname_part_ei(part_ar[a]);
strcpy(ei->name, name);
ei->adrcode= part_ar[a];
//if(ei->adrcode & MA_MAP1) {
// ei->adrcode-= MA_MAP1;
// ei->adrcode |= texchannel_to_adrcode(si->channel);
//}
//else {
// if(ei->adrcode==MA_MODE) ei->disptype= IPO_DISPBITS;
//}
ei->col= ipo_rainbow(a, PART_TOTIPO);
//len= strlen(ei->name);
//if(len) {
// if( ei->name[ len-1 ]=='R') ei->col= 0x5050FF;
// else if( ei->name[ len-1 ]=='G') ei->col= 0x50FF50;
// else if( ei->name[ len-1 ]=='B') ei->col= 0xFF7050;
//}
ei->icu= find_ipocurve(si->ipo, ei->adrcode);
if(ei->icu) {
ei->flag= ei->icu->flag;
}
ei++;
}
}
// copied from make_seq_editipo
static void make_fluidsim_editipo(SpaceIpo *si) // NT
{
@ -913,6 +975,12 @@ static void make_editipo(void)
make_fluidsim_editipo(G.sipo);
}
}
else if(G.sipo->blocktype==ID_PA) {
if (ob) {
ob->ipowin= ID_PA;
make_part_editipo(G.sipo);
}
}
if(G.sipo->editipo==0) return;
@ -1097,6 +1165,13 @@ static void get_ipo_context(short blocktype, ID **from, Ipo **ipo, char *actname
if(fss) *ipo= fss->ipo;
}
}
else if(blocktype==ID_PA) {
ParticleSystem *psys = psys_get_current(ob);
if(psys){
*from= (ID *)ob;
*ipo= psys->part->ipo;
}
}
}
/* called on each redraw, check if editipo data has to be remade */
@ -1760,6 +1835,16 @@ Ipo *verify_ipo(ID *from, short blocktype, char *actname, char *constname)
return fss->ipo;
}
}
else if(blocktype== ID_PA){
Object *ob= (Object *)from;
ParticleSystem *psys= psys_get_current(ob);
if(psys){
if(psys->part->ipo==0)
psys->part->ipo= add_ipo("ParticleIpo", ID_PA);
return psys->part->ipo;
}
return NULL;
}
}
break;
case ID_MA:
@ -2942,7 +3027,9 @@ void common_insertkey(void)
if(event==4) {
insertkey(id, ID_OB, NULL, NULL, OB_PD_FFALL, 0);
}
if(event==5) {
insertkey(id, ID_OB, NULL, NULL, OB_PD_FMAXD, 0);
}
}
}
}

@ -59,7 +59,7 @@ char *ob_ic_names[OB_TOTNAM] = { "LocX", "LocY", "LocZ", "dLocX", "dLocY", "dLoc
"RotX", "RotY", "RotZ", "dRotX", "dRotY", "dRotZ",
"ScaleX", "ScaleY", "ScaleZ", "dScaleX", "dScaleY", "dScaleZ",
"Layer", "Time", "ColR", "ColG", "ColB", "ColA",
"FStreng", "FFall", "RDamp", "Damping", "Perm" };
"FStreng", "FFall", "RDamp", "Damping", "Perm", "FMaxD" };
char *co_ic_names[CO_TOTNAM] = { "Inf", "HeadTail" };
char *mtex_ic_names[TEX_TOTNAM] = { "OfsX", "OfsY", "OfsZ", "SizeX", "SizeY", "SizeZ",
@ -101,6 +101,9 @@ char *ac_ic_names[AC_TOTNAM] = {"LocX", "LocY", "LocZ", "ScaleX", "ScaleY",
"ScaleZ", "QuatW", "QuatX", "QuatY", "QuatZ"};
char *ic_name_empty[1] ={ "" };
char *fluidsim_ic_names[FLUIDSIM_TOTNAM] = { "Fac-Visc", "Fac-Time", "GravX","GravY","GravZ", "VelX","VelY","VelZ", "Active" };
char *part_ic_names[PART_TOTNAM] = { "E_Freq", "E_Life", "E_Speed", "E_Angular", "E_Size",
"Angular", "Size", "Drag", "Brown", "Damp", "Length", "Clump",
"GravX", "GravY", "GravZ", "KinkAmp", "KinkFreq", "KinkShape", "BBTilt"};
/* gets the appropriate icon for the given blocktype */
int geticon_ipo_blocktype(short blocktype)
@ -199,7 +202,7 @@ char *getname_co_ei(int nr)
char *getname_ob_ei(int nr, int colipo)
{
if(nr>=OB_LOC_X && nr <= OB_PD_PERM) return ob_ic_names[nr-1];
if(nr>=OB_LOC_X && nr <= OB_PD_FMAXD) return ob_ic_names[nr-1];
return ic_name_empty[0];
}
@ -274,6 +277,11 @@ char *getname_fluidsim_ei(int nr)
if(nr <= FLUIDSIM_TOTIPO) return fluidsim_ic_names[nr-1];
return ic_name_empty[0];
}
char *getname_part_ei(int nr)
{
if(nr <= PART_TOTIPO) return part_ic_names[nr-1];
return ic_name_empty[0];
}
void boundbox_ipocurve(IpoCurve *icu, int selectedonly)

@ -80,6 +80,7 @@
#include "DNA_space_types.h"
#include "DNA_screen_types.h"
#include "DNA_texture_types.h"
#include "DNA_particle_types.h"
#include "DNA_property_types.h"
#include "DNA_userdef_types.h"
#include "DNA_view3d_types.h"
@ -118,6 +119,7 @@
#include "BKE_mesh.h"
#include "BKE_nla.h"
#include "BKE_object.h"
#include "BKE_particle.h"
#include "BKE_property.h"
#include "BKE_sca.h"
#include "BKE_scene.h"
@ -134,6 +136,7 @@
#include "BIF_editlattice.h"
#include "BIF_editmesh.h"
#include "BIF_editoops.h"
#include "BIF_editparticle.h"
#include "BIF_editview.h"
#include "BIF_editarmature.h"
#include "BIF_gl.h"
@ -183,11 +186,22 @@
/* --------------------------------- */
void exit_paint_modes(void)
{
if(G.f & G_VERTEXPAINT) set_vpaint();
if(G.f & G_TEXTUREPAINT) set_texturepaint();
if(G.f & G_WEIGHTPAINT) set_wpaint();
if(G.f & G_SCULPTMODE) set_sculptmode();
if(G.f & G_PARTICLEEDIT) PE_set_particle_edit();
G.f &= ~(G_VERTEXPAINT+G_TEXTUREPAINT+G_WEIGHTPAINT+G_SCULPTMODE+G_PARTICLEEDIT);
}
void add_object_draw(int type) /* for toolbox or menus, only non-editmode stuff */
{
Object *ob;
G.f &= ~(G_VERTEXPAINT+G_TEXTUREPAINT+G_WEIGHTPAINT+G_SCULPTMODE);
exit_paint_modes();
setcursor_space(SPACE_VIEW3D, CURSOR_STD);
if ELEM3(curarea->spacetype, SPACE_VIEW3D, SPACE_BUTS, SPACE_INFO) {
@ -262,8 +276,6 @@ void delete_obj(int ok)
if(G.obedit) return;
if(G.scene->id.lib) return;
if(G.f & G_SCULPTMODE) set_sculptmode();
base= FIRSTBASE;
while(base) {
Base *nbase= base->next;
@ -280,6 +292,8 @@ void delete_obj(int ok)
}
}
exit_paint_modes();
if(base->object->type==OB_LAMP) islamp= 1;
#ifdef WITH_VERSE
if(base->object->vnode) b_verse_delete_object(base->object);
@ -307,7 +321,6 @@ void delete_obj(int ok)
}
countall();
G.f &= ~(G_VERTEXPAINT+G_TEXTUREPAINT+G_WEIGHTPAINT);
setcursor_space(SPACE_VIEW3D, CURSOR_STD);
if(islamp) reshadeall_displist(); /* only frees displist */
@ -2275,6 +2288,39 @@ void special_editmenu(void)
pose_adds_vgroups(ob, (nr == 2));
}
}
else if(G.f & G_PARTICLEEDIT) {
ParticleSystem *psys = PE_get_current(ob);
ParticleEditSettings *pset = PE_settings();
if(!psys)
return;
if(G.scene->selectmode & SCE_SELECT_POINT)
nr= pupmenu("Specials%t|Rekey%x1|Subdivide%x2|Select First%x3|Select Last%x4");
else
nr= pupmenu("Specials%t|Rekey%x1");
switch(nr) {
case 1:
if(button(&pset->totrekey, 2, 100, "Number of Keys:")==0) return;
waitcursor(1);
PE_rekey();
break;
case 2:
PE_subdivide();
break;
case 3:
PE_select_root();
break;
case 4:
PE_select_tip();
break;
}
DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
if(nr>0) waitcursor(0);
}
else {
Base *base, *base_select= NULL;
@ -5351,7 +5397,10 @@ void mirrormenu(void)
short mode = 0;
if (G.obedit==0) {
if(G.f & G_PARTICLEEDIT) {
PE_mirror_x(0);
}
else if (G.obedit==0) {
mode=pupmenu("Mirror Axis %t|X Local%x4|Y Local%x5|Z Local%x6|");
if (mode==-1) return; /* return */

File diff suppressed because it is too large Load Diff

@ -178,6 +178,7 @@ static int choose_cursor(ScrArea *sa)
return CURSOR_VPAINT;
else if(FACESEL_PAINT_TEST) return CURSOR_FACESEL;
else if(G.f & G_SCULPTMODE) return CURSOR_EDIT;
else if(G.f & G_PARTICLEEDIT) return CURSOR_EDIT;
else return CURSOR_STD;
}
else if (sa->spacetype==SPACE_TEXT) {

@ -73,6 +73,7 @@
#include "BKE_main.h"
#include "BKE_mesh.h"
#include "BKE_object.h" /* fly mode where_is_object to get camera location */
#include "BKE_particle.h"
#include "BKE_utildefines.h"
#include "BKE_customdata.h"
@ -80,6 +81,7 @@
#include "BIF_butspace.h"
#include "BIF_editaction.h"
#include "BIF_editarmature.h"
#include "BIF_editparticle.h"
#include "BIF_editgroup.h"
#include "BIF_editmesh.h"
#include "BIF_editoops.h"
@ -248,7 +250,7 @@ static int edge_inside_rect(rcti *rect, short x1, short y1, short x2, short y2)
#define MOVES_GESTURE 50
#define MOVES_LASSO 500
static int lasso_inside(short mcords[][2], short moves, short sx, short sy)
int lasso_inside(short mcords[][2], short moves, short sx, short sy)
{
/* we do the angle rule, define that all added angles should be about zero or 2*PI */
float angletot=0.0, len, dot, ang, cross, fp1[2], fp2[2];
@ -641,6 +643,8 @@ static void do_lasso_select(short mcords[][2], short moves, short select)
do_lasso_select_facemode(mcords, moves, select);
else if(G.f & (G_VERTEXPAINT|G_TEXTUREPAINT|G_WEIGHTPAINT))
;
else if(G.f & G_PARTICLEEDIT)
PE_do_lasso_select(mcords, moves, select);
else
do_lasso_select_objects(mcords, moves, select);
}
@ -1161,18 +1165,8 @@ void set_active_base(Base *base)
Base *tbase;
/* activating a non-mesh, should end a couple of modes... */
if(base) {
if(base->object->type!=OB_MESH) {
if(G.f & G_SCULPTMODE)
set_sculptmode(); /* toggle */
if(G.f & G_WEIGHTPAINT)
set_wpaint(); /* toggle */
if(G.f & G_VERTEXPAINT)
set_vpaint(); /* toggle */
if(G.f & G_TEXTUREPAINT)
set_texturepaint(); /* Switch off tex paint */
}
}
if(base && base->object->type!=OB_MESH)
exit_paint_modes();
/* sets scene->basact */
BASACT= base;
@ -1745,6 +1739,10 @@ void borderselect(void)
face_borderselect();
return;
}
else if(G.obedit==NULL && (G.f & G_PARTICLEEDIT)) {
PE_borderselect();
return;
}
a = 0;
#ifdef __APPLE__

@ -690,7 +690,8 @@ void buts_buttons(void)
case CONTEXT_OBJECT:
uiBlockBeginAlign(block);
uiDefIconButC(block, ROW, B_CONTEXT_SWITCH, ICON_OBJECT, xco+=XIC, t_base, XIC, YIC, &(G.buts->tab[CONTEXT_OBJECT]), 1.0, (float)TAB_OBJECT_OBJECT, 0, 0, "Object buttons ");
uiDefIconButC(block, ROW, B_CONTEXT_SWITCH, ICON_EFFECTS, xco+=XIC, t_base, XIC, YIC, &(G.buts->tab[CONTEXT_OBJECT]), 1.0, (float)TAB_OBJECT_PHYSICS, 0, 0, "Physics buttons");
uiDefIconButC(block, ROW, B_CONTEXT_SWITCH, ICON_PHYSICS, xco+=XIC, t_base, XIC, YIC, &(G.buts->tab[CONTEXT_OBJECT]), 1.0, (float)TAB_OBJECT_PHYSICS, 0, 0, "Physics buttons");
uiDefIconButC(block, ROW, B_CONTEXT_SWITCH, ICON_PARTICLES, xco+=XIC, t_base, XIC, YIC, &(G.buts->tab[CONTEXT_OBJECT]), 1.0, (float)TAB_OBJECT_PARTICLE, 0, 0, "Particle buttons");
break;
case CONTEXT_SHADING:

@ -486,9 +486,7 @@ void do_info_buttons(unsigned short event)
/* exit modes... could become single call once */
exit_editmode(EM_FREEDATA|EM_WAITCURSOR);
if(G.f & G_VERTEXPAINT) set_vpaint(); /* Switch off vertex paint */
if(G.f & G_TEXTUREPAINT) set_texturepaint(); /* Switch off tex paint */
if(G.f & G_WEIGHTPAINT) set_wpaint(); /* Switch off weight paint */
exit_paint_modes();
/* check all sets */
sce1= G.main->scene.first;

@ -54,6 +54,7 @@
#include "DNA_material_types.h"
#include "DNA_object_types.h"
#include "DNA_object_fluidsim.h"
#include "DNA_particle_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_texture_types.h"
@ -69,6 +70,7 @@
#include "BKE_key.h"
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_particle.h"
#include "BKE_texture.h"
#include "BKE_utildefines.h"
@ -152,6 +154,15 @@ void spaceipo_assign_ipo(SpaceIpo *si, Ipo *ipo)
}
ob->fluidsimSettings->ipo = ipo;
}
else if(si->blocktype==ID_PA) {
ParticleSystem *psys=psys_get_current(ob);
if(psys){
if(psys->part->ipo){
psys->part->ipo->id.us--;
}
psys->part->ipo = ipo;
}
}
else if(si->blocktype==ID_OB) {
if(ob->ipo)
ob->ipo->id.us--;
@ -935,6 +946,10 @@ static char *ipo_modeselect_pup(void)
if(ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) {
str += sprintf(str,formatstring,"Fluidsim",ID_FLUIDSIM, ICON_WORLD);
}
if(ob->particlesystem.first) {
str += sprintf(str,formatstring,"Particles",ID_PA, ICON_PARTICLES);
}
}
str += sprintf(str,formatstring, "Sequence",ID_SEQ, ICON_SEQUENCE);
@ -1304,6 +1319,8 @@ void ipo_buttons(void)
icon = ICON_TEXTURE;
else if(G.sipo->blocktype == ID_FLUIDSIM)
icon = ICON_WORLD;
else if(G.sipo->blocktype == ID_PA)
icon = ICON_PARTICLES;
uiDefIconTextButS(block, MENU, B_IPOMAIN, icon, ipo_modeselect_pup(), xco,0,100,20, &(G.sipo->blocktype), 0, 0, 0, 0, "Show IPO type");

@ -72,6 +72,7 @@
#include "BKE_main.h"
#include "BKE_mesh.h"
#include "BKE_modifier.h"
#include "BKE_particle.h"
#include "BKE_utildefines.h" /* for VECCOPY */
#ifdef WITH_VERSE
@ -98,6 +99,7 @@
#include "BIF_editlattice.h"
#include "BIF_editarmature.h"
#include "BIF_editparticle.h"
#include "BIF_editconstraint.h"
#include "BIF_editdeform.h"
#include "BIF_editfont.h"
@ -150,6 +152,7 @@
#define V3D_TEXTUREPAINTMODE_SEL ICON_TPAINT_HLT
#define V3D_WEIGHTPAINTMODE_SEL ICON_WPAINT_HLT
#define V3D_POSEMODE_SEL ICON_POSE_HLT
#define V3D_PARTICLEEDITMODE_SEL ICON_ANIM
#define TEST_EDITMESH if(G.obedit==0) return; \
if( (G.vd->lay & G.obedit->lay)==0 ) return;
@ -4548,6 +4551,184 @@ static uiBlock *view3d_faceselmenu(void *arg_unused)
return block;
}
void do_view3d_select_particlemenu(void *arg, int event)
{
/* events >= 6 are registered bpython scripts */
if (event >= 6) BPY_menu_do_python(PYMENU_FACESELECT, event - 6);
switch(event) {
case 0:
PE_borderselect();
break;
case 1:
PE_deselectall();
break;
case 2:
PE_select_root();
break;
case 3:
PE_select_tip();
break;
case 4:
PE_select_more();
break;
case 5:
PE_select_less();
break;
case 7:
PE_select_linked();
break;
}
allqueue(REDRAWVIEW3D, 0);
}
static uiBlock *view3d_select_particlemenu(void *arg_unused)
{
uiBlock *block;
short yco= 0, menuwidth=120;
block= uiNewBlock(&curarea->uiblocks, "view3d_select_particlemenu", UI_EMBOSSP, UI_HELV, curarea->headwin);
uiBlockSetButmFunc(block, do_view3d_select_particlemenu, NULL);
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Border Select|B",
0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 0, "");
uiDefBut(block, SEPR, 0, "",
0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Select/Deselect All|A",
0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Select Linked|L",
0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 7, "");
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Select Last|W, 4",
0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Select First|W, 3",
0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
uiDefBut(block, SEPR, 0, "",
0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "More|Ctrl NumPad +",
0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, "");
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Less|Ctrl NumPad -",
0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 5, "");
if(curarea->headertype==HEADERTOP) {
uiBlockSetDirection(block, UI_DOWN);
}
else {
uiBlockSetDirection(block, UI_TOP);
uiBlockFlipOrder(block);
}
uiTextBoundsBlock(block, 50);
return block;
}
void do_view3d_particle_showhidemenu(void *arg, int event)
{
switch(event) {
case 1: /* show hidden */
PE_hide(0);
break;
case 2: /* hide selected */
PE_hide(2);
break;
case 3: /* hide deselected */
PE_hide(1);
break;
}
allqueue(REDRAWVIEW3D, 0);
}
static uiBlock *view3d_particle_showhidemenu(void *arg_unused)
{
uiBlock *block;
short yco = 20, menuwidth = 120;
block= uiNewBlock(&curarea->uiblocks, "view3d_particle_showhidemenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
uiBlockSetButmFunc(block, do_view3d_particle_showhidemenu, NULL);
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Show Hidden|Alt H",
0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Hide Selected|H",
0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Hide Deselected|Shift H",
0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
uiBlockSetDirection(block, UI_RIGHT);
uiTextBoundsBlock(block, 60);
return block;
}
void do_view3d_particlemenu(void *arg, int event)
{
ParticleEditSettings *pset= PE_settings();
switch(event) {
case 1:
add_blockhandler(curarea, VIEW3D_HANDLER_OBJECT, UI_PNL_UNSTOW);
break;
case 2:
if(button(&pset->totrekey, 2, 100, "Number of Keys:")==0) return;
PE_rekey();
break;
case 3:
PE_subdivide();
break;
case 4:
PE_delete_particle();
break;
case 5:
PE_mirror_x(0);
break;
case 6:
pset->flag ^= PE_X_MIRROR;
break;
}
allqueue(REDRAWVIEW3D, 0);
}
uiBlock *view3d_particlemenu(void *arg_unused)
{
uiBlock *block;
ParticleEditSettings *pset= PE_settings();
short yco= 0, menuwidth= 120;
block= uiNewBlock(&curarea->uiblocks, "view3d_particlemenu", UI_EMBOSSP, UI_HELV, curarea->headwin);
uiBlockSetButmFunc(block, do_view3d_particlemenu, NULL);
uiDefIconTextBut(block, BUTM, 1, ICON_MENU_PANEL, "Particle Edit Properties|N", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, "");
uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
uiDefIconTextBut(block, BUTM, 1, (pset->flag & PE_X_MIRROR)? ICON_CHECKBOX_HLT: ICON_CHECKBOX_DEHLT, "X-Axis Mirror Editing", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 6, "");
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Mirror|Ctrl M", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 5, "");
uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Delete...|X", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, "");
if(G.scene->selectmode & SCE_SELECT_POINT)
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Subdivide|W, 2", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Rekey|W, 1", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
uiDefIconTextBlockBut(block, view3d_particle_showhidemenu, NULL, ICON_RIGHTARROW_THIN, "Show/Hide Particles", 0, yco-=20, menuwidth, 19, "");
if(curarea->headertype==HEADERTOP) {
uiBlockSetDirection(block, UI_DOWN);
}
else {
uiBlockSetDirection(block, UI_TOP);
uiBlockFlipOrder(block);
}
uiTextBoundsBlock(block, 50);
return block;
}
static char *view3d_modeselect_pup(void)
{
@ -4584,7 +4765,11 @@ static char *view3d_modeselect_pup(void)
if (ob->type==OB_ARMATURE) {
str += sprintf(str, formatstr, "Pose Mode", V3D_POSEMODE_SEL, ICON_POSE_HLT);
}
if (ob->particlesystem.first) {
str += sprintf(str, formatstr, "Particle Mode", V3D_PARTICLEEDITMODE_SEL, ICON_PHYSICS);
}
return (string);
}
@ -4708,21 +4893,14 @@ void do_view3d_buttons(short event)
if (G.vd->modeselect == V3D_OBJECTMODE_SEL) {
G.vd->flag &= ~V3D_MODE;
if(G.f & G_SCULPTMODE) set_sculptmode(); /* Switch off sculptmode */
if(G.f & G_VERTEXPAINT) set_vpaint(); /* Switch off vertex paint */
if(G.f & G_TEXTUREPAINT) set_texturepaint(); /* Switch off tex paint */
if(G.f & G_WEIGHTPAINT) set_wpaint(); /* Switch off weight paint */
exit_paint_modes();
if(ob) exit_posemode(); /* exit posemode for active object */
if(G.obedit) exit_editmode(EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR); /* exit editmode and undo */
}
else if (G.vd->modeselect == V3D_EDITMODE_SEL) {
if(!G.obedit) {
G.vd->flag &= ~V3D_MODE;
if(G.f & G_SCULPTMODE) set_sculptmode(); /* Switch off sculptmode */
if(G.f & G_VERTEXPAINT) set_vpaint(); /* Switch off vertex paint */
if(G.f & G_TEXTUREPAINT) set_texturepaint(); /* Switch off tex paint */
if(G.f & G_WEIGHTPAINT) set_wpaint(); /* Switch off weight paint */
exit_paint_modes();
enter_editmode(EM_WAITCURSOR);
BIF_undo_push("Original"); /* here, because all over code enter_editmode is abused */
}
@ -4730,9 +4908,7 @@ void do_view3d_buttons(short event)
else if (G.vd->modeselect == V3D_SCULPTMODE_SEL) {
if (!(G.f & G_SCULPTMODE)) {
G.vd->flag &= ~V3D_MODE;
if(G.f & G_VERTEXPAINT) set_vpaint(); /* Switch off vertex paint */
if(G.f & G_TEXTUREPAINT) set_texturepaint(); /* Switch off tex paint */
if(G.f & G_WEIGHTPAINT) set_wpaint(); /* Switch off weight paint */
exit_paint_modes();
if(G.obedit) exit_editmode(2); /* exit editmode and undo */
set_sculptmode();
@ -4741,9 +4917,7 @@ void do_view3d_buttons(short event)
else if (G.vd->modeselect == V3D_VERTEXPAINTMODE_SEL) {
if (!(G.f & G_VERTEXPAINT)) {
G.vd->flag &= ~V3D_MODE;
if(G.f & G_SCULPTMODE) set_sculptmode(); /* Switch off sculptmode */
if(G.f & G_TEXTUREPAINT) set_texturepaint(); /* Switch off tex paint */
if(G.f & G_WEIGHTPAINT) set_wpaint(); /* Switch off weight paint */
exit_paint_modes();
if(G.obedit) exit_editmode(EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR); /* exit editmode and undo */
set_vpaint();
@ -4752,9 +4926,7 @@ void do_view3d_buttons(short event)
else if (G.vd->modeselect == V3D_TEXTUREPAINTMODE_SEL) {
if (!(G.f & G_TEXTUREPAINT)) {
G.vd->flag &= ~V3D_MODE;
if(G.f & G_SCULPTMODE) set_sculptmode(); /* Switch off sculptmode */
if(G.f & G_VERTEXPAINT) set_vpaint(); /* Switch off vertex paint */
if(G.f & G_WEIGHTPAINT) set_wpaint(); /* Switch off weight paint */
exit_paint_modes();
if(G.obedit) exit_editmode(EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR); /* exit editmode and undo */
set_texturepaint();
@ -4763,9 +4935,7 @@ void do_view3d_buttons(short event)
else if (G.vd->modeselect == V3D_WEIGHTPAINTMODE_SEL) {
if (!(G.f & G_WEIGHTPAINT) && (ob && ob->type == OB_MESH) ) {
G.vd->flag &= ~V3D_MODE;
if(G.f & G_SCULPTMODE) set_sculptmode(); /* Switch off sculptmode */
if(G.f & G_VERTEXPAINT) set_vpaint(); /* Switch off vertex paint */
if(G.f & G_TEXTUREPAINT) set_texturepaint(); /* Switch off tex paint */
exit_paint_modes();
if(G.obedit) exit_editmode(EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR); /* exit editmode and undo */
set_wpaint();
@ -4780,6 +4950,15 @@ void do_view3d_buttons(short event)
enter_posemode();
}
}
else if(G.vd->modeselect == V3D_PARTICLEEDITMODE_SEL){
if (!(G.f & G_PARTICLEEDIT)) {
G.vd->flag &= ~V3D_MODE;
exit_paint_modes();
if(G.obedit) exit_editmode(EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR); /* exit editmode and undo */
PE_set_particle_edit();
}
}
allqueue(REDRAWVIEW3D, 1);
break;
@ -4823,6 +5002,22 @@ void do_view3d_buttons(short event)
allqueue(REDRAWVIEW3D, 1);
allqueue(REDRAWIMAGE, 0); /* only needed in cases where mesh and UV selection are in sync */
break;
case B_SEL_PATH:
G.scene->selectmode= SCE_SELECT_PATH;
BIF_undo_push("Selectmode Set: Path");
allqueue(REDRAWVIEW3D, 1);
break;
case B_SEL_POINT:
G.scene->selectmode = SCE_SELECT_POINT;
BIF_undo_push("Selectmode Set: Point");
allqueue(REDRAWVIEW3D, 1);
break;
case B_SEL_END:
G.scene->selectmode = SCE_SELECT_END;
BIF_undo_push("Selectmode Set: End point");
allqueue(REDRAWVIEW3D, 1);
break;
case B_MAN_TRANS:
if( (G.qual & LR_SHIFTKEY)==0 || G.vd->twtype==0)
@ -4928,6 +5123,8 @@ static void view3d_header_pulldowns(uiBlock *block, short *xcoord)
}
} else if ((G.f & G_VERTEXPAINT) || (G.f & G_TEXTUREPAINT) || (G.f & G_WEIGHTPAINT)) {
uiDefBut(block, LABEL,0,"", xco, 0, xmax, 20, 0, 0, 0, 0, 0, "");
} else if (G.f & G_PARTICLEEDIT) {
uiDefPulldownBut(block, view3d_select_particlemenu, NULL, "Select", xco,-2, xmax-3, 24, "");
} else {
if (ob && (ob->flag & OB_POSEMODE))
@ -4995,7 +5192,13 @@ static void view3d_header_pulldowns(uiBlock *block, short *xcoord)
uiDefPulldownBut(block, view3d_faceselmenu, NULL, "Face", xco,-2, xmax-3, 24, "");
xco+= xmax;
}
} else {
}
else if(G.f & G_PARTICLEEDIT) {
xmax= GetButStringLength("Particle");
uiDefPulldownBut(block, view3d_particlemenu, NULL, "Particle", xco,-2, xmax-3, 24, "");
xco+= xmax;
}
else {
if (ob && (ob->flag & OB_POSEMODE)) {
xmax= GetButStringLength("Pose");
uiDefPulldownBut(block, view3d_pose_armaturemenu, NULL, "Pose", xco,-2, xmax-3, 24, "");
@ -5058,6 +5261,7 @@ void view3d_buttons(void)
else if (G.f & G_VERTEXPAINT) G.vd->modeselect = V3D_VERTEXPAINTMODE_SEL;
else if (G.f & G_TEXTUREPAINT) G.vd->modeselect = V3D_TEXTUREPAINTMODE_SEL;
/*else if(G.f & G_FACESELECT) G.vd->modeselect = V3D_FACESELECTMODE_SEL;*/
else if(G.f & G_PARTICLEEDIT) G.vd->modeselect = V3D_PARTICLEEDITMODE_SEL;
G.vd->flag &= ~V3D_MODE;
@ -5173,7 +5377,7 @@ void view3d_buttons(void)
}
/* proportional falloff */
if(G.obedit && (G.obedit->type == OB_MESH || G.obedit->type == OB_CURVE || G.obedit->type == OB_SURF || G.obedit->type == OB_LATTICE)) {
if((G.obedit && (G.obedit->type == OB_MESH || G.obedit->type == OB_CURVE || G.obedit->type == OB_SURF || G.obedit->type == OB_LATTICE)) || G.f & G_PARTICLEEDIT) {
uiBlockBeginAlign(block);
uiDefIconTextButS(block, ICONTEXTROW,B_REDR, ICON_PROP_OFF, "Proportional %t|Off %x0|On %x1|Connected %x2", xco,0,XIC+10,YIC, &(G.scene->proportional), 0, 1.0, 0, 0, "Proportional Edit Falloff (Hotkeys: O, Alt O) ");
@ -5220,7 +5424,22 @@ void view3d_buttons(void)
}
xco+= 20;
}
else if(G.f & G_PARTICLEEDIT) {
uiBlockBeginAlign(block);
uiDefIconButBitS(block, TOG, SCE_SELECT_PATH, B_SEL_PATH, ICON_EDGESEL, xco,0,XIC,YIC, &G.scene->selectmode, 1.0, 0.0, 0, 0, "Path edit mode (Ctrl Tab 1)");
xco+= XIC;
uiDefIconButBitS(block, TOG, SCE_SELECT_POINT, B_SEL_POINT, ICON_VERTEXSEL, xco,0,XIC,YIC, &G.scene->selectmode, 1.0, 0.0, 0, 0, "Point select mode (Ctrl Tab 2)");
xco+= XIC;
uiDefIconButBitS(block, TOG, SCE_SELECT_END, B_SEL_END, ICON_FACESEL, xco,0,XIC,YIC, &G.scene->selectmode, 1.0, 0.0, 0, 0, "Tip select mode (Ctrl Tab 3)");
xco+= XIC;
uiBlockEndAlign(block);
if(G.vd->drawtype > OB_WIRE) {
uiDefIconButBitS(block, TOG, V3D_ZBUF_SELECT, B_REDR, ICON_ORTHO, xco,0,XIC,YIC, &G.vd->flag, 1.0, 0.0, 0, 0, "Limit selection to visible (clipped with depth buffer)");
xco+= XIC;
}
xco+= 20;
}
uiDefIconBut(block, BUT, B_VIEWRENDER, ICON_SCENE_DEHLT, xco,0,XIC,YIC, NULL, 0, 1.0, 0, 0, "Render this window (hold CTRL for anim)");
if (ob && (ob->flag & OB_POSEMODE)) {

@ -255,7 +255,7 @@ int std_libbuttons(uiBlock *block, short xco, short yco,
if(browse) {
char *extrastr= NULL;
if(ELEM3(id_code, ID_MA, ID_TE, ID_BR)) add_addbutton= 1;
if(ELEM4(id_code, ID_MA, ID_TE, ID_BR, ID_PA)) add_addbutton= 1;
lb= wich_libbase(G.main, id_code);
@ -265,7 +265,7 @@ int std_libbuttons(uiBlock *block, short xco, short yco,
uiBlockSetCol(block, TH_BUT_SETTING2);
}
if ELEM8( id_code, ID_SCE, ID_SCR, ID_MA, ID_TE, ID_WO, ID_IP, ID_AC, ID_BR) extrastr= "ADD NEW %x 32767";
if (ELEM8( id_code, ID_SCE, ID_SCR, ID_MA, ID_TE, ID_WO, ID_IP, ID_AC, ID_BR) || id_code == ID_PA) extrastr= "ADD NEW %x 32767";
else if (id_code==ID_TXT) extrastr= "OPEN NEW %x 32766 |ADD NEW %x 32767";
else if (id_code==ID_SO) extrastr= "OPEN NEW %x 32766";
@ -1076,6 +1076,7 @@ void do_global_buttons(unsigned short event)
else if(nr==ID_CA) idtest= (ID *)add_ipo("CaIpo", nr);
else if(nr==ID_SO) idtest= (ID *)add_ipo("SndIpo", nr);
else if(nr==ID_FLUIDSIM) idtest= (ID *)add_ipo("FluidsimIpo", nr);
else if(nr==ID_PA) idtest= (ID *)add_ipo("PaIpo", nr);
else error("Warn bugtracker!");
}
idtest->us--;

@ -93,6 +93,7 @@ void sort_faces(void);
#include "BDR_sculptmode.h"
#include "BLI_editVert.h"
#include "BLI_ghash.h"
#include "BLI_threads.h"
#include "BLI_rand.h" /* for randome face sorting */
@ -820,6 +821,100 @@ EditVert *editmesh_get_x_mirror_vert(Object *ob, float *co)
return NULL;
}
static unsigned int mirror_facehash(void *ptr)
{
MFace *mf= ptr;
int v0, v1;
if(mf->v4) {
v0= MIN4(mf->v1, mf->v2, mf->v3, mf->v4);
v1= MAX4(mf->v1, mf->v2, mf->v3, mf->v4);
}
else {
v0= MIN3(mf->v1, mf->v2, mf->v3);
v1= MAX3(mf->v1, mf->v2, mf->v3);
}
return ((v0*39)^(v1*31));
}
static int mirror_facerotation(MFace *a, MFace *b)
{
if(b->v4) {
if(a->v1==b->v1 && a->v2==b->v2 && a->v3==b->v3 && a->v4==b->v4)
return 0;
else if(a->v4==b->v1 && a->v1==b->v2 && a->v2==b->v3 && a->v3==b->v4)
return 1;
else if(a->v3==b->v1 && a->v4==b->v2 && a->v1==b->v3 && a->v2==b->v4)
return 2;
else if(a->v2==b->v1 && a->v3==b->v2 && a->v4==b->v3 && a->v1==b->v4)
return 3;
}
else {
if(a->v1==b->v1 && a->v2==b->v2 && a->v3==b->v3)
return 0;
else if(a->v3==b->v1 && a->v1==b->v2 && a->v2==b->v3)
return 1;
else if(a->v2==b->v1 && a->v3==b->v2 && a->v1==b->v3)
return 2;
}
return -1;
}
static int mirror_facecmp(void *a, void *b)
{
return (mirror_facerotation((MFace*)a, (MFace*)b) == -1);
}
int *mesh_get_x_mirror_faces(Object *ob)
{
Mesh *me= ob->data;
MVert *mv, *mvert= me->mvert;
MFace mirrormf, *mf, *hashmf, *mface= me->mface;
GHash *fhash;
int *mirrorverts, *mirrorfaces;
float vec[3];
int a;
mirrorverts= MEM_callocN(sizeof(int)*me->totvert, "MirrorVerts");
mirrorfaces= MEM_callocN(sizeof(int)*2*me->totface, "MirrorFaces");
mesh_octree_table(ob, NULL, 's');
for(a=0, mv=mvert; a<me->totvert; a++, mv++) {
vec[0]= -mv->co[0];
vec[1]= mv->co[1];
vec[2]= mv->co[2];
mirrorverts[a]= mesh_octree_table(ob, vec, 'u');
}
mesh_octree_table(ob, NULL, 'e');
fhash= BLI_ghash_new(mirror_facehash, mirror_facecmp);
for(a=0, mf=mface; a<me->totface; a++, mf++)
BLI_ghash_insert(fhash, mf, mf);
for(a=0, mf=mface; a<me->totface; a++, mf++) {
mirrormf.v1= mirrorverts[mf->v3];
mirrormf.v2= mirrorverts[mf->v2];
mirrormf.v3= mirrorverts[mf->v1];
mirrormf.v4= (mf->v4)? mirrorverts[mf->v4]: 0;
hashmf= BLI_ghash_lookup(fhash, &mirrormf);
if(hashmf) {
mirrorfaces[a*2]= hashmf - mface;
mirrorfaces[a*2+1]= mirror_facerotation(&mirrormf, hashmf);
}
else
mirrorfaces[a*2]= -1;
}
BLI_ghash_free(fhash, NULL, NULL);
MEM_freeN(mirrorverts);
return mirrorfaces;
}
/* ****************** render BAKING ********************** */

@ -2873,9 +2873,6 @@ static PBool p_chart_lscm_solve(PChart *chart)
sinmax = MAX3(sina1, sina2, sina3);
/* shift vertices to find most stable order */
#define SHIFT3(type, a, b, c) \
{ type tmp; tmp = a; a = c; c = b; b = tmp; }
if (sina3 != sinmax) {
SHIFT3(PVert*, v1, v2, v3);
SHIFT3(float, a1, a2, a3);

File diff suppressed because it is too large Load Diff

@ -65,6 +65,7 @@
#include "DNA_meshdata_types.h"
#include "DNA_modifier_types.h" /* used for select grouped hooks */
#include "DNA_object_types.h"
#include "DNA_particle_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_sequence_types.h"
@ -90,6 +91,7 @@
#include "BKE_texture.h"
#include "BKE_utildefines.h"
#include "BKE_image.h" /* for IMA_TYPE_COMPOSITE and IMA_TYPE_R_RESULT */
#include "BKE_particle.h"
#include "BIF_spacetypes.h" /* first, nasty dependency with typedef */
@ -99,6 +101,7 @@
#include "BIF_drawtext.h"
#include "BIF_drawscript.h"
#include "BIF_editarmature.h"
#include "BIF_editparticle.h"
#include "BIF_editconstraint.h"
#include "BIF_editdeform.h"
#include "BIF_editfont.h"
@ -988,6 +991,9 @@ void BIF_undo_push(char *str)
else if (G.obedit->type==OB_ARMATURE)
undo_push_armature(str);
}
else if(G.f & G_PARTICLEEDIT) {
PE_undo_push(str);
}
else {
if(U.uiflag & USER_GLOBALUNDO)
BKE_write_undo(str);
@ -1005,6 +1011,8 @@ void BIF_undo(void)
imagepaint_undo();
else if(curarea->spacetype==SPACE_IMAGE && (G.sima->flag & SI_DRAWTOOL))
imagepaint_undo();
else if(G.f & G_PARTICLEEDIT)
PE_undo();
else {
/* now also in faceselect mode */
if(U.uiflag & USER_GLOBALUNDO) {
@ -1026,6 +1034,8 @@ void BIF_redo(void)
imagepaint_undo();
else if(curarea->spacetype==SPACE_IMAGE && (G.sima->flag & SI_DRAWTOOL))
imagepaint_undo();
else if(G.f & G_PARTICLEEDIT)
PE_redo();
else {
/* includes faceselect now */
if(U.uiflag & USER_GLOBALUNDO) {
@ -1044,7 +1054,9 @@ void BIF_undo_menu(void)
allqueue(REDRAWALL, 0);
}
else {
if(U.uiflag & USER_GLOBALUNDO) {
if(G.f & G_PARTICLEEDIT)
PE_undo_menu();
else if(U.uiflag & USER_GLOBALUNDO) {
char *menu= BKE_undo_menu_string();
if(menu) {
short event= pupmenu_col(menu, 20);
@ -1193,6 +1205,17 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
allqueue(REDRAWVIEW3D, 0);
}
}
else if(!G.obedit && OBACT && G.f&G_PARTICLEEDIT){
ParticleSystem *psys=PE_get_current(OBACT);
ParticleEditSettings *pset=PE_settings();
if(psys && psys->edit){
if(pset->brushtype>=0 &&
event!=LEFTMOUSE && event!=RIGHTMOUSE && event!=MIDDLEMOUSE &&
(event==MOUSEY || event==MOUSEX) && bwin_qtest(sa->win)==0) {
allqueue(REDRAWVIEW3D, 0);
}
}
}
/* Handle retopo painting */
if(retopo_mesh_paint_check()) {
@ -1557,7 +1580,7 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
* based on user preference USER_LMOUSESELECT
*/
case LEFTMOUSE:
if ((G.obedit) || !(G.f&(G_VERTEXPAINT|G_WEIGHTPAINT|G_TEXTUREPAINT))) {
if ((G.obedit) || !(G.f&(G_VERTEXPAINT|G_WEIGHTPAINT|G_TEXTUREPAINT|G_PARTICLEEDIT))) {
mouse_cursor();
}
else if (G.f & G_WEIGHTPAINT) {
@ -1569,6 +1592,12 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
else if (G.f & G_TEXTUREPAINT) {
imagepaint_paint(L_MOUSE, 1);
}
else if (G.f & G_PARTICLEEDIT) {
if(G.qual & LR_CTRLKEY)
mouse_cursor();
else if(!PE_brush_particles())
mouse_cursor();
}
break;
case MIDDLEMOUSE:
handle_view_middlemouse();
@ -1596,6 +1625,8 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
face_select();
else if( G.f & (G_VERTEXPAINT|G_TEXTUREPAINT))
sample_vpaint();
else if( G.f & G_PARTICLEEDIT)
PE_mouse_particles();
else
mouse_select(); /* does poses too */
break;
@ -1714,6 +1745,7 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
}
else {
if(FACESEL_PAINT_TEST) deselectall_tface();
else if(G.f & G_PARTICLEEDIT) PE_deselectall();
else {
/* by design, the center of the active object
* (which need not necessarily by selected) will
@ -1984,6 +2016,14 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
}
else if(FACESEL_PAINT_TEST)
hide_tface();
else if(G.f & G_PARTICLEEDIT) {
if(G.qual == LR_ALTKEY)
PE_hide(0);
else if(G.qual == LR_SHIFTKEY)
PE_hide(1);
else if(G.qual == 0)
PE_hide(2);
}
else if(ob && (ob->flag & OB_POSEMODE)) {
if (G.qual==0)
hide_selected_pose_bones();
@ -2097,6 +2137,9 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
else if(G.qual==LR_CTRLKEY)
select_linked_tfaces(2);
}
else if(G.f & G_PARTICLEEDIT) {
PE_select_linked();
}
else {
if((G.qual==0))
make_local_menu();
@ -2172,7 +2215,7 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
break;
case OKEY:
if (G.obedit) {
if (G.obedit || G.f&G_PARTICLEEDIT) {
if (G.qual==LR_SHIFTKEY) {
G.scene->prop_mode = (G.scene->prop_mode+1)%7;
allqueue(REDRAWHEADERS, 0);
@ -2377,6 +2420,10 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
}
}
}
else if(G.f & G_PARTICLEEDIT) {
initTransform(TFM_BAKE_TIME, CTX_NONE);
Transform();
}
else if(G.qual==LR_CTRLKEY) {
if(ob && (ob->flag & OB_POSEMODE));
else make_track();
@ -2405,6 +2452,9 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
uv_autocalc_tface();
}
}
else if (G.f & G_PARTICLEEDIT){
if(G.qual==0) BIF_undo(); else BIF_redo();
}
else if((G.qual==0)) {
if(G.f & G_WEIGHTPAINT)
BIF_undo();
@ -2583,6 +2633,9 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
else if ( (G.qual==LR_CTRLKEY)
&& (G.obedit) && (G.obedit->type==OB_SURF) )
select_less_nurb();
else if ( (G.qual==LR_CTRLKEY)
&& (G.f & G_PARTICLEEDIT) )
PE_select_less();
else {
persptoetsen(event);
doredraw= 1;
@ -2599,6 +2652,9 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
else if ( (G.qual==LR_CTRLKEY)
&& (G.obedit) && (G.obedit->type==OB_SURF) )
select_more_nurb();
else if ( (G.qual==LR_CTRLKEY)
&& (G.f & G_PARTICLEEDIT) )
PE_select_more();
else {
persptoetsen(event);
doredraw= 1;
@ -4396,6 +4452,8 @@ void extern_set_butspace(int fkey, int do_cycle)
if (sbuts->tab[CONTEXT_OBJECT]==TAB_OBJECT_OBJECT)
sbuts->tab[CONTEXT_OBJECT]=TAB_OBJECT_PHYSICS;
else if (sbuts->tab[CONTEXT_OBJECT]==TAB_OBJECT_PHYSICS)
sbuts->tab[CONTEXT_OBJECT]=TAB_OBJECT_PARTICLE;
else if (sbuts->tab[CONTEXT_OBJECT]==TAB_OBJECT_PARTICLE)
sbuts->tab[CONTEXT_OBJECT]=TAB_OBJECT_OBJECT;
}
else sbuts->mainb= CONTEXT_OBJECT;

@ -74,6 +74,7 @@
#include "BIF_editsound.h"
#include "BIF_editmesh.h"
#include "BIF_imasel.h"
#include "BIF_editparticle.h"
#include "BIF_interface.h"
#include "BKE_object.h"
#include "BIF_poseobject.h"
@ -740,6 +741,9 @@ int blenderqread(unsigned short event, short val)
}
}
}
else if(G.qual&LR_CTRLKEY && G.qual&LR_SHIFTKEY){
PE_set_particle_edit();
}
break;
case BACKSPACEKEY:

@ -75,6 +75,7 @@
#include "BIF_toolbox.h" /* notice */
#include "BIF_editmesh.h"
#include "BIF_editsima.h"
#include "BIF_editparticle.h"
#include "BIF_drawimage.h" /* uvco_to_areaco_noclip */
#include "BIF_editaction.h"
@ -82,6 +83,7 @@
#include "BKE_global.h"
#include "BKE_utildefines.h"
#include "BKE_bad_level_calls.h"/* popmenu and error */
#include "BKE_particle.h"
#include "BSE_drawipo.h"
#include "BSE_editnla_types.h" /* for NLAWIDTH */
@ -583,6 +585,8 @@ static char *transform_to_undostr(TransInfo *t)
return "Scale Anim. Data";
case TFM_TIME_SLIDE:
return "Time Slide";
case TFM_BAKE_TIME:
return "Key Time";
}
return "Transform";
}
@ -1009,6 +1013,9 @@ void initTransform(int mode, int context) {
/* now that transdata has been made, do like for TFM_TIME_TRANSLATE */
initTimeTranslate(&Trans);
break;
case TFM_BAKE_TIME:
initBakeTime(&Trans);
break;
}
}
@ -1401,6 +1408,9 @@ int Warp(TransInfo *t, short mval[2])
float loc[3];
if (td->flag & TD_NOACTION)
break;
if (td->flag & TD_SKIP)
continue;
/* translate point to center, rotate in such a way that outline==distance */
VECCOPY(vec, td->iloc);
@ -1527,6 +1537,9 @@ int Shear(TransInfo *t, short mval[2])
if (td->flag & TD_NOACTION)
break;
if (td->flag & TD_SKIP)
continue;
if (G.obedit) {
float mat3[3][3];
Mat3MulMat3(mat3, totmat, td->mtx);
@ -1805,6 +1818,9 @@ int Resize(TransInfo *t, short mval[2])
for(i = 0, td=t->data; i < t->total; i++, td++) {
if (td->flag & TD_NOACTION)
break;
if (td->flag & TD_SKIP)
continue;
ElementResize(t, td, mat);
}
@ -1896,6 +1912,9 @@ int ToSphere(TransInfo *t, short mval[2])
if (td->flag & TD_NOACTION)
break;
if (td->flag & TD_SKIP)
continue;
VecSubf(vec, td->iloc, t->center);
radius = Normalize(vec);
@ -1949,10 +1968,20 @@ static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3]) {
VecAddf(td->loc, vec, t->center);
VecSubf(vec,td->loc,td->iloc);
protectedTransBits(td->protectflag, vec);
VecAddf(td->loc, td->iloc, vec);
if(td->flag & TD_USEQUAT) {
Mat3MulSerie(fmat, td->mtx, mat, td->smtx, 0, 0, 0, 0, 0);
Mat3ToQuat(fmat, quat); // Actual transform
QuatMul(td->ext->quat, quat, td->ext->iquat);
if(td->ext->quat){
QuatMul(td->ext->quat, quat, td->ext->iquat);
/* is there a reason not to have this here? -jahka */
protectedQuaternionBits(td->protectflag, td->ext->quat, td->ext->iquat);
}
}
}
/**
@ -2111,6 +2140,9 @@ static void applyRotation(TransInfo *t, float angle, float axis[3])
if (td->flag & TD_NOACTION)
break;
if (td->flag & TD_SKIP)
continue;
/* local constraint shouldn't alter center */
if (t->around == V3D_LOCAL) {
@ -2271,6 +2303,9 @@ static void applyTrackball(TransInfo *t, float axis1[3], float axis2[3], float a
for(i = 0 ; i < t->total; i++, td++) {
if (td->flag & TD_NOACTION)
break;
if (td->flag & TD_SKIP)
continue;
VECCOPY(center, t->center);
@ -2450,6 +2485,9 @@ static void applyTranslation(TransInfo *t, float vec[3]) {
if (td->flag & TD_NOACTION)
break;
if (td->flag & TD_SKIP)
continue;
if (t->con.applyVec) {
float pvec[3];
t->con.applyVec(t, td, vec, tvec, pvec);
@ -2577,6 +2615,9 @@ int ShrinkFatten(TransInfo *t, short mval[2])
if (td->flag & TD_NOACTION)
break;
if (td->flag & TD_SKIP)
continue;
VECCOPY(vec, td->axismtx[2]);
VecMulf(vec, distance);
VecMulf(vec, td->factor);
@ -2668,6 +2709,9 @@ int Tilt(TransInfo *t, short mval[2])
if (td->flag & TD_NOACTION)
break;
if (td->flag & TD_SKIP)
continue;
if (td->val) {
*td->val = td->ival + final * td->factor;
}
@ -2729,6 +2773,9 @@ int CurveShrinkFatten(TransInfo *t, short mval[2])
for(i = 0 ; i < t->total; i++, td++) {
if (td->flag & TD_NOACTION)
break;
if (td->flag & TD_SKIP)
continue;
if(td->val) {
//*td->val= ratio;
@ -2818,6 +2865,9 @@ int PushPull(TransInfo *t, short mval[2])
if (td->flag & TD_NOACTION)
break;
if (td->flag & TD_SKIP)
continue;
VecSubf(vec, t->center, td->center);
if (t->con.applyRot && t->con.mode & CON_APPLY) {
t->con.applyRot(t, td, axis);
@ -2926,6 +2976,9 @@ int Crease(TransInfo *t, short mval[2])
if (td->flag & TD_NOACTION)
break;
if (td->flag & TD_SKIP)
continue;
if (td->val) {
*td->val = td->ival + crease * td->factor;
if (*td->val < 0.0f) *td->val = 0.0f;
@ -3069,6 +3122,9 @@ int BoneSize(TransInfo *t, short mval[2])
for(i = 0 ; i < t->total; i++, td++) {
if (td->flag & TD_NOACTION)
break;
if (td->flag & TD_SKIP)
continue;
ElementBoneSize(t, td, mat);
}
@ -3151,6 +3207,9 @@ int BoneEnvelope(TransInfo *t, short mval[2])
for(i = 0 ; i < t->total; i++, td++) {
if (td->flag & TD_NOACTION)
break;
if (td->flag & TD_SKIP)
continue;
if (td->val) {
/* if the old/original value was 0.0f, then just use ratio */
@ -3248,6 +3307,9 @@ int BoneRoll(TransInfo *t, short mval[2])
for (i = 0; i < t->total; i++, td++) {
if (td->flag & TD_NOACTION)
break;
if (td->flag & TD_SKIP)
continue;
*(td->val) = td->ival - final;
}
@ -3263,6 +3325,85 @@ int BoneRoll(TransInfo *t, short mval[2])
return 1;
}
/* ************************** BAKE TIME ******************* */
void initBakeTime(TransInfo *t)
{
t->idx_max = 0;
t->num.idx_max = 0;
t->snap[0] = 0.0f;
t->snap[1] = 1.0f;
t->snap[2] = t->snap[1] * 0.1f;
t->transform = BakeTime;
t->fac = 0.1f;
}
int BakeTime(TransInfo *t, short mval[2])
{
TransData *td = t->data;
float time;
int i;
char str[50];
if(t->flag & T_SHIFT_MOD) {
/* calculate ratio for shiftkey pos, and for total, and blend these for precision */
time= (float)(t->center2d[0] - t->shiftmval[0])*t->fac;
time+= 0.1f*((float)(t->center2d[0]*t->fac - mval[0]) -time);
}
else {
time = (float)(t->center2d[0] - mval[0])*t->fac;
}
snapGrid(t, &time);
applyNumInput(&t->num, &time);
/* header print for NumInput */
if (hasNumInput(&t->num)) {
char c[20];
outputNumInput(&(t->num), c);
if (time >= 0.0f)
sprintf(str, "Time: +%s %s", c, t->proptext);
else
sprintf(str, "Time: %s %s", c, t->proptext);
}
else {
/* default header print */
if (time >= 0.0f)
sprintf(str, "Time: +%.3f %s", time, t->proptext);
else
sprintf(str, "Time: %.3f %s", time, t->proptext);
}
for(i = 0 ; i < t->total; i++, td++) {
if (td->flag & TD_NOACTION)
break;
if (td->flag & TD_SKIP)
continue;
if (td->val) {
*td->val = td->ival + time * td->factor;
if (td->ext->size && *td->val < *td->ext->size) *td->val = *td->ext->size;
if (td->ext->quat && *td->val > *td->ext->quat) *td->val = *td->ext->quat;
}
}
recalcData(t);
headerprint(str);
viewRedrawForce(t);
helpline (t, t->center);
return 1;
}
/* ************************** MIRROR *************************** */
void Mirror(short mode)
@ -3345,6 +3486,9 @@ void Mirror(short mode)
for(i = 0 ; i < Trans.total; i++, td++) {
if (td->flag & TD_NOACTION)
break;
if (td->flag & TD_SKIP)
continue;
ElementResize(&Trans, td, mat);
}

@ -61,6 +61,7 @@
#include "DNA_nla_types.h"
#include "DNA_object_types.h"
#include "DNA_object_force.h"
#include "DNA_particle_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
@ -92,6 +93,7 @@
#include "BKE_mesh.h"
#include "BKE_modifier.h"
#include "BKE_object.h"
#include "BKE_particle.h"
#include "BKE_softbody.h"
#include "BKE_utildefines.h"
@ -103,6 +105,7 @@
#include "BIF_editmesh.h"
#include "BIF_editnla.h"
#include "BIF_editsima.h"
#include "BIF_editparticle.h"
#include "BIF_gl.h"
#include "BIF_poseobject.h"
#include "BIF_meshtools.h"
@ -1371,6 +1374,159 @@ static void createTransLatticeVerts(TransInfo *t)
}
}
/* ******************* particle edit **************** */
static void createTransParticleVerts(TransInfo *t)
{
TransData *td = NULL;
TransDataExtension *tx;
Base *base = BASACT;
Object *ob = OBACT;
ParticleSystem *psys = PE_get_current(ob);
ParticleSystemModifierData *psmd = NULL;
ParticleEditSettings *pset = PE_settings();
ParticleData *pa = NULL;
ParticleEdit *edit;
ParticleEditKey *key;
float mat[4][4];
int i,k, totpart, transformparticle;
int count = 0, hasselected = 0;
int propmode = t->flag & T_PROP_EDIT;
if(psys==NULL || G.scene->selectmode==SCE_SELECT_PATH) return;
psmd = psys_get_modifier(ob,psys);
edit = psys->edit;
totpart = psys->totpart;
base->flag |= BA_HAS_RECALC_DATA;
for(i=0, pa=psys->particles; i<totpart; i++, pa++) {
pa->flag &= ~PARS_TRANSFORM;
transformparticle= 0;
if((pa->flag & PARS_HIDE)==0) {
for(k=0, key=edit->keys[i]; k<pa->totkey; k++, key++) {
if((key->flag&PEK_HIDE)==0) {
if(key->flag&PEK_SELECT) {
hasselected= 1;
transformparticle= 1;
}
else if(propmode)
transformparticle= 1;
}
}
}
if(transformparticle) {
count += pa->totkey;
pa->flag |= PARS_TRANSFORM;
}
}
/* note: in prop mode we need at least 1 selected */
if (hasselected==0) return;
t->total = count;
td = t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(Particle Mode)");
if(t->mode == TFM_BAKE_TIME)
tx = t->ext = MEM_callocN(t->total * sizeof(TransDataExtension), "Particle_TransExtension");
else
tx = t->ext = NULL;
Mat4One(mat);
Mat4Invert(ob->imat,ob->obmat);
for(i=0, pa=psys->particles; i<totpart; i++, pa++) {
TransData *head, *tail;
head = tail = td;
if(!(pa->flag & PARS_TRANSFORM)) continue;
psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, mat);
for(k=0, key=edit->keys[i]; k<pa->totkey; k++, key++) {
VECCOPY(key->world_co, key->co);
Mat4MulVecfl(mat, key->world_co);
td->loc = key->world_co;
VECCOPY(td->iloc, td->loc);
VECCOPY(td->center, td->loc);
if(key->flag & PEK_SELECT)
td->flag |= TD_SELECTED;
else if(!propmode)
td->flag |= TD_SKIP;
Mat3One(td->mtx);
Mat3One(td->smtx);
/* don't allow moving roots */
if(k==0 && pset->flag & PE_LOCK_FIRST)
td->protectflag |= OB_LOCK_LOC;
td->ext = tx;
td->tdi = NULL;
if(t->mode == TFM_BAKE_TIME) {
td->val = key->time;
td->ival = *(key->time);
/* abuse size and quat for min/max values */
td->flag |= TD_NO_EXT;
if(k==0) tx->size = 0;
else tx->size = (key - 1)->time;
if(k == pa->totkey - 1) tx->quat = 0;
else tx->quat = (key + 1)->time;
}
td++;
if(tx)
tx++;
tail++;
}
if (propmode && head != tail)
calc_distanceCurveVerts(head, tail - 1);
}
}
void flushTransParticles(TransInfo *t)
{
Object *ob = OBACT;
ParticleSystem *psys = PE_get_current(ob);
ParticleSystemModifierData *psmd;
ParticleData *pa;
ParticleEditKey *key;
TransData *td;
float mat[4][4], imat[4][4], co[3];
int i, k, propmode = t->flag & T_PROP_EDIT;
psmd = psys_get_modifier(ob, psys);
/* we do transform in world space, so flush world space position
* back to particle local space */
td= t->data;
for(i=0, pa=psys->particles; i<psys->totpart; i++, pa++, td++) {
if(!(pa->flag & PARS_TRANSFORM)) continue;
psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, mat);
Mat4Invert(imat,mat);
for(k=0, key=psys->edit->keys[i]; k<pa->totkey; k++, key++) {
VECCOPY(co, key->world_co);
Mat4MulVecfl(imat, co);
/* optimization for proportional edit */
if(!propmode || !FloatCompare(key->co, co, 0.0001f)) {
VECCOPY(key->co, co);
pa->flag |= PARS_EDIT_RECALC;
}
}
}
PE_update_object(OBACT, 1);
}
/* ********************* mesh ****************** */
/* proportional distance based on connectivity */
@ -1504,9 +1660,14 @@ static void get_face_center(float *cent, EditVert *eve)
}
}
//way to overwrite what data is edited with transform
//static void VertsToTransData(TransData *td, EditVert *eve, BakeKey *key)
static void VertsToTransData(TransData *td, EditVert *eve)
{
td->flag = 0;
//if(key)
// td->loc = key->co;
//else
td->loc = eve->co;
VECCOPY(td->center, td->loc);
@ -3053,6 +3214,9 @@ void special_aftertrans_update(TransInfo *t)
allqueue(REDRAWBUTSEDIT, 0);
}
else if(G.f & G_PARTICLEEDIT) {
;
}
else {
base= FIRSTBASE;
while (base) {
@ -3315,6 +3479,17 @@ void createTransData(TransInfo *t)
createTransPose(t, base->object);
}
}
else if (G.f & G_PARTICLEEDIT) {
createTransParticleVerts(t);
if(t->data && t->flag & T_PROP_EDIT) {
sort_trans_data(t); // makes selected become first in array
set_prop_dist(t, 1);
sort_trans_data_dist(t);
}
t->flag |= T_POINTS;
}
else {
createTransObject(t);
t->flag |= T_OBJECT;

@ -44,6 +44,7 @@
#include "DNA_modifier_types.h"
#include "DNA_object_types.h"
#include "DNA_object_force.h"
#include "DNA_particle_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
#include "DNA_scene_types.h"
@ -59,6 +60,7 @@
#include "BIF_editmesh.h"
#include "BIF_editnla.h"
#include "BIF_editsima.h"
#include "BIF_editparticle.h"
#include "BIF_meshtools.h"
#include "BIF_retopo.h"
@ -188,6 +190,8 @@ static void clipMirrorModifier(TransInfo *t, Object *ob)
break;
if (td->loc==NULL)
break;
if (td->flag & TD_SKIP)
continue;
VecCopyf(loc, td->loc);
VecCopyf(iloc, td->iloc);
@ -246,6 +250,8 @@ static void editmesh_apply_to_mirror(TransInfo *t)
break;
if (td->loc==NULL)
break;
if (td->flag & TD_SKIP)
continue;
eve= td->tdmir;
if(eve) {
@ -468,6 +474,9 @@ void recalcData(TransInfo *t)
else
where_is_pose(ob);
}
else if(G.f & G_PARTICLEEDIT) {
flushTransParticles(t);
}
else {
for(base= FIRSTBASE; base; base= base->next) {
Object *ob= base->object;
@ -561,6 +570,7 @@ void initTrans (TransInfo *t)
{
/* moving: is shown in drawobject() (transform color) */
if(G.obedit || (t->flag & T_POSE) ) G.moving= G_TRANSFORM_EDIT;
else if(G.f & G_PARTICLEEDIT) G.moving= G_TRANSFORM_PARTICLE;
else G.moving= G_TRANSFORM_OBJ;
t->data = NULL;
@ -708,7 +718,7 @@ static void restoreElement(TransData *td) {
if (td->val) {
*td->val = td->ival;
}
if (td->ext) {
if (td->ext && (td->flag&TD_NO_EXT)==0) {
if (td->ext->rot) {
VECCOPY(td->ext->rot, td->ext->irot);
}

@ -53,6 +53,7 @@
#include "DNA_mesh_types.h"
#include "DNA_meta_types.h"
#include "DNA_object_types.h"
#include "DNA_particle_types.h"
#include "DNA_screen_types.h"
#include "DNA_scene_types.h"
#include "DNA_space_types.h"
@ -63,6 +64,7 @@
#include "BKE_global.h"
#include "BKE_lattice.h"
#include "BKE_object.h"
#include "BKE_particle.h"
#include "BKE_utildefines.h"
#include "BLI_arithb.h"
@ -76,6 +78,7 @@
#include "BIF_space.h"
#include "BIF_transform.h"
#include "BIF_editmesh.h"
#include "BIF_editparticle.h"
#include "BSE_edit.h"
#include "BSE_view.h"
@ -434,6 +437,27 @@ int calc_manipulator_stats(ScrArea *sa)
else if(G.f & (G_VERTEXPAINT + G_TEXTUREPAINT + G_WEIGHTPAINT + G_SCULPTMODE)) {
;
}
else if(G.f & G_PARTICLEEDIT) {
ParticleSystem *psys=PE_get_current(OBACT);
ParticleData *pa = psys->particles;
ParticleEditKey *ek;
int k;
if(psys->edit){
for(a=0; a<psys->totpart; a++,pa++){
if(pa->flag & PARS_HIDE) continue;
for(k=0, ek=psys->edit->keys[a]; k<pa->totkey; k++,ek++){
if(ek->flag & PEK_SELECT){
calc_tw_center(ek->world_co);
totsel++;
}
}
}
/* selection center */
if(totsel)
VecMulf(G.scene->twcent, 1.0f/(float)totsel); // centroid!
}
}
else {
/* we need the one selected object, if its not active */

@ -68,11 +68,12 @@
#include "BKE_object.h"
#include "BKE_utildefines.h"
#include "BIF_editparticle.h"
#include "BIF_gl.h"
#include "BIF_space.h"
#include "BIF_mywindow.h"
#include "BIF_previewrender.h"
#include "BIF_mywindow.h"
#include "BIF_retopo.h"
#include "BIF_space.h"
#include "BIF_screen.h"
#include "BIF_toolbox.h"
@ -1441,6 +1442,9 @@ void centerview() /* like a localview without local! */
else if (FACESEL_PAINT_TEST) {
ok= minmax_tface(min, max);
}
else if (G.f & G_PARTICLEEDIT) {
ok= PE_minmax(min, max);
}
else {
Base *base= FIRSTBASE;
while(base) {