From dd5148e265ac519776da5df78c6186eaefc7e7b8 Mon Sep 17 00:00:00 2001 From: Janne Karhu Date: Sun, 6 Jul 2008 22:52:55 +0000 Subject: [PATCH 01/37] Fix for bug: [#14570] particle system: grid distribution + vertex emitting bug - grid distribution didn't check for emission from vertices --- source/blender/blenkernel/intern/particle.c | 2 +- source/blender/blenkernel/intern/particle_system.c | 10 +++++----- source/blender/src/buttons_object.c | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 18fca5439ef..24a3d348ae7 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -1371,7 +1371,7 @@ void psys_particle_on_shape(int distr, int index, float *fuv, float *vec, float /************************************************/ void psys_particle_on_emitter(Object *ob, ParticleSystemModifierData *psmd, int from, int index, int index_dmcache, float *fuv, float foffset, float *vec, float *nor, float *utan, float *vtan, float *orco, float *ornor){ if(psmd){ - if(psmd->psys->part->distr==PART_DISTR_GRID){ + if(psmd->psys->part->distr==PART_DISTR_GRID && psmd->psys->part->from != PART_FROM_VERT){ if(vec){ VECCOPY(vec,fuv); } diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 458171cc232..f70648965f4 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -168,7 +168,7 @@ static void realloc_particles(Object *ob, ParticleSystem *psys, int new_totpart) int i, totpart, totsaved = 0; if(new_totpart<0) { - if(psys->part->distr==PART_DISTR_GRID) { + if(psys->part->distr==PART_DISTR_GRID && psys->part->from != PART_FROM_VERT) { totpart= psys->part->grid_res; totpart*=totpart*totpart; } @@ -1056,7 +1056,7 @@ int psys_threads_init_distribution(ParticleThread *threads, DerivedMesh *finaldm dm= CDDM_from_mesh((Mesh*)ob->data, ob); /* special handling of grid distribution */ - if(part->distr==PART_DISTR_GRID){ + if(part->distr==PART_DISTR_GRID && from != PART_FROM_VERT){ distribute_particles_in_grid(dm,psys); dm->release(dm); return 0; @@ -1600,7 +1600,7 @@ void initialize_particle(ParticleData *pa, int p, Object *ob, ParticleSystem *ps NormalQuat(pa->r_rot); - if(part->distr!=PART_DISTR_GRID){ + if(part->distr!=PART_DISTR_GRID && part->from != PART_FROM_VERT){ /* any unique random number will do (r_ave[0]) */ if(ptex.exist < 0.5*(1.0+pa->r_ave[0])) pa->flag |= PARS_UNEXIST; @@ -4515,7 +4515,7 @@ void psys_changed_type(ParticleSystem *psys) if(part->from == PART_FROM_PARTICLE) { if(part->type != PART_REACTOR) part->from = PART_FROM_FACE; - if(part->distr == PART_DISTR_GRID) + if(part->distr == PART_DISTR_GRID && part->from != PART_FROM_VERT) part->distr = PART_DISTR_JIT; } @@ -4710,7 +4710,7 @@ static void system_step(Object *ob, ParticleSystem *psys, ParticleSystemModifier oldtotpart = psys->totpart; oldtotchild = psys->totchild; - if(part->distr == PART_DISTR_GRID) + if(part->distr == PART_DISTR_GRID && part->from != PART_FROM_VERT) totpart = part->grid_res*part->grid_res*part->grid_res; else totpart = psys->part->totpart; diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index ba409723784..ebe770c89e7 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -4812,7 +4812,7 @@ static void object_panel_particle_system(Object *ob) uiDefBut(block, LABEL, 0, "Basic:", butx,(buty-=buth),butw,buth, NULL, 0.0, 0, 0, 0, ""); uiBlockBeginAlign(block); - if(part->distr==PART_DISTR_GRID) + if(part->distr==PART_DISTR_GRID && part->from != PART_FROM_VERT) uiDefButI(block, NUM, B_PART_ALLOC, "Resol:", butx,(buty-=buth),butw,buth, &part->grid_res, 1.0, 100.0, 0, 0, "The resolution of the particle grid"); else uiDefButI(block, NUM, B_PART_ALLOC, "Amount:", butx,(buty-=buth),butw,buth, &part->totpart, 0.0, 100000.0, 0, 0, "The total number of particles"); From 707301ad1b502fbbb552ae8827402f2d67ba881e Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Mon, 7 Jul 2008 00:54:32 +0000 Subject: [PATCH 02/37] Little tweak to timeline_force_draw, so that button windows are updated properly --- source/blender/src/edittime.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/src/edittime.c b/source/blender/src/edittime.c index 5a10ea65738..2c37a0eb20f 100644 --- a/source/blender/src/edittime.c +++ b/source/blender/src/edittime.c @@ -803,11 +803,11 @@ static void timeline_force_draw(short val) if(sa->spacetype==SPACE_VIEW3D) { if(sa==samin || (val & TIME_ALL_3D_WIN)) dodraw= 1; } - else if(ELEM6(sa->spacetype, SPACE_NLA, SPACE_IPO, SPACE_SEQ, SPACE_BUTS, SPACE_ACTION, SPACE_SOUND)) { + else if(ELEM5(sa->spacetype, SPACE_NLA, SPACE_IPO, SPACE_SEQ, SPACE_ACTION, SPACE_SOUND)) { if(val & TIME_ALL_ANIM_WIN) dodraw= 1; } else if(sa->spacetype==SPACE_BUTS) { - if(val & TIME_ALL_BUTS_WIN) dodraw= 1; + if(val & TIME_ALL_BUTS_WIN) dodraw= 2; } else if(sa->spacetype==SPACE_IMAGE) { if (val & TIME_ALL_IMAGE_WIN) dodraw = 1; From 32cefbdecfc4867dfca813e304a6184987115013 Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Mon, 7 Jul 2008 01:56:47 +0000 Subject: [PATCH 03/37] Derived Mesh Bugfix EditMesh MEdge vertex index were doubled incremented, so more or less always wrong (even worse, could read outside of array). --- source/blender/blenkernel/intern/DerivedMesh.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index 30405660658..4d3f9143b85 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -1052,7 +1052,7 @@ void emDM_copyEdgeArray(DerivedMesh *dm, MEdge *edge_r) /* store vertex indices in tmp union */ for(ev = em->verts.first, i = 0; ev; ev = ev->next, ++i) - ev->tmp.l = (long) i++; + ev->tmp.l = (long) i; for( ; ee; ee = ee->next, ++edge_r) { edge_r->crease = (unsigned char) (ee->crease*255.0f); From 0456a71eddb53a60ffe127c4d6870ce46374264c Mon Sep 17 00:00:00 2001 From: Matt Ebb Date: Mon, 7 Jul 2008 02:02:10 +0000 Subject: [PATCH 04/37] * New UV editor selection mode: Island This goes alongside vertex and face selection and selects an entire UV island with a single click. It's a lot less painful to use when rearranging UV layouts, especially with Drag Immediately on - see: http://mke3.net/blender/etc/uv_island.mov --- source/blender/makesdna/DNA_space_types.h | 11 +++++++++-- source/blender/src/drawimage.c | 2 +- source/blender/src/editsima.c | 16 ++++++++++++---- source/blender/src/header_image.c | 23 +++++++++++++---------- 4 files changed, 35 insertions(+), 17 deletions(-) diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index af60f9ca713..bc30a12ff27 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -232,8 +232,9 @@ typedef struct SpaceImage { short imanr; short curtile; /* the currently active tile of the image when tile is enabled, is kept in sync with the active faces tile */ int flag; + short selectmode; short imtypenr, lock; - short pin, pad2; + short pin; float zoom; char dt_uv; /* UV draw type */ char sticky; /* sticky selection type */ @@ -496,6 +497,12 @@ typedef struct SpaceImaSel { #define SI_STICKY_DISABLE 1 #define SI_STICKY_VERTEX 2 +/* SpaceImage->selectmode */ +#define SI_SELECT_VERTEX 0 +#define SI_SELECT_EDGE 1 /* not implemented */ +#define SI_SELECT_FACE 2 +#define SI_SELECT_ISLAND 3 + /* SpaceImage->flag */ #define SI_BE_SQUARE 1<<0 #define SI_EDITTILE 1<<1 @@ -503,7 +510,7 @@ typedef struct SpaceImaSel { #define SI_DRAWTOOL 1<<3 #define SI_DEPRECATED1 1<<4 /* stick UVs to others in the same location */ #define SI_DRAWSHADOW 1<<5 -#define SI_SELACTFACE 1<<6 +#define SI_SELACTFACE 1<<6 /* deprecated */ #define SI_DEPRECATED2 1<<7 #define SI_DEPRECATED3 1<<8 /* stick UV selection to mesh vertex (UVs wont always be touching) */ #define SI_COORDFLOATS 1<<9 diff --git a/source/blender/src/drawimage.c b/source/blender/src/drawimage.c index 547de85e856..14849cdd450 100644 --- a/source/blender/src/drawimage.c +++ b/source/blender/src/drawimage.c @@ -422,7 +422,7 @@ int draw_uvs_face_check(void) return 1; } } else { - if (G.sima->flag & SI_SELACTFACE) { + if (G.sima->selectmode == SI_SELECT_FACE) { return 1; } } diff --git a/source/blender/src/editsima.c b/source/blender/src/editsima.c index 18a9803dcae..7c2edc3e236 100644 --- a/source/blender/src/editsima.c +++ b/source/blender/src/editsima.c @@ -694,7 +694,7 @@ void mouse_select_sima(void) EditFace *efa; MTFace *tf, *nearesttf; EditFace *nearestefa=NULL; - int a, selectsticky, edgeloop, actface, nearestuv, nearestedge, i, shift; + int a, selectsticky, edgeloop, actface, nearestuv, nearestedge, i, shift, island; char sticky= 0; int flush = 0; /* 0 == dont flush, 1 == sel, -1 == desel; only use when selection sync is enabled */ unsigned int hitv[4], nearestv; @@ -706,7 +706,7 @@ void mouse_select_sima(void) edgeloop= G.qual & LR_ALTKEY; shift= G.qual & LR_SHIFTKEY; - + if (G.sima->flag & SI_SYNC_UVSEL) { /* copy from mesh */ if (G.scene->selectmode == SCE_SELECT_FACE) { @@ -718,7 +718,8 @@ void mouse_select_sima(void) } } else { /* normal operation */ - actface= G.sima->flag & SI_SELACTFACE; + actface= G.sima->selectmode == SI_SELECT_FACE; + island= G.sima->selectmode == SI_SELECT_ISLAND; switch(G.sima->sticky) { case SI_STICKY_LOC: @@ -760,6 +761,9 @@ void mouse_select_sima(void) if (nearestefa->v4) hitv[3]= nearestefa->v4->tmp.l; else hitv[3]= 0xFFFFFFFF; + } + else if (island) { + } else { find_nearest_uv(&nearesttf, &nearestefa, &nearestv, &nearestuv); @@ -774,7 +778,11 @@ void mouse_select_sima(void) } } - if(!edgeloop && shift) { + if (island) { + if(shift) select_linked_tface_uv(1); + else select_linked_tface_uv(0); + } + else if(!edgeloop && shift) { /* (de)select face */ if(actface) { if(simaFaceSel_Check(nearestefa, nearesttf)) { diff --git a/source/blender/src/header_image.c b/source/blender/src/header_image.c index 7ac57cb839b..fac9e3af1af 100644 --- a/source/blender/src/header_image.c +++ b/source/blender/src/header_image.c @@ -1214,28 +1214,31 @@ void image_buttons(void) uiBlockBeginAlign(block); /* B_SEL_VERT & B_SEL_FACE are not defined here which is a bit bad, BUT it works even if image editor is fullscreen */ - uiDefIconButBitS(block, TOG, SCE_SELECT_VERTEX, B_SEL_VERT, ICON_VERTEXSEL, xco,0,XIC,YIC, &G.scene->selectmode, 1.0, 0.0, 0, 0, "Vertex select mode (Ctrl Tab 1)"); - xco+= XIC; + uiDefIconButBitS(block, TOG, SCE_SELECT_VERTEX, B_SEL_VERT, ICON_VERTEXSEL, + xco,0,XIC,YIC, &G.scene->selectmode, 1.0, 0.0, 0, 0, "Vertex select mode (Ctrl Tab 1)"); /* no edge */ /*uiDefIconButBitS(block, TOG, SCE_SELECT_EDGE, B_SEL_EDGE, ICON_EDGESEL, xco,0,XIC,YIC, &G.scene->selectmode, 1.0, 0.0, 0, 0, "Edge select mode (Ctrl Tab 2)"); xco+= XIC; */ - uiDefIconButBitS(block, TOG, SCE_SELECT_FACE, B_SEL_FACE, ICON_FACESEL, xco,0,XIC,YIC, &G.scene->selectmode, 1.0, 0.0, 0, 0, "Face select mode (Ctrl Tab 3)"); - xco+= XIC+8; + uiDefIconButBitS(block, TOG, SCE_SELECT_FACE, B_SEL_FACE, ICON_FACESEL, + xco+=XIC,0,XIC,YIC, &G.scene->selectmode, 1.0, 0.0, 0, 0, "Face select mode (Ctrl Tab 3)"); uiBlockEndAlign(block); } else { uiBlockBeginAlign(block); - uiDefIconButBitI(block, TOGN, SI_SELACTFACE, B_REDR, ICON_VERTEXSEL, xco,0,XIC,YIC, &G.sima->flag, 1.0, 0.0, 0, 0, "UV Vertex select mode"); - xco+= XIC; - uiDefIconButBitI(block, TOG, SI_SELACTFACE, B_REDR, ICON_FACESEL, xco,0,XIC,YIC, &G.sima->flag, 0, 0, 0, 0, "UV Face select mode"); - xco+= XIC+8; - uiBlockEndAlign(block); + uiDefIconButS(block, ROW, B_REDR, ICON_VERTEXSEL, + xco,0,XIC,YIC, &G.sima->selectmode, 0.0, SI_SELECT_VERTEX, 0, 0, "UV vertex select mode"); + uiDefIconButS(block, ROW, B_REDR, ICON_FACESEL, + xco+=XIC,0,XIC,YIC, &G.sima->selectmode, 0.0, SI_SELECT_FACE, 0, 0, "UV Face select mode"); + uiDefIconButS(block, ROW, B_REDR, ICON_MESH, + xco+=XIC,0,XIC,YIC, &G.sima->selectmode, 0.0, SI_SELECT_ISLAND, 0, 0, "UV Island select mode"); + uiBlockEndAlign(block); + /* would use these if const's could go in strings * SI_STICKY_LOC SI_STICKY_DISABLE SI_STICKY_VERTEX */ ubut = uiDefIconTextButC(block, ICONTEXTROW, B_REDR, ICON_STICKY_UVS_LOC, "Sticky UV Selection: %t|Disable%x1|Shared Location%x0|Shared Vertex%x2", - xco,0,XIC+10,YIC, &(G.sima->sticky), 0, 3.0, 0, 0, + xco+=XIC+10,0,XIC+10,YIC, &(G.sima->sticky), 0, 3.0, 0, 0, "Sticky UV Selection (Hotkeys: Shift C, Alt C, Ctrl C)"); } From 17dc66c1d1e9ac276e7e5bc772d23caf83e7a2d2 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 7 Jul 2008 04:17:03 +0000 Subject: [PATCH 05/37] [#17288] Sequencer API: added a method, a geter/setter, the blend modes dict and corrected a malfunction on audio strips blend mode from Luca Bonavita (mindrones) - adds the method "rebuildProxy()" useful to rebuild all the strips at once: the user can do - adds a BlendModes dictionary under the Blender.Scene.Sequence module: the user can see the blending option with - adds the getter/setter "blendMode" - adds a function seq_can_blend in sequence.c as requested by Peter, useful for these purposes but also to solve a bug after - the bug is you can apply blend modes to an audio strip that doesn't make sense: changed the test and now you cannot assign blend mode other than Replace to audio strips Omitted DNA cleanup part since its only whitespace and Id prefer to have a useful "svn blame" output. --- source/blender/include/BSE_sequence.h | 2 + source/blender/python/api2_2x/sceneSequence.c | 74 ++++++++++++++++++- source/blender/src/buttons_scene.c | 2 +- source/blender/src/sequence.c | 10 +++ 4 files changed, 84 insertions(+), 4 deletions(-) diff --git a/source/blender/include/BSE_sequence.h b/source/blender/include/BSE_sequence.h index 15a9218b735..0d96de7be60 100644 --- a/source/blender/include/BSE_sequence.h +++ b/source/blender/include/BSE_sequence.h @@ -92,6 +92,8 @@ void update_changed_seq_and_deps(struct Sequence *seq, int len_change, int ibuf_ struct RenderResult; void do_render_seq(struct RenderResult *rr, int cfra); +int seq_can_blend(struct Sequence *seq); + #define SEQ_HAS_PATH(seq) (seq->type==SEQ_MOVIE || seq->type==SEQ_HD_SOUND || seq->type==SEQ_RAM_SOUND || seq->type==SEQ_IMAGE) #endif diff --git a/source/blender/python/api2_2x/sceneSequence.c b/source/blender/python/api2_2x/sceneSequence.c index 56821980cd2..0d3ad3fcb44 100644 --- a/source/blender/python/api2_2x/sceneSequence.c +++ b/source/blender/python/api2_2x/sceneSequence.c @@ -81,6 +81,7 @@ returns None if notfound.\nIf 'name' is not specified, it returns a list of all static PyObject *Sequence_copy( BPy_Sequence * self ); static PyObject *Sequence_new( BPy_Sequence * self, PyObject * args ); static PyObject *Sequence_remove( BPy_Sequence * self, PyObject * args ); +static PyObject *Sequence_rebuildProxy( BPy_Sequence * self ); static PyObject *SceneSeq_new( BPy_SceneSeq * self, PyObject * args ); static PyObject *SceneSeq_remove( BPy_SceneSeq * self, PyObject * args ); @@ -96,6 +97,8 @@ static PyMethodDef BPy_Sequence_methods[] = { "() - Return a copy of the sequence containing the same objects."}, {"copy", ( PyCFunction ) Sequence_copy, METH_NOARGS, "() - Return a copy of the sequence containing the same objects."}, + {"rebuildProxy", ( PyCFunction ) Sequence_rebuildProxy, METH_VARARGS, + "() - Rebuild the active strip's Proxy."}, {NULL, NULL, 0, NULL} }; @@ -309,6 +312,7 @@ static PyObject *Sequence_copy( BPy_Sequence * self ) Py_RETURN_NONE; } + /*****************************************************************************/ /* PythonTypeObject callback function prototypes */ /*****************************************************************************/ @@ -383,8 +387,6 @@ static PyObject *SceneSeq_nextIter( BPy_Sequence * self ) } - - static PyObject *Sequence_getName( BPy_Sequence * self ) { return PyString_FromString( self->seq->name+2 ); @@ -403,11 +405,13 @@ static int Sequence_setName( BPy_Sequence * self, PyObject * value ) return 0; } + static PyObject *Sequence_getProxyDir( BPy_Sequence * self ) { return PyString_FromString( self->seq->strip->proxy ? self->seq->strip->proxy->dir : "" ); } + static int Sequence_setProxyDir( BPy_Sequence * self, PyObject * value ) { char *name = NULL; @@ -430,6 +434,14 @@ static int Sequence_setProxyDir( BPy_Sequence * self, PyObject * value ) } +static PyObject *Sequence_rebuildProxy( BPy_Sequence * self ) +{ + if (self->seq->strip->proxy) + seq_proxy_rebuild(self->seq); + Py_RETURN_NONE; +} + + static PyObject *Sequence_getSound( BPy_Sequence * self ) { if (self->seq->type == SEQ_RAM_SOUND && self->seq->sound) @@ -622,6 +634,54 @@ static int Sequence_setImages( BPy_Sequence * self, PyObject *value ) return 0; } +static PyObject *M_Sequence_BlendModesDict( void ) +{ + PyObject *M = PyConstant_New( ); + + if( M ) { + BPy_constant *d = ( BPy_constant * ) M; + PyConstant_Insert( d, "CROSS", PyInt_FromLong( SEQ_CROSS ) ); + PyConstant_Insert( d, "ADD", PyInt_FromLong( SEQ_ADD ) ); + PyConstant_Insert( d, "SUBTRACT", PyInt_FromLong( SEQ_SUB ) ); + PyConstant_Insert( d, "ALPHAOVER", PyInt_FromLong( SEQ_ALPHAOVER ) ); + PyConstant_Insert( d, "ALPHAUNDER", PyInt_FromLong( SEQ_ALPHAUNDER ) ); + PyConstant_Insert( d, "GAMMACROSS", PyInt_FromLong( SEQ_GAMCROSS ) ); + PyConstant_Insert( d, "MULTIPLY", PyInt_FromLong( SEQ_MUL ) ); + PyConstant_Insert( d, "OVERDROP", PyInt_FromLong( SEQ_OVERDROP ) ); + PyConstant_Insert( d, "PLUGIN", PyInt_FromLong( SEQ_PLUGIN ) ); + PyConstant_Insert( d, "WIPE", PyInt_FromLong( SEQ_WIPE ) ); + PyConstant_Insert( d, "GLOW", PyInt_FromLong( SEQ_GLOW ) ); + PyConstant_Insert( d, "TRANSFORM", PyInt_FromLong( SEQ_TRANSFORM ) ); + PyConstant_Insert( d, "COLOR", PyInt_FromLong( SEQ_COLOR ) ); + PyConstant_Insert( d, "SPEED", PyInt_FromLong( SEQ_SPEED ) ); + } + return M; +} + +static PyObject *Sequence_getBlendMode( BPy_Sequence * self ) +{ + return PyInt_FromLong( self->seq->blend_mode ); +} + +static int Sequence_setBlendMode( BPy_Sequence * self, PyObject * value ) +{ + struct Sequence *seq= self->seq; + int number = PyInt_AsLong( value ); + + if( number==-1 && PyErr_Occurred() ) + return EXPP_ReturnIntError( PyExc_TypeError, "expected an int value" ); + + if ( !seq_can_blend(seq) ) + return EXPP_ReturnIntError( PyExc_AttributeError, "this sequence type dosnt support blending" ); + + if (numberSEQ_EFFECT_MAX) + return EXPP_ReturnIntError( PyExc_TypeError, "expected an int value" ); + + seq->blend_mode=number; + + return 0; +} + /* * get floating point attributes */ @@ -836,7 +896,11 @@ static PyGetSetDef BPy_Sequence_getseters[] = { (getter)Sequence_getImages, (setter)Sequence_setImages, "Sequence scene", NULL}, - + {"blendMode", + (getter)Sequence_getBlendMode, (setter)Sequence_setBlendMode, + "Sequence Blend Mode", + NULL}, + {"type", (getter)getIntAttr, (setter)NULL, "", @@ -1131,6 +1195,7 @@ PyObject *M_Sequence_Get( PyObject * self, PyObject * args ) /*****************************************************************************/ PyObject *Sequence_Init( void ) { + PyObject *BlendModesDict = M_Sequence_BlendModesDict( ); PyObject *submodule; if( PyType_Ready( &Sequence_Type ) < 0 ) return NULL; @@ -1142,6 +1207,9 @@ PyObject *Sequence_Init( void ) "The Blender Sequence module\n\n\ This module provides access to **Sequence Data** in Blender.\n" ); + if( BlendModesDict ) + PyModule_AddObject( submodule, "BlendModes", BlendModesDict ); + /*Add SUBMODULES to the module*/ /*PyDict_SetItemString(dict, "Constraint", Constraint_Init()); //creates a *new* module*/ return submodule; diff --git a/source/blender/src/buttons_scene.c b/source/blender/src/buttons_scene.c index 1c98950080a..af90d01fb59 100644 --- a/source/blender/src/buttons_scene.c +++ b/source/blender/src/buttons_scene.c @@ -499,7 +499,7 @@ static char* seq_panel_blend_modes() so that would collide also. */ - if (!(last_seq->type & SEQ_EFFECT)) { + if ( seq_can_blend(last_seq) ) { int i; for (i = SEQ_EFFECT; i <= SEQ_EFFECT_MAX; i++) { diff --git a/source/blender/src/sequence.c b/source/blender/src/sequence.c index 6851929bbc2..9426548dc38 100644 --- a/source/blender/src/sequence.c +++ b/source/blender/src/sequence.c @@ -2380,6 +2380,16 @@ ImBuf *give_ibuf_seq(int rectx, int recty, int cfra, int chanshown) return i; } +/* check used when we need to change seq->blend_mode but not to effect or audio strips */ +int seq_can_blend(Sequence *seq) +{ + if (ELEM4(seq->type, SEQ_IMAGE, SEQ_META, SEQ_SCENE, SEQ_MOVIE)) { + return 1; + } else { + return 0; + } +} + /* threading api */ static ListBase running_threads; From e341586f9d4b2f7dec633217bf613a8b5e50f060 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 7 Jul 2008 21:04:30 +0000 Subject: [PATCH 06/37] own mistake with drawing used state bits. Other minor changes and removed some warnings. --- source/blender/src/buttons_logic.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/source/blender/src/buttons_logic.c b/source/blender/src/buttons_logic.c index 1a9e1030688..616a5a227c4 100644 --- a/source/blender/src/buttons_logic.c +++ b/source/blender/src/buttons_logic.c @@ -1560,7 +1560,6 @@ static void set_col_actuator(int item, int medium) static void change_object_actuator(void *act, void *arg) { bObjectActuator *oa = act; - int i; if (oa->type != oa->otype) { switch (oa->type) { @@ -1679,7 +1678,7 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh uiDefButF(block, NUM, 0, "", xco+45+2*wval, yco-148, wval, 19, oa->angularvelocity+2, -10000.0, 10000.0, 10, 0, ""); uiDefBut(block, LABEL, 0, "damp", xco, yco-171, 45, 19, NULL, 0, 0, 0, 0, "Number of frames to reach the target velocity"); - uiDefButI(block, NUM, 0, "", xco+45, yco-171, wval, 19, &oa->damping, 0.0, 1000.0, 100, 0, ""); + uiDefButS(block, NUM, 0, "", xco+45, yco-171, wval, 19, &oa->damping, 0.0, 1000.0, 100, 0, ""); uiDefButBitS(block, TOG, ACT_FORCE_LOCAL, 0, "L", xco+45+3*wval, yco-45, 15, 19, &oa->flag, 0.0, 0.0, 0, 0, "Local transformation"); uiDefButBitS(block, TOG, ACT_TORQUE_LOCAL, 0, "L", xco+45+3*wval, yco-64, 15, 19, &oa->flag, 0.0, 0.0, 0, 0, "Local transformation"); @@ -1816,11 +1815,11 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh uiDefButI(block, NUM, 0, "Sta", xco+20, yco-44, (width-100)/2, 19, &ia->sta, 0.0, MAXFRAMEF, 0, 0, - "Start frame"); + "Start frame, (subtract 1 to match blenders frame numbers)"); uiDefButI(block, NUM, 0, "End", xco+18+(width-90)/2, yco-44, (width-100)/2, 19, &ia->end, 0.0, MAXFRAMEF, 0, 0, - "End frame"); + "End frame, (subtract 1 to match blenders frame numbers)"); uiDefButBitS(block, TOG, ACT_IPOFORCE, B_REDR, "Force", xco+width-78, yco-44, 43, 19, @@ -1967,7 +1966,7 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh glRects(xco, yco-ysize, xco+width, yco); uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - uiDefIDPoinBut(block, test_obpoin_but, ID_OB, 1, "OB:", xco+10, yco-44, (width-20)/2, 19, &(eoa->ob), "Add this Object (cant be on an visible layer)"); + uiDefIDPoinBut(block, test_obpoin_but, ID_OB, 1, "OB:", xco+10, yco-44, (width-20)/2, 19, &(eoa->ob), "Add this Object and all its children (cant be on an visible layer)"); uiDefButI(block, NUM, 0, "Time:", xco+10+(width-20)/2, yco-44, (width-20)/2, 19, &eoa->time, 0.0, 2000.0, 0, 0, "Duration the new Object lives"); wval= (width-60)/3; @@ -2248,7 +2247,7 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh uiDefBut(block, TEX, 0, "Prop: ", xco+20, yco-44, width-40, 19, ga->name, 0.0, 31.0, 0, 0, "Use this property to define the Group position"); } else { - uiDefButI(block, NUM, 0, "Sta", xco+20, yco-44, (width-40)/2, 19, &ga->sta, 0.0, 2500.0, 0, 0, "Start frame"); + uiDefButI(block, NUM, 0, "State", xco+20, yco-44, (width-40)/2, 19, &ga->sta, 0.0, 2500.0, 0, 0, "Start frame"); uiDefButI(block, NUM, 0, "End", xco+20+(width-40)/2, yco-44, (width-40)/2, 19, &ga->end, 0.0, 2500.0, 0, 0, "End frame"); } yco-= ysize; @@ -3171,7 +3170,7 @@ void logic_buts(void) uiButSetFunc(but, check_object_state, but, &(ob->state)); } for (stbit=0; stbit<5; stbit++) { - but = uiDefButBitI(block, controller_state_mask&(1<<(stbit+offset)) ? BUT_TOGDUAL:TOG, 1<<(stbit+offset+15), stbit+offset+15, "", (short)(xco+35+12*stbit+13*offset), yco-12, 12, 12, (int *)&(ob->state), 0, 0, 0, 0, get_state_name(ob, (short)(stbit+offset+15))); + but = uiDefButBitI(block, controller_state_mask&(1<<(stbit+offset+15)) ? BUT_TOGDUAL:TOG, 1<<(stbit+offset+15), stbit+offset+15, "", (short)(xco+35+12*stbit+13*offset), yco-12, 12, 12, (int *)&(ob->state), 0, 0, 0, 0, get_state_name(ob, (short)(stbit+offset+15))); uiButSetFunc(but, check_object_state, but, &(ob->state)); } } @@ -3255,7 +3254,7 @@ void logic_buts(void) uiDefButBitS(block, TOG, BUTS_SENS_SEL, B_REDR, "Sel", xco+80, yco+35, (width-70)/4, 19, &G.buts->scaflag, 0, 0, 0, 0, "Show all selected Objects"); uiDefButBitS(block, TOG, BUTS_SENS_ACT, B_REDR, "Act", xco+80+(width-70)/4, yco+35, (width-70)/4, 19, &G.buts->scaflag, 0, 0, 0, 0, "Show active Object"); uiDefButBitS(block, TOG, BUTS_SENS_LINK, B_REDR, "Link", xco+80+2*(width-70)/4, yco+35, (width-70)/4, 19, &G.buts->scaflag, 0, 0, 0, 0, "Show linked Objects to Controller"); - uiDefButBitS(block, TOG, BUTS_SENS_STATE, B_REDR, "Sta", xco+80+3*(width-70)/4, yco+35, (width-70)/4, 19, &G.buts->scaflag, 0, 0, 0, 0, "Show only sensors connected to active states"); + uiDefButBitS(block, TOG, BUTS_SENS_STATE, B_REDR, "State", xco+80+3*(width-70)/4, yco+35, (width-70)/4, 19, &G.buts->scaflag, 0, 0, 0, 0, "Show only sensors connected to active states"); uiBlockEndAlign(block); for(a=0; ascaflag, 0, 0, 0, 0, "Show all selected Objects"); uiDefButBitS(block, TOG, BUTS_ACT_ACT, B_REDR, "Act", xco+110+(width-100)/4, yco+35, (width-100)/4, 19, &G.buts->scaflag, 0, 0, 0, 0, "Show active Object"); uiDefButBitS(block, TOG, BUTS_ACT_LINK, B_REDR, "Link", xco+110+2*(width-100)/4, yco+35, (width-100)/4, 19, &G.buts->scaflag, 0, 0, 0, 0, "Show linked Objects to Controller"); - uiDefButBitS(block, TOG, BUTS_ACT_STATE, B_REDR, "Sta", xco+110+3*(width-100)/4, yco+35, (width-100)/4, 19, &G.buts->scaflag, 0, 0, 0, 0, "Show only actuators connected to active states"); + uiDefButBitS(block, TOG, BUTS_ACT_STATE, B_REDR, "State", xco+110+3*(width-100)/4, yco+35, (width-100)/4, 19, &G.buts->scaflag, 0, 0, 0, 0, "Show only actuators connected to active states"); uiBlockEndAlign(block); for(a=0; a Date: Mon, 7 Jul 2008 22:11:11 +0000 Subject: [PATCH 07/37] patch from res2k to stop the blender window being upscaled on vista. --- intern/ghost/intern/GHOST_SystemWin32.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index 82a76b3c706..293f8fc1661 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -302,6 +302,15 @@ GHOST_TSuccess GHOST_SystemWin32::init() { GHOST_TSuccess success = GHOST_System::init(); + /* Disable scaling on high DPI displays on Vista */ + HMODULE user32 = ::LoadLibraryA("user32.dll"); + typedef BOOL (WINAPI * LPFNSETPROCESSDPIAWARE)(); + LPFNSETPROCESSDPIAWARE SetProcessDPIAware = + (LPFNSETPROCESSDPIAWARE)GetProcAddress(user32, "SetProcessDPIAware"); + if (SetProcessDPIAware) + SetProcessDPIAware(); + FreeLibrary(user32); + // Determine whether this system has a high frequency performance counter. */ m_hasPerformanceCounter = ::QueryPerformanceFrequency((LARGE_INTEGER*)&m_freq) == TRUE; if (m_hasPerformanceCounter) { From 3185253a066053ba0ece547e4f17adcc152ddb71 Mon Sep 17 00:00:00 2001 From: Geoffrey Bantle Date: Tue, 8 Jul 2008 02:22:37 +0000 Subject: [PATCH 08/37] -> UV and VCOL support for bevel (editmode) BMesh and the bevel code now support UVs/VCOLS. The offset is fixed at this time, but will be made dynamic later. --- source/blender/blenkernel/BKE_customdata.h | 5 + .../blenkernel/intern/BME_conversions.c | 137 ++++++++++++++++-- source/blender/blenkernel/intern/BME_eulers.c | 14 +- .../blender/blenkernel/intern/BME_structure.c | 1 - source/blender/blenkernel/intern/BME_tools.c | 82 ++++++++++- source/blender/blenkernel/intern/customdata.c | 117 ++++++++++++++- source/blender/blenlib/BLI_mempool.h | 4 +- source/blender/blenlib/intern/BLI_mempool.c | 13 +- 8 files changed, 339 insertions(+), 34 deletions(-) diff --git a/source/blender/blenkernel/BKE_customdata.h b/source/blender/blenkernel/BKE_customdata.h index 81c2e4a4b94..12f68c771e0 100644 --- a/source/blender/blenkernel/BKE_customdata.h +++ b/source/blender/blenkernel/BKE_customdata.h @@ -41,6 +41,7 @@ extern const CustomDataMask CD_MASK_MESH; extern const CustomDataMask CD_MASK_EDITMESH; extern const CustomDataMask CD_MASK_DERIVEDMESH; extern const CustomDataMask CD_MASK_BMESH; +extern const CustomDataMask CD_MASK_FACECORNERS; /* for ORIGINDEX layer type, indicates no original index for this element */ #define ORIGINDEX_NONE -1 @@ -264,4 +265,8 @@ void CustomData_set_layer_unique_name(struct CustomData *data, int index); /* for file reading compatibility, returns false if the layer was freed, only after this test passes, layer->data should be assigned */ int CustomData_verify_versions(struct CustomData *data, int index); + +void CustomData_to_bmeshpoly(struct CustomData *fdata, struct CustomData *pdata, struct CustomData *ldata); +void CustomData_from_bmeshpoly(struct CustomData *fdata, struct CustomData *pdata, struct CustomData *ldata); +void CustomData_bmesh_init_pool(struct CustomData *data, int allocsize); #endif diff --git a/source/blender/blenkernel/intern/BME_conversions.c b/source/blender/blenkernel/intern/BME_conversions.c index 7952546de7c..f375ca62726 100644 --- a/source/blender/blenkernel/intern/BME_conversions.c +++ b/source/blender/blenkernel/intern/BME_conversions.c @@ -55,14 +55,104 @@ #include "bmesh_private.h" #include "BSE_edit.h" -/*Converts an EditMesh to a BME_Mesh.*/ -static void bmesh_init_cdPool(CustomData *data, int allocsize){ - if(data->totlayer)data->pool = BLI_mempool_create(data->totsize, allocsize, allocsize); + +static void BME_corners_to_loops(BME_Mesh *bm, CustomData *facedata, void *face_block, BME_Poly *f,int numCol, int numTex){ + int i, j; + BME_Loop *l; + MTFace *texface; + MTexPoly *texpoly; + MCol *mcol; + MLoopCol *mloopcol; + MLoopUV *mloopuv; + + for(i=0; i < numTex; i++){ + texface = CustomData_em_get_n(facedata, face_block, CD_MTFACE, i); + texpoly = CustomData_bmesh_get_n(&bm->pdata, f->data, CD_MTEXPOLY, i); + + texpoly->tpage = texface->tpage; + texpoly->flag = texface->flag; + texpoly->transp = texface->transp; + texpoly->mode = texface->mode; + texpoly->tile = texface->tile; + texpoly->unwrap = texface->unwrap; + + j = 0; + l = f->loopbase; + do{ + mloopuv = CustomData_bmesh_get_n(&bm->ldata, l->data, CD_MLOOPUV, i); + mloopuv->uv[0] = texface->uv[j][0]; + mloopuv->uv[1] = texface->uv[j][1]; + j++; + l = l->next; + }while(l!=f->loopbase); + + } + for(i=0; i < numCol; i++){ + mcol = CustomData_em_get_n(facedata, face_block, CD_MCOL, i); + j = 0; + l = f->loopbase; + do{ + mloopcol = CustomData_bmesh_get_n(&bm->ldata, l->data, CD_MLOOPCOL, i); + mloopcol->r = mcol[j].r; + mloopcol->g = mcol[j].g; + mloopcol->b = mcol[j].b; + mloopcol->a = mcol[j].a; + j++; + l = l->next; + }while(l!=f->loopbase); + } } +static void BME_loops_to_corners(BME_Mesh *bm, CustomData *facedata, void *face_block, BME_Poly *f,int numCol, int numTex){ + int i, j; + BME_Loop *l; + MTFace *texface; + MTexPoly *texpoly; + MCol *mcol; + MLoopCol *mloopcol; + MLoopUV *mloopuv; + + for(i=0; i < numTex; i++){ + texface = CustomData_em_get_n(facedata, face_block, CD_MTFACE, i); + texpoly = CustomData_bmesh_get_n(&bm->pdata, f->data, CD_MTEXPOLY, i); + + texface->tpage = texpoly->tpage; + texface->flag = texpoly->flag; + texface->transp = texpoly->transp; + texface->mode = texpoly->mode; + texface->tile = texpoly->tile; + texface->unwrap = texpoly->unwrap; + + j = 0; + l = f->loopbase; + do{ + mloopuv = CustomData_bmesh_get_n(&bm->ldata, l->data, CD_MLOOPUV, i); + texface->uv[j][0] = mloopuv->uv[0]; + texface->uv[j][1] = mloopuv->uv[1]; + j++; + l = l->next; + }while(l!=f->loopbase); + + } + for(i=0; i < numCol; i++){ + mcol = CustomData_em_get_n(facedata, face_block, CD_MCOL, i); + j = 0; + l = f->loopbase; + do{ + mloopcol = CustomData_bmesh_get_n(&bm->ldata, l->data, CD_MLOOPCOL, i); + mcol[j].r = mloopcol->r; + mcol[j].g = mloopcol->g; + mcol[j].b = mloopcol->b; + mcol[j].a = mloopcol->a; + j++; + l = l->next; + }while(l!=f->loopbase); + } +} +/*move the EditMesh conversion functions to editmesh_tools.c*/ BME_Mesh *BME_editmesh_to_bmesh(EditMesh *em) { BME_Mesh *bm; - int allocsize[4] = {512,512,2048,512}; + int allocsize[4] = {512,512,2048,512}, numTex, numCol; BME_Vert *v1, *v2; BME_Edge *e, *edar[4]; BME_Poly *f; @@ -74,8 +164,21 @@ BME_Mesh *BME_editmesh_to_bmesh(EditMesh *em) { int len; bm = BME_make_mesh(allocsize); + /*copy custom data layout*/ CustomData_copy(&em->vdata, &bm->vdata, CD_MASK_BMESH, CD_CALLOC, 0); - bmesh_init_cdPool(&bm->vdata, allocsize[0]); + CustomData_copy(&em->edata, &bm->edata, CD_MASK_BMESH, CD_CALLOC, 0); + CustomData_copy(&em->fdata, &bm->pdata, CD_MASK_BMESH, CD_CALLOC, 0); + + /*copy face corner data*/ + CustomData_to_bmeshpoly(&em->fdata, &bm->pdata, &bm->ldata); + /*initialize memory pools*/ + CustomData_bmesh_init_pool(&bm->vdata, allocsize[0]); + CustomData_bmesh_init_pool(&bm->edata, allocsize[1]); + CustomData_bmesh_init_pool(&bm->ldata, allocsize[2]); + CustomData_bmesh_init_pool(&bm->pdata, allocsize[3]); + /*needed later*/ + numTex = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY); + numCol = CustomData_number_of_layers(&bm->ldata, CD_MLOOPCOL); BME_model_begin(bm); /*add verts*/ @@ -86,7 +189,6 @@ BME_Mesh *BME_editmesh_to_bmesh(EditMesh *em) { v1->flag = eve->f; v1->h = eve->h; v1->bweight = eve->bweight; - /*Copy Custom Data*/ CustomData_bmesh_copy_data(&em->vdata, &bm->vdata, eve->data, &v1->data); eve->tmp.v = (EditVert*)v1; @@ -106,15 +208,10 @@ BME_Mesh *BME_editmesh_to_bmesh(EditMesh *em) { if(eed->seam) e->flag |= ME_SEAM; if(eed->h & EM_FGON) e->flag |= ME_FGON; if(eed->h & 1) e->flag |= ME_HIDE; - - /* link the edges for face construction; - * kind of a dangerous thing - remember to cast back to BME_Edge before using! */ - /*Copy CustomData*/ - eed->tmp.e = (EditEdge*)e; + CustomData_bmesh_copy_data(&em->edata, &bm->edata, eed->data, &e->data); eed = eed->next; } - /*add faces.*/ efa= em->faces.first; while(efa) { @@ -143,12 +240,13 @@ BME_Mesh *BME_editmesh_to_bmesh(EditMesh *em) { if(efa->f & 1) f->flag |= ME_FACE_SEL; else f->flag &= ~ME_FACE_SEL; } + CustomData_bmesh_copy_data(&em->fdata, &bm->pdata, efa->data, &f->data); + BME_corners_to_loops(bm, &em->fdata, efa->data, f,numCol,numTex); efa = efa->next; } BME_model_end(bm); return bm; } - /* adds the geometry in the bmesh to G.editMesh (does not free G.editMesh) * if td != NULL, the transdata will be mapped to the EditVert's co */ EditMesh *BME_bmesh_to_editmesh(BME_Mesh *bm, BME_TransData_Head *td) { @@ -163,7 +261,7 @@ EditMesh *BME_bmesh_to_editmesh(BME_Mesh *bm, BME_TransData_Head *td) { EditEdge *eed; EditFace *efa; - int totvert, len, i; + int totvert, len, i, numTex, numCol; em = G.editMesh; @@ -171,6 +269,13 @@ EditMesh *BME_bmesh_to_editmesh(BME_Mesh *bm, BME_TransData_Head *td) { CustomData_copy(&bm->vdata, &em->vdata, CD_MASK_BMESH, CD_CALLOC, 0); + CustomData_copy(&bm->edata, &em->edata, CD_MASK_BMESH, CD_CALLOC, 0); + CustomData_copy(&bm->pdata, &em->fdata, CD_MASK_BMESH, CD_CALLOC, 0); + CustomData_from_bmeshpoly(&em->fdata, &bm->pdata, &bm->ldata); + numTex = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY); + numCol = CustomData_number_of_layers(&bm->ldata, CD_MLOOPCOL); + + /* convert to EditMesh */ /* make editverts */ totvert = BLI_countlist(&(bm->verts)); @@ -202,6 +307,8 @@ EditMesh *BME_bmesh_to_editmesh(BME_Mesh *bm, BME_TransData_Head *td) { if(e->flag & ME_HIDE) eed->h |= 1; if(G.scene->selectmode==SCE_SELECT_EDGE) EM_select_edge(eed, eed->f & SELECT); + + CustomData_em_copy_data(&bm->edata, &em->edata, e->data, &eed->data); } } @@ -228,6 +335,8 @@ EditMesh *BME_bmesh_to_editmesh(BME_Mesh *bm, BME_TransData_Head *td) { if(f->flag & ME_HIDE) efa->h= 1; if((G.f & G_FACESELECT) && (efa->f & SELECT)) EM_select_face(efa, 1); /* flush down */ + CustomData_em_copy_data(&bm->pdata, &em->fdata, f->data, &efa->data); + BME_loops_to_corners(bm, &em->fdata, efa->data, f,numCol,numTex); } } diff --git a/source/blender/blenkernel/intern/BME_eulers.c b/source/blender/blenkernel/intern/BME_eulers.c index 3403f5829fe..801e0b8bdec 100644 --- a/source/blender/blenkernel/intern/BME_eulers.c +++ b/source/blender/blenkernel/intern/BME_eulers.c @@ -39,6 +39,7 @@ #include "DNA_mesh_types.h" #include "BKE_utildefines.h" +#include "BKE_customdata.h" #include "BKE_bmesh.h" #include "BLI_blenlib.h" @@ -618,8 +619,8 @@ BME_Poly *BME_SFME(BME_Mesh *bm, BME_Poly *f, BME_Vert *v1, BME_Vert *v2, BME_Lo BME_disk_append_edge(e, v2); f2 = BME_addpolylist(bm,f); - f1loop = BME_create_loop(bm,v2,e,f,NULL); - f2loop = BME_create_loop(bm,v1,e,f2,NULL); + f1loop = BME_create_loop(bm,v2,e,f,v2loop); + f2loop = BME_create_loop(bm,v1,e,f2,v1loop); f1loop->prev = v2loop->prev; f2loop->prev = v1loop->prev; @@ -663,16 +664,16 @@ BME_Poly *BME_SFME(BME_Mesh *bm, BME_Poly *f, BME_Vert *v1, BME_Vert *v2, BME_Lo * Takes a an edge and pointer to one of its vertices and collapses * the edge on that vertex. * - * Before: OE KE + * Before: OE KE * ------- ------- * | || | - * OV KV TV + * OV KV TV * * * After: OE * --------------- * | | - * OV TV + * OV TV * * * Restrictions: @@ -723,6 +724,8 @@ int BME_JEKV(BME_Mesh *bm, BME_Edge *ke, BME_Vert *kv) /*remove ke from tv's disk cycle*/ BME_disk_remove_edge(ke, tv); + + /*deal with radial cycle of ke*/ if(ke->loop){ /*first step, fix the neighboring loops of all loops in ke's radial cycle*/ @@ -763,6 +766,7 @@ int BME_JEKV(BME_Mesh *bm, BME_Edge *ke, BME_Vert *kv) } + /*Validate disk cycles*/ diskbase = BME_disk_getpointer(ov->edge,ov); edok = BME_cycle_validate(valance1, diskbase); diff --git a/source/blender/blenkernel/intern/BME_structure.c b/source/blender/blenkernel/intern/BME_structure.c index 92ef9e3e03c..ca27f5efd10 100644 --- a/source/blender/blenkernel/intern/BME_structure.c +++ b/source/blender/blenkernel/intern/BME_structure.c @@ -41,7 +41,6 @@ #include "BLI_blenlib.h" #include "BLI_linklist.h" #include "BLI_ghash.h" - /** * MISC utility functions. * diff --git a/source/blender/blenkernel/intern/BME_tools.c b/source/blender/blenkernel/intern/BME_tools.c index 916e6bee59f..90259031e5c 100644 --- a/source/blender/blenkernel/intern/BME_tools.c +++ b/source/blender/blenkernel/intern/BME_tools.c @@ -215,10 +215,42 @@ static void BME_data_interp_from_verts(BME_Mesh *bm, BME_Vert *v1, BME_Vert *v2, src[1]= v2->data; w[0] = 1.0f-fac; w[1] = fac; - CustomData_em_interp(&bm->vdata, src, w, NULL, 2, v->data); + CustomData_bmesh_interp(&bm->vdata, src, w, NULL, 2, v->data); } } + +static void BME_data_facevert_edgesplit(BME_Mesh *bm, BME_Vert *v1, BME_Vert *v2, BME_Vert *v, BME_Edge *e1, float fac){ + void *src[2]; + float w[2]; + BME_Loop *l=NULL, *v1loop = NULL, *vloop = NULL, *v2loop = NULL; + + w[0] = 1.0f - fac; + w[1] = fac; + + if(!e1->loop) return; + l = e1->loop; + do{ + if(l->v == v1){ + v1loop = l; + vloop = v1loop->next; + v2loop = vloop->next; + }else if(l->v == v){ + v1loop = l->next; + vloop = l; + v2loop = l->prev; + + } + + src[0] = v1loop->data; + src[1] = v2loop->data; + + CustomData_bmesh_interp(&bm->ldata, src,w, NULL, 2, vloop->data); + l = l->radial.next->data; + }while(l!=e1->loop); +} + + /* a wrapper for BME_SEMV that transfers element flags */ /*add custom data interpolation in here!*/ static BME_Vert *BME_split_edge(BME_Mesh *bm, BME_Vert *v, BME_Edge *e, BME_Edge **ne, float percent) { BME_Vert *nv, *v2; @@ -238,9 +270,37 @@ static BME_Vert *BME_split_edge(BME_Mesh *bm, BME_Vert *v, BME_Edge *e, BME_Edge (*ne)->crease = e->crease; (*ne)->bweight = e->bweight; } + /*v->nv->v2*/ + BME_data_facevert_edgesplit(bm,v2, v, nv, e, 0.75); return nv; } +static void BME_collapse_vert(BME_Mesh *bm, BME_Edge *ke, BME_Vert *kv, float fac){ + void *src[2]; + float w[2]; + BME_Loop *l=NULL, *kvloop=NULL, *tvloop=NULL; + BME_Vert *tv = BME_edge_getothervert(ke,kv); + + w[0] = 1.0f - fac; + w[1] = fac; + + if(ke->loop){ + l = ke->loop; + do{ + if(l->v == tv && l->next->v == kv){ + tvloop = l; + kvloop = l->next; + + src[0] = kvloop->data; + src[1] = tvloop->data; + CustomData_bmesh_interp(&bm->ldata, src,w, NULL, 2, kvloop->data); + } + l=l->radial.next->data; + }while(l!=ke->loop); + } + BME_JEKV(bm,ke,kv); +} + static int BME_bevel_is_split_vert(BME_Loop *l) { @@ -367,6 +427,8 @@ static BME_Vert *BME_bevel_split_edge(BME_Mesh *bm, BME_Vert *v, BME_Vert *v1, B ov = BME_edge_getothervert(e1,v); sv = BME_split_edge(bm,v,e1,&ne,0); //BME_data_interp_from_verts(bm, v, ov, sv, 0.25); /*this is technically wrong...*/ + //BME_data_interp_from_faceverts(bm, v, ov, sv, 0.25); + //BME_data_interp_from_faceverts(bm, ov, v, sv, 0.25); BME_assign_transdata(td, bm, sv, sv->co, sv->co, NULL, sv->co, 0, -1, -1, NULL); /* quick default */ sv->tflag1 |= BME_BEVEL_BEVEL; ne->tflag1 = BME_BEVEL_ORIG; /* mark edge as original, even though it isn't */ @@ -408,6 +470,8 @@ static BME_Vert *BME_bevel_split_edge(BME_Mesh *bm, BME_Vert *v, BME_Vert *v1, B ov = BME_edge_getothervert(l->e,v); sv = BME_split_edge(bm,v,l->e,&ne,0); //BME_data_interp_from_verts(bm, v, ov, sv, 0.25); /*this is technically wrong...*/ + //BME_data_interp_from_faceverts(bm, v, ov, sv, 0.25); + //BME_data_interp_from_faceverts(bm, ov, v, sv, 0.25); BME_assign_transdata(td, bm, sv, sv->co, sv->co, NULL, sv->co, 0, -1, -1, NULL); /* quick default */ sv->tflag1 |= BME_BEVEL_BEVEL; ne->tflag1 = BME_BEVEL_ORIG; /* mark edge as original, even though it isn't */ @@ -586,12 +650,15 @@ static BME_Loop *BME_bevel_edge(BME_Mesh *bm, BME_Loop *l, float value, int opti if (kl->v == kv) { BME_split_face(bm,kl->f,kl->prev->v,kl->next->v,&nl,kl->prev->e); BME_JFKE(bm,((BME_Loop*)kl->prev->radial.next->data)->f,kl->f,kl->prev->e); - BME_JEKV(bm,kl->e,kv); + BME_collapse_vert(bm, kl->e, kv, 1.0); + //BME_JEKV(bm,kl->e,kv); + } else { BME_split_face(bm,kl->f,kl->next->next->v,kl->v,&nl,kl->next->e); BME_JFKE(bm,((BME_Loop*)kl->next->radial.next->data)->f,kl->f,kl->next->e); - BME_JEKV(bm,kl->e,kv); + BME_collapse_vert(bm, kl->e, kv, 1.0); + //BME_JEKV(bm,kl->e,kv); } l = l->prev; } @@ -620,12 +687,14 @@ static BME_Loop *BME_bevel_edge(BME_Mesh *bm, BME_Loop *l, float value, int opti if (kl->v == kv) { BME_split_face(bm,kl->f,kl->prev->v,kl->next->v,&nl,kl->prev->e); BME_JFKE(bm,((BME_Loop*)kl->prev->radial.next->data)->f,kl->f,kl->prev->e); - BME_JEKV(bm,kl->e,kv); + BME_collapse_vert(bm, kl->e, kv, 1.0); + //BME_JEKV(bm,kl->e,kv); } else { BME_split_face(bm,kl->f,kl->next->next->v,kl->v,&nl,kl->next->e); BME_JFKE(bm,((BME_Loop*)kl->next->radial.next->data)->f,kl->f,kl->next->e); - BME_JEKV(bm,kl->e,kv); + BME_collapse_vert(bm, kl->e, kv, 1.0); + //BME_JEKV(bm,kl->e,kv); } } @@ -1092,7 +1161,8 @@ static void bmesh_dissolve_disk(BME_Mesh *bm, BME_Vert *v){ e = BME_disk_nextedge(e,v); }while(e != v->edge); } - BME_JEKV(bm,v->edge,v); + BME_collapse_vert(bm, v->edge, v, 1.0); + //BME_JEKV(bm,v->edge,v); } } static BME_Mesh *BME_bevel_mesh(BME_Mesh *bm, float value, int res, int options, int defgrp_index, BME_TransData_Head *td) { diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index 4880a246e1c..d79dcb14f37 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -360,8 +360,80 @@ static void layerDefault_origspace_face(void *data, int count) } /* --------- */ +static void layerDefault_mloopcol(void *data, int count) +{ + static MLoopCol default_mloopcol = {255,255,255,255}; + MLoopCol *mlcol = (MLoopCol*)data; + int i; + for(i = 0; i < count; i++) + mlcol[i] = default_mloopcol; +} +static void layerInterp_mloopcol(void **sources, float *weights, + float *sub_weights, int count, void *dest) +{ + MLoopCol *mc = dest; + int i; + float *sub_weight; + struct { + float a; + float r; + float g; + float b; + } col; + col.a = col.r = col.g = col.b = 0; + + sub_weight = sub_weights; + for(i = 0; i < count; ++i){ + float weight = weights ? weights[i] : 1; + MLoopCol *src = sources[i]; + if(sub_weights){ + col.a += src->a * (*sub_weight) * weight; + col.r += src->r * (*sub_weight) * weight; + col.g += src->g * (*sub_weight) * weight; + col.b += src->b * (*sub_weight) * weight; + sub_weight++; + } else { + col.a += src->a * weight; + col.r += src->r * weight; + col.g += src->g * weight; + col.b += src->b * weight; + } + } + mc->a = (int)col.a; + mc->r = (int)col.r; + mc->g = (int)col.g; + mc->b = (int)col.b; +} +static void layerInterp_mloopuv(void **sources, float *weights, + float *sub_weights, int count, void *dest) +{ + MLoopUV *mluv = dest; + int i; + float *sub_weight; + struct { + float u; + float v; + }uv; + uv.u = uv.v = 0.0; + + sub_weight = sub_weights; + for(i = 0; i < count; ++i){ + float weight = weights ? weights[i] : 1; + MLoopUV *src = sources[i]; + if(sub_weights){ + uv.u += src->uv[0] * (*sub_weight) * weight; + uv.v += src->uv[1] * (*sub_weight) * weight; + sub_weight++; + } else { + uv.u += src->uv[0] * weight; + uv.v += src->uv[1] * weight; + } + } + mluv->uv[0] = uv.u; + mluv->uv[1] = uv.v; +} static void layerInterp_mcol(void **sources, float *weights, float *sub_weights, int count, void *dest) @@ -433,6 +505,8 @@ static void layerDefault_mcol(void *data, int count) mcol[i] = default_mcol; } + + const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { {sizeof(MVert), "MVert", 1, NULL, NULL, NULL, NULL, NULL, NULL}, {sizeof(MSticky), "MSticky", 1, NULL, NULL, NULL, layerInterp_msticky, NULL, @@ -457,8 +531,8 @@ const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { layerInterp_origspace_face, layerSwap_origspace_face, layerDefault_origspace_face}, {sizeof(float)*3, "", 0, NULL, NULL, NULL, NULL, NULL, NULL}, {sizeof(MTexPoly), "MTexPoly", 1, "Face Texture", NULL, NULL, NULL, NULL, NULL}, - {sizeof(MLoopUV), "MLoopUV", 1, "UV coord", NULL, NULL, NULL, NULL, NULL}, - {sizeof(MLoopCol), "MLoopCol", 1, "Col", NULL, NULL, NULL, NULL, NULL} + {sizeof(MLoopUV), "MLoopUV", 1, "UV coord", NULL, NULL, layerInterp_mloopuv, NULL, NULL}, + {sizeof(MLoopCol), "MLoopCol", 1, "Col", NULL, NULL, layerInterp_mloopcol, NULL, layerDefault_mloopcol} }; const char *LAYERTYPENAMES[CD_NUMTYPES] = { @@ -480,7 +554,11 @@ const CustomDataMask CD_MASK_DERIVEDMESH = CD_MASK_MCOL | CD_MASK_ORIGINDEX | CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR | CD_MASK_ORIGSPACE | CD_MASK_ORCO; const CustomDataMask CD_MASK_BMESH = - CD_MASK_MDEFORMVERT | CD_MASK_MTFACE | CD_MASK_MCOL; + CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR; +const CustomDataMask CD_MASK_FACECORNERS = + CD_MASK_MTFACE | CD_MASK_MCOL | CD_MASK_MTEXPOLY | CD_MASK_MLOOPUV | + CD_MASK_MLOOPCOL; + static const LayerTypeInfo *layerType_getInfo(int type) { @@ -1456,6 +1534,36 @@ void CustomData_from_em_block(const CustomData *source, CustomData *dest, } /*Bmesh functions*/ + +void CustomData_to_bmeshpoly(CustomData *fdata, CustomData *pdata, CustomData *ldata) +{ + int i; + for(i=0; i < fdata->totlayer; i++){ + if(fdata->layers[i].type == CD_MTFACE){ + CustomData_add_layer(pdata, CD_MTEXPOLY, CD_CALLOC, &(fdata->layers[i].name), 0); + CustomData_add_layer(ldata, CD_MLOOPUV, CD_CALLOC, &(fdata->layers[i].name), 0); + } + else if(fdata->layers[i].type == CD_MCOL) + CustomData_add_layer(ldata, CD_MLOOPCOL, CD_CALLOC, &(fdata->layers[i].name), 0); + } +} +void CustomData_from_bmeshpoly(CustomData *fdata, CustomData *pdata, CustomData *ldata){ + int i; + for(i=0; i < pdata->totlayer; i++){ + if(pdata->layers[i].type == CD_MTEXPOLY) + CustomData_add_layer(fdata, CD_MTFACE, CD_CALLOC, &(pdata->layers[i].name), 0); + } + for(i=0; i < ldata->totlayer; i++){ + if(ldata->layers[i].type == CD_MLOOPCOL) + CustomData_add_layer(fdata, CD_MCOL, CD_CALLOC, &(ldata->layers[i].name), 0); + } +} + + +void CustomData_bmesh_init_pool(CustomData *data, int allocsize){ + if(data->totlayer)data->pool = BLI_mempool_create(data->totsize, allocsize, allocsize); +} + void CustomData_bmesh_free_block(CustomData *data, void **block) { const LayerTypeInfo *typeInfo; @@ -1484,7 +1592,7 @@ static void CustomData_bmesh_alloc_block(CustomData *data, void **block) CustomData_bmesh_free_block(data, block); if (data->totsize > 0) - *block = BLI_mempool_alloc(data->pool); + *block = BLI_mempool_calloc(data->pool); else *block = NULL; } @@ -1601,7 +1709,6 @@ void CustomData_bmesh_interp(CustomData *data, void **src_blocks, float *weights for(i = 0; i < data->totlayer; ++i) { CustomDataLayer *layer = &data->layers[i]; const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type); - if(typeInfo->interp) { for(j = 0; j < count; ++j) sources[j] = (char *)src_blocks[j] + layer->offset; diff --git a/source/blender/blenlib/BLI_mempool.h b/source/blender/blenlib/BLI_mempool.h index a706e5f3874..8b31459dd38 100644 --- a/source/blender/blenlib/BLI_mempool.h +++ b/source/blender/blenlib/BLI_mempool.h @@ -36,7 +36,9 @@ typedef struct BLI_mempool BLI_mempool; BLI_mempool *BLI_mempool_create(int esize, int tote, int pchunk); void *BLI_mempool_alloc(BLI_mempool *pool); +void *BLI_mempool_calloc(BLI_mempool *pool); void BLI_mempool_free(BLI_mempool *pool, void *addr); void BLI_mempool_destroy(BLI_mempool *pool); -#endif \ No newline at end of file + +#endif diff --git a/source/blender/blenlib/intern/BLI_mempool.c b/source/blender/blenlib/intern/BLI_mempool.c index 7bbf0c4732e..7ac7b8b1791 100644 --- a/source/blender/blenlib/intern/BLI_mempool.c +++ b/source/blender/blenlib/intern/BLI_mempool.c @@ -89,7 +89,6 @@ BLI_mempool *BLI_mempool_create(int esize, int tote, int pchunk) curnode->next = NULL; return pool; } - void *BLI_mempool_alloc(BLI_mempool *pool){ void *retval=NULL; BLI_freenode *curnode=NULL; @@ -117,6 +116,16 @@ void *BLI_mempool_alloc(BLI_mempool *pool){ //memset(retval, 0, pool->esize); return retval; } + +void *BLI_mempool_calloc(BLI_mempool *pool){ + void *retval=NULL; + retval = BLI_mempool_alloc(pool); + memset(retval, 0, pool->esize); + return retval; +} + + + void BLI_mempool_free(BLI_mempool *pool, void *addr){ //doesnt protect against double frees, dont be stupid! BLI_freenode *newhead = addr; newhead->next = pool->free; @@ -128,4 +137,4 @@ void BLI_mempool_destroy(BLI_mempool *pool) for(mpchunk = pool->chunks.first; mpchunk; mpchunk = mpchunk->next) MEM_freeN(mpchunk->data); BLI_freelistN(&(pool->chunks)); MEM_freeN(pool); -} \ No newline at end of file +} From 22e87792f155b774399f66c512802a62c5751719 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Tue, 8 Jul 2008 07:06:42 +0000 Subject: [PATCH 09/37] == Select Swap for Armatures (Ctrl I) == It is now possible to swap the selection of bones in EditMode and PoseMode using the CTRL IKEY hotkey. As a result, the hotkey for adding IK Constraints has now changed to SHIFT IKEY (so that select swap can have a consistent hotkey) --- source/blender/src/editarmature.c | 51 ++++++++++++++++++++++-------- source/blender/src/header_view3d.c | 15 +++++++-- source/blender/src/space.c | 16 +++++++--- 3 files changed, 62 insertions(+), 20 deletions(-) diff --git a/source/blender/src/editarmature.c b/source/blender/src/editarmature.c index 39f93510358..6310dd0a262 100644 --- a/source/blender/src/editarmature.c +++ b/source/blender/src/editarmature.c @@ -1646,8 +1646,9 @@ void load_editArmature(void) } /* toggle==0: deselect - toggle==1: swap + toggle==1: swap (based on test) toggle==2: only active tag + toggle==3: swap (no test) */ void deselectall_armature(int toggle, int doundo) { @@ -1670,18 +1671,30 @@ void deselectall_armature(int toggle, int doundo) else sel= toggle; /* Set the flags */ - for (eBone=G.edbo.first;eBone;eBone=eBone->next){ - if (sel==1) { + for (eBone=G.edbo.first;eBone;eBone=eBone->next) { + if (sel==3) { + /* invert selection of bone */ + if ((arm->layer & eBone->layer) && (eBone->flag & BONE_HIDDEN_A)==0) { + eBone->flag ^= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); + eBone->flag &= ~BONE_ACTIVE; + } + } + else if (sel==1) { + /* select bone */ if(arm->layer & eBone->layer && (eBone->flag & BONE_HIDDEN_A)==0) { eBone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); if(eBone->parent) eBone->parent->flag |= (BONE_TIPSEL); } } - else if (sel==2) + else if (sel==2) { + /* clear active flag */ eBone->flag &= ~(BONE_ACTIVE); - else + } + else { + /* deselect bone */ eBone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL | BONE_ACTIVE); + } } allqueue(REDRAWVIEW3D, 0); @@ -3276,8 +3289,9 @@ int do_pose_selectbuffer(Base *base, unsigned int *buffer, short hits) } /* test==0: deselect all - test==1: swap select - test==2: only clear active tag + test==1: swap select (apply to all the opposite of current situation) + test==2: only clear active tag + test==3: swap select (no test / inverse selection status of all independently) */ void deselectall_posearmature (Object *ob, int test, int doundo) { @@ -3307,16 +3321,27 @@ void deselectall_posearmature (Object *ob, int test, int doundo) /* Set the flags accordingly */ for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { if ((pchan->bone->layer & arm->layer) && !(pchan->bone->flag & BONE_HIDDEN_P)) { - if (selectmode==0) pchan->bone->flag &= ~(BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL|BONE_ACTIVE); - else if (selectmode==1) pchan->bone->flag |= BONE_SELECTED; - else pchan->bone->flag &= ~BONE_ACTIVE; + if (test==3) { + pchan->bone->flag ^= (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL); + pchan->bone->flag &= ~BONE_ACTIVE; + } + else { + if (selectmode==0) pchan->bone->flag &= ~(BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL|BONE_ACTIVE); + else if (selectmode==1) pchan->bone->flag |= BONE_SELECTED; + else pchan->bone->flag &= ~BONE_ACTIVE; + } } } /* action editor */ - deselect_actionchannels(ob->action, 0); /* deselects for sure */ - if (selectmode == 1) - deselect_actionchannels(ob->action, 1); /* swaps */ + if (test == 3) { + deselect_actionchannels(ob->action, 2); /* inverts selection */ + } + else { + deselect_actionchannels(ob->action, 0); /* deselects for sure */ + if (selectmode == 1) + deselect_actionchannels(ob->action, 1); /* swaps */ + } allqueue(REDRAWBUTSEDIT, 0); allqueue(REDRAWBUTSOBJECT, 0); diff --git a/source/blender/src/header_view3d.c b/source/blender/src/header_view3d.c index 1ada2729289..0f3a46c8a8c 100644 --- a/source/blender/src/header_view3d.c +++ b/source/blender/src/header_view3d.c @@ -1313,6 +1313,9 @@ static void do_view3d_select_armaturemenu(void *arg, int event) case 3: /* Select Parent(s) */ select_bone_parent(); break; + case 4: /* Swap Select All */ + deselectall_armature(3, 1); + break; } allqueue(REDRAWVIEW3D, 0); } @@ -1331,6 +1334,8 @@ static uiBlock *view3d_select_armaturemenu(void *arg_unused) uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Select/Deselect All|A", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Swap Select All|Ctrl I", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Select Parent(s)|P", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, ""); if(curarea->headertype==HEADERTOP) { @@ -1356,12 +1361,15 @@ static void do_view3d_select_pose_armaturemenu(void *arg, int event) case 2: /* Select/Deselect all */ deselectall_posearmature(OBACT, 1, 1); break; - case 3: + case 3: /* Select Target(s) of Constraint(s) */ pose_select_constraint_target(); break; - case 4: + case 4: /* Select Bone's Parent */ select_bone_parent(); break; + case 5: /* Swap Select All */ + deselectall_posearmature(OBACT, 3, 1); + break; } allqueue(REDRAWVIEW3D, 0); } @@ -1379,6 +1387,7 @@ static uiBlock *view3d_select_pose_armaturemenu(void *arg_unused) uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Select/Deselect All|A", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Swap Select All|Ctrl I", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 5, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Select Constraint Target|W", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Select Parent(s)|P", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, ""); @@ -4106,7 +4115,7 @@ static uiBlock *view3d_pose_armature_ikmenu(void *arg_unused) block= uiNewBlock(&curarea->uiblocks, "view3d_pose_armature_ikmenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin); uiBlockSetButmFunc(block, do_view3d_pose_armature_ikmenu, NULL); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Add IK to Bone...|Ctrl I", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Add IK to Bone...|Shift I", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Clear IK...|Alt I", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, ""); uiBlockSetDirection(block, UI_RIGHT); diff --git a/source/blender/src/space.c b/source/blender/src/space.c index 4422411b1c5..fe9bb3279cc 100644 --- a/source/blender/src/space.c +++ b/source/blender/src/space.c @@ -2189,10 +2189,14 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) break; case IKEY: if(G.qual==LR_CTRLKEY) { - if(ob && (ob->flag & OB_POSEMODE) && ob->type==OB_ARMATURE) - pose_add_IK(); - else if(ob && G.obedit) - selectswap_mesh(); + if((ob) && (ob->flag & OB_POSEMODE) && (ob->type==OB_ARMATURE)) + deselectall_posearmature(ob, 3, 1); + else if(ob && G.obedit) { + if(G.obedit->type == OB_ARMATURE) + deselectall_armature(3, 1); + else + selectswap_mesh(); + } else selectswap(); } @@ -2200,6 +2204,10 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) if(ob && (ob->flag & OB_POSEMODE) && ob->type==OB_ARMATURE) pose_clear_IK(); } + else if(G.qual==LR_SHIFTKEY) { + if(ob && (ob->flag & OB_POSEMODE) && ob->type==OB_ARMATURE) + pose_add_IK(); + } break; case JKEY: From 878a5303f3f2e310e5bcbc5cead6ed9e4eb28286 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Tue, 8 Jul 2008 07:30:38 +0000 Subject: [PATCH 10/37] Compiler warning fixes (how some of this stuff compiled without stopping compiling I don't know) ;) --- source/blender/blenkernel/BKE_bmeshCustomData.h | 4 ++-- source/blender/blenkernel/intern/BME_Customdata.c | 9 +++++---- source/blender/blenlib/intern/BLI_kdopbvh.c | 2 ++ source/blender/src/editsima.c | 2 +- source/blender/src/view.c | 2 +- 5 files changed, 11 insertions(+), 8 deletions(-) diff --git a/source/blender/blenkernel/BKE_bmeshCustomData.h b/source/blender/blenkernel/BKE_bmeshCustomData.h index 423f75e532d..4f5f2641f54 100644 --- a/source/blender/blenkernel/BKE_bmeshCustomData.h +++ b/source/blender/blenkernel/BKE_bmeshCustomData.h @@ -38,7 +38,7 @@ #ifndef BKE_BMESHCUSTOMDATA_H #define BKE_BMESHCUSTOMDATA_H -struct BME_mempool; +struct BLI_mempool; /*Custom Data Types and defines Eventual plan is to move almost everything to custom data and let caller @@ -62,7 +62,7 @@ typedef struct BME_CustomDataLayer { typedef struct BME_CustomData { struct BME_CustomDataLayer *layers; /*Custom Data Layers*/ - struct BME_mempool *pool; /*pool for alloc of blocks*/ + struct BLI_mempool *pool; /*pool for alloc of blocks*/ int totlayer, totsize; /*total layers and total size in bytes of each block*/ } BME_CustomData; diff --git a/source/blender/blenkernel/intern/BME_Customdata.c b/source/blender/blenkernel/intern/BME_Customdata.c index 8b48efbdbd2..1fc8a4071dc 100644 --- a/source/blender/blenkernel/intern/BME_Customdata.c +++ b/source/blender/blenkernel/intern/BME_Customdata.c @@ -40,6 +40,7 @@ #include "bmesh_private.h" #include #include "MEM_guardedalloc.h" +#include "BLI_mempool.h" /********************* Layer type information **********************/ typedef struct BME_LayerTypeInfo { @@ -83,7 +84,7 @@ void BME_CD_Create(BME_CustomData *data, BME_CustomDataInit *init, int initalloc if(data->totlayer){ /*alloc memory*/ data->layers = MEM_callocN(sizeof(BME_CustomDataLayer)*data->totlayer, "BMesh Custom Data Layers"); - data->pool = BME_mempool_create(data->totsize, initalloc, initalloc); + data->pool = BLI_mempool_create(data->totsize, initalloc, initalloc); /*initialize layer data*/ for(i=0; i < BME_CD_NUMTYPES; i++){ if(init->layout[i]){ @@ -102,7 +103,7 @@ void BME_CD_Create(BME_CustomData *data, BME_CustomDataInit *init, int initalloc void BME_CD_Free(BME_CustomData *data) { - if(data->pool) BME_mempool_destroy(data->pool); + if(data->pool) BLI_mempool_destroy(data->pool); } /*Block level ops*/ @@ -119,7 +120,7 @@ void BME_CD_free_block(BME_CustomData *data, void **block) typeInfo->free((char*)*block + offset, 1, typeInfo->size); } } - BME_mempool_free(data->pool, *block); + BLI_mempool_free(data->pool, *block); *block = NULL; } @@ -130,7 +131,7 @@ static void BME_CD_alloc_block(BME_CustomData *data, void **block) if (*block) BME_CD_free_block(data, block); //if we copy layers that have their own free functions like deformverts if (data->totsize > 0) - *block = BME_mempool_alloc(data->pool); + *block = BLI_mempool_alloc(data->pool); else *block = NULL; } diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index a85883f6572..a97b9ca6672 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -523,6 +523,7 @@ static void bvh_div_nodes(BVHTree *tree, BVHNode *node, int start, int end, char return; } +#if 0 static void verify_tree(BVHTree *tree) { int i, j, check = 0; @@ -569,6 +570,7 @@ static void verify_tree(BVHTree *tree) printf("branches: %d, leafs: %d, total: %d\n", tree->totbranch, tree->totleaf, tree->totbranch + tree->totleaf); } +#endif void BLI_bvhtree_balance(BVHTree *tree) { diff --git a/source/blender/src/editsima.c b/source/blender/src/editsima.c index 7c2edc3e236..69070d61bf0 100644 --- a/source/blender/src/editsima.c +++ b/source/blender/src/editsima.c @@ -694,7 +694,7 @@ void mouse_select_sima(void) EditFace *efa; MTFace *tf, *nearesttf; EditFace *nearestefa=NULL; - int a, selectsticky, edgeloop, actface, nearestuv, nearestedge, i, shift, island; + int a, selectsticky, edgeloop, actface, nearestuv, nearestedge, i, shift, island=0; char sticky= 0; int flush = 0; /* 0 == dont flush, 1 == sel, -1 == desel; only use when selection sync is enabled */ unsigned int hitv[4], nearestv; diff --git a/source/blender/src/view.c b/source/blender/src/view.c index f457f9203ff..12450bee9de 100644 --- a/source/blender/src/view.c +++ b/source/blender/src/view.c @@ -1154,7 +1154,7 @@ void viewmoveNDOF(int mode) float q1[4]; float obofs[3]; float reverse; - float diff[4]; + //float diff[4]; float d, curareaX, curareaY; float mat[3][3]; float upvec[3]; From a166def7b3b20f3a36779fa5a336a6b286e0f966 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 8 Jul 2008 10:18:34 +0000 Subject: [PATCH 11/37] scenes set pose objects would draw in posemode while weight painting if they were set to posemode in their scene. --- source/blender/include/BDR_drawobject.h | 1 + source/blender/include/BIF_editarmature.h | 2 +- source/blender/src/drawarmature.c | 17 +++++++++-------- source/blender/src/drawobject.c | 8 ++++---- source/blender/src/drawview.c | 4 ++-- 5 files changed, 17 insertions(+), 15 deletions(-) diff --git a/source/blender/include/BDR_drawobject.h b/source/blender/include/BDR_drawobject.h index 3f9a6e438cc..de28db64c3b 100644 --- a/source/blender/include/BDR_drawobject.h +++ b/source/blender/include/BDR_drawobject.h @@ -63,6 +63,7 @@ void get_local_bounds(struct Object *ob, float *center, float *size); /* drawing flags: */ #define DRAW_PICKING 1 #define DRAW_CONSTCOLOR 2 +#define DRAW_SCENESET 4 void draw_object(struct Base *base, int flag); void drawaxes(float size, int flag, char drawtype); diff --git a/source/blender/include/BIF_editarmature.h b/source/blender/include/BIF_editarmature.h index 0e1557ac378..24112c7f11a 100644 --- a/source/blender/include/BIF_editarmature.h +++ b/source/blender/include/BIF_editarmature.h @@ -80,7 +80,7 @@ void clear_armature(struct Object *ob, char mode); void delete_armature(void); void deselectall_armature(int toggle, int doundo); void deselectall_posearmature (struct Object *ob, int test, int doundo); -int draw_armature(struct Base *base, int dt); +int draw_armature(struct Base *base, int dt, int flag); void extrude_armature(int forked); void subdivide_armature(int numcuts); diff --git a/source/blender/src/drawarmature.c b/source/blender/src/drawarmature.c index 73915a69139..6d78b21dfbb 100644 --- a/source/blender/src/drawarmature.c +++ b/source/blender/src/drawarmature.c @@ -2500,7 +2500,7 @@ static void draw_ghost_poses(Base *base) /* ********************************** Armature Drawing - Main ************************* */ /* called from drawobject.c, return 1 if nothing was drawn */ -int draw_armature(Base *base, int dt) +int draw_armature(Base *base, int dt, int flag) { Object *ob= base->object; bArmature *arm= ob->data; @@ -2544,15 +2544,16 @@ int draw_armature(Base *base, int dt) if (arm->ghostep) draw_ghost_poses(base); } + if ((flag & DRAW_SCENESET)==0) { + if(ob==OBACT) + arm->flag |= ARM_POSEMODE; + else if(G.f & G_WEIGHTPAINT) + arm->flag |= ARM_POSEMODE; - if(ob==OBACT) - arm->flag |= ARM_POSEMODE; - else if(G.f & G_WEIGHTPAINT) - arm->flag |= ARM_POSEMODE; - - draw_pose_paths(ob); + draw_pose_paths(ob); + } } - } + } draw_pose_channels(base, dt); arm->flag &= ~ARM_POSEMODE; diff --git a/source/blender/src/drawobject.c b/source/blender/src/drawobject.c index 96ba8c71755..045bf292446 100644 --- a/source/blender/src/drawobject.c +++ b/source/blender/src/drawobject.c @@ -4620,7 +4620,7 @@ static void drawSolidSelect(Base *base) } else if(ob->type==OB_ARMATURE) { if(!(ob->flag & OB_POSEMODE)) { - draw_armature(base, OB_WIRE); + draw_armature(base, OB_WIRE, 0); } } @@ -4741,7 +4741,7 @@ void drawRBpivot(bRigidBodyJointConstraint *data){ setlinestyle(0); } -/* flag can be DRAW_PICKING and/or DRAW_CONSTCOLOR */ +/* flag can be DRAW_PICKING and/or DRAW_CONSTCOLOR, DRAW_SCENESET */ void draw_object(Base *base, int flag) { static int warning_recursive= 0; @@ -4943,7 +4943,7 @@ void draw_object(Base *base, int flag) /* draw outline for selected solid objects, mesh does itself */ if((G.vd->flag & V3D_SELECT_OUTLINE) && ob->type!=OB_MESH) { - if(dt>OB_WIRE && dtOB_WIRE && dtdtx&OB_DRAWWIRE) && (ob->flag&SELECT) && !(flag&DRAW_PICKING)) { drawSolidSelect(base); } @@ -5090,7 +5090,7 @@ void draw_object(Base *base, int flag) break; case OB_ARMATURE: if(dt>OB_WIRE) set_gl_material(0); // we use defmaterial - empty_object= draw_armature(base, dt); + empty_object= draw_armature(base, dt, flag); break; default: drawaxes(1.0, flag, OB_ARROWS); diff --git a/source/blender/src/drawview.c b/source/blender/src/drawview.c index 2f1cdb8b951..f595a101f63 100644 --- a/source/blender/src/drawview.c +++ b/source/blender/src/drawview.c @@ -3097,7 +3097,7 @@ void drawview3dspace(ScrArea *sa, void *spacedata) if(v3d->lay & base->lay) { BIF_ThemeColorBlend(TH_WIRE, TH_BACK, 0.6f); - draw_object(base, DRAW_CONSTCOLOR); + draw_object(base, DRAW_CONSTCOLOR|DRAW_SCENESET); if(base->object->transflag & OB_DUPLI) { draw_dupli_objects_color(v3d, base, TH_WIRE); @@ -3319,7 +3319,7 @@ void drawview3d_render(struct View3D *v3d, int winx, int winy, float winmat[][4] where_is_object(base->object); BIF_ThemeColorBlend(TH_WIRE, TH_BACK, 0.6f); - draw_object(base, DRAW_CONSTCOLOR); + draw_object(base, DRAW_CONSTCOLOR|DRAW_SCENESET); if(base->object->transflag & OB_DUPLI) { draw_dupli_objects(v3d, base); From 168ae6765e3b53d4485bccc1ddbc39e74bdfe0d9 Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Tue, 8 Jul 2008 11:47:22 +0000 Subject: [PATCH 12/37] Bugfix #16535 The infamous Fkey 'make face' in editmode still failed in cases, giving an annoying convex error popup. Found two errors in this code: - not all cases were evaluated to make a face of 4 vertices (6 cases) - the function that makes always a face when the 4 edges already exist failed when not in vertex-select mode. I also removed the popup, but added a print... its still not perfect. --- source/blender/src/editmesh_add.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/source/blender/src/editmesh_add.c b/source/blender/src/editmesh_add.c index 952ae957f34..9516f39b05c 100644 --- a/source/blender/src/editmesh_add.c +++ b/source/blender/src/editmesh_add.c @@ -379,7 +379,7 @@ static EditFace *addface_from_edges(void) /* find the 4 edges */ for(eed= em->edges.first; eed; eed= eed->next) { - if(eed->f & SELECT) { + if( (eed->f & SELECT) || (eed->v1->f & eed->v2->f & SELECT) ) { if(eedar[0]==NULL) eedar[0]= eed; else if(eedar[1]==NULL) eedar[1]= eed; else if(eedar[2]==NULL) eedar[2]= eed; @@ -765,6 +765,7 @@ void addedgeface_mesh(void) /* if 4 edges exist, we just create the face, convex or not */ efa= addface_from_edges(); if(efa==NULL) { + /* the order of vertices can be anything, 6 cases to check */ if( convex(neweve[0]->co, neweve[1]->co, neweve[2]->co, neweve[3]->co) ) { efa= addfacelist(neweve[0], neweve[1], neweve[2], neweve[3], NULL, NULL); @@ -775,17 +776,16 @@ void addedgeface_mesh(void) else if( convex(neweve[0]->co, neweve[2]->co, neweve[1]->co, neweve[3]->co) ) { efa= addfacelist(neweve[0], neweve[2], neweve[1], neweve[3], NULL, NULL); } - - else if( convex(neweve[1]->co, neweve[2]->co, neweve[3]->co, neweve[0]->co) ) { - efa= addfacelist(neweve[1], neweve[2], neweve[3], neweve[0], NULL, NULL); + else if( convex(neweve[0]->co, neweve[1]->co, neweve[3]->co, neweve[2]->co) ) { + efa= addfacelist(neweve[0], neweve[1], neweve[3], neweve[2], NULL, NULL); } - else if( convex(neweve[1]->co, neweve[3]->co, neweve[0]->co, neweve[2]->co) ) { - efa= addfacelist(neweve[1], neweve[3], neweve[0], neweve[2], NULL, NULL); + else if( convex(neweve[0]->co, neweve[3]->co, neweve[2]->co, neweve[1]->co) ) { + efa= addfacelist(neweve[0], neweve[3], neweve[2], neweve[1], NULL, NULL); } - else if( convex(neweve[1]->co, neweve[3]->co, neweve[2]->co, neweve[0]->co) ) { - efa= addfacelist(neweve[1], neweve[3], neweve[2], neweve[0], NULL, NULL); + else if( convex(neweve[0]->co, neweve[3]->co, neweve[1]->co, neweve[2]->co) ) { + efa= addfacelist(neweve[0], neweve[3], neweve[1], neweve[2], NULL, NULL); } - else error("The selected vertices form a concave quad"); + else printf("cannot find nice quad from concave set of vertices\n"); } } } From d1fd99b0700b6a779e4d01ddbffb4b946d02b382 Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Tue, 8 Jul 2008 12:18:43 +0000 Subject: [PATCH 13/37] BGE logic patch: new "Add" mode for Ipo actuator, several corrections in state system. New Add mode for Ipo actuator ============================= A new Add button, mutually exclusive with Force button, is available in the Ipo actuator. When selected, it activates the Add mode that consists in adding the Ipo curve to the current object situation in world coordinates, or parent coordinates if the object has a parent. Scale Ipo curves are multiplied instead of added to the object current scale. If the local flag is selected, the Ipo curve is added (multiplied) in the object's local coordinates. Delta Ipo curves are handled identically to normal Ipo curve and there is no need to work with Delta Ipo curves provided that you make sure that the Ipo curve starts from origin. Origin means location 0 for Location Ipo curve, rotation 0 for Rotation Ipo curve and scale 1 for Scale Ipo curve. The "current object situation" means the object's location, rotation and scale at the start of the Ipo curve. For Loop Stop and Loop End Ipo actuators, this means at the start of each loop. This initial state is used as a base during the execution of the Ipo Curve but when the Ipo curve is restarted (later or immediately in case of Loop mode), the object current situation at that time is used as the new base. For reference, here is the exact operation of the Add mode for each type of Ipo curve (oLoc, oRot, oScale, oMat: object's loc/rot/scale and orientation matrix at the start of the curve; iLoc, iRot, iScale, iMat: Ipo curve loc/rot/scale and orientation matrix resulting from the rotation). Location Local=false: newLoc = oLoc+iLoc Local=true : newLoc = oLoc+oScale*(oMat*iLoc) Rotation Local=false: newMat = iMat*oMat Local=true : newMat = oMat*iMat Scale Local=false: newScale = oScale*iScale Local=true : newScale = oScale*iScale Add+Local mode is very useful to have dynamic object executing complex movement relative to their current location/orientation. Of cource, dynamics should be disabled during the execution of the curve. Several corrections in state system =================================== - Object initial state is taken into account when adding object dynamically - Fix bug with link count when adding object dynamically - Fix false on-off detection for Actuator sensor when actuator is trigged on negative event. - Fix Parent actuator false activation on negative event - Loop Ipo curve not restarting at correct frame when start frame is different from one. --- .../blender/blenlib/BLI_blenlib.vcproj | 6 + source/blender/makesdna/DNA_actuator_types.h | 5 +- source/blender/src/buttons_logic.c | 61 ++++--- .../Converter/BL_BlenderDataConversion.cpp | 3 +- .../Converter/KX_ConvertActuators.cpp | 7 +- .../GameLogic/SCA_ActuatorSensor.cpp | 2 +- source/gameengine/GameLogic/SCA_IActuator.h | 1 + source/gameengine/GameLogic/SCA_IObject.cpp | 8 +- source/gameengine/GameLogic/SCA_IObject.h | 15 ++ source/gameengine/GameLogic/SCA_ISensor.h | 2 + source/gameengine/Ketsji/KX_GameObject.cpp | 39 ++-- source/gameengine/Ketsji/KX_GameObject.h | 14 +- .../gameengine/Ketsji/KX_IPO_SGController.cpp | 87 ++++++--- .../gameengine/Ketsji/KX_IPO_SGController.h | 7 +- source/gameengine/Ketsji/KX_IpoActuator.cpp | 171 ++++++++---------- source/gameengine/Ketsji/KX_IpoActuator.h | 12 +- .../gameengine/Ketsji/KX_ParentActuator.cpp | 6 + source/gameengine/Ketsji/KX_Scene.cpp | 2 + source/gameengine/SceneGraph/SG_Controller.h | 4 +- 19 files changed, 274 insertions(+), 178 deletions(-) diff --git a/projectfiles_vc7/blender/blenlib/BLI_blenlib.vcproj b/projectfiles_vc7/blender/blenlib/BLI_blenlib.vcproj index 34c195cf23d..0dfbcaa5577 100644 --- a/projectfiles_vc7/blender/blenlib/BLI_blenlib.vcproj +++ b/projectfiles_vc7/blender/blenlib/BLI_blenlib.vcproj @@ -358,6 +358,9 @@ + + @@ -473,6 +476,9 @@ + + diff --git a/source/blender/makesdna/DNA_actuator_types.h b/source/blender/makesdna/DNA_actuator_types.h index 3cf80a4efa6..77ebef744eb 100644 --- a/source/blender/makesdna/DNA_actuator_types.h +++ b/source/blender/makesdna/DNA_actuator_types.h @@ -339,8 +339,9 @@ typedef struct FreeCamera { /* ipoactuator->flag */ #define ACT_IPOFORCE (1 << 0) #define ACT_IPOEND (1 << 1) -#define ACT_IPOFORCE_LOCAL (1 << 2) -#define ACT_IPOCHILD (1 << 4) +#define ACT_IPOLOCAL (1 << 2) +#define ACT_IPOCHILD (1 << 4) +#define ACT_IPOADD (1 << 5) /* ipoactuator->flag for k2k */ #define ACT_K2K_PREV 1 diff --git a/source/blender/src/buttons_logic.c b/source/blender/src/buttons_logic.c index 616a5a227c4..7050e61a6ac 100644 --- a/source/blender/src/buttons_logic.c +++ b/source/blender/src/buttons_logic.c @@ -1581,6 +1581,18 @@ static void change_object_actuator(void *act, void *arg) } } +static void change_ipo_actuator(void *arg1_but, void *arg2_ia) +{ + bIpoActuator *ia = arg2_ia; + uiBut *but = arg1_but; + + if (but->retval & ACT_IPOFORCE) + ia->flag &= ~ACT_IPOADD; + else if (but->retval & ACT_IPOADD) + ia->flag &= ~ACT_IPOFORCE; + but->retval = B_REDR; +} + void update_object_actuator_PID(void *act, void *arg) { bObjectActuator *oa = act; @@ -1799,42 +1811,49 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh str = "Ipo types %t|Play %x0|Ping Pong %x1|Flipper %x2|Loop Stop %x3|Loop End %x4|Property %x6"; - uiDefButS(block, MENU, B_REDR, str, xco+20, yco-24, width-40 - (width-40)/3, 19, &ia->type, 0, 0, 0, 0, ""); - uiDefButBitS(block, TOG, ACT_IPOCHILD, B_REDR, - "Child", xco+20+0.666*(width-40), yco-24, (width-40)/3, 19, + uiDefButS(block, MENU, B_REDR, str, xco+10, yco-24, (width-20)/2, 19, &ia->type, 0, 0, 0, 0, ""); + + but = uiDefButBitS(block, TOG, ACT_IPOFORCE, ACT_IPOFORCE, + "Force", xco+10+(width-20)/2, yco-24, (width-20)/4-10, 19, &ia->flag, 0, 0, 0, 0, - "Add all children Objects as well"); + "Convert Ipo to force. Force is applied in global or local coordinate according to Local flag"); + uiButSetFunc(but, change_ipo_actuator, but, ia); + + but = uiDefButBitS(block, TOG, ACT_IPOADD, ACT_IPOADD, + "Add", xco+3*(width-20)/4, yco-24, (width-20)/4-10, 19, + &ia->flag, 0, 0, 0, 0, + "Ipo is added to the current loc/rot/scale in global or local coordinate according to Local flag"); + uiButSetFunc(but, change_ipo_actuator, but, ia); + + /* Only show the do-force-local toggle if force is requested */ + if (ia->flag & (ACT_IPOFORCE|ACT_IPOADD)) { + uiDefButBitS(block, TOG, ACT_IPOLOCAL, 0, + "L", xco+width-30, yco-24, 20, 19, + &ia->flag, 0, 0, 0, 0, + "Let the ipo acts in local coordinates, used in Force and Add mode."); + } if(ia->type==ACT_IPO_FROM_PROP) { uiDefBut(block, TEX, 0, - "Prop: ", xco+20, yco-44, width-40, 19, + "Prop: ", xco+10, yco-44, width-80, 19, ia->name, 0.0, 31.0, 0, 0, "Use this property to define the Ipo position"); } else { uiDefButI(block, NUM, 0, - "Sta", xco+20, yco-44, (width-100)/2, 19, + "Sta", xco+10, yco-44, (width-80)/2, 19, &ia->sta, 0.0, MAXFRAMEF, 0, 0, "Start frame, (subtract 1 to match blenders frame numbers)"); uiDefButI(block, NUM, 0, - "End", xco+18+(width-90)/2, yco-44, (width-100)/2, 19, + "End", xco+10+(width-80)/2, yco-44, (width-80)/2, 19, &ia->end, 0.0, MAXFRAMEF, 0, 0, "End frame, (subtract 1 to match blenders frame numbers)"); - - uiDefButBitS(block, TOG, ACT_IPOFORCE, B_REDR, - "Force", xco+width-78, yco-44, 43, 19, - &ia->flag, 0, 0, 0, 0, - "Convert Ipo to force"); - - /* Only show the do-force-local toggle if force is requested */ - if (ia->flag & ACT_IPOFORCE) { - uiDefButBitS(block, TOG, ACT_IPOFORCE_LOCAL, 0, - "L", xco+width-35, yco-44, 15, 19, - &ia->flag, 0, 0, 0, 0, - "Let the force-ipo act in local coordinates."); - } - } + uiDefButBitS(block, TOG, ACT_IPOCHILD, B_REDR, + "Child", xco+10+(width-80), yco-44, 60, 19, + &ia->flag, 0, 0, 0, 0, + "Update IPO on all children Objects as well"); + yco-= ysize; break; } diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index 665783a1ba5..d8b157cb5b4 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -2331,7 +2331,8 @@ void BL_ConvertBlenderObjects(struct Main* maggie, { KX_GameObject* gameobj = static_cast(logicbrick_conversionlist->GetValue(i)); struct Object* blenderobj = converter->FindBlenderObject(gameobj); - gameobj->SetState((blenderobj->init_state)?blenderobj->init_state:blenderobj->state); + gameobj->SetInitState((blenderobj->init_state)?blenderobj->init_state:blenderobj->state); + gameobj->ResetState(); } #endif //CONVERT_LOGIC diff --git a/source/gameengine/Converter/KX_ConvertActuators.cpp b/source/gameengine/Converter/KX_ConvertActuators.cpp index 6e05ea31fe8..9b1bc1e6b90 100644 --- a/source/gameengine/Converter/KX_ConvertActuators.cpp +++ b/source/gameengine/Converter/KX_ConvertActuators.cpp @@ -233,7 +233,8 @@ void BL_ConvertActuators(char* maggiename, STR_String propname = ( ipoact->name ? ipoact->name : ""); // first bit? bool ipo_as_force = (ipoact->flag & ACT_IPOFORCE); - bool force_local = (ipoact->flag & ACT_IPOFORCE_LOCAL); + bool local = (ipoact->flag & ACT_IPOLOCAL); + bool ipo_add = (ipoact->flag & ACT_IPOADD); KX_IpoActuator* tmpbaseact = new KX_IpoActuator( gameobj, @@ -244,8 +245,8 @@ void BL_ConvertActuators(char* maggiename, ipoact->type + 1, // + 1, because Blender starts to count at zero, // Ketsji at 1, because zero is reserved for "NoDef" ipo_as_force, - force_local - ); + ipo_add, + local); baseact = tmpbaseact; break; } diff --git a/source/gameengine/GameLogic/SCA_ActuatorSensor.cpp b/source/gameengine/GameLogic/SCA_ActuatorSensor.cpp index 9645bfbed4a..e1c8ef87dd1 100644 --- a/source/gameengine/GameLogic/SCA_ActuatorSensor.cpp +++ b/source/gameengine/GameLogic/SCA_ActuatorSensor.cpp @@ -111,7 +111,7 @@ void SCA_ActuatorSensor::Update() { if (m_actuator) { - m_midresult = m_actuator->IsActive(); + m_midresult = m_actuator->IsActive() && !m_actuator->IsNegativeEvent(); } } diff --git a/source/gameengine/GameLogic/SCA_IActuator.h b/source/gameengine/GameLogic/SCA_IActuator.h index 774b27c5ad4..7ffb21b5490 100644 --- a/source/gameengine/GameLogic/SCA_IActuator.h +++ b/source/gameengine/GameLogic/SCA_IActuator.h @@ -87,6 +87,7 @@ public: bool IsNegativeEvent() const; virtual ~SCA_IActuator(); + void ClrLink() { m_links=0; } void IncLink() { m_links++; } void DecLink(); bool IsNoLink() const { return !m_links; } diff --git a/source/gameengine/GameLogic/SCA_IObject.cpp b/source/gameengine/GameLogic/SCA_IObject.cpp index 27e7d5faada..c5bb4a41552 100644 --- a/source/gameengine/GameLogic/SCA_IObject.cpp +++ b/source/gameengine/GameLogic/SCA_IObject.cpp @@ -40,7 +40,7 @@ MT_Point3 SCA_IObject::m_sDummy=MT_Point3(0,0,0); -SCA_IObject::SCA_IObject(PyTypeObject* T): m_state(0), CValue(T) +SCA_IObject::SCA_IObject(PyTypeObject* T): m_initState(0), m_state(0), CValue(T) { m_suspended = false; } @@ -164,7 +164,9 @@ void SCA_IObject::ReParentLogic() { SCA_IActuator* newactuator = (SCA_IActuator*) (*ita)->GetReplica(); newactuator->ReParent(this); + // actuators are initially not connected to any controller newactuator->SetActive(false); + newactuator->ClrLink(); oldactuators[act++] = newactuator; } @@ -175,6 +177,7 @@ void SCA_IObject::ReParentLogic() { SCA_IController* newcontroller = (SCA_IController*)(*itc)->GetReplica(); newcontroller->ReParent(this); + newcontroller->SetActive(false); oldcontrollers[con++]=newcontroller; } @@ -186,6 +189,9 @@ void SCA_IObject::ReParentLogic() { SCA_ISensor* newsensor = (SCA_ISensor*)(*its)->GetReplica(); newsensor->ReParent(this); + newsensor->SetActive(false); + // sensors are initially not connected to any controller + newsensor->ClrLink(); oldsensors[sen++] = newsensor; } diff --git a/source/gameengine/GameLogic/SCA_IObject.h b/source/gameengine/GameLogic/SCA_IObject.h index 07b4310a91e..38a7ed29dca 100644 --- a/source/gameengine/GameLogic/SCA_IObject.h +++ b/source/gameengine/GameLogic/SCA_IObject.h @@ -68,6 +68,11 @@ protected: */ bool m_suspended; + /** + * init state of object (used when object is created) + */ + unsigned int m_initState; + /** * current state = bit mask of state that are active */ @@ -117,6 +122,16 @@ public: */ void Resume(void); + /** + * Set init state + */ + void SetInitState(unsigned int initState) { m_initState = initState; } + + /** + * initialize the state when object is created + */ + void ResetState(void) { SetState(m_initState); } + /** * Set the object state */ diff --git a/source/gameengine/GameLogic/SCA_ISensor.h b/source/gameengine/GameLogic/SCA_ISensor.h index f2ed6a803c2..4ce49e71507 100644 --- a/source/gameengine/GameLogic/SCA_ISensor.h +++ b/source/gameengine/GameLogic/SCA_ISensor.h @@ -126,6 +126,8 @@ public: /** Resume sensing. */ void Resume(); + void ClrLink() + { m_links = 0; } void IncLink() { m_links++; } void DecLink(); diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index bde5e2cd0a2..88fbbb5fd1f 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -405,34 +405,25 @@ void KX_GameObject::ResetDebugColor() SetDebugColor(0xff000000); } +void KX_GameObject::InitIPO(bool ipo_as_force, + bool ipo_add, + bool ipo_local) +{ + SGControllerList::iterator it = GetSGNode()->GetSGControllerList().begin(); + while (it != GetSGNode()->GetSGControllerList().end()) { + (*it)->SetOption(SG_Controller::SG_CONTR_IPO_RESET, true); + (*it)->SetOption(SG_Controller::SG_CONTR_IPO_IPO_AS_FORCE, ipo_as_force); + (*it)->SetOption(SG_Controller::SG_CONTR_IPO_IPO_ADD, ipo_add); + (*it)->SetOption(SG_Controller::SG_CONTR_IPO_LOCAL, ipo_local); + it++; + } +} void KX_GameObject::UpdateIPO(float curframetime, - bool recurse, - bool ipo_as_force, - bool force_local) + bool recurse) { - - // The ipo-actuator needs a sumo reference... this is retrieved (unfortunately) - // by the iposgcontr itself... -// ipocontr->SetSumoReference(gameobj->GetSumoScene(), -// gameobj->GetSumoObject()); - - - // The ipo has to be treated as a force, and not a displacement! - // For this case, we send some settings to the controller. This - // may need some caching... - if (ipo_as_force) { - SGControllerList::iterator it = GetSGNode()->GetSGControllerList().begin(); - - while (it != GetSGNode()->GetSGControllerList().end()) { - (*it)->SetOption(SG_Controller::SG_CONTR_IPO_IPO_AS_FORCE, ipo_as_force); - (*it)->SetOption(SG_Controller::SG_CONTR_IPO_FORCES_ACT_LOCAL, force_local); - it++; - } - } - - // The rest is the 'normal' update procedure. + // just the 'normal' update procedure. GetSGNode()->SetSimulatedTime(curframetime,recurse); GetSGNode()->UpdateWorldData(curframetime); UpdateTransform(); diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h index 5e44a36515d..b4f50087742 100644 --- a/source/gameengine/Ketsji/KX_GameObject.h +++ b/source/gameengine/Ketsji/KX_GameObject.h @@ -489,15 +489,23 @@ public: UpdateNonDynas( ); + /** + * Function to set IPO option at start of IPO + */ + void + InitIPO( + bool ipo_as_force, + bool ipo_add, + bool ipo_local + ); + /** * Odd function to update an ipo. ??? */ void UpdateIPO( float curframetime, - bool recurse, - bool ipo_as_force, - bool force_ipo_local + bool recurse ); /** * Updates Material Ipo data diff --git a/source/gameengine/Ketsji/KX_IPO_SGController.cpp b/source/gameengine/Ketsji/KX_IPO_SGController.cpp index 5303e9a9e85..d3aa924665e 100644 --- a/source/gameengine/Ketsji/KX_IPO_SGController.cpp +++ b/source/gameengine/Ketsji/KX_IPO_SGController.cpp @@ -55,7 +55,8 @@ typedef unsigned long uint_ptr; // start on another frame, the 1.0 should change. KX_IpoSGController::KX_IpoSGController() : m_ipo_as_force(false), - m_force_ipo_acts_local(false), + m_ipo_add(false), + m_ipo_local(false), m_modified(true), m_ipo_start_initialized(false), m_ipotime(1.0) @@ -75,8 +76,23 @@ void KX_IpoSGController::SetOption( m_ipo_as_force = (value != 0); m_modified = true; break; - case SG_CONTR_IPO_FORCES_ACT_LOCAL: - m_force_ipo_acts_local = (value != 0); + case SG_CONTR_IPO_IPO_ADD: + m_ipo_add = (value != 0); + m_modified = true; + break; + case SG_CONTR_IPO_RESET: + if (m_ipo_start_initialized && value) { + m_ipo_start_initialized = false; + m_modified = true; + } + break; + case SG_CONTR_IPO_LOCAL: + if (value/* && ((SG_Node*)m_pObject)->GetSGParent() == NULL*/) { + // only accept local Ipo if the object has no parent + m_ipo_local = true; + } else { + m_ipo_local = false; + } m_modified = true; break; default: @@ -129,15 +145,19 @@ bool KX_IpoSGController::Update(double currentTime) { if (m_game_object && ob) { - m_game_object->GetPhysicsController()->ApplyForce(m_force_ipo_acts_local ? + m_game_object->GetPhysicsController()->ApplyForce(m_ipo_local ? ob->GetWorldOrientation() * m_ipo_xform.GetPosition() : m_ipo_xform.GetPosition(), false); } } else { - //by default, leave object as it stands - MT_Point3 newPosition = ob->GetLocalPosition(); + // Local ipo should be defined with the object position at (0,0,0) + // Local transform is applied to the object based on initial position + MT_Point3 newPosition(0.0,0.0,0.0); + + if (!m_ipo_add) + newPosition = ob->GetLocalPosition(); //apply separate IPO channels if there is any data in them //Loc and dLoc act by themselves or are additive //LocX and dLocX @@ -145,23 +165,28 @@ bool KX_IpoSGController::Update(double currentTime) newPosition[0] = (m_ipo_channels_active[OB_DLOC_X] ? m_ipo_xform.GetPosition()[0] + m_ipo_xform.GetDeltaPosition()[0] : m_ipo_xform.GetPosition()[0]); } else if (m_ipo_channels_active[OB_DLOC_X] && m_ipo_start_initialized) { - newPosition[0] = (m_ipo_start_point[0] + m_ipo_xform.GetDeltaPosition()[0]); + newPosition[0] = (((!m_ipo_add)?m_ipo_start_point[0]:0.0) + m_ipo_xform.GetDeltaPosition()[0]); } //LocY and dLocY if (m_ipo_channels_active[OB_LOC_Y]) { newPosition[1] = (m_ipo_channels_active[OB_DLOC_Y] ? m_ipo_xform.GetPosition()[1] + m_ipo_xform.GetDeltaPosition()[1] : m_ipo_xform.GetPosition()[1]); } else if (m_ipo_channels_active[OB_DLOC_Y] && m_ipo_start_initialized) { - newPosition[1] = (m_ipo_start_point[1] + m_ipo_xform.GetDeltaPosition()[1]); + newPosition[1] = (((!m_ipo_add)?m_ipo_start_point[1]:0.0) + m_ipo_xform.GetDeltaPosition()[1]); } //LocZ and dLocZ if (m_ipo_channels_active[OB_LOC_Z]) { newPosition[2] = (m_ipo_channels_active[OB_DLOC_Z] ? m_ipo_xform.GetPosition()[2] + m_ipo_xform.GetDeltaPosition()[2] : m_ipo_xform.GetPosition()[2]); } else if (m_ipo_channels_active[OB_DLOC_Z] && m_ipo_start_initialized) { - newPosition[2] = (m_ipo_start_point[2] + m_ipo_xform.GetDeltaPosition()[2]); + newPosition[2] = (((!m_ipo_add)?m_ipo_start_point[2]:0.0) + m_ipo_xform.GetDeltaPosition()[2]); + } + if (m_ipo_add) { + if (m_ipo_local) + newPosition = m_ipo_start_point + m_ipo_start_scale*(m_ipo_start_orient*newPosition); + else + newPosition = m_ipo_start_point + newPosition; } - ob->SetLocalPosition(newPosition); } } @@ -170,21 +195,23 @@ bool KX_IpoSGController::Update(double currentTime) if (m_ipo_as_force) { if (m_game_object && ob) { - m_game_object->ApplyTorque(m_force_ipo_acts_local ? + m_game_object->ApplyTorque(m_ipo_local ? ob->GetWorldOrientation() * m_ipo_xform.GetEulerAngles() : m_ipo_xform.GetEulerAngles(), false); } } else { - double yaw, pitch, roll; //final Euler angles + double yaw=0, pitch=0, roll=0; //final Euler angles double tempYaw=0, tempPitch=0, tempRoll=0; //temp holders - ob->GetLocalOrientation().getEuler(yaw, pitch, roll); + if (!m_ipo_add) + ob->GetLocalOrientation().getEuler(yaw, pitch, roll); //RotX and dRotX if (m_ipo_channels_active[OB_ROT_X]) { yaw = (m_ipo_channels_active[OB_DROT_X] ? (m_ipo_xform.GetEulerAngles()[0] + m_ipo_xform.GetDeltaEulerAngles()[0]) : m_ipo_xform.GetEulerAngles()[0] ); } else if (m_ipo_channels_active[OB_DROT_X] && m_ipo_start_initialized) { - m_ipo_start_orient.getEuler(tempYaw, tempPitch, tempRoll); + if (!m_ipo_add) + m_ipo_start_orient.getEuler(tempYaw, tempPitch, tempRoll); yaw = tempYaw + m_ipo_xform.GetDeltaEulerAngles()[0]; } @@ -193,7 +220,8 @@ bool KX_IpoSGController::Update(double currentTime) pitch = (m_ipo_channels_active[OB_DROT_Y] ? (m_ipo_xform.GetEulerAngles()[1] + m_ipo_xform.GetDeltaEulerAngles()[1]) : m_ipo_xform.GetEulerAngles()[1] ); } else if (m_ipo_channels_active[OB_DROT_Y] && m_ipo_start_initialized) { - m_ipo_start_orient.getEuler(tempYaw, tempPitch, tempRoll); + if (!m_ipo_add) + m_ipo_start_orient.getEuler(tempYaw, tempPitch, tempRoll); pitch = tempPitch + m_ipo_xform.GetDeltaEulerAngles()[1]; } @@ -202,23 +230,34 @@ bool KX_IpoSGController::Update(double currentTime) roll = (m_ipo_channels_active[OB_DROT_Z] ? (m_ipo_xform.GetEulerAngles()[2] + m_ipo_xform.GetDeltaEulerAngles()[2]) : m_ipo_xform.GetEulerAngles()[2] ); } else if (m_ipo_channels_active[OB_DROT_Z] && m_ipo_start_initialized) { - m_ipo_start_orient.getEuler(tempYaw, tempPitch, tempRoll); + if (!m_ipo_add) + m_ipo_start_orient.getEuler(tempYaw, tempPitch, tempRoll); roll = tempRoll + m_ipo_xform.GetDeltaEulerAngles()[2]; } - - ob->SetLocalOrientation(MT_Vector3(yaw, pitch, roll)); + if (m_ipo_add) { + MT_Matrix3x3 rotation(MT_Vector3(yaw, pitch, roll)); + if (m_ipo_local) + rotation = m_ipo_start_orient * rotation; + else + rotation = rotation * m_ipo_start_orient; + ob->SetLocalOrientation(rotation); + } else { + ob->SetLocalOrientation(MT_Vector3(yaw, pitch, roll)); + } } } //modifies scale? if (m_ipo_channels_active[OB_SIZE_X] || m_ipo_channels_active[OB_SIZE_Y] || m_ipo_channels_active[OB_SIZE_Z] || m_ipo_channels_active[OB_DSIZE_X] || m_ipo_channels_active[OB_DSIZE_Y] || m_ipo_channels_active[OB_DSIZE_Z]) { //default is no scale change - MT_Vector3 newScale = ob->GetLocalScale(); + MT_Vector3 newScale(1.0,1.0,1.0); + if (!m_ipo_add) + newScale = ob->GetLocalScale(); if (m_ipo_channels_active[OB_SIZE_X]) { newScale[0] = (m_ipo_channels_active[OB_DSIZE_X] ? (m_ipo_xform.GetScaling()[0] + m_ipo_xform.GetDeltaScaling()[0]) : m_ipo_xform.GetScaling()[0]); } else if (m_ipo_channels_active[OB_DSIZE_X] && m_ipo_start_initialized) { - newScale[0] = (m_ipo_xform.GetDeltaScaling()[0] + m_ipo_start_scale[0]); + newScale[0] = (m_ipo_xform.GetDeltaScaling()[0] + ((!m_ipo_add)?m_ipo_start_scale[0]:0.0)); } //RotY dRotY @@ -226,7 +265,7 @@ bool KX_IpoSGController::Update(double currentTime) newScale[1] = (m_ipo_channels_active[OB_DSIZE_Y] ? (m_ipo_xform.GetScaling()[1] + m_ipo_xform.GetDeltaScaling()[1]): m_ipo_xform.GetScaling()[1]); } else if (m_ipo_channels_active[OB_DSIZE_Y] && m_ipo_start_initialized) { - newScale[1] = (m_ipo_xform.GetDeltaScaling()[1] + m_ipo_start_scale[1]); + newScale[1] = (m_ipo_xform.GetDeltaScaling()[1] + ((!m_ipo_add)?m_ipo_start_scale[1]:0.0)); } //RotZ and dRotZ @@ -234,7 +273,11 @@ bool KX_IpoSGController::Update(double currentTime) newScale[2] = (m_ipo_channels_active[OB_DSIZE_Z] ? (m_ipo_xform.GetScaling()[2] + m_ipo_xform.GetDeltaScaling()[2]) : m_ipo_xform.GetScaling()[2]); } else if (m_ipo_channels_active[OB_DSIZE_Z] && m_ipo_start_initialized) { - newScale[2] = (m_ipo_xform.GetDeltaScaling()[2] + m_ipo_start_scale[2]); + newScale[2] = (m_ipo_xform.GetDeltaScaling()[2] + ((!m_ipo_add)?m_ipo_start_scale[2]:1.0)); + } + + if (m_ipo_add) { + newScale = m_ipo_start_scale * newScale; } ob->SetLocalScale(newScale); diff --git a/source/gameengine/Ketsji/KX_IPO_SGController.h b/source/gameengine/Ketsji/KX_IPO_SGController.h index 7b5a151b41c..0bd8980f11c 100644 --- a/source/gameengine/Ketsji/KX_IPO_SGController.h +++ b/source/gameengine/Ketsji/KX_IPO_SGController.h @@ -48,8 +48,11 @@ class KX_IpoSGController : public SG_Controller /** Interpret the ipo as a force rather than a displacement? */ bool m_ipo_as_force; - /** Ipo-as-force acts in local rather than in global coordinates? */ - bool m_force_ipo_acts_local; + /** Add Ipo curve to current loc/rot/scale */ + bool m_ipo_add; + + /** Ipo must be applied in local coordinate rather than in global coordinates (used for force and Add mode)*/ + bool m_ipo_local; /** Were settings altered since the last update? */ bool m_modified; diff --git a/source/gameengine/Ketsji/KX_IpoActuator.cpp b/source/gameengine/Ketsji/KX_IpoActuator.cpp index cf246342cf9..b7103f49aee 100644 --- a/source/gameengine/Ketsji/KX_IpoActuator.cpp +++ b/source/gameengine/Ketsji/KX_IpoActuator.cpp @@ -59,40 +59,6 @@ STR_String KX_IpoActuator::S_KX_ACT_IPO_FROM_PROP_STRING = "FromProp"; /* ------------------------------------------------------------------------- */ /* Native functions */ /* ------------------------------------------------------------------------- */ -/** Another poltergeist? This seems to be a very transient class... */ -class CIpoAction : public CAction -{ - float m_curtime; - bool m_recurse; - KX_GameObject* m_gameobj; - bool m_ipo_as_force; - bool m_force_ipo_local; - -public: - CIpoAction(KX_GameObject* gameobj, - float curtime, - bool recurse, - bool ipo_as_force, - bool force_ipo_local) : - m_curtime(curtime) , - m_recurse(recurse), - m_gameobj(gameobj), - m_ipo_as_force(ipo_as_force), - m_force_ipo_local(force_ipo_local) - { - /* intentionally empty */ - }; - - virtual void Execute() const - { - m_gameobj->UpdateIPO( - m_curtime, - m_recurse, - m_ipo_as_force, - m_force_ipo_local); - }; - -}; KX_IpoActuator::KX_IpoActuator(SCA_IObject* gameobj, const STR_String& propname, @@ -101,7 +67,8 @@ KX_IpoActuator::KX_IpoActuator(SCA_IObject* gameobj, bool recurse, int acttype, bool ipo_as_force, - bool force_ipo_local, + bool ipo_add, + bool ipo_local, PyTypeObject* T) : SCA_IActuator(gameobj,T), m_bNegativeEvent(false), @@ -112,7 +79,8 @@ KX_IpoActuator::KX_IpoActuator(SCA_IObject* gameobj, m_direction(1), m_propname(propname), m_ipo_as_force(ipo_as_force), - m_force_ipo_local(force_ipo_local), + m_ipo_add(ipo_add), + m_ipo_local(ipo_local), m_type((IpoActType)acttype) { m_starttime = -2.0*fabs(m_endframe - m_startframe) - 1.0; @@ -160,7 +128,7 @@ bool KX_IpoActuator::ClampLocalTime() void KX_IpoActuator::SetStartTime(float curtime) { - float direction = m_startframe < m_endframe ? 1.0 : -1.0; + float direction = m_startframe < m_endframe ? 1.0f : -1.0f; curtime = curtime - KX_KetsjiEngine::GetSuspendedDelta(); if (m_direction > 0) @@ -195,31 +163,26 @@ bool KX_IpoActuator::Update(double curtime, bool frame) // maybe there are events for us in the queue ! bool bNegativeEvent = false; int numevents = 0; + bool bIpoStart = false; if (frame) { numevents = m_events.size(); - for (vector::iterator i=m_events.end(); !(i==m_events.begin());) - { - --i; - if ((*i)->GetNumber() == 0.0f) - bNegativeEvent = true; - - (*i)->Release(); - } - m_events.clear(); + bNegativeEvent = IsNegativeEvent(); + RemoveAllEvents(); } - double start_smaller_then_end = ( m_startframe < m_endframe ? 1.0 : -1.0); + float start_smaller_then_end = ( m_startframe < m_endframe ? 1.0f : -1.0f); bool result=true; if (!bNegativeEvent) { - if (m_starttime < -2.0*start_smaller_then_end*(m_endframe - m_startframe)) + if (m_starttime < -2.0f*start_smaller_then_end*(m_endframe - m_startframe)) { // start for all Ipo, initial start for LOOP_STOP m_starttime = curtime - KX_KetsjiEngine::GetSuspendedDelta(); m_bIpoPlaying = true; + bIpoStart = true; } } @@ -230,7 +193,7 @@ bool KX_IpoActuator::Update(double curtime, bool frame) { // Check if playing forwards. result = ! finished - if (start_smaller_then_end > 0.0) + if (start_smaller_then_end > 0.f) result = (m_localtime < m_endframe && m_bIpoPlaying); else result = (m_localtime > m_endframe && m_bIpoPlaying); @@ -241,14 +204,10 @@ bool KX_IpoActuator::Update(double curtime, bool frame) /* Perform clamping */ ClampLocalTime(); - - CIpoAction ipoaction( - (KX_GameObject*)GetParent(), - m_localtime, - m_recurse, - m_ipo_as_force, - m_force_ipo_local); - GetParent()->Execute(ipoaction); + + if (bIpoStart) + ((KX_GameObject*)GetParent())->InitIPO(m_ipo_as_force, m_ipo_add, m_ipo_local); + ((KX_GameObject*)GetParent())->UpdateIPO(m_localtime,m_recurse); } else { m_localtime=m_startframe; @@ -270,13 +229,9 @@ bool KX_IpoActuator::Update(double curtime, bool frame) m_direction = -m_direction; } - CIpoAction ipoaction( - (KX_GameObject*) GetParent(), - m_localtime, - m_recurse, - m_ipo_as_force, - m_force_ipo_local); - GetParent()->Execute(ipoaction); + if (bIpoStart && m_direction > 0) + ((KX_GameObject*)GetParent())->InitIPO(m_ipo_as_force, m_ipo_add, m_ipo_local); + ((KX_GameObject*)GetParent())->UpdateIPO(m_localtime,m_recurse); break; } case KX_ACT_IPO_FLIPPER: @@ -299,14 +254,10 @@ bool KX_IpoActuator::Update(double curtime, bool frame) if (ClampLocalTime() && m_localtime == m_startframe) result = false; - - CIpoAction ipoaction( - (KX_GameObject*) GetParent(), - m_localtime, - m_recurse, - m_ipo_as_force, - m_force_ipo_local); - GetParent()->Execute(ipoaction); + + if (bIpoStart) + ((KX_GameObject*)GetParent())->InitIPO(m_ipo_as_force, m_ipo_add, m_ipo_local); + ((KX_GameObject*)GetParent())->UpdateIPO(m_localtime,m_recurse); break; } @@ -352,8 +303,12 @@ bool KX_IpoActuator::Update(double curtime, bool frame) if (!m_bNegativeEvent){ /* Perform wraparound */ SetLocalTime(curtime); - m_localtime = m_startframe + fmod(m_localtime, m_startframe - m_endframe); + if (start_smaller_then_end > 0.f) + m_localtime = m_startframe + fmod(m_localtime - m_startframe, m_endframe - m_startframe); + else + m_localtime = m_startframe - fmod(m_startframe - m_localtime, m_startframe - m_endframe); SetStartTime(curtime); + bIpoStart = true; } else { @@ -365,13 +320,9 @@ bool KX_IpoActuator::Update(double curtime, bool frame) } } - CIpoAction ipoaction( - (KX_GameObject*) GetParent(), - m_localtime, - m_recurse, - m_ipo_as_force, - m_force_ipo_local); - GetParent()->Execute(ipoaction); + if (m_bIpoPlaying && bIpoStart) + ((KX_GameObject*)GetParent())->InitIPO(m_ipo_as_force, m_ipo_add, m_ipo_local); + ((KX_GameObject*)GetParent())->UpdateIPO(m_localtime,m_recurse); break; } @@ -391,14 +342,9 @@ bool KX_IpoActuator::Update(double curtime, bool frame) { m_localtime = propval->GetNumber(); - CIpoAction ipoaction( - (KX_GameObject*) GetParent(), - m_localtime, - m_recurse, - m_ipo_as_force, - m_force_ipo_local); - GetParent()->Execute(ipoaction); - + if (bIpoStart) + ((KX_GameObject*)GetParent())->InitIPO(m_ipo_as_force, m_ipo_add, m_ipo_local); + ((KX_GameObject*)GetParent())->UpdateIPO(m_localtime,m_recurse); } else { result = false; @@ -493,6 +439,10 @@ PyMethodDef KX_IpoActuator::Methods[] = { METH_VARARGS, SetIpoAsForce_doc}, {"getIpoAsForce", (PyCFunction) KX_IpoActuator::sPyGetIpoAsForce, METH_VARARGS, GetIpoAsForce_doc}, + {"setIpoAdd", (PyCFunction) KX_IpoActuator::sPySetIpoAdd, + METH_VARARGS, SetIpoAdd_doc}, + {"getIpoAdd", (PyCFunction) KX_IpoActuator::sPyGetIpoAdd, + METH_VARARGS, GetIpoAdd_doc}, {"setType", (PyCFunction) KX_IpoActuator::sPySetType, METH_VARARGS, SetType_doc}, {"getType", (PyCFunction) KX_IpoActuator::sPyGetType, @@ -512,11 +462,11 @@ PyObject* KX_IpoActuator::_getattr(const STR_String& attr) { /* set --------------------------------------------------------------------- */ char KX_IpoActuator::Set_doc[] = -"set(mode, startframe, endframe, force?)\n" -"\t - mode: Play, PingPong, Flipper, LoopStop, LoopEnd or FromProp (string)\n" +"set(type, startframe, endframe, mode?)\n" +"\t - type: Play, PingPong, Flipper, LoopStop, LoopEnd or FromProp (string)\n" "\t - startframe: first frame to use (int)\n" "\t - endframe : last frame to use (int)\n" -"\t - force? : interpret this ipo as a force? (KX_TRUE, KX_FALSE)" +"\t - mode? : special mode (0=normal, 1=interpret location as force, 2=additive)" "\tSet the properties of the actuator.\n"; PyObject* KX_IpoActuator::PySet(PyObject* self, PyObject* args, @@ -543,7 +493,8 @@ PyObject* KX_IpoActuator::PySet(PyObject* self, m_type = modenum; m_startframe = startFrame; m_endframe = stopFrame; - m_ipo_as_force = PyArgToBool(forceToggle); + m_ipo_as_force = forceToggle == 1; + m_ipo_add = forceToggle == 2; break; default: ; /* error */ @@ -641,6 +592,8 @@ PyObject* KX_IpoActuator::PySetIpoAsForce(PyObject* self, } m_ipo_as_force = PyArgToBool(boolArg); + if (m_ipo_as_force) + m_ipo_add = false; Py_Return; } @@ -654,6 +607,36 @@ PyObject* KX_IpoActuator::PyGetIpoAsForce(PyObject* self, return BoolToPyArg(m_ipo_as_force); } +/* 6. setIpoAsForce: */ +char KX_IpoActuator::SetIpoAdd_doc[] = +"setIpoAdd(add?)\n" +"\t - add? : add flag (KX_TRUE, KX_FALSE)\n" +"\tSet whether to interpret the ipo as additive rather than absolute.\n"; +PyObject* KX_IpoActuator::PySetIpoAdd(PyObject* self, + PyObject* args, + PyObject* kwds) { + int boolArg; + + if (!PyArg_ParseTuple(args, "i", &boolArg)) { + return NULL; + } + + m_ipo_add = PyArgToBool(boolArg); + if (m_ipo_add) + m_ipo_as_force = false; + + Py_Return; +} +/* 7. getIpoAsForce: */ +char KX_IpoActuator::GetIpoAdd_doc[] = +"getIpoAsAdd()\n" +"\tReturns whether to interpret the ipo as additive rather than absolute.\n"; +PyObject* KX_IpoActuator::PyGetIpoAdd(PyObject* self, + PyObject* args, + PyObject* kwds) { + return BoolToPyArg(m_ipo_add); +} + /* 8. setType: */ char KX_IpoActuator::SetType_doc[] = "setType(mode)\n" @@ -701,7 +684,7 @@ PyObject* KX_IpoActuator::PySetForceIpoActsLocal(PyObject* self, return NULL; } - m_force_ipo_local = PyArgToBool(boolArg); + m_ipo_local = PyArgToBool(boolArg); Py_Return; } @@ -713,7 +696,7 @@ char KX_IpoActuator::GetForceIpoActsLocal_doc[] = PyObject* KX_IpoActuator::PyGetForceIpoActsLocal(PyObject* self, PyObject* args, PyObject* kwds) { - return BoolToPyArg(m_force_ipo_local); + return BoolToPyArg(m_ipo_local); } diff --git a/source/gameengine/Ketsji/KX_IpoActuator.h b/source/gameengine/Ketsji/KX_IpoActuator.h index 79e8daa3f87..ae554fb0fce 100644 --- a/source/gameengine/Ketsji/KX_IpoActuator.h +++ b/source/gameengine/Ketsji/KX_IpoActuator.h @@ -75,8 +75,11 @@ protected: /** Interpret the ipo as a force? */ bool m_ipo_as_force; - /** Apply a force-ipo locally? */ - bool m_force_ipo_local; + /** Add Ipo curve to current loc/rot/scale */ + bool m_ipo_add; + + /** The Ipo curve is applied in local coordinates */ + bool m_ipo_local; bool m_bIpoPlaying; @@ -113,7 +116,8 @@ public: bool recurse, int acttype, bool ipo_as_force, - bool force_ipo_local, + bool ipo_add, + bool ipo_local, PyTypeObject* T=&Type); virtual ~KX_IpoActuator() {}; @@ -144,6 +148,8 @@ public: KX_PYMETHOD_DOC(KX_IpoActuator,GetEnd); KX_PYMETHOD_DOC(KX_IpoActuator,SetIpoAsForce); KX_PYMETHOD_DOC(KX_IpoActuator,GetIpoAsForce); + KX_PYMETHOD_DOC(KX_IpoActuator,SetIpoAdd); + KX_PYMETHOD_DOC(KX_IpoActuator,GetIpoAdd); KX_PYMETHOD_DOC(KX_IpoActuator,SetType); KX_PYMETHOD_DOC(KX_IpoActuator,GetType); KX_PYMETHOD_DOC(KX_IpoActuator,SetForceIpoActsLocal); diff --git a/source/gameengine/Ketsji/KX_ParentActuator.cpp b/source/gameengine/Ketsji/KX_ParentActuator.cpp index 5c433cb68b1..8b379bcd44f 100644 --- a/source/gameengine/Ketsji/KX_ParentActuator.cpp +++ b/source/gameengine/Ketsji/KX_ParentActuator.cpp @@ -77,6 +77,12 @@ CValue* KX_ParentActuator::GetReplica() bool KX_ParentActuator::Update() { + bool bNegativeEvent = IsNegativeEvent(); + RemoveAllEvents(); + + if (bNegativeEvent) + return false; // do nothing on negative events + KX_GameObject *obj = (KX_GameObject*) GetParent(); KX_Scene *scene = PHY_GetActiveScene(); switch (m_mode) { diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index 337b1af6df7..c5f6230b2f2 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -601,6 +601,8 @@ void KX_Scene::ReplicateLogic(KX_GameObject* newobj) } } } + // ready to set initial state + newobj->ResetState(); } diff --git a/source/gameengine/SceneGraph/SG_Controller.h b/source/gameengine/SceneGraph/SG_Controller.h index d65a2f0c256..c32885b915f 100644 --- a/source/gameengine/SceneGraph/SG_Controller.h +++ b/source/gameengine/SceneGraph/SG_Controller.h @@ -101,7 +101,9 @@ public: enum SG_Controller_option { SG_CONTR_NODEF = 0, SG_CONTR_IPO_IPO_AS_FORCE, - SG_CONTR_IPO_FORCES_ACT_LOCAL, + SG_CONTR_IPO_IPO_ADD, + SG_CONTR_IPO_LOCAL, + SG_CONTR_IPO_RESET, SG_CONTR_CAMIPO_LENS, SG_CONTR_CAMIPO_CLIPEND, SG_CONTR_CAMIPO_CLIPSTART, From 092a5b9fbdc4bfe2d5fd31db697fa81bc7a3f71b Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Tue, 8 Jul 2008 17:04:58 +0000 Subject: [PATCH 14/37] Fix for crash in freeing group nodes, node trees have to be freed before materials. --- source/blender/blenkernel/intern/library.c | 60 +++++++++++----------- 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index 7c50b409693..c3dddf06e7c 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -224,48 +224,50 @@ void flag_all_listbases_ids(short flag, short value) /* note: MAX_LIBARRAY define should match this code */ int set_listbasepointers(Main *main, ListBase **lb) { + int a = 0; + /* BACKWARDS! also watch order of free-ing! (mesh<->mat) */ - lb[0]= &(main->ipo); - lb[1]= &(main->key); - lb[2]= &(main->image); - lb[3]= &(main->tex); - lb[4]= &(main->mat); - lb[5]= &(main->vfont); + lb[a++]= &(main->ipo); + lb[a++]= &(main->key); + lb[a++]= &(main->nodetree); + lb[a++]= &(main->image); + lb[a++]= &(main->tex); + lb[a++]= &(main->mat); + lb[a++]= &(main->vfont); /* Important!: When adding a new object type, * the specific data should be inserted here */ - lb[6]= &(main->armature); - lb[7]= &(main->action); + lb[a++]= &(main->armature); + lb[a++]= &(main->action); - lb[8]= &(main->mesh); - lb[9]= &(main->curve); - lb[10]= &(main->mball); + lb[a++]= &(main->mesh); + lb[a++]= &(main->curve); + lb[a++]= &(main->mball); - lb[11]= &(main->wave); - lb[12]= &(main->latt); - lb[13]= &(main->lamp); - lb[14]= &(main->camera); + lb[a++]= &(main->wave); + lb[a++]= &(main->latt); + lb[a++]= &(main->lamp); + lb[a++]= &(main->camera); - lb[15]= &(main->text); - lb[16]= &(main->sound); - lb[17]= &(main->group); - lb[18]= &(main->nodetree); - lb[19]= &(main->brush); - lb[20]= &(main->script); - lb[21]= &(main->particle); + lb[a++]= &(main->text); + lb[a++]= &(main->sound); + lb[a++]= &(main->group); + lb[a++]= &(main->brush); + lb[a++]= &(main->script); + lb[a++]= &(main->particle); - lb[22]= &(main->world); - lb[23]= &(main->screen); - lb[24]= &(main->object); - lb[25]= &(main->scene); - lb[26]= &(main->library); + lb[a++]= &(main->world); + lb[a++]= &(main->screen); + lb[a++]= &(main->object); + lb[a++]= &(main->scene); + lb[a++]= &(main->library); - lb[27]= NULL; + lb[a]= NULL; - return 27; + return a; } /* *********** ALLOC AND FREE ***************** From bbf1ce2762651f0d3f3a9c302c3575c68ca21ca7 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 8 Jul 2008 17:57:31 +0000 Subject: [PATCH 15/37] bugfix - GameEngine PyObject methods did not all return when using dir(), because inherited methods were ignored, This made it incredibly annoying, not only having to search a C++ file to see what functions were available. but looking up methods inherited from other C++ classes. There is still no __members__ attribute so dir() wont work at all for attributes. --- source/gameengine/Expressions/PyObjectPlus.h | 32 +++++++++++++++----- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/source/gameengine/Expressions/PyObjectPlus.h b/source/gameengine/Expressions/PyObjectPlus.h index 04cc119efee..2bcb604dd23 100644 --- a/source/gameengine/Expressions/PyObjectPlus.h +++ b/source/gameengine/Expressions/PyObjectPlus.h @@ -76,18 +76,36 @@ static inline void Py_Fatal(char *M) { virtual PyTypeObject *GetType(void) {return &Type;}; \ virtual PyParentObject *GetParents(void) {return Parents;} + // This defines the _getattr_up macro // which allows attribute and method calls // to be properly passed up the hierarchy. #define _getattr_up(Parent) \ - PyObject *rvalue = Py_FindMethod(Methods, this, const_cast(attr.ReadPtr())); \ - if (rvalue == NULL) \ - { \ - PyErr_Clear(); \ - return Parent::_getattr(attr); \ + PyObject *rvalue = NULL; \ + if (attr=="__methods__") { \ + PyObject *_attr_string = NULL; \ + PyMethodDef *meth = Methods; \ + rvalue = Parent::_getattr(attr); \ + if (rvalue==NULL) { \ + PyErr_Clear(); \ + rvalue = PyList_New(0); \ } \ - else \ - return rvalue + if (meth) { \ + for (; meth->ml_name != NULL; meth++) { \ + _attr_string = PyString_FromString(meth->ml_name); \ + PyList_Append(rvalue, _attr_string); \ + Py_DECREF(_attr_string); \ + } \ + } \ + } else { \ + rvalue = Py_FindMethod(Methods, this, const_cast(attr.ReadPtr())); \ + if (rvalue == NULL) { \ + PyErr_Clear(); \ + rvalue = Parent::_getattr(attr); \ + } \ + } \ + return rvalue; \ + /** * These macros are helpfull when embedding Python routines. The second From e279fc4a8181a7e8083c80c29e1c1bb6dfba7473 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 8 Jul 2008 22:43:44 +0000 Subject: [PATCH 16/37] fix for crasher with touch sensor, ben you may want to look at this, should be ok since the ray sensor does NULL checks in for getNewClientInfo in a similar area. --- .../gameengine/Ketsji/KX_TouchEventManager.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/source/gameengine/Ketsji/KX_TouchEventManager.cpp b/source/gameengine/Ketsji/KX_TouchEventManager.cpp index 80ee15a9475..423543eef5c 100644 --- a/source/gameengine/Ketsji/KX_TouchEventManager.cpp +++ b/source/gameengine/Ketsji/KX_TouchEventManager.cpp @@ -137,14 +137,18 @@ void KX_TouchEventManager::NextFrame() // KX_GameObject* gameOb1 = ctrl1->getClientInfo(); KX_ClientObjectInfo *client_info = static_cast(ctrl1->getNewClientInfo()); - list::iterator sit; - for ( sit = client_info->m_sensors.begin(); sit != client_info->m_sensors.end(); ++sit) - static_cast(*sit)->NewHandleCollision((*cit).first, (*cit).second, NULL); - + if (client_info) { + for ( sit = client_info->m_sensors.begin(); sit != client_info->m_sensors.end(); ++sit) { + static_cast(*sit)->NewHandleCollision((*cit).first, (*cit).second, NULL); + } + } client_info = static_cast((*cit).second->getNewClientInfo()); - for ( sit = client_info->m_sensors.begin(); sit != client_info->m_sensors.end(); ++sit) - static_cast(*sit)->NewHandleCollision((*cit).second, (*cit).first, NULL); + if (client_info) { + for ( sit = client_info->m_sensors.begin(); sit != client_info->m_sensors.end(); ++sit) { + static_cast(*sit)->NewHandleCollision((*cit).second, (*cit).first, NULL); + } + } } m_newCollisions.clear(); From 16dccd3ffdb00bb81400c804b30b13de26d1dc10 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 9 Jul 2008 00:58:57 +0000 Subject: [PATCH 17/37] exiting wasnt working (was raising errors), also use dict.keys() rather then appending from iteritems, --- tools/Blender.py | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/tools/Blender.py b/tools/Blender.py index 30e9979cf9a..2c982a0a46f 100644 --- a/tools/Blender.py +++ b/tools/Blender.py @@ -69,10 +69,10 @@ def internal_lib_to_dict(dict = None, libtype = None, libname = None, priority = dict[libtype][priority] = libname # libtype and priority can both be lists, for defining lib in multiple places -def add_lib_to_dict(dict = None, libtype = None, libname = None, priority = 100): +def add_lib_to_dict(env, dict = None, libtype = None, libname = None, priority = 100): if not dict or not libtype or not libname: print "Passed wrong arg" - Exit() + env.Exit() if type(libtype) is str and type(priority) is int: internal_lib_to_dict(dict, libtype, libname, priority) @@ -82,10 +82,10 @@ def add_lib_to_dict(dict = None, libtype = None, libname = None, priority = 100) internal_lib_to_dict(dict, lt, libname, p) else: print "libtype and priority lists are unequal in length" - Exit() + env.Exit() else: print "Wrong type combinations for libtype and priority. Only str and int or list and list" - Exit() + env.Exit() def create_blender_liblist(lenv = None, libtype = None): if not lenv or not libtype: @@ -93,11 +93,9 @@ def create_blender_liblist(lenv = None, libtype = None): lst = [] if libtype in possible_types: - sortlist = [] - for k,v in libs[libtype].iteritems(): - sortlist.append(k) - sortlist.sort() curlib = libs[libtype] + sortlist = curlib.keys() + sortlist.sort() for sk in sortlist: v = curlib[sk] lst.append('#' + root_build_dir + 'lib/'+lenv['LIBPREFIX'] + v + lenv['LIBSUFFIX']) @@ -175,11 +173,10 @@ def propose_priorities(): for t in possible_types: print bc.OKGREEN+"\t"+t+bc.ENDC new_priority = 0 - sortlist = [] - for k,v in libs[t].iteritems(): - sortlist.append(k) - sortlist.sort() curlib = libs[t] + sortlist = curlib.keys() + sortlist.sort() + for sk in sortlist: v = curlib[sk] #for p,v in sorted(libs[t].iteritems()): @@ -368,7 +365,7 @@ class BlenderEnvironment(SConsEnvironment): global libs if not self or not libname or not source: print bc.FAIL+'Cannot continue. Missing argument for BlenderRes '+libname+bc.ENDC - Exit() + self.Exit() if self['OURPLATFORM'] not in ('win32-vc','win32-mingw','linuxcross'): print bc.FAIL+'BlenderRes is for windows only!'+bc.END self.Exit() @@ -383,7 +380,7 @@ class BlenderEnvironment(SConsEnvironment): def BlenderLib(self=None, libname=None, sources=None, includes=[], defines=[], libtype='common', priority = 100, compileflags=None): if not self or not libname or not sources: print bc.FAIL+'Cannot continue. Missing argument for BuildBlenderLib '+libname+bc.ENDC - Exit() + self.Exit() if libname in quickie or len(quickie)==0: if libname in quickdebug: print bc.HEADER+'Configuring library '+bc.ENDC+bc.OKGREEN+libname +bc.ENDC+bc.OKBLUE+ " (debug mode)" + bc.ENDC @@ -419,7 +416,7 @@ class BlenderEnvironment(SConsEnvironment): else: print bc.WARNING+'Not building '+bc.ENDC+bc.OKGREEN+libname+bc.ENDC+' for '+bc.OKBLUE+'BF_QUICK'+bc.ENDC # note: libs is a global - add_lib_to_dict(libs, libtype, libname, priority) + add_lib_to_dict(self, libs, libtype, libname, priority) def BlenderProg(self=None, builddir=None, progname=None, sources=None, includes=None, libs=None, libpath=None, binarykind=''): print bc.HEADER+'Configuring program '+bc.ENDC+bc.OKGREEN+progname+bc.ENDC From 60d099648c05ac469e3499e9755477c5180b9721 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 9 Jul 2008 09:21:52 +0000 Subject: [PATCH 18/37] added a factor argument for aligning to vector, this isn't correct since it does linear interpolation of the vector and renormalizes. (can be improved to rotate correctly but for our use ist ok for now, would also be useful to have an argument to clamp the maximum rotation angle to get a constant rotation speed), This will used to make franky upright when falling from an angle, to track to a surface when hanging onto a ledge and setting the glide pitch. Without this rotation is instant and jerky. currently this is done with Mathutils which isnt available in Blender Player. def do_rotate_up(own): own.alignAxisToVect([0,0,1], 2, 0.1) replaces... def do_rotate_up(own): up_nor = Vector(0,0,1) own_mat = Matrix(*own.getOrientation()).transpose() own_up = up_nor * own_mat ang = AngleBetweenVecs(own_up, up_nor) if ang > 0.005: # Set orientation cross = CrossVecs(own_up, up_nor) new_mat = own_mat * RotationMatrix(ang*0.1, 3, 'r', cross) own.setOrientation(new_mat.transpose()) M source/gameengine/Ketsji/KX_GameObject.cpp M source/gameengine/Ketsji/KX_GameObject.h --- source/gameengine/Ketsji/KX_GameObject.cpp | 39 ++++++++++++++++++---- source/gameengine/Ketsji/KX_GameObject.h | 3 +- 2 files changed, 35 insertions(+), 7 deletions(-) diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index 88fbbb5fd1f..e29ca72500a 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -572,7 +572,7 @@ void KX_GameObject::SetObjectColor(const MT_Vector4& rgbavec) m_objectColor = rgbavec; } -void KX_GameObject::AlignAxisToVect(const MT_Vector3& dir, int axis) +void KX_GameObject::AlignAxisToVect(const MT_Vector3& dir, int axis, float fac) { MT_Matrix3x3 orimat; MT_Vector3 vect,ori,z,x,y; @@ -585,6 +585,11 @@ void KX_GameObject::AlignAxisToVect(const MT_Vector3& dir, int axis) cout << "alignAxisToVect() Error: Null vector!\n"; return; } + + if (fac<=0.0) { + return; + } + // normalize vect /= len; orimat = GetSGNode()->GetWorldOrientation(); @@ -594,7 +599,14 @@ void KX_GameObject::AlignAxisToVect(const MT_Vector3& dir, int axis) ori = MT_Vector3(orimat[0][2], orimat[1][2], orimat[2][2]); //pivot axis if (MT_abs(vect.dot(ori)) > 1.0-3.0*MT_EPSILON) //is the vector paralell to the pivot? ori = MT_Vector3(orimat[0][1], orimat[1][1], orimat[2][1]); //change the pivot! - x = vect; + if (fac == 1.0) { + x = vect; + } else { + x = (vect * fac) + ((orimat * MT_Vector3(1.0, 0.0, 0.0)) * (1-fac)); + len = x.length(); + if (MT_fuzzyZero(len)) x = vect; + else x /= len; + } y = ori.cross(x); z = x.cross(y); break; @@ -602,7 +614,14 @@ void KX_GameObject::AlignAxisToVect(const MT_Vector3& dir, int axis) ori = MT_Vector3(orimat[0][0], orimat[1][0], orimat[2][0]); if (MT_abs(vect.dot(ori)) > 1.0-3.0*MT_EPSILON) ori = MT_Vector3(orimat[0][2], orimat[1][2], orimat[2][2]); - y = vect; + if (fac == 1.0) { + y = vect; + } else { + y = (vect * fac) + ((orimat * MT_Vector3(0.0, 1.0, 0.0)) * (1-fac)); + len = y.length(); + if (MT_fuzzyZero(len)) y = vect; + else y /= len; + } z = ori.cross(y); x = y.cross(z); break; @@ -610,7 +629,14 @@ void KX_GameObject::AlignAxisToVect(const MT_Vector3& dir, int axis) ori = MT_Vector3(orimat[0][1], orimat[1][1], orimat[2][1]); if (MT_abs(vect.dot(ori)) > 1.0-3.0*MT_EPSILON) ori = MT_Vector3(orimat[0][0], orimat[1][0], orimat[2][0]); - z = vect; + if (fac == 1.0) { + z = vect; + } else { + z = (vect * fac) + ((orimat * MT_Vector3(0.0, 0.0, 1.0)) * (1-fac)); + len = z.length(); + if (MT_fuzzyZero(len)) z = vect; + else z /= len; + } x = ori.cross(z); y = z.cross(x); break; @@ -1386,13 +1412,14 @@ PyObject* KX_GameObject::PyAlignAxisToVect(PyObject* self, { PyObject* pyvect; int axis = 2; //z axis is the default + float fac = 1.0; - if (PyArg_ParseTuple(args,"O|i",&pyvect,&axis)) + if (PyArg_ParseTuple(args,"O|if",&pyvect,&axis, &fac)) { MT_Vector3 vect; if (PyVecTo(pyvect, vect)) { - AlignAxisToVect(vect,axis); + AlignAxisToVect(vect,axis,fac); Py_RETURN_NONE; } } diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h index b4f50087742..ddbf863aa1a 100644 --- a/source/gameengine/Ketsji/KX_GameObject.h +++ b/source/gameengine/Ketsji/KX_GameObject.h @@ -278,7 +278,8 @@ public: void AlignAxisToVect( const MT_Vector3& vect, - int axis = 2 + int axis = 2, + float fac = 1.0 ); /** From 838886daf35b791d24e18e3f039a7f9c3c8332e4 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 9 Jul 2008 10:13:09 +0000 Subject: [PATCH 19/37] Fix for bugfix #12075: gamma node check for nan was always checking red channel. --- source/blender/nodes/intern/CMP_nodes/CMP_gamma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_gamma.c b/source/blender/nodes/intern/CMP_nodes/CMP_gamma.c index ff9e2b716ce..e77de3726cb 100644 --- a/source/blender/nodes/intern/CMP_nodes/CMP_gamma.c +++ b/source/blender/nodes/intern/CMP_nodes/CMP_gamma.c @@ -47,7 +47,7 @@ static void do_gamma(bNode *node, float *out, float *in, float *fac) int i=0; for(i=0; i<3; i++) { /* check for negative to avoid nan's */ - out[i] = (in[0] > 0.0f)? pow(in[i],fac[0]): in[0]; + out[i] = (in[i] > 0.0f)? pow(in[i],fac[0]): in[i]; } out[3] = in[3]; } From bad6b003db72c9265bf817c55f909aa23ec84fb3 Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Wed, 9 Jul 2008 10:51:03 +0000 Subject: [PATCH 20/37] Fix for reported openexr file reading failures. For simple RGB(A) files, the channel names in openexr were supposed to be simply "R" "G" "B" and "A" too. Other programs like other names... like lower case, or like "ambient.r" Tested with file from renderman. --- .../imbuf/intern/openexr/openexr_api.cpp | 42 +++++++++++++++---- 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp index b59908fef39..7dee9891ce5 100644 --- a/source/blender/imbuf/intern/openexr/openexr_api.cpp +++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp @@ -842,7 +842,7 @@ typedef struct RGBA } RGBA; -#if 0 +/* debug only */ static void exr_print_filecontents(InputFile *file) { const ChannelList &channels = file->header().channels(); @@ -853,7 +853,28 @@ static void exr_print_filecontents(InputFile *file) printf("OpenEXR-load: Found channel %s of type %d\n", i.name(), channel.type); } } -#endif + +/* for non-multilayer, map R G B A channel names to something that's in this file */ +static const char *exr_rgba_channelname(InputFile *file, const char *chan) +{ + const ChannelList &channels = file->header().channels(); + + for (ChannelList::ConstIterator i = channels.begin(); i != channels.end(); ++i) + { + const Channel &channel = i.channel(); + const char *str= i.name(); + int len= strlen(str); + if(len) { + if(strcasecmp(chan, str+len-1)==0) { + printf("name %s\n", str); + return str; + } + } + } + return chan; +} + + static int exr_has_zbuffer(InputFile *file) { @@ -896,7 +917,8 @@ struct ImBuf *imb_load_openexr(unsigned char *mem, int size, int flags) //printf("OpenEXR-load: image data window %d %d %d %d\n", // dw.min.x, dw.min.y, dw.max.x, dw.max.y); - // exr_print_filecontents(file); + if(0) // debug + exr_print_filecontents(file); is_multi= exr_is_renderresult(file); @@ -935,11 +957,15 @@ struct ImBuf *imb_load_openexr(unsigned char *mem, int size, int flags) /* but, since we read y-flipped (negative y stride) we move to last scanline */ first+= 4*(height-1)*width; - frameBuffer.insert ("R", Slice (FLOAT, (char *) first, xstride, ystride)); - frameBuffer.insert ("G", Slice (FLOAT, (char *) (first+1), xstride, ystride)); - frameBuffer.insert ("B", Slice (FLOAT, (char *) (first+2), xstride, ystride)); - /* 1.0 is fill value */ - frameBuffer.insert ("A", Slice (FLOAT, (char *) (first+3), xstride, ystride, 1, 1, 1.0f)); + frameBuffer.insert ( exr_rgba_channelname(file, "R"), + Slice (FLOAT, (char *) first, xstride, ystride)); + frameBuffer.insert ( exr_rgba_channelname(file, "G"), + Slice (FLOAT, (char *) (first+1), xstride, ystride)); + frameBuffer.insert ( exr_rgba_channelname(file, "B"), + Slice (FLOAT, (char *) (first+2), xstride, ystride)); + + frameBuffer.insert ( exr_rgba_channelname(file, "A"), + Slice (FLOAT, (char *) (first+3), xstride, ystride, 1, 1, 1.0f)); /* 1.0 is fill value */ if(exr_has_zbuffer(file)) { From 180a7d1f623bfa78ff9f8397507053e679a0efbc Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Wed, 9 Jul 2008 13:12:58 +0000 Subject: [PATCH 21/37] Replaced strcasecmp with BLI_strcasecmp, to make msvc happy! --- source/blender/imbuf/intern/openexr/openexr_api.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp index 7dee9891ce5..16e76331916 100644 --- a/source/blender/imbuf/intern/openexr/openexr_api.cpp +++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp @@ -865,7 +865,7 @@ static const char *exr_rgba_channelname(InputFile *file, const char *chan) const char *str= i.name(); int len= strlen(str); if(len) { - if(strcasecmp(chan, str+len-1)==0) { + if(BLI_strcasecmp(chan, str+len-1)==0) { printf("name %s\n", str); return str; } From d0d179dce604a529381425a6c53f6cf4ea756b1d Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Wed, 9 Jul 2008 15:25:34 +0000 Subject: [PATCH 22/37] Buhh... and now I left in testing print in exr code. --- source/blender/imbuf/intern/openexr/openexr_api.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp index 16e76331916..fe352610a40 100644 --- a/source/blender/imbuf/intern/openexr/openexr_api.cpp +++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp @@ -866,7 +866,6 @@ static const char *exr_rgba_channelname(InputFile *file, const char *chan) int len= strlen(str); if(len) { if(BLI_strcasecmp(chan, str+len-1)==0) { - printf("name %s\n", str); return str; } } From 732d886e0a8853ad8029e3e68cc826b69a28cf87 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 9 Jul 2008 15:30:15 +0000 Subject: [PATCH 23/37] bugfix, vector was not checked for zero length before normalizing, closing blender instantly with an assert. --- source/gameengine/Ketsji/KX_GameObject.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index e29ca72500a..db13d30e2f1 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -1608,14 +1608,18 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCast, other = static_cast(pyfrom); fromPoint = other->NodeGetWorldPosition(); } - - if (dist != 0.0f) - { + + if (dist != 0.0f) { MT_Vector3 toDir = toPoint-fromPoint; + if (MT_fuzzyZero(toDir.length2())) { + return Py_BuildValue("OOO", Py_None, Py_None, Py_None); + } toDir.normalize(); toPoint = fromPoint + (dist) * toDir; + } else if (MT_fuzzyZero((toPoint-fromPoint).length2())) { + return Py_BuildValue("OOO", Py_None, Py_None, Py_None); } - + MT_Point3 resultPoint; MT_Vector3 resultNormal; PHY_IPhysicsEnvironment* pe = GetPhysicsEnvironment(); From 12c128ac040a842f3fb72a1f4e103abf061a47e2 Mon Sep 17 00:00:00 2001 From: Ben Batt Date: Wed, 9 Jul 2008 15:54:53 +0000 Subject: [PATCH 24/37] Fixed bug #14510 - wave modifier crash CDDM_apply_vert_coords needs a CDDerivedMesh, but it was getting a CCGDerivedMesh from the preceding Subsurf modifier. This fix just makes a CDDerivedMesh copy of the supplied DerivedMesh rather than using it directly. --- source/blender/blenkernel/intern/modifier.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index a0841bb9f03..f13f8ef0298 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -4920,7 +4920,7 @@ static void waveModifier_deformVertsEM( if(!wmd->texture && !wmd->defgrp_name[0] && !(wmd->flag & MOD_WAVE_NORM)) dm = derivedData; - else if(derivedData) dm = derivedData; + else if(derivedData) dm = CDDM_copy(derivedData); else dm = CDDM_from_editmesh(editData, ob->data); if(wmd->flag & MOD_WAVE_NORM) { From b915ba5e970b1dd594e81318828321c5fb8c38f7 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 9 Jul 2008 19:15:26 +0000 Subject: [PATCH 25/37] [#17298] surface normal direction compensation for objects with negative scale in rendering with radiosity from Roelf De Kock (kiemdoder) Fixes bug [#7969] Mirroring Object Breaks Radiosity Calculations - copied from the tracker. The code in this patch detects whether an object has negative scale (test the OB_NEG_SCALE bit in Object.transflag) and then compensate for the negative scale when the surface normals are calculated for a radiosity render. --- .../blender/radiosity/intern/source/radrender.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/source/blender/radiosity/intern/source/radrender.c b/source/blender/radiosity/intern/source/radrender.c index e5ef1e9a4a2..68b5fa81f43 100644 --- a/source/blender/radiosity/intern/source/radrender.c +++ b/source/blender/radiosity/intern/source/radrender.c @@ -369,9 +369,18 @@ printf(" Rad elems: %d emittors %d\n", RG.totelem, RG.totpatch); if(vlr->mat->mode & MA_RADIO) { /* during render, vlr->n gets flipped/corrected, we cannot have that */ - if(vlr->v4) CalcNormFloat4(vlr->v1->co, vlr->v2->co, vlr->v3->co, vlr->v4->co, rf->norm); - else CalcNormFloat(vlr->v1->co, vlr->v2->co, vlr->v3->co, rf->norm); - + if (obr->ob->transflag & OB_NEG_SCALE){ + /* The object has negative scale that will cause the normals to flip. + To counter this unwanted normal flip, swap vertex 2 and 4 for a quad + or vertex 2 and 3 (see flip_face) for a triangle in the call to CalcNormFloat4 + in order to flip the normals back to the way they were in the original mesh. */ + if(vlr->v4) CalcNormFloat4(vlr->v1->co, vlr->v4->co, vlr->v3->co, vlr->v2->co, rf->norm); + else CalcNormFloat(vlr->v1->co, vlr->v3->co, vlr->v2->co, rf->norm); + }else{ + if(vlr->v4) CalcNormFloat4(vlr->v1->co, vlr->v2->co, vlr->v3->co, vlr->v4->co, rf->norm); + else CalcNormFloat(vlr->v1->co, vlr->v2->co, vlr->v3->co, rf->norm); + } + rf->totrad[0]= vlr->mat->emit*vlr->mat->r; rf->totrad[1]= vlr->mat->emit*vlr->mat->g; rf->totrad[2]= vlr->mat->emit*vlr->mat->b; From 496a9c1a95c4d7f4219f713c274edf29d9d5d41d Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Thu, 10 Jul 2008 00:15:57 +0000 Subject: [PATCH 26/37] Apricot Request: When changing the active action in the NLA editor with NLA-override off, armatures now have their restpose applied before the new action is evaluated. I've commented the code here to make it clearer what is going on. --- source/blender/src/editnla.c | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/source/blender/src/editnla.c b/source/blender/src/editnla.c index d758f34949a..dbc0deecb2c 100644 --- a/source/blender/src/editnla.c +++ b/source/blender/src/editnla.c @@ -501,26 +501,47 @@ static void set_active_strip(Object *ob, bActionStrip *act) { bActionStrip *strip; + /* make sure all other strips are not active */ for (strip = ob->nlastrips.first; strip; strip=strip->next) strip->flag &= ~ACTSTRIP_ACTIVE; - if(act) { + /* act is new active strip */ + if (act) { + /* set active flag for this strip */ act->flag |= ACTSTRIP_ACTIVE; - - if(ob->action!=act->act) { - if(ob->action) ob->action->id.us--; - if(act->act->id.lib) { + + /* check if active action will still be the same one */ + if (ob->action != act->act) { + /* clear object's links with its current action (if present) */ + if (ob->action) { + ob->action->id.us--; + } + + /* only set object's action to active strip's action if possible */ + if (act->act->id.lib) { ob->action= NULL; } else { ob->action= act->act; id_us_plus(&ob->action->id); - } + } + + /* request redrawing in relevant spaces */ allqueue(REDRAWIPO, 0); allqueue(REDRAWVIEW3D, 0); allqueue(REDRAWACTION, 0); allqueue(REDRAWNLA, 0); - ob->ctime= -1234567.0f; // eveil! + + /* when only showing action (i.e. nla-override off), + * reset pose to restpose for armatures + */ + if ((ob->nlaflag & OB_NLA_OVERRIDE)==0) { + if (ob->type == OB_ARMATURE) + rest_pose(ob->pose); + } + + /* flush depsgraph */ + ob->ctime= -1234567.0f; // evil! DAG_object_flush_update(G.scene, ob, OB_RECALC_OB|OB_RECALC_DATA); } } From 5c825162616b39a70639ead6d7f4146c84e0b13f Mon Sep 17 00:00:00 2001 From: Geoffrey Bantle Date: Thu, 10 Jul 2008 00:46:19 +0000 Subject: [PATCH 27/37] -> Support for Custom Data in bevel modifier Added Customdata to Bmesh <-> derivedmesh functions --- source/blender/blenkernel/BKE_customdata.h | 3 +- .../blenkernel/intern/BME_conversions.c | 136 +++++++++++++++++- source/blender/blenkernel/intern/customdata.c | 8 +- 3 files changed, 138 insertions(+), 9 deletions(-) diff --git a/source/blender/blenkernel/BKE_customdata.h b/source/blender/blenkernel/BKE_customdata.h index 12f68c771e0..e84c7d30956 100644 --- a/source/blender/blenkernel/BKE_customdata.h +++ b/source/blender/blenkernel/BKE_customdata.h @@ -266,7 +266,8 @@ void CustomData_set_layer_unique_name(struct CustomData *data, int index); only after this test passes, layer->data should be assigned */ int CustomData_verify_versions(struct CustomData *data, int index); +/*BMesh specific customdata stuff*/ void CustomData_to_bmeshpoly(struct CustomData *fdata, struct CustomData *pdata, struct CustomData *ldata); -void CustomData_from_bmeshpoly(struct CustomData *fdata, struct CustomData *pdata, struct CustomData *ldata); +void CustomData_from_bmeshpoly(struct CustomData *fdata, struct CustomData *pdata, struct CustomData *ldata, int total); void CustomData_bmesh_init_pool(struct CustomData *data, int allocsize); #endif diff --git a/source/blender/blenkernel/intern/BME_conversions.c b/source/blender/blenkernel/intern/BME_conversions.c index f375ca62726..daf0de5b748 100644 --- a/source/blender/blenkernel/intern/BME_conversions.c +++ b/source/blender/blenkernel/intern/BME_conversions.c @@ -56,6 +56,102 @@ #include "BSE_edit.h" +/*merge these functions*/ +static void BME_DMcorners_to_loops(BME_Mesh *bm, CustomData *facedata, int index, BME_Poly *f, int numCol, int numTex){ + int i, j; + BME_Loop *l; + MTFace *texface; + MTexPoly *texpoly; + MCol *mcol; + MLoopCol *mloopcol; + MLoopUV *mloopuv; + + for(i=0; i< numTex; i++){ + texface = CustomData_get_layer_n(facedata, CD_MTFACE, i); + texpoly = CustomData_bmesh_get_n(&bm->pdata, f->data, CD_MTEXPOLY, i); + + texpoly->tpage = texface[index].tpage; + texpoly->flag = texface[index].flag; + texpoly->transp = texface[index].transp; + texpoly->mode = texface[index].mode; + texpoly->tile = texface[index].tile; + texpoly->unwrap = texface[index].unwrap; + + j = 0; + l = f->loopbase; + do{ + mloopuv = CustomData_bmesh_get_n(&bm->ldata, l->data, CD_MLOOPUV, i); + mloopuv->uv[0] = texface[index].uv[j][0]; + mloopuv->uv[1] = texface[index].uv[j][1]; + j++; + l = l->next; + }while(l!=f->loopbase); + } + + for(i=0; i < numCol; i++){ + mcol = CustomData_get_layer_n(facedata, CD_MCOL, i); + j = 0; + l = f->loopbase; + do{ + mloopcol = CustomData_bmesh_get_n(&bm->ldata, l->data, CD_MLOOPCOL, i); + mloopcol->r = mcol[(index*4)+j].r; + mloopcol->g = mcol[(index*4)+j].g; + mloopcol->b = mcol[(index*4)+j].b; + mloopcol->a = mcol[(index*4)+j].a; + j++; + l = l->next; + }while(l!=f->loopbase); + } +} + +static void BME_DMloops_to_corners(BME_Mesh *bm, CustomData *facedata, int index, BME_Poly *f,int numCol, int numTex){ + int i, j; + BME_Loop *l; + MTFace *texface; + MTexPoly *texpoly; + MCol *mcol; + MLoopCol *mloopcol; + MLoopUV *mloopuv; + + for(i=0; i < numTex; i++){ + texface = CustomData_get_layer_n(facedata, CD_MTFACE, i); + texpoly = CustomData_bmesh_get_n(&bm->pdata, f->data, CD_MTEXPOLY, i); + + texface[index].tpage = texpoly->tpage; + texface[index].flag = texpoly->flag; + texface[index].transp = texpoly->transp; + texface[index].mode = texpoly->mode; + texface[index].tile = texpoly->tile; + texface[index].unwrap = texpoly->unwrap; + + j = 0; + l = f->loopbase; + do{ + mloopuv = CustomData_bmesh_get_n(&bm->ldata, l->data, CD_MLOOPUV, i); + texface[index].uv[j][0] = mloopuv->uv[0]; + texface[index].uv[j][1] = mloopuv->uv[1]; + j++; + l = l->next; + }while(l!=f->loopbase); + + } + for(i=0; i < numCol; i++){ + mcol = CustomData_get_layer_n(facedata,CD_MCOL, i); + j = 0; + l = f->loopbase; + do{ + mloopcol = CustomData_bmesh_get_n(&bm->ldata, l->data, CD_MLOOPCOL, i); + mcol[(index*4) + j].r = mloopcol->r; + mcol[(index*4) + j].g = mloopcol->g; + mcol[(index*4) + j].b = mloopcol->b; + mcol[(index*4) + j].a = mloopcol->a; + j++; + l = l->next; + }while(l!=f->loopbase); + } +} + + static void BME_corners_to_loops(BME_Mesh *bm, CustomData *facedata, void *face_block, BME_Poly *f,int numCol, int numTex){ int i, j; BME_Loop *l; @@ -271,7 +367,7 @@ EditMesh *BME_bmesh_to_editmesh(BME_Mesh *bm, BME_TransData_Head *td) { CustomData_copy(&bm->vdata, &em->vdata, CD_MASK_BMESH, CD_CALLOC, 0); CustomData_copy(&bm->edata, &em->edata, CD_MASK_BMESH, CD_CALLOC, 0); CustomData_copy(&bm->pdata, &em->fdata, CD_MASK_BMESH, CD_CALLOC, 0); - CustomData_from_bmeshpoly(&em->fdata, &bm->pdata, &bm->ldata); + CustomData_from_bmeshpoly(&em->fdata, &bm->pdata, &bm->ldata,0); numTex = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY); numCol = CustomData_number_of_layers(&bm->ldata, CD_MLOOPCOL); @@ -357,7 +453,7 @@ BME_Mesh *BME_derivedmesh_to_bmesh(DerivedMesh *dm) MVert *mvert, *mv; MEdge *medge, *me; MFace *mface, *mf; - int totface,totedge,totvert,i,len; + int totface,totedge,totvert,i,len, numTex, numCol; BME_Vert *v1=NULL,*v2=NULL, **vert_array; BME_Edge *e=NULL; BME_Poly *f=NULL; @@ -365,6 +461,22 @@ BME_Mesh *BME_derivedmesh_to_bmesh(DerivedMesh *dm) EdgeHash *edge_hash = BLI_edgehash_new(); bm = BME_make_mesh(allocsize); + /*copy custom data layout*/ + CustomData_copy(&dm->vertData, &bm->vdata, CD_MASK_BMESH, CD_CALLOC, 0); + CustomData_copy(&dm->edgeData, &bm->edata, CD_MASK_BMESH, CD_CALLOC, 0); + CustomData_copy(&dm->faceData, &bm->pdata, CD_MASK_BMESH, CD_CALLOC, 0); + + /*copy face corner data*/ + CustomData_to_bmeshpoly(&dm->faceData, &bm->pdata, &bm->ldata); + /*initialize memory pools*/ + CustomData_bmesh_init_pool(&bm->vdata, allocsize[0]); + CustomData_bmesh_init_pool(&bm->edata, allocsize[1]); + CustomData_bmesh_init_pool(&bm->ldata, allocsize[2]); + CustomData_bmesh_init_pool(&bm->pdata, allocsize[3]); + /*needed later*/ + numTex = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY); + numCol = CustomData_number_of_layers(&bm->ldata, CD_MLOOPCOL); + totvert = dm->getNumVerts(dm); totedge = dm->getNumEdges(dm); totface = dm->getNumFaces(dm); @@ -381,6 +493,7 @@ BME_Mesh *BME_derivedmesh_to_bmesh(DerivedMesh *dm) vert_array[i] = v1; v1->flag = mv->flag; v1->bweight = mv->bweight/255.0f; + CustomData_to_bmesh_block(&dm->vertData, &bm->vdata, i, &v1->data); } /*add edges*/ for(i=0,me = medge; i < totedge;i++,me++){ @@ -391,6 +504,7 @@ BME_Mesh *BME_derivedmesh_to_bmesh(DerivedMesh *dm) e->bweight = me->bweight/255.0f; e->flag = (unsigned char)me->flag; BLI_edgehash_insert(edge_hash,me->v1,me->v2,e); + CustomData_to_bmesh_block(&dm->edgeData, &bm->edata, i, &e->data); } /*add faces.*/ for(i=0,mf = mface; i < totface;i++,mf++){ @@ -414,6 +528,8 @@ BME_Mesh *BME_derivedmesh_to_bmesh(DerivedMesh *dm) f = BME_MF(bm,v1,v2,edar,len); f->mat_nr = mf->mat_nr; f->flag = mf->flag; + CustomData_to_bmesh_block(&dm->faceData,&bm->pdata,i,&f->data); + BME_DMcorners_to_loops(bm, &dm->faceData,i,f, numCol,numTex); } BME_model_end(bm); @@ -427,7 +543,7 @@ DerivedMesh *BME_bmesh_to_derivedmesh(BME_Mesh *bm, DerivedMesh *dm) MFace *mface, *mf; MEdge *medge, *me; MVert *mvert, *mv; - int totface,totedge,totvert,i,bmeshok,len; + int totface,totedge,totvert,i,bmeshok,len, numTex, numCol; BME_Vert *v1=NULL; BME_Edge *e=NULL, *oe=NULL; @@ -463,12 +579,21 @@ DerivedMesh *BME_bmesh_to_derivedmesh(BME_Mesh *bm, DerivedMesh *dm) /*convert back to mesh*/ result = CDDM_from_template(dm,totvert,totedge,totface); + CustomData_merge(&bm->vdata, &result->vertData, CD_MASK_BMESH, CD_CALLOC, totvert); + CustomData_merge(&bm->edata, &result->edgeData, CD_MASK_BMESH, CD_CALLOC, totedge); + CustomData_merge(&bm->pdata, &result->faceData, CD_MASK_BMESH, CD_CALLOC, totface); + CustomData_from_bmeshpoly(&result->faceData, &bm->pdata, &bm->ldata,totface); + numTex = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY); + numCol = CustomData_number_of_layers(&bm->ldata, CD_MLOOPCOL); + + /*Make Verts*/ mvert = CDDM_get_verts(result); for(i=0,v1=bm->verts.first,mv=mvert;v1;v1=v1->next,i++,mv++){ VECCOPY(mv->co,v1->co); mv->flag = (unsigned char)v1->flag; mv->bweight = (char)(255.0*v1->bweight); + CustomData_from_bmesh_block(&bm->vdata, &result->vertData, &v1->data, i); } medge = CDDM_get_edges(result); i=0; @@ -486,6 +611,7 @@ DerivedMesh *BME_bmesh_to_derivedmesh(BME_Mesh *bm, DerivedMesh *dm) me->crease = (char)(255.0*e->crease); me->bweight = (char)(255.0*e->bweight); me->flag = e->flag; + CustomData_from_bmesh_block(&bm->edata, &result->edgeData, &e->data, i); me++; i++; } @@ -507,9 +633,11 @@ DerivedMesh *BME_bmesh_to_derivedmesh(BME_Mesh *bm, DerivedMesh *dm) if(mf->v3 == 0 || (len == 4 && mf->v4 == 0)){ test_index_face(mf, NULL, i, len); } - i++; mf->mat_nr = (unsigned char)f->mat_nr; mf->flag = (unsigned char)f->flag; + CustomData_from_bmesh_block(&bm->pdata, &result->faceData, &f->data, i); + BME_DMloops_to_corners(bm, &result->faceData, i, f,numCol,numTex); + i++; } } } diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index d79dcb14f37..501293ecd81 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -1534,7 +1534,7 @@ void CustomData_from_em_block(const CustomData *source, CustomData *dest, } /*Bmesh functions*/ - +/*needed to convert to/from different face reps*/ void CustomData_to_bmeshpoly(CustomData *fdata, CustomData *pdata, CustomData *ldata) { int i; @@ -1547,15 +1547,15 @@ void CustomData_to_bmeshpoly(CustomData *fdata, CustomData *pdata, CustomData *l CustomData_add_layer(ldata, CD_MLOOPCOL, CD_CALLOC, &(fdata->layers[i].name), 0); } } -void CustomData_from_bmeshpoly(CustomData *fdata, CustomData *pdata, CustomData *ldata){ +void CustomData_from_bmeshpoly(CustomData *fdata, CustomData *pdata, CustomData *ldata, int total){ int i; for(i=0; i < pdata->totlayer; i++){ if(pdata->layers[i].type == CD_MTEXPOLY) - CustomData_add_layer(fdata, CD_MTFACE, CD_CALLOC, &(pdata->layers[i].name), 0); + CustomData_add_layer(fdata, CD_MTFACE, CD_CALLOC, &(pdata->layers[i].name), total); } for(i=0; i < ldata->totlayer; i++){ if(ldata->layers[i].type == CD_MLOOPCOL) - CustomData_add_layer(fdata, CD_MCOL, CD_CALLOC, &(ldata->layers[i].name), 0); + CustomData_add_layer(fdata, CD_MCOL, CD_CALLOC, &(ldata->layers[i].name), total); } } From 3d7358539df4526ffc2c2bbd40cf2001c5acf374 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Thu, 10 Jul 2008 01:47:51 +0000 Subject: [PATCH 28/37] AutoMerge Keyframes option for Action/NLA editors will now also delete duplicate keyframes if a Duplicate (SHIFT-DKEY) operation is cancelled. --- source/blender/src/transform_conversions.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/source/blender/src/transform_conversions.c b/source/blender/src/transform_conversions.c index dcebf6b7557..10e49cdd218 100644 --- a/source/blender/src/transform_conversions.c +++ b/source/blender/src/transform_conversions.c @@ -3610,6 +3610,7 @@ void special_aftertrans_update(TransInfo *t) Base *base; short redrawipo=0, resetslowpar=1; int cancelled= (t->state == TRANS_CANCEL); + short duplicate= (t->undostr && strstr(t->undostr, "Duplicate")) ? 1 : 0; if (t->spacetype==SPACE_VIEW3D) { if (G.obedit) { @@ -3622,7 +3623,7 @@ void special_aftertrans_update(TransInfo *t) } } } - if (t->spacetype == SPACE_ACTION) { + else if (t->spacetype == SPACE_ACTION) { void *data; short datatype; @@ -3644,7 +3645,7 @@ void special_aftertrans_update(TransInfo *t) /* Do curve cleanups? */ if ( (G.saction->flag & SACTION_NOTRANSKEYCULL)==0 && - (cancelled == 0) ) + ((cancelled == 0) || (duplicate)) ) { posttrans_action_clean((bAction *)data); } @@ -3659,7 +3660,7 @@ void special_aftertrans_update(TransInfo *t) IpoCurve *icu; if ( (G.saction->flag & SACTION_NOTRANSKEYCULL)==0 && - (cancelled == 0) ) + ((cancelled == 0) || (duplicate)) ) { posttrans_ipo_clean(key->ipo); } @@ -3685,7 +3686,7 @@ void special_aftertrans_update(TransInfo *t) /* after transform, remove duplicate keyframes on a frame that resulted from transform */ if ( (G.snla->flag & SNLA_NOTRANSKEYCULL)==0 && - (cancelled == 0) ) + ((cancelled == 0) || (duplicate)) ) { posttrans_nla_clean(t); } From 99fdf27af92b9bd9d05c108f2c2c8a240c5536bc Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Thu, 10 Jul 2008 12:47:20 +0000 Subject: [PATCH 29/37] Sync with Apricot Game Engine ============================= * Clean up and optimizations in skinned/deformed mesh code. * Compatibility fixes and clean up in the rasterizer. * Changes related to GLSL shadow buffers which should have no effect, to keep the code in sync with apricot. --- intern/moto/include/GEN_Map.h | 18 ++ source/blender/src/usiblender.c | 2 + .../BlenderRoutines/KX_BlenderGL.cpp | 2 +- .../Converter/BL_BlenderDataConversion.cpp | 118 ++++++------- .../gameengine/Converter/BL_MeshDeformer.cpp | 164 ++++++++++-------- source/gameengine/Converter/BL_MeshDeformer.h | 14 +- .../gameengine/Converter/BL_ShapeDeformer.h | 11 +- .../gameengine/Converter/BL_SkinDeformer.cpp | 53 +++--- source/gameengine/Converter/BL_SkinDeformer.h | 6 +- .../Converter/BL_SkinMeshObject.cpp | 84 --------- .../gameengine/Converter/BL_SkinMeshObject.h | 94 ---------- source/gameengine/Ketsji/BL_BlenderShader.cpp | 80 ++++++--- source/gameengine/Ketsji/BL_BlenderShader.h | 15 +- source/gameengine/Ketsji/BL_Material.cpp | 6 +- source/gameengine/Ketsji/BL_Material.h | 7 +- .../gameengine/Ketsji/KX_BlenderMaterial.cpp | 100 +++++++---- source/gameengine/Ketsji/KX_BlenderMaterial.h | 2 + source/gameengine/Ketsji/KX_GameObject.cpp | 2 +- source/gameengine/Ketsji/KX_KetsjiEngine.cpp | 46 ++++- source/gameengine/Ketsji/KX_KetsjiEngine.h | 1 + source/gameengine/Ketsji/KX_Light.cpp | 80 ++++++++- source/gameengine/Ketsji/KX_Light.h | 16 +- source/gameengine/Ketsji/KX_Scene.cpp | 41 +++-- source/gameengine/Ketsji/KX_Scene.h | 8 +- .../Rasterizer/RAS_BucketManager.cpp | 2 +- .../Rasterizer/RAS_IPolygonMaterial.cpp | 16 ++ .../Rasterizer/RAS_IPolygonMaterial.h | 2 + .../gameengine/Rasterizer/RAS_IRasterizer.h | 59 ++++--- .../Rasterizer/RAS_MaterialBucket.cpp | 53 +++--- .../Rasterizer/RAS_MaterialBucket.h | 10 +- .../gameengine/Rasterizer/RAS_MeshObject.cpp | 63 ++++--- source/gameengine/Rasterizer/RAS_MeshObject.h | 6 +- .../RAS_ListRasterizer.cpp | 25 ++- .../RAS_OpenGLRasterizer/RAS_ListRasterizer.h | 8 +- .../RAS_OpenGLRasterizer.cpp | 102 ++--------- .../RAS_OpenGLRasterizer.h | 10 +- .../RAS_VAOpenGLRasterizer.cpp | 94 +++++----- .../RAS_VAOpenGLRasterizer.h | 8 +- source/gameengine/Rasterizer/RAS_TexVert.cpp | 42 +---- source/gameengine/Rasterizer/RAS_TexVert.h | 24 ++- source/kernel/gen_system/GEN_HashedPtr.h | 1 + source/kernel/gen_system/GEN_Map.h | 18 ++ 42 files changed, 762 insertions(+), 751 deletions(-) diff --git a/intern/moto/include/GEN_Map.h b/intern/moto/include/GEN_Map.h index db3335d6110..9f56924419e 100644 --- a/intern/moto/include/GEN_Map.h +++ b/intern/moto/include/GEN_Map.h @@ -82,6 +82,24 @@ public: } return 0; } + + Key* getKey(int index) { + int count=0; + for (int i=0;im_key; + } + bucket = bucket->m_next; + count++; + } + } + return 0; + } void clear() { for (int i = 0; i < m_num_buckets; ++i) { diff --git a/source/blender/src/usiblender.c b/source/blender/src/usiblender.c index 2a4672e3052..4aea0df74b9 100644 --- a/source/blender/src/usiblender.c +++ b/source/blender/src/usiblender.c @@ -34,6 +34,8 @@ #include #include +#include "GL/glew.h" + #ifdef WIN32 #include /* need to include windows.h so _WIN32_IE is defined */ #ifndef _WIN32_IE diff --git a/source/gameengine/BlenderRoutines/KX_BlenderGL.cpp b/source/gameengine/BlenderRoutines/KX_BlenderGL.cpp index 230d6b262c6..ed6ea7c5f6a 100644 --- a/source/gameengine/BlenderRoutines/KX_BlenderGL.cpp +++ b/source/gameengine/BlenderRoutines/KX_BlenderGL.cpp @@ -26,6 +26,7 @@ * ***** END GPL LICENSE BLOCK ***** */ +#include "GL/glew.h" #include "KX_BlenderGL.h" #ifdef HAVE_CONFIG_H @@ -44,7 +45,6 @@ #include "BMF_Api.h" -#include "GL/glew.h" #include "BIF_gl.h" #include "BL_Material.h" // MAXTEX diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index d8b157cb5b4..f3e22cd297a 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -312,11 +312,13 @@ BL_Material* ConvertMaterial( Mesh* mesh, Material *mat, MTFace* tface, + const char *tfaceName, MFace* mface, MCol* mmcol, int lightlayer, Object* blenderobj, - MTF_localLayer *layers) + MTF_localLayer *layers, + bool glslmat) { //this needs some type of manager BL_Material *material = new BL_Material(); @@ -335,7 +337,7 @@ BL_Material* ConvertMaterial( if(validmat) { // use vertex colors by explicitly setting - if(mat->mode &MA_VERTEXCOLP) + if(mat->mode &MA_VERTEXCOLP || glslmat) type = 0; // use lighting? @@ -558,6 +560,7 @@ BL_Material* ConvertMaterial( } else { int valid = 0; + // check for tface tex to fallback on if( validface ){ @@ -590,6 +593,7 @@ BL_Material* ConvertMaterial( } MT_Point2 uv[4]; MT_Point2 uv2[4]; + const char *uvName = "", *uv2Name = ""; uv[0]= uv[1]= uv[2]= uv[3]= MT_Point2(0.0f, 0.0f); uv2[0]= uv2[1]= uv2[2]= uv2[3]= MT_Point2(0.0f, 0.0f); @@ -616,6 +620,8 @@ BL_Material* ConvertMaterial( if (mface->v4) uv[3] = MT_Point2(tface->uv[3]); + + uvName = tfaceName; } else { // nothing at all @@ -641,39 +647,38 @@ BL_Material* ConvertMaterial( isFirstSet = false; else { - MT_Point2 uvSet[4]; for (int lay=0; layuv[0]); uvSet[1] = MT_Point2(layer.face->uv[1]); uvSet[2] = MT_Point2(layer.face->uv[2]); if (mface->v4) uvSet[3] = MT_Point2(layer.face->uv[3]); + else + uvSet[3] = MT_Point2(0.0f, 0.0f); - processed = true; - } - - if (!processed) continue; - - if (isFirstSet) - { - uv[0] = uvSet[0]; uv[1] = uvSet[1]; - uv[2] = uvSet[2]; uv[3] = uvSet[3]; - isFirstSet = false; - } - else - { - uv2[0] = uvSet[0]; uv2[1] = uvSet[1]; - uv2[2] = uvSet[2]; uv2[3] = uvSet[3]; - map.mapping |= USECUSTOMUV; + if (isFirstSet) + { + uv[0] = uvSet[0]; uv[1] = uvSet[1]; + uv[2] = uvSet[2]; uv[3] = uvSet[3]; + isFirstSet = false; + uvName = layer.name; + } + else + { + uv2[0] = uvSet[0]; uv2[1] = uvSet[1]; + uv2[2] = uvSet[2]; uv2[3] = uvSet[3]; + map.mapping |= USECUSTOMUV; + uv2Name = layer.name; + } } } } @@ -693,9 +698,8 @@ BL_Material* ConvertMaterial( } material->SetConversionRGB(rgb); - material->SetConversionUV(uv); - material->SetConversionUV2(uv2); - + material->SetConversionUV(uvName, uv); + material->SetConversionUV2(uv2Name, uv2); material->ras_mode |= (mface->v4==0)?TRIANGLE:0; if(validmat) @@ -797,6 +801,7 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools* MFace* mface = static_cast(mesh->mface); MTFace* tface = static_cast(mesh->mtface); + const char *tfaceName = ""; MCol* mmcol = mesh->mcol; MT_assert(mface || mesh->totface == 0); @@ -832,14 +837,14 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools* layers[validLayers].face = (MTFace*)mesh->fdata.layers[i].data;; layers[validLayers].name = mesh->fdata.layers[i].name; + if(tface == layers[validLayers].face) + tfaceName = layers[validLayers].name; validLayers++; } } meshobj->SetName(mesh->id.name); meshobj->m_xyz_index_to_vertex_index_mapping.resize(mesh->totvert); - if(skinMesh) - ((BL_SkinMeshObject*)meshobj)->m_mvert_to_dvert_mapping.resize(mesh->totvert); for (int f=0;ftotface;f++,mface++) { @@ -898,8 +903,7 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools* else ma = give_current_material(blenderobj, 1); - bl_mat = ConvertMaterial(mesh, ma, tface, mface, mmcol, lightlayer, blenderobj, layers); - bl_mat->glslmat = converter->GetGLSLMaterials(); + bl_mat = ConvertMaterial(mesh, ma, tface, tfaceName, mface, mmcol, lightlayer, blenderobj, layers, converter->GetGLSLMaterials()); // set the index were dealing with bl_mat->material_index = (int)mface->mat_nr; @@ -1059,35 +1063,25 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools* int nverts = mface->v4?4:3; int vtxarray = meshobj->FindVertexArray(nverts,polymat); RAS_Polygon* poly = new RAS_Polygon(bucket,polyvisible,nverts,vtxarray); - if (skinMesh) { - int d1, d2, d3, d4=0; - bool flat; + bool flat; + + if (skinMesh) { /* If the face is set to solid, all fnors are the same */ if (mface->flag & ME_SMOOTH) flat = false; else flat = true; - - d1=((BL_SkinMeshObject*)meshobj)->FindOrAddDeform(vtxarray, mface->v1, &mesh->dvert[mface->v1], polymat); - d2=((BL_SkinMeshObject*)meshobj)->FindOrAddDeform(vtxarray, mface->v2, &mesh->dvert[mface->v2], polymat); - d3=((BL_SkinMeshObject*)meshobj)->FindOrAddDeform(vtxarray, mface->v3, &mesh->dvert[mface->v3], polymat); - if (nverts==4) - d4=((BL_SkinMeshObject*)meshobj)->FindOrAddDeform(vtxarray, mface->v4, &mesh->dvert[mface->v4], polymat); - poly->SetVertex(0,((BL_SkinMeshObject*)meshobj)->FindOrAddVertex(vtxarray,pt0,uv0,uv20,tan0,rgb0,no0,d1,flat,polymat,mface->v1)); - poly->SetVertex(1,((BL_SkinMeshObject*)meshobj)->FindOrAddVertex(vtxarray,pt1,uv1,uv21,tan1,rgb1,no1,d2,flat,polymat,mface->v2)); - poly->SetVertex(2,((BL_SkinMeshObject*)meshobj)->FindOrAddVertex(vtxarray,pt2,uv2,uv22,tan2,rgb2,no2,d3,flat,polymat,mface->v3)); - if (nverts==4) - poly->SetVertex(3,((BL_SkinMeshObject*)meshobj)->FindOrAddVertex(vtxarray,pt3,uv3,uv23,tan3,rgb3,no3,d4,flat,polymat,mface->v4)); } else - { - poly->SetVertex(0,meshobj->FindOrAddVertex(vtxarray,pt0,uv0,uv20,tan0,rgb0,no0,false,polymat,mface->v1)); - poly->SetVertex(1,meshobj->FindOrAddVertex(vtxarray,pt1,uv1,uv21,tan1,rgb1,no1,false,polymat,mface->v2)); - poly->SetVertex(2,meshobj->FindOrAddVertex(vtxarray,pt2,uv2,uv22,tan2,rgb2,no2,false,polymat,mface->v3)); - if (nverts==4) - poly->SetVertex(3,meshobj->FindOrAddVertex(vtxarray,pt3,uv3,uv23,tan3,rgb3,no3,false,polymat,mface->v4)); - } + flat = false; + + poly->SetVertex(0,meshobj->FindOrAddVertex(vtxarray,pt0,uv0,uv20,tan0,rgb0,no0,flat,polymat,mface->v1)); + poly->SetVertex(1,meshobj->FindOrAddVertex(vtxarray,pt1,uv1,uv21,tan1,rgb1,no1,flat,polymat,mface->v2)); + poly->SetVertex(2,meshobj->FindOrAddVertex(vtxarray,pt2,uv2,uv22,tan2,rgb2,no2,flat,polymat,mface->v3)); + if (nverts==4) + poly->SetVertex(3,meshobj->FindOrAddVertex(vtxarray,pt3,uv3,uv23,tan3,rgb3,no3,flat,polymat,mface->v4)); + meshobj->AddPolygon(poly); if (poly->IsCollider()) { @@ -1125,8 +1119,6 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools* } } meshobj->m_xyz_index_to_vertex_index_mapping.clear(); - if(skinMesh) - ((BL_SkinMeshObject*)meshobj)->m_mvert_to_dvert_mapping.clear(); meshobj->UpdateMaterialList(); // pre calculate texture generation @@ -1545,7 +1537,7 @@ void BL_CreatePhysicsObjectNew(KX_GameObject* gameobj, -static KX_LightObject *gamelight_from_blamp(Lamp *la, unsigned int layerflag, KX_Scene *kxscene, RAS_IRenderTools *rendertools, KX_BlenderSceneConverter *converter) { +static KX_LightObject *gamelight_from_blamp(Object *ob, Lamp *la, unsigned int layerflag, KX_Scene *kxscene, RAS_IRenderTools *rendertools, KX_BlenderSceneConverter *converter) { RAS_LightObject lightobj; KX_LightObject *gamelight; @@ -1577,8 +1569,15 @@ static KX_LightObject *gamelight_from_blamp(Lamp *la, unsigned int layerflag, KX } else { lightobj.m_type = RAS_LightObject::LIGHT_NORMAL; } + +#ifdef BLENDER_GLSL + if(converter->GetGLSLMaterials()) + GPU_lamp_from_blender(ob, la); - gamelight = new KX_LightObject(kxscene, KX_Scene::m_callbacks, rendertools, lightobj); + gamelight = new KX_LightObject(kxscene, KX_Scene::m_callbacks, rendertools, lightobj, ob->gpulamp); +#else + gamelight = new KX_LightObject(kxscene, KX_Scene::m_callbacks, rendertools, lightobj, NULL); +#endif BL_ConvertLampIpos(la, gamelight, converter); return gamelight; @@ -1610,7 +1609,7 @@ static KX_GameObject *gameobject_from_blenderobject( { case OB_LAMP: { - KX_LightObject* gamelight= gamelight_from_blamp(static_cast(ob->data), ob->lay, kxscene, rendertools, converter); + KX_LightObject* gamelight= gamelight_from_blamp(ob, static_cast(ob->data), ob->lay, kxscene, rendertools, converter); gameobj = gamelight; gamelight->AddRef(); @@ -1660,7 +1659,7 @@ static KX_GameObject *gameobject_from_blenderobject( // two options exists for deform: shape keys and armature // only support relative shape key bool bHasShapeKey = mesh->key != NULL && mesh->key->type==KEY_RELATIVE; - bool bHasDvert = mesh->dvert != NULL; + bool bHasDvert = mesh->dvert != NULL && ob->defbase.first; bool bHasArmature = (ob->parent && ob->parent->type == OB_ARMATURE && ob->partype==PARSKEL && bHasDvert); if (bHasShapeKey) { @@ -1671,13 +1670,15 @@ static KX_GameObject *gameobject_from_blenderobject( if (bHasArmature) dcont->LoadShapeDrivers(ob->parent); } else if (bHasArmature) { - BL_SkinDeformer *dcont = new BL_SkinDeformer(ob, (BL_SkinMeshObject*)meshobj ); + BL_SkinDeformer *dcont = new BL_SkinDeformer((BL_DeformableGameObject*)gameobj, + ob, (BL_SkinMeshObject*)meshobj); ((BL_DeformableGameObject*)gameobj)->m_pDeformer = dcont; } else if (bHasDvert) { // this case correspond to a mesh that can potentially deform but not with the // object to which it is attached for the moment. A skin mesh was created in // BL_ConvertMesh() so must create a deformer too! - BL_MeshDeformer *dcont = new BL_MeshDeformer(ob, (BL_SkinMeshObject*)meshobj ); + BL_MeshDeformer *dcont = new BL_MeshDeformer((BL_DeformableGameObject*)gameobj, + ob, (BL_SkinMeshObject*)meshobj); ((BL_DeformableGameObject*)gameobj)->m_pDeformer = dcont; } @@ -2075,7 +2076,8 @@ void BL_ConvertBlenderObjects(struct Main* maggie, if (blenderscene->camera) { KX_Camera *gamecamera= (KX_Camera*) converter->FindGameObject(blenderscene->camera); - kxscene->SetActiveCamera(gamecamera); + if(gamecamera) + kxscene->SetActiveCamera(gamecamera); } // Set up armatures diff --git a/source/gameengine/Converter/BL_MeshDeformer.cpp b/source/gameengine/Converter/BL_MeshDeformer.cpp index 212827a660f..39d66a90e92 100644 --- a/source/gameengine/Converter/BL_MeshDeformer.cpp +++ b/source/gameengine/Converter/BL_MeshDeformer.cpp @@ -39,6 +39,7 @@ #endif #include "RAS_IPolygonMaterial.h" +#include "BL_DeformableGameObject.h" #include "BL_MeshDeformer.h" #include "BL_SkinMeshObject.h" #include "DNA_mesh_types.h" @@ -47,33 +48,40 @@ #include "GEN_Map.h" #include "STR_HashedString.h" -bool BL_MeshDeformer::Apply(RAS_IPolyMaterial *mat) +bool BL_MeshDeformer::Apply(RAS_IPolyMaterial*) { - size_t i, j, index; - vecVertexArray array; - vecIndexArrays mvarray; - vecIndexArrays diarray; + size_t i, j; + float *co; - RAS_TexVert *tv; - MVert *mvert; + // only apply once per frame if the mesh is actually modified + if(m_pMeshObject->MeshModified() && + m_lastDeformUpdate != m_gameobj->GetLastFrame()) { + // For each material + for(RAS_MaterialBucket::Set::iterator mit = m_pMeshObject->GetFirstMaterial(); + mit != m_pMeshObject->GetLastMaterial(); ++ mit) { + RAS_IPolyMaterial *mat = (*mit)->GetPolyMaterial(); - // For each material - array = m_pMeshObject->GetVertexCache(mat); - mvarray = m_pMeshObject->GetMVertCache(mat); - diarray = m_pMeshObject->GetDIndexCache(mat); + vecVertexArray& vertexarrays = m_pMeshObject->GetVertexCache(mat); - // For each array - for (i=0; isize(); j++){ - tv = &((*array[i])[j]); - index = ((*diarray[i])[j]); + // For each array + for (i=0; imvert[((*mvarray[i])[index])]); - tv->SetXYZ(MT_Point3(mvert->co)); + // For each vertex + for (j=0; jmvert[v.getOrigIndex()].co; + v.SetXYZ(MT_Point3(co)); + } + } } + + m_lastDeformUpdate = m_gameobj->GetLastFrame(); + + return true; } - return true; + + return false; } BL_MeshDeformer::~BL_MeshDeformer() @@ -92,83 +100,86 @@ void BL_MeshDeformer::RecalcNormals() /* We don't normalize for performance, not doing it for faces normals * gives area-weight normals which often look better anyway, and use * GL_NORMALIZE so we don't have to do per vertex normalization either - * since the GPU can do it faster - * - * There's a lot of indirection here to get to the data, can this work - * with less arrays/indirection? */ - - vecIndexArrays indexarrays; - vecIndexArrays mvarrays; - vecIndexArrays diarrays; - vecVertexArray vertexarrays; + * since the GPU can do it faster */ size_t i, j; /* set vertex normals to zero */ - for (i=0; i<(size_t)m_bmesh->totvert; i++) - m_transnors[i] = MT_Vector3(0.0f, 0.0f, 0.0f); + memset(m_transnors, 0, sizeof(float)*3*m_bmesh->totvert); /* add face normals to vertices. */ for(RAS_MaterialBucket::Set::iterator mit = m_pMeshObject->GetFirstMaterial(); mit != m_pMeshObject->GetLastMaterial(); ++ mit) { RAS_IPolyMaterial *mat = (*mit)->GetPolyMaterial(); - indexarrays = m_pMeshObject->GetIndexCache(mat); - vertexarrays = m_pMeshObject->GetVertexCache(mat); - diarrays = m_pMeshObject->GetDIndexCache(mat); - mvarrays = m_pMeshObject->GetMVertCache(mat); + const vecIndexArrays& indexarrays = m_pMeshObject->GetIndexCache(mat); + vecVertexArray& vertexarrays = m_pMeshObject->GetVertexCache(mat); for (i=0; iUsesTriangles()? 3: 4; for(j=0; jgetLocalXYZ(); - fnor = (((mv2-mv1).cross(mv3-mv2))+((mv4-mv3).cross(mv1-mv4))); //.safe_normalized(); + n1[0]= co1[0]-co3[0]; + n1[1]= co1[1]-co3[1]; + n1[2]= co1[2]-co3[2]; + + n2[0]= co2[0]-co4[0]; + n2[1]= co2[1]-co4[1]; + n2[2]= co2[2]-co4[2]; } - else - fnor = ((mv2-mv1).cross(mv3-mv2)); //.safe_normalized(); + else { + n1[0]= co1[0]-co2[0]; + n2[0]= co2[0]-co3[0]; + n1[1]= co1[1]-co2[1]; + + n2[1]= co2[1]-co3[1]; + n1[2]= co1[2]-co2[2]; + n2[2]= co2[2]-co3[2]; + } + + fnor[0]= n1[1]*n2[2] - n1[2]*n2[1]; + fnor[1]= n1[2]*n2[0] - n1[0]*n2[2]; + fnor[2]= n1[0]*n2[1] - n1[1]*n2[0]; /* add to vertices for smooth normals */ - m_transnors[mvarray[diarray[i1]]] += fnor; - m_transnors[mvarray[diarray[i2]]] += fnor; - m_transnors[mvarray[diarray[i3]]] += fnor; + float *vn1 = m_transnors[v1.getOrigIndex()]; + float *vn2 = m_transnors[v2.getOrigIndex()]; + float *vn3 = m_transnors[v3.getOrigIndex()]; + + vn1[0] += fnor[0]; vn1[1] += fnor[1]; vn1[2] += fnor[2]; + vn2[0] += fnor[0]; vn2[1] += fnor[1]; vn2[2] += fnor[2]; + vn3[0] += fnor[0]; vn3[1] += fnor[1]; vn3[2] += fnor[2]; + + if(v4) { + float *vn4 = m_transnors[v4->getOrigIndex()]; + vn4[0] += fnor[0]; vn4[1] += fnor[1]; vn4[2] += fnor[2]; + } /* in case of flat - just assign, the vertices are split */ if(v1.getFlag() & TV_CALCFACENORMAL) { v1.SetNormal(fnor); v2.SetNormal(fnor); v3.SetNormal(fnor); - } - - if(nvert == 4) { - int i4 = indexarray[j+3]; - RAS_TexVert& v4 = vertexarray[i4]; - - /* same as above */ - m_transnors[mvarray[diarray[i4]]] += fnor; - - if(v4.getFlag() & TV_CALCFACENORMAL) - v4.SetNormal(fnor); + if(v4) + v4->SetNormal(fnor); } } } @@ -179,18 +190,17 @@ void BL_MeshDeformer::RecalcNormals() mit != m_pMeshObject->GetLastMaterial(); ++ mit) { RAS_IPolyMaterial *mat = (*mit)->GetPolyMaterial(); - vertexarrays = m_pMeshObject->GetVertexCache(mat); - diarrays = m_pMeshObject->GetDIndexCache(mat); - mvarrays = m_pMeshObject->GetMVertCache(mat); + vecVertexArray& vertexarrays = m_pMeshObject->GetVertexCache(mat); for (i=0; itotvert)][3]; - m_transnors=new MT_Vector3[m_bmesh->totvert]; + m_transverts=new float[m_bmesh->totvert][3]; + m_transnors=new float[m_bmesh->totvert][3]; m_tvtot = m_bmesh->totvert; } } diff --git a/source/gameengine/Converter/BL_MeshDeformer.h b/source/gameengine/Converter/BL_MeshDeformer.h index 8d8b56b1eed..e9f7f0b192f 100644 --- a/source/gameengine/Converter/BL_MeshDeformer.h +++ b/source/gameengine/Converter/BL_MeshDeformer.h @@ -40,19 +40,25 @@ #pragma warning (disable:4786) // get rid of stupid stl-visual compiler debug warning #endif //WIN32 +class BL_DeformableGameObject; + class BL_MeshDeformer : public RAS_Deformer { public: void VerifyStorage(); void RecalcNormals(); virtual void Relink(GEN_Map*map){}; - BL_MeshDeformer(struct Object* obj, class BL_SkinMeshObject *meshobj ): + BL_MeshDeformer(BL_DeformableGameObject *gameobj, + struct Object* obj, + class BL_SkinMeshObject *meshobj ): m_pMeshObject(meshobj), m_bmesh((struct Mesh*)(obj->data)), m_transverts(0), m_transnors(0), m_objMesh(obj), - m_tvtot(0) + m_tvtot(0), + m_gameobj(gameobj), + m_lastDeformUpdate(-1) {}; virtual ~BL_MeshDeformer(); virtual void SetSimulatedTime(double time){}; @@ -68,10 +74,12 @@ protected: // this is so m_transverts doesn't need to be converted // before deformation float (*m_transverts)[3]; - MT_Vector3* m_transnors; + float (*m_transnors)[3]; struct Object* m_objMesh; // -- int m_tvtot; + BL_DeformableGameObject* m_gameobj; + double m_lastDeformUpdate; }; #endif diff --git a/source/gameengine/Converter/BL_ShapeDeformer.h b/source/gameengine/Converter/BL_ShapeDeformer.h index 9f8361dbaca..5f0188e3a42 100644 --- a/source/gameengine/Converter/BL_ShapeDeformer.h +++ b/source/gameengine/Converter/BL_ShapeDeformer.h @@ -58,9 +58,8 @@ public: Object *bmeshobj, BL_SkinMeshObject *mesh) : - BL_SkinDeformer(bmeshobj, mesh), - m_lastShapeUpdate(-1), - m_gameobj(gameobj) + BL_SkinDeformer(gameobj,bmeshobj, mesh), + m_lastShapeUpdate(-1) { }; @@ -72,9 +71,8 @@ public: bool release_object, BL_ArmatureObject* arma = NULL) : - BL_SkinDeformer(bmeshobj_old, bmeshobj_new, mesh, release_object, arma), - m_lastShapeUpdate(-1), - m_gameobj(gameobj) + BL_SkinDeformer(gameobj, bmeshobj_old, bmeshobj_new, mesh, release_object, arma), + m_lastShapeUpdate(-1) { }; @@ -94,7 +92,6 @@ public: protected: vector m_shapeDrivers; double m_lastShapeUpdate; - BL_DeformableGameObject* m_gameobj; }; diff --git a/source/gameengine/Converter/BL_SkinDeformer.cpp b/source/gameengine/Converter/BL_SkinDeformer.cpp index dd7119b1031..d3442fe5298 100644 --- a/source/gameengine/Converter/BL_SkinDeformer.cpp +++ b/source/gameengine/Converter/BL_SkinDeformer.cpp @@ -57,11 +57,12 @@ extern "C"{ #define __NLA_DEFNORMALS //#undef __NLA_DEFNORMALS -BL_SkinDeformer::BL_SkinDeformer(struct Object *bmeshobj, +BL_SkinDeformer::BL_SkinDeformer(BL_DeformableGameObject *gameobj, + struct Object *bmeshobj, class BL_SkinMeshObject *mesh, BL_ArmatureObject* arma) : // - BL_MeshDeformer(bmeshobj, mesh), + BL_MeshDeformer(gameobj, bmeshobj, mesh), m_armobj(arma), m_lastArmaUpdate(-1), m_defbase(&bmeshobj->defbase), @@ -71,12 +72,13 @@ BL_SkinDeformer::BL_SkinDeformer(struct Object *bmeshobj, }; BL_SkinDeformer::BL_SkinDeformer( + BL_DeformableGameObject *gameobj, struct Object *bmeshobj_old, // Blender object that owns the new mesh struct Object *bmeshobj_new, // Blender object that owns the original mesh class BL_SkinMeshObject *mesh, bool release_object, BL_ArmatureObject* arma) : - BL_MeshDeformer(bmeshobj_old, mesh), + BL_MeshDeformer(gameobj, bmeshobj_old, mesh), m_armobj(arma), m_lastArmaUpdate(-1), m_defbase(&bmeshobj_old->defbase), @@ -96,35 +98,32 @@ BL_SkinDeformer::~BL_SkinDeformer() m_armobj->Release(); } -bool BL_SkinDeformer::Apply(RAS_IPolyMaterial *mat) +bool BL_SkinDeformer::Apply(RAS_IPolyMaterial *) { - size_t i, j, index; - vecVertexArray array; - vecIndexArrays mvarray; - vecMDVertArray dvarray; - vecIndexArrays diarray; + size_t i, j; - RAS_TexVert *tv; - MT_Point3 pt; -// float co[3]; + if (!Update()) + // no need to update the cache + return false; - Update(); + // Update all materials at once, so we can do the above update test + // without ending up with some materials not updated + for(RAS_MaterialBucket::Set::iterator mit = m_pMeshObject->GetFirstMaterial(); + mit != m_pMeshObject->GetLastMaterial(); ++ mit) { + RAS_IPolyMaterial *mat = (*mit)->GetPolyMaterial(); - array = m_pMeshObject->GetVertexCache(mat); - mvarray = m_pMeshObject->GetMVertCache(mat); - diarray = m_pMeshObject->GetDIndexCache(mat); - // For each array - for (i=0; isize(); j++) { + vecVertexArray& vertexarrays = m_pMeshObject->GetVertexCache(mat); - tv = &((*array[i])[j]); - - index = ((*diarray[i])[j]); - - // Copy the untransformed data from the original mvert - // Set the data - tv->SetXYZ(m_transverts[((*mvarray[i])[index])]); + // For each array + for (i=0; im_MvertArrayCache1[vtxarray]->size(); - - /* Check to see if this has already been pushed */ - for (vector::iterator it = m_mvert_to_dvert_mapping[mv].begin(); - it != m_mvert_to_dvert_mapping[mv].end(); - it++) - { - if(it->mat == mat) - return it->index; - } - - ao->m_MvertArrayCache1[vtxarray]->push_back(mv); - ao->m_DvertArrayCache1[vtxarray]->push_back(dv); - - BL_MDVertMap mdmap; - mdmap.mat = mat; - mdmap.index = numvert; - m_mvert_to_dvert_mapping[mv].push_back(mdmap); - - return numvert; -}; - -int BL_SkinMeshObject::FindVertexArray(int numverts,RAS_IPolyMaterial* polymat) -{ - int array=-1; - - BL_SkinArrayOptimizer* ao = (BL_SkinArrayOptimizer*)GetArrayOptimizer(polymat); - - - for (size_t i=0;im_VertexArrayCache1.size();i++) - { - if ( (ao->m_TriangleArrayCount[i] + (numverts-2)) < BUCKET_MAX_TRIANGLES) - { - if((ao->m_VertexArrayCache1[i]->size()+numverts < BUCKET_MAX_INDICES)) - { - array = i; - ao->m_TriangleArrayCount[array]+=numverts-2; - break; - } - } - } - - - if (array == -1) - { - array = ao->m_VertexArrayCache1.size(); - - vector* va = new vector; - ao->m_VertexArrayCache1.push_back(va); - - KX_IndexArray *ia = new KX_IndexArray(); - ao->m_IndexArrayCache1.push_back(ia); - - KX_IndexArray *bva = new KX_IndexArray(); - ao->m_MvertArrayCache1.push_back(bva); - - BL_DeformVertArray *dva = new BL_DeformVertArray(); - ao->m_DvertArrayCache1.push_back(dva); - - KX_IndexArray *da = new KX_IndexArray(); - ao->m_DIndexArrayCache1.push_back(da); - - ao->m_TriangleArrayCount.push_back(numverts-2); - - } - - - return array; -} - - //void BL_SkinMeshObject::Bucketize(double* oglmatrix,void* clientobj,bool useObjectColor,const MT_Vector4& rgbavec,RAS_BucketManager* bucketmgr) void BL_SkinMeshObject::Bucketize(double* oglmatrix,void* clientobj,bool useObjectColor,const MT_Vector4& rgbavec) { diff --git a/source/gameengine/Converter/BL_SkinMeshObject.h b/source/gameengine/Converter/BL_SkinMeshObject.h index cc2b8de600e..c21fb64204b 100644 --- a/source/gameengine/Converter/BL_SkinMeshObject.h +++ b/source/gameengine/Converter/BL_SkinMeshObject.h @@ -44,78 +44,19 @@ #include "DNA_key_types.h" #include "DNA_meshdata_types.h" -typedef vector BL_MVertArray; -typedef vector BL_DeformVertArray; -typedef vector BL_VertexArray; - - -typedef vector*> vecMDVertArray; -typedef vector*> vecBVertexArray; - -class BL_SkinArrayOptimizer : public KX_ArrayOptimizer -{ -public: - BL_SkinArrayOptimizer(int index) - :KX_ArrayOptimizer (index) {}; - virtual ~BL_SkinArrayOptimizer(){ - - for (vector::iterator itv = m_MvertArrayCache1.begin(); - !(itv == m_MvertArrayCache1.end());itv++) - { - delete (*itv); - } - for (vector::iterator itd = m_DvertArrayCache1.begin(); - !(itd == m_DvertArrayCache1.end());itd++) - { - delete (*itd); - } - for (vector::iterator iti = m_DIndexArrayCache1.begin(); - !(iti == m_DIndexArrayCache1.end());iti++) - { - delete (*iti); - } - - m_MvertArrayCache1.clear(); - m_DvertArrayCache1.clear(); - m_DIndexArrayCache1.clear(); - }; - - vector m_MvertArrayCache1; - vector m_DvertArrayCache1; - vector m_DIndexArrayCache1; - -}; - class BL_SkinMeshObject : public RAS_MeshObject { // enum { BUCKET_MAX_INDICES = 16384};//2048};//8192}; // enum { BUCKET_MAX_TRIANGLES = 4096}; - KX_ArrayOptimizer* GetArrayOptimizer(RAS_IPolyMaterial* polymat) - { - KX_ArrayOptimizer** aop = (m_matVertexArrayS[*polymat]); - if (aop) - return *aop; - int numelements = m_matVertexArrayS.size(); - m_sortedMaterials.push_back(polymat); - - BL_SkinArrayOptimizer* ao = new BL_SkinArrayOptimizer(numelements); - m_matVertexArrayS.insert(*polymat,ao); - return ao; - } - protected: vector m_cacheWeightIndex; public: - struct BL_MDVertMap { RAS_IPolyMaterial *mat; int index; }; - vector > m_mvert_to_dvert_mapping; - void Bucketize(double* oglmatrix,void* clientobj,bool useObjectColor,const MT_Vector4& rgbavec); // void Bucketize(double* oglmatrix,void* clientobj,bool useObjectColor,const MT_Vector4& rgbavec,class RAS_BucketManager* bucketmgr); - int FindVertexArray(int numverts,RAS_IPolyMaterial* polymat); BL_SkinMeshObject(Mesh* mesh, int lightlayer) : RAS_MeshObject (mesh, lightlayer) { m_class = 1; @@ -144,42 +85,7 @@ public: } } }; - - const vecIndexArrays& GetDIndexCache (RAS_IPolyMaterial* mat) - { - BL_SkinArrayOptimizer* ao = (BL_SkinArrayOptimizer*)GetArrayOptimizer(mat);//*(m_matVertexArrays[*mat]); - return ao->m_DIndexArrayCache1; - } - const vecMDVertArray& GetDVertCache (RAS_IPolyMaterial* mat) - { - BL_SkinArrayOptimizer* ao = (BL_SkinArrayOptimizer*)GetArrayOptimizer(mat);//*(m_matVertexArrays[*mat]); - return ao->m_DvertArrayCache1; - } - const vecIndexArrays& GetMVertCache (RAS_IPolyMaterial* mat) - { - BL_SkinArrayOptimizer* ao = (BL_SkinArrayOptimizer*)GetArrayOptimizer(mat);//*(m_matVertexArrays[*mat]); - return ao->m_MvertArrayCache1; - } - void AddPolygon(RAS_Polygon* poly); - int FindOrAddDeform(unsigned int vtxarray, unsigned int mv, struct MDeformVert *dv, RAS_IPolyMaterial* mat); - int FindOrAddVertex(int vtxarray,const MT_Point3& xyz, - const MT_Point2& uv, - const MT_Point2& uv2, - const MT_Vector4& tangent, - const unsigned int rgbacolor, - const MT_Vector3& normal, int defnr, bool flat, RAS_IPolyMaterial* mat, int origindex) - { - BL_SkinArrayOptimizer* ao = (BL_SkinArrayOptimizer*)GetArrayOptimizer(mat); - int numverts = ao->m_VertexArrayCache1[vtxarray]->size(); - int index = RAS_MeshObject::FindOrAddVertex(vtxarray, xyz, uv, uv2, tangent, rgbacolor, normal, flat, mat, origindex); - - /* this means a new vertex was added, so we add the defnr too */ - if(index == numverts) - ao->m_DIndexArrayCache1[vtxarray]->push_back(defnr); - - return index; - } // for shape keys, void CheckWeightCache(struct Object* obj); diff --git a/source/gameengine/Ketsji/BL_BlenderShader.cpp b/source/gameengine/Ketsji/BL_BlenderShader.cpp index 06e012123b1..dd45d522b9f 100644 --- a/source/gameengine/Ketsji/BL_BlenderShader.cpp +++ b/source/gameengine/Ketsji/BL_BlenderShader.cpp @@ -1,9 +1,11 @@ #include "DNA_customdata_types.h" +#include "DNA_material_types.h" #include "BL_BlenderShader.h" +#include "BL_Material.h" -#if 0 +#ifdef BLENDER_GLSL #include "GPU_extensions.h" #include "GPU_material.h" #endif @@ -13,29 +15,32 @@ const bool BL_BlenderShader::Ok()const { -#if 0 +#ifdef BLENDER_GLSL return (mGPUMat != 0); +#else + return 0; #endif - - return false; } -BL_BlenderShader::BL_BlenderShader(struct Material *ma) +BL_BlenderShader::BL_BlenderShader(struct Material *ma, int lightlayer) : -#if 0 +#ifdef BLENDER_GLSL mGPUMat(0), #endif - mBound(false) + mBound(false), + mLightLayer(lightlayer) { -#if 0 - if(ma) - mGPUMat = GPU_material_from_blender(ma, GPU_PROFILE_DERIVEDMESH); +#ifdef BLENDER_GLSL + if(ma) { + GPU_material_from_blender(ma); + mGPUMat = ma->gpumaterial; + } #endif } BL_BlenderShader::~BL_BlenderShader() { -#if 0 +#ifdef BLENDER_GLSL if(mGPUMat) { GPU_material_unbind(mGPUMat); mGPUMat = 0; @@ -43,16 +48,12 @@ BL_BlenderShader::~BL_BlenderShader() #endif } -void BL_BlenderShader::ApplyShader() -{ -} - void BL_BlenderShader::SetProg(bool enable) { -#if 0 +#ifdef BLENDER_GLSL if(mGPUMat) { if(enable) { - GPU_material_bind(mGPUMat); + GPU_material_bind(mGPUMat, mLightLayer); mBound = true; } else { @@ -65,7 +66,7 @@ void BL_BlenderShader::SetProg(bool enable) int BL_BlenderShader::GetAttribNum() { -#if 0 +#ifdef BLENDER_GLSL GPUVertexAttribs attribs; int i, enabled = 0; @@ -82,17 +83,19 @@ int BL_BlenderShader::GetAttribNum() enabled = BL_MAX_ATTRIB; return enabled; -#endif - +#else return 0; +#endif } -void BL_BlenderShader::SetTexCoords(RAS_IRasterizer* ras) +void BL_BlenderShader::SetAttribs(RAS_IRasterizer* ras, const BL_Material *mat) { -#if 0 +#ifdef BLENDER_GLSL GPUVertexAttribs attribs; int i, attrib_num; + ras->SetAttribNum(0); + if(!mGPUMat) return; @@ -109,14 +112,24 @@ void BL_BlenderShader::SetTexCoords(RAS_IRasterizer* ras) if(attribs.layer[i].glindex > attrib_num) continue; - if(attribs.layer[i].type == CD_MTFACE) - ras->SetAttrib(RAS_IRasterizer::RAS_TEXCO_UV1, attribs.layer[i].glindex); + if(attribs.layer[i].type == CD_MTFACE) { + if(!mat->uvName.IsEmpty() && strcmp(mat->uvName.ReadPtr(), attribs.layer[i].name) == 0) + ras->SetAttrib(RAS_IRasterizer::RAS_TEXCO_UV1, attribs.layer[i].glindex); + else if(!mat->uv2Name.IsEmpty() && strcmp(mat->uv2Name.ReadPtr(), attribs.layer[i].name) == 0) + ras->SetAttrib(RAS_IRasterizer::RAS_TEXCO_UV2, attribs.layer[i].glindex); + else + ras->SetAttrib(RAS_IRasterizer::RAS_TEXCO_UV1, attribs.layer[i].glindex); + } else if(attribs.layer[i].type == CD_TANGENT) ras->SetAttrib(RAS_IRasterizer::RAS_TEXTANGENT, attribs.layer[i].glindex); else if(attribs.layer[i].type == CD_ORCO) ras->SetAttrib(RAS_IRasterizer::RAS_TEXCO_ORCO, attribs.layer[i].glindex); else if(attribs.layer[i].type == CD_NORMAL) ras->SetAttrib(RAS_IRasterizer::RAS_TEXCO_NORM, attribs.layer[i].glindex); + else if(attribs.layer[i].type == CD_MCOL) + ras->SetAttrib(RAS_IRasterizer::RAS_TEXCO_VCOL, attribs.layer[i].glindex); + else + ras->SetAttrib(RAS_IRasterizer::RAS_TEXCO_DISABLE, attribs.layer[i].glindex); } ras->EnableTextures(true); @@ -128,8 +141,8 @@ void BL_BlenderShader::SetTexCoords(RAS_IRasterizer* ras) void BL_BlenderShader::Update( const KX_MeshSlot & ms, RAS_IRasterizer* rasty ) { -#if 0 - float obmat[4][4], viewmat[4][4]; +#ifdef BLENDER_GLSL + float obmat[4][4], viewmat[4][4], viewinvmat[4][4]; if(!mGPUMat || !mBound) return; @@ -142,7 +155,20 @@ void BL_BlenderShader::Update( const KX_MeshSlot & ms, RAS_IRasterizer* rasty ) model.getValue((float*)obmat); view.getValue((float*)viewmat); - GPU_material_bind_uniforms(mGPUMat, obmat, viewmat); + view.invert(); + view.getValue((float*)viewinvmat); + + GPU_material_bind_uniforms(mGPUMat, obmat, viewmat, viewinvmat); +#endif +} + +bool BL_BlenderShader::Equals(BL_BlenderShader *blshader) +{ +#ifdef BLENDER_GLSL + /* to avoid unneeded state switches */ + return (blshader && mGPUMat == blshader->mGPUMat && mLightLayer == blshader->mLightLayer); +#else + return true; #endif } diff --git a/source/gameengine/Ketsji/BL_BlenderShader.h b/source/gameengine/Ketsji/BL_BlenderShader.h index 4cab0e644c3..b758d1a9cba 100644 --- a/source/gameengine/Ketsji/BL_BlenderShader.h +++ b/source/gameengine/Ketsji/BL_BlenderShader.h @@ -2,7 +2,7 @@ #ifndef __BL_GPUSHADER_H__ #define __BL_GPUSHADER_H__ -#if 0 +#ifdef BLENDER_GLSL #include "GPU_material.h" #endif @@ -12,7 +12,10 @@ #include "MT_Tuple3.h" #include "MT_Tuple4.h" +#include "RAS_IPolygonMaterial.h" + struct Material; +class BL_Material; #define BL_MAX_ATTRIB 16 @@ -23,22 +26,24 @@ struct Material; class BL_BlenderShader { private: -#if 0 +#ifdef BLENDER_GLSL GPUMaterial *mGPUMat; #endif bool mBound; + int mLightLayer; public: - BL_BlenderShader(struct Material *ma); + BL_BlenderShader(struct Material *ma, int lightlayer); virtual ~BL_BlenderShader(); const bool Ok()const; void SetProg(bool enable); - void ApplyShader(); - void SetTexCoords(class RAS_IRasterizer* ras); int GetAttribNum(); + void SetAttribs(class RAS_IRasterizer* ras, const BL_Material *mat); void Update(const class KX_MeshSlot & ms, class RAS_IRasterizer* rasty); + + bool Equals(BL_BlenderShader *blshader); }; #endif//__BL_GPUSHADER_H__ diff --git a/source/gameengine/Ketsji/BL_Material.cpp b/source/gameengine/Ketsji/BL_Material.cpp index f5312ccd023..7e3d6984f19 100644 --- a/source/gameengine/Ketsji/BL_Material.cpp +++ b/source/gameengine/Ketsji/BL_Material.cpp @@ -105,7 +105,8 @@ void BL_Material::GetConversionRGB(unsigned int *nrgb) { *nrgb = rgb[3]; } -void BL_Material::SetConversionUV(MT_Point2 *nuv) { +void BL_Material::SetConversionUV(const STR_String& name, MT_Point2 *nuv) { + uvName = name; uv[0] = *nuv++; uv[1] = *nuv++; uv[2] = *nuv++; @@ -118,7 +119,8 @@ void BL_Material::GetConversionUV(MT_Point2 *nuv){ *nuv++ = uv[2]; *nuv = uv[3]; } -void BL_Material::SetConversionUV2(MT_Point2 *nuv) { +void BL_Material::SetConversionUV2(const STR_String& name, MT_Point2 *nuv) { + uv2Name = name; uv2[0] = *nuv++; uv2[1] = *nuv++; uv2[2] = *nuv++; diff --git a/source/gameengine/Ketsji/BL_Material.h b/source/gameengine/Ketsji/BL_Material.h index ddb6662830a..568f7e171de 100644 --- a/source/gameengine/Ketsji/BL_Material.h +++ b/source/gameengine/Ketsji/BL_Material.h @@ -83,13 +83,16 @@ public: MT_Point2 uv[4]; MT_Point2 uv2[4]; + STR_String uvName; + STR_String uv2Name; + void SetConversionRGB(unsigned int *rgb); void GetConversionRGB(unsigned int *rgb); - void SetConversionUV(MT_Point2 *uv); + void SetConversionUV(const STR_String& name, MT_Point2 *uv); void GetConversionUV(MT_Point2 *uv); - void SetConversionUV2(MT_Point2 *uv); + void SetConversionUV2(const STR_String& name, MT_Point2 *uv); void GetConversionUV2(MT_Point2 *uv); void SetSharedMaterial(bool v); diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp index 02b1ffd432a..0f445a9f32e 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp @@ -38,6 +38,8 @@ extern "C" { // ------------------------------------ #define spit(x) std::cout << x << std::endl; +BL_BlenderShader *KX_BlenderMaterial::mLastBlenderShader = NULL; + //static PyObject *gTextureDict = 0; KX_BlenderMaterial::KX_BlenderMaterial( @@ -126,32 +128,31 @@ void KX_BlenderMaterial::OnConstruction() // when material are reused between objects return; - if(mMaterial->glslmat) { + if(mMaterial->glslmat) SetBlenderGLSLShader(); - } - else { - // for each unique material... - int i; - for(i=0; inum_enabled; i++) { - if( mMaterial->mapping[i].mapping & USEENV ) { - if(!GLEW_ARB_texture_cube_map) { - spit("CubeMap textures not supported"); - continue; - } - if(!mTextures[i].InitCubeMap(i, mMaterial->cubemap[i] ) ) + + // for each unique material... + int i; + for(i=0; inum_enabled; i++) { + if( mMaterial->mapping[i].mapping & USEENV ) { + if(!GLEW_ARB_texture_cube_map) { + spit("CubeMap textures not supported"); + continue; + } + if(!mTextures[i].InitCubeMap(i, mMaterial->cubemap[i] ) ) + spit("unable to initialize image("<matname<< ", image will not be available"); + } + + else { + if( mMaterial->img[i] ) { + if( ! mTextures[i].InitFromImage(i, mMaterial->img[i], (mMaterial->flag[i] &MIPMAP)!=0 )) spit("unable to initialize image("<matname<< ", image will not be available"); - } - - else { - if( mMaterial->img[i] ) { - if( ! mTextures[i].InitFromImage(i, mMaterial->img[i], (mMaterial->flag[i] &MIPMAP)!=0 )) - spit("unable to initialize image("<matname<< ", image will not be available"); - } + mMaterial->matname<< ", image will not be available"); } } } + mBlendFunc[0] =0; mBlendFunc[1] =0; mConstructed = true; @@ -168,7 +169,11 @@ void KX_BlenderMaterial::OnExit() } if( mBlenderShader ) { - mBlenderShader->SetProg(false); + if(mBlenderShader == mLastBlenderShader) { + mBlenderShader->SetProg(false); + mLastBlenderShader = NULL; + } + delete mBlenderShader; mBlenderShader = 0; } @@ -225,14 +230,23 @@ void KX_BlenderMaterial::setBlenderShaderData( bool enable, RAS_IRasterizer *ras { if( !enable || !mBlenderShader->Ok() ) { // frame cleanup. - mBlenderShader->SetProg(false); + if(mLastBlenderShader) { + mLastBlenderShader->SetProg(false); + mLastBlenderShader= NULL; + } BL_Texture::DisableAllTextures(); return; } - BL_Texture::DisableAllTextures(); - mBlenderShader->SetProg(true); - mBlenderShader->ApplyShader(); + if(!mBlenderShader->Equals(mLastBlenderShader)) { + BL_Texture::DisableAllTextures(); + + if(mLastBlenderShader) + mLastBlenderShader->SetProg(false); + + mBlenderShader->SetProg(true); + mLastBlenderShader= mBlenderShader; + } } void KX_BlenderMaterial::setTexData( bool enable, RAS_IRasterizer *ras) @@ -298,7 +312,12 @@ KX_BlenderMaterial::ActivatShaders( // reset... if(tmp->mMaterial->IsShared()) cachingInfo =0; - + + if(mLastBlenderShader) { + mLastBlenderShader->SetProg(false); + mLastBlenderShader= NULL; + } + if (GetCachingInfo() != cachingInfo) { if (!cachingInfo) @@ -372,7 +391,7 @@ KX_BlenderMaterial::ActivateBlenderShaders( } ActivatGLMaterials(rasty); - mBlenderShader->SetTexCoords(rasty); + mBlenderShader->SetAttribs(rasty, mMaterial); } void @@ -382,6 +401,12 @@ KX_BlenderMaterial::ActivateMat( )const { KX_BlenderMaterial *tmp = const_cast(this); + + if(mLastBlenderShader) { + mLastBlenderShader->SetProg(false); + mLastBlenderShader= NULL; + } + if (GetCachingInfo() != cachingInfo) { if (!cachingInfo) tmp->setTexData( false,rasty ); @@ -460,17 +485,29 @@ KX_BlenderMaterial::Activate( return dopass; } +bool KX_BlenderMaterial::UsesLighting(RAS_IRasterizer *rasty) const +{ + if(!RAS_IPolyMaterial::UsesLighting(rasty)) + return false; + + if(mShader && mShader->Ok()); + else if(mBlenderShader && mBlenderShader->Ok()) + return false; + + return true; +} + void KX_BlenderMaterial::ActivateMeshSlot(const KX_MeshSlot & ms, RAS_IRasterizer* rasty) const { if(mShader && GLEW_ARB_shader_objects) mShader->Update(ms, rasty); - if(mBlenderShader && GLEW_ARB_shader_objects) + else if(mBlenderShader && GLEW_ARB_shader_objects) mBlenderShader->Update(ms, rasty); } void KX_BlenderMaterial::ActivatGLMaterials( RAS_IRasterizer* rasty )const { - if(!mBlenderShader) { + if(mShader || !mBlenderShader) { rasty->SetSpecularity( mMaterial->speccolor[0]*mMaterial->spec_f, mMaterial->speccolor[1]*mMaterial->spec_f, @@ -506,6 +543,7 @@ void KX_BlenderMaterial::ActivateTexGen(RAS_IRasterizer *ras) const ras->SetAttribNum(0); if(mShader && GLEW_ARB_shader_objects) { if(mShader->GetAttribute() == BL_Shader::SHD_TANGENT) { + ras->SetAttrib(RAS_IRasterizer::RAS_TEXCO_DISABLE, 0); ras->SetAttrib(RAS_IRasterizer::RAS_TEXTANGENT, 1); ras->SetAttribNum(2); } @@ -793,7 +831,7 @@ KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getShader , "getShader()") void KX_BlenderMaterial::SetBlenderGLSLShader(void) { if(!mBlenderShader) - mBlenderShader = new BL_BlenderShader(mMaterial->material); + mBlenderShader = new BL_BlenderShader(mMaterial->material, m_lightlayer); if(!mBlenderShader->Ok()) { delete mBlenderShader; diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.h b/source/gameengine/Ketsji/KX_BlenderMaterial.h index 62e96b71937..bf6d2095e7c 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.h +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.h @@ -94,6 +94,7 @@ private: BL_Material* mMaterial; BL_Shader* mShader; BL_BlenderShader* mBlenderShader; + static BL_BlenderShader *mLastBlenderShader; KX_Scene* mScene; BL_Texture mTextures[MAXTEX]; // texture array bool mUserDefBlend; @@ -106,6 +107,7 @@ private: void ActivatGLMaterials( RAS_IRasterizer* rasty )const; void ActivateTexGen( RAS_IRasterizer *ras ) const; + bool UsesLighting(RAS_IRasterizer *rasty) const; // message centers void setTexData( bool enable,RAS_IRasterizer *ras); diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index db13d30e2f1..2ac4f909077 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -1306,7 +1306,7 @@ PyObject* KX_GameObject::PyGetMesh(PyObject* self, return meshproxy; } } - return NULL; + Py_RETURN_NONE; } diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp index 56a06786679..20187a193ba 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp @@ -55,6 +55,7 @@ #include "KX_Scene.h" #include "MT_CmMatrix4x4.h" #include "KX_Camera.h" +#include "KX_Light.h" #include "KX_PythonInit.h" #include "KX_PyConstraintBinding.h" #include "PHY_IPhysicsEnvironment.h" @@ -614,6 +615,9 @@ void KX_KetsjiEngine::Render() // pass the scene's worldsettings to the rasterizer SetWorldSettings(scene->GetWorldInfo()); + // shadow buffers + RenderShadowBuffers(scene); + // Avoid drawing the scene with the active camera twice when it's viewport is enabled if(cam && !cam->GetViewport()) { @@ -885,8 +889,48 @@ void KX_KetsjiEngine::SetupRenderFrame(KX_Scene *scene, KX_Camera* cam) viewport.GetTop() ); -} +} +void KX_KetsjiEngine::RenderShadowBuffers(KX_Scene *scene) +{ + CListValue *lightlist = scene->GetLightList(); + int i, drawmode; + + for(i=0; iGetCount(); i++) { + KX_LightObject *light = (KX_LightObject*)lightlist->GetValue(i); + + light->Update(); + + if(m_drawingmode == RAS_IRasterizer::KX_TEXTURED && light->HasShadowBuffer()) { + /* make temporary camera */ + RAS_CameraData camdata = RAS_CameraData(); + KX_Camera *cam = new KX_Camera(scene, scene->m_callbacks, camdata, false); + cam->SetName("__shadow__cam__"); + + MT_Transform camtrans; + + /* switch drawmode for speed */ + drawmode = m_rasterizer->GetDrawingMode(); + m_rasterizer->SetDrawingMode(RAS_IRasterizer::KX_SHADOW); + + /* binds framebuffer object, sets up camera .. */ + light->BindShadowBuffer(m_rasterizer, cam, camtrans); + + /* update scene */ + scene->UpdateMeshTransformations(); + scene->CalculateVisibleMeshes(m_rasterizer, cam, light->GetShadowLayer()); + + /* render */ + m_rasterizer->ClearDepthBuffer(); + scene->RenderBuckets(camtrans, m_rasterizer, m_rendertools); + + /* unbind framebuffer object, restore drawmode, free camera */ + light->UnbindShadowBuffer(m_rasterizer); + m_rasterizer->SetDrawingMode(drawmode); + cam->Release(); + } + } +} // update graphics void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam) diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.h b/source/gameengine/Ketsji/KX_KetsjiEngine.h index 4c09bc3fcd5..77b69ec2d9e 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.h +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.h @@ -179,6 +179,7 @@ private: void RenderFrame(KX_Scene* scene, KX_Camera* cam); void PostRenderFrame(); void RenderDebugProperties(); + void RenderShadowBuffers(KX_Scene *scene); void SetBackGround(KX_WorldInfo* worldinfo); void SetWorldSettings(KX_WorldInfo* worldinfo); void DoSound(KX_Scene* scene); diff --git a/source/gameengine/Ketsji/KX_Light.cpp b/source/gameengine/Ketsji/KX_Light.cpp index 7decc5bc769..4e3d6180d22 100644 --- a/source/gameengine/Ketsji/KX_Light.cpp +++ b/source/gameengine/Ketsji/KX_Light.cpp @@ -36,14 +36,20 @@ #endif #include "KX_Light.h" +#include "KX_Camera.h" +#include "RAS_IRasterizer.h" #include "RAS_IRenderTools.h" #include "KX_PyMath.h" +#ifdef BLENDER_GLSL +#include "GPU_material.h" +#endif KX_LightObject::KX_LightObject(void* sgReplicationInfo,SG_Callbacks callbacks, class RAS_IRenderTools* rendertools, const RAS_LightObject& lightobj, + struct GPULamp *gpulamp, PyTypeObject* T ) : @@ -53,12 +59,12 @@ KX_LightObject::KX_LightObject(void* sgReplicationInfo,SG_Callbacks callbacks, m_lightobj = lightobj; m_lightobj.m_worldmatrix = GetOpenGLMatrixPtr(); m_rendertools->AddLight(&m_lightobj); + m_gpulamp = gpulamp; }; KX_LightObject::~KX_LightObject() { - m_rendertools->RemoveLight(&m_lightobj); } @@ -78,6 +84,78 @@ CValue* KX_LightObject::GetReplica() return replica; } +void KX_LightObject::Update() +{ +#ifdef BLENDER_GLSL + if(m_gpulamp) { + float obmat[4][4]; + double *dobmat = GetOpenGLMatrixPtr()->getPointer(); + + for(int i=0; i<4; i++) + for(int j=0; j<4; j++, dobmat++) + obmat[i][j] = (float)*dobmat; + + GPU_lamp_update(m_gpulamp, obmat); + } +#endif +} + +bool KX_LightObject::HasShadowBuffer() +{ +#ifdef BLENDER_GLSL + return (m_gpulamp && GPU_lamp_has_shadow_buffer(m_gpulamp)); +#else + return false; +#endif +} + +int KX_LightObject::GetShadowLayer() +{ +#ifdef BLENDER_GLSL + if(m_gpulamp) + return GPU_lamp_shadow_layer(m_gpulamp); + else +#endif + return 0; +} + +void KX_LightObject::BindShadowBuffer(RAS_IRasterizer *ras, KX_Camera *cam, MT_Transform& camtrans) +{ +#ifdef BLENDER_GLSL + float viewmat[4][4], winmat[4][4]; + int winsize; + + /* bind framebuffer */ + GPU_lamp_shadow_buffer_bind(m_gpulamp, viewmat, &winsize, winmat); + + /* setup camera transformation */ + MT_Matrix4x4 modelviewmat((float*)viewmat); + MT_Matrix4x4 projectionmat((float*)winmat); + + MT_Transform trans = MT_Transform((float*)viewmat); + camtrans.invert(trans); + + cam->SetModelviewMatrix(modelviewmat); + cam->SetProjectionMatrix(projectionmat); + + cam->NodeSetLocalPosition(camtrans.getOrigin()); + cam->NodeSetLocalOrientation(camtrans.getBasis()); + cam->NodeUpdateGS(0,true); + + /* setup rasterizer transformations */ + ras->SetProjectionMatrix(projectionmat); + ras->SetViewMatrix(modelviewmat, cam->NodeGetWorldPosition(), + cam->GetCameraLocation(), cam->GetCameraOrientation()); +#endif +} + +void KX_LightObject::UnbindShadowBuffer(RAS_IRasterizer *ras) +{ +#ifdef BLENDER_GLSL + GPU_lamp_shadow_buffer_unbind(m_gpulamp); +#endif +} + PyObject* KX_LightObject::_getattr(const STR_String& attr) { if (attr == "layer") diff --git a/source/gameengine/Ketsji/KX_Light.h b/source/gameengine/Ketsji/KX_Light.h index 236d3e4e12e..62eb26c61a8 100644 --- a/source/gameengine/Ketsji/KX_Light.h +++ b/source/gameengine/Ketsji/KX_Light.h @@ -32,19 +32,33 @@ #include "RAS_LightObject.h" #include "KX_GameObject.h" +struct GPULamp; +class KX_Camera; +class RAS_IRasterizer; +class RAS_IRenderTools; +class MT_Transform; + class KX_LightObject : public KX_GameObject { Py_Header; protected: RAS_LightObject m_lightobj; class RAS_IRenderTools* m_rendertools; //needed for registering and replication of lightobj + struct GPULamp *m_gpulamp; static char doc[]; public: - KX_LightObject(void* sgReplicationInfo,SG_Callbacks callbacks,class RAS_IRenderTools* rendertools,const struct RAS_LightObject& lightobj, PyTypeObject *T = &Type); + KX_LightObject(void* sgReplicationInfo,SG_Callbacks callbacks,class RAS_IRenderTools* rendertools,const struct RAS_LightObject& lightobj, struct GPULamp *gpulamp, PyTypeObject *T = &Type); virtual ~KX_LightObject(); virtual CValue* GetReplica(); RAS_LightObject* GetLightData() { return &m_lightobj;} + + /* GLSL shadow */ + bool HasShadowBuffer(); + int GetShadowLayer(); + void BindShadowBuffer(class RAS_IRasterizer *ras, class KX_Camera *cam, class MT_Transform& camtrans); + void UnbindShadowBuffer(class RAS_IRasterizer *ras); + void Update(); virtual PyObject* _getattr(const STR_String& attr); /* lens, near, far, projection_matrix */ virtual int _setattr(const STR_String& attr, PyObject *pyvalue); diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index c5f6230b2f2..065800379d8 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -888,6 +888,7 @@ void KX_Scene::ReplaceMesh(class CValue* obj,void* meshobj) else if (bHasArmature) { BL_SkinDeformer* skinDeformer = new BL_SkinDeformer( + newobj, oldblendobj, blendobj, static_cast(mesh), true, @@ -899,7 +900,7 @@ void KX_Scene::ReplaceMesh(class CValue* obj,void* meshobj) else if (bHasDvert) { BL_MeshDeformer* meshdeformer = new BL_MeshDeformer( - oldblendobj, static_cast(mesh) + newobj, oldblendobj, static_cast(mesh) ); newobj->m_pDeformer = meshdeformer; } @@ -1004,12 +1005,13 @@ void KX_Scene::UpdateMeshTransformations() } } -void KX_Scene::MarkVisible(SG_Tree *node, RAS_IRasterizer* rasty, KX_Camera* cam) +void KX_Scene::MarkVisible(SG_Tree *node, RAS_IRasterizer* rasty, KX_Camera* cam, int layer) { int intersect = KX_Camera::INTERSECT; KX_GameObject *gameobj = node->Client()?(KX_GameObject*) node->Client()->GetSGClientObject():NULL; - bool dotest = (gameobj && gameobj->GetVisible()) || node->Left() || node->Right(); - + bool visible = (gameobj && gameobj->GetVisible() && (!layer || (gameobj->GetLayer() & layer))); + bool dotest = visible || node->Left() || node->Right(); + /* If the camera is inside the box, assume intersect. */ if (dotest && !node->inside( cam->NodeGetWorldPosition())) { @@ -1033,19 +1035,19 @@ void KX_Scene::MarkVisible(SG_Tree *node, RAS_IRasterizer* rasty, KX_Camera* cam break; case KX_Camera::INTERSECT: if (gameobj) - MarkVisible(rasty, gameobj,cam); + MarkVisible(rasty, gameobj, cam, layer); if (node->Left()) - MarkVisible(node->Left(), rasty,cam); + MarkVisible(node->Left(), rasty, cam, layer); if (node->Right()) - MarkVisible(node->Right(), rasty,cam); + MarkVisible(node->Right(), rasty, cam, layer); break; case KX_Camera::INSIDE: - MarkSubTreeVisible(node, rasty, true,cam); + MarkSubTreeVisible(node, rasty, true, cam, layer); break; } } -void KX_Scene::MarkSubTreeVisible(SG_Tree *node, RAS_IRasterizer* rasty, bool visible,KX_Camera* cam) +void KX_Scene::MarkSubTreeVisible(SG_Tree *node, RAS_IRasterizer* rasty, bool visible, KX_Camera* cam, int layer) { if (node->Client()) { @@ -1068,16 +1070,23 @@ void KX_Scene::MarkSubTreeVisible(SG_Tree *node, RAS_IRasterizer* rasty, bool vi } } if (node->Left()) - MarkSubTreeVisible(node->Left(), rasty, visible,cam); + MarkSubTreeVisible(node->Left(), rasty, visible, cam, layer); if (node->Right()) - MarkSubTreeVisible(node->Right(), rasty, visible,cam); + MarkSubTreeVisible(node->Right(), rasty, visible, cam, layer); } -void KX_Scene::MarkVisible(RAS_IRasterizer* rasty, KX_GameObject* gameobj,KX_Camera* cam) +void KX_Scene::MarkVisible(RAS_IRasterizer* rasty, KX_GameObject* gameobj,KX_Camera* cam,int layer) { // User (Python/Actuator) has forced object invisible... if (!gameobj->GetVisible()) return; + + // Shadow lamp layers + if(layer && !(gameobj->GetLayer() & layer)) { + gameobj->MarkVisible(false); + return; + } + // If Frustum culling is off, the object is always visible. bool vis = !cam->GetFrustumCulling(); @@ -1127,20 +1136,20 @@ void KX_Scene::MarkVisible(RAS_IRasterizer* rasty, KX_GameObject* gameobj,KX_Cam } } -void KX_Scene::CalculateVisibleMeshes(RAS_IRasterizer* rasty,KX_Camera* cam) +void KX_Scene::CalculateVisibleMeshes(RAS_IRasterizer* rasty,KX_Camera* cam, int layer) { // FIXME: When tree is operational #if 1 // do this incrementally in the future for (int i = 0; i < m_objectlist->GetCount(); i++) { - MarkVisible(rasty, static_cast(m_objectlist->GetValue(i)), cam); + MarkVisible(rasty, static_cast(m_objectlist->GetValue(i)), cam, layer); } #else if (cam->GetFrustumCulling()) - MarkVisible(m_objecttree, rasty, cam); + MarkVisible(m_objecttree, rasty, cam, layer); else - MarkSubTreeVisible(m_objecttree, rasty, true, cam); + MarkSubTreeVisible(m_objecttree, rasty, true, cam, layer); #endif } diff --git a/source/gameengine/Ketsji/KX_Scene.h b/source/gameengine/Ketsji/KX_Scene.h index 733df2f69a1..28dee1b5893 100644 --- a/source/gameengine/Ketsji/KX_Scene.h +++ b/source/gameengine/Ketsji/KX_Scene.h @@ -260,9 +260,9 @@ protected: /** * Visibility testing functions. */ - void MarkVisible(SG_Tree *node, RAS_IRasterizer* rasty, KX_Camera*cam); - void MarkSubTreeVisible(SG_Tree *node, RAS_IRasterizer* rasty, bool visible, KX_Camera*cam); - void MarkVisible(RAS_IRasterizer* rasty, KX_GameObject* gameobj, KX_Camera*cam); + void MarkVisible(SG_Tree *node, RAS_IRasterizer* rasty, KX_Camera*cam,int layer=0); + void MarkSubTreeVisible(SG_Tree *node, RAS_IRasterizer* rasty, bool visible, KX_Camera*cam,int layer=0); + void MarkVisible(RAS_IRasterizer* rasty, KX_GameObject* gameobj, KX_Camera*cam, int layer=0); double m_suspendedtime; double m_suspendeddelta; @@ -483,7 +483,7 @@ public: void SetNetworkScene(NG_NetworkScene *newScene); void SetWorldInfo(class KX_WorldInfo* wi); KX_WorldInfo* GetWorldInfo(); - void CalculateVisibleMeshes(RAS_IRasterizer* rasty, KX_Camera *cam); + void CalculateVisibleMeshes(RAS_IRasterizer* rasty, KX_Camera *cam, int layer=0); void UpdateMeshTransformations(); KX_Camera* GetpCamera(); SND_Scene* GetSoundScene(); diff --git a/source/gameengine/Rasterizer/RAS_BucketManager.cpp b/source/gameengine/Rasterizer/RAS_BucketManager.cpp index 50df1a1e2ea..b4492ca03a9 100644 --- a/source/gameengine/Rasterizer/RAS_BucketManager.cpp +++ b/source/gameengine/Rasterizer/RAS_BucketManager.cpp @@ -109,7 +109,7 @@ void RAS_BucketManager::RenderAlphaBuckets( // it is needed for compatibility. rasty->SetDepthMask(RAS_IRasterizer::KX_DEPTHMASK_DISABLED); - int drawingmode; + RAS_IRasterizer::DrawMode drawingmode; std::multiset< alphamesh, backtofront>::iterator msit = alphameshset.begin(); for (; msit != alphameshset.end(); ++msit) { diff --git a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp index bff98abe058..cb10ba6bf37 100644 --- a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp +++ b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp @@ -27,6 +27,7 @@ */ #include "RAS_IPolygonMaterial.h" +#include "RAS_IRasterizer.h" #ifdef HAVE_CONFIG_H #include @@ -148,4 +149,19 @@ const unsigned int RAS_IPolyMaterial::GetFlag() const return m_flag; } +bool RAS_IPolyMaterial::UsesLighting(RAS_IRasterizer *rasty) const +{ + bool dolights = false; + + if(m_flag & RAS_BLENDERMAT) + dolights = (m_flag &RAS_MULTILIGHT)!=0; + else if(rasty->GetDrawingMode() < RAS_IRasterizer::KX_SOLID); + else if(rasty->GetDrawingMode() == RAS_IRasterizer::KX_SHADOW); + else + dolights = (m_drawingmode & 16)!=0; + + return dolights; +} + unsigned int RAS_IPolyMaterial::m_newpolymatid = 0; + diff --git a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h index 09824f6975c..d2d1dba99d9 100644 --- a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h +++ b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h @@ -140,6 +140,8 @@ public: const STR_String& GetMaterialName() const; const STR_String& GetTextureName() const; const unsigned int GetFlag() const; + + virtual bool UsesLighting(RAS_IRasterizer *rasty) const; /* * PreCalculate texture gen diff --git a/source/gameengine/Rasterizer/RAS_IRasterizer.h b/source/gameengine/Rasterizer/RAS_IRasterizer.h index dbedc492afa..d4a9177a85d 100644 --- a/source/gameengine/Rasterizer/RAS_IRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_IRasterizer.h @@ -33,12 +33,23 @@ #pragma warning (disable:4786) #endif +#include "STR_HashedString.h" + #include "MT_CmMatrix4x4.h" #include "MT_Matrix4x4.h" +#include "RAS_TexVert.h" + +#include +using namespace std; + class RAS_ICanvas; class RAS_IPolyMaterial; -#include "RAS_MaterialBucket.h" + +typedef vector KX_IndexArray; +typedef vector KX_VertexArray; +typedef vector< KX_VertexArray* > vecVertexArray; +typedef vector< KX_IndexArray* > vecIndexArrays; /** * 3D rendering device context interface. @@ -62,7 +73,18 @@ public: KX_WIREFRAME, KX_SOLID, KX_SHADED, - KX_TEXTURED + KX_TEXTURED, + KX_SHADOW + }; + + /** + * Drawing modes + */ + + enum DrawMode { + KX_MODE_LINES = 1, + KX_MODE_TRIANGLES, + KX_MODE_QUADS }; /** @@ -111,6 +133,7 @@ public: RAS_TEXCO_NORM, //< Normal coordinates RAS_TEXTANGENT, //< RAS_TEXCO_UV2, //< + RAS_TEXCO_VCOL, //< Vertex Color RAS_TEXCO_DISABLE //< Disable this texture unit (cached) }; @@ -197,45 +220,37 @@ public: * IndexPrimitives: Renders primitives. * @param vertexarrays is an array of vertex arrays * @param indexarrays is an array of index arrays - * @param mode determines the type of primitive stored in the vertex/index arrays: - * 0 triangles - * 1 lines (default) - * 2 quads - * @param polymat (reserved) + * @param mode determines the type of primitive stored in the vertex/index arrays * @param useObjectColor will render the object using @param rgbacolor instead of * vertex colors. */ - virtual void IndexPrimitives( const vecVertexArray& vertexarrays, + virtual void IndexPrimitives( const vecVertexArray& vertexarrays, const vecIndexArrays & indexarrays, - int mode, - class RAS_IPolyMaterial* polymat, - class RAS_IRenderTools* rendertools, + DrawMode mode, bool useObjectColor, const MT_Vector4& rgbacolor, class KX_ListSlot** slot)=0; + virtual void IndexPrimitivesMulti( + const vecVertexArray& vertexarrays, + const vecIndexArrays & indexarrays, + DrawMode mode, + bool useObjectColor, + const MT_Vector4& rgbacolor, + class KX_ListSlot** slot)=0; + /** * IndexPrimitives_3DText will render text into the polygons. * The text to be rendered is from @param rendertools client object's text property. */ virtual void IndexPrimitives_3DText( const vecVertexArray& vertexarrays, const vecIndexArrays & indexarrays, - int mode, + DrawMode mode, class RAS_IPolyMaterial* polymat, class RAS_IRenderTools* rendertools, bool useObjectColor, const MT_Vector4& rgbacolor)=0; - virtual void IndexPrimitivesMulti( - const vecVertexArray& vertexarrays, - const vecIndexArrays & indexarrays, - int mode, - class RAS_IPolyMaterial* polymat, - class RAS_IRenderTools* rendertools, - bool useObjectColor, - const MT_Vector4& rgbacolor, - class KX_ListSlot** slot)=0; - virtual void SetProjectionMatrix(MT_CmMatrix4x4 & mat)=0; /* This one should become our final version, methinks. */ /** diff --git a/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp b/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp index 1beade7acf7..e295d69e48e 100644 --- a/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp +++ b/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp @@ -167,38 +167,30 @@ RAS_MaterialBucket::T_MeshSlotList::iterator RAS_MaterialBucket::msEnd() } bool RAS_MaterialBucket::ActivateMaterial(const MT_Transform& cameratrans, RAS_IRasterizer* rasty, - RAS_IRenderTools *rendertools, int &drawmode) + RAS_IRenderTools *rendertools, RAS_IRasterizer::DrawMode &drawmode) { rendertools->SetViewMat(cameratrans); if (!rasty->SetMaterial(*m_material)) return false; - bool dolights = false; - const unsigned int flag = m_material->GetFlag(); - - if( flag & RAS_BLENDERMAT) - dolights = (flag &RAS_MULTILIGHT)!=0; - else - dolights = (m_material->GetDrawingMode()&16)!=0; - - if ((rasty->GetDrawingMode() < RAS_IRasterizer::KX_SOLID) || !dolights) - { - rendertools->ProcessLighting(-1); - } - else - { + if (m_material->UsesLighting(rasty)) rendertools->ProcessLighting(RAS_IRenderTools::RAS_LIGHT_OBJECT_LAYER/*m_material->GetLightLayer()*/); - } + else + rendertools->ProcessLighting(-1); - drawmode = (rasty->GetDrawingMode() < RAS_IRasterizer::KX_SOLID ? - 1: (m_material->UsesTriangles() ? 0 : 2)); + if(rasty->GetDrawingMode() < RAS_IRasterizer::KX_SOLID) + drawmode = RAS_IRasterizer::KX_MODE_LINES; + else if(m_material->UsesTriangles()) + drawmode = RAS_IRasterizer::KX_MODE_TRIANGLES; + else + drawmode = RAS_IRasterizer::KX_MODE_QUADS; return true; } void RAS_MaterialBucket::RenderMeshSlot(const MT_Transform& cameratrans, RAS_IRasterizer* rasty, - RAS_IRenderTools* rendertools, const KX_MeshSlot &ms, int drawmode) + RAS_IRenderTools* rendertools, const KX_MeshSlot &ms, RAS_IRasterizer::DrawMode drawmode) { if (!ms.m_bVisible) return; @@ -225,6 +217,17 @@ void RAS_MaterialBucket::RenderMeshSlot(const MT_Transform& cameratrans, RAS_IRa ms.m_DisplayList->SetModified(ms.m_mesh->MeshModified()); } + // verify if we can use display list, not for deformed object, and + // also don't create a new display list when drawing shadow buffers, + // then it won't have texture coordinates for actual drawing + KX_ListSlot **displaylist; + if(ms.m_pDeformer) + displaylist = 0; + else if(!ms.m_DisplayList && rasty->GetDrawingMode() == RAS_IRasterizer::KX_SHADOW) + displaylist = 0; + else + displaylist = &ms.m_DisplayList; + // Use the text-specific IndexPrimitives for text faces if (m_material->GetDrawingMode() & RAS_IRasterizer::RAS_RENDER_3DPOLYGON_TEXT) { @@ -245,12 +248,9 @@ void RAS_MaterialBucket::RenderMeshSlot(const MT_Transform& cameratrans, RAS_IRa ms.m_mesh->GetVertexCache(m_material), ms.m_mesh->GetIndexCache(m_material), drawmode, - m_material, - rendertools, ms.m_bObjectColor, ms.m_RGBAcolor, - (ms.m_pDeformer)? 0: &ms.m_DisplayList - ); + displaylist); } // Use the normal IndexPrimitives @@ -260,12 +260,9 @@ void RAS_MaterialBucket::RenderMeshSlot(const MT_Transform& cameratrans, RAS_IRa ms.m_mesh->GetVertexCache(m_material), ms.m_mesh->GetIndexCache(m_material), drawmode, - m_material, - rendertools, // needed for textprinting on polys ms.m_bObjectColor, ms.m_RGBAcolor, - (ms.m_pDeformer)? 0: &ms.m_DisplayList - ); + displaylist); } if(rasty->QueryLists()) { @@ -287,7 +284,7 @@ void RAS_MaterialBucket::Render(const MT_Transform& cameratrans, //rasty->SetMaterial(*m_material); - int drawmode; + RAS_IRasterizer::DrawMode drawmode; for (T_MeshSlotList::const_iterator it = m_meshSlots.begin(); ! (it == m_meshSlots.end()); ++it) { diff --git a/source/gameengine/Rasterizer/RAS_MaterialBucket.h b/source/gameengine/Rasterizer/RAS_MaterialBucket.h index 5ad0c173a56..13d8a53714a 100644 --- a/source/gameengine/Rasterizer/RAS_MaterialBucket.h +++ b/source/gameengine/Rasterizer/RAS_MaterialBucket.h @@ -35,17 +35,13 @@ #include "MT_Transform.h" #include "RAS_IPolygonMaterial.h" +#include "RAS_IRasterizer.h" #include "RAS_Deformer.h" // __NLA #include #include #include using namespace std; -typedef vector KX_IndexArray; -typedef vector KX_VertexArray; -typedef vector< KX_VertexArray* > vecVertexArray; -typedef vector< KX_IndexArray* > vecIndexArrays; - /** * KX_VertexIndex */ @@ -146,9 +142,9 @@ public: const MT_Vector4& rgbavec); void RenderMeshSlot(const MT_Transform& cameratrans, RAS_IRasterizer* rasty, - RAS_IRenderTools* rendertools, const KX_MeshSlot &ms, int drawmode); + RAS_IRenderTools* rendertools, const KX_MeshSlot &ms, RAS_IRasterizer::DrawMode drawmode); bool ActivateMaterial(const MT_Transform& cameratrans, RAS_IRasterizer* rasty, - RAS_IRenderTools *rendertools, int &drawmode); + RAS_IRenderTools *rendertools, RAS_IRasterizer::DrawMode& drawmode); unsigned int NumMeshSlots(); T_MeshSlotList::iterator msBegin(); diff --git a/source/gameengine/Rasterizer/RAS_MeshObject.cpp b/source/gameengine/Rasterizer/RAS_MeshObject.cpp index d7ab88a6b06..4420f16c56d 100644 --- a/source/gameengine/Rasterizer/RAS_MeshObject.cpp +++ b/source/gameengine/Rasterizer/RAS_MeshObject.cpp @@ -68,8 +68,8 @@ RAS_MeshObject::RAS_MeshObject(Mesh* mesh, int lightlayer) m_lightlayer(lightlayer), m_zsort(false), m_MeshMod(true), - m_class(0), - m_mesh(mesh) + m_mesh(mesh), + m_class(0) { } @@ -259,18 +259,18 @@ int RAS_MeshObject::FindOrAddVertex(int vtxarray, const MT_Vector3& normal, bool flat, RAS_IPolyMaterial* mat, - int orgindex) + int origindex) { - KX_ArrayOptimizer* ao = GetArrayOptimizer(mat);//*(m_matVertexArrays[*mat]); + KX_ArrayOptimizer* ao = GetArrayOptimizer(mat); int numverts = ao->m_VertexArrayCache1[vtxarray]->size();//m_VertexArrayCount[vtxarray]; - RAS_TexVert newvert(xyz,uv,uv2,tangent,rgbacolor,normal, flat? TV_CALCFACENORMAL: 0); + RAS_TexVert newvert(xyz,uv,uv2,tangent,rgbacolor,normal, flat? TV_CALCFACENORMAL: 0,origindex); #define KX_FIND_SHARED_VERTICES #ifdef KX_FIND_SHARED_VERTICES if(!flat) { - for (std::vector::iterator it = m_xyz_index_to_vertex_index_mapping[orgindex].begin(); - it != m_xyz_index_to_vertex_index_mapping[orgindex].end(); + for (std::vector::iterator it = m_xyz_index_to_vertex_index_mapping[origindex].begin(); + it != m_xyz_index_to_vertex_index_mapping[origindex].end(); it++) { if ((*it).m_arrayindex1 == ao->m_index1 && @@ -293,22 +293,18 @@ int RAS_MeshObject::FindOrAddVertex(int vtxarray, idx.m_array = vtxarray; idx.m_index = numverts; idx.m_matid = mat; - m_xyz_index_to_vertex_index_mapping[orgindex].push_back(idx); + m_xyz_index_to_vertex_index_mapping[origindex].push_back(idx); return numverts; } - - -const vecVertexArray& RAS_MeshObject::GetVertexCache (RAS_IPolyMaterial* mat) +vecVertexArray& RAS_MeshObject::GetVertexCache (RAS_IPolyMaterial* mat) { - KX_ArrayOptimizer* ao = GetArrayOptimizer(mat);//*(m_matVertexArrays[*mat]); + KX_ArrayOptimizer* ao = GetArrayOptimizer(mat); return ao->m_VertexArrayCache1; } - - int RAS_MeshObject::GetVertexArrayLength(RAS_IPolyMaterial* mat) { int len = 0; @@ -362,7 +358,7 @@ RAS_TexVert* RAS_MeshObject::GetVertex(unsigned int matid, const vecIndexArrays& RAS_MeshObject::GetIndexCache (RAS_IPolyMaterial* mat) { - KX_ArrayOptimizer* ao = GetArrayOptimizer(mat);//*(m_matVertexArrays[*mat]); + KX_ArrayOptimizer* ao = GetArrayOptimizer(mat); return ao->m_IndexArrayCache1; } @@ -371,16 +367,27 @@ const vecIndexArrays& RAS_MeshObject::GetIndexCache (RAS_IPolyMaterial* mat) KX_ArrayOptimizer* RAS_MeshObject::GetArrayOptimizer(RAS_IPolyMaterial* polymat) { - KX_ArrayOptimizer** aop = (m_matVertexArrayS[*polymat]); + KX_ArrayOptimizer** aop = m_matVertexArrayS[polymat]; - if (aop) + if(aop) return *aop; + // didn't find array, but an array might already exist + // for a material equal to this one + for(int i=0;igetValue()); + if(*mat == *polymat) { + m_matVertexArrayS.insert(polymat, *m_matVertexArrayS.at(i)); + return *m_matVertexArrayS.at(i); + } + } + + // create new array int numelements = m_matVertexArrayS.size(); m_sortedMaterials.push_back(polymat); - + KX_ArrayOptimizer* ao = new KX_ArrayOptimizer(numelements); - m_matVertexArrayS.insert(*polymat,ao); + m_matVertexArrayS.insert(polymat, ao); return ao; } @@ -463,7 +470,7 @@ RAS_TexVert* RAS_MeshObject::GetVertex(short array, unsigned int index, RAS_IPolyMaterial* polymat) { - KX_ArrayOptimizer* ao = GetArrayOptimizer(polymat);//*(m_matVertexArrays[*polymat]); + KX_ArrayOptimizer* ao = GetArrayOptimizer(polymat); return &((*(ao->m_VertexArrayCache1)[array])[index]); } @@ -471,13 +478,19 @@ RAS_TexVert* RAS_MeshObject::GetVertex(short array, void RAS_MeshObject::ClearArrayData() { - for (int i=0;i m_matVertexArrayS; + GEN_Map m_matVertexArrayS; RAS_MaterialBucket::Set m_materials; Mesh* m_mesh; @@ -242,10 +242,10 @@ public: const MT_Vector3& normal, bool flat, RAS_IPolyMaterial* mat, - int orgindex + int origindex ); - const vecVertexArray& GetVertexCache (RAS_IPolyMaterial* mat); + vecVertexArray& GetVertexCache (RAS_IPolyMaterial* mat); int GetVertexArrayLength(RAS_IPolyMaterial* mat); diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp index 39080b80492..c2687319717 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp @@ -161,9 +161,7 @@ void RAS_ListRasterizer::ReleaseAlloc() void RAS_ListRasterizer::IndexPrimitives( const vecVertexArray & vertexarrays, const vecIndexArrays & indexarrays, - int mode, - class RAS_IPolyMaterial* polymat, - class RAS_IRenderTools* rendertools, + DrawMode mode, bool useObjectColor, const MT_Vector4& rgbacolor, class KX_ListSlot** slot) @@ -185,15 +183,13 @@ void RAS_ListRasterizer::IndexPrimitives( if (mUseVertexArrays) { RAS_VAOpenGLRasterizer::IndexPrimitives( vertexarrays, indexarrays, - mode, polymat, - rendertools, useObjectColor, + mode, useObjectColor, rgbacolor,slot ); } else { RAS_OpenGLRasterizer::IndexPrimitives( vertexarrays, indexarrays, - mode, polymat, - rendertools, useObjectColor, + mode, useObjectColor, rgbacolor,slot ); } @@ -208,9 +204,7 @@ void RAS_ListRasterizer::IndexPrimitives( void RAS_ListRasterizer::IndexPrimitivesMulti( const vecVertexArray& vertexarrays, const vecIndexArrays & indexarrays, - int mode, - class RAS_IPolyMaterial* polymat, - class RAS_IRenderTools* rendertools, + DrawMode mode, bool useObjectColor, const MT_Vector4& rgbacolor, class KX_ListSlot** slot) @@ -230,18 +224,19 @@ void RAS_ListRasterizer::IndexPrimitivesMulti( } } - if (mUseVertexArrays) { + // workaround: note how we do not use vertex arrays for making display + // lists, since glVertexAttribPointerARB doesn't seem to work correct + // in display lists on ATI? either a bug in the driver or in Blender .. + if (mUseVertexArrays && !localSlot) { RAS_VAOpenGLRasterizer::IndexPrimitivesMulti( vertexarrays, indexarrays, - mode, polymat, - rendertools, useObjectColor, + mode, useObjectColor, rgbacolor,slot ); } else { RAS_OpenGLRasterizer::IndexPrimitivesMulti( vertexarrays, indexarrays, - mode, polymat, - rendertools, useObjectColor, + mode, useObjectColor, rgbacolor,slot ); } diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h index 4b3304d7396..b1b19144c12 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h @@ -52,9 +52,7 @@ public: virtual void IndexPrimitives( const vecVertexArray& vertexarrays, const vecIndexArrays & indexarrays, - int mode, - class RAS_IPolyMaterial* polymat, - class RAS_IRenderTools* rendertools, + DrawMode mode, bool useObjectColor, const MT_Vector4& rgbacolor, class KX_ListSlot** slot @@ -63,9 +61,7 @@ public: virtual void IndexPrimitivesMulti( const vecVertexArray& vertexarrays, const vecIndexArrays & indexarrays, - int mode, - class RAS_IPolyMaterial* polymat, - class RAS_IRenderTools* rendertools, + DrawMode mode, bool useObjectColor, const MT_Vector4& rgbacolor, class KX_ListSlot** slot diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp index 18147b53f4c..dcc36bf5a39 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp @@ -368,23 +368,11 @@ void RAS_OpenGLRasterizer::SetDrawingMode(int drawingmode) switch (m_drawingmode) { - case KX_BOUNDINGBOX: - { - } case KX_WIREFRAME: { glDisable (GL_CULL_FACE); break; } - case KX_TEXTURED: - { - } - case KX_SHADED: - { - } - case KX_SOLID: - { - } default: { } @@ -603,33 +591,14 @@ void RAS_OpenGLRasterizer::GetViewMatrix(MT_Matrix4x4 &mat) const void RAS_OpenGLRasterizer::IndexPrimitives(const vecVertexArray & vertexarrays, const vecIndexArrays & indexarrays, - int mode, - class RAS_IPolyMaterial* polymat, - class RAS_IRenderTools* rendertools, + DrawMode mode, bool useObjectColor, const MT_Vector4& rgbacolor, class KX_ListSlot** slot ) { - GLenum drawmode; - switch (mode) - { - case 0: - drawmode = GL_TRIANGLES; - break; - case 1: - drawmode = GL_LINES; - break; - case 2: - drawmode = GL_QUADS; - break; - default: - drawmode = GL_LINES; - break; - } - - const RAS_TexVert* vertexarray ; - unsigned int numindices,vt; + const RAS_TexVert* vertexarray; + unsigned int numindices, vt; for (vt=0;vtgetLocalXYZ()); - glTexCoordPointer(2,GL_FLOAT,vtxstride,vertexarray->getUV1()); - glColorPointer(4,GL_UNSIGNED_BYTE,vtxstride,vertexarray->getRGBA()); glNormalPointer(GL_FLOAT,vtxstride,vertexarray->getNormal()); + glTexCoordPointer(2,GL_FLOAT,vtxstride,vertexarray->getUV1()); + if(glIsEnabled(GL_COLOR_ARRAY)) + glColorPointer(4,GL_UNSIGNED_BYTE,vtxstride,vertexarray->getRGBA()); //if(m_Lock) // local->Begin(vertexarrays[vt]->size()); @@ -169,8 +166,6 @@ void RAS_VAOpenGLRasterizer::IndexPrimitives( const vecVertexArray& vertexarrays //if(m_Lock) // local->End(); - - } glDisableClientState(GL_TEXTURE_COORD_ARRAY); @@ -178,28 +173,21 @@ void RAS_VAOpenGLRasterizer::IndexPrimitives( const vecVertexArray& vertexarrays void RAS_VAOpenGLRasterizer::IndexPrimitivesMulti( const vecVertexArray& vertexarrays, const vecIndexArrays & indexarrays, - int mode, - class RAS_IPolyMaterial* polymat, - class RAS_IRenderTools* rendertools, + DrawMode mode, bool useObjectColor, const MT_Vector4& rgbacolor, class KX_ListSlot** slot) { static const GLsizei vtxstride = sizeof(RAS_TexVert); + GLenum drawmode; - switch (mode) - { - case 0: - drawmode = GL_TRIANGLES; - break; - case 2: - drawmode = GL_QUADS; - break; - case 1: //lines - default: - drawmode = GL_LINES; - break; - } + if(mode == KX_MODE_TRIANGLES) + drawmode = GL_TRIANGLES; + else if(mode == KX_MODE_QUADS) + drawmode = GL_QUADS; + else + drawmode = GL_LINES; + const RAS_TexVert* vertexarray; unsigned int numindices, vt; @@ -232,10 +220,10 @@ void RAS_VAOpenGLRasterizer::IndexPrimitivesMulti( const vecVertexArray& vertexa continue; glVertexPointer(3,GL_FLOAT,vtxstride,vertexarray->getLocalXYZ()); - TexCoordPtr(vertexarray); - - glColorPointer(4,GL_UNSIGNED_BYTE,vtxstride,vertexarray->getRGBA()); glNormalPointer(GL_FLOAT,vtxstride,vertexarray->getNormal()); + TexCoordPtr(vertexarray); + if(glIsEnabled(GL_COLOR_ARRAY)) + glColorPointer(4,GL_UNSIGNED_BYTE,vtxstride,vertexarray->getRGBA()); //if(m_Lock) // local->Begin(vertexarrays[vt]->size()); @@ -296,19 +284,22 @@ void RAS_VAOpenGLRasterizer::TexCoordPtr(const RAS_TexVert *tv) switch(m_attrib[unit]) { case RAS_TEXCO_ORCO: case RAS_TEXCO_GLOB: - glVertexAttribPointer(unit, 3, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getLocalXYZ()); + glVertexAttribPointerARB(unit, 3, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getLocalXYZ()); break; case RAS_TEXCO_UV1: - glVertexAttribPointer(unit, 2, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getUV1()); + glVertexAttribPointerARB(unit, 2, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getUV1()); break; case RAS_TEXCO_NORM: - glVertexAttribPointer(unit, 3, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getNormal()); + glVertexAttribPointerARB(unit, 3, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getNormal()); break; case RAS_TEXTANGENT: - glVertexAttribPointer(unit, 4, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getTangent()); + glVertexAttribPointerARB(unit, 4, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getTangent()); break; case RAS_TEXCO_UV2: - glVertexAttribPointer(unit, 2, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getUV2()); + glVertexAttribPointerARB(unit, 2, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getUV2()); + break; + case RAS_TEXCO_VCOL: + glVertexAttribPointerARB(unit, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(RAS_TexVert), tv->getRGBA()); break; default: break; @@ -386,11 +377,12 @@ void RAS_VAOpenGLRasterizer::EnableTextures(bool enable) case RAS_TEXCO_NORM: case RAS_TEXTANGENT: case RAS_TEXCO_UV2: - if(enable) glEnableVertexAttribArray(unit); - else glDisableVertexAttribArray(unit); + case RAS_TEXCO_VCOL: + if(enable) glEnableVertexAttribArrayARB(unit); + else glDisableVertexAttribArrayARB(unit); break; default: - glDisableVertexAttribArray(unit); + glDisableVertexAttribArrayARB(unit); break; } } diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.h index ea08887028f..e4cc4ace0e8 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.h @@ -52,9 +52,7 @@ public: virtual void IndexPrimitives( const vecVertexArray& vertexarrays, const vecIndexArrays & indexarrays, - int mode, - class RAS_IPolyMaterial* polymat, - class RAS_IRenderTools* rendertools, + DrawMode mode, bool useObjectColor, const MT_Vector4& rgbacolor, class KX_ListSlot** slot); @@ -62,9 +60,7 @@ public: virtual void IndexPrimitivesMulti( const vecVertexArray& vertexarrays, const vecIndexArrays & indexarrays, - int mode, - class RAS_IPolyMaterial* polymat, - class RAS_IRenderTools* rendertools, + DrawMode mode, bool useObjectColor, const MT_Vector4& rgbacolor, class KX_ListSlot** slot); diff --git a/source/gameengine/Rasterizer/RAS_TexVert.cpp b/source/gameengine/Rasterizer/RAS_TexVert.cpp index 61ac456b2bc..935633dc636 100644 --- a/source/gameengine/Rasterizer/RAS_TexVert.cpp +++ b/source/gameengine/Rasterizer/RAS_TexVert.cpp @@ -40,7 +40,8 @@ RAS_TexVert::RAS_TexVert(const MT_Point3& xyz, const MT_Vector4& tangent, const unsigned int rgba, const MT_Vector3& normal, - const short flag) + const short flag, + const unsigned int origindex) { xyz.getValue(m_localxyz); uv.getValue(m_uv1); @@ -49,6 +50,7 @@ RAS_TexVert::RAS_TexVert(const MT_Point3& xyz, SetNormal(normal); tangent.getValue(m_tangent); m_flag = flag; + m_origindex = origindex; m_unit = 2; } @@ -107,44 +109,6 @@ void RAS_TexVert::SetNormal(const MT_Vector3& normal) normal.getValue(m_normal); } -#ifndef RAS_TexVert_INLINE - -// leave multiline for debugging -const float* RAS_TexVert::getUV1 () const -{ - return m_uv1; -} - -const float* RAS_TexVert::getUV2 () const -{ - return m_uv2; -} - - - -const float* RAS_TexVert::getNormal() const -{ - return m_normal; -} - -const float* RAS_TexVert::getTangent() const -{ - return m_tangent; -} - - -const float* RAS_TexVert::getLocalXYZ() const -{ - return m_localxyz; -} - -const unsigned char* RAS_TexVert::getRGBA() const -{ - return (unsigned char*) &m_rgba; -} - -#endif - // compare two vertices, and return TRUE if both are almost identical (they can be shared) bool RAS_TexVert::closeTo(const RAS_TexVert* other) { diff --git a/source/gameengine/Rasterizer/RAS_TexVert.h b/source/gameengine/Rasterizer/RAS_TexVert.h index 84135db918f..bf092b4b230 100644 --- a/source/gameengine/Rasterizer/RAS_TexVert.h +++ b/source/gameengine/Rasterizer/RAS_TexVert.h @@ -42,8 +42,6 @@ static MT_Point2 g_pt2; #define TV_MAX 3//match Def in BL_Material.h -#define RAS_TexVert_INLINE 1 - class RAS_TexVert { @@ -55,9 +53,10 @@ class RAS_TexVert float m_normal[3]; // 3*2 = 6 short m_flag; // 2 unsigned int m_unit; // 4 + unsigned int m_origindex; // 4 //--------- - // 52 - //32 bytes total size, fits nice = 52 = not fit nice. + // 56 + // 32 bytes total size, fits nice = 56 = not fit nice. // We'll go for 64 bytes total size - 24 bytes left. public: short getFlag() const; @@ -71,11 +70,10 @@ public: const MT_Vector4& tangent, const unsigned int rgba, const MT_Vector3& normal, - const short flag); + const short flag, + const unsigned int origindex); ~RAS_TexVert() {}; - // leave multiline for debugging -#ifdef RAS_TexVert_INLINE const float* getUV1 () const { return m_uv1; }; @@ -99,13 +97,11 @@ public: const unsigned char* getRGBA() const { return (unsigned char *) &m_rgba; } -#else - const float* getUV1 () const; - const float* getUV2 () const; - const float* getNormal() const; - const float* getLocalXYZ() const; - const unsigned char* getRGBA() const; -#endif + + const unsigned int getOrigIndex() const { + return m_origindex; + } + void SetXYZ(const MT_Point3& xyz); void SetUV(const MT_Point2& uv); void SetUV2(const MT_Point2& uv); diff --git a/source/kernel/gen_system/GEN_HashedPtr.h b/source/kernel/gen_system/GEN_HashedPtr.h index 777ec76e067..13faa5f227b 100644 --- a/source/kernel/gen_system/GEN_HashedPtr.h +++ b/source/kernel/gen_system/GEN_HashedPtr.h @@ -39,6 +39,7 @@ public: GEN_HashedPtr(void* val) : m_valptr(val) {}; unsigned int hash() const { return GEN_Hash(m_valptr);}; inline friend bool operator ==(const GEN_HashedPtr & rhs, const GEN_HashedPtr & lhs) { return rhs.m_valptr == lhs.m_valptr;}; + void *getValue() const { return m_valptr; } }; #endif //__GEN_HASHEDPTR diff --git a/source/kernel/gen_system/GEN_Map.h b/source/kernel/gen_system/GEN_Map.h index f9c14800499..37c75d8293a 100644 --- a/source/kernel/gen_system/GEN_Map.h +++ b/source/kernel/gen_system/GEN_Map.h @@ -82,6 +82,24 @@ public: } return 0; } + + Key* getKey(int index) { + int count=0; + for (int i=0;im_key; + } + bucket = bucket->m_next; + count++; + } + } + return 0; + } void clear() { for (int i = 0; i < m_num_buckets; ++i) { From 310a37c29c283b2a7aef0ec2e3cc7fe366b23698 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 10 Jul 2008 14:23:19 +0000 Subject: [PATCH 30/37] Adding an option for action actuator - "Continue" this means animations always play from where they left off. Continue was the 2.46 operation too, so new functionality is the option to disable. When using states, an action like kick or throw can often switch out before finishing playing the action, and there was no way to play from the start frame the second time round. (even setting the actions current frame through python doesn't work work) --- source/blender/makesdna/DNA_actuator_types.h | 5 +-- source/blender/src/buttons_logic.c | 20 +++++++----- .../Converter/BL_ActionActuator.cpp | 32 +++++++++++++++++-- .../gameengine/Converter/BL_ActionActuator.h | 5 +++ .../Converter/KX_ConvertActuators.cpp | 1 + source/gameengine/PyDoc/BL_ActionActuator.py | 15 +++++++++ 6 files changed, 65 insertions(+), 13 deletions(-) diff --git a/source/blender/makesdna/DNA_actuator_types.h b/source/blender/makesdna/DNA_actuator_types.h index 77ebef744eb..a467722e8e1 100644 --- a/source/blender/makesdna/DNA_actuator_types.h +++ b/source/blender/makesdna/DNA_actuator_types.h @@ -51,8 +51,9 @@ typedef struct bActionActuator { int sta, end; /* Start & End frames */ char name[32]; /* For property-driven playback */ char frameProp[32]; /* Set this property to the actions current frame */ - int blendin; /* Number of frames of blending */ - short priority; /* Execution priority */ + short blendin; /* Number of frames of blending */ + short priority; /* Execution priority */ + short end_reset; /* Ending the actuator (negative pulse) wont reset the the action to its starting frame */ short strideaxis; /* Displacement axis */ float stridelength; /* Displacement incurred by cycle */ } bActionActuator; diff --git a/source/blender/src/buttons_logic.c b/source/blender/src/buttons_logic.c index 7050e61a6ac..cc4df06e22d 100644 --- a/source/blender/src/buttons_logic.c +++ b/source/blender/src/buttons_logic.c @@ -1769,23 +1769,27 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh #else str= "Action types %t|Play %x0|Flipper %x2|Loop Stop %x3|Loop End %x4|Property %x6"; #endif - uiDefButS(block, MENU, B_REDR, str, xco+30, yco-24, (width-60)/2, 19, &aa->type, 0.0, 0.0, 0.0, 0.0, "Action playback type"); - uiDefIDPoinBut(block, test_actionpoin_but, ID_AC, 1, "AC: ", xco+30 + ((width-60)/2), yco-24, (width-60)/2, 19, &aa->act, "Action name"); + uiDefButS(block, MENU, B_REDR, str, xco+10, yco-24, width/3, 19, &aa->type, 0.0, 0.0, 0.0, 0.0, "Action playback type"); + uiDefIDPoinBut(block, test_actionpoin_but, ID_AC, 1, "AC: ", xco+10+ (width/3), yco-24, ((width/3)*2) - (20 + 60), 19, &aa->act, "Action name"); + + uiDefButBitS(block, TOGN, 1, 0, "Continue", xco+((width/3)*2)+20, yco-24, 60, 19, + &aa->end_reset, 0.0, 0.0, 0, 0, "Restore last frame when switching on/off, otherwise play from the start each time"); + if(aa->type == ACT_ACTION_FROM_PROP) { - uiDefBut(block, TEX, 0, "Prop: ",xco+30, yco-44, width-60, 19, aa->name, 0.0, 31.0, 0, 0, "Use this property to define the Action position"); + uiDefBut(block, TEX, 0, "Prop: ",xco+10, yco-44, width-20, 19, aa->name, 0.0, 31.0, 0, 0, "Use this property to define the Action position"); } else { - uiDefButI(block, NUM, 0, "Sta: ",xco+30, yco-44, (width-60)/2, 19, &aa->sta, 0.0, MAXFRAMEF, 0, 0, "Start frame"); - uiDefButI(block, NUM, 0, "End: ",xco+30+(width-60)/2, yco-44, (width-60)/2, 19, &aa->end, 0.0, MAXFRAMEF, 0, 0, "End frame"); + uiDefButI(block, NUM, 0, "Sta: ",xco+10, yco-44, (width-20)/2, 19, &aa->sta, 0.0, MAXFRAMEF, 0, 0, "Start frame"); + uiDefButI(block, NUM, 0, "End: ",xco+10+(width-20)/2, yco-44, (width-20)/2, 19, &aa->end, 0.0, MAXFRAMEF, 0, 0, "End frame"); } - uiDefButI(block, NUM, 0, "Blendin: ", xco+30, yco-64, (width-60)/2, 19, &aa->blendin, 0.0, MAXFRAMEF, 0.0, 0.0, "Number of frames of motion blending"); - uiDefButS(block, NUM, 0, "Priority: ", xco+30+(width-60)/2, yco-64, (width-60)/2, 19, &aa->priority, 0.0, 100.0, 0.0, 0.0, "Execution priority - lower numbers will override actions with higher numbers, With 2 or more actions at once, the overriding channels must be lower in the stack"); + uiDefButS(block, NUM, 0, "Blendin: ", xco+10, yco-64, (width-20)/2, 19, &aa->blendin, 0.0, 32767, 0.0, 0.0, "Number of frames of motion blending"); + uiDefButS(block, NUM, 0, "Priority: ", xco+10+(width-20)/2, yco-64, (width-20)/2, 19, &aa->priority, 0.0, 100.0, 0.0, 0.0, "Execution priority - lower numbers will override actions with higher numbers, With 2 or more actions at once, the overriding channels must be lower in the stack"); - uiDefBut(block, TEX, 0, "FrameProp: ",xco+30, yco-84, width-60, 19, aa->frameProp, 0.0, 31.0, 0, 0, "Assign this property this actions current frame number"); + uiDefBut(block, TEX, 0, "FrameProp: ",xco+10, yco-84, width-20, 19, aa->frameProp, 0.0, 31.0, 0, 0, "Assign this property this actions current frame number"); #ifdef __NLA_ACTION_BY_MOTION_ACTUATOR diff --git a/source/gameengine/Converter/BL_ActionActuator.cpp b/source/gameengine/Converter/BL_ActionActuator.cpp index 44f6ec1af90..5d6dd694765 100644 --- a/source/gameengine/Converter/BL_ActionActuator.cpp +++ b/source/gameengine/Converter/BL_ActionActuator.cpp @@ -184,6 +184,11 @@ bool BL_ActionActuator::Update(double curtime, bool frame) if (bNegativeEvent) { + // dont continue where we left off when restarting + if (m_end_reset) { + m_flag &= ~ACT_FLAG_LOCKINPUT; + } + if (!(m_flag & ACT_FLAG_ACTIVE)) return false; m_flag &= ~ACT_FLAG_ACTIVE; @@ -472,8 +477,10 @@ PyMethodDef BL_ActionActuator::Methods[] = { {"getFrameProperty", (PyCFunction) BL_ActionActuator::sPyGetFrameProperty, METH_VARARGS, GetFrameProperty_doc}, {"setChannel", (PyCFunction) BL_ActionActuator::sPySetChannel, METH_VARARGS, SetChannel_doc}, // {"getChannel", (PyCFunction) BL_ActionActuator::sPyGetChannel, METH_VARARGS}, - {"getType", (PyCFunction) BL_ActionActuator::sPyGetType, METH_VARARGS, GetType_doc}, + {"getType", (PyCFunction) BL_ActionActuator::sPyGetType, METH_VARARGS, GetType_doc}, {"setType", (PyCFunction) BL_ActionActuator::sPySetType, METH_VARARGS, SetType_doc}, + {"getContinue", (PyCFunction) BL_ActionActuator::sPyGetContinue, METH_NOARGS, 0}, + {"setContinue", (PyCFunction) BL_ActionActuator::sPySetContinue, METH_O, 0}, {NULL,NULL} //Sentinel }; @@ -978,7 +985,26 @@ PyObject* BL_ActionActuator::PySetType(PyObject* self, default: printf("Invalid type for action actuator: %d\n", typeArg); /* error */ } - - Py_Return; + Py_RETURN_NONE; +} + +PyObject* BL_ActionActuator::PyGetContinue(PyObject* self) { + return PyInt_FromLong((long)(m_end_reset==0)); +} + +PyObject* BL_ActionActuator::PySetContinue(PyObject* self, PyObject* value) { + int param = PyObject_IsTrue( value ); + + if( param == -1 ) { + PyErr_SetString( PyExc_TypeError, "expected True/False or 0/1" ); + return NULL; + } + + if (param) { + m_end_reset = 0; + } else { + m_end_reset = 1; + } + Py_RETURN_NONE; } diff --git a/source/gameengine/Converter/BL_ActionActuator.h b/source/gameengine/Converter/BL_ActionActuator.h index 190f727c9c3..a67b6d29b74 100644 --- a/source/gameengine/Converter/BL_ActionActuator.h +++ b/source/gameengine/Converter/BL_ActionActuator.h @@ -47,6 +47,7 @@ public: short playtype, short blendin, short priority, + short end_reset, float stride, PyTypeObject* T=&Type) : SCA_IActuator(gameobj,T), @@ -64,6 +65,7 @@ public: m_stridelength(stride), m_playtype(playtype), m_priority(priority), + m_end_reset(end_reset), m_pose(NULL), m_blendpose(NULL), m_userpose(NULL), @@ -101,6 +103,8 @@ public: // KX_PYMETHOD(BL_ActionActuator,GetChannel); KX_PYMETHOD_DOC(BL_ActionActuator,GetType); KX_PYMETHOD_DOC(BL_ActionActuator,SetType); + KX_PYMETHOD_NOARGS(BL_ActionActuator,GetContinue); + KX_PYMETHOD_O(BL_ActionActuator,SetContinue); virtual PyObject* _getattr(const STR_String& attr); @@ -137,6 +141,7 @@ protected: float m_stridelength; short m_playtype; short m_priority; + short m_end_reset; struct bPose* m_pose; struct bPose* m_blendpose; struct bPose* m_userpose; diff --git a/source/gameengine/Converter/KX_ConvertActuators.cpp b/source/gameengine/Converter/KX_ConvertActuators.cpp index 9b1bc1e6b90..1f87e9d9ac7 100644 --- a/source/gameengine/Converter/KX_ConvertActuators.cpp +++ b/source/gameengine/Converter/KX_ConvertActuators.cpp @@ -193,6 +193,7 @@ void BL_ConvertActuators(char* maggiename, actact->type, // + 1, because Blender starts to count at zero, actact->blendin, actact->priority, + actact->end_reset, actact->stridelength // Ketsji at 1, because zero is reserved for "NoDef" ); diff --git a/source/gameengine/PyDoc/BL_ActionActuator.py b/source/gameengine/PyDoc/BL_ActionActuator.py index 41f41080c31..d56888cde80 100644 --- a/source/gameengine/PyDoc/BL_ActionActuator.py +++ b/source/gameengine/PyDoc/BL_ActionActuator.py @@ -86,6 +86,14 @@ class BL_ActionActuator(SCA_IActuator): @param mode: KX_ACTIONACT_PLAY, KX_ACTIONACT_PROPERTY, KX_ACTIONACT_FLIPPER, KX_ACTIONACT_LOOPSTOP, KX_ACTIONACT_LOOPEND @type mode: integer """ + + def setContinue(cont): + """ + Set the actions continue option True or False. see getContinue. + + @param cont: The continue option. + @type cont: bool + """ def getType(): """ @@ -94,6 +102,13 @@ class BL_ActionActuator(SCA_IActuator): @rtype: integer @return: KX_ACTIONACT_PLAY, KX_ACTIONACT_PROPERTY, KX_ACTIONACT_FLIPPER, KX_ACTIONACT_LOOPSTOP, KX_ACTIONACT_LOOPEND """ + + def getContinue(): + """ + When True, the action will always play from where last left off, otherwise negative events to this actuator will reset it to its start frame. + + @rtype: bool + """ def getAction(): """ From 46493c0af5e60f8841eaccb7d79b9537c9252406 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Thu, 10 Jul 2008 15:30:35 +0000 Subject: [PATCH 31/37] Fix for bug #17292: vertex paint blur darkens the colors as you paint, due to old optimization to use >>8, but this is equivalent to /256, and it should be /255. --- source/blender/src/vpaint.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/source/blender/src/vpaint.c b/source/blender/src/vpaint.c index 4e883caba55..935c546a235 100644 --- a/source/blender/src/vpaint.c +++ b/source/blender/src/vpaint.c @@ -566,9 +566,9 @@ static unsigned int mcol_blend(unsigned int col1, unsigned int col2, int fac) cp= (char *)&col; cp[0]= 255; - cp[1]= (mfac*cp1[1]+fac*cp2[1])>>8; - cp[2]= (mfac*cp1[2]+fac*cp2[2])>>8; - cp[3]= (mfac*cp1[3]+fac*cp2[3])>>8; + cp[1]= (mfac*cp1[1]+fac*cp2[1])/255; + cp[2]= (mfac*cp1[2]+fac*cp2[2])/255; + cp[3]= (mfac*cp1[3]+fac*cp2[3])/255; return col; } @@ -586,11 +586,11 @@ static unsigned int mcol_add(unsigned int col1, unsigned int col2, int fac) cp= (char *)&col; cp[0]= 255; - temp= cp1[1] + ((fac*cp2[1])>>8); + temp= cp1[1] + ((fac*cp2[1])/255); if(temp>254) cp[1]= 255; else cp[1]= temp; - temp= cp1[2] + ((fac*cp2[2])>>8); + temp= cp1[2] + ((fac*cp2[2])/255); if(temp>254) cp[2]= 255; else cp[2]= temp; - temp= cp1[3] + ((fac*cp2[3])>>8); + temp= cp1[3] + ((fac*cp2[3])/255); if(temp>254) cp[3]= 255; else cp[3]= temp; return col; @@ -609,11 +609,11 @@ static unsigned int mcol_sub(unsigned int col1, unsigned int col2, int fac) cp= (char *)&col; cp[0]= 255; - temp= cp1[1] - ((fac*cp2[1])>>8); + temp= cp1[1] - ((fac*cp2[1])/255); if(temp<0) cp[1]= 0; else cp[1]= temp; - temp= cp1[2] - ((fac*cp2[2])>>8); + temp= cp1[2] - ((fac*cp2[2])/255); if(temp<0) cp[2]= 0; else cp[2]= temp; - temp= cp1[3] - ((fac*cp2[3])>>8); + temp= cp1[3] - ((fac*cp2[3])/255); if(temp<0) cp[3]= 0; else cp[3]= temp; return col; @@ -635,9 +635,9 @@ static unsigned int mcol_mul(unsigned int col1, unsigned int col2, int fac) /* first mul, then blend the fac */ cp[0]= 255; - cp[1]= (mfac*cp1[1] + fac*((cp2[1]*cp1[1])>>8) )>>8; - cp[2]= (mfac*cp1[2] + fac*((cp2[2]*cp1[2])>>8) )>>8; - cp[3]= (mfac*cp1[3] + fac*((cp2[3]*cp1[3])>>8) )>>8; + cp[1]= (mfac*cp1[1] + fac*((cp2[1]*cp1[1])/255) )/255; + cp[2]= (mfac*cp1[2] + fac*((cp2[2]*cp1[2])/255) )/255; + cp[3]= (mfac*cp1[3] + fac*((cp2[3]*cp1[3])/255) )/255; return col; @@ -664,9 +664,9 @@ static unsigned int mcol_lighten(unsigned int col1, unsigned int col2, int fac) return col1; cp[0]= 255; - cp[1]= (mfac*cp1[1]+fac*cp2[1])>>8; - cp[2]= (mfac*cp1[2]+fac*cp2[2])>>8; - cp[3]= (mfac*cp1[3]+fac*cp2[3])>>8; + cp[1]= (mfac*cp1[1]+fac*cp2[1])/255; + cp[2]= (mfac*cp1[2]+fac*cp2[2])/255; + cp[3]= (mfac*cp1[3]+fac*cp2[3])/255; return col; } @@ -692,9 +692,9 @@ static unsigned int mcol_darken(unsigned int col1, unsigned int col2, int fac) return col1; cp[0]= 255; - cp[1]= (mfac*cp1[1]+fac*cp2[1])>>8; - cp[2]= (mfac*cp1[2]+fac*cp2[2])>>8; - cp[3]= (mfac*cp1[3]+fac*cp2[3])>>8; + cp[1]= (mfac*cp1[1]+fac*cp2[1])/255; + cp[2]= (mfac*cp1[2]+fac*cp2[2])/255; + cp[3]= (mfac*cp1[3]+fac*cp2[3])/255; return col; } From 7971d7c9f308e54066da748d24943b7f65cbb869 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Thu, 10 Jul 2008 16:29:42 +0000 Subject: [PATCH 32/37] Fix for bug #14665: stars not working in 3D view. --- source/blender/render/intern/source/convertblender.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index f9ec0e9d843..faa7a68f754 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -204,6 +204,7 @@ void RE_make_stars(Render *re, void (*initfunc)(void), else stargrid *= 1.0; /* then it draws fewer */ if(re) MTC_Mat4Invert(mat, re->viewmat); + else MTC_Mat4One(mat); /* BOUNDING BOX CALCULATION * bbox goes from z = loc_near_var | loc_far_var, From 8eab9e15d5e4dac5373b8a2c3ed771cf2cf2f933 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Thu, 10 Jul 2008 18:11:36 +0000 Subject: [PATCH 33/37] Fix for bug #14411: missing preview render redraw for a few lamp buttons. --- source/blender/src/buttons_shading.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/blender/src/buttons_shading.c b/source/blender/src/buttons_shading.c index ca6705b2084..1b580381ca5 100644 --- a/source/blender/src/buttons_shading.c +++ b/source/blender/src/buttons_shading.c @@ -2900,15 +2900,15 @@ static void lamp_panel_lamp(Object *ob, Lamp *la) uiBlockSetCol(block, TH_BUT_SETTING1); uiDefButS(block, MENU, B_LAMPREDRAW, "Falloff %t|Constant %x0|Inverse Linear %x1|Inverse Square %x2|Custom Curve %x3|Lin/Quad Weighted %x4|", 10,150,100,19, &la->falloff_type, 0,0,0,0, "Lamp falloff - intensity decay with distance"); - uiDefButBitS(block, TOG, LA_SPHERE, REDRAWVIEW3D,"Sphere", 10,130,100,19,&la->mode, 0, 0, 0, 0, "Sets light intensity to zero for objects beyond the distance value"); + uiDefButBitS(block, TOG, LA_SPHERE, B_LAMPPRV,"Sphere", 10,130,100,19,&la->mode, 0, 0, 0, 0, "Sets light intensity to zero for objects beyond the distance value"); } uiBlockBeginAlign(block); uiBlockSetCol(block, TH_BUT_SETTING1); uiDefButBitS(block, TOG, LA_LAYER, 0,"Layer", 10,70,100,19,&la->mode, 0, 0, 0, 0, "Illuminates objects in the same layer as the lamp only"); uiDefButBitS(block, TOG, LA_NEG, B_LAMPPRV,"Negative", 10,50,100,19,&la->mode, 0, 0, 0, 0, "Sets lamp to cast negative light"); - uiDefButBitS(block, TOG, LA_NO_DIFF, 0,"No Diffuse", 10,30,100,19,&la->mode, 0, 0, 0, 0, "Disables diffuse shading of material illuminated by this lamp"); - uiDefButBitS(block, TOG, LA_NO_SPEC, 0,"No Specular", 10,10,100,19,&la->mode, 0, 0, 0, 0, "Disables specular shading of material illuminated by this lamp"); + uiDefButBitS(block, TOG, LA_NO_DIFF, B_LAMPPRV,"No Diffuse", 10,30,100,19,&la->mode, 0, 0, 0, 0, "Disables diffuse shading of material illuminated by this lamp"); + uiDefButBitS(block, TOG, LA_NO_SPEC, B_LAMPPRV,"No Specular", 10,10,100,19,&la->mode, 0, 0, 0, 0, "Disables specular shading of material illuminated by this lamp"); uiBlockEndAlign(block); uiBlockSetCol(block, TH_AUTO); From 2e144abfbdeed7f6011c47e36d5f8f514b1bcee7 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 11 Jul 2008 00:36:38 +0000 Subject: [PATCH 34/37] Bugfix #17306: Missing refresh call for button in UserPrefs Autokey settings were missing redraw for Info-window --- source/blender/src/space.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/source/blender/src/space.c b/source/blender/src/space.c index fe9bb3279cc..3b8bb4c3929 100644 --- a/source/blender/src/space.c +++ b/source/blender/src/space.c @@ -4440,7 +4440,10 @@ static void winqreadinfospace(ScrArea *sa, void *spacedata, BWinEvent *evt) switch(event) { case UI_BUT_EVENT: - if(val==REDRAWTIME) allqueue(REDRAWTIME, 0); + if(val==REDRAWTIME) { + allqueue(REDRAWTIME, 0); + addqueue(sa->win, REDRAW, 1); + } else if(val==B_ADD_THEME) { bTheme *btheme, *new; From 3fce5ba59ad7ce7033ecf135e45ce768b7f81026 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Fri, 11 Jul 2008 14:11:55 +0000 Subject: [PATCH 35/37] Memory leak fix: br_find_exe() uses strdup() which uses malloc and therefore the returned string needs free'ing (Found with valgrind). --- source/blender/blenlib/intern/util.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source/blender/blenlib/intern/util.c b/source/blender/blenlib/intern/util.c index 5a85fbfc375..48ebf770e1b 100644 --- a/source/blender/blenlib/intern/util.c +++ b/source/blender/blenlib/intern/util.c @@ -1722,6 +1722,7 @@ void BLI_where_am_i(char *fullname, const char *name) path = br_find_exe( NULL ); if (path) { strcpy(fullname, path); + free(path); return; } #endif From efb2639a26d2dbbc11e2edc3b17c34646eade902 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Fri, 11 Jul 2008 17:08:45 +0000 Subject: [PATCH 36/37] Memory leak fix (found with Valgrind) --- source/blender/blenlib/intern/storage.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source/blender/blenlib/intern/storage.c b/source/blender/blenlib/intern/storage.c index ca7a376d3a2..fbcc56ac21d 100644 --- a/source/blender/blenlib/intern/storage.c +++ b/source/blender/blenlib/intern/storage.c @@ -382,6 +382,7 @@ void BLI_adddirstrings() pwuser = getpwuid(files[num].s.st_uid); if ( pwuser ) { strcpy(files[num].owner, pwuser->pw_name); + free(pwuser); } else { sprintf(files[num].owner, "%d", files[num].s.st_uid); } From 1ffdc6679171c40ac1b2e5852ceaaa1495fbcd17 Mon Sep 17 00:00:00 2001 From: Janne Karhu Date: Fri, 11 Jul 2008 23:47:44 +0000 Subject: [PATCH 37/37] Fix for bug [#13479] Particle system "corrupts" when changing material colour and used in conjunction with softbodies - changing particlesystem settings for hair particles cleared & recalculated everything even when hair softbody was baked --- source/blender/blenkernel/intern/pointcache.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index 57ecffbb796..43805959e62 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -459,9 +459,10 @@ int BKE_ptcache_object_reset(Object *ob, int mode) PTCacheID pid; ParticleSystem *psys; ModifierData *md; - int reset; + int reset, skip; reset= 0; + skip= 0; if(ob->soft) { BKE_ptcache_id_from_softbody(&pid, ob, ob->soft); @@ -469,11 +470,18 @@ int BKE_ptcache_object_reset(Object *ob, int mode) } for(psys=ob->particlesystem.first; psys; psys=psys->next) { - BKE_ptcache_id_from_particles(&pid, ob, psys); - reset |= BKE_ptcache_id_reset(&pid, mode); - + /* Baked softbody hair has to be checked first, because we don't want to reset */ + /* particles or softbody in that case -jahka */ 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); + else + skip = 1; + } + + if(skip == 0) { + BKE_ptcache_id_from_particles(&pid, ob, psys); reset |= BKE_ptcache_id_reset(&pid, mode); } }