From 70dae5f49339a791c1c84d72047cde144e4e2843 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 21 Apr 2009 01:59:14 +0000 Subject: [#18557] incorrect alpha IPO behavior in game engine from Louis-Dominique Dubeau (zenoparadox) report contained fix, ancient bug from rev2. --- source/blender/blenkernel/intern/ipo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c index 29db0ddd808..0077cf95262 100644 --- a/source/blender/blenkernel/intern/ipo.c +++ b/source/blender/blenkernel/intern/ipo.c @@ -2876,7 +2876,7 @@ float IPO_GetFloatValue (Ipo *ipo, IPO_Channel channel, float ctime) calc_ipo_spec(ipo, channel, &ctime); /* unapply rotation hack, as gameengine doesn't use it */ - if ((OB_ROT_X <= channel) && (channel <= OB_DROT_Z)) + if ((ipo->blocktype == ID_OB) && (OB_ROT_X <= channel) && (channel <= OB_DROT_Z)) ctime *= (float)(M_PI_2/9.0); /* return the value of this channel */ -- cgit v1.2.3 From 3e7cbd5388426a612b4066fbe7f2964c976fb23e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 21 Apr 2009 09:44:29 +0000 Subject: Blender Python API - Removed the gen_utils.c dependency from Mathutils (since gen_utils wont go into 2.5 but mathutils will), repalced with python functions. - removed Blender.Mathutils.Point, since it was not documented, the C api never used it, none of our scripts used it (and I never saw a script that used it). --- source/blender/blenkernel/BKE_scene.h | 1 + 1 file changed, 1 insertion(+) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h index 2c3ef42c021..647f7e95fd9 100644 --- a/source/blender/blenkernel/BKE_scene.h +++ b/source/blender/blenkernel/BKE_scene.h @@ -35,6 +35,7 @@ struct bglMats; struct Scene; struct Object; struct Base; +struct Text; struct AviCodecData; struct QuicktimeCodecData; struct SculptData; -- cgit v1.2.3 From d11a5bbef2750c9e95c0657eb9d965de375b2982 Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Tue, 21 Apr 2009 11:01:09 +0000 Subject: BGE: Support mesh modifiers in the game engine. Realtime modifiers applied on mesh objects will be supported in the game engine with the following limitations: - Only real time modifiers are supported (basically all of them!) - Virtual modifiers resulting from parenting are not supported: armature, curve, lattice. You can still use these modifiers (armature is really not recommended) but in non parent mode. The BGE has it's own parenting capability for armature. - Modifiers are computed on the host (using blender modifier stack). - Modifiers are statically evaluated: any possible time dependency in the modifiers is not supported (don't know enough about modifiers to be more specific). - Modifiers are reevaluated if the underlying mesh is deformed due to shape action or armature action. Beware that this is very CPU intensive; modifiers should really be used for static objects only. - Physics is still based on the original mesh: if you have a mirror modifier, the physic shape will be limited to one half of the resulting object. Therefore, the modifiers should preferably be used on graphic objects. - Scripts have no access to the modified mesh. - Modifiers that are based on objects interaction (boolean,..) will not be dependent on the objects position in the GE. What you see in the 3D view is what you get in the GE regardless on the object position, velocity, etc. Besides that, the feature is compatible with all the BGE features that affect meshes: armature action, shape action, relace mesh, VideoTexture, add object, dupligroup. Known problems: - This feature is a bit hacky: the BGE uses the derived mesh draw functions to display the object. This drawing method is a bit slow and is not 100% compatible with the BGE. There may be some problems in multi-texture mode: the multi-texture coordinates are not sent to the GPU. Texface and GLSL on the other hand should be fully supported. - Culling is still based on the extend of the original mesh. If you have a modifer that extends the size of the mesh, the object may disappear while still in the view frustrum. - Derived mesh is not shared between replicas. The derived mesh is allocated and computed for each object with modifiers, regardless if they are static replicas. - Display list are not created on objects with modifiers. I should be able to fix the above problems before release. However, the feature is already useful for game development. Once you are ready to release the game, you can apply the modifiers to get back display list support and mesh sharing capability. MSVC, scons, Cmake, makefile updated. Enjoy /benoit --- source/blender/blenkernel/BKE_DerivedMesh.h | 3 +++ source/blender/blenkernel/intern/DerivedMesh.c | 21 +++++++++++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h index 263b17151e7..7ee8a424d03 100644 --- a/source/blender/blenkernel/BKE_DerivedMesh.h +++ b/source/blender/blenkernel/BKE_DerivedMesh.h @@ -444,6 +444,9 @@ DerivedMesh *mesh_create_derived_no_deform(struct Object *ob, DerivedMesh *mesh_create_derived_no_deform_render(struct Object *ob, float (*vertCos)[3], CustomDataMask dataMask); +/* for gameengine */ +DerivedMesh *mesh_create_derived_no_virtual(struct Object *ob, float (*vertCos)[3], + CustomDataMask dataMask); DerivedMesh *editmesh_get_derived_base(void); DerivedMesh *editmesh_get_derived_cage(CustomDataMask dataMask); diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index d43cbdebe72..eb2975be0c0 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -2111,6 +2111,11 @@ static void add_orco_dm(Object *ob, EditMesh *em, DerivedMesh *dm, DerivedMesh * DM_add_vert_layer(dm, CD_ORCO, CD_ASSIGN, orco); } +/* new value for useDeform -1 (hack for the gameengine): + * - apply only the modifier stack of the object, skipping the virtual modifiers, + * - don't apply the key + * - apply deform modifiers and input vertexco + */ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3], DerivedMesh **deform_r, DerivedMesh **final_r, int useRenderParams, int useDeform, @@ -2125,7 +2130,7 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3], int numVerts = me->totvert; int required_mode; - md = firstmd = modifiers_getVirtualModifierList(ob); + md = firstmd = (useDeform<0) ? ob->modifiers.first : modifiers_getVirtualModifierList(ob); modifiers_clearErrors(ob); @@ -2142,8 +2147,10 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3], else required_mode = eModifierMode_Realtime; if(useDeform) { - if(do_ob_key(ob)) /* shape key makes deform verts */ + if(useDeform > 0 && do_ob_key(ob)) /* shape key makes deform verts */ deformedVerts = mesh_getVertexCos(me, &numVerts); + else if(inputVertexCos) + deformedVerts = inputVertexCos; /* Apply all leading deforming modifiers */ for(;md; md = md->next, curr = curr->next) { @@ -2947,6 +2954,16 @@ DerivedMesh *mesh_create_derived_no_deform(Object *ob, float (*vertCos)[3], return final; } +DerivedMesh *mesh_create_derived_no_virtual(Object *ob, float (*vertCos)[3], + CustomDataMask dataMask) +{ + DerivedMesh *final; + + mesh_calc_modifiers(ob, vertCos, NULL, &final, 0, -1, 0, dataMask, -1); + + return final; +} + DerivedMesh *mesh_create_derived_no_deform_render(Object *ob, float (*vertCos)[3], CustomDataMask dataMask) -- cgit v1.2.3 From 6c33cc9bae9a565ee2ea5247754c6a4b127795bf Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Tue, 21 Apr 2009 15:38:53 +0000 Subject: Bugfix #18550 "Copy constraints" should increase ipo user count. --- source/blender/blenkernel/intern/constraint.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index f93fc403404..6b6f4a58e79 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -3551,6 +3551,8 @@ void copy_constraints (ListBase *dst, ListBase *src) /* make a new copy of the constraint's data */ con->data = MEM_dupallocN(con->data); + id_us_plus((ID *)con->ipo); + /* only do specific constraints if required */ if (cti && cti->copy_data) cti->copy_data(con, srccon); -- cgit v1.2.3 From a82a6bedc55fe676c11bf36f1017c0cbddcd9ca2 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Tue, 21 Apr 2009 16:58:25 +0000 Subject: Fix for bug #17457. This bug relates to files that have missing multires vertex data. The fix is, if the file was saved on the highest multires level, then mesh contains a copy of the vertices anyway, and we can just copy it back into multires. Otherwise, multires is removed from the mesh to avoid a crash. --- source/blender/blenkernel/intern/multires.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index 4d312632b1a..8112c64d79f 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -111,7 +111,8 @@ void multires_free(Multires *mr) lvl= lvl->next; } - MEM_freeN(mr->verts); + if(mr->verts) + MEM_freeN(mr->verts); BLI_freelistN(&mr->levels); -- cgit v1.2.3 From 95b43536f6c1da49b8ee94c287e84686c6732a8f Mon Sep 17 00:00:00 2001 From: "Guillermo S. Romero" Date: Tue, 21 Apr 2009 17:24:16 +0000 Subject: Some Makefile changes still laying around. --- source/blender/blenkernel/intern/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/Makefile b/source/blender/blenkernel/intern/Makefile index 226e416dad7..75f75b0c3c5 100644 --- a/source/blender/blenkernel/intern/Makefile +++ b/source/blender/blenkernel/intern/Makefile @@ -82,7 +82,7 @@ CPPFLAGS += -I../../gpu CPPFLAGS += -I.. # path to bullet2, for cloth -CPPFLAGS += -I../../../../extern/bullet2/src +CPPFLAGS += -I$(NAN_BULLET2)/include ifeq ($(WITH_FREETYPE2), true) CPPFLAGS += -DWITH_FREETYPE2 -- cgit v1.2.3 From c5756a9822f72579ddc1797dbe7612035a9b2bfe Mon Sep 17 00:00:00 2001 From: "Guillermo S. Romero" Date: Tue, 21 Apr 2009 17:37:07 +0000 Subject: Compile warnings, typos and some clarifications. --- source/blender/blenkernel/bad_level_call_stubs/stubs.c | 5 +++-- source/blender/blenkernel/intern/image.c | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/bad_level_call_stubs/stubs.c b/source/blender/blenkernel/bad_level_call_stubs/stubs.c index 5f6472ce56e..341379de1d9 100644 --- a/source/blender/blenkernel/bad_level_call_stubs/stubs.c +++ b/source/blender/blenkernel/bad_level_call_stubs/stubs.c @@ -327,7 +327,7 @@ void antialias_tagbuf(int xsize, int ysize, char *rectmove) {} /* imagetexture.c stub */ void ibuf_sample(struct ImBuf *ibuf, float fx, float fy, float dx, float dy, float *result) {} -void update_for_newframe() {} +void update_for_newframe(void) {} struct FileList; void BIF_filelist_freelib(struct FileList* filelist) {}; @@ -336,7 +336,8 @@ void BIF_filelist_freelib(struct FileList* filelist) {}; TimeMarker *get_frame_marker(int frame){return 0;}; /* editseq.c */ -Sequence *get_forground_frame_seq(int frame){return 0;}; +#include "BIF_editseq.h" // And fix the missing void there +Sequence *get_foreground_frame_seq(int frame){return 0;}; void clear_last_seq(Sequence *seq){}; diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index e817c38618f..01d8ed4d41c 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -407,7 +407,7 @@ static ImBuf *add_ibuf_size(int width, int height, char *name, int floatbuf, sho unsigned char *rect= NULL; float *rect_float= NULL; int x, y; - int checkerwidth=21, dark=1; + int checkerwidth=32, dark=1; if (floatbuf) { ibuf= IMB_allocImBuf(width, height, 24, IB_rectfloat, 0); @@ -1024,7 +1024,7 @@ static void stampdata(StampData *stamp_data, int do_prefix) } if (G.scene->r.stamp & R_STAMP_SEQSTRIP) { - Sequence *seq = get_forground_frame_seq(CFRA); + Sequence *seq = get_foreground_frame_seq(CFRA); if (seq) strcpy(text, seq->name+2); else strcpy(text, ""); -- cgit v1.2.3 From 971cabc2d687c86b8ff1e7a5a57474d85450b170 Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Wed, 22 Apr 2009 17:06:47 +0000 Subject: Bugfix #18058 Ray-transparent didn't pass on thread number to shading code, giving "blothes" in render, when using node materials. This also rewinds Campbells commit of feb 21, which tackled the error, but not the cause. --- source/blender/blenkernel/intern/node.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index e4e5883b2d8..413c2fc20f5 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -1982,9 +1982,9 @@ static void group_tag_used_outputs(bNode *gnode, bNodeStack *stack) } } +/* notes below are ancient! (ton) */ /* stack indices make sure all nodes only write in allocated data, for making it thread safe */ /* only root tree gets the stack, to enable instances to have own stack entries */ -/* only two threads now! */ /* per tree (and per group) unique indices are created */ /* the index_ext we need to be able to map from groups to the group-node own stack */ @@ -1999,14 +1999,9 @@ static bNodeThreadStack *ntreeGetThreadStack(bNodeTree *ntree, int thread) ListBase *lb= &ntree->threadstack[thread]; bNodeThreadStack *nts; - /* for material shading this is called quite a lot (perhaps too much locking unlocking) - * however without locking we get bug #18058 - Campbell */ - BLI_lock_thread(LOCK_CUSTOM1); - for(nts=lb->first; nts; nts=nts->next) { if(!nts->used) { nts->used= 1; - BLI_unlock_thread(LOCK_CUSTOM1); return nts; } } @@ -2014,7 +2009,7 @@ static bNodeThreadStack *ntreeGetThreadStack(bNodeTree *ntree, int thread) nts->stack= MEM_dupallocN(ntree->stack); nts->used= 1; BLI_addtail(lb, nts); - BLI_unlock_thread(LOCK_CUSTOM1); + return nts; } -- cgit v1.2.3 From b22819f686539f75438938ed45751e7dc3405a0c Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Wed, 22 Apr 2009 17:35:37 +0000 Subject: Bugfix #18039 Armature modifier didn't set amd->prevCos temp variable to NULL after freeing. Saving this in file will cause error or crash on reading. Quite weird how it survived so long? --- source/blender/blenkernel/intern/modifier.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 7977e7b0160..f7620f5b88c 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -8846,8 +8846,10 @@ void modifier_freeTemporaryData(ModifierData *md) if(md->type == eModifierType_Armature) { ArmatureModifierData *amd= (ArmatureModifierData*)md; - if(amd->prevCos) + if(amd->prevCos) { MEM_freeN(amd->prevCos); + amd->prevCos= NULL; + } } } -- cgit v1.2.3 From 1ca6768051a74a370bf16f877a5ffc1691545ae6 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 22 Apr 2009 22:38:23 +0000 Subject: Fix for bug #18509: mesh deform modifier not working on load, with cage on hidden layer. --- source/blender/blenkernel/intern/modifier.c | 92 +++++++++++++++++------------ 1 file changed, 55 insertions(+), 37 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index f7620f5b88c..10bcb2e09f2 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -6054,8 +6054,6 @@ static void surfaceModifier_deformVerts( float (*vertexCos)[3], int numVerts) { SurfaceModifierData *surmd = (SurfaceModifierData*) md; - DerivedMesh *dm = NULL; - float current_time = 0; unsigned int numverts = 0, i = 0; if(surmd->dm) @@ -6258,6 +6256,48 @@ static int is_last_displist(Object *ob) return 0; } + +static DerivedMesh *get_original_dm(Object *ob, float (*vertexCos)[3], int orco) +{ + DerivedMesh *dm= NULL; + + if(ob->type==OB_MESH) { + dm = CDDM_from_mesh((Mesh*)(ob->data), ob); + + if(vertexCos) { + CDDM_apply_vert_coords(dm, vertexCos); + //CDDM_calc_normals(dm); + } + + if(orco) + DM_add_vert_layer(dm, CD_ORCO, CD_ASSIGN, get_mesh_orco_verts(ob)); + } + else if(ELEM3(ob->type,OB_FONT,OB_CURVE,OB_SURF)) { + Object *tmpobj; + Curve *tmpcu; + + if(is_last_displist(ob)) { + /* copies object and modifiers (but not the data) */ + tmpobj= copy_object(ob); + tmpcu = (Curve *)tmpobj->data; + tmpcu->id.us--; + + /* copies the data */ + tmpobj->data = copy_curve((Curve *) ob->data); + + makeDispListCurveTypes(tmpobj, 1); + nurbs_to_mesh(tmpobj); + + dm = CDDM_from_mesh((Mesh*)(tmpobj->data), tmpobj); + //CDDM_calc_normals(dm); + + free_libblock_us(&G.main->object, tmpobj); + } + } + + return dm; +} + /* saves the current emitter state for a particle system and calculates particles */ static void particleSystemModifier_deformVerts( ModifierData *md, Object *ob, DerivedMesh *derivedData, @@ -6285,43 +6325,13 @@ static void particleSystemModifier_deformVerts( if(!psys_check_enabled(ob, psys)) return; - if(dm==0){ - if(ob->type==OB_MESH){ - dm = CDDM_from_mesh((Mesh*)(ob->data), ob); - - CDDM_apply_vert_coords(dm, vertexCos); - //CDDM_calc_normals(dm); - - DM_add_vert_layer(dm, CD_ORCO, CD_ASSIGN, get_mesh_orco_verts(ob)); - - needsFree=1; - } - else if(ELEM3(ob->type,OB_FONT,OB_CURVE,OB_SURF)){ - Object *tmpobj; - Curve *tmpcu; - - if(is_last_displist(ob)){ - /* copies object and modifiers (but not the data) */ - tmpobj= copy_object( ob ); - tmpcu = (Curve *)tmpobj->data; - tmpcu->id.us--; - - /* copies the data */ - tmpobj->data = copy_curve( (Curve *) ob->data ); - - makeDispListCurveTypes( tmpobj, 1 ); - nurbs_to_mesh( tmpobj ); + if(dm==0) { + dm= get_original_dm(ob, vertexCos, 1); - dm = CDDM_from_mesh((Mesh*)(tmpobj->data), tmpobj); - //CDDM_calc_normals(dm); - - free_libblock_us( &G.main->object, tmpobj ); + if(!dm) + return; - needsFree=1; - } - else return; - } - else return; + needsFree= 1; } /* clear old dm */ @@ -7658,6 +7668,14 @@ static void meshdeformModifier_do( } else cagedm= mmd->object->derivedFinal; + + /* if we don't have one computed, use derivedmesh from data + * without any modifiers */ + if(!cagedm) { + cagedm= get_original_dm(mmd->object, NULL, 0); + if(cagedm) + cagedm->needsFree= 1; + } if(!cagedm) return; -- cgit v1.2.3 From d568794a9873eed10a9d240c1e1a1ba52aba929c Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 22 Apr 2009 23:01:40 +0000 Subject: Fix for bug #14410: multires + vertex colors crash rendering or baking while in editmode. --- source/blender/blenkernel/intern/multires.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index 8112c64d79f..ee9255df837 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -966,9 +966,9 @@ void multires_update_levels(Mesh *me, const int render) multires_update_colors(me, em); } -static void check_colors(Mesh *me) +static void check_colors(Mesh *me, const int render) { - CustomData *src= G.obedit ? &G.editMesh->fdata : &me->fdata; + CustomData *src= (!render && G.obedit)? &G.editMesh->fdata : &me->fdata; const char col= CustomData_has_layer(src, CD_MCOL); /* Check if vertex colors have been deleted or added */ @@ -1110,7 +1110,7 @@ void multires_add_level(Object *ob, Mesh *me, const char subdiv_type) lvl= MEM_callocN(sizeof(MultiresLevel), "multireslevel"); if(me->pv) mesh_pmv_off(ob, me); - check_colors(me); + check_colors(me, 0); multires_update_levels(me, 0); ++me->mr->level_count; @@ -1276,7 +1276,7 @@ void multires_set_level(Object *ob, Mesh *me, const int render) { if(me->pv) mesh_pmv_off(ob, me); - check_colors(me); + check_colors(me, render); multires_update_levels(me, render); me->mr->current= me->mr->newlvl; -- cgit v1.2.3 From 252928ab36b03e73b35ea79e36a03e8f982274f6 Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Fri, 24 Apr 2009 19:49:15 +0000 Subject: BGE: removed support for time dependent modifiers, they don't make sense in the GE. Disable modifiers when Bullet soft body is used: bullet needs the original vertex array. --- source/blender/blenkernel/intern/DerivedMesh.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index eb2975be0c0..6cf934fa165 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -2158,6 +2158,7 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3], if((md->mode & required_mode) != required_mode) continue; if(mti->isDisabled && mti->isDisabled(md)) continue; + if(useDeform < 0 && mti->dependsOnTime && mti->dependsOnTime(md)) continue; if(mti->type == eModifierTypeType_OnlyDeform) { if(!deformedVerts) @@ -2228,6 +2229,7 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3], } if(mti->isDisabled && mti->isDisabled(md)) continue; if(needMapping && !modifier_supportsMapping(md)) continue; + if(useDeform < 0 && mti->dependsOnTime && mti->dependsOnTime(md)) continue; /* add an orco layer if needed by this modifier */ if(dm && mti->requiredDataMask) { -- cgit v1.2.3 From af1c25c9d0b69a268a2ac824b8ab0e3032d5f110 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Sun, 26 Apr 2009 13:26:18 +0000 Subject: Fixed shrinkwrap bug: shrinkwrap wasn't using the updated coordinates/normals of vertexs when the DerivedMesh had been modified by a previous modifier. before revision 19744, users would only notice a strange behaviour of shrinkwrap in projection mode (because it was using the wrong normals) (jpbouza reported this) after revision 19744 this bug was "bigger". Anyway it's fixed now :) --- source/blender/blenkernel/intern/modifier.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 10bcb2e09f2..c9f6bc18abd 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -7915,7 +7915,7 @@ static void shrinkwrapModifier_deformVerts(ModifierData *md, Object *ob, Derived else if(ob->type==OB_LATTICE) dm = NULL; else return; - if(dm != NULL && (dataMask & CD_MVERT)) + if(dm != NULL && (dataMask & (1<type==OB_LATTICE) dm = NULL; else return; - if(dm != NULL && (dataMask & CD_MVERT)) + if(dm != NULL && (dataMask & (1< Date: Sun, 26 Apr 2009 18:38:16 +0000 Subject: Missing end-of-line. --- source/blender/blenkernel/intern/particle.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 3fea9e44acb..0ebdcdf58e0 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -3974,4 +3974,4 @@ void psys_make_billboard(ParticleBillboardData *bb, float xvec[3], float yvec[3] VECADDFAC(center, bb->vec, xvec, bb->offset[0]); VECADDFAC(center, center, yvec, bb->offset[1]); -} \ No newline at end of file +} -- cgit v1.2.3 From 310356a732d9460bd647c8e5b465bed6ae037e89 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Sun, 26 Apr 2009 21:33:22 +0000 Subject: Shrinkwrap fix (before I only fixed normal projection) nearest surface + nearest vertex fixed now --- source/blender/blenkernel/intern/shrinkwrap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c index 6784f014efa..69ce9f3d5cd 100644 --- a/source/blender/blenkernel/intern/shrinkwrap.c +++ b/source/blender/blenkernel/intern/shrinkwrap.c @@ -191,7 +191,7 @@ void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Object *ob, DerivedM calc.vgroup = get_named_vertexgroup_num(calc.ob, smd->vgroup_name); - if(dm != NULL) + if(dm != NULL && smd->shrinkType == MOD_SHRINKWRAP_PROJECT) { //Setup arrays to get vertexs positions, normals and deform weights calc.vert = dm->getVertDataArray(dm, CD_MVERT); -- cgit v1.2.3 From 352eaccd5d991ad8966d686ae0954c7a0b03345c Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Mon, 27 Apr 2009 16:44:02 +0000 Subject: BGE: Add soft body welding parameter to the Advanced Settings panel. The values are very small so I chose to use logarithmic scale. Should be fine, it's an advanced setting after all. --- source/blender/blenkernel/intern/bullet.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/bullet.c b/source/blender/blenkernel/intern/bullet.c index b389f8c0536..657507ee048 100644 --- a/source/blender/blenkernel/intern/bullet.c +++ b/source/blender/blenkernel/intern/bullet.c @@ -82,6 +82,7 @@ BulletSoftBody *bsbNew(void) bsb->collisionflags = 0; //bsb->collisionflags = OB_BSB_COL_CL_RS + OB_BSB_COL_CL_SS; bsb->numclusteriterations = 64; + bsb->welding = -4.f; return bsb; } -- cgit v1.2.3 From d4f8b416e92ec5b71bddfa688e9a63ea86510721 Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Mon, 27 Apr 2009 22:21:42 +0000 Subject: BGE soft body: change welding option to disable welding check by default: speeds up shape conversion. This is fine if the object has no duplicate vertices. Otherwise, bullet will be extremely slow and you can either set some welding or remove duplicates in the mesh. Welding is now displayed in linear scale: 0.0 -> 0.01, no need to use logarithmic scale ;-). Fix a bug with Bullet by which vertex array for soft body must have 3xfloat stride. --- source/blender/blenkernel/intern/bullet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/bullet.c b/source/blender/blenkernel/intern/bullet.c index 657507ee048..44e8ed1f08c 100644 --- a/source/blender/blenkernel/intern/bullet.c +++ b/source/blender/blenkernel/intern/bullet.c @@ -82,7 +82,7 @@ BulletSoftBody *bsbNew(void) bsb->collisionflags = 0; //bsb->collisionflags = OB_BSB_COL_CL_RS + OB_BSB_COL_CL_SS; bsb->numclusteriterations = 64; - bsb->welding = -4.f; + bsb->welding = 0.f; return bsb; } -- cgit v1.2.3 From 3b19b6c33fa5a68309efe99c49fca0df60db02aa Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Wed, 29 Apr 2009 15:25:13 +0000 Subject: 2.5+ file read provision for 2.49 I've managed to find a basic fail-safe method to prevent using the read data with an OK popup. I then still will read the file, but wait for user confirmation to continue, or just free the database. The pupup tells the user that at least animation data will be lost. For background renders of 2.5+ things are more tricky, so here I've added a default failure to read, returning 0, which will typically gracefully quit blender. --- source/blender/blenkernel/intern/blender.c | 32 +++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index 5dcccc56d06..906971f8bae 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -423,18 +423,31 @@ static void setup_app_data(BlendFileData *bfd, char *filename) MEM_freeN(bfd); } -static void handle_subversion_warning(Main *main) +static int handle_subversion_warning(Main *main) { if(main->minversionfile > BLENDER_VERSION || (main->minversionfile == BLENDER_VERSION && main->minsubversionfile > BLENDER_SUBVERSION)) { + extern int okee(char *str, ...); // XXX BAD LEVEL, DO NOT PORT TO 2.5! char str[128]; - - sprintf(str, "File written by newer Blender binary: %d.%d , expect loss of data!", main->minversionfile, main->minsubversionfile); - error(str); + + if(main->minversionfile >= 250) { + sprintf(str, "You have opened a %d file, key information will get lost, like animation data. Continue?", main->minversionfile); + + if(G.background) { + printf("ERROR: cannot render %d file\n", main->versionfile); + return 0; + } + else + return okee(str); + } + else { + sprintf(str, "File written by newer Blender binary: %d.%d , expect loss of data!", main->minversionfile, main->minsubversionfile); + error(str); + } } - + return 1; } /* returns: @@ -458,9 +471,14 @@ int BKE_read_file(char *dir, void *type_r) if (type_r) *((BlenFileType*)type_r)= bfd->type; - setup_app_data(bfd, dir); + if(0==handle_subversion_warning(bfd->main)) { + free_main(bfd->main); + MEM_freeN(bfd); + bfd= NULL; + } + else + setup_app_data(bfd, dir); // frees BFD - handle_subversion_warning(G.main); } else { error("Loading %s failed: %s", dir, BLO_bre_as_string(bre)); -- cgit v1.2.3 From f56bfbdd0c25feb815accdd377cf0b743c5d7e19 Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Wed, 29 Apr 2009 16:07:10 +0000 Subject: Bugfix from own testing: Blender crashed, when started in debug -d, with compositor, after render. Reason was the BKE_image_print_memlist() which reads the ibuf->rect from all images, but for Image types "VIEWER" that's not valid, this data is coming from other sources. --- source/blender/blenkernel/intern/image.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 01d8ed4d41c..444c7c080ea 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -640,6 +640,11 @@ static uintptr_t image_mem_size(Image *ima) uintptr_t size = 0; size= 0; + + /* viewers have memory depending on other rules, has no valid rect pointer */ + if(ima->source==IMA_SRC_VIEWER) + return 0; + for(ibuf= ima->ibufs.first; ibuf; ibuf= ibuf->next) { if(ibuf->rect) size += MEM_allocN_len(ibuf->rect); else if(ibuf->rect_float) size += MEM_allocN_len(ibuf->rect_float); -- cgit v1.2.3 From 11dcf7461cff32131efe1f22930b0a10e3562842 Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Wed, 29 Apr 2009 17:41:41 +0000 Subject: Bugfix #18632 Duplicating an armature, with constraints having a local Ipo, didn't make a copy of this Ipo too, frustrating its drivers too. --- source/blender/blenkernel/intern/object.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 0b153c3c065..bffbcf73672 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -1169,6 +1169,9 @@ static void copy_object_pose(Object *obn, Object *ob) * is changed to object->proxy_from when evaluating the driver. */ if(con->ipo && !con->ipo->id.lib) { IpoCurve *icu; + + con->ipo= copy_ipo(con->ipo); + for(icu= con->ipo->curve.first; icu; icu= icu->next) { if(icu->driver && icu->driver->ob==ob) icu->driver->ob= obn; -- cgit v1.2.3 From a9aac77ccf6b915e15915ba1e10daebabd79610a Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Wed, 29 Apr 2009 19:13:32 +0000 Subject: Win64 fixes - I don't think that they introduced any bugs yet, but I want to be sure. Please report problems. --- source/blender/blenkernel/intern/DerivedMesh.c | 2 +- source/blender/blenkernel/intern/bmfont.c | 2 +- source/blender/blenkernel/intern/customdata.c | 4 ++-- source/blender/blenkernel/intern/displist.c | 2 +- source/blender/blenkernel/intern/exotic.c | 18 +++++++++--------- source/blender/blenkernel/intern/font.c | 2 +- 6 files changed, 15 insertions(+), 15 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index 6cf934fa165..ddb7d853f2f 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -909,7 +909,7 @@ static void emDM_drawMappedFacesGLSL(DerivedMesh *dm, glShadeModel(GL_SMOOTH); for (i=0,eve=em->verts.first; eve; eve= eve->next) - eve->tmp.l = (long) i++; + eve->tmp.l = (intptr_t) i++; #define PASSATTRIB(efa, eve, vert) { \ if(attribs.totorco) { \ diff --git a/source/blender/blenkernel/intern/bmfont.c b/source/blender/blenkernel/intern/bmfont.c index 0af54b86ed6..09770b2b4ba 100644 --- a/source/blender/blenkernel/intern/bmfont.c +++ b/source/blender/blenkernel/intern/bmfont.c @@ -178,7 +178,7 @@ void detectBitmapFont(ImBuf *ibuf) { unsigned char * rect; unsigned short version; - long i; + int i; if (ibuf != NULL) { // bitmap must have an x size that is a power of two diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index 05271aa59a7..6d5b86fa874 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -626,7 +626,7 @@ void CustomData_merge(const struct CustomData *source, struct CustomData *dest, number++; if(layer->flag & CD_FLAG_NOCOPY) continue; - else if(!(mask & (1 << type))) continue; + else if(!((int)mask & (int)(1 << (int)type))) continue; else if(number < CustomData_number_of_layers(dest, type)) continue; if((alloctype == CD_ASSIGN) && (layer->flag & CD_FLAG_NOFREE)) @@ -1144,7 +1144,7 @@ void CustomData_set_only_copy(const struct CustomData *data, int i; for(i = 0; i < data->totlayer; ++i) - if(!(mask & (1 << data->layers[i].type))) + if(!((int)mask & (int)(1 << (int)data->layers[i].type))) data->layers[i].flag |= CD_FLAG_NOCOPY; } diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index 7716d71225e..91eea56c9e7 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -937,7 +937,7 @@ void filldisplist(ListBase *dispbase, ListBase *to) DispList *dlnew=0, *dl; float *f1; int colnr=0, charidx=0, cont=1, tot, a, *index; - long totvert; + intptr_t totvert; if(dispbase==0) return; if(dispbase->first==0) return; diff --git a/source/blender/blenkernel/intern/exotic.c b/source/blender/blenkernel/intern/exotic.c index ee3fd59fe9f..76ad0cf07c3 100644 --- a/source/blender/blenkernel/intern/exotic.c +++ b/source/blender/blenkernel/intern/exotic.c @@ -1131,7 +1131,7 @@ static int iv_finddata(struct IvNode *iv, char *field, int fieldnr) float *fp; int len, stackcount, skipdata=0; char *cpa, terminator, str[64]; - long i; + intptr_t i; len= strlen(field); @@ -2592,7 +2592,7 @@ static void write_videoscape_mesh(Object *ob, char *str) unsigned int kleur[32]; float co[3]; int a; - long tot; + intptr_t tot; char *cp; if(ob && ob->type==OB_MESH); @@ -2642,17 +2642,17 @@ static void write_videoscape_mesh(Object *ob, char *str) if(evl->v4==0) { fprintf(fp, "3 %ld %ld %ld 0x%x\n", - (long int) evl->v1->tmp.l, - (long int) evl->v2->tmp.l, - (long int) evl->v3->tmp.l, + (intptr_t) evl->v1->tmp.l, + (intptr_t) evl->v2->tmp.l, + (intptr_t) evl->v3->tmp.l, kleur[evl->mat_nr]); } else { fprintf(fp, "4 %ld %ld %ld %ld 0x%x\n", - (long int) evl->v1->tmp.l, - (long int) evl->v2->tmp.l, - (long int) evl->v3->tmp.l, - (long int) evl->v4->tmp.l, + (intptr_t) evl->v1->tmp.l, + (intptr_t) evl->v2->tmp.l, + (intptr_t) evl->v3->tmp.l, + (intptr_t) evl->v4->tmp.l, kleur[evl->mat_nr]); } evl= evl->next; diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c index 52275e507dd..45b52f5af8e 100644 --- a/source/blender/blenkernel/intern/font.c +++ b/source/blender/blenkernel/intern/font.c @@ -1131,7 +1131,7 @@ struct chartrans *text_to_curve(Object *ob, int mode) ct= chartransdata; if (cu->sepchar==0) { for (i= 0; istrinfo[i]); if (info->mat_nr > (ob->totcol)) { /* printf("Error: Illegal material index (%d) in text object, setting to 0\n", info->mat_nr); */ -- cgit v1.2.3 From ebf631b3fe70b9fe640129adf06bbd0bab27ef22 Mon Sep 17 00:00:00 2001 From: Nathan Letwory Date: Wed, 29 Apr 2009 22:09:28 +0000 Subject: * instead of using okee() (breaking builds) use error() in 250 subversion handling in 2.49 --- source/blender/blenkernel/intern/blender.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index 906971f8bae..73c93abdf4b 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -429,7 +429,6 @@ static int handle_subversion_warning(Main *main) (main->minversionfile == BLENDER_VERSION && main->minsubversionfile > BLENDER_SUBVERSION)) { - extern int okee(char *str, ...); // XXX BAD LEVEL, DO NOT PORT TO 2.5! char str[128]; if(main->minversionfile >= 250) { @@ -437,10 +436,9 @@ static int handle_subversion_warning(Main *main) if(G.background) { printf("ERROR: cannot render %d file\n", main->versionfile); - return 0; } - else - return okee(str); + error(str); + return 0; } else { sprintf(str, "File written by newer Blender binary: %d.%d , expect loss of data!", main->minversionfile, main->minsubversionfile); @@ -475,6 +473,7 @@ int BKE_read_file(char *dir, void *type_r) free_main(bfd->main); MEM_freeN(bfd); bfd= NULL; + retval= 0; } else setup_app_data(bfd, dir); // frees BFD -- cgit v1.2.3 From de2cc4d14d1b7a7b47cbbf01db7c980d929a7846 Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Thu, 30 Apr 2009 10:11:37 +0000 Subject: Second trial to get an OK menu work to allow people to decide whether or not to use a 2.5+ saved file in 2.49. Apparently the msvc linker was choking on it? --- source/blender/blenkernel/BKE_bad_level_calls.h | 1 + source/blender/blenkernel/bad_level_call_stubs/stubs.c | 1 + source/blender/blenkernel/intern/blender.c | 4 ++-- 3 files changed, 4 insertions(+), 2 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_bad_level_calls.h b/source/blender/blenkernel/BKE_bad_level_calls.h index 0962a174a8e..71f8aee8e99 100644 --- a/source/blender/blenkernel/BKE_bad_level_calls.h +++ b/source/blender/blenkernel/BKE_bad_level_calls.h @@ -92,6 +92,7 @@ int pytype_is_pynode(struct PyObject *pyob); struct Oops; void free_oops(struct Oops *oops); void error(char *str, ...); +int okee(char *str, ...); /* anim.c */ extern struct ListBase editNurb; diff --git a/source/blender/blenkernel/bad_level_call_stubs/stubs.c b/source/blender/blenkernel/bad_level_call_stubs/stubs.c index 341379de1d9..3012c19ff02 100644 --- a/source/blender/blenkernel/bad_level_call_stubs/stubs.c +++ b/source/blender/blenkernel/bad_level_call_stubs/stubs.c @@ -160,6 +160,7 @@ void BPY_pyconstraint_target(struct bPythonConstraint *con, struct bConstraintTa void free_oops(struct Oops *oops){} void exit_posemode(int freedata){} void error(char *str, ...){} +int okee(char *str, ...){} /* anim.c */ ListBase editNurb; diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index 73c93abdf4b..107953138c6 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -431,14 +431,14 @@ static int handle_subversion_warning(Main *main) char str[128]; + /* XXX DO NOT PORT OVER TO 2.5 BRANCH! */ if(main->minversionfile >= 250) { sprintf(str, "You have opened a %d file, key information will get lost, like animation data. Continue?", main->minversionfile); if(G.background) { printf("ERROR: cannot render %d file\n", main->versionfile); } - error(str); - return 0; + return okee(str); } else { sprintf(str, "File written by newer Blender binary: %d.%d , expect loss of data!", main->minversionfile, main->minsubversionfile); -- cgit v1.2.3 From ab3339f3801dcaedff8d4758c40c612cc65e86c9 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sun, 3 May 2009 11:46:57 +0000 Subject: NLA SoC: Initial commit of changes for the way NLA is evaluated * Recoded the flags for NLA-Strips to take into account the new design directions * Modified parts of the evaluation pipeline to reflect this --- source/blender/blenkernel/intern/action.c | 32 +---- source/blender/blenkernel/intern/anim_sys.c | 212 ++++++++++++++++++++-------- 2 files changed, 159 insertions(+), 85 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index d54bc749b71..f2e3583c87b 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -717,45 +717,25 @@ static bActionStrip *get_active_strip(Object *ob) return NULL; } -/* non clipped mapping of strip */ -static float get_actionstrip_frame(bActionStrip *strip, float cframe, int invert) -{ - float length, actlength, repeat, scale; - - if (strip->repeat == 0.0f) strip->repeat = 1.0f; - repeat = (strip->flag & ACTSTRIP_USESTRIDE) ? (1.0f) : (strip->repeat); - - if (strip->scale == 0.0f) strip->scale= 1.0f; - scale = (float)fabs(strip->scale); /* scale must be positive (for now) */ - - actlength = strip->actend-strip->actstart; - if (actlength == 0.0f) actlength = 1.0f; - length = repeat * scale * actlength; - - /* invert = convert action-strip time to global time */ - if (invert) - return length*(cframe - strip->actstart)/(repeat*actlength) + strip->start; - else - return repeat*actlength*(cframe - strip->start)/length + strip->actstart; -} - /* if the conditions match, it converts current time to strip time */ +// TODO: change this adt float get_action_frame(Object *ob, float cframe) { bActionStrip *strip= get_active_strip(ob); - if(strip) - return get_actionstrip_frame(strip, cframe, 0); + //if(strip) + // return get_actionstrip_frame(strip, cframe, 0); return cframe; } /* inverted, strip time to current time */ +// TODO: change this to adt float get_action_frame_inv(Object *ob, float cframe) { bActionStrip *strip= get_active_strip(ob); - if(strip) - return get_actionstrip_frame(strip, cframe, 1); + //if(strip) + // return get_actionstrip_frame(strip, cframe, 1); return cframe; } diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 30dcb383ef6..2840e3f5d45 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -5,6 +5,7 @@ #include #include #include +#include #include "MEM_guardedalloc.h" @@ -544,19 +545,17 @@ typedef struct NlaEvalStrip { struct NlaEvalStrip *next, *prev; NlaTrack *track; /* track that this strip belongs to */ - NlaStrip *strip; /* strip that's being used */ - NlaStrip *sblend; /* strip that's being blended towards (if applicable) */ + NlaStrip *strip; /* strip that's being used */ short track_index; /* the index of the track within the list */ short strip_mode; /* which end of the strip are we looking at */ } NlaEvalStrip; -/* bNlaEvalStrip->strip_mode */ +/* NlaEvalStrip->strip_mode */ enum { NES_TIME_BEFORE = -1, NES_TIME_WITHIN, NES_TIME_AFTER, - NES_TIME_AFTER_BLEND } eNlaEvalStrip_StripMode; @@ -565,8 +564,9 @@ enum { typedef struct NlaEvalChannel { struct NlaEvalChannel *next, *prev; - char *path; /* ready-to-use path (i.e. remapped already) */ - int array_index; /* if applicable... */ + PointerRNA *ptr; /* pointer to struct containing property to use */ + PropertyRNA *prop; /* RNA-property type to use (should be in the struct given) */ + int index; /* array index (where applicable) */ float value; /* value of this channel */ } NlaEvalChannel; @@ -574,24 +574,98 @@ typedef struct NlaEvalChannel { /* ---------------------- */ -/* evaluate the F-Curves controlling settings for the NLA-strips (currently, not relinkable) */ -static void nlastrip_evaluate_fcurves (NlaStrip *strip, float ctime) +/* non clipped mapping for strip-time <-> global time + * invert = convert action-strip time to global time + */ +static float nlastrip_get_frame (NlaStrip *strip, float cframe, short invert) { - //PointerRNA actstrip_ptr; - //FCurve *fcu; + float length, actlength, repeat, scale; + + /* get number of repeats */ + if (strip->repeat == 0.0f) strip->repeat = 1.0f; + repeat = strip->repeat; + + /* scaling */ + if (strip->scale == 0.0f) strip->scale= 1.0f; + scale = (float)fabs(strip->scale); /* scale must be positive - we've got a special flag for reversing */ - /* create RNA-pointer needed to set values */ - //RNA_pointer_create(NULL, &RNA_NlaStrip, strip, &actstrip_ptr); + /* length of referenced action */ + actlength = strip->actend-strip->actstart; + if (actlength == 0.0f) actlength = 1.0f; - /* execute these settings as per normal */ - //animsys_evaluate_fcurves(&actstrip_ptr, &strip->fcurves, NULL, ctime); + /* length of strip */ + length = repeat * scale * actlength; + + /* reversed = play strip backwards */ + if (strip->flag & NLASTRIP_FLAG_REVERSE) { + // FIXME: verify these + /* invert = convert action-strip time to global time */ + if (invert) + return length*(strip->actend - cframe)/(repeat*actlength) + strip->start; + else + return strip->actend - repeat*actlength*(cframe - strip->start)/length; + } + else { + /* invert = convert action-strip time to global time */ + if (invert) + return length*(cframe - strip->actstart)/(repeat*actlength) + strip->start; + else + return repeat*actlength*(cframe - strip->start)/length + strip->actstart; + } +} + +/* calculate influence of strip based for given frame based on blendin/out values */ +static float nlastrip_get_influence (NlaStrip *strip, float cframe) +{ + /* sanity checks - normalise the blendin/out values? */ + strip->blendin= (float)fabs(strip->blendin); + strip->blendout= (float)fabs(strip->blendout); + + /* result depends on where frame is in respect to blendin/out values */ + // TODO: are the fabs() tests needed here? + if (IS_EQ(strip->blendin, 0)==0 && (cframe <= (strip->start + strip->blendin))) { + /* there is some blend-in */ + return (float)fabs(cframe - strip->start) / (strip->blendin); + } + else if (IS_EQ(strip->blendout, 0)==0 && (cframe >= (strip->end - strip->blendout))) { + /* there is some blend-out */ + return (float)fabs(strip->end - cframe) / (strip->blendout); + } + else { + /* in the middle of the strip, we should be full strength */ + return 1.0f; + } +} + +/* evaluate the evaluation time and influence for the strip, storing the results in the strip */ +void nlastrip_evaluate_controls (NlaStrip *strip, float cframe) +{ + /* firstly, analytically generate values for influence and time (if applicable) */ + if ((strip->flag & NLASTRIP_FLAG_USR_TIME) == 0) + strip->strip_time= nlastrip_get_frame(strip, cframe, 1); /* last arg '1' means current time to 'strip'/action time */ + if ((strip->flag & NLASTRIP_FLAG_USR_INFLUENCE) == 0) + strip->influence= nlastrip_get_influence(strip, cframe); + + /* now strip's evaluate F-Curves for these settings (if applicable) */ + if (strip->fcurves.first) { +#if 0 + PointerRNA strip_ptr; + FCurve *fcu; + + /* create RNA-pointer needed to set values */ + RNA_pointer_create(NULL, &RNA_NlaStrip, strip, &strip_ptr); + + /* execute these settings as per normal */ + animsys_evaluate_fcurves(&actstrip_ptr, &strip->fcurves, NULL, ctime); +#endif + } } -/* gets the strip active at the current time for a track */ +/* gets the strip active at the current time for a track for evaluation purposes */ static void nlatrack_ctime_get_strip (ListBase *list, NlaTrack *nlt, short index, float ctime) { - NlaStrip *strip, *astrip=NULL, *bstrip=NULL; + NlaStrip *strip, *estrip=NULL; NlaEvalStrip *nes; short side= 0; @@ -601,71 +675,91 @@ static void nlatrack_ctime_get_strip (ListBase *list, NlaTrack *nlt, short index /* loop over strips, checking if they fall within the range */ for (strip= nlt->strips.first; strip; strip= strip->next) { - /* only consider if: - * - current time occurs within strip's extents - * - current time occurs before strip (if it is the first) - * - current time occurs after strip (if hold is on) - * - current time occurs between strips (1st of those isn't holding) - blend! - */ + /* check if current time occurs within this strip */ if (IN_RANGE(ctime, strip->start, strip->end)) { - astrip= strip; + /* this strip is active, so try to use it */ + estrip= strip; side= NES_TIME_WITHIN; break; } - else if (ctime < strip->start) { + + /* if time occurred before current strip... */ + if (ctime < strip->start) { if (strip == nlt->strips.first) { - astrip= strip; + /* before first strip - only try to use it if it extends backwards in time too */ + if (strip->extendmode == NLASTRIP_EXTEND_HOLD) + estrip= strip; + + /* side is 'before' regardless of whether there's a useful strip */ side= NES_TIME_BEFORE; - break; } else { - astrip= strip->prev; + /* before next strip - previous strip has ended, but next hasn't begun, + * so blending mode depends on whether strip is being held or not... + * - only occurs when no transition strip added, otherwise the transition would have + * been picked up above... + */ + strip= strip->prev; - if (astrip->flag & NLASTRIP_HOLDLASTFRAME) { - side= NES_TIME_AFTER; - break; - } - else { - bstrip= strip; - side= NES_TIME_AFTER_BLEND; - break; - } + if (strip->extendmode != NLASTRIP_EXTEND_NOTHING) + estrip= strip; + side= NES_TIME_AFTER; + } + break; + } + + /* if time occurred after current strip... */ + if (ctime > strip->end) { + /* only if this is the last strip should we do anything, and only if that is being held */ + if (strip == nlt->strips.last) { + if (strip->extendmode != NLASTRIP_EXTEND_NOTHING) + estrip= strip; + + side= NES_TIME_AFTER; + break; } + + /* otherwise, skip... as the 'before' case will catch it more elegantly! */ } } - /* check if strip has been found (and whether it has data worth considering) */ - if (ELEM(NULL, astrip, astrip->act)) - return; - if (astrip->flag & NLASTRIP_MUTE) + /* check if a valid strip was found + * - must not be muted (i.e. will have contribution + */ + if ((estrip == NULL) || (estrip->flag & NLASTRIP_FLAG_MUTED)) return; - /* check if blending between strips */ - if (side == NES_TIME_AFTER_BLEND) { - /* blending between strips... so calculate influence+act_time of both */ - nlastrip_evaluate_fcurves(astrip, ctime); - nlastrip_evaluate_fcurves(bstrip, ctime); - - if ((astrip->influence <= 0.0f) && (bstrip->influence <= 0.0f)) - return; - } - else { - /* calculate/set the influence+act_time of this strip - don't consider if 0 influence */ - nlastrip_evaluate_fcurves(astrip, ctime); + /* evaluate strip's evaluation controls + * - skip if no influence (i.e. same effect as muting the strip) + * - negative influence is not supported yet... how would that be defined? + */ + // TODO: this sounds a bit hacky having a few isolated F-Curves stuck on some data it operates on... + nlastrip_evaluate_controls(estrip, ctime); + if (estrip->influence <= 0.0f) + return; - if (astrip->influence <= 0.0f) - return; + /* check if strip has valid data to evaluate */ + switch (estrip->type) { + case NLASTRIP_TYPE_CLIP: + /* clip must have some action to evaluate */ + if (estrip->act == NULL) + return; + break; + case NLASTRIP_TYPE_TRANSITION: + /* there must be strips to transition from and to (i.e. prev and next required) */ + // TODO: what happens about cross-track transitions? + if (ELEM(NULL, estrip->prev, estrip->next)) + return; + break; } - - /* allocate new eval-strip for this strip + add to stack */ + /* add to list of strips we need to evaluate */ nes= MEM_callocN(sizeof(NlaEvalStrip), "NlaEvalStrip"); nes->track= nlt; - nes->strip= astrip; - nes->sblend= bstrip; - nes->track_index= index; + nes->strip= estrip; nes->strip_mode= side; + nes->track_index= index; BLI_addtail(list, nes); } -- cgit v1.2.3 From 25b415f310bd181671f11afbe9d9b0ab899a87ec Mon Sep 17 00:00:00 2001 From: Janne Karhu Date: Wed, 6 May 2009 08:33:40 +0000 Subject: Fix for [#18697] 2.49RC1: Keyed Particles fine in viewport but give me a crash during render --- source/blender/blenkernel/intern/particle_system.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index bbf62d033bf..d3ba3fa3802 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -2007,7 +2007,6 @@ static void set_keyed_keys(Object *ob, ParticleSystem *psys) Object *kob = ob; ParticleSystem *kpsys = psys; ParticleData *pa; - ParticleKey state; int totpart = psys->totpart, i, k, totkeys = psys->totkeyed + 1; float prevtime, nexttime, keyedtime; @@ -2031,10 +2030,11 @@ static void set_keyed_keys(Object *ob, ParticleSystem *psys) } psys->flag &= ~PSYS_KEYED; - state.time=-1.0; for(k=0; kparticles; ikeys + k)->time = -1.0; /* use current time */ + if(kpsys->totpart > 0) psys_get_particle_state(kob, kpsys, i%kpsys->totpart, pa->keys + k, 1); -- cgit v1.2.3 From 57beadf40613b3c4ba6f20cbaddc1066c6800bbc Mon Sep 17 00:00:00 2001 From: Janne Karhu Date: Thu, 7 May 2009 22:31:19 +0000 Subject: Second fix for [#18697] 2.49RC1: Keyed Particles fine in viewport but give me a crash during render --- source/blender/blenkernel/intern/particle_system.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index d3ba3fa3802..f74e32acdbf 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -203,8 +203,11 @@ static void realloc_particles(Object *ob, ParticleSystem *psys, int new_totpart) if(psys->particles->keys) MEM_freeN(psys->particles->keys); - for(i=0, pa=psys->particles; ikeys) pa->keys= NULL; + for(i=totsaved, pa=psys->particles+totsaved; itotpart; i++, pa++) + if(pa->keys) { + pa->keys= NULL; + pa->totkey= 0; + } for(i=totsaved, pa=psys->particles+totsaved; itotpart; i++, pa++) if(pa->hair) MEM_freeN(pa->hair); -- cgit v1.2.3 From 0aeaf08242631cd53a2d1065b3a7686d0022d77c Mon Sep 17 00:00:00 2001 From: Janne Karhu Date: Mon, 11 May 2009 19:19:36 +0000 Subject: Ugh, yet another try to fix [#18697] 2.49RC1: Keyed Particles fine in viewport but give me a crash during render. Hopefully it's now fixed for good. --- source/blender/blenkernel/intern/particle.c | 12 +++++++++++- source/blender/blenkernel/intern/particle_system.c | 2 +- 2 files changed, 12 insertions(+), 2 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 0ebdcdf58e0..41ce23347a3 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -351,8 +351,18 @@ void free_hair(ParticleSystem *psys, int softbody) } void free_keyed_keys(ParticleSystem *psys) { - if(psys->particles && psys->particles->keys) + ParticleData *pa; + int i; + + if(psys->particles && psys->particles->keys) { MEM_freeN(psys->particles->keys); + + for(i=0, pa=psys->particles; itotpart; i++, pa++) + if(pa->keys) { + pa->keys= NULL; + pa->totkey= 0; + } + } } void free_child_path_cache(ParticleSystem *psys) { diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index f74e32acdbf..3445556b53b 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -203,7 +203,7 @@ static void realloc_particles(Object *ob, ParticleSystem *psys, int new_totpart) if(psys->particles->keys) MEM_freeN(psys->particles->keys); - for(i=totsaved, pa=psys->particles+totsaved; itotpart; i++, pa++) + for(i=0, pa=psys->particles; itotpart; i++, pa++) if(pa->keys) { pa->keys= NULL; pa->totkey= 0; -- cgit v1.2.3 From b6fa9afccb941aa413ac788a5bc73d9170fd6228 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 12 May 2009 15:28:07 +0000 Subject: [#13726] Segfault with (Re)Appending objects fix this by freeing the lib-file-data after linking or appending, re-appending will be slower now (as slow as appending for the first time). Not strictly needed, set the memory for bhead's to zero in readfile.c since comparisons are done later on with this data making valgrind complain. Added some missing headers too. --- source/blender/blenkernel/intern/fluidsim.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/fluidsim.c b/source/blender/blenkernel/intern/fluidsim.c index 29c4e0f2fb5..b650f3a3e98 100644 --- a/source/blender/blenkernel/intern/fluidsim.c +++ b/source/blender/blenkernel/intern/fluidsim.c @@ -36,6 +36,8 @@ #include "DNA_particle_types.h" #include "DNA_scene_types.h" // N_T +#include "PIL_time.h" // for PIL_sleep_ms + #include "BLI_arithb.h" #include "BLI_blenlib.h" -- cgit v1.2.3 From c7519789b8a7ba8973b2a165b2d008679c3f8241 Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Wed, 13 May 2009 17:02:39 +0000 Subject: BGE: 1-liner patch to put the Always sensor in non pulse mode by default. I've seen enough games with Always sensors in pulse mode while they should not; this patch should prevent this common mistake. --- source/blender/blenkernel/intern/sca.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/sca.c b/source/blender/blenkernel/intern/sca.c index 47d11bb9d29..bbca97d75f7 100644 --- a/source/blender/blenkernel/intern/sca.c +++ b/source/blender/blenkernel/intern/sca.c @@ -134,7 +134,7 @@ void init_sensor(bSensor *sens) switch(sens->type) { case SENS_ALWAYS: - sens->pulse = 1; + sens->pulse = 0; break; case SENS_TOUCH: sens->data= MEM_callocN(sizeof(bTouchSensor), "touchsens"); -- cgit v1.2.3 From a74d2574ee5322dc29754fe2ac93e100fcf73633 Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Thu, 14 May 2009 09:32:47 +0000 Subject: Bugfix #18725 Particles using group-duplication, with Metaballs in group, enter eternal loop in our code now. This is a non-supported case... metaball code doesn't support recursions. Added a provision in code to catch this case, and print an error in console to denote this. --- source/blender/blenkernel/intern/mball.c | 5 ++++- source/blender/blenkernel/intern/scene.c | 16 ++++++++++++++-- 2 files changed, 18 insertions(+), 3 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c index 79205814ae7..97226b5ec42 100644 --- a/source/blender/blenkernel/intern/mball.c +++ b/source/blender/blenkernel/intern/mball.c @@ -297,7 +297,10 @@ Object *find_basis_mball(Object *basis) splitIDname(basis->id.name+2, basisname, &basisnr); totelem= 0; - next_object(0, 0, 0); + /* XXX recursion check, see scene.c, just too simple code this next_object() */ + if(F_ERROR==next_object(0, 0, 0)) + return NULL; + while(next_object(1, &base, &ob)) { if (ob->type==OB_MBALL) { diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 5def3577218..ed1a77d645e 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -402,16 +402,25 @@ int next_object(int val, Base **base, Object **ob) { static ListBase *duplilist= NULL; static DupliObject *dupob; - static int fase; + static int fase= F_START, in_next_object= 0; int run_again=1; /* init */ if(val==0) { fase= F_START; dupob= NULL; + + /* XXX particle systems with metas+dupligroups call this recursively */ + /* see bug #18725 */ + if(in_next_object) { + printf("ERROR: MetaBall generation called recursively, not supported\n"); + + return F_ERROR; + } } else { - + in_next_object= 1; + /* run_again is set when a duplilist has been ended */ while(run_again) { run_again= 0; @@ -493,6 +502,9 @@ int next_object(int val, Base **base, Object **ob) } } + /* reset recursion test */ + in_next_object= 0; + return fase; } -- cgit v1.2.3 From e295cfd4d5e9adcd006cbab95f84eb93a73ea6bc Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 15 May 2009 13:23:03 +0000 Subject: NLA Branch: Setting up evaluation system for action strips * Refactored F-Curve Modifier stack evaluation into functions which can be reused for F-Curve Modifiers on NLA-Strips * Started setting up temporary accumulation buffer system for use when evaluating strips --- source/blender/blenkernel/BKE_fcurve.h | 6 +- source/blender/blenkernel/intern/anim_sys.c | 110 ++++++++++++++++++-- source/blender/blenkernel/intern/fcurve.c | 156 +++++++++++++++++----------- 3 files changed, 201 insertions(+), 71 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h index 9b8a2990fe5..7058b9d236a 100644 --- a/source/blender/blenkernel/BKE_fcurve.h +++ b/source/blender/blenkernel/BKE_fcurve.h @@ -108,11 +108,15 @@ struct FModifier *fcurve_add_modifier(struct FCurve *fcu, int type); void fcurve_copy_modifiers(ListBase *dst, ListBase *src); void fcurve_remove_modifier(struct FCurve *fcu, struct FModifier *fcm); void fcurve_free_modifiers(struct FCurve *fcu); -void fcurve_bake_modifiers(struct FCurve *fcu, int start, int end); struct FModifier *fcurve_find_active_modifier(struct FCurve *fcu); void fcurve_set_active_modifier(struct FCurve *fcu, struct FModifier *fcm); +float evaluate_time_fmodifiers(ListBase *modifiers, struct FCurve *fcu, float cvalue, float evaltime); +void evaluate_value_fmodifiers(ListBase *modifiers, struct FCurve *fcu, float *cvalue, float evaltime); + +void fcurve_bake_modifiers(struct FCurve *fcu, int start, int end); + /* ************** F-Curves API ******************** */ /* -------- Data Managemnt -------- */ diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 2840e3f5d45..5a4a2d91469 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -6,6 +6,7 @@ #include #include #include +#include #include "MEM_guardedalloc.h" @@ -564,7 +565,7 @@ enum { typedef struct NlaEvalChannel { struct NlaEvalChannel *next, *prev; - PointerRNA *ptr; /* pointer to struct containing property to use */ + PointerRNA ptr; /* pointer to struct containing property to use */ PropertyRNA *prop; /* RNA-property type to use (should be in the struct given) */ int index; /* array index (where applicable) */ @@ -638,13 +639,13 @@ static float nlastrip_get_influence (NlaStrip *strip, float cframe) } /* evaluate the evaluation time and influence for the strip, storing the results in the strip */ -void nlastrip_evaluate_controls (NlaStrip *strip, float cframe) +void nlastrip_evaluate_controls (NlaStrip *strip, float ctime) { /* firstly, analytically generate values for influence and time (if applicable) */ if ((strip->flag & NLASTRIP_FLAG_USR_TIME) == 0) - strip->strip_time= nlastrip_get_frame(strip, cframe, 1); /* last arg '1' means current time to 'strip'/action time */ + strip->strip_time= nlastrip_get_frame(strip, ctime, 1); /* last arg '1' means current time to 'strip'/action time */ if ((strip->flag & NLASTRIP_FLAG_USR_INFLUENCE) == 0) - strip->influence= nlastrip_get_influence(strip, cframe); + strip->influence= nlastrip_get_influence(strip, ctime); /* now strip's evaluate F-Curves for these settings (if applicable) */ if (strip->fcurves.first) { @@ -766,13 +767,104 @@ static void nlatrack_ctime_get_strip (ListBase *list, NlaTrack *nlt, short index /* ---------------------- */ +/* verify that an appropriate NlaEvalChannel for this F-Curve */ +static NlaEvalChannel *nlaevalchan_verify (PointerRNA *ptr, ListBase *channels, NlaEvalStrip *nes, FCurve *fcu, short *newChan) +{ + NlaEvalChannel *nec= NULL; + NlaStrip *strip= nes->strip; + PropertyRNA *prop; + PointerRNA new_ptr; + char *path = NULL; + short free_path=0; + + /* sanity checks */ + if (channels == NULL) + return NULL; + + /* get RNA pointer+property info from F-Curve for more convenient handling */ + /* get path, remapped as appropriate to work in its new environment */ + free_path= animsys_remap_path(strip->remap, fcu->rna_path, &path); + + /* get property to write to */ + if (RNA_path_resolve(ptr, path, &new_ptr, &prop) == 0) + return NULL; + /* only ok if animateable */ + else if (RNA_property_animateable(&new_ptr, prop) == 0) + return NULL; + + /* loop through existing channels, checking for a channel which affects the same property */ + for (nec= channels->first; nec; nec= nec->next) { + if ((nec->ptr.data == new_ptr.data) && (nec->prop == prop)) + return nec; + } + + /* allocate a new struct for this */ + nec= MEM_callocN(sizeof(NlaEvalChannel), "NlaEvalChannel"); + *newChan= 1; + BLI_addtail(channels, nec); + + nec->ptr= new_ptr; + nec->prop= prop; + nec->index= fcu->array_index; + + return nec; +} + +/* ---------------------- */ + +/* evaluate action-clip strip */ +static void nlastrip_evaluate_actionclip (PointerRNA *ptr, ListBase *channels, NlaEvalStrip *nes) +{ + NlaStrip *strip= nes->strip; + FCurve *fcu; + float evaltime; + + /* evaluate strip's modifiers which modify time to evaluate the base curves at */ + evaltime= evaluate_time_fmodifiers(&strip->modifiers, NULL, 0.0f, strip->strip_time); + + /* evaluate all the F-Curves in the action, saving the relevant pointers to data that will need to be used */ + for (fcu= strip->act->curves.first; fcu; fcu= fcu->next) { + NlaEvalChannel *nec; + float value = 0.0f; + short newChan = -1; + + /* check if this curve should be skipped */ + if (fcu->flag & (FCURVE_MUTED|FCURVE_DISABLED)) + continue; + + /* evaluate the F-Curve's value for the time given in the strip + * NOTE: we use the modified time here, since strip's F-Curve Modifiers are applied on top of this + */ + value= evaluate_fcurve(fcu, evaltime); + + /* apply strip's F-Curve Modifiers on this value + * NOTE: we apply the strip's original evaluation time not the modified one (as per standard F-Curve eval) + */ + evaluate_value_fmodifiers(&strip->modifiers, fcu, &value, strip->strip_time); + + + /* get an NLA evaluation channel to work with, and accumulate the evaluated value with the value(s) + * stored in this channel if it has been used already + */ + nec= nlaevalchan_verify(ptr, channels, nes, fcu, &newChan); + //if (nec) + // nlaevalchan_accumulate(ptr, nec, nes, newChan, value); + } +} + /* evaluates the given evaluation strip */ -// FIXME: will we need the evaluation cache table set up to blend stuff in? // TODO: only evaluate here, but flush in one go using the accumulated channels at end... -static void nlastrip_ctime_evaluate (ListBase *channels, NlaEvalStrip *nes, float ctime) +static void nlastrip_evaluate (PointerRNA *ptr, ListBase *channels, NlaEvalStrip *nes) { - // 1. (in old code) was to extract 'IPO-channels' from actions - // 2. blend between the 'accumulated' data, and the new data + /* actions to take depend on the type of strip */ + switch (nes->strip->type) { + case NLASTRIP_TYPE_CLIP: /* action-clip */ + nlastrip_evaluate_actionclip(ptr, channels, nes); + break; + case NLASTRIP_TYPE_TRANSITION: /* transition */ + // XXX code this... + break; + } } /* write the accumulated settings to */ @@ -807,7 +899,7 @@ static void animsys_evaluate_nla (PointerRNA *ptr, AnimData *adt, float ctime) /* 2. for each strip, evaluate then accumulate on top of existing channels, but don't set values yet */ for (nes= estrips.first; nes; nes= nes->next) - nlastrip_ctime_evaluate(&echannels, nes, ctime); + nlastrip_evaluate(ptr, &echannels, nes); /* 3. flush effects of accumulating channels in NLA to the actual data they affect */ nladata_flush_channels(ptr, &echannels); diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index cade555a07a..1a40911170e 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -2166,34 +2166,6 @@ void fcurve_free_modifiers (FCurve *fcu) } } -/* Bake modifiers for given F-Curve to curve sample data, in the frame range defined - * by start and end (inclusive). - */ -void fcurve_bake_modifiers (FCurve *fcu, int start, int end) -{ - ChannelDriver *driver; - - /* sanity checks */ - // TODO: make these tests report errors using reports not printf's - if ELEM(NULL, fcu, fcu->modifiers.first) { - printf("Error: No F-Curve with F-Curve Modifiers to Bake\n"); - return; - } - - /* temporarily, disable driver while we sample, so that they don't influence the outcome */ - driver= fcu->driver; - fcu->driver= NULL; - - /* bake the modifiers, by sampling the curve at each frame */ - fcurve_store_samples(fcu, NULL, start, end, fcurve_samplingcb_evalcurve); - - /* free the modifiers now */ - fcurve_free_modifiers(fcu); - - /* restore driver */ - fcu->driver= driver; -} - /* Find the active F-Curve Modifier */ FModifier *fcurve_find_active_modifier (FCurve *fcu) { @@ -2231,6 +2203,98 @@ void fcurve_set_active_modifier (FCurve *fcu, FModifier *fcm) fcm->flag |= FMODIFIER_FLAG_ACTIVE; } +/* Evaluation API --------------------------- */ + +/* evaluate time modifications imposed by some F-Curve Modifiers + * - this step acts as an optimisation to prevent the F-Curve stack being evaluated + * several times by modifiers requesting the time be modified, as the final result + * would have required using the modified time + * - modifiers only ever recieve the unmodified time, as subsequent modifiers should be + * working on the 'global' result of the modified curve, not some localised segment, + * so nevaltime gets set to whatever the last time-modifying modifier likes... + * - we start from the end of the stack, as only the last one matters for now + */ +float evaluate_time_fmodifiers (ListBase *modifiers, FCurve *fcu, float cvalue, float evaltime) +{ + FModifier *fcm; + float m_evaltime= evaltime; + + /* sanity checks */ + if ELEM(NULL, modifiers, modifiers->first) + return evaltime; + + /* find the first modifier from end of stack that modifies time, and calculate the time the modifier + * would calculate time at + */ + for (fcm= fcu->modifiers.last; fcm; fcm= fcm->prev) { + FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm); + + /* only evaluate if there's a callback for this */ + // TODO: implement the 'influence' control feature... + if (fmi && fmi->evaluate_modifier_time) { + if ((fcm->flag & (FMODIFIER_FLAG_DISABLED|FMODIFIER_FLAG_MUTED)) == 0) + m_evaltime= fmi->evaluate_modifier_time(fcu, fcm, cvalue, evaltime); + break; + } + } + + /* return the modified evaltime */ + return m_evaltime; +} + +/* Evalautes the given set of F-Curve Modifiers using the given data + * Should only be called after evaluate_time_fmodifiers() has been called... + */ +void evaluate_value_fmodifiers (ListBase *modifiers, FCurve *fcu, float *cvalue, float evaltime) +{ + FModifier *fcm; + + /* sanity checks */ + if ELEM(NULL, modifiers, modifiers->first) + return; + + /* evaluate modifiers */ + for (fcm= modifiers->first; fcm; fcm= fcm->next) { + FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm); + + /* only evaluate if there's a callback for this */ + // TODO: implement the 'influence' control feature... + if (fmi && fmi->evaluate_modifier) { + if ((fcm->flag & (FMODIFIER_FLAG_DISABLED|FMODIFIER_FLAG_MUTED)) == 0) + fmi->evaluate_modifier(fcu, fcm, cvalue, evaltime); + } + } +} + + +/* Bake modifiers for given F-Curve to curve sample data, in the frame range defined + * by start and end (inclusive). + */ +void fcurve_bake_modifiers (FCurve *fcu, int start, int end) +{ + ChannelDriver *driver; + + /* sanity checks */ + // TODO: make these tests report errors using reports not printf's + if ELEM(NULL, fcu, fcu->modifiers.first) { + printf("Error: No F-Curve with F-Curve Modifiers to Bake\n"); + return; + } + + /* temporarily, disable driver while we sample, so that they don't influence the outcome */ + driver= fcu->driver; + fcu->driver= NULL; + + /* bake the modifiers, by sampling the curve at each frame */ + fcurve_store_samples(fcu, NULL, start, end, fcurve_samplingcb_evalcurve); + + /* free the modifiers now */ + fcurve_free_modifiers(fcu); + + /* restore driver */ + fcu->driver= driver; +} + /* ***************************** F-Curve - Evaluation ********************************* */ /* Evaluate and return the value of the given F-Curve at the specified frame ("evaltime") @@ -2238,7 +2302,6 @@ void fcurve_set_active_modifier (FCurve *fcu, FModifier *fcm) */ float evaluate_fcurve (FCurve *fcu, float evaltime) { - FModifier *fcm; float cvalue= 0.0f; float devaltime; @@ -2251,28 +2314,8 @@ float evaluate_fcurve (FCurve *fcu, float evaltime) evaltime= cvalue= evaluate_driver(fcu->driver, evaltime); } - /* evaluate time modifications imposed by some F-Curve Modifiers - * - this step acts as an optimisation to prevent the F-Curve stack being evaluated - * several times by modifiers requesting the time be modified, as the final result - * would have required using the modified time - * - modifiers only ever recieve the unmodified time, as subsequent modifiers should be - * working on the 'global' result of the modified curve, not some localised segment, - * so nevaltime gets set to whatever the last time-modifying modifier likes... - * - we start from the end of the stack, as only the last one matters for now - */ - devaltime= evaltime; - - for (fcm= fcu->modifiers.last; fcm; fcm= fcm->prev) { - FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm); - - /* only evaluate if there's a callback for this */ - // TODO: implement the 'influence' control feature... - if (fmi && fmi->evaluate_modifier_time) { - if ((fcm->flag & (FMODIFIER_FLAG_DISABLED|FMODIFIER_FLAG_MUTED)) == 0) - devaltime= fmi->evaluate_modifier_time(fcu, fcm, cvalue, evaltime); - break; - } - } + /* evaluate modifiers which modify time to evaluate the base curve at */ + devaltime= evaluate_time_fmodifiers(&fcu->modifiers, fcu, cvalue, evaltime); /* evaluate curve-data * - 'devaltime' instead of 'evaltime', as this is the time that the last time-modifying @@ -2284,16 +2327,7 @@ float evaluate_fcurve (FCurve *fcu, float evaltime) cvalue= fcurve_eval_samples(fcu, fcu->fpt, devaltime); /* evaluate modifiers */ - for (fcm= fcu->modifiers.first; fcm; fcm= fcm->next) { - FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm); - - /* only evaluate if there's a callback for this */ - // TODO: implement the 'influence' control feature... - if (fmi && fmi->evaluate_modifier) { - if ((fcm->flag & (FMODIFIER_FLAG_DISABLED|FMODIFIER_FLAG_MUTED)) == 0) - fmi->evaluate_modifier(fcu, fcm, &cvalue, evaltime); - } - } + evaluate_value_fmodifiers(&fcu->modifiers, fcu, &cvalue, evaltime); /* if curve can only have integral values, perform truncation (i.e. drop the decimal part) * here so that the curve can be sampled correctly -- cgit v1.2.3 From cebf6cb22deb930f5ec235e81c20072bf7154a83 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sat, 16 May 2009 01:00:41 +0000 Subject: NLA SoC: Code for basic evaluation of NLA strips done In theory, actions can now be evaluated in NLA, though in practice, we don't have an NLA Editor to create data to use this yet! Next up, transitions... Some notes: * Recoded the way the 'accumulation' methods work (i.e. blend, add, etc.), adding a few new ones. It should now be more obvious how these work. * Some assorted code cleanups done too (removing unneeded vars/args) --- source/blender/blenkernel/intern/anim_sys.c | 157 ++++++++++++++++++++++++---- 1 file changed, 135 insertions(+), 22 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 5a4a2d91469..702da23ef47 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -735,8 +735,9 @@ static void nlatrack_ctime_get_strip (ListBase *list, NlaTrack *nlt, short index * - negative influence is not supported yet... how would that be defined? */ // TODO: this sounds a bit hacky having a few isolated F-Curves stuck on some data it operates on... + // TODO: should we clamp the time to only be on the endpoints of the strip? nlastrip_evaluate_controls(estrip, ctime); - if (estrip->influence <= 0.0f) + if (estrip->influence <= 0.0f) // XXX is it useful to invert the strip? return; /* check if strip has valid data to evaluate */ @@ -767,10 +768,36 @@ static void nlatrack_ctime_get_strip (ListBase *list, NlaTrack *nlt, short index /* ---------------------- */ -/* verify that an appropriate NlaEvalChannel for this F-Curve */ +/* find an NlaEvalChannel that matches the given criteria + * - ptr and prop are the RNA data to find a match for + */ +static NlaEvalChannel *nlaevalchan_find_match (ListBase *channels, PointerRNA *ptr, PropertyRNA *prop, int array_index) +{ + NlaEvalChannel *nec; + + /* sanity check */ + if (channels == NULL) + return NULL; + + /* loop through existing channels, checking for a channel which affects the same property */ + for (nec= channels->first; nec; nec= nec->next) { + /* - comparing the PointerRNA's is done by comparing the pointers + * to the actual struct the property resides in, since that all the + * other data stored in PointerRNA cannot allow us to definitively + * identify the data + */ + if ((nec->ptr.data == ptr->data) && (nec->prop == prop) && (nec->index == array_index)) + return nec; + } + + /* not found */ + return NULL; +} + +/* verify that an appropriate NlaEvalChannel for this F-Curve exists */ static NlaEvalChannel *nlaevalchan_verify (PointerRNA *ptr, ListBase *channels, NlaEvalStrip *nes, FCurve *fcu, short *newChan) { - NlaEvalChannel *nec= NULL; + NlaEvalChannel *nec; NlaStrip *strip= nes->strip; PropertyRNA *prop; PointerRNA new_ptr; @@ -785,31 +812,79 @@ static NlaEvalChannel *nlaevalchan_verify (PointerRNA *ptr, ListBase *channels, /* get path, remapped as appropriate to work in its new environment */ free_path= animsys_remap_path(strip->remap, fcu->rna_path, &path); - /* get property to write to */ - if (RNA_path_resolve(ptr, path, &new_ptr, &prop) == 0) + /* a valid property must be available, and it must be animateable */ + if (RNA_path_resolve(ptr, path, &new_ptr, &prop) == 0) { + if (G.f & G_DEBUG) printf("NLA Strip Eval: Cannot resolve path \n"); return NULL; + } /* only ok if animateable */ - else if (RNA_property_animateable(&new_ptr, prop) == 0) + else if (RNA_property_animateable(&new_ptr, prop) == 0) { + if (G.f & G_DEBUG) printf("NLA Strip Eval: Property not animateable \n"); return NULL; - - /* loop through existing channels, checking for a channel which affects the same property */ - for (nec= channels->first; nec; nec= nec->next) { - if ((nec->ptr.data == new_ptr.data) && (nec->prop == prop)) - return nec; } - /* allocate a new struct for this */ - nec= MEM_callocN(sizeof(NlaEvalChannel), "NlaEvalChannel"); - *newChan= 1; - BLI_addtail(channels, nec); + /* try to find a match */ + nec= nlaevalchan_find_match(channels, &new_ptr, prop, fcu->array_index); - nec->ptr= new_ptr; - nec->prop= prop; - nec->index= fcu->array_index; + /* allocate a new struct for this if none found */ + if (nec == NULL) { + nec= MEM_callocN(sizeof(NlaEvalChannel), "NlaEvalChannel"); + *newChan= 1; + BLI_addtail(channels, nec); + + nec->ptr= new_ptr; + nec->prop= prop; + nec->index= fcu->array_index; + } + /* we can now return */ return nec; } +/* accumulate (i.e. blend) the given value on to the channel it affects */ +static void nlaevalchan_accumulate (NlaEvalChannel *nec, NlaEvalStrip *nes, short newChan, float value) +{ + NlaStrip *strip= nes->strip; + float inf= strip->influence; + + /* if channel is new, just store value regardless of blending factors, etc. */ + if (newChan) { + nec->value= value; + return; + } + + /* premultiply the value by the weighting factor */ + if (IS_EQ(inf, 0)) return; + value *= inf; + + /* perform blending */ + switch (strip->blendmode) { + case NLASTRIP_MODE_ADD: + /* simply add the scaled value on to the stack */ + nec->value += value; + break; + + case NLASTRIP_MODE_SUBTRACT: + /* simply subtract the scaled value from the stack */ + nec->value -= value; + break; + + case NLASTRIP_MODE_MULTIPLY: + /* multiply the scaled value with the stack */ + nec->value *= value; + break; + + case NLASTRIP_MODE_BLEND: + default: // TODO: do we really want to blend by default? it seems more uses might prefer add... + /* do linear interpolation + * - the influence of the accumulated data (elsewhere, that is called dstweight) + * is 1 - influence, since the strip's influence is srcweight + */ + nec->value= nec->value * (1.0f - inf) + value; + break; + } +} + /* ---------------------- */ /* evaluate action-clip strip */ @@ -847,8 +922,8 @@ static void nlastrip_evaluate_actionclip (PointerRNA *ptr, ListBase *channels, N * stored in this channel if it has been used already */ nec= nlaevalchan_verify(ptr, channels, nes, fcu, &newChan); - //if (nec) - // nlaevalchan_accumulate(ptr, nec, nes, newChan, value); + if (nec) + nlaevalchan_accumulate(nec, nes, newChan, value); } } @@ -868,9 +943,47 @@ static void nlastrip_evaluate (PointerRNA *ptr, ListBase *channels, NlaEvalStrip } /* write the accumulated settings to */ -static void nladata_flush_channels (PointerRNA *ptr, ListBase *channels) +static void nladata_flush_channels (ListBase *channels) { + NlaEvalChannel *nec; + /* sanity checks */ + if (channels == NULL) + return; + + /* for each channel with accumulated values, write its value on the property it affects */ + for (nec= channels->first; nec; nec= nec->next) { + PointerRNA *ptr= &nec->ptr; + PropertyRNA *prop= nec->prop; + int array_index= nec->index; + float value= nec->value; + + /* write values - see animsys_write_rna_setting() to sync the code */ + switch (RNA_property_type(prop)) + { + case PROP_BOOLEAN: + if (RNA_property_array_length(prop)) + RNA_property_boolean_set_index(ptr, prop, array_index, (int)value); + else + RNA_property_boolean_set(ptr, prop, (int)value); + break; + case PROP_INT: + if (RNA_property_array_length(prop)) + RNA_property_int_set_index(ptr, prop, array_index, (int)value); + else + RNA_property_int_set(ptr, prop, (int)value); + break; + case PROP_FLOAT: + if (RNA_property_array_length(prop)) + RNA_property_float_set_index(ptr, prop, array_index, value); + else + RNA_property_float_set(ptr, prop, value); + break; + case PROP_ENUM: + RNA_property_enum_set(ptr, prop, (int)value); + break; + } + } } /* ---------------------- */ @@ -902,7 +1015,7 @@ static void animsys_evaluate_nla (PointerRNA *ptr, AnimData *adt, float ctime) nlastrip_evaluate(ptr, &echannels, nes); /* 3. flush effects of accumulating channels in NLA to the actual data they affect */ - nladata_flush_channels(ptr, &echannels); + nladata_flush_channels(&echannels); /* 4. free temporary evaluation data */ BLI_freelistN(&estrips); -- cgit v1.2.3 From 96aa60cee36dfb8a98501b6b9d4c88222b909c35 Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Sun, 17 May 2009 12:25:06 +0000 Subject: cmake: apply ADD_SUBDIR patch. --- source/blender/blenkernel/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index 27be1b45779..3a8058b2b21 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -66,7 +66,7 @@ IF(WITH_FFMPEG) ENDIF(WITH_FFMPEG) IF(WITH_PLAYER) - SUBDIRS(bad_level_call_stubs) + ADD_SUBDIRECTORY(bad_level_call_stubs) ENDIF(WITH_PLAYER) BLENDERLIB(bf_blenkernel "${SRC}" "${INC}") -- cgit v1.2.3 From 9ce8a676906b6b07b0971f0d5886ae338d188629 Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Sun, 17 May 2009 20:37:13 +0000 Subject: BGE Dome: removing of size option and adding tilt option. - Size adjustments can be accomplished with warp mesh data now. So we get a free spot in the GUI for a tilt option. - Tilt option to tilt the camera (for planetarium domes). Angle is in degree from -180 to +180. It's needed for planetarium domes (as this one http://domejunky.blogspot.com/2009/05/dome-corrected-bge.html ). - This is the last commit regarding dome code I expected to 2.49. I consider this feature full implemented now. (working on docs now) --- source/blender/blenkernel/intern/scene.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index ed1a77d645e..df304568ed5 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -232,9 +232,9 @@ Scene *add_scene(char *name) sce->r.stereomode = 1; // no stereo sce->r.domeangle = 180; sce->r.domemode = 1; - sce->r.domesize = 1.0f; sce->r.domeres = 4; sce->r.domeresbuf = 1.0f; + sce->r.dometilt = 0; sce->r.simplify_subsurf= 6; sce->r.simplify_particles= 1.0f; -- cgit v1.2.3 From 07fc2aa5268da7708a289fa785b0f0cbd9be2575 Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Mon, 18 May 2009 08:22:51 +0000 Subject: BGE #18665: Servo control and relative motion Servo control motion actuator did not work as expected when the object is moving on a moving platform. This patch introduces a new Ref field in the servo motion actuator to set a reference object for the velocity calculation. You can set the object during the game using the actuator "reference" attribute; use an object name or an object reference. The servo controller takes into account the angular velocity of the reference object to compute the relative local velocity. --- source/blender/blenkernel/intern/sca.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/sca.c b/source/blender/blenkernel/intern/sca.c index bbca97d75f7..ea7b566c3b5 100644 --- a/source/blender/blenkernel/intern/sca.c +++ b/source/blender/blenkernel/intern/sca.c @@ -579,6 +579,10 @@ void set_sca_new_poins_ob(Object *ob) bCameraActuator *ca= act->data; ID_NEW(ca->ob); } + else if(act->type==ACT_OBJECT) { + bObjectActuator *oa= act->data; + ID_NEW(oa->reference); + } else if(act->type==ACT_SCENE) { bSceneActuator *sca= act->data; ID_NEW(sca->camera); @@ -606,6 +610,7 @@ void sca_remove_ob_poin(Object *obt, Object *ob) bMessageSensor *ms; bActuator *act; bCameraActuator *ca; + bObjectActuator *oa; bSceneActuator *sa; bEditObjectActuator *eoa; bPropertyActuator *pa; @@ -628,6 +633,10 @@ void sca_remove_ob_poin(Object *obt, Object *ob) ca= act->data; if(ca->ob==ob) ca->ob= NULL; break; + case ACT_OBJECT: + oa= act->data; + if(oa->reference==ob) oa->reference= NULL; + break; case ACT_PROPERTY: pa= act->data; if(pa->ob==ob) pa->ob= NULL; -- cgit v1.2.3 From 3f584de8ecf76ad084b15eb4fb1e78e827ab1328 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 21 May 2009 07:28:02 +0000 Subject: [#18795] Subdivide Smooth can give wrong vcol weights given by subdivide are not normalized, if that was fixed could avoid clamping. --- source/blender/blenkernel/intern/customdata.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index 6d5b86fa874..4038ccb1ea7 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -33,7 +33,7 @@ */ #include "BKE_customdata.h" - +#include "BKE_utildefines.h" // CLAMP #include "BLI_blenlib.h" #include "BLI_linklist.h" #include "BLI_mempool.h" @@ -421,6 +421,14 @@ static void layerInterp_mloopcol(void **sources, float *weights, col.b += src->b * weight; } } + + /* Subdivide smooth or fractal can cause problems without clamping + * although weights should also not cause this situation */ + CLAMP(col.a, 0.0f, 255.0f); + CLAMP(col.r, 0.0f, 255.0f); + CLAMP(col.g, 0.0f, 255.0f); + CLAMP(col.b, 0.0f, 255.0f); + mc->a = (int)col.a; mc->r = (int)col.r; mc->g = (int)col.g; @@ -496,6 +504,14 @@ static void layerInterp_mcol(void **sources, float *weights, } for(j = 0; j < 4; ++j) { + + /* Subdivide smooth or fractal can cause problems without clamping + * although weights should also not cause this situation */ + CLAMP(col[j].a, 0.0f, 255.0f); + CLAMP(col[j].r, 0.0f, 255.0f); + CLAMP(col[j].g, 0.0f, 255.0f); + CLAMP(col[j].b, 0.0f, 255.0f); + mc[j].a = (int)col[j].a; mc[j].r = (int)col[j].r; mc[j].g = (int)col[j].g; -- cgit v1.2.3 From 06a7155b681cdb02c6b75b9934f9235efcc6c297 Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Thu, 21 May 2009 13:32:15 +0000 Subject: BGE: user control to compound shape and setParent. Compound shape control ====================== 1) GUI control It is now possible to control which child shape is added to a parent compound shape in the Physics buttons. The "Compound" shape button becomes "Add to parent" on child objects and determines whether the child shape is to be added to the top parent compound shape when the game is stated. Notes: * "Compound" is only available to top parent objects (objects without parent). * Nesting of compound shape is not possible: a child object with "Add to parent" button set will be added to the top parent compound shape, regardless of its position in the parent-child hierarchy and even if its immediate parent doesn't have the "Add to parent" button set. 2) runtime control It is now possible to control the compound shape at runtime: The SetParent actuator has a new "Compound" button that indicates whether the object shape should be added to the compound shape of the parent object, provided the parent has a compound shape of course. If not, the object retain it's individual state while parented. Similarly, the KX_GameObject.setParent() python function has a new compound parameter. Notes: * When an object is dynamically added to a compound shape, it looses temporarily all its physics capability to the benefit of the parent: it cannot register collisions and the characteristics of its shape are lost (ghost, sensor, dynamic, etc.). * Nested compound shape is not supported: if the object being parented is already a compound shape, it is not added to the compound parent (as if the Compound option was not set in the actuator or the setParent function). * To ensure compatibility with old blend files, the Blender subversion is changed to 2.48.5 and the old blend files are automatically converted to match the old behavior: all children of a Compound object will have the "Add to parent" button set automatically. Child ghost control =================== It is now possible to control if an object should becomes ghost or solid when parented. This is only applicable if the object is not added to the parent compound shape (see above). A new "Ghost" button is available on the SetParent actuator to that effect. Similarly the KX_GameObject.setParent() python function has a new compound parameter. Notes: * This option is not applicable to sensor objects: they stay ghost all the time. * Make sure the child object does not enter in collision with the parent shape when the Ghost option if off and the parent is dynamic: the collision creates a reaction force but the parent cannot escape the child, so the force builds up and produces eratic movements. * The collision capability of an ordinary object (dynamic or static) is limited when it is parented: it becomes automatically static and can only detect dynamic and sensor objects. * A sensor object retain its full collision capability when parented: it can detect static and dynamic object. Python control ============== KX_GameObject.setParent(parent,compound,ghost): Sets this object's parent. Control the shape status with the optional compound and ghost parameters: compound=1: the object shape should be added to the parent compound shape (default) compound=0: the object should keep its individual shape. In that case you can control if it should be ghost or not: ghost=1 if the object should be made ghost while parented (default) ghost=0 if the object should be solid while parented Note: if the object type is sensor, it stays ghost regardless of ghost parameter parent: KX_GameObject reference or string (object name w/o OB prefix) --- source/blender/blenkernel/BKE_blender.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index d49a5425b61..aa2366661f8 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -41,7 +41,7 @@ struct ListBase; struct MemFile; #define BLENDER_VERSION 248 -#define BLENDER_SUBVERSION 4 +#define BLENDER_SUBVERSION 5 #define BLENDER_MINVERSION 245 #define BLENDER_MINSUBVERSION 15 -- cgit v1.2.3 From 036ebc55233241bf9bd8149f855185cfcfb1ab67 Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Thu, 21 May 2009 18:10:19 +0000 Subject: BGE: GUI control over frame rate, logic rate, physics rate and physics subrate. Four new buttons in World settings to control frame rate: fps: Nominal frame rate in frame per second. Also sets the physics timestep = 1/fps phys: Maximum number of physics timestep per game frame in case the actual fps is less than nominal. This allows the physics to keep up with real time even if the graphics slows down the game. sub: Fixed number of simulation substeps per physic timestep. Improves the precision of the physics simulation. Useful for fast moving objects for example. log: Maximum number of logic steps per game frame in case the actual fps is less than nominal. This allows the logic system to follow the physics simulation. Upper bound = phys (setting the value higher than phys has no effect). On games with heavy logic system, it is useful to set this value to 1, to keep logic time under control. All these values were already accessible from Python except phys: GameLogic.getMaxPhysicsFrame(): Gets the maximum number of physics frame per render frame. GameLogic.setMaxPhysicsFrame(phys): Sets the maximum number of physics timestep that are executed per render frame. Higher value allows physics to keep up with realtime even if graphics slows down the game. Physics timestep is fixed and equal to 1/tickrate (see setLogicTicRate) maxphysics/ticrate is the maximum delay of the renderer that physics can compensate. phys: integer --- source/blender/blenkernel/intern/world.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c index 6635ef29d51..d47f4efeb4e 100644 --- a/source/blender/blenkernel/intern/world.c +++ b/source/blender/blenkernel/intern/world.c @@ -109,6 +109,10 @@ World *add_world(char *name) wrld->mode = WO_DBVT_CULLING; // DBVT culling by default wrld->occlusionRes = 128; wrld->preview = NULL; + wrld->ticrate = 60; + wrld->maxlogicstep = 5; + wrld->physubstep = 1; + wrld->maxphystep = 5; return wrld; } -- cgit v1.2.3 From 9b1ce6e55608e868a1fa1bc62710e053919c39de Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 22 May 2009 01:16:26 +0000 Subject: NLA SoC: Part 1 of NLA-Data Management API In this commit: * Added code for freeing NLA data now stored in AnimData * Started writing some utilities for adding NLA data, especially the 'push-down' concept for Actions * Cleanups of existing code - removal of obsolete NLA code from various places Next commits/parts: * File IO code for new-style NLA data * Version patching for old data to new data --- source/blender/blenkernel/BKE_nla.h | 33 ++- source/blender/blenkernel/intern/anim_sys.c | 7 + source/blender/blenkernel/intern/nla.c | 345 +++++++++++++++++++--------- source/blender/blenkernel/intern/object.c | 8 +- 4 files changed, 265 insertions(+), 128 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_nla.h b/source/blender/blenkernel/BKE_nla.h index 230096d7ea7..0f23a5cb44d 100644 --- a/source/blender/blenkernel/BKE_nla.h +++ b/source/blender/blenkernel/BKE_nla.h @@ -17,12 +17,12 @@ * 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. + * The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung * All rights reserved. * * The Original Code is: all of this file. * - * Contributor(s): none yet. + * Contributor(s): Joshua Leung (full recode) * * ***** END GPL LICENSE BLOCK ***** */ @@ -30,15 +30,26 @@ #ifndef BKE_NLA_H #define BKE_NLA_H -struct bActionStrip; -struct ListBase; -struct Object; +struct AnimData; +struct NlaStrip; +struct NlaTrack; + +/* ----------------------------- */ +/* Data Management */ + +void free_nlastrip(ListBase *strips, struct NlaStrip *strip); +void free_nlatrack(ListBase *tracks, struct NlaTrack *nlt); +void free_nladata(ListBase *tracks); + +struct NlaTrack *add_nlatrack(struct AnimData *adt); + +/* ----------------------------- */ +/* API */ + +struct NlaTrack *BKE_nlatrack_find_active(ListBase *tracks); +void BKE_nlatrack_set_active(ListBase *tracks, struct NlaTrack *nlt_a); + +void BKE_nla_action_pushdown(struct AnimData *adt); -void free_actionstrip (struct bActionStrip* strip); -void free_nlastrips (struct ListBase *nlalist); -void copy_nlastrips (struct ListBase *dst, struct ListBase *src); -void copy_actionstrip (struct bActionStrip **dst, struct bActionStrip **src); -void find_stridechannel(struct Object *ob, struct bActionStrip *strip); -struct bActionStrip *convert_action_to_strip (struct Object *ob); #endif diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 702da23ef47..b47d734ef4f 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -17,6 +17,7 @@ #include "BKE_animsys.h" #include "BKE_action.h" #include "BKE_fcurve.h" +#include "BKE_nla.h" #include "BKE_global.h" #include "BKE_main.h" #include "BKE_utildefines.h" @@ -118,6 +119,9 @@ void BKE_free_animdata (ID *id) if (adt->action) adt->action->id.us--; + /* free nla data */ + free_nladata(&adt->nla_tracks); + /* free drivers - stored as a list of F-Curves */ free_fcurves(&adt->drivers); @@ -982,6 +986,9 @@ static void nladata_flush_channels (ListBase *channels) case PROP_ENUM: RNA_property_enum_set(ptr, prop, (int)value); break; + default: + // can't do anything with other types of property.... + break; } } } diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index dc2bf26759f..ac767fe86cc 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -17,171 +17,296 @@ * 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. + * The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung * All rights reserved. * * The Original Code is: all of this file. * - * Contributor(s): none yet. + * Contributor(s): Joshua Leung (full recode) * * ***** END GPL LICENSE BLOCK ***** */ #include +#include +#include +#include +#include #include "MEM_guardedalloc.h" #include "BLI_blenlib.h" -#include "DNA_space_types.h" -#include "DNA_nla_types.h" +#include "DNA_anim_types.h" #include "DNA_action_types.h" -#include "DNA_ID.h" -#include "DNA_ipo_types.h" -#include "DNA_object_types.h" -#include "BKE_nla.h" +#include "BKE_animsys.h" #include "BKE_action.h" +#include "BKE_fcurve.h" +#include "BKE_nla.h" #include "BKE_blender.h" #include "BKE_library.h" -#include "BKE_object.h" /* for convert_action_to_strip(ob) */ +#include "BKE_object.h" +#include "BKE_utildefines.h" #ifdef HAVE_CONFIG_H #include #endif -/* NOTE: in group.c the strips get copied for group-nla override, this assumes - that strips are one single block, without additional data to be copied */ -void copy_actionstrip (bActionStrip **dst, bActionStrip **src){ - bActionStrip *dstrip; - bActionStrip *sstrip = *src; +/* *************************************************** */ +/* Data Management */ - if (!*src){ - *dst=NULL; +/* Freeing ------------------------------------------- */ + +/* Remove the given NLA strip from the NLA track it occupies, free the strip's data, + * and the strip itself. + */ +// TODO: with things like transitions, should these get freed too? Maybe better as a UI tool +void free_nlastrip (ListBase *strips, NlaStrip *strip) +{ + FModifier *fcm, *fmn; + + /* sanity checks */ + if (strip == NULL) return; + + /* remove reference to action */ + if (strip->act) + strip->act->id.us--; + + /* free remapping info */ + //if (strip->remap) + // BKE_animremap_free(); + + /* free own F-Curves */ + free_fcurves(&strip->fcurves); + + /* free F-Modifiers */ + for (fcm= strip->modifiers.first; fcm; fcm= fmn) { + fmn= fcm->next; + + BLI_remlink(&strip->modifiers, fcm); + fcurve_remove_modifier(NULL, fcm); } + + /* free the strip itself */ + if (strips) + BLI_freelinkN(strips, strip); + else + MEM_freeN(strip); +} - *dst = MEM_dupallocN(sstrip); - - dstrip = *dst; - if (dstrip->act) - dstrip->act->id.us++; - - if (dstrip->ipo) - dstrip->ipo->id.us++; +/* Remove the given NLA track from the set of NLA tracks, free the track's data, + * and the track itself. + */ +void free_nlatrack (ListBase *tracks, NlaTrack *nlt) +{ + NlaStrip *strip, *stripn; - if (dstrip->modifiers.first) { - BLI_duplicatelist (&dstrip->modifiers, &sstrip->modifiers); + /* sanity checks */ + if (nlt == NULL) + return; + + /* free strips */ + for (strip= nlt->strips.first; strip; strip= stripn) { + stripn= strip->next; + free_nlastrip(&nlt->strips, strip); } + /* free NLA track itself now */ + if (tracks) + BLI_freelinkN(tracks, nlt); + else + MEM_freeN(nlt); } -void copy_nlastrips (ListBase *dst, ListBase *src) +/* Free the elements of type NLA Tracks provided in the given list, but do not free + * the list itself since that is not free-standing + */ +void free_nladata (ListBase *tracks) { - bActionStrip *strip; - - dst->first=dst->last=NULL; - - BLI_duplicatelist (dst, src); - - /* Update specific data */ - if (!dst->first) + NlaTrack *nlt, *nltn; + + /* sanity checks */ + if ELEM(NULL, tracks, tracks->first) return; - - for (strip = dst->first; strip; strip=strip->next){ - if (strip->act) - strip->act->id.us++; - if (strip->ipo) - strip->ipo->id.us++; - if (strip->modifiers.first) { - ListBase listb; - BLI_duplicatelist (&listb, &strip->modifiers); - strip->modifiers= listb; - } + + /* free tracks one by one */ + for (nlt= tracks->first; nlt; nlt= nltn) { + nltn= nlt->next; + free_nlatrack(tracks, nlt); } + + /* clear the list's pointers to be safe */ + tracks->first= tracks->last= NULL; } -/* from editnla, for convert_action_to_strip -- no UI code so should be ok here.. */ -void find_stridechannel(Object *ob, bActionStrip *strip) +/* Copying ------------------------------------------- */ + +// TODO... + +/* Adding ------------------------------------------- */ + +/* Add a NLA Strip referencing the given Action, to the given NLA Track */ +// TODO: any extra parameters to control how this is done? +NlaStrip *add_nlastrip (NlaTrack *nlt, bAction *act) { - if(ob && ob->pose) { - bPoseChannel *pchan; - for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) - if(pchan->flag & POSE_STRIDE) - break; - if(pchan) - BLI_strncpy(strip->stridechannel, pchan->name, 32); - else - strip->stridechannel[0]= 0; - } + NlaStrip *strip; + + /* sanity checks */ + if ELEM(NULL, nlt, act) + return NULL; + + /* allocate new strip */ + strip= MEM_callocN(sizeof(NlaStrip), "NlaStrip"); + BLI_addtail(&nlt->strips, strip); + + /* generic settings + * - selected flag to highlight this to the user + * - auto-blends to ensure that blend in/out values are automatically + * determined by overlaps of strips + * - (XXX) synchronisation of strip-length in accordance with changes to action-length + * is not done though, since this should only really happens in editmode for strips now + * though this decision is still subject to further review... + */ + strip->flag = NLASTRIP_FLAG_SELECT|NLASTRIP_FLAG_AUTO_BLENDS; + + /* assign the action reference */ + strip->act= act; + id_us_plus(&act->id); + + /* determine initial range + * - strip length cannot be 0... ever... + */ + calc_action_range(strip->act, &strip->actstart, &strip->actend, 1); + + strip->start = strip->actstart; + strip->end = (IS_EQ(strip->actstart, strip->actend)) ? (strip->actstart + 1.0f): (strip->actend); + + /* strip should be referenced as-is */ + strip->scale= 1.0f; + strip->repeat = 1.0f; + + /* return the new strip */ + return strip; } -//called by convert_nla / bpy api with an object with the action to be converted to a new strip -bActionStrip *convert_action_to_strip (Object *ob) +/* Add a NLA Track to the given AnimData */ +NlaTrack *add_nlatrack (AnimData *adt) { - bActionStrip *nstrip; - - /* Make new actionstrip */ - nstrip = MEM_callocN(sizeof(bActionStrip), "bActionStrip"); - - /* Link the action to the nstrip */ - nstrip->act = ob->action; - id_us_plus(&nstrip->act->id); - calc_action_range(nstrip->act, &nstrip->actstart, &nstrip->actend, 1); - nstrip->start = nstrip->actstart; - nstrip->end = nstrip->actend; - nstrip->flag = ACTSTRIP_SELECT|ACTSTRIP_LOCK_ACTION; - - find_stridechannel(ob, nstrip); - //set_active_strip(ob, nstrip); /* is in editnla as does UI calls */ - - nstrip->repeat = 1.0; - - if(ob->nlastrips.first == NULL) - ob->nlaflag |= OB_NLA_OVERRIDE; - - BLI_addtail(&ob->nlastrips, nstrip); - return nstrip; /* is created, malloced etc. here so is safe to just return the pointer? - this is needed for setting this active in UI, and probably useful for API too */ + NlaTrack *nlt; + + /* sanity checks */ + if (adt == NULL) + return NULL; + + /* allocate new track */ + nlt= MEM_callocN(sizeof(NlaTrack), "NlaTrack"); + + /* set settings requiring the track to not be part of the stack yet */ + nlt->flag = NLATRACK_SELECTED; + nlt->index= BLI_countlist(&adt->nla_tracks); + + /* add track to stack, and make it the active one */ + BLI_addtail(&adt->nla_tracks, nlt); + BKE_nlatrack_set_active(&adt->nla_tracks, nlt); + + /* must have unique name, but we need to seed this */ + sprintf(nlt->name, "NlaTrack"); + BLI_uniquename(&adt->nla_tracks, nlt, "NlaTrack", '.', offsetof(NlaTrack, name), 64); + /* return the new track */ + return nlt; } +/* *************************************************** */ +/* Basic Utilities */ -/* not strip itself! */ -void free_actionstrip(bActionStrip* strip) -{ - if (!strip) - return; +/* States ------------------------------------------- */ - if (strip->act){ - strip->act->id.us--; - strip->act = NULL; - } - if (strip->ipo){ - strip->ipo->id.us--; - strip->ipo = NULL; - } - if (strip->modifiers.first) { - BLI_freelistN(&strip->modifiers); +/* Find the active NLA-track for the given stack */ +NlaTrack *BKE_nlatrack_find_active (ListBase *tracks) +{ + NlaTrack *nlt; + + /* sanity check */ + if ELEM(NULL, tracks, tracks->first) + return NULL; + + /* try to find the first active track */ + for (nlt= tracks->first; nlt; nlt= nlt->next) { + if (nlt->flag & NLATRACK_ACTIVE) + return nlt; } + /* none found */ + return NULL; } -void free_nlastrips (ListBase *nlalist) +/* Make the given NLA-track the active one for the given stack. If no track is provided, + * this function can be used to simply deactivate all the NLA tracks in the given stack too. + */ +void BKE_nlatrack_set_active (ListBase *tracks, NlaTrack *nlt_a) { - bActionStrip *strip; - - if (!nlalist->first) + NlaTrack *nlt; + + /* sanity check */ + if ELEM(NULL, tracks, tracks->first) return; + + /* deactive all the rest */ + for (nlt= tracks->first; nlt; nlt= nlt->next) + nlt->flag &= ~NLATRACK_ACTIVE; + + /* set the given one as the active one */ + if (nlt_a) + nlt_a->flag |= NLATRACK_ACTIVE; +} - /* Do any specific freeing */ - for (strip=nlalist->first; strip; strip=strip->next) - { - free_actionstrip (strip); - }; +/* Tools ------------------------------------------- */ - /* Free the whole list */ - BLI_freelistN(nlalist); +/* For the given AnimData block, add the active action to the NLA + * stack (i.e. 'push-down' action). The UI should only allow this + * for normal editing only (i.e. not in editmode for some strip's action), + * so no checks for this are performed. + */ +// TODO: maybe we should have checks for this too... +void BKE_nla_action_pushdown (AnimData *adt) +{ + NlaTrack *nlt; + NlaStrip *strip; + + /* sanity checks */ + // TODO: need to report the error for this + if ELEM(NULL, adt, adt->action) + return; + + /* if the action is empty, we also shouldn't try to add to stack, + * as that will cause us grief down the track + */ + // TODO: code a method for this, and report errors after... + + /* add a new NLA track to house this action + * - we could investigate trying to fit the action into an appropriately + * sized gap in the existing tracks, however, this may result in unexpected + * changes in blending behaviour... + */ + nlt= add_nlatrack(adt); + if (nlt == NULL) + return; + + /* add a new NLA strip to the track, which references the active action */ + strip= add_nlastrip(nlt, adt->action); + + /* clear reference to action now that we've pushed it onto the stack */ + if (strip) { + adt->action->id.us--; + adt->action= NULL; + } + + // TODO: set any other flags necessary here... } + +/* *************************************************** */ diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index b913651d856..b0902784687 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -1193,18 +1193,12 @@ Object *copy_object(Object *ob) armature_rebuild_pose(obn, obn->data); } copy_defgroups(&obn->defbase, &ob->defbase); -#if 0 // XXX old animation system - copy_nlastrips(&obn->nlastrips, &ob->nlastrips); -#endif // XXX old animation system copy_constraints(&obn->constraints, &ob->constraints); /* increase user numbers */ id_us_plus((ID *)obn->data); -#if 0 // XXX old animation system - id_us_plus((ID *)obn->ipo); - id_us_plus((ID *)obn->action); -#endif // XXX old animation system id_us_plus((ID *)obn->dup_group); + // FIXME: add this for animdata too... for(a=0; atotcol; a++) id_us_plus((ID *)obn->mat[a]); -- cgit v1.2.3 From 3b7f63a0884c6ec9db5abb938708f4191ea35274 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 22 May 2009 11:19:35 +0000 Subject: NLA SoC: File IO for new NLA Datatypes --- source/blender/blenkernel/BKE_nla.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_nla.h b/source/blender/blenkernel/BKE_nla.h index 0f23a5cb44d..3864d9da5f6 100644 --- a/source/blender/blenkernel/BKE_nla.h +++ b/source/blender/blenkernel/BKE_nla.h @@ -33,6 +33,7 @@ struct AnimData; struct NlaStrip; struct NlaTrack; +struct bAction; /* ----------------------------- */ /* Data Management */ @@ -41,6 +42,7 @@ void free_nlastrip(ListBase *strips, struct NlaStrip *strip); void free_nlatrack(ListBase *tracks, struct NlaTrack *nlt); void free_nladata(ListBase *tracks); +struct NlaStrip *add_nlastrip(struct NlaTrack *nlt, struct bAction *act); struct NlaTrack *add_nlatrack(struct AnimData *adt); /* ----------------------------- */ -- cgit v1.2.3 From d141aff097d17c106071f2ad966fdd97a1fb5ba4 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sat, 23 May 2009 09:36:18 +0000 Subject: NLA SoC: Adding more backend code/utilities * Data copying * Strip sorting --- source/blender/blenkernel/BKE_action.h | 3 + source/blender/blenkernel/BKE_nla.h | 9 +- source/blender/blenkernel/intern/action.c | 17 +++- source/blender/blenkernel/intern/anim_sys.c | 2 +- source/blender/blenkernel/intern/nla.c | 148 +++++++++++++++++++++++++++- 5 files changed, 173 insertions(+), 6 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h index 67eb2ed58bf..cc10a4071a6 100644 --- a/source/blender/blenkernel/BKE_action.h +++ b/source/blender/blenkernel/BKE_action.h @@ -68,6 +68,9 @@ void make_local_action(struct bAction *act); /* Some kind of bounding box operation on the action */ void calc_action_range(const struct bAction *act, float *start, float *end, int incl_hidden); +/* Does action have any motion data at all? */ +short action_has_motion(const struct bAction *act); + /* Action Groups API ----------------- */ /* Make the given Action Group the active one */ diff --git a/source/blender/blenkernel/BKE_nla.h b/source/blender/blenkernel/BKE_nla.h index 3864d9da5f6..49796250633 100644 --- a/source/blender/blenkernel/BKE_nla.h +++ b/source/blender/blenkernel/BKE_nla.h @@ -42,6 +42,10 @@ void free_nlastrip(ListBase *strips, struct NlaStrip *strip); void free_nlatrack(ListBase *tracks, struct NlaTrack *nlt); void free_nladata(ListBase *tracks); +struct NlaStrip *copy_nlastrip(struct NlaStrip *strip); +struct NlaTrack *copy_nlatrack(struct NlaTrack *nlt); +void copy_nladata(ListBase *dst, ListBase *src); + struct NlaStrip *add_nlastrip(struct NlaTrack *nlt, struct bAction *act); struct NlaTrack *add_nlatrack(struct AnimData *adt); @@ -49,7 +53,10 @@ struct NlaTrack *add_nlatrack(struct AnimData *adt); /* API */ struct NlaTrack *BKE_nlatrack_find_active(ListBase *tracks); -void BKE_nlatrack_set_active(ListBase *tracks, struct NlaTrack *nlt_a); +void BKE_nlatrack_set_active(ListBase *tracks, struct NlaTrack *nlt); + +short BKE_nlatrack_has_space(struct NlaTrack *nlt, float start, float end); +void BKE_nlatrack_sort_strips(struct NlaTrack *nlt); void BKE_nla_action_pushdown(struct AnimData *adt); diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index f2e3583c87b..bb458cc7e25 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -740,7 +740,22 @@ float get_action_frame_inv(Object *ob, float cframe) } - +/* Check if the given action has any keyframes */ +short action_has_motion(const bAction *act) +{ + FCurve *fcu; + + /* return on the first F-Curve that has some keyframes/samples defined */ + if (act) { + for (fcu= act->curves.first; fcu; fcu= fcu->next) { + if (fcu->totvert) + return 1; + } + } + + /* nothing found */ + return 0; +} /* Calculate the extents of given action */ void calc_action_range(const bAction *act, float *start, float *end, int incl_hidden) diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index b47d734ef4f..f21fed416cc 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -153,7 +153,7 @@ AnimData *BKE_copy_animdata (AnimData *adt) dadt->action= copy_action(adt->action); /* duplicate NLA data */ - // XXX todo... + copy_nladata(&dadt->nla_tracks, &adt->nla_tracks); /* duplicate drivers (F-Curves) */ copy_fcurves(&dadt->drivers, &adt->drivers); diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index ac767fe86cc..d062a2ab14b 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -145,7 +145,73 @@ void free_nladata (ListBase *tracks) /* Copying ------------------------------------------- */ -// TODO... +/* Copy NLA strip */ +NlaStrip *copy_nlastrip (NlaStrip *strip) +{ + NlaStrip *strip_d; + + /* sanity check */ + if (strip == NULL) + return NULL; + + /* make a copy */ + strip_d= MEM_dupallocN(strip); + strip_d->next= strip_d->prev= NULL; + + /* increase user-count of action */ + if (strip_d->act) + strip_d->act->id.us++; + + /* copy F-Curves and modifiers */ + copy_fcurves(&strip_d->fcurves, &strip->fcurves); + fcurve_copy_modifiers(&strip_d->modifiers, &strip->modifiers); + + /* return the strip */ + return strip_d; +} + +/* Copy NLA Track */ +NlaTrack *copy_nlatrack (NlaTrack *nlt) +{ + NlaStrip *strip, *strip_d; + NlaTrack *nlt_d; + + /* sanity check */ + if (nlt == NULL) + return NULL; + + /* make a copy */ + nlt_d= MEM_dupallocN(nlt); + nlt_d->next= nlt_d->prev= NULL; + + /* make a copy of all the strips, one at a time */ + nlt_d->strips.first= nlt_d->strips.last= NULL; + + for (strip= nlt->strips.first; strip; strip= strip->next) { + strip_d= copy_nlastrip(strip); + BLI_addtail(&nlt_d->strips, strip_d); + } + + /* return the copy */ + return nlt_d; +} + +/* Copy all NLA data */ +void copy_nladata (ListBase *dst, ListBase *src) +{ + NlaTrack *nlt, *nlt_d; + + /* sanity checks */ + if ELEM(NULL, dst, src) + return; + + /* copy each NLA-track, one at a time */ + for (nlt= src->first; nlt; nlt= nlt->next) { + /* make a copy, and add the copy to the destination list */ + nlt_d= copy_nlatrack(nlt); + BLI_addtail(dst, nlt_d); + } +} /* Adding ------------------------------------------- */ @@ -224,7 +290,7 @@ NlaTrack *add_nlatrack (AnimData *adt) /* *************************************************** */ /* Basic Utilities */ -/* States ------------------------------------------- */ +/* NLA-Tracks ---------------------------------------- */ /* Find the active NLA-track for the given stack */ NlaTrack *BKE_nlatrack_find_active (ListBase *tracks) @@ -265,6 +331,80 @@ void BKE_nlatrack_set_active (ListBase *tracks, NlaTrack *nlt_a) nlt_a->flag |= NLATRACK_ACTIVE; } +/* Check if there is any space in the last track to add the given strip */ +short BKE_nlatrack_has_space (NlaTrack *nlt, float start, float end) +{ + NlaStrip *strip; + + /* sanity checks */ + if ((nlt == NULL) || IS_EQ(start, end)) + return 0; + if (start > end) { + puts("BKE_nlatrack_has_space error... start and end arguments swapped"); + SWAP(float, start, end); + } + + /* loop over NLA strips checking for any overlaps with this area... */ + for (strip= nlt->strips.first; strip; strip= strip->next) { + /* if start frame of strip is past the target end-frame, that means that + * we've gone past the window we need to check for, so things are fine + */ + if (strip->start > end) + return 1; + + /* if the end of the strip is greater than either of the boundaries, the range + * must fall within the extents of the strip + */ + if ((strip->end > start) || (strip->end > end)) + return 0; + } + + /* if we are still here, we haven't encountered any overlapping strips */ + return 1; +} + +/* Rearrange the strips in the track so that they are always in order + * (usually only needed after a strip has been moved) + */ +void BKE_nlatrack_sort_strips (NlaTrack *nlt) +{ + ListBase tmp = {NULL, NULL}; + NlaStrip *strip, *sstrip; + + /* sanity checks */ + if ELEM(NULL, nlt, nlt->strips.first) + return; + + /* we simply perform insertion sort on this list, since it is assumed that per track, + * there are only likely to be at most 5-10 strips + */ + for (strip= nlt->strips.first; strip; strip= strip->next) { + short not_added = 1; + + /* remove this strip from the list, and add it to the new list, searching from the end of + * the list, assuming that the lists are in order + */ + BLI_remlink(&nlt->strips, strip); + + for (sstrip= tmp.last; not_added && sstrip; sstrip= sstrip->prev) { + /* check if add after */ + if (sstrip->end < strip->start) { + BLI_insertlinkafter(&tmp, sstrip, strip); + not_added= 0; + break; + } + } + + /* add before first? */ + if (not_added) + BLI_addhead(&tmp, strip); + } + + /* reassign the start and end points of the strips */ + nlt->strips.first= tmp.first; + nlt->strips.last= tmp.last; +} + /* Tools ------------------------------------------- */ /* For the given AnimData block, add the active action to the NLA @@ -286,7 +426,9 @@ void BKE_nla_action_pushdown (AnimData *adt) /* if the action is empty, we also shouldn't try to add to stack, * as that will cause us grief down the track */ - // TODO: code a method for this, and report errors after... + // TODO: what about modifiers? + if (action_has_motion(adt->action) == 0) + return; /* add a new NLA track to house this action * - we could investigate trying to fit the action into an appropriately -- cgit v1.2.3 From eb8c5f3272b87fffaf017badf55f761de9a04fd1 Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Sat, 23 May 2009 22:35:47 +0000 Subject: Set default constraint solver mode more compatible to Blender 2.48 settings, this fixes rigid body stacking in this blend file: http://blenderartists.org/forum/showpost.php?p=1382653&postcount=102 (todo: expose this setting in World setting GUI) Expose contact processing threshold in Advanced GUI, next to rigid body margin, called CPT. Default to 1, makes rigid body stacking a bit more stable, smaller values makes sliding easier (at the cost of easier jittering). Disabled for 'dynamic' objects that don't rotate, because characters etc. always need smooth sliding. --- source/blender/blenkernel/intern/object.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index bffbcf73672..9739668c7c7 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -984,6 +984,8 @@ Object *add_only_object(int type, char *name) ob->anisotropicFriction[2] = 1.0f; ob->gameflag= OB_PROP|OB_COLLISION; ob->margin = 0.0; + /* ob->pad3 == Contact Processing Threshold */ + ob->pad3 = 1.; /* NT fluid sim defaults */ ob->fluidsimFlag = 0; -- cgit v1.2.3 From 83bb096f24cb2252f90a77923bd1818930a2fed2 Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Sun, 24 May 2009 06:31:47 +0000 Subject: + renamed pad3 to m_contactProcessingThreshold (thanks Campbell Barton/ideasman for confirming it is ok to rename it) + fixed Python method, PyArg_ParseTuple already checks for errors, no returning of NULL, thanks Campbell too) + added linear/angular spring for each of the 6DOFs of a generic 6dof constraint. This makes the generic 6dof constraint very versatile. --- source/blender/blenkernel/intern/object.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 9739668c7c7..ec068c35c11 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -985,7 +985,7 @@ Object *add_only_object(int type, char *name) ob->gameflag= OB_PROP|OB_COLLISION; ob->margin = 0.0; /* ob->pad3 == Contact Processing Threshold */ - ob->pad3 = 1.; + ob->m_contactProcessingThreshold = 1.; /* NT fluid sim defaults */ ob->fluidsimFlag = 0; -- cgit v1.2.3 From e93d1ba8e775a481e9a719355b12d4523cabcae1 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 26 May 2009 10:44:14 +0000 Subject: Misc warnings - Removed/Commented some unused vars - CValue::GetPropertyText() could return a temp reference to a variable on the stack, option wasnt used anywhere so removed. - KX_ConstraintWrapper::GetConstraintId allows args but ignored them - KX_ConstraintWrapper::PySetParam didnt return NULL on an error (messing up pythons exceptions). - BLI_natstrcmp didnt return 0 when the while loop exited --- source/blender/blenkernel/bad_level_call_stubs/stubs.c | 3 ++- source/blender/blenkernel/intern/anim.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/bad_level_call_stubs/stubs.c b/source/blender/blenkernel/bad_level_call_stubs/stubs.c index 3012c19ff02..1a33102f845 100644 --- a/source/blender/blenkernel/bad_level_call_stubs/stubs.c +++ b/source/blender/blenkernel/bad_level_call_stubs/stubs.c @@ -57,6 +57,7 @@ struct bConstraintOb; struct bConstraintTarget; struct ListBase; struct EditFace; +struct LOD_Decimation_Info; char *getIpoCurveName( struct IpoCurve * icu ); void insert_vert_icu(struct IpoCurve *icu, float x, float y, short fast); @@ -160,7 +161,7 @@ void BPY_pyconstraint_target(struct bPythonConstraint *con, struct bConstraintTa void free_oops(struct Oops *oops){} void exit_posemode(int freedata){} void error(char *str, ...){} -int okee(char *str, ...){} +int okee(char *str, ...){return 1;} /* anim.c */ ListBase editNurb; diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index 50be417c8ef..ffb7ff51b87 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -747,7 +747,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Object *par, float par_ float ctime, pa_time, scale = 1.0f; float tmat[4][4], mat[4][4], pamat[4][4], size=0.0; float (*obmat)[4], (*oldobmat)[4]; - int lay, a, b, k, counter, hair = 0; + int lay, a, b, counter, hair = 0; int totpart, totchild, totgroup=0, pa_num; if(psys==0) return; -- cgit v1.2.3 From 01f8956a6d6848e738dbd665b1c1b4dee6dbb445 Mon Sep 17 00:00:00 2001 From: Peter Schlaile Date: Wed, 27 May 2009 22:37:45 +0000 Subject: == FFMPEG == This fixes: [#17505] Bad Interlacing for NTSC in mpeg-2 files --- source/blender/blenkernel/intern/writeffmpeg.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c index c3d8ed855a2..6576d25dd76 100644 --- a/source/blender/blenkernel/intern/writeffmpeg.c +++ b/source/blender/blenkernel/intern/writeffmpeg.c @@ -248,6 +248,9 @@ static void write_video_frame(AVFrame* frame) #ifdef FFMPEG_CODEC_TIME_BASE frame->pts = G.scene->r.cfra - G.scene->r.sfra; #endif + if (G.scene->r.mode & R_FIELDS) { + frame->top_field_first = ((G.scene->r.mode & R_ODDFIELD) != 0); + } outsize = avcodec_encode_video(c, video_buffer, video_buffersize, frame); -- cgit v1.2.3 From 17c51c6cb778aa584dee93c9bd70d1a0844d53ac Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Thu, 28 May 2009 22:26:28 +0000 Subject: Bullet Physics maxphystep = 1 is better general default to avoid vicious circle (graphics slower -> physics slower -> overall frametime slower -> graphics slower etc.) See difference in vault.blend --- source/blender/blenkernel/intern/world.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c index d47f4efeb4e..41017cb0116 100644 --- a/source/blender/blenkernel/intern/world.c +++ b/source/blender/blenkernel/intern/world.c @@ -112,7 +112,7 @@ World *add_world(char *name) wrld->ticrate = 60; wrld->maxlogicstep = 5; wrld->physubstep = 1; - wrld->maxphystep = 5; + wrld->maxphystep = 1; return wrld; } -- cgit v1.2.3 From 39177018af16b208e41714d454a44c58a2eea0b7 Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Fri, 29 May 2009 08:55:14 +0000 Subject: Revert commit 20478: instead of changing the default in blender, it's better to change the values for the demos that need it. --- source/blender/blenkernel/intern/world.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c index 41017cb0116..d47f4efeb4e 100644 --- a/source/blender/blenkernel/intern/world.c +++ b/source/blender/blenkernel/intern/world.c @@ -112,7 +112,7 @@ World *add_world(char *name) wrld->ticrate = 60; wrld->maxlogicstep = 5; wrld->physubstep = 1; - wrld->maxphystep = 1; + wrld->maxphystep = 5; return wrld; } -- cgit v1.2.3 From b3ce0c6a49d2d9e90bbee2c5de2130b7c40c3186 Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Fri, 29 May 2009 17:51:16 +0000 Subject: Last pre-2.49 commit part 1: splash c file and release number --- source/blender/blenkernel/BKE_blender.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index aa2366661f8..cc2f9bd8334 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -40,8 +40,8 @@ extern "C" { struct ListBase; struct MemFile; -#define BLENDER_VERSION 248 -#define BLENDER_SUBVERSION 5 +#define BLENDER_VERSION 249 +#define BLENDER_SUBVERSION 0 #define BLENDER_MINVERSION 245 #define BLENDER_MINSUBVERSION 15 -- cgit v1.2.3 From aa4d64d7ff17d4557acd74540914de872a32ba81 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sat, 30 May 2009 11:05:29 +0000 Subject: NLA SoC: Bugfixes for previous commit * Compile fix in nla_draw.c * Not totally correct yet, but now NLA-tracks get drawn too after action 'push-down' --- source/blender/blenkernel/intern/nla.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index d062a2ab14b..3356f599c59 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -427,8 +427,10 @@ void BKE_nla_action_pushdown (AnimData *adt) * as that will cause us grief down the track */ // TODO: what about modifiers? - if (action_has_motion(adt->action) == 0) + if (action_has_motion(adt->action) == 0) { + printf("BKE_nla_action_pushdown(): action has no data \n"); return; + } /* add a new NLA track to house this action * - we could investigate trying to fit the action into an appropriately @@ -436,8 +438,10 @@ void BKE_nla_action_pushdown (AnimData *adt) * changes in blending behaviour... */ nlt= add_nlatrack(adt); - if (nlt == NULL) + if (nlt == NULL) { + printf("BKE_nla_action_pushdown(): no NLA-track added \n"); return; + } /* add a new NLA strip to the track, which references the active action */ strip= add_nlastrip(nlt, adt->action); @@ -448,6 +452,9 @@ void BKE_nla_action_pushdown (AnimData *adt) adt->action= NULL; } + // TEMP DEBUG... + printf("BKE_nla_action_pushdown(): NLA strip added.. done \n"); + // TODO: set any other flags necessary here... } -- cgit v1.2.3 From 2e85686fe379f99c27944e3e4b5842d89e620f3b Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sat, 30 May 2009 12:40:07 +0000 Subject: NLA SoC: Fixes (UI, evaluation?) * Fixed some bugs which meant that NLA-strips weren't getting drawn * Removed some debugging code * Fixed bug with Action-line disappearing after 'pushing down' actions * Fixed bug where Objects with no animation data showed up in NLA * Tried fixing a bug where NLA-strips were evaluated erratically. I have a feeling that there are some rounding errors I'll need to pay more attention to somewhere :/ --- source/blender/blenkernel/intern/anim_sys.c | 6 +++--- source/blender/blenkernel/intern/nla.c | 3 --- 2 files changed, 3 insertions(+), 6 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index f21fed416cc..652f733d553 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -627,14 +627,14 @@ static float nlastrip_get_influence (NlaStrip *strip, float cframe) strip->blendout= (float)fabs(strip->blendout); /* result depends on where frame is in respect to blendin/out values */ - // TODO: are the fabs() tests needed here? + // the +0.0001 factors are to combat rounding errors if (IS_EQ(strip->blendin, 0)==0 && (cframe <= (strip->start + strip->blendin))) { /* there is some blend-in */ - return (float)fabs(cframe - strip->start) / (strip->blendin); + return (float)(fabs(cframe - strip->start) + 0.0001) / (strip->blendin); } else if (IS_EQ(strip->blendout, 0)==0 && (cframe >= (strip->end - strip->blendout))) { /* there is some blend-out */ - return (float)fabs(strip->end - cframe) / (strip->blendout); + return (float)(fabs(strip->end - cframe) + 0.0001) / (strip->blendout); } else { /* in the middle of the strip, we should be full strength */ diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index 3356f599c59..62500af85ff 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -452,9 +452,6 @@ void BKE_nla_action_pushdown (AnimData *adt) adt->action= NULL; } - // TEMP DEBUG... - printf("BKE_nla_action_pushdown(): NLA strip added.. done \n"); - // TODO: set any other flags necessary here... } -- cgit v1.2.3 From c42eeddea491d6a79dbcc0b8b28386237085643d Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sun, 31 May 2009 04:52:20 +0000 Subject: NLA SoC: Bugfixes + Improvements to 'Push Down' track-selection * Trying to save no longer crashes in some cases when the NLA Editor was open with some data. The sanity check added in filesel.c might be able to be backported to 2.5? (Elubie, please check) * NLA-track names now get drawn with the correct colours for identifying themselves as being selected or not selected. * Now the 'push down' functionality for actions will try to add the new strip to the last NLA track, provided it has space in the range required. * When new strips are added, they will only be allowed to extrapolate before/after if they are the first (time-wise) strip for the set of NLA data per AnimData block. This stops layered strips overriding strips that occurred in earlier tracks at earlier times. --- source/blender/blenkernel/BKE_nla.h | 3 +- source/blender/blenkernel/intern/nla.c | 156 ++++++++++++++++++++++++--------- 2 files changed, 119 insertions(+), 40 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_nla.h b/source/blender/blenkernel/BKE_nla.h index 49796250633..ededd77a92f 100644 --- a/source/blender/blenkernel/BKE_nla.h +++ b/source/blender/blenkernel/BKE_nla.h @@ -46,8 +46,9 @@ struct NlaStrip *copy_nlastrip(struct NlaStrip *strip); struct NlaTrack *copy_nlatrack(struct NlaTrack *nlt); void copy_nladata(ListBase *dst, ListBase *src); -struct NlaStrip *add_nlastrip(struct NlaTrack *nlt, struct bAction *act); struct NlaTrack *add_nlatrack(struct AnimData *adt); +struct NlaStrip *add_nlastrip(struct bAction *act); +struct NlaStrip *add_nlastrip_to_stack(struct AnimData *adt, struct bAction *act); /* ----------------------------- */ /* API */ diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index 62500af85ff..3efa823f9fe 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -215,19 +215,45 @@ void copy_nladata (ListBase *dst, ListBase *src) /* Adding ------------------------------------------- */ -/* Add a NLA Strip referencing the given Action, to the given NLA Track */ -// TODO: any extra parameters to control how this is done? -NlaStrip *add_nlastrip (NlaTrack *nlt, bAction *act) +/* Add a NLA Track to the given AnimData */ +NlaTrack *add_nlatrack (AnimData *adt) +{ + NlaTrack *nlt; + + /* sanity checks */ + if (adt == NULL) + return NULL; + + /* allocate new track */ + nlt= MEM_callocN(sizeof(NlaTrack), "NlaTrack"); + + /* set settings requiring the track to not be part of the stack yet */ + nlt->flag = NLATRACK_SELECTED; + nlt->index= BLI_countlist(&adt->nla_tracks); + + /* add track to stack, and make it the active one */ + BLI_addtail(&adt->nla_tracks, nlt); + BKE_nlatrack_set_active(&adt->nla_tracks, nlt); + + /* must have unique name, but we need to seed this */ + sprintf(nlt->name, "NlaTrack"); + BLI_uniquename(&adt->nla_tracks, nlt, "NlaTrack", '.', offsetof(NlaTrack, name), 64); + + /* return the new track */ + return nlt; +} + +/* Add a NLA Strip referencing the given Action */ +NlaStrip *add_nlastrip (bAction *act) { NlaStrip *strip; /* sanity checks */ - if ELEM(NULL, nlt, act) + if (act == NULL) return NULL; /* allocate new strip */ strip= MEM_callocN(sizeof(NlaStrip), "NlaStrip"); - BLI_addtail(&nlt->strips, strip); /* generic settings * - selected flag to highlight this to the user @@ -259,32 +285,54 @@ NlaStrip *add_nlastrip (NlaTrack *nlt, bAction *act) return strip; } -/* Add a NLA Track to the given AnimData */ -NlaTrack *add_nlatrack (AnimData *adt) +/* Add new NLA-strip to the top of the NLA stack - i.e. into the last track if space, or a new one otherwise */ +NlaStrip *add_nlastrip_to_stack (AnimData *adt, bAction *act) { + NlaStrip *strip, *ns; NlaTrack *nlt; + short not_added = 1; /* sanity checks */ - if (adt == NULL) + if ELEM(NULL, adt, act) return NULL; - - /* allocate new track */ - nlt= MEM_callocN(sizeof(NlaTrack), "NlaTrack"); - /* set settings requiring the track to not be part of the stack yet */ - nlt->flag = NLATRACK_SELECTED; - nlt->index= BLI_countlist(&adt->nla_tracks); + /* create a new NLA strip */ + strip= add_nlastrip(act); + if (strip == NULL) + return NULL; - /* add track to stack, and make it the active one */ - BLI_addtail(&adt->nla_tracks, nlt); - BKE_nlatrack_set_active(&adt->nla_tracks, nlt); + /* check if the last NLA-track (if it exists) has any space for this strip: + * - if so, add this strip to that track + */ + if ( (adt->nla_tracks.last == NULL) || + (BKE_nlatrack_has_space(adt->nla_tracks.last, strip->start, strip->end)==0) ) + { + /* no space, so add to a new track... */ + nlt= add_nlatrack(adt); + } + else + { + /* there's some space, so add to this track... */ + nlt= adt->nla_tracks.last; + } - /* must have unique name, but we need to seed this */ - sprintf(nlt->name, "NlaTrack"); - BLI_uniquename(&adt->nla_tracks, nlt, "NlaTrack", '.', offsetof(NlaTrack, name), 64); + /* find the right place to add the strip to the nominated track */ + for (ns= nlt->strips.first; ns; ns= ns->next) { + /* if current strip occurs after the new strip, add it before */ + if (ns->start > strip->end) { + BLI_insertlinkbefore(&nlt->strips, ns, strip); + not_added= 0; + break; + } + } + if (not_added) { + /* just add to the end of the list of the strips then... */ + BLI_addtail(&nlt->strips, strip); + } - /* return the new track */ - return nlt; + + /* returns the strip added */ + return strip; } /* *************************************************** */ @@ -404,7 +452,39 @@ void BKE_nlatrack_sort_strips (NlaTrack *nlt) nlt->strips.first= tmp.first; nlt->strips.last= tmp.last; } - + +/* NLA Strips -------------------------------------- */ + +/* Is the given NLA-strip the first one to occur for the given AnimData block */ +// TODO: make this an api method if necesary, but need to add prefix first +short nlastrip_is_first (AnimData *adt, NlaStrip *strip) +{ + NlaTrack *nlt; + NlaStrip *ns; + + /* sanity checks */ + if ELEM(NULL, adt, strip) + return 0; + + /* check if strip has any strips before it */ + if (strip->prev) + return 0; + + /* check other tracks to see if they have a strip that's earlier */ + // TODO: or should we check that the strip's track is also the first? + for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) { + /* only check the first strip, assuming that they're all in order */ + ns= nlt->strips.first; + if (ns) { + if (ns->start < strip->start) + return 0; + } + } + + /* should be first now */ + return 1; +} + /* Tools ------------------------------------------- */ /* For the given AnimData block, add the active action to the NLA @@ -415,7 +495,6 @@ void BKE_nlatrack_sort_strips (NlaTrack *nlt) // TODO: maybe we should have checks for this too... void BKE_nla_action_pushdown (AnimData *adt) { - NlaTrack *nlt; NlaStrip *strip; /* sanity checks */ @@ -431,28 +510,27 @@ void BKE_nla_action_pushdown (AnimData *adt) printf("BKE_nla_action_pushdown(): action has no data \n"); return; } - - /* add a new NLA track to house this action - * - we could investigate trying to fit the action into an appropriately - * sized gap in the existing tracks, however, this may result in unexpected - * changes in blending behaviour... - */ - nlt= add_nlatrack(adt); - if (nlt == NULL) { - printf("BKE_nla_action_pushdown(): no NLA-track added \n"); - return; - } /* add a new NLA strip to the track, which references the active action */ - strip= add_nlastrip(nlt, adt->action); + strip= add_nlastrip_to_stack(adt, adt->action); - /* clear reference to action now that we've pushed it onto the stack */ + /* do other necessary work on strip */ if (strip) { + /* clear reference to action now that we've pushed it onto the stack */ adt->action->id.us--; adt->action= NULL; + + /* if the strip is the first one in the track it lives in, check if there + * are strips in any other tracks that may be before this, and set the extend + * mode accordingly + */ + if (nlastrip_is_first(adt, strip) == 0) { + /* not first, so extend mode can only be NLASTRIP_EXTEND_HOLD_FORWARD not NLASTRIP_EXTEND_HOLD, + * so that it doesn't override strips in previous tracks + */ + strip->extendmode= NLASTRIP_EXTEND_HOLD_FORWARD; + } } - - // TODO: set any other flags necessary here... } /* *************************************************** */ -- cgit v1.2.3 From 33267f58581ea8f9d89028958c6e64a8d048d4db Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sun, 31 May 2009 11:14:50 +0000 Subject: NLA SoC: Basic selection operators * Added click-select/left-right select and deselect all/invert all selection operators. For now, these basic operators will suffice (more advanced selection operators will be coded at a later stage). * Fixed a few bugs in DopeSheet found while coding the relevant tools for NLA. * Added custom border-select operator for NLA channels (since the standard one assumes negative direction channel order) * Added new API-method for NLA strips to check if the strip occurs within a given range, since this test needed to be performed in a few places... * Tweaked the NLA Editor View2D ranges a bit to give saner default sizing. This still isn't right yet though. --- source/blender/blenkernel/BKE_nla.h | 2 ++ source/blender/blenkernel/intern/nla.c | 31 +++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_nla.h b/source/blender/blenkernel/BKE_nla.h index ededd77a92f..3c3abe11da3 100644 --- a/source/blender/blenkernel/BKE_nla.h +++ b/source/blender/blenkernel/BKE_nla.h @@ -59,6 +59,8 @@ void BKE_nlatrack_set_active(ListBase *tracks, struct NlaTrack *nlt); short BKE_nlatrack_has_space(struct NlaTrack *nlt, float start, float end); void BKE_nlatrack_sort_strips(struct NlaTrack *nlt); +short BKE_nlastrip_within_bounds(struct NlaStrip *strip, float min, float max); + void BKE_nla_action_pushdown(struct AnimData *adt); #endif diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index 3efa823f9fe..cf115cb6faf 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -455,6 +455,37 @@ void BKE_nlatrack_sort_strips (NlaTrack *nlt) /* NLA Strips -------------------------------------- */ +/* Does the given NLA-strip fall within the given bounds (times)? */ +short BKE_nlastrip_within_bounds (NlaStrip *strip, float min, float max) +{ + const float stripLen= (strip) ? strip->end - strip->start : 0.0f; + const float boundsLen= (float)fabs(max - min); + + /* sanity checks */ + if ((strip == NULL) || IS_EQ(stripLen, 0.0f) || IS_EQ(boundsLen, 0.0f)) + return 0; + + /* only ok if at least part of the strip is within the bounding window + * - first 2 cases cover when the strip length is less than the bounding area + * - second 2 cases cover when the strip length is greater than the bounding area + */ + if ( (stripLen < boundsLen) && + !(IN_RANGE(strip->start, min, max) || + IN_RANGE(strip->end, min, max)) ) + { + return 0; + } + if ( (stripLen > boundsLen) && + !(IN_RANGE(min, strip->start, strip->end) || + IN_RANGE(max, strip->start, strip->end)) ) + { + return 0; + } + + /* should be ok! */ + return 1; +} + /* Is the given NLA-strip the first one to occur for the given AnimData block */ // TODO: make this an api method if necesary, but need to add prefix first short nlastrip_is_first (AnimData *adt, NlaStrip *strip) -- cgit v1.2.3 From 6a35302a54071bfd12df7d4a71e710d1e250b34d Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Tue, 2 Jun 2009 09:58:06 +0000 Subject: NLA SoC: Fixed merge errors. Manually copied over any files from 2.5 that were modified in a commit by Brecht between the time when I had done the previous merge and the time when the commit for that finally got through. --- source/blender/blenkernel/BKE_library.h | 1 + source/blender/blenkernel/intern/library.c | 6 ++++++ 2 files changed, 7 insertions(+) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h index e598394cc60..ce182267b93 100644 --- a/source/blender/blenkernel/BKE_library.h +++ b/source/blender/blenkernel/BKE_library.h @@ -45,6 +45,7 @@ void *copy_libblock(void *rt); void id_lib_extern(struct ID *id); void id_us_plus(struct ID *id); +void id_us_min(struct ID *id); int check_for_dupid(struct ListBase *lb, struct ID *id, char *name); int new_id(struct ListBase *lb, struct ID *id, const char *name); diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index d0e4c1a15bc..90ab4e05d44 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -142,6 +142,12 @@ void id_us_plus(ID *id) } } +void id_us_min(ID *id) +{ + if(id) + id->us--; +} + ListBase *wich_libbase(Main *mainlib, short type) { switch( type ) { -- cgit v1.2.3 From a9c29cd4154fcc3933d59eb06d4fe20790298e88 Mon Sep 17 00:00:00 2001 From: Kent Mein Date: Tue, 2 Jun 2009 19:29:20 +0000 Subject: This commit fixes the following two coverity issues: CID: 475 Checker: REVERSE_INULL (help) File: base/src/source/blender/blenkernel/intern/cloth.c Function: bvhselftree_build_from_cloth Description: Pointer "clmd" dereferenced before NULL check CID: 476 Checker: REVERSE_INULL (help) File: base/src/source/blender/blenkernel/intern/cloth.c Function: bvhtree_build_from_cloth Description: Pointer "clmd" dereferenced before NULL check You'll notice in the code the var is actually set again a few lines down before being used so better to set it after you've made sure the pointer is valid. Kent --- source/blender/blenkernel/intern/cloth.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index dbc94571cad..f74c96482e0 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -157,7 +157,7 @@ BVHTree *bvhselftree_build_from_cloth (ClothModifierData *clmd, float epsilon) { unsigned int i; BVHTree *bvhtree; - Cloth *cloth = clmd->clothObject; + Cloth *cloth; ClothVertex *verts; MFace *mfaces; float co[12]; @@ -198,7 +198,7 @@ BVHTree *bvhtree_build_from_cloth (ClothModifierData *clmd, float epsilon) { unsigned int i; BVHTree *bvhtree; - Cloth *cloth = clmd->clothObject; + Cloth *cloth; ClothVertex *verts; MFace *mfaces; float co[12]; -- cgit v1.2.3 From f6cac5bec7418b58fe250c65293e85a8f0095cb2 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Wed, 3 Jun 2009 11:22:49 +0000 Subject: NLA SoC: More Drawing Tweaks * Following user feedback, I've increased the separation between normal NLA-tracks and the 'action lines' to try and differentiate them more. This hopefully this will be sufficient, otherwise, I'm going to have to abandon the use of nice, generic channel-identification code for lists of channels... * Improved drawing of 'active' strips. - Now, the active strip (when NOT being 'tweaked') will be simply drawn as a yellow strip + a white border. - The active strip (when BEING 'tweaked') will now be greenish + a white border. The colour here may be tweakable, but we'll see... * Strip extrapolation modes (hold, etc.) are now visualised as rects with alpha and the same colour as the strip they belong to. * Selecting strips now makes them 'active' (and deactivates the others). Only one strip can be active at a time. Still need to figure out precisely how this will work with multiple AnimData blocks + NLA-'tweaking'. * Fixed view-matrix bug introduced in last commit for text drawing. For now, we'll just reset the view matrix after doing that, since it's not too acceptable to move these calls to the end yet, as they should get overlapped by some other editor features (such as the Current Frame indicator) --- source/blender/blenkernel/intern/nla.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index cf115cb6faf..6235ec58d40 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -455,6 +455,25 @@ void BKE_nlatrack_sort_strips (NlaTrack *nlt) /* NLA Strips -------------------------------------- */ +/* Find the active NLA-strip within the given track */ +NlaStrip *BKE_nlastrip_find_active (NlaTrack *nlt) +{ + NlaStrip *strip; + + /* sanity check */ + if ELEM(NULL, nlt, nlt->strips.first) + return NULL; + + /* try to find the first active strip */ + for (strip= nlt->strips.first; strip; strip= strip->next) { + if (strip->flag & NLASTRIP_FLAG_ACTIVE) + return strip; + } + + /* none found */ + return NULL; +} + /* Does the given NLA-strip fall within the given bounds (times)? */ short BKE_nlastrip_within_bounds (NlaStrip *strip, float min, float max) { -- cgit v1.2.3 From eafd2720f65224791a59e763c1a9de529dfe70d5 Mon Sep 17 00:00:00 2001 From: Kent Mein Date: Wed, 3 Jun 2009 15:14:09 +0000 Subject: Missed this one before. It's another coverity issue: CID: 477 Checker: REVERSE_INULL (help) File: base/src/source/blender/blenkernel/intern/cloth.c Function: cloth_apply_vgroup Description: Pointer "dm" dereferenced before NULL check Just like the others it assigned the value twice, removed the one that was before checking for NULL. Kent --- source/blender/blenkernel/intern/cloth.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index f74c96482e0..af42d612870 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -786,15 +786,14 @@ static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm ) int j = 0; MDeformVert *dvert = NULL; Cloth *clothObj = NULL; - int numverts = dm->getNumVerts ( dm ); + int numverts; float goalfac = 0; ClothVertex *verts = NULL; + if (!clmd || !dm) return; + clothObj = clmd->clothObject; - if ( !dm ) - return; - numverts = dm->getNumVerts ( dm ); verts = clothObj->verts; -- cgit v1.2.3 From 9b088acc676bed7f30851720358b00327905e85d Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 3 Jun 2009 20:06:40 +0000 Subject: KX_MouseFocusSensor - bug reported by Micro27 on blenderartist vertical bounds checking for multiple viewports was inverted. quiet some compiler warnings and minor corrections --- source/blender/blenkernel/intern/fluidsim.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/fluidsim.c b/source/blender/blenkernel/intern/fluidsim.c index b650f3a3e98..29c4e0f2fb5 100644 --- a/source/blender/blenkernel/intern/fluidsim.c +++ b/source/blender/blenkernel/intern/fluidsim.c @@ -36,8 +36,6 @@ #include "DNA_particle_types.h" #include "DNA_scene_types.h" // N_T -#include "PIL_time.h" // for PIL_sleep_ms - #include "BLI_arithb.h" #include "BLI_blenlib.h" -- cgit v1.2.3 From c5b05fd4503359e929c501e3de61144d98f87e7b Mon Sep 17 00:00:00 2001 From: Kent Mein Date: Fri, 5 Jun 2009 04:15:19 +0000 Subject: coverity issues: CID: 478 Checker: REVERSE_INULL (help) File: base/src/source/blender/blenkernel/intern/softbody.c Function: apply_spring_memory Description: Pointer "sb" dereferenced before NULL check and CID: 480 Checker: REVERSE_INULL (help) File: base/src/source/blender/blenkernel/intern/softbody.c Function: springs_from_particles Description: Pointer "ob" dereferenced before NULL check again moved assignment after check to make sure pointer is valid. Kent --- source/blender/blenkernel/intern/softbody.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c index f63f6edf4b3..011660a7f8b 100644 --- a/source/blender/blenkernel/intern/softbody.c +++ b/source/blender/blenkernel/intern/softbody.c @@ -3075,8 +3075,8 @@ static void apply_spring_memory(Object *ob) int a; float b,l,r; - b = sb->plastic; if (sb && sb->totspring){ + b = sb->plastic; for(a=0; atotspring; a++) { bs = &sb->bspring[a]; bp1 =&sb->bpoint[bs->v1]; @@ -3546,9 +3546,9 @@ static void springs_from_particles(Object *ob) int a,k; float hairmat[4][4]; - psys= ob->soft->particles; - sb= ob->soft; - if(ob && sb && psys) { + if(ob && ob->soft && ob->soft->particles) { + psys= ob->soft->particles; + sb= ob->soft; psmd = psys_get_modifier(ob, psys); bp= sb->bpoint; -- cgit v1.2.3 From 5c21c176fa0a571f3ba47af8ad2c7906a5dc375f Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 5 Jun 2009 05:18:07 +0000 Subject: NLA SoC: Operators for 'tweaking' strip actions (TAB-Key for both) In this commit, I've introduced the mechanism by which actions already referenced by strips used in the NLA can be edited (or 'tweaked'). To use, simply select a strip you wish to edit, and hit that TAB key to start tweaking that strip's action, and hit TAB again once you're done. What happens when you enter 'tweak mode': 1) The action of the active strip temporarily becomes the 'active action' of the AnimData block. You are now able to edit this in one of the Animation Editors (DopeSheet/Action, Graph Editors) as per normal (i.e. sliding keyframes around, inserting keyframes, etc.). The 'action-line' will therefore get drawn immediately above the active track containing the active strip, so that it's clear that that's what we're editing. 2) All the NLA-tracks (and all the strips within them) that occur after the track that the active strip lived in get disabled while you're in tweakmode. This is equivalent to travelling back to an earlier state in a construction history stack. 3) The active NLA track also gets disabled while in tweakmode, since it would otherwise interfere with the correct functioning of the tweaking for the action of interest. 4) The 'real' active action (i.e. the one displaced by the active strip's action) gets put into temp storage, and will be restored after you exit tweakmode. 5) Any strips which also reference the action being tweaked will get highlighted in red shading to indicate that you may be making some changes to the action which you don't really want to make for the other users too. Please note though, that this is only a rough prototype of this functionality, with some niceties still to come. i.e.: * NLA-tracks after the active track should still get drawn above the 'tweaking action line', but perhaps with different appearance? * Various tools will still need awareness of this to prevent corrupting operations from taking place. How to proceed is still undecided... * When exiting tweak-mode, the strip the action came from still needs some form of syncing with the modified action... there are a few tricky issues here that will need to be solved * Evaluation code doesn't totally take this into account yet... --- Also, fixed a number of bugs with various code (notably selection, and also a few drawing bugs) --- source/blender/blenkernel/BKE_nla.h | 4 ++ source/blender/blenkernel/intern/anim_sys.c | 15 +++-- source/blender/blenkernel/intern/nla.c | 100 ++++++++++++++++++++++++++++ 3 files changed, 114 insertions(+), 5 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_nla.h b/source/blender/blenkernel/BKE_nla.h index 3c3abe11da3..89e5f1af7e1 100644 --- a/source/blender/blenkernel/BKE_nla.h +++ b/source/blender/blenkernel/BKE_nla.h @@ -59,9 +59,13 @@ void BKE_nlatrack_set_active(ListBase *tracks, struct NlaTrack *nlt); short BKE_nlatrack_has_space(struct NlaTrack *nlt, float start, float end); void BKE_nlatrack_sort_strips(struct NlaTrack *nlt); +struct NlaStrip *BKE_nlastrip_find_active(struct NlaTrack *nlt); short BKE_nlastrip_within_bounds(struct NlaStrip *strip, float min, float max); void BKE_nla_action_pushdown(struct AnimData *adt); +short BKE_nla_tweakmode_enter(struct AnimData *adt); +void BKE_nla_tweakmode_exit(struct AnimData *adt); + #endif diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 652f733d553..dbc38d2fc7e 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -118,6 +118,9 @@ void BKE_free_animdata (ID *id) /* unlink action (don't free, as it's in its own list) */ if (adt->action) adt->action->id.us--; + /* same goes for the temporarily displaced action */ + if (adt->tmpact) + adt->tmpact->id.us--; /* free nla data */ free_nladata(&adt->nla_tracks); @@ -151,6 +154,7 @@ AnimData *BKE_copy_animdata (AnimData *adt) // XXX review this... it might not be optimal behaviour yet... //id_us_plus((ID *)dadt->action); dadt->action= copy_action(adt->action); + dadt->tmpact= copy_action(adt->action); /* duplicate NLA data */ copy_nladata(&dadt->nla_tracks, &adt->nla_tracks); @@ -595,7 +599,7 @@ static float nlastrip_get_frame (NlaStrip *strip, float cframe, short invert) scale = (float)fabs(strip->scale); /* scale must be positive - we've got a special flag for reversing */ /* length of referenced action */ - actlength = strip->actend-strip->actstart; + actlength = strip->actend - strip->actstart; if (actlength == 0.0f) actlength = 1.0f; /* length of strip */ @@ -630,11 +634,11 @@ static float nlastrip_get_influence (NlaStrip *strip, float cframe) // the +0.0001 factors are to combat rounding errors if (IS_EQ(strip->blendin, 0)==0 && (cframe <= (strip->start + strip->blendin))) { /* there is some blend-in */ - return (float)(fabs(cframe - strip->start) + 0.0001) / (strip->blendin); + return (float)fabs(cframe - strip->start) / (strip->blendin); } else if (IS_EQ(strip->blendout, 0)==0 && (cframe >= (strip->end - strip->blendout))) { /* there is some blend-out */ - return (float)(fabs(strip->end - cframe) + 0.0001) / (strip->blendout); + return (float)fabs(strip->end - cframe) / (strip->blendout); } else { /* in the middle of the strip, we should be full strength */ @@ -674,8 +678,8 @@ static void nlatrack_ctime_get_strip (ListBase *list, NlaTrack *nlt, short index NlaEvalStrip *nes; short side= 0; - /* skip if track is muted */ - if (nlt->flag & NLATRACK_MUTED) + /* skip if track is muted or disabled */ + if (nlt->flag & (NLATRACK_MUTED|NLATRACK_DISABLED)) return; /* loop over strips, checking if they fall within the range */ @@ -1104,6 +1108,7 @@ void BKE_animsys_evaluate_animdata (ID *id, AnimData *adt, float ctime, short re * - NLA before Active Action, as Active Action behaves as 'tweaking track' * that overrides 'rough' work in NLA */ + // TODO: need to double check that this all works correctly if ((recalc & ADT_RECALC_ANIM) || (adt->recalc & ADT_RECALC_ANIM)) { /* evaluate NLA data */ diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index 6235ec58d40..84f98096364 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -583,4 +583,104 @@ void BKE_nla_action_pushdown (AnimData *adt) } } + +/* Find the active strip + track combo, and set them up as the tweaking track, + * and return if successful or not. + */ +short BKE_nla_tweakmode_enter (AnimData *adt) +{ + NlaTrack *nlt, *activeTrack=NULL; + NlaStrip *strip, *activeStrip=NULL; + + /* verify that data is valid */ + if ELEM(NULL, adt, adt->nla_tracks.first) + return 0; + + /* if block is already in tweakmode, just leave, but we should report + * that this block is in tweakmode (as our returncode) + */ + // FIXME: hopefully the flag is correct! + if (adt->flag & ADT_NLA_EDIT_ON) + return 1; + + /* go over the tracks, finding the active one, and its active strip + * - if we cannot find both, then there's nothing to do + */ + for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) { + /* check if active */ + if (nlt->flag & NLATRACK_ACTIVE) { + /* store reference to this active track */ + activeTrack= nlt; + + /* now try to find active strip */ + activeStrip= BKE_nlastrip_find_active(nlt); + break; + } + } + if ELEM3(NULL, activeTrack, activeStrip, activeStrip->act) { + printf("NLA tweakmode enter - neither active requirement found \n"); + return 0; + } + + /* go over all the tracks up to the active one, tagging each strip that uses the same + * action as the active strip, but leaving everything else alone + */ + for (nlt= activeTrack->prev; nlt; nlt= nlt->prev) { + for (strip= nlt->strips.first; strip; strip= strip->next) { + if (strip->act == activeStrip->act) + strip->flag |= NLASTRIP_FLAG_TWEAKUSER; + else + strip->flag &= ~NLASTRIP_FLAG_TWEAKUSER; // XXX probably don't need to clear this... + } + } + + + /* go over all the tracks after AND INCLUDING the active one, tagging them as being disabled + * - the active track needs to also be tagged, otherwise, it'll overlap with the tweaks going on + */ + for (nlt= activeTrack; nlt; nlt= nlt->next) + nlt->flag |= NLATRACK_DISABLED; + + /* handle AnimData level changes: + * - 'real' active action to temp storage (no need to change user-counts) + * - action of active strip set to be the 'active action' + * - editing-flag for this AnimData block should also get turned on (for more efficient restoring) + */ + adt->tmpact= adt->action; + adt->action= activeStrip->act; + adt->flag |= ADT_NLA_EDIT_ON; + + /* done! */ + return 1; +} + +/* Exit tweakmode for this AnimData block */ +void BKE_nla_tweakmode_exit (AnimData *adt) +{ + NlaTrack *nlt; + + /* verify that data is valid */ + if ELEM(NULL, adt, adt->nla_tracks.first) + return; + + /* hopefully the flag is correct - skip if not on */ + if ((adt->flag & ADT_NLA_EDIT_ON) == 0) + return; + + // TODO: need to sync the user-strip with the new state of the action! + + /* for all NLA-tracks, clear the 'disabled' flag */ + for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) + nlt->flag &= ~NLATRACK_DISABLED; + + /* handle AnimData level changes: + * - 'real' active action is restored from storage + * - storage pointer gets cleared (to avoid having bad notes hanging around) + * - editing-flag for this AnimData block should also get turned off + */ + adt->action= adt->tmpact; + adt->tmpact= NULL; + adt->flag &= ~ADT_NLA_EDIT_ON; +} + /* *************************************************** */ -- cgit v1.2.3 From 308b567e9c2c36ddb3e9571e4d064a8954f83607 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 5 Jun 2009 11:51:27 +0000 Subject: NLA SoC: NLA-Evaluation Bugfixes * Fixed an evil bug where the last frame of a strip was always incorrectly evaluated. This was because these frames were not being included in the strip's 'range' as defined by the IN_RANGE() testing macro, which only considers the given range as an open interval (i.e. non-inclusive of boundary points). I've added a new macro, IN_RANGE_INCL(), which is inclusive of boundary points, since this is a common test in many other parts of the code. * When an AnimData block is in 'tweaking' mode, the tracks following (and including the active track) are now correctly skipped during evaluation. * Finished coding the option of setting a single NLA-track per NLA-block to play 'solo' (i.e. only that track is enabled for evaluation). To enable this, simply click on one of the grey 'dots' beside the NLA-track names, turning this dot yellow. The 'yellow' dot means that the track will play by itself (even the 'active action' gets silenced). Only one track per AnimData block can play solo at a time. To disable, simply click on the 'yellow' dot again. NOTE: this currently uses the View3D layer-status icons. We probably need some special ones for these later (coloured vs grey star?) * Also (not related to evaluation) made the selection operators for the NLA Editor only work when not in tweaking mode, since in tweaking mode they can potentially result in data being resolved inappropriately when leaving tweaking mode. --- source/blender/blenkernel/BKE_nla.h | 4 ++++ source/blender/blenkernel/BKE_utildefines.h | 1 + source/blender/blenkernel/intern/anim_sys.c | 34 ++++++++++++++++++++--------- source/blender/blenkernel/intern/nla.c | 32 +++++++++++++++++++++++++++ 4 files changed, 61 insertions(+), 10 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_nla.h b/source/blender/blenkernel/BKE_nla.h index 89e5f1af7e1..da824fd2093 100644 --- a/source/blender/blenkernel/BKE_nla.h +++ b/source/blender/blenkernel/BKE_nla.h @@ -56,12 +56,16 @@ struct NlaStrip *add_nlastrip_to_stack(struct AnimData *adt, struct bAction *act struct NlaTrack *BKE_nlatrack_find_active(ListBase *tracks); void BKE_nlatrack_set_active(ListBase *tracks, struct NlaTrack *nlt); +void BKE_nlatrack_solo_toggle(struct AnimData *adt, struct NlaTrack *nlt); + short BKE_nlatrack_has_space(struct NlaTrack *nlt, float start, float end); void BKE_nlatrack_sort_strips(struct NlaTrack *nlt); + struct NlaStrip *BKE_nlastrip_find_active(struct NlaTrack *nlt); short BKE_nlastrip_within_bounds(struct NlaStrip *strip, float min, float max); + void BKE_nla_action_pushdown(struct AnimData *adt); short BKE_nla_tweakmode_enter(struct AnimData *adt); diff --git a/source/blender/blenkernel/BKE_utildefines.h b/source/blender/blenkernel/BKE_utildefines.h index 6584af085cd..0bed2c095e2 100644 --- a/source/blender/blenkernel/BKE_utildefines.h +++ b/source/blender/blenkernel/BKE_utildefines.h @@ -128,6 +128,7 @@ #define IS_EQT(a, b, c) ((a > b)? (((a-b) <= c)? 1:0) : ((((b-a) <= c)? 1:0))) #define IN_RANGE(a, b, c) ((b < c)? ((bflag & (NLATRACK_MUTED|NLATRACK_DISABLED)) - return; - /* loop over strips, checking if they fall within the range */ for (strip= nlt->strips.first; strip; strip= strip->next) { /* check if current time occurs within this strip */ - if (IN_RANGE(ctime, strip->start, strip->end)) { + if (IN_RANGE_INCL(ctime, strip->start, strip->end)) { /* this strip is active, so try to use it */ estrip= strip; side= NES_TIME_WITHIN; @@ -1013,8 +1009,21 @@ static void animsys_evaluate_nla (PointerRNA *ptr, AnimData *adt, float ctime) NlaEvalStrip *nes; /* 1. get the stack of strips to evaluate at current time (influence calculated here) */ - for (nlt=adt->nla_tracks.first; nlt; nlt=nlt->next, track_index++) + for (nlt=adt->nla_tracks.first; nlt; nlt=nlt->next, track_index++) { + /* if tweaking is on and this strip is the tweaking track, stop on this one */ + if ((adt->flag & ADT_NLA_EDIT_ON) && (nlt->flag & NLATRACK_DISABLED)) + break; + + /* skip if we're only considering a track tagged 'solo' */ + if ((adt->flag & ADT_NLA_SOLO_TRACK) && (nlt->flag & NLATRACK_SOLO)==0) + continue; + /* skip if track is muted */ + if (nlt->flag & NLATRACK_MUTED) + continue; + + /* otherwise, get strip to evaluate for this channel */ nlatrack_ctime_get_strip(&estrips, nlt, track_index, ctime); + } /* only continue if there are strips to evaluate */ if (estrips.first == NULL) @@ -1114,12 +1123,17 @@ void BKE_animsys_evaluate_animdata (ID *id, AnimData *adt, float ctime, short re /* evaluate NLA data */ if ((adt->nla_tracks.first) && !(adt->flag & ADT_NLA_EVAL_OFF)) { + /* evaluate NLA-stack */ animsys_evaluate_nla(&id_ptr, adt, ctime); + + /* evaluate 'active' Action (may be tweaking track) on top of results of NLA-evaluation + * - only do this if we're not exclusively evaluating the 'solo' NLA-track + */ + if ((adt->action) && !(adt->flag & ADT_NLA_SOLO_TRACK)) + animsys_evaluate_action(&id_ptr, adt->action, adt->remap, ctime); } - - /* evaluate Action data */ - // FIXME: what if the solo track was not tweaking one, then nla-solo should be checked too? - if (adt->action) + /* evaluate Active Action only */ + else if (adt->action) animsys_evaluate_action(&id_ptr, adt->action, adt->remap, ctime); /* reset tag */ diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index 84f98096364..d3a01b6d610 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -359,6 +359,38 @@ NlaTrack *BKE_nlatrack_find_active (ListBase *tracks) return NULL; } +/* Toggle the 'solo' setting for the given NLA-track, making sure that it is the only one + * that has this status in its AnimData block. + */ +void BKE_nlatrack_solo_toggle (AnimData *adt, NlaTrack *nlt) +{ + NlaTrack *nt; + + /* sanity check */ + if ELEM(NULL, adt, adt->nla_tracks.first) + return; + + /* firstly, make sure 'solo' flag for all tracks is disabled */ + for (nt= adt->nla_tracks.first; nt; nt= nt->next) { + if (nt != nlt) + nt->flag &= ~NLATRACK_SOLO; + } + + /* now, enable 'solo' for the given track if appropriate */ + if (nlt) { + /* toggle solo status */ + nlt->flag ^= NLATRACK_SOLO; + + /* set or clear solo-status on AnimData */ + if (nlt->flag & NLATRACK_SOLO) + adt->flag |= ADT_NLA_SOLO_TRACK; + else + adt->flag &= ~ADT_NLA_SOLO_TRACK; + } + else + adt->flag &= ~ADT_NLA_SOLO_TRACK; +} + /* Make the given NLA-track the active one for the given stack. If no track is provided, * this function can be used to simply deactivate all the NLA tracks in the given stack too. */ -- cgit v1.2.3 From 9621d626a0484d19e2c18e57cbdd5f9c24c827f4 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sat, 6 Jun 2009 05:06:46 +0000 Subject: NLA SoC: Various user-counts and file IO bugfixes for tweaking actions... --- source/blender/blenkernel/intern/anim_sys.c | 2 +- source/blender/blenkernel/intern/nla.c | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index fb4c2663c3c..390efc5ced4 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -154,7 +154,7 @@ AnimData *BKE_copy_animdata (AnimData *adt) // XXX review this... it might not be optimal behaviour yet... //id_us_plus((ID *)dadt->action); dadt->action= copy_action(adt->action); - dadt->tmpact= copy_action(adt->action); + dadt->tmpact= copy_action(adt->tmpact); /* duplicate NLA data */ copy_nladata(&dadt->nla_tracks, &adt->nla_tracks); diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index d3a01b6d610..9acbad32a42 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -675,11 +675,12 @@ short BKE_nla_tweakmode_enter (AnimData *adt) /* handle AnimData level changes: * - 'real' active action to temp storage (no need to change user-counts) - * - action of active strip set to be the 'active action' + * - action of active strip set to be the 'active action', and have its usercount incremented * - editing-flag for this AnimData block should also get turned on (for more efficient restoring) */ adt->tmpact= adt->action; adt->action= activeStrip->act; + id_us_plus(&activeStrip->act->id); adt->flag |= ADT_NLA_EDIT_ON; /* done! */ @@ -706,10 +707,12 @@ void BKE_nla_tweakmode_exit (AnimData *adt) nlt->flag &= ~NLATRACK_DISABLED; /* handle AnimData level changes: + * - 'temporary' active action needs its usercount decreased, since we're removing this reference * - 'real' active action is restored from storage * - storage pointer gets cleared (to avoid having bad notes hanging around) * - editing-flag for this AnimData block should also get turned off */ + if (adt->action) adt->action->id.us--; adt->action= adt->tmpact; adt->tmpact= NULL; adt->flag &= ~ADT_NLA_EDIT_ON; -- cgit v1.2.3 From 580e69b365a2b308bc5d8a2e7cc41b7f3ee5c248 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Sat, 6 Jun 2009 21:49:00 +0000 Subject: Patch/Bugfix so wind noise got controlable seed and therefore redoable cloth sims - bug reported by istvan --- source/blender/blenkernel/BKE_blender.h | 2 +- source/blender/blenkernel/intern/effect.c | 10 ++++------ 2 files changed, 5 insertions(+), 7 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index cc2f9bd8334..5513f98b299 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -41,7 +41,7 @@ struct ListBase; struct MemFile; #define BLENDER_VERSION 249 -#define BLENDER_SUBVERSION 0 +#define BLENDER_SUBVERSION 1 #define BLENDER_MINVERSION 245 #define BLENDER_MINSUBVERSION 15 diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index cca5d68167e..5bc3e295272 100644 --- a/source/blender/blenkernel/intern/effect.c +++ b/source/blender/blenkernel/intern/effect.c @@ -80,7 +80,6 @@ #include "BKE_screen.h" #include "BKE_utildefines.h" -#include "PIL_time.h" #include "RE_render_ext.h" /* fluid sim particle import */ @@ -161,8 +160,7 @@ static void add_to_effectorcache(ListBase *lb, Object *ob, Object *obsrc) if(pd->forcefield == PFIELD_WIND) { - pd->rng = rng_new(1); - rng_srandom(pd->rng, (unsigned int)(ceil(PIL_check_seconds_timer()))); // use better seed + pd->rng = rng_new(pd->seed); } ec= MEM_callocN(sizeof(pEffectorCache), "effector cache"); @@ -286,14 +284,14 @@ static float eff_calc_visibility(Object *ob, float *co, float *dir) // noise function for wind e.g. static float wind_func(struct RNG *rng, float strength) { - int random = (rng_getInt(rng)+1) % 65535; // max 2357 + int random = (rng_getInt(rng)+1) % 128; // max 2357 float force = rng_getFloat(rng) + 1.0f; float ret; float sign = 0; - sign = (random > 32000.0) ? 1.0: -1.0; // dividing by 2 is not giving equal sign distribution + sign = ((float)random > 64.0) ? 1.0: -1.0; // dividing by 2 is not giving equal sign distribution - ret = sign*((float)random / force)*strength/65535.0f; + ret = sign*((float)random / force)*strength/128.0f; return ret; } -- cgit v1.2.3 From 34f29749c8d83b279dc0dd186da32018d0b30685 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sun, 7 Jun 2009 06:49:04 +0000 Subject: NLA SoC: RNA wrapping for NLA Data Most of the relevant properties have been wrapped. - There are still some properties I'm not sure about whether they should be exposed at all (which have been left out for now). Most of these are really internal flags which are used in a few select places. - To maintain the integrity of the settings, I've included some custom code for a few of the setters (i.e. scale/end-frame) where changing one should result in a change in the other and vica-versa. Also, tweaked the wrapping for a few other types. Another side effect of this commit is that I can now uncommented some code for using F-Curves to control the influence and time of the strips. These F-Curves would need to be specifically attached to the NLA-Strip they affect for now (TODO: I need to review this again...), and as such, cannot be used yet since there's no (end-user-accessible) way to do this :) --- source/blender/blenkernel/intern/anim_sys.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 390efc5ced4..44817b47860 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -657,16 +657,13 @@ void nlastrip_evaluate_controls (NlaStrip *strip, float ctime) /* now strip's evaluate F-Curves for these settings (if applicable) */ if (strip->fcurves.first) { -#if 0 PointerRNA strip_ptr; - FCurve *fcu; /* create RNA-pointer needed to set values */ RNA_pointer_create(NULL, &RNA_NlaStrip, strip, &strip_ptr); /* execute these settings as per normal */ - animsys_evaluate_fcurves(&actstrip_ptr, &strip->fcurves, NULL, ctime); -#endif + animsys_evaluate_fcurves(&strip_ptr, &strip->fcurves, NULL, ctime); } } -- cgit v1.2.3 From 43c7c15e2be555454f54840307fd5ea7d61d0216 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sun, 7 Jun 2009 07:04:31 +0000 Subject: NLA SoC: 2 little tweaks - Evaluation times for strips are now strictly clamped to the endpoints of the strips - i.e. if a strip has 'extend' on, the strip's evaluation time won't continue to change as time changes - New NLA Editor instances now have auto-snapping turned on by default (as they should) --- source/blender/blenkernel/intern/anim_sys.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 44817b47860..3290e06dfb4 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -730,6 +730,16 @@ static void nlatrack_ctime_get_strip (ListBase *list, NlaTrack *nlt, short index */ if ((estrip == NULL) || (estrip->flag & NLASTRIP_FLAG_MUTED)) return; + + /* if ctime was not within the boundaries of the strip, clamp! */ + switch (side) { + case NES_TIME_BEFORE: /* extend first frame only */ + ctime= estrip->start; + break; + case NES_TIME_AFTER: /* extend last frame only */ + ctime= estrip->end; + break; + } /* evaluate strip's evaluation controls * - skip if no influence (i.e. same effect as muting the strip) -- cgit v1.2.3 From 105d3fd32324c3d6dcf1b1ecbd5d50c4afea89cc Mon Sep 17 00:00:00 2001 From: Ken Hughes Date: Mon, 8 Jun 2009 17:30:53 +0000 Subject: Fix "no newline at end of file" warning. --- source/blender/blenkernel/intern/scene.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index df304568ed5..2c71f07a97a 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -802,4 +802,4 @@ void free_dome_warp_text(struct Text *txt) scene->r.dometext = NULL; scene = scene->id.next; } -} \ No newline at end of file +} -- cgit v1.2.3 From 20eaa1466dbb530e583699e189c9f8b8597b7eb4 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Tue, 9 Jun 2009 13:03:00 +0000 Subject: Fix for bug #18881 and #18866: Surface option for Fields crashed on non-mesh objects, so hide it if not applicable. Also made it support surf, curve, font objects. --- source/blender/blenkernel/BKE_displist.h | 2 +- source/blender/blenkernel/intern/displist.c | 10 ++- source/blender/blenkernel/intern/modifier.c | 135 ++++++++++++++-------------- 3 files changed, 76 insertions(+), 71 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_displist.h b/source/blender/blenkernel/BKE_displist.h index a534dcc3669..9108846330c 100644 --- a/source/blender/blenkernel/BKE_displist.h +++ b/source/blender/blenkernel/BKE_displist.h @@ -86,7 +86,7 @@ extern void count_displist(struct ListBase *lb, int *totvert, int *totface); extern void freedisplist(struct ListBase *lb); extern int displist_has_faces(struct ListBase *lb); extern void makeDerivedMesh(struct Object *ob, CustomDataMask dataMask); -extern void makeDispListSurf(struct Object *ob, struct ListBase *dispbase, int forRender); +extern void makeDispListSurf(struct Object *ob, struct ListBase *dispbase, int forRender, int forOrco); extern void makeDispListCurveTypes(struct Object *ob, int forOrco); extern void makeDispListMBall(struct Object *ob); extern void shadeDispList(struct Base *base); diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index 91eea56c9e7..afc769b0966 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -1356,7 +1356,7 @@ static void displist_surf_indices(DispList *dl) } -void makeDispListSurf(Object *ob, ListBase *dispbase, int forRender) +void makeDispListSurf(Object *ob, ListBase *dispbase, int forRender, int forOrco) { ListBase *nubase; Nurb *nu; @@ -1375,7 +1375,8 @@ void makeDispListSurf(Object *ob, ListBase *dispbase, int forRender) nubase= &cu->nurb; } - curve_calc_modifiers_pre(ob, nubase, forRender, &originalVerts, &deformedVerts, &numVerts); + if(!forOrco) + curve_calc_modifiers_pre(ob, nubase, forRender, &originalVerts, &deformedVerts, &numVerts); for (nu=nubase->first; nu; nu=nu->next) { if(forRender || nu->hide==0) { @@ -1429,7 +1430,8 @@ void makeDispListSurf(Object *ob, ListBase *dispbase, int forRender) tex_space_curve(cu); } - curve_calc_modifiers_post(ob, nubase, dispbase, forRender, originalVerts, deformedVerts); + if(!forOrco) + curve_calc_modifiers_post(ob, nubase, dispbase, forRender, originalVerts, deformedVerts); } void makeDispListCurveTypes(Object *ob, int forOrco) @@ -1445,7 +1447,7 @@ void makeDispListCurveTypes(Object *ob, int forOrco) freedisplist(dispbase); if(ob->type==OB_SURF) { - makeDispListSurf(ob, dispbase, 0); + makeDispListSurf(ob, dispbase, 0, forOrco); } else if ELEM(ob->type, OB_CURVE, OB_FONT) { ListBase dlbev; diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index c9f6bc18abd..2c4528f641e 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -114,6 +114,72 @@ #include "RE_shader_ext.h" +/* Utility */ + +static int is_last_displist(Object *ob) +{ + Curve *cu = ob->data; + static int curvecount=0, totcurve=0; + + if(curvecount == 0){ + DispList *dl; + + totcurve = 0; + for(dl=cu->disp.first; dl; dl=dl->next) + totcurve++; + } + + curvecount++; + + if(curvecount == totcurve){ + curvecount = 0; + return 1; + } + + return 0; +} + +static DerivedMesh *get_original_dm(Object *ob, float (*vertexCos)[3], int orco) +{ + DerivedMesh *dm= NULL; + + if(ob->type==OB_MESH) { + dm = CDDM_from_mesh((Mesh*)(ob->data), ob); + + if(vertexCos) { + CDDM_apply_vert_coords(dm, vertexCos); + //CDDM_calc_normals(dm); + } + + if(orco) + DM_add_vert_layer(dm, CD_ORCO, CD_ASSIGN, get_mesh_orco_verts(ob)); + } + else if(ELEM3(ob->type,OB_FONT,OB_CURVE,OB_SURF)) { + Object *tmpobj; + Curve *tmpcu; + + if(is_last_displist(ob)) { + /* copies object and modifiers (but not the data) */ + tmpobj= copy_object(ob); + tmpcu = (Curve *)tmpobj->data; + tmpcu->id.us--; + + /* copies the data */ + tmpobj->data = copy_curve((Curve *) ob->data); + + makeDispListCurveTypes(tmpobj, 1); + nurbs_to_mesh(tmpobj); + + dm = CDDM_from_mesh((Mesh*)(tmpobj->data), tmpobj); + //CDDM_calc_normals(dm); + + free_libblock_us(&G.main->object, tmpobj); + } + } + + return dm; +} + /***/ static int noneModifier_isDisabled(ModifierData *md) @@ -6037,7 +6103,8 @@ static void surfaceModifier_freeData(ModifierData *md) MEM_freeN(surmd->bvhtree); } - surmd->dm->release(surmd->dm); + if(surmd->dm) + surmd->dm->release(surmd->dm); surmd->bvhtree = NULL; surmd->dm = NULL; @@ -6061,7 +6128,7 @@ static void surfaceModifier_deformVerts( /* if possible use/create DerivedMesh */ if(derivedData) surmd->dm = CDDM_copy(derivedData); - else if(ob->type==OB_MESH) surmd->dm = CDDM_from_mesh(ob->data, ob); + else surmd->dm = get_original_dm(ob, NULL, 0); if(!ob->pd) { @@ -6233,70 +6300,6 @@ CustomDataMask particleSystemModifier_requiredDataMask(ModifierData *md) return dataMask; } -static int is_last_displist(Object *ob) -{ - Curve *cu = ob->data; - static int curvecount=0, totcurve=0; - - if(curvecount==0){ - DispList *dl; - - totcurve=0; - for(dl=cu->disp.first; dl; dl=dl->next){ - totcurve++; - } - } - - curvecount++; - - if(curvecount==totcurve){ - curvecount=0; - return 1; - } - - return 0; -} - -static DerivedMesh *get_original_dm(Object *ob, float (*vertexCos)[3], int orco) -{ - DerivedMesh *dm= NULL; - - if(ob->type==OB_MESH) { - dm = CDDM_from_mesh((Mesh*)(ob->data), ob); - - if(vertexCos) { - CDDM_apply_vert_coords(dm, vertexCos); - //CDDM_calc_normals(dm); - } - - if(orco) - DM_add_vert_layer(dm, CD_ORCO, CD_ASSIGN, get_mesh_orco_verts(ob)); - } - else if(ELEM3(ob->type,OB_FONT,OB_CURVE,OB_SURF)) { - Object *tmpobj; - Curve *tmpcu; - - if(is_last_displist(ob)) { - /* copies object and modifiers (but not the data) */ - tmpobj= copy_object(ob); - tmpcu = (Curve *)tmpobj->data; - tmpcu->id.us--; - - /* copies the data */ - tmpobj->data = copy_curve((Curve *) ob->data); - - makeDispListCurveTypes(tmpobj, 1); - nurbs_to_mesh(tmpobj); - - dm = CDDM_from_mesh((Mesh*)(tmpobj->data), tmpobj); - //CDDM_calc_normals(dm); - - free_libblock_us(&G.main->object, tmpobj); - } - } - - return dm; -} /* saves the current emitter state for a particle system and calculates particles */ static void particleSystemModifier_deformVerts( -- cgit v1.2.3 From 9a54ca9af79012354e91424d3b434ea23bc053ad Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Tue, 9 Jun 2009 18:50:02 +0000 Subject: Fix for bug #18710: a crash with hair emitted from vertices. --- source/blender/blenkernel/intern/particle_system.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 3445556b53b..31e246f66b9 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -1307,9 +1307,23 @@ int psys_threads_init_distribution(ParticleThread *threads, DerivedMesh *finaldm /* for hair, sort by origindex, allows optimizations in rendering */ /* however with virtual parents the children need to be in random order */ if(part->type == PART_HAIR && !(part->childtype==PART_CHILD_FACES && part->parents!=0.0)) { - COMPARE_ORIG_INDEX= dm->getFaceDataArray(dm, CD_ORIGINDEX); - if(COMPARE_ORIG_INDEX) - qsort(index, totpart, sizeof(int), compare_orig_index); + if(from != PART_FROM_PARTICLE) { + COMPARE_ORIG_INDEX = NULL; + + if(from == PART_FROM_VERT) { + if(dm->numVertData) + COMPARE_ORIG_INDEX= dm->getVertDataArray(dm, CD_ORIGINDEX); + } + else { + if(dm->numFaceData) + COMPARE_ORIG_INDEX= dm->getFaceDataArray(dm, CD_ORIGINDEX); + } + + if(COMPARE_ORIG_INDEX) { + qsort(index, totpart, sizeof(int), compare_orig_index); + COMPARE_ORIG_INDEX = NULL; + } + } } /* weights are no longer used except for FROM_PARTICLE, which needs them zeroed for indexing */ -- cgit v1.2.3 From 867e1291350de7c128c18c9f9a2e7c4b7a5513f4 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Wed, 10 Jun 2009 05:03:27 +0000 Subject: F-Modifiers (in Nla branch): For fun, added 'sinc' (i.e. y = sin(pi*x)/(pi*x)) as a type of builtin function usable through the generator modifier. This makes a nice 'jolt' which tapers off. --- source/blender/blenkernel/intern/fcurve.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index 6a3870f8f31..5820761234c 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -1410,6 +1410,18 @@ static void fcm_generator_verify (FModifier *fcm) } } +/* Unary 'normalised sine' function + * y = sin(PI + x) / (PI * x), + * except for x = 0 when y = 1. + */ +static double sinc (double x) +{ + if (fabs(x) < 0.0001) + return 1.0; + else + return sin(M_PI * x) / (M_PI * x); +} + static void fcm_generator_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime) { FMod_Generator *data= (FMod_Generator *)fcm->data; @@ -1490,6 +1502,9 @@ static void fcm_generator_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, case FCM_GENERATOR_FN_COS: /* cosine wave */ fn= cos; break; + case FCM_GENERATOR_FN_SINC: /* normalised sine wave */ + fn= sinc; + break; /* validation required */ case FCM_GENERATOR_FN_TAN: /* tangent wave */ @@ -1527,7 +1542,7 @@ static void fcm_generator_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, } } break; - + default: printf("Invalid Function-Generator for F-Modifier - %d \n", data->func_type); } -- cgit v1.2.3 From 64f94a670ea9a5704276f1e80f61afdcb067a2b6 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Thu, 11 Jun 2009 02:14:56 +0000 Subject: NLA SoC: Evaluation bugfixes * Strip scaling was being evaluated in the wrong way, resulting in scaled strips not being played too fast (for lengthened strips) or too slow (shortened strips) * Also, verified that the 'reversed' option works correctly (no changes needed to be made here) --- source/blender/blenkernel/intern/anim_sys.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 3290e06dfb4..a864e3d4e87 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -591,23 +591,23 @@ static float nlastrip_get_frame (NlaStrip *strip, float cframe, short invert) float length, actlength, repeat, scale; /* get number of repeats */ - if (strip->repeat == 0.0f) strip->repeat = 1.0f; + if (IS_EQ(strip->repeat, 0.0f)) strip->repeat = 1.0f; repeat = strip->repeat; /* scaling */ - if (strip->scale == 0.0f) strip->scale= 1.0f; + if (IS_EQ(strip->scale, 0.0f)) strip->scale= 1.0f; scale = (float)fabs(strip->scale); /* scale must be positive - we've got a special flag for reversing */ /* length of referenced action */ actlength = strip->actend - strip->actstart; - if (actlength == 0.0f) actlength = 1.0f; + if (IS_EQ(actlength, 0.0f)) actlength = 1.0f; /* length of strip */ - length = repeat * scale * actlength; + length = strip->end - strip->start; + if (IS_EQ(length, 0.0f)) length= actlength * scale * repeat; /* reversed = play strip backwards */ if (strip->flag & NLASTRIP_FLAG_REVERSE) { - // FIXME: verify these /* invert = convert action-strip time to global time */ if (invert) return length*(strip->actend - cframe)/(repeat*actlength) + strip->start; @@ -651,7 +651,7 @@ void nlastrip_evaluate_controls (NlaStrip *strip, float ctime) { /* firstly, analytically generate values for influence and time (if applicable) */ if ((strip->flag & NLASTRIP_FLAG_USR_TIME) == 0) - strip->strip_time= nlastrip_get_frame(strip, ctime, 1); /* last arg '1' means current time to 'strip'/action time */ + strip->strip_time= nlastrip_get_frame(strip, ctime, 0); if ((strip->flag & NLASTRIP_FLAG_USR_INFLUENCE) == 0) strip->influence= nlastrip_get_influence(strip, ctime); -- cgit v1.2.3 From f0f9034966be8692250686aee74048294960aad3 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Thu, 11 Jun 2009 03:19:08 +0000 Subject: NLA SoC: Operator for adding new NLA-Tracks New tracks can be added in the following ways (with the mouse hovering over the channels-list): * Shift-A - this will add a new track at the top of the stack (i.e. above all the existing NLA-tracks but below the Active Action) for every AnimData block where there was a selected NLA-Track * Ctrl-Shift-A - this will add a new track above every selected one --- source/blender/blenkernel/BKE_nla.h | 2 +- source/blender/blenkernel/intern/nla.c | 13 +++++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_nla.h b/source/blender/blenkernel/BKE_nla.h index da824fd2093..078c1ba52bb 100644 --- a/source/blender/blenkernel/BKE_nla.h +++ b/source/blender/blenkernel/BKE_nla.h @@ -46,7 +46,7 @@ struct NlaStrip *copy_nlastrip(struct NlaStrip *strip); struct NlaTrack *copy_nlatrack(struct NlaTrack *nlt); void copy_nladata(ListBase *dst, ListBase *src); -struct NlaTrack *add_nlatrack(struct AnimData *adt); +struct NlaTrack *add_nlatrack(struct AnimData *adt, struct NlaTrack *prev); struct NlaStrip *add_nlastrip(struct bAction *act); struct NlaStrip *add_nlastrip_to_stack(struct AnimData *adt, struct bAction *act); diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index 9acbad32a42..cef14128032 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -215,8 +215,10 @@ void copy_nladata (ListBase *dst, ListBase *src) /* Adding ------------------------------------------- */ -/* Add a NLA Track to the given AnimData */ -NlaTrack *add_nlatrack (AnimData *adt) +/* Add a NLA Track to the given AnimData + * - prev: NLA-Track to add the new one after + */ +NlaTrack *add_nlatrack (AnimData *adt, NlaTrack *prev) { NlaTrack *nlt; @@ -232,7 +234,10 @@ NlaTrack *add_nlatrack (AnimData *adt) nlt->index= BLI_countlist(&adt->nla_tracks); /* add track to stack, and make it the active one */ - BLI_addtail(&adt->nla_tracks, nlt); + if (prev) + BLI_insertlinkafter(&adt->nla_tracks, prev, nlt); + else + BLI_addtail(&adt->nla_tracks, nlt); BKE_nlatrack_set_active(&adt->nla_tracks, nlt); /* must have unique name, but we need to seed this */ @@ -308,7 +313,7 @@ NlaStrip *add_nlastrip_to_stack (AnimData *adt, bAction *act) (BKE_nlatrack_has_space(adt->nla_tracks.last, strip->start, strip->end)==0) ) { /* no space, so add to a new track... */ - nlt= add_nlatrack(adt); + nlt= add_nlatrack(adt, NULL); } else { -- cgit v1.2.3 From c4ad2ed2536407cf2a9b3bc8f0b77bc88cccf71d Mon Sep 17 00:00:00 2001 From: Robin Allen Date: Sat, 13 Jun 2009 14:22:40 +0000 Subject: Omission of a texture node to specify coordinates was regarded as a bug by some users. I rather agree :) --- source/blender/blenkernel/BKE_node.h | 3 ++- source/blender/blenkernel/intern/node.c | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 184b28b2cd2..66e8492b357 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -407,8 +407,9 @@ struct TexResult; #define TEX_NODE_DECOMPOSE 420 #define TEX_NODE_VALTONOR 421 #define TEX_NODE_SCALE 422 +#define TEX_NODE_AT 423 -/* 201-299 reserved. Use like this: TEX_NODE_PROC + TEX_CLOUDS, etc */ +/* 501-599 reserved. Use like this: TEX_NODE_PROC + TEX_CLOUDS, etc */ #define TEX_NODE_PROC 500 #define TEX_NODE_PROC_MAX 600 diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 413c2fc20f5..62064799aca 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -2921,6 +2921,7 @@ static void registerTextureNodes(ListBase *ntypelist) nodeRegisterType(ntypelist, &tex_node_rotate); nodeRegisterType(ntypelist, &tex_node_translate); nodeRegisterType(ntypelist, &tex_node_scale); + nodeRegisterType(ntypelist, &tex_node_at); nodeRegisterType(ntypelist, &tex_node_proc_voronoi); nodeRegisterType(ntypelist, &tex_node_proc_blend); -- cgit v1.2.3 From a7ac260cc5e47bfca6e9678f1271fbdd438ac119 Mon Sep 17 00:00:00 2001 From: Kent Mein Date: Sat, 13 Jun 2009 16:57:26 +0000 Subject: coverity issue CID: 469 Checker: REVERSE_INULL (help) File: base/src/source/blender/blenkernel/intern/BME_tools.c Function: BME_split_face Description: Pointer "example" dereferenced before NULL check Check for null before we try to use it. Kent --- source/blender/blenkernel/intern/BME_tools.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/BME_tools.c b/source/blender/blenkernel/intern/BME_tools.c index f3e4add34e9..a2cd6389e7d 100644 --- a/source/blender/blenkernel/intern/BME_tools.c +++ b/source/blender/blenkernel/intern/BME_tools.c @@ -192,7 +192,7 @@ static BME_Poly *BME_split_face(BME_Mesh *bm, BME_Poly *f, BME_Vert *v1, BME_Ver nf = BME_SFME(bm,f,v1,v2,nl); nf->flag = f->flag; /* if the edge was selected, select this face, too */ - if (example->flag & SELECT) f->flag |= ME_FACE_SEL; + if (example && (example->flag & SELECT)) f->flag |= ME_FACE_SEL; nf->h = f->h; nf->mat_nr = f->mat_nr; if (nl && example) { -- cgit v1.2.3 From 472239cc948443e8265fc6359834225214ae03c5 Mon Sep 17 00:00:00 2001 From: Kent Mein Date: Sat, 13 Jun 2009 22:23:24 +0000 Subject: coverity issue CID: 307 Checker: FORWARD_NULL (help) File: base/src/source/blender/blenkernel/intern/modifier.c Function: meshdeformModifier_deformVerts Description: Variable "dm" tracked as NULL was passed to a function that dereferences it. fix provided by Brecht. Kent --- source/blender/blenkernel/intern/modifier.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 2c4528f641e..29930b3eb58 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -7813,10 +7813,12 @@ static void meshdeformModifier_deformVerts( { DerivedMesh *dm; - if(!derivedData && ob->type==OB_MESH) - dm= CDDM_from_mesh(ob->data, ob); - else - dm= derivedData; + if (!derivedData) { + dm= get_original_dm(ob, NULL, 0); + if (dm == NULL) return; + } + else dm= derivedData; + modifier_vgroup_cache(md, vertexCos); /* if next modifier needs original vertices */ -- cgit v1.2.3 From ca12954e9fb3b38d662190d12e72937ef9990d89 Mon Sep 17 00:00:00 2001 From: Peter Schlaile Date: Sun, 14 Jun 2009 18:54:35 +0000 Subject: == Sequencer == Big proxy fix (addressing hopefully most complaints on mailing list and in tracker) * proxy render settings are now independent of render size settings. That means: which proxy size is used, is controlled by two parameters now: the proxy size of the files, can be controlled with additional buttons within the proxy panels. What is shown in a specific preview window depends on the header settings of the preview panel. So: proxies are _only_ used in those windows, that are switched to a specific proxy resolution. * output rendering is always done _without_ proxies. * proxy generation now shows a waitcursor with numbers. (closing Bug: [#18909] Building Proxies doesn't give any feedback which was rather a feature request, since the problem mentioned there was always the case :) ) --- source/blender/blenkernel/BKE_blender.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index 5513f98b299..30e68b83149 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -41,7 +41,7 @@ struct ListBase; struct MemFile; #define BLENDER_VERSION 249 -#define BLENDER_SUBVERSION 1 +#define BLENDER_SUBVERSION 2 #define BLENDER_MINVERSION 245 #define BLENDER_MINSUBVERSION 15 -- cgit v1.2.3 From e6aa552e25cd2c8ff6582b3f8fb2a91b8aad2711 Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Mon, 15 Jun 2009 09:54:37 +0000 Subject: 2.5 Text Object: editmode suffered wrong allocation and reading from wrong memory, causing crashes when typing more than a few chars. --- source/blender/blenkernel/intern/curve.c | 2 +- source/blender/blenkernel/intern/font.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index fab9669d55f..7dd868278f4 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -155,7 +155,7 @@ Curve *add_curve(char *name, int type) cu->str= MEM_mallocN(12, "str"); strcpy(cu->str, "Text"); cu->pos= 4; - cu->strinfo= MEM_callocN(12*sizeof(CharInfo), "strinfo"); + cu->strinfo= MEM_callocN(12*sizeof(CharInfo), "strinfo new"); cu->totbox= cu->actbox= 1; cu->tb= MEM_callocN(MAXTEXTBOX*sizeof(TextBox), "textbox"); cu->tb[0].w = cu->tb[0].h = 0.0; diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c index c3cf6e06c09..60a7ffc28d9 100644 --- a/source/blender/blenkernel/intern/font.c +++ b/source/blender/blenkernel/intern/font.c @@ -682,7 +682,7 @@ struct chartrans *BKE_text_to_curve(Scene *scene, Object *ob, int mode) cu->ulheight = 0.05; if (cu->strinfo==NULL) /* old file */ - cu->strinfo = MEM_callocN((slen+1) * sizeof(CharInfo), "strinfo compat"); + cu->strinfo = MEM_callocN((slen+4) * sizeof(CharInfo), "strinfo compat"); custrinfo= cu->strinfo; if (cu->editfont) @@ -1145,7 +1145,7 @@ struct chartrans *BKE_text_to_curve(Scene *scene, Object *ob, int mode) if (cu->sepchar==0) { for (i= 0; istrinfo[i]); + info = &(custrinfo[i]); if (info->mat_nr > (ob->totcol)) { /* printf("Error: Illegal material index (%d) in text object, setting to 0\n", info->mat_nr); */ info->mat_nr = 0; -- cgit v1.2.3 From b8d0f62fd2a9088034fa7da1d7e5e82ca845b728 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 15 Jun 2009 11:48:42 +0000 Subject: Fix for bug #18924: OpenGL performance issue with particle modifiers, actually two modifier datamask optimizations that were never done. * Don't use modifier data mask for disabled modifiers. * Check if UV data is needed for particle system instead of always requesting it. --- source/blender/blenkernel/BKE_modifier.h | 9 ++- source/blender/blenkernel/intern/DerivedMesh.c | 26 +++---- source/blender/blenkernel/intern/modifier.c | 80 +++++++++++++++------- source/blender/blenkernel/intern/particle.c | 4 +- source/blender/blenkernel/intern/particle_system.c | 5 +- 5 files changed, 78 insertions(+), 46 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h index a41716ed1ff..e6d83793f94 100644 --- a/source/blender/blenkernel/BKE_modifier.h +++ b/source/blender/blenkernel/BKE_modifier.h @@ -202,7 +202,7 @@ typedef struct ModifierTypeInfo { * * This function is optional. */ - CustomDataMask (*requiredDataMask)(struct ModifierData *md); + CustomDataMask (*requiredDataMask)(struct Object *ob, struct ModifierData *md); /* Free internal modifier data variables, this function should * not free the md variable itself. @@ -270,6 +270,7 @@ int modifier_dependsOnTime(struct ModifierData *md); int modifier_supportsMapping(struct ModifierData *md); int modifier_couldBeCage(struct ModifierData *md); int modifier_isDeformer(struct ModifierData *md); +int modifier_isEnabled(struct ModifierData *md, int required_mode); void modifier_setError(struct ModifierData *md, char *format, ...); void modifiers_foreachObjectLink(struct Object *ob, @@ -300,8 +301,10 @@ int modifiers_indexInObject(struct Object *ob, struct ModifierData *md * evaluation, assuming the data indicated by dataMask is required at the * end of the stack. */ -struct LinkNode *modifiers_calcDataMasks(struct ModifierData *md, - CustomDataMask dataMask); +struct LinkNode *modifiers_calcDataMasks(struct Object *ob, + struct ModifierData *md, + CustomDataMask dataMask, + int required_mode); struct ModifierData *modifiers_getVirtualModifierList(struct Object *ob); #endif diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index ddb7d853f2f..1d0d91c4208 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -2134,18 +2134,18 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3], modifiers_clearErrors(ob); + if(useRenderParams) required_mode = eModifierMode_Render; + else required_mode = eModifierMode_Realtime; + /* we always want to keep original indices */ dataMask |= CD_MASK_ORIGINDEX; - datamasks = modifiers_calcDataMasks(md, dataMask); + datamasks = modifiers_calcDataMasks(ob, md, dataMask, required_mode); curr = datamasks; if(deform_r) *deform_r = NULL; *final_r = NULL; - if(useRenderParams) required_mode = eModifierMode_Render; - else required_mode = eModifierMode_Realtime; - if(useDeform) { if(useDeform > 0 && do_ob_key(ob)) /* shape key makes deform verts */ deformedVerts = mesh_getVertexCos(me, &numVerts); @@ -2156,8 +2156,7 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3], for(;md; md = md->next, curr = curr->next) { ModifierTypeInfo *mti = modifierType_getInfo(md->type); - if((md->mode & required_mode) != required_mode) continue; - if(mti->isDisabled && mti->isDisabled(md)) continue; + if(!modifier_isEnabled(md, required_mode)) continue; if(useDeform < 0 && mti->dependsOnTime && mti->dependsOnTime(md)) continue; if(mti->type == eModifierTypeType_OnlyDeform) { @@ -2221,19 +2220,18 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3], for(;md; md = md->next, curr = curr->next) { ModifierTypeInfo *mti = modifierType_getInfo(md->type); - if((md->mode & required_mode) != required_mode) continue; + if(!modifier_isEnabled(md, required_mode)) continue; if(mti->type == eModifierTypeType_OnlyDeform && !useDeform) continue; if((mti->flags & eModifierTypeFlag_RequiresOriginalData) && dm) { modifier_setError(md, "Modifier requires original data, bad stack position."); continue; } - if(mti->isDisabled && mti->isDisabled(md)) continue; if(needMapping && !modifier_supportsMapping(md)) continue; if(useDeform < 0 && mti->dependsOnTime && mti->dependsOnTime(md)) continue; /* add an orco layer if needed by this modifier */ if(dm && mti->requiredDataMask) { - mask = mti->requiredDataMask(md); + mask = mti->requiredDataMask(ob, md); if(mask & CD_MASK_ORCO) add_orco_dm(ob, NULL, dm, orcodm); } @@ -2405,14 +2403,11 @@ static int editmesh_modifier_is_enabled(ModifierData *md, DerivedMesh *dm) ModifierTypeInfo *mti = modifierType_getInfo(md->type); int required_mode = eModifierMode_Realtime | eModifierMode_Editmode; - if((md->mode & required_mode) != required_mode) return 0; + if(!modifier_isEnabled(md, required_mode)) return 0; if((mti->flags & eModifierTypeFlag_RequiresOriginalData) && dm) { modifier_setError(md, "Modifier requires original data, bad stack position."); return 0; } - if(mti->isDisabled && mti->isDisabled(md)) return 0; - if(!(mti->flags & eModifierTypeFlag_SupportsEditmode)) return 0; - if(md->mode & eModifierMode_DisableTemporary) return 0; return 1; } @@ -2429,6 +2424,7 @@ static void editmesh_calc_modifiers(DerivedMesh **cage_r, DerivedMesh *dm, *orcodm = NULL; int i, numVerts = 0, cageIndex = modifiers_getCageIndex(ob, NULL); LinkNode *datamasks, *curr; + int required_mode = eModifierMode_Realtime | eModifierMode_Editmode; modifiers_clearErrors(ob); @@ -2442,7 +2438,7 @@ static void editmesh_calc_modifiers(DerivedMesh **cage_r, /* we always want to keep original indices */ dataMask |= CD_MASK_ORIGINDEX; - datamasks = modifiers_calcDataMasks(md, dataMask); + datamasks = modifiers_calcDataMasks(ob, md, dataMask, required_mode); curr = datamasks; for(i = 0; md; i++, md = md->next, curr = curr->next) { @@ -2453,7 +2449,7 @@ static void editmesh_calc_modifiers(DerivedMesh **cage_r, /* add an orco layer if needed by this modifier */ if(dm && mti->requiredDataMask) { - mask = mti->requiredDataMask(md); + mask = mti->requiredDataMask(ob, md); if(mask & CD_MASK_ORCO) add_orco_dm(ob, em, dm, orcodm); } diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 29930b3eb58..fa2f857cc8b 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -206,7 +206,7 @@ static void curveModifier_copyData(ModifierData *md, ModifierData *target) strncpy(tcmd->name, cmd->name, 32); } -CustomDataMask curveModifier_requiredDataMask(ModifierData *md) +CustomDataMask curveModifier_requiredDataMask(Object *ob, ModifierData *md) { CurveModifierData *cmd = (CurveModifierData *)md; CustomDataMask dataMask = 0; @@ -282,7 +282,7 @@ static void latticeModifier_copyData(ModifierData *md, ModifierData *target) strncpy(tlmd->name, lmd->name, 32); } -CustomDataMask latticeModifier_requiredDataMask(ModifierData *md) +CustomDataMask latticeModifier_requiredDataMask(Object *ob, ModifierData *md) { LatticeModifierData *lmd = (LatticeModifierData *)md; CustomDataMask dataMask = 0; @@ -665,7 +665,7 @@ static void maskModifier_copyData(ModifierData *md, ModifierData *target) strcpy(tmmd->vgroup, mmd->vgroup); } -static CustomDataMask maskModifier_requiredDataMask(ModifierData *md) +static CustomDataMask maskModifier_requiredDataMask(Object *ob, ModifierData *md) { return (1 << CD_MDEFORMVERT); } @@ -3393,7 +3393,7 @@ static void bevelModifier_copyData(ModifierData *md, ModifierData *target) strncpy(tbmd->defgrp_name, bmd->defgrp_name, 32); } -CustomDataMask bevelModifier_requiredDataMask(ModifierData *md) +CustomDataMask bevelModifier_requiredDataMask(Object *ob, ModifierData *md) { BevelModifierData *bmd = (BevelModifierData *)md; CustomDataMask dataMask = 0; @@ -3473,7 +3473,7 @@ static void displaceModifier_copyData(ModifierData *md, ModifierData *target) strncpy(tdmd->uvlayer_name, dmd->uvlayer_name, 32); } -CustomDataMask displaceModifier_requiredDataMask(ModifierData *md) +CustomDataMask displaceModifier_requiredDataMask(Object *ob, ModifierData *md) { DisplaceModifierData *dmd = (DisplaceModifierData *)md; CustomDataMask dataMask = 0; @@ -3816,7 +3816,7 @@ static void uvprojectModifier_copyData(ModifierData *md, ModifierData *target) tumd->aspecty = umd->aspecty; } -CustomDataMask uvprojectModifier_requiredDataMask(ModifierData *md) +CustomDataMask uvprojectModifier_requiredDataMask(Object *ob, ModifierData *md) { CustomDataMask dataMask = 0; @@ -4276,7 +4276,7 @@ int smoothModifier_isDisabled(ModifierData *md) return 0; } -CustomDataMask smoothModifier_requiredDataMask(ModifierData *md) +CustomDataMask smoothModifier_requiredDataMask(Object *ob, ModifierData *md) { SmoothModifierData *smd = (SmoothModifierData *)md; CustomDataMask dataMask = 0; @@ -4505,7 +4505,7 @@ int castModifier_isDisabled(ModifierData *md) return 0; } -CustomDataMask castModifier_requiredDataMask(ModifierData *md) +CustomDataMask castModifier_requiredDataMask(Object *ob, ModifierData *md) { CastModifierData *cmd = (CastModifierData *)md; CustomDataMask dataMask = 0; @@ -5136,7 +5136,7 @@ static void waveModifier_updateDepgraph( } } -CustomDataMask waveModifier_requiredDataMask(ModifierData *md) +CustomDataMask waveModifier_requiredDataMask(Object *ob, ModifierData *md) { WaveModifierData *wmd = (WaveModifierData *)md; CustomDataMask dataMask = 0; @@ -5473,7 +5473,7 @@ static void armatureModifier_copyData(ModifierData *md, ModifierData *target) strncpy(tamd->defgrp_name, amd->defgrp_name, 32); } -CustomDataMask armatureModifier_requiredDataMask(ModifierData *md) +CustomDataMask armatureModifier_requiredDataMask(Object *ob, ModifierData *md) { CustomDataMask dataMask = 0; @@ -5587,7 +5587,7 @@ static void hookModifier_copyData(ModifierData *md, ModifierData *target) strncpy(thmd->name, hmd->name, 32); } -CustomDataMask hookModifier_requiredDataMask(ModifierData *md) +CustomDataMask hookModifier_requiredDataMask(Object *ob, ModifierData *md) { HookModifierData *hmd = (HookModifierData *)md; CustomDataMask dataMask = 0; @@ -5846,7 +5846,7 @@ static void clothModifier_updateDepgraph( } } -CustomDataMask clothModifier_requiredDataMask(ModifierData *md) +CustomDataMask clothModifier_requiredDataMask(Object *ob, ModifierData *md) { CustomDataMask dataMask = 0; @@ -6230,7 +6230,7 @@ static DerivedMesh *booleanModifier_applyModifier( return derivedData; } -CustomDataMask booleanModifier_requiredDataMask(ModifierData *md) +CustomDataMask booleanModifier_requiredDataMask(Object *ob, ModifierData *md) { CustomDataMask dataMask = (1 << CD_MTFACE) + (1 << CD_MEDGE); @@ -6278,12 +6278,27 @@ static void particleSystemModifier_copyData(ModifierData *md, ModifierData *targ tpsmd->psys = psmd->psys; } -CustomDataMask particleSystemModifier_requiredDataMask(ModifierData *md) +CustomDataMask particleSystemModifier_requiredDataMask(Object *ob, ModifierData *md) { ParticleSystemModifierData *psmd= (ParticleSystemModifierData*) md; - CustomDataMask dataMask = (1 << CD_MTFACE) + (1 << CD_MEDGE); + CustomDataMask dataMask = 0; + Material *ma; + MTex *mtex; int i; + ma= give_current_material(ob, psmd->psys->part->omat); + if(ma) { + for(i=0; imtex[i]; + if(mtex && (ma->septex & (1<pmapto && (mtex->texco & TEXCO_UV)) + dataMask |= (1 << CD_MTFACE); + } + } + + if(psmd->psys->part->tanfac!=0.0) + dataMask |= (1 << CD_MTFACE); + /* ask for vertexgroups if we need them */ for(i=0; ipsys->vgroup[i]){ @@ -6638,7 +6653,7 @@ static int explodeModifier_dependsOnTime(ModifierData *md) { return 1; } -CustomDataMask explodeModifier_requiredDataMask(ModifierData *md) +CustomDataMask explodeModifier_requiredDataMask(Object *ob, ModifierData *md) { ExplodeModifierData *emd= (ExplodeModifierData*) md; CustomDataMask dataMask = 0; @@ -7552,7 +7567,7 @@ static void meshdeformModifier_copyData(ModifierData *md, ModifierData *target) tmmd->object = mmd->object; } -CustomDataMask meshdeformModifier_requiredDataMask(ModifierData *md) +CustomDataMask meshdeformModifier_requiredDataMask(Object *ob, ModifierData *md) { MeshDeformModifierData *mmd = (MeshDeformModifierData *)md; CustomDataMask dataMask = 0; @@ -7876,7 +7891,7 @@ static void shrinkwrapModifier_copyData(ModifierData *md, ModifierData *target) tsmd->subsurfLevels = smd->subsurfLevels; } -CustomDataMask shrinkwrapModifier_requiredDataMask(ModifierData *md) +CustomDataMask shrinkwrapModifier_requiredDataMask(Object *ob, ModifierData *md) { ShrinkwrapModifierData *smd = (ShrinkwrapModifierData *)md; CustomDataMask dataMask = 0; @@ -7910,7 +7925,7 @@ static void shrinkwrapModifier_foreachObjectLink(ModifierData *md, Object *ob, O static void shrinkwrapModifier_deformVerts(ModifierData *md, Object *ob, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts) { DerivedMesh *dm = NULL; - CustomDataMask dataMask = shrinkwrapModifier_requiredDataMask(md); + CustomDataMask dataMask = shrinkwrapModifier_requiredDataMask(ob, md); /* We implement requiredDataMask but thats not really usefull since mesh_calc_modifiers pass a NULL derivedData or without the modified vertexs applied */ if(dataMask) @@ -7936,7 +7951,7 @@ static void shrinkwrapModifier_deformVerts(ModifierData *md, Object *ob, Derived static void shrinkwrapModifier_deformVertsEM(ModifierData *md, Object *ob, EditMesh *editData, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts) { DerivedMesh *dm = NULL; - CustomDataMask dataMask = shrinkwrapModifier_requiredDataMask(md); + CustomDataMask dataMask = shrinkwrapModifier_requiredDataMask(ob, md); if(dataMask) { @@ -7995,7 +8010,7 @@ static void simpledeformModifier_copyData(ModifierData *md, ModifierData *target memcpy(tsmd->limit, smd->limit, sizeof(tsmd->limit)); } -static CustomDataMask simpledeformModifier_requiredDataMask(ModifierData *md) +static CustomDataMask simpledeformModifier_requiredDataMask(Object *ob, ModifierData *md) { SimpleDeformModifierData *smd = (SimpleDeformModifierData *)md; CustomDataMask dataMask = 0; @@ -8024,7 +8039,7 @@ static void simpledeformModifier_updateDepgraph(ModifierData *md, DagForest *for static void simpledeformModifier_deformVerts(ModifierData *md, Object *ob, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts) { DerivedMesh *dm = NULL; - CustomDataMask dataMask = simpledeformModifier_requiredDataMask(md); + CustomDataMask dataMask = simpledeformModifier_requiredDataMask(ob, md); /* We implement requiredDataMask but thats not really usefull since mesh_calc_modifiers pass a NULL derivedData or without the modified vertexs applied */ if(dataMask) @@ -8051,7 +8066,7 @@ static void simpledeformModifier_deformVerts(ModifierData *md, Object *ob, Deriv static void simpledeformModifier_deformVertsEM(ModifierData *md, Object *ob, EditMesh *editData, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts) { DerivedMesh *dm = NULL; - CustomDataMask dataMask = simpledeformModifier_requiredDataMask(md); + CustomDataMask dataMask = simpledeformModifier_requiredDataMask(ob, md); /* We implement requiredDataMask but thats not really usefull since mesh_calc_modifiers pass a NULL derivedData or without the modified vertexs applied */ if(dataMask) @@ -8658,7 +8673,20 @@ int modifiers_isParticleEnabled(Object *ob) return (md && md->mode & (eModifierMode_Realtime | eModifierMode_Render)); } -LinkNode *modifiers_calcDataMasks(ModifierData *md, CustomDataMask dataMask) +int modifier_isEnabled(ModifierData *md, int required_mode) +{ + ModifierTypeInfo *mti = modifierType_getInfo(md->type); + + if((md->mode & required_mode) != required_mode) return 0; + if(mti->isDisabled && mti->isDisabled(md)) return 0; + if(md->mode & eModifierMode_DisableTemporary) return 0; + if(required_mode & eModifierMode_Editmode) + if(!(mti->flags & eModifierTypeFlag_SupportsEditmode)) return 0; + + return 1; +} + +LinkNode *modifiers_calcDataMasks(Object *ob, ModifierData *md, CustomDataMask dataMask, int required_mode) { LinkNode *dataMasks = NULL; LinkNode *curr, *prev; @@ -8668,7 +8696,9 @@ LinkNode *modifiers_calcDataMasks(ModifierData *md, CustomDataMask dataMask) ModifierTypeInfo *mti = modifierType_getInfo(md->type); CustomDataMask mask = 0; - if(mti->requiredDataMask) mask = mti->requiredDataMask(md); + if(modifier_isEnabled(md, required_mode)) + if(mti->requiredDataMask) + mask = mti->requiredDataMask(ob, md); BLI_linklist_prepend(&dataMasks, (void *)mask); } diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 41ce23347a3..b5b2c07af9c 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -3182,7 +3182,7 @@ static void get_cpa_texture(DerivedMesh *dm, Material *ma, int face_index, float if(ma) for(m=0; mmtex[m]; - if(mtex && (ma->septex & (1<septex & (1<pmapto){ float def=mtex->def_var; float var=mtex->varfac; short blend=mtex->blendtype; @@ -3231,7 +3231,7 @@ void psys_get_texture(Object *ob, Material *ma, ParticleSystemModifierData *psmd if(ma) for(m=0; mmtex[m]; - if(mtex && (ma->septex & (1<septex & (1<pmapto){ float var=mtex->varfac; float def=mtex->def_var; short blend=mtex->blendtype; diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 31e246f66b9..6ac57934670 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -1762,7 +1762,10 @@ void reset_particle(ParticleData *pa, ParticleSystem *psys, ParticleSystemModifi where_is_object_time(ob,pa->time); /* get birth location from object */ - psys_particle_on_emitter(psmd,part->from,pa->num, pa->num_dmcache, pa->fuv,pa->foffset,loc,nor,utan,vtan,0,0); + if(part->tanfac!=0.0) + psys_particle_on_emitter(psmd,part->from,pa->num, pa->num_dmcache, pa->fuv,pa->foffset,loc,nor,utan,vtan,0,0); + else + psys_particle_on_emitter(psmd,part->from,pa->num, pa->num_dmcache, pa->fuv,pa->foffset,loc,nor,0,0,0,0); /* save local coordinates for later */ VECCOPY(tloc,loc); -- cgit v1.2.3 From 51fbc95e8c8699cd9ba2f7b1958df7270851af39 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Tue, 16 Jun 2009 00:52:21 +0000 Subject: RNA * Added icon to property and enum property items. The latter is responsible for the large number of files changed. * For RNA functions, added PROP_RNAPTR flag to ask for a PointerRNA as argument instead of a C pointer, instead of doing it implicitly with the AnyType type. * Material: properly wrap diffuse/specular param variables, and rename some things for consistency. * MaterialTextureSlot: added "enabled" property (ma->septex). * Image: make animated property editable. * Image Editor: make some things editable, notifiers, respect state. * Context: fix issue with screen not being set as ID. --- source/blender/blenkernel/intern/ipo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c index 8cbf25eaeed..e4c366dd3d7 100644 --- a/source/blender/blenkernel/intern/ipo.c +++ b/source/blender/blenkernel/intern/ipo.c @@ -545,7 +545,7 @@ static char *material_adrcodes_to_paths (int adrcode, int *array_index) return "ambient"; case MA_SPEC: - return "specularity"; + return "specular_reflection"; case MA_HARD: return "specular_hardness"; -- cgit v1.2.3 From f10541f7cfa13b3f2c92abea2c99c2901efbf91a Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Tue, 16 Jun 2009 01:08:39 +0000 Subject: UI * Added option for panel to be closed by default. * Added support for RNA property and enum icons in buttons. * Remove some deprecated RNA menu code. * Fix issue with newly created panels not being inserted in the right place. * Fix issue with 3-split layout not being divided correctly. * FIx issue with menu items not drawing correct using python UI. --- source/blender/blenkernel/BKE_screen.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h index 9b5d99f6ae6..750f4fba7e6 100644 --- a/source/blender/blenkernel/BKE_screen.h +++ b/source/blender/blenkernel/BKE_screen.h @@ -157,6 +157,8 @@ typedef struct PanelType { int space_type; int region_type; + int flag; + /* verify if the panel should draw or not */ int (*poll)(const struct bContext *, struct PanelType *); /* draw header (optional) */ -- cgit v1.2.3 From 2faf20c4b3ae1ca6c82dd2a942d2f2a580685436 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 16 Jun 2009 18:25:48 +0000 Subject: BGE Action Actuator setChannel() function was broken in a number of ways. * extract_pose_from_pose only checked one of the list items for NULL when looping over them yet its possible they are different sizes. * game_free_pose needed to be used rather then MEM_freeN, channels would never be freed leaking memory. * setChannel() would make a new pose that wasnt aligned with the existing pose, the lists are assumed aligned so when extracting the channels its unlikely this was ever useful. * Added getChannel() - returns pose loc/size/quat * Added option args for setChannel(channel, matrix) or setChannel(channel, loc, size, quat) --- source/blender/blenkernel/intern/action.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index e0afdec5e23..dea8b72bbfd 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -798,6 +798,7 @@ void calc_action_range(const bAction *act, float *start, float *end, int incl_hi /* Copy the data from the action-pose (src) into the pose */ /* both args are assumed to be valid */ /* exported to game engine */ +/* Note! this assumes both poses are aligned, this isnt always true when dealing with user poses */ void extract_pose_from_pose(bPose *pose, const bPose *src) { const bPoseChannel *schan; @@ -808,7 +809,7 @@ void extract_pose_from_pose(bPose *pose, const bPose *src) return; } - for (schan=src->chanbase.first; schan; schan=schan->next, pchan= pchan->next) { + for (schan=src->chanbase.first; (schan && pchan); schan=schan->next, pchan= pchan->next) { copy_pose_channel_data(pchan, schan); } } -- cgit v1.2.3 From a87bc73d321f5bddc17fb5c6332637738bfb7fa6 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 19 Jun 2009 04:45:56 +0000 Subject: NLA SoC: Transition Strips + Strip Adding Operators + Bugfixes == Transitions == Transition strips are now able to be created + evaluated. Transitions allow for interpolation between the endpoints of two adjacent strips in the same track (i.e. two strips which occur in the same track one after the other, but with a gap between them). - The current behaviour when only one endpoint affects some setting is non-optimal, since it appears somewhat inconsistently extend/replace values... - Transform code needs a few fixes still to deal with these == Strip Adding Operators == * New strips referencing Actions can be added using the Shift-A hotkey while in the strips-area. You must have a track selected first though. The new strip will get added, starting from the current frame, in the selected track(s) only if there is enough space to do so. Otherwise, the new strip gets added at the top of the stack in a new track. * New transition strips can be added with the Shift-T hotkey while in the strips area. You must have two adjacent strips selected for this to work. == New Backend Methods == * Recoded the strip/track adding API to be more flexible * Added a new method for testing whether F-Curve has any modifiers of with certain attributes. Will be used in a later bugfix... == Bugfixes == - Fixed bug with strip-blending which caused the blending modes to be useless. - NLA buttons now use proper poll callbacks instead of defining checks - Commented out missing operator in menus, silencing warnings in console - Removed obsolete/incorrect comments --- source/blender/blenkernel/BKE_fcurve.h | 2 + source/blender/blenkernel/BKE_nla.h | 2 + source/blender/blenkernel/intern/anim_sys.c | 156 ++++++++++++++++++++++++++-- source/blender/blenkernel/intern/fcurve.c | 36 +++++++ source/blender/blenkernel/intern/nla.c | 72 +++++++------ 5 files changed, 227 insertions(+), 41 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h index 7058b9d236a..af272e892f2 100644 --- a/source/blender/blenkernel/BKE_fcurve.h +++ b/source/blender/blenkernel/BKE_fcurve.h @@ -112,6 +112,8 @@ void fcurve_free_modifiers(struct FCurve *fcu); struct FModifier *fcurve_find_active_modifier(struct FCurve *fcu); void fcurve_set_active_modifier(struct FCurve *fcu, struct FModifier *fcm); +short fcurve_has_suitable_modifier(FCurve *fcu, int mtype, short acttype); + float evaluate_time_fmodifiers(ListBase *modifiers, struct FCurve *fcu, float cvalue, float evaltime); void evaluate_value_fmodifiers(ListBase *modifiers, struct FCurve *fcu, float *cvalue, float evaltime); diff --git a/source/blender/blenkernel/BKE_nla.h b/source/blender/blenkernel/BKE_nla.h index 078c1ba52bb..5200ca6d4d7 100644 --- a/source/blender/blenkernel/BKE_nla.h +++ b/source/blender/blenkernel/BKE_nla.h @@ -61,6 +61,8 @@ void BKE_nlatrack_solo_toggle(struct AnimData *adt, struct NlaTrack *nlt); short BKE_nlatrack_has_space(struct NlaTrack *nlt, float start, float end); void BKE_nlatrack_sort_strips(struct NlaTrack *nlt); +short BKE_nlatrack_add_strip(struct NlaTrack *nlt, struct NlaStrip *strip); + struct NlaStrip *BKE_nlastrip_find_active(struct NlaTrack *nlt); short BKE_nlastrip_within_bounds(struct NlaStrip *strip, float min, float max); diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index a864e3d4e87..2efb4f2b2d3 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -558,13 +558,20 @@ typedef struct NlaEvalStrip { short track_index; /* the index of the track within the list */ short strip_mode; /* which end of the strip are we looking at */ + + float strip_time; /* time at which which strip is being evaluated */ } NlaEvalStrip; /* NlaEvalStrip->strip_mode */ enum { + /* standard evaluation */ NES_TIME_BEFORE = -1, NES_TIME_WITHIN, NES_TIME_AFTER, + + /* transition-strip evaluations */ + NES_TIME_TRANSITION_START, + NES_TIME_TRANSITION_END, } eNlaEvalStrip_StripMode; @@ -583,10 +590,10 @@ typedef struct NlaEvalChannel { /* ---------------------- */ -/* non clipped mapping for strip-time <-> global time +/* non clipped mapping for strip-time <-> global time (for Action-Clips) * invert = convert action-strip time to global time */ -static float nlastrip_get_frame (NlaStrip *strip, float cframe, short invert) +static float nlastrip_get_frame_actionclip (NlaStrip *strip, float cframe, short invert) { float length, actlength, repeat, scale; @@ -603,8 +610,8 @@ static float nlastrip_get_frame (NlaStrip *strip, float cframe, short invert) if (IS_EQ(actlength, 0.0f)) actlength = 1.0f; /* length of strip */ - length = strip->end - strip->start; - if (IS_EQ(length, 0.0f)) length= actlength * scale * repeat; + length= actlength * scale * repeat; + if (IS_EQ(length, 0.0f)) length= strip->end - strip->start; /* reversed = play strip backwards */ if (strip->flag & NLASTRIP_FLAG_REVERSE) { @@ -623,6 +630,48 @@ static float nlastrip_get_frame (NlaStrip *strip, float cframe, short invert) } } +/* non clipped mapping for strip-time <-> global time (for Transitions) + * invert = convert action-strip time to global time + */ +static float nlastrip_get_frame_transition (NlaStrip *strip, float cframe, short invert) +{ + float length; + + /* length of strip */ + length= strip->end - strip->start; + + /* reversed = play strip backwards */ + if (strip->flag & NLASTRIP_FLAG_REVERSE) { + /* invert = convert within-strip-time to global time */ + if (invert) + return strip->end - (length * cframe); + else + return (strip->end - cframe) / length; + } + else { + /* invert = convert within-strip-time to global time */ + if (invert) + return (length * cframe) + strip->start; + else + return (cframe - strip->start) / length; + } +} + +/* non clipped mapping for strip-time <-> global time + * invert = convert action-strip time to global time + */ +static float nlastrip_get_frame (NlaStrip *strip, float cframe, short invert) +{ + switch (strip->type) { + case NLASTRIP_TYPE_TRANSITION: /* transition */ + return nlastrip_get_frame_transition(strip, cframe, invert); + + case NLASTRIP_TYPE_CLIP: /* action-clip (default) */ + default: + return nlastrip_get_frame_actionclip(strip, cframe, invert); + } +} + /* calculate influence of strip based for given frame based on blendin/out values */ static float nlastrip_get_influence (NlaStrip *strip, float cframe) { @@ -631,7 +680,6 @@ static float nlastrip_get_influence (NlaStrip *strip, float cframe) strip->blendout= (float)fabs(strip->blendout); /* result depends on where frame is in respect to blendin/out values */ - // the +0.0001 factors are to combat rounding errors if (IS_EQ(strip->blendin, 0)==0 && (cframe <= (strip->start + strip->blendin))) { /* there is some blend-in */ return (float)fabs(cframe - strip->start) / (strip->blendin); @@ -746,12 +794,13 @@ static void nlatrack_ctime_get_strip (ListBase *list, NlaTrack *nlt, short index * - negative influence is not supported yet... how would that be defined? */ // TODO: this sounds a bit hacky having a few isolated F-Curves stuck on some data it operates on... - // TODO: should we clamp the time to only be on the endpoints of the strip? nlastrip_evaluate_controls(estrip, ctime); if (estrip->influence <= 0.0f) // XXX is it useful to invert the strip? return; - /* check if strip has valid data to evaluate */ + /* check if strip has valid data to evaluate, + * and/or perform any additional type-specific actions + */ switch (estrip->type) { case NLASTRIP_TYPE_CLIP: /* clip must have some action to evaluate */ @@ -760,9 +809,12 @@ static void nlatrack_ctime_get_strip (ListBase *list, NlaTrack *nlt, short index break; case NLASTRIP_TYPE_TRANSITION: /* there must be strips to transition from and to (i.e. prev and next required) */ - // TODO: what happens about cross-track transitions? if (ELEM(NULL, estrip->prev, estrip->next)) return; + + /* evaluate controls for the relevant extents of the bordering strips... */ + nlastrip_evaluate_controls(estrip->prev, estrip->start); + nlastrip_evaluate_controls(estrip->next, estrip->end); break; } @@ -773,6 +825,7 @@ static void nlatrack_ctime_get_strip (ListBase *list, NlaTrack *nlt, short index nes->strip= estrip; nes->strip_mode= side; nes->track_index= index; + nes->strip_time= estrip->strip_time; BLI_addtail(list, nes); } @@ -847,6 +900,8 @@ static NlaEvalChannel *nlaevalchan_verify (PointerRNA *ptr, ListBase *channels, nec->prop= prop; nec->index= fcu->array_index; } + else + *newChan= 0; /* we can now return */ return nec; @@ -856,6 +911,7 @@ static NlaEvalChannel *nlaevalchan_verify (PointerRNA *ptr, ListBase *channels, static void nlaevalchan_accumulate (NlaEvalChannel *nec, NlaEvalStrip *nes, short newChan, float value) { NlaStrip *strip= nes->strip; + short blendmode= strip->blendmode; float inf= strip->influence; /* if channel is new, just store value regardless of blending factors, etc. */ @@ -863,13 +919,19 @@ static void nlaevalchan_accumulate (NlaEvalChannel *nec, NlaEvalStrip *nes, shor nec->value= value; return; } + + /* if this is being performed as part of transition evaluation, incorporate + * an additional weighting factor for the influence + */ + if (nes->strip_mode == NES_TIME_TRANSITION_END) + inf *= nes->strip_time; /* premultiply the value by the weighting factor */ if (IS_EQ(inf, 0)) return; value *= inf; /* perform blending */ - switch (strip->blendmode) { + switch (blendmode) { case NLASTRIP_MODE_ADD: /* simply add the scaled value on to the stack */ nec->value += value; @@ -938,8 +1000,80 @@ static void nlastrip_evaluate_actionclip (PointerRNA *ptr, ListBase *channels, N } } +/* evaluate transition strip */ +static void nlastrip_evaluate_transition (PointerRNA *ptr, ListBase *channels, NlaEvalStrip *nes) +{ + ListBase tmp_channels = {NULL, NULL}; + NlaEvalChannel *nec, *necn, *necd; + NlaEvalStrip tmp_nes; + NlaStrip *s1, *s2; + + /* get the two strips to operate on + * - we use the endpoints of the strips directly flanking our strip + * using these as the endpoints of the transition (destination and source) + * - these should have already been determined to be valid... + * - if this strip is being played in reverse, we need to swap these endpoints + * otherwise they will be interpolated wrong + */ + if (nes->strip->flag & NLASTRIP_FLAG_REVERSE) { + s1= nes->strip->next; + s2= nes->strip->prev; + } + else { + s1= nes->strip->prev; + s2= nes->strip->next; + } + + /* prepare template for 'evaluation strip' + * - based on the transition strip's evaluation strip data + * - strip_mode is NES_TIME_TRANSITION_* based on which endpoint + * - strip_time is the 'normalised' (i.e. in-strip) time for evaluation, + * which doubles up as an additional weighting factor for the strip influences + * which allows us to appear to be 'interpolating' between the two extremes + */ + tmp_nes= *nes; + + /* evaluate these strips into a temp-buffer (tmp_channels) */ + /* first strip */ + tmp_nes.strip_mode= NES_TIME_TRANSITION_START; + tmp_nes.strip= s1; + nlastrip_evaluate_actionclip(ptr, &tmp_channels, &tmp_nes); + + /* second strip */ + tmp_nes.strip_mode= NES_TIME_TRANSITION_END; + tmp_nes.strip= s2; + nlastrip_evaluate_actionclip(ptr, &tmp_channels, &tmp_nes); + + + /* optimise - abort if no channels */ + if (tmp_channels.first == NULL) + return; + + + /* accumulate results in tmp_channels buffer to the accumulation buffer */ + for (nec= tmp_channels.first; nec; nec= necn) { + /* get pointer to next channel in case we remove the current channel from the temp-buffer */ + necn= nec->next; + + /* try to find an existing matching channel for this setting in the accumulation buffer */ + necd= nlaevalchan_find_match(channels, &nec->ptr, nec->prop, nec->index); + + /* if there was a matching channel already in the buffer, accumulate to it, + * otherwise, add the current channel to the buffer for efficiency + */ + if (necd) + nlaevalchan_accumulate(necd, nes, 0, nec->value); + else { + BLI_remlink(&tmp_channels, nec); + BLI_addtail(channels, nec); + } + } + + /* free temp-channels that haven't been assimilated into the buffer */ + BLI_freelistN(&tmp_channels); +} + /* evaluates the given evaluation strip */ -// TODO: only evaluate here, but flush in one go using the accumulated channels at end... static void nlastrip_evaluate (PointerRNA *ptr, ListBase *channels, NlaEvalStrip *nes) { /* actions to take depend on the type of strip */ @@ -948,7 +1082,7 @@ static void nlastrip_evaluate (PointerRNA *ptr, ListBase *channels, NlaEvalStrip nlastrip_evaluate_actionclip(ptr, channels, nes); break; case NLASTRIP_TYPE_TRANSITION: /* transition */ - // XXX code this... + nlastrip_evaluate_transition(ptr, channels, nes); break; } } diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index 5820761234c..d8b5135a1b1 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -2242,6 +2242,42 @@ void fcurve_set_active_modifier (FCurve *fcu, FModifier *fcm) fcm->flag |= FMODIFIER_FLAG_ACTIVE; } +/* Do we have any modifiers which match certain criteria + * - mtype - type of modifier (if 0, doesn't matter) + * - acttype - type of action to perform (if -1, doesn't matter) + */ +short fcurve_has_suitable_modifier (FCurve *fcu, int mtype, short acttype) +{ + FModifier *fcm; + + /* if there are no specific filtering criteria, just skip */ + if ((mtype == 0) && (acttype == 0)) + return (fcu && fcu->modifiers.first); + + /* sanity checks */ + if ELEM(NULL, fcu, fcu->modifiers.first) + return 0; + + /* find the first mdifier fitting these criteria */ + for (fcm= fcu->modifiers.first; fcm; fcm= fcm->next) { + FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm); + short mOk=1, aOk=1; /* by default 1, so that when only one test, won't fail */ + + /* check if applicable ones are fullfilled */ + if (mtype) + mOk= (fcm->type == mtype); + if (acttype > -1) + aOk= (fmi->acttype == acttype); + + /* if both are ok, we've found a hit */ + if (mOk && aOk) + return 1; + } + + /* no matches */ + return 0; +} + /* Evaluation API --------------------------- */ /* evaluate time modifications imposed by some F-Curve Modifiers diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index cef14128032..0684d943754 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -293,9 +293,8 @@ NlaStrip *add_nlastrip (bAction *act) /* Add new NLA-strip to the top of the NLA stack - i.e. into the last track if space, or a new one otherwise */ NlaStrip *add_nlastrip_to_stack (AnimData *adt, bAction *act) { - NlaStrip *strip, *ns; + NlaStrip *strip; NlaTrack *nlt; - short not_added = 1; /* sanity checks */ if ELEM(NULL, adt, act) @@ -306,36 +305,15 @@ NlaStrip *add_nlastrip_to_stack (AnimData *adt, bAction *act) if (strip == NULL) return NULL; - /* check if the last NLA-track (if it exists) has any space for this strip: - * - if so, add this strip to that track - */ - if ( (adt->nla_tracks.last == NULL) || - (BKE_nlatrack_has_space(adt->nla_tracks.last, strip->start, strip->end)==0) ) - { - /* no space, so add to a new track... */ + /* firstly try adding strip to last track, but if that fails, add to a new track */ + if (BKE_nlatrack_add_strip(adt->nla_tracks.last, strip) == 0) { + /* trying to add to the last track failed (no track or no space), + * so add a new track to the stack, and add to that... + */ nlt= add_nlatrack(adt, NULL); - } - else - { - /* there's some space, so add to this track... */ - nlt= adt->nla_tracks.last; + BKE_nlatrack_add_strip(nlt, strip); } - /* find the right place to add the strip to the nominated track */ - for (ns= nlt->strips.first; ns; ns= ns->next) { - /* if current strip occurs after the new strip, add it before */ - if (ns->start > strip->end) { - BLI_insertlinkbefore(&nlt->strips, ns, strip); - not_added= 0; - break; - } - } - if (not_added) { - /* just add to the end of the list of the strips then... */ - BLI_addtail(&nlt->strips, strip); - } - - /* returns the strip added */ return strip; } @@ -490,6 +468,40 @@ void BKE_nlatrack_sort_strips (NlaTrack *nlt) nlt->strips.last= tmp.last; } +/* Add the given NLA-Strip to the given NLA-Track, assuming that it + * isn't currently attached to another one + */ +short BKE_nlatrack_add_strip (NlaTrack *nlt, NlaStrip *strip) +{ + NlaStrip *ns; + short not_added = 1; + + /* sanity checks */ + if ELEM(NULL, nlt, strip) + return 0; + + /* check if any space to add */ + if (BKE_nlatrack_has_space(nlt, strip->start, strip->end)==0) + return 0; + + /* find the right place to add the strip to the nominated track */ + for (ns= nlt->strips.first; ns; ns= ns->next) { + /* if current strip occurs after the new strip, add it before */ + if (ns->start > strip->end) { + BLI_insertlinkbefore(&nlt->strips, ns, strip); + not_added= 0; + break; + } + } + if (not_added) { + /* just add to the end of the list of the strips then... */ + BLI_addtail(&nlt->strips, strip); + } + + /* added... */ + return 1; +} + /* NLA Strips -------------------------------------- */ /* Find the active NLA-strip within the given track */ @@ -571,7 +583,7 @@ short nlastrip_is_first (AnimData *adt, NlaStrip *strip) /* should be first now */ return 1; } - + /* Tools ------------------------------------------- */ /* For the given AnimData block, add the active action to the NLA -- cgit v1.2.3 From 8ffb1dacad032e42830debe9b51fdd961def354f Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 19 Jun 2009 04:58:40 +0000 Subject: NLA SoC: Bugfix for Deleting Keyframes When an F-Curve doesn't contain any keyframes anymore but it still exists, the F-Curve's value is not recalculated and flushed anymore if the F-Curve's value will not change. That is, if the F-Curve doesn't have any other data, i.e. drivers or generator-modifiers, which would still change its value, it wouldn't be recalculated to have a value of zero. This solves the problem of deleting all scale keyframes, whereby objects/bones would appear to 'vanish' --- source/blender/blenkernel/BKE_fcurve.h | 2 +- source/blender/blenkernel/intern/fcurve.c | 12 +++++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h index af272e892f2..5c77e3c2ae4 100644 --- a/source/blender/blenkernel/BKE_fcurve.h +++ b/source/blender/blenkernel/BKE_fcurve.h @@ -112,7 +112,7 @@ void fcurve_free_modifiers(struct FCurve *fcu); struct FModifier *fcurve_find_active_modifier(struct FCurve *fcu); void fcurve_set_active_modifier(struct FCurve *fcu, struct FModifier *fcm); -short fcurve_has_suitable_modifier(FCurve *fcu, int mtype, short acttype); +short fcurve_has_suitable_modifier(struct FCurve *fcu, int mtype, short acttype); float evaluate_time_fmodifiers(ListBase *modifiers, struct FCurve *fcu, float cvalue, float evaltime); void evaluate_value_fmodifiers(ListBase *modifiers, struct FCurve *fcu, float *cvalue, float evaltime); diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index d8b5135a1b1..856930e5a44 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -2415,10 +2415,16 @@ float evaluate_fcurve (FCurve *fcu, float evaltime) } /* Calculate the value of the given F-Curve at the given frame, and set its curval */ -// TODO: will this be necessary? void calculate_fcurve (FCurve *fcu, float ctime) { - /* calculate and set curval (evaluates driver too) */ - fcu->curval= evaluate_fcurve(fcu, ctime); + /* only calculate + set curval (overriding the existing value) if curve has + * any data which warrants this... + */ + if ( (fcu->totvert) || (fcu->driver && !(fcu->driver->flag & DRIVER_FLAG_INVALID)) || + fcurve_has_suitable_modifier(fcu, 0, FMI_TYPE_GENERATE_CURVE) ) + { + /* calculate and set curval (evaluates driver too if necessary) */ + fcu->curval= evaluate_fcurve(fcu, ctime); + } } -- cgit v1.2.3 From 42e60acce669a425a3ce3a588a2bd649cd6963eb Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 19 Jun 2009 11:17:56 +0000 Subject: Animato - Conversions Bugfix Object actions are now converted before object ipo's so that if both of them exist, the Action can still preserve its name. --- source/blender/blenkernel/intern/ipo.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c index e4c366dd3d7..a6aac096814 100644 --- a/source/blender/blenkernel/intern/ipo.c +++ b/source/blender/blenkernel/intern/ipo.c @@ -1515,14 +1515,7 @@ void do_versions_ipos_to_animato(Main *main) /* Add AnimData block */ adt= BKE_id_add_animdata(id); - /* IPO first */ - if (ob->ipo) { - ipo_to_animdata(id, ob->ipo, NULL, NULL); - ob->ipo->id.us--; - ob->ipo= NULL; - } - - /* now Action */ + /* Action first - so that Action name get conserved */ if (ob->action) { action_to_animdata(id, ob->action); @@ -1533,6 +1526,13 @@ void do_versions_ipos_to_animato(Main *main) } } + /* IPO second... */ + if (ob->ipo) { + ipo_to_animdata(id, ob->ipo, NULL, NULL); + ob->ipo->id.us--; + ob->ipo= NULL; + } + /* finally NLA */ // XXX todo... for now, new NLA code not hooked up yet, so keep old stuff (but not for too long!) } -- cgit v1.2.3 From c3b8db4833fe561ce8803af1619a4f1eb5f0c3b6 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 19 Jun 2009 16:27:01 +0000 Subject: BGE: allow action blending by bringing back blend_poses() as game_blend_poses, the new animation system doesnt use it but doesnt have a replacement function so it can be kept for the BGE only. --- source/blender/blenkernel/BKE_action.h | 2 +- source/blender/blenkernel/intern/action.c | 140 +++++++++++++++--------------- 2 files changed, 72 insertions(+), 70 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h index 67eb2ed58bf..f0796697670 100644 --- a/source/blender/blenkernel/BKE_action.h +++ b/source/blender/blenkernel/BKE_action.h @@ -137,7 +137,7 @@ void framechange_poses_clear_unkeyed(void); void what_does_obaction(struct Scene *scene, struct Object *ob, struct Object *workob, struct bPose *pose, struct bAction *act, char groupname[], float cframe); /* exported for game engine */ -void blend_poses(struct bPose *dst, struct bPose *src, float srcweight, short mode); +void game_blend_poses(struct bPose *dst, struct bPose *src, float srcweight/*, short mode*/); /* was blend_poses */ void extract_pose_from_pose(struct bPose *pose, const struct bPose *src); /* for proxy */ diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index fb1b2e9cf70..f7e15cef4c4 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -581,6 +581,77 @@ void game_copy_pose(bPose **dst, bPose *src) *dst=out; } + +/* Only allowed for Poses with identical channels */ +void game_blend_poses(bPose *dst, bPose *src, float srcweight/*, short mode*/) +{ + short mode= ACTSTRIPMODE_BLEND; + + bPoseChannel *dchan; + const bPoseChannel *schan; + bConstraint *dcon, *scon; + float dstweight; + int i; + + switch (mode){ + case ACTSTRIPMODE_BLEND: + dstweight = 1.0F - srcweight; + break; + case ACTSTRIPMODE_ADD: + dstweight = 1.0F; + break; + default : + dstweight = 1.0F; + } + + schan= src->chanbase.first; + for (dchan = dst->chanbase.first; dchan; dchan=dchan->next, schan= schan->next){ + if (schan->flag & (POSE_ROT|POSE_LOC|POSE_SIZE)) { + /* replaced quat->matrix->quat conversion with decent quaternion interpol (ton) */ + + /* Do the transformation blend */ + if (schan->flag & POSE_ROT) { + /* quat interpolation done separate */ + if (schan->rotmode == PCHAN_ROT_QUAT) { + float dquat[4], squat[4]; + + QUATCOPY(dquat, dchan->quat); + QUATCOPY(squat, schan->quat); + if (mode==ACTSTRIPMODE_BLEND) + QuatInterpol(dchan->quat, dquat, squat, srcweight); + else { + QuatMulFac(squat, srcweight); + QuatMul(dchan->quat, dquat, squat); + } + + NormalQuat(dchan->quat); + } + } + + for (i=0; i<3; i++) { + /* blending for loc and scale are pretty self-explanatory... */ + if (schan->flag & POSE_LOC) + dchan->loc[i] = (dchan->loc[i]*dstweight) + (schan->loc[i]*srcweight); + if (schan->flag & POSE_SIZE) + dchan->size[i] = 1.0f + ((dchan->size[i]-1.0f)*dstweight) + ((schan->size[i]-1.0f)*srcweight); + + /* euler-rotation interpolation done here instead... */ + // FIXME: are these results decent? + if ((schan->flag & POSE_ROT) && (schan->rotmode)) + dchan->eul[i] = (dchan->eul[i]*dstweight) + (schan->eul[i]*srcweight); + } + dchan->flag |= schan->flag; + } + for(dcon= dchan->constraints.first, scon= schan->constraints.first; dcon && scon; dcon= dcon->next, scon= scon->next) { + /* no 'add' option for constraint blending */ + dcon->enforce= dcon->enforce*(1.0f-srcweight) + scon->enforce*srcweight; + } + } + + /* this pose is now in src time */ + dst->ctime= src->ctime; +} + void game_free_pose(bPose *pose) { if (pose) { @@ -1039,75 +1110,6 @@ static void blend_pose_offset_bone(bActionStrip *strip, bPose *dst, bPose *src, VecAddf(dst->cyclic_offset, dst->cyclic_offset, src->cyclic_offset); } - -/* Only allowed for Poses with identical channels */ -void blend_poses(bPose *dst, bPose *src, float srcweight, short mode) -{ - bPoseChannel *dchan; - const bPoseChannel *schan; - bConstraint *dcon, *scon; - float dstweight; - int i; - - switch (mode){ - case ACTSTRIPMODE_BLEND: - dstweight = 1.0F - srcweight; - break; - case ACTSTRIPMODE_ADD: - dstweight = 1.0F; - break; - default : - dstweight = 1.0F; - } - - schan= src->chanbase.first; - for (dchan = dst->chanbase.first; dchan; dchan=dchan->next, schan= schan->next){ - if (schan->flag & (POSE_ROT|POSE_LOC|POSE_SIZE)) { - /* replaced quat->matrix->quat conversion with decent quaternion interpol (ton) */ - - /* Do the transformation blend */ - if (schan->flag & POSE_ROT) { - /* quat interpolation done separate */ - if (schan->rotmode == PCHAN_ROT_QUAT) { - float dquat[4], squat[4]; - - QUATCOPY(dquat, dchan->quat); - QUATCOPY(squat, schan->quat); - if (mode==ACTSTRIPMODE_BLEND) - QuatInterpol(dchan->quat, dquat, squat, srcweight); - else { - QuatMulFac(squat, srcweight); - QuatMul(dchan->quat, dquat, squat); - } - - NormalQuat(dchan->quat); - } - } - - for (i=0; i<3; i++) { - /* blending for loc and scale are pretty self-explanatory... */ - if (schan->flag & POSE_LOC) - dchan->loc[i] = (dchan->loc[i]*dstweight) + (schan->loc[i]*srcweight); - if (schan->flag & POSE_SIZE) - dchan->size[i] = 1.0f + ((dchan->size[i]-1.0f)*dstweight) + ((schan->size[i]-1.0f)*srcweight); - - /* euler-rotation interpolation done here instead... */ - // FIXME: are these results decent? - if ((schan->flag & POSE_ROT) && (schan->rotmode)) - dchan->eul[i] = (dchan->eul[i]*dstweight) + (schan->eul[i]*srcweight); - } - dchan->flag |= schan->flag; - } - for(dcon= dchan->constraints.first, scon= schan->constraints.first; dcon && scon; dcon= dcon->next, scon= scon->next) { - /* no 'add' option for constraint blending */ - dcon->enforce= dcon->enforce*(1.0f-srcweight) + scon->enforce*srcweight; - } - } - - /* this pose is now in src time */ - dst->ctime= src->ctime; -} - typedef struct NlaIpoChannel { struct NlaIpoChannel *next, *prev; float val; -- cgit v1.2.3 From aa0aac706e4381624482978110a54b5959414d14 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Fri, 19 Jun 2009 23:05:21 +0000 Subject: 2.5 * Optimized RNA property lookups and path resolving, still can be much better, but now the 1000 IPO example on bf-taskforce25 runs at reasonable speed. * Also an optimization in the depsgraph when dealing with many objects, this was actually also a bottleneck here. --- source/blender/blenkernel/BKE_depsgraph.h | 1 + source/blender/blenkernel/depsgraph_private.h | 2 ++ source/blender/blenkernel/intern/depsgraph.c | 41 ++++++++++++++++----------- 3 files changed, 28 insertions(+), 16 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_depsgraph.h b/source/blender/blenkernel/BKE_depsgraph.h index b86a58780dc..70b6c1d13f4 100644 --- a/source/blender/blenkernel/BKE_depsgraph.h +++ b/source/blender/blenkernel/BKE_depsgraph.h @@ -36,6 +36,7 @@ struct Scene; struct DagNodeQueue; struct DagForest; struct DagNode; +struct GHash; /* **** DAG relation types *** */ diff --git a/source/blender/blenkernel/depsgraph_private.h b/source/blender/blenkernel/depsgraph_private.h index 78717393baf..47e33c0e81e 100644 --- a/source/blender/blenkernel/depsgraph_private.h +++ b/source/blender/blenkernel/depsgraph_private.h @@ -65,6 +65,7 @@ typedef struct DagNode void * first_ancestor; int ancestor_count; int lay; // accumulated layers of its relations + itself + int scelay; // layers due to being in scene int lasttime; // if lasttime != DagForest->time, this node was not evaluated yet for flushing int BFS_dist; // BFS distance int DFS_dist; // DFS distance @@ -93,6 +94,7 @@ typedef struct DagNodeQueue typedef struct DagForest { ListBase DagNode; + struct GHash *nodeHash; int numNodes; int is_acyclic; int time; // for flushing/tagging, compare with node->lasttime diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index dfe3b7ea279..8bb34bde122 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -61,6 +61,8 @@ #include "DNA_view2d_types.h" #include "DNA_view3d_types.h" +#include "BLI_ghash.h" + #include "BKE_action.h" #include "BKE_effect.h" #include "BKE_global.h" @@ -754,6 +756,9 @@ void free_forest(DagForest *Dag) itN = itN->next; MEM_freeN(tempN); } + + BLI_ghash_free(Dag->nodeHash, NULL, NULL); + Dag->nodeHash= NULL; Dag->DagNode.first = NULL; Dag->DagNode.last = NULL; Dag->numNodes = 0; @@ -762,13 +767,9 @@ void free_forest(DagForest *Dag) DagNode * dag_find_node (DagForest *forest,void * fob) { - DagNode *node = forest->DagNode.first; - - while (node) { - if (node->ob == fob) - return node; - node = node->next; - } + if(forest->nodeHash) + return BLI_ghash_lookup(forest->nodeHash, fob); + return NULL; } @@ -794,7 +795,12 @@ DagNode * dag_add_node (DagForest *forest, void * fob) forest->DagNode.first = node; forest->numNodes = 1; } + + if(!forest->nodeHash) + forest->nodeHash= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp); + BLI_ghash_insert(forest->nodeHash, fob, node); } + return node; } @@ -1805,17 +1811,10 @@ static void flush_update_node(DagNode *node, unsigned int layer, int curtime) /* node was checked to have lasttime != curtime , and is of type ID_OB */ static unsigned int flush_layer_node(Scene *sce, DagNode *node, int curtime) { - Base *base; DagAdjList *itA; node->lasttime= curtime; - node->lay= 0; - for(base= sce->base.first; base; base= base->next) { - if(node->ob == base->object) { - node->lay= ((Object *)node->ob)->lay; - break; - } - } + node->lay= node->scelay; for(itA = node->child; itA; itA= itA->next) { if(itA->node->type==ID_OB) { @@ -1860,9 +1859,10 @@ static void flush_pointcache_reset(DagNode *node, int curtime, int reset) /* flushes all recalc flags in objects down the dependency tree */ void DAG_scene_flush_update(Scene *sce, unsigned int lay, int time) { - DagNode *firstnode; + DagNode *firstnode, *node; DagAdjList *itA; Object *ob; + Base *base; int lasttime; if(sce->theDag==NULL) { @@ -1879,6 +1879,15 @@ void DAG_scene_flush_update(Scene *sce, unsigned int lay, int time) sce->theDag->time++; // so we know which nodes were accessed lasttime= sce->theDag->time; + + for(base= sce->base.first; base; base= base->next) { + node= dag_get_node(sce->theDag, base->object); + if(node) + node->scelay= base->object->lay; + else + node->scelay= 0; + } + for(itA = firstnode->child; itA; itA= itA->next) if(itA->node->lasttime!=lasttime && itA->node->type==ID_OB) flush_layer_node(sce, itA->node, lasttime); -- cgit v1.2.3 From 7785ead4eb64f9702d7a59060e73b3e121e674a7 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 20 Jun 2009 02:44:57 +0000 Subject: ObColor wasnt converted into an RNA string. Updated Mathutils.Vector/Euler/Quaternion/Matrix so these are types rather then module methods, each type now has a tp_new function, matching python builtins float/int/str. Also cleaned up float conversion and arg passing. Changed buttons_objects.py... if ob in groups.objects: # no longer works if ob.name in groups.objects: # is the new syntax ...its more dict like and a lot faster (avoids python iterating over each item and comparing each, use a single rna lookup instead). --- source/blender/blenkernel/intern/ipo.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c index a6aac096814..54618813a0b 100644 --- a/source/blender/blenkernel/intern/ipo.c +++ b/source/blender/blenkernel/intern/ipo.c @@ -235,17 +235,15 @@ static char *ob_adrcodes_to_paths (int adrcode, int *array_index) *array_index= 1; return "delta_scale"; case OB_DSIZE_Z: *array_index= 2; return "delta_scale"; - -#if 0 - case OB_COL_R: - poin= &(ob->col[0]); break; + case OB_COL_R: + *array_index= 0; return "color"; case OB_COL_G: - poin= &(ob->col[1]); break; + *array_index= 1; return "color"; case OB_COL_B: - poin= &(ob->col[2]); break; + *array_index= 2; return "color"; case OB_COL_A: - poin= &(ob->col[3]); break; - + *array_index= 3; return "color"; +#if 0 case OB_PD_FSTR: if (ob->pd) poin= &(ob->pd->f_strength); break; -- cgit v1.2.3 From 6394ee9e8143988b2a0f9316fb7bca5dc78e6e53 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sat, 20 Jun 2009 04:02:49 +0000 Subject: NLA SoC: Drawing + Editing Fixes * Strips using the same action as the 'tweaking action' now get the error flag cleared after tweakmode is exited. (These strips draw with red shading) * The direction in which strips get played (as a result of the 'reversed' option) now gets indicated on strips by the direction of the arrow text printed on each strip * The active strip flag is now cleared after duplicating/splitting strips. --- source/blender/blenkernel/intern/nla.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index 0684d943754..1ce6d9f98c7 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -648,7 +648,6 @@ short BKE_nla_tweakmode_enter (AnimData *adt) /* if block is already in tweakmode, just leave, but we should report * that this block is in tweakmode (as our returncode) */ - // FIXME: hopefully the flag is correct! if (adt->flag & ADT_NLA_EDIT_ON) return 1; @@ -707,6 +706,7 @@ short BKE_nla_tweakmode_enter (AnimData *adt) /* Exit tweakmode for this AnimData block */ void BKE_nla_tweakmode_exit (AnimData *adt) { + NlaStrip *strip; NlaTrack *nlt; /* verify that data is valid */ @@ -719,9 +719,15 @@ void BKE_nla_tweakmode_exit (AnimData *adt) // TODO: need to sync the user-strip with the new state of the action! - /* for all NLA-tracks, clear the 'disabled' flag */ - for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) + /* for all NLA-tracks, clear the 'disabled' flag + * for all NLA-strips, clear the 'tweak-user' flag + */ + for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) { nlt->flag &= ~NLATRACK_DISABLED; + + for (strip= nlt->strips.first; strip; strip= strip->next) + strip->flag &= ~NLASTRIP_FLAG_TWEAKUSER; + } /* handle AnimData level changes: * - 'temporary' active action needs its usercount decreased, since we're removing this reference -- cgit v1.2.3 From ef7860ed9a68e3b92346697028ef0bdd9d21932f Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sat, 20 Jun 2009 09:36:55 +0000 Subject: NLA SoC: Conversions for old NLA-data to the new system Old NLA-data now gets mostly ported converted over to the new system, with strips and their respective Actions being handled correctly in the test cases I've got. The conversion procedure now tries to fit multiple strips into since tracks as it is assumed that quite a few old setups tried to do. However, some old setups may be adversely affected by this (i.e. if they depend on a certain order of holding adds for example). For now, there are no complete replacements for the NLA-Modifier/Auto-Walking stuff yet, so that info is currently just ignored (but correctly freed). The current plan here is to get Armature-level pose-offset system + F-Modifiers where appropriate. This should be one of the major causes of file breakage now... Also, I've yet to restore some patching for group instancing NLA stuff, since more trickery here is required. This is probably the second major cause of file breakage... --- source/blender/blenkernel/intern/ipo.c | 111 +++++++++++++++++++++++++++++++-- 1 file changed, 107 insertions(+), 4 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c index 54618813a0b..5642e63326f 100644 --- a/source/blender/blenkernel/intern/ipo.c +++ b/source/blender/blenkernel/intern/ipo.c @@ -58,6 +58,7 @@ #include "DNA_key_types.h" #include "DNA_material_types.h" #include "DNA_mesh_types.h" +#include "DNA_nla_types.h" #include "DNA_object_types.h" #include "DNA_object_force.h" #include "DNA_particle_types.h" @@ -85,6 +86,7 @@ #include "BKE_library.h" #include "BKE_main.h" #include "BKE_mesh.h" +#include "BKE_nla.h" #include "BKE_object.h" @@ -1463,6 +1465,87 @@ static void action_to_animdata (ID *id, bAction *act) action_to_animato(act, &adt->action->groups, &adt->action->curves, &adt->drivers); } +/* ------------------------- */ + +// TODO: +// - NLA group duplicators info +// - NLA curve/stride modifiers... + +/* Convert NLA-Strip to new system */ +static void nlastrips_to_animdata (ID *id, ListBase *strips) +{ + AnimData *adt= BKE_animdata_from_id(id); + NlaTrack *nlt = NULL; + NlaStrip *strip; + bActionStrip *as, *asn; + + /* for each one of the original strips, convert to a new strip and free the old... */ + for (as= strips->first; as; as= asn) { + asn= as->next; + + /* this old strip is only worth something if it had an action... */ + if (as->act) { + /* convert Action data (if not yet converted), storing the results in the same Action */ + action_to_animato(as->act, &as->act->groups, &as->act->curves, &adt->drivers); + + /* create a new-style NLA-strip which references this Action, then copy over relevant settings */ + { + /* init a new strip, and assign the action to it + * - no need to muck around with the user-counts, since this is just + * passing over the ref to the new owner, not creating an additional ref + */ + strip= MEM_callocN(sizeof(NlaStrip), "NlaStrip"); + strip->act= as->act; + + /* endpoints */ + strip->start= as->start; + strip->end= as->end; + strip->actstart= as->actstart; + strip->actend= as->actend; + + /* action reuse */ + strip->repeat= as->repeat; + strip->scale= as->scale; + if (as->flag & ACTSTRIP_LOCK_ACTION) strip->flag |= NLASTRIP_FLAG_SYNC_LENGTH; + + /* blending */ + strip->blendin= as->blendin; + strip->blendout= as->blendout; + strip->blendmode= (as->mode==ACTSTRIPMODE_ADD) ? NLASTRIP_MODE_ADD : NLASTRIP_MODE_BLEND; + if (as->flag & ACTSTRIP_AUTO_BLENDS) strip->flag |= NLASTRIP_FLAG_AUTO_BLENDS; + + /* assorted setting flags */ + if (as->flag & ACTSTRIP_SELECT) strip->flag |= NLASTRIP_FLAG_SELECT; + if (as->flag & ACTSTRIP_ACTIVE) strip->flag |= NLASTRIP_FLAG_ACTIVE; + + if (as->flag & ACTSTRIP_MUTE) strip->flag |= NLASTRIP_FLAG_MUTED; + if (as->flag & ACTSTRIP_REVERSE) strip->flag |= NLASTRIP_FLAG_REVERSE; + + /* by default, we now always extrapolate, while in the past this was optional */ + if ((as->flag & ACTSTRIP_HOLDLASTFRAME)==0) + strip->extendmode= NLASTRIP_EXTEND_NOTHING; + } + + /* try to add this strip to the current NLA-Track (i.e. the 'last' one on the stack atm) */ + if (BKE_nlatrack_add_strip(nlt, strip) == 0) { + /* trying to add to the current failed (no space), + * so add a new track to the stack, and add to that... + */ + nlt= add_nlatrack(adt, NULL); + BKE_nlatrack_add_strip(nlt, strip); + } + } + + /* modifiers */ + // FIXME: for now, we just free them... + if (as->modifiers.first) + BLI_freelistN(&as->modifiers); + + /* free the old strip */ + BLI_freelinkN(strips, as); + } +} + /* *************************************************** */ /* External API - Only Called from do_versions() */ @@ -1509,7 +1592,30 @@ void do_versions_ipos_to_animato(Main *main) if (G.f & G_DEBUG) printf("\tconverting ob %s \n", id->name+2); /* check if object has any animation data */ - if ((ob->ipo) || (ob->action) || (ob->nlastrips.first)) { + if (ob->nlastrips.first) { + /* Add AnimData block */ + adt= BKE_id_add_animdata(id); + + /* IPO first to take into any non-NLA'd Object Animation */ + if (ob->ipo) { + ipo_to_animdata(id, ob->ipo, NULL, NULL); + + ob->ipo->id.us--; + ob->ipo= NULL; + } + + /* Action is skipped since it'll be used by some strip in the NLA anyway, + * causing errors with evaluation in the new evaluation pipeline + */ + if (ob->action) { + ob->action->id.us--; + ob->action= NULL; + } + + /* finally NLA */ + nlastrips_to_animdata(id, &ob->nlastrips); + } + else if ((ob->ipo) || (ob->action)) { /* Add AnimData block */ adt= BKE_id_add_animdata(id); @@ -1530,9 +1636,6 @@ void do_versions_ipos_to_animato(Main *main) ob->ipo->id.us--; ob->ipo= NULL; } - - /* finally NLA */ - // XXX todo... for now, new NLA code not hooked up yet, so keep old stuff (but not for too long!) } /* check PoseChannels for constraints with local data */ -- cgit v1.2.3 From 6ff4a7229f316548046ab5593070b082cc1a4a7a Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sat, 20 Jun 2009 11:44:56 +0000 Subject: NLA SoC: Conversion fixes - Curve 'Speed' Curves + Constraints These fixes get the 'pathJumper.blend' file from our testing suite workable in 2.5 (with a few minor tweaks still needed *) Changes required: - Added a 'ctime' var to curve structs for storing the value that used to be obtained by specially evaluating the 'speed' curve when evaluating objects parented to the curve. This can now be animated as a 'proper' var as per normal. - Added a special hack for detecting constraint blocks, as the old method resulted in paths for Objects instead... (*) Issues: - Unfortunately, the paths still don't work out of the box. For some reason, the constraint names in the paths are spelt incorrectly - "Ar" and "Br" instead of "Ap" and "Bp". I'm not sure where this problem is coming from, but changing the paths manually in the Datablocks viewer fixes this error... - I noticed that in the buttons view, only 1st of the constraints gets shown. This seems a bit like some of the intermittent problems I've had with some arrays/lists not expanding properly in Datablocks view. --- source/blender/blenkernel/intern/anim_sys.c | 14 +++++++++++++- source/blender/blenkernel/intern/ipo.c | 11 +++++++++-- source/blender/blenkernel/intern/object.c | 16 ++++++++-------- 3 files changed, 30 insertions(+), 11 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 2efb4f2b2d3..7a6706b7c5a 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -1341,10 +1341,22 @@ void BKE_animsys_evaluate_all_animation (Main *main, float ctime) EVAL_ANIM_IDS(main->camera.first, ADT_RECALC_ANIM); /* shapekeys */ + // TODO: we probably need the same hack as for curves (ctime-hack) EVAL_ANIM_IDS(main->key.first, ADT_RECALC_ANIM); /* curves */ - // TODO... + /* we need to perform a special hack here to ensure that the ctime + * value of the curve gets set in case there's no animation for that + * - it needs to be set before animation is evaluated just so that + * animation can successfully override... + */ + for (id= main->curve.first; id; id= id->next) { + AnimData *adt= BKE_animdata_from_id(id); + Curve *cu= (Curve *)id; + + cu->ctime= ctime; + BKE_animsys_evaluate_animdata(id, adt, ctime, ADT_RECALC_ANIM); + } /* meshes */ // TODO... diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c index 5642e63326f..968a0e68fb9 100644 --- a/source/blender/blenkernel/intern/ipo.c +++ b/source/blender/blenkernel/intern/ipo.c @@ -827,6 +827,10 @@ char *get_rna_access (int blocktype, int adrcode, char actname[], char constname char buf[512]; int dummy_index= 0; + /* hack: if constname is set, we can only be dealing with an Constraint curve */ + if (constname) + blocktype= ID_CO; + /* get property name based on blocktype */ switch (blocktype) { case ID_OB: /* object */ @@ -842,7 +846,7 @@ char *get_rna_access (int blocktype, int adrcode, char actname[], char constname break; case ID_CO: /* constraint */ - propname= constraint_adrcodes_to_paths(adrcode, &dummy_index); + propname= constraint_adrcodes_to_paths(adrcode, &dummy_index); break; case ID_TE: /* texture */ @@ -872,7 +876,10 @@ char *get_rna_access (int blocktype, int adrcode, char actname[], char constname /* XXX problematic blocktypes */ case ID_CU: /* curve */ - propname= "speed"; // XXX this was a 'dummy curve' that didn't really correspond to any real var... + /* this used to be a 'dummy' curve which got evaluated on the fly... + * now we've got real var for this! + */ + propname= "eval_time"; break; case ID_SEQ: /* sequencer strip */ diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index c2916bc2231..6490ff3c724 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -1569,14 +1569,14 @@ static void ob_parcurve(Scene *scene, Object *ob, Object *par, float mat[][4]) } /* catch exceptions: curve paths used as a duplicator */ else if(enable_cu_speed) { - ctime= bsystem_time(scene, ob, (float)scene->r.cfra, 0.0); - -#if 0 // XXX old animation system - if(calc_ipo_spec(cu->ipo, CU_SPEED, &ctime)==0) { - ctime /= cu->pathlen; - CLAMP(ctime, 0.0, 1.0); - } -#endif // XXX old animation system + /* ctime is now a proper var setting of Curve which gets set by Animato like any other var that's animated, + * but this will only work if it actually is animated... + * + * we firstly calculate the modulus of cu->ctime/cu->pathlen to clamp ctime within the 0.0 to 1.0 times pathlen + * range, then divide this (the modulus) by pathlen to get a value between 0.0 and 1.0 + */ + ctime= fmod(cu->ctime, cu->pathlen) / cu->pathlen; + CLAMP(ctime, 0.0, 1.0); } else { ctime= scene->r.cfra - give_timeoffset(ob); -- cgit v1.2.3 From ad07fc19c0fb97540bfe8d259c0b39098b9d7b9b Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Sat, 20 Jun 2009 14:55:28 +0000 Subject: Context Python dir(context) now gives the items from the data context too, modified context callbacks to also return a list of items in the context. --- source/blender/blenkernel/BKE_context.h | 15 ++++-- source/blender/blenkernel/intern/context.c | 76 ++++++++++++++++++++++++++++-- 2 files changed, 83 insertions(+), 8 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_context.h b/source/blender/blenkernel/BKE_context.h index 6a43f4ca25c..898b84ecdc3 100644 --- a/source/blender/blenkernel/BKE_context.h +++ b/source/blender/blenkernel/BKE_context.h @@ -126,12 +126,14 @@ void CTX_wm_menu_set(bContext *C, struct ARegion *menu); /* Data Context - - note: listbases consist of LinkData items and must be - freed with BLI_freelistN! */ + - listbases consist of CollectionPointerLink items and must be + freed with BLI_freelistN! + - the dir listbase consits of LinkData items */ -PointerRNA CTX_data_pointer_get(bContext *C, const char *member); -ListBase CTX_data_collection_get(bContext *C, const char *member); -void CTX_data_get(bContext *C, const char *member, PointerRNA *r_ptr, ListBase *r_lb); +PointerRNA CTX_data_pointer_get(const bContext *C, const char *member); +ListBase CTX_data_collection_get(const bContext *C, const char *member); +ListBase CTX_data_dir_get(const bContext *C); +void CTX_data_get(const bContext *C, const char *member, PointerRNA *r_ptr, ListBase *r_lb); void CTX_data_id_pointer_set(bContextDataResult *result, struct ID *id); void CTX_data_pointer_set(bContextDataResult *result, struct ID *id, StructRNA *type, void *data); @@ -139,7 +141,10 @@ void CTX_data_pointer_set(bContextDataResult *result, struct ID *id, StructRNA * void CTX_data_id_list_add(bContextDataResult *result, struct ID *id); void CTX_data_list_add(bContextDataResult *result, struct ID *id, StructRNA *type, void *data); +void CTX_data_dir_set(bContextDataResult *result, const char **member); + int CTX_data_equals(const char *member, const char *str); +int CTX_data_dir(const char *member); /*void CTX_data_pointer_set(bContextDataResult *result, void *data); void CTX_data_list_add(bContextDataResult *result, void *data);*/ diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c index ae541365b1e..12deec838a8 100644 --- a/source/blender/blenkernel/intern/context.c +++ b/source/blender/blenkernel/intern/context.c @@ -280,6 +280,7 @@ void CTX_wm_menu_set(bContext *C, ARegion *menu) struct bContextDataResult { PointerRNA ptr; ListBase list; + const char **dir; }; static int ctx_data_get(bContext *C, const char *member, bContextDataResult *result) @@ -360,7 +361,7 @@ static int ctx_data_collection_get(const bContext *C, const char *member, ListBa return 0; } -PointerRNA CTX_data_pointer_get(bContext *C, const char *member) +PointerRNA CTX_data_pointer_get(const bContext *C, const char *member) { bContextDataResult result; @@ -375,7 +376,7 @@ PointerRNA CTX_data_pointer_get(bContext *C, const char *member) } -ListBase CTX_data_collection_get(bContext *C, const char *member) +ListBase CTX_data_collection_get(const bContext *C, const char *member) { bContextDataResult result; @@ -389,7 +390,7 @@ ListBase CTX_data_collection_get(bContext *C, const char *member) } } -void CTX_data_get(bContext *C, const char *member, PointerRNA *r_ptr, ListBase *r_lb) +void CTX_data_get(const bContext *C, const char *member, PointerRNA *r_ptr, ListBase *r_lb) { bContextDataResult result; @@ -403,11 +404,75 @@ void CTX_data_get(bContext *C, const char *member, PointerRNA *r_ptr, ListBase * } } +static void data_dir_add(ListBase *lb, const char *member) +{ + LinkData *link; + + if(strcmp(member, "scene") == 0) /* exception */ + return; + + for(link=lb->first; link; link=link->next) + if(strcmp(link->data, member) == 0) + return; + + link= MEM_callocN(sizeof(LinkData), "LinkData"); + link->data= (void*)member; + BLI_addtail(lb, link); +} + +ListBase CTX_data_dir_get(const bContext *C) +{ + bContextDataResult result; + ListBase lb; + int a; + + memset(&lb, 0, sizeof(lb)); + + if(C->wm.store) { + bContextStoreEntry *entry; + + for(entry=C->wm.store->entries.first; entry; entry=entry->next) + data_dir_add(&lb, entry->name); + } + if(C->wm.region && C->wm.region->type && C->wm.region->type->context) { + memset(&result, 0, sizeof(result)); + C->wm.region->type->context(C, "", &result); + + if(result.dir) + for(a=0; result.dir[a]; a++) + data_dir_add(&lb, result.dir[a]); + } + if(C->wm.area && C->wm.area->type && C->wm.area->type->context) { + memset(&result, 0, sizeof(result)); + C->wm.area->type->context(C, "", &result); + + if(result.dir) + for(a=0; result.dir[a]; a++) + data_dir_add(&lb, result.dir[a]); + } + if(C->wm.screen && C->wm.screen->context) { + bContextDataCallback cb= C->wm.screen->context; + memset(&result, 0, sizeof(result)); + cb(C, "", &result); + + if(result.dir) + for(a=0; result.dir[a]; a++) + data_dir_add(&lb, result.dir[a]); + } + + return lb; +} + int CTX_data_equals(const char *member, const char *str) { return (strcmp(member, str) == 0); } +int CTX_data_dir(const char *member) +{ + return (strcmp(member, "") == 0); +} + void CTX_data_id_pointer_set(bContextDataResult *result, ID *id) { RNA_id_pointer_create(id, &result->ptr); @@ -451,6 +516,11 @@ int ctx_data_list_count(const bContext *C, int (*func)(const bContext*, ListBase return 0; } +void CTX_data_dir_set(bContextDataResult *result, const char **dir) +{ + result->dir= dir; +} + /* data context */ Main *CTX_data_main(const bContext *C) -- cgit v1.2.3 From 984ab796298bac49ea7519ee7c4efbccabf3a35b Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sun, 21 Jun 2009 02:51:42 +0000 Subject: 2.5/Multires: Bugfix for loading older files with the pre-modifier multires. --- source/blender/blenkernel/intern/multires.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index b1387281cf5..5def910ddef 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -1270,8 +1270,10 @@ void multires_free(Multires *mr) if(lvl) { CustomData_free(&mr->vdata, lvl->totvert); CustomData_free(&mr->fdata, lvl->totface); - MEM_freeN(mr->edge_flags); - MEM_freeN(mr->edge_creases); + if(mr->edge_flags) + MEM_freeN(mr->edge_flags); + if(mr->edge_creases) + MEM_freeN(mr->edge_creases); } while(lvl) { -- cgit v1.2.3 From 6b15024f4a7b999331694d8a9135d47e4b783a34 Mon Sep 17 00:00:00 2001 From: Janne Karhu Date: Sun, 21 Jun 2009 10:16:52 +0000 Subject: Pointcache refresh part 1: * Particles support larger than 1 frame changes, bigger frame changes can result in inaccurate results, but it's super fast and you get a nice feeling of how the particles behave! * "Cache to current frame" button calculates the exact result of particles at current frame. * Current state of cache can be protected by making it a bake. * Cache is now in memory by default, disk cache is an option. * Only "viewport %" number of particles are calculated and cached in viewport, baking and rendering calculate all particles. * Info on cached frames and memory usage given in ui. * Support for exact "autocaching" of changes and large frame changes(disabled for now until exact place in event system is decided) * "Continue physics" is probably deprecated after this and should be removed once sb & cloth use the new cache code. Todo: * Make softbody & cloth use the new cache things. Other changes: * Some cleanup of particle buttons. --- source/blender/blenkernel/BKE_particle.h | 5 + source/blender/blenkernel/BKE_pointcache.h | 56 +- source/blender/blenkernel/intern/depsgraph.c | 18 +- source/blender/blenkernel/intern/particle.c | 48 +- source/blender/blenkernel/intern/particle_system.c | 187 +++-- source/blender/blenkernel/intern/pointcache.c | 753 +++++++++++++++++++-- 6 files changed, 930 insertions(+), 137 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index 4efd9a7f8ba..0ecd71fc4a3 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -217,6 +217,7 @@ 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 Object *psys_find_object(struct Scene *scene, struct ParticleSystem *psys); //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); @@ -251,6 +252,7 @@ struct ParticleSystemModifierData *psys_get_modifier(struct Object *ob, struct P struct ParticleSettings *psys_new_settings(char *name, struct Main *main); struct ParticleSettings *psys_copy_settings(struct ParticleSettings *part); +int psys_count_autocache(struct Scene *scene, struct ParticleSettings *part); void psys_flush_particle_settings(struct Scene *scene, struct ParticleSettings *part, int recalc); void make_local_particlesettings(struct ParticleSettings *part); @@ -290,10 +292,13 @@ void psys_get_reactor_target(struct Object *ob, struct ParticleSystem *psys, str void psys_init_effectors(struct Scene *scene, struct Object *obsrc, struct Group *group, struct ParticleSystem *psys); void psys_end_effectors(struct ParticleSystem *psys); +void psys_get_pointcache_start_end(struct Scene *scene, struct ParticleSystem *psys, int *sfra, int *efra); + void particle_system_update(struct Scene *scene, struct Object *ob, struct ParticleSystem *psys); /* ----------- functions needed only inside particlesystem ------------ */ /* particle.c */ +void psys_interpolate_particle(short type, struct ParticleKey keys[4], float dt, struct ParticleKey *result, int velocity); 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); diff --git a/source/blender/blenkernel/BKE_pointcache.h b/source/blender/blenkernel/BKE_pointcache.h index 8ef3ff4d4b7..b79357edf36 100644 --- a/source/blender/blenkernel/BKE_pointcache.h +++ b/source/blender/blenkernel/BKE_pointcache.h @@ -31,6 +31,8 @@ #include "DNA_ID.h" +#include "MEM_guardedalloc.h" + /* Point cache clearing option, for BKE_ptcache_id_clear, before * and after are non inclusive (they wont remove the cfra) */ #define PTCACHE_CLEAR_ALL 0 @@ -42,6 +44,7 @@ #define PTCACHE_RESET_DEPSGRAPH 0 #define PTCACHE_RESET_BAKED 1 #define PTCACHE_RESET_OUTDATED 2 +#define PTCACHE_RESET_FREE 3 /* Add the blendfile name after blendcache_ */ #define PTCACHE_EXT ".bphys" @@ -56,6 +59,11 @@ #define PTCACHE_TYPE_PARTICLES 1 #define PTCACHE_TYPE_CLOTH 2 +/* PTCache read return code */ +#define PTCACHE_READ_EXACT 1 +#define PTCACHE_READ_INTERPOLATED 2 +#define PTCACHE_READ_OLD 3 + /* Structs */ struct Object; struct Scene; @@ -80,6 +88,41 @@ typedef struct PTCacheID { struct PointCache *cache; } PTCacheID; +typedef struct PTCacheWriter { + struct PTCacheID *pid; + int cfra; + int totelem; + + float *(*elem_ptr)(int index, void *calldata); + void *calldata; +} PTCacheWriter; + +typedef struct PTCacheReader { + struct Scene *scene; + struct PTCacheID *pid; + float cfra; + int totelem; + + void (*set_elem)(int index, void *calldata, float *data); + void (*interpolate_elem)(int index, void *calldata, float frs_sec, float cfra, int cfra1, int cfra2, float *data1, float *data2); + void *calldata; + + int allow_interpolate; + int allow_old; + int *old_frame; +} PTCacheReader; + +typedef struct PTCacheBaker { + struct Scene *scene; + int bake; + int render; + struct PTCacheID *pid; + int (*break_test)(void *data); + void *break_data; + void (*progressbar)(void *data, int num); + void *progresscontext; +} PTCacheBaker; + /* Creating ID's */ void BKE_ptcache_id_from_softbody(PTCacheID *pid, struct Object *ob, struct SoftBody *sb); void BKE_ptcache_id_from_particles(PTCacheID *pid, struct Object *ob, struct ParticleSystem *psys); @@ -93,9 +136,9 @@ void BKE_ptcache_remove(void); /* ID specific functions */ void BKE_ptcache_id_clear(PTCacheID *id, int mode, int cfra); int BKE_ptcache_id_exist(PTCacheID *id, int cfra); -int BKE_ptcache_id_reset(PTCacheID *id, int mode); +int BKE_ptcache_id_reset(struct Scene *scene, PTCacheID *id, int mode); void BKE_ptcache_id_time(PTCacheID *pid, struct Scene *scene, float cfra, int *startframe, int *endframe, float *timescale); -int BKE_ptcache_object_reset(struct Object *ob, int mode); +int BKE_ptcache_object_reset(struct Scene *scene, struct Object *ob, int mode); /* File reading/writing */ PTCacheFile *BKE_ptcache_file_open(PTCacheID *id, int mode, int cfra); @@ -103,6 +146,10 @@ void BKE_ptcache_file_close(PTCacheFile *pf); int BKE_ptcache_file_read_floats(PTCacheFile *pf, float *f, int tot); int BKE_ptcache_file_write_floats(PTCacheFile *pf, float *f, int tot); +/* General cache reading/writing */ +int BKE_ptcache_read_cache(PTCacheReader *reader); +int BKE_ptcache_write_cache(PTCacheWriter *writer); + /* Continue physics */ void BKE_ptcache_set_continue_physics(struct Scene *scene, int enable); int BKE_ptcache_get_continue_physics(void); @@ -112,4 +159,9 @@ struct PointCache *BKE_ptcache_add(void); void BKE_ptcache_free(struct PointCache *cache); struct PointCache *BKE_ptcache_copy(struct PointCache *cache); +/* Baking */ +void BKE_ptcache_autocache_all(struct Scene *scene); +void BKE_ptcache_make_cache(struct PTCacheBaker* baker); +void BKE_ptcache_toggle_disk_cache(struct PTCacheID *pid); + #endif diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index 8bb34bde122..b57b8b7a6da 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -1831,7 +1831,7 @@ static unsigned int flush_layer_node(Scene *sce, DagNode *node, int curtime) } /* node was checked to have lasttime != curtime , and is of type ID_OB */ -static void flush_pointcache_reset(DagNode *node, int curtime, int reset) +static void flush_pointcache_reset(Scene *scene, DagNode *node, int curtime, int reset) { DagAdjList *itA; Object *ob; @@ -1844,13 +1844,13 @@ static void flush_pointcache_reset(DagNode *node, int curtime, int reset) ob= (Object*)(node->ob); if(reset || (ob->recalc & OB_RECALC)) { - if(BKE_ptcache_object_reset(ob, PTCACHE_RESET_DEPSGRAPH)) + if(BKE_ptcache_object_reset(scene, ob, PTCACHE_RESET_DEPSGRAPH)) ob->recalc |= OB_RECALC_DATA; - flush_pointcache_reset(itA->node, curtime, 1); + flush_pointcache_reset(scene, itA->node, curtime, 1); } else - flush_pointcache_reset(itA->node, curtime, 0); + flush_pointcache_reset(scene, itA->node, curtime, 0); } } } @@ -1908,13 +1908,13 @@ void DAG_scene_flush_update(Scene *sce, unsigned int lay, int time) ob= (Object*)(itA->node->ob); if(ob->recalc & OB_RECALC) { - if(BKE_ptcache_object_reset(ob, PTCACHE_RESET_DEPSGRAPH)) + if(BKE_ptcache_object_reset(sce, ob, PTCACHE_RESET_DEPSGRAPH)) ob->recalc |= OB_RECALC_DATA; - flush_pointcache_reset(itA->node, lasttime, 1); + flush_pointcache_reset(sce, itA->node, lasttime, 1); } else - flush_pointcache_reset(itA->node, lasttime, 0); + flush_pointcache_reset(sce, itA->node, lasttime, 0); } } } @@ -2132,7 +2132,7 @@ void DAG_object_flush_update(Scene *sce, Object *ob, short flag) if(ob==NULL || sce->theDag==NULL) return; ob->recalc |= flag; - BKE_ptcache_object_reset(ob, PTCACHE_RESET_DEPSGRAPH); + BKE_ptcache_object_reset(sce, ob, PTCACHE_RESET_DEPSGRAPH); /* all users of this ob->data should be checked */ /* BUT! displists for curves are still only on cu */ @@ -2147,7 +2147,7 @@ void DAG_object_flush_update(Scene *sce, Object *ob, short flag) for (obt=G.main->object.first; obt; obt= obt->id.next) { if (obt != ob && obt->data==ob->data) { obt->recalc |= OB_RECALC_DATA; - BKE_ptcache_object_reset(obt, PTCACHE_RESET_DEPSGRAPH); + BKE_ptcache_object_reset(sce, obt, PTCACHE_RESET_DEPSGRAPH); } } } diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 34e69b2d736..5b3720cd6b0 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -222,6 +222,45 @@ short psys_get_current_num(Object *ob) return i; } +Object *psys_find_object(Scene *scene, ParticleSystem *psys) +{ + Base *base = scene->base.first; + ParticleSystem *tpsys; + + for(base = scene->base.first; base; base = base->next) { + for(tpsys = base->object->particlesystem.first; psys; psys=psys->next) { + if(tpsys == psys) + return base->object; + } + } + + return NULL; +} +int psys_count_autocache(Scene *scene, ParticleSettings *part) +{ + Base *base = scene->base.first; + ParticleSystem *psys; + PTCacheID pid; + int autocache_count= 0; + + for(base = scene->base.first; base; base = base->next) { + for(psys = base->object->particlesystem.first; psys; psys=psys->next) { + if(part && psys->part != part) + continue; + + BKE_ptcache_id_from_particles(&pid, base->object, psys); + + if((psys->pointcache->flag & PTCACHE_BAKED) + || (psys->pointcache->flag & PTCACHE_AUTOCACHE)==0) + continue; + + if((psys->pointcache->flag & PTCACHE_OUTDATED) + || BKE_ptcache_id_exist(&pid, CFRA)==0) + autocache_count++; + } + } + return autocache_count; +} /* change object's active particle system */ void psys_change_act(void *ob_v, void *act_v) { @@ -864,7 +903,7 @@ static void weighted_particle_vector(float *v1, float *v2, float *v3, float *v4, vec[1]= weights[0]*v1[1] + weights[1]*v2[1] + weights[2]*v3[1] + weights[3]*v4[1]; vec[2]= weights[0]*v1[2] + weights[1]*v2[2] + weights[2]*v3[2] + weights[3]*v4[2]; } -static void interpolate_particle(short type, ParticleKey keys[4], float dt, ParticleKey *result, int velocity) +void psys_interpolate_particle(short type, ParticleKey keys[4], float dt, ParticleKey *result, int velocity) { float t[4]; @@ -2569,7 +2608,7 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra } /* now we should have in chronologiacl order k1<=k2<=t<=k3<=k4 with keytime between [0,1]->[k2,k3] (k1 & k4 used for cardinal & bspline interpolation)*/ - interpolate_particle((psys->flag & PSYS_KEYED) ? -1 /* signal for cubic interpolation */ + psys_interpolate_particle((psys->flag & PSYS_KEYED) ? -1 /* signal for cubic interpolation */ : ((psys->part->flag & PART_HAIR_BSPLINE) ? KEY_BSPLINE : KEY_CARDINAL) ,keys, keytime, &result, 0); @@ -3062,7 +3101,6 @@ void make_local_particlesettings(ParticleSettings *part) } } } - void psys_flush_particle_settings(Scene *scene, ParticleSettings *part, int recalc) { Base *base = scene->base.first; @@ -3495,7 +3533,7 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i QuatInterpol(state->rot,keys[1].rot,keys[2].rot,keytime); } - interpolate_particle((psys->flag & PSYS_KEYED) ? -1 /* signal for cubic interpolation */ + psys_interpolate_particle((psys->flag & PSYS_KEYED) ? -1 /* signal for cubic interpolation */ : ((psys->part->flag & PART_HAIR_BSPLINE) ? KEY_BSPLINE : KEY_CARDINAL) ,keys, keytime, state, 1); @@ -3776,7 +3814,7 @@ int psys_get_particle_state(struct Scene *scene, Object *ob, ParticleSystem *psy VecMulf(keys[1].vel, dfra / frs_sec); VecMulf(keys[2].vel, dfra / frs_sec); - interpolate_particle(-1, keys, keytime, state, 1); + psys_interpolate_particle(-1, keys, keytime, state, 1); /* convert back to real velocity */ VecMulf(state->vel, frs_sec / dfra); diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 52f13eeadb8..fc6413849d1 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -104,7 +104,8 @@ static int get_current_display_percentage(ParticleSystem *psys) { ParticleSettings *part=psys->part; - if(psys->renderdata || (part->child_nbr && part->childtype)) + if(psys->renderdata || (part->child_nbr && part->childtype) + || (psys->pointcache->flag & PTCACHE_BAKING)) return 100; if(part->phystype==PART_PHYS_KEYED){ @@ -2195,57 +2196,80 @@ void psys_get_reactor_target(Object *ob, ParticleSystem *psys, Object **target_o /************************************************/ /* Point Cache */ /************************************************/ - -static void write_particles_to_cache(Object *ob, ParticleSystem *psys, int cfra) +void psys_get_pointcache_start_end(Scene *scene, ParticleSystem *psys, int *sfra, int *efra) { - PTCacheID pid; - PTCacheFile *pf; - ParticleData *pa; - int i, totpart= psys->totpart; + ParticleSettings *part = psys->part; - if(totpart == 0) - return; + *sfra = MAX2(1, (int)part->sta); + *efra = MIN2((int)(part->end + part->lifetime + 1.0), scene->r.efra); +} +static float *particle_state_ptr(int index, ParticleSystem *psys) +{ + return (float *)(&(psys->particles+index)->state); +} +static void particle_read_state(int index, ParticleSystem *psys, float *data) +{ + ParticleData *pa = psys->particles + index; + ParticleKey *key = (ParticleKey *)data; - BKE_ptcache_id_from_particles(&pid, ob, psys); - pf= BKE_ptcache_file_open(&pid, PTCACHE_FILE_WRITE, cfra); - if(!pf) - return; + if(key->time > pa->state.time) + copy_particle_key(&pa->prev_state, &pa->state, 1); - /* assuming struct consists of tightly packed floats */ - for(i=0, pa=psys->particles; istate, sizeof(ParticleKey)/sizeof(float)); - - BKE_ptcache_file_close(pf); + copy_particle_key(&pa->state, key, 1); } +static void particle_cache_interpolate(int index, ParticleSystem *psys, float frs_sec, float cfra, int cfra1, int cfra2, float *data1, float *data2) +{ + ParticleData *pa = psys->particles + index; + ParticleKey keys[4]; + float dfra; + + keys[1] = *((ParticleKey*)data1); + keys[2] = *((ParticleKey*)data2); + + dfra = keys[2].time - keys[1].time; -static int get_particles_from_cache(Object *ob, ParticleSystem *psys, int cfra) + VecMulf(keys[1].vel, dfra / frs_sec); + VecMulf(keys[2].vel, dfra / frs_sec); + + psys_interpolate_particle(-1, keys, (keys[1].time - cfra) / dfra, &pa->state, 1); + + VecMulf(pa->state.vel, frs_sec / dfra); +} +static void write_particles_to_cache(Object *ob, ParticleSystem *psys, int cfra) { + PTCacheWriter writer; PTCacheID pid; - PTCacheFile *pf; - ParticleData *pa; - int i, totpart= psys->totpart; - - if(totpart == 0) - return 0; BKE_ptcache_id_from_particles(&pid, ob, psys); - pf= BKE_ptcache_file_open(&pid, PTCACHE_FILE_READ, cfra); - if(!pf) - return 0; - /* assuming struct consists of tightly packed floats */ - for(i=0, pa=psys->particles; istate.time) - copy_particle_key(&pa->prev_state,&pa->state,1); - if(!BKE_ptcache_file_read_floats(pf, (float*)&pa->state, sizeof(ParticleKey)/sizeof(float))) { - BKE_ptcache_file_close(pf); - return 0; - } - } + writer.calldata = psys; + writer.cfra = cfra; + writer.elem_ptr = particle_state_ptr; + writer.pid = &pid; + writer.totelem = psys->totpart; - BKE_ptcache_file_close(pf); + BKE_ptcache_write_cache(&writer); +} - return 1; +static int get_particles_from_cache(Scene *scene, Object *ob, ParticleSystem *psys, float cfra, int allow_interpolate, int allow_old, int *old_frame) +{ + PTCacheReader reader; + PTCacheID pid; + + BKE_ptcache_id_from_particles(&pid, ob, psys); + + reader.allow_interpolate = allow_interpolate; + reader.allow_old = allow_old; + reader.calldata = psys; + reader.cfra = cfra; + reader.interpolate_elem = particle_cache_interpolate; + reader.old_frame = old_frame; + reader.pid = &pid; + reader.scene = scene; + reader.set_elem = particle_read_state; + reader.totelem = psys->totpart; + + return BKE_ptcache_read_cache(&reader); } /************************************************/ @@ -4085,7 +4109,7 @@ static void dynamics_step(Scene *scene, Object *ob, ParticleSystem *psys, Partic /* main loop: calculate physics for all particles */ for(p=0, pa=psys->particles; pflag & PARS_UNEXIST) continue; + if(pa->flag & (PARS_UNEXIST+PARS_NO_DISP)) continue; copy_particle_key(&pa->prev_state,&pa->state,1); @@ -4110,25 +4134,26 @@ static void dynamics_step(Scene *scene, Object *ob, ParticleSystem *psys, Partic if(pa->alive==PARS_UNBORN || pa->alive==PARS_KILLED || ELEM(part->phystype,PART_PHYS_NO,PART_PHYS_KEYED) - || birthtime >= cfra){ + || birthtime >= psys->cfra){ reset_particle(scene, pa,psys,psmd,ob,dtime,cfra,vg_vel,vg_tan,vg_rot); } pa_dfra = dfra; pa_dtime = dtime; - if(birthtime <= cfra && birthtime >= psys->cfra){ + + if(dietime <= cfra && psys->cfra < dietime){ + /* particle dies some time between this and last step */ + pa_dfra = dietime - ((birthtime > psys->cfra) ? birthtime : psys->cfra); + pa_dtime = pa_dfra * timestep; + pa->alive = PARS_DYING; + } + else if(birthtime <= cfra && birthtime >= psys->cfra){ /* particle is born some time between this and last step*/ pa->alive = PARS_ALIVE; pa_dfra = cfra - birthtime; pa_dtime = pa_dfra*timestep; } - else if(dietime <= cfra && psys->cfra < dietime){ - /* particle dies some time between this and last step */ - pa_dfra = dietime - psys->cfra; - pa_dtime = pa_dfra * timestep; - pa->alive = PARS_DYING; - } else if(dietime < cfra){ /* nothing to be done when particle is dead */ } @@ -4520,7 +4545,7 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle int totpart, oldtotpart, totchild, oldtotchild, p; float disp, *vg_vel= 0, *vg_tan= 0, *vg_rot= 0, *vg_size= 0; int init= 0, distr= 0, alloc= 0, usecache= 0, only_children_changed= 0; - int framenr, framedelta, startframe, endframe; + int framenr, framedelta, startframe, endframe, old_framenr; part= psys->part; cache= psys->pointcache; @@ -4528,6 +4553,10 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle framenr= (int)scene->r.cfra; framedelta= framenr - cache->simframe; + /* set suitable cache range automatically */ + if((cache->flag & (PTCACHE_BAKING|PTCACHE_BAKED))==0) + psys_get_pointcache_start_end(scene, psys, &cache->startframe, &cache->endframe); + BKE_ptcache_id_from_particles(&pid, ob, psys); BKE_ptcache_id_time(&pid, scene, 0.0f, &startframe, &endframe, NULL); @@ -4600,9 +4629,13 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle if(init) { if(distr) { - if(alloc) + if(alloc) { realloc_particles(ob, psys, totpart); + if(usecache) + BKE_ptcache_id_clear(&pid, PTCACHE_CLEAR_ALL, 0); + } + distribute_particles(scene, ob, psys, part->from); if((psys->part->type == PART_HAIR) && !(psys->flag & PSYS_HAIR_DONE)) @@ -4616,9 +4649,11 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle free_keyed_keys(psys); initialize_all_particles(ob, psys, psmd); + - if(alloc) + if(alloc) { reset_all_particles(scene, ob, psys, psmd, 0.0, cfra, oldtotpart); + } } /* flag for possible explode modifiers after this system */ @@ -4627,25 +4662,47 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle /* try to read from the cache */ if(usecache) { - if(get_particles_from_cache(ob, psys, framenr)) { - if(part->phystype==PART_PHYS_KEYED && psys->flag&PSYS_FIRST_KEYED) { - psys_count_keyed_targets(ob,psys); - set_keyed_keys(scene, ob, psys); - } + int result = get_particles_from_cache(scene, ob, psys, (float)framenr, 0, 1, &old_framenr); + + if(result == PTCACHE_READ_EXACT) { + //if(part->phystype==PART_PHYS_KEYED && psys->flag&PSYS_FIRST_KEYED) { + // psys_count_keyed_targets(ob,psys); + // set_keyed_keys(scene, ob, psys); + //} cached_step(scene, ob, psmd, psys, cfra); psys->cfra=cfra; psys->recalc = 0; - if(part->phystype==PART_PHYS_KEYED && psys->flag&PSYS_FIRST_KEYED) { - psys_update_path_cache(scene, ob, psmd, psys, framenr); - } + //if(part->phystype==PART_PHYS_KEYED && psys->flag&PSYS_FIRST_KEYED) { + // psys_update_path_cache(scene, ob, psmd, psys, framenr); + //} cache->simframe= framenr; cache->flag |= PTCACHE_SIMULATION_VALID; + if(cache->flag & PTCACHE_OUTDATED) + BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_FREE); + return; } + else if((cache->flag & PTCACHE_AUTOCACHE)==0 && result==PTCACHE_READ_OLD) { + /* clear cache after current frame */ + BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_FREE); + + /* set old cfra */ + psys->cfra = (float)old_framenr; + + for(p=0, pa=psys->particles; ptime > psys->cfra) + pa->alive = PARS_UNBORN; + else if(pa->dietime <= psys->cfra) + pa->alive = PARS_DEAD; + else + pa->alive = PARS_ALIVE; + } + } else if(ob->id.lib || (cache->flag & PTCACHE_BAKED)) { psys_reset(psys, PSYS_RESET_CACHE_MISS); psys->cfra=cfra; @@ -4653,8 +4710,10 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle return; } - if(framenr != startframe && framedelta != 1) { - psys_reset(psys, PSYS_RESET_CACHE_MISS); + if(framenr != startframe && framedelta != 1 && cache->flag & PTCACHE_AUTOCACHE) { + //psys_reset(psys, PSYS_RESET_CACHE_MISS); + /* make sure cache is recalculated */ + BKE_ptcache_id_clear(&pid, PTCACHE_CLEAR_FRAME, (int)cfra); psys->cfra = cfra; psys->recalc = 0; return; @@ -4663,10 +4722,11 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle else { cache->flag &= ~PTCACHE_SIMULATION_VALID; cache->simframe= 0; + cache->last_exact= 0; } /* if on second frame, write cache for first frame */ - if(usecache && framenr == startframe+1) + if(usecache && psys->cfra == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0)) write_particles_to_cache(ob, psys, startframe); if(part->phystype==PART_PHYS_KEYED && psys->flag&PSYS_FIRST_KEYED) @@ -4768,8 +4828,7 @@ static void psys_to_softbody(Scene *scene, Object *ob, ParticleSystem *psys) static int hair_needs_recalc(ParticleSystem *psys) { if((psys->flag & PSYS_EDITED)==0 && - ((psys->flag & PSYS_HAIR_DONE)==0 || psys->recalc & PSYS_RECALC_REDO)) { - psys->recalc &= ~PSYS_RECALC_REDO; + ((psys->flag & PSYS_HAIR_DONE)==0 || psys->recalc & PSYS_RECALC_RESET)) { return 1; } diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index b00755f7135..f59336518d7 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -51,9 +51,11 @@ #include "BKE_object.h" #include "BKE_particle.h" #include "BKE_pointcache.h" +#include "BKE_scene.h" #include "BKE_softbody.h" #include "BKE_utildefines.h" +#include "BLI_blenlib.h" /* needed for directory lookup */ #ifndef WIN32 @@ -213,21 +215,29 @@ static int BKE_ptcache_id_filename(PTCacheID *pid, char *filename, int cfra, sho filename[0] = '\0'; newname = filename; - /*if (!G.relbase_valid) return 0; *//* save blend file before using pointcache */ + if (!G.relbase_valid) return 0; /* save blend file before using disk pointcache */ /* start with temp dir */ if (do_path) { len = ptcache_path(pid, filename); newname += len; } - idname = (pid->ob->id.name+2); - /* convert chars to hex so they are always a valid filename */ - while('\0' != *idname) { - snprintf(newname, MAX_PTCACHE_FILE, "%02X", (char)(*idname++)); - newname+=2; - len += 2; + if(strcmp(pid->cache->name, "")==0) { + idname = (pid->ob->id.name+2); + /* convert chars to hex so they are always a valid filename */ + while('\0' != *idname) { + snprintf(newname, MAX_PTCACHE_FILE, "%02X", (char)(*idname++)); + newname+=2; + len += 2; + } } - + else { + int temp = strlen(pid->cache->name); + strcpy(newname, pid->cache->name); + newname+=temp; + len += temp; + } + if (do_ext) { snprintf(newname, MAX_PTCACHE_FILE, "_%06d_%02d"PTCACHE_EXT, cfra, pid->stack_index); /* always 6 chars */ len += 16; @@ -247,7 +257,7 @@ PTCacheFile *BKE_ptcache_file_open(PTCacheID *pid, int mode, int cfra) if(pid->ob->id.lib && mode == PTCACHE_FILE_WRITE) return NULL; - /*if (!G.relbase_valid) return NULL; *//* save blend file before using pointcache */ + if (!G.relbase_valid) return NULL; /* save blend file before using disk pointcache */ BKE_ptcache_id_filename(pid, filename, cfra, 1, 1); @@ -286,6 +296,323 @@ int BKE_ptcache_file_write_floats(PTCacheFile *pf, float *f, int tot) return (fwrite(f, sizeof(float), tot, pf->fp) == tot); } +static int ptcache_pid_elemsize(PTCacheID *pid) +{ + if(pid->type==PTCACHE_TYPE_SOFTBODY) + return 0; // TODO + else if(pid->type==PTCACHE_TYPE_PARTICLES) + return sizeof(ParticleKey); + else if(pid->type==PTCACHE_TYPE_CLOTH) + return 0; // TODO + + return 0; +} +static int ptcache_pid_totelem(PTCacheID *pid) +{ + if(pid->type==PTCACHE_TYPE_SOFTBODY) + return 0; // TODO + else if(pid->type==PTCACHE_TYPE_PARTICLES) { + ParticleSystem *psys = pid->data; + return psys->totpart; + } + else if(pid->type==PTCACHE_TYPE_CLOTH) + return 0; // TODO + + return 0; +} + +void ptcache_update_info(PTCacheID *pid) +{ + PointCache *cache = pid->cache; + int totframes = 0; + + if(cache->flag & PTCACHE_DISK_CACHE) { + int cfra = cache->startframe; + + for(; cfra<=cache->endframe; cfra++) { + if(BKE_ptcache_id_exist(pid, cfra)) + totframes++; + } + + sprintf(cache->info, "%i frames on disk.", totframes); + } + else { + PTCacheMem *pm = cache->mem_cache.first; + float framesize = 0.0f, bytes = 0.0f; + int mb; + + if(pm) + framesize = (float)ptcache_pid_elemsize(pid) * (float)pm->totpoint; + + for(; pm; pm=pm->next) + totframes++; + + bytes = totframes * framesize; + + mb = (bytes > 1024.0f * 1024.0f); + + sprintf(cache->info, "%i frames in memory (%.1f %s).", + totframes, + bytes / (mb ? 1024.0f * 1024.0f : 1024.0f), + mb ? "Mb" : "kb"); + } +} +/* reads cache from disk or memory */ +/* possible to get old or interpolated result */ +int BKE_ptcache_read_cache(PTCacheReader *reader) +{ + PTCacheID *pid = reader->pid; + PTCacheFile *pf=NULL, *pf2=NULL; + PTCacheMem *pm=NULL, *pm2=NULL; + int totelem = reader->totelem; + float cfra = reader->cfra; + int cfrai = (int)cfra; + int elemsize = ptcache_pid_elemsize(pid); + int i, incr = elemsize / sizeof(float); + float frs_sec = reader->scene->r.frs_sec; + + if(totelem == 0) + return 0; + + /* first check if we have the actual frame cached */ + if(cfra == (float)cfrai) { + if(pid->cache->flag & PTCACHE_DISK_CACHE) { + pf= BKE_ptcache_file_open(pid, PTCACHE_FILE_READ, cfrai); + } + else { + pm = pid->cache->mem_cache.first; + + for(; pm; pm=pm->next) { + if(pm->frame == cfrai) + break; + } + } + } + + /* if found, use exact frame */ + if(pf || pm) { + float *data; + + if(pm) + data = pm->data; + else + data = MEM_callocN(elemsize, "pointcache read data"); + + for(i=0; iset_elem(i, reader->calldata, data); + } + else { + reader->set_elem(i, reader->calldata, data); + data += incr; + } + } + + if(pf) { + BKE_ptcache_file_close(pf); + MEM_freeN(data); + } + + return PTCACHE_READ_EXACT; + } + /* no exact cache frame found so try to find cached frames around cfra */ + if(reader->allow_interpolate || reader->allow_old) { + int cfra1, cfra2; + + if(pid->cache->flag & PTCACHE_DISK_CACHE) { + pf=NULL; + while(cfrai > pid->cache->startframe && !pf) { + cfrai--; + pf= BKE_ptcache_file_open(pid, PTCACHE_FILE_READ, cfrai); + cfra1 = cfrai; + } + + *(reader->old_frame) = cfrai; + + cfrai = (int)cfra; + while(cfrai < pid->cache->endframe && !pf2) { + cfrai++; + pf2= BKE_ptcache_file_open(pid, PTCACHE_FILE_READ, cfrai); + cfra2 = cfrai; + } + } + else if(pid->cache->mem_cache.first){ + pm = pid->cache->mem_cache.first; + + while(pm->next && pm->next->frame < cfra) + pm= pm->next; + + if(pm) { + *(reader->old_frame) = pm->frame; + cfra1 = pm->frame; + } + + pm2 = pid->cache->mem_cache.last; + + while(pm2->prev && pm2->frame > cfra) + pm2= pm2->prev; + + if(pm2) + cfra2 = pm2->frame; + } + + if(reader->allow_interpolate && ((pf && pf2) || (pm && pm2))) { + /* interpolate from nearest frames */ + float *data1, *data2; + + if(pm) { + data1 = pm->data; + data2 = pm2->data; + } + else { + data1 = MEM_callocN(elemsize, "pointcache read data1"); + data2 = MEM_callocN(elemsize, "pointcache read data2"); + } + + for(i=0; iinterpolate_elem(i, reader->calldata, frs_sec, cfra, cfra1, cfra2, data1, data2); + } + else { + reader->interpolate_elem(i, reader->calldata, frs_sec, cfra, cfra1, cfra2, data1, data2); + data1 += incr; + data2 += incr; + } + } + + if(pf) { + BKE_ptcache_file_close(pf); + BKE_ptcache_file_close(pf2); + MEM_freeN(data1); + MEM_freeN(data2); + } + + return PTCACHE_READ_INTERPOLATED; + } + else if(reader->allow_old && (pf || pm)) { + /* use last valid cache frame */ + float *data; + + if(pm) + data = pm->data; + else + data = MEM_callocN(elemsize, "pointcache read data"); + + for(i=0; iset_elem(i, reader->calldata, data); + } + else { + reader->set_elem(i, reader->calldata, data); + data += incr; + } + } + + if(pf) { + BKE_ptcache_file_close(pf); + MEM_freeN(data); + } + if(pf2) + BKE_ptcache_file_close(pf2); + + return PTCACHE_READ_OLD; + } + } + + if(pf) + BKE_ptcache_file_close(pf); + if(pf2) + BKE_ptcache_file_close(pf2); + + return 0; +} +/* writes cache to disk or memory */ +int BKE_ptcache_write_cache(PTCacheWriter *writer) +{ + PointCache *cache = writer->pid->cache; + PTCacheFile *pf= NULL; + int elemsize = ptcache_pid_elemsize(writer->pid); + int i, incr = elemsize / sizeof(float); + + if(writer->totelem == 0 || writer->cfra <= 0) + return 0; + + if(cache->flag & PTCACHE_DISK_CACHE) { + pf = BKE_ptcache_file_open(writer->pid, PTCACHE_FILE_WRITE, writer->cfra); + if(!pf) + return 0; + + for(i=0; itotelem; i++) + BKE_ptcache_file_write_floats(pf, writer->elem_ptr(i, writer->calldata), incr); + } + else { + PTCacheMem *pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache mem"); + PTCacheMem *pm2; + float *pmdata; + + pm->data = MEM_callocN(elemsize * writer->totelem, "Pointcache mem data"); + pmdata = pm->data; + + for(i=0; itotelem; i++, pmdata+=incr) + memcpy(pmdata, writer->elem_ptr(i, writer->calldata), elemsize); + + pm->frame = writer->cfra; + pm->totpoint = writer->totelem; + + /* find add location */ + pm2 = cache->mem_cache.first; + if(!pm2) + BLI_addtail(&cache->mem_cache, pm); + else if(pm2->frame == writer->cfra) { + /* overwrite same frame */ + MEM_freeN(pm2->data); + pm2->data = pm->data; + MEM_freeN(pm); + } + else { + while(pm2->next && pm2->next->frame < writer->cfra) + pm2 = pm2->next; + + BLI_insertlinkafter(&cache->mem_cache, pm2, pm); + } + } + + if(writer->cfra - cache->last_exact == 1) + cache->last_exact = writer->cfra; + + if(pf) + BKE_ptcache_file_close(pf); + + ptcache_update_info(writer->pid); + + return 1; +} /* youll need to close yourself after! * mode - PTCACHE_CLEAR_ALL, @@ -317,62 +644,116 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra) case PTCACHE_CLEAR_ALL: case PTCACHE_CLEAR_BEFORE: case PTCACHE_CLEAR_AFTER: - ptcache_path(pid, path); - - len = BKE_ptcache_id_filename(pid, filename, cfra, 0, 0); /* no path */ - - dir = opendir(path); - if (dir==NULL) - return; - - snprintf(ext, sizeof(ext), "_%02d"PTCACHE_EXT, pid->stack_index); - - while ((de = readdir(dir)) != NULL) { - if (strstr(de->d_name, 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*/ - BLI_strncpy(num, de->d_name + (strlen(de->d_name) - 15), sizeof(num)); - frame = atoi(num); - - if((mode==PTCACHE_CLEAR_BEFORE && frame < cfra) || - (mode==PTCACHE_CLEAR_AFTER && frame > cfra) ) { + if(pid->cache->flag & PTCACHE_DISK_CACHE) { + ptcache_path(pid, path); + + len = BKE_ptcache_id_filename(pid, filename, cfra, 0, 0); /* no path */ + + dir = opendir(path); + if (dir==NULL) + return; + + snprintf(ext, sizeof(ext), "_%02d"PTCACHE_EXT, pid->stack_index); + + while ((de = readdir(dir)) != NULL) { + if (strstr(de->d_name, 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) { + pid->cache->last_exact = 0; + 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*/ + BLI_strncpy(num, de->d_name + (strlen(de->d_name) - 15), sizeof(num)); + frame = atoi(num); - BLI_join_dirfile(path_full, path, de->d_name); - BLI_delete(path_full, 0, 0); + 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); + } + else { + PTCacheMem *pm= pid->cache->mem_cache.first; + PTCacheMem *link= NULL; + + if(mode == PTCACHE_CLEAR_ALL) { + pid->cache->last_exact = 0; + for(; pm; pm=pm->next) + MEM_freeN(pm->data); + BLI_freelistN(&pid->cache->mem_cache); + } else { + while(pm) { + if((mode==PTCACHE_CLEAR_BEFORE && pm->frame < cfra) || + (mode==PTCACHE_CLEAR_AFTER && pm->frame > cfra) ) { + link = pm; + pm = pm->next; + MEM_freeN(link->data); + BLI_freelinkN(&pid->cache->mem_cache, link); + } + else + pm = pm->next; + } + } } - closedir(dir); break; case PTCACHE_CLEAR_FRAME: - len = BKE_ptcache_id_filename(pid, filename, cfra, 1, 1); /* no path */ - BLI_delete(filename, 0, 0); + if(pid->cache->flag & PTCACHE_DISK_CACHE) { + if(BKE_ptcache_id_exist(pid, cfra)) { + BKE_ptcache_id_filename(pid, filename, cfra, 1, 1); /* no path */ + BLI_delete(filename, 0, 0); + } + } + else { + PTCacheMem *pm = pid->cache->mem_cache.first; + + for(; pm; pm=pm->next) { + if(pm->frame == cfra) { + MEM_freeN(pm->data); + BLI_freelinkN(&pid->cache->mem_cache, pm); + break; + } + } + } break; } + + ptcache_update_info(pid); } int BKE_ptcache_id_exist(PTCacheID *pid, int cfra) { - char filename[MAX_PTCACHE_FILE]; - if(!pid->cache) return 0; - BKE_ptcache_id_filename(pid, filename, cfra, 1, 1); + if(pid->cache->flag & PTCACHE_DISK_CACHE) { + char filename[MAX_PTCACHE_FILE]; + + BKE_ptcache_id_filename(pid, filename, cfra, 1, 1); - return BLI_exists(filename); + return BLI_exists(filename); + } + else { + PTCacheMem *pm = pid->cache->mem_cache.first; + + for(; pm; pm=pm->next) { + if(pm->frame==cfra) + return 1; + } + return 0; + } } void BKE_ptcache_id_time(PTCacheID *pid, Scene *scene, float cfra, int *startframe, int *endframe, float *timescale) @@ -414,10 +795,10 @@ void BKE_ptcache_id_time(PTCacheID *pid, Scene *scene, float cfra, int *startfra } } -int BKE_ptcache_id_reset(PTCacheID *pid, int mode) +int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode) { PointCache *cache; - int reset, clear; + int reset, clear, current, after; if(!pid->cache) return 0; @@ -425,11 +806,20 @@ int BKE_ptcache_id_reset(PTCacheID *pid, int mode) cache= pid->cache; reset= 0; clear= 0; + current= 0; + after= 0; if(mode == PTCACHE_RESET_DEPSGRAPH) { if(!(cache->flag & PTCACHE_BAKED) && !BKE_ptcache_get_continue_physics()) { - reset= 1; - clear= 1; + if(cache->flag & PTCACHE_AUTOCACHE) { + reset= 1; + clear= 1; + } + else { + current= 1; + after= 1; + cache->flag |= PTCACHE_OUTDATED; + } } else cache->flag |= PTCACHE_OUTDATED; @@ -449,10 +839,19 @@ int BKE_ptcache_id_reset(PTCacheID *pid, int mode) if(!(cache->flag & PTCACHE_BAKED)) clear= 1; } + else if(mode == PTCACHE_RESET_FREE) { + if(!(cache->flag & PTCACHE_BAKED) && !BKE_ptcache_get_continue_physics()) { + if((cache->flag & PTCACHE_AUTOCACHE)==0) { + current= 1; + after= 1; + } + } + } if(reset) { cache->flag &= ~(PTCACHE_OUTDATED|PTCACHE_SIMULATION_VALID); cache->simframe= 0; + cache->last_exact= 0; if(pid->type == PTCACHE_TYPE_CLOTH) cloth_free_modifier(pid->ob, pid->data); @@ -463,11 +862,15 @@ int BKE_ptcache_id_reset(PTCacheID *pid, int mode) } if(clear) BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0); + if(after) + BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, CFRA); + if(current) + BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_FRAME, CFRA); - return (reset || clear); + return (reset || clear || current || after); } -int BKE_ptcache_object_reset(Object *ob, int mode) +int BKE_ptcache_object_reset(Scene *scene, Object *ob, int mode) { PTCacheID pid; ParticleSystem *psys; @@ -479,7 +882,7 @@ int BKE_ptcache_object_reset(Object *ob, int mode) if(ob->soft) { BKE_ptcache_id_from_softbody(&pid, ob, ob->soft); - reset |= BKE_ptcache_id_reset(&pid, mode); + reset |= BKE_ptcache_id_reset(scene, &pid, mode); } for(psys=ob->particlesystem.first; psys; psys=psys->next) { @@ -488,23 +891,23 @@ int BKE_ptcache_object_reset(Object *ob, int mode) if(psys->soft) { BKE_ptcache_id_from_softbody(&pid, ob, psys->soft); if(mode == PSYS_RESET_ALL || !(psys->part->type == PART_HAIR && (pid.cache->flag & PTCACHE_BAKED))) - reset |= BKE_ptcache_id_reset(&pid, mode); + reset |= BKE_ptcache_id_reset(scene, &pid, mode); else skip = 1; } - else if((psys->recalc & PSYS_RECALC_RESET)==0) + else if(psys->recalc & PSYS_RECALC_REDO || psys->recalc & PSYS_RECALC_CHILD) skip = 1; if(skip == 0) { BKE_ptcache_id_from_particles(&pid, ob, psys); - reset |= BKE_ptcache_id_reset(&pid, mode); + reset |= BKE_ptcache_id_reset(scene, &pid, mode); } } for(md=ob->modifiers.first; md; md=md->next) { if(md->type == eModifierType_Cloth) { BKE_ptcache_id_from_cloth(&pid, ob, (ClothModifierData*)md); - reset |= BKE_ptcache_id_reset(&pid, mode); + reset |= BKE_ptcache_id_reset(scene, &pid, mode); } } @@ -564,7 +967,7 @@ void BKE_ptcache_set_continue_physics(Scene *scene, int enable) if(CONTINUE_PHYSICS == 0) { for(ob=G.main->object.first; ob; ob=ob->id.next) - if(BKE_ptcache_object_reset(ob, PTCACHE_RESET_OUTDATED)) + if(BKE_ptcache_object_reset(scene, ob, PTCACHE_RESET_OUTDATED)) DAG_object_flush_update(scene, ob, OB_RECALC_DATA); } } @@ -590,6 +993,14 @@ PointCache *BKE_ptcache_add() void BKE_ptcache_free(PointCache *cache) { + PTCacheMem *pm = cache->mem_cache.first; + if(pm) { + for(; pm; pm=pm->next) + MEM_freeN(pm->data); + + BLI_freelistN(&cache->mem_cache); + } + MEM_freeN(cache); } @@ -605,3 +1016,231 @@ PointCache *BKE_ptcache_copy(PointCache *cache) return ncache; } + + +/* Baking */ +void BKE_ptcache_autocache_all(Scene *scene) +{ + PTCacheBaker baker; + + baker.bake=0; + baker.break_data=NULL; + baker.break_test=NULL; + baker.pid=NULL; + baker.progressbar=NULL; + baker.progresscontext=NULL; + baker.render=0; + baker.scene=scene; + + if(psys_count_autocache(scene, NULL)) + BKE_ptcache_make_cache(&baker); +} + +/* if bake is not given run simulations to current frame */ +void BKE_ptcache_make_cache(PTCacheBaker* baker) +{ + Scene *scene = baker->scene; + Base *base; + ListBase pidlist; + PTCacheID *pid = baker->pid; + PointCache *cache; + float frameleno = scene->r.framelen; + int cfrao = CFRA; + int startframe = MAXFRAME; + int endframe = CFRA; + int bake = baker->bake; + int render = baker->render; + int end = 0; + + G.afbreek = 0; + + //printf("Caching physics..."); + + /* set caches to baking mode and figure out start frame */ + if(pid) { + /* cache/bake a single object */ + cache = pid->cache; + if((cache->flag & PTCACHE_BAKED)==0) { + if(pid->type==PTCACHE_TYPE_PARTICLES) + psys_get_pointcache_start_end(scene, pid->data, &cache->startframe, &cache->endframe); + + if(bake || cache->flag & PTCACHE_OUTDATED) + BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0); + + startframe = MAX2(cache->last_exact, cache->startframe); + + if(bake) { + endframe = cache->endframe; + cache->flag |= PTCACHE_BAKING; + } + else + endframe = MIN2(endframe, cache->endframe); + + cache->flag &= ~PTCACHE_BAKED; + } + } + else for(base=scene->base.first; base; base= base->next) { + /* cache/bake everything in the scene */ + BKE_ptcache_ids_from_object(&pidlist, base->object); + + for(pid=pidlist.first; pid; pid=pid->next) { + cache = pid->cache; + if((cache->flag & PTCACHE_BAKED)==0) { + if(pid->type==PTCACHE_TYPE_PARTICLES) + psys_get_pointcache_start_end(scene, pid->data, &cache->startframe, &cache->endframe); + + if(cache->flag & PTCACHE_OUTDATED) + BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0); + + startframe = MIN2(startframe, cache->startframe); + + if(bake) { + endframe = MAX2(endframe, cache->endframe); + cache->flag |= PTCACHE_BAKING; + } + else if(render) + cache->flag |= PTCACHE_BAKING; + + cache->flag &= ~PTCACHE_BAKED; + + } + } + + BLI_freelistN(&pidlist); + } + + CFRA= startframe; + scene->r.framelen = 1.0; + scene_update_for_newframe(scene, scene->lay); + + for(; CFRA <= endframe; CFRA++) { + float prog; + + if(bake) + prog = (int)(100.0 * (float)(CFRA - startframe)/(float)(endframe-startframe)); + else + prog = CFRA; + + /* NOTE: baking should not redraw whole ui as this slows things down */ + if(baker->progressbar) + baker->progressbar(baker->progresscontext, prog); + + scene_update_for_newframe(scene, scene->lay); + + /* NOTE: breaking baking should leave calculated frames in cache, not clear it */ + if(baker->break_test && baker->break_test(baker->break_data)) + break; + } + + /* clear baking flag */ + if(pid) { + cache->flag &= ~(PTCACHE_BAKING|PTCACHE_OUTDATED); + if(bake) + cache->flag |= PTCACHE_BAKED; + } + else for(base=scene->base.first; base; base= base->next) { + BKE_ptcache_ids_from_object(&pidlist, base->object); + + for(pid=pidlist.first; pid; pid=pid->next) { + cache->flag &= ~(PTCACHE_BAKING|PTCACHE_OUTDATED); + if(bake) + cache->flag |= PTCACHE_BAKED; + } + } + + //printf("done!\n"); + + scene->r.framelen = frameleno; + CFRA = cfrao; + scene_update_for_newframe(scene, scene->lay); +} + +void BKE_ptcache_toggle_disk_cache(PTCacheID *pid) { + PointCache *cache = pid->cache; + PTCacheFile *pf; + PTCacheMem *pm; + int totelem=0; + int float_count=0; + int tot; + int write_error=0; + + if (!G.relbase_valid){ + cache->flag &= ~PTCACHE_DISK_CACHE; + return; + } + + totelem = ptcache_pid_totelem(pid); + float_count = ptcache_pid_elemsize(pid) / sizeof(float); + + if(totelem==0 || float_count==0) + return; + + tot = totelem*float_count; + + /* MEM -> DISK */ + if(cache->flag & PTCACHE_DISK_CACHE) { + pm = cache->mem_cache.first; + + BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0); + + for(; pm; pm=pm->next) { + pf = BKE_ptcache_file_open(pid, PTCACHE_FILE_WRITE, pm->frame); + + if(pf) { + if(fwrite(pm->data, sizeof(float), tot, pf->fp) != tot) { + printf("Error writing to disk cache\n"); + + cache->flag &= ~PTCACHE_DISK_CACHE; + + BKE_ptcache_file_close(pf); + return; + } + BKE_ptcache_file_close(pf); + } + else + printf("Error creating disk cache file\n"); + } + + cache->flag &= ~PTCACHE_DISK_CACHE; + BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0); + cache->flag |= PTCACHE_DISK_CACHE; + } + /* DISK -> MEM */ + else { + int cfra; + int sfra = cache->startframe; + int efra = cache->endframe; + + BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0); + + for(cfra=sfra; cfra <= efra; cfra++) { + pf = BKE_ptcache_file_open(pid, PTCACHE_FILE_READ, cfra); + + if(pf) { + pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache mem"); + pm->data = MEM_callocN(sizeof(float)*tot, "Pointcache mem data"); + + if(fread(pm->data, sizeof(float), tot, pf->fp)!= tot) { + printf("Error reading from disk cache\n"); + + cache->flag |= PTCACHE_DISK_CACHE; + + MEM_freeN(pm->data); + MEM_freeN(pm); + BKE_ptcache_file_close(pf); + return; + } + + pm->frame = cfra; + + BLI_addtail(&pid->cache->mem_cache, pm); + + BKE_ptcache_file_close(pf); + } + } + + cache->flag |= PTCACHE_DISK_CACHE; + BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0); + cache->flag &= ~PTCACHE_DISK_CACHE; + } +} \ No newline at end of file -- cgit v1.2.3 From 8ead648fd1ca35f02901764445afc7b675524b67 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 21 Jun 2009 16:18:38 +0000 Subject: Spring Cleaning * removed radiosity render code, DNA and RNA (left in radio render pass options), we'll get GI to replace this probably, better allow baking to vertex colors for people who used this. * removed deprecated solid physics library, sumo integrations and qhull, a dependency * removed ODE, was no longer being build or supported * remove BEOS and AMIGA defines and references in Makefiles. --- source/blender/blenkernel/BKE_utildefines.h | 2 +- source/blender/blenkernel/intern/blender.c | 1 - source/blender/blenkernel/intern/scene.c | 2 -- 3 files changed, 1 insertion(+), 4 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_utildefines.h b/source/blender/blenkernel/BKE_utildefines.h index 6584af085cd..8043eb74749 100644 --- a/source/blender/blenkernel/BKE_utildefines.h +++ b/source/blender/blenkernel/BKE_utildefines.h @@ -130,7 +130,7 @@ #define IN_RANGE(a, b, c) ((b < c)? ((bbase); seq_free_editing(sce->ed); - if(sce->radio) MEM_freeN(sce->radio); - sce->radio= 0; #ifndef DISABLE_PYTHON BPY_free_scriptlink(&sce->scriptlink); -- cgit v1.2.3 From b9f5676caac84b3795e0e0263744f1fad59cc6d5 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 21 Jun 2009 16:58:22 +0000 Subject: remove support for videoscape, amiga 3D app that came before lightwave. --- source/blender/blenkernel/BKE_exotic.h | 1 - source/blender/blenkernel/BKE_utildefines.h | 6 - source/blender/blenkernel/intern/exotic.c | 593 +--------------------------- 3 files changed, 2 insertions(+), 598 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_exotic.h b/source/blender/blenkernel/BKE_exotic.h index 11dc1f41109..5c47eeabfe8 100644 --- a/source/blender/blenkernel/BKE_exotic.h +++ b/source/blender/blenkernel/BKE_exotic.h @@ -47,7 +47,6 @@ int BKE_read_exotic(struct Scene *scene, char *name); void write_dxf(struct Scene *scene, char *str); void write_vrml(struct Scene *scene, char *str); -void write_videoscape(struct Scene *scene, char *str); void write_stl(struct Scene *scene, char *str); #endif diff --git a/source/blender/blenkernel/BKE_utildefines.h b/source/blender/blenkernel/BKE_utildefines.h index 8043eb74749..419f0f5beeb 100644 --- a/source/blender/blenkernel/BKE_utildefines.h +++ b/source/blender/blenkernel/BKE_utildefines.h @@ -148,12 +148,6 @@ #define ID_NEW(a) if( (a) && (a)->id.newid ) (a)= (void *)(a)->id.newid #define FORM MAKE_ID('F','O','R','M') -#define DDG1 MAKE_ID('3','D','G','1') -#define DDG2 MAKE_ID('3','D','G','2') -#define DDG3 MAKE_ID('3','D','G','3') -#define DDG4 MAKE_ID('3','D','G','4') - -#define GOUR MAKE_ID('G','O','U','R') #define BLEN MAKE_ID('B','L','E','N') #define DER_ MAKE_ID('D','E','R','_') diff --git a/source/blender/blenkernel/intern/exotic.c b/source/blender/blenkernel/intern/exotic.c index 929d3f942dc..f15e1c24949 100644 --- a/source/blender/blenkernel/intern/exotic.c +++ b/source/blender/blenkernel/intern/exotic.c @@ -27,47 +27,7 @@ * * - Blender Foundation * - * ***** END GPL LICENSE BLOCK ***** - * - * eigen videoscape formaat: - * - * - * lamp: - * 3DG2 - aantal_lampen - - type - spsi spbl - r, g, b, energy - locx, locy, locz - vecx, vecy, vecz - - - curve / nurbs: - 3DG3 - 5 of 11 (curve of surf) - aantal_nurbs - extr1 extr2 - - mat[0][0] mat[0][1] mat[0][2] mat[0][3] - mat[1][0] mat[1][1] mat[1][2] mat[1][3] - ... - - type - pntsu, pntsv - resolu, resolv - orderu, orderv - flagu, flagv - - (als type==nurb) x y z w - x y z w - ... - (als type==bez) xyz xyz xyz h1 h2 h3 - xyz xyz xyz h1 h2 h3 - ... - * - * - */ + * ***** END GPL LICENSE BLOCK *****/ #include /* isdigit, isspace */ @@ -482,385 +442,6 @@ static void read_stl_mesh_ascii(Scene *scene, char *str) #undef STLREADLINE #undef STLREADVERT -static void read_videoscape_mesh(Scene *scene, char *str) -{ - Object *ob; - Mesh *me; - MVert *mvert; - MFace *mface; - Material *ma; - FILE *fp; - float *vertdata, *vd, min[3], max[3], cent[3], ftemp; - unsigned int color[32], col; - int totcol, a, b, verts, tottria=0, totquad=0, totedge=0, poly, nr0, nr, first; - int end; - char s[50]; - - fp= fopen(str, "rb"); - if(fp==NULL) { - //XXX error("Can't read file"); - return; - } - - fscanf(fp, "%40s", s); - - fscanf(fp, "%d\n", &verts); - if(verts<=0) { - fclose(fp); - //XXX error("Read error"); - return; - } - - if(verts>MESH_MAX_VERTS) { - //XXX error("too many vertices"); - fclose(fp); - return; - } - - INIT_MINMAX(min, max); - vd= vertdata= MEM_mallocN(sizeof(float)*3*verts, "videoscapelezer"); - - for(a=0; a0) { - end= fscanf(fp,"%d", &poly); - if(end<=0) break; - - if(poly==3) tottria++; - else if(poly==4) totquad++; - else totedge+= poly; - - for(a=0;a=totcol && totcol<32) { - color[totcol]= col; - totcol++; - } - } - - /* new object */ - ob= add_object(scene, OB_MESH); - me= ob->data; - me->totvert= verts; - me->totface= totedge+tottria+totquad; - - me->mvert= CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, - NULL, me->totvert); - me->mface= CustomData_add_layer(&me->fdata, CD_MFACE, CD_CALLOC, - NULL, me->totface); - - /* colors */ - if(totcol) { - ob->mat= MEM_callocN(sizeof(void *)*totcol, "ob->mat"); - me->mat= MEM_callocN(sizeof(void *)*totcol, "me->mat"); - me->totcol= totcol; - ob->totcol= (unsigned char) me->totcol; - ob->actcol= 1; - } - - /* materials */ - for(a=0; amat.first; - while(ma) { - if(ma->mtex[0]==0) { - col= rgb_to_cpack(ma->r, ma->g, ma->b); - if(color[a]==col) { - me->mat[a]= ma; - ma->id.us++; - break; - } - } - ma= ma->id.next; - } - if(ma==0) { - ma= add_material("ext"); - me->mat[a]= ma; - cpack_to_rgb(color[a], cent, cent+1, cent+2); - ma->r= cent[0]; - ma->g= cent[1]; - ma->b= cent[2]; - automatname(ma); - } - } - - /* verts */ - - cent[0]= (min[0]+max[0])/2.0f; - cent[1]= (min[1]+max[1])/2.0f; - cent[2]= (min[2]+max[2])/2.0f; - VECCOPY(ob->loc, cent); - - a= me->totvert; - vd= vertdata; - mvert= me->mvert; - while(a--) { - VecSubf(mvert->co, vd, cent); - mvert++; - vd+= 3; - } - - /* faces */ - if(me->totface) { - rewind(fp); - - fscanf(fp, "%40s", s); - fscanf(fp, "%d\n", &verts); - /* fake read */ - for(a=0;atotface; - mface= me->mface; - while(a--) { - end= fscanf(fp,"%d", &poly); - if(end<=0) break; - - if(poly==3 || poly==4) { - fscanf(fp,"%d", &nr); - mface->v1= MIN2(nr, me->totvert-1); - fscanf(fp,"%d", &nr); - mface->v2= MIN2(nr, me->totvert-1); - fscanf(fp,"%d", &nr); - mface->v3= MIN2(nr, me->totvert-1); - if(poly==4) { - if( fscanf(fp,"%d", &nr) <=0 ) break; - mface->v4= MIN2(nr, me->totvert-1); - } - - test_index_face(mface, NULL, 0, poly); - - mface++; - } - else { - if( fscanf(fp,"%d", &nr0) <=0) break; - first= nr0; - for(b=1; btotvert-1); - mface->v1= nr; - mface->v2= nr0; - nr0= nr; - mface++; - a--; - } - mface->v1= first; - mface->v2= nr; - mface++; - if(end<=0) break; - } - end= fscanf(fp,"%i", &col); - col &= 0xF0F0F0; - if(end<=0) break; - - for(b=0; bmat_nr= b; - break; - } - } - } - } - - fclose(fp); - MEM_freeN(vertdata); - - mesh_add_normals_flags(me); - make_edges(me, 0); - - //XXX waitcursor(1); -} - -static void read_videoscape_lamp(Scene *scene, char *str) -{ - Object *ob; - Lamp *la; - FILE *fp; - float vec[3], q1[4]; - int tot, val; - char s[50]; - - fp= fopen(str, "rb"); - if(fp==NULL) { - //XXX error("Can't read file"); - return; - } - - fscanf(fp, "%40s", s); - fscanf(fp, "%d\n", &tot); - - while(tot--) { - ob= add_object(scene, OB_LAMP); - la= ob->data; - - fscanf(fp, "%d\n", &val); - la->type= val; - if(la->type==1) la->type= LA_SPOT; - else if(la->type==2) la->type= LA_SUN; - - fscanf(fp, "%f %f\n", &la->spotsize, &la->spotblend); - - fscanf(fp, "%f %f %f %f\n", &la->r, &la->g, &la->b, &la->energy); - - fscanf(fp, "%f %f %f\n", ob->loc, ob->loc+1, ob->loc+2); - val= fscanf(fp, "%f %f %f\n", vec, vec+1, vec+2); - vectoquat(vec, 5, 2, q1); - QuatToEul(q1, ob->rot); - - if(val<=0) break; - - } - fclose(fp); -} - -static void read_videoscape_nurbs(Scene *scene, char *str) -{ - Object *ob; - Curve *cu; - Nurb *nu; - BezTriple *bezt; - BPoint *bp; - FILE *fp; - float tmat[4][4], omat[3][3], imat[3][3], mat[3][3]; - int a, tot, type, val; - char s[50]; - - fp= fopen(str, "rb"); - if(fp==NULL) { - //XXX error("Can't read file"); - return; - } - - fscanf(fp, "%40s", s); - fscanf(fp, "%d\n", &type); - - if(type==5) ob= add_object(scene, OB_SURF); - else ob= add_object(scene, OB_CURVE); - cu= ob->data; - - fscanf(fp, "%d\n", &tot); - fscanf(fp, "%d %d\n", &type, &val); - - cu->ext1= 0.002f*type; - cu->ext2= 0.002f*val; - - for(a=0; a<4; a++) fscanf(fp, "%e %e %e %e\n", tmat[a], tmat[a]+1, tmat[a]+2, tmat[a]+3); - - VECCOPY(ob->loc, tmat[3]); - - Mat3CpyMat4(omat, tmat); - Mat3ToEul(omat, ob->rot); - EulToMat3(ob->rot, mat); - Mat3Inv(imat, mat); - Mat3MulMat3((float ( * )[3])tmat, imat, omat); - - while(tot--) { - nu= (Nurb*)MEM_callocN(sizeof(Nurb),"nu from exotic"); - BLI_addtail(&cu->nurb, nu); - - fscanf(fp, "%d\n", &type); - nu->type= type; - - fscanf(fp, "%d %d\n", &type, &val); - nu->pntsu= type; nu->pntsv= val; - fscanf(fp, "%d %d\n", &type, &val); - nu->resolu= type; nu->resolv= val; - fscanf(fp, "%d %d\n", &type, &val); - nu->orderu= type; nu->orderv= val; - fscanf(fp, "%d %d\n", &type, &val); - nu->flagu= type; nu->flagv= val; - - if( (nu->type & 7)==CU_BEZIER) { - a= nu->pntsu; - nu->bezt= bezt= MEM_callocN(a*sizeof(BezTriple), "bezt from exotic"); - while(a--) { - fscanf(fp, "%f %f %f ", bezt->vec[0], bezt->vec[0]+1, bezt->vec[0]+2); - Mat4MulVecfl(tmat, bezt->vec[0]); - fscanf(fp, "%f %f %f ", bezt->vec[1], bezt->vec[1]+1, bezt->vec[1]+2); - Mat4MulVecfl(tmat, bezt->vec[1]); - fscanf(fp, "%f %f %f ", bezt->vec[2], bezt->vec[2]+1, bezt->vec[2]+2); - Mat4MulVecfl(tmat, bezt->vec[2]); - fscanf(fp, "%d %d\n", &type, &val); - bezt->h1= type; - bezt->h2= val; - bezt++; - } - } - else { - a= nu->pntsu*nu->pntsv; - if(a) { - nu->bp= bp= MEM_callocN(a*sizeof(BPoint), "bp from exotic"); - while(a--) { - fscanf(fp, "%f %f %f %f\n", bp->vec, bp->vec+1, bp->vec+2, bp->vec+3); - Mat4MulVecfl(tmat, bp->vec); - bp++; - } - - val= KNOTSU(nu); - nu->knotsu= MEM_mallocN(sizeof(float)*val, "knots"); - for(a=0; aknotsu+a); - - if(nu->pntsv>1) { - val= KNOTSV(nu); - nu->knotsv= MEM_mallocN(sizeof(float)*val, "knots"); - for(a=0; aknotsv+a); - } - } - else { - BLI_remlink(&cu->nurb, nu); - MEM_freeN(nu); - } - } - } - fclose(fp); -} - -static void read_videoscape(Scene *scene, char *str) -{ - int file, type; - unsigned int val; - unsigned short numlen; - char name[FILE_MAXDIR+FILE_MAXFILE], head[FILE_MAXDIR+FILE_MAXFILE], tail[FILE_MAXFILE]; - - strcpy(name, str); - - while( TRUE ) { - file= open(name, O_BINARY|O_RDONLY); - if(file<=0) break; - else { - read(file, &type, 4); - close(file); - - if(type==DDG1) read_videoscape_mesh(scene, name); - else if(type==DDG2) read_videoscape_lamp(scene, name); - else if(type==DDG3) read_videoscape_nurbs(scene, name); - } - - val = BLI_stringdec(name, head, tail, &numlen); - BLI_stringenc(name, head, tail, numlen, val + 1); - - } -} - - /* ***************** INVENTOR ******************* */ @@ -2204,16 +1785,7 @@ int BKE_read_exotic(Scene *scene, char *name) if ((*s0 != FORM) && (strncmp(str, "BLEN", 4) != 0) && !BLI_testextensie(name,".blend.gz")) { //XXX waitcursor(1); - - if(ELEM4(*s0, DDG1, DDG2, DDG3, DDG4)) { - if(0) { // XXX obedit) { - //XXX error("Unable to perform function in EditMode"); - } else { - read_videoscape(scene, name); - retval = 1; - } - } - else if(strncmp(str, "#Inventor V1.0", 14)==0) { + if(strncmp(str, "#Inventor V1.0", 14)==0) { if( strncmp(str+15, "ascii", 5)==0) { read_inventor(scene, name, &lbase); displist_to_objects(scene, &lbase); @@ -2385,167 +1957,6 @@ void write_stl(Scene *scene, char *str) //XXX waitcursor(0); } -static void write_videoscape_mesh(Scene *scene, Object *ob, char *str) -{ - Mesh *me= ob->data; - EditMesh *em = BKE_mesh_get_editmesh(me); - Material *ma; - MFace *mface; - FILE *fp; - EditVert *eve; - EditFace *evl; - unsigned int kleur[32]; - float co[3]; - int a; - intptr_t tot; - char *cp; - - if(ob && ob->type==OB_MESH); - else { - return; - } - - kleur[0]= 0x00C0C0C0; - - cp= (char *)kleur; - for(a=0; atotcol; a++, cp+=4) { - - ma= give_current_material(ob, a+1); - if(ma) { - cp[0]= (unsigned char) (255.0*ma->emit); - cp[1]= (unsigned char) (255.0*ma->b); - cp[2]= (unsigned char) (255.0*ma->g); - cp[3]= (unsigned char) (255.0*ma->r); - if(ENDIAN_ORDER==L_ENDIAN) SWITCH_INT(kleur[a]); - } - else kleur[a]= 0x00C0C0C0; - - if(a>30) break; - } - - fp= fopen(str, "wb"); - if(fp==NULL) return; - - fprintf(fp,"3DG1\n"); - - if(em) { - - fprintf(fp, "%d\n", em->totvert); - - tot= 0; - eve= em->verts.first; - while(eve) { - VECCOPY(co, eve->co); - Mat4MulVecfl(ob->obmat, co); - fprintf(fp, "%f %f %f\n", co[0], co[1], co[2] ); - eve->tmp.l = tot; - tot++; - eve= eve->next; - } - evl= em->faces.first; - while(evl) { - - if(evl->v4==0) { - fprintf(fp, "3 %ld %ld %ld 0x%x\n", - (intptr_t) evl->v1->tmp.l, - (intptr_t) evl->v2->tmp.l, - (intptr_t) evl->v3->tmp.l, - kleur[evl->mat_nr]); - } - else { - fprintf(fp, "4 %ld %ld %ld %ld 0x%x\n", - (intptr_t) evl->v1->tmp.l, - (intptr_t) evl->v2->tmp.l, - (intptr_t) evl->v3->tmp.l, - (intptr_t) evl->v4->tmp.l, - kleur[evl->mat_nr]); - } - evl= evl->next; - } - } - else { - DerivedMesh *dm = mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH); - - me= ob->data; - - fprintf(fp, "%d\n", me->totvert); - - mface= me->mface; - for(a=0; atotvert; a++) { - dm->getVertCo(dm, a, co); - Mat4MulVecfl(ob->obmat, co); - fprintf(fp, "%f %f %f\n", co[0], co[1], co[2] ); - } - for(a=0; atotface; a++, mface++) { - if(mface->v4==0) { - fprintf(fp, "3 %d %d %d 0x%x\n", mface->v1, mface->v2, mface->v3, kleur[(int)mface->mat_nr]); - } - else { - fprintf(fp, "4 %d %d %d %d 0x%x\n", mface->v1, mface->v2, mface->v3, mface->v4, kleur[(int)mface->mat_nr]); - } - } - - dm->release(dm); - } - - fclose(fp); - - if (em) BKE_mesh_end_editmesh(me, em); - -} - - -void write_videoscape(Scene *scene, char *str) -{ - Base *base; - int file, val, lampdone=0; - unsigned short numlen; - char head[FILE_MAXFILE], tail[FILE_MAXFILE]; - - if(BLI_testextensie(str,".trace")) str[ strlen(str)-6]= 0; - if(BLI_testextensie(str,".blend")) str[ strlen(str)-6]= 0; - if(BLI_testextensie(str,".ble")) str[ strlen(str)-4]= 0; - if(BLI_testextensie(str,".obj")==0) strcat(str, ".obj"); - - file= open(str,O_BINARY|O_RDONLY); - close(file); - //XXX saveover() - // if(file>-1) if(!during_script() && saveover(str)==0) return; - - strcpy(temp_dir, str); - - base= scene->base.first; - while(base) { - if((base->flag & SELECT) && (base->lay & scene->lay)) { - if(base->object->type==OB_MESH) { - write_videoscape_mesh(scene, base->object, str); - val = BLI_stringdec(str, head, tail, &numlen); - BLI_stringenc(str, head, tail, numlen, val + 1); - } - else if(base->object->type==OB_CURVE || base->object->type==OB_SURF) { - /* write_videoscape_nurbs(base->object, str); */ - /* val = stringdec(str, head, tail, &numlen); */ - /* stringenc(str, head, tail, numlen, val + 1); */ - } - else if(lampdone==0 && base->object->type==OB_LAMP) { - /* lampdone= 1; */ - /* write_videoscape_lamps(str); */ - /* val = stringdec(str, head, tail, &numlen); */ - /* stringenc(str, head, tail, numlen, val + 1); */ - } - } - base= base->next; - } - - - /* remove when higher numbers exist */ - while(remove(str)==0) { - - val = BLI_stringdec(str, head, tail, &numlen); - BLI_stringenc(str, head, tail, numlen, val + 1); - } -} - /* ******************************* WRITE VRML ***************************** */ static void replace_chars(char *str1, char *str2) -- cgit v1.2.3 From e7d02e567990b8cac05565501e0b74a9bb195a6d Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 22 Jun 2009 18:19:18 +0000 Subject: 2.5: warning fixes Mostly harmless ones, except for one about "gzopen64" being undeclared. This needs some defines in BLI_storage.h to be set before is included. Might fix a crash in compressed file reading, though I'm not sure since it's hard to repeat the crash consistently. --- source/blender/blenkernel/intern/constraint.c | 8 ++++---- source/blender/blenkernel/intern/effect.c | 2 ++ source/blender/blenkernel/intern/exotic.c | 1 + source/blender/blenkernel/intern/fluidsim.c | 2 ++ source/blender/blenkernel/intern/idprop.c | 8 ++++---- source/blender/blenkernel/intern/particle_system.c | 12 +++++++++--- source/blender/blenkernel/intern/pointcache.c | 4 +--- 7 files changed, 23 insertions(+), 14 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index a43389a2ef6..88e73a00ba7 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -3028,7 +3028,7 @@ static void transform_evaluate (bConstraint *con, bConstraintOb *cob, ListBase * if (VALID_CONS_TARGET(ct)) { float loc[3], eul[3], size[3]; float dvec[3], sval[3]; - short i; + int i; /* obtain target effect */ switch (data->from) { @@ -3075,7 +3075,7 @@ static void transform_evaluate (bConstraint *con, bConstraintOb *cob, ListBase * switch (data->to) { case 2: /* scaling */ for (i=0; i<3; i++) - size[i]= data->to_min[i] + (sval[data->map[i]] * (data->to_max[i] - data->to_min[i])); + size[i]= data->to_min[i] + (sval[(int)data->map[i]] * (data->to_max[i] - data->to_min[i])); break; case 1: /* rotation */ for (i=0; i<3; i++) { @@ -3085,7 +3085,7 @@ static void transform_evaluate (bConstraint *con, bConstraintOb *cob, ListBase * tmax= data->to_max[i]; /* all values here should be in degrees */ - eul[i]= tmin + (sval[data->map[i]] * (tmax - tmin)); + eul[i]= tmin + (sval[(int)data->map[i]] * (tmax - tmin)); /* now convert final value back to radians */ eul[i] = (float)(eul[i] / 180 * M_PI); @@ -3094,7 +3094,7 @@ static void transform_evaluate (bConstraint *con, bConstraintOb *cob, ListBase * default: /* location */ /* get new location */ for (i=0; i<3; i++) - loc[i]= (data->to_min[i] + (sval[data->map[i]] * (data->to_max[i] - data->to_min[i]))); + loc[i]= (data->to_min[i] + (sval[(int)data->map[i]] * (data->to_max[i] - data->to_min[i]))); /* add original location back on (so that it can still be moved) */ VecAddf(loc, cob->matrix[3], loc); diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index 9858025af5a..eaa2d541638 100644 --- a/source/blender/blenkernel/intern/effect.c +++ b/source/blender/blenkernel/intern/effect.c @@ -29,6 +29,8 @@ * ***** END GPL LICENSE BLOCK ***** */ +#include "BLI_storage.h" /* _LARGEFILE_SOURCE */ + #include #include diff --git a/source/blender/blenkernel/intern/exotic.c b/source/blender/blenkernel/intern/exotic.c index f15e1c24949..4e7e76dfae3 100644 --- a/source/blender/blenkernel/intern/exotic.c +++ b/source/blender/blenkernel/intern/exotic.c @@ -29,6 +29,7 @@ * * ***** END GPL LICENSE BLOCK *****/ +#include "BLI_storage.h" #include /* isdigit, isspace */ #include diff --git a/source/blender/blenkernel/intern/fluidsim.c b/source/blender/blenkernel/intern/fluidsim.c index 9eefd48cae4..54008185f72 100644 --- a/source/blender/blenkernel/intern/fluidsim.c +++ b/source/blender/blenkernel/intern/fluidsim.c @@ -28,6 +28,8 @@ * ***** END GPL LICENSE BLOCK ***** */ +#include "BLI_storage.h" /* _LARGEFILE_SOURCE */ + #include "MEM_guardedalloc.h" #include "DNA_mesh_types.h" diff --git a/source/blender/blenkernel/intern/idprop.c b/source/blender/blenkernel/intern/idprop.c index 3be47778674..54366aadd92 100644 --- a/source/blender/blenkernel/intern/idprop.c +++ b/source/blender/blenkernel/intern/idprop.c @@ -230,16 +230,16 @@ void IDP_ResizeArray(IDProperty *prop, int newlen) */ newsize = (newsize >> 3) + (newsize < 9 ? 3 : 6) + newsize; - newarr = MEM_callocN(idp_size_table[prop->subtype]*newsize, "idproperty array resized"); + newarr = MEM_callocN(idp_size_table[(int)prop->subtype]*newsize, "idproperty array resized"); if (newlen >= prop->len) { /* newlen is bigger*/ - memcpy(newarr, prop->data.pointer, prop->len*idp_size_table[prop->subtype]); + memcpy(newarr, prop->data.pointer, prop->len*idp_size_table[(int)prop->subtype]); idp_resize_group_array(prop, newlen, newarr); } else { /* newlen is smaller*/ idp_resize_group_array(prop, newlen, newarr); - memcpy(newarr, prop->data.pointer, newlen*prop->len*idp_size_table[prop->subtype]); + memcpy(newarr, prop->data.pointer, newlen*prop->len*idp_size_table[(int)prop->subtype]); } MEM_freeN(prop->data.pointer); @@ -546,7 +546,7 @@ int IDP_EqualsProperties(IDProperty *prop1, IDProperty *prop2) return BSTR_EQ(IDP_String(prop1), IDP_String(prop2)); else if(prop1->type == IDP_ARRAY) { if(prop1->len == prop2->len && prop1->subtype == prop2->subtype) - return memcmp(IDP_Array(prop1), IDP_Array(prop2), idp_size_table[prop1->subtype]*prop1->len); + return memcmp(IDP_Array(prop1), IDP_Array(prop2), idp_size_table[(int)prop1->subtype]*prop1->len); else return 0; } diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index fc6413849d1..97b1956bba9 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -29,6 +29,8 @@ * ***** END GPL LICENSE BLOCK ***** */ +#include "BLI_storage.h" /* _LARGEFILE_SOURCE */ + #include #include #include @@ -2203,12 +2205,15 @@ void psys_get_pointcache_start_end(Scene *scene, ParticleSystem *psys, int *sfra *sfra = MAX2(1, (int)part->sta); *efra = MIN2((int)(part->end + part->lifetime + 1.0), scene->r.efra); } -static float *particle_state_ptr(int index, ParticleSystem *psys) +static float *particle_state_ptr(int index, void *psys_ptr) { + ParticleSystem *psys= psys_ptr; + return (float *)(&(psys->particles+index)->state); } -static void particle_read_state(int index, ParticleSystem *psys, float *data) +static void particle_read_state(int index, void *psys_ptr, float *data) { + ParticleSystem *psys= psys_ptr; ParticleData *pa = psys->particles + index; ParticleKey *key = (ParticleKey *)data; @@ -2217,8 +2222,9 @@ static void particle_read_state(int index, ParticleSystem *psys, float *data) copy_particle_key(&pa->state, key, 1); } -static void particle_cache_interpolate(int index, ParticleSystem *psys, float frs_sec, float cfra, int cfra1, int cfra2, float *data1, float *data2) +static void particle_cache_interpolate(int index, void *psys_ptr, float frs_sec, float cfra, int cfra1, int cfra2, float *data1, float *data2) { + ParticleSystem *psys= psys_ptr; ParticleData *pa = psys->particles + index; ParticleKey keys[4]; float dfra; diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index f59336518d7..b514ac026fb 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -1050,7 +1050,6 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker) int endframe = CFRA; int bake = baker->bake; int render = baker->render; - int end = 0; G.afbreek = 0; @@ -1162,7 +1161,6 @@ void BKE_ptcache_toggle_disk_cache(PTCacheID *pid) { int totelem=0; int float_count=0; int tot; - int write_error=0; if (!G.relbase_valid){ cache->flag &= ~PTCACHE_DISK_CACHE; @@ -1243,4 +1241,4 @@ void BKE_ptcache_toggle_disk_cache(PTCacheID *pid) { BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0); cache->flag &= ~PTCACHE_DISK_CACHE; } -} \ No newline at end of file +} -- cgit v1.2.3 From 333e231fa6c8e44582d94fedd2dda958e5131316 Mon Sep 17 00:00:00 2001 From: "Guillermo S. Romero" Date: Tue, 23 Jun 2009 00:09:26 +0000 Subject: SVN maintenance. --- source/blender/blenkernel/BKE_gpencil.h | 2 +- source/blender/blenkernel/intern/gpencil.c | 2 +- source/blender/blenkernel/intern/sequence.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_gpencil.h b/source/blender/blenkernel/BKE_gpencil.h index 581285be21c..1892c8e71a4 100644 --- a/source/blender/blenkernel/BKE_gpencil.h +++ b/source/blender/blenkernel/BKE_gpencil.h @@ -1,5 +1,5 @@ /** - * $Id: BDR_gpencil.h 19541 2009-04-05 06:54:47Z aligorith $ + * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** * diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c index 6086aa58d40..dd8f44c71d5 100644 --- a/source/blender/blenkernel/intern/gpencil.c +++ b/source/blender/blenkernel/intern/gpencil.c @@ -1,5 +1,5 @@ /** - * $Id: gpencil.c 19758 2009-04-16 13:10:08Z aligorith $ + * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** * diff --git a/source/blender/blenkernel/intern/sequence.c b/source/blender/blenkernel/intern/sequence.c index bb0665a5b0f..7fc262b4796 100644 --- a/source/blender/blenkernel/intern/sequence.c +++ b/source/blender/blenkernel/intern/sequence.c @@ -1,5 +1,5 @@ /** -* $Id: sequence.c 17508 2008-11-20 00:34:24Z campbellbarton $ +* $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** * -- cgit v1.2.3 From e2b6cea3b95ca41854661726ccea684421738c8f Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Tue, 23 Jun 2009 00:41:55 +0000 Subject: 2.5: Tool Settings * Moved proportional edit, snap, autokey mode, and a few others from Scene to ToolSettings. * RNA wrapped properties in ToolSettings for the UV editor: proportional edit, snap settings, selection modes. --- source/blender/blenkernel/intern/scene.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 3b51af57e0b..23da5c66850 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -203,9 +203,6 @@ Scene *add_scene(char *name) sce= alloc_libblock(&G.main->scene, ID_SCE, name); sce->lay= 1; - sce->selectmode= SCE_SELECT_VERTEX; - sce->editbutsize= 0.1; - sce->autokey_mode= U.autokey_mode; sce->r.mode= R_GAMMA; sce->r.cfra= 1; @@ -275,6 +272,10 @@ Scene *add_scene(char *name) sce->toolsettings->select_thresh= 0.01f; sce->toolsettings->jointrilimit = 0.8f; + sce->toolsettings->selectmode= SCE_SELECT_VERTEX; + sce->toolsettings->normalsize= 0.1; + sce->toolsettings->autokey_mode= U.autokey_mode; + sce->toolsettings->skgen_resolution = 100; sce->toolsettings->skgen_threshold_internal = 0.01f; sce->toolsettings->skgen_threshold_external = 0.01f; -- cgit v1.2.3 From b4acd77526f32faab0c3d86436eef56096985c3d Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Tue, 23 Jun 2009 13:25:31 +0000 Subject: NLA SoC: Big Commit - Restored NLA-Mapping Corrections In TweakMode, the keyframes of the Active Action are now shown (and can be edited) in NLA-mapped time, with appropriate corrections applied when editing. This works in the DopeSheet and Graph Editors :) To do this, got rid of the old wrappers/API-methods, replacing them with new-style ones. A few methods previously (in this branch) used only for evaluation are now used for this purpose too. As the same code is used for editing + evaluation, this should now be much better to work with. I've only done a few brief tests now, but I think I might've muddled the invert-flags on one or two cases which I'll need to check out tomorrow. So, beware that there may be some weird and critical bugs for the next few days here... Also, added proper license headers to new NLA files. TODO: - testing + bugfixing due to this commit - show range of keyframes in NLA Editor active-action line --- source/blender/blenkernel/BKE_action.h | 6 -- source/blender/blenkernel/BKE_nla.h | 2 + source/blender/blenkernel/intern/action.c | 42 -------- source/blender/blenkernel/intern/anim_sys.c | 158 ++++++---------------------- source/blender/blenkernel/intern/fcurve.c | 29 ++++- source/blender/blenkernel/intern/nla.c | 136 ++++++++++++++++++++++++ source/blender/blenkernel/nla_private.h | 78 ++++++++++++++ 7 files changed, 274 insertions(+), 177 deletions(-) create mode 100644 source/blender/blenkernel/nla_private.h (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h index 1fb200b94a8..0c9bba5e413 100644 --- a/source/blender/blenkernel/BKE_action.h +++ b/source/blender/blenkernel/BKE_action.h @@ -148,12 +148,6 @@ void copy_pose_result(struct bPose *to, struct bPose *from); /* clear all transforms */ void rest_pose(struct bPose *pose); -/* map global time (frame nr) to strip converted time, doesn't clip */ -float get_action_frame(struct Object *ob, float cframe); -/* map strip time to global time (frame nr) */ -float get_action_frame_inv(struct Object *ob, float cframe); - - /* functions used by the game engine */ void game_copy_pose(struct bPose **dst, struct bPose *src); void game_free_pose(struct bPose *pose); diff --git a/source/blender/blenkernel/BKE_nla.h b/source/blender/blenkernel/BKE_nla.h index 5200ca6d4d7..cc73ac02690 100644 --- a/source/blender/blenkernel/BKE_nla.h +++ b/source/blender/blenkernel/BKE_nla.h @@ -73,5 +73,7 @@ void BKE_nla_action_pushdown(struct AnimData *adt); short BKE_nla_tweakmode_enter(struct AnimData *adt); void BKE_nla_tweakmode_exit(struct AnimData *adt); +float BKE_nla_tweakedit_remap(struct AnimData *adt, float cframe, short invert); + #endif diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index f88e249d38c..96896509f60 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -769,48 +769,6 @@ void framechange_poses_clear_unkeyed(void) /* ************** time ****************** */ -static bActionStrip *get_active_strip(Object *ob) -{ -#if 0 // XXX old animation system - bActionStrip *strip; - - if(ob->action==NULL) - return NULL; - - for (strip=ob->nlastrips.first; strip; strip=strip->next) - if(strip->flag & ACTSTRIP_ACTIVE) - break; - - if(strip && strip->act==ob->action) - return strip; -#endif // XXX old animation system - - return NULL; -} - -/* if the conditions match, it converts current time to strip time */ -// TODO: change this adt -float get_action_frame(Object *ob, float cframe) -{ - bActionStrip *strip= get_active_strip(ob); - - //if(strip) - // return get_actionstrip_frame(strip, cframe, 0); - return cframe; -} - -/* inverted, strip time to current time */ -// TODO: change this to adt -float get_action_frame_inv(Object *ob, float cframe) -{ - bActionStrip *strip= get_active_strip(ob); - - //if(strip) - // return get_actionstrip_frame(strip, cframe, 1); - return cframe; -} - - /* Check if the given action has any keyframes */ short action_has_motion(const bAction *act) { diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 7a6706b7c5a..877353a85e9 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -1,5 +1,30 @@ -/* Testing code for new animation system in 2.5 - * Copyright 2009, Joshua Leung +/** + * $Id: anim_sys.c 21023 2009-06-20 04:02:49Z aligorith $ + * + * ***** 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) 2009 Blender Foundation, Joshua Leung + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Joshua Leung (full recode) + * + * ***** END GPL LICENSE BLOCK ***** */ #include @@ -14,6 +39,8 @@ #include "BLI_arithb.h" #include "BLI_dynstr.h" +#include "DNA_anim_types.h" + #include "BKE_animsys.h" #include "BKE_action.h" #include "BKE_fcurve.h" @@ -25,7 +52,7 @@ #include "RNA_access.h" #include "RNA_types.h" -#include "DNA_anim_types.h" +#include "nla_private.h" /* ***************************************** */ /* AnimData API */ @@ -549,129 +576,6 @@ void animsys_evaluate_action (PointerRNA *ptr, bAction *act, AnimMapper *remap, /* ***************************************** */ /* NLA System - Evaluation */ -/* used for list of strips to accumulate at current time */ -typedef struct NlaEvalStrip { - struct NlaEvalStrip *next, *prev; - - NlaTrack *track; /* track that this strip belongs to */ - NlaStrip *strip; /* strip that's being used */ - - short track_index; /* the index of the track within the list */ - short strip_mode; /* which end of the strip are we looking at */ - - float strip_time; /* time at which which strip is being evaluated */ -} NlaEvalStrip; - -/* NlaEvalStrip->strip_mode */ -enum { - /* standard evaluation */ - NES_TIME_BEFORE = -1, - NES_TIME_WITHIN, - NES_TIME_AFTER, - - /* transition-strip evaluations */ - NES_TIME_TRANSITION_START, - NES_TIME_TRANSITION_END, -} eNlaEvalStrip_StripMode; - - -/* temp channel for accumulating data from NLA (avoids needing to clear all values first) */ -// TODO: maybe this will be used as the 'cache' stuff needed for editable values too? -typedef struct NlaEvalChannel { - struct NlaEvalChannel *next, *prev; - - PointerRNA ptr; /* pointer to struct containing property to use */ - PropertyRNA *prop; /* RNA-property type to use (should be in the struct given) */ - int index; /* array index (where applicable) */ - - float value; /* value of this channel */ -} NlaEvalChannel; - - -/* ---------------------- */ - -/* non clipped mapping for strip-time <-> global time (for Action-Clips) - * invert = convert action-strip time to global time - */ -static float nlastrip_get_frame_actionclip (NlaStrip *strip, float cframe, short invert) -{ - float length, actlength, repeat, scale; - - /* get number of repeats */ - if (IS_EQ(strip->repeat, 0.0f)) strip->repeat = 1.0f; - repeat = strip->repeat; - - /* scaling */ - if (IS_EQ(strip->scale, 0.0f)) strip->scale= 1.0f; - scale = (float)fabs(strip->scale); /* scale must be positive - we've got a special flag for reversing */ - - /* length of referenced action */ - actlength = strip->actend - strip->actstart; - if (IS_EQ(actlength, 0.0f)) actlength = 1.0f; - - /* length of strip */ - length= actlength * scale * repeat; - if (IS_EQ(length, 0.0f)) length= strip->end - strip->start; - - /* reversed = play strip backwards */ - if (strip->flag & NLASTRIP_FLAG_REVERSE) { - /* invert = convert action-strip time to global time */ - if (invert) - return length*(strip->actend - cframe)/(repeat*actlength) + strip->start; - else - return strip->actend - repeat*actlength*(cframe - strip->start)/length; - } - else { - /* invert = convert action-strip time to global time */ - if (invert) - return length*(cframe - strip->actstart)/(repeat*actlength) + strip->start; - else - return repeat*actlength*(cframe - strip->start)/length + strip->actstart; - } -} - -/* non clipped mapping for strip-time <-> global time (for Transitions) - * invert = convert action-strip time to global time - */ -static float nlastrip_get_frame_transition (NlaStrip *strip, float cframe, short invert) -{ - float length; - - /* length of strip */ - length= strip->end - strip->start; - - /* reversed = play strip backwards */ - if (strip->flag & NLASTRIP_FLAG_REVERSE) { - /* invert = convert within-strip-time to global time */ - if (invert) - return strip->end - (length * cframe); - else - return (strip->end - cframe) / length; - } - else { - /* invert = convert within-strip-time to global time */ - if (invert) - return (length * cframe) + strip->start; - else - return (cframe - strip->start) / length; - } -} - -/* non clipped mapping for strip-time <-> global time - * invert = convert action-strip time to global time - */ -static float nlastrip_get_frame (NlaStrip *strip, float cframe, short invert) -{ - switch (strip->type) { - case NLASTRIP_TYPE_TRANSITION: /* transition */ - return nlastrip_get_frame_transition(strip, cframe, invert); - - case NLASTRIP_TYPE_CLIP: /* action-clip (default) */ - default: - return nlastrip_get_frame_actionclip(strip, cframe, invert); - } -} - /* calculate influence of strip based for given frame based on blendin/out values */ static float nlastrip_get_influence (NlaStrip *strip, float cframe) { @@ -695,7 +599,7 @@ static float nlastrip_get_influence (NlaStrip *strip, float cframe) } /* evaluate the evaluation time and influence for the strip, storing the results in the strip */ -void nlastrip_evaluate_controls (NlaStrip *strip, float ctime) +static void nlastrip_evaluate_controls (NlaStrip *strip, float ctime) { /* firstly, analytically generate values for influence and time (if applicable) */ if ((strip->flag & NLASTRIP_FLAG_USR_TIME) == 0) diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index 856930e5a44..27ca6332cdc 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -1,5 +1,30 @@ -/* Testing code for new animation system in 2.5 - * Copyright 2009, Joshua Leung +/** + * $Id: fcurve.c 21023 2009-06-20 04:02:49Z aligorith $ + * + * ***** 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) 2009 Blender Foundation, Joshua Leung + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Joshua Leung (full recode) + * + * ***** END GPL LICENSE BLOCK ***** */ diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index 1ce6d9f98c7..a5b3b59d310 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -49,6 +49,9 @@ #include "BKE_object.h" #include "BKE_utildefines.h" +#include "RNA_access.h" +#include "nla_private.h" + #ifdef HAVE_CONFIG_H #include @@ -318,6 +321,135 @@ NlaStrip *add_nlastrip_to_stack (AnimData *adt, bAction *act) return strip; } +/* *************************************************** */ +/* NLA Evaluation <-> Editing Stuff */ + +/* Strip Mapping ------------------------------------- */ + +/* non clipped mapping for strip-time <-> global time (for Action-Clips) + * invert = convert action-strip time to global time + */ +static float nlastrip_get_frame_actionclip (NlaStrip *strip, float cframe, short invert) +{ + float length, actlength, repeat, scale; + + /* get number of repeats */ + if (IS_EQ(strip->repeat, 0.0f)) strip->repeat = 1.0f; + repeat = strip->repeat; + + /* scaling */ + if (IS_EQ(strip->scale, 0.0f)) strip->scale= 1.0f; + scale = (float)fabs(strip->scale); /* scale must be positive - we've got a special flag for reversing */ + + /* length of referenced action */ + actlength = strip->actend - strip->actstart; + if (IS_EQ(actlength, 0.0f)) actlength = 1.0f; + + /* length of strip */ + length= actlength * scale * repeat; + if (IS_EQ(length, 0.0f)) length= strip->end - strip->start; + + /* reversed = play strip backwards */ + if (strip->flag & NLASTRIP_FLAG_REVERSE) { + /* invert = convert action-strip time to global time */ + if (invert) + return length*(strip->actend - cframe)/(repeat*actlength) + strip->start; + else + return strip->actend - repeat*actlength*(cframe - strip->start)/length; + } + else { + /* invert = convert action-strip time to global time */ + if (invert) + return length*(cframe - strip->actstart)/(repeat*actlength) + strip->start; + else + return repeat*actlength*(cframe - strip->start)/length + strip->actstart; + } +} + +/* non clipped mapping for strip-time <-> global time (for Transitions) + * invert = convert action-strip time to global time + */ +static float nlastrip_get_frame_transition (NlaStrip *strip, float cframe, short invert) +{ + float length; + + /* length of strip */ + length= strip->end - strip->start; + + /* reversed = play strip backwards */ + if (strip->flag & NLASTRIP_FLAG_REVERSE) { + /* invert = convert within-strip-time to global time */ + if (invert) + return strip->end - (length * cframe); + else + return (strip->end - cframe) / length; + } + else { + /* invert = convert within-strip-time to global time */ + if (invert) + return (length * cframe) + strip->start; + else + return (cframe - strip->start) / length; + } +} + +/* non clipped mapping for strip-time <-> global time + * invert = convert action-strip time to global time + * + * only secure for 'internal' (i.e. within AnimSys evaluation) operations, + * but should not be directly relied on for stuff which interacts with editors + */ +float nlastrip_get_frame (NlaStrip *strip, float cframe, short invert) +{ + switch (strip->type) { + case NLASTRIP_TYPE_TRANSITION: /* transition */ + return nlastrip_get_frame_transition(strip, cframe, invert); + + case NLASTRIP_TYPE_CLIP: /* action-clip (default) */ + default: + return nlastrip_get_frame_actionclip(strip, cframe, invert); + } +} + + +/* Non clipped mapping for strip-time <-> global time + * invert = convert strip-time to global time + * + * Public API method - perform this mapping using the given AnimData block + * and perform any necessary sanity checks on the value + */ +float BKE_nla_tweakedit_remap (AnimData *adt, float cframe, short invert) +{ + NlaStrip *strip; + + /* sanity checks + * - obviously we've got to have some starting data + * - when not in tweakmode, the active Action does not have any scaling applied :) + */ + if ((adt == NULL) || (adt->flag & ADT_NLA_EDIT_ON)==0) + return cframe; + + /* if the active-strip info has been stored already, access this, otherwise look this up + * and store for (very probable) future usage + */ + if (adt->actstrip == NULL) { + NlaTrack *nlt= BKE_nlatrack_find_active(adt); + adt->actstrip= BKE_nlastrip_find_active(nlt); + } + strip= adt->actstrip; + + /* sanity checks + * - in rare cases, we may not be able to find this strip for some reason (internal error) + * - for now, if the user has defined a curve to control the time, this correction cannot be performed + * reliably... + */ + if ((strip == NULL) || (strip->flag & NLASTRIP_FLAG_USR_TIME)) + return cframe; + + /* perform the correction now... */ + return nlastrip_get_frame(strip, cframe, invert); +} + /* *************************************************** */ /* Basic Utilities */ @@ -693,9 +825,11 @@ short BKE_nla_tweakmode_enter (AnimData *adt) * - 'real' active action to temp storage (no need to change user-counts) * - action of active strip set to be the 'active action', and have its usercount incremented * - editing-flag for this AnimData block should also get turned on (for more efficient restoring) + * - take note of the active strip for mapping-correction of keyframes in the action being edited */ adt->tmpact= adt->action; adt->action= activeStrip->act; + adt->actstrip= activeStrip; id_us_plus(&activeStrip->act->id); adt->flag |= ADT_NLA_EDIT_ON; @@ -734,10 +868,12 @@ void BKE_nla_tweakmode_exit (AnimData *adt) * - 'real' active action is restored from storage * - storage pointer gets cleared (to avoid having bad notes hanging around) * - editing-flag for this AnimData block should also get turned off + * - clear pointer to active strip */ if (adt->action) adt->action->id.us--; adt->action= adt->tmpact; adt->tmpact= NULL; + adt->actstrip= NULL; adt->flag &= ~ADT_NLA_EDIT_ON; } diff --git a/source/blender/blenkernel/nla_private.h b/source/blender/blenkernel/nla_private.h new file mode 100644 index 00000000000..af886fb7de8 --- /dev/null +++ b/source/blender/blenkernel/nla_private.h @@ -0,0 +1,78 @@ +/** + * $Id: BKE_nla.h 20999 2009-06-19 04:45:56Z aligorith $ + * + * ***** 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) 2009 Blender Foundation, Joshua Leung + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Joshua Leung (full recode) + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef NLA_PRIVATE +#define NLA_PRIVATE + +/* --------------- NLA Evaluation DataTypes ----------------------- */ + +/* used for list of strips to accumulate at current time */ +typedef struct NlaEvalStrip { + struct NlaEvalStrip *next, *prev; + + NlaTrack *track; /* track that this strip belongs to */ + NlaStrip *strip; /* strip that's being used */ + + short track_index; /* the index of the track within the list */ + short strip_mode; /* which end of the strip are we looking at */ + + float strip_time; /* time at which which strip is being evaluated */ +} NlaEvalStrip; + +/* NlaEvalStrip->strip_mode */ +enum { + /* standard evaluation */ + NES_TIME_BEFORE = -1, + NES_TIME_WITHIN, + NES_TIME_AFTER, + + /* transition-strip evaluations */ + NES_TIME_TRANSITION_START, + NES_TIME_TRANSITION_END, +} eNlaEvalStrip_StripMode; + + +/* temp channel for accumulating data from NLA (avoids needing to clear all values first) */ +// TODO: maybe this will be used as the 'cache' stuff needed for editable values too? +typedef struct NlaEvalChannel { + struct NlaEvalChannel *next, *prev; + + PointerRNA ptr; /* pointer to struct containing property to use */ + PropertyRNA *prop; /* RNA-property type to use (should be in the struct given) */ + int index; /* array index (where applicable) */ + + float value; /* value of this channel */ +} NlaEvalChannel; + +/* --------------- NLA Functions (not to be used as a proper API) ----------------------- */ + +/* convert from strip time <-> global time */ +float nlastrip_get_frame(NlaStrip *strip, float cframe, short invert); + +#endif // NLA_PRIVATE -- cgit v1.2.3 From db03788ad3ffe3a4c777b70fa5c53f99c5900620 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Wed, 24 Jun 2009 02:11:36 +0000 Subject: 2.5 - Particle Settings now Animateable Added AnimData to ParticleSettings so that this will work. This seems to be ok in the brief tests I did, but be warned that this may not be optimal for the Particles System... --- source/blender/blenkernel/intern/anim_sys.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 30dcb383ef6..441e17f3318 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -43,6 +43,7 @@ static short id_has_animdata (ID *id) case ID_OB: case ID_CU: case ID_KE: + case ID_PA: case ID_MA: case ID_TE: case ID_NT: case ID_LA: case ID_CA: case ID_WO: case ID_SCE: @@ -883,6 +884,9 @@ void BKE_animsys_evaluate_all_animation (Main *main, float ctime) /* meshes */ // TODO... + /* particles */ + EVAL_ANIM_IDS(main->particle.first, ADT_RECALC_ANIM); + /* objects */ /* ADT_RECALC_ANIM doesn't need to be supplied here, since object AnimData gets * this tagged by Depsgraph on framechange -- cgit v1.2.3 From e5119ee2c0d5b9510d89364600e08e40a4407f40 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Wed, 24 Jun 2009 10:32:13 +0000 Subject: NLA SoC: Drawing Tweaks * Transition tracks are now drawn in a different colour (bluish) * Action line now shows keyframe indicators for the action it is representing. These are drawn as small empty diamonds to show that they're not directly editable (and never ever will be) via the NLA Editor. * Action line is also drawn with borders to help differentiate it from the other tracks. * As an experiment, removed the 'TweakMode' buttons from the header. I had originally added this as a way of indicating that this functionality was there (and to allow for keeping track of it), though it seems to have caused far too much confusion and frustration about 'modality' instead. --- source/blender/blenkernel/intern/nla.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index a5b3b59d310..747113b6531 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -433,7 +433,7 @@ float BKE_nla_tweakedit_remap (AnimData *adt, float cframe, short invert) * and store for (very probable) future usage */ if (adt->actstrip == NULL) { - NlaTrack *nlt= BKE_nlatrack_find_active(adt); + NlaTrack *nlt= BKE_nlatrack_find_active(&adt->nla_tracks); adt->actstrip= BKE_nlastrip_find_active(nlt); } strip= adt->actstrip; -- cgit v1.2.3 From 242d9c31d3316f99525925eb7da30522457064e8 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 24 Jun 2009 14:03:55 +0000 Subject: RNA * RNA_struct_name_get_alloc function to get the name from a pointer, instead of having to deal with name property. * CTX_data_pointer_get_type to get data from context with a check for the RNA type. --- source/blender/blenkernel/BKE_context.h | 1 + source/blender/blenkernel/intern/context.c | 19 ++++++++++++------- 2 files changed, 13 insertions(+), 7 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_context.h b/source/blender/blenkernel/BKE_context.h index 898b84ecdc3..f536e117b7b 100644 --- a/source/blender/blenkernel/BKE_context.h +++ b/source/blender/blenkernel/BKE_context.h @@ -131,6 +131,7 @@ void CTX_wm_menu_set(bContext *C, struct ARegion *menu); - the dir listbase consits of LinkData items */ PointerRNA CTX_data_pointer_get(const bContext *C, const char *member); +PointerRNA CTX_data_pointer_get_type(const bContext *C, const char *member, StructRNA *type); ListBase CTX_data_collection_get(const bContext *C, const char *member); ListBase CTX_data_dir_get(const bContext *C); void CTX_data_get(const bContext *C, const char *member, PointerRNA *r_ptr, ListBase *r_lb); diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c index 12deec838a8..90880e354ec 100644 --- a/source/blender/blenkernel/intern/context.c +++ b/source/blender/blenkernel/intern/context.c @@ -365,15 +365,20 @@ PointerRNA CTX_data_pointer_get(const bContext *C, const char *member) { bContextDataResult result; - if(ctx_data_get((bContext*)C, member, &result)) { + if(ctx_data_get((bContext*)C, member, &result)) return result.ptr; - } - else { - PointerRNA ptr; - memset(&ptr, 0, sizeof(ptr)); - return ptr; - } + else + return PointerRNA_NULL; +} + +PointerRNA CTX_data_pointer_get_type(const bContext *C, const char *member, StructRNA *type) +{ + PointerRNA ptr = CTX_data_pointer_get(C, member); + if(ptr.data && ptr.type == type) + return ptr; + + return PointerRNA_NULL; } ListBase CTX_data_collection_get(const bContext *C, const char *member) -- cgit v1.2.3 From a379fdd7fba460fdceb14d6dd164116d9a4744bd Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 24 Jun 2009 14:07:48 +0000 Subject: 2.5: Object material slot operators add/remove/assign/select/deselect. --- source/blender/blenkernel/BKE_material.h | 15 ++++++++++----- source/blender/blenkernel/intern/material.c | 4 ++-- 2 files changed, 12 insertions(+), 7 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_material.h b/source/blender/blenkernel/BKE_material.h index 38a1d9b13b7..382754ee2b2 100644 --- a/source/blender/blenkernel/BKE_material.h +++ b/source/blender/blenkernel/BKE_material.h @@ -39,6 +39,8 @@ struct Material; struct ID; struct Object; +/* materials */ + void init_def_material(void); void free_material(struct Material *sc); void test_object_materials(struct ID *id); @@ -47,15 +49,22 @@ struct Material *add_material(char *name); struct Material *copy_material(struct Material *ma); void make_local_material(struct Material *ma); +void automatname(struct Material *); + +/* material slots */ + struct Material ***give_matarar(struct Object *ob); short *give_totcolp(struct Object *ob); struct Material *give_current_material(struct Object *ob, int act); struct ID *material_from(struct Object *ob, int act); void assign_material(struct Object *ob, struct Material *ma, int act); -void new_material_to_objectdata(struct Object *ob); int find_material_index(struct Object *ob, struct Material *ma); +void object_add_material_slot(struct Object *ob); +void object_remove_material_slot(struct Object *ob); + +/* rendering */ void init_render_material(struct Material *, int, float *); void init_render_materials(int, float *); @@ -64,12 +73,8 @@ void end_render_materials(void); int material_in_material(struct Material *parmat, struct Material *mat); -void automatname(struct Material *); -void delete_material_index(struct Object *ob); - void ramp_blend(int type, float *r, float *g, float *b, float fac, float *col); - #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index b410c521dea..57b88bb0b3f 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -615,7 +615,7 @@ int find_material_index(Object *ob, Material *ma) return 0; } -void new_material_to_objectdata(Object *ob) +void object_add_material_slot(Object *ob) { Material *ma; @@ -854,7 +854,7 @@ void automatname(Material *ma) } -void delete_material_index(Object *ob) +void object_remove_material_slot(Object *ob) { Material *mao, ***matarar; Object *obt; -- cgit v1.2.3 From d839a9ae9ccbf17375e28cc92aa75a0cb4cf6b11 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Sat, 27 Jun 2009 01:10:39 +0000 Subject: RNA * Added support for passing collections to/from RNA functions, this is done using a ListBase of CollectionPointerLink, which is a standard ListBase link + PointerRNA. * Added editable active uv/vcol layer to Mesh. * Armature.bones now includes all bones, not only the ones without parents. * Modifier UV layer fields now are allowed to be empty, previously this would set the name during modifier evaluation if there was none. --- source/blender/blenkernel/intern/modifier.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index bf3d27cafbf..1a6f57e75c4 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -3543,7 +3543,7 @@ static void displaceModifier_updateDepgraph( } } -static void validate_layer_name(const CustomData *data, int type, char *name) +static void validate_layer_name(const CustomData *data, int type, char *name, char *outname) { int index = -1; @@ -3556,8 +3556,10 @@ static void validate_layer_name(const CustomData *data, int type, char *name) * deleted, so assign the active layer to name */ index = CustomData_get_active_layer_index(data, CD_MTFACE); - strcpy(name, data->layers[index].name); + strcpy(outname, data->layers[index].name); } + else + strcpy(outname, name); } static void get_texture_coords(DisplaceModifierData *dmd, Object *ob, @@ -3583,12 +3585,11 @@ static void get_texture_coords(DisplaceModifierData *dmd, Object *ob, char *done = MEM_callocN(sizeof(*done) * numVerts, "get_texture_coords done"); int numFaces = dm->getNumFaces(dm); + char uvname[32]; MTFace *tf; - validate_layer_name(&dm->faceData, CD_MTFACE, dmd->uvlayer_name); - - tf = CustomData_get_layer_named(&dm->faceData, CD_MTFACE, - dmd->uvlayer_name); + validate_layer_name(&dm->faceData, CD_MTFACE, dmd->uvlayer_name, uvname); + tf = CustomData_get_layer_named(&dm->faceData, CD_MTFACE, uvname); /* verts are given the UV from the first face that uses them */ for(i = 0, mf = mface; i < numFaces; ++i, ++mf, ++tf) { @@ -3884,6 +3885,7 @@ static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd, Projector projectors[MOD_UVPROJECT_MAXPROJECTORS]; int num_projectors = 0; float aspect; + char uvname[32]; if(umd->aspecty != 0) aspect = umd->aspectx / umd->aspecty; else aspect = 1.0f; @@ -3898,12 +3900,11 @@ static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd, if(!dm->getFaceDataArray(dm, CD_MTFACE)) return dm; /* make sure we're using an existing layer */ - validate_layer_name(&dm->faceData, CD_MTFACE, umd->uvlayer_name); + validate_layer_name(&dm->faceData, CD_MTFACE, umd->uvlayer_name, uvname); /* make sure we are not modifying the original UV layer */ tface = CustomData_duplicate_referenced_layer_named(&dm->faceData, - CD_MTFACE, - umd->uvlayer_name); + CD_MTFACE, uvname); numVerts = dm->getNumVerts(dm); @@ -5185,12 +5186,11 @@ static void wavemod_get_texture_coords(WaveModifierData *wmd, Object *ob, char *done = MEM_callocN(sizeof(*done) * numVerts, "get_texture_coords done"); int numFaces = dm->getNumFaces(dm); + char uvname[32]; MTFace *tf; - validate_layer_name(&dm->faceData, CD_MTFACE, wmd->uvlayer_name); - - tf = CustomData_get_layer_named(&dm->faceData, CD_MTFACE, - wmd->uvlayer_name); + validate_layer_name(&dm->faceData, CD_MTFACE, wmd->uvlayer_name, uvname); + tf = CustomData_get_layer_named(&dm->faceData, CD_MTFACE, uvname); /* verts are given the UV from the first face that uses them */ for(i = 0, mf = mface; i < numFaces; ++i, ++mf, ++tf) { -- cgit v1.2.3 From d3557fc487bc5e5c02c9758b6a05200575e82e84 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sat, 27 Jun 2009 12:35:11 +0000 Subject: NLA SoC: Recoded the strip<->global time conversion code * Strip evaluation now takes into account repeats * Increasing the number of repeats lengthens the strip, while decreasing the number of repeats does the opposite. TODO: - inverse correction doesn't take into account repeats != 1, so tweaking strips with repeats is currently not recommended! --- source/blender/blenkernel/intern/nla.c | 44 +++++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 11 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index 747113b6531..760139bee15 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -331,7 +331,7 @@ NlaStrip *add_nlastrip_to_stack (AnimData *adt, bAction *act) */ static float nlastrip_get_frame_actionclip (NlaStrip *strip, float cframe, short invert) { - float length, actlength, repeat, scale; + float actlength, repeat, scale; /* get number of repeats */ if (IS_EQ(strip->repeat, 0.0f)) strip->repeat = 1.0f; @@ -345,24 +345,46 @@ static float nlastrip_get_frame_actionclip (NlaStrip *strip, float cframe, short actlength = strip->actend - strip->actstart; if (IS_EQ(actlength, 0.0f)) actlength = 1.0f; - /* length of strip */ - length= actlength * scale * repeat; - if (IS_EQ(length, 0.0f)) length= strip->end - strip->start; - /* reversed = play strip backwards */ if (strip->flag & NLASTRIP_FLAG_REVERSE) { /* invert = convert action-strip time to global time */ if (invert) - return length*(strip->actend - cframe)/(repeat*actlength) + strip->start; - else - return strip->actend - repeat*actlength*(cframe - strip->start)/length; + return scale*(strip->actend - cframe) + strip->start; // FIXME: this doesn't work for multiple repeats yet + else { + if (IS_EQ(cframe, strip->end) && IS_EQ(strip->repeat, ((int)strip->repeat))) { + /* this case prevents the motion snapping back to the first frame at the end of the strip + * by catching the case where repeats is a whole number, which means that the end of the strip + * could also be interpreted as the end of the start of a repeat + */ + return strip->actstart; + } + else { + /* - the 'fmod(..., actlength*scale)' is needed to get the repeats working + * - the '/ scale' is needed to ensure that scaling influences the timing within the repeat + */ + return strip->actend - fmod(cframe - strip->start, actlength*scale) / scale; + } + } } else { /* invert = convert action-strip time to global time */ if (invert) - return length*(cframe - strip->actstart)/(repeat*actlength) + strip->start; - else - return repeat*actlength*(cframe - strip->start)/length + strip->actstart; + return scale*(cframe - strip->actstart) + strip->start; // FIXME: this doesn't work for mutiple repeats yet + else { + if (IS_EQ(cframe, strip->end) && IS_EQ(strip->repeat, ((int)strip->repeat))) { + /* this case prevents the motion snapping back to the first frame at the end of the strip + * by catching the case where repeats is a whole number, which means that the end of the strip + * could also be interpreted as the end of the start of a repeat + */ + return strip->actend; + } + else { + /* - the 'fmod(..., actlength*scale)' is needed to get the repeats working + * - the '/ scale' is needed to ensure that scaling influences the timing within the repeat + */ + return strip->actstart + fmod(cframe - strip->start, actlength*scale) / scale; + } + } } } -- cgit v1.2.3 From 912c2f440b447aa8cae9f3e3a86acf51cd495e3d Mon Sep 17 00:00:00 2001 From: Janne Karhu Date: Sat, 27 Jun 2009 15:28:58 +0000 Subject: Pointcache refresh part 2 * Based on what happens during simulation the cache is marked (also in cache panel, this could possibly be extended to 3d view as well) as: - exact (not marked) - outdated (simulation is not done completely with current settings) - non-exact (frames were skipped during simulation) * The parameter "cache step" effects the number of frames between saved cache frames. - This can save a lot of memory (or disk space) if absolutely frame accurate simulation is not required. - Speeds up the "quick caching" very much. - Frames between cached frames are interpolated from the cached frames. - Current default value of 10 frames works nicely with up/down-arrows (skip 10 frames forwards/backwards on timeline), but can be changed if wanted. * The caching can work in normal or "quick" mode: [Normal cache] - Basic: Calculate what even happens (settings change, big frame steps etc.) and cache results, if possible try to use "cache step" when saving cache frames. - Becomes non-exact: After larger than 1 frame steps. - Becomes outdated: After any change effecting the simulation other than frame steps. - Pros/cons: Freedom of doing anything and playing with particles, but exact results have to calculated from the beginning. [Quick cache] - Basic: Calculate simulation up to current frame automatically on changes with cache step sized jumps in simulation. With multiple "quick cached" simulations the smallest cache step is used. - Becomes non-exact: Always from frame 1 (unless cache step = 1). - Becomes outdated: Never. - Pros/cons: Not very accurate, but super fast! - Todo: Transform of any animated (non-autokeyed) object is locked! Probably needs some tinkering with anim sys overrides. * The simulation can be run forwards or backwards even if it's cache is outdated or non-exact, the following rules apply in these situations: - step forwards (to unknown) -> simulate from last exact frame, store result - step backwards (to known) -> result is interpolated from existing frames, store result, clear cache forwards if current frame is after last exact frame * "Calculate to current frame" runs the simulation from start to current frame with a frame steps of 1. - Baking does the same, but runs the simulation all the way to the end of simulation. - Rendering does this automatically if the simulation is outdated of non-exact, so all rendered simulations will always be updated and exact. * Every cache panel also holds buttons to "Bake all dynamics", "Free all dynamics" and "Update all dynamics to current frame". * Cloth simulation supports the new cache too. --- source/blender/blenkernel/BKE_cloth.h | 5 +- source/blender/blenkernel/BKE_particle.h | 1 - source/blender/blenkernel/BKE_pointcache.h | 13 +- source/blender/blenkernel/intern/cloth.c | 164 ++++--- source/blender/blenkernel/intern/implicit.c | 10 +- source/blender/blenkernel/intern/particle.c | 27 +- source/blender/blenkernel/intern/particle_system.c | 57 ++- source/blender/blenkernel/intern/pointcache.c | 475 +++++++++++++-------- 8 files changed, 457 insertions(+), 295 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h index e09be838f06..4270c677338 100644 --- a/source/blender/blenkernel/BKE_cloth.h +++ b/source/blender/blenkernel/BKE_cloth.h @@ -46,6 +46,7 @@ #include "DNA_meshdata_types.h" #include "DNA_modifier_types.h" #include "DNA_object_types.h" +#include "DNA_scene_types.h" #include "BKE_collision.h" @@ -245,8 +246,8 @@ void bvhtree_update_from_cloth ( ClothModifierData *clmd, int moving ); void bvhselftree_update_from_cloth ( ClothModifierData *clmd, int moving ); // needed for editmesh.c -void cloth_write_cache ( Object *ob, ClothModifierData *clmd, float framenr ); -int cloth_read_cache ( Object *ob, ClothModifierData *clmd, float framenr ); +void cloth_write_cache( Object *ob, ClothModifierData *clmd, int framenr ); +int cloth_read_cache( Scene *scene, Object *ob, ClothModifierData *clmd, float framenr, int *old_framenr ); // needed for button_object.c void cloth_clear_cache ( Object *ob, ClothModifierData *clmd, float framenr ); diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index 0ecd71fc4a3..08aa111e0e6 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -252,7 +252,6 @@ struct ParticleSystemModifierData *psys_get_modifier(struct Object *ob, struct P struct ParticleSettings *psys_new_settings(char *name, struct Main *main); struct ParticleSettings *psys_copy_settings(struct ParticleSettings *part); -int psys_count_autocache(struct Scene *scene, struct ParticleSettings *part); void psys_flush_particle_settings(struct Scene *scene, struct ParticleSettings *part, int recalc); void make_local_particlesettings(struct ParticleSettings *part); diff --git a/source/blender/blenkernel/BKE_pointcache.h b/source/blender/blenkernel/BKE_pointcache.h index b79357edf36..3f1c45d28ec 100644 --- a/source/blender/blenkernel/BKE_pointcache.h +++ b/source/blender/blenkernel/BKE_pointcache.h @@ -93,7 +93,7 @@ typedef struct PTCacheWriter { int cfra; int totelem; - float *(*elem_ptr)(int index, void *calldata); + void (*set_elem)(int index, void *calldata, float *data); void *calldata; } PTCacheWriter; @@ -103,12 +103,10 @@ typedef struct PTCacheReader { float cfra; int totelem; - void (*set_elem)(int index, void *calldata, float *data); - void (*interpolate_elem)(int index, void *calldata, float frs_sec, float cfra, int cfra1, int cfra2, float *data1, float *data2); + void (*set_elem)(int elem_index, void *calldata, float *data); + void (*interpolate_elem)(int index, void *calldata, float frs_sec, float cfra, float cfra1, float cfra2, float *data1, float *data2); void *calldata; - int allow_interpolate; - int allow_old; int *old_frame; } PTCacheReader; @@ -116,6 +114,7 @@ typedef struct PTCacheBaker { struct Scene *scene; int bake; int render; + int quick_step; struct PTCacheID *pid; int (*break_test)(void *data); void *break_data; @@ -146,6 +145,8 @@ void BKE_ptcache_file_close(PTCacheFile *pf); int BKE_ptcache_file_read_floats(PTCacheFile *pf, float *f, int tot); int BKE_ptcache_file_write_floats(PTCacheFile *pf, float *f, int tot); +void BKE_ptcache_update_info(PTCacheID *pid); + /* General cache reading/writing */ int BKE_ptcache_read_cache(PTCacheReader *reader); int BKE_ptcache_write_cache(PTCacheWriter *writer); @@ -160,7 +161,7 @@ void BKE_ptcache_free(struct PointCache *cache); struct PointCache *BKE_ptcache_copy(struct PointCache *cache); /* Baking */ -void BKE_ptcache_autocache_all(struct Scene *scene); +void BKE_ptcache_quick_cache_all(struct Scene *scene); void BKE_ptcache_make_cache(struct PTCacheBaker* baker); void BKE_ptcache_toggle_disk_cache(struct PTCacheID *pid); diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index e98d7bb01a4..08caea565aa 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -33,6 +33,7 @@ #include "DNA_mesh_types.h" #include "DNA_object_force.h" #include "DNA_scene_types.h" +#include "DNA_particle_types.h" #include "BKE_deform.h" #include "BKE_DerivedMesh.h" @@ -42,6 +43,7 @@ #include "BKE_object.h" #include "BKE_modifier.h" #include "BKE_utildefines.h" +#include "BKE_particle.h" #include "BKE_pointcache.h" @@ -339,78 +341,99 @@ void bvhselftree_update_from_cloth(ClothModifierData *clmd, int moving) } int modifiers_indexInObject(Object *ob, ModifierData *md_seek); +static void cloth_write_state(int index, Cloth *cloth, float *data) +{ + ClothVertex *vert = cloth->verts + index; -int cloth_read_cache(Object *ob, ClothModifierData *clmd, float framenr) + memcpy(data, vert->x, 3 * sizeof(float)); + memcpy(data + 3, vert->xconst, 3 * sizeof(float)); + memcpy(data + 6, vert->v, 3 * sizeof(float)); +} +static void cloth_read_state(int index, Cloth *cloth, float *data) { - PTCacheID pid; - PTCacheFile *pf; - Cloth *cloth = clmd->clothObject; - unsigned int a, ret = 1; + ClothVertex *vert = cloth->verts + index; - if(!cloth) - return 0; - - BKE_ptcache_id_from_cloth(&pid, ob, clmd); - pf = BKE_ptcache_file_open(&pid, PTCACHE_FILE_READ, framenr); - if(pf) { - for(a = 0; a < cloth->numverts; a++) { - if(!BKE_ptcache_file_read_floats(pf, cloth->verts[a].x, 3)) { - ret = 0; - break; - } - if(!BKE_ptcache_file_read_floats(pf, cloth->verts[a].xconst, 3)) { - ret = 0; - break; - } - if(!BKE_ptcache_file_read_floats(pf, cloth->verts[a].v, 3)) { - ret = 0; - break; - } - } - - BKE_ptcache_file_close(pf); - } - else - ret = 0; - - return ret; + memcpy(vert->x, data, 3 * sizeof(float)); + memcpy(vert->xconst, data + 3, 3 * sizeof(float)); + memcpy(vert->v, data + 6, 3 * sizeof(float)); } +static void cloth_cache_interpolate(int index, Cloth *cloth, float frs_sec, float cfra, float cfra1, float cfra2, float *data1, float *data2) +{ + ClothVertex *vert = cloth->verts + index; + ParticleKey keys[4]; + float dfra; -void cloth_clear_cache(Object *ob, ClothModifierData *clmd, float framenr) + if(cfra1 == cfra2) { + cloth_read_state(index, cloth, data1); + return; + } + + memcpy(keys[1].co, data1, 3 * sizeof(float)); + memcpy(keys[1].vel, data1 + 6, 3 * sizeof(float)); + + memcpy(keys[2].co, data2, 3 * sizeof(float)); + memcpy(keys[2].vel, data2 + 6, 3 * sizeof(float)); + + dfra = cfra2 - cfra1; + + VecMulf(keys[1].vel, dfra); + VecMulf(keys[2].vel, dfra); + + psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, keys, 1); + + VecMulf(keys->vel, 1.0f / dfra); + + memcpy(vert->x, keys->co, 3 * sizeof(float)); + memcpy(vert->v, keys->vel, 3 * sizeof(float)); + + /* not sure what to do with this - jahka */ + memcpy(vert->xconst, data1 + 3, 3 * sizeof(float)); +} +void cloth_write_cache(Object *ob, ClothModifierData *clmd, int cfra) { + PTCacheWriter writer; PTCacheID pid; - + BKE_ptcache_id_from_cloth(&pid, ob, clmd); - // don't do anything as long as we're in editmode! - if(pid.cache->flag & PTCACHE_BAKE_EDIT_ACTIVE) - return; - - BKE_ptcache_id_clear(&pid, PTCACHE_CLEAR_AFTER, framenr); + writer.calldata = clmd->clothObject; + writer.cfra = cfra; + writer.set_elem = cloth_write_state; + writer.pid = &pid; + writer.totelem = clmd->clothObject->numverts; + + BKE_ptcache_write_cache(&writer); } -void cloth_write_cache(Object *ob, ClothModifierData *clmd, float framenr) +int cloth_read_cache(Scene *scene, Object *ob, ClothModifierData *clmd, float cfra, int *old_framenr) { - Cloth *cloth = clmd->clothObject; + PTCacheReader reader; PTCacheID pid; - PTCacheFile *pf; - unsigned int a; - if(!cloth) - return; + BKE_ptcache_id_from_cloth(&pid, ob, clmd); + + reader.calldata = clmd->clothObject; + reader.cfra = cfra; + reader.interpolate_elem = cloth_cache_interpolate; + reader.old_frame = old_framenr; + reader.pid = &pid; + reader.scene = scene; + reader.set_elem = cloth_read_state; + reader.totelem = clmd->clothObject->numverts; + + return BKE_ptcache_read_cache(&reader); +} +void cloth_clear_cache(Object *ob, ClothModifierData *clmd, float framenr) +{ + PTCacheID pid; BKE_ptcache_id_from_cloth(&pid, ob, clmd); - pf = BKE_ptcache_file_open(&pid, PTCACHE_FILE_WRITE, framenr); - if(!pf) + + // don't do anything as long as we're in editmode! + if(pid.cache->flag & PTCACHE_BAKE_EDIT_ACTIVE) return; - for(a = 0; a < cloth->numverts; a++) { - BKE_ptcache_file_write_floats(pf, cloth->verts[a].x, 3); - BKE_ptcache_file_write_floats(pf, cloth->verts[a].xconst, 3); - BKE_ptcache_file_write_floats(pf, cloth->verts[a].v, 3); - } - - BKE_ptcache_file_close(pf); + BKE_ptcache_id_clear(&pid, PTCACHE_CLEAR_AFTER, framenr); } static int do_init_cloth(Object *ob, ClothModifierData *clmd, DerivedMesh *result, int framenr) @@ -486,6 +509,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, PTCacheID pid; float timescale; int framedelta, framenr, startframe, endframe; + int cache_result, old_framenr; clmd->scene= scene; /* nice to pass on later :) */ framenr= (int)scene->r.cfra; @@ -499,6 +523,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, if(!result) { cache->flag &= ~PTCACHE_SIMULATION_VALID; cache->simframe= 0; + cache->last_exact= 0; return dm; } @@ -510,6 +535,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, if(result->getNumVerts(result) != clmd->clothObject->numverts) { cache->flag &= ~PTCACHE_SIMULATION_VALID; cache->simframe= 0; + cache->last_exact= 0; return result; } } @@ -521,6 +547,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, if(BKE_ptcache_get_continue_physics()) { cache->flag &= ~PTCACHE_SIMULATION_VALID; cache->simframe= 0; + cache->last_exact= 0; /* do simulation */ if(!do_init_cloth(ob, clmd, result, framenr)) @@ -536,6 +563,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, if(framenr < startframe) { cache->flag &= ~PTCACHE_SIMULATION_VALID; cache->simframe= 0; + cache->last_exact= 0; return result; } else if(framenr > endframe) { @@ -552,7 +580,9 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, return result; /* try to read from cache */ - if(cloth_read_cache(ob, clmd, framenr)) { + cache_result = cloth_read_cache(scene, ob, clmd, framenr, &old_framenr); + + if(cache_result == PTCACHE_READ_EXACT || cache_result == PTCACHE_READ_INTERPOLATED) { cache->flag |= PTCACHE_SIMULATION_VALID; cache->simframe= framenr; @@ -561,25 +591,40 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, return result; } + else if(cache_result==PTCACHE_READ_OLD) { + BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_FREE); + + implicit_set_positions(clmd); + + cache->flag |= PTCACHE_SIMULATION_VALID; + cache->simframe= old_framenr; + } else if(ob->id.lib || (cache->flag & PTCACHE_BAKED)) { /* if baked and nothing in cache, do nothing */ cache->flag &= ~PTCACHE_SIMULATION_VALID; cache->simframe= 0; + cache->last_exact= 0; return result; } if(framenr == startframe) { + if(cache->flag & PTCACHE_REDO_NEEDED) { + BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED); + do_init_cloth(ob, clmd, result, framenr); + } cache->flag |= PTCACHE_SIMULATION_VALID; cache->simframe= framenr; /* don't write cache on first frame, but on second frame write * cache for frame 1 and 2 */ } - else if(framedelta == 1) { + else { /* if on second frame, write cache for first frame */ - if(framenr == startframe+1) + if(cache->simframe == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0)) cloth_write_cache(ob, clmd, startframe); + clmd->sim_parms->timescale *= framenr - cache->simframe; + /* do simulation */ cache->flag |= PTCACHE_SIMULATION_VALID; cache->simframe= framenr; @@ -587,16 +632,13 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, if(!do_step_cloth(ob, clmd, result, framenr)) { cache->flag &= ~PTCACHE_SIMULATION_VALID; cache->simframe= 0; + cache->last_exact= 0; } else cloth_write_cache(ob, clmd, framenr); cloth_to_object (ob, clmd, result); } - else { - cache->flag &= ~PTCACHE_SIMULATION_VALID; - cache->simframe= 0; - } return result; } diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c index 40c98c1d9cc..fc5213d5532 100644 --- a/source/blender/blenkernel/intern/implicit.c +++ b/source/blender/blenkernel/intern/implicit.c @@ -1600,6 +1600,10 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase if(clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_ENABLED) { + float temp = clmd->sim_parms->stepsPerFrame; + /* not too nice hack, but collisions need this correction -jahka */ + clmd->sim_parms->stepsPerFrame /= clmd->sim_parms->timescale; + // collisions // itstart(); @@ -1614,7 +1618,7 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase // call collision function // TODO: check if "step" or "step+dt" is correct - dg - result = cloth_bvh_objcollision(ob, clmd, step, dt); + result = cloth_bvh_objcollision(ob, clmd, step/clmd->sim_parms->timescale, dt/clmd->sim_parms->timescale); // correct velocity again, just to be sure we had to change it due to adaptive collisions for(i = 0; i < numverts; i++) @@ -1637,6 +1641,9 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase } } + /* restore original stepsPerFrame */ + clmd->sim_parms->stepsPerFrame = temp; + // X = Xnew; cp_lfvector(id->X, id->Xnew, numverts); @@ -1654,7 +1661,6 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase simulate_implicit_euler(id->Vnew, id->X, id->V, id->F, id->dFdV, id->dFdX, dt / 2.0f, id->A, id->B, id->dV, id->S, id->z, id->olddV, id->P, id->Pinv, id->M, id->bigI); } - } else { diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 5b3720cd6b0..04215b1ddd1 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -236,31 +236,6 @@ Object *psys_find_object(Scene *scene, ParticleSystem *psys) return NULL; } -int psys_count_autocache(Scene *scene, ParticleSettings *part) -{ - Base *base = scene->base.first; - ParticleSystem *psys; - PTCacheID pid; - int autocache_count= 0; - - for(base = scene->base.first; base; base = base->next) { - for(psys = base->object->particlesystem.first; psys; psys=psys->next) { - if(part && psys->part != part) - continue; - - BKE_ptcache_id_from_particles(&pid, base->object, psys); - - if((psys->pointcache->flag & PTCACHE_BAKED) - || (psys->pointcache->flag & PTCACHE_AUTOCACHE)==0) - continue; - - if((psys->pointcache->flag & PTCACHE_OUTDATED) - || BKE_ptcache_id_exist(&pid, CFRA)==0) - autocache_count++; - } - } - return autocache_count; -} /* change object's active particle system */ void psys_change_act(void *ob_v, void *act_v) { @@ -3740,6 +3715,8 @@ int psys_get_particle_state(struct Scene *scene, Object *ob, ParticleSystem *psy if((pa->alive==PARS_UNBORN && (part->flag & PART_UNBORN)==0) || (pa->alive==PARS_DEAD && (part->flag & PART_DIED)==0)) return 0; + + state->time = MIN2(state->time, pa->dietime); } if(psys->flag & PSYS_KEYED){ diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 97b1956bba9..591b6ca9be5 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -2205,11 +2205,9 @@ void psys_get_pointcache_start_end(Scene *scene, ParticleSystem *psys, int *sfra *sfra = MAX2(1, (int)part->sta); *efra = MIN2((int)(part->end + part->lifetime + 1.0), scene->r.efra); } -static float *particle_state_ptr(int index, void *psys_ptr) +static void particle_write_state(int index, ParticleSystem *psys, float *data) { - ParticleSystem *psys= psys_ptr; - - return (float *)(&(psys->particles+index)->state); + memcpy(data, (float *)(&(psys->particles+index)->state), sizeof(ParticleKey)); } static void particle_read_state(int index, void *psys_ptr, float *data) { @@ -2222,24 +2220,35 @@ static void particle_read_state(int index, void *psys_ptr, float *data) copy_particle_key(&pa->state, key, 1); } -static void particle_cache_interpolate(int index, void *psys_ptr, float frs_sec, float cfra, int cfra1, int cfra2, float *data1, float *data2) +static void particle_cache_interpolate(int index, void *psys_ptr, float frs_sec, float cfra, float cfra1, float cfra2, float *data1, float *data2) { ParticleSystem *psys= psys_ptr; ParticleData *pa = psys->particles + index; ParticleKey keys[4]; - float dfra; + float dfra, cfra1f = (float)cfra1, cfra2f(float); + + cfra = MIN2(cfra, pa->dietime); + cfra1 = MIN2(cfra1, pa->dietime); + cfra2 = MIN2(cfra2, pa->dietime); keys[1] = *((ParticleKey*)data1); keys[2] = *((ParticleKey*)data2); - dfra = keys[2].time - keys[1].time; + if(cfra1 == cfra2) { + copy_particle_key(&pa->state, &keys[1], 1); + return; + } + + dfra = cfra2 - cfra1; VecMulf(keys[1].vel, dfra / frs_sec); VecMulf(keys[2].vel, dfra / frs_sec); - psys_interpolate_particle(-1, keys, (keys[1].time - cfra) / dfra, &pa->state, 1); + psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, &pa->state, 1); VecMulf(pa->state.vel, frs_sec / dfra); + + pa->state.time = cfra; } static void write_particles_to_cache(Object *ob, ParticleSystem *psys, int cfra) { @@ -2250,22 +2259,20 @@ static void write_particles_to_cache(Object *ob, ParticleSystem *psys, int cfra) writer.calldata = psys; writer.cfra = cfra; - writer.elem_ptr = particle_state_ptr; + writer.set_elem = particle_write_state; writer.pid = &pid; writer.totelem = psys->totpart; BKE_ptcache_write_cache(&writer); } -static int get_particles_from_cache(Scene *scene, Object *ob, ParticleSystem *psys, float cfra, int allow_interpolate, int allow_old, int *old_frame) +static int get_particles_from_cache(Scene *scene, Object *ob, ParticleSystem *psys, float cfra, int *old_frame) { PTCacheReader reader; PTCacheID pid; BKE_ptcache_id_from_particles(&pid, ob, psys); - reader.allow_interpolate = allow_interpolate; - reader.allow_old = allow_old; reader.calldata = psys; reader.cfra = cfra; reader.interpolate_elem = particle_cache_interpolate; @@ -2402,6 +2409,8 @@ static void add_to_effectors(ListBase *lb, Scene *scene, Object *ob, Object *obs Object *tob; for(i=0; epsys; epsys=epsys->next,i++){ + if(!psys_check_enabled(ob, epsys)) + continue; type=0; if(epsys!=psys || (psys->part->flag & PART_SELF_EFFECT)){ epart=epsys->part; @@ -4366,7 +4375,7 @@ static void cached_step(Scene *scene, Object *ob, ParticleSystemModifierData *ps pa->alive = PARS_UNBORN; else if(dietime <= cfra){ if(dietime > psys->cfra){ - state.time = pa->dietime; + state.time = dietime; psys_get_particle_state(scene, ob,psys,p,&state,1); push_reaction(ob,psys,p,PART_EVENT_DEATH,&state); } @@ -4668,9 +4677,9 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle /* try to read from the cache */ if(usecache) { - int result = get_particles_from_cache(scene, ob, psys, (float)framenr, 0, 1, &old_framenr); + int result = get_particles_from_cache(scene, ob, psys, (float)framenr, &old_framenr); - if(result == PTCACHE_READ_EXACT) { + if(result == PTCACHE_READ_EXACT || result == PTCACHE_READ_INTERPOLATED) { //if(part->phystype==PART_PHYS_KEYED && psys->flag&PSYS_FIRST_KEYED) { // psys_count_keyed_targets(ob,psys); // set_keyed_keys(scene, ob, psys); @@ -4687,15 +4696,12 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle cache->simframe= framenr; cache->flag |= PTCACHE_SIMULATION_VALID; - if(cache->flag & PTCACHE_OUTDATED) - BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_FREE); + if(result == PTCACHE_READ_INTERPOLATED && cache->flag & PTCACHE_REDO_NEEDED) + write_particles_to_cache(ob, psys, cfra); return; } - else if((cache->flag & PTCACHE_AUTOCACHE)==0 && result==PTCACHE_READ_OLD) { - /* clear cache after current frame */ - BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_FREE); - + else if(result==PTCACHE_READ_OLD) { /* set old cfra */ psys->cfra = (float)old_framenr; @@ -4715,15 +4721,6 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle psys->recalc = 0; return; } - - if(framenr != startframe && framedelta != 1 && cache->flag & PTCACHE_AUTOCACHE) { - //psys_reset(psys, PSYS_RESET_CACHE_MISS); - /* make sure cache is recalculated */ - BKE_ptcache_id_clear(&pid, PTCACHE_CLEAR_FRAME, (int)cfra); - psys->cfra = cfra; - psys->recalc = 0; - return; - } } else { cache->flag &= ~PTCACHE_SIMULATION_VALID; diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index b514ac026fb..64473d07151 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -303,7 +303,7 @@ static int ptcache_pid_elemsize(PTCacheID *pid) else if(pid->type==PTCACHE_TYPE_PARTICLES) return sizeof(ParticleKey); else if(pid->type==PTCACHE_TYPE_CLOTH) - return 0; // TODO + return 9 * sizeof(float); return 0; } @@ -321,10 +321,11 @@ static int ptcache_pid_totelem(PTCacheID *pid) return 0; } -void ptcache_update_info(PTCacheID *pid) +void BKE_ptcache_update_info(PTCacheID *pid) { PointCache *cache = pid->cache; int totframes = 0; + char mem_info[64]; if(cache->flag & PTCACHE_DISK_CACHE) { int cfra = cache->startframe; @@ -334,7 +335,7 @@ void ptcache_update_info(PTCacheID *pid) totframes++; } - sprintf(cache->info, "%i frames on disk.", totframes); + sprintf(mem_info, "%i frames on disk", totframes); } else { PTCacheMem *pm = cache->mem_cache.first; @@ -351,11 +352,20 @@ void ptcache_update_info(PTCacheID *pid) mb = (bytes > 1024.0f * 1024.0f); - sprintf(cache->info, "%i frames in memory (%.1f %s).", + sprintf(mem_info, "%i frames in memory (%.1f %s)", totframes, bytes / (mb ? 1024.0f * 1024.0f : 1024.0f), mb ? "Mb" : "kb"); } + + if(cache->flag & PTCACHE_OUTDATED) { + sprintf(cache->info, "%s, cache is outdated!", mem_info); + } + else if(cache->flag & PTCACHE_FRAMES_SKIPPED) { + sprintf(cache->info, "%s, not exact since frame %i.", mem_info, cache->last_exact); + } + else + sprintf(cache->info, "%s.", mem_info); } /* reads cache from disk or memory */ /* possible to get old or interpolated result */ @@ -370,10 +380,13 @@ int BKE_ptcache_read_cache(PTCacheReader *reader) int elemsize = ptcache_pid_elemsize(pid); int i, incr = elemsize / sizeof(float); float frs_sec = reader->scene->r.frs_sec; + int cfra1=0, cfra2; + int ret = 0; if(totelem == 0) return 0; + /* first check if we have the actual frame cached */ if(cfra == (float)cfrai) { if(pid->cache->flag & PTCACHE_DISK_CACHE) { @@ -419,130 +432,147 @@ int BKE_ptcache_read_cache(PTCacheReader *reader) MEM_freeN(data); } - return PTCACHE_READ_EXACT; + ret = PTCACHE_READ_EXACT; } - /* no exact cache frame found so try to find cached frames around cfra */ - if(reader->allow_interpolate || reader->allow_old) { - int cfra1, cfra2; - if(pid->cache->flag & PTCACHE_DISK_CACHE) { - pf=NULL; - while(cfrai > pid->cache->startframe && !pf) { - cfrai--; - pf= BKE_ptcache_file_open(pid, PTCACHE_FILE_READ, cfrai); - cfra1 = cfrai; - } + if(ret) + ; + /* no exact cache frame found so try to find cached frames around cfra */ + else if(pid->cache->flag & PTCACHE_DISK_CACHE) { + pf=NULL; + while(cfrai > pid->cache->startframe && !pf) { + cfrai--; + pf= BKE_ptcache_file_open(pid, PTCACHE_FILE_READ, cfrai); + cfra1 = cfrai; + } + if(reader->old_frame) *(reader->old_frame) = cfrai; - cfrai = (int)cfra; - while(cfrai < pid->cache->endframe && !pf2) { - cfrai++; - pf2= BKE_ptcache_file_open(pid, PTCACHE_FILE_READ, cfrai); - cfra2 = cfrai; - } + cfrai = (int)cfra; + while(cfrai < pid->cache->endframe && !pf2) { + cfrai++; + pf2= BKE_ptcache_file_open(pid, PTCACHE_FILE_READ, cfrai); + cfra2 = cfrai; } - else if(pid->cache->mem_cache.first){ - pm = pid->cache->mem_cache.first; + } + else if(pid->cache->mem_cache.first){ + pm = pid->cache->mem_cache.first; - while(pm->next && pm->next->frame < cfra) - pm= pm->next; + while(pm->next && pm->next->frame < cfra) + pm= pm->next; - if(pm) { + if(pm) { + if(reader->old_frame) *(reader->old_frame) = pm->frame; - cfra1 = pm->frame; - } + cfra1 = pm->frame; + } - pm2 = pid->cache->mem_cache.last; + pm2 = pid->cache->mem_cache.last; - while(pm2->prev && pm2->frame > cfra) + if(pm2 && pm2->frame < cfra) + pm2 = NULL; + else { + while(pm2->prev && pm2->prev->frame > cfra) pm2= pm2->prev; if(pm2) cfra2 = pm2->frame; } + } - if(reader->allow_interpolate && ((pf && pf2) || (pm && pm2))) { - /* interpolate from nearest frames */ - float *data1, *data2; + if(ret) + ; + else if((pf && pf2) || (pm && pm2)) { + /* interpolate from nearest frames if cache isn't outdated */ + float *data1, *data2; - if(pm) { - data1 = pm->data; - data2 = pm2->data; - } - else { - data1 = MEM_callocN(elemsize, "pointcache read data1"); - data2 = MEM_callocN(elemsize, "pointcache read data2"); - } + if(pm) { + data1 = pm->data; + data2 = pm2->data; + } + else { + data1 = MEM_callocN(elemsize, "pointcache read data1"); + data2 = MEM_callocN(elemsize, "pointcache read data2"); + } - for(i=0; iinterpolate_elem(i, reader->calldata, frs_sec, cfra, cfra1, cfra2, data1, data2); + for(i=0; iinterpolate_elem(i, reader->calldata, frs_sec, cfra, cfra1, cfra2, data1, data2); - data1 += incr; - data2 += incr; + if(!BKE_ptcache_file_read_floats(pf2, data2, incr)) { + BKE_ptcache_file_close(pf); + BKE_ptcache_file_close(pf2); + MEM_freeN(data1); + MEM_freeN(data2); + return 0; } + reader->interpolate_elem(i, reader->calldata, frs_sec, cfra, (float)cfra1, (float)cfra2, data1, data2); } + else { + reader->interpolate_elem(i, reader->calldata, frs_sec, cfra, (float)cfra1, (float)cfra2, data1, data2); + data1 += incr; + data2 += incr; + } + } - if(pf) { + if(pf) { + BKE_ptcache_file_close(pf); + BKE_ptcache_file_close(pf2); + MEM_freeN(data1); + MEM_freeN(data2); + } + + ret = PTCACHE_READ_INTERPOLATED; + } + else if(pf || pm) { + /* use last valid cache frame */ + float *data; + + /* don't read cache if allready simulated past cached frame */ + if(cfra1 && cfra1 <= pid->cache->simframe) { + if(pf) BKE_ptcache_file_close(pf); + if(pf2) BKE_ptcache_file_close(pf2); - MEM_freeN(data1); - MEM_freeN(data2); - } - return PTCACHE_READ_INTERPOLATED; + return 0; } - else if(reader->allow_old && (pf || pm)) { - /* use last valid cache frame */ - float *data; - if(pm) - data = pm->data; - else - data = MEM_callocN(elemsize, "pointcache read data"); - - for(i=0; iset_elem(i, reader->calldata, data); - } - else { - reader->set_elem(i, reader->calldata, data); - data += incr; - } - } + if(pm) + data = pm->data; + else + data = MEM_callocN(elemsize, "pointcache read data"); + for(i=0; iset_elem(i, reader->calldata, data); } - if(pf2) - BKE_ptcache_file_close(pf2); + else { + reader->set_elem(i, reader->calldata, data); + data += incr; + } + } - return PTCACHE_READ_OLD; + if(pf) { + BKE_ptcache_file_close(pf); + MEM_freeN(data); } + if(pf2) + BKE_ptcache_file_close(pf2); + + ret = PTCACHE_READ_OLD; } if(pf) @@ -550,7 +580,20 @@ int BKE_ptcache_read_cache(PTCacheReader *reader) if(pf2) BKE_ptcache_file_close(pf2); - return 0; + if((pid->cache->flag & PTCACHE_QUICK_CACHE)==0) { + /* clear invalid cache frames so that better stuff can be simulated */ + if(pid->cache->flag & PTCACHE_OUTDATED) { + BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, cfra); + } + else if(pid->cache->flag & PTCACHE_FRAMES_SKIPPED) { + if(cfra <= pid->cache->last_exact) + pid->cache->flag &= ~PTCACHE_FRAMES_SKIPPED; + + BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, MAX2(cfra,pid->cache->last_exact)); + } + } + + return ret; } /* writes cache to disk or memory */ int BKE_ptcache_write_cache(PTCacheWriter *writer) @@ -559,57 +602,118 @@ int BKE_ptcache_write_cache(PTCacheWriter *writer) PTCacheFile *pf= NULL; int elemsize = ptcache_pid_elemsize(writer->pid); int i, incr = elemsize / sizeof(float); + int add = 0, overwrite = 0, ocfra; + float temp[14]; if(writer->totelem == 0 || writer->cfra <= 0) return 0; if(cache->flag & PTCACHE_DISK_CACHE) { - pf = BKE_ptcache_file_open(writer->pid, PTCACHE_FILE_WRITE, writer->cfra); - if(!pf) - return 0; + /* allways start from scratch on the first frame */ + if(writer->cfra == cache->startframe) { + BKE_ptcache_id_clear(writer->pid, PTCACHE_CLEAR_ALL, writer->cfra); + cache->flag &= ~PTCACHE_REDO_NEEDED; + add = 1; + } + else { + int cfra = cache->endframe; + /* find last cached frame */ + while(cfra > cache->startframe && !BKE_ptcache_id_exist(writer->pid, cfra)) + cfra--; + + /* find second last cached frame */ + ocfra = cfra-1; + while(ocfra > cache->startframe && !BKE_ptcache_id_exist(writer->pid, ocfra)) + ocfra--; + + if(writer->cfra > cfra) { + if(ocfra >= cache->startframe && cfra - ocfra < cache->step) + overwrite = 1; + else + add = 1; + } + } - for(i=0; itotelem; i++) - BKE_ptcache_file_write_floats(pf, writer->elem_ptr(i, writer->calldata), incr); + if(add || overwrite) { + if(overwrite) + BKE_ptcache_id_clear(writer->pid, PTCACHE_CLEAR_FRAME, ocfra); + + pf = BKE_ptcache_file_open(writer->pid, PTCACHE_FILE_WRITE, writer->cfra); + if(!pf) + return 0; + + for(i=0; itotelem; i++) { + writer->set_elem(i, writer->calldata, &temp); + BKE_ptcache_file_write_floats(pf, &temp, incr); + } + } } else { - PTCacheMem *pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache mem"); + PTCacheMem *pm; PTCacheMem *pm2; float *pmdata; - pm->data = MEM_callocN(elemsize * writer->totelem, "Pointcache mem data"); - pmdata = pm->data; + pm2 = cache->mem_cache.first; + + /* allways start from scratch on the first frame */ + if(writer->cfra == cache->startframe) { + BKE_ptcache_id_clear(writer->pid, PTCACHE_CLEAR_ALL, writer->cfra); + cache->flag &= ~PTCACHE_REDO_NEEDED; + add = 1; + } + else { + pm2 = cache->mem_cache.last; + + if(pm2 && writer->cfra > pm2->frame) { + if(pm2 && pm2->prev && pm2->frame - pm2->prev->frame < cache->step) + overwrite = 1; + else + add = 1; + } + } - for(i=0; itotelem; i++, pmdata+=incr) - memcpy(pmdata, writer->elem_ptr(i, writer->calldata), elemsize); + if(overwrite) { + pm = cache->mem_cache.last; + pmdata = pm->data; - pm->frame = writer->cfra; - pm->totpoint = writer->totelem; + for(i=0; itotelem; i++, pmdata+=incr) { + writer->set_elem(i, writer->calldata, &temp); + memcpy(pmdata, &temp, elemsize); + } - /* find add location */ - pm2 = cache->mem_cache.first; - if(!pm2) - BLI_addtail(&cache->mem_cache, pm); - else if(pm2->frame == writer->cfra) { - /* overwrite same frame */ - MEM_freeN(pm2->data); - pm2->data = pm->data; - MEM_freeN(pm); + pm->frame = writer->cfra; } - else { - while(pm2->next && pm2->next->frame < writer->cfra) - pm2 = pm2->next; + else if(add) { + pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache mem"); + pm->data = MEM_callocN(elemsize * writer->totelem, "Pointcache mem data"); + pmdata = pm->data; + + for(i=0; itotelem; i++, pmdata+=incr) { + writer->set_elem(i, writer->calldata, &temp); + memcpy(pmdata, &temp, elemsize); + } + + pm->frame = writer->cfra; + pm->totpoint = writer->totelem; - BLI_insertlinkafter(&cache->mem_cache, pm2, pm); + BLI_addtail(&cache->mem_cache, pm); } } - if(writer->cfra - cache->last_exact == 1) - cache->last_exact = writer->cfra; + if(add || overwrite) { + if(writer->cfra - cache->last_exact == 1 + || writer->cfra == cache->startframe) { + cache->last_exact = writer->cfra; + cache->flag &= ~PTCACHE_FRAMES_SKIPPED; + } + else + cache->flag |= PTCACHE_FRAMES_SKIPPED; + } if(pf) BKE_ptcache_file_close(pf); - ptcache_update_info(writer->pid); + BKE_ptcache_update_info(writer->pid); return 1; } @@ -730,7 +834,7 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra) break; } - ptcache_update_info(pid); + BKE_ptcache_update_info(pid); } int BKE_ptcache_id_exist(PTCacheID *pid, int cfra) @@ -762,6 +866,9 @@ void BKE_ptcache_id_time(PTCacheID *pid, Scene *scene, float cfra, int *startfra PointCache *cache; float offset, time, nexttime; + /* TODO: this has to be sorter out once bsystem_time gets redone, */ + /* now caches can handle interpolating etc. too - jahka */ + /* time handling for point cache: * - simulation time is scaled by result of bsystem_time * - for offsetting time only time offset is taken into account, since @@ -798,7 +905,7 @@ void BKE_ptcache_id_time(PTCacheID *pid, Scene *scene, float cfra, int *startfra int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode) { PointCache *cache; - int reset, clear, current, after; + int reset, clear, after; if(!pid->cache) return 0; @@ -806,23 +913,17 @@ int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode) cache= pid->cache; reset= 0; clear= 0; - current= 0; after= 0; if(mode == PTCACHE_RESET_DEPSGRAPH) { if(!(cache->flag & PTCACHE_BAKED) && !BKE_ptcache_get_continue_physics()) { - if(cache->flag & PTCACHE_AUTOCACHE) { - reset= 1; + if(cache->flag & PTCACHE_QUICK_CACHE) clear= 1; - } - else { - current= 1; - after= 1; - cache->flag |= PTCACHE_OUTDATED; - } + + after= 1; } - else - cache->flag |= PTCACHE_OUTDATED; + + cache->flag |= PTCACHE_OUTDATED; } else if(mode == PTCACHE_RESET_BAKED) { if(!BKE_ptcache_get_continue_physics()) { @@ -839,17 +940,9 @@ int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode) if(!(cache->flag & PTCACHE_BAKED)) clear= 1; } - else if(mode == PTCACHE_RESET_FREE) { - if(!(cache->flag & PTCACHE_BAKED) && !BKE_ptcache_get_continue_physics()) { - if((cache->flag & PTCACHE_AUTOCACHE)==0) { - current= 1; - after= 1; - } - } - } if(reset) { - cache->flag &= ~(PTCACHE_OUTDATED|PTCACHE_SIMULATION_VALID); + cache->flag &= ~(PTCACHE_REDO_NEEDED|PTCACHE_SIMULATION_VALID); cache->simframe= 0; cache->last_exact= 0; @@ -862,12 +955,10 @@ int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode) } if(clear) BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0); - if(after) + else if(after) BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, CFRA); - if(current) - BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_FRAME, CFRA); - return (reset || clear || current || after); + return (reset || clear || after); } int BKE_ptcache_object_reset(Scene *scene, Object *ob, int mode) @@ -987,6 +1078,7 @@ PointCache *BKE_ptcache_add() cache= MEM_callocN(sizeof(PointCache), "PointCache"); cache->startframe= 1; cache->endframe= 250; + cache->step= 10; return cache; } @@ -1019,7 +1111,39 @@ PointCache *BKE_ptcache_copy(PointCache *cache) /* Baking */ -void BKE_ptcache_autocache_all(Scene *scene) +static int count_quick_cache(Scene *scene, int *quick_step) +{ + Base *base = scene->base.first; + PTCacheID *pid; + ListBase pidlist; + int autocache_count= 0; + + for(base = scene->base.first; base; base = base->next) { + if(base->object) { + BKE_ptcache_ids_from_object(&pidlist, base->object); + + for(pid=pidlist.first; pid; pid=pid->next) { + if((pid->cache->flag & PTCACHE_BAKED) + || (pid->cache->flag & PTCACHE_QUICK_CACHE)==0) + continue; + + if(pid->cache->flag & PTCACHE_OUTDATED || (pid->cache->flag & PTCACHE_SIMULATION_VALID)==0) { + if(!autocache_count) + *quick_step = pid->cache->step; + else + *quick_step = MIN2(*quick_step, pid->cache->step); + + autocache_count++; + } + } + + BLI_freelistN(&pidlist); + } + } + + return autocache_count; +} +void BKE_ptcache_quick_cache_all(Scene *scene) { PTCacheBaker baker; @@ -1032,7 +1156,7 @@ void BKE_ptcache_autocache_all(Scene *scene) baker.render=0; baker.scene=scene; - if(psys_count_autocache(scene, NULL)) + if(count_quick_cache(scene, &baker.quick_step)) BKE_ptcache_make_cache(&baker); } @@ -1050,11 +1174,10 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker) int endframe = CFRA; int bake = baker->bake; int render = baker->render; + int step = baker->quick_step; G.afbreek = 0; - //printf("Caching physics..."); - /* set caches to baking mode and figure out start frame */ if(pid) { /* cache/bake a single object */ @@ -1063,7 +1186,7 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker) if(pid->type==PTCACHE_TYPE_PARTICLES) psys_get_pointcache_start_end(scene, pid->data, &cache->startframe, &cache->endframe); - if(bake || cache->flag & PTCACHE_OUTDATED) + if(bake || cache->flag & PTCACHE_REDO_NEEDED) BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0); startframe = MAX2(cache->last_exact, cache->startframe); @@ -1072,8 +1195,9 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker) endframe = cache->endframe; cache->flag |= PTCACHE_BAKING; } - else + else { endframe = MIN2(endframe, cache->endframe); + } cache->flag &= ~PTCACHE_BAKED; } @@ -1088,31 +1212,30 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker) if(pid->type==PTCACHE_TYPE_PARTICLES) psys_get_pointcache_start_end(scene, pid->data, &cache->startframe, &cache->endframe); - if(cache->flag & PTCACHE_OUTDATED) + if((cache->flag & PTCACHE_REDO_NEEDED || (cache->flag & PTCACHE_SIMULATION_VALID)==0) + && ((cache->flag & PTCACHE_QUICK_CACHE)==0 || render || bake)) BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0); startframe = MIN2(startframe, cache->startframe); - if(bake) { - endframe = MAX2(endframe, cache->endframe); + if(bake || render) { cache->flag |= PTCACHE_BAKING; + + if(bake) + endframe = MAX2(endframe, cache->endframe); } - else if(render) - cache->flag |= PTCACHE_BAKING; cache->flag &= ~PTCACHE_BAKED; } } - BLI_freelistN(&pidlist); } CFRA= startframe; scene->r.framelen = 1.0; - scene_update_for_newframe(scene, scene->lay); - for(; CFRA <= endframe; CFRA++) { + for(; CFRA <= endframe; CFRA+=step) { float prog; if(bake) @@ -1133,7 +1256,8 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker) /* clear baking flag */ if(pid) { - cache->flag &= ~(PTCACHE_BAKING|PTCACHE_OUTDATED); + cache->flag &= ~(PTCACHE_BAKING|PTCACHE_REDO_NEEDED); + cache->flag |= PTCACHE_SIMULATION_VALID; if(bake) cache->flag |= PTCACHE_BAKED; } @@ -1141,17 +1265,26 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker) BKE_ptcache_ids_from_object(&pidlist, base->object); for(pid=pidlist.first; pid; pid=pid->next) { - cache->flag &= ~(PTCACHE_BAKING|PTCACHE_OUTDATED); + cache = pid->cache; + + if(step > 1) + cache->flag &= ~(PTCACHE_BAKING|PTCACHE_OUTDATED); + else + cache->flag &= ~(PTCACHE_BAKING|PTCACHE_REDO_NEEDED); + + cache->flag |= PTCACHE_SIMULATION_VALID; + if(bake) cache->flag |= PTCACHE_BAKED; } + BLI_freelistN(&pidlist); } - - //printf("done!\n"); scene->r.framelen = frameleno; CFRA = cfrao; scene_update_for_newframe(scene, scene->lay); + + /* TODO: call redraw all windows somehow */ } void BKE_ptcache_toggle_disk_cache(PTCacheID *pid) { @@ -1161,6 +1294,7 @@ void BKE_ptcache_toggle_disk_cache(PTCacheID *pid) { int totelem=0; int float_count=0; int tot; + int last_exact = cache->last_exact; if (!G.relbase_valid){ cache->flag &= ~PTCACHE_DISK_CACHE; @@ -1230,6 +1364,7 @@ void BKE_ptcache_toggle_disk_cache(PTCacheID *pid) { } pm->frame = cfra; + pm->totpoint = totelem; BLI_addtail(&pid->cache->mem_cache, pm); @@ -1241,4 +1376,8 @@ void BKE_ptcache_toggle_disk_cache(PTCacheID *pid) { BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0); cache->flag &= ~PTCACHE_DISK_CACHE; } + + cache->last_exact = last_exact; + + BKE_ptcache_update_info(pid); } -- cgit v1.2.3 From 7b547f7ce7351548a5dd4518ae1fc1ad9a726cbd Mon Sep 17 00:00:00 2001 From: Janne Karhu Date: Sat, 27 Jun 2009 15:41:47 +0000 Subject: Particle ID block controls: * Adding/removing particle systems to an object. * Changing of particle settings. * Currently showing an object's particle systems in a list (like materials). --- source/blender/blenkernel/BKE_particle.h | 3 ++ source/blender/blenkernel/intern/depsgraph.c | 2 +- source/blender/blenkernel/intern/modifier.c | 3 ++ source/blender/blenkernel/intern/particle.c | 74 +++++++++++++++++++++++++++- 4 files changed, 80 insertions(+), 2 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index 08aa111e0e6..4d9916b9557 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -217,6 +217,7 @@ 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); +void psys_set_current_num(Object *ob, int index); struct Object *psys_find_object(struct Scene *scene, struct ParticleSystem *psys); //struct ParticleSystem *psys_get(struct Object *ob, int index); struct ParticleData *psys_get_selected_particle(struct ParticleSystem *psys, int *index); @@ -250,6 +251,8 @@ void copy_particle_key(struct ParticleKey *to, struct ParticleKey *from, int tim void psys_particle_on_emitter(struct ParticleSystemModifierData *psmd, int distr, int index, int index_dmcache, float *fuv, float foffset, float *vec, float *nor, float *utan, float *vtan, float *orco, float *ornor); struct ParticleSystemModifierData *psys_get_modifier(struct Object *ob, struct ParticleSystem *psys); +void object_add_particle_system_slot(struct Scene *scene, struct Object *ob); +void object_remove_particle_system_slot(struct Scene *scene, struct Object *ob); struct ParticleSettings *psys_new_settings(char *name, struct Main *main); struct ParticleSettings *psys_copy_settings(struct ParticleSettings *part); void psys_flush_particle_settings(struct Scene *scene, struct ParticleSettings *part, int recalc); diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index b57b8b7a6da..a36b825293e 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -559,7 +559,7 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O dag_add_relation(dag, node, node, DAG_RL_OB_DATA, "Particle-Object Relation"); - if(psys->flag & PSYS_DISABLED || psys->flag & PSYS_DELETE) + if(!psys_check_enabled(ob, psys)) continue; if(part->phystype==PART_PHYS_KEYED && psys->keyed_ob && diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 1a6f57e75c4..80a9f173d6a 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -6295,6 +6295,9 @@ CustomDataMask particleSystemModifier_requiredDataMask(Object *ob, ModifierData MTex *mtex; int i; + if(!psmd->psys->part) + return 0; + ma= give_current_material(ob, psmd->psys->part->omat); if(ma) { for(i=0; iparticlesystem.first, i=0; psys; psys=psys->next, i++) { + if(i == index - 1) + psys->flag |= PSYS_CURRENT; + else + psys->flag &= ~PSYS_CURRENT; + } +} Object *psys_find_object(Scene *scene, ParticleSystem *psys) { Base *base = scene->base.first; @@ -307,7 +321,7 @@ int psys_check_enabled(Object *ob, ParticleSystem *psys) ParticleSystemModifierData *psmd; Mesh *me; - if(psys->flag & PSYS_DISABLED || psys->flag & PSYS_DELETE) + if(psys->flag & PSYS_DISABLED || psys->flag & PSYS_DELETE || !psys->part) return 0; if(ob->type == OB_MESH) { @@ -2915,6 +2929,61 @@ void psys_mat_hair_to_global(Object *ob, DerivedMesh *dm, short from, ParticleDa /************************************************/ /* ParticleSettings handling */ /************************************************/ +void object_add_particle_system_slot(Scene *scene, Object *ob) +{ + ParticleSystem *psys; + ModifierData *md; + ParticleSystemModifierData *psmd; + + if(!ob || ob->type != OB_MESH) + return; + + psys = ob->particlesystem.first; + for(; psys; psys=psys->next) + psys->flag &= ~PSYS_CURRENT; + + psys = MEM_callocN(sizeof(ParticleSystem), "particle_system"); + psys->pointcache = BKE_ptcache_add(); + BLI_addtail(&ob->particlesystem, psys); + + psys->part = psys_new_settings("PSys", NULL); + + 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); + + psys->totpart=0; + psys->flag = PSYS_ENABLED|PSYS_CURRENT; + psys->cfra=bsystem_time(scene,ob,scene->r.cfra+1,0.0); + + DAG_scene_sort(scene); + DAG_object_flush_update(scene, ob, OB_RECALC_DATA); +} +void object_remove_particle_system_slot(Scene *scene, Object *ob) +{ + ParticleSystem *psys = psys_get_current(ob); + ParticleSystemModifierData *psmd; + + if(!psys) + return; + + /* clear modifier */ + psmd= psys_get_modifier(ob, psys); + BLI_remlink(&ob->modifiers, psmd); + modifier_free((ModifierData *)psmd); + + /* clear particle system */ + BLI_remlink(&ob->particlesystem, psys); + psys_free(ob,psys); + + if(ob->particlesystem.first) + ((ParticleSystem *) ob->particlesystem.first)->flag |= PSYS_CURRENT; + + DAG_scene_sort(scene); + DAG_object_flush_update(scene, ob, OB_RECALC_DATA); +} static void default_particle_settings(ParticleSettings *part) { int i; @@ -3001,6 +3070,9 @@ ParticleSettings *psys_new_settings(char *name, Main *main) { ParticleSettings *part; + if(main==NULL) + main = G.main; + part= alloc_libblock(&main->particle, ID_PA, name); default_particle_settings(part); -- cgit v1.2.3 From aa4ed13e4a216a3464f7b9d6643c195927aea98a Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sun, 28 Jun 2009 07:32:00 +0000 Subject: NLA SoC: NLA Mapping Cleanup While trying to fix the mapping conversions for repeat, I came across some limitations with the current (soon to be previous) mapping methods. Now the mapping conversions should work nicely for all places that use them. --- source/blender/blenkernel/BKE_nla.h | 17 ++++++++- source/blender/blenkernel/intern/anim_sys.c | 2 +- source/blender/blenkernel/intern/nla.c | 59 +++++++++++++++++++---------- source/blender/blenkernel/nla_private.h | 3 +- 4 files changed, 58 insertions(+), 23 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_nla.h b/source/blender/blenkernel/BKE_nla.h index cc73ac02690..e2b1dd89deb 100644 --- a/source/blender/blenkernel/BKE_nla.h +++ b/source/blender/blenkernel/BKE_nla.h @@ -73,7 +73,22 @@ void BKE_nla_action_pushdown(struct AnimData *adt); short BKE_nla_tweakmode_enter(struct AnimData *adt); void BKE_nla_tweakmode_exit(struct AnimData *adt); -float BKE_nla_tweakedit_remap(struct AnimData *adt, float cframe, short invert); +/* ----------------------------- */ +/* Time Mapping */ + +/* time mapping conversion modes */ +enum { + /* convert from global time to strip time - for evaluation */ + NLATIME_CONVERT_EVAL = 0, + /* convert from global time to strip time - for editing corrections */ + // XXX old 0 invert + NLATIME_CONVERT_UNMAP, + /* convert from strip time to global time */ + // xxx old 1 invert + NLATIME_CONVERT_MAP, +} eNlaTime_ConvertModes; + +float BKE_nla_tweakedit_remap(struct AnimData *adt, float cframe, short mode); #endif diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 288867505be..4c0c30fe5c1 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -604,7 +604,7 @@ static void nlastrip_evaluate_controls (NlaStrip *strip, float ctime) { /* firstly, analytically generate values for influence and time (if applicable) */ if ((strip->flag & NLASTRIP_FLAG_USR_TIME) == 0) - strip->strip_time= nlastrip_get_frame(strip, ctime, 0); + strip->strip_time= nlastrip_get_frame(strip, ctime, NLATIME_CONVERT_EVAL); if ((strip->flag & NLASTRIP_FLAG_USR_INFLUENCE) == 0) strip->influence= nlastrip_get_influence(strip, ctime); diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index 760139bee15..2b95584dc25 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -329,7 +329,7 @@ NlaStrip *add_nlastrip_to_stack (AnimData *adt, bAction *act) /* non clipped mapping for strip-time <-> global time (for Action-Clips) * invert = convert action-strip time to global time */ -static float nlastrip_get_frame_actionclip (NlaStrip *strip, float cframe, short invert) +static float nlastrip_get_frame_actionclip (NlaStrip *strip, float cframe, short mode) { float actlength, repeat, scale; @@ -347,9 +347,20 @@ static float nlastrip_get_frame_actionclip (NlaStrip *strip, float cframe, short /* reversed = play strip backwards */ if (strip->flag & NLASTRIP_FLAG_REVERSE) { - /* invert = convert action-strip time to global time */ - if (invert) - return scale*(strip->actend - cframe) + strip->start; // FIXME: this doesn't work for multiple repeats yet + // FIXME: this won't work right with Graph Editor? + if (mode == NLATIME_CONVERT_MAP) { + return strip->end - scale*(cframe - strip->actstart); + } + else if (mode == NLATIME_CONVERT_UNMAP) { + int repeatsNum = (int)((cframe - strip->start) / (actlength * scale)); + + /* this method doesn't clip the values to lie within the action range only + * - the '(repeatsNum * actlength * scale)' compensates for the fmod(...) + * - the fmod(...) works in the same way as for eval + */ + return strip->actend - (repeatsNum * actlength * scale) + - (fmod(cframe - strip->start, actlength*scale) / scale); + } else { if (IS_EQ(cframe, strip->end) && IS_EQ(strip->repeat, ((int)strip->repeat))) { /* this case prevents the motion snapping back to the first frame at the end of the strip @@ -367,10 +378,20 @@ static float nlastrip_get_frame_actionclip (NlaStrip *strip, float cframe, short } } else { - /* invert = convert action-strip time to global time */ - if (invert) - return scale*(cframe - strip->actstart) + strip->start; // FIXME: this doesn't work for mutiple repeats yet - else { + if (mode == NLATIME_CONVERT_MAP) { + return strip->start + scale*(cframe - strip->actstart); + } + else if (mode == NLATIME_CONVERT_UNMAP) { + int repeatsNum = (int)((cframe - strip->start) / (actlength * scale)); + + /* this method doesn't clip the values to lie within the action range only + * - the '(repeatsNum * actlength * scale)' compensates for the fmod(...) + * - the fmod(...) works in the same way as for eval + */ + return strip->actstart + (repeatsNum * actlength * scale) + + (fmod(cframe - strip->start, actlength*scale) / scale); + } + else /* if (mode == NLATIME_CONVERT_EVAL) */{ if (IS_EQ(cframe, strip->end) && IS_EQ(strip->repeat, ((int)strip->repeat))) { /* this case prevents the motion snapping back to the first frame at the end of the strip * by catching the case where repeats is a whole number, which means that the end of the strip @@ -391,7 +412,7 @@ static float nlastrip_get_frame_actionclip (NlaStrip *strip, float cframe, short /* non clipped mapping for strip-time <-> global time (for Transitions) * invert = convert action-strip time to global time */ -static float nlastrip_get_frame_transition (NlaStrip *strip, float cframe, short invert) +static float nlastrip_get_frame_transition (NlaStrip *strip, float cframe, short mode) { float length; @@ -400,15 +421,13 @@ static float nlastrip_get_frame_transition (NlaStrip *strip, float cframe, short /* reversed = play strip backwards */ if (strip->flag & NLASTRIP_FLAG_REVERSE) { - /* invert = convert within-strip-time to global time */ - if (invert) + if (mode == NLATIME_CONVERT_MAP) return strip->end - (length * cframe); else return (strip->end - cframe) / length; } else { - /* invert = convert within-strip-time to global time */ - if (invert) + if (mode == NLATIME_CONVERT_MAP) return (length * cframe) + strip->start; else return (cframe - strip->start) / length; @@ -416,31 +435,31 @@ static float nlastrip_get_frame_transition (NlaStrip *strip, float cframe, short } /* non clipped mapping for strip-time <-> global time - * invert = convert action-strip time to global time + * mode = eNlaTime_ConvertModes[] -> NLATIME_CONVERT_* * * only secure for 'internal' (i.e. within AnimSys evaluation) operations, * but should not be directly relied on for stuff which interacts with editors */ -float nlastrip_get_frame (NlaStrip *strip, float cframe, short invert) +float nlastrip_get_frame (NlaStrip *strip, float cframe, short mode) { switch (strip->type) { case NLASTRIP_TYPE_TRANSITION: /* transition */ - return nlastrip_get_frame_transition(strip, cframe, invert); + return nlastrip_get_frame_transition(strip, cframe, mode); case NLASTRIP_TYPE_CLIP: /* action-clip (default) */ default: - return nlastrip_get_frame_actionclip(strip, cframe, invert); + return nlastrip_get_frame_actionclip(strip, cframe, mode); } } /* Non clipped mapping for strip-time <-> global time - * invert = convert strip-time to global time + * mode = eNlaTime_ConvertModesp[] -> NLATIME_CONVERT_* * * Public API method - perform this mapping using the given AnimData block * and perform any necessary sanity checks on the value */ -float BKE_nla_tweakedit_remap (AnimData *adt, float cframe, short invert) +float BKE_nla_tweakedit_remap (AnimData *adt, float cframe, short mode) { NlaStrip *strip; @@ -469,7 +488,7 @@ float BKE_nla_tweakedit_remap (AnimData *adt, float cframe, short invert) return cframe; /* perform the correction now... */ - return nlastrip_get_frame(strip, cframe, invert); + return nlastrip_get_frame(strip, cframe, mode); } /* *************************************************** */ diff --git a/source/blender/blenkernel/nla_private.h b/source/blender/blenkernel/nla_private.h index af886fb7de8..1514a79f03b 100644 --- a/source/blender/blenkernel/nla_private.h +++ b/source/blender/blenkernel/nla_private.h @@ -73,6 +73,7 @@ typedef struct NlaEvalChannel { /* --------------- NLA Functions (not to be used as a proper API) ----------------------- */ /* convert from strip time <-> global time */ -float nlastrip_get_frame(NlaStrip *strip, float cframe, short invert); +float nlastrip_get_frame(NlaStrip *strip, float cframe, short mode); + #endif // NLA_PRIVATE -- cgit v1.2.3 From 6998a0f47b673591f8561cda35d50e93979de32c Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Sun, 28 Jun 2009 09:35:37 +0000 Subject: 2.5 Bugfixes: - Preview Icon for render result crashed, there was still need for a scene pointer to be passed on. - Added quick fix for preventing shaded drawmode to call render while rendering is in progress. It crashes badly. Rendering while UI is alive is still in probation, most UI stuff will probably get blocked, with exception from inspecting buttons and using the image window. --- source/blender/blenkernel/intern/displist.c | 36 ++++++++++++++++++----------- source/blender/blenkernel/intern/image.c | 2 +- 2 files changed, 24 insertions(+), 14 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index 736165a8a98..cdf4b90cee1 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -315,13 +315,19 @@ static void init_fastshade_shadeinput(Render *re) static Render *fastshade_get_render(Scene *scene) { - Render *re= RE_GetRender("_Shade View_"); - if(re==NULL) { - re= RE_NewRender("_Shade View_"); - - RE_Database_Baking(re, scene, 0, 0); /* 0= no faces */ + /* XXX ugly global still, but we can't do preview while rendering */ + if(G.rendering==0) { + + Render *re= RE_GetRender("_Shade View_"); + if(re==NULL) { + re= RE_NewRender("_Shade View_"); + + RE_Database_Baking(re, scene, 0, 0); /* 0= no faces */ + } + return re; } - return re; + + return NULL; } /* called on file reading */ @@ -611,18 +617,20 @@ static void mesh_create_shadedColors(Render *re, Object *ob, int onlyForMesh, un void shadeMeshMCol(Scene *scene, Object *ob, Mesh *me) { + Render *re= fastshade_get_render(scene); int a; char *cp; unsigned int *mcol= (unsigned int*)me->mcol; - Render *re= fastshade_get_render(scene); - mesh_create_shadedColors(re, ob, 1, &mcol, NULL); - me->mcol= (MCol*)mcol; + if(re) { + mesh_create_shadedColors(re, ob, 1, &mcol, NULL); + me->mcol= (MCol*)mcol; - /* swap bytes */ - for(cp= (char *)me->mcol, a= 4*me->totface; a>0; a--, cp+=4) { - SWAP(char, cp[0], cp[3]); - SWAP(char, cp[1], cp[2]); + /* swap bytes */ + for(cp= (char *)me->mcol, a= 4*me->totface; a>0; a--, cp+=4) { + SWAP(char, cp[0], cp[3]); + SWAP(char, cp[1], cp[2]); + } } } @@ -641,6 +649,8 @@ void shadeDispList(Scene *scene, Base *base) int a, need_orco; re= fastshade_get_render(scene); + if(re==NULL) + return; dl = find_displist(&ob->disp, DL_VERTCOL); if (dl) { diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 8eef9984c92..6b231cfc702 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -1812,7 +1812,7 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser) Render *re= NULL; RenderResult *rr= NULL; - if(iuser->scene) { + if(iuser && iuser->scene) { re= RE_GetRender(iuser->scene->id.name); rr= RE_GetResult(re); } -- cgit v1.2.3 From 8bf355533e9868f0c39f1e9330753d9da5810b83 Mon Sep 17 00:00:00 2001 From: Elia Sarti Date: Sun, 28 Jun 2009 11:37:45 +0000 Subject: Zeroing listbase result for context data collection get when no data is found. Caused crash for uninitialized pointers when getting collection data for editors not supporting that member, e.g. "deselect all" operator in non-3dview editors. --- source/blender/blenkernel/intern/context.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c index 90880e354ec..fbad585d9b7 100644 --- a/source/blender/blenkernel/intern/context.c +++ b/source/blender/blenkernel/intern/context.c @@ -358,6 +358,9 @@ static int ctx_data_collection_get(const bContext *C, const char *member, ListBa return 1; } + list->first= NULL; + list->last= NULL; + return 0; } -- cgit v1.2.3 From 37864a4273a5f9217f9b5995dc70212bb97a6cf6 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Tue, 30 Jun 2009 19:20:45 +0000 Subject: 2.5 Image Window * Unpack operator now works. * Some small layout code tweaks. Info Window Header * Moved to python UI code. * template_running_jobs, template_operator_search added. * Ported external data operators: pack/unpack all, make paths relative/absolute, find/report missing files. Also * Report RPT_INFO too, not only warnings and errors. * Run UI handle functions after RNA and Operators. * Rename particle system add/remove operators, to not include "slot", that's only there for materials because that's what they are called now in RNA. --- source/blender/blenkernel/BKE_packedFile.h | 54 +++--- source/blender/blenkernel/BKE_particle.h | 4 +- source/blender/blenkernel/BKE_report.h | 5 +- source/blender/blenkernel/intern/font.c | 8 +- source/blender/blenkernel/intern/image.c | 4 +- source/blender/blenkernel/intern/packedFile.c | 227 +++++++++----------------- source/blender/blenkernel/intern/particle.c | 4 +- source/blender/blenkernel/intern/report.c | 4 +- 8 files changed, 124 insertions(+), 186 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_packedFile.h b/source/blender/blenkernel/BKE_packedFile.h index 2d5acc51b7b..efd930d375a 100644 --- a/source/blender/blenkernel/BKE_packedFile.h +++ b/source/blender/blenkernel/BKE_packedFile.h @@ -31,31 +31,43 @@ #ifndef BKE_PACKEDFILE_H #define BKE_PACKEDFILE_H -#define RET_OK 0 -#define RET_ERROR 1 +#define RET_OK 0 +#define RET_ERROR 1 -struct PackedFile; -struct VFont; struct bSample; struct bSound; struct Image; +struct Main; +struct PackedFile; +struct ReportList; +struct VFont; + +/* pack */ +struct PackedFile *newPackedFile(struct ReportList *reports, char *filename); +struct PackedFile *newPackedFileMemory(void *mem, int memlen); + +void packAll(struct Main *bmain, struct ReportList *reports); + +/* unpack */ +char *unpackFile(struct ReportList *reports, char *abs_name, char *local_name, struct PackedFile *pf, int how); +int unpackVFont(struct ReportList *reports, struct VFont *vfont, int how); +int unpackSample(struct ReportList *reports, struct bSample *sample, int how); +int unpackImage(struct ReportList *reports, struct Image *ima, int how); +void unpackAll(struct Main *bmain, struct ReportList *reports, int how); + +int writePackedFile(struct ReportList *reports, char *filename, struct PackedFile *pf, int guimode); + +/* free */ +void freePackedFile(struct PackedFile *pf); + +/* info */ +int countPackedFiles(struct Main *bmain); +int checkPackedFile(char *filename, struct PackedFile *pf); + +/* read */ +int seekPackedFile(struct PackedFile *pf, int offset, int whence); +void rewindPackedFile(struct PackedFile *pf); +int readPackedFile(struct PackedFile *pf, void *data, int size); -struct PackedFile * newPackedFile(char * filename); -struct PackedFile * newPackedFileMemory(void *mem, int memlen); - -int seekPackedFile(struct PackedFile * pf, int offset, int whence); -void rewindPackedFile(struct PackedFile * pf); -int readPackedFile(struct PackedFile * pf, void * data, int size); -int countPackedFiles(void); -void freePackedFile(struct PackedFile * pf); -void packAll(void); -int writePackedFile(char * filename, struct PackedFile *pf, int guimode); -int checkPackedFile(char * filename, struct PackedFile * pf); -char * unpackFile(char * abs_name, char * local_name, struct PackedFile * pf, int how); -int unpackVFont(struct VFont * vfont, int how); -int unpackSample(struct bSample *sample, int how); -int unpackImage(struct Image * ima, int how); -void unpackAll(int how); - #endif diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index 4d9916b9557..73f0195d1d8 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -251,8 +251,8 @@ void copy_particle_key(struct ParticleKey *to, struct ParticleKey *from, int tim void psys_particle_on_emitter(struct ParticleSystemModifierData *psmd, int distr, int index, int index_dmcache, float *fuv, float foffset, float *vec, float *nor, float *utan, float *vtan, float *orco, float *ornor); struct ParticleSystemModifierData *psys_get_modifier(struct Object *ob, struct ParticleSystem *psys); -void object_add_particle_system_slot(struct Scene *scene, struct Object *ob); -void object_remove_particle_system_slot(struct Scene *scene, struct Object *ob); +void object_add_particle_system(struct Scene *scene, struct Object *ob); +void object_remove_particle_system(struct Scene *scene, struct Object *ob); struct ParticleSettings *psys_new_settings(char *name, struct Main *main); struct ParticleSettings *psys_copy_settings(struct ParticleSettings *part); void psys_flush_particle_settings(struct Scene *scene, struct ParticleSettings *part, int recalc); diff --git a/source/blender/blenkernel/BKE_report.h b/source/blender/blenkernel/BKE_report.h index 21221026b8b..1bb7152fbf3 100644 --- a/source/blender/blenkernel/BKE_report.h +++ b/source/blender/blenkernel/BKE_report.h @@ -34,7 +34,10 @@ extern "C" { #include "DNA_listBase.h" -/* Reporting Information and Errors */ +/* Reporting Information and Errors + * + * These functions also accept NULL in case no error reporting + * is needed. */ typedef enum ReportType { RPT_DEBUG = 0, diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c index 60a7ffc28d9..70901778585 100644 --- a/source/blender/blenkernel/intern/font.c +++ b/source/blender/blenkernel/intern/font.c @@ -333,11 +333,11 @@ static VFontData *vfont_get_data(VFont *vfont) BLI_addtail(&ttfdata, tmpfnt); } } else { - pf= newPackedFile(vfont->name); + pf= newPackedFile(NULL, vfont->name); if(!tmpfnt) { - tpf= newPackedFile(vfont->name); + tpf= newPackedFile(NULL, vfont->name); // Add temporary packed file to globals tmpfnt= (struct TmpFont *) MEM_callocN(sizeof(struct TmpFont), "temp_font"); @@ -385,8 +385,8 @@ VFont *load_vfont(char *name) strcpy(dir, name); BLI_splitdirstring(dir, filename); - pf= newPackedFile(name); - tpf= newPackedFile(name); + pf= newPackedFile(NULL, name); + tpf= newPackedFile(NULL, name); is_builtin= 0; } diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 6b231cfc702..ef0984bf93d 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -1431,7 +1431,7 @@ void BKE_image_signal(Image *ima, ImageUser *iuser, int signal) /* try to repack file */ if(ima->packedfile) { PackedFile *pf; - pf = newPackedFile(ima->name); + pf = newPackedFile(NULL, ima->name); if (pf) { freePackedFile(ima->packedfile); ima->packedfile = pf; @@ -1750,7 +1750,7 @@ static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra) /* make packed file for autopack */ if ((ima->packedfile == NULL) && (G.fileflags & G_AUTOPACK)) - ima->packedfile = newPackedFile(str); + ima->packedfile = newPackedFile(NULL, str); } if(ima->flag & IMA_DO_PREMUL) diff --git a/source/blender/blenkernel/intern/packedFile.c b/source/blender/blenkernel/intern/packedFile.c index 22e4e8a8309..4d88556d8bf 100644 --- a/source/blender/blenkernel/intern/packedFile.c +++ b/source/blender/blenkernel/intern/packedFile.c @@ -61,8 +61,9 @@ #include "BKE_image.h" #include "BKE_font.h" #include "BKE_packedFile.h" +#include "BKE_report.h" -int seekPackedFile(PackedFile * pf, int offset, int whence) +int seekPackedFile(PackedFile *pf, int offset, int whence) { int oldseek = -1, seek = 0; @@ -92,12 +93,12 @@ int seekPackedFile(PackedFile * pf, int offset, int whence) return(oldseek); } -void rewindPackedFile(PackedFile * pf) +void rewindPackedFile(PackedFile *pf) { seekPackedFile(pf, 0, SEEK_SET); } -int readPackedFile(PackedFile * pf, void * data, int size) +int readPackedFile(PackedFile *pf, void *data, int size) { if ((pf != NULL) && (size >= 0) && (data != NULL)) { if (size + pf->seek > pf->size) { @@ -118,66 +119,55 @@ int readPackedFile(PackedFile * pf, void * data, int size) return(size); } -int countPackedFiles() +int countPackedFiles(Main *bmain) { - int count = 0; Image *ima; VFont *vf; bSample *sample; + int count = 0; // let's check if there are packed files... - ima = G.main->image.first; - while (ima) { - if (ima->packedfile) { + for(ima=bmain->image.first; ima; ima=ima->id.next) + if(ima->packedfile) count++; - } - ima= ima->id.next; - } - vf = G.main->vfont.first; - while (vf) { - if (vf->packedfile) { + for(vf=bmain->vfont.first; vf; vf=vf->id.next) + if(vf->packedfile) count++; - } - vf = vf->id.next; - } - sample = samples->first; - while (sample) { - if (sample->packedfile) { - count++; - } - sample = sample->id.next; - } + if(samples) + for(sample=samples->first; sample; sample=sample->id.next) + if(sample->packedfile) + count++; - return(count); + return count; } -void freePackedFile(PackedFile * pf) +void freePackedFile(PackedFile *pf) { - if (pf) { + if(pf) { MEM_freeN(pf->data); MEM_freeN(pf); - } else { - printf("freePackedFile: Trying to free a NULL pointer\n"); } + else + printf("freePackedFile: Trying to free a NULL pointer\n"); } -PackedFile * newPackedFileMemory(void *mem, int memlen) +PackedFile *newPackedFileMemory(void *mem, int memlen) { - PackedFile * pf = MEM_callocN(sizeof(*pf), "PackedFile"); + PackedFile *pf = MEM_callocN(sizeof(*pf), "PackedFile"); pf->data = mem; pf->size = memlen; return pf; } -PackedFile * newPackedFile(char * filename) +PackedFile *newPackedFile(ReportList *reports, char *filename) { - PackedFile * pf = NULL; + PackedFile *pf = NULL; int file, filelen; char name[FILE_MAXDIR+FILE_MAXFILE]; - void * data; + void *data; //XXX waitcursor(1); @@ -191,7 +181,7 @@ PackedFile * newPackedFile(char * filename) file= open(name, O_BINARY|O_RDONLY); if (file <= 0) { - // error("Can't open file: %s", name); + BKE_reportf(reports, RPT_ERROR, "Can't open file: %s", name); } else { filelen = BLI_filesize(file); @@ -214,36 +204,24 @@ PackedFile * newPackedFile(char * filename) return (pf); } -void packAll() +void packAll(Main *bmain, ReportList *reports) { Image *ima; VFont *vf; bSample *sample; - ima = G.main->image.first; - while (ima) { - if (ima->packedfile == NULL) { - ima->packedfile = newPackedFile(ima->name); - } - ima= ima->id.next; - } - - vf = G.main->vfont.first; - while (vf) { - if (vf->packedfile == NULL) { - vf->packedfile = newPackedFile(vf->name); - } - vf = vf->id.next; - } + for(ima=bmain->image.first; ima; ima=ima->id.next) + if(ima->packedfile == NULL) + ima->packedfile = newPackedFile(reports, ima->name); + for(vf=bmain->vfont.first; vf; vf=vf->id.next) + if(vf->packedfile == NULL) + vf->packedfile = newPackedFile(reports, vf->name); - sample = samples->first; - while (sample) { - if (sample->packedfile == NULL) { - sound_set_packedfile(sample, newPackedFile(sample->name)); - } - sample = sample->id.next; - } + if(samples) + for(sample=samples->first; sample; sample=sample->id.next) + if(sample->packedfile == NULL) + sound_set_packedfile(sample, newPackedFile(reports, sample->name)); } @@ -252,10 +230,10 @@ void packAll() // attempt to create a function that generates an unique filename // this will work when all funtions in fileops.c understand relative filenames... -char * find_new_name(char * name) +char *find_new_name(char *name) { char tempname[FILE_MAXDIR + FILE_MAXFILE]; - char * newname; + char *newname; if (fop_exists(name)) { for (number = 1; number <= 999; number++) { @@ -274,13 +252,13 @@ char * find_new_name(char * name) */ -int writePackedFile(char * filename, PackedFile *pf, int guimode) +int writePackedFile(ReportList *reports, char *filename, PackedFile *pf, int guimode) { int file, number, remove_tmp = FALSE; int ret_value = RET_OK; char name[FILE_MAXDIR + FILE_MAXFILE]; char tempname[FILE_MAXDIR + FILE_MAXFILE]; -/* void * data; */ +/* void *data; */ if (guimode); //XXX waitcursor(1); @@ -305,23 +283,23 @@ int writePackedFile(char * filename, PackedFile *pf, int guimode) file = open(name, O_BINARY + O_WRONLY + O_CREAT + O_TRUNC, 0666); if (file >= 0) { if (write(file, pf->data, pf->size) != pf->size) { - if(guimode) ; //XXX error("Error writing file: %s", name); + BKE_reportf(reports, RPT_ERROR, "Error writing file: %s", name); ret_value = RET_ERROR; } close(file); } else { - if(guimode); //XXX error("Error creating file: %s", name); + BKE_reportf(reports, RPT_ERROR, "Error creating file: %s", name); ret_value = RET_ERROR; } if (remove_tmp) { if (ret_value == RET_ERROR) { if (BLI_rename(tempname, name) != 0) { - if(guimode); //XXX error("Error restoring tempfile. Check files: '%s' '%s'", tempname, name); + BKE_reportf(reports, RPT_ERROR, "Error restoring tempfile. Check files: '%s' '%s'", tempname, name); } } else { if (BLI_delete(tempname, 0, 0) != 0) { - if(guimode); //XXX error("Error deleting '%s' (ignored)"); + BKE_reportf(reports, RPT_ERROR, "Error deleting '%s' (ignored)", tempname); } } } @@ -342,7 +320,7 @@ PF_NOFILE - the original file doens't exist */ -int checkPackedFile(char * filename, PackedFile * pf) +int checkPackedFile(char *filename, PackedFile *pf) { struct stat st; int ret_val, i, len, file; @@ -390,68 +368,23 @@ int checkPackedFile(char * filename, PackedFile * pf) /* -unpackFile() looks at the existing files (abs_name, local_name) and a packed file. -If how == PF_ASK it offers the user a couple of options what to do with the packed file. + unpackFile() looks at the existing files (abs_name, local_name) and a packed file. -It returns a char * to the existing file name / new file name or NULL when +It returns a char *to the existing file name / new file name or NULL when there was an error or when the user desides to cancel the operation. */ -char *unpackFile(char * abs_name, char * local_name, PackedFile * pf, int how) +char *unpackFile(ReportList *reports, char *abs_name, char *local_name, PackedFile *pf, int how) { - char menu[6 * (FILE_MAXDIR + FILE_MAXFILE + 100)]; + char menu[6 *(FILE_MAXDIR + FILE_MAXFILE + 100)]; char line[FILE_MAXDIR + FILE_MAXFILE + 100]; - char * newname = NULL, * temp = NULL; + char *newname = NULL, *temp = NULL; // char newabs[FILE_MAXDIR + FILE_MAXFILE]; // char newlocal[FILE_MAXDIR + FILE_MAXFILE]; if (pf != NULL) { - if (how == PF_ASK) { - sprintf(menu, "UnPack file%%t|Remove Pack %%x%d", PF_REMOVE); - - if (strcmp(abs_name, local_name)) { - switch (checkPackedFile(local_name, pf)) { - case PF_NOFILE: - sprintf(line, "|Create %s%%x%d", local_name, PF_WRITE_LOCAL); - strcat(menu, line); - break; - case PF_EQUAL: - sprintf(line, "|Use %s (identical)%%x%d", local_name, PF_USE_LOCAL); - strcat(menu, line); - break; - case PF_DIFFERS: - sprintf(line, "|Use %s (differs)%%x%d", local_name, PF_USE_LOCAL); - strcat(menu, line); - sprintf(line, "|Overwrite %s%%x%d", local_name, PF_WRITE_LOCAL); - strcat(menu, line); - break; - } - // sprintf(line, "|%%x%d", PF_INVALID); - // strcat(menu, line); - } - - switch (checkPackedFile(abs_name, pf)) { - case PF_NOFILE: - sprintf(line, "|Create %s%%x%d", abs_name, PF_WRITE_ORIGINAL); - strcat(menu, line); - break; - case PF_EQUAL: - sprintf(line, "|Use %s (identical)%%x%d", abs_name, PF_USE_ORIGINAL); - strcat(menu, line); - break; - case PF_DIFFERS: - sprintf(line, "|Use %s (differs)%%x%d", abs_name, PF_USE_ORIGINAL); - strcat(menu, line); - sprintf(line, "|Overwrite %s%%x%d", abs_name, PF_WRITE_ORIGINAL); - strcat(menu, line); - break; - } - - //XXX how = pupmenu(menu); - } - switch (how) { case -1: case PF_KEEP: @@ -467,7 +400,7 @@ char *unpackFile(char * abs_name, char * local_name, PackedFile * pf, int how) } // else fall through and create it case PF_WRITE_LOCAL: - if (writePackedFile(local_name, pf, 1) == RET_OK) { + if (writePackedFile(reports, local_name, pf, 1) == RET_OK) { temp = local_name; } break; @@ -479,7 +412,7 @@ char *unpackFile(char * abs_name, char * local_name, PackedFile * pf, int how) } // else fall through and create it case PF_WRITE_ORIGINAL: - if (writePackedFile(abs_name, pf, 1) == RET_OK) { + if (writePackedFile(reports, abs_name, pf, 1) == RET_OK) { temp = abs_name; } break; @@ -498,10 +431,10 @@ char *unpackFile(char * abs_name, char * local_name, PackedFile * pf, int how) } -int unpackVFont(VFont * vfont, int how) +int unpackVFont(ReportList *reports, VFont *vfont, int how) { char localname[FILE_MAXDIR + FILE_MAXFILE], fi[FILE_MAXFILE]; - char * newname; + char *newname; int ret_value = RET_ERROR; if (vfont != NULL) { @@ -510,7 +443,7 @@ int unpackVFont(VFont * vfont, int how) sprintf(localname, "//fonts/%s", fi); - newname = unpackFile(vfont->name, localname, vfont->packedfile, how); + newname = unpackFile(reports, vfont->name, localname, vfont->packedfile, how); if (newname != NULL) { ret_value = RET_OK; freePackedFile(vfont->packedfile); @@ -523,10 +456,10 @@ int unpackVFont(VFont * vfont, int how) return (ret_value); } -int unpackSample(bSample *sample, int how) +int unpackSample(ReportList *reports, bSample *sample, int how) { char localname[FILE_MAXDIR + FILE_MAX], fi[FILE_MAX]; - char * newname; + char *newname; int ret_value = RET_ERROR; PackedFile *pf; @@ -535,7 +468,7 @@ int unpackSample(bSample *sample, int how) BLI_splitdirstring(localname, fi); sprintf(localname, "//samples/%s", fi); - newname = unpackFile(sample->name, localname, sample->packedfile, how); + newname = unpackFile(reports, sample->name, localname, sample->packedfile, how); if (newname != NULL) { strcpy(sample->name, newname); MEM_freeN(newname); @@ -553,10 +486,10 @@ int unpackSample(bSample *sample, int how) return(ret_value); } -int unpackImage(Image * ima, int how) +int unpackImage(ReportList *reports, Image *ima, int how) { char localname[FILE_MAXDIR + FILE_MAX], fi[FILE_MAX]; - char * newname; + char *newname; int ret_value = RET_ERROR; if (ima != NULL) { @@ -564,7 +497,7 @@ int unpackImage(Image * ima, int how) BLI_splitdirstring(localname, fi); sprintf(localname, "//textures/%s", fi); - newname = unpackFile(ima->name, localname, ima->packedfile, how); + newname = unpackFile(reports, ima->name, localname, ima->packedfile, how); if (newname != NULL) { ret_value = RET_OK; freePackedFile(ima->packedfile); @@ -578,33 +511,23 @@ int unpackImage(Image * ima, int how) return(ret_value); } -void unpackAll(int how) +void unpackAll(Main *bmain, ReportList *reports, int how) { Image *ima; VFont *vf; bSample *sample; - - ima = G.main->image.first; - while (ima) { - if (ima->packedfile) { - unpackImage(ima, how); - } - ima= ima->id.next; - } - - vf = G.main->vfont.first; - while (vf) { - if (vf->packedfile) { - unpackVFont(vf, how); - } - vf = vf->id.next; - } - sample = samples->first; - while (sample) { - if (sample->packedfile) { - unpackSample(sample, how); - } - sample = sample->id.next; - } + for(ima=bmain->image.first; ima; ima=ima->id.next) + if(ima->packedfile) + unpackImage(reports, ima, how); + + for(vf=bmain->vfont.first; vf; vf=vf->id.next) + if(vf->packedfile) + unpackVFont(reports, vf, how); + + if(samples) + for(sample=samples->first; sample; sample=sample->id.next) + if(sample->packedfile) + unpackSample(reports, sample, how); } + diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 2474053298d..31e60e985d5 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -2929,7 +2929,7 @@ void psys_mat_hair_to_global(Object *ob, DerivedMesh *dm, short from, ParticleDa /************************************************/ /* ParticleSettings handling */ /************************************************/ -void object_add_particle_system_slot(Scene *scene, Object *ob) +void object_add_particle_system(Scene *scene, Object *ob) { ParticleSystem *psys; ModifierData *md; @@ -2961,7 +2961,7 @@ void object_add_particle_system_slot(Scene *scene, Object *ob) DAG_scene_sort(scene); DAG_object_flush_update(scene, ob, OB_RECALC_DATA); } -void object_remove_particle_system_slot(Scene *scene, Object *ob) +void object_remove_particle_system(Scene *scene, Object *ob) { ParticleSystem *psys = psys_get_current(ob); ParticleSystemModifierData *psmd; diff --git a/source/blender/blenkernel/intern/report.c b/source/blender/blenkernel/intern/report.c index 116fd069948..8de8cf8d0f4 100644 --- a/source/blender/blenkernel/intern/report.c +++ b/source/blender/blenkernel/intern/report.c @@ -65,8 +65,8 @@ void BKE_reports_init(ReportList *reports, int flag) memset(reports, 0, sizeof(ReportList)); - reports->storelevel= RPT_WARNING; - reports->printlevel= RPT_WARNING; + reports->storelevel= RPT_INFO; + reports->printlevel= RPT_INFO; reports->flag= flag; } -- cgit v1.2.3 From 82055c82170885249bf922b05a5c7a3186c07c71 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 1 Jul 2009 12:19:00 +0000 Subject: RNA * Mesh.add_geometry, Mesh.update and make indices editable. This is without checking if they are valid still, no time now to implement this. * Also fix warnings in rna_ui.c, and a bug in CDDM_calc_edges. Example code: co = [0.0, 0.0, 0.0] + [1.0, 0.0, 0.0] + [0.0, 1.0, 0.0] + [1.0, 1.0, 0.0] faces = [0, 1, 2, 0] + [1, 3, 2, 0] mesh.add_geometry(4, 0, 2) mesh.verts.foreach_set("co", co) mesh.faces.foreach_set("verts", faces) mesh.update() --- source/blender/blenkernel/intern/cdderivedmesh.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index 57ef920f75b..706eece108c 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -1220,7 +1220,7 @@ void CDDM_calc_edges(DerivedMesh *dm) BLI_edgehashIterator_free(ehi); /* free old CustomData and assign new one */ - CustomData_free(&dm->edgeData, dm->numVertData); + CustomData_free(&dm->edgeData, dm->numEdgeData); dm->edgeData = edgeData; dm->numEdgeData = numEdges; -- cgit v1.2.3 From 421f44278cebff49a1485251f92a4277934c4e4c Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 1 Jul 2009 22:25:49 +0000 Subject: 2.5: Lists for vertex groups, shape keys, uvs, vertex colors. RNA * Added the relevant active_*_index properties, with proper get/set/range, updates and notifiers. * Context.tool_settings. * ToolSettings.vertex_group_weight. Operators * MESH_OT_uv_texture_add/remove * MESH_OT_vertex_color_add/remove * MESH_OT_sticky_add/remove * OBJECT_OT_vertex_group_add/remove/assign/remove_from/ select/deselect/copy/copy_to_linked * OBJECT_OT_shape_key_add/remove UI * Some updates and cleanups in list template code. Known issue: when going in & out of editmode, uv textures and vertex colors dissappear. I thought me->edit_mesh would be NULL when not in edit mode but it is not? --- source/blender/blenkernel/intern/particle.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 31e60e985d5..5bf9335d211 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -230,7 +230,7 @@ void psys_set_current_num(Object *ob, int index) if(ob==0) return; for(psys=ob->particlesystem.first, i=0; psys; psys=psys->next, i++) { - if(i == index - 1) + if(i == index) psys->flag |= PSYS_CURRENT; else psys->flag &= ~PSYS_CURRENT; -- cgit v1.2.3 From 1588de008a7c9c80d193034c0f8b4dc766620a38 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Thu, 2 Jul 2009 02:12:37 +0000 Subject: NLA SoC: Separated 'Built-In Function Generator' FModifier into a separate FModifier Started cleaning up FModifiers in preparation for allowing them to be used on NLA Strips. This commit separates the 'Built-in Function' mode for the Generator modifier out into its own modifier, since it was being quite frequently used (and the RNA wrapping for this used to be quite hackish). BACKWARDS COMPATABILITY WARNING: Old files with FModifiers saved (i.e. old 2.5 files, but not any others) will not load correctly as a result of these changes (the wrong modifiers will be shown). I've decided that there are not likely to be many files affected by this yet, but doing this will result in a much nicer modifiers-define list in the long run. --- source/blender/blenkernel/intern/fcurve.c | 256 +++++++++++++++--------------- 1 file changed, 130 insertions(+), 126 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index 27ca6332cdc..e52c63d1b21 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -1,5 +1,5 @@ /** - * $Id: fcurve.c 21023 2009-06-20 04:02:49Z aligorith $ + * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** * @@ -1314,11 +1314,6 @@ static FModifierTypeInfo FMI_MODNAME = { * 1) simple polynomial generator: * - Exanded form - (y = C[0]*(x^(n)) + C[1]*(x^(n-1)) + ... + C[n]) * - Factorised form - (y = (C[0][0]*x + C[0][1]) * (C[1][0]*x + C[1][1]) * ... * (C[n][0]*x + C[n][1])) - * 2) simple builin 'functions': - * of the form (y = C[0] * fn( C[1]*x + C[2] ) + C[3]) - * where fn() can be any one of: - * sin, cos, tan, ln, sqrt - * 3) expression... */ static void fcm_generator_free (FModifier *fcm) @@ -1408,45 +1403,11 @@ static void fcm_generator_verify (FModifier *fcm) data->coefficients= nc; data->arraysize= data->poly_order * 2; } - } - break; - - case FCM_GENERATOR_FUNCTION: /* builtin function */ - { - /* arraysize needs to be 4*/ - if (data->arraysize != 4) { - float *nc; - - /* free the old data */ - if (data->coefficients) - MEM_freeN(data->coefficients); - - /* make new coefficients array, and init using default values */ - nc= data->coefficients= MEM_callocN(sizeof(float)*4, "FMod_Generator_Coefs"); - data->arraysize= 4; - - nc[0]= 1.0f; - nc[1]= 1.0f; - nc[2]= 0.0f; - nc[3]= 0.0f; - } } break; } } -/* Unary 'normalised sine' function - * y = sin(PI + x) / (PI * x), - * except for x = 0 when y = 1. - */ -static double sinc (double x) -{ - if (fabs(x) < 0.0001) - return 1.0; - else - return sin(M_PI * x) / (M_PI * x); -} - static void fcm_generator_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime) { FMod_Generator *data= (FMod_Generator *)fcm->data; @@ -1509,86 +1470,6 @@ static void fcm_generator_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, } } break; - - case FCM_GENERATOR_FUNCTION: /* builtin function */ - { - double arg= data->coefficients[1]*evaltime + data->coefficients[2]; - double (*fn)(double v) = NULL; - - /* get function pointer to the func to use: - * WARNING: must perform special argument validation hereto guard against crashes - */ - switch (data->func_type) - { - /* simple ones */ - case FCM_GENERATOR_FN_SIN: /* sine wave */ - fn= sin; - break; - case FCM_GENERATOR_FN_COS: /* cosine wave */ - fn= cos; - break; - case FCM_GENERATOR_FN_SINC: /* normalised sine wave */ - fn= sinc; - break; - - /* validation required */ - case FCM_GENERATOR_FN_TAN: /* tangent wave */ - { - /* check that argument is not on one of the discontinuities (i.e. 90deg, 270 deg, etc) */ - if IS_EQ(fmod((arg - M_PI_2), M_PI), 0.0) { - if ((data->flag & FCM_GENERATOR_ADDITIVE) == 0) - *cvalue = 0.0f; /* no value possible here */ - } - else - fn= tan; - } - break; - case FCM_GENERATOR_FN_LN: /* natural log */ - { - /* check that value is greater than 1? */ - if (arg > 1.0f) { - fn= log; - } - else { - if ((data->flag & FCM_GENERATOR_ADDITIVE) == 0) - *cvalue = 0.0f; /* no value possible here */ - } - } - break; - case FCM_GENERATOR_FN_SQRT: /* square root */ - { - /* no negative numbers */ - if (arg > 0.0f) { - fn= sqrt; - } - else { - if ((data->flag & FCM_GENERATOR_ADDITIVE) == 0) - *cvalue = 0.0f; /* no value possible here */ - } - } - break; - - default: - printf("Invalid Function-Generator for F-Modifier - %d \n", data->func_type); - } - - /* execute function callback to set value if appropriate */ - if (fn) { - float value= (float)(data->coefficients[0]*fn(arg) + data->coefficients[3]); - - if (data->flag & FCM_GENERATOR_ADDITIVE) - *cvalue += value; - else - *cvalue= value; - } - } - break; - -#ifndef DISABLE_PYTHON - case FCM_GENERATOR_EXPRESSION: /* py-expression */ - // TODO... - break; -#endif /* DISABLE_PYTHON */ } } @@ -1607,6 +1488,128 @@ static FModifierTypeInfo FMI_GENERATOR = { fcm_generator_evaluate /* evaluate */ }; +/* Built-In Function Generator F-Curve Modifier --------------------------- */ + +/* This uses the general equation for equations: + * y = amplitude * fn(phase_multiplier*x + phase_offset) + y_offset + * + * where amplitude, phase_multiplier/offset, y_offset are user-defined coefficients, + * x is the evaluation 'time', and 'y' is the resultant value + * + * Functions available are + * sin, cos, tan, sinc (normalised sin), natural log, square root + */ + +static void fcm_fn_generator_new_data (void *mdata) +{ + FMod_FunctionGenerator *data= (FMod_FunctionGenerator *)mdata; + + /* set amplitude and phase multiplier to 1.0f so that something is generated */ + data->amplitude= 1.0f; + data->phase_multiplier= 1.0f; +} + +/* Unary 'normalised sine' function + * y = sin(PI + x) / (PI * x), + * except for x = 0 when y = 1. + */ +static double sinc (double x) +{ + if (fabs(x) < 0.0001) + return 1.0; + else + return sin(M_PI * x) / (M_PI * x); +} + +static void fcm_fn_generator_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime) +{ + FMod_FunctionGenerator *data= (FMod_FunctionGenerator *)fcm->data; + double arg= data->phase_multiplier*evaltime + data->phase_offset; + double (*fn)(double v) = NULL; + + /* get function pointer to the func to use: + * WARNING: must perform special argument validation hereto guard against crashes + */ + switch (data->type) + { + /* simple ones */ + case FCM_GENERATOR_FN_SIN: /* sine wave */ + fn= sin; + break; + case FCM_GENERATOR_FN_COS: /* cosine wave */ + fn= cos; + break; + case FCM_GENERATOR_FN_SINC: /* normalised sine wave */ + fn= sinc; + break; + + /* validation required */ + case FCM_GENERATOR_FN_TAN: /* tangent wave */ + { + /* check that argument is not on one of the discontinuities (i.e. 90deg, 270 deg, etc) */ + if IS_EQ(fmod((arg - M_PI_2), M_PI), 0.0) { + if ((data->flag & FCM_GENERATOR_ADDITIVE) == 0) + *cvalue = 0.0f; /* no value possible here */ + } + else + fn= tan; + } + break; + case FCM_GENERATOR_FN_LN: /* natural log */ + { + /* check that value is greater than 1? */ + if (arg > 1.0f) { + fn= log; + } + else { + if ((data->flag & FCM_GENERATOR_ADDITIVE) == 0) + *cvalue = 0.0f; /* no value possible here */ + } + } + break; + case FCM_GENERATOR_FN_SQRT: /* square root */ + { + /* no negative numbers */ + if (arg > 0.0f) { + fn= sqrt; + } + else { + if ((data->flag & FCM_GENERATOR_ADDITIVE) == 0) + *cvalue = 0.0f; /* no value possible here */ + } + } + break; + + default: + printf("Invalid Function-Generator for F-Modifier - %d \n", data->type); + } + + /* execute function callback to set value if appropriate */ + if (fn) { + float value= (float)(data->amplitude*fn(arg) + data->value_offset); + + if (data->flag & FCM_GENERATOR_ADDITIVE) + *cvalue += value; + else + *cvalue= value; + } +} + +static FModifierTypeInfo FMI_FN_GENERATOR = { + FMODIFIER_TYPE_FN_GENERATOR, /* type */ + sizeof(FMod_FunctionGenerator), /* size */ + FMI_TYPE_GENERATE_CURVE, /* action type */ + FMI_REQUIRES_NOTHING, /* requirements */ + "Built-In Function", /* name */ + "FMod_FunctionGenerator", /* struct name */ + NULL, /* free data */ + NULL, /* copy data */ + fcm_fn_generator_new_data, /* new data */ + NULL, /* verify */ + NULL, /* evaluate time */ + fcm_fn_generator_evaluate /* evaluate */ +}; + /* Envelope F-Curve Modifier --------------------------- */ static void fcm_envelope_free (FModifier *fcm) @@ -2081,12 +2084,13 @@ static void fmods_init_typeinfo () { fmodifiersTypeInfo[0]= NULL; /* 'Null' F-Curve Modifier */ fmodifiersTypeInfo[1]= &FMI_GENERATOR; /* Generator F-Curve Modifier */ - fmodifiersTypeInfo[2]= &FMI_ENVELOPE; /* Envelope F-Curve Modifier */ - fmodifiersTypeInfo[3]= &FMI_CYCLES; /* Cycles F-Curve Modifier */ - fmodifiersTypeInfo[4]= &FMI_NOISE; /* Apply-Noise F-Curve Modifier */ - fmodifiersTypeInfo[5]= NULL/*&FMI_FILTER*/; /* Filter F-Curve Modifier */ // XXX unimplemented - fmodifiersTypeInfo[6]= &FMI_PYTHON; /* Custom Python F-Curve Modifier */ - fmodifiersTypeInfo[7]= &FMI_LIMITS; /* Limits F-Curve Modifier */ + fmodifiersTypeInfo[2]= &FMI_FN_GENERATOR; /* Built-In Function Generator F-Curve Modifier */ + fmodifiersTypeInfo[3]= &FMI_ENVELOPE; /* Envelope F-Curve Modifier */ + fmodifiersTypeInfo[4]= &FMI_CYCLES; /* Cycles F-Curve Modifier */ + fmodifiersTypeInfo[5]= &FMI_NOISE; /* Apply-Noise F-Curve Modifier */ + fmodifiersTypeInfo[6]= NULL/*&FMI_FILTER*/; /* Filter F-Curve Modifier */ // XXX unimplemented + fmodifiersTypeInfo[7]= &FMI_PYTHON; /* Custom Python F-Curve Modifier */ + fmodifiersTypeInfo[8]= &FMI_LIMITS; /* Limits F-Curve Modifier */ } /* This function should be used for getting the appropriate type-info when only -- cgit v1.2.3 From b1a106dd49a8653977cdfd722b1d30abf827fa28 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Thu, 2 Jul 2009 03:32:57 +0000 Subject: NLA SoC: Merge from 2.5 21210 to 21300 Note to self: the next merge will be messy again, since 2 commits occurred this one was complete --- source/blender/blenkernel/BKE_packedFile.h | 54 +++--- source/blender/blenkernel/BKE_particle.h | 4 +- source/blender/blenkernel/BKE_report.h | 5 +- source/blender/blenkernel/intern/cdderivedmesh.c | 2 +- source/blender/blenkernel/intern/context.c | 3 + source/blender/blenkernel/intern/displist.c | 36 ++-- source/blender/blenkernel/intern/font.c | 8 +- source/blender/blenkernel/intern/image.c | 6 +- source/blender/blenkernel/intern/packedFile.c | 227 ++++++++--------------- source/blender/blenkernel/intern/particle.c | 6 +- source/blender/blenkernel/intern/report.c | 4 +- 11 files changed, 153 insertions(+), 202 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_packedFile.h b/source/blender/blenkernel/BKE_packedFile.h index 2d5acc51b7b..efd930d375a 100644 --- a/source/blender/blenkernel/BKE_packedFile.h +++ b/source/blender/blenkernel/BKE_packedFile.h @@ -31,31 +31,43 @@ #ifndef BKE_PACKEDFILE_H #define BKE_PACKEDFILE_H -#define RET_OK 0 -#define RET_ERROR 1 +#define RET_OK 0 +#define RET_ERROR 1 -struct PackedFile; -struct VFont; struct bSample; struct bSound; struct Image; +struct Main; +struct PackedFile; +struct ReportList; +struct VFont; + +/* pack */ +struct PackedFile *newPackedFile(struct ReportList *reports, char *filename); +struct PackedFile *newPackedFileMemory(void *mem, int memlen); + +void packAll(struct Main *bmain, struct ReportList *reports); + +/* unpack */ +char *unpackFile(struct ReportList *reports, char *abs_name, char *local_name, struct PackedFile *pf, int how); +int unpackVFont(struct ReportList *reports, struct VFont *vfont, int how); +int unpackSample(struct ReportList *reports, struct bSample *sample, int how); +int unpackImage(struct ReportList *reports, struct Image *ima, int how); +void unpackAll(struct Main *bmain, struct ReportList *reports, int how); + +int writePackedFile(struct ReportList *reports, char *filename, struct PackedFile *pf, int guimode); + +/* free */ +void freePackedFile(struct PackedFile *pf); + +/* info */ +int countPackedFiles(struct Main *bmain); +int checkPackedFile(char *filename, struct PackedFile *pf); + +/* read */ +int seekPackedFile(struct PackedFile *pf, int offset, int whence); +void rewindPackedFile(struct PackedFile *pf); +int readPackedFile(struct PackedFile *pf, void *data, int size); -struct PackedFile * newPackedFile(char * filename); -struct PackedFile * newPackedFileMemory(void *mem, int memlen); - -int seekPackedFile(struct PackedFile * pf, int offset, int whence); -void rewindPackedFile(struct PackedFile * pf); -int readPackedFile(struct PackedFile * pf, void * data, int size); -int countPackedFiles(void); -void freePackedFile(struct PackedFile * pf); -void packAll(void); -int writePackedFile(char * filename, struct PackedFile *pf, int guimode); -int checkPackedFile(char * filename, struct PackedFile * pf); -char * unpackFile(char * abs_name, char * local_name, struct PackedFile * pf, int how); -int unpackVFont(struct VFont * vfont, int how); -int unpackSample(struct bSample *sample, int how); -int unpackImage(struct Image * ima, int how); -void unpackAll(int how); - #endif diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index 4d9916b9557..73f0195d1d8 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -251,8 +251,8 @@ void copy_particle_key(struct ParticleKey *to, struct ParticleKey *from, int tim void psys_particle_on_emitter(struct ParticleSystemModifierData *psmd, int distr, int index, int index_dmcache, float *fuv, float foffset, float *vec, float *nor, float *utan, float *vtan, float *orco, float *ornor); struct ParticleSystemModifierData *psys_get_modifier(struct Object *ob, struct ParticleSystem *psys); -void object_add_particle_system_slot(struct Scene *scene, struct Object *ob); -void object_remove_particle_system_slot(struct Scene *scene, struct Object *ob); +void object_add_particle_system(struct Scene *scene, struct Object *ob); +void object_remove_particle_system(struct Scene *scene, struct Object *ob); struct ParticleSettings *psys_new_settings(char *name, struct Main *main); struct ParticleSettings *psys_copy_settings(struct ParticleSettings *part); void psys_flush_particle_settings(struct Scene *scene, struct ParticleSettings *part, int recalc); diff --git a/source/blender/blenkernel/BKE_report.h b/source/blender/blenkernel/BKE_report.h index 21221026b8b..1bb7152fbf3 100644 --- a/source/blender/blenkernel/BKE_report.h +++ b/source/blender/blenkernel/BKE_report.h @@ -34,7 +34,10 @@ extern "C" { #include "DNA_listBase.h" -/* Reporting Information and Errors */ +/* Reporting Information and Errors + * + * These functions also accept NULL in case no error reporting + * is needed. */ typedef enum ReportType { RPT_DEBUG = 0, diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index 57ef920f75b..706eece108c 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -1220,7 +1220,7 @@ void CDDM_calc_edges(DerivedMesh *dm) BLI_edgehashIterator_free(ehi); /* free old CustomData and assign new one */ - CustomData_free(&dm->edgeData, dm->numVertData); + CustomData_free(&dm->edgeData, dm->numEdgeData); dm->edgeData = edgeData; dm->numEdgeData = numEdges; diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c index 90880e354ec..fbad585d9b7 100644 --- a/source/blender/blenkernel/intern/context.c +++ b/source/blender/blenkernel/intern/context.c @@ -358,6 +358,9 @@ static int ctx_data_collection_get(const bContext *C, const char *member, ListBa return 1; } + list->first= NULL; + list->last= NULL; + return 0; } diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index 736165a8a98..cdf4b90cee1 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -315,13 +315,19 @@ static void init_fastshade_shadeinput(Render *re) static Render *fastshade_get_render(Scene *scene) { - Render *re= RE_GetRender("_Shade View_"); - if(re==NULL) { - re= RE_NewRender("_Shade View_"); - - RE_Database_Baking(re, scene, 0, 0); /* 0= no faces */ + /* XXX ugly global still, but we can't do preview while rendering */ + if(G.rendering==0) { + + Render *re= RE_GetRender("_Shade View_"); + if(re==NULL) { + re= RE_NewRender("_Shade View_"); + + RE_Database_Baking(re, scene, 0, 0); /* 0= no faces */ + } + return re; } - return re; + + return NULL; } /* called on file reading */ @@ -611,18 +617,20 @@ static void mesh_create_shadedColors(Render *re, Object *ob, int onlyForMesh, un void shadeMeshMCol(Scene *scene, Object *ob, Mesh *me) { + Render *re= fastshade_get_render(scene); int a; char *cp; unsigned int *mcol= (unsigned int*)me->mcol; - Render *re= fastshade_get_render(scene); - mesh_create_shadedColors(re, ob, 1, &mcol, NULL); - me->mcol= (MCol*)mcol; + if(re) { + mesh_create_shadedColors(re, ob, 1, &mcol, NULL); + me->mcol= (MCol*)mcol; - /* swap bytes */ - for(cp= (char *)me->mcol, a= 4*me->totface; a>0; a--, cp+=4) { - SWAP(char, cp[0], cp[3]); - SWAP(char, cp[1], cp[2]); + /* swap bytes */ + for(cp= (char *)me->mcol, a= 4*me->totface; a>0; a--, cp+=4) { + SWAP(char, cp[0], cp[3]); + SWAP(char, cp[1], cp[2]); + } } } @@ -641,6 +649,8 @@ void shadeDispList(Scene *scene, Base *base) int a, need_orco; re= fastshade_get_render(scene); + if(re==NULL) + return; dl = find_displist(&ob->disp, DL_VERTCOL); if (dl) { diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c index 60a7ffc28d9..70901778585 100644 --- a/source/blender/blenkernel/intern/font.c +++ b/source/blender/blenkernel/intern/font.c @@ -333,11 +333,11 @@ static VFontData *vfont_get_data(VFont *vfont) BLI_addtail(&ttfdata, tmpfnt); } } else { - pf= newPackedFile(vfont->name); + pf= newPackedFile(NULL, vfont->name); if(!tmpfnt) { - tpf= newPackedFile(vfont->name); + tpf= newPackedFile(NULL, vfont->name); // Add temporary packed file to globals tmpfnt= (struct TmpFont *) MEM_callocN(sizeof(struct TmpFont), "temp_font"); @@ -385,8 +385,8 @@ VFont *load_vfont(char *name) strcpy(dir, name); BLI_splitdirstring(dir, filename); - pf= newPackedFile(name); - tpf= newPackedFile(name); + pf= newPackedFile(NULL, name); + tpf= newPackedFile(NULL, name); is_builtin= 0; } diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 8eef9984c92..ef0984bf93d 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -1431,7 +1431,7 @@ void BKE_image_signal(Image *ima, ImageUser *iuser, int signal) /* try to repack file */ if(ima->packedfile) { PackedFile *pf; - pf = newPackedFile(ima->name); + pf = newPackedFile(NULL, ima->name); if (pf) { freePackedFile(ima->packedfile); ima->packedfile = pf; @@ -1750,7 +1750,7 @@ static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra) /* make packed file for autopack */ if ((ima->packedfile == NULL) && (G.fileflags & G_AUTOPACK)) - ima->packedfile = newPackedFile(str); + ima->packedfile = newPackedFile(NULL, str); } if(ima->flag & IMA_DO_PREMUL) @@ -1812,7 +1812,7 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser) Render *re= NULL; RenderResult *rr= NULL; - if(iuser->scene) { + if(iuser && iuser->scene) { re= RE_GetRender(iuser->scene->id.name); rr= RE_GetResult(re); } diff --git a/source/blender/blenkernel/intern/packedFile.c b/source/blender/blenkernel/intern/packedFile.c index 22e4e8a8309..4d88556d8bf 100644 --- a/source/blender/blenkernel/intern/packedFile.c +++ b/source/blender/blenkernel/intern/packedFile.c @@ -61,8 +61,9 @@ #include "BKE_image.h" #include "BKE_font.h" #include "BKE_packedFile.h" +#include "BKE_report.h" -int seekPackedFile(PackedFile * pf, int offset, int whence) +int seekPackedFile(PackedFile *pf, int offset, int whence) { int oldseek = -1, seek = 0; @@ -92,12 +93,12 @@ int seekPackedFile(PackedFile * pf, int offset, int whence) return(oldseek); } -void rewindPackedFile(PackedFile * pf) +void rewindPackedFile(PackedFile *pf) { seekPackedFile(pf, 0, SEEK_SET); } -int readPackedFile(PackedFile * pf, void * data, int size) +int readPackedFile(PackedFile *pf, void *data, int size) { if ((pf != NULL) && (size >= 0) && (data != NULL)) { if (size + pf->seek > pf->size) { @@ -118,66 +119,55 @@ int readPackedFile(PackedFile * pf, void * data, int size) return(size); } -int countPackedFiles() +int countPackedFiles(Main *bmain) { - int count = 0; Image *ima; VFont *vf; bSample *sample; + int count = 0; // let's check if there are packed files... - ima = G.main->image.first; - while (ima) { - if (ima->packedfile) { + for(ima=bmain->image.first; ima; ima=ima->id.next) + if(ima->packedfile) count++; - } - ima= ima->id.next; - } - vf = G.main->vfont.first; - while (vf) { - if (vf->packedfile) { + for(vf=bmain->vfont.first; vf; vf=vf->id.next) + if(vf->packedfile) count++; - } - vf = vf->id.next; - } - sample = samples->first; - while (sample) { - if (sample->packedfile) { - count++; - } - sample = sample->id.next; - } + if(samples) + for(sample=samples->first; sample; sample=sample->id.next) + if(sample->packedfile) + count++; - return(count); + return count; } -void freePackedFile(PackedFile * pf) +void freePackedFile(PackedFile *pf) { - if (pf) { + if(pf) { MEM_freeN(pf->data); MEM_freeN(pf); - } else { - printf("freePackedFile: Trying to free a NULL pointer\n"); } + else + printf("freePackedFile: Trying to free a NULL pointer\n"); } -PackedFile * newPackedFileMemory(void *mem, int memlen) +PackedFile *newPackedFileMemory(void *mem, int memlen) { - PackedFile * pf = MEM_callocN(sizeof(*pf), "PackedFile"); + PackedFile *pf = MEM_callocN(sizeof(*pf), "PackedFile"); pf->data = mem; pf->size = memlen; return pf; } -PackedFile * newPackedFile(char * filename) +PackedFile *newPackedFile(ReportList *reports, char *filename) { - PackedFile * pf = NULL; + PackedFile *pf = NULL; int file, filelen; char name[FILE_MAXDIR+FILE_MAXFILE]; - void * data; + void *data; //XXX waitcursor(1); @@ -191,7 +181,7 @@ PackedFile * newPackedFile(char * filename) file= open(name, O_BINARY|O_RDONLY); if (file <= 0) { - // error("Can't open file: %s", name); + BKE_reportf(reports, RPT_ERROR, "Can't open file: %s", name); } else { filelen = BLI_filesize(file); @@ -214,36 +204,24 @@ PackedFile * newPackedFile(char * filename) return (pf); } -void packAll() +void packAll(Main *bmain, ReportList *reports) { Image *ima; VFont *vf; bSample *sample; - ima = G.main->image.first; - while (ima) { - if (ima->packedfile == NULL) { - ima->packedfile = newPackedFile(ima->name); - } - ima= ima->id.next; - } - - vf = G.main->vfont.first; - while (vf) { - if (vf->packedfile == NULL) { - vf->packedfile = newPackedFile(vf->name); - } - vf = vf->id.next; - } + for(ima=bmain->image.first; ima; ima=ima->id.next) + if(ima->packedfile == NULL) + ima->packedfile = newPackedFile(reports, ima->name); + for(vf=bmain->vfont.first; vf; vf=vf->id.next) + if(vf->packedfile == NULL) + vf->packedfile = newPackedFile(reports, vf->name); - sample = samples->first; - while (sample) { - if (sample->packedfile == NULL) { - sound_set_packedfile(sample, newPackedFile(sample->name)); - } - sample = sample->id.next; - } + if(samples) + for(sample=samples->first; sample; sample=sample->id.next) + if(sample->packedfile == NULL) + sound_set_packedfile(sample, newPackedFile(reports, sample->name)); } @@ -252,10 +230,10 @@ void packAll() // attempt to create a function that generates an unique filename // this will work when all funtions in fileops.c understand relative filenames... -char * find_new_name(char * name) +char *find_new_name(char *name) { char tempname[FILE_MAXDIR + FILE_MAXFILE]; - char * newname; + char *newname; if (fop_exists(name)) { for (number = 1; number <= 999; number++) { @@ -274,13 +252,13 @@ char * find_new_name(char * name) */ -int writePackedFile(char * filename, PackedFile *pf, int guimode) +int writePackedFile(ReportList *reports, char *filename, PackedFile *pf, int guimode) { int file, number, remove_tmp = FALSE; int ret_value = RET_OK; char name[FILE_MAXDIR + FILE_MAXFILE]; char tempname[FILE_MAXDIR + FILE_MAXFILE]; -/* void * data; */ +/* void *data; */ if (guimode); //XXX waitcursor(1); @@ -305,23 +283,23 @@ int writePackedFile(char * filename, PackedFile *pf, int guimode) file = open(name, O_BINARY + O_WRONLY + O_CREAT + O_TRUNC, 0666); if (file >= 0) { if (write(file, pf->data, pf->size) != pf->size) { - if(guimode) ; //XXX error("Error writing file: %s", name); + BKE_reportf(reports, RPT_ERROR, "Error writing file: %s", name); ret_value = RET_ERROR; } close(file); } else { - if(guimode); //XXX error("Error creating file: %s", name); + BKE_reportf(reports, RPT_ERROR, "Error creating file: %s", name); ret_value = RET_ERROR; } if (remove_tmp) { if (ret_value == RET_ERROR) { if (BLI_rename(tempname, name) != 0) { - if(guimode); //XXX error("Error restoring tempfile. Check files: '%s' '%s'", tempname, name); + BKE_reportf(reports, RPT_ERROR, "Error restoring tempfile. Check files: '%s' '%s'", tempname, name); } } else { if (BLI_delete(tempname, 0, 0) != 0) { - if(guimode); //XXX error("Error deleting '%s' (ignored)"); + BKE_reportf(reports, RPT_ERROR, "Error deleting '%s' (ignored)", tempname); } } } @@ -342,7 +320,7 @@ PF_NOFILE - the original file doens't exist */ -int checkPackedFile(char * filename, PackedFile * pf) +int checkPackedFile(char *filename, PackedFile *pf) { struct stat st; int ret_val, i, len, file; @@ -390,68 +368,23 @@ int checkPackedFile(char * filename, PackedFile * pf) /* -unpackFile() looks at the existing files (abs_name, local_name) and a packed file. -If how == PF_ASK it offers the user a couple of options what to do with the packed file. + unpackFile() looks at the existing files (abs_name, local_name) and a packed file. -It returns a char * to the existing file name / new file name or NULL when +It returns a char *to the existing file name / new file name or NULL when there was an error or when the user desides to cancel the operation. */ -char *unpackFile(char * abs_name, char * local_name, PackedFile * pf, int how) +char *unpackFile(ReportList *reports, char *abs_name, char *local_name, PackedFile *pf, int how) { - char menu[6 * (FILE_MAXDIR + FILE_MAXFILE + 100)]; + char menu[6 *(FILE_MAXDIR + FILE_MAXFILE + 100)]; char line[FILE_MAXDIR + FILE_MAXFILE + 100]; - char * newname = NULL, * temp = NULL; + char *newname = NULL, *temp = NULL; // char newabs[FILE_MAXDIR + FILE_MAXFILE]; // char newlocal[FILE_MAXDIR + FILE_MAXFILE]; if (pf != NULL) { - if (how == PF_ASK) { - sprintf(menu, "UnPack file%%t|Remove Pack %%x%d", PF_REMOVE); - - if (strcmp(abs_name, local_name)) { - switch (checkPackedFile(local_name, pf)) { - case PF_NOFILE: - sprintf(line, "|Create %s%%x%d", local_name, PF_WRITE_LOCAL); - strcat(menu, line); - break; - case PF_EQUAL: - sprintf(line, "|Use %s (identical)%%x%d", local_name, PF_USE_LOCAL); - strcat(menu, line); - break; - case PF_DIFFERS: - sprintf(line, "|Use %s (differs)%%x%d", local_name, PF_USE_LOCAL); - strcat(menu, line); - sprintf(line, "|Overwrite %s%%x%d", local_name, PF_WRITE_LOCAL); - strcat(menu, line); - break; - } - // sprintf(line, "|%%x%d", PF_INVALID); - // strcat(menu, line); - } - - switch (checkPackedFile(abs_name, pf)) { - case PF_NOFILE: - sprintf(line, "|Create %s%%x%d", abs_name, PF_WRITE_ORIGINAL); - strcat(menu, line); - break; - case PF_EQUAL: - sprintf(line, "|Use %s (identical)%%x%d", abs_name, PF_USE_ORIGINAL); - strcat(menu, line); - break; - case PF_DIFFERS: - sprintf(line, "|Use %s (differs)%%x%d", abs_name, PF_USE_ORIGINAL); - strcat(menu, line); - sprintf(line, "|Overwrite %s%%x%d", abs_name, PF_WRITE_ORIGINAL); - strcat(menu, line); - break; - } - - //XXX how = pupmenu(menu); - } - switch (how) { case -1: case PF_KEEP: @@ -467,7 +400,7 @@ char *unpackFile(char * abs_name, char * local_name, PackedFile * pf, int how) } // else fall through and create it case PF_WRITE_LOCAL: - if (writePackedFile(local_name, pf, 1) == RET_OK) { + if (writePackedFile(reports, local_name, pf, 1) == RET_OK) { temp = local_name; } break; @@ -479,7 +412,7 @@ char *unpackFile(char * abs_name, char * local_name, PackedFile * pf, int how) } // else fall through and create it case PF_WRITE_ORIGINAL: - if (writePackedFile(abs_name, pf, 1) == RET_OK) { + if (writePackedFile(reports, abs_name, pf, 1) == RET_OK) { temp = abs_name; } break; @@ -498,10 +431,10 @@ char *unpackFile(char * abs_name, char * local_name, PackedFile * pf, int how) } -int unpackVFont(VFont * vfont, int how) +int unpackVFont(ReportList *reports, VFont *vfont, int how) { char localname[FILE_MAXDIR + FILE_MAXFILE], fi[FILE_MAXFILE]; - char * newname; + char *newname; int ret_value = RET_ERROR; if (vfont != NULL) { @@ -510,7 +443,7 @@ int unpackVFont(VFont * vfont, int how) sprintf(localname, "//fonts/%s", fi); - newname = unpackFile(vfont->name, localname, vfont->packedfile, how); + newname = unpackFile(reports, vfont->name, localname, vfont->packedfile, how); if (newname != NULL) { ret_value = RET_OK; freePackedFile(vfont->packedfile); @@ -523,10 +456,10 @@ int unpackVFont(VFont * vfont, int how) return (ret_value); } -int unpackSample(bSample *sample, int how) +int unpackSample(ReportList *reports, bSample *sample, int how) { char localname[FILE_MAXDIR + FILE_MAX], fi[FILE_MAX]; - char * newname; + char *newname; int ret_value = RET_ERROR; PackedFile *pf; @@ -535,7 +468,7 @@ int unpackSample(bSample *sample, int how) BLI_splitdirstring(localname, fi); sprintf(localname, "//samples/%s", fi); - newname = unpackFile(sample->name, localname, sample->packedfile, how); + newname = unpackFile(reports, sample->name, localname, sample->packedfile, how); if (newname != NULL) { strcpy(sample->name, newname); MEM_freeN(newname); @@ -553,10 +486,10 @@ int unpackSample(bSample *sample, int how) return(ret_value); } -int unpackImage(Image * ima, int how) +int unpackImage(ReportList *reports, Image *ima, int how) { char localname[FILE_MAXDIR + FILE_MAX], fi[FILE_MAX]; - char * newname; + char *newname; int ret_value = RET_ERROR; if (ima != NULL) { @@ -564,7 +497,7 @@ int unpackImage(Image * ima, int how) BLI_splitdirstring(localname, fi); sprintf(localname, "//textures/%s", fi); - newname = unpackFile(ima->name, localname, ima->packedfile, how); + newname = unpackFile(reports, ima->name, localname, ima->packedfile, how); if (newname != NULL) { ret_value = RET_OK; freePackedFile(ima->packedfile); @@ -578,33 +511,23 @@ int unpackImage(Image * ima, int how) return(ret_value); } -void unpackAll(int how) +void unpackAll(Main *bmain, ReportList *reports, int how) { Image *ima; VFont *vf; bSample *sample; - - ima = G.main->image.first; - while (ima) { - if (ima->packedfile) { - unpackImage(ima, how); - } - ima= ima->id.next; - } - - vf = G.main->vfont.first; - while (vf) { - if (vf->packedfile) { - unpackVFont(vf, how); - } - vf = vf->id.next; - } - sample = samples->first; - while (sample) { - if (sample->packedfile) { - unpackSample(sample, how); - } - sample = sample->id.next; - } + for(ima=bmain->image.first; ima; ima=ima->id.next) + if(ima->packedfile) + unpackImage(reports, ima, how); + + for(vf=bmain->vfont.first; vf; vf=vf->id.next) + if(vf->packedfile) + unpackVFont(reports, vf, how); + + if(samples) + for(sample=samples->first; sample; sample=sample->id.next) + if(sample->packedfile) + unpackSample(reports, sample, how); } + diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 2474053298d..5bf9335d211 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -230,7 +230,7 @@ void psys_set_current_num(Object *ob, int index) if(ob==0) return; for(psys=ob->particlesystem.first, i=0; psys; psys=psys->next, i++) { - if(i == index - 1) + if(i == index) psys->flag |= PSYS_CURRENT; else psys->flag &= ~PSYS_CURRENT; @@ -2929,7 +2929,7 @@ void psys_mat_hair_to_global(Object *ob, DerivedMesh *dm, short from, ParticleDa /************************************************/ /* ParticleSettings handling */ /************************************************/ -void object_add_particle_system_slot(Scene *scene, Object *ob) +void object_add_particle_system(Scene *scene, Object *ob) { ParticleSystem *psys; ModifierData *md; @@ -2961,7 +2961,7 @@ void object_add_particle_system_slot(Scene *scene, Object *ob) DAG_scene_sort(scene); DAG_object_flush_update(scene, ob, OB_RECALC_DATA); } -void object_remove_particle_system_slot(Scene *scene, Object *ob) +void object_remove_particle_system(Scene *scene, Object *ob) { ParticleSystem *psys = psys_get_current(ob); ParticleSystemModifierData *psmd; diff --git a/source/blender/blenkernel/intern/report.c b/source/blender/blenkernel/intern/report.c index 116fd069948..8de8cf8d0f4 100644 --- a/source/blender/blenkernel/intern/report.c +++ b/source/blender/blenkernel/intern/report.c @@ -65,8 +65,8 @@ void BKE_reports_init(ReportList *reports, int flag) memset(reports, 0, sizeof(ReportList)); - reports->storelevel= RPT_WARNING; - reports->printlevel= RPT_WARNING; + reports->storelevel= RPT_INFO; + reports->printlevel= RPT_INFO; reports->flag= flag; } -- cgit v1.2.3 From f3c47a66b0cb3bb70505ed46522e6c557769eaa5 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Thu, 2 Jul 2009 05:25:14 +0000 Subject: NLA SoC: Separating out F-Modifier API * F-Modifier API is now in its own file in blenkernel * Renamed and refactored these so that they're no dependent on F-Curves, since all they really used was the fcu->modifiers list * Added missing license blocks to a few files --- source/blender/blenkernel/BKE_fcurve.h | 14 +- source/blender/blenkernel/intern/fcurve.c | 1137 +----------------------- source/blender/blenkernel/intern/fmodifier.c | 1197 ++++++++++++++++++++++++++ source/blender/blenkernel/intern/ipo.c | 2 +- source/blender/blenkernel/intern/nla.c | 13 +- 5 files changed, 1212 insertions(+), 1151 deletions(-) create mode 100644 source/blender/blenkernel/intern/fmodifier.c (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h index 5c77e3c2ae4..cfc4e9077f6 100644 --- a/source/blender/blenkernel/BKE_fcurve.h +++ b/source/blender/blenkernel/BKE_fcurve.h @@ -104,15 +104,15 @@ FModifierTypeInfo *get_fmodifier_typeinfo(int type); /* ---------------------- */ -struct FModifier *fcurve_add_modifier(struct FCurve *fcu, int type); -void fcurve_copy_modifiers(ListBase *dst, ListBase *src); -void fcurve_remove_modifier(struct FCurve *fcu, struct FModifier *fcm); -void fcurve_free_modifiers(struct FCurve *fcu); +struct FModifier *add_fmodifier(ListBase *modifiers, int type); +void copy_fmodifiers(ListBase *dst, ListBase *src); +void remove_fmodifier(ListBase *modifiers, struct FModifier *fcm); +void free_fmodifiers(ListBase *modifiers); -struct FModifier *fcurve_find_active_modifier(struct FCurve *fcu); -void fcurve_set_active_modifier(struct FCurve *fcu, struct FModifier *fcm); +struct FModifier *find_active_fmodifier(ListBase *modifiers); +void set_active_fmodifier(ListBase *modifiers, struct FModifier *fcm); -short fcurve_has_suitable_modifier(struct FCurve *fcu, int mtype, short acttype); +short list_has_suitable_fmodifier(ListBase *modifiers, int mtype, short acttype); float evaluate_time_fmodifiers(ListBase *modifiers, struct FCurve *fcu, float cvalue, float evaltime); void evaluate_value_fmodifiers(ListBase *modifiers, struct FCurve *fcu, float *cvalue, float evaltime); diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index e52c63d1b21..4c2ba61fc71 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -56,7 +56,7 @@ #include "RNA_types.h" #ifndef DISABLE_PYTHON -#include "BPY_extern.h" /* for BPY_pydriver_eval() */ +#include "BPY_extern.h" #endif #define SMALL -1.0e-10 @@ -84,7 +84,7 @@ void free_fcurve (FCurve *fcu) /* free extra data - i.e. modifiers, and driver */ fcurve_free_driver(fcu); - fcurve_free_modifiers(fcu); + free_fmodifiers(&fcu->modifiers); /* free f-curve itself */ MEM_freeN(fcu); @@ -140,7 +140,7 @@ FCurve *copy_fcurve (FCurve *fcu) fcu_d->driver= fcurve_copy_driver(fcu_d->driver); /* copy modifiers */ - fcurve_copy_modifiers(&fcu_d->modifiers, &fcu->modifiers); + copy_fmodifiers(&fcu_d->modifiers, &fcu->modifiers); /* return new data */ return fcu_d; @@ -1270,1135 +1270,6 @@ static float fcurve_eval_samples (FCurve *fcu, FPoint *fpts, float evaltime) return cvalue; } -/* ******************************** F-Curve Modifiers ********************************* */ - -/* Template --------------------------- */ - -/* Each modifier defines a set of functions, which will be called at the appropriate - * times. In addition to this, each modifier should have a type-info struct, where - * its functions are attached for use. - */ - -/* Template for type-info data: - * - make a copy of this when creating new modifiers, and just change the functions - * pointed to as necessary - * - although the naming of functions doesn't matter, it would help for code - * readability, to follow the same naming convention as is presented here - * - any functions that a constraint doesn't need to define, don't define - * for such cases, just use NULL - * - these should be defined after all the functions have been defined, so that - * forward-definitions/prototypes don't need to be used! - * - keep this copy #if-def'd so that future constraints can get based off this - */ -#if 0 -static FModifierTypeInfo FMI_MODNAME = { - FMODIFIER_TYPE_MODNAME, /* type */ - sizeof(FMod_ModName), /* size */ - FMI_TYPE_SOME_ACTION, /* action type */ - FMI_REQUIRES_SOME_REQUIREMENT, /* requirements */ - "Modifier Name", /* name */ - "FMod_ModName", /* struct name */ - fcm_modname_free, /* free data */ - fcm_modname_relink, /* relink data */ - fcm_modname_copy, /* copy data */ - fcm_modname_new_data, /* new data */ - fcm_modname_verify, /* verify */ - fcm_modname_time, /* evaluate time */ - fcm_modname_evaluate /* evaluate */ -}; -#endif - -/* Generator F-Curve Modifier --------------------------- */ - -/* Generators available: - * 1) simple polynomial generator: - * - Exanded form - (y = C[0]*(x^(n)) + C[1]*(x^(n-1)) + ... + C[n]) - * - Factorised form - (y = (C[0][0]*x + C[0][1]) * (C[1][0]*x + C[1][1]) * ... * (C[n][0]*x + C[n][1])) - */ - -static void fcm_generator_free (FModifier *fcm) -{ - FMod_Generator *data= (FMod_Generator *)fcm->data; - - /* free polynomial coefficients array */ - if (data->coefficients) - MEM_freeN(data->coefficients); -} - -static void fcm_generator_copy (FModifier *fcm, FModifier *src) -{ - FMod_Generator *gen= (FMod_Generator *)fcm->data; - FMod_Generator *ogen= (FMod_Generator *)src->data; - - /* copy coefficients array? */ - if (ogen->coefficients) - gen->coefficients= MEM_dupallocN(ogen->coefficients); -} - -static void fcm_generator_new_data (void *mdata) -{ - FMod_Generator *data= (FMod_Generator *)mdata; - float *cp; - - /* set default generator to be linear 0-1 (gradient = 1, y-offset = 0) */ - data->poly_order= 1; - data->arraysize= 2; - cp= data->coefficients= MEM_callocN(sizeof(float)*2, "FMod_Generator_Coefs"); - cp[0] = 0; // y-offset - cp[1] = 1; // gradient -} - -static void fcm_generator_verify (FModifier *fcm) -{ - FMod_Generator *data= (FMod_Generator *)fcm->data; - - /* requirements depend on mode */ - switch (data->mode) { - case FCM_GENERATOR_POLYNOMIAL: /* expanded polynomial expression */ - { - /* arraysize needs to be order+1, so resize if not */ - if (data->arraysize != (data->poly_order+1)) { - float *nc; - - /* make new coefficients array, and copy over as much data as can fit */ - nc= MEM_callocN(sizeof(float)*(data->poly_order+1), "FMod_Generator_Coefs"); - - if (data->coefficients) { - if (data->arraysize > (data->poly_order+1)) - memcpy(nc, data->coefficients, sizeof(float)*(data->poly_order+1)); - else - memcpy(nc, data->coefficients, sizeof(float)*data->arraysize); - - /* free the old data */ - MEM_freeN(data->coefficients); - } - - /* set the new data */ - data->coefficients= nc; - data->arraysize= data->poly_order+1; - } - } - break; - - case FCM_GENERATOR_POLYNOMIAL_FACTORISED: /* expanded polynomial expression */ - { - /* arraysize needs to be 2*order, so resize if not */ - if (data->arraysize != (data->poly_order * 2)) { - float *nc; - - /* make new coefficients array, and copy over as much data as can fit */ - nc= MEM_callocN(sizeof(float)*(data->poly_order*2), "FMod_Generator_Coefs"); - - if (data->coefficients) { - if (data->arraysize > (data->poly_order * 2)) - memcpy(nc, data->coefficients, sizeof(float)*(data->poly_order * 2)); - else - memcpy(nc, data->coefficients, sizeof(float)*data->arraysize); - - /* free the old data */ - MEM_freeN(data->coefficients); - } - - /* set the new data */ - data->coefficients= nc; - data->arraysize= data->poly_order * 2; - } - } - break; - } -} - -static void fcm_generator_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime) -{ - FMod_Generator *data= (FMod_Generator *)fcm->data; - - /* behaviour depends on mode - * NOTE: the data in its default state is fine too - */ - switch (data->mode) { - case FCM_GENERATOR_POLYNOMIAL: /* expanded polynomial expression */ - { - /* we overwrite cvalue with the sum of the polynomial */ - float *powers = MEM_callocN(sizeof(float)*data->arraysize, "Poly Powers"); - float value= 0.0f; - unsigned int i; - - /* for each x^n, precalculate value based on previous one first... this should be - * faster that calling pow() for each entry - */ - for (i=0; i < data->arraysize; i++) { - /* first entry is x^0 = 1, otherwise, calculate based on previous */ - if (i) - powers[i]= powers[i-1] * evaltime; - else - powers[0]= 1; - } - - /* for each coefficient, add to value, which we'll write to *cvalue in one go */ - for (i=0; i < data->arraysize; i++) - value += data->coefficients[i] * powers[i]; - - /* only if something changed, write *cvalue in one go */ - if (data->poly_order) { - if (data->flag & FCM_GENERATOR_ADDITIVE) - *cvalue += value; - else - *cvalue= value; - } - - /* cleanup */ - if (powers) - MEM_freeN(powers); - } - break; - - case FCM_GENERATOR_POLYNOMIAL_FACTORISED: /* factorised polynomial */ - { - float value= 1.0f, *cp=NULL; - unsigned int i; - - /* for each coefficient pair, solve for that bracket before accumulating in value by multiplying */ - for (cp=data->coefficients, i=0; (cp) && (i < data->poly_order); cp+=2, i++) - value *= (cp[0]*evaltime + cp[1]); - - /* only if something changed, write *cvalue in one go */ - if (data->poly_order) { - if (data->flag & FCM_GENERATOR_ADDITIVE) - *cvalue += value; - else - *cvalue= value; - } - } - break; - } -} - -static FModifierTypeInfo FMI_GENERATOR = { - FMODIFIER_TYPE_GENERATOR, /* type */ - sizeof(FMod_Generator), /* size */ - FMI_TYPE_GENERATE_CURVE, /* action type */ - FMI_REQUIRES_NOTHING, /* requirements */ - "Generator", /* name */ - "FMod_Generator", /* struct name */ - fcm_generator_free, /* free data */ - fcm_generator_copy, /* copy data */ - fcm_generator_new_data, /* new data */ - fcm_generator_verify, /* verify */ - NULL, /* evaluate time */ - fcm_generator_evaluate /* evaluate */ -}; - -/* Built-In Function Generator F-Curve Modifier --------------------------- */ - -/* This uses the general equation for equations: - * y = amplitude * fn(phase_multiplier*x + phase_offset) + y_offset - * - * where amplitude, phase_multiplier/offset, y_offset are user-defined coefficients, - * x is the evaluation 'time', and 'y' is the resultant value - * - * Functions available are - * sin, cos, tan, sinc (normalised sin), natural log, square root - */ - -static void fcm_fn_generator_new_data (void *mdata) -{ - FMod_FunctionGenerator *data= (FMod_FunctionGenerator *)mdata; - - /* set amplitude and phase multiplier to 1.0f so that something is generated */ - data->amplitude= 1.0f; - data->phase_multiplier= 1.0f; -} - -/* Unary 'normalised sine' function - * y = sin(PI + x) / (PI * x), - * except for x = 0 when y = 1. - */ -static double sinc (double x) -{ - if (fabs(x) < 0.0001) - return 1.0; - else - return sin(M_PI * x) / (M_PI * x); -} - -static void fcm_fn_generator_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime) -{ - FMod_FunctionGenerator *data= (FMod_FunctionGenerator *)fcm->data; - double arg= data->phase_multiplier*evaltime + data->phase_offset; - double (*fn)(double v) = NULL; - - /* get function pointer to the func to use: - * WARNING: must perform special argument validation hereto guard against crashes - */ - switch (data->type) - { - /* simple ones */ - case FCM_GENERATOR_FN_SIN: /* sine wave */ - fn= sin; - break; - case FCM_GENERATOR_FN_COS: /* cosine wave */ - fn= cos; - break; - case FCM_GENERATOR_FN_SINC: /* normalised sine wave */ - fn= sinc; - break; - - /* validation required */ - case FCM_GENERATOR_FN_TAN: /* tangent wave */ - { - /* check that argument is not on one of the discontinuities (i.e. 90deg, 270 deg, etc) */ - if IS_EQ(fmod((arg - M_PI_2), M_PI), 0.0) { - if ((data->flag & FCM_GENERATOR_ADDITIVE) == 0) - *cvalue = 0.0f; /* no value possible here */ - } - else - fn= tan; - } - break; - case FCM_GENERATOR_FN_LN: /* natural log */ - { - /* check that value is greater than 1? */ - if (arg > 1.0f) { - fn= log; - } - else { - if ((data->flag & FCM_GENERATOR_ADDITIVE) == 0) - *cvalue = 0.0f; /* no value possible here */ - } - } - break; - case FCM_GENERATOR_FN_SQRT: /* square root */ - { - /* no negative numbers */ - if (arg > 0.0f) { - fn= sqrt; - } - else { - if ((data->flag & FCM_GENERATOR_ADDITIVE) == 0) - *cvalue = 0.0f; /* no value possible here */ - } - } - break; - - default: - printf("Invalid Function-Generator for F-Modifier - %d \n", data->type); - } - - /* execute function callback to set value if appropriate */ - if (fn) { - float value= (float)(data->amplitude*fn(arg) + data->value_offset); - - if (data->flag & FCM_GENERATOR_ADDITIVE) - *cvalue += value; - else - *cvalue= value; - } -} - -static FModifierTypeInfo FMI_FN_GENERATOR = { - FMODIFIER_TYPE_FN_GENERATOR, /* type */ - sizeof(FMod_FunctionGenerator), /* size */ - FMI_TYPE_GENERATE_CURVE, /* action type */ - FMI_REQUIRES_NOTHING, /* requirements */ - "Built-In Function", /* name */ - "FMod_FunctionGenerator", /* struct name */ - NULL, /* free data */ - NULL, /* copy data */ - fcm_fn_generator_new_data, /* new data */ - NULL, /* verify */ - NULL, /* evaluate time */ - fcm_fn_generator_evaluate /* evaluate */ -}; - -/* Envelope F-Curve Modifier --------------------------- */ - -static void fcm_envelope_free (FModifier *fcm) -{ - FMod_Envelope *env= (FMod_Envelope *)fcm->data; - - /* free envelope data array */ - if (env->data) - MEM_freeN(env->data); -} - -static void fcm_envelope_copy (FModifier *fcm, FModifier *src) -{ - FMod_Envelope *env= (FMod_Envelope *)fcm->data; - FMod_Envelope *oenv= (FMod_Envelope *)src->data; - - /* copy envelope data array */ - if (oenv->data) - env->data= MEM_dupallocN(oenv->data); -} - -static void fcm_envelope_new_data (void *mdata) -{ - FMod_Envelope *env= (FMod_Envelope *)mdata; - - /* set default min/max ranges */ - env->min= -1.0f; - env->max= 1.0f; -} - -static void fcm_envelope_verify (FModifier *fcm) -{ - FMod_Envelope *env= (FMod_Envelope *)fcm->data; - - /* if the are points, perform bubble-sort on them, as user may have changed the order */ - if (env->data) { - // XXX todo... - } -} - -static void fcm_envelope_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime) -{ - FMod_Envelope *env= (FMod_Envelope *)fcm->data; - FCM_EnvelopeData *fed, *prevfed, *lastfed; - float min=0.0f, max=0.0f, fac=0.0f; - int a; - - /* get pointers */ - if (env->data == NULL) return; - prevfed= env->data; - fed= prevfed + 1; - lastfed= prevfed + (env->totvert-1); - - /* get min/max values for envelope at evaluation time (relative to mid-value) */ - if (prevfed->time >= evaltime) { - /* before or on first sample, so just extend value */ - min= prevfed->min; - max= prevfed->max; - } - else if (lastfed->time <= evaltime) { - /* after or on last sample, so just extend value */ - min= lastfed->min; - max= lastfed->max; - } - else { - /* evaltime occurs somewhere between segments */ - // TODO: implement binary search for this to make it faster? - for (a=0; prevfed && fed && (a < env->totvert-1); a++, prevfed=fed, fed++) { - /* evaltime occurs within the interval defined by these two envelope points */ - if ((prevfed->time <= evaltime) && (fed->time >= evaltime)) { - float afac, bfac, diff; - - diff= fed->time - prevfed->time; - afac= (evaltime - prevfed->time) / diff; - bfac= (fed->time - evaltime) / diff; - - min= bfac*prevfed->min + afac*fed->min; - max= bfac*prevfed->max + afac*fed->max; - - break; - } - } - } - - /* adjust *cvalue - * - fac is the ratio of how the current y-value corresponds to the reference range - * - thus, the new value is found by mapping the old range to the new! - */ - fac= (*cvalue - (env->midval + env->min)) / (env->max - env->min); - *cvalue= min + fac*(max - min); -} - -static FModifierTypeInfo FMI_ENVELOPE = { - FMODIFIER_TYPE_ENVELOPE, /* type */ - sizeof(FMod_Envelope), /* size */ - FMI_TYPE_REPLACE_VALUES, /* action type */ - 0, /* requirements */ - "Envelope", /* name */ - "FMod_Envelope", /* struct name */ - fcm_envelope_free, /* free data */ - fcm_envelope_copy, /* copy data */ - fcm_envelope_new_data, /* new data */ - fcm_envelope_verify, /* verify */ - NULL, /* evaluate time */ - fcm_envelope_evaluate /* evaluate */ -}; - -/* Cycles F-Curve Modifier --------------------------- */ - -/* This modifier changes evaltime to something that exists within the curve's frame-range, - * then re-evaluates modifier stack up to this point using the new time. This re-entrant behaviour - * is very likely to be more time-consuming than the original approach... (which was tighly integrated into - * the calculation code...). - * - * NOTE: this needs to be at the start of the stack to be of use, as it needs to know the extents of the keyframes/sample-data - * Possible TODO - store length of cycle information that can be initialised from the extents of the keyframes/sample-data, and adjusted - * as appropriate - */ - -/* temp data used during evaluation */ -typedef struct tFCMED_Cycles { - float cycyofs; /* y-offset to apply */ -} tFCMED_Cycles; - -static void fcm_cycles_new_data (void *mdata) -{ - FMod_Cycles *data= (FMod_Cycles *)mdata; - - /* turn on cycles by default */ - data->before_mode= data->after_mode= FCM_EXTRAPOLATE_CYCLIC; -} - -static float fcm_cycles_time (FCurve *fcu, FModifier *fcm, float cvalue, float evaltime) -{ - FMod_Cycles *data= (FMod_Cycles *)fcm->data; - float prevkey[2], lastkey[2], cycyofs=0.0f; - short side=0, mode=0; - int cycles=0; - - /* check if modifier is first in stack, otherwise disable ourself... */ - // FIXME... - if (fcm->prev) { - fcm->flag |= FMODIFIER_FLAG_DISABLED; - return evaltime; - } - - /* calculate new evaltime due to cyclic interpolation */ - if (fcu && fcu->bezt) { - BezTriple *prevbezt= fcu->bezt; - BezTriple *lastbezt= prevbezt + fcu->totvert-1; - - prevkey[0]= prevbezt->vec[1][0]; - prevkey[1]= prevbezt->vec[1][1]; - - lastkey[0]= lastbezt->vec[1][0]; - lastkey[1]= lastbezt->vec[1][1]; - } - else if (fcu && fcu->fpt) { - FPoint *prevfpt= fcu->fpt; - FPoint *lastfpt= prevfpt + fcu->totvert-1; - - prevkey[0]= prevfpt->vec[0]; - prevkey[1]= prevfpt->vec[1]; - - lastkey[0]= lastfpt->vec[0]; - lastkey[1]= lastfpt->vec[1]; - } - else - return evaltime; - - /* check if modifier will do anything - * 1) if in data range, definitely don't do anything - * 2) if before first frame or after last frame, make sure some cycling is in use - */ - if (evaltime < prevkey[0]) { - if (data->before_mode) { - side= -1; - mode= data->before_mode; - cycles= data->before_cycles; - } - } - else if (evaltime > lastkey[0]) { - if (data->after_mode) { - side= 1; - mode= data->after_mode; - cycles= data->after_cycles; - } - } - if ELEM(0, side, mode) - return evaltime; - - /* find relative place within a cycle */ - { - float cycdx=0, cycdy=0, ofs=0; - float cycle= 0; - - /* ofs is start frame of cycle */ - ofs= prevkey[0]; - - /* calculate period and amplitude (total height) of a cycle */ - cycdx= lastkey[0] - prevkey[0]; - cycdy= lastkey[1] - prevkey[1]; - - /* check if cycle is infinitely small, to be point of being impossible to use */ - if (cycdx == 0) - return evaltime; - - /* calculate the 'number' of the cycle */ - cycle= ((float)side * (evaltime - ofs) / cycdx); - - /* check that cyclic is still enabled for the specified time */ - if (cycles == 0) { - /* catch this case so that we don't exit when we have cycles=0 - * as this indicates infinite cycles... - */ - } - else if (cycle > (cycles+1)) { - /* we are too far away from range to evaluate - * TODO: but we should still hold last value... - */ - return evaltime; - } - - /* check if 'cyclic extrapolation', and thus calculate y-offset for this cycle */ - if (mode == FCM_EXTRAPOLATE_CYCLIC_OFFSET) { - cycyofs = (float)floor((evaltime - ofs) / cycdx); - cycyofs *= cycdy; - } - - /* calculate where in the cycle we are (overwrite evaltime to reflect this) */ - if ((mode == FCM_EXTRAPOLATE_MIRROR) && ((int)(cycle) % 2)) { - /* when 'mirror' option is used and cycle number is odd, this cycle is played in reverse - * - for 'before' extrapolation, we need to flip in a different way, otherwise values past - * then end of the curve get referenced (result of fmod will be negative, and with different phase) - */ - if (side < 0) - evaltime= (float)(prevkey[0] - fmod(evaltime-ofs, cycdx)); - else - evaltime= (float)(lastkey[0] - fmod(evaltime-ofs, cycdx)); - } - else { - /* the cycle is played normally... */ - evaltime= (float)(fmod(evaltime-ofs, cycdx) + ofs); - } - if (evaltime < ofs) evaltime += cycdx; - } - - /* store temp data if needed */ - if (mode == FCM_EXTRAPOLATE_CYCLIC_OFFSET) { - tFCMED_Cycles *edata; - - /* for now, this is just a float, but we could get more stuff... */ - fcm->edata= edata= MEM_callocN(sizeof(tFCMED_Cycles), "tFCMED_Cycles"); - edata->cycyofs= cycyofs; - } - - /* return the new frame to evaluate */ - return evaltime; -} - -static void fcm_cycles_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime) -{ - tFCMED_Cycles *edata= (tFCMED_Cycles *)fcm->edata; - - /* use temp data */ - if (edata) { - /* add cyclic offset - no need to check for now, otherwise the data wouldn't exist! */ - *cvalue += edata->cycyofs; - - /* free temp data */ - MEM_freeN(edata); - fcm->edata= NULL; - } -} - -static FModifierTypeInfo FMI_CYCLES = { - FMODIFIER_TYPE_CYCLES, /* type */ - sizeof(FMod_Cycles), /* size */ - FMI_TYPE_EXTRAPOLATION, /* action type */ - FMI_REQUIRES_ORIGINAL_DATA, /* requirements */ - "Cycles", /* name */ - "FMod_Cycles", /* struct name */ - NULL, /* free data */ - NULL, /* copy data */ - fcm_cycles_new_data, /* new data */ - NULL /*fcm_cycles_verify*/, /* verify */ - fcm_cycles_time, /* evaluate time */ - fcm_cycles_evaluate /* evaluate */ -}; - -/* Noise F-Curve Modifier --------------------------- */ - -static void fcm_noise_new_data (void *mdata) -{ - FMod_Noise *data= (FMod_Noise *)mdata; - - /* defaults */ - data->size= 1.0f; - data->strength= 1.0f; - data->phase= 1.0f; - data->depth = 0; - data->modification = FCM_NOISE_MODIF_REPLACE; -} - -static void fcm_noise_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime) -{ - FMod_Noise *data= (FMod_Noise *)fcm->data; - float noise; - - noise = BLI_turbulence(data->size, evaltime, data->phase, 0.f, data->depth); - - switch (data->modification) { - case FCM_NOISE_MODIF_ADD: - *cvalue= *cvalue + noise * data->strength; - break; - case FCM_NOISE_MODIF_SUBTRACT: - *cvalue= *cvalue - noise * data->strength; - break; - case FCM_NOISE_MODIF_MULTIPLY: - *cvalue= *cvalue * noise * data->strength; - break; - case FCM_NOISE_MODIF_REPLACE: - default: - *cvalue= *cvalue + (noise - 0.5f) * data->strength; - break; - } -} - -static FModifierTypeInfo FMI_NOISE = { - FMODIFIER_TYPE_NOISE, /* type */ - sizeof(FMod_Noise), /* size */ - FMI_TYPE_REPLACE_VALUES, /* action type */ - 0, /* requirements */ - "Noise", /* name */ - "FMod_Noise", /* struct name */ - NULL, /* free data */ - NULL, /* copy data */ - fcm_noise_new_data, /* new data */ - NULL /*fcm_noise_verify*/, /* verify */ - NULL, /* evaluate time */ - fcm_noise_evaluate /* evaluate */ -}; - -/* Filter F-Curve Modifier --------------------------- */ - -#if 0 // XXX not yet implemented -static FModifierTypeInfo FMI_FILTER = { - FMODIFIER_TYPE_FILTER, /* type */ - sizeof(FMod_Filter), /* size */ - FMI_TYPE_REPLACE_VALUES, /* action type */ - 0, /* requirements */ - "Filter", /* name */ - "FMod_Filter", /* struct name */ - NULL, /* free data */ - NULL, /* copy data */ - NULL, /* new data */ - NULL /*fcm_filter_verify*/, /* verify */ - NULL, /* evlauate time */ - fcm_filter_evaluate /* evaluate */ -}; -#endif // XXX not yet implemented - - -/* Python F-Curve Modifier --------------------------- */ - -static void fcm_python_free (FModifier *fcm) -{ - FMod_Python *data= (FMod_Python *)fcm->data; - - /* id-properties */ - IDP_FreeProperty(data->prop); - MEM_freeN(data->prop); -} - -static void fcm_python_new_data (void *mdata) -{ - FMod_Python *data= (FMod_Python *)mdata; - - /* everything should be set correctly by calloc, except for the prop->type constant.*/ - data->prop = MEM_callocN(sizeof(IDProperty), "PyFModifierProps"); - data->prop->type = IDP_GROUP; -} - -static void fcm_python_copy (FModifier *fcm, FModifier *src) -{ - FMod_Python *pymod = (FMod_Python *)fcm->data; - FMod_Python *opymod = (FMod_Python *)src->data; - - pymod->prop = IDP_CopyProperty(opymod->prop); -} - -static void fcm_python_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime) -{ -#ifndef DISABLE_PYTHON - //FMod_Python *data= (FMod_Python *)fcm->data; - - /* FIXME... need to implement this modifier... - * It will need it execute a script using the custom properties - */ -#endif /* DISABLE_PYTHON */ -} - -static FModifierTypeInfo FMI_PYTHON = { - FMODIFIER_TYPE_PYTHON, /* type */ - sizeof(FMod_Python), /* size */ - FMI_TYPE_GENERATE_CURVE, /* action type */ - FMI_REQUIRES_RUNTIME_CHECK, /* requirements */ - "Python", /* name */ - "FMod_Python", /* struct name */ - fcm_python_free, /* free data */ - fcm_python_copy, /* copy data */ - fcm_python_new_data, /* new data */ - NULL /*fcm_python_verify*/, /* verify */ - NULL /*fcm_python_time*/, /* evaluate time */ - fcm_python_evaluate /* evaluate */ -}; - - -/* Limits F-Curve Modifier --------------------------- */ - -static float fcm_limits_time (FCurve *fcu, FModifier *fcm, float cvalue, float evaltime) -{ - FMod_Limits *data= (FMod_Limits *)fcm->data; - - /* check for the time limits */ - if ((data->flag & FCM_LIMIT_XMIN) && (evaltime < data->rect.xmin)) - return data->rect.xmin; - if ((data->flag & FCM_LIMIT_XMAX) && (evaltime > data->rect.xmax)) - return data->rect.xmax; - - /* modifier doesn't change time */ - return evaltime; -} - -static void fcm_limits_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime) -{ - FMod_Limits *data= (FMod_Limits *)fcm->data; - - /* value limits now */ - if ((data->flag & FCM_LIMIT_YMIN) && (*cvalue < data->rect.ymin)) - *cvalue= data->rect.ymin; - if ((data->flag & FCM_LIMIT_YMAX) && (*cvalue > data->rect.ymax)) - *cvalue= data->rect.ymax; -} - -static FModifierTypeInfo FMI_LIMITS = { - FMODIFIER_TYPE_LIMITS, /* type */ - sizeof(FMod_Limits), /* size */ - FMI_TYPE_GENERATE_CURVE, /* action type */ /* XXX... err... */ - FMI_REQUIRES_RUNTIME_CHECK, /* requirements */ - "Limits", /* name */ - "FMod_Limits", /* struct name */ - NULL, /* free data */ - NULL, /* copy data */ - NULL, /* new data */ - NULL, /* verify */ - fcm_limits_time, /* evaluate time */ - fcm_limits_evaluate /* evaluate */ -}; - -/* F-Curve Modifier API --------------------------- */ -/* All of the F-Curve Modifier api functions use FModifierTypeInfo structs to carry out - * and operations that involve F-Curve modifier specific code. - */ - -/* These globals only ever get directly accessed in this file */ -static FModifierTypeInfo *fmodifiersTypeInfo[FMODIFIER_NUM_TYPES]; -static short FMI_INIT= 1; /* when non-zero, the list needs to be updated */ - -/* This function only gets called when FMI_INIT is non-zero */ -static void fmods_init_typeinfo () -{ - fmodifiersTypeInfo[0]= NULL; /* 'Null' F-Curve Modifier */ - fmodifiersTypeInfo[1]= &FMI_GENERATOR; /* Generator F-Curve Modifier */ - fmodifiersTypeInfo[2]= &FMI_FN_GENERATOR; /* Built-In Function Generator F-Curve Modifier */ - fmodifiersTypeInfo[3]= &FMI_ENVELOPE; /* Envelope F-Curve Modifier */ - fmodifiersTypeInfo[4]= &FMI_CYCLES; /* Cycles F-Curve Modifier */ - fmodifiersTypeInfo[5]= &FMI_NOISE; /* Apply-Noise F-Curve Modifier */ - fmodifiersTypeInfo[6]= NULL/*&FMI_FILTER*/; /* Filter F-Curve Modifier */ // XXX unimplemented - fmodifiersTypeInfo[7]= &FMI_PYTHON; /* Custom Python F-Curve Modifier */ - fmodifiersTypeInfo[8]= &FMI_LIMITS; /* Limits F-Curve Modifier */ -} - -/* This function should be used for getting the appropriate type-info when only - * a F-Curve modifier type is known - */ -FModifierTypeInfo *get_fmodifier_typeinfo (int type) -{ - /* initialise the type-info list? */ - if (FMI_INIT) { - fmods_init_typeinfo(); - FMI_INIT = 0; - } - - /* only return for valid types */ - if ( (type >= FMODIFIER_TYPE_NULL) && - (type <= FMODIFIER_NUM_TYPES ) ) - { - /* there shouldn't be any segfaults here... */ - return fmodifiersTypeInfo[type]; - } - else { - printf("No valid F-Curve Modifier type-info data available. Type = %i \n", type); - } - - return NULL; -} - -/* This function should always be used to get the appropriate type-info, as it - * has checks which prevent segfaults in some weird cases. - */ -FModifierTypeInfo *fmodifier_get_typeinfo (FModifier *fcm) -{ - /* only return typeinfo for valid modifiers */ - if (fcm) - return get_fmodifier_typeinfo(fcm->type); - else - return NULL; -} - -/* API --------------------------- */ - -/* Add a new F-Curve Modifier to the given F-Curve of a certain type */ -FModifier *fcurve_add_modifier (FCurve *fcu, int type) -{ - FModifierTypeInfo *fmi= get_fmodifier_typeinfo(type); - FModifier *fcm; - - /* sanity checks */ - if ELEM(NULL, fcu, fmi) - return NULL; - - /* special checks for whether modifier can be added */ - if ((fcu->modifiers.first) && (type == FMODIFIER_TYPE_CYCLES)) { - /* cycles modifier must be first in stack, so for now, don't add if it can't be */ - // TODO: perhaps there is some better way, but for now, - printf("Error: Cannot add 'Cycles' modifier to F-Curve, as 'Cycles' modifier can only be first in stack. \n"); - return NULL; - } - - /* add modifier itself */ - fcm= MEM_callocN(sizeof(FModifier), "F-Curve Modifier"); - fcm->type = type; - fcm->flag = FMODIFIER_FLAG_EXPANDED; - BLI_addtail(&fcu->modifiers, fcm); - - /* add modifier's data */ - fcm->data= MEM_callocN(fmi->size, fmi->structName); - - /* init custom settings if necessary */ - if (fmi->new_data) - fmi->new_data(fcm->data); - - /* return modifier for further editing */ - return fcm; -} - -/* Duplicate all of the F-Curve Modifiers in the Modifier stacks */ -void fcurve_copy_modifiers (ListBase *dst, ListBase *src) -{ - FModifier *fcm, *srcfcm; - - if ELEM(NULL, dst, src) - return; - - dst->first= dst->last= NULL; - BLI_duplicatelist(dst, src); - - for (fcm=dst->first, srcfcm=src->first; fcm && srcfcm; srcfcm=srcfcm->next, fcm=fcm->next) { - FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm); - - /* make a new copy of the F-Modifier's data */ - fcm->data = MEM_dupallocN(fcm->data); - - /* only do specific constraints if required */ - if (fmi && fmi->copy_data) - fmi->copy_data(fcm, srcfcm); - } -} - -/* Remove and free the given F-Curve Modifier from the given F-Curve's stack */ -void fcurve_remove_modifier (FCurve *fcu, FModifier *fcm) -{ - FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm); - - /* sanity check */ - if (fcm == NULL) - return; - - /* free modifier's special data (stored inside fcm->data) */ - if (fcm->data) { - if (fmi && fmi->free_data) - fmi->free_data(fcm); - - /* free modifier's data (fcm->data) */ - MEM_freeN(fcm->data); - } - - /* remove modifier from stack */ - if (fcu) - BLI_freelinkN(&fcu->modifiers, fcm); - else { - // XXX this case can probably be removed some day, as it shouldn't happen... - printf("fcurve_remove_modifier() - no fcurve \n"); - MEM_freeN(fcm); - } -} - -/* Remove all of a given F-Curve's modifiers */ -void fcurve_free_modifiers (FCurve *fcu) -{ - FModifier *fcm, *fmn; - - /* sanity check */ - if (fcu == NULL) - return; - - /* free each modifier in order - modifier is unlinked from list and freed */ - for (fcm= fcu->modifiers.first; fcm; fcm= fmn) { - fmn= fcm->next; - fcurve_remove_modifier(fcu, fcm); - } -} - -/* Find the active F-Curve Modifier */ -FModifier *fcurve_find_active_modifier (FCurve *fcu) -{ - FModifier *fcm; - - /* sanity checks */ - if ELEM(NULL, fcu, fcu->modifiers.first) - return NULL; - - /* loop over modifiers until 'active' one is found */ - for (fcm= fcu->modifiers.first; fcm; fcm= fcm->next) { - if (fcm->flag & FMODIFIER_FLAG_ACTIVE) - return fcm; - } - - /* no modifier is active */ - return NULL; -} - -/* Set the active F-Curve Modifier */ -void fcurve_set_active_modifier (FCurve *fcu, FModifier *fcm) -{ - FModifier *fm; - - /* sanity checks */ - if ELEM(NULL, fcu, fcu->modifiers.first) - return; - - /* deactivate all, and set current one active */ - for (fm= fcu->modifiers.first; fm; fm= fm->next) - fm->flag &= ~FMODIFIER_FLAG_ACTIVE; - - /* make given modifier active */ - if (fcm) - fcm->flag |= FMODIFIER_FLAG_ACTIVE; -} - -/* Do we have any modifiers which match certain criteria - * - mtype - type of modifier (if 0, doesn't matter) - * - acttype - type of action to perform (if -1, doesn't matter) - */ -short fcurve_has_suitable_modifier (FCurve *fcu, int mtype, short acttype) -{ - FModifier *fcm; - - /* if there are no specific filtering criteria, just skip */ - if ((mtype == 0) && (acttype == 0)) - return (fcu && fcu->modifiers.first); - - /* sanity checks */ - if ELEM(NULL, fcu, fcu->modifiers.first) - return 0; - - /* find the first mdifier fitting these criteria */ - for (fcm= fcu->modifiers.first; fcm; fcm= fcm->next) { - FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm); - short mOk=1, aOk=1; /* by default 1, so that when only one test, won't fail */ - - /* check if applicable ones are fullfilled */ - if (mtype) - mOk= (fcm->type == mtype); - if (acttype > -1) - aOk= (fmi->acttype == acttype); - - /* if both are ok, we've found a hit */ - if (mOk && aOk) - return 1; - } - - /* no matches */ - return 0; -} - -/* Evaluation API --------------------------- */ - -/* evaluate time modifications imposed by some F-Curve Modifiers - * - this step acts as an optimisation to prevent the F-Curve stack being evaluated - * several times by modifiers requesting the time be modified, as the final result - * would have required using the modified time - * - modifiers only ever recieve the unmodified time, as subsequent modifiers should be - * working on the 'global' result of the modified curve, not some localised segment, - * so nevaltime gets set to whatever the last time-modifying modifier likes... - * - we start from the end of the stack, as only the last one matters for now - */ -float evaluate_time_fmodifiers (ListBase *modifiers, FCurve *fcu, float cvalue, float evaltime) -{ - FModifier *fcm; - float m_evaltime= evaltime; - - /* sanity checks */ - if ELEM(NULL, modifiers, modifiers->first) - return evaltime; - - /* find the first modifier from end of stack that modifies time, and calculate the time the modifier - * would calculate time at - */ - for (fcm= fcu->modifiers.last; fcm; fcm= fcm->prev) { - FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm); - - /* only evaluate if there's a callback for this */ - // TODO: implement the 'influence' control feature... - if (fmi && fmi->evaluate_modifier_time) { - if ((fcm->flag & (FMODIFIER_FLAG_DISABLED|FMODIFIER_FLAG_MUTED)) == 0) - m_evaltime= fmi->evaluate_modifier_time(fcu, fcm, cvalue, evaltime); - break; - } - } - - /* return the modified evaltime */ - return m_evaltime; -} - -/* Evalautes the given set of F-Curve Modifiers using the given data - * Should only be called after evaluate_time_fmodifiers() has been called... - */ -void evaluate_value_fmodifiers (ListBase *modifiers, FCurve *fcu, float *cvalue, float evaltime) -{ - FModifier *fcm; - - /* sanity checks */ - if ELEM(NULL, modifiers, modifiers->first) - return; - - /* evaluate modifiers */ - for (fcm= modifiers->first; fcm; fcm= fcm->next) { - FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm); - - /* only evaluate if there's a callback for this */ - // TODO: implement the 'influence' control feature... - if (fmi && fmi->evaluate_modifier) { - if ((fcm->flag & (FMODIFIER_FLAG_DISABLED|FMODIFIER_FLAG_MUTED)) == 0) - fmi->evaluate_modifier(fcu, fcm, cvalue, evaltime); - } - } -} - - -/* Bake modifiers for given F-Curve to curve sample data, in the frame range defined - * by start and end (inclusive). - */ -void fcurve_bake_modifiers (FCurve *fcu, int start, int end) -{ - ChannelDriver *driver; - - /* sanity checks */ - // TODO: make these tests report errors using reports not printf's - if ELEM(NULL, fcu, fcu->modifiers.first) { - printf("Error: No F-Curve with F-Curve Modifiers to Bake\n"); - return; - } - - /* temporarily, disable driver while we sample, so that they don't influence the outcome */ - driver= fcu->driver; - fcu->driver= NULL; - - /* bake the modifiers, by sampling the curve at each frame */ - fcurve_store_samples(fcu, NULL, start, end, fcurve_samplingcb_evalcurve); - - /* free the modifiers now */ - fcurve_free_modifiers(fcu); - - /* restore driver */ - fcu->driver= driver; -} - /* ***************************** F-Curve - Evaluation ********************************* */ /* Evaluate and return the value of the given F-Curve at the specified frame ("evaltime") @@ -2450,7 +1321,7 @@ void calculate_fcurve (FCurve *fcu, float ctime) * any data which warrants this... */ if ( (fcu->totvert) || (fcu->driver && !(fcu->driver->flag & DRIVER_FLAG_INVALID)) || - fcurve_has_suitable_modifier(fcu, 0, FMI_TYPE_GENERATE_CURVE) ) + list_has_suitable_fmodifier(&fcu->modifiers, 0, FMI_TYPE_GENERATE_CURVE) ) { /* calculate and set curval (evaluates driver too if necessary) */ fcu->curval= evaluate_fcurve(fcu, ctime); diff --git a/source/blender/blenkernel/intern/fmodifier.c b/source/blender/blenkernel/intern/fmodifier.c new file mode 100644 index 00000000000..aa5214979d9 --- /dev/null +++ b/source/blender/blenkernel/intern/fmodifier.c @@ -0,0 +1,1197 @@ +/** + * $Id: fcurve.c 21299 2009-07-02 02:12:37Z aligorith $ + * + * ***** 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) 2009 Blender Foundation, Joshua Leung + * All rights reserved. + * + * Contributor(s): Joshua Leung (full recode) + * + * ***** END GPL LICENSE BLOCK ***** + */ + + +#include +#include +#include +#include +#include + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "MEM_guardedalloc.h" + +#include "DNA_anim_types.h" + +#include "BLI_blenlib.h" +#include "BLI_arithb.h" +#include "BLI_noise.h" + +#include "BKE_fcurve.h" +#include "BKE_curve.h" +#include "BKE_global.h" +#include "BKE_idprop.h" +#include "BKE_utildefines.h" + +#include "RNA_access.h" +#include "RNA_types.h" + +#ifndef DISABLE_PYTHON +#include "BPY_extern.h" /* for BPY_pydriver_eval() */ +#endif + +#define SMALL -1.0e-10 +#define SELECT 1 + +/* ******************************** F-Modifiers ********************************* */ + +/* Info ------------------------------- */ + +/* F-Modifiers are modifiers which operate on F-Curves. However, they can also be defined + * on NLA-Strips to affect all of the F-Curves referenced by the NLA-Strip. + */ + +/* Template --------------------------- */ + +/* Each modifier defines a set of functions, which will be called at the appropriate + * times. In addition to this, each modifier should have a type-info struct, where + * its functions are attached for use. + */ + +/* Template for type-info data: + * - make a copy of this when creating new modifiers, and just change the functions + * pointed to as necessary + * - although the naming of functions doesn't matter, it would help for code + * readability, to follow the same naming convention as is presented here + * - any functions that a constraint doesn't need to define, don't define + * for such cases, just use NULL + * - these should be defined after all the functions have been defined, so that + * forward-definitions/prototypes don't need to be used! + * - keep this copy #if-def'd so that future constraints can get based off this + */ +#if 0 +static FModifierTypeInfo FMI_MODNAME = { + FMODIFIER_TYPE_MODNAME, /* type */ + sizeof(FMod_ModName), /* size */ + FMI_TYPE_SOME_ACTION, /* action type */ + FMI_REQUIRES_SOME_REQUIREMENT, /* requirements */ + "Modifier Name", /* name */ + "FMod_ModName", /* struct name */ + fcm_modname_free, /* free data */ + fcm_modname_relink, /* relink data */ + fcm_modname_copy, /* copy data */ + fcm_modname_new_data, /* new data */ + fcm_modname_verify, /* verify */ + fcm_modname_time, /* evaluate time */ + fcm_modname_evaluate /* evaluate */ +}; +#endif + +/* Generator F-Curve Modifier --------------------------- */ + +/* Generators available: + * 1) simple polynomial generator: + * - Exanded form - (y = C[0]*(x^(n)) + C[1]*(x^(n-1)) + ... + C[n]) + * - Factorised form - (y = (C[0][0]*x + C[0][1]) * (C[1][0]*x + C[1][1]) * ... * (C[n][0]*x + C[n][1])) + */ + +static void fcm_generator_free (FModifier *fcm) +{ + FMod_Generator *data= (FMod_Generator *)fcm->data; + + /* free polynomial coefficients array */ + if (data->coefficients) + MEM_freeN(data->coefficients); +} + +static void fcm_generator_copy (FModifier *fcm, FModifier *src) +{ + FMod_Generator *gen= (FMod_Generator *)fcm->data; + FMod_Generator *ogen= (FMod_Generator *)src->data; + + /* copy coefficients array? */ + if (ogen->coefficients) + gen->coefficients= MEM_dupallocN(ogen->coefficients); +} + +static void fcm_generator_new_data (void *mdata) +{ + FMod_Generator *data= (FMod_Generator *)mdata; + float *cp; + + /* set default generator to be linear 0-1 (gradient = 1, y-offset = 0) */ + data->poly_order= 1; + data->arraysize= 2; + cp= data->coefficients= MEM_callocN(sizeof(float)*2, "FMod_Generator_Coefs"); + cp[0] = 0; // y-offset + cp[1] = 1; // gradient +} + +static void fcm_generator_verify (FModifier *fcm) +{ + FMod_Generator *data= (FMod_Generator *)fcm->data; + + /* requirements depend on mode */ + switch (data->mode) { + case FCM_GENERATOR_POLYNOMIAL: /* expanded polynomial expression */ + { + /* arraysize needs to be order+1, so resize if not */ + if (data->arraysize != (data->poly_order+1)) { + float *nc; + + /* make new coefficients array, and copy over as much data as can fit */ + nc= MEM_callocN(sizeof(float)*(data->poly_order+1), "FMod_Generator_Coefs"); + + if (data->coefficients) { + if (data->arraysize > (data->poly_order+1)) + memcpy(nc, data->coefficients, sizeof(float)*(data->poly_order+1)); + else + memcpy(nc, data->coefficients, sizeof(float)*data->arraysize); + + /* free the old data */ + MEM_freeN(data->coefficients); + } + + /* set the new data */ + data->coefficients= nc; + data->arraysize= data->poly_order+1; + } + } + break; + + case FCM_GENERATOR_POLYNOMIAL_FACTORISED: /* expanded polynomial expression */ + { + /* arraysize needs to be 2*order, so resize if not */ + if (data->arraysize != (data->poly_order * 2)) { + float *nc; + + /* make new coefficients array, and copy over as much data as can fit */ + nc= MEM_callocN(sizeof(float)*(data->poly_order*2), "FMod_Generator_Coefs"); + + if (data->coefficients) { + if (data->arraysize > (data->poly_order * 2)) + memcpy(nc, data->coefficients, sizeof(float)*(data->poly_order * 2)); + else + memcpy(nc, data->coefficients, sizeof(float)*data->arraysize); + + /* free the old data */ + MEM_freeN(data->coefficients); + } + + /* set the new data */ + data->coefficients= nc; + data->arraysize= data->poly_order * 2; + } + } + break; + } +} + +static void fcm_generator_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime) +{ + FMod_Generator *data= (FMod_Generator *)fcm->data; + + /* behaviour depends on mode + * NOTE: the data in its default state is fine too + */ + switch (data->mode) { + case FCM_GENERATOR_POLYNOMIAL: /* expanded polynomial expression */ + { + /* we overwrite cvalue with the sum of the polynomial */ + float *powers = MEM_callocN(sizeof(float)*data->arraysize, "Poly Powers"); + float value= 0.0f; + unsigned int i; + + /* for each x^n, precalculate value based on previous one first... this should be + * faster that calling pow() for each entry + */ + for (i=0; i < data->arraysize; i++) { + /* first entry is x^0 = 1, otherwise, calculate based on previous */ + if (i) + powers[i]= powers[i-1] * evaltime; + else + powers[0]= 1; + } + + /* for each coefficient, add to value, which we'll write to *cvalue in one go */ + for (i=0; i < data->arraysize; i++) + value += data->coefficients[i] * powers[i]; + + /* only if something changed, write *cvalue in one go */ + if (data->poly_order) { + if (data->flag & FCM_GENERATOR_ADDITIVE) + *cvalue += value; + else + *cvalue= value; + } + + /* cleanup */ + if (powers) + MEM_freeN(powers); + } + break; + + case FCM_GENERATOR_POLYNOMIAL_FACTORISED: /* factorised polynomial */ + { + float value= 1.0f, *cp=NULL; + unsigned int i; + + /* for each coefficient pair, solve for that bracket before accumulating in value by multiplying */ + for (cp=data->coefficients, i=0; (cp) && (i < data->poly_order); cp+=2, i++) + value *= (cp[0]*evaltime + cp[1]); + + /* only if something changed, write *cvalue in one go */ + if (data->poly_order) { + if (data->flag & FCM_GENERATOR_ADDITIVE) + *cvalue += value; + else + *cvalue= value; + } + } + break; + } +} + +static FModifierTypeInfo FMI_GENERATOR = { + FMODIFIER_TYPE_GENERATOR, /* type */ + sizeof(FMod_Generator), /* size */ + FMI_TYPE_GENERATE_CURVE, /* action type */ + FMI_REQUIRES_NOTHING, /* requirements */ + "Generator", /* name */ + "FMod_Generator", /* struct name */ + fcm_generator_free, /* free data */ + fcm_generator_copy, /* copy data */ + fcm_generator_new_data, /* new data */ + fcm_generator_verify, /* verify */ + NULL, /* evaluate time */ + fcm_generator_evaluate /* evaluate */ +}; + +/* Built-In Function Generator F-Curve Modifier --------------------------- */ + +/* This uses the general equation for equations: + * y = amplitude * fn(phase_multiplier*x + phase_offset) + y_offset + * + * where amplitude, phase_multiplier/offset, y_offset are user-defined coefficients, + * x is the evaluation 'time', and 'y' is the resultant value + * + * Functions available are + * sin, cos, tan, sinc (normalised sin), natural log, square root + */ + +static void fcm_fn_generator_new_data (void *mdata) +{ + FMod_FunctionGenerator *data= (FMod_FunctionGenerator *)mdata; + + /* set amplitude and phase multiplier to 1.0f so that something is generated */ + data->amplitude= 1.0f; + data->phase_multiplier= 1.0f; +} + +/* Unary 'normalised sine' function + * y = sin(PI + x) / (PI * x), + * except for x = 0 when y = 1. + */ +static double sinc (double x) +{ + if (fabs(x) < 0.0001) + return 1.0; + else + return sin(M_PI * x) / (M_PI * x); +} + +static void fcm_fn_generator_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime) +{ + FMod_FunctionGenerator *data= (FMod_FunctionGenerator *)fcm->data; + double arg= data->phase_multiplier*evaltime + data->phase_offset; + double (*fn)(double v) = NULL; + + /* get function pointer to the func to use: + * WARNING: must perform special argument validation hereto guard against crashes + */ + switch (data->type) + { + /* simple ones */ + case FCM_GENERATOR_FN_SIN: /* sine wave */ + fn= sin; + break; + case FCM_GENERATOR_FN_COS: /* cosine wave */ + fn= cos; + break; + case FCM_GENERATOR_FN_SINC: /* normalised sine wave */ + fn= sinc; + break; + + /* validation required */ + case FCM_GENERATOR_FN_TAN: /* tangent wave */ + { + /* check that argument is not on one of the discontinuities (i.e. 90deg, 270 deg, etc) */ + if IS_EQ(fmod((arg - M_PI_2), M_PI), 0.0) { + if ((data->flag & FCM_GENERATOR_ADDITIVE) == 0) + *cvalue = 0.0f; /* no value possible here */ + } + else + fn= tan; + } + break; + case FCM_GENERATOR_FN_LN: /* natural log */ + { + /* check that value is greater than 1? */ + if (arg > 1.0f) { + fn= log; + } + else { + if ((data->flag & FCM_GENERATOR_ADDITIVE) == 0) + *cvalue = 0.0f; /* no value possible here */ + } + } + break; + case FCM_GENERATOR_FN_SQRT: /* square root */ + { + /* no negative numbers */ + if (arg > 0.0f) { + fn= sqrt; + } + else { + if ((data->flag & FCM_GENERATOR_ADDITIVE) == 0) + *cvalue = 0.0f; /* no value possible here */ + } + } + break; + + default: + printf("Invalid Function-Generator for F-Modifier - %d \n", data->type); + } + + /* execute function callback to set value if appropriate */ + if (fn) { + float value= (float)(data->amplitude*fn(arg) + data->value_offset); + + if (data->flag & FCM_GENERATOR_ADDITIVE) + *cvalue += value; + else + *cvalue= value; + } +} + +static FModifierTypeInfo FMI_FN_GENERATOR = { + FMODIFIER_TYPE_FN_GENERATOR, /* type */ + sizeof(FMod_FunctionGenerator), /* size */ + FMI_TYPE_GENERATE_CURVE, /* action type */ + FMI_REQUIRES_NOTHING, /* requirements */ + "Built-In Function", /* name */ + "FMod_FunctionGenerator", /* struct name */ + NULL, /* free data */ + NULL, /* copy data */ + fcm_fn_generator_new_data, /* new data */ + NULL, /* verify */ + NULL, /* evaluate time */ + fcm_fn_generator_evaluate /* evaluate */ +}; + +/* Envelope F-Curve Modifier --------------------------- */ + +static void fcm_envelope_free (FModifier *fcm) +{ + FMod_Envelope *env= (FMod_Envelope *)fcm->data; + + /* free envelope data array */ + if (env->data) + MEM_freeN(env->data); +} + +static void fcm_envelope_copy (FModifier *fcm, FModifier *src) +{ + FMod_Envelope *env= (FMod_Envelope *)fcm->data; + FMod_Envelope *oenv= (FMod_Envelope *)src->data; + + /* copy envelope data array */ + if (oenv->data) + env->data= MEM_dupallocN(oenv->data); +} + +static void fcm_envelope_new_data (void *mdata) +{ + FMod_Envelope *env= (FMod_Envelope *)mdata; + + /* set default min/max ranges */ + env->min= -1.0f; + env->max= 1.0f; +} + +static void fcm_envelope_verify (FModifier *fcm) +{ + FMod_Envelope *env= (FMod_Envelope *)fcm->data; + + /* if the are points, perform bubble-sort on them, as user may have changed the order */ + if (env->data) { + // XXX todo... + } +} + +static void fcm_envelope_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime) +{ + FMod_Envelope *env= (FMod_Envelope *)fcm->data; + FCM_EnvelopeData *fed, *prevfed, *lastfed; + float min=0.0f, max=0.0f, fac=0.0f; + int a; + + /* get pointers */ + if (env->data == NULL) return; + prevfed= env->data; + fed= prevfed + 1; + lastfed= prevfed + (env->totvert-1); + + /* get min/max values for envelope at evaluation time (relative to mid-value) */ + if (prevfed->time >= evaltime) { + /* before or on first sample, so just extend value */ + min= prevfed->min; + max= prevfed->max; + } + else if (lastfed->time <= evaltime) { + /* after or on last sample, so just extend value */ + min= lastfed->min; + max= lastfed->max; + } + else { + /* evaltime occurs somewhere between segments */ + // TODO: implement binary search for this to make it faster? + for (a=0; prevfed && fed && (a < env->totvert-1); a++, prevfed=fed, fed++) { + /* evaltime occurs within the interval defined by these two envelope points */ + if ((prevfed->time <= evaltime) && (fed->time >= evaltime)) { + float afac, bfac, diff; + + diff= fed->time - prevfed->time; + afac= (evaltime - prevfed->time) / diff; + bfac= (fed->time - evaltime) / diff; + + min= bfac*prevfed->min + afac*fed->min; + max= bfac*prevfed->max + afac*fed->max; + + break; + } + } + } + + /* adjust *cvalue + * - fac is the ratio of how the current y-value corresponds to the reference range + * - thus, the new value is found by mapping the old range to the new! + */ + fac= (*cvalue - (env->midval + env->min)) / (env->max - env->min); + *cvalue= min + fac*(max - min); +} + +static FModifierTypeInfo FMI_ENVELOPE = { + FMODIFIER_TYPE_ENVELOPE, /* type */ + sizeof(FMod_Envelope), /* size */ + FMI_TYPE_REPLACE_VALUES, /* action type */ + 0, /* requirements */ + "Envelope", /* name */ + "FMod_Envelope", /* struct name */ + fcm_envelope_free, /* free data */ + fcm_envelope_copy, /* copy data */ + fcm_envelope_new_data, /* new data */ + fcm_envelope_verify, /* verify */ + NULL, /* evaluate time */ + fcm_envelope_evaluate /* evaluate */ +}; + +/* Cycles F-Curve Modifier --------------------------- */ + +/* This modifier changes evaltime to something that exists within the curve's frame-range, + * then re-evaluates modifier stack up to this point using the new time. This re-entrant behaviour + * is very likely to be more time-consuming than the original approach... (which was tighly integrated into + * the calculation code...). + * + * NOTE: this needs to be at the start of the stack to be of use, as it needs to know the extents of the keyframes/sample-data + * Possible TODO - store length of cycle information that can be initialised from the extents of the keyframes/sample-data, and adjusted + * as appropriate + */ + +/* temp data used during evaluation */ +typedef struct tFCMED_Cycles { + float cycyofs; /* y-offset to apply */ +} tFCMED_Cycles; + +static void fcm_cycles_new_data (void *mdata) +{ + FMod_Cycles *data= (FMod_Cycles *)mdata; + + /* turn on cycles by default */ + data->before_mode= data->after_mode= FCM_EXTRAPOLATE_CYCLIC; +} + +static float fcm_cycles_time (FCurve *fcu, FModifier *fcm, float cvalue, float evaltime) +{ + FMod_Cycles *data= (FMod_Cycles *)fcm->data; + float prevkey[2], lastkey[2], cycyofs=0.0f; + short side=0, mode=0; + int cycles=0; + + /* check if modifier is first in stack, otherwise disable ourself... */ + // FIXME... + if (fcm->prev) { + fcm->flag |= FMODIFIER_FLAG_DISABLED; + return evaltime; + } + + /* calculate new evaltime due to cyclic interpolation */ + if (fcu && fcu->bezt) { + BezTriple *prevbezt= fcu->bezt; + BezTriple *lastbezt= prevbezt + fcu->totvert-1; + + prevkey[0]= prevbezt->vec[1][0]; + prevkey[1]= prevbezt->vec[1][1]; + + lastkey[0]= lastbezt->vec[1][0]; + lastkey[1]= lastbezt->vec[1][1]; + } + else if (fcu && fcu->fpt) { + FPoint *prevfpt= fcu->fpt; + FPoint *lastfpt= prevfpt + fcu->totvert-1; + + prevkey[0]= prevfpt->vec[0]; + prevkey[1]= prevfpt->vec[1]; + + lastkey[0]= lastfpt->vec[0]; + lastkey[1]= lastfpt->vec[1]; + } + else + return evaltime; + + /* check if modifier will do anything + * 1) if in data range, definitely don't do anything + * 2) if before first frame or after last frame, make sure some cycling is in use + */ + if (evaltime < prevkey[0]) { + if (data->before_mode) { + side= -1; + mode= data->before_mode; + cycles= data->before_cycles; + } + } + else if (evaltime > lastkey[0]) { + if (data->after_mode) { + side= 1; + mode= data->after_mode; + cycles= data->after_cycles; + } + } + if ELEM(0, side, mode) + return evaltime; + + /* find relative place within a cycle */ + { + float cycdx=0, cycdy=0, ofs=0; + float cycle= 0; + + /* ofs is start frame of cycle */ + ofs= prevkey[0]; + + /* calculate period and amplitude (total height) of a cycle */ + cycdx= lastkey[0] - prevkey[0]; + cycdy= lastkey[1] - prevkey[1]; + + /* check if cycle is infinitely small, to be point of being impossible to use */ + if (cycdx == 0) + return evaltime; + + /* calculate the 'number' of the cycle */ + cycle= ((float)side * (evaltime - ofs) / cycdx); + + /* check that cyclic is still enabled for the specified time */ + if (cycles == 0) { + /* catch this case so that we don't exit when we have cycles=0 + * as this indicates infinite cycles... + */ + } + else if (cycle > (cycles+1)) { + /* we are too far away from range to evaluate + * TODO: but we should still hold last value... + */ + return evaltime; + } + + /* check if 'cyclic extrapolation', and thus calculate y-offset for this cycle */ + if (mode == FCM_EXTRAPOLATE_CYCLIC_OFFSET) { + cycyofs = (float)floor((evaltime - ofs) / cycdx); + cycyofs *= cycdy; + } + + /* calculate where in the cycle we are (overwrite evaltime to reflect this) */ + if ((mode == FCM_EXTRAPOLATE_MIRROR) && ((int)(cycle) % 2)) { + /* when 'mirror' option is used and cycle number is odd, this cycle is played in reverse + * - for 'before' extrapolation, we need to flip in a different way, otherwise values past + * then end of the curve get referenced (result of fmod will be negative, and with different phase) + */ + if (side < 0) + evaltime= (float)(prevkey[0] - fmod(evaltime-ofs, cycdx)); + else + evaltime= (float)(lastkey[0] - fmod(evaltime-ofs, cycdx)); + } + else { + /* the cycle is played normally... */ + evaltime= (float)(fmod(evaltime-ofs, cycdx) + ofs); + } + if (evaltime < ofs) evaltime += cycdx; + } + + /* store temp data if needed */ + if (mode == FCM_EXTRAPOLATE_CYCLIC_OFFSET) { + tFCMED_Cycles *edata; + + /* for now, this is just a float, but we could get more stuff... */ + fcm->edata= edata= MEM_callocN(sizeof(tFCMED_Cycles), "tFCMED_Cycles"); + edata->cycyofs= cycyofs; + } + + /* return the new frame to evaluate */ + return evaltime; +} + +static void fcm_cycles_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime) +{ + tFCMED_Cycles *edata= (tFCMED_Cycles *)fcm->edata; + + /* use temp data */ + if (edata) { + /* add cyclic offset - no need to check for now, otherwise the data wouldn't exist! */ + *cvalue += edata->cycyofs; + + /* free temp data */ + MEM_freeN(edata); + fcm->edata= NULL; + } +} + +static FModifierTypeInfo FMI_CYCLES = { + FMODIFIER_TYPE_CYCLES, /* type */ + sizeof(FMod_Cycles), /* size */ + FMI_TYPE_EXTRAPOLATION, /* action type */ + FMI_REQUIRES_ORIGINAL_DATA, /* requirements */ + "Cycles", /* name */ + "FMod_Cycles", /* struct name */ + NULL, /* free data */ + NULL, /* copy data */ + fcm_cycles_new_data, /* new data */ + NULL /*fcm_cycles_verify*/, /* verify */ + fcm_cycles_time, /* evaluate time */ + fcm_cycles_evaluate /* evaluate */ +}; + +/* Noise F-Curve Modifier --------------------------- */ + +static void fcm_noise_new_data (void *mdata) +{ + FMod_Noise *data= (FMod_Noise *)mdata; + + /* defaults */ + data->size= 1.0f; + data->strength= 1.0f; + data->phase= 1.0f; + data->depth = 0; + data->modification = FCM_NOISE_MODIF_REPLACE; +} + +static void fcm_noise_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime) +{ + FMod_Noise *data= (FMod_Noise *)fcm->data; + float noise; + + noise = BLI_turbulence(data->size, evaltime, data->phase, 0.f, data->depth); + + switch (data->modification) { + case FCM_NOISE_MODIF_ADD: + *cvalue= *cvalue + noise * data->strength; + break; + case FCM_NOISE_MODIF_SUBTRACT: + *cvalue= *cvalue - noise * data->strength; + break; + case FCM_NOISE_MODIF_MULTIPLY: + *cvalue= *cvalue * noise * data->strength; + break; + case FCM_NOISE_MODIF_REPLACE: + default: + *cvalue= *cvalue + (noise - 0.5f) * data->strength; + break; + } +} + +static FModifierTypeInfo FMI_NOISE = { + FMODIFIER_TYPE_NOISE, /* type */ + sizeof(FMod_Noise), /* size */ + FMI_TYPE_REPLACE_VALUES, /* action type */ + 0, /* requirements */ + "Noise", /* name */ + "FMod_Noise", /* struct name */ + NULL, /* free data */ + NULL, /* copy data */ + fcm_noise_new_data, /* new data */ + NULL /*fcm_noise_verify*/, /* verify */ + NULL, /* evaluate time */ + fcm_noise_evaluate /* evaluate */ +}; + +/* Filter F-Curve Modifier --------------------------- */ + +#if 0 // XXX not yet implemented +static FModifierTypeInfo FMI_FILTER = { + FMODIFIER_TYPE_FILTER, /* type */ + sizeof(FMod_Filter), /* size */ + FMI_TYPE_REPLACE_VALUES, /* action type */ + 0, /* requirements */ + "Filter", /* name */ + "FMod_Filter", /* struct name */ + NULL, /* free data */ + NULL, /* copy data */ + NULL, /* new data */ + NULL /*fcm_filter_verify*/, /* verify */ + NULL, /* evlauate time */ + fcm_filter_evaluate /* evaluate */ +}; +#endif // XXX not yet implemented + + +/* Python F-Curve Modifier --------------------------- */ + +static void fcm_python_free (FModifier *fcm) +{ + FMod_Python *data= (FMod_Python *)fcm->data; + + /* id-properties */ + IDP_FreeProperty(data->prop); + MEM_freeN(data->prop); +} + +static void fcm_python_new_data (void *mdata) +{ + FMod_Python *data= (FMod_Python *)mdata; + + /* everything should be set correctly by calloc, except for the prop->type constant.*/ + data->prop = MEM_callocN(sizeof(IDProperty), "PyFModifierProps"); + data->prop->type = IDP_GROUP; +} + +static void fcm_python_copy (FModifier *fcm, FModifier *src) +{ + FMod_Python *pymod = (FMod_Python *)fcm->data; + FMod_Python *opymod = (FMod_Python *)src->data; + + pymod->prop = IDP_CopyProperty(opymod->prop); +} + +static void fcm_python_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime) +{ +#ifndef DISABLE_PYTHON + //FMod_Python *data= (FMod_Python *)fcm->data; + + /* FIXME... need to implement this modifier... + * It will need it execute a script using the custom properties + */ +#endif /* DISABLE_PYTHON */ +} + +static FModifierTypeInfo FMI_PYTHON = { + FMODIFIER_TYPE_PYTHON, /* type */ + sizeof(FMod_Python), /* size */ + FMI_TYPE_GENERATE_CURVE, /* action type */ + FMI_REQUIRES_RUNTIME_CHECK, /* requirements */ + "Python", /* name */ + "FMod_Python", /* struct name */ + fcm_python_free, /* free data */ + fcm_python_copy, /* copy data */ + fcm_python_new_data, /* new data */ + NULL /*fcm_python_verify*/, /* verify */ + NULL /*fcm_python_time*/, /* evaluate time */ + fcm_python_evaluate /* evaluate */ +}; + + +/* Limits F-Curve Modifier --------------------------- */ + +static float fcm_limits_time (FCurve *fcu, FModifier *fcm, float cvalue, float evaltime) +{ + FMod_Limits *data= (FMod_Limits *)fcm->data; + + /* check for the time limits */ + if ((data->flag & FCM_LIMIT_XMIN) && (evaltime < data->rect.xmin)) + return data->rect.xmin; + if ((data->flag & FCM_LIMIT_XMAX) && (evaltime > data->rect.xmax)) + return data->rect.xmax; + + /* modifier doesn't change time */ + return evaltime; +} + +static void fcm_limits_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime) +{ + FMod_Limits *data= (FMod_Limits *)fcm->data; + + /* value limits now */ + if ((data->flag & FCM_LIMIT_YMIN) && (*cvalue < data->rect.ymin)) + *cvalue= data->rect.ymin; + if ((data->flag & FCM_LIMIT_YMAX) && (*cvalue > data->rect.ymax)) + *cvalue= data->rect.ymax; +} + +static FModifierTypeInfo FMI_LIMITS = { + FMODIFIER_TYPE_LIMITS, /* type */ + sizeof(FMod_Limits), /* size */ + FMI_TYPE_GENERATE_CURVE, /* action type */ /* XXX... err... */ + FMI_REQUIRES_RUNTIME_CHECK, /* requirements */ + "Limits", /* name */ + "FMod_Limits", /* struct name */ + NULL, /* free data */ + NULL, /* copy data */ + NULL, /* new data */ + NULL, /* verify */ + fcm_limits_time, /* evaluate time */ + fcm_limits_evaluate /* evaluate */ +}; + +/* F-Curve Modifier API --------------------------- */ +/* All of the F-Curve Modifier api functions use FModifierTypeInfo structs to carry out + * and operations that involve F-Curve modifier specific code. + */ + +/* These globals only ever get directly accessed in this file */ +static FModifierTypeInfo *fmodifiersTypeInfo[FMODIFIER_NUM_TYPES]; +static short FMI_INIT= 1; /* when non-zero, the list needs to be updated */ + +/* This function only gets called when FMI_INIT is non-zero */ +static void fmods_init_typeinfo () +{ + fmodifiersTypeInfo[0]= NULL; /* 'Null' F-Curve Modifier */ + fmodifiersTypeInfo[1]= &FMI_GENERATOR; /* Generator F-Curve Modifier */ + fmodifiersTypeInfo[2]= &FMI_FN_GENERATOR; /* Built-In Function Generator F-Curve Modifier */ + fmodifiersTypeInfo[3]= &FMI_ENVELOPE; /* Envelope F-Curve Modifier */ + fmodifiersTypeInfo[4]= &FMI_CYCLES; /* Cycles F-Curve Modifier */ + fmodifiersTypeInfo[5]= &FMI_NOISE; /* Apply-Noise F-Curve Modifier */ + fmodifiersTypeInfo[6]= NULL/*&FMI_FILTER*/; /* Filter F-Curve Modifier */ // XXX unimplemented + fmodifiersTypeInfo[7]= &FMI_PYTHON; /* Custom Python F-Curve Modifier */ + fmodifiersTypeInfo[8]= &FMI_LIMITS; /* Limits F-Curve Modifier */ +} + +/* This function should be used for getting the appropriate type-info when only + * a F-Curve modifier type is known + */ +FModifierTypeInfo *get_fmodifier_typeinfo (int type) +{ + /* initialise the type-info list? */ + if (FMI_INIT) { + fmods_init_typeinfo(); + FMI_INIT = 0; + } + + /* only return for valid types */ + if ( (type >= FMODIFIER_TYPE_NULL) && + (type <= FMODIFIER_NUM_TYPES ) ) + { + /* there shouldn't be any segfaults here... */ + return fmodifiersTypeInfo[type]; + } + else { + printf("No valid F-Curve Modifier type-info data available. Type = %i \n", type); + } + + return NULL; +} + +/* This function should always be used to get the appropriate type-info, as it + * has checks which prevent segfaults in some weird cases. + */ +FModifierTypeInfo *fmodifier_get_typeinfo (FModifier *fcm) +{ + /* only return typeinfo for valid modifiers */ + if (fcm) + return get_fmodifier_typeinfo(fcm->type); + else + return NULL; +} + +/* API --------------------------- */ + +/* Add a new F-Curve Modifier to the given F-Curve of a certain type */ +FModifier *add_fmodifier (ListBase *modifiers, int type) +{ + FModifierTypeInfo *fmi= get_fmodifier_typeinfo(type); + FModifier *fcm; + + /* sanity checks */ + if ELEM(NULL, modifiers, fmi) + return NULL; + + /* special checks for whether modifier can be added */ + if ((modifiers->first) && (type == FMODIFIER_TYPE_CYCLES)) { + /* cycles modifier must be first in stack, so for now, don't add if it can't be */ + // TODO: perhaps there is some better way, but for now, + printf("Error: Cannot add 'Cycles' modifier to F-Curve, as 'Cycles' modifier can only be first in stack. \n"); + return NULL; + } + + /* add modifier itself */ + fcm= MEM_callocN(sizeof(FModifier), "F-Curve Modifier"); + fcm->type = type; + fcm->flag = FMODIFIER_FLAG_EXPANDED; + BLI_addtail(modifiers, fcm); + + /* add modifier's data */ + fcm->data= MEM_callocN(fmi->size, fmi->structName); + + /* init custom settings if necessary */ + if (fmi->new_data) + fmi->new_data(fcm->data); + + /* return modifier for further editing */ + return fcm; +} + +/* Duplicate all of the F-Modifiers in the Modifier stacks */ +void copy_fmodifiers (ListBase *dst, ListBase *src) +{ + FModifier *fcm, *srcfcm; + + if ELEM(NULL, dst, src) + return; + + dst->first= dst->last= NULL; + BLI_duplicatelist(dst, src); + + for (fcm=dst->first, srcfcm=src->first; fcm && srcfcm; srcfcm=srcfcm->next, fcm=fcm->next) { + FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm); + + /* make a new copy of the F-Modifier's data */ + fcm->data = MEM_dupallocN(fcm->data); + + /* only do specific constraints if required */ + if (fmi && fmi->copy_data) + fmi->copy_data(fcm, srcfcm); + } +} + +/* Remove and free the given F-Modifier from the given stack */ +void remove_fmodifier (ListBase *modifiers, FModifier *fcm) +{ + FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm); + + /* sanity check */ + if (fcm == NULL) + return; + + /* free modifier's special data (stored inside fcm->data) */ + if (fcm->data) { + if (fmi && fmi->free_data) + fmi->free_data(fcm); + + /* free modifier's data (fcm->data) */ + MEM_freeN(fcm->data); + } + + /* remove modifier from stack */ + if (modifiers) + BLI_freelinkN(modifiers, fcm); + else { + // XXX this case can probably be removed some day, as it shouldn't happen... + printf("remove_fmodifier() - no modifier stack given \n"); + MEM_freeN(fcm); + } +} + +/* Remove all of a given F-Curve's modifiers */ +void free_fmodifiers (ListBase *modifiers) +{ + FModifier *fcm, *fmn; + + /* sanity check */ + if (modifiers == NULL) + return; + + /* free each modifier in order - modifier is unlinked from list and freed */ + for (fcm= modifiers->first; fcm; fcm= fmn) { + fmn= fcm->next; + remove_fmodifier(modifiers, fcm); + } +} + +/* Find the active F-Modifier */ +FModifier *find_active_fmodifier (ListBase *modifiers) +{ + FModifier *fcm; + + /* sanity checks */ + if ELEM(NULL, modifiers, modifiers->first) + return NULL; + + /* loop over modifiers until 'active' one is found */ + for (fcm= modifiers->first; fcm; fcm= fcm->next) { + if (fcm->flag & FMODIFIER_FLAG_ACTIVE) + return fcm; + } + + /* no modifier is active */ + return NULL; +} + +/* Set the active F-Modifier */ +void set_active_fmodifier (ListBase *modifiers, FModifier *fcm) +{ + FModifier *fm; + + /* sanity checks */ + if ELEM(NULL, modifiers, modifiers->first) + return; + + /* deactivate all, and set current one active */ + for (fm= modifiers->first; fm; fm= fm->next) + fm->flag &= ~FMODIFIER_FLAG_ACTIVE; + + /* make given modifier active */ + if (fcm) + fcm->flag |= FMODIFIER_FLAG_ACTIVE; +} + +/* Do we have any modifiers which match certain criteria + * - mtype - type of modifier (if 0, doesn't matter) + * - acttype - type of action to perform (if -1, doesn't matter) + */ +short list_has_suitable_fmodifier (ListBase *modifiers, int mtype, short acttype) +{ + FModifier *fcm; + + /* if there are no specific filtering criteria, just skip */ + if ((mtype == 0) && (acttype == 0)) + return (modifiers && modifiers->first); + + /* sanity checks */ + if ELEM(NULL, modifiers, modifiers->first) + return 0; + + /* find the first mdifier fitting these criteria */ + for (fcm= modifiers->first; fcm; fcm= fcm->next) { + FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm); + short mOk=1, aOk=1; /* by default 1, so that when only one test, won't fail */ + + /* check if applicable ones are fullfilled */ + if (mtype) + mOk= (fcm->type == mtype); + if (acttype > -1) + aOk= (fmi->acttype == acttype); + + /* if both are ok, we've found a hit */ + if (mOk && aOk) + return 1; + } + + /* no matches */ + return 0; +} + +/* Evaluation API --------------------------- */ + +/* evaluate time modifications imposed by some F-Curve Modifiers + * - this step acts as an optimisation to prevent the F-Curve stack being evaluated + * several times by modifiers requesting the time be modified, as the final result + * would have required using the modified time + * - modifiers only ever recieve the unmodified time, as subsequent modifiers should be + * working on the 'global' result of the modified curve, not some localised segment, + * so nevaltime gets set to whatever the last time-modifying modifier likes... + * - we start from the end of the stack, as only the last one matters for now + */ +float evaluate_time_fmodifiers (ListBase *modifiers, FCurve *fcu, float cvalue, float evaltime) +{ + FModifier *fcm; + float m_evaltime= evaltime; + + /* sanity checks */ + if ELEM(NULL, modifiers, modifiers->last) + return evaltime; + + /* find the first modifier from end of stack that modifies time, and calculate the time the modifier + * would calculate time at + */ + for (fcm= modifiers->last; fcm; fcm= fcm->prev) { + FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm); + + /* only evaluate if there's a callback for this */ + // TODO: implement the 'influence' control feature... + if (fmi && fmi->evaluate_modifier_time) { + if ((fcm->flag & (FMODIFIER_FLAG_DISABLED|FMODIFIER_FLAG_MUTED)) == 0) + m_evaltime= fmi->evaluate_modifier_time(fcu, fcm, cvalue, evaltime); + break; + } + } + + /* return the modified evaltime */ + return m_evaltime; +} + +/* Evalautes the given set of F-Curve Modifiers using the given data + * Should only be called after evaluate_time_fmodifiers() has been called... + */ +void evaluate_value_fmodifiers (ListBase *modifiers, FCurve *fcu, float *cvalue, float evaltime) +{ + FModifier *fcm; + + /* sanity checks */ + if ELEM(NULL, modifiers, modifiers->first) + return; + + /* evaluate modifiers */ + for (fcm= modifiers->first; fcm; fcm= fcm->next) { + FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm); + + /* only evaluate if there's a callback for this */ + // TODO: implement the 'influence' control feature... + if (fmi && fmi->evaluate_modifier) { + if ((fcm->flag & (FMODIFIER_FLAG_DISABLED|FMODIFIER_FLAG_MUTED)) == 0) + fmi->evaluate_modifier(fcu, fcm, cvalue, evaltime); + } + } +} + +/* ---------- */ + +/* Bake modifiers for given F-Curve to curve sample data, in the frame range defined + * by start and end (inclusive). + */ +void fcurve_bake_modifiers (FCurve *fcu, int start, int end) +{ + ChannelDriver *driver; + + /* sanity checks */ + // TODO: make these tests report errors using reports not printf's + if ELEM(NULL, fcu, fcu->modifiers.first) { + printf("Error: No F-Curve with F-Curve Modifiers to Bake\n"); + return; + } + + /* temporarily, disable driver while we sample, so that they don't influence the outcome */ + driver= fcu->driver; + fcu->driver= NULL; + + /* bake the modifiers, by sampling the curve at each frame */ + fcurve_store_samples(fcu, NULL, start, end, fcurve_samplingcb_evalcurve); + + /* free the modifiers now */ + free_fmodifiers(&fcu->modifiers); + + /* restore driver */ + fcu->driver= driver; +} diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c index 968a0e68fb9..c3c5483574e 100644 --- a/source/blender/blenkernel/intern/ipo.c +++ b/source/blender/blenkernel/intern/ipo.c @@ -1153,7 +1153,7 @@ static void icu_to_fcurves (ListBase *groups, ListBase *list, IpoCurve *icu, cha /* Add a new FModifier (Cyclic) instead of setting extend value * as that's the new equivilant of that option. */ - FModifier *fcm= fcurve_add_modifier(fcu, FMODIFIER_TYPE_CYCLES); + FModifier *fcm= add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_CYCLES); FMod_Cycles *data= (FMod_Cycles *)fcm->data; /* if 'offset' one is in use, set appropriate settings */ diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index 2b95584dc25..14e658b3903 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -69,8 +69,6 @@ // TODO: with things like transitions, should these get freed too? Maybe better as a UI tool void free_nlastrip (ListBase *strips, NlaStrip *strip) { - FModifier *fcm, *fmn; - /* sanity checks */ if (strip == NULL) return; @@ -86,13 +84,8 @@ void free_nlastrip (ListBase *strips, NlaStrip *strip) /* free own F-Curves */ free_fcurves(&strip->fcurves); - /* free F-Modifiers */ - for (fcm= strip->modifiers.first; fcm; fcm= fmn) { - fmn= fcm->next; - - BLI_remlink(&strip->modifiers, fcm); - fcurve_remove_modifier(NULL, fcm); - } + /* free own F-Modifiers */ + free_fmodifiers(&strip->modifiers); /* free the strip itself */ if (strips) @@ -167,7 +160,7 @@ NlaStrip *copy_nlastrip (NlaStrip *strip) /* copy F-Curves and modifiers */ copy_fcurves(&strip_d->fcurves, &strip->fcurves); - fcurve_copy_modifiers(&strip_d->modifiers, &strip->modifiers); + copy_fmodifiers(&strip_d->modifiers, &strip->modifiers); /* return the strip */ return strip_d; -- cgit v1.2.3 From c7bd0d12484d7abf18f74c2ed8405ad6f5888d99 Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Thu, 2 Jul 2009 11:23:19 +0000 Subject: 2.5 More toolbar functionality for workflow review. - Split the region in two parts, bottom has the Tool Properties, the top part shows 2 panels, one for python defined tools, other for a "tool shelf" which (later) will get saved in files. - Added a full context driven framework for this toolbar, showing the tools depending on 3D window 'mode'. Both python defined tools as the shelf respect this. So - for example - you will see different tools in editmode mesh, as in vertex paint mode, etc. - First template for the python tools will be committed after this commit; it has placeholder tools to just show/test functioning. NOTE: if you had saved a layout that shows tools region, open/close it once to get the new region created for properties. TODO: - Moving paint properties to tool settings - Test a layout with horizontal toolbar (without properties) - Bring back floating panels, and put tool-properties here. (as option) --- source/blender/blenkernel/BKE_screen.h | 5 ++++- source/blender/blenkernel/intern/screen.c | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h index 750f4fba7e6..be625fb856a 100644 --- a/source/blender/blenkernel/BKE_screen.h +++ b/source/blender/blenkernel/BKE_screen.h @@ -91,6 +91,9 @@ typedef struct SpaceType { /* region type definitions */ ListBase regiontypes; + /* tool shelf definitions */ + ListBase toolshelf; + /* read and write... */ /* default keymaps to add */ @@ -139,7 +142,7 @@ typedef struct ARegionType { /* menu type definitions */ ListBase menutypes; - + /* hardcoded constraints, smaller than these values region is not visible */ int minsizex, minsizey; /* default keymaps to add */ diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c index e25e4be90c8..4b6eddf60d0 100644 --- a/source/blender/blenkernel/intern/screen.c +++ b/source/blender/blenkernel/intern/screen.c @@ -78,6 +78,8 @@ static void spacetype_free(SpaceType *st) } BLI_freelistN(&st->regiontypes); + BLI_freelistN(&st->toolshelf); + } void BKE_spacetypes_free(void) -- cgit v1.2.3 From 093ff8202ced6391a2ef657abe42615672146954 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Thu, 2 Jul 2009 19:41:31 +0000 Subject: 2.5: Physics Buttons All kinds of changes to get it ready for UI layouts. This means RNA and operators should be working correct, but most buttons are still not actually there yet. * Added near empty soft body, fluid, field and collision panels, tweaks to cloth panels. * Fluid bake works, but without escape or showing any progress. * Fluid/Softbody/Cloth/Collision can now be both added as modifiers or in the physics panels. * Missing: fields & soft body for particles. * Missing: proper updating softbodies, guess this code still needs updates after pointcache refactor? --- source/blender/blenkernel/BKE_effect.h | 2 ++ source/blender/blenkernel/BKE_fluidsim.h | 44 ++++++++++++++++++----------- source/blender/blenkernel/BKE_modifier.h | 5 +++- source/blender/blenkernel/intern/context.c | 2 +- source/blender/blenkernel/intern/effect.c | 16 +++++++++++ source/blender/blenkernel/intern/fluidsim.c | 19 ++++++++++++- source/blender/blenkernel/intern/modifier.c | 13 ++++++--- 7 files changed, 77 insertions(+), 24 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_effect.h b/source/blender/blenkernel/BKE_effect.h index fd065978800..e21e83bf5cf 100644 --- a/source/blender/blenkernel/BKE_effect.h +++ b/source/blender/blenkernel/BKE_effect.h @@ -41,6 +41,8 @@ struct Particle; struct Group; struct RNG; +struct PartDeflect *object_add_collision_fields(void); + typedef struct pEffectorCache { struct pEffectorCache *next, *prev; Object *ob; diff --git a/source/blender/blenkernel/BKE_fluidsim.h b/source/blender/blenkernel/BKE_fluidsim.h index 93358fcf7e8..145ae48e732 100644 --- a/source/blender/blenkernel/BKE_fluidsim.h +++ b/source/blender/blenkernel/BKE_fluidsim.h @@ -1,6 +1,5 @@ /** - * BKE_fluidsim.h - * + * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** * @@ -28,29 +27,40 @@ * ***** END GPL LICENSE BLOCK ***** */ -#include "DNA_modifier_types.h" -#include "DNA_object_fluidsim.h" // N_T -#include "DNA_object_types.h" +#ifndef BKE_FLUIDSIM_H +#define BKE_FLUIDSIM_H -#include "BKE_DerivedMesh.h" +struct Object; +struct Scene; +struct FluidsimModifierData; +struct DerivedMesh; +struct MVert; /* old interface */ -FluidsimSettings *fluidsimSettingsNew(Object *srcob); - -void initElbeemMesh(Scene *scene, Object *ob, int *numVertices, float **vertices, int *numTriangles, int **triangles, int useGlobalCoords, int modifierIndex); +struct FluidsimSettings *fluidsimSettingsNew(struct Object *srcob); +void initElbeemMesh(struct Scene *scene, struct Object *ob, + int *numVertices, float **vertices, + int *numTriangles, int **triangles, + int useGlobalCoords, int modifierIndex); /* new fluid-modifier interface */ -void fluidsim_init(FluidsimModifierData *fluidmd); -void fluidsim_free(FluidsimModifierData *fluidmd); +void fluidsim_init(struct FluidsimModifierData *fluidmd); +void fluidsim_free(struct FluidsimModifierData *fluidmd); -DerivedMesh *fluidsim_read_cache(Object *ob, DerivedMesh *orgdm, FluidsimModifierData *fluidmd, int framenr, int useRenderParams); -void fluidsim_read_vel_cache(FluidsimModifierData *fluidmd, DerivedMesh *dm, char *filename); -DerivedMesh *fluidsimModifier_do(FluidsimModifierData *fluidmd, Scene *scene, Object *ob, DerivedMesh *dm, int useRenderParams, int isFinalCalc); +struct DerivedMesh *fluidsim_read_cache(struct Object *ob, struct DerivedMesh *orgdm, + struct FluidsimModifierData *fluidmd, int framenr, int useRenderParams); +void fluidsim_read_vel_cache(struct FluidsimModifierData *fluidmd, struct DerivedMesh *dm, + char *filename); +struct DerivedMesh *fluidsimModifier_do(struct FluidsimModifierData *fluidmd, + struct Scene *scene, struct Object *ob, struct DerivedMesh *dm, + int useRenderParams, int isFinalCalc); -// get bounding box of mesh -void fluid_get_bb(MVert *mvert, int totvert, float obmat[][4], - /*RET*/ float start[3], /*RET*/ float size[3] ); +/* bounding box & memory estimate */ +void fluid_get_bb(struct MVert *mvert, int totvert, float obmat[][4], + float start[3], float size[3]); +void fluid_estimate_memory(struct Object *ob, struct FluidsimSettings *fss, char *value); +#endif diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h index 4065cbb7007..144ed3bc624 100644 --- a/source/blender/blenkernel/BKE_modifier.h +++ b/source/blender/blenkernel/BKE_modifier.h @@ -62,7 +62,7 @@ typedef enum { * 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 + eModifierTypeType_DeformOrConstruct, } ModifierTypeType; typedef enum { @@ -87,6 +87,9 @@ typedef enum { /* For modifiers that support pointcache, so we can check to see if it has files we need to deal with */ eModifierTypeFlag_UsesPointCache = (1<<6), + + /* For physics modifiers, max one per type */ + eModifierTypeFlag_Single = (1<<7) } ModifierTypeFlag; typedef void (*ObjectWalkFunc)(void *userData, struct Object *ob, struct Object **obpoin); diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c index fbad585d9b7..4a68d90a4ed 100644 --- a/source/blender/blenkernel/intern/context.c +++ b/source/blender/blenkernel/intern/context.c @@ -378,7 +378,7 @@ PointerRNA CTX_data_pointer_get_type(const bContext *C, const char *member, Stru { PointerRNA ptr = CTX_data_pointer_get(C, member); - if(ptr.data && ptr.type == type) + if(ptr.data && RNA_struct_is_a(ptr.type, type)) return ptr; return PointerRNA_NULL; diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index eaa2d541638..553fdfe530e 100644 --- a/source/blender/blenkernel/intern/effect.c +++ b/source/blender/blenkernel/intern/effect.c @@ -56,6 +56,8 @@ #include "BLI_jitter.h" #include "BLI_rand.h" +#include "PIL_time.h" + #include "BKE_action.h" #include "BKE_anim.h" /* needed for where_on_path */ #include "BKE_armature.h" @@ -93,6 +95,20 @@ //XXX #include "BIF_screen.h" +PartDeflect *object_add_collision_fields(void) +{ + PartDeflect *pd; + + pd= MEM_callocN(sizeof(PartDeflect), "PartDeflect"); + + pd->pdef_sbdamp = 0.1f; + pd->pdef_sbift = 0.2f; + pd->pdef_sboft = 0.02f; + pd->seed = ((unsigned int)(ceil(PIL_check_seconds_timer()))+1) % 128; + + return pd; +} + /* temporal struct, used for reading return of mesh_get_mapped_verts_nors() */ typedef struct VeNoCo { diff --git a/source/blender/blenkernel/intern/fluidsim.c b/source/blender/blenkernel/intern/fluidsim.c index 54008185f72..6eba64cf33d 100644 --- a/source/blender/blenkernel/intern/fluidsim.c +++ b/source/blender/blenkernel/intern/fluidsim.c @@ -34,7 +34,9 @@ #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" +#include "DNA_object_fluidsim.h" #include "DNA_object_force.h" // for pointcache +#include "DNA_object_types.h" #include "DNA_particle_types.h" #include "DNA_scene_types.h" // N_T @@ -78,7 +80,7 @@ void fluidsim_init(FluidsimModifierData *fluidmd) if(!fss) return; - fss->type = OB_FSBND_NOSLIP; + fss->type = OB_FLUIDSIM_ENABLE; fss->show_advancedoptions = 0; fss->resolutionxyz = 50; @@ -657,5 +659,20 @@ void initElbeemMesh(struct Scene *scene, struct Object *ob, dm->release(dm); } +void fluid_estimate_memory(Object *ob, FluidsimSettings *fss, char *value) +{ + Mesh *mesh; + + value[0]= '\0'; + + if(ob->type == OB_MESH) { + /* use mesh bounding box and object scaling */ + mesh= ob->data; + + fluid_get_bb(mesh->mvert, mesh->totvert, ob->obmat, fss->bbStart, fss->bbSize); + elbeemEstimateMemreq(fss->resolutionxyz, fss->bbSize[0],fss->bbSize[1],fss->bbSize[2], fss->maxRefine, value); + } +} + #endif // DISABLE_ELBEEM diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 80a9f173d6a..9ecf3a32c2b 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -63,6 +63,7 @@ #include "DNA_meshdata_types.h" #include "DNA_modifier_types.h" #include "DNA_object_types.h" +#include "DNA_object_fluidsim.h" #include "DNA_object_force.h" #include "DNA_particle_types.h" #include "DNA_scene_types.h" @@ -8387,7 +8388,8 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) mti = INIT_TYPE(Softbody); mti->type = eModifierTypeType_OnlyDeform; mti->flags = eModifierTypeFlag_AcceptsCVs - | eModifierTypeFlag_RequiresOriginalData; + | eModifierTypeFlag_RequiresOriginalData + | eModifierTypeFlag_Single; mti->deformVerts = softbodyModifier_deformVerts; mti->dependsOnTime = softbodyModifier_dependsOnTime; @@ -8395,7 +8397,8 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) mti->type = eModifierTypeType_Nonconstructive; mti->initData = clothModifier_initData; mti->flags = eModifierTypeFlag_AcceptsMesh - | eModifierTypeFlag_UsesPointCache; + | eModifierTypeFlag_UsesPointCache + | eModifierTypeFlag_Single; mti->dependsOnTime = clothModifier_dependsOnTime; mti->freeData = clothModifier_freeData; mti->requiredDataMask = clothModifier_requiredDataMask; @@ -8406,7 +8409,8 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) mti = INIT_TYPE(Collision); mti->type = eModifierTypeType_OnlyDeform; mti->initData = collisionModifier_initData; - mti->flags = eModifierTypeFlag_AcceptsMesh; + mti->flags = eModifierTypeFlag_AcceptsMesh + | eModifierTypeFlag_Single; mti->dependsOnTime = collisionModifier_dependsOnTime; mti->freeData = collisionModifier_freeData; mti->deformVerts = collisionModifier_deformVerts; @@ -8489,7 +8493,8 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) mti = INIT_TYPE(Fluidsim); mti->type = eModifierTypeType_Nonconstructive - | eModifierTypeFlag_RequiresOriginalData; + | eModifierTypeFlag_RequiresOriginalData + | eModifierTypeFlag_Single; mti->flags = eModifierTypeFlag_AcceptsMesh; mti->initData = fluidsimModifier_initData; mti->freeData = fluidsimModifier_freeData; -- cgit v1.2.3 From 28d371d1178642e17f5dfc300f1500a132ce7149 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 3 Jul 2009 01:10:46 +0000 Subject: NLA SoC: Assorted fixes * Made NLA Editing functions more aware of transitions. - A transition can only be added between a pair of action-clips. Previous, two transitions could be added next to each other, which has undefined behaviour - Deleting a strip with transition(s) on either side will remove the transitions too. Feedback welcome on this - The 'type' setting for NLA-Strips is no longer editable. This was dangerous as it could result in transitions with undefined behaviour (though nothing would happen). * Menus for adding F-Modifiers now only show relevant modifiers (i.e. 'Invalid' is not included in the list, and 'Cycles' doesn't need to be shown for NLA since we've got repeat) * Function Generator and Noise F-Modifiers now have complete GUI's. A few settings were missed during the porting process. * F-Modifier buttons now have their source-ID's included in the RNA Pointers used. This didn't get them animateable directly, but is a step closer. --- source/blender/blenkernel/BKE_fcurve.h | 33 +++++++++++++++++++++++++++------ source/blender/blenkernel/intern/nla.c | 8 ++++---- 2 files changed, 31 insertions(+), 10 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h index cfc4e9077f6..4dcb08dc0df 100644 --- a/source/blender/blenkernel/BKE_fcurve.h +++ b/source/blender/blenkernel/BKE_fcurve.h @@ -1,12 +1,33 @@ -/* Testing code for new animation system in 2.5 - * Copyright 2009, Joshua Leung +/** + * $Id$ + * + * ***** 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) 2009 Blender Foundation, Joshua Leung + * All rights reserved. + * + * Contributor(s): Joshua Leung (full recode) + * + * ***** END GPL LICENSE BLOCK ***** */ #ifndef BKE_FCURVE_H #define BKE_FCURVE_H -//struct ListBase; - struct FCurve; struct FModifier; struct ChannelDriver; @@ -54,8 +75,8 @@ typedef struct FModifierTypeInfo { short size; /* size in bytes of the struct */ short acttype; /* eFMI_Action_Types */ short requires; /* eFMI_Requirement_Flags */ - char name[32]; /* name of modifier in interface */ - char structName[32]; /* name of struct for SDNA */ + char name[64]; /* name of modifier in interface */ + char structName[64]; /* name of struct for SDNA */ /* data management function pointers - special handling */ /* free any data that is allocated separately (optional) */ diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index 14e658b3903..d554fbbabc1 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -66,7 +66,6 @@ /* Remove the given NLA strip from the NLA track it occupies, free the strip's data, * and the strip itself. */ -// TODO: with things like transitions, should these get freed too? Maybe better as a UI tool void free_nlastrip (ListBase *strips, NlaStrip *strip) { /* sanity checks */ @@ -793,6 +792,7 @@ void BKE_nla_action_pushdown (AnimData *adt) /* not first, so extend mode can only be NLASTRIP_EXTEND_HOLD_FORWARD not NLASTRIP_EXTEND_HOLD, * so that it doesn't override strips in previous tracks */ + // FIXME: this needs to be more automated, since user can rearrange strips strip->extendmode= NLASTRIP_EXTEND_HOLD_FORWARD; } } @@ -844,7 +844,7 @@ short BKE_nla_tweakmode_enter (AnimData *adt) if (strip->act == activeStrip->act) strip->flag |= NLASTRIP_FLAG_TWEAKUSER; else - strip->flag &= ~NLASTRIP_FLAG_TWEAKUSER; // XXX probably don't need to clear this... + strip->flag &= ~NLASTRIP_FLAG_TWEAKUSER; } } @@ -887,8 +887,8 @@ void BKE_nla_tweakmode_exit (AnimData *adt) // TODO: need to sync the user-strip with the new state of the action! - /* for all NLA-tracks, clear the 'disabled' flag - * for all NLA-strips, clear the 'tweak-user' flag + /* for all Tracks, clear the 'disabled' flag + * for all Strips, clear the 'tweak-user' flag */ for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) { nlt->flag &= ~NLATRACK_DISABLED; -- cgit v1.2.3 From 66efea5e2d94ec7296efbe03ddeb7c6c4878c9ab Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 3 Jul 2009 04:48:44 +0000 Subject: NLA SoC: Toggle for 'Editing in Place' The 'pin' icon beside the name of the active Action when tweaking some strip's action can be used to toggle between editing the Action's keyframes in 'mapped' time or in 'un-mapped' time. --- source/blender/blenkernel/intern/nla.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index d554fbbabc1..1244b2900fd 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -458,8 +458,9 @@ float BKE_nla_tweakedit_remap (AnimData *adt, float cframe, short mode) /* sanity checks * - obviously we've got to have some starting data * - when not in tweakmode, the active Action does not have any scaling applied :) + * - when in tweakmode, if the no-mapping flag is set, do not map */ - if ((adt == NULL) || (adt->flag & ADT_NLA_EDIT_ON)==0) + if ((adt == NULL) || (adt->flag & ADT_NLA_EDIT_ON)==0 || (adt->flag & ADT_NLA_EDIT_NOMAP)) return cframe; /* if the active-strip info has been stored already, access this, otherwise look this up -- cgit v1.2.3 From b8042f535c43c371d6bdb2fe44d0560d5802083c Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 3 Jul 2009 10:28:10 +0000 Subject: NLA SoC: Muting and Graph-Editor Curve visibility for (Action) Groups Groups (the Action variety) can now be muted, and also be set to not be drawn in the Graph Editor. These settings get applied to all the F-Curves within the group, overriding any settings individual F-Curves might have, allowing users to quickly mute or hide groups of curves without having to go through clicking on all of them. Also, added a flag that can be used to set the curve visiblity on AnimData level too. This will be enabled in a future commit. --- source/blender/blenkernel/intern/anim_sys.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 4c0c30fe5c1..9befe9dc9cb 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -492,11 +492,14 @@ static void animsys_evaluate_fcurves (PointerRNA *ptr, ListBase *list, AnimMappe /* calculate then execute each curve */ for (fcu= list->first; fcu; fcu= fcu->next) { - /* check if this curve should be skipped */ - if ((fcu->flag & (FCURVE_MUTED|FCURVE_DISABLED)) == 0) - { - calculate_fcurve(fcu, ctime); - animsys_execute_fcurve(ptr, remap, fcu); + /* check if this F-Curve doesn't belong to a muted group */ + if ((fcu->grp == NULL) || (fcu->grp->flag & AGRP_MUTED)==0) { + /* check if this curve should be skipped */ + if ((fcu->flag & (FCURVE_MUTED|FCURVE_DISABLED)) == 0) + { + calculate_fcurve(fcu, ctime); + animsys_execute_fcurve(ptr, remap, fcu); + } } } } @@ -551,6 +554,10 @@ void animsys_evaluate_action_group (PointerRNA *ptr, bAction *act, bActionGroup if ELEM(NULL, act, agrp) return; if ((remap) && (remap->target != act)) remap= NULL; + /* if group is muted, don't evaluated any of the F-Curve */ + if (agrp->flag & AGRP_MUTED) + return; + /* calculate then execute each curve */ for (fcu= agrp->channels.first; (fcu) && (fcu->grp == agrp); fcu= fcu->next) { @@ -884,6 +891,8 @@ static void nlastrip_evaluate_actionclip (PointerRNA *ptr, ListBase *channels, N /* check if this curve should be skipped */ if (fcu->flag & (FCURVE_MUTED|FCURVE_DISABLED)) continue; + if ((fcu->grp) && (fcu->grp->flag & AGRP_MUTED)) + continue; /* evaluate the F-Curve's value for the time given in the strip * NOTE: we use the modified time here, since strip's F-Curve Modifiers are applied on top of this -- cgit v1.2.3 From 9f33496088e6373600641b8471fe487aa1587e75 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Fri, 3 Jul 2009 15:23:33 +0000 Subject: 2.5 * Lattices: properties editable, editmode operators, menus working again. As a bonus you can now edit u/v/w in editmode. * Shape Keys: some code cleanup, and added more buttons. The value/min/max buttons don't work correct yet though. * Fix issue with uv textures, vertex colors not being visible outside editmode, and a few other issue. Mesh.edit_mesh is now NULL when not in editmode. --- source/blender/blenkernel/intern/lattice.c | 105 ++++++++++++++++------------- 1 file changed, 57 insertions(+), 48 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c index 5cf52d09314..67d63d527cb 100644 --- a/source/blender/blenkernel/intern/lattice.c +++ b/source/blender/blenkernel/intern/lattice.c @@ -232,8 +232,8 @@ void free_lattice(Lattice *lt) if(lt->def) MEM_freeN(lt->def); if(lt->dvert) free_dverts(lt->dvert, lt->pntsu*lt->pntsv*lt->pntsw); if(lt->editlatt) { - if(lt->def) MEM_freeN(lt->def); - if(lt->dvert) free_dverts(lt->dvert, lt->pntsu*lt->pntsv*lt->pntsw); + if(lt->editlatt->def) MEM_freeN(lt->editlatt->def); + if(lt->editlatt->dvert) free_dverts(lt->editlatt->dvert, lt->pntsu*lt->pntsv*lt->pntsw); MEM_freeN(lt->editlatt); } } @@ -817,59 +817,68 @@ void outside_lattice(Lattice *lt) int u, v, w; float fac1, du=0.0, dv=0.0, dw=0.0; - bp= lt->def; + if(lt->flag & LT_OUTSIDE) { + bp= lt->def; - if(lt->pntsu>1) du= 1.0f/((float)lt->pntsu-1); - if(lt->pntsv>1) dv= 1.0f/((float)lt->pntsv-1); - if(lt->pntsw>1) dw= 1.0f/((float)lt->pntsw-1); - - for(w=0; wpntsw; w++) { - - for(v=0; vpntsv; v++) { - - for(u=0; upntsu; u++, bp++) { - if(u==0 || v==0 || w==0 || u==lt->pntsu-1 || v==lt->pntsv-1 || w==lt->pntsw-1); - else { - - bp->hide= 1; - bp->f1 &= ~SELECT; - - /* u extrema */ - bp1= latt_bp(lt, 0, v, w); - bp2= latt_bp(lt, lt->pntsu-1, v, w); - - fac1= du*u; - bp->vec[0]= (1.0f-fac1)*bp1->vec[0] + fac1*bp2->vec[0]; - bp->vec[1]= (1.0f-fac1)*bp1->vec[1] + fac1*bp2->vec[1]; - bp->vec[2]= (1.0f-fac1)*bp1->vec[2] + fac1*bp2->vec[2]; - - /* v extrema */ - bp1= latt_bp(lt, u, 0, w); - bp2= latt_bp(lt, u, lt->pntsv-1, w); - - fac1= dv*v; - bp->vec[0]+= (1.0f-fac1)*bp1->vec[0] + fac1*bp2->vec[0]; - bp->vec[1]+= (1.0f-fac1)*bp1->vec[1] + fac1*bp2->vec[1]; - bp->vec[2]+= (1.0f-fac1)*bp1->vec[2] + fac1*bp2->vec[2]; - - /* w extrema */ - bp1= latt_bp(lt, u, v, 0); - bp2= latt_bp(lt, u, v, lt->pntsw-1); - - fac1= dw*w; - bp->vec[0]+= (1.0f-fac1)*bp1->vec[0] + fac1*bp2->vec[0]; - bp->vec[1]+= (1.0f-fac1)*bp1->vec[1] + fac1*bp2->vec[1]; - bp->vec[2]+= (1.0f-fac1)*bp1->vec[2] + fac1*bp2->vec[2]; - - VecMulf(bp->vec, 0.3333333f); + if(lt->pntsu>1) du= 1.0f/((float)lt->pntsu-1); + if(lt->pntsv>1) dv= 1.0f/((float)lt->pntsv-1); + if(lt->pntsw>1) dw= 1.0f/((float)lt->pntsw-1); + + for(w=0; wpntsw; w++) { + + for(v=0; vpntsv; v++) { + + for(u=0; upntsu; u++, bp++) { + if(u==0 || v==0 || w==0 || u==lt->pntsu-1 || v==lt->pntsv-1 || w==lt->pntsw-1); + else { + bp->hide= 1; + bp->f1 &= ~SELECT; + + /* u extrema */ + bp1= latt_bp(lt, 0, v, w); + bp2= latt_bp(lt, lt->pntsu-1, v, w); + + fac1= du*u; + bp->vec[0]= (1.0f-fac1)*bp1->vec[0] + fac1*bp2->vec[0]; + bp->vec[1]= (1.0f-fac1)*bp1->vec[1] + fac1*bp2->vec[1]; + bp->vec[2]= (1.0f-fac1)*bp1->vec[2] + fac1*bp2->vec[2]; + + /* v extrema */ + bp1= latt_bp(lt, u, 0, w); + bp2= latt_bp(lt, u, lt->pntsv-1, w); + + fac1= dv*v; + bp->vec[0]+= (1.0f-fac1)*bp1->vec[0] + fac1*bp2->vec[0]; + bp->vec[1]+= (1.0f-fac1)*bp1->vec[1] + fac1*bp2->vec[1]; + bp->vec[2]+= (1.0f-fac1)*bp1->vec[2] + fac1*bp2->vec[2]; + + /* w extrema */ + bp1= latt_bp(lt, u, v, 0); + bp2= latt_bp(lt, u, v, lt->pntsw-1); + + fac1= dw*w; + bp->vec[0]+= (1.0f-fac1)*bp1->vec[0] + fac1*bp2->vec[0]; + bp->vec[1]+= (1.0f-fac1)*bp1->vec[1] + fac1*bp2->vec[1]; + bp->vec[2]+= (1.0f-fac1)*bp1->vec[2] + fac1*bp2->vec[2]; + + VecMulf(bp->vec, 0.3333333f); + + } } + } } - } - + else { + bp= lt->def; + + for(w=0; wpntsw; w++) + for(v=0; vpntsv; v++) + for(u=0; upntsu; u++, bp++) + bp->hide= 0; + } } float (*lattice_getVertexCos(struct Object *ob, int *numVerts_r))[3] -- cgit v1.2.3 From 36df48eef63e4bc629ffae6f9b7c300ba2fdb35d Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Fri, 3 Jul 2009 19:56:19 +0000 Subject: 2.5: * Fix crash in python with enum properties, and don't throw error if no matching identifier is found. This shouldn't happen, but it should break a python script either, which is not at fault. * Fix a wrong variable initialization in fluidsim. --- source/blender/blenkernel/intern/fluidsim.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/fluidsim.c b/source/blender/blenkernel/intern/fluidsim.c index 6eba64cf33d..2b4032af503 100644 --- a/source/blender/blenkernel/intern/fluidsim.c +++ b/source/blender/blenkernel/intern/fluidsim.c @@ -114,7 +114,7 @@ void fluidsim_init(FluidsimModifierData *fluidmd) // no bounding box needed // todo - reuse default init from elbeem! - fss->typeFlags = 0; + fss->typeFlags = OB_FSBND_NOSLIP; fss->domainNovecgen = 0; fss->volumeInitType = 1; // volume fss->partSlipValue = 0.0; -- cgit v1.2.3 From 66918b3add4dfc90a8074f4bdc1c797ae9bf1371 Mon Sep 17 00:00:00 2001 From: Janne Karhu Date: Sat, 4 Jul 2009 03:50:12 +0000 Subject: A bunch of fun stuff now possible because of new pointcache code: * Baked normal particles can now use the "Path" visualization. * Path "max length" & "abs length" are now history: - New option to set path start & end times + random variation to length. - Much more flexible (and calculated better) than previous options. - This works with parents, children, hair & normal particles unlike old length option. - Only known issue for now is that children from faces don't get calculated correctly when using path start time. * New option "trails" for "halo", "line" and "billboard" visualizations: - Draws user controllable number of particle instances along particles path backwards from current position. - Works with children too for cool/weird visualizations that weren't possible before. * Normal particle children's velocities are now approximated better when needed so that "line" visualization trails will look nice. * New particle instance modifier options: - "path"-option works better and has controllable (max)position along path (with random variation possible). - "keep shape"-option for hair, keyed, or baked particles allows to place the instances to a single point (with random variation possible) along particle path. - "axis" option to make rotation handling better (still not perfect, but will have to do for now). Some fixes & cleanup done along the way: * Random path length didn't work for non-child particles. * Cached & unborn particles weren't reset to emit locations. * Particle numbers weren't drawn in the correct place. * Setting proper render & draw visualizations was lost somewhere when initializing new particle settings. * Changing child mode wasn't working correctly. * Some cleanup & modularization of particle child effector code and particle drawing & rendering code. * Object & group visualizations didn't work. * Child simplification didn't work. --- source/blender/blenkernel/BKE_particle.h | 5 +- source/blender/blenkernel/intern/anim.c | 13 +- source/blender/blenkernel/intern/depsgraph.c | 4 +- source/blender/blenkernel/intern/modifier.c | 62 ++- source/blender/blenkernel/intern/particle.c | 541 ++++++++++++--------- source/blender/blenkernel/intern/particle_system.c | 36 +- source/blender/blenkernel/intern/pointcache.c | 15 +- 7 files changed, 387 insertions(+), 289 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index 73f0195d1d8..aa24706077d 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -91,7 +91,8 @@ 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, rough; /* used in path caching */ + float length, clump, kink, effector;/* used in path caching */ + float rough1, rough2, roughe; /* used in path caching */ } ParticleTexture; typedef struct BoidVecFunc{ @@ -270,7 +271,7 @@ void psys_update_world_cos(struct Object *ob, struct ParticleSystem *psys); int do_guide(struct Scene *scene, 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, struct ChildParticle *cpa, float cfra); +float psys_get_child_time(struct ParticleSystem *psys, struct ChildParticle *cpa, float cfra, float *birthtime, float *dietime); float psys_get_child_size(struct ParticleSystem *psys, struct ChildParticle *cpa, float cfra, float *pa_time); void psys_get_particle_on_path(struct Scene *scene, struct Object *ob, struct ParticleSystem *psys, int pa_num, struct ParticleKey *state, int vel); int psys_get_particle_state(struct Scene *scene, struct Object *ob, struct ParticleSystem *psys, int p, struct ParticleKey *state, int always); diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index 1aceca454d2..6c1b8eb9000 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -786,8 +786,9 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p BLI_srandom(31415926 + psys->seed); lay= 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)) { + if((psys->renderdata || part->draw_as==PART_DRAW_REND) && + ((part->ren_as == PART_DRAW_OB && part->dup_ob) || + (part->ren_as == PART_DRAW_GR && part->dup_group && part->dup_group->gobject.first))) { /* if we have a hair particle system, use the path cache */ if(part->type == PART_HAIR) { @@ -804,7 +805,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p psys->lattice = psys_get_lattice(scene, par, psys); /* gather list of objects or single object */ - if(part->draw_as==PART_DRAW_GR) { + if(part->ren_as==PART_DRAW_GR) { group_handle_recalc_and_update(scene, par, part->dup_group); for(go=part->dup_group->gobject.first; go; go=go->next) @@ -850,7 +851,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p size = psys_get_child_size(psys, cpa, ctime, 0); } - if(part->draw_as==PART_DRAW_GR) { + if(part->ren_as==PART_DRAW_GR) { /* for groups, pick the object based on settings */ if(part->draw&PART_DRAW_RAND_GR) b= BLI_rand() % totgroup; @@ -894,7 +895,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p pamat[3][3]= 1.0f; } - if(part->draw_as==PART_DRAW_GR && psys->part->draw & PART_DRAW_WHOLE_GR) { + if(part->ren_as==PART_DRAW_GR && psys->part->draw & PART_DRAW_WHOLE_GR) { for(go= part->dup_group->gobject.first, b=0; go; go= go->next, b++) { Mat4MulMat4(tmat, oblist[b]->obmat, pamat); Mat4MulFloat3((float *)tmat, size*scale); @@ -930,7 +931,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p } /* restore objects since they were changed in where_is_object_time */ - if(part->draw_as==PART_DRAW_GR) { + if(part->ren_as==PART_DRAW_GR) { for(a=0; adraw_as == PART_DRAW_OB && part->dup_ob) { + if(part->ren_as == PART_DRAW_OB && part->dup_ob) { node2 = dag_get_node(dag, part->dup_ob); dag_add_relation(dag, node, node2, DAG_RL_OB_OB, "Particle Object Visualisation"); if(part->dup_ob->type == OB_MBALL) dag_add_relation(dag, node, node2, DAG_RL_DATA_DATA, "Particle Object Visualisation"); } - if(part->draw_as == PART_DRAW_GR && part->dup_group) { + if(part->ren_as == PART_DRAW_GR && part->dup_group) { for(go=part->dup_group->gobject.first; go; go=go->next) { node2 = dag_get_node(dag, go->ob); dag_add_relation(dag, node, node2, DAG_RL_OB_OB, "Particle Group Visualisation"); diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 9ecf3a32c2b..71428a9e947 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -6390,6 +6390,7 @@ static void particleSystemModifier_deformVerts( } if(psys){ + psmd->flag &= ~eParticleSystemFlag_psys_updated; particle_system_update(md->scene, ob, psys); psmd->flag |= eParticleSystemFlag_psys_updated; psmd->flag &= ~eParticleSystemFlag_DM_changed; @@ -6421,6 +6422,8 @@ static void particleInstanceModifier_initData(ModifierData *md) pimd->flag = eParticleInstanceFlag_Parents|eParticleInstanceFlag_Unborn| eParticleInstanceFlag_Alive|eParticleInstanceFlag_Dead; pimd->psys = 1; + pimd->position = 1.0f; + pimd->axis = 2; } static void particleInstanceModifier_copyData(ModifierData *md, ModifierData *target) @@ -6431,6 +6434,8 @@ static void particleInstanceModifier_copyData(ModifierData *md, ModifierData *ta tpimd->ob = pimd->ob; tpimd->psys = pimd->psys; tpimd->flag = pimd->flag; + tpimd->position = pimd->position; + tpimd->random_position = pimd->random_position; } static int particleInstanceModifier_dependsOnTime(ModifierData *md) @@ -6470,7 +6475,7 @@ static DerivedMesh * particleInstanceModifier_applyModifier( MFace *mface, *orig_mface; MVert *mvert, *orig_mvert; int i,totvert, totpart=0, totface, maxvert, maxface, first_particle=0; - short track=ob->trackflag%3, trackneg; + short track=ob->trackflag%3, trackneg, axis = pimd->axis; float max_co=0.0, min_co=0.0, temp_co[3], cross[3]; trackneg=((ob->trackflag>2)?1:0); @@ -6508,7 +6513,7 @@ static DerivedMesh * particleInstanceModifier_applyModifier( psys->lattice=psys_get_lattice(md->scene, ob, psys); - if(psys->flag & (PSYS_HAIR_DONE|PSYS_KEYED)){ + if(psys->flag & (PSYS_HAIR_DONE|PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED){ float min_r[3], max_r[3]; INIT_MINMAX(min_r, max_r); @@ -6533,33 +6538,50 @@ static DerivedMesh * particleInstanceModifier_applyModifier( /*change orientation based on object trackflag*/ VECCOPY(temp_co,mv->co); - mv->co[0]=temp_co[track]; - mv->co[1]=temp_co[(track+1)%3]; - mv->co[2]=temp_co[(track+2)%3]; - - if(psys->flag & (PSYS_HAIR_DONE|PSYS_KEYED) && pimd->flag & eParticleInstanceFlag_Path){ - state.time=(mv->co[0]-min_co)/(max_co-min_co); - if(trackneg) - state.time=1.0f-state.time; - psys_get_particle_on_path(md->scene, pimd->ob, psys,first_particle + i/totvert, &state,1); + mv->co[axis]=temp_co[track]; + mv->co[(axis+1)%3]=temp_co[(track+1)%3]; + mv->co[(axis+2)%3]=temp_co[(track+2)%3]; + + if((psys->flag & (PSYS_HAIR_DONE|PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED) && pimd->flag & eParticleInstanceFlag_Path){ + float ran = 0.0f; + if(pimd->random_position != 0.0f) { + /* just use some static collection of random numbers */ + /* TODO: use something else that's unique to each instanced object */ + pa = psys->particles + (i/totvert)%totpart; + ran = pimd->random_position * 0.5 * (1.0f + pa->r_ave[0]); + } - mv->co[0] = 0.0; + if(pimd->flag & eParticleInstanceFlag_KeepShape) { + state.time = pimd->position * (1.0f - ran); + } + else { + state.time=(mv->co[axis]-min_co)/(max_co-min_co) * pimd->position * (1.0f - ran); + + if(trackneg) + state.time=1.0f-state.time; + + mv->co[axis] = 0.0; + } + + psys_get_particle_on_path(md->scene, pimd->ob, psys,first_particle + i/totvert, &state,1); Normalize(state.vel); - if(state.vel[0] < -0.9999 || state.vel[0] > 0.9999) { - state.rot[0] = 1.0; + /* TODO: incremental rotations somehow */ + if(state.vel[axis] < -0.9999 || state.vel[axis] > 0.9999) { + state.rot[0] = 1; state.rot[1] = state.rot[2] = state.rot[3] = 0.0f; } else { - /* a cross product of state.vel and a unit vector in x-direction */ - cross[0] = 0.0f; - cross[1] = -state.vel[2]; - cross[2] = state.vel[1]; + float temp[3] = {0.0f,0.0f,0.0f}; + temp[axis] = 1.0f; - /* state.vel[0] is the only component surviving from a dot product with a vector in x-direction*/ - VecRotToQuat(cross,saacos(state.vel[0]),state.rot); + Crossf(cross, temp, state.vel); + + /* state.vel[axis] is the only component surviving from a dot product with the axis */ + VecRotToQuat(cross,saacos(state.vel[axis]),state.rot); } + } else{ state.time=-1.0; diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 5bf9335d211..6ab8d72aa6d 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -81,6 +81,10 @@ static void key_from_object(Object *ob, ParticleKey *key); static void get_cpa_texture(DerivedMesh *dm, Material *ma, int face_index, float *fuv, float *orco, ParticleTexture *ptex, int event); +static void get_child_modifier_parameters(ParticleSettings *part, ParticleThreadContext *ctx, + ChildParticle *cpa, short cpa_from, int cpa_num, float *cpa_fuv, float *orco, ParticleTexture *ptex); +static void do_child_modifiers(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSettings *part, + ParticleTexture *ptex, ParticleKey *par, float *par_rot, ChildParticle *cpa, float *orco, ParticleKey *state, float t); /* few helpers for countall etc. */ int count_particles(ParticleSystem *psys){ @@ -452,7 +456,7 @@ void psys_free(Object *ob, ParticleSystem * psys) for(tpsys=ob->particlesystem.first; tpsys; tpsys=tpsys->next){ if(tpsys->part) { - if(ELEM(tpsys->part->draw_as,PART_DRAW_OB,PART_DRAW_GR)) + if(ELEM(tpsys->part->ren_as,PART_DRAW_OB,PART_DRAW_GR)) { nr++; break; @@ -491,6 +495,7 @@ typedef struct ParticleRenderData { ChildParticle *child; ParticleCacheKey **pathcache; ParticleCacheKey **childcache; + ListBase pathcachebufs, childcachebufs; int totchild, totcached, totchildcache; DerivedMesh *dm; int totdmvert, totdmedge, totdmface; @@ -577,8 +582,12 @@ void psys_render_set(Object *ob, ParticleSystem *psys, float viewmat[][4], float data->child= psys->child; data->totchild= psys->totchild; data->pathcache= psys->pathcache; + data->pathcachebufs.first = psys->pathcachebufs.first; + data->pathcachebufs.last = psys->pathcachebufs.last; data->totcached= psys->totcached; data->childcache= psys->childcache; + data->childcachebufs.first = psys->childcachebufs.first; + data->childcachebufs.last = psys->childcachebufs.last; data->totchildcache= psys->totchildcache; if(psmd->dm) @@ -591,6 +600,8 @@ void psys_render_set(Object *ob, ParticleSystem *psys, float viewmat[][4], float psys->pathcache= NULL; psys->childcache= NULL; psys->totchild= psys->totcached= psys->totchildcache= 0; + psys->pathcachebufs.first = psys->pathcachebufs.last = NULL; + psys->childcachebufs.first = psys->childcachebufs.last = NULL; Mat4CpyMat4(data->winmat, winmat); Mat4MulMat4(data->viewmat, ob->obmat, viewmat); @@ -631,8 +642,12 @@ void psys_render_restore(Object *ob, ParticleSystem *psys) psys->child= data->child; psys->totchild= data->totchild; psys->pathcache= data->pathcache; + psys->pathcachebufs.first = data->pathcachebufs.first; + psys->pathcachebufs.last = data->pathcachebufs.last; psys->totcached= data->totcached; psys->childcache= data->childcache; + psys->childcachebufs.first = data->childcachebufs.first; + psys->childcachebufs.last = data->childcachebufs.last; psys->totchildcache= data->totchildcache; psmd->dm= data->dm; @@ -663,7 +678,7 @@ int psys_render_simplify_distribution(ParticleThreadContext *ctx, int tot) int *origindex, *facetotvert; int a, b, totorigface, totface, newtot, skipped; - if(part->draw_as!=PART_DRAW_PATH || !(part->draw & PART_DRAW_REN_STRAND)) + if(part->ren_as!=PART_DRAW_PATH || !(part->draw & PART_DRAW_REN_STRAND)) return tot; if(!ctx->psys->renderdata) return tot; @@ -1992,11 +2007,9 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, ParticleData *pa=NULL; ParticleTexture ptex; float *cpa_fuv=0, *par_rot=0; - float co[3], orco[3], ornor[3], t, rough_t, cpa_1st[3], dvec[3]; + float co[3], orco[3], ornor[3], t, cpa_1st[3], dvec[3]; float branch_begin, branch_end, branch_prob, branchfac, rough_rand; - float pa_rough1, pa_rough2, pa_roughe; - float length, pa_length, pa_clump, pa_kink, pa_effector; - float max_length = 1.0f, cur_length = 0.0f; + float length, max_length = 1.0f, cur_length = 0.0f; float eff_length, eff_vec[3]; int k, cpa_num, guided = 0; short cpa_from; @@ -2059,9 +2072,11 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, psys_particle_on_emitter(ctx->psmd,cpa_from,cpa_num,DMCACHE_ISCHILD,cpa->fuv,foffset,co,ornor,0,0,orco,0); - /* we need to save the actual root position of the child for positioning it accurately to the surface of the emitter */ - VECCOPY(cpa_1st,co); - Mat4MulVecfl(ob->obmat,cpa_1st); + if(part->path_start==0.0f) { + /* we need to save the actual root position of the child for positioning it accurately to the surface of the emitter */ + VECCOPY(cpa_1st,co); + Mat4MulVecfl(ob->obmat,cpa_1st); + } pa=0; } @@ -2098,43 +2113,13 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, #endif // XXX old animation system /* get different child parameters from textures & vgroups */ - ptex.length=part->length*(1.0f - part->randlength*cpa->rand[0]); - ptex.clump=1.0; - ptex.kink=1.0; - ptex.rough= 1.0; - ptex.exist= 1.0; - - get_cpa_texture(ctx->dm,ctx->ma,cpa_num,cpa_fuv,orco,&ptex, - MAP_PA_DENS|MAP_PA_LENGTH|MAP_PA_CLUMP|MAP_PA_KINK|MAP_PA_ROUGH); - - pa_length=ptex.length; - pa_clump=ptex.clump; - pa_kink=ptex.kink; - pa_rough1=ptex.rough; - pa_rough2=ptex.rough; - pa_roughe=ptex.rough; - pa_effector= 1.0f; + get_child_modifier_parameters(part, ctx, cpa, cpa_from, cpa_num, cpa_fuv, orco, &ptex); if(ptex.exist < cpa->rand[1]) { keys->steps = -1; return; } - if(ctx->vg_length) - pa_length*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_length); - if(ctx->vg_clump) - pa_clump*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_clump); - if(ctx->vg_kink) - pa_kink*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_kink); - if(ctx->vg_rough1) - pa_rough1*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_rough1); - if(ctx->vg_rough2) - pa_rough2*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_rough2); - if(ctx->vg_roughe) - pa_roughe*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_roughe); - if(ctx->vg_effector) - pa_effector*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_effector); - /* create the child path */ for(k=0,state=keys; k<=ctx->steps; k++,state++){ if(ctx->between){ @@ -2158,12 +2143,14 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, key[w]++; w++; } - if(k==0){ - /* calculate the offset between actual child root position and first position interpolated from parents */ - VECSUB(cpa_1st,cpa_1st,state->co); + if(part->path_start==0.0f) { + if(k==0){ + /* calculate the offset between actual child root position and first position interpolated from parents */ + VECSUB(cpa_1st,cpa_1st,state->co); + } + /* apply offset for correct positioning */ + VECADD(state->co,state->co,cpa_1st); } - /* apply offset for correct positioning */ - VECADD(state->co,state->co,cpa_1st); } else{ /* offset the child from the parent position */ @@ -2177,7 +2164,7 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, if(part->flag & PART_CHILD_EFFECT) { for(k=0,state=keys; k<=ctx->steps; k++,state++) { if(k) { - do_path_effectors(ctx->scene, ob, psys, cpa->pa[0], state, k, ctx->steps, keys->co, pa_effector, 0.0f, ctx->cfra, &eff_length, eff_vec); + do_path_effectors(ctx->scene, ob, psys, cpa->pa[0], state, k, ctx->steps, keys->co, ptex.effector, 0.0f, ctx->cfra, &eff_length, eff_vec); } else { VecSubf(eff_vec,(state+1)->co,state->co); @@ -2203,67 +2190,50 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, } /* apply different deformations to the child path */ - if(part->flag & PART_CHILD_EFFECT) - /* state is safe to cast, since only co and vel are used */ - guided = do_guide(ctx->scene, (ParticleKey*)state, cpa->parent, t, &(psys->effectors)); - - if(guided==0){ - if(part->kink) - do_prekink((ParticleKey*)state, (ParticleKey*)par, par_rot, t, - part->kink_freq * pa_kink, part->kink_shape, part->kink_amp, part->kink, part->kink_axis, ob->obmat); - - do_clump((ParticleKey*)state, (ParticleKey*)par, t, part->clumpfac, part->clumppow, pa_clump); - } - - if(part->flag & PART_BRANCHING && ctx->between == 0 && part->flag & PART_ANIM_BRANCHING) - rough_t = t * rough_rand; - else - rough_t = t; + do_child_modifiers(ctx->scene, ob, psys, part, &ptex, (ParticleKey *)par, par_rot, cpa, orco, (ParticleKey *)state, t); - if(part->rough1 != 0.0 && pa_rough1 != 0.0) - do_rough(orco, rough_t, pa_rough1*part->rough1, part->rough1_size, 0.0, (ParticleKey*)state); - - if(part->rough2 != 0.0 && pa_rough2 != 0.0) - do_rough(cpa->rand, rough_t, pa_rough2*part->rough2, part->rough2_size, part->rough2_thres, (ParticleKey*)state); - - if(part->rough_end != 0.0 && pa_roughe != 0.0) - do_rough_end(cpa->rand, rough_t, pa_roughe*part->rough_end, part->rough_end_shape, (ParticleKey*)state, (ParticleKey*)par); - - if(part->flag & PART_BRANCHING && ctx->between==0){ - if(branch_prob > part->branch_thres){ - branchfac=0.0f; - } - else{ - if(part->flag & PART_SYMM_BRANCHING){ - if(t < branch_begin || t > branch_end) - branchfac=0.0f; - else{ - if((t-branch_begin)/(branch_end-branch_begin)<0.5) - branchfac=2.0f*(t-branch_begin)/(branch_end-branch_begin); - else - branchfac=2.0f*(branch_end-t)/(branch_end-branch_begin); + /* TODO: better branching */ + //if(part->flag & PART_BRANCHING && ctx->between == 0 && part->flag & PART_ANIM_BRANCHING) + // rough_t = t * rough_rand; + //else + // rough_t = t; - CLAMP(branchfac,0.0f,1.0f); - } - } - else{ - if(t < branch_begin){ - branchfac=0.0f; - } - else{ - branchfac=(t-branch_begin)/((1.0f-branch_begin)*0.5f); - CLAMP(branchfac,0.0f,1.0f); - } - } - } + /* TODO: better branching */ + //if(part->flag & PART_BRANCHING && ctx->between==0){ + // if(branch_prob > part->branch_thres){ + // branchfac=0.0f; + // } + // else{ + // if(part->flag & PART_SYMM_BRANCHING){ + // if(t < branch_begin || t > branch_end) + // branchfac=0.0f; + // else{ + // if((t-branch_begin)/(branch_end-branch_begin)<0.5) + // branchfac=2.0f*(t-branch_begin)/(branch_end-branch_begin); + // else + // branchfac=2.0f*(branch_end-t)/(branch_end-branch_begin); + + // CLAMP(branchfac,0.0f,1.0f); + // } + // } + // else{ + // if(t < branch_begin){ + // branchfac=0.0f; + // } + // else{ + // branchfac=(t-branch_begin)/((1.0f-branch_begin)*0.5f); + // CLAMP(branchfac,0.0f,1.0f); + // } + // } + // } - if(itotpart) - VecLerpf(state->co, (pcache[i] + k)->co, state->co, branchfac); - else - /* this is not threadsafe, but should only happen for - * branching particles particles, which are not threaded */ - VecLerpf(state->co, (cache[i - psys->totpart] + k)->co, state->co, branchfac); - } + // if(itotpart) + // VecLerpf(state->co, (pcache[i] + k)->co, state->co, branchfac); + // else + // /* this is not threadsafe, but should only happen for + // * branching particles particles, which are not threaded */ + // VecLerpf(state->co, (cache[i - psys->totpart] + k)->co, state->co, branchfac); + //} /* we have to correct velocity because of kink & clump */ if(k>1){ @@ -2287,9 +2257,9 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, else{ /* initialize length calculation */ if(part->flag&PART_ABS_LENGTH) - max_length= part->abslength*pa_length; + max_length= part->abslength*ptex.length; else - max_length= pa_length; + max_length= ptex.length; cur_length= 0.0f; } @@ -2383,7 +2353,36 @@ void psys_cache_child_paths(Scene *scene, Object *ob, ParticleSystem *psys, floa psys_threads_free(pthreads); } +static void get_pointcache_keys_for_time(ParticleSystem *psys, int index, float t, ParticleKey *key1, ParticleKey *key2) +{ + PointCache *cache = psys->pointcache; + static PTCacheMem *pm = NULL; + + if(cache->flag & PTCACHE_DISK_CACHE) { + /* TODO */ + } + else { + if(index < 0) { /* initialize */ + pm = cache->mem_cache.first; + if(pm) + pm = pm->next; + } + else { + if(pm) { + while(pm && pm->next && (float)pm->frame < t) + pm = pm->next; + copy_particle_key(key2, ((ParticleKey *)pm->data) + index, 1); + copy_particle_key(key1, ((ParticleKey *)(pm->prev)->data) + index, 1); + } + else if(cache->mem_cache.first) { + pm = cache->mem_cache.first; + copy_particle_key(key2, ((ParticleKey *)pm->data) + index, 1); + copy_particle_key(key1, ((ParticleKey *)pm->data) + index, 1); + } + } + } +} /* Calculates paths ready for drawing/rendering. */ /* -Usefull for making use of opengl vertex arrays for super fast strand drawing. */ /* -Makes child strands possible and creates them too into the cache. */ @@ -2409,7 +2408,7 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra float birthtime = 0.0, dietime = 0.0; float t, time = 0.0, keytime = 0.0, dfra = 1.0, frs_sec = scene->r.frs_sec; - float col[3] = {0.5f, 0.5f, 0.5f}; + float col[4] = {0.5f, 0.5f, 0.5f, 1.0f}; float prev_tangent[3], hairmat[4][4]; int k,i; int steps = (int)pow(2.0, (double)psys->part->draw_step); @@ -2419,12 +2418,17 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra float length, vec[3]; float *vg_effector= NULL, effector=0.0f; float *vg_length= NULL, pa_length=1.0f, max_length=1.0f, cur_length=0.0f; - float len, dvec[3]; + int keyed, baked; /* we don't have anything valid to create paths from so let's quit here */ - if((psys->flag & PSYS_HAIR_DONE)==0 && (psys->flag & PSYS_KEYED)==0) + if((psys->flag & PSYS_HAIR_DONE)==0 && (psys->flag & PSYS_KEYED)==0 && (psys->pointcache->flag & PTCACHE_BAKED)==0) return; + BLI_srandom(psys->seed); + + keyed = psys->flag & PSYS_KEYED; + baked = psys->pointcache->flag & PTCACHE_BAKED; + if(psys->renderdata) { steps = (int)pow(2.0, (double)psys->part->ren_step); } @@ -2488,7 +2492,8 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra else memset(cache[i], 0, sizeof(*cache[i])*(steps+1)); if(!edit && !psys->totchild) { - pa_length = part->length * (1.0f - part->randlength*pa->r_ave[0]); + //pa_length = part->length * (1.0f - part->randlength*pa->r_ave[0]); + pa_length = 1.0f - part->randlength * 0.5 * (1.0f + pa->r_ave[0]); if(vg_length) pa_length *= psys_particle_value_from_verts(psmd->dm,part->from,pa,vg_length); } @@ -2499,13 +2504,19 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra ekey = edit->keys[i]; /*--get the first data points--*/ - if(psys->flag & PSYS_KEYED) { + if(keyed) { kkey[0] = pa->keys; kkey[1] = kkey[0] + 1; birthtime = kkey[0]->time; dietime = kkey[0][pa->totkey-1].time; } + else if(baked) { + get_pointcache_keys_for_time(psys, -1, 0.0f, NULL, NULL); + + birthtime = pa->time; + dietime = pa->dietime; + } else { hkey[0] = pa->hair; hkey[1] = hkey[0] + 1; @@ -2516,6 +2527,25 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat); } + if(!edit) { + if(part->draw & PART_ABS_PATH_TIME) { + birthtime = MAX2(birthtime, part->path_start); + dietime = MIN2(dietime, part->path_end); + } + else { + float tb = birthtime; + birthtime = tb + part->path_start * (dietime - tb); + dietime = tb + part->path_end * (dietime - tb); + } + + if(birthtime >= dietime) { + cache[i]->steps = -1; + continue; + } + + dietime = birthtime + pa_length * (dietime - birthtime); + } + if(soft){ bp[0] = soft->bpoint + pa->bpi; bp[1] = bp[0] + 1; @@ -2527,13 +2557,16 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra t = birthtime + time * (dietime - birthtime); - if(psys->flag & PSYS_KEYED) { + if(keyed) { while(kkey[1]->time < t) { kkey[1]++; } kkey[0] = kkey[1] - 1; } + else if(baked) { + get_pointcache_keys_for_time(psys, i, t, keys+1, keys+2); + } else { while(hkey[1]->time < t) { hkey[1]++; @@ -2548,17 +2581,19 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra bp_to_particle(keys + 1, bp[0], hkey[0]); bp_to_particle(keys + 2, bp[1], hkey[1]); } - else if(psys->flag & PSYS_KEYED) { + else if(keyed) { memcpy(keys + 1, kkey[0], sizeof(ParticleKey)); memcpy(keys + 2, kkey[1], sizeof(ParticleKey)); } + else if(baked) + ; /* keys already set */ else { hair_to_particle(keys + 1, hkey[0]); hair_to_particle(keys + 2, hkey[1]); } - if((psys->flag & PSYS_KEYED)==0) { + if(!keyed && !baked) { if(soft) { if(hkey[0] != pa->hair) bp_to_particle(keys, bp[0] - 1, hkey[0] - 1); @@ -2591,18 +2626,18 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra keytime = (t - keys[1].time) / dfra; /* convert velocity to timestep size */ - if(psys->flag & PSYS_KEYED){ + if(keyed || baked){ VecMulf(keys[1].vel, dfra / frs_sec); VecMulf(keys[2].vel, dfra / frs_sec); } /* now we should have in chronologiacl order k1<=k2<=t<=k3<=k4 with keytime between [0,1]->[k2,k3] (k1 & k4 used for cardinal & bspline interpolation)*/ - psys_interpolate_particle((psys->flag & PSYS_KEYED) ? -1 /* signal for cubic interpolation */ + psys_interpolate_particle((keyed || baked) ? -1 /* signal for cubic interpolation */ : ((psys->part->flag & PART_HAIR_BSPLINE) ? KEY_BSPLINE : KEY_CARDINAL) ,keys, keytime, &result, 0); /* the velocity needs to be converted back from cubic interpolation */ - if(psys->flag & PSYS_KEYED){ + if(keyed || baked){ VecMulf(result.vel, frs_sec / dfra); } else if(soft==NULL) { /* softbody and keyed are allready in global space */ @@ -2717,28 +2752,6 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra } } - - if(!edit && !psys->totchild) { - /* check if path needs to be cut before actual end of data points */ - if(k){ - VECSUB(dvec,ca->co,(ca-1)->co); - if(part->flag&PART_ABS_LENGTH) - len=VecLength(dvec); - else - len=1.0f/(float)steps; - - k=check_path_length(k,cache[i],ca,max_length,&cur_length,len,dvec); - } - else{ - /* initialize length calculation */ - if(part->flag&PART_ABS_LENGTH) - max_length= part->abslength*pa_length; - else - max_length= pa_length; - - cur_length= 0.0f; - } - } } } @@ -2990,7 +3003,8 @@ static void default_particle_settings(ParticleSettings *part) part->type= PART_EMITTER; part->distr= PART_DISTR_JIT; - part->draw_as=PART_DRAW_DOT; + part->draw_as = PART_DRAW_REND; + part->ren_as = PART_DRAW_HALO; part->bb_uv_split=1; part->bb_align=PART_BB_VIEW; part->bb_split_offset=PART_BB_OFF_LINEAR; @@ -3046,6 +3060,8 @@ static void default_particle_settings(ParticleSettings *part) part->rough_end_shape=1.0; part->draw_line[0]=0.5; + part->path_start = 0.0f; + part->path_end = 1.0f; part->banking=1.0; part->max_bank=1.0; @@ -3282,7 +3298,7 @@ static void get_cpa_texture(DerivedMesh *dm, Material *ma, int face_index, float if((event & mtex->pmapto) & MAP_PA_KINK) ptex->kink= texture_value_blend(def,ptex->kink,value,var,blend,neg & MAP_PA_KINK); if((event & mtex->pmapto) & MAP_PA_ROUGH) - ptex->rough= texture_value_blend(def,ptex->rough,value,var,blend,neg & MAP_PA_ROUGH); + ptex->rough1= ptex->rough2= ptex->roughe= texture_value_blend(def,ptex->rough1,value,var,blend,neg & MAP_PA_ROUGH); if((event & mtex->pmapto) & MAP_PA_DENS) ptex->exist= texture_value_blend(def,ptex->exist,value,var,blend,neg & MAP_PA_DENS); } @@ -3291,7 +3307,11 @@ static void get_cpa_texture(DerivedMesh *dm, Material *ma, int face_index, float if(event & MAP_PA_LENGTH) { CLAMP(ptex->length,0.0,1.0); } if(event & MAP_PA_CLUMP) { CLAMP(ptex->clump,0.0,1.0); } if(event & MAP_PA_KINK) { CLAMP(ptex->kink,0.0,1.0); } - if(event & MAP_PA_ROUGH) { CLAMP(ptex->rough,0.0,1.0); } + if(event & MAP_PA_ROUGH) { + CLAMP(ptex->rough1,0.0,1.0); + CLAMP(ptex->rough2,0.0,1.0); + CLAMP(ptex->roughe,0.0,1.0); + } if(event & MAP_PA_DENS) { CLAMP(ptex->exist,0.0,1.0); } } void psys_get_texture(Object *ob, Material *ma, ParticleSystemModifierData *psmd, ParticleSystem *psys, ParticleData *pa, ParticleTexture *ptex, int event) @@ -3392,12 +3412,12 @@ float psys_get_size(Object *ob, Material *ma, ParticleSystemModifierData *psmd, return size*part->size; } -float psys_get_child_time(ParticleSystem *psys, ChildParticle *cpa, float cfra) +float psys_get_child_time(ParticleSystem *psys, ChildParticle *cpa, float cfra, float *birthtime, float *dietime) { ParticleSettings *part = psys->part; + float time, life; if(part->childtype==PART_CHILD_FACES){ - float time; int w=0; time=0.0; while(w<4 && cpa->pa[w]>=0){ @@ -3405,12 +3425,21 @@ float psys_get_child_time(ParticleSystem *psys, ChildParticle *cpa, float cfra) w++; } - return (cfra-time)/(part->lifetime*(1.0f-part->randlife*cpa->rand[1])); + life = part->lifetime*(1.0f-part->randlife*cpa->rand[1]); } else{ ParticleData *pa = psys->particles + cpa->parent; - return (cfra-pa->time)/pa->lifetime; + + time = pa->time; + life = pa->lifetime; } + + if(birthtime) + *birthtime = time; + if(dietime) + *dietime = time+life; + + return (cfra-time)/life; } float psys_get_child_size(ParticleSystem *psys, ChildParticle *cpa, float cfra, float *pa_time) { @@ -3427,7 +3456,7 @@ float psys_get_child_size(ParticleSystem *psys, ChildParticle *cpa, float cfra, if(pa_time) time=*pa_time; else - time=psys_get_child_time(psys,cpa,cfra); + time=psys_get_child_time(psys,cpa,cfra,NULL,NULL); /* correction for lifetime */ calc_ipo(part->ipo, 100*time); @@ -3449,6 +3478,64 @@ float psys_get_child_size(ParticleSystem *psys, ChildParticle *cpa, float cfra, return size; } +static void get_child_modifier_parameters(ParticleSettings *part, ParticleThreadContext *ctx, ChildParticle *cpa, short cpa_from, int cpa_num, float *cpa_fuv, float *orco, ParticleTexture *ptex) +{ + ptex->length=part->length*(1.0f - part->randlength*cpa->rand[0]); + ptex->clump=1.0; + ptex->kink=1.0; + ptex->rough1= 1.0; + ptex->rough2= 1.0; + ptex->roughe= 1.0; + ptex->exist= 1.0; + ptex->effector= 1.0; + + get_cpa_texture(ctx->dm,ctx->ma,cpa_num,cpa_fuv,orco,ptex, + MAP_PA_DENS|MAP_PA_LENGTH|MAP_PA_CLUMP|MAP_PA_KINK|MAP_PA_ROUGH); + + + if(ptex->exist < cpa->rand[1]) + return; + + if(ctx->vg_length) + ptex->length*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_length); + if(ctx->vg_clump) + ptex->clump*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_clump); + if(ctx->vg_kink) + ptex->kink*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_kink); + if(ctx->vg_rough1) + ptex->rough1*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_rough1); + if(ctx->vg_rough2) + ptex->rough2*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_rough2); + if(ctx->vg_roughe) + ptex->roughe*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_roughe); + if(ctx->vg_effector) + ptex->effector*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_effector); +} +static void do_child_modifiers(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSettings *part, ParticleTexture *ptex, ParticleKey *par, float *par_rot, ChildParticle *cpa, float *orco, ParticleKey *state, float t) +{ + int guided = 0; + + if(part->flag & PART_CHILD_EFFECT) + /* state is safe to cast, since only co and vel are used */ + guided = do_guide(scene, (ParticleKey*)state, cpa->parent, t, &(psys->effectors)); + + if(guided==0){ + if(part->kink) + do_prekink(state, par, par_rot, t, part->kink_freq * ptex->kink, part->kink_shape, + part->kink_amp, part->kink, part->kink_axis, ob->obmat); + + do_clump(state, par, t, part->clumpfac, part->clumppow, ptex->clump); + } + + if(part->rough1 != 0.0 && ptex->rough1 != 0.0) + do_rough(orco, t, ptex->rough1*part->rough1, part->rough1_size, 0.0, state); + + if(part->rough2 != 0.0 && ptex->rough2 != 0.0) + do_rough(cpa->rand, t, ptex->rough2*part->rough2, part->rough2_size, part->rough2_thres, state); + + if(part->rough_end != 0.0 && ptex->roughe != 0.0) + do_rough_end(cpa->rand, t, ptex->roughe*part->rough_end, part->rough_end_shape, state, par); +} /* get's hair (or keyed) particles state at the "path time" specified in state->time */ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, int p, ParticleKey *state, int vel) { @@ -3460,7 +3547,8 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i ParticleTexture ptex; ParticleKey *kkey[2] = {NULL, NULL}; HairKey *hkey[2] = {NULL, NULL}; - ParticleKey *par=0, keys[4]; + ParticleKey *par=0, keys[4], tstate; + ParticleThreadContext ctx; /* fake thread context for child modifiers */ float t, real_t, dfra, keytime, frs_sec = scene->r.frs_sec; float co[3], orco[3]; @@ -3471,6 +3559,9 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i int totchild = psys->totchild; short between = 0, edit = 0; + int keyed = psys->flag & PSYS_KEYED; + int cached = !keyed && part->type != PART_HAIR; + float *cpa_fuv; int cpa_num; short cpa_from; //if(psys_in_edit_mode(scene, psys)){ @@ -3479,12 +3570,6 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i // edit=1; //} - /* user want's cubic interpolation but only without sb it possible */ - //if(interpolation==PART_INTER_CUBIC && baked && psys->softflag==OB_SB_ENABLE) - // interpolation=PART_INTER_BSPLINE; - //else if(baked==0) /* it doesn't make sense to use other types for keyed */ - // interpolation=PART_INTER_CUBIC; - t=state->time; CLAMP(t, 0.0, 1.0); @@ -3497,20 +3582,29 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i return; } - if(psys->flag & PSYS_KEYED) { + if(keyed) { kkey[0] = pa->keys; kkey[1] = kkey[0] + 1; - real_t = kkey[0]->time + t * (kkey[0][pa->totkey-1].time - kkey[0]->time); + if(state->time < 0.0f) + real_t = -state->time; + else + real_t = kkey[0]->time + t * (kkey[0][pa->totkey-1].time - kkey[0]->time); + } + else if(cached) { + get_pointcache_keys_for_time(psys, -1, 0.0f, NULL, NULL); } else { hkey[0] = pa->hair; hkey[1] = pa->hair + 1; - real_t = hkey[0]->time + (hkey[0][pa->totkey-1].time - hkey[0]->time) * t; + if(state->time < 0.0f) + real_t = -state->time; + else + real_t = hkey[0]->time + t * (hkey[0][pa->totkey-1].time - hkey[0]->time); } - if(psys->flag & PSYS_KEYED) { + if(keyed) { while(kkey[1]->time < real_t) { kkey[1]++; } @@ -3519,6 +3613,14 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i memcpy(keys + 1, kkey[0], sizeof(ParticleKey)); memcpy(keys + 2, kkey[1], sizeof(ParticleKey)); } + else if(cached) { + if(state->time < 0.0f) /* flag for time in frames */ + real_t = -state->time; + else + real_t = pa->time + t * (pa->dietime - pa->time); + + get_pointcache_keys_for_time(psys, p, real_t, keys+1, keys+2); + } else { while(hkey[1]->time < real_t) hkey[1]++; @@ -3529,63 +3631,35 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i hair_to_particle(keys + 2, hkey[1]); } - if((psys->flag & PSYS_KEYED)==0) { - //if(soft){ - // if(key[0] != sbel.keys) - // DB_copy_key(&k1,key[0]-1); - // else - // DB_copy_key(&k1,&k2); - //} - //else{ + if(!keyed && !cached) { if(hkey[0] != pa->hair) hair_to_particle(keys, hkey[0] - 1); else hair_to_particle(keys, hkey[0]); - //} - //if(soft){ - // if(key[1] != sbel.keys + sbel.totkey-1) - // DB_copy_key(&k4,key[1]+1); - // else - // DB_copy_key(&k4,&k3); - //} - //else { if(hkey[1] != pa->hair + pa->totkey - 1) hair_to_particle(keys + 3, hkey[1] + 1); else hair_to_particle(keys + 3, hkey[1]); } - //} - - //psys_get_particle_on_path(scene, bsys,p,t,bkey,ckey[0]); - - //if(part->rotfrom==PART_ROT_KEYS) - // QuatInterpol(state->rot,k2.rot,k3.rot,keytime); - //else{ - // /* TODO: different rotations */ - // float nvel[3]; - // VECCOPY(nvel,state->vel); - // VecMulf(nvel,-1.0f); - // vectoquat(nvel, OB_POSX, OB_POSZ, state->rot); - //} dfra = keys[2].time - keys[1].time; keytime = (real_t - keys[1].time) / dfra; /* convert velocity to timestep size */ - if(psys->flag & PSYS_KEYED){ + if(keyed || cached){ VecMulf(keys[1].vel, dfra / frs_sec); VecMulf(keys[2].vel, dfra / frs_sec); QuatInterpol(state->rot,keys[1].rot,keys[2].rot,keytime); } - psys_interpolate_particle((psys->flag & PSYS_KEYED) ? -1 /* signal for cubic interpolation */ + psys_interpolate_particle((keyed || cached) ? -1 /* signal for cubic interpolation */ : ((psys->part->flag & PART_HAIR_BSPLINE) ? KEY_BSPLINE : KEY_CARDINAL) ,keys, keytime, state, 1); /* the velocity needs to be converted back from cubic interpolation */ - if(psys->flag & PSYS_KEYED){ + if(keyed || cached){ VecMulf(state->vel, frs_sec / dfra); } else { @@ -3606,8 +3680,11 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i } else if(totchild){ //Mat4Invert(imat,ob->obmat); - + cpa=psys->child+p-totpart; + + if(state->time < 0.0f) + t = psys_get_child_time(psys, cpa, -state->time, NULL, NULL); if(totchild && part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES){ totparent=(int)(totchild*part->parents*0.3); @@ -3624,7 +3701,7 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i /* get parent states */ while(w<4 && cpa->pa[w]>=0){ - keys[w].time = t; + keys[w].time = state->time; psys_get_particle_on_path(scene, ob, psys, cpa->pa[w], keys+w, 1); w++; } @@ -3650,7 +3727,7 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i else{ /* get the parent state */ - keys->time = t; + keys->time = state->time; psys_get_particle_on_path(scene, ob, psys, cpa->parent, keys,1); /* get the original coordinates (orco) for texture usage */ @@ -3672,15 +3749,11 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i #endif // XXX old animation system /* get different child parameters from textures & vgroups */ - ptex.clump=1.0; - ptex.kink=1.0; - - get_cpa_texture(psmd->dm,ma,cpa_num,cpa_fuv,orco,&ptex,MAP_PA_CLUMP|MAP_PA_KINK); - - pa_clump=ptex.clump; - pa_kink=ptex.kink; - - /* TODO: vertex groups */ + memset(&ctx, 0, sizeof(ParticleThreadContext)); + ctx.dm = psmd->dm; + ctx.ma = ma; + /* TODO: assign vertex groups */ + get_child_modifier_parameters(part, &ctx, cpa, cpa_from, cpa_num, cpa_fuv, orco, &ptex); if(between){ int w=0; @@ -3708,46 +3781,34 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i } par = keys; - //if(totparent){ - // if(p-totpart>=totparent){ - // key.time=t; - // psys_get_particle_on_path(ob,psys,totpart+cpa->parent,&key,1); - // bti->convert_dynamic_key(bsys,&key,par,cpar); - // } - // else - // par=0; - //} - //else - // DB_get_key_on_path(bsys,cpa->parent,t,par,cpar); - - /* apply different deformations to the child path */ - if(part->kink) - do_prekink(state, par, par->rot, t, part->kink_freq * pa_kink, part->kink_shape, - part->kink_amp, part->kink, part->kink_axis, ob->obmat); - - do_clump(state, par, t, part->clumpfac, part->clumppow, 1.0f); - - if(part->rough1 != 0.0) - do_rough(orco, t, part->rough1, part->rough1_size, 0.0, state); - if(part->rough2 != 0.0) - do_rough(cpa->rand, t, part->rough2, part->rough2_size, part->rough2_thres, state); + if(vel) + copy_particle_key(&tstate, state, 1); - if(part->rough_end != 0.0) - do_rough_end(cpa->rand, t, part->rough_end, part->rough_end_shape, state, par); + /* apply different deformations to the child path */ + do_child_modifiers(scene, ob, psys, part, &ptex, par, par->rot, cpa, orco, state, t); + + /* try to estimate correct velocity */ + if(vel){ + ParticleKey tstate; + float length = VecLength(state->vel); + + if(t>=0.001f){ + tstate.time=t-0.001f; + psys_get_particle_on_path(scene,ob,psys,p,&tstate,0); + VECSUB(state->vel,state->co,tstate.co); + Normalize(state->vel); + } + else{ + float length = VecLength(state->vel); + tstate.time=t+0.001f; + psys_get_particle_on_path(scene, ob,psys,p,&tstate,0); + VECSUB(state->vel,tstate.co,state->co); + Normalize(state->vel); + } - //if(vel){ - // if(t>=0.001f){ - // tstate.time=t-0.001f; - // psys_get_particle_on_path(scene,ob,psys,p,&tstate,0); - // VECSUB(state->vel,state->co,tstate.co); - // } - // else{ - // tstate.time=t+0.001f; - // psys_get_particle_on_path(scene, ob,psys,p,&tstate,0); - // VECSUB(state->vel,tstate.co,state->co); - // } - //} + VecMulf(state->vel, length); + } } } /* gets particle's state at a time, returns 1 if particle exists and can be seen and 0 if not */ @@ -3774,7 +3835,7 @@ int psys_get_particle_state(struct Scene *scene, Object *ob, ParticleSystem *psy pa=psys->particles+p; if(between){ - state->time = psys_get_child_time(psys,&psys->child[p-totpart],cfra); + state->time = psys_get_child_time(psys,&psys->child[p-totpart],cfra,NULL,NULL); if(always==0) if((state->time<0.0 && (part->flag & PART_UNBORN)==0) diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 591b6ca9be5..92b919f6b0e 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -4254,7 +4254,7 @@ static void psys_update_path_cache(Scene *scene, Object *ob, ParticleSystemModif } } - if((part->type==PART_HAIR || psys->flag&PSYS_KEYED) && ( psys_in_edit_mode(scene, psys) || (part->type==PART_HAIR + if((part->type==PART_HAIR || psys->flag&PSYS_KEYED || psys->pointcache->flag & PTCACHE_BAKED) && ( psys_in_edit_mode(scene, psys) || (part->type==PART_HAIR || (part->ren_as == PART_DRAW_PATH && (part->draw_as == PART_DRAW_REND || psys->renderdata))))){ psys_cache_paths(scene, ob, psys, cfra, 0); @@ -4371,8 +4371,10 @@ static void cached_step(Scene *scene, Object *ob, ParticleSystemModifierData *ps dietime = birthtime + (1 + pa->loop) * (pa->dietime - pa->time); /* update alive status and push events */ - if(pa->time > cfra) + if(pa->time > cfra) { pa->alive = PARS_UNBORN; + reset_particle(scene, pa, psys, psmd, ob, 0.0f, cfra, NULL, NULL, NULL); + } else if(dietime <= cfra){ if(dietime > psys->cfra){ state.time = dietime; @@ -4406,6 +4408,8 @@ static void cached_step(Scene *scene, Object *ob, ParticleSystemModifierData *ps distribute_particles(scene, ob, psys, PART_FROM_CHILD); } + psys_update_path_cache(scene, ob,psmd,psys,cfra); + if(vg_size) MEM_freeN(vg_size); } @@ -4433,10 +4437,17 @@ void psys_changed_type(ParticleSystem *psys) if(ELEM3(part->draw_as, PART_DRAW_NOT, PART_DRAW_REND, PART_DRAW_PATH)==0) part->draw_as = PART_DRAW_REND; + + CLAMP(part->path_start, 0.0f, 100.0f); + CLAMP(part->path_end, 0.0f, 100.0f); } - else + else { free_hair(psys, 1); + CLAMP(part->path_start, part->sta, part->end + part->lifetime); + CLAMP(part->path_end, part->sta, part->end + part->lifetime); + } + psys->softflag= 0; psys_reset(psys, PSYS_RESET_ALL); @@ -4629,9 +4640,8 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle totpart = psys->part->totpart; totchild = get_psys_tot_child(scene, psys); - if(oldtotpart != totpart || (psys->part->childtype && oldtotchild != totchild)) { + if(oldtotpart != totpart || oldtotchild != totchild) { only_children_changed = (oldtotpart == totpart); - realloc_particles(ob, psys, totpart); alloc = 1; distr= 1; init= 1; @@ -4647,11 +4657,12 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle if(alloc) { realloc_particles(ob, psys, totpart); - if(usecache) + if(usecache && !only_children_changed) BKE_ptcache_id_clear(&pid, PTCACHE_CLEAR_ALL, 0); } - distribute_particles(scene, ob, psys, part->from); + if(!only_children_changed) + distribute_particles(scene, ob, psys, part->from); if((psys->part->type == PART_HAIR) && !(psys->flag & PSYS_HAIR_DONE)) /* don't generate children while growing hair - waste of time */ @@ -4660,7 +4671,7 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle distribute_particles(scene, ob, psys, PART_FROM_CHILD); } - if(only_children_changed==0) { + if(!only_children_changed) { free_keyed_keys(psys); initialize_all_particles(ob, psys, psmd); @@ -4680,19 +4691,10 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle int result = get_particles_from_cache(scene, ob, psys, (float)framenr, &old_framenr); if(result == PTCACHE_READ_EXACT || result == PTCACHE_READ_INTERPOLATED) { - //if(part->phystype==PART_PHYS_KEYED && psys->flag&PSYS_FIRST_KEYED) { - // psys_count_keyed_targets(ob,psys); - // set_keyed_keys(scene, ob, psys); - //} - cached_step(scene, ob, psmd, psys, cfra); psys->cfra=cfra; psys->recalc = 0; - //if(part->phystype==PART_PHYS_KEYED && psys->flag&PSYS_FIRST_KEYED) { - // psys_update_path_cache(scene, ob, psmd, psys, framenr); - //} - cache->simframe= framenr; cache->flag |= PTCACHE_SIMULATION_VALID; diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index 64473d07151..b8a0b111324 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -1209,8 +1209,13 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker) for(pid=pidlist.first; pid; pid=pid->next) { cache = pid->cache; if((cache->flag & PTCACHE_BAKED)==0) { - if(pid->type==PTCACHE_TYPE_PARTICLES) + if(pid->type==PTCACHE_TYPE_PARTICLES) { + /* skip hair particles */ + if(((ParticleSystem*)pid->data)->part->type == PART_HAIR) + continue; + psys_get_pointcache_start_end(scene, pid->data, &cache->startframe, &cache->endframe); + } if((cache->flag & PTCACHE_REDO_NEEDED || (cache->flag & PTCACHE_SIMULATION_VALID)==0) && ((cache->flag & PTCACHE_QUICK_CACHE)==0 || render || bake)) @@ -1265,6 +1270,10 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker) BKE_ptcache_ids_from_object(&pidlist, base->object); for(pid=pidlist.first; pid; pid=pid->next) { + /* skip hair particles */ + if(pid->type==PTCACHE_TYPE_PARTICLES && ((ParticleSystem*)pid->data)->part->type == PART_HAIR) + continue; + cache = pid->cache; if(step > 1) @@ -1282,7 +1291,9 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker) scene->r.framelen = frameleno; CFRA = cfrao; - scene_update_for_newframe(scene, scene->lay); + + if(bake) /* already on cfra unless baking */ + scene_update_for_newframe(scene, scene->lay); /* TODO: call redraw all windows somehow */ } -- cgit v1.2.3 From 7055702530f778ebf66e53bc4336e812fb0cd885 Mon Sep 17 00:00:00 2001 From: Janne Karhu Date: Sat, 4 Jul 2009 12:09:21 +0000 Subject: Rendering animations with particle trails cached. --- source/blender/blenkernel/BKE_pointcache.h | 1 + source/blender/blenkernel/intern/pointcache.c | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_pointcache.h b/source/blender/blenkernel/BKE_pointcache.h index 3f1c45d28ec..c5d423c13ba 100644 --- a/source/blender/blenkernel/BKE_pointcache.h +++ b/source/blender/blenkernel/BKE_pointcache.h @@ -114,6 +114,7 @@ typedef struct PTCacheBaker { struct Scene *scene; int bake; int render; + int anim_init; int quick_step; struct PTCacheID *pid; int (*break_test)(void *data); diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index b8a0b111324..2fbd0278e0e 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -1154,6 +1154,7 @@ void BKE_ptcache_quick_cache_all(Scene *scene) baker.progressbar=NULL; baker.progresscontext=NULL; baker.render=0; + baker.anim_init = 0; baker.scene=scene; if(count_quick_cache(scene, &baker.quick_step)) @@ -1171,7 +1172,7 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker) float frameleno = scene->r.framelen; int cfrao = CFRA; int startframe = MAXFRAME; - int endframe = CFRA; + int endframe = baker->anim_init ? scene->r.sfra : CFRA; int bake = baker->bake; int render = baker->render; int step = baker->quick_step; -- cgit v1.2.3 From 46f6cdcdcc68917bf54926a72aae34a061c4ec7f Mon Sep 17 00:00:00 2001 From: Janne Karhu Date: Sun, 5 Jul 2009 12:36:20 +0000 Subject: Added a particle instance modifier option to use particle size. --- source/blender/blenkernel/intern/modifier.c | 33 +++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 71428a9e947..046dfcc9f87 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -6477,6 +6477,7 @@ static DerivedMesh * particleInstanceModifier_applyModifier( int i,totvert, totpart=0, totface, maxvert, maxface, first_particle=0; short track=ob->trackflag%3, trackneg, axis = pimd->axis; float max_co=0.0, min_co=0.0, temp_co[3], cross[3]; + float *size=NULL; trackneg=((ob->trackflag>2)?1:0); @@ -6503,6 +6504,25 @@ static DerivedMesh * particleInstanceModifier_applyModifier( if(totpart==0) return derivedData; + if(pimd->flag & eParticleInstanceFlag_UseSize) { + int p; + float *si; + si = size = MEM_callocN(totpart * sizeof(float), "particle size array"); + + if(pimd->flag & eParticleInstanceFlag_Parents) { + for(p=0, pa= psys->particles; ptotpart; p++, pa++, si++) + *si = pa->size; + } + + if(pimd->flag & eParticleInstanceFlag_Children) { + ChildParticle *cpa = psys->child; + + for(p=0; ptotchild; p++, cpa++, si++) { + *si = psys_get_child_size(psys, cpa, 0.0f, NULL); + } + } + } + pars=psys->particles; totvert=dm->getNumVerts(dm); @@ -6585,10 +6605,12 @@ static DerivedMesh * particleInstanceModifier_applyModifier( } else{ state.time=-1.0; - psys_get_particle_state(md->scene, pimd->ob, psys, i/totvert, &state,1); + psys_get_particle_state(md->scene, pimd->ob, psys, first_particle + i/totvert, &state,1); } QuatMulVecf(state.rot,mv->co); + if(pimd->flag & eParticleInstanceFlag_UseSize) + VecMulf(mv->co, size[i/totvert]); VECADD(mv->co,mv->co,state.co); } @@ -6641,6 +6663,9 @@ static DerivedMesh * particleInstanceModifier_applyModifier( psys->lattice= NULL; } + if(size) + MEM_freeN(size); + return result; } static DerivedMesh *particleInstanceModifier_applyModifierEM( @@ -7279,10 +7304,10 @@ static DerivedMesh * explodeModifier_explodeMesh(ExplodeModifierData *emd, timestep= psys_get_timestep(part); - if(part->flag & PART_GLOB_TIME) + //if(part->flag & PART_GLOB_TIME) cfra=bsystem_time(scene, 0,(float)scene->r.cfra,0.0); - else - cfra=bsystem_time(scene, ob,(float)scene->r.cfra,0.0); + //else + // cfra=bsystem_time(scene, ob,(float)scene->r.cfra,0.0); /* hash table for vertice <-> particle relations */ vertpahash= BLI_edgehash_new(); -- cgit v1.2.3 From f87fcde686c85820c510c5c7806f6b6b8466ba5c Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Mon, 6 Jul 2009 03:44:44 +0000 Subject: NLA SoC: Start of 'Meta' Strips Refactored the backend code/API's to support 'meta' strips (i.e. strips containing other strips). These have been implemented to be nested to 'unlimited' depths (in terms of common usages that is, though there is a very remote chance of stack-overflow in theoretrical evil cases only that shouldn't ever be encountered in production). This paves the way for implementing the necessary tweaks needed for the transform code (in addition to some cool user-level tricks) --- source/blender/blenkernel/BKE_nla.h | 8 ++ source/blender/blenkernel/intern/anim_sys.c | 47 ++++-- source/blender/blenkernel/intern/nla.c | 213 ++++++++++++++++++---------- 3 files changed, 183 insertions(+), 85 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_nla.h b/source/blender/blenkernel/BKE_nla.h index e2b1dd89deb..efa0591bd53 100644 --- a/source/blender/blenkernel/BKE_nla.h +++ b/source/blender/blenkernel/BKE_nla.h @@ -53,6 +53,13 @@ struct NlaStrip *add_nlastrip_to_stack(struct AnimData *adt, struct bAction *act /* ----------------------------- */ /* API */ +short BKE_nlastrips_has_space(ListBase *strips, float start, float end); +void BKE_nlastrips_sort_strips(ListBase *strips); + +short BKE_nlastrips_add_strip(ListBase *strips, struct NlaStrip *strip); + +/* ............ */ + struct NlaTrack *BKE_nlatrack_find_active(ListBase *tracks); void BKE_nlatrack_set_active(ListBase *tracks, struct NlaTrack *nlt); @@ -63,6 +70,7 @@ void BKE_nlatrack_sort_strips(struct NlaTrack *nlt); short BKE_nlatrack_add_strip(struct NlaTrack *nlt, struct NlaStrip *strip); +/* ............ */ struct NlaStrip *BKE_nlastrip_find_active(struct NlaTrack *nlt); short BKE_nlastrip_within_bounds(struct NlaStrip *strip, float min, float max); diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 9befe9dc9cb..1d10744ac80 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -628,15 +628,13 @@ static void nlastrip_evaluate_controls (NlaStrip *strip, float ctime) } -/* gets the strip active at the current time for a track for evaluation purposes */ -static void nlatrack_ctime_get_strip (ListBase *list, NlaTrack *nlt, short index, float ctime) +/* gets the strip active at the current time for a given list of strips */ +static NlaStrip *ctime_get_strip (ListBase *strips, short *side, float ctime) { NlaStrip *strip, *estrip=NULL; - NlaEvalStrip *nes; - short side= 0; /* loop over strips, checking if they fall within the range */ - for (strip= nlt->strips.first; strip; strip= strip->next) { + for (strip= strips->first; strip; strip= strip->next) { /* check if current time occurs within this strip */ if (IN_RANGE_INCL(ctime, strip->start, strip->end)) { /* this strip is active, so try to use it */ @@ -647,13 +645,13 @@ static void nlatrack_ctime_get_strip (ListBase *list, NlaTrack *nlt, short index /* if time occurred before current strip... */ if (ctime < strip->start) { - if (strip == nlt->strips.first) { + if (strip == strips->first) { /* before first strip - only try to use it if it extends backwards in time too */ if (strip->extendmode == NLASTRIP_EXTEND_HOLD) estrip= strip; /* side is 'before' regardless of whether there's a useful strip */ - side= NES_TIME_BEFORE; + *side= NES_TIME_BEFORE; } else { /* before next strip - previous strip has ended, but next hasn't begun, @@ -665,7 +663,7 @@ static void nlatrack_ctime_get_strip (ListBase *list, NlaTrack *nlt, short index if (strip->extendmode != NLASTRIP_EXTEND_NOTHING) estrip= strip; - side= NES_TIME_AFTER; + *side= NES_TIME_AFTER; } break; } @@ -673,11 +671,11 @@ static void nlatrack_ctime_get_strip (ListBase *list, NlaTrack *nlt, short index /* if time occurred after current strip... */ if (ctime > strip->end) { /* only if this is the last strip should we do anything, and only if that is being held */ - if (strip == nlt->strips.last) { + if (strip == strips->last) { if (strip->extendmode != NLASTRIP_EXTEND_NOTHING) estrip= strip; - side= NES_TIME_AFTER; + *side= NES_TIME_AFTER; break; } @@ -685,6 +683,35 @@ static void nlatrack_ctime_get_strip (ListBase *list, NlaTrack *nlt, short index } } + /* return the matching strip found */ + return estrip; +} + +/* gets the strip active at the current time for a track for evaluation purposes */ +static void nlatrack_ctime_get_strip (ListBase *list, NlaTrack *nlt, short index, float ctime) +{ + ListBase *strips= &nlt->strips; + NlaStrip *strip, *estrip=NULL; + NlaEvalStrip *nes; + short side= 0; + + /* keep looping over hierarchy of strips until one which fits for the current time is found */ + while (strips->first) { + /* try to get the strip at this frame for this strip */ + strip= ctime_get_strip(strips, &side, ctime); + + /* if a strip was found, make this the new estrip, otherwise, stop trying */ + if (strip) { + /* set new estrip */ + estrip= strip; + + /* check children (only available if this is a meta-strip) for better match */ + strips= &strip->strips; + } + else + break; + } + /* check if a valid strip was found * - must not be muted (i.e. will have contribution */ diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index 1244b2900fd..d01fa2c1965 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -68,10 +68,18 @@ */ void free_nlastrip (ListBase *strips, NlaStrip *strip) { + NlaStrip *cs, *csn; + /* sanity checks */ if (strip == NULL) return; + /* free child-strips */ + for (cs= strip->strips.first; cs; cs= csn) { + csn= cs->next; + free_nlastrip(&strip->strips, cs); + } + /* remove reference to action */ if (strip->act) strip->act->id.us--; @@ -144,6 +152,7 @@ void free_nladata (ListBase *tracks) NlaStrip *copy_nlastrip (NlaStrip *strip) { NlaStrip *strip_d; + NlaStrip *cs, *cs_d; /* sanity check */ if (strip == NULL) @@ -161,6 +170,14 @@ NlaStrip *copy_nlastrip (NlaStrip *strip) copy_fcurves(&strip_d->fcurves, &strip->fcurves); copy_fmodifiers(&strip_d->modifiers, &strip->modifiers); + /* make a copy of all the child-strips, one at a time */ + strip_d->strips.first= strip_d->strips.last= NULL; + + for (cs= strip->strips.first; cs; cs= cs->next) { + cs_d= copy_nlastrip(cs); + BLI_addtail(&strip_d->strips, cs_d); + } + /* return the strip */ return strip_d; } @@ -435,6 +452,7 @@ static float nlastrip_get_frame_transition (NlaStrip *strip, float cframe, short float nlastrip_get_frame (NlaStrip *strip, float cframe, short mode) { switch (strip->type) { + case NLASTRIP_TYPE_META: /* meta (is just a container for other strips, so shouldn't use the action-clip method) */ case NLASTRIP_TYPE_TRANSITION: /* transition */ return nlastrip_get_frame_transition(strip, cframe, mode); @@ -487,6 +505,117 @@ float BKE_nla_tweakedit_remap (AnimData *adt, float cframe, short mode) /* *************************************************** */ /* Basic Utilities */ +/* List of Strips ------------------------------------ */ +/* (these functions are used for NLA-Tracks and also for nested/meta-strips) */ + +/* Check if there is any space in the given list to add the given strip */ +short BKE_nlastrips_has_space (ListBase *strips, float start, float end) +{ + NlaStrip *strip; + + /* sanity checks */ + if ((strips == NULL) || IS_EQ(start, end)) + return 0; + if (start > end) { + puts("BKE_nlastrips_has_space() error... start and end arguments swapped"); + SWAP(float, start, end); + } + + /* loop over NLA strips checking for any overlaps with this area... */ + for (strip= strips->first; strip; strip= strip->next) { + /* if start frame of strip is past the target end-frame, that means that + * we've gone past the window we need to check for, so things are fine + */ + if (strip->start > end) + return 1; + + /* if the end of the strip is greater than either of the boundaries, the range + * must fall within the extents of the strip + */ + if ((strip->end > start) || (strip->end > end)) + return 0; + } + + /* if we are still here, we haven't encountered any overlapping strips */ + return 1; +} + +/* Rearrange the strips in the track so that they are always in order + * (usually only needed after a strip has been moved) + */ +void BKE_nlastrips_sort_strips (ListBase *strips) +{ + ListBase tmp = {NULL, NULL}; + NlaStrip *strip, *sstrip; + + /* sanity checks */ + if ELEM(NULL, strips, strips->first) + return; + + /* we simply perform insertion sort on this list, since it is assumed that per track, + * there are only likely to be at most 5-10 strips + */ + for (strip= strips->first; strip; strip= strip->next) { + short not_added = 1; + + /* remove this strip from the list, and add it to the new list, searching from the end of + * the list, assuming that the lists are in order + */ + BLI_remlink(strips, strip); + + for (sstrip= tmp.last; not_added && sstrip; sstrip= sstrip->prev) { + /* check if add after */ + if (sstrip->end < strip->start) { + BLI_insertlinkafter(&tmp, sstrip, strip); + not_added= 0; + break; + } + } + + /* add before first? */ + if (not_added) + BLI_addhead(&tmp, strip); + } + + /* reassign the start and end points of the strips */ + strips->first= tmp.first; + strips->last= tmp.last; +} + +/* Add the given NLA-Strip to the given list of strips, assuming that it + * isn't currently a member of another list + */ +short BKE_nlastrips_add_strip (ListBase *strips, NlaStrip *strip) +{ + NlaStrip *ns; + short not_added = 1; + + /* sanity checks */ + if ELEM(NULL, strips, strip) + return 0; + + /* check if any space to add */ + if (BKE_nlastrips_has_space(strips, strip->start, strip->end)==0) + return 0; + + /* find the right place to add the strip to the nominated track */ + for (ns= strips->first; ns; ns= ns->next) { + /* if current strip occurs after the new strip, add it before */ + if (ns->start > strip->end) { + BLI_insertlinkbefore(strips, ns, strip); + not_added= 0; + break; + } + } + if (not_added) { + /* just add to the end of the list of the strips then... */ + BLI_addtail(strips, strip); + } + + /* added... */ + return 1; +} + /* NLA-Tracks ---------------------------------------- */ /* Find the active NLA-track for the given stack */ @@ -560,36 +689,20 @@ void BKE_nlatrack_set_active (ListBase *tracks, NlaTrack *nlt_a) nlt_a->flag |= NLATRACK_ACTIVE; } -/* Check if there is any space in the last track to add the given strip */ + +/* Check if there is any space in the given track to add a strip of the given length */ short BKE_nlatrack_has_space (NlaTrack *nlt, float start, float end) { - NlaStrip *strip; - /* sanity checks */ if ((nlt == NULL) || IS_EQ(start, end)) return 0; if (start > end) { - puts("BKE_nlatrack_has_space error... start and end arguments swapped"); + puts("BKE_nlatrack_has_space() error... start and end arguments swapped"); SWAP(float, start, end); } - /* loop over NLA strips checking for any overlaps with this area... */ - for (strip= nlt->strips.first; strip; strip= strip->next) { - /* if start frame of strip is past the target end-frame, that means that - * we've gone past the window we need to check for, so things are fine - */ - if (strip->start > end) - return 1; - - /* if the end of the strip is greater than either of the boundaries, the range - * must fall within the extents of the strip - */ - if ((strip->end > start) || (strip->end > end)) - return 0; - } - - /* if we are still here, we haven't encountered any overlapping strips */ - return 1; + /* check if there's any space left in the track for a strip of the given length */ + return BKE_nlastrips_has_space(&nlt->strips, start, end); } /* Rearrange the strips in the track so that they are always in order @@ -597,41 +710,12 @@ short BKE_nlatrack_has_space (NlaTrack *nlt, float start, float end) */ void BKE_nlatrack_sort_strips (NlaTrack *nlt) { - ListBase tmp = {NULL, NULL}; - NlaStrip *strip, *sstrip; - /* sanity checks */ if ELEM(NULL, nlt, nlt->strips.first) return; - - /* we simply perform insertion sort on this list, since it is assumed that per track, - * there are only likely to be at most 5-10 strips - */ - for (strip= nlt->strips.first; strip; strip= strip->next) { - short not_added = 1; - - /* remove this strip from the list, and add it to the new list, searching from the end of - * the list, assuming that the lists are in order - */ - BLI_remlink(&nlt->strips, strip); - - for (sstrip= tmp.last; not_added && sstrip; sstrip= sstrip->prev) { - /* check if add after */ - if (sstrip->end < strip->start) { - BLI_insertlinkafter(&tmp, sstrip, strip); - not_added= 0; - break; - } - } - - /* add before first? */ - if (not_added) - BLI_addhead(&tmp, strip); - } - /* reassign the start and end points of the strips */ - nlt->strips.first= tmp.first; - nlt->strips.last= tmp.last; + /* sort the strips with a more generic function */ + BKE_nlastrips_sort_strips(&nlt->strips); } /* Add the given NLA-Strip to the given NLA-Track, assuming that it @@ -639,33 +723,12 @@ void BKE_nlatrack_sort_strips (NlaTrack *nlt) */ short BKE_nlatrack_add_strip (NlaTrack *nlt, NlaStrip *strip) { - NlaStrip *ns; - short not_added = 1; - /* sanity checks */ if ELEM(NULL, nlt, strip) return 0; - /* check if any space to add */ - if (BKE_nlatrack_has_space(nlt, strip->start, strip->end)==0) - return 0; - - /* find the right place to add the strip to the nominated track */ - for (ns= nlt->strips.first; ns; ns= ns->next) { - /* if current strip occurs after the new strip, add it before */ - if (ns->start > strip->end) { - BLI_insertlinkbefore(&nlt->strips, ns, strip); - not_added= 0; - break; - } - } - if (not_added) { - /* just add to the end of the list of the strips then... */ - BLI_addtail(&nlt->strips, strip); - } - - /* added... */ - return 1; + /* try to add the strip to the track using a more generic function */ + return BKE_nlastrips_add_strip(&nlt->strips, strip); } /* NLA Strips -------------------------------------- */ -- cgit v1.2.3 From 158657026122d3b169f1bea12a69ff8eb16bbe04 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Mon, 6 Jul 2009 11:06:34 +0000 Subject: NLA SoC: More work on Meta-Strips * Added several API functions for Meta-Strips editing. One of these (flush transform) still needs a few tweaks before it does its job well enough for all cases. * Meta strips are now drawn with a purple-ish colour. The start/end points of the strips they encompass are shown with lines along the length of the strips, with lines starting from the top indicating start-points and lines starting from the bottom indicating end-points. * Meta strips can be made (i.e. strips can be assigned to meta-strips) by selecting some strips and pressing Shift-G. Meta strips can be removed by selecting some meta-strips and pressing Alt-G. * Strips can now be 'snapped' to start from: the current frame, the nearest frame, the nearest second, or the nearest marker; using the Shift-S hotkey. 'Islands' of adjacent selected strips occurring in the same track are moved together as a single strip so that the start-point of the first strip is on the sepcified time, but all the relative lengths of strips stay the same. Internally, temporary meta-strips are created to facilitate this. --- source/blender/blenkernel/BKE_nla.h | 6 + source/blender/blenkernel/intern/nla.c | 193 +++++++++++++++++++++++++++++++++ 2 files changed, 199 insertions(+) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_nla.h b/source/blender/blenkernel/BKE_nla.h index efa0591bd53..3fcd799310e 100644 --- a/source/blender/blenkernel/BKE_nla.h +++ b/source/blender/blenkernel/BKE_nla.h @@ -58,6 +58,12 @@ void BKE_nlastrips_sort_strips(ListBase *strips); short BKE_nlastrips_add_strip(ListBase *strips, struct NlaStrip *strip); + +void BKE_nlastrips_make_metas(ListBase *strips, short temp); +void BKE_nlastrips_clear_metas(ListBase *strips, short onlySel, short onlyTemp); +short BKE_nlameta_add_strip(struct NlaStrip *mstrip, struct NlaStrip *strip); +void BKE_nlameta_flush_transforms(struct NlaStrip *mstrip); + /* ............ */ struct NlaTrack *BKE_nlatrack_find_active(ListBase *tracks); diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index d01fa2c1965..715f99c820f 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -616,6 +616,199 @@ short BKE_nlastrips_add_strip (ListBase *strips, NlaStrip *strip) return 1; } + +/* Meta-Strips ------------------------------------ */ + +/* Convert 'islands' (i.e. continuous string of) selected strips to be + * contained within 'Meta-Strips' which act as strips which contain strips. + * temp: are the meta-strips to be created 'temporary' ones used for transforms? + */ +void BKE_nlastrips_make_metas (ListBase *strips, short temp) +{ + NlaStrip *mstrip = NULL; + NlaStrip *strip, *stripn; + + /* sanity checks */ + if ELEM(NULL, strips, strips->first) + return; + + /* group all continuous chains of selected strips into meta-strips */ + for (strip= strips->first; strip; strip= stripn) { + stripn= strip->next; + + if (strip->flag & NLASTRIP_FLAG_SELECT) { + /* if there is an existing meta-strip, add this strip to it, otherwise, create a new one */ + if (mstrip == NULL) { + /* add a new meta-strip, and add it before the current strip that it will replace... */ + mstrip= MEM_callocN(sizeof(NlaStrip), "Meta-NlaStrip"); + mstrip->type = NLASTRIP_TYPE_META; + BLI_insertlinkbefore(strips, strip, mstrip); + + /* set flags */ + mstrip->flag = NLASTRIP_FLAG_SELECT; + + /* set temp flag if appropriate (i.e. for transform-type editing) */ + if (temp) + mstrip->flag |= NLASTRIP_FLAG_TEMP_META; + + /* make its start frame be set to the start frame of the current strip */ + mstrip->start= strip->start; + } + + /* remove the selected strips from the track, and add to the meta */ + BLI_remlink(strips, strip); + BLI_addtail(&mstrip->strips, strip); + + /* expand the meta's dimensions to include the newly added strip- i.e. its last frame */ + mstrip->end= strip->end; + } + else { + /* current strip wasn't selected, so the end of 'island' of selected strips has been reached, + * so stop adding strips to the current meta + */ + mstrip= NULL; + } + } +} + +/* Remove meta-strips (i.e. flatten the list of strips) from the top-level of the list of strips + * sel: only consider selected meta-strips, otherwise all meta-strips are removed + * onlyTemp: only remove the 'temporary' meta-strips used for transforms + */ +void BKE_nlastrips_clear_metas (ListBase *strips, short onlySel, short onlyTemp) +{ + NlaStrip *strip, *stripn; + + /* sanity checks */ + if ELEM(NULL, strips, strips->first) + return; + + /* remove meta-strips fitting the criteria of the arguments */ + for (strip= strips->first; strip; strip= stripn) { + stripn= strip->next; + + /* check if strip is a meta-strip */ + if (strip->type == NLASTRIP_TYPE_META) { + /* if check if selection and 'temporary-only' considerations are met */ + if ((onlySel==0) || (strip->flag & NLASTRIP_FLAG_SELECT)) { + if ((!onlyTemp) || (strip->flag & NLASTRIP_FLAG_TEMP_META)) { + NlaStrip *cs, *csn; + + /* move each one of the meta-strip's children before the meta-strip + * in the list of strips after unlinking them from the meta-strip + */ + for (cs= strip->strips.first; cs; cs= csn) { + csn= cs->next; + BLI_remlink(&strip->strips, cs); + BLI_insertlinkbefore(strips, strip, cs); + } + + /* free the meta-strip now */ + BLI_freelinkN(strips, strip); + } + } + } + } +} + +/* Add the given NLA-Strip to the given Meta-Strip, assuming that the + * strip isn't attached to anyy list of strips + */ +short BKE_nlameta_add_strip (NlaStrip *mstrip, NlaStrip *strip) +{ + /* sanity checks */ + if ELEM(NULL, mstrip, strip) + return 0; + + /* firstly, check if the meta-strip has space for this */ + if (BKE_nlastrips_has_space(&mstrip->strips, strip->start, strip->end) == 0) + return 0; + + /* check if this would need to be added to the ends of the meta, + * and subsequently, if the neighbouring strips allow us enough room + */ + if (strip->start < mstrip->start) { + /* check if strip to the left (if it exists) ends before the + * start of the strip we're trying to add + */ + if ((mstrip->prev == NULL) || (mstrip->prev->end <= strip->start)) { + /* add strip to start of meta's list, and expand dimensions */ + BLI_addhead(&mstrip->strips, strip); + mstrip->start= strip->start; + + return 1; + } + else /* failed... no room before */ + return 0; + } + else if (strip->end > mstrip->end) { + /* check if strip to the right (if it exists) starts before the + * end of the strip we're trying to add + */ + if ((mstrip->next == NULL) || (mstrip->next->start >= strip->end)) { + /* add strip to end of meta's list, and expand dimensions */ + BLI_addtail(&mstrip->strips, strip); + mstrip->end= strip->end; + + return 1; + } + else /* failed... no room after */ + return 0; + } + else { + /* just try to add to the meta-strip (no dimension changes needed) */ + return BKE_nlastrips_add_strip(&mstrip->strips, strip); + } +} + +/* Adjust the settings of NLA-Strips contained within a Meta-Strip (recursively), + * until the Meta-Strips children all fit within the Meta-Strip's new dimensions + */ +void BKE_nlameta_flush_transforms (NlaStrip *mstrip) +{ + NlaStrip *strip; + float oStart, oEnd, offset; + + /* sanity checks + * - strip must exist + * - strip must be a meta-strip with some contents + */ + if ELEM(NULL, mstrip, mstrip->strips.first) + return; + if (mstrip->type != NLASTRIP_TYPE_META) + return; + + /* get the original start/end points, and calculate the start-frame offset + * - these are simply the start/end frames of the child strips, + * since we assume they weren't transformed yet + */ + oStart= ((NlaStrip *)mstrip->strips.first)->start; + oEnd= ((NlaStrip *)mstrip->strips.last)->end; + offset= mstrip->start - oStart; + + /* optimisation: + * don't flush if nothing changed yet + * TODO: maybe we need a flag to say always flush? + */ + if (IS_EQ(oStart, mstrip->start) && IS_EQ(oEnd, mstrip->end)) + return; + + /* for each child-strip, calculate new start/end points based on this new info */ + for (strip= mstrip->strips.first; strip; strip= strip->next) { + //PointerRNA strip_ptr; + + /* firstly, just apply the changes in offset to both ends of the strip */ + strip->start += offset; + strip->end += offset; + + /* now, we need to fix the endpoint to take into account scaling */ + // TODO.. + + /* finally, make sure the strip's children (if it is a meta-itself), get updated */ + BKE_nlameta_flush_transforms(strip); + } +} + /* NLA-Tracks ---------------------------------------- */ /* Find the active NLA-track for the given stack */ -- cgit v1.2.3 From f98c3ed70b86d12945078c288c2bd3288a297841 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Mon, 6 Jul 2009 12:24:09 +0000 Subject: NLA SoC: Fixes for Meta-Strips and Editing * Split strip (YKEY) now plays nicely with Transitions and Metas. Meta strips get split up into their child strips, while transitions are ignored. * Wrapped Meta_Strip->strips in RNA * Bugfixes in Meta-strip API functions to silence some runtime-errors... --- source/blender/blenkernel/BKE_nla.h | 1 + source/blender/blenkernel/intern/nla.c | 39 ++++++++++++++++++++++------------ 2 files changed, 27 insertions(+), 13 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_nla.h b/source/blender/blenkernel/BKE_nla.h index 3fcd799310e..5cb967c9c59 100644 --- a/source/blender/blenkernel/BKE_nla.h +++ b/source/blender/blenkernel/BKE_nla.h @@ -61,6 +61,7 @@ short BKE_nlastrips_add_strip(ListBase *strips, struct NlaStrip *strip); void BKE_nlastrips_make_metas(ListBase *strips, short temp); void BKE_nlastrips_clear_metas(ListBase *strips, short onlySel, short onlyTemp); +void BKE_nlastrips_clear_metastrip(ListBase *strips, struct NlaStrip *strip); short BKE_nlameta_add_strip(struct NlaStrip *mstrip, struct NlaStrip *strip); void BKE_nlameta_flush_transforms(struct NlaStrip *mstrip); diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index 715f99c820f..a83fa0abe1e 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -650,6 +650,9 @@ void BKE_nlastrips_make_metas (ListBase *strips, short temp) /* set temp flag if appropriate (i.e. for transform-type editing) */ if (temp) mstrip->flag |= NLASTRIP_FLAG_TEMP_META; + + /* set default repeat/scale values to prevent warnings */ + mstrip->repeat= mstrip->scale= 1.0f; /* make its start frame be set to the start frame of the current strip */ mstrip->start= strip->start; @@ -671,6 +674,28 @@ void BKE_nlastrips_make_metas (ListBase *strips, short temp) } } +/* Split a meta-strip into a set of normal strips */ +void BKE_nlastrips_clear_metastrip (ListBase *strips, NlaStrip *strip) +{ + NlaStrip *cs, *csn; + + /* sanity check */ + if ELEM(NULL, strips, strip) + return; + + /* move each one of the meta-strip's children before the meta-strip + * in the list of strips after unlinking them from the meta-strip + */ + for (cs= strip->strips.first; cs; cs= csn) { + csn= cs->next; + BLI_remlink(&strip->strips, cs); + BLI_insertlinkbefore(strips, strip, cs); + } + + /* free the meta-strip now */ + BLI_freelinkN(strips, strip); +} + /* Remove meta-strips (i.e. flatten the list of strips) from the top-level of the list of strips * sel: only consider selected meta-strips, otherwise all meta-strips are removed * onlyTemp: only remove the 'temporary' meta-strips used for transforms @@ -692,19 +717,7 @@ void BKE_nlastrips_clear_metas (ListBase *strips, short onlySel, short onlyTemp) /* if check if selection and 'temporary-only' considerations are met */ if ((onlySel==0) || (strip->flag & NLASTRIP_FLAG_SELECT)) { if ((!onlyTemp) || (strip->flag & NLASTRIP_FLAG_TEMP_META)) { - NlaStrip *cs, *csn; - - /* move each one of the meta-strip's children before the meta-strip - * in the list of strips after unlinking them from the meta-strip - */ - for (cs= strip->strips.first; cs; cs= csn) { - csn= cs->next; - BLI_remlink(&strip->strips, cs); - BLI_insertlinkbefore(strips, strip, cs); - } - - /* free the meta-strip now */ - BLI_freelinkN(strips, strip); + BKE_nlastrips_clear_metastrip(strips, strip); } } } -- cgit v1.2.3 From 905b1380054f42fe30b19fb37861057af4760e32 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Tue, 7 Jul 2009 02:12:50 +0000 Subject: NLA SoC: Start of integration of Meta-strips in Transform * Chains of selected strips are now converted to meta-strips before transforms begin, and converted back afterwards. This simplifies the transform code needed in later stages... * Transform-flushing code for Meta-Strips should now work. There seems to be a little bit of numeric inaccuracy problems somewhere, as two strips which met at the same frame can get separated when scaling. * Meta-strips now draw with proper text identification * Snapping strips now properly clears meta-strips if a moved strip needs to be moved into a new track to be accomodated. * Fixed a filter used by a selection-operator. --- source/blender/blenkernel/intern/nla.c | 45 ++++++++++++++++++++++++++++------ 1 file changed, 37 insertions(+), 8 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index a83fa0abe1e..851a0d7b549 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -781,6 +781,8 @@ void BKE_nlameta_flush_transforms (NlaStrip *mstrip) { NlaStrip *strip; float oStart, oEnd, offset; + float oLen, nLen; + short scaleChanged= 0; /* sanity checks * - strip must exist @@ -806,16 +808,43 @@ void BKE_nlameta_flush_transforms (NlaStrip *mstrip) if (IS_EQ(oStart, mstrip->start) && IS_EQ(oEnd, mstrip->end)) return; + /* check if scale changed */ + oLen = oEnd - oStart; + nLen = mstrip->end - mstrip->start; + if (IS_EQ(nLen, oLen) == 0) + scaleChanged= 1; + /* for each child-strip, calculate new start/end points based on this new info */ for (strip= mstrip->strips.first; strip; strip= strip->next) { - //PointerRNA strip_ptr; - - /* firstly, just apply the changes in offset to both ends of the strip */ - strip->start += offset; - strip->end += offset; - - /* now, we need to fix the endpoint to take into account scaling */ - // TODO.. + if (scaleChanged) { + PointerRNA ptr; + float p1, p2, nStart, nEnd; + + /* compute positions of endpoints relative to old extents of strip */ + p1= (strip->start - oStart) / oLen; + p2= (strip->end - oStart) / oLen; + + /* compute the new strip endpoints using the proportions */ + nStart= (p1 * nLen) + mstrip->start; + nEnd= (p2 * nLen) + mstrip->start; + + /* firstly, apply the new positions manually, then apply using RNA + * - first time is to make sure no truncation errors from one endpoint not being + * set yet occur + * - second time is to make sure scale is computed properly... + */ + strip->start= nStart; + strip->end= nEnd; + + RNA_pointer_create(NULL, &RNA_NlaStrip, strip, &ptr); + RNA_float_set(&ptr, "start_frame", nStart); + RNA_float_set(&ptr, "end_frame", nEnd); + } + else { + /* just apply the changes in offset to both ends of the strip */ + strip->start += offset; + strip->end += offset; + } /* finally, make sure the strip's children (if it is a meta-itself), get updated */ BKE_nlameta_flush_transforms(strip); -- cgit v1.2.3 From e22fefc2c8ef2c844d32d9aed23a04013cc364fb Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Tue, 7 Jul 2009 10:25:55 +0000 Subject: NLA SoC: Fixed bug with NLA-Transform Strip-sorting code was buggy, as it was trying to access an invalid pointer, so the call to sort strips after transform was temporarily disabled in previous commits. --- source/blender/blenkernel/intern/nla.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index 851a0d7b549..4dce9aebe24 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -546,26 +546,28 @@ short BKE_nlastrips_has_space (ListBase *strips, float start, float end) void BKE_nlastrips_sort_strips (ListBase *strips) { ListBase tmp = {NULL, NULL}; - NlaStrip *strip, *sstrip; + NlaStrip *strip, *sstrip, *stripn; /* sanity checks */ if ELEM(NULL, strips, strips->first) return; - + /* we simply perform insertion sort on this list, since it is assumed that per track, * there are only likely to be at most 5-10 strips */ - for (strip= strips->first; strip; strip= strip->next) { + for (strip= strips->first; strip; strip= stripn) { short not_added = 1; + stripn= strip->next; + /* remove this strip from the list, and add it to the new list, searching from the end of * the list, assuming that the lists are in order */ BLI_remlink(strips, strip); - for (sstrip= tmp.last; not_added && sstrip; sstrip= sstrip->prev) { + for (sstrip= tmp.last; sstrip; sstrip= sstrip->prev) { /* check if add after */ - if (sstrip->end < strip->start) { + if (sstrip->end <= strip->start) { BLI_insertlinkafter(&tmp, sstrip, strip); not_added= 0; break; -- cgit v1.2.3 From d1677e36b663f077312050ac46cea0de1b1212c2 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Tue, 7 Jul 2009 11:37:33 +0000 Subject: NLA SoC: Recoded way that Meta-Strips are Evaluated Previously, the quick-hack I coded for Meta-strips evaluation didn't really take into account the possibilities to use Meta-Strips as strips in their own right - i.e. reversed, muted, time-mapping-curves, influence-blending - were all unavailable. This commit makes the aforementioned capabilities of other strips available for Meta-Strips too. The evaluation is now kind-of recursive (as with most of the other methods which take them into account) so that each 'level' of strips get evaluated correctly within their frame-of-reference. TODO: * F-Modifier support for Metas... --- source/blender/blenkernel/intern/anim_sys.c | 158 ++++++++++++++++------------ source/blender/blenkernel/intern/nla.c | 2 +- source/blender/blenkernel/nla_private.h | 6 ++ 3 files changed, 97 insertions(+), 69 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 1d10744ac80..0aadb1825ad 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -627,11 +627,12 @@ static void nlastrip_evaluate_controls (NlaStrip *strip, float ctime) } } - -/* gets the strip active at the current time for a given list of strips */ -static NlaStrip *ctime_get_strip (ListBase *strips, short *side, float ctime) +/* gets the strip active at the current time for a list of strips for evaluation purposes */ +NlaEvalStrip *nlastrips_ctime_get_strip (ListBase *list, ListBase *strips, short index, float ctime) { NlaStrip *strip, *estrip=NULL; + NlaEvalStrip *nes; + short side= 0; /* loop over strips, checking if they fall within the range */ for (strip= strips->first; strip; strip= strip->next) { @@ -651,7 +652,7 @@ static NlaStrip *ctime_get_strip (ListBase *strips, short *side, float ctime) estrip= strip; /* side is 'before' regardless of whether there's a useful strip */ - *side= NES_TIME_BEFORE; + side= NES_TIME_BEFORE; } else { /* before next strip - previous strip has ended, but next hasn't begun, @@ -663,7 +664,7 @@ static NlaStrip *ctime_get_strip (ListBase *strips, short *side, float ctime) if (strip->extendmode != NLASTRIP_EXTEND_NOTHING) estrip= strip; - *side= NES_TIME_AFTER; + side= NES_TIME_AFTER; } break; } @@ -675,7 +676,7 @@ static NlaStrip *ctime_get_strip (ListBase *strips, short *side, float ctime) if (strip->extendmode != NLASTRIP_EXTEND_NOTHING) estrip= strip; - *side= NES_TIME_AFTER; + side= NES_TIME_AFTER; break; } @@ -683,40 +684,11 @@ static NlaStrip *ctime_get_strip (ListBase *strips, short *side, float ctime) } } - /* return the matching strip found */ - return estrip; -} - -/* gets the strip active at the current time for a track for evaluation purposes */ -static void nlatrack_ctime_get_strip (ListBase *list, NlaTrack *nlt, short index, float ctime) -{ - ListBase *strips= &nlt->strips; - NlaStrip *strip, *estrip=NULL; - NlaEvalStrip *nes; - short side= 0; - - /* keep looping over hierarchy of strips until one which fits for the current time is found */ - while (strips->first) { - /* try to get the strip at this frame for this strip */ - strip= ctime_get_strip(strips, &side, ctime); - - /* if a strip was found, make this the new estrip, otherwise, stop trying */ - if (strip) { - /* set new estrip */ - estrip= strip; - - /* check children (only available if this is a meta-strip) for better match */ - strips= &strip->strips; - } - else - break; - } - /* check if a valid strip was found * - must not be muted (i.e. will have contribution */ if ((estrip == NULL) || (estrip->flag & NLASTRIP_FLAG_MUTED)) - return; + return NULL; /* if ctime was not within the boundaries of the strip, clamp! */ switch (side) { @@ -734,8 +706,8 @@ static void nlatrack_ctime_get_strip (ListBase *list, NlaTrack *nlt, short index */ // TODO: this sounds a bit hacky having a few isolated F-Curves stuck on some data it operates on... nlastrip_evaluate_controls(estrip, ctime); - if (estrip->influence <= 0.0f) // XXX is it useful to invert the strip? - return; + if (estrip->influence <= 0.0f) + return NULL; /* check if strip has valid data to evaluate, * and/or perform any additional type-specific actions @@ -744,12 +716,12 @@ static void nlatrack_ctime_get_strip (ListBase *list, NlaTrack *nlt, short index case NLASTRIP_TYPE_CLIP: /* clip must have some action to evaluate */ if (estrip->act == NULL) - return; + return NULL; break; case NLASTRIP_TYPE_TRANSITION: /* there must be strips to transition from and to (i.e. prev and next required) */ if (ELEM(NULL, estrip->prev, estrip->next)) - return; + return NULL; /* evaluate controls for the relevant extents of the bordering strips... */ nlastrip_evaluate_controls(estrip->prev, estrip->start); @@ -760,13 +732,15 @@ static void nlatrack_ctime_get_strip (ListBase *list, NlaTrack *nlt, short index /* add to list of strips we need to evaluate */ nes= MEM_callocN(sizeof(NlaEvalStrip), "NlaEvalStrip"); - nes->track= nlt; nes->strip= estrip; nes->strip_mode= side; nes->track_index= index; nes->strip_time= estrip->strip_time; - BLI_addtail(list, nes); + if (list) + BLI_addtail(list, nes); + + return nes; } /* ---------------------- */ @@ -897,6 +871,38 @@ static void nlaevalchan_accumulate (NlaEvalChannel *nec, NlaEvalStrip *nes, shor } } +/* accumulate the results of a temporary buffer with the results of the full-buffer */ +static void nlaevalchan_buffers_accumulate (ListBase *channels, ListBase *tmp_buffer, NlaEvalStrip *nes) +{ + NlaEvalChannel *nec, *necn, *necd; + + /* optimise - abort if no channels */ + if (tmp_buffer->first == NULL) + return; + + /* accumulate results in tmp_channels buffer to the accumulation buffer */ + for (nec= tmp_buffer->first; nec; nec= necn) { + /* get pointer to next channel in case we remove the current channel from the temp-buffer */ + necn= nec->next; + + /* try to find an existing matching channel for this setting in the accumulation buffer */ + necd= nlaevalchan_find_match(channels, &nec->ptr, nec->prop, nec->index); + + /* if there was a matching channel already in the buffer, accumulate to it, + * otherwise, add the current channel to the buffer for efficiency + */ + if (necd) + nlaevalchan_accumulate(necd, nes, 0, nec->value); + else { + BLI_remlink(tmp_buffer, nec); + BLI_addtail(channels, nec); + } + } + + /* free temp-channels that haven't been assimilated into the buffer */ + BLI_freelistN(tmp_buffer); +} + /* ---------------------- */ /* evaluate action-clip strip */ @@ -945,7 +951,6 @@ static void nlastrip_evaluate_actionclip (PointerRNA *ptr, ListBase *channels, N static void nlastrip_evaluate_transition (PointerRNA *ptr, ListBase *channels, NlaEvalStrip *nes) { ListBase tmp_channels = {NULL, NULL}; - NlaEvalChannel *nec, *necn, *necd; NlaEvalStrip tmp_nes; NlaStrip *s1, *s2; @@ -986,38 +991,51 @@ static void nlastrip_evaluate_transition (PointerRNA *ptr, ListBase *channels, N nlastrip_evaluate_actionclip(ptr, &tmp_channels, &tmp_nes); - /* optimise - abort if no channels */ - if (tmp_channels.first == NULL) - return; + /* assumulate temp-buffer and full-buffer, using the 'real' strip */ + nlaevalchan_buffers_accumulate(channels, &tmp_channels, nes); +} + +/* evaluate meta-strip */ +static void nlastrip_evaluate_meta (PointerRNA *ptr, ListBase *channels, NlaEvalStrip *nes) +{ + ListBase tmp_channels = {NULL, NULL}; + NlaStrip *strip= nes->strip; + NlaEvalStrip *tmp_nes; + float evaltime; + /* meta-strip was calculated normally to have some time to be evaluated at + * and here we 'look inside' the meta strip, treating it as a decorated window to + * it's child strips, which get evaluated as if they were some tracks on a strip + * (but with some extra modifiers to apply). + * + * NOTE: keep this in sync with animsys_evaluate_nla() + */ - /* accumulate results in tmp_channels buffer to the accumulation buffer */ - for (nec= tmp_channels.first; nec; nec= necn) { - /* get pointer to next channel in case we remove the current channel from the temp-buffer */ - necn= nec->next; - - /* try to find an existing matching channel for this setting in the accumulation buffer */ - necd= nlaevalchan_find_match(channels, &nec->ptr, nec->prop, nec->index); + /* find the child-strip to evaluate */ + evaltime= (nes->strip_time * (strip->end - strip->start)) + strip->start; + tmp_nes= nlastrips_ctime_get_strip(NULL, &strip->strips, -1, evaltime); + if (tmp_nes == NULL) + return; - /* if there was a matching channel already in the buffer, accumulate to it, - * otherwise, add the current channel to the buffer for efficiency - */ - if (necd) - nlaevalchan_accumulate(necd, nes, 0, nec->value); - else { - BLI_remlink(&tmp_channels, nec); - BLI_addtail(channels, nec); - } - } + /* evaluate child-strip into tmp_channels buffer before accumulating + * in the accumulation buffer + */ + // TODO: need to supply overriding modifiers which will get applied over the top of these + nlastrip_evaluate(ptr, &tmp_channels, tmp_nes); - /* free temp-channels that haven't been assimilated into the buffer */ - BLI_freelistN(&tmp_channels); + /* assumulate temp-buffer and full-buffer, using the 'real' strip */ + nlaevalchan_buffers_accumulate(channels, &tmp_channels, nes); + + /* free temp eval-strip */ + MEM_freeN(tmp_nes); } + /* evaluates the given evaluation strip */ -static void nlastrip_evaluate (PointerRNA *ptr, ListBase *channels, NlaEvalStrip *nes) +void nlastrip_evaluate (PointerRNA *ptr, ListBase *channels, NlaEvalStrip *nes) { /* actions to take depend on the type of strip */ + // TODO: add 'modifiers' tag to chain switch (nes->strip->type) { case NLASTRIP_TYPE_CLIP: /* action-clip */ nlastrip_evaluate_actionclip(ptr, channels, nes); @@ -1025,11 +1043,14 @@ static void nlastrip_evaluate (PointerRNA *ptr, ListBase *channels, NlaEvalStrip case NLASTRIP_TYPE_TRANSITION: /* transition */ nlastrip_evaluate_transition(ptr, channels, nes); break; + case NLASTRIP_TYPE_META: /* meta */ + nlastrip_evaluate_meta(ptr, channels, nes); + break; } } /* write the accumulated settings to */ -static void nladata_flush_channels (ListBase *channels) +void nladata_flush_channels (ListBase *channels) { NlaEvalChannel *nec; @@ -1104,7 +1125,8 @@ static void animsys_evaluate_nla (PointerRNA *ptr, AnimData *adt, float ctime) continue; /* otherwise, get strip to evaluate for this channel */ - nlatrack_ctime_get_strip(&estrips, nlt, track_index, ctime); + nes= nlastrips_ctime_get_strip(&estrips, &nlt->strips, track_index, ctime); + if (nes) nes->track= nlt; } /* only continue if there are strips to evaluate */ diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index 4dce9aebe24..511623f46fc 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -452,7 +452,7 @@ static float nlastrip_get_frame_transition (NlaStrip *strip, float cframe, short float nlastrip_get_frame (NlaStrip *strip, float cframe, short mode) { switch (strip->type) { - case NLASTRIP_TYPE_META: /* meta (is just a container for other strips, so shouldn't use the action-clip method) */ + case NLASTRIP_TYPE_META: /* meta - for now, does the same as transition (is really just an empty container) */ case NLASTRIP_TYPE_TRANSITION: /* transition */ return nlastrip_get_frame_transition(strip, cframe, mode); diff --git a/source/blender/blenkernel/nla_private.h b/source/blender/blenkernel/nla_private.h index 1514a79f03b..016eaedfe4c 100644 --- a/source/blender/blenkernel/nla_private.h +++ b/source/blender/blenkernel/nla_private.h @@ -75,5 +75,11 @@ typedef struct NlaEvalChannel { /* convert from strip time <-> global time */ float nlastrip_get_frame(NlaStrip *strip, float cframe, short mode); +/* --------------- NLA Evaluation (very-private stuff) ----------------------- */ +/* these functions are only defined here to avoid problems with the order in which they get defined... */ + +NlaEvalStrip *nlastrips_ctime_get_strip(ListBase *list, ListBase *strips, short index, float ctime); +void nlastrip_evaluate(PointerRNA *ptr, ListBase *channels, NlaEvalStrip *nes); +void nladata_flush_channels(ListBase *channels); #endif // NLA_PRIVATE -- cgit v1.2.3 From f8c344bd17e09f21b5f022f65016fc13a7aa1d69 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Tue, 7 Jul 2009 12:17:06 +0000 Subject: NLA SoC: Meta Strips + F-Modifiers F-Modifiers now work on 'all' types of NLA Strip. To get them working on Meta-strips, F-Modifiers on the Meta strip must be applied on top of those for child strips. For now, this is done by joining the lists of modifiers, and evaluating the joined list. Currently, Transitions don't work that great with F-Modifiers yet (only the endpoints get evaluated with the F-Modifiers). Solving this is for another time... --- source/blender/blenkernel/intern/anim_sys.c | 106 +++++++++++++++++++++++----- source/blender/blenkernel/nla_private.h | 2 +- 2 files changed, 91 insertions(+), 17 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 0aadb1825ad..1037b2fd15d 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -903,17 +903,76 @@ static void nlaevalchan_buffers_accumulate (ListBase *channels, ListBase *tmp_bu BLI_freelistN(tmp_buffer); } +/* ---------------------- */ +/* F-Modifier stack joining/separation utilities - should we generalise these for BLI_listbase.h interface? */ + +/* Temporarily join two lists of modifiers together, storing the result in a third list */ +static void nlaeval_fmodifiers_join_stacks (ListBase *result, ListBase *list1, ListBase *list2) +{ + FModifier *fcm1, *fcm2; + + /* if list1 is invalid... */ + if ELEM(NULL, list1, list1->first) { + if (list2 && list2->first) { + result->first= list2->first; + result->last= list2->last; + } + } + /* if list 2 is invalid... */ + else if ELEM(NULL, list2, list2->first) { + result->first= list1->first; + result->last= list1->last; + } + else { + /* list1 should be added first, and list2 second, with the endpoints of these being the endpoints for result + * - the original lists must be left unchanged though, as we need that fact for restoring + */ + result->first= list1->first; + result->last= list2->last; + + fcm1= list1->last; + fcm2= list2->first; + + fcm1->next= fcm2; + fcm2->prev= fcm1; + } +} + +/* Split two temporary lists of modifiers */ +static void nlaeval_fmodifiers_split_stacks (ListBase *list1, ListBase *list2) +{ + FModifier *fcm1, *fcm2; + + /* if list1/2 is invalid... just skip */ + if ELEM(NULL, list1, list2) + return; + if ELEM(NULL, list1->first, list2->first) + return; + + /* get endpoints */ + fcm1= list1->last; + fcm2= list2->first; + + /* clear their links */ + fcm1->next= NULL; + fcm2->prev= NULL; +} + /* ---------------------- */ /* evaluate action-clip strip */ -static void nlastrip_evaluate_actionclip (PointerRNA *ptr, ListBase *channels, NlaEvalStrip *nes) +static void nlastrip_evaluate_actionclip (PointerRNA *ptr, ListBase *channels, ListBase *modifiers, NlaEvalStrip *nes) { + ListBase tmp_modifiers = {NULL, NULL}; NlaStrip *strip= nes->strip; FCurve *fcu; float evaltime; + /* join this strip's modifiers to the parent's modifiers (own modifiers first) */ + nlaeval_fmodifiers_join_stacks(&tmp_modifiers, &strip->modifiers, modifiers); + /* evaluate strip's modifiers which modify time to evaluate the base curves at */ - evaltime= evaluate_time_fmodifiers(&strip->modifiers, NULL, 0.0f, strip->strip_time); + evaltime= evaluate_time_fmodifiers(&tmp_modifiers, NULL, 0.0f, strip->strip_time); /* evaluate all the F-Curves in the action, saving the relevant pointers to data that will need to be used */ for (fcu= strip->act->curves.first; fcu; fcu= fcu->next) { @@ -935,7 +994,7 @@ static void nlastrip_evaluate_actionclip (PointerRNA *ptr, ListBase *channels, N /* apply strip's F-Curve Modifiers on this value * NOTE: we apply the strip's original evaluation time not the modified one (as per standard F-Curve eval) */ - evaluate_value_fmodifiers(&strip->modifiers, fcu, &value, strip->strip_time); + evaluate_value_fmodifiers(&tmp_modifiers, fcu, &value, strip->strip_time); /* get an NLA evaluation channel to work with, and accumulate the evaluated value with the value(s) @@ -945,15 +1004,22 @@ static void nlastrip_evaluate_actionclip (PointerRNA *ptr, ListBase *channels, N if (nec) nlaevalchan_accumulate(nec, nes, newChan, value); } + + /* unlink this strip's modifiers from the parent's modifiers again */ + nlaeval_fmodifiers_split_stacks(&strip->modifiers, modifiers); } /* evaluate transition strip */ -static void nlastrip_evaluate_transition (PointerRNA *ptr, ListBase *channels, NlaEvalStrip *nes) +static void nlastrip_evaluate_transition (PointerRNA *ptr, ListBase *channels, ListBase *modifiers, NlaEvalStrip *nes) { ListBase tmp_channels = {NULL, NULL}; + ListBase tmp_modifiers = {NULL, NULL}; NlaEvalStrip tmp_nes; NlaStrip *s1, *s2; + /* join this strip's modifiers to the parent's modifiers (own modifiers first) */ + nlaeval_fmodifiers_join_stacks(&tmp_modifiers, &nes->strip->modifiers, modifiers); + /* get the two strips to operate on * - we use the endpoints of the strips directly flanking our strip * using these as the endpoints of the transition (destination and source) @@ -980,25 +1046,30 @@ static void nlastrip_evaluate_transition (PointerRNA *ptr, ListBase *channels, N tmp_nes= *nes; /* evaluate these strips into a temp-buffer (tmp_channels) */ + // FIXME: modifier evalation here needs some work... /* first strip */ tmp_nes.strip_mode= NES_TIME_TRANSITION_START; tmp_nes.strip= s1; - nlastrip_evaluate_actionclip(ptr, &tmp_channels, &tmp_nes); + nlastrip_evaluate_actionclip(ptr, &tmp_channels, &tmp_modifiers, &tmp_nes); /* second strip */ tmp_nes.strip_mode= NES_TIME_TRANSITION_END; tmp_nes.strip= s2; - nlastrip_evaluate_actionclip(ptr, &tmp_channels, &tmp_nes); + nlastrip_evaluate_actionclip(ptr, &tmp_channels, &tmp_modifiers, &tmp_nes); /* assumulate temp-buffer and full-buffer, using the 'real' strip */ nlaevalchan_buffers_accumulate(channels, &tmp_channels, nes); + + /* unlink this strip's modifiers from the parent's modifiers again */ + nlaeval_fmodifiers_split_stacks(&nes->strip->modifiers, modifiers); } /* evaluate meta-strip */ -static void nlastrip_evaluate_meta (PointerRNA *ptr, ListBase *channels, NlaEvalStrip *nes) +static void nlastrip_evaluate_meta (PointerRNA *ptr, ListBase *channels, ListBase *modifiers, NlaEvalStrip *nes) { ListBase tmp_channels = {NULL, NULL}; + ListBase tmp_modifiers = {NULL, NULL}; NlaStrip *strip= nes->strip; NlaEvalStrip *tmp_nes; float evaltime; @@ -1010,6 +1081,9 @@ static void nlastrip_evaluate_meta (PointerRNA *ptr, ListBase *channels, NlaEval * * NOTE: keep this in sync with animsys_evaluate_nla() */ + + /* join this strip's modifiers to the parent's modifiers (own modifiers first) */ + nlaeval_fmodifiers_join_stacks(&tmp_modifiers, &strip->modifiers, modifiers); /* find the child-strip to evaluate */ evaltime= (nes->strip_time * (strip->end - strip->start)) + strip->start; @@ -1020,31 +1094,31 @@ static void nlastrip_evaluate_meta (PointerRNA *ptr, ListBase *channels, NlaEval /* evaluate child-strip into tmp_channels buffer before accumulating * in the accumulation buffer */ - // TODO: need to supply overriding modifiers which will get applied over the top of these - nlastrip_evaluate(ptr, &tmp_channels, tmp_nes); + nlastrip_evaluate(ptr, &tmp_channels, &tmp_modifiers, tmp_nes); /* assumulate temp-buffer and full-buffer, using the 'real' strip */ nlaevalchan_buffers_accumulate(channels, &tmp_channels, nes); /* free temp eval-strip */ MEM_freeN(tmp_nes); + + /* unlink this strip's modifiers from the parent's modifiers again */ + nlaeval_fmodifiers_split_stacks(&strip->modifiers, modifiers); } - /* evaluates the given evaluation strip */ -void nlastrip_evaluate (PointerRNA *ptr, ListBase *channels, NlaEvalStrip *nes) +void nlastrip_evaluate (PointerRNA *ptr, ListBase *channels, ListBase *modifiers, NlaEvalStrip *nes) { /* actions to take depend on the type of strip */ - // TODO: add 'modifiers' tag to chain switch (nes->strip->type) { case NLASTRIP_TYPE_CLIP: /* action-clip */ - nlastrip_evaluate_actionclip(ptr, channels, nes); + nlastrip_evaluate_actionclip(ptr, channels, modifiers, nes); break; case NLASTRIP_TYPE_TRANSITION: /* transition */ - nlastrip_evaluate_transition(ptr, channels, nes); + nlastrip_evaluate_transition(ptr, channels, modifiers, nes); break; case NLASTRIP_TYPE_META: /* meta */ - nlastrip_evaluate_meta(ptr, channels, nes); + nlastrip_evaluate_meta(ptr, channels, modifiers, nes); break; } } @@ -1136,7 +1210,7 @@ static void animsys_evaluate_nla (PointerRNA *ptr, AnimData *adt, float ctime) /* 2. for each strip, evaluate then accumulate on top of existing channels, but don't set values yet */ for (nes= estrips.first; nes; nes= nes->next) - nlastrip_evaluate(ptr, &echannels, nes); + nlastrip_evaluate(ptr, &echannels, NULL, nes); /* 3. flush effects of accumulating channels in NLA to the actual data they affect */ nladata_flush_channels(&echannels); diff --git a/source/blender/blenkernel/nla_private.h b/source/blender/blenkernel/nla_private.h index 016eaedfe4c..df7ffaa3064 100644 --- a/source/blender/blenkernel/nla_private.h +++ b/source/blender/blenkernel/nla_private.h @@ -79,7 +79,7 @@ float nlastrip_get_frame(NlaStrip *strip, float cframe, short mode); /* these functions are only defined here to avoid problems with the order in which they get defined... */ NlaEvalStrip *nlastrips_ctime_get_strip(ListBase *list, ListBase *strips, short index, float ctime); -void nlastrip_evaluate(PointerRNA *ptr, ListBase *channels, NlaEvalStrip *nes); +void nlastrip_evaluate(PointerRNA *ptr, ListBase *channels, ListBase *modifiers, NlaEvalStrip *nes); void nladata_flush_channels(ListBase *channels); #endif // NLA_PRIVATE -- cgit v1.2.3 From be5293d3ad38ba5f9f32ac8585d012bc44a9e684 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Wed, 8 Jul 2009 05:00:10 +0000 Subject: NLA SoC: Influence/Time properties for strips can now be animated * These settings can now be edited + keyframed (using IKEY over the button only for now... other cases will fail) * Reshuffled some of the keyframing code to make this sort of thing easier to do. Also, restored corrections for NLA-mapping when inserting/removing keyframes. TODOS: * animation editors don't show these keyframes yet * the buttons don't change colour yet to reflect this state. How to do this efficiently? * allow keyframing of these in more places * more robust UI handling for this. --- source/blender/blenkernel/BKE_nla.h | 4 +++ source/blender/blenkernel/intern/nla.c | 52 ++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_nla.h b/source/blender/blenkernel/BKE_nla.h index 5cb967c9c59..7fdff7e41f7 100644 --- a/source/blender/blenkernel/BKE_nla.h +++ b/source/blender/blenkernel/BKE_nla.h @@ -80,8 +80,12 @@ short BKE_nlatrack_add_strip(struct NlaTrack *nlt, struct NlaStrip *strip); /* ............ */ struct NlaStrip *BKE_nlastrip_find_active(struct NlaTrack *nlt); + short BKE_nlastrip_within_bounds(struct NlaStrip *strip, float min, float max); +void BKE_nlastrip_validate_fcurves(struct NlaStrip *strip); + +/* ............ */ void BKE_nla_action_pushdown(struct AnimData *adt); diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index 511623f46fc..217444d16d2 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -1049,6 +1049,58 @@ short nlastrip_is_first (AnimData *adt, NlaStrip *strip) /* should be first now */ return 1; } + +/* Validate the NLA-Strips 'control' F-Curves based on the flags set*/ +void BKE_nlastrip_validate_fcurves (NlaStrip *strip) +{ + FCurve *fcu; + + /* sanity checks */ + if (strip == NULL) + return; + + /* if controlling influence... */ + if (strip->flag & NLASTRIP_FLAG_USR_INFLUENCE) { + /* try to get F-Curve */ + fcu= list_find_fcurve(&strip->fcurves, "influence", 0); + + /* add one if not found */ + if (fcu == NULL) { + /* make new F-Curve */ + fcu= MEM_callocN(sizeof(FCurve), "NlaStrip FCurve"); + BLI_addtail(&strip->fcurves, fcu); + + /* set default flags */ + fcu->flag = (FCURVE_VISIBLE|FCURVE_AUTO_HANDLES|FCURVE_SELECTED); + + /* store path - make copy, and store that */ + fcu->rna_path= BLI_strdupn("influence", 9); + + // TODO: insert a few keyframes to ensure default behaviour? + } + } + + /* if controlling time... */ + if (strip->flag & NLASTRIP_FLAG_USR_TIME) { + /* try to get F-Curve */ + fcu= list_find_fcurve(&strip->fcurves, "strip_time", 0); + + /* add one if not found */ + if (fcu == NULL) { + /* make new F-Curve */ + fcu= MEM_callocN(sizeof(FCurve), "NlaStrip FCurve"); + BLI_addtail(&strip->fcurves, fcu); + + /* set default flags */ + fcu->flag = (FCURVE_VISIBLE|FCURVE_AUTO_HANDLES|FCURVE_SELECTED); + + /* store path - make copy, and store that */ + fcu->rna_path= BLI_strdupn("strip_time", 10); + + // TODO: insert a few keyframes to ensure default behaviour? + } + } +} /* Tools ------------------------------------------- */ -- cgit v1.2.3 From 5f5ddb00146884d28414811bc92311af56d55904 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Wed, 8 Jul 2009 12:30:09 +0000 Subject: NLA SoC: Little optimisation + Drawing bugfix * Text labels on NLA-Strips should now draw properly for most short-strips now. Previously, the padding on the text was a bit too extreme, so for very short strips (less than 4 frames or so), the text was often pushed down into the bottom-right corner of view. * Optimised the keyframe-highlighting code for buttons a bit. Replaced the custom linear-search with the binary-search used when inserting keyframes (and for the 3d-view keyframe-indicator). There should be some theoretical improvements due to this at least... --- source/blender/blenkernel/BKE_fcurve.h | 3 --- source/blender/blenkernel/intern/fcurve.c | 14 -------------- 2 files changed, 17 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h index 4dcb08dc0df..cda64c6b241 100644 --- a/source/blender/blenkernel/BKE_fcurve.h +++ b/source/blender/blenkernel/BKE_fcurve.h @@ -153,9 +153,6 @@ void copy_fcurves(ListBase *dst, ListBase *src); /* find matching F-Curve in the given list of F-Curves */ struct FCurve *list_find_fcurve(ListBase *list, const char rna_path[], const int array_index); -/* test if there is a keyframe at cfra */ -short on_keyframe_fcurve(struct FCurve *fcu, float cfra); - /* get the time extents for F-Curve */ void calc_fcurve_range(struct FCurve *fcu, float *min, float *max); diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index 4c2ba61fc71..ebd94b94f8c 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -200,20 +200,6 @@ FCurve *list_find_fcurve (ListBase *list, const char rna_path[], const int array return NULL; } -short on_keyframe_fcurve(FCurve *fcu, float cfra) -{ - BezTriple *bezt; - unsigned i; - - bezt= fcu->bezt; - for (i=0; itotvert; i++, bezt++) { - if (IS_EQ(bezt->vec[1][0], cfra)) - return 1; - } - - return 0; -} - /* Calculate the extents of F-Curve's data */ void calc_fcurve_bounds (FCurve *fcu, float *xmin, float *xmax, float *ymin, float *ymax) { -- cgit v1.2.3 From eacb31dbb2f9a181f01d2b1138754cdea386c80f Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 8 Jul 2009 16:17:47 +0000 Subject: 2.5: code consistency * Rename BIF_transform/retopo.h to ED_transform/retopo.h for consistency. * Move MESH_OT_duplicate_add to editmesh_add.c. * Remove some code from BIF_gl.h which is not needed there anymore. --- source/blender/blenkernel/intern/subsurf_ccg.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index 15969fc9ab9..6e95fe7ebc7 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -60,6 +60,7 @@ #include "BLI_edgehash.h" #include "BIF_gl.h" +#include "BIF_glutil.h" #include "GPU_draw.h" #include "GPU_extensions.h" -- cgit v1.2.3 From 70fc83e958be8cf697798f46f2b3f18aaca61070 Mon Sep 17 00:00:00 2001 From: Peter Schlaile Date: Wed, 8 Jul 2009 17:41:45 +0000 Subject: == Sequencer == * Added a lot of update notifiers to RNA * Fixed strip deallocation (didn't free effect data for some reason...) --- source/blender/blenkernel/intern/sequence.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/sequence.c b/source/blender/blenkernel/intern/sequence.c index 7fc262b4796..c8d95929027 100644 --- a/source/blender/blenkernel/intern/sequence.c +++ b/source/blender/blenkernel/intern/sequence.c @@ -184,11 +184,11 @@ void seq_free_sequence(Editing *ed, Sequence *seq) if(seq->anim) IMB_free_anim(seq->anim); //XXX if(seq->hdaudio) sound_close_hdaudio(seq->hdaudio); - /* XXX if (seq->type & SEQ_EFFECT) { + if (seq->type & SEQ_EFFECT) { struct SeqEffectHandle sh = get_sequence_effect(seq); sh.free(seq); - }*/ + } if (ed->act_seq==seq) ed->act_seq= NULL; -- cgit v1.2.3 From 518911e78c2ae4511cbb9261c5cca410c0a77d73 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Thu, 9 Jul 2009 01:04:42 +0000 Subject: NLA SoC: Assorted cleanups * Some cleanups aimed at giving some (neglible) speedups * Preparation for NLA-Strip keyframes to be editable --- source/blender/blenkernel/BKE_nla.h | 2 ++ source/blender/blenkernel/intern/anim_sys.c | 8 +++--- source/blender/blenkernel/intern/nla.c | 41 ++++++++++++++++++++++++++++- 3 files changed, 47 insertions(+), 4 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_nla.h b/source/blender/blenkernel/BKE_nla.h index 7fdff7e41f7..04d4b0f8da2 100644 --- a/source/blender/blenkernel/BKE_nla.h +++ b/source/blender/blenkernel/BKE_nla.h @@ -83,6 +83,8 @@ struct NlaStrip *BKE_nlastrip_find_active(struct NlaTrack *nlt); short BKE_nlastrip_within_bounds(struct NlaStrip *strip, float min, float max); +short BKE_nlatrack_has_animated_strips(struct NlaTrack *nlt); +short BKE_nlatracks_have_animated_strips(ListBase *tracks); void BKE_nlastrip_validate_fcurves(struct NlaStrip *strip); /* ............ */ diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 1037b2fd15d..ebe3d28cb21 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -392,10 +392,10 @@ void BKE_keyingsets_free (ListBase *list) short animsys_remap_path (AnimMapper *remap, char *path, char **dst) { /* is there a valid remapping table to use? */ - if (remap) { + //if (remap) { /* find a matching entry... to use to remap */ // ...TODO... - } + //} /* nothing suitable found, so just set dst to look at path (i.e. no alloc/free needed) */ *dst= path; @@ -521,7 +521,6 @@ static void animsys_evaluate_drivers (PointerRNA *ptr, AnimData *adt, float ctim short ok= 0; /* check if this driver's curve should be skipped */ - // FIXME: maybe we shouldn't check for muted, though that would make things more confusing, as there's already too many ways to disable? if ((fcu->flag & (FCURVE_MUTED|FCURVE_DISABLED)) == 0) { /* check if driver itself is tagged for recalculation */ @@ -1185,6 +1184,9 @@ static void animsys_evaluate_nla (PointerRNA *ptr, AnimData *adt, float ctime) ListBase echannels= {NULL, NULL}; NlaEvalStrip *nes; + // TODO: need to zero out all channels used, otherwise we have problems with threadsafety + // and also when the user jumps between different times instead of moving sequentially... + /* 1. get the stack of strips to evaluate at current time (influence calculated here) */ for (nlt=adt->nla_tracks.first; nlt; nlt=nlt->next, track_index++) { /* if tweaking is on and this strip is the tweaking track, stop on this one */ diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index 217444d16d2..c697f639021 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -926,7 +926,6 @@ void BKE_nlatrack_set_active (ListBase *tracks, NlaTrack *nlt_a) nlt_a->flag |= NLATRACK_ACTIVE; } - /* Check if there is any space in the given track to add a strip of the given length */ short BKE_nlatrack_has_space (NlaTrack *nlt, float start, float end) { @@ -1050,6 +1049,46 @@ short nlastrip_is_first (AnimData *adt, NlaStrip *strip) return 1; } +/* Animated Strips ------------------------------------------- */ + +/* Check if the given NLA-Track has any strips with own F-Curves */ +short BKE_nlatrack_has_animated_strips (NlaTrack *nlt) +{ + NlaStrip *strip; + + /* sanity checks */ + if ELEM(NULL, nlt, nlt->strips.first) + return 0; + + /* check each strip for F-Curves only (don't care about whether the flags are set) */ + for (strip= nlt->strips.first; strip; strip= strip->next) { + if (strip->fcurves.first) + return 1; + } + + /* none found */ + return 0; +} + +/* Check if given NLA-Tracks have any strips with own F-Curves */ +short BKE_nlatracks_have_animated_strips (ListBase *tracks) +{ + NlaTrack *nlt; + + /* sanity checks */ + if ELEM(NULL, tracks, tracks->first) + return 0; + + /* check each track, stopping on the first hit */ + for (nlt= tracks->first; nlt; nlt= nlt->next) { + if (BKE_nlatrack_has_animated_strips(nlt)) + return 1; + } + + /* none found */ + return 0; +} + /* Validate the NLA-Strips 'control' F-Curves based on the flags set*/ void BKE_nlastrip_validate_fcurves (NlaStrip *strip) { -- cgit v1.2.3 From 5e659c0b0895e07351bd2b2425deea342141e515 Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Thu, 9 Jul 2009 15:40:04 +0000 Subject: 2.5 Monthly cleaning round to make it compile warning free. Mostly it was const stuff (strings, Context), but also a couple useful fixes, like wrong use of temp pointers. Only Mathutils callback struct I left alone... design issue. --- source/blender/blenkernel/intern/cloth.c | 9 ++++++--- source/blender/blenkernel/intern/packedFile.c | 2 -- source/blender/blenkernel/intern/particle.c | 8 +++----- source/blender/blenkernel/intern/particle_system.c | 6 ++++-- source/blender/blenkernel/intern/pointcache.c | 12 ++++++------ 5 files changed, 19 insertions(+), 18 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 08caea565aa..089dafeb8c7 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -341,24 +341,27 @@ void bvhselftree_update_from_cloth(ClothModifierData *clmd, int moving) } int modifiers_indexInObject(Object *ob, ModifierData *md_seek); -static void cloth_write_state(int index, Cloth *cloth, float *data) +static void cloth_write_state(int index, void *cloth_v, float *data) { + Cloth *cloth= cloth_v; ClothVertex *vert = cloth->verts + index; memcpy(data, vert->x, 3 * sizeof(float)); memcpy(data + 3, vert->xconst, 3 * sizeof(float)); memcpy(data + 6, vert->v, 3 * sizeof(float)); } -static void cloth_read_state(int index, Cloth *cloth, float *data) +static void cloth_read_state(int index, void *cloth_v, float *data) { + Cloth *cloth= cloth_v; ClothVertex *vert = cloth->verts + index; memcpy(vert->x, data, 3 * sizeof(float)); memcpy(vert->xconst, data + 3, 3 * sizeof(float)); memcpy(vert->v, data + 6, 3 * sizeof(float)); } -static void cloth_cache_interpolate(int index, Cloth *cloth, float frs_sec, float cfra, float cfra1, float cfra2, float *data1, float *data2) +static void cloth_cache_interpolate(int index, void *cloth_v, float frs_sec, float cfra, float cfra1, float cfra2, float *data1, float *data2) { + Cloth *cloth= cloth_v; ClothVertex *vert = cloth->verts + index; ParticleKey keys[4]; float dfra; diff --git a/source/blender/blenkernel/intern/packedFile.c b/source/blender/blenkernel/intern/packedFile.c index 4d88556d8bf..02b0f6a45a0 100644 --- a/source/blender/blenkernel/intern/packedFile.c +++ b/source/blender/blenkernel/intern/packedFile.c @@ -377,8 +377,6 @@ there was an error or when the user desides to cancel the operation. char *unpackFile(ReportList *reports, char *abs_name, char *local_name, PackedFile *pf, int how) { - char menu[6 *(FILE_MAXDIR + FILE_MAXFILE + 100)]; - char line[FILE_MAXDIR + FILE_MAXFILE + 100]; char *newname = NULL, *temp = NULL; // char newabs[FILE_MAXDIR + FILE_MAXFILE]; diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 6ab8d72aa6d..4488f8cdffd 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -2008,10 +2008,10 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, ParticleTexture ptex; float *cpa_fuv=0, *par_rot=0; float co[3], orco[3], ornor[3], t, cpa_1st[3], dvec[3]; - float branch_begin, branch_end, branch_prob, branchfac, rough_rand; + float branch_begin, branch_end, branch_prob, rough_rand; float length, max_length = 1.0f, cur_length = 0.0f; float eff_length, eff_vec[3]; - int k, cpa_num, guided = 0; + int k, cpa_num; short cpa_from; if(part->flag & PART_BRANCHING) { @@ -2417,7 +2417,7 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra float nosel_col[3]; float length, vec[3]; float *vg_effector= NULL, effector=0.0f; - float *vg_length= NULL, pa_length=1.0f, max_length=1.0f, cur_length=0.0f; + float *vg_length= NULL, pa_length=1.0f; int keyed, baked; /* we don't have anything valid to create paths from so let's quit here */ @@ -3553,7 +3553,6 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i float t, real_t, dfra, keytime, frs_sec = scene->r.frs_sec; float co[3], orco[3]; float hairmat[4][4]; - float pa_clump = 0.0, pa_kink = 0.0; int totparent = 0; int totpart = psys->totpart; int totchild = psys->totchild; @@ -3800,7 +3799,6 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i Normalize(state->vel); } else{ - float length = VecLength(state->vel); tstate.time=t+0.001f; psys_get_particle_on_path(scene, ob,psys,p,&tstate,0); VECSUB(state->vel,tstate.co,state->co); diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 92b919f6b0e..07e0e82a86d 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -2205,8 +2205,10 @@ void psys_get_pointcache_start_end(Scene *scene, ParticleSystem *psys, int *sfra *sfra = MAX2(1, (int)part->sta); *efra = MIN2((int)(part->end + part->lifetime + 1.0), scene->r.efra); } -static void particle_write_state(int index, ParticleSystem *psys, float *data) +static void particle_write_state(int index, void *psys_ptr, float *data) { + ParticleSystem *psys= psys_ptr; + memcpy(data, (float *)(&(psys->particles+index)->state), sizeof(ParticleKey)); } static void particle_read_state(int index, void *psys_ptr, float *data) @@ -2225,7 +2227,7 @@ static void particle_cache_interpolate(int index, void *psys_ptr, float frs_sec, ParticleSystem *psys= psys_ptr; ParticleData *pa = psys->particles + index; ParticleKey keys[4]; - float dfra, cfra1f = (float)cfra1, cfra2f(float); + float dfra; cfra = MIN2(cfra, pa->dietime); cfra1 = MIN2(cfra1, pa->dietime); diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index 2fbd0278e0e..2fe46be7a89 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -643,8 +643,8 @@ int BKE_ptcache_write_cache(PTCacheWriter *writer) return 0; for(i=0; itotelem; i++) { - writer->set_elem(i, writer->calldata, &temp); - BKE_ptcache_file_write_floats(pf, &temp, incr); + writer->set_elem(i, writer->calldata, temp); + BKE_ptcache_file_write_floats(pf, temp, incr); } } } @@ -677,8 +677,8 @@ int BKE_ptcache_write_cache(PTCacheWriter *writer) pmdata = pm->data; for(i=0; itotelem; i++, pmdata+=incr) { - writer->set_elem(i, writer->calldata, &temp); - memcpy(pmdata, &temp, elemsize); + writer->set_elem(i, writer->calldata, temp); + memcpy(pmdata, temp, elemsize); } pm->frame = writer->cfra; @@ -689,8 +689,8 @@ int BKE_ptcache_write_cache(PTCacheWriter *writer) pmdata = pm->data; for(i=0; itotelem; i++, pmdata+=incr) { - writer->set_elem(i, writer->calldata, &temp); - memcpy(pmdata, &temp, elemsize); + writer->set_elem(i, writer->calldata, temp); + memcpy(pmdata, temp, elemsize); } pm->frame = writer->cfra; -- cgit v1.2.3 From d7a7081e633f458d3c68f6ccff5376c0340fe42e Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 10 Jul 2009 00:32:13 +0000 Subject: NLA SoC: Tweaks from feedback from Broken + jez * Renamed the 'blend' blending mode to 'replace', since that's what it usually does * Drawing a darkened rect behind the keyframes shown in the action line -- * Fixed typo made last night which broke compiling * Consolidated all the keyframe-shape drawing code to use a single codebase. Even if we don't ultimately go with OpenGL keyframes, there's always a tidy option for that now. --- source/blender/blenkernel/intern/anim_sys.c | 2 +- source/blender/blenkernel/intern/ipo.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index ebe3d28cb21..19337f9de5d 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -859,7 +859,7 @@ static void nlaevalchan_accumulate (NlaEvalChannel *nec, NlaEvalStrip *nes, shor nec->value *= value; break; - case NLASTRIP_MODE_BLEND: + case NLASTRIP_MODE_REPLACE: default: // TODO: do we really want to blend by default? it seems more uses might prefer add... /* do linear interpolation * - the influence of the accumulated data (elsewhere, that is called dstweight) diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c index c3c5483574e..cf7e486613b 100644 --- a/source/blender/blenkernel/intern/ipo.c +++ b/source/blender/blenkernel/intern/ipo.c @@ -1518,7 +1518,7 @@ static void nlastrips_to_animdata (ID *id, ListBase *strips) /* blending */ strip->blendin= as->blendin; strip->blendout= as->blendout; - strip->blendmode= (as->mode==ACTSTRIPMODE_ADD) ? NLASTRIP_MODE_ADD : NLASTRIP_MODE_BLEND; + strip->blendmode= (as->mode==ACTSTRIPMODE_ADD) ? NLASTRIP_MODE_ADD : NLASTRIP_MODE_REPLACE; if (as->flag & ACTSTRIP_AUTO_BLENDS) strip->flag |= NLASTRIP_FLAG_AUTO_BLENDS; /* assorted setting flags */ -- cgit v1.2.3 From 3bf0400a6935b8d77404d86d3d0c5e6067d031cb Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Fri, 10 Jul 2009 16:55:49 +0000 Subject: 2.5 Render usability: - Option back to render to imagewindow, or fullscreen. The latter is default. Setting is stored in Scene. - Added button in output panel, the option "to new window" will follow! - F11 again toggles render view (moved MS Windows "full screen" to shift+F11 for now) --- source/blender/blenkernel/intern/image.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index ef0984bf93d..754ec06f23f 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -253,6 +253,10 @@ void free_image(Image *ima) if (ima->preview) { BKE_previewimg_free(&ima->preview); } + if (ima->render_text) { + MEM_freeN(ima->render_text); + ima->render_text= NULL; + } } /* only image block itself */ -- cgit v1.2.3 From 66a81a4062b8cc01452316c8eeb442b0acf2663e Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 10 Jul 2009 23:25:30 +0000 Subject: NLA SoC: Names for NLA Strips In order to be able to better identify NLA Strips (and to reduce the complexity of the text on them), I've implemented a name property for the strips. The names are made to be unique within the AnimData block the strip comes from, though this may not always happen if not enough relevant context info is present to validate this. --- source/blender/blenkernel/BKE_nla.h | 4 ++ source/blender/blenkernel/intern/nla.c | 93 ++++++++++++++++++++++++++++++++-- 2 files changed, 94 insertions(+), 3 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_nla.h b/source/blender/blenkernel/BKE_nla.h index 04d4b0f8da2..bb5a2782663 100644 --- a/source/blender/blenkernel/BKE_nla.h +++ b/source/blender/blenkernel/BKE_nla.h @@ -83,6 +83,10 @@ struct NlaStrip *BKE_nlastrip_find_active(struct NlaTrack *nlt); short BKE_nlastrip_within_bounds(struct NlaStrip *strip, float min, float max); +void BKE_nlastrip_validate_name(struct AnimData *adt, struct NlaStrip *strip); + +/* ............ */ + short BKE_nlatrack_has_animated_strips(struct NlaTrack *nlt); short BKE_nlatracks_have_animated_strips(ListBase *tracks); void BKE_nlastrip_validate_fcurves(struct NlaStrip *strip); diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index c697f639021..a240de209d9 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -30,12 +30,14 @@ #include #include #include +#include #include #include #include "MEM_guardedalloc.h" #include "BLI_blenlib.h" +#include "BLI_ghash.h" #include "DNA_anim_types.h" #include "DNA_action_types.h" @@ -326,6 +328,9 @@ NlaStrip *add_nlastrip_to_stack (AnimData *adt, bAction *act) BKE_nlatrack_add_strip(nlt, strip); } + /* automatically name it too */ + BKE_nlastrip_validate_name(adt, strip); + /* returns the strip added */ return strip; } @@ -503,7 +508,7 @@ float BKE_nla_tweakedit_remap (AnimData *adt, float cframe, short mode) } /* *************************************************** */ -/* Basic Utilities */ +/* NLA API */ /* List of Strips ------------------------------------ */ /* (these functions are used for NLA-Tracks and also for nested/meta-strips) */ @@ -1140,8 +1145,90 @@ void BKE_nlastrip_validate_fcurves (NlaStrip *strip) } } } - -/* Tools ------------------------------------------- */ + +/* Sanity Validation ------------------------------------ */ + +/* Find (and set) a unique name for a strip from the whole AnimData block + * Uses a similar method to the BLI method, but is implemented differently + * as we need to ensure that the name is unique over several lists of tracks, + * not just a single track. + */ +void BKE_nlastrip_validate_name (AnimData *adt, NlaStrip *strip) +{ + GHash *gh; + NlaStrip *tstrip; + NlaTrack *nlt; + + /* sanity checks */ + if ELEM(NULL, adt, strip) + return; + + /* give strip a default name if none already */ + if (strip->name[0]==0) { + switch (strip->type) { + case NLASTRIP_TYPE_CLIP: /* act-clip */ + sprintf(strip->name, "Act: %s", (strip->act)?(strip->act->id.name+2):("")); + break; + case NLASTRIP_TYPE_TRANSITION: /* transition */ + sprintf(strip->name, "Transition"); + break; + case NLASTRIP_TYPE_META: /* meta */ + sprintf(strip->name, "Meta"); + break; + default: + sprintf(strip->name, "NLA Strip"); + break; + } + } + + /* build a hash-table of all the strips in the tracks + * - this is easier than iterating over all the tracks+strips hierarchy everytime + * (and probably faster) + */ + gh= BLI_ghash_new(BLI_ghashutil_strhash, BLI_ghashutil_strcmp); + + for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) { + for (tstrip= nlt->strips.first; tstrip; tstrip= tstrip->next) { + /* don't add the strip of interest */ + if (tstrip == strip) + continue; + + /* use the name of the strip as the key, and the strip as the value, since we're mostly interested in the keys */ + BLI_ghash_insert(gh, tstrip->name, tstrip); + } + } + + /* if the hash-table has a match for this name, try other names... + * - in an extreme case, it might not be able to find a name, but then everything else in Blender would fail too :) + */ + if (BLI_ghash_haskey(gh, strip->name)) { + char tempname[128]; + int number = 1; + char *dot; + + /* Strip off the suffix */ + dot = strchr(strip->name, '.'); + if (dot) *dot=0; + + /* Try different possibilities */ + for (number = 1; number <= 999; number++) { + /* assemble alternative name */ + BLI_snprintf(tempname, 128, "%s%c%03d", strip->name, ".", number); + + /* if hash doesn't have this, set it */ + if (BLI_ghash_haskey(gh, tempname) == 0) { + BLI_strncpy(strip->name, tempname, sizeof(strip->name)); + break; + } + } + } + + /* free the hash... */ + BLI_ghash_free(gh, NULL, NULL); +} + + +/* Core Tools ------------------------------------------- */ /* For the given AnimData block, add the active action to the NLA * stack (i.e. 'push-down' action). The UI should only allow this -- cgit v1.2.3 From 1105ee701ed20d6301a174fc4285de00f8e0f95e Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sat, 11 Jul 2009 03:09:44 +0000 Subject: NLA SoC: Quick commit of skeleton of auto-blending setting code to be completed later... --- source/blender/blenkernel/intern/nla.c | 56 ++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index a240de209d9..457df9be7a9 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -1227,6 +1227,62 @@ void BKE_nlastrip_validate_name (AnimData *adt, NlaStrip *strip) BLI_ghash_free(gh, NULL, NULL); } +/* ---- */ + +/* Determine auto-blending for the given strip */ +void BKE_nlastrip_validate_autoblends (NlaTrack *nlt, NlaStrip *nls) +{ + NlaTrack *track; + NlaStrip *strip; + //float *ps=NULL, *pe=NULL; + //float *ns=NULL, *ne=NULL; + + /* sanity checks */ + if ELEM(NULL, nls, nlt) + return; + if ((nlt->prev == NULL) && (nlt->next == NULL)) + return; + if ((nls->flag & NLASTRIP_FLAG_AUTO_BLENDS)==0) + return; + + /* get test ranges */ + if (nlt->prev) { + /* find strips that overlap over the start/end of the given strip, + * but which don't cover the entire length + */ + track= nlt->prev; + for (strip= track->strips.first; strip; strip= strip->next) { + + } + } + if (nlt->next) { + /* find strips that overlap over the start/end of the given strip, + * but which don't cover the entire length + */ + track= nlt->next; + for (strip= track->strips.first; strip; strip= strip->next) { + + } + } +} + +/* Ensure that auto-blending and other settings are set correctly */ +void BKE_nla_validate_state (AnimData *adt) +{ + NlaStrip *strip; + NlaTrack *nlt; + + /* sanity checks */ + if ELEM(NULL, adt, adt->nla_tracks.first) + return; + + /* adjust blending values for auto-blending */ + for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) { + for (strip= nlt->strips.first; strip; strip= strip->next) { + BKE_nlastrip_validate_autoblends(nlt, strip); + } + } +} /* Core Tools ------------------------------------------- */ -- cgit v1.2.3 From 8a1caaed32717f88218ea0c6222c749c14648ab3 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 11 Jul 2009 11:31:49 +0000 Subject: Object mode select grouped operator (Shift+G and Select manu) Group option currently doesnt handle multiple groups. Set makefiles python version to 2.6 for linux since its common now. --- source/blender/blenkernel/BKE_context.h | 3 +++ source/blender/blenkernel/intern/context.c | 10 ++++++++++ 2 files changed, 13 insertions(+) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_context.h b/source/blender/blenkernel/BKE_context.h index f536e117b7b..92c79ff757f 100644 --- a/source/blender/blenkernel/BKE_context.h +++ b/source/blender/blenkernel/BKE_context.h @@ -186,6 +186,9 @@ int CTX_data_selected_bases(const bContext *C, ListBase *list); int CTX_data_visible_objects(const bContext *C, ListBase *list); int CTX_data_visible_bases(const bContext *C, ListBase *list); +int CTX_data_selectable_objects(const bContext *C, ListBase *list); +int CTX_data_selectable_bases(const bContext *C, ListBase *list); + struct Object *CTX_data_active_object(const bContext *C); struct Base *CTX_data_active_base(const bContext *C); struct Object *CTX_data_edit_object(const bContext *C); diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c index 4a68d90a4ed..1b499384886 100644 --- a/source/blender/blenkernel/intern/context.c +++ b/source/blender/blenkernel/intern/context.c @@ -606,6 +606,16 @@ int CTX_data_visible_bases(const bContext *C, ListBase *list) return ctx_data_collection_get(C, "visible_bases", list); } +int CTX_data_selectable_objects(const bContext *C, ListBase *list) +{ + return ctx_data_collection_get(C, "selectable_objects", list); +} + +int CTX_data_selectable_bases(const bContext *C, ListBase *list) +{ + return ctx_data_collection_get(C, "selectable_bases", list); +} + struct Object *CTX_data_active_object(const bContext *C) { return ctx_data_pointer_get(C, "active_object"); -- cgit v1.2.3 From 42469ba1e51c639c3fd317b812c486913d803fde Mon Sep 17 00:00:00 2001 From: "Guillermo S. Romero" Date: Sat, 11 Jul 2009 22:22:53 +0000 Subject: SVN maintenance. --- source/blender/blenkernel/intern/fmodifier.c | 2 +- source/blender/blenkernel/nla_private.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/fmodifier.c b/source/blender/blenkernel/intern/fmodifier.c index aa5214979d9..64558d0b456 100644 --- a/source/blender/blenkernel/intern/fmodifier.c +++ b/source/blender/blenkernel/intern/fmodifier.c @@ -1,5 +1,5 @@ /** - * $Id: fcurve.c 21299 2009-07-02 02:12:37Z aligorith $ + * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** * diff --git a/source/blender/blenkernel/nla_private.h b/source/blender/blenkernel/nla_private.h index df7ffaa3064..325798f325f 100644 --- a/source/blender/blenkernel/nla_private.h +++ b/source/blender/blenkernel/nla_private.h @@ -1,5 +1,5 @@ /** - * $Id: BKE_nla.h 20999 2009-06-19 04:45:56Z aligorith $ + * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** * -- cgit v1.2.3 From fa8bd34d95d91712ffa6dc9066c255e9ee40e7e4 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sun, 12 Jul 2009 04:29:36 +0000 Subject: NLA Bugfixes: * Fixed crash when anim-playback is running and a strip beside a transition gets transformed. Transition strips no-longer assume that their neighbours are action-clips, using the standard NLA-strip evaluation function instead to evaluate their neighbours. However, a check for ping-pong recursion needed to be added there, so that a transition beside a meta-strip, with the meta having a transition nested at the start of one of its levels, wouldn't fail with stack overflow. * Moved 'Tweak Mode' menu entry to Edit menu, since it's not really that modal. --- source/blender/blenkernel/intern/anim_sys.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 19337f9de5d..e4882d8f555 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -1049,12 +1049,12 @@ static void nlastrip_evaluate_transition (PointerRNA *ptr, ListBase *channels, L /* first strip */ tmp_nes.strip_mode= NES_TIME_TRANSITION_START; tmp_nes.strip= s1; - nlastrip_evaluate_actionclip(ptr, &tmp_channels, &tmp_modifiers, &tmp_nes); + nlastrip_evaluate(ptr, &tmp_channels, &tmp_modifiers, &tmp_nes); /* second strip */ tmp_nes.strip_mode= NES_TIME_TRANSITION_END; tmp_nes.strip= s2; - nlastrip_evaluate_actionclip(ptr, &tmp_channels, &tmp_modifiers, &tmp_nes); + nlastrip_evaluate(ptr, &tmp_channels, &tmp_modifiers, &tmp_nes); /* assumulate temp-buffer and full-buffer, using the 'real' strip */ @@ -1108,8 +1108,18 @@ static void nlastrip_evaluate_meta (PointerRNA *ptr, ListBase *channels, ListBas /* evaluates the given evaluation strip */ void nlastrip_evaluate (PointerRNA *ptr, ListBase *channels, ListBase *modifiers, NlaEvalStrip *nes) { + NlaStrip *strip= nes->strip; + + /* to prevent potential infinite recursion problems (i.e. transition strip, beside meta strip containing a transition + * several levels deep inside it), we tag the current strip as being evaluated, and clear this when we leave + */ + // TODO: be careful with this flag, since some edit tools may be running and have set this while animplayback was running + if (strip->flag & NLASTRIP_FLAG_EDIT_TOUCHED) + return; + strip->flag |= NLASTRIP_FLAG_EDIT_TOUCHED; + /* actions to take depend on the type of strip */ - switch (nes->strip->type) { + switch (strip->type) { case NLASTRIP_TYPE_CLIP: /* action-clip */ nlastrip_evaluate_actionclip(ptr, channels, modifiers, nes); break; @@ -1120,6 +1130,9 @@ void nlastrip_evaluate (PointerRNA *ptr, ListBase *channels, ListBase *modifiers nlastrip_evaluate_meta(ptr, channels, modifiers, nes); break; } + + /* clear temp recursion safe-check */ + strip->flag &= ~NLASTRIP_FLAG_EDIT_TOUCHED; } /* write the accumulated settings to */ -- cgit v1.2.3 From 6fb0181b50461b529bb960950870de941711041e Mon Sep 17 00:00:00 2001 From: Janne Karhu Date: Sun, 12 Jul 2009 23:38:47 +0000 Subject: Keyed physics refresh: - Keyed targets in one list instead of "chaining", this opens up many more possibilities than before and is much less obscure. - Better keyed timing possibilities (time & duration in frames). - Looping over keyed targets list. Other changes: - New child setting "length" with threshold (great for guard & underfur with a single particle system) - Modularization of path interpolation code. - Cleared "animateable" flags from many particle settings that shouldn't be animateable. Fixes: - Keyed particles weren't copied properly (ancient bug). - Hair rotations depended on global z-axis for root rotation so downward facing strands could flip rotation randomly. Now initial hair rotation is derived from face dependent hair matrix. (This caused for example ugly flipping of child strands on some cases). - Children from faces weren't calculated straight after activating them. - Multiple disk cache fixes: * Disk cache didn't work correctly with frame steps. * Conversion from memory cache to disk cache didn't work with cloth. * Disk cache crashed on some frames trying to close an already closed cache file. * Trails didn't work with disk cached particles. - Child rough effects were effected by emitter object loc/rot making them next to useless with animation, why didn't anybody tell me this!! - Lots of random code cleanup. --- source/blender/blenkernel/BKE_particle.h | 5 +- source/blender/blenkernel/intern/depsgraph.c | 15 +- source/blender/blenkernel/intern/object.c | 26 +- source/blender/blenkernel/intern/particle.c | 669 +++++++++++---------- source/blender/blenkernel/intern/particle_system.c | 279 +++++---- source/blender/blenkernel/intern/pointcache.c | 36 +- 6 files changed, 536 insertions(+), 494 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index aa24706077d..bb0b905b8e3 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -260,7 +260,6 @@ void psys_flush_particle_settings(struct Scene *scene, struct ParticleSettings * void make_local_particlesettings(struct ParticleSettings *part); struct LinkNode *psys_using_settings(struct Scene *scene, struct ParticleSettings *part, int flush_update); -void psys_changed_type(struct ParticleSystem *psys); void psys_reset(struct ParticleSystem *psys, int mode); void psys_find_parents(struct Object *ob, struct ParticleSystemModifierData *psmd, struct ParticleSystem *psys); @@ -289,12 +288,14 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, void psys_make_billboard(ParticleBillboardData *bb, float xvec[3], float yvec[3], float zvec[3], float center[3]); /* particle_system.c */ -int psys_count_keyed_targets(struct Object *ob, struct ParticleSystem *psys); +void 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 Scene *scene, struct Object *obsrc, struct Group *group, struct ParticleSystem *psys); void psys_end_effectors(struct ParticleSystem *psys); +void psys_make_temp_pointcache(struct Object *ob, struct ParticleSystem *psys); +void psys_end_temp_pointcache(struct ParticleSystem *psys); void psys_get_pointcache_start_end(struct Scene *scene, struct ParticleSystem *psys, int *sfra, int *efra); void particle_system_update(struct Scene *scene, struct Object *ob, struct ParticleSystem *psys); diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index de036e25d82..f52eec34cc7 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -562,10 +562,17 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O if(!psys_check_enabled(ob, psys)) continue; - 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, "Particle Keyed Physics"); + if(part->phystype==PART_PHYS_KEYED) { + KeyedParticleTarget *kpt = psys->keyed_targets.first; + + for(; kpt; kpt=kpt->next) { + if(kpt->ob && BLI_findlink(&kpt->ob->particlesystem, kpt->psys-1)) { + node2 = dag_get_node(dag, kpt->ob); + dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA|DAG_RL_OB_DATA, "Particle Keyed Physics"); + } + else + break; + } } if(part->ren_as == PART_DRAW_OB && part->dup_ob) { diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 6490ff3c724..7d6a83d7900 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -427,17 +427,14 @@ void unlink_object(Scene *scene, Object *ob) 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; + KeyedParticleTarget *kpt = tpsys->keyed_targets.first; + for(; kpt; kpt=kpt->next) { + if(kpt->ob==ob) { + BLI_remlink(&tpsys->keyed_targets, kpt); + MEM_freeN(kpt); + obt->recalc |= OB_RECALC_DATA; + break; } - else - tpsys->keyed_ob= NULL; - - obt->recalc |= OB_RECALC_DATA; } if(tpsys->target_ob==ob) { @@ -1050,18 +1047,23 @@ ParticleSystem *copy_particlesystem(ParticleSystem *psys) psysn= MEM_dupallocN(psys); psysn->particles= MEM_dupallocN(psys->particles); psysn->child= MEM_dupallocN(psys->child); + if(psysn->particles->keys) + psysn->particles->keys = MEM_dupallocN(psys->particles->keys); for(a=0, pa=psysn->particles; atotpart; a++, pa++) { if(pa->hair) pa->hair= MEM_dupallocN(pa->hair); - if(pa->keys) - pa->keys= MEM_dupallocN(pa->keys); + if(a) + pa->keys= (pa-1)->keys + (pa-1)->totkey; } if(psys->soft) { psysn->soft= copy_softbody(psys->soft); psysn->soft->particles = psysn; } + + if(psys->keyed_targets.first) + BLI_duplicatelist(&psysn->keyed_targets, &psys->keyed_targets); psysn->pathcache= NULL; psysn->childcache= NULL; diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 4488f8cdffd..cefeafcdd50 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -84,7 +84,8 @@ static void get_cpa_texture(DerivedMesh *dm, Material *ma, int face_index, static void get_child_modifier_parameters(ParticleSettings *part, ParticleThreadContext *ctx, ChildParticle *cpa, short cpa_from, int cpa_num, float *cpa_fuv, float *orco, ParticleTexture *ptex); static void do_child_modifiers(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSettings *part, - ParticleTexture *ptex, ParticleKey *par, float *par_rot, ChildParticle *cpa, float *orco, ParticleKey *state, float t); + ParticleTexture *ptex, ParticleKey *par, float *par_rot, ChildParticle *cpa, + float *orco, float mat[4][4], ParticleKey *state, float t); /* few helpers for countall etc. */ int count_particles(ParticleSystem *psys){ @@ -478,10 +479,16 @@ void psys_free(Object *ob, ParticleSystem * psys) if(psys->pointcache) BKE_ptcache_free(psys->pointcache); + if(psys->keyed_targets.first) + BLI_freelistN(&psys->keyed_targets); + MEM_freeN(psys); } } +/************************************************/ +/* Rendering */ +/************************************************/ /* these functions move away particle data and bring it back after * rendering, to make different render settings possible without * removing the previous data. this should be solved properly once */ @@ -889,7 +896,7 @@ int psys_render_simplify_params(ParticleSystem *psys, ChildParticle *cpa, float } /************************************************/ -/* Interpolated Particles */ +/* Interpolation */ /************************************************/ static float interpolate_particle_value(float v1, float v2, float v3, float v4, float *w, int four) { @@ -938,6 +945,214 @@ void psys_interpolate_particle(short type, ParticleKey keys[4], float dt, Partic +typedef struct ParticleInterpolationData { + ParticleKey *kkey[2]; + HairKey *hkey[2]; + BodyPoint *bp[2]; + SoftBody *soft; + int keyed, cached; + float birthtime, dietime; +} ParticleInterpolationData; +/* Assumes pointcache->mem_cache exists, so for disk cached particles call psys_make_temp_pointcache() before use */ +static void get_pointcache_keys_for_time(Object *ob, ParticleSystem *psys, int index, float t, ParticleKey *key1, ParticleKey *key2) +{ + PointCache *cache = psys->pointcache; + static PTCacheMem *pm = NULL; /* not thread safe */ + + if(index < 0) { /* initialize */ + pm = cache->mem_cache.first; + + if(pm) + pm = pm->next; + } + else { + if(pm) { + while(pm && pm->next && (float)pm->frame < t) + pm = pm->next; + + copy_particle_key(key2, ((ParticleKey *)pm->data) + index, 1); + copy_particle_key(key1, ((ParticleKey *)(pm->prev)->data) + index, 1); + } + else if(cache->mem_cache.first) { + PTCacheMem *pm2 = cache->mem_cache.first; + copy_particle_key(key2, ((ParticleKey *)pm2->data) + index, 1); + copy_particle_key(key1, ((ParticleKey *)pm2->data) + index, 1); + } + } +} +static void init_particle_interpolation(Object *ob, ParticleSystem *psys, ParticleData *pa, ParticleInterpolationData *pind) +{ + + if(pind->keyed) { + pind->kkey[0] = pa->keys; + + if(pa->totkey > 1) + pind->kkey[1] = pa->keys + 1; + else + pind->kkey[1] = NULL; + + pind->birthtime = pa->keys->time; + pind->dietime = (pa->keys + pa->totkey - 1)->time; + } + else if(pind->cached) { + get_pointcache_keys_for_time(ob, psys, -1, 0.0f, NULL, NULL); + + pind->birthtime = pa->time; + pind->dietime = pa->dietime; + } + else { + pind->hkey[0] = pa->hair; + pind->hkey[1] = pa->hair + 1; + + pind->birthtime = pa->hair->time; + pind->dietime = (pa->hair + pa->totkey - 1)->time; + } + + if(pind->soft) { + pind->bp[0] = pind->soft->bpoint + pa->bpi; + pind->bp[1] = pind->soft->bpoint + pa->bpi + 1; + } +} +static void hair_to_particle(ParticleKey *key, HairKey *hkey) +{ + VECCOPY(key->co, hkey->co); + key->time = hkey->time; +} +static void bp_to_particle(ParticleKey *key, BodyPoint *bp, HairKey *hkey) +{ + VECCOPY(key->co, bp->pos); + key->time = hkey->time; +} + +static void do_particle_interpolation(ParticleSystem *psys, int p, ParticleData *pa, float t, float frs_sec, ParticleInterpolationData *pind, ParticleKey *result) +{ + ParticleKey keys[4]; + float real_t, dfra, keytime; + + /* interpret timing and find keys */ + if(pind->keyed) { + /* we have only one key, so let's use that */ + if(pind->kkey[1]==NULL) { + copy_particle_key(result, pind->kkey[0], 1); + return; + } + + if(result->time < 0.0f) + real_t = -result->time; + else + real_t = pind->kkey[0]->time + t * (pind->kkey[0][pa->totkey-1].time - pind->kkey[0]->time); + + if(psys->part->phystype==PART_PHYS_KEYED && psys->flag & PSYS_KEYED_TIMING) { + KeyedParticleTarget *kpt = psys->keyed_targets.first; + + kpt=kpt->next; + + while(kpt && pa->time + kpt->time < real_t) + kpt= kpt->next; + + if(kpt) { + kpt=kpt->prev; + + if(pa->time + kpt->time + kpt->duration > real_t) + real_t = pa->time + kpt->time; + } + else + real_t = pa->time + ((KeyedParticleTarget*)psys->keyed_targets.last)->time; + } + + CLAMP(real_t, pa->time, pa->dietime); + + while(pind->kkey[1]->time < real_t) + pind->kkey[1]++; + + pind->kkey[0] = pind->kkey[1] - 1; + } + else if(pind->cached) { + if(result->time < 0.0f) /* flag for time in frames */ + real_t = -result->time; + else + real_t = pa->time + t * (pa->dietime - pa->time); + } + else { + if(result->time < 0.0f) + real_t = -result->time; + else + real_t = pind->hkey[0]->time + t * (pind->hkey[0][pa->totkey-1].time - pind->hkey[0]->time); + + while(pind->hkey[1]->time < real_t) { + pind->hkey[1]++; + pind->bp[1]++; + } + + pind->hkey[0] = pind->hkey[1] - 1; + } + + /* set actual interpolation keys */ + if(pind->soft) { + pind->bp[0] = pind->bp[1] - 1; + bp_to_particle(keys + 1, pind->bp[0], pind->hkey[0]); + bp_to_particle(keys + 2, pind->bp[1], pind->hkey[1]); + } + else if(pind->keyed) { + memcpy(keys + 1, pind->kkey[0], sizeof(ParticleKey)); + memcpy(keys + 2, pind->kkey[1], sizeof(ParticleKey)); + } + else if(pind->cached) { + get_pointcache_keys_for_time(NULL, psys, p, real_t, keys+1, keys+2); + } + else { + hair_to_particle(keys + 1, pind->hkey[0]); + hair_to_particle(keys + 2, pind->hkey[1]); + } + + /* set secondary interpolation keys for hair */ + if(!pind->keyed && !pind->cached) { + if(pind->soft) { + if(pind->hkey[0] != pa->hair) + bp_to_particle(keys, pind->bp[0] - 1, pind->hkey[0] - 1); + else + bp_to_particle(keys, pind->bp[0], pind->hkey[0]); + } + else { + if(pind->hkey[0] != pa->hair) + hair_to_particle(keys, pind->hkey[0] - 1); + else + hair_to_particle(keys, pind->hkey[0]); + } + + if(pind->soft) { + if(pind->hkey[1] != pa->hair + pa->totkey - 1) + bp_to_particle(keys + 3, pind->bp[1] + 1, pind->hkey[1] + 1); + else + bp_to_particle(keys + 3, pind->bp[1], pind->hkey[1]); + } + else { + if(pind->hkey[1] != pa->hair + pa->totkey - 1) + hair_to_particle(keys + 3, pind->hkey[1] + 1); + else + hair_to_particle(keys + 3, pind->hkey[1]); + } + } + + dfra = keys[2].time - keys[1].time; + keytime = (real_t - keys[1].time) / dfra; + + /* convert velocity to timestep size */ + if(pind->keyed || pind->cached){ + VecMulf(keys[1].vel, dfra / frs_sec); + VecMulf(keys[2].vel, dfra / frs_sec); + QuatInterpol(result->rot,keys[1].rot,keys[2].rot,keytime); + } + + /* now we should have in chronologiacl order k1<=k2<=t<=k3<=k4 with keytime between [0,1]->[k2,k3] (k1 & k4 used for cardinal & bspline interpolation)*/ + psys_interpolate_particle((pind->keyed || pind->cached) ? -1 /* signal for cubic interpolation */ + : ((psys->part->flag & PART_HAIR_BSPLINE) ? KEY_BSPLINE : KEY_CARDINAL) + ,keys, keytime, result, 1); + + /* the velocity needs to be converted back from cubic interpolation */ + if(pind->keyed || pind->cached) + VecMulf(result->vel, frs_sec / dfra); +} /************************************************/ /* Particles on a dm */ /************************************************/ @@ -1438,16 +1653,6 @@ void psys_particle_on_emitter(ParticleSystemModifierData *psmd, int from, int in /************************************************/ /* Path Cache */ /************************************************/ -static void hair_to_particle(ParticleKey *key, HairKey *hkey) -{ - VECCOPY(key->co, hkey->co); - key->time = hkey->time; -} -static void bp_to_particle(ParticleKey *key, BodyPoint *bp, HairKey *hkey) -{ - VECCOPY(key->co, bp->pos); - key->time = hkey->time; -} static float vert_weight(MDeformVert *dvert, int group) { MDeformWeight *dw; @@ -1734,7 +1939,7 @@ int do_guide(Scene *scene, ParticleKey *state, int pa_num, float time, ListBase } return 0; } -static void do_rough(float *loc, float t, float fac, float size, float thres, ParticleKey *state) +static void do_rough(float *loc, float mat[4][4], float t, float fac, float size, float thres, ParticleKey *state) { float rough[3]; float rco[3]; @@ -1747,32 +1952,24 @@ static void do_rough(float *loc, float t, float fac, float size, float thres, Pa rough[0]=-1.0f+2.0f*BLI_gTurbulence(size, rco[0], rco[1], rco[2], 2,0,2); rough[1]=-1.0f+2.0f*BLI_gTurbulence(size, rco[1], rco[2], rco[0], 2,0,2); rough[2]=-1.0f+2.0f*BLI_gTurbulence(size, rco[2], rco[0], rco[1], 2,0,2); - VECADDFAC(state->co,state->co,rough,fac); + + VECADDFAC(state->co,state->co,mat[0],fac*rough[0]); + VECADDFAC(state->co,state->co,mat[1],fac*rough[1]); + VECADDFAC(state->co,state->co,mat[2],fac*rough[2]); } -static void do_rough_end(float *loc, float t, float fac, float shape, ParticleKey *state, ParticleKey *par) +static void do_rough_end(float *loc, float mat[4][4], float t, float fac, float shape, ParticleKey *state) { - float rough[3], rnor[3]; + float rough[2]; float roughfac; roughfac=fac*(float)pow((double)t,shape); VECCOPY(rough,loc); rough[0]=-1.0f+2.0f*rough[0]; rough[1]=-1.0f+2.0f*rough[1]; - rough[2]=-1.0f+2.0f*rough[2]; VecMulf(rough,roughfac); - - if(par){ - VECCOPY(rnor,par->vel); - } - else{ - VECCOPY(rnor,state->vel); - } - Normalize(rnor); - Projf(rnor,rough,rnor); - VECSUB(rough,rough,rnor); - - VECADD(state->co,state->co,rough); + VECADDFAC(state->co,state->co,mat[0],rough[0]); + VECADDFAC(state->co,state->co,mat[1],rough[1]); } static void do_path_effectors(Scene *scene, Object *ob, ParticleSystem *psys, int i, ParticleCacheKey *ca, int k, int steps, float *rootco, float effector, float dfra, float cfra, float *length, float *vec) { @@ -2007,7 +2204,7 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, ParticleData *pa=NULL; ParticleTexture ptex; float *cpa_fuv=0, *par_rot=0; - float co[3], orco[3], ornor[3], t, cpa_1st[3], dvec[3]; + float co[3], orco[3], ornor[3], hairmat[4][4], t, cpa_1st[3], dvec[3]; float branch_begin, branch_end, branch_prob, rough_rand; float length, max_length = 1.0f, cur_length = 0.0f; float eff_length, eff_vec[3]; @@ -2065,8 +2262,6 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, cpa_num = cpa->num; foffset= cpa->foffset; - if(part->childtype == PART_CHILD_FACES) - foffset = -(2.0f + part->childspread); cpa_fuv = cpa->fuv; cpa_from = PART_FROM_FACE; @@ -2078,6 +2273,10 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, Mat4MulVecfl(ob->obmat,cpa_1st); } + pa = psys->particles + cpa->parent; + + psys_mat_hair_to_global(ob, ctx->psmd->dm, psys->part->from, pa, hairmat); + pa=0; } else{ @@ -2099,6 +2298,8 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, cpa_fuv=pa->fuv; psys_particle_on_emitter(ctx->psmd,cpa_from,cpa_num,DMCACHE_ISCHILD,cpa_fuv,pa->foffset,co,ornor,0,0,orco,0); + + psys_mat_hair_to_global(ob, ctx->psmd->dm, psys->part->from, pa, hairmat); } keys->steps = ctx->steps; @@ -2190,7 +2391,7 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, } /* apply different deformations to the child path */ - do_child_modifiers(ctx->scene, ob, psys, part, &ptex, (ParticleKey *)par, par_rot, cpa, orco, (ParticleKey *)state, t); + do_child_modifiers(ctx->scene, ob, psys, part, &ptex, (ParticleKey *)par, par_rot, cpa, orco, hairmat, (ParticleKey *)state, t); /* TODO: better branching */ //if(part->flag & PART_BRANCHING && ctx->between == 0 && part->flag & PART_ANIM_BRANCHING) @@ -2247,20 +2448,12 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, /* check if path needs to be cut before actual end of data points */ if(k){ VECSUB(dvec,state->co,(state-1)->co); - if(part->flag&PART_ABS_LENGTH) - length=VecLength(dvec); - else - length=1.0f/(float)ctx->steps; - + length=1.0f/(float)ctx->steps; k=check_path_length(k,keys,state,max_length,&cur_length,length,dvec); } else{ /* initialize length calculation */ - if(part->flag&PART_ABS_LENGTH) - max_length= part->abslength*ptex.length; - else - max_length= ptex.length; - + max_length= ptex.length; cur_length= 0.0f; } @@ -2353,36 +2546,6 @@ void psys_cache_child_paths(Scene *scene, Object *ob, ParticleSystem *psys, floa psys_threads_free(pthreads); } -static void get_pointcache_keys_for_time(ParticleSystem *psys, int index, float t, ParticleKey *key1, ParticleKey *key2) -{ - PointCache *cache = psys->pointcache; - static PTCacheMem *pm = NULL; - - if(cache->flag & PTCACHE_DISK_CACHE) { - /* TODO */ - } - else { - if(index < 0) { /* initialize */ - pm = cache->mem_cache.first; - if(pm) - pm = pm->next; - } - else { - if(pm) { - while(pm && pm->next && (float)pm->frame < t) - pm = pm->next; - - copy_particle_key(key2, ((ParticleKey *)pm->data) + index, 1); - copy_particle_key(key1, ((ParticleKey *)(pm->prev)->data) + index, 1); - } - else if(cache->mem_cache.first) { - pm = cache->mem_cache.first; - copy_particle_key(key2, ((ParticleKey *)pm->data) + index, 1); - copy_particle_key(key1, ((ParticleKey *)pm->data) + index, 1); - } - } - } -} /* Calculates paths ready for drawing/rendering. */ /* -Usefull for making use of opengl vertex arrays for super fast strand drawing. */ /* -Makes child strands possible and creates them too into the cache. */ @@ -2395,7 +2558,7 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra ParticleSettings *part = psys->part; ParticleData *pa; - ParticleKey keys[4], result, *kkey[2] = {NULL, NULL}; + ParticleKey result, *kkey[2] = {NULL, NULL}; HairKey *hkey[2] = {NULL, NULL}; ParticleEdit *edit = 0; @@ -2405,11 +2568,14 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra BodyPoint *bp[2] = {NULL, NULL}; Material *ma; + + ParticleInterpolationData pind; float birthtime = 0.0, dietime = 0.0; float t, time = 0.0, keytime = 0.0, dfra = 1.0, frs_sec = scene->r.frs_sec; float col[4] = {0.5f, 0.5f, 0.5f, 1.0f}; float prev_tangent[3], hairmat[4][4]; + float rotmat[3][3]; int k,i; int steps = (int)pow(2.0, (double)psys->part->draw_step); int totpart = psys->totpart; @@ -2492,7 +2658,6 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra else memset(cache[i], 0, sizeof(*cache[i])*(steps+1)); if(!edit && !psys->totchild) { - //pa_length = part->length * (1.0f - part->randlength*pa->r_ave[0]); pa_length = 1.0f - part->randlength * 0.5 * (1.0f + pa->r_ave[0]); if(vg_length) pa_length *= psys_particle_value_from_verts(psmd->dm,part->from,pa,vg_length); @@ -2504,38 +2669,27 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra ekey = edit->keys[i]; /*--get the first data points--*/ - if(keyed) { - kkey[0] = pa->keys; - kkey[1] = kkey[0] + 1; + pind.keyed = keyed; + pind.cached = baked; + pind.soft = soft; + init_particle_interpolation(ob, psys, pa, &pind); - birthtime = kkey[0]->time; - dietime = kkey[0][pa->totkey-1].time; - } - else if(baked) { - get_pointcache_keys_for_time(psys, -1, 0.0f, NULL, NULL); - - birthtime = pa->time; - dietime = pa->dietime; - } - else { - hkey[0] = pa->hair; - hkey[1] = hkey[0] + 1; - birthtime = hkey[0]->time; - dietime = hkey[0][pa->totkey-1].time; - - psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat); - } + /* hairmat is needed for for non-hair particle too so we get proper rotations */ + psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat); + VECCOPY(rotmat[0], hairmat[2]); + VECCOPY(rotmat[1], hairmat[1]); + VECCOPY(rotmat[2], hairmat[0]); if(!edit) { if(part->draw & PART_ABS_PATH_TIME) { - birthtime = MAX2(birthtime, part->path_start); - dietime = MIN2(dietime, part->path_end); + birthtime = MAX2(pind.birthtime, part->path_start); + dietime = MIN2(pind.dietime, part->path_end); } else { - float tb = birthtime; - birthtime = tb + part->path_start * (dietime - tb); - dietime = tb + part->path_end * (dietime - tb); + float tb = pind.birthtime; + birthtime = tb + part->path_start * (pind.dietime - tb); + dietime = tb + part->path_end * (pind.dietime - tb); } if(birthtime >= dietime) { @@ -2546,101 +2700,18 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra dietime = birthtime + pa_length * (dietime - birthtime); } - if(soft){ - bp[0] = soft->bpoint + pa->bpi; - bp[1] = bp[0] + 1; - } - /*--interpolate actual path from data points--*/ for(k=0, ca=cache[i]; k<=steps; k++, ca++){ time = (float)k / (float)steps; t = birthtime + time * (dietime - birthtime); - if(keyed) { - while(kkey[1]->time < t) { - kkey[1]++; - } + result.time = -t; - kkey[0] = kkey[1] - 1; - } - else if(baked) { - get_pointcache_keys_for_time(psys, i, t, keys+1, keys+2); - } - else { - while(hkey[1]->time < t) { - hkey[1]++; - bp[1]++; - } - - hkey[0] = hkey[1] - 1; - } + do_particle_interpolation(psys, i, pa, t, frs_sec, &pind, &result); - if(soft) { - bp[0] = bp[1] - 1; - bp_to_particle(keys + 1, bp[0], hkey[0]); - bp_to_particle(keys + 2, bp[1], hkey[1]); - } - else if(keyed) { - memcpy(keys + 1, kkey[0], sizeof(ParticleKey)); - memcpy(keys + 2, kkey[1], sizeof(ParticleKey)); - } - else if(baked) - ; /* keys already set */ - else { - hair_to_particle(keys + 1, hkey[0]); - hair_to_particle(keys + 2, hkey[1]); - } - - - if(!keyed && !baked) { - if(soft) { - if(hkey[0] != pa->hair) - bp_to_particle(keys, bp[0] - 1, hkey[0] - 1); - else - bp_to_particle(keys, bp[0], hkey[0]); - } - else { - if(hkey[0] != pa->hair) - hair_to_particle(keys, hkey[0] - 1); - else - hair_to_particle(keys, hkey[0]); - } - - if(soft) { - if(hkey[1] != pa->hair + pa->totkey - 1) - bp_to_particle(keys + 3, bp[1] + 1, hkey[1] + 1); - else - bp_to_particle(keys + 3, bp[1], hkey[1]); - } - else { - if(hkey[1] != pa->hair + pa->totkey - 1) - hair_to_particle(keys + 3, hkey[1] + 1); - else - hair_to_particle(keys + 3, hkey[1]); - } - } - - dfra = keys[2].time - keys[1].time; - - keytime = (t - keys[1].time) / dfra; - - /* convert velocity to timestep size */ - if(keyed || baked){ - VecMulf(keys[1].vel, dfra / frs_sec); - VecMulf(keys[2].vel, dfra / frs_sec); - } - - /* now we should have in chronologiacl order k1<=k2<=t<=k3<=k4 with keytime between [0,1]->[k2,k3] (k1 & k4 used for cardinal & bspline interpolation)*/ - psys_interpolate_particle((keyed || baked) ? -1 /* signal for cubic interpolation */ - : ((psys->part->flag & PART_HAIR_BSPLINE) ? KEY_BSPLINE : KEY_CARDINAL) - ,keys, keytime, &result, 0); - - /* the velocity needs to be converted back from cubic interpolation */ - if(keyed || baked){ - VecMulf(result.vel, frs_sec / dfra); - } - else if(soft==NULL) { /* softbody and keyed are allready in global space */ + /* keyed, baked and softbody are allready in global space */ + if(!keyed && !baked && !soft) { Mat4MulVecfl(hairmat, result.co); } @@ -2678,8 +2749,9 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra VECCOPY(ca->col, col); } } + - /*--modify paths--*/ + /*--modify paths and calculate rotation & velocity--*/ VecSubf(vec,(cache[i]+1)->co,cache[i]->co); length = VecLength(vec); @@ -2708,12 +2780,18 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra float cosangle, angle, tangent[3], normal[3], q[4]; if(k == 1) { + /* calculate initial tangent for incremental rotations */ VECSUB(tangent, ca->co, (ca - 1)->co); - - vectoquat(tangent, OB_POSX, OB_POSZ, (ca-1)->rot); - VECCOPY(prev_tangent, tangent); Normalize(prev_tangent); + + /* First rotation is based on emitting face orientation. */ + /* This is way better than having flipping rotations resulting */ + /* from using a global axis as a rotation pole (vec_to_quat()). */ + /* It's not an ideal solution though since it disregards the */ + /* initial tangent, but taking that in to account will allow */ + /* the possibility of flipping again. -jahka */ + Mat3ToQuat_is_ok(rotmat, (ca-1)->rot); } else { VECSUB(tangent, ca->co, (ca - 1)->co); @@ -2780,15 +2858,6 @@ void copy_particle_key(ParticleKey *to, ParticleKey *from, int time){ memcpy(to,from,sizeof(ParticleKey)); to->time=to_time; } - /* - VECCOPY(to->co,from->co); - VECCOPY(to->vel,from->vel); - QUATCOPY(to->rot,from->rot); - if(time) - to->time=from->time; - to->flag=from->flag; - to->sbw=from->sbw; - */ } void psys_get_from_key(ParticleKey *key, float *loc, float *vel, float *rot, float *time){ if(loc) VECCOPY(loc,key->co); @@ -3017,8 +3086,6 @@ static void default_particle_settings(ParticleSettings *part) part->totpart= 1000; part->grid_res= 10; part->timetweak= 1.0; - part->keyed_time= 0.5; - //part->userjit; part->integrator= PART_INT_MIDPOINT; part->phystype= PART_PHYS_NEWTON; @@ -3032,7 +3099,6 @@ static void default_particle_settings(ParticleSettings *part) part->reactevent= PART_EVENT_DEATH; part->disp=100; part->from= PART_FROM_FACE; - part->length= 1.0; part->nbetween= 4; part->boidneighbours= 5; @@ -3059,10 +3125,15 @@ static void default_particle_settings(ParticleSettings *part) part->rough2_size=1.0; part->rough_end_shape=1.0; + part->clength=1.0f; + part->clength_thres=0.0f; + part->draw_line[0]=0.5; part->path_start = 0.0f; part->path_end = 1.0f; + part->keyed_loops = 1; + part->banking=1.0; part->max_bank=1.0; @@ -3480,7 +3551,7 @@ float psys_get_child_size(ParticleSystem *psys, ChildParticle *cpa, float cfra, } static void get_child_modifier_parameters(ParticleSettings *part, ParticleThreadContext *ctx, ChildParticle *cpa, short cpa_from, int cpa_num, float *cpa_fuv, float *orco, ParticleTexture *ptex) { - ptex->length=part->length*(1.0f - part->randlength*cpa->rand[0]); + ptex->length= 1.0f - part->randlength*cpa->rand[0]; ptex->clump=1.0; ptex->kink=1.0; ptex->rough1= 1.0; @@ -3489,6 +3560,8 @@ static void get_child_modifier_parameters(ParticleSettings *part, ParticleThread ptex->exist= 1.0; ptex->effector= 1.0; + ptex->length*= part->clength_thres < cpa->rand[1] ? part->clength : 1.0f; + get_cpa_texture(ctx->dm,ctx->ma,cpa_num,cpa_fuv,orco,ptex, MAP_PA_DENS|MAP_PA_LENGTH|MAP_PA_CLUMP|MAP_PA_KINK|MAP_PA_ROUGH); @@ -3511,7 +3584,7 @@ static void get_child_modifier_parameters(ParticleSettings *part, ParticleThread if(ctx->vg_effector) ptex->effector*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_effector); } -static void do_child_modifiers(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSettings *part, ParticleTexture *ptex, ParticleKey *par, float *par_rot, ChildParticle *cpa, float *orco, ParticleKey *state, float t) +static void do_child_modifiers(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSettings *part, ParticleTexture *ptex, ParticleKey *par, float *par_rot, ChildParticle *cpa, float *orco, float mat[4][4], ParticleKey *state, float t) { int guided = 0; @@ -3528,13 +3601,13 @@ static void do_child_modifiers(Scene *scene, Object *ob, ParticleSystem *psys, P } if(part->rough1 != 0.0 && ptex->rough1 != 0.0) - do_rough(orco, t, ptex->rough1*part->rough1, part->rough1_size, 0.0, state); + do_rough(orco, mat, t, ptex->rough1*part->rough1, part->rough1_size, 0.0, state); if(part->rough2 != 0.0 && ptex->rough2 != 0.0) - do_rough(cpa->rand, t, ptex->rough2*part->rough2, part->rough2_size, part->rough2_thres, state); + do_rough(cpa->rand, mat, t, ptex->rough2*part->rough2, part->rough2_size, part->rough2_thres, state); if(part->rough_end != 0.0 && ptex->roughe != 0.0) - do_rough_end(cpa->rand, t, ptex->roughe*part->rough_end, part->rough_end_shape, state, par); + do_rough_end(cpa->rand, mat, t, ptex->roughe*part->rough_end, part->rough_end_shape, state); } /* get's hair (or keyed) particles state at the "path time" specified in state->time */ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, int p, ParticleKey *state, int vel) @@ -3549,8 +3622,9 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i HairKey *hkey[2] = {NULL, NULL}; ParticleKey *par=0, keys[4], tstate; ParticleThreadContext ctx; /* fake thread context for child modifiers */ + ParticleInterpolationData pind; - float t, real_t, dfra, keytime, frs_sec = scene->r.frs_sec; + float t, frs_sec = scene->r.frs_sec; float co[3], orco[3]; float hairmat[4][4]; int totparent = 0; @@ -3558,7 +3632,7 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i int totchild = psys->totchild; short between = 0, edit = 0; - int keyed = psys->flag & PSYS_KEYED; + int keyed = part->phystype & PART_PHYS_KEYED && psys->flag & PSYS_KEYED; int cached = !keyed && part->type != PART_HAIR; float *cpa_fuv; int cpa_num; short cpa_from; @@ -3580,88 +3654,14 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i key_from_object(pa->stick_ob,state); return; } - - if(keyed) { - kkey[0] = pa->keys; - kkey[1] = kkey[0] + 1; - if(state->time < 0.0f) - real_t = -state->time; - else - real_t = kkey[0]->time + t * (kkey[0][pa->totkey-1].time - kkey[0]->time); - } - else if(cached) { - get_pointcache_keys_for_time(psys, -1, 0.0f, NULL, NULL); - } - else { - hkey[0] = pa->hair; - hkey[1] = pa->hair + 1; - - if(state->time < 0.0f) - real_t = -state->time; - else - real_t = hkey[0]->time + t * (hkey[0][pa->totkey-1].time - hkey[0]->time); - } - - if(keyed) { - while(kkey[1]->time < real_t) { - kkey[1]++; - } - kkey[0] = kkey[1] - 1; - - memcpy(keys + 1, kkey[0], sizeof(ParticleKey)); - memcpy(keys + 2, kkey[1], sizeof(ParticleKey)); - } - else if(cached) { - if(state->time < 0.0f) /* flag for time in frames */ - real_t = -state->time; - else - real_t = pa->time + t * (pa->dietime - pa->time); - - get_pointcache_keys_for_time(psys, p, real_t, keys+1, keys+2); - } - else { - while(hkey[1]->time < real_t) - hkey[1]++; - - hkey[0] = hkey[1] - 1; - - hair_to_particle(keys + 1, hkey[0]); - hair_to_particle(keys + 2, hkey[1]); - } + pind.keyed = keyed; + pind.cached = cached; + pind.soft = NULL; + init_particle_interpolation(ob, psys, pa, &pind); + do_particle_interpolation(psys, p, pa, t, frs_sec, &pind, state); if(!keyed && !cached) { - if(hkey[0] != pa->hair) - hair_to_particle(keys, hkey[0] - 1); - else - hair_to_particle(keys, hkey[0]); - - if(hkey[1] != pa->hair + pa->totkey - 1) - hair_to_particle(keys + 3, hkey[1] + 1); - else - hair_to_particle(keys + 3, hkey[1]); - } - - dfra = keys[2].time - keys[1].time; - - keytime = (real_t - keys[1].time) / dfra; - - /* convert velocity to timestep size */ - if(keyed || cached){ - VecMulf(keys[1].vel, dfra / frs_sec); - VecMulf(keys[2].vel, dfra / frs_sec); - QuatInterpol(state->rot,keys[1].rot,keys[2].rot,keytime); - } - - psys_interpolate_particle((keyed || cached) ? -1 /* signal for cubic interpolation */ - : ((psys->part->flag & PART_HAIR_BSPLINE) ? KEY_BSPLINE : KEY_CARDINAL) - ,keys, keytime, state, 1); - - /* the velocity needs to be converted back from cubic interpolation */ - if(keyed || cached){ - VecMulf(state->vel, frs_sec / dfra); - } - else { if((pa->flag & PARS_REKEY)==0) { psys_mat_hair_to_global(ob, psmd->dm, part->from, pa, hairmat); Mat4MulVecfl(hairmat, state->co); @@ -3709,8 +3709,6 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i cpa_num=cpa->num; foffset= cpa->foffset; - if(part->childtype == PART_CHILD_FACES) - foffset = -(2.0f + part->childspread); cpa_fuv = cpa->fuv; cpa_from = PART_FROM_FACE; @@ -3721,11 +3719,14 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i //Mat4MulVecfl(ob->obmat,cpa_1st); + pa = psys->particles + cpa->parent; + + psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat); + pa=0; } else{ /* get the parent state */ - keys->time = state->time; psys_get_particle_on_path(scene, ob, psys, cpa->parent, keys,1); @@ -3737,6 +3738,8 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i cpa_fuv=pa->fuv; psys_particle_on_emitter(psmd,cpa_from,cpa_num,DMCACHE_ISCHILD,cpa_fuv,pa->foffset,co,0,0,0,orco,0); + + psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat); } /* correct child ipo timing */ @@ -3785,7 +3788,7 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i copy_particle_key(&tstate, state, 1); /* apply different deformations to the child path */ - do_child_modifiers(scene, ob, psys, part, &ptex, par, par->rot, cpa, orco, state, t); + do_child_modifiers(scene, ob, psys, part, &ptex, par, par->rot, cpa, orco, hairmat, state, t); /* try to estimate correct velocity */ if(vel){ @@ -3856,7 +3859,7 @@ int psys_get_particle_state(struct Scene *scene, Object *ob, ParticleSystem *psy state->time= (cfra-(part->sta+(part->end-part->sta)*cpa->rand[0]))/(part->lifetime*cpa->rand[1]); } else - state->time= (cfra-pa->time)/(pa->dietime-pa->time); + state->time= -cfra; psys_get_particle_on_path(scene, ob, psys, p, state,1); return 1; @@ -3893,57 +3896,55 @@ int psys_get_particle_state(struct Scene *scene, Object *ob, ParticleSystem *psy calc_latt_deform(psys->lattice, state->co,1.0f); } else{ - if (pa) { /* TODO PARTICLE - should this ever be NULL? - Campbell */ - if(pa->state.time==state->time || ELEM(part->phystype,PART_PHYS_NO,PART_PHYS_KEYED)) - copy_particle_key(state, &pa->state, 1); - else if(pa->prev_state.time==state->time) - copy_particle_key(state, &pa->prev_state, 1); - else { - /* let's interpolate to try to be as accurate as possible */ - if(pa->state.time + 1.0f > state->time && pa->prev_state.time - 1.0f < state->time) { - ParticleKey keys[4]; - float dfra, keytime, frs_sec = scene->r.frs_sec; + if(pa->state.time==state->time || ELEM(part->phystype,PART_PHYS_NO,PART_PHYS_KEYED)) + copy_particle_key(state, &pa->state, 1); + else if(pa->prev_state.time==state->time) + copy_particle_key(state, &pa->prev_state, 1); + else { + /* let's interpolate to try to be as accurate as possible */ + if(pa->state.time + 1.0f > state->time && pa->prev_state.time - 1.0f < state->time) { + ParticleKey keys[4]; + float dfra, keytime, frs_sec = scene->r.frs_sec; - if(pa->prev_state.time >= pa->state.time) { - /* prev_state is wrong so let's not use it, this can happen at frame 1 or particle birth */ - copy_particle_key(state, &pa->state, 1); + if(pa->prev_state.time >= pa->state.time) { + /* prev_state is wrong so let's not use it, this can happen at frame 1 or particle birth */ + copy_particle_key(state, &pa->state, 1); - VECADDFAC(state->co, state->co, state->vel, (state->time-pa->state.time)/frs_sec); - } - else { - copy_particle_key(keys+1, &pa->prev_state, 1); - copy_particle_key(keys+2, &pa->state, 1); + VECADDFAC(state->co, state->co, state->vel, (state->time-pa->state.time)/frs_sec); + } + else { + copy_particle_key(keys+1, &pa->prev_state, 1); + copy_particle_key(keys+2, &pa->state, 1); - dfra = keys[2].time - keys[1].time; + dfra = keys[2].time - keys[1].time; - keytime = (state->time - keys[1].time) / dfra; + keytime = (state->time - keys[1].time) / dfra; - /* convert velocity to timestep size */ - VecMulf(keys[1].vel, dfra / frs_sec); - VecMulf(keys[2].vel, dfra / frs_sec); - - psys_interpolate_particle(-1, keys, keytime, state, 1); - - /* convert back to real velocity */ - VecMulf(state->vel, frs_sec / dfra); + /* convert velocity to timestep size */ + VecMulf(keys[1].vel, dfra / frs_sec); + VecMulf(keys[2].vel, dfra / frs_sec); + + psys_interpolate_particle(-1, keys, keytime, state, 1); + + /* convert back to real velocity */ + VecMulf(state->vel, frs_sec / dfra); - VecLerpf(state->ave, keys[1].ave, keys[2].ave, keytime); - QuatInterpol(state->rot, keys[1].rot, keys[2].rot, keytime); - } - } - else { - /* extrapolating over big ranges is not accurate so let's just give something close to reasonable back */ - copy_particle_key(state, &pa->state, 0); + VecLerpf(state->ave, keys[1].ave, keys[2].ave, keytime); + QuatInterpol(state->rot, keys[1].rot, keys[2].rot, keytime); } } - - if(pa->alive==PARS_DEAD && part->flag&PART_STICKY && pa->flag&PARS_STICKY && pa->stick_ob){ - key_from_object(pa->stick_ob,state); + else { + /* extrapolating over big ranges is not accurate so let's just give something close to reasonable back */ + copy_particle_key(state, &pa->state, 0); } + } - if(psys->lattice) - calc_latt_deform(psys->lattice, state->co,1.0f); + if(pa->alive==PARS_DEAD && part->flag&PART_STICKY && pa->flag&PARS_STICKY && pa->stick_ob){ + key_from_object(pa->stick_ob,state); } + + if(psys->lattice) + calc_latt_deform(psys->lattice, state->co,1.0f); } return 1; diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 07e0e82a86d..56ca3e8e22b 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -111,10 +111,7 @@ static int get_current_display_percentage(ParticleSystem *psys) return 100; if(part->phystype==PART_PHYS_KEYED){ - if(psys->flag & PSYS_FIRST_KEYED) - return psys->part->disp; - else - return 100; + return psys->part->disp; } else return psys->part->disp; @@ -199,7 +196,7 @@ static void realloc_particles(Object *ob, ParticleSystem *psys, int new_totpart) if(psys->particles->keys) MEM_freeN(psys->particles->keys); - for(i=0, pa=psys->particles; itotpart; i++, pa++) + for(i=0, pa=newpars; ikeys) { pa->keys= NULL; pa->totkey= 0; @@ -1976,64 +1973,59 @@ static void reset_all_particles(Scene *scene, Object *ob, ParticleSystem *psys, /************************************************/ /* Keyed particles */ /************************************************/ -/* a bit of an unintuitive function :) counts objects in a keyed chain and returns 1 if some of them were selected (used in drawing) */ -int psys_count_keyed_targets(Object *ob, ParticleSystem *psys) +/* Counts valid keyed targets */ +void psys_count_keyed_targets(Object *ob, ParticleSystem *psys) { - ParticleSystem *kpsys=psys,*tpsys; - ParticleSettings *tpart; - Object *kob=ob,*tob; - int select=ob->flag&SELECT; - short totkeyed=0; - Base *base; - - ListBase lb; - lb.first=lb.last=0; - - tob=psys->keyed_ob; - while(tob){ - if((tpsys=BLI_findlink(&tob->particlesystem,kpsys->keyed_psys-1))){ - tpart=tpsys->part; - - if(tpart->phystype==PART_PHYS_KEYED){ - if(lb.first){ - for(base=lb.first;base;base=base->next){ - if(tob==base->object){ - fprintf(stderr,"Error: loop in keyed chain!\n"); - BLI_freelistN(&lb); - return select; - } - } - } - base=MEM_callocN(sizeof(Base), "keyed base"); - base->object=tob; - BLI_addtail(&lb,base); - - if(tob->flag&SELECT) - select++; - kob=tob; - kpsys=tpsys; - tob=tpsys->keyed_ob; - totkeyed++; + ParticleSystem *kpsys; + KeyedParticleTarget *kpt = psys->keyed_targets.first; + int psys_num = BLI_findindex(&ob->particlesystem, psys); + int keys_valid = 1; + psys->totkeyed = 0; + + for(; kpt; kpt=kpt->next) { + kpsys = NULL; + if(kpt->ob==ob || kpt->ob==NULL) { + if(kpt->psys >= psys_num) + kpsys = BLI_findlink(&ob->particlesystem, kpt->psys-1); + + if(kpsys && kpsys->totpart) { + kpt->flag |= KEYED_TARGET_VALID; + psys->totkeyed += keys_valid; + if(psys->flag & PSYS_KEYED_TIMING && kpt->duration != 0.0f) + psys->totkeyed += 1; } - else{ - tob=0; - totkeyed++; + else { + kpt->flag &= ~KEYED_TARGET_VALID; + keys_valid = 0; + } + } + else { + if(kpt->ob) + kpsys = BLI_findlink(&kpt->ob->particlesystem, kpt->psys-1); + + if(kpsys && kpsys->totpart) { + kpt->flag |= KEYED_TARGET_VALID; + psys->totkeyed += keys_valid; + if(psys->flag & PSYS_KEYED_TIMING && kpt->duration != 0.0f) + psys->totkeyed += 1; + } + else { + kpt->flag &= ~KEYED_TARGET_VALID; + keys_valid = 0; } } - else - tob=0; } - psys->totkeyed=totkeyed; - BLI_freelistN(&lb); - return select; + + psys->totkeyed *= psys->flag & PSYS_KEYED_TIMING ? 1 : psys->part->keyed_loops; } static void set_keyed_keys(Scene *scene, Object *ob, ParticleSystem *psys) { Object *kob = ob; ParticleSystem *kpsys = psys; + KeyedParticleTarget *kpt; ParticleData *pa; - int totpart = psys->totpart, i, k, totkeys = psys->totkeyed + 1; + int totpart = psys->totpart, i, k, totkeys = psys->totkeyed; float prevtime, nexttime, keyedtime; /* no proper targets so let's clear and bail out */ @@ -2046,7 +2038,7 @@ static void set_keyed_keys(Scene *scene, Object *ob, ParticleSystem *psys) if(totpart && psys->particles->totkey != totkeys) { free_keyed_keys(psys); - psys->particles->keys = MEM_callocN(psys->totpart*totkeys*sizeof(ParticleKey), "Keyed keys"); + psys->particles->keys = MEM_callocN(totpart*totkeys*sizeof(ParticleKey), "Keyed keys"); psys->particles->totkey = totkeys; for(i=1, pa=psys->particles+1; iflag &= ~PSYS_KEYED; + + kpt = psys->keyed_targets.first; for(k=0; kob) + kpsys = BLI_findlink(&kpt->ob->particlesystem, kpt->psys - 1); + else + kpsys = BLI_findlink(&ob->particlesystem, kpt->psys - 1); + for(i=0,pa=psys->particles; ikeys + k)->time = -1.0; /* use current time */ - if(kpsys->totpart > 0) - psys_get_particle_state(scene, kob, kpsys, i%kpsys->totpart, pa->keys + k, 1); + psys_get_particle_state(scene, kpt->ob, kpsys, i%kpsys->totpart, pa->keys + k, 1); - if(k==0) - pa->keys->time = pa->time; - else if(k==totkeys-1) - (pa->keys + k)->time = pa->time + pa->lifetime; - else{ - if(psys->flag & PSYS_KEYED_TIME){ - prevtime = (pa->keys + k - 1)->time; - nexttime = pa->time + pa->lifetime; - keyedtime = kpsys->part->keyed_time; - (pa->keys + k)->time = (1.0f - keyedtime) * prevtime + keyedtime * nexttime; + if(psys->flag & PSYS_KEYED_TIMING){ + (pa->keys+k)->time = pa->time + kpt->time; + if(kpt->duration != 0.0f && k+1 < totkeys) { + copy_particle_key(pa->keys+k+1, pa->keys+k, 1); + (pa->keys+k+1)->time = pa->time + kpt->time + kpt->duration; } - else - (pa->keys+k)->time = pa->time + (float)k / (float)(totkeys - 1) * pa->lifetime; } + else if(totkeys > 1) + (pa->keys+k)->time = pa->time + (float)k / (float)(totkeys - 1) * pa->lifetime; + else + pa->keys->time = pa->time; } - if(kpsys->keyed_ob){ - kob = kpsys->keyed_ob; - kpsys = BLI_findlink(&kob->particlesystem, kpsys->keyed_psys - 1); - } + + if(psys->flag & PSYS_KEYED_TIMING && kpt->duration!=0.0f) + k++; + + kpt = (kpt->next && kpt->next->flag & KEYED_TARGET_VALID) ? kpt = kpt->next : psys->keyed_targets.first; } psys->flag |= PSYS_KEYED; @@ -2198,6 +2194,60 @@ void psys_get_reactor_target(Object *ob, ParticleSystem *psys, Object **target_o /************************************************/ /* Point Cache */ /************************************************/ +void psys_make_temp_pointcache(Object *ob, ParticleSystem *psys) +{ + PointCache *cache = psys->pointcache; + PTCacheFile *pf = NULL; + PTCacheMem *pm = NULL; + PTCacheID pid; + int cfra, sfra = cache->startframe, efra = cache->endframe; + int totelem = psys->totpart; + int float_count = sizeof(ParticleKey) / sizeof(float); + int tot = totelem * float_count; + + if((cache->flag & PTCACHE_DISK_CACHE)==0 || cache->mem_cache.first) + return; + + BKE_ptcache_id_from_particles(&pid, ob, psys); + + for(cfra=sfra; cfra <= efra; cfra++) { + pf = BKE_ptcache_file_open(&pid, PTCACHE_FILE_READ, cfra); + + if(pf) { + pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache temp mem"); + pm->data = MEM_callocN(sizeof(float)*tot, "Pointcache temp mem data"); + + if(fread(pm->data, sizeof(float), tot, pf->fp)!= tot) { + printf("Error reading from disk cache\n"); + + MEM_freeN(pm->data); + MEM_freeN(pm); + BKE_ptcache_file_close(pf); + return; + } + + pm->frame = cfra; + pm->totpoint = totelem; + + BLI_addtail(&cache->mem_cache, pm); + + BKE_ptcache_file_close(pf); + } + } +} +void psys_clear_temp_pointcache(ParticleSystem *psys) +{ + PTCacheMem *pm = psys->pointcache->mem_cache.first; + + if((psys->pointcache->flag & PTCACHE_DISK_CACHE)==0) + return; + + for(; pm; pm=pm->next) { + MEM_freeN(pm->data); + } + + BLI_freelistN(&psys->pointcache->mem_cache); +} void psys_get_pointcache_start_end(Scene *scene, ParticleSystem *psys, int *sfra, int *efra) { ParticleSettings *part = psys->part; @@ -3912,61 +3962,6 @@ static void boid_body(Scene *scene, BoidVecFunc *bvf, ParticleData *pa, Particle if(part->flag & PART_BOIDS_2D){ pa->state.vel[2]=0.0; pa->state.co[2]=part->groundz; - - if(psys->keyed_ob && (psys->keyed_ob->type == OB_MESH)){ - Object *zob=psys->keyed_ob; - int min_face; - float co1[3],co2[3],min_d=2.0,min_w[4],imat[4][4]; - VECCOPY(co1,pa->state.co); - VECCOPY(co2,pa->state.co); - - co1[2]=1000.0f; - co2[2]=-1000.0f; - - Mat4Invert(imat,zob->obmat); - Mat4MulVecfl(imat,co1); - Mat4MulVecfl(imat,co2); - - if(psys_intersect_dm(scene,zob,0,0,co1,co2,&min_d,&min_face,min_w,0,0,0,0)){ - DerivedMesh *dm; - MFace *mface; - MVert *mvert; - float loc[3],nor[3],q1[4]; - - psys_disable_all(zob); - dm=mesh_get_derived_final(scene, zob, 0); - psys_enable_all(zob); - - mface=dm->getFaceDataArray(dm,CD_MFACE); - mface+=min_face; - mvert=dm->getVertDataArray(dm,CD_MVERT); - - /* get deflection point & normal */ - psys_interpolate_face(mvert,mface,0,0,min_w,loc,nor,0,0,0,0); - - Mat4MulVecfl(zob->obmat,loc); - Mat4Mul3Vecfl(zob->obmat,nor); - - Normalize(nor); - - VECCOPY(pa->state.co,loc); - - zvec[2]=1.0; - - Crossf(loc,zvec,nor); - - bank=VecLength(loc); - if(bank>0.0){ - bank=saasin(bank); - - VecRotToQuat(loc,bank,q); - - QUATCOPY(q1,pa->state.rot); - - QuatMul(pa->state.rot,q,q1); - } - } - } } length=bvf->Length(pa->state.vel); @@ -4238,7 +4233,7 @@ static void psys_update_path_cache(Scene *scene, Object *ob, ParticleSystemModif if((psys->part->childtype && psys->totchild != get_psys_tot_child(scene, psys)) || psys->recalc&PSYS_RECALC_RESET) alloc=1; - if(alloc || psys->recalc&PSYS_RECALC_RESET || (psys->vgroup[PSYS_VG_DENSITY] && (G.f & G_WEIGHTPAINT))) + if(alloc || psys->recalc&PSYS_RECALC_CHILD || (psys->vgroup[PSYS_VG_DENSITY] && (G.f & G_WEIGHTPAINT))) distr=1; if(distr){ @@ -4416,12 +4411,15 @@ static void cached_step(Scene *scene, Object *ob, ParticleSystemModifierData *ps MEM_freeN(vg_size); } -void psys_changed_type(ParticleSystem *psys) +static void psys_changed_type(Object *ob, ParticleSystem *psys) { ParticleSettings *part; + PTCacheID pid; part= psys->part; + BKE_ptcache_id_from_particles(&pid, ob, psys); + /* system type has changed so set sensible defaults and clear non applicable flags */ if(part->from == PART_FROM_PARTICLE) { if(part->type != PART_REACTOR) @@ -4430,7 +4428,7 @@ void psys_changed_type(ParticleSystem *psys) part->distr = PART_DISTR_JIT; } - if(psys->part->phystype != PART_PHYS_KEYED) + if(part->phystype != PART_PHYS_KEYED) psys->flag &= ~PSYS_KEYED; if(part->type == PART_HAIR) { @@ -4442,6 +4440,8 @@ void psys_changed_type(ParticleSystem *psys) CLAMP(part->path_start, 0.0f, 100.0f); CLAMP(part->path_end, 0.0f, 100.0f); + + BKE_ptcache_id_clear(&pid, PTCACHE_CLEAR_ALL, 0); } else { free_hair(psys, 1); @@ -4454,7 +4454,18 @@ void psys_changed_type(ParticleSystem *psys) psys_reset(psys, PSYS_RESET_ALL); } - +void psys_changed_physics(Object *ob, ParticleSystem *psys) +{ + if(ELEM(psys->part->phystype, PART_PHYS_NO, PART_PHYS_KEYED)) { + PTCacheID pid; + BKE_ptcache_id_from_particles(&pid, ob, psys); + BKE_ptcache_id_clear(&pid, PTCACHE_CLEAR_ALL, 0); + } + else { + free_keyed_keys(psys); + psys->flag &= ~PSYS_KEYED; + } +} static void particles_fluid_step(Scene *scene, Object *ob, ParticleSystem *psys, int cfra) { if(psys->particles){ @@ -4588,6 +4599,8 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle BKE_ptcache_id_from_particles(&pid, ob, psys); BKE_ptcache_id_time(&pid, scene, 0.0f, &startframe, &endframe, NULL); + psys_clear_temp_pointcache(psys); + /* update ipo's */ #if 0 // XXX old animation system if((part->flag & PART_ABS_TIME) && part->ipo) { @@ -4736,7 +4749,7 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle if(usecache && psys->cfra == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0)) write_particles_to_cache(ob, psys, startframe); - if(part->phystype==PART_PHYS_KEYED && psys->flag&PSYS_FIRST_KEYED) + if(part->phystype==PART_PHYS_KEYED) psys_count_keyed_targets(ob,psys); /* initialize vertex groups */ @@ -4783,7 +4796,7 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle write_particles_to_cache(ob, psys, framenr); /* for keyed particles the path is allways known so it can be drawn */ - if(part->phystype==PART_PHYS_KEYED && psys->flag&PSYS_FIRST_KEYED){ + if(part->phystype==PART_PHYS_KEYED) { set_keyed_keys(scene, ob, psys); psys_update_path_cache(scene, ob, psmd, psys,(int)cfra); } @@ -4866,7 +4879,9 @@ void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys) return; if(psys->recalc & PSYS_RECALC_TYPE) - psys_changed_type(psys); + psys_changed_type(ob, psys); + else if(psys->recalc & PSYS_RECALC_PHYS) + psys_changed_physics(ob, psys); /* (re-)create hair */ if(psys->part->type==PART_HAIR && hair_needs_recalc(psys)) { diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index 2fe46be7a89..6107510fa47 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -315,8 +315,10 @@ static int ptcache_pid_totelem(PTCacheID *pid) ParticleSystem *psys = pid->data; return psys->totpart; } - else if(pid->type==PTCACHE_TYPE_CLOTH) - return 0; // TODO + else if(pid->type==PTCACHE_TYPE_CLOTH) { + ClothModifierData *clmd = pid->data; + return clmd->clothObject->numverts; + } return 0; } @@ -429,6 +431,7 @@ int BKE_ptcache_read_cache(PTCacheReader *reader) if(pf) { BKE_ptcache_file_close(pf); + pf = NULL; MEM_freeN(data); } @@ -523,7 +526,9 @@ int BKE_ptcache_read_cache(PTCacheReader *reader) if(pf) { BKE_ptcache_file_close(pf); + pf = NULL; BKE_ptcache_file_close(pf2); + pf2 = NULL; MEM_freeN(data1); MEM_freeN(data2); } @@ -567,10 +572,13 @@ int BKE_ptcache_read_cache(PTCacheReader *reader) if(pf) { BKE_ptcache_file_close(pf); + pf = NULL; MEM_freeN(data); } - if(pf2) + if(pf2) { BKE_ptcache_file_close(pf2); + pf = NULL; + } ret = PTCACHE_READ_OLD; } @@ -602,13 +610,15 @@ int BKE_ptcache_write_cache(PTCacheWriter *writer) PTCacheFile *pf= NULL; int elemsize = ptcache_pid_elemsize(writer->pid); int i, incr = elemsize / sizeof(float); - int add = 0, overwrite = 0, ocfra; + int add = 0, overwrite = 0; float temp[14]; if(writer->totelem == 0 || writer->cfra <= 0) return 0; if(cache->flag & PTCACHE_DISK_CACHE) { + int cfra = cache->endframe; + /* allways start from scratch on the first frame */ if(writer->cfra == cache->startframe) { BKE_ptcache_id_clear(writer->pid, PTCACHE_CLEAR_ALL, writer->cfra); @@ -616,7 +626,7 @@ int BKE_ptcache_write_cache(PTCacheWriter *writer) add = 1; } else { - int cfra = cache->endframe; + int ocfra; /* find last cached frame */ while(cfra > cache->startframe && !BKE_ptcache_id_exist(writer->pid, cfra)) cfra--; @@ -626,7 +636,7 @@ int BKE_ptcache_write_cache(PTCacheWriter *writer) while(ocfra > cache->startframe && !BKE_ptcache_id_exist(writer->pid, ocfra)) ocfra--; - if(writer->cfra > cfra) { + if(cfra >= cache->startframe && writer->cfra > cfra) { if(ocfra >= cache->startframe && cfra - ocfra < cache->step) overwrite = 1; else @@ -636,7 +646,7 @@ int BKE_ptcache_write_cache(PTCacheWriter *writer) if(add || overwrite) { if(overwrite) - BKE_ptcache_id_clear(writer->pid, PTCACHE_CLEAR_FRAME, ocfra); + BKE_ptcache_id_clear(writer->pid, PTCACHE_CLEAR_FRAME, cfra); pf = BKE_ptcache_file_open(writer->pid, PTCACHE_FILE_WRITE, writer->cfra); if(!pf) @@ -665,7 +675,7 @@ int BKE_ptcache_write_cache(PTCacheWriter *writer) pm2 = cache->mem_cache.last; if(pm2 && writer->cfra > pm2->frame) { - if(pm2 && pm2->prev && pm2->frame - pm2->prev->frame < cache->step) + if(pm2->prev && pm2->frame - pm2->prev->frame < cache->step) overwrite = 1; else add = 1; @@ -1102,6 +1112,10 @@ PointCache *BKE_ptcache_copy(PointCache *cache) ncache= MEM_dupallocN(cache); + /* hmm, should these be copied over instead? */ + ncache->mem_cache.first = NULL; + ncache->mem_cache.last = NULL; + ncache->flag= 0; ncache->simframe= 0; @@ -1211,8 +1225,9 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker) cache = pid->cache; if((cache->flag & PTCACHE_BAKED)==0) { if(pid->type==PTCACHE_TYPE_PARTICLES) { - /* skip hair particles */ - if(((ParticleSystem*)pid->data)->part->type == PART_HAIR) + ParticleSystem *psys = (ParticleSystem*)pid->data; + /* skip hair & keyed particles */ + if(psys->part->type == PART_HAIR || psys->part->phystype == PART_PHYS_KEYED) continue; psys_get_pointcache_start_end(scene, pid->data, &cache->startframe, &cache->endframe); @@ -1310,6 +1325,7 @@ void BKE_ptcache_toggle_disk_cache(PTCacheID *pid) { if (!G.relbase_valid){ cache->flag &= ~PTCACHE_DISK_CACHE; + printf("File must be saved before using disk cache!\n"); return; } -- cgit v1.2.3 From 26ef6da24b3324fb6f8ab6cfe12f101f0d7dedb4 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 13 Jul 2009 00:40:20 +0000 Subject: 2.5 * Objects now support up to 32767 material slots. It's easy to increase this further, but I prefer not to increase the memory usage of mesh faces, it seems unlikely that someone would create 32767 distinct materials? * Forward compatibility: the only thing you can potentially lose reading a 2.5 file in 2.4 is object linking (instead of default data), though usually that will go fine too. Reading files with > 32 material slots in 2.4 can start giving issues. * The ob->colbits variable is deprecated by the array ob->matbits but I didn't remove the ob->colbits updates in very few places it is set. * I hope I changed all the relevant things, various places just hardcoded the number 16 instead of using the MAXMAT define. * Join Objects operator back. This is using the version from the animsys2 branch coded by Joshua, which means it now supports joining of shape keys. * Fix for crash reading file saved during render. --- source/blender/blenkernel/intern/exotic.c | 19 +++++------ source/blender/blenkernel/intern/material.c | 52 ++++++++++++++++++++--------- source/blender/blenkernel/intern/object.c | 7 +++- source/blender/blenkernel/intern/texture.c | 2 +- 4 files changed, 52 insertions(+), 28 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/exotic.c b/source/blender/blenkernel/intern/exotic.c index 4e7e76dfae3..c7a8b150d3a 100644 --- a/source/blender/blenkernel/intern/exotic.c +++ b/source/blender/blenkernel/intern/exotic.c @@ -1415,11 +1415,6 @@ static void displist_to_mesh(Scene *scene, DispList *dlfirst) return; } - if(totcol>16) { - //XXX error("Found more than 16 different colors"); - totcol= 16; - } - vec[0]= (min[0]+max[0])/2; vec[1]= (min[1]+max[1])/2; vec[2]= (min[2]+max[2])/2; @@ -1433,6 +1428,7 @@ static void displist_to_mesh(Scene *scene, DispList *dlfirst) /* colors */ if(totcol) { ob->mat= MEM_callocN(sizeof(void *)*totcol, "ob->mat"); + ob->matbits= MEM_callocN(sizeof(char)*totcol, "ob->matbits"); me->mat= MEM_callocN(sizeof(void *)*totcol, "me->mat"); me->totcol= totcol; ob->totcol= (unsigned char) me->totcol; @@ -1482,7 +1478,7 @@ static void displist_to_mesh(Scene *scene, DispList *dlfirst) dl= dlfirst; while(dl) { - colnr= (dl->col>15 ? 15: dl->col); + colnr= dl->col; if(colnr) colnr--; if(dl->type==DL_SURF) { @@ -2804,8 +2800,11 @@ static void dxf_add_mat (Object *ob, Mesh *me, float color[3], char *layer) if (!me) return; - if(ob) ob->mat= MEM_callocN(sizeof(void *)*1, "ob->mat"); - if(ob) ob->actcol= 1; + if(ob) { + ob->mat= MEM_callocN(sizeof(void *)*1, "ob->mat"); + ob->matbits= MEM_callocN(sizeof(char)*1, "ob->matbits"); + ob->actcol= 1; + } me->totcol= 1; me->mat= MEM_callocN(sizeof(void *)*1, "me->mat"); @@ -4053,7 +4052,6 @@ static void dxf_read(Scene *scene, char *filename) ob->type= OB_MESH; ob->dt= OB_SHADED; - if(U.flag & USER_MAT_ON_OB) ob->colbits= -1; ob->trackflag= OB_POSY; ob->upflag= OB_POSZ; @@ -4072,9 +4070,10 @@ static void dxf_read(Scene *scene, char *filename) VECCOPY(ob->rot, obrot); ob->mat= MEM_callocN(sizeof(void *)*1, "ob->mat"); + ob->matbits= MEM_callocN(sizeof(char)*1, "ob->matbits"); ob->totcol= (unsigned char) ((Mesh*)ob->data)->totcol; ob->actcol= 1; - + /* note: materials are either linked to mesh or object, if both then you have to increase user counts. below line is not needed. I leave it commented out here as warning (ton) */ diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index 57b88bb0b3f..d1fdac65dbb 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -43,6 +43,7 @@ #include "DNA_object_types.h" #include "DNA_scene_types.h" #include "DNA_texture_types.h" +#include "DNA_userdef_types.h" #include "BLI_blenlib.h" #include "BLI_arithb.h" @@ -445,7 +446,7 @@ Material *give_current_material(Object *ob, int act) if(act>ob->totcol) act= ob->totcol; else if(act<=0) act= 1; - if( BTST(ob->colbits, act-1) ) { /* in object */ + if(ob->matbits[act-1]) { /* in object */ ma= ob->mat[act-1]; } else { /* in data */ @@ -473,7 +474,7 @@ ID *material_from(Object *ob, int act) if(ob->totcol==0) return ob->data; if(act==0) act= 1; - if( BTST(ob->colbits, act-1) ) return (ID *)ob; + if(ob->matbits[act-1]) return (ID *)ob; else return ob->data; } @@ -498,6 +499,7 @@ void test_object_materials(ID *id) Curve *cu; MetaBall *mb; Material **newmatar; + char *newmatbits; int totcol=0; if(id==0) return; @@ -524,16 +526,22 @@ void test_object_materials(ID *id) if(totcol==0) { if(ob->totcol) { MEM_freeN(ob->mat); - ob->mat= 0; + MEM_freeN(ob->matbits); + ob->mat= NULL; + ob->matbits= NULL; } } else if(ob->totcoltotcol) { memcpy(newmatar, ob->mat, sizeof(void *)*ob->totcol); + memcpy(newmatbits, ob->matbits, sizeof(char)*ob->totcol); MEM_freeN(ob->mat); + MEM_freeN(ob->matbits); } ob->mat= newmatar; + ob->matbits= newmatbits; } ob->totcol= totcol; if(ob->totcol && ob->actcol==0) ob->actcol= 1; @@ -547,6 +555,7 @@ void test_object_materials(ID *id) void assign_material(Object *ob, Material *ma, int act) { Material *mao, **matar, ***matarar; + char *matbits; short *totcolp; if(act>MAXMAT) return; @@ -559,29 +568,41 @@ void assign_material(Object *ob, Material *ma, int act) if(totcolp==0 || matarar==0) return; - if( act > *totcolp) { + if(act > *totcolp) { matar= MEM_callocN(sizeof(void *)*act, "matarray1"); - if( *totcolp) { - memcpy(matar, *matarar, sizeof(void *)*( *totcolp )); + + if(*totcolp) { + memcpy(matar, *matarar, sizeof(void *)*(*totcolp)); MEM_freeN(*matarar); } + *matarar= matar; *totcolp= act; } if(act > ob->totcol) { matar= MEM_callocN(sizeof(void *)*act, "matarray2"); + matbits= MEM_callocN(sizeof(char)*act, "matbits1"); if( ob->totcol) { memcpy(matar, ob->mat, sizeof(void *)*( ob->totcol )); + memcpy(matbits, ob->matbits, sizeof(char)*(*totcolp)); MEM_freeN(ob->mat); + MEM_freeN(ob->matbits); } ob->mat= matar; + ob->matbits= matbits; ob->totcol= act; + + /* copy object/mesh linking, or assign based on userpref */ + if(ob->actcol) + ob->matbits[act-1]= ob->matbits[ob->actcol-1]; + else + ob->matbits[act-1]= (U.flag & USER_MAT_ON_OB)? 1: 0; } /* do it */ - if( BTST(ob->colbits, act-1) ) { /* in object */ + if(ob->matbits[act-1]) { /* in object */ mao= ob->mat[act-1]; if(mao) mao->id.us--; ob->mat[act-1]= ma; @@ -591,6 +612,7 @@ void assign_material(Object *ob, Material *ma, int act) if(mao) mao->id.us--; (*matarar)[act-1]= ma; } + id_us_plus((ID *)ma); test_object_materials(ob->data); } @@ -630,12 +652,6 @@ void object_add_material_slot(Object *ob) ma->id.us= 0; /* eeh... */ - if(ob->actcol) { - if( BTST(ob->colbits, ob->actcol-1) ) { - ob->colbits= BSET(ob->colbits, ob->totcol); - } - } - assign_material(ob, ma, ob->totcol+1); ob->actcol= ob->totcol; } @@ -880,9 +896,8 @@ void object_remove_material_slot(Object *ob) if(mao) mao->id.us--; } - for(a=ob->actcol; atotcol; a++) { + for(a=ob->actcol; atotcol; a++) (*matarar)[a-1]= (*matarar)[a]; - } (*totcolp)--; if(*totcolp==0) { @@ -900,13 +915,18 @@ void object_remove_material_slot(Object *ob) mao= obt->mat[actcol-1]; if(mao) mao->id.us--; - for(a=actcol; atotcol; a++) obt->mat[a-1]= obt->mat[a]; + for(a=actcol; atotcol; a++) { + obt->mat[a-1]= obt->mat[a]; + obt->matbits[a-1]= obt->matbits[a]; + } obt->totcol--; if(obt->actcol > obt->totcol) obt->actcol= obt->totcol; if(obt->totcol==0) { MEM_freeN(obt->mat); + MEM_freeN(obt->matbits); obt->mat= 0; + obt->matbits= NULL; } } obt= obt->id.next; diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 7d6a83d7900..02c0d46a73f 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -243,7 +243,9 @@ void free_object(Object *ob) if(ob->mat[a]) ob->mat[a]->id.us--; } if(ob->mat) MEM_freeN(ob->mat); + if(ob->matbits) MEM_freeN(ob->matbits); ob->mat= 0; + ob->matbits= 0; if(ob->bb) MEM_freeN(ob->bb); ob->bb= 0; if(ob->path) free_path(ob->path); @@ -942,7 +944,6 @@ Object *add_only_object(int type, char *name) Mat4One(ob->parentinv); Mat4One(ob->obmat); ob->dt= OB_SHADED; - if(U.flag & USER_MAT_ON_OB) ob->colbits= -1; ob->empty_drawtype= OB_ARROWS; ob->empty_drawsize= 1.0; @@ -1170,6 +1171,7 @@ Object *copy_object(Object *ob) if(ob->totcol) { obn->mat= MEM_dupallocN(ob->mat); + obn->matbits= MEM_dupallocN(ob->matbits); } if(ob->bb) obn->bb= MEM_dupallocN(ob->bb); @@ -1397,7 +1399,9 @@ void object_make_proxy(Object *ob, Object *target, Object *gob) /* copy material and index information */ ob->actcol= ob->totcol= 0; if(ob->mat) MEM_freeN(ob->mat); + if(ob->matbits) MEM_freeN(ob->matbits); ob->mat = NULL; + ob->matbits= NULL; if ((target->totcol) && (target->mat) && ELEM5(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL)) { //XXX OB_SUPPORT_MATERIAL int i; ob->colbits = target->colbits; @@ -1406,6 +1410,7 @@ void object_make_proxy(Object *ob, Object *target, Object *gob) ob->totcol= target->totcol; ob->mat = MEM_dupallocN(target->mat); + ob->matbits = MEM_dupallocN(target->matbits); for(i=0; itotcol; i++) { /* dont need to run test_object_materials since we know this object is new and not used elsewhere */ id_us_plus((ID *)ob->mat[i]); diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c index 66f7fe8a44b..bcdea06936f 100644 --- a/source/blender/blenkernel/intern/texture.c +++ b/source/blender/blenkernel/intern/texture.c @@ -784,7 +784,7 @@ Tex *give_current_texture(Object *ob, int act) if(act>ob->totcol) act= ob->totcol; else if(act==0) act= 1; - if( BTST(ob->colbits, act-1) ) { /* in object */ + if(ob->matbits[act-1]) { /* in object */ ma= ob->mat[act-1]; } else { /* in data */ -- cgit v1.2.3 From 41fb3626f3d7c1e75a31aebeb1e488f59aeedf68 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 13 Jul 2009 19:09:13 +0000 Subject: 2.5: Render * UI layout for scene buttons has quite some changes, I tried to better organize things according to the pipeline, and also showing important properties by default, and collapsing less important ones. Some changes compared to 2.4x: * Panorama is now a Camera property. * Sequence and Compositing are now enabled by default, but will only do something when there is a node tree using nodes, or a strip in the sequence editor. * Enabling Full Sample now automatically enables Save Buffers too. * Stamp option to include info in file is removed, it now simply always does this if one of the stamp infos is enabled. * Xvid, H.264 and Ogg Theora are now directly in the file format menu, but still using FFMPEG. Unfortunately Ogg is broken at the moment (also in 2.4x), so that's disabled. And Xvid crashes on 64bit linux, maybe solvable by upgrading extern/xvidcore/, using ubuntu libs makes it work. * Organized file format menu by image/movie types. Added: * Render layers RNA wrapped, operatorized, layouted. * FFMPEG format/codec options are now working. Defaults changed: * Compositing & Sequencer enabled. * Tiles set to 8x8. * Time/Date/Frame/Scene/Camera/Filename enabled for stamp. --- source/blender/blenkernel/BKE_writeffmpeg.h | 22 +- source/blender/blenkernel/intern/image.c | 11 +- source/blender/blenkernel/intern/scene.c | 17 +- source/blender/blenkernel/intern/sequence.c | 7 +- source/blender/blenkernel/intern/writeavi.c | 3 +- source/blender/blenkernel/intern/writeffmpeg.c | 317 +++++++++++++++++++++++++ 6 files changed, 356 insertions(+), 21 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_writeffmpeg.h b/source/blender/blenkernel/BKE_writeffmpeg.h index dba3944a58d..be136bd9d6d 100644 --- a/source/blender/blenkernel/BKE_writeffmpeg.h +++ b/source/blender/blenkernel/BKE_writeffmpeg.h @@ -46,19 +46,29 @@ extern "C" { #define FFMPEG_MKV 9 #define FFMPEG_OGG 10 -#define FFMPEG_PRESET_NONE 0 -#define FFMPEG_PRESET_DVD 1 -#define FFMPEG_PRESET_SVCD 2 -#define FFMPEG_PRESET_VCD 3 -#define FFMPEG_PRESET_DV 4 -#define FFMPEG_PRESET_H264 5 +#define FFMPEG_PRESET_NONE 0 +#define FFMPEG_PRESET_DVD 1 +#define FFMPEG_PRESET_SVCD 2 +#define FFMPEG_PRESET_VCD 3 +#define FFMPEG_PRESET_DV 4 +#define FFMPEG_PRESET_H264 5 +#define FFMPEG_PRESET_THEORA 6 +#define FFMPEG_PRESET_XVID 7 +struct IDProperty; struct RenderData; extern void start_ffmpeg(struct RenderData *rd, int rectx, int recty); extern void end_ffmpeg(void); extern void append_ffmpeg(struct RenderData *rd, int frame, int *pixels, int rectx, int recty); +extern void ffmpeg_set_preset(struct RenderData *rd, int preset); +extern void ffmpeg_verify_image_type(struct RenderData *rd); + +extern struct IDProperty *ffmpeg_property_add(struct RenderData *Rd, char *type, int opt_index, int parent_index); +extern int ffmpeg_property_add_string(struct RenderData *rd, const char *type, const char *str); +extern void ffmpeg_property_del(struct RenderData *rd, void *type, void *prop_); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 754ec06f23f..93924d1ea0d 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -860,6 +860,9 @@ int BKE_imtype_is_movie(int imtype) case R_AVICODEC: case R_QUICKTIME: case R_FFMPEG: + case R_H264: + case R_THEORA: + case R_XVID: case R_FRAMESERVER: return 1; } @@ -870,7 +873,7 @@ void BKE_add_image_extension(Scene *scene, char *string, int imtype) { char *extension=""; - if(scene->r.imtype== R_IRIS) { + if(imtype== R_IRIS) { if(!BLI_testextensie(string, ".rgb")) extension= ".rgb"; } @@ -882,7 +885,7 @@ void BKE_add_image_extension(Scene *scene, char *string, int imtype) if(!BLI_testextensie(string, ".hdr")) extension= ".hdr"; } - else if(imtype==R_PNG || imtype==R_FFMPEG) { + else if (ELEM5(imtype, R_PNG, R_FFMPEG, R_H264, R_THEORA, R_XVID)) { if(!BLI_testextensie(string, ".png")) extension= ".png"; } @@ -1230,7 +1233,7 @@ int BKE_write_ibuf(Scene *scene, ImBuf *ibuf, char *name, int imtype, int subimt else if ((imtype==R_RADHDR)) { ibuf->ftype= RADHDR; } - else if (imtype==R_PNG || imtype==R_FFMPEG) { + else if (ELEM5(imtype, R_PNG, R_FFMPEG, R_H264, R_THEORA, R_XVID)) { ibuf->ftype= PNG; } #ifdef WITH_DDS @@ -1305,7 +1308,7 @@ int BKE_write_ibuf(Scene *scene, ImBuf *ibuf, char *name, int imtype, int subimt BLI_make_existing_file(name); - if(scene->r.scemode & R_STAMP_INFO) + if(scene->r.stamp & R_STAMP_ALL) BKE_stamp_info(scene, ibuf); ok = IMB_saveiff(ibuf, name, IB_rect | IB_zbuf | IB_zbuffloat); diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 23da5c66850..598336886c2 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -204,17 +204,17 @@ Scene *add_scene(char *name) sce= alloc_libblock(&G.main->scene, ID_SCE, name); sce->lay= 1; - sce->r.mode= R_GAMMA; + sce->r.mode= R_GAMMA|R_OSA|R_SHADOW|R_SSS|R_ENVMAP|R_RAYTRACE; sce->r.cfra= 1; sce->r.sfra= 1; sce->r.efra= 250; - sce->r.xsch= 320; - sce->r.ysch= 256; + sce->r.xsch= 1920; + sce->r.ysch= 1080; sce->r.xasp= 1; sce->r.yasp= 1; - sce->r.xparts= 4; - sce->r.yparts= 4; - sce->r.size= 100; + sce->r.xparts= 8; + sce->r.yparts= 8; + sce->r.size= 25; sce->r.planes= 24; sce->r.quality= 90; sce->r.framapto= 100; @@ -225,7 +225,7 @@ Scene *add_scene(char *name) sce->r.ocres = 128; sce->r.bake_mode= 1; /* prevent to include render stuff here */ - sce->r.bake_filter= 2; + sce->r.bake_filter= 8; sce->r.bake_osa= 5; sce->r.bake_flag= R_BAKE_CLEAR; sce->r.bake_normal_space= R_BAKE_SPACE_TANGENT; @@ -234,6 +234,9 @@ Scene *add_scene(char *name) sce->r.yplay= 480; sce->r.freqplay= 60; sce->r.depth= 32; + + sce->r.scemode= R_DOCOMP|R_DOSEQ|R_EXTENSION; + sce->r.stamp= R_STAMP_TIME|R_STAMP_FRAME|R_STAMP_DATE|R_STAMP_SCENE|R_STAMP_CAMERA; sce->r.threads= 1; diff --git a/source/blender/blenkernel/intern/sequence.c b/source/blender/blenkernel/intern/sequence.c index c8d95929027..3eeecd94a85 100644 --- a/source/blender/blenkernel/intern/sequence.c +++ b/source/blender/blenkernel/intern/sequence.c @@ -2017,7 +2017,8 @@ static void do_build_seq_ibuf(Scene *scene, Sequence * seq, TStripElem *se, int RenderResult rres; int doseq, rendering= G.rendering; char scenename[64]; - int sce_valid =sce&& (sce->camera || sce->r.scemode & R_DOSEQ); + int have_seq= (sce->r.scemode & R_DOSEQ) && sce->ed && sce->ed->seqbase.first; + int sce_valid =sce && (sce->camera || have_seq); if (se->ibuf == NULL && sce_valid && !build_proxy_run) { se->ibuf = seq_proxy_fetch(scene, seq, cfra, render_size); @@ -2038,7 +2039,7 @@ static void do_build_seq_ibuf(Scene *scene, Sequence * seq, TStripElem *se, int } else if (se->ibuf==NULL && sce_valid) { /* no need to display a waitcursor on sequencer scene strips */ - if (!(sce->r.scemode & R_DOSEQ)) + if (!have_seq) waitcursor(1); /* Hack! This function can be called from do_render_seq(), in that case @@ -2093,7 +2094,7 @@ static void do_build_seq_ibuf(Scene *scene, Sequence * seq, TStripElem *se, int // XXX #if 0 if((G.f & G_PLAYANIM)==0 /* bad, is set on do_render_seq */ - && !(sce->r.scemode & R_DOSEQ) + && !have_seq && !build_proxy_run) #endif diff --git a/source/blender/blenkernel/intern/writeavi.c b/source/blender/blenkernel/intern/writeavi.c index f84bd690347..cfbe3f629d6 100644 --- a/source/blender/blenkernel/intern/writeavi.c +++ b/source/blender/blenkernel/intern/writeavi.c @@ -40,6 +40,7 @@ #include "BLI_blenlib.h" #include "BKE_global.h" +#include "BKE_utildefines.h" #include "BKE_writeavi.h" #include "AVI_avi.h" @@ -87,7 +88,7 @@ bMovieHandle *BKE_get_movie_handle(int imtype) } #endif #ifdef WITH_FFMPEG - if (imtype == R_FFMPEG) { + if (ELEM4(imtype, R_FFMPEG, R_H264, R_XVID, R_THEORA)) { mh.start_movie = start_ffmpeg; mh.append_movie = append_ffmpeg; mh.end_movie = end_ffmpeg; diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c index 25dc6fa2fd7..5e3c8024524 100644 --- a/source/blender/blenkernel/intern/writeffmpeg.c +++ b/source/blender/blenkernel/intern/writeffmpeg.c @@ -937,5 +937,322 @@ void end_ffmpeg(void) img_convert_ctx = 0; } } + +/* properties */ + +void ffmpeg_property_del(RenderData *rd, void *type, void *prop_) +{ + struct IDProperty *prop = (struct IDProperty *) prop_; + IDProperty * group; + + if (!rd->ffcodecdata.properties) { + return; + } + + group = IDP_GetPropertyFromGroup( + rd->ffcodecdata.properties, (char*) type); + if (group && prop) { + IDP_RemFromGroup(group, prop); + IDP_FreeProperty(prop); + MEM_freeN(prop); + } +} + +IDProperty *ffmpeg_property_add(RenderData *rd, char * type, int opt_index, int parent_index) +{ + AVCodecContext c; + const AVOption * o; + const AVOption * parent; + IDProperty * group; + IDProperty * prop; + IDPropertyTemplate val; + int idp_type; + char name[256]; + + avcodec_get_context_defaults(&c); + + o = c.av_class->option + opt_index; + parent = c.av_class->option + parent_index; + + if (!rd->ffcodecdata.properties) { + IDPropertyTemplate val; + + rd->ffcodecdata.properties + = IDP_New(IDP_GROUP, val, "ffmpeg"); + } + + group = IDP_GetPropertyFromGroup( + rd->ffcodecdata.properties, (char*) type); + + if (!group) { + IDPropertyTemplate val; + + group = IDP_New(IDP_GROUP, val, (char*) type); + IDP_AddToGroup(rd->ffcodecdata.properties, group); + } + + if (parent_index) { + sprintf(name, "%s:%s", parent->name, o->name); + } else { + strcpy(name, o->name); + } + + fprintf(stderr, "ffmpeg_property_add: %s %d %d %s\n", + type, parent_index, opt_index, name); + + prop = IDP_GetPropertyFromGroup(group, name); + if (prop) { + return prop; + } + + switch (o->type) { + case FF_OPT_TYPE_INT: + case FF_OPT_TYPE_INT64: + val.i = o->default_val; + idp_type = IDP_INT; + break; + case FF_OPT_TYPE_DOUBLE: + case FF_OPT_TYPE_FLOAT: + val.f = o->default_val; + idp_type = IDP_FLOAT; + break; + case FF_OPT_TYPE_STRING: + val.str = " "; + idp_type = IDP_STRING; + break; + case FF_OPT_TYPE_CONST: + val.i = 1; + idp_type = IDP_INT; + break; + default: + return NULL; + } + prop = IDP_New(idp_type, val, name); + IDP_AddToGroup(group, prop); + return prop; +} + +/* not all versions of ffmpeg include that, so here we go ... */ + +static const AVOption *my_av_find_opt(void *v, const char *name, + const char *unit, int mask, int flags){ + AVClass *c= *(AVClass**)v; + const AVOption *o= c->option; + + for(;o && o->name; o++){ + if(!strcmp(o->name, name) && + (!unit || (o->unit && !strcmp(o->unit, unit))) && + (o->flags & mask) == flags ) + return o; + } + return NULL; +} + +int ffmpeg_property_add_string(RenderData *rd, const char * type, const char * str) +{ + AVCodecContext c; + const AVOption * o = 0; + const AVOption * p = 0; + char name_[128]; + char * name; + char * param; + IDProperty * prop; + + avcodec_get_context_defaults(&c); + + strncpy(name_, str, 128); + + name = name_; + while (*name == ' ') name++; + + param = strchr(name, ':'); + + if (!param) { + param = strchr(name, ' '); + } + if (param) { + *param++ = 0; + while (*param == ' ') param++; + } + + o = my_av_find_opt(&c, name, NULL, 0, 0); + if (!o) { + return 0; + } + if (param && o->type == FF_OPT_TYPE_CONST) { + return 0; + } + if (param && o->type != FF_OPT_TYPE_CONST && o->unit) { + p = my_av_find_opt(&c, param, o->unit, 0, 0); + prop = ffmpeg_property_add(rd, + (char*) type, p - c.av_class->option, + o - c.av_class->option); + } else { + prop = ffmpeg_property_add(rd, + (char*) type, o - c.av_class->option, 0); + } + + + if (!prop) { + return 0; + } + + if (param && !p) { + switch (prop->type) { + case IDP_INT: + IDP_Int(prop) = atoi(param); + break; + case IDP_FLOAT: + IDP_Float(prop) = atof(param); + break; + case IDP_STRING: + strncpy(IDP_String(prop), param, prop->len); + break; + } + } + return 1; +} + +void ffmpeg_set_preset(RenderData *rd, int preset) +{ + int isntsc = (rd->frs_sec != 25); + + switch (preset) { + case FFMPEG_PRESET_VCD: + rd->ffcodecdata.type = FFMPEG_MPEG1; + rd->ffcodecdata.video_bitrate = 1150; + rd->xsch = 352; + rd->ysch = isntsc ? 240 : 288; + rd->ffcodecdata.gop_size = isntsc ? 18 : 15; + rd->ffcodecdata.rc_max_rate = 1150; + rd->ffcodecdata.rc_min_rate = 1150; + rd->ffcodecdata.rc_buffer_size = 40*8; + rd->ffcodecdata.mux_packet_size = 2324; + rd->ffcodecdata.mux_rate = 2352 * 75 * 8; + break; + + case FFMPEG_PRESET_SVCD: + rd->ffcodecdata.type = FFMPEG_MPEG2; + rd->ffcodecdata.video_bitrate = 2040; + rd->xsch = 480; + rd->ysch = isntsc ? 480 : 576; + rd->ffcodecdata.gop_size = isntsc ? 18 : 15; + rd->ffcodecdata.rc_max_rate = 2516; + rd->ffcodecdata.rc_min_rate = 0; + rd->ffcodecdata.rc_buffer_size = 224*8; + rd->ffcodecdata.mux_packet_size = 2324; + rd->ffcodecdata.mux_rate = 0; + break; + + case FFMPEG_PRESET_DVD: + rd->ffcodecdata.type = FFMPEG_MPEG2; + rd->ffcodecdata.video_bitrate = 6000; + rd->xsch = 720; + rd->ysch = isntsc ? 480 : 576; + rd->ffcodecdata.gop_size = isntsc ? 18 : 15; + rd->ffcodecdata.rc_max_rate = 9000; + rd->ffcodecdata.rc_min_rate = 0; + rd->ffcodecdata.rc_buffer_size = 224*8; + rd->ffcodecdata.mux_packet_size = 2048; + rd->ffcodecdata.mux_rate = 10080000; + break; + + case FFMPEG_PRESET_DV: + rd->ffcodecdata.type = FFMPEG_DV; + rd->xsch = 720; + rd->ysch = isntsc ? 480 : 576; + break; + + case FFMPEG_PRESET_H264: + rd->ffcodecdata.type = FFMPEG_AVI; + rd->ffcodecdata.codec = CODEC_ID_H264; + rd->ffcodecdata.video_bitrate = 6000; + rd->ffcodecdata.gop_size = isntsc ? 18 : 15; + rd->ffcodecdata.rc_max_rate = 9000; + rd->ffcodecdata.rc_min_rate = 0; + rd->ffcodecdata.rc_buffer_size = 224*8; + rd->ffcodecdata.mux_packet_size = 2048; + rd->ffcodecdata.mux_rate = 10080000; + + ffmpeg_property_add_string(rd, "video", "coder:vlc"); + ffmpeg_property_add_string(rd, "video", "flags:loop"); + ffmpeg_property_add_string(rd, "video", "cmp:chroma"); + ffmpeg_property_add_string(rd, "video", "partitions:parti4x4"); + ffmpeg_property_add_string(rd, "video", "partitions:partp8x8"); + ffmpeg_property_add_string(rd, "video", "partitions:partb8x8"); + ffmpeg_property_add_string(rd, "video", "me:hex"); + ffmpeg_property_add_string(rd, "video", "subq:5"); + ffmpeg_property_add_string(rd, "video", "me_range:16"); + ffmpeg_property_add_string(rd, "video", "keyint_min:25"); + ffmpeg_property_add_string(rd, "video", "sc_threshold:40"); + ffmpeg_property_add_string(rd, "video", "i_qfactor:0.71"); + ffmpeg_property_add_string(rd, "video", "b_strategy:1"); + + break; + + case FFMPEG_PRESET_THEORA: + case FFMPEG_PRESET_XVID: + if(preset == FFMPEG_PRESET_XVID) { + rd->ffcodecdata.type = FFMPEG_AVI; + rd->ffcodecdata.codec = CODEC_ID_XVID; + } + else if(preset == FFMPEG_PRESET_THEORA) { + rd->ffcodecdata.type = FFMPEG_OGG; // XXX broken + rd->ffcodecdata.codec = CODEC_ID_THEORA; + } + + rd->ffcodecdata.video_bitrate = 6000; + rd->ffcodecdata.gop_size = isntsc ? 18 : 15; + rd->ffcodecdata.rc_max_rate = 9000; + rd->ffcodecdata.rc_min_rate = 0; + rd->ffcodecdata.rc_buffer_size = 224*8; + rd->ffcodecdata.mux_packet_size = 2048; + rd->ffcodecdata.mux_rate = 10080000; + break; + + } +} + +void ffmpeg_verify_image_type(RenderData *rd) +{ + int audio= 0; + + if(rd->imtype == R_FFMPEG) { + if(rd->ffcodecdata.type <= 0 || + rd->ffcodecdata.codec <= 0 || + rd->ffcodecdata.audio_codec <= 0 || + rd->ffcodecdata.video_bitrate <= 1) { + + rd->ffcodecdata.codec = CODEC_ID_MPEG2VIDEO; + ffmpeg_set_preset(rd, FFMPEG_PRESET_DVD); + } + + audio= 1; + } + else if(rd->imtype == R_H264) { + if(rd->ffcodecdata.codec != CODEC_ID_H264) { + ffmpeg_set_preset(rd, FFMPEG_PRESET_H264); + audio= 1; + } + } + else if(rd->imtype == R_XVID) { + if(rd->ffcodecdata.codec != CODEC_ID_XVID) { + ffmpeg_set_preset(rd, FFMPEG_PRESET_XVID); + audio= 1; + } + } + else if(rd->imtype == R_THEORA) { + if(rd->ffcodecdata.codec != CODEC_ID_THEORA) { + ffmpeg_set_preset(rd, FFMPEG_PRESET_THEORA); + audio= 1; + } + } + + if(audio && rd->ffcodecdata.audio_codec <= 0) { + rd->ffcodecdata.audio_codec = CODEC_ID_MP2; + rd->ffcodecdata.audio_bitrate = 128; + } +} + #endif -- cgit v1.2.3