diff options
37 files changed, 382 insertions, 151 deletions
diff --git a/source/blender/blenkernel/BKE_idprop.h b/source/blender/blenkernel/BKE_idprop.h index 2d7d0e9286f..2274c54ad3b 100644 --- a/source/blender/blenkernel/BKE_idprop.h +++ b/source/blender/blenkernel/BKE_idprop.h @@ -46,6 +46,7 @@ struct ID; typedef union { int i; float f; + double d; char *str; struct ID *id; struct { diff --git a/source/blender/blenkernel/bad_level_call_stubs/stubs.c b/source/blender/blenkernel/bad_level_call_stubs/stubs.c index 856816e619e..dd079f69a0b 100644 --- a/source/blender/blenkernel/bad_level_call_stubs/stubs.c +++ b/source/blender/blenkernel/bad_level_call_stubs/stubs.c @@ -1,4 +1,3 @@ - /** * $Id$ * @@ -352,6 +351,8 @@ TimeMarker *get_frame_marker(int frame){return 0;}; /* editseq.c */ Sequence *get_forground_frame_seq(int frame){return 0;}; void set_last_seq(Sequence *seq){}; +void clear_last_seq(Sequence *seq){}; + /* modifier.c stub */ void harmonic_coordinates_bind(struct MeshDeformModifierData *mmd, diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 068501780bc..f13fd5f9963 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -558,8 +558,8 @@ static void contarget_get_mesh_mat (Object *ob, char *substring, float mat[][4]) if (dgroup < 0) return; /* get DerivedMesh */ - if (G.obedit && G.editMesh) { - /* we are in editmode, so get a special derived mesh */ + if ((G.obedit == ob) && (G.editMesh)) { + /* target is in editmode, so get a special derived mesh */ dm = CDDM_from_editmesh(G.editMesh, ob->data); } else { diff --git a/source/blender/blenkernel/intern/idprop.c b/source/blender/blenkernel/intern/idprop.c index 2ef2f3a1b77..b16f52571f6 100644 --- a/source/blender/blenkernel/intern/idprop.c +++ b/source/blender/blenkernel/intern/idprop.c @@ -54,7 +54,8 @@ static char idp_size_table[] = { sizeof(float)*16, /*Matrix type, deprecated*/ 0, /*arrays don't have a fixed size*/ sizeof(ListBase), /*Group type*/ - sizeof(void*) + sizeof(void*), + sizeof(double) }; @@ -365,10 +366,14 @@ IDProperty *IDP_New(int type, IDPropertyTemplate val, char *name) prop = MEM_callocN(sizeof(IDProperty), "IDProperty float"); *(float*)&prop->data.val = val.f; break; + case IDP_DOUBLE: + prop = MEM_callocN(sizeof(IDProperty), "IDProperty float"); + *(double*)&prop->data.val = val.d; + break; case IDP_ARRAY: { - /*for now, we only support float and int arrays*/ - if (val.array.type == IDP_FLOAT || val.array.type == IDP_INT) { + /*for now, we only support float and int and double arrays*/ + if (val.array.type == IDP_FLOAT || val.array.type == IDP_INT || val.array.type == IDP_DOUBLE) { prop = MEM_callocN(sizeof(IDProperty), "IDProperty array"); prop->len = prop->totallen = val.array.len; prop->subtype = val.array.type; @@ -411,6 +416,10 @@ IDProperty *IDP_New(int type, IDPropertyTemplate val, char *name) prop->type = type; strncpy(prop->name, name, MAX_IDPROP_NAME); + + /*security null byte*/ + prop->name[MAX_IDPROP_NAME-1] = 0; + return prop; } diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c index 9005db1312f..d5b5ab6d63e 100644 --- a/source/blender/blenkernel/intern/softbody.c +++ b/source/blender/blenkernel/intern/softbody.c @@ -2053,7 +2053,6 @@ static void softbody_calc_forces(Object *ob, float forcetime, float timenow, int /* check conditions for various options */ do_deflector= query_external_colliders(ob); - do_effector= pdInitEffectors(ob,NULL); do_selfcollision=((ob->softflag & OB_SB_EDGES) && (sb->bspring)&& (ob->softflag & OB_SB_SELF)); do_springcollision=do_deflector && (ob->softflag & OB_SB_EDGES) &&(ob->softflag & OB_SB_EDGECOLL); do_aero=((sb->aeroedge)&& (ob->softflag & OB_SB_EDGES)); @@ -2061,9 +2060,10 @@ static void softbody_calc_forces(Object *ob, float forcetime, float timenow, int iks = 1.0f/(1.0f-sb->inspring)-1.0f ;/* inner spring constants function */ bproot= sb->bpoint; /* need this for proper spring addressing */ - - if (do_springcollision || do_aero) scan_for_ext_spring_forces(ob,timenow); + /* after spring scan because it uses Effoctors too */ + do_effector= pdInitEffectors(ob,NULL); + if (do_deflector) { float defforce[3]; do_deflector = sb_detect_aabb_collisionCached(defforce,ob->lay,ob,timenow); diff --git a/source/blender/blenlib/intern/arithb.c b/source/blender/blenlib/intern/arithb.c index 486ff623b5a..108f24bef49 100644 --- a/source/blender/blenlib/intern/arithb.c +++ b/source/blender/blenlib/intern/arithb.c @@ -2544,11 +2544,6 @@ int IsectPQ2Df(float pt[2], float v1[2], float v2[2], float v3[2], float v4[2]) } - - /* copied from Geometry.c - todo - move to arithb.c or some other generic place we can reuse */ -#define SIDE_OF_LINE(pa,pb,pp) ((pa[0]-pp[0])*(pb[1]-pp[1]))-((pb[0]-pp[0])*(pa[1]-pp[1])) -#define POINT_IN_TRI(p0,p1,p2,p3) ((SIDE_OF_LINE(p1,p2,p0)>=0) && (SIDE_OF_LINE(p2,p3,p0)>=0) && (SIDE_OF_LINE(p3,p1,p0)>=0)) - /** * * @param min diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 2a72f27dbc1..d42e381fff7 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -1356,8 +1356,14 @@ void IDP_DirectLinkArray(IDProperty *prop, int switch_endian, void *fd) prop->data.pointer = newdataadr(fd, prop->data.pointer); if (switch_endian) { - for (i=0; i<prop->len; i++) { - SWITCH_INT(((int*)prop->data.pointer)[i]); + if (prop->subtype != IDP_DOUBLE) { + for (i=0; i<prop->len; i++) { + SWITCH_INT(((int*)prop->data.pointer)[i]); + } + } else { + for (i=0; i<prop->len; i++) { + SWITCH_LONGINT(((double*)prop->data.pointer)[i]); + } } } } @@ -1394,6 +1400,24 @@ void IDP_DirectLinkProperty(IDProperty *prop, int switch_endian, void *fd) case IDP_ARRAY: IDP_DirectLinkArray(prop, switch_endian, fd); break; + case IDP_DOUBLE: + /*erg, stupid doubles. since I'm storing them + in the same field as int val; val2 in the + IDPropertyData struct, they have to deal with + endianness specifically + + in theory, val and val2 would've already been swapped + if switch_endian is true, so we have to first unswap + them then reswap them as a single 64-bit entity. + */ + + if (switch_endian) { + SWITCH_INT(prop->data.val); + SWITCH_INT(prop->data.val2); + SWITCH_LONGINT(prop->data.val); + } + + break; } } diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 34dfa15e875..02cc5cab6d5 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -533,6 +533,7 @@ static void write_particlesettings(WriteData *wd, ListBase *idbase) if(part->id.us>0 || wd->current) { /* write LibData */ writestruct(wd, ID_PA, "ParticleSettings", 1, part); + if (part->id.properties) IDP_WriteProperty(part->id.properties, wd); writestruct(wd, DATA, "PartDeflect", 1, part->pd); } part= part->id.next; diff --git a/source/blender/include/BDR_gpencil.h b/source/blender/include/BDR_gpencil.h index 8f3d6b92963..d2fc7be29ea 100644 --- a/source/blender/include/BDR_gpencil.h +++ b/source/blender/include/BDR_gpencil.h @@ -69,6 +69,6 @@ void gpencil_delete_operation(short mode); void gpencil_delete_menu(void); //short gpencil_paint(short mousebutton); -short gpencil_do_paint(struct ScrArea *sa); +short gpencil_do_paint(struct ScrArea *sa, short mousebutton); #endif /* BDR_GPENCIL_H */ diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h index 22649abefa2..784335c1144 100644 --- a/source/blender/makesdna/DNA_ID.h +++ b/source/blender/makesdna/DNA_ID.h @@ -46,7 +46,7 @@ struct ID; typedef struct IDPropertyData { void *pointer; ListBase group; - int val, pad; + int val, val2; /*note, we actually fit a double into these two ints*/ } IDPropertyData; typedef struct IDProperty { @@ -77,6 +77,7 @@ typedef struct IDProperty { /*the ID link property type hasn't been implemented yet, this will require some cleanup of blenkernel, most likely.*/ #define IDP_ID 7 +#define IDP_DOUBLE 8 /*add any future new id property types here.*/ diff --git a/source/blender/makesdna/DNA_gpencil_types.h b/source/blender/makesdna/DNA_gpencil_types.h index 2ac5faab066..b88dd698c3f 100644 --- a/source/blender/makesdna/DNA_gpencil_types.h +++ b/source/blender/makesdna/DNA_gpencil_types.h @@ -59,6 +59,8 @@ typedef struct bGPDstroke { #define GP_STROKE_3DSPACE (1<<0) /* stroke is in 2d-space */ #define GP_STROKE_2DSPACE (1<<1) + /* stroke is an "eraser" stroke */ +#define GP_STROKE_ERASER (1<<2) /* Grease-Pencil Annotations - 'Frame' @@ -127,12 +129,12 @@ typedef struct bGPdata { } bGPdata; /* bGPdata->flag */ - /* draw this datablock's data (not used) */ -#define GP_DATA_DISP (1<<0) + /* don't allow painting to occur at all */ +#define GP_DATA_LMBPLOCK (1<<0) /* show debugging info in viewport (i.e. status print) */ #define GP_DATA_DISPINFO (1<<1) /* in Action Editor, show as expanded channel */ -#define GP_DATA_EXPAND (1<<2) +#define GP_DATA_EXPAND (1<<2) /* is the block overriding all clicks? */ #define GP_DATA_EDITPAINT (1<<3) /* new strokes are added in viewport space */ diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_material.c b/source/blender/nodes/intern/SHD_nodes/SHD_material.c index 6773baff98f..c0a2534ac4a 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_material.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_material.c @@ -54,7 +54,6 @@ static bNodeSocketType sh_node_material_ext_in[]= { { SOCK_VALUE, 1, "Refl", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, { SOCK_VECTOR, 1, "Normal", 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f}, { SOCK_RGBA, 1, "Mirror", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 1, "AmbCol", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, { SOCK_VALUE, 1, "Ambient", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, { SOCK_VALUE, 1, "Emit", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, { SOCK_VALUE, 1, "SpecTra", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, @@ -117,8 +116,6 @@ static void node_shader_exec_material(void *data, bNode *node, bNodeStack **in, if (node->type == SH_NODE_MATERIAL_EXT) { if(in[MAT_IN_MIR]->hasinput) nodestack_get_vec(&shi->mirr, SOCK_VECTOR, in[MAT_IN_MIR]); - if(in[MAT_IN_AMBCOL]->hasinput) - nodestack_get_vec(&shi->ambr, SOCK_VECTOR, in[MAT_IN_AMBCOL]); if(in[MAT_IN_AMB]->hasinput) nodestack_get_vec(&shi->amb, SOCK_VALUE, in[MAT_IN_AMB]); if(in[MAT_IN_EMIT]->hasinput) diff --git a/source/blender/nodes/intern/SHD_util.c b/source/blender/nodes/intern/SHD_util.c index c9f58fbce49..f673834d2b7 100644 --- a/source/blender/nodes/intern/SHD_util.c +++ b/source/blender/nodes/intern/SHD_util.c @@ -164,7 +164,7 @@ void nodeShaderSynchronizeID(bNode *node, int copyto) case MAT_IN_MIR: VECCOPY(&ma->mirr, sock->ns.vec); break; case MAT_IN_AMB: - VECCOPY(&ma->ambr, sock->ns.vec); break; + ma->amb= sock->ns.vec[0]; break; case MAT_IN_EMIT: ma->emit= sock->ns.vec[0]; break; case MAT_IN_SPECTRA: @@ -188,7 +188,7 @@ void nodeShaderSynchronizeID(bNode *node, int copyto) case MAT_IN_MIR: VECCOPY(sock->ns.vec, &ma->mirr); break; case MAT_IN_AMB: - VECCOPY(sock->ns.vec, &ma->ambr); break; + sock->ns.vec[0]= ma->amb; break; case MAT_IN_EMIT: sock->ns.vec[0]= ma->emit; break; case MAT_IN_SPECTRA: diff --git a/source/blender/nodes/intern/SHD_util.h b/source/blender/nodes/intern/SHD_util.h index 3044d72e3ac..eda985529c1 100644 --- a/source/blender/nodes/intern/SHD_util.h +++ b/source/blender/nodes/intern/SHD_util.h @@ -119,13 +119,12 @@ typedef struct ShaderCallData { #define MAT_IN_REFL 2 #define MAT_IN_NORMAL 3 #define MAT_IN_MIR 4 -#define MAT_IN_AMBCOL 5 -#define MAT_IN_AMB 6 -#define MAT_IN_EMIT 7 -#define MAT_IN_SPECTRA 8 -#define MAT_IN_RAY_MIRROR 9 -#define MAT_IN_ALPHA 10 -#define MAT_IN_TRANSLUCENCY 11 +#define MAT_IN_AMB 5 +#define MAT_IN_EMIT 6 +#define MAT_IN_SPECTRA 7 +#define MAT_IN_RAY_MIRROR 8 +#define MAT_IN_ALPHA 9 +#define MAT_IN_TRANSLUCENCY 10 /* output socket defines */ #define MAT_OUT_COLOR 0 diff --git a/source/blender/python/BPY_interface.c b/source/blender/python/BPY_interface.c index e94bb335912..5c2ffa7e615 100644 --- a/source/blender/python/BPY_interface.c +++ b/source/blender/python/BPY_interface.c @@ -410,12 +410,14 @@ void BPY_rebuild_syspath( void ) mod = PyImport_ImportModule( "sys" ); if (!mod) { printf("error: could not import python sys module. some modules may not import.\n"); + PyGILState_Release(gilstate); return; } if (!bpy_orig_syspath_List) { /* should never happen */ printf("error refershing python path\n"); Py_DECREF(mod); + PyGILState_Release(gilstate); return; } diff --git a/source/blender/python/api2_2x/IDProp.c b/source/blender/python/api2_2x/IDProp.c index f60ebf8dee1..4a51619aec4 100644 --- a/source/blender/python/api2_2x/IDProp.c +++ b/source/blender/python/api2_2x/IDProp.c @@ -60,6 +60,8 @@ PyObject *BPy_IDGroup_WrapData( ID *id, IDProperty *prop ) return PyInt_FromLong( (long)prop->data.val ); case IDP_FLOAT: return PyFloat_FromDouble( (double)(*(float*)(&prop->data.val)) ); + case IDP_DOUBLE: + return PyFloat_FromDouble( (*(double*)(&prop->data.val)) ); case IDP_GROUP: /*blegh*/ { @@ -128,7 +130,19 @@ int BPy_IDGroup_SetData(BPy_IDProperty *self, IDProperty *prop, PyObject *value) Py_XDECREF(value); break; } - + case IDP_DOUBLE: + { + double dvalue; + if (!PyNumber_Check(value)) + return EXPP_ReturnIntError(PyExc_TypeError, "expected a float!"); + value = PyNumber_Float(value); + if (!value) + return EXPP_ReturnIntError(PyExc_TypeError, "expected a float!"); + dvalue = (float) PyFloat_AsDouble(value); + *(double*)&self->prop->data.val = dvalue; + Py_XDECREF(value); + break; + } default: return EXPP_ReturnIntError(PyExc_AttributeError, "attempt to set read-only attribute!"); } @@ -204,8 +218,8 @@ char *BPy_IDProperty_Map_ValidateAndCreate(char *name, IDProperty *group, PyObje IDPropertyTemplate val = {0}; if (PyFloat_Check(ob)) { - val.f = (float) PyFloat_AsDouble(ob); - prop = IDP_New(IDP_FLOAT, val, name); + val.d = PyFloat_AsDouble(ob); + prop = IDP_New(IDP_DOUBLE, val, name); } else if (PyInt_Check(ob)) { val.i = (int) PyInt_AsLong(ob); prop = IDP_New(IDP_INT, val, name); @@ -223,7 +237,7 @@ char *BPy_IDProperty_Map_ValidateAndCreate(char *name, IDProperty *group, PyObje val.array.len = PySequence_Length(ob); for (i=0; i<val.array.len; i++) { item = PySequence_GetItem(ob, i); - if (PyFloat_Check(item)) val.array.type = IDP_FLOAT; + if (PyFloat_Check(item)) val.array.type = IDP_DOUBLE; else if (!PyInt_Check(item)) return "only floats and ints are allowed in ID property arrays"; Py_XDECREF(item); } @@ -236,7 +250,7 @@ char *BPy_IDProperty_Map_ValidateAndCreate(char *name, IDProperty *group, PyObje ((int*)prop->data.pointer)[i] = (int)PyInt_AsLong(item); } else { item = PyNumber_Float(item); - ((float*)prop->data.pointer)[i] = (float)PyFloat_AsDouble(item); + ((double*)prop->data.pointer)[i] = (float)PyFloat_AsDouble(item); } Py_XDECREF(item); } @@ -334,6 +348,9 @@ PyObject *BPy_IDGroup_MapDataToPy(IDProperty *prop) case IDP_FLOAT: return PyFloat_FromDouble(*((float*)&prop->data.val)); break; + case IDP_DOUBLE: + return PyFloat_FromDouble(*((double*)&prop->data.val)); + break; case IDP_INT: return PyInt_FromLong( (long)prop->data.val ); break; @@ -347,12 +364,15 @@ PyObject *BPy_IDGroup_MapDataToPy(IDProperty *prop) "PyList_New() failed" ); for (i=0; i<prop->len; i++) { - if (prop->subtype == IDP_FLOAT) + if (prop->subtype == IDP_FLOAT) { PyList_SetItem(seq, i, PyFloat_FromDouble(((float*)prop->data.pointer)[i])); - - else PyList_SetItem(seq, i, - PyInt_FromLong(((int*)prop->data.pointer)[i])); + } else if (prop->subtype == IDP_DOUBLE) { + PyList_SetItem(seq, i, + PyFloat_FromDouble(((double*)prop->data.pointer)[i])); + } else { PyList_SetItem(seq, i, + PyInt_FromLong(((int*)prop->data.pointer)[i])); + } } return seq; } @@ -451,7 +471,7 @@ PyObject *BPy_IDGroup_GetKeys(BPy_IDProperty *self) /*set correct group length*/ self->prop->len = i; - /*free the old list*/ + /*free the list*/ Py_DECREF(seq); /*call self again*/ @@ -688,6 +708,9 @@ PyObject *BPy_IDArray_GetItem(BPy_IDArray *self, int index) case IDP_FLOAT: return PyFloat_FromDouble( (double)(((float*)self->prop->data.pointer)[index])); break; + case IDP_DOUBLE: + return PyFloat_FromDouble( (((double*)self->prop->data.pointer)[index])); + break; case IDP_INT: return PyInt_FromLong( (long)((int*)self->prop->data.pointer)[index] ); break; @@ -700,7 +723,8 @@ int BPy_IDArray_SetItem(BPy_IDArray *self, int index, PyObject *val) { int i; float f; - + double d; + if (index < 0 || index >= self->prop->len) return EXPP_ReturnIntError( PyExc_RuntimeError, "index out of range!"); @@ -717,6 +741,17 @@ int BPy_IDArray_SetItem(BPy_IDArray *self, int index, PyObject *val) ((float*)self->prop->data.pointer)[index] = f; Py_XDECREF(val); break; + case IDP_DOUBLE: + if (!PyNumber_Check(val)) return EXPP_ReturnIntError( PyExc_TypeError, + "expected a float"); + val = PyNumber_Float(val); + if (!val) return EXPP_ReturnIntError( PyExc_TypeError, + "expected a float"); + + d = (double) PyFloat_AsDouble(val); + ((double*)self->prop->data.pointer)[index] = d; + Py_XDECREF(val); + break; case IDP_INT: if (!PyNumber_Check(val)) return EXPP_ReturnIntError( PyExc_TypeError, "expected an int"); diff --git a/source/blender/python/api2_2x/doc/IDProp.py b/source/blender/python/api2_2x/doc/IDProp.py index 0a0df335fa3..01d5136cd70 100644 --- a/source/blender/python/api2_2x/doc/IDProp.py +++ b/source/blender/python/api2_2x/doc/IDProp.py @@ -18,7 +18,9 @@ class IDGroup: Note that for arrays, the array type defaults to int unless a float is found while scanning the template list; if any floats are found, then the whole - array is float. + array is float. Note that double-precision floating point numbers are used for + python-created float ID properties and arrays (though the internal C api does + support single-precision floats, and the python code will read them). You can also delete properties with the del operator. For example: diff --git a/source/blender/python/api2_2x/sceneRender.c b/source/blender/python/api2_2x/sceneRender.c index d382d450970..8f251fc8452 100644 --- a/source/blender/python/api2_2x/sceneRender.c +++ b/source/blender/python/api2_2x/sceneRender.c @@ -565,6 +565,8 @@ PyObject *RenderData_SaveRenderedImage ( BPy_RenderData * self, PyObject *args ) PyObject *RenderData_RenderAnim( BPy_RenderData * self ) { Scene *oldsce; + /* this prevents a deadlock when there are pynodes: */ + PyThreadState *tstate = PyEval_SaveThread(); if (!G.background) { oldsce = G.scene; @@ -582,9 +584,9 @@ PyObject *RenderData_RenderAnim( BPy_RenderData * self ) if (G.scene->r.sfra > G.scene->r.efra) return EXPP_ReturnPyObjError (PyExc_RuntimeError, "start frame must be less or equal to end frame"); - RE_BlenderAnim(re, G.scene, G.scene->r.sfra, G.scene->r.efra); } + PyEval_RestoreThread(tstate); Py_RETURN_NONE; } diff --git a/source/blender/src/drawaction.c b/source/blender/src/drawaction.c index fc629b7c1b0..0782ccfc7ee 100644 --- a/source/blender/src/drawaction.c +++ b/source/blender/src/drawaction.c @@ -646,7 +646,7 @@ static void draw_channel_names(void) case SPACE_VIEW3D: { /* this shouldn't cause any overflow... */ - sprintf(name, "3D-View: <%s>", view3d_get_name(sa->spacedata.first)); + sprintf(name, "3DView: %s", view3d_get_name(sa->spacedata.first)); special= ICON_VIEW3D; } break; @@ -684,8 +684,10 @@ static void draw_channel_names(void) break; default: - sprintf(name, "GP-Data"); + { + sprintf(name, "<Unknown GP-Data Source>"); special= -1; + } break; } } @@ -775,13 +777,19 @@ static void draw_channel_names(void) offset += 17; } - /* draw special icon indicating type of ipo-blocktype? - * only for expand widgets for Ipo and Constraint Channels - */ - if (special > 0) { - offset = (group) ? 29 : 24; - BIF_icon_draw(x+offset, yminc, special); - offset += 17; + /* draw special icon indicating certain data-types */ + if (special > -1) { + if (group == 3) { + /* for gpdatablock channels */ + BIF_icon_draw(x+offset, yminc, special); + offset += 17; + } + else { + /* for ipo/constraint channels */ + offset = (group) ? 29 : 24; + BIF_icon_draw(x+offset, yminc, special); + offset += 17; + } } /* draw name */ @@ -797,13 +805,13 @@ static void draw_channel_names(void) offset = 0; /* draw protect 'lock' */ - if (protect > 0) { + if (protect > -1) { offset = 16; BIF_icon_draw(NAMEWIDTH-offset, yminc, protect); } /* draw mute 'eye' */ - if (mute > 0) { + if (mute > -1) { offset += 16; BIF_icon_draw(NAMEWIDTH-offset, yminc, mute); } diff --git a/source/blender/src/drawgpencil.c b/source/blender/src/drawgpencil.c index 2e1586c369b..aacae08d972 100644 --- a/source/blender/src/drawgpencil.c +++ b/source/blender/src/drawgpencil.c @@ -94,7 +94,7 @@ void gp_ui_activelayer_cb (void *gpd, void *gpl) { gpencil_layer_setactive(gpd, gpl); - force_draw_plus(SPACE_ACTION, 0); + allqueue(REDRAWACTION, 0); } /* rename layer and set active */ @@ -105,21 +105,21 @@ void gp_ui_renamelayer_cb (void *gpd_arg, void *gpl_arg) BLI_uniquename(&gpd->layers, gpl, "GP_Layer", offsetof(bGPDlayer, info[0]), 128); gpencil_layer_setactive(gpd, gpl); - force_draw_plus(SPACE_ACTION, 0); + allqueue(REDRAWACTION, 0); } /* add a new layer */ void gp_ui_addlayer_cb (void *gpd, void *dummy) { gpencil_layer_addnew(gpd); - force_draw_plus(SPACE_ACTION, 0); + allqueue(REDRAWACTION, 0); } /* delete active layer */ void gp_ui_dellayer_cb (void *gpd, void *dummy) { gpencil_layer_delactive(gpd); - force_draw_plus(SPACE_ACTION, 0); + allqueue(REDRAWACTION, 0); } /* delete last stroke of active layer */ @@ -139,7 +139,7 @@ void gp_ui_delframe_cb (void *gpd, void *gpl) gpencil_layer_setactive(gpd, gpl); gpencil_layer_delframe(gpl, gpf); - force_draw_plus(SPACE_ACTION, 0); + allqueue(REDRAWACTION, 0); } /* ------- Drawing Code ------- */ @@ -148,6 +148,7 @@ void gp_ui_delframe_cb (void *gpd, void *gpl) static void gp_drawui_layer (uiBlock *block, bGPdata *gpd, bGPDlayer *gpl, short *xco, short *yco) { uiBut *but; + short active= (gpl->flag & GP_LAYER_ACTIVE); short width= 314; short height; int rb_col; @@ -160,10 +161,10 @@ static void gp_drawui_layer (uiBlock *block, bGPdata *gpd, bGPDlayer *gpl, short uiBlockSetEmboss(block, UI_EMBOSSN); /* rounded header */ - //uiBlockSetCol(block, TH_BUT_SETTING1); // FIXME: maybe another color - rb_col= (gpl->flag & GP_LAYER_ACTIVE)?50:20; + if (active) uiBlockSetCol(block, TH_BUT_ACTION); + rb_col= (active)?-20:20; uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-8, *yco-2, width, 24, NULL, 5.0, 0.0, 15 , rb_col-20, ""); - //uiBlockSetCol(block, TH_AUTO); + if (active) uiBlockSetCol(block, TH_AUTO); /* lock toggle */ uiDefIconButBitI(block, ICONTOG, GP_LAYER_LOCKED, B_REDR, ICON_UNLOCKED, *xco-7, *yco-1, 20, 20, &gpl->flag, 0.0, 0.0, 0, 0, "Layer cannot be modified"); @@ -212,9 +213,9 @@ static void gp_drawui_layer (uiBlock *block, bGPdata *gpd, bGPDlayer *gpl, short } /* draw backdrop */ - //uiBlockSetCol(block, TH_BUT_SETTING1); // fixme: maybe another color + if (active) uiBlockSetCol(block, TH_BUT_ACTION); uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-8, *yco-height, width, height-1, NULL, 5.0, 0.0, 12, rb_col, ""); - //uiBlockSetCol(block, TH_AUTO); + if (active) uiBlockSetCol(block, TH_AUTO); /* draw settings */ { @@ -235,11 +236,13 @@ static void gp_drawui_layer (uiBlock *block, bGPdata *gpd, bGPDlayer *gpl, short uiBlockEndAlign(block); /* options */ - but= uiDefBut(block, BUT, B_REDR, "Del Active Frame", *xco+160, *yco-75, 140, 20, NULL, 0, 0, 0, 0, "Erases the the active frame for this layer"); - uiButSetFunc(but, gp_ui_delframe_cb, gpd, gpl); - - but= uiDefBut(block, BUT, B_REDR, "Del Last Stroke", *xco+160, *yco-95, 140, 20, NULL, 0, 0, 0, 0, "Erases the last stroke from the active frame"); - uiButSetFunc(but, gp_ui_delstroke_cb, gpd, gpl); + uiBlockBeginAlign(block); + but= uiDefBut(block, BUT, B_REDR, "Del Active Frame", *xco+160, *yco-75, 140, 20, NULL, 0, 0, 0, 0, "Erases the the active frame for this layer (Hotkey = Alt-XKEY/DEL)"); + uiButSetFunc(but, gp_ui_delframe_cb, gpd, gpl); + + but= uiDefBut(block, BUT, B_REDR, "Del Last Stroke", *xco+160, *yco-95, 140, 20, NULL, 0, 0, 0, 0, "Erases the last stroke from the active frame (Hotkey = Alt-XKEY/DEL)"); + uiButSetFunc(but, gp_ui_delstroke_cb, gpd, gpl); + uiBlockEndAlign(block); //uiDefButBitI(block, TOG, GP_LAYER_DRAWDEBUG, B_REDR, "Show Points", *xco+160, *yco-75, 130, 20, &gpl->flag, 0, 0, 0, 0, "Show points which form the strokes"); } @@ -268,8 +271,14 @@ short draw_gpencil_panel (uiBlock *block, bGPdata *gpd, ScrArea *sa) uiButSetFunc(but, gp_ui_addlayer_cb, gpd, NULL); - /* show override lmb-clicks button */ - uiDefButBitI(block, TOG, GP_DATA_EDITPAINT, B_REDR, "Draw Mode", 170, 225, 150, 20, &gpd->flag, 0, 0, 0, 0, "Interpret LMB-click as new strokes (same as holding Shift-Key per stroke)"); + /* show override lmb-clicks button + painting lock */ + uiBlockBeginAlign(block); + uiDefButBitI(block, TOG, GP_DATA_EDITPAINT, B_REDR, "Draw Mode", 170, 225, 130, 20, &gpd->flag, 0, 0, 0, 0, "Interpret LMB-click as new strokes (same as holding Shift-Key per stroke)"); + + uiBlockSetCol(block, TH_BUT_SETTING); + uiDefIconButBitI(block, ICONTOG, GP_DATA_LMBPLOCK, B_REDR, ICON_UNLOCKED, 300, 225, 20, 20, &gpd->flag, 0.0, 0.0, 0, 0, "Painting cannot occur with Shift-LMB (when making selections)"); + uiBlockSetCol(block, TH_AUTO); + uiBlockEndAlign(block); /* 'view align' button (naming depends on context) */ if (sa->spacetype == SPACE_VIEW3D) @@ -406,6 +415,45 @@ static void gp_draw_stroke (bGPDspoint *points, int totpoints, short thickness, } } +/* draw a set of strokes */ +static void gp_draw_strokes (bGPDframe *gpf, int winx, int winy, int dflag, short debug, + short lthick, float color[4]) +{ + bGPDstroke *gps; + + /* set color first (may need to reset it again later too) */ + glColor4f(color[0], color[1], color[2], color[3]); + + for (gps= gpf->strokes.first; gps; gps= gps->next) { + /* handle 'eraser' strokes differently */ + if (gps->flag & GP_STROKE_ERASER) { + // FIXME: this method is a failed experiment +#if 0 + /* draw stroke twice, first time with 'white' to set a mask to invert + * contents of framebuffer, then second-time the same again but to restore + * the contents + */ + glEnable(GL_COLOR_LOGIC_OP); + glLogicOp(GL_XOR); + + glColor4f(1, 1, 1, 1); /* white */ + + gp_draw_stroke(gps->points, gps->totpoints, lthick, dflag, gps->flag, 0, winx, winy); + gp_draw_stroke(gps->points, gps->totpoints, lthick, dflag, gps->flag, 0, winx, winy); + + glDisable(GL_COLOR_LOGIC_OP); + + /* reset color for drawing next stroke */ + glColor4f(color[0], color[1], color[2], color[3]); +#endif + } + else { + /* just draw the stroke once */ + gp_draw_stroke(gps->points, gps->totpoints, lthick, dflag, gps->flag, debug, winx, winy); + } + } +} + /* draw grease-pencil datablock */ static void gp_draw_data (bGPdata *gpd, int winx, int winy, int dflag) { @@ -421,11 +469,10 @@ static void gp_draw_data (bGPdata *gpd, int winx, int winy, int dflag) /* loop over layers, drawing them */ for (gpl= gpd->layers.first; gpl; gpl= gpl->next) { bGPDframe *gpf; - bGPDstroke *gps; short debug = (gpl->flag & GP_LAYER_DRAWDEBUG) ? 1 : 0; short lthick= gpl->thickness; - float color[4]; + float color[4], tcolor[4]; /* don't draw layer if hidden */ if (gpl->flag & GP_LAYER_HIDE) @@ -443,6 +490,7 @@ static void gp_draw_data (bGPdata *gpd, int winx, int winy, int dflag) /* set color, stroke thickness, and point size */ glLineWidth(lthick); QUATCOPY(color, gpl->color); // just for copying 4 array elements + QUATCOPY(tcolor, gpl->color); // additional copy of color (for ghosting) glColor4f(color[0], color[1], color[2], color[3]); glPointSize(gpl->thickness + 2); @@ -458,11 +506,8 @@ static void gp_draw_data (bGPdata *gpd, int winx, int winy, int dflag) /* check if frame is drawable */ if ((gpf->framenum - gf->framenum) <= gpl->gstep) { /* alpha decreases with distance from curframe index */ - glColor4f(color[0], color[1], color[2], (color[3]-(i*0.7))); - - for (gps= gf->strokes.first; gps; gps= gps->next) { - gp_draw_stroke(gps->points, gps->totpoints, lthick, dflag, gps->flag, debug, winx, winy); - } + tcolor[3] = color[3] - (i * 0.7); + gp_draw_strokes(gpf, winx, winy, dflag, debug, lthick, tcolor); } else break; @@ -473,11 +518,8 @@ static void gp_draw_data (bGPdata *gpd, int winx, int winy, int dflag) /* check if frame is drawable */ if ((gf->framenum - gpf->framenum) <= gpl->gstep) { /* alpha decreases with distance from curframe index */ - glColor4f(color[0], color[1], color[2], (color[3]-(i*0.7))); - - for (gps= gf->strokes.first; gps; gps= gps->next) { - gp_draw_stroke(gps->points, gps->totpoints, lthick, dflag, gps->flag, debug, winx, winy); - } + tcolor[3] = color[3] - (i * 0.7); + gp_draw_strokes(gpf, winx, winy, dflag, debug, lthick, tcolor); } else break; @@ -488,19 +530,14 @@ static void gp_draw_data (bGPdata *gpd, int winx, int winy, int dflag) } else { /* draw the strokes for the ghost frames (at half of the alpha set by user) */ - glColor4f(color[0], color[1], color[2], (color[3] / 7)); - if (gpf->prev) { - for (gps= gpf->prev->strokes.first; gps; gps= gps->next) { - gp_draw_stroke(gps->points, gps->totpoints, lthick, dflag, gps->flag, debug, winx, winy); - } + tcolor[3] = (color[3] / 7); + gp_draw_strokes(gpf, winx, winy, dflag, debug, lthick, tcolor); } - glColor4f(color[0], color[1], color[2], (color[3] / 4)); if (gpf->next) { - for (gps= gpf->next->strokes.first; gps; gps= gps->next) { - gp_draw_stroke(gps->points, gps->totpoints, lthick, dflag, gps->flag, debug, winx, winy); - } + tcolor[3] = (color[3] / 4); + gp_draw_strokes(gpf, winx, winy, dflag, debug, lthick, tcolor); } /* restore alpha */ @@ -509,9 +546,8 @@ static void gp_draw_data (bGPdata *gpd, int winx, int winy, int dflag) } /* draw the strokes already in active frame */ - for (gps= gpf->strokes.first; gps; gps= gps->next) { - gp_draw_stroke(gps->points, gps->totpoints, lthick, dflag, gps->flag, debug, winx, winy); - } + tcolor[3]= color[3]; + gp_draw_strokes(gpf, winx, winy, dflag, debug, lthick, tcolor); /* Check if may need to draw the active stroke cache, only if this layer is the active layer * that is being edited. (Stroke cache is currently stored in gp-data) diff --git a/source/blender/src/editnode.c b/source/blender/src/editnode.c index 5c137e67c1a..98f4f1bb46f 100644 --- a/source/blender/src/editnode.c +++ b/source/blender/src/editnode.c @@ -2400,7 +2400,7 @@ void winqreadnodespace(ScrArea *sa, void *spacedata, BWinEvent *evt) switch(event) { case LEFTMOUSE: - if(gpencil_do_paint(sa)) { + if(gpencil_do_paint(sa, L_MOUSE)) { return; } else if(fromlib) { @@ -2421,7 +2421,10 @@ void winqreadnodespace(ScrArea *sa, void *spacedata, BWinEvent *evt) break; case RIGHTMOUSE: - if(find_indicated_socket(snode, &actnode, &actsock, SOCK_IN)) { + if(gpencil_do_paint(sa, R_MOUSE)) { + return; + } + else if(find_indicated_socket(snode, &actnode, &actsock, SOCK_IN)) { if(actsock->flag & SOCK_SEL) { snode->edittree->selin= NULL; actsock->flag&= ~SOCK_SEL; @@ -2568,8 +2571,13 @@ void winqreadnodespace(ScrArea *sa, void *spacedata, BWinEvent *evt) break; case DELKEY: case XKEY: - if(fromlib) fromlib= -1; - else node_delete(snode); + if(G.qual==LR_ALTKEY) { + gpencil_delete_menu(); + } + else { + if(fromlib) fromlib= -1; + else node_delete(snode); + } break; } } diff --git a/source/blender/src/gpencil.c b/source/blender/src/gpencil.c index d8299fc2a61..e9f023bdd5c 100644 --- a/source/blender/src/gpencil.c +++ b/source/blender/src/gpencil.c @@ -616,7 +616,7 @@ void gpencil_delete_actframe (bGPdata *gpd) * 2 - active frame * 3 - active layer */ -void gpencil_delete_operation (short mode) // unused +void gpencil_delete_operation (short mode) { bGPdata *gpd; @@ -642,11 +642,15 @@ void gpencil_delete_operation (short mode) // unused } /* display a menu for deleting different grease-pencil elements */ -void gpencil_delete_menu (void) // unused +void gpencil_delete_menu (void) { + bGPdata *gpd= gpencil_data_getactive(NULL); short mode; - mode= pupmenu("Erase...%t|Last Stroke%x1|Active Frame%x2|Active Layer%x3"); + /* only show menu if it will be relevant */ + if (gpd == NULL) return; + + mode= pupmenu("Grease Pencil Erase...%t|Last Stroke%x1|Active Frame%x2|Active Layer%x3"); if (mode <= 0) return; gpencil_delete_operation(mode); @@ -658,7 +662,7 @@ void gpencil_delete_menu (void) // unused /* ---------- 'Globals' and Defines ----------------- */ /* maximum sizes of gp-session buffer */ -#define GP_STROKE_BUFFER_MAX 500 +#define GP_STROKE_BUFFER_MAX 5000 /* ------ */ @@ -968,7 +972,7 @@ static void gp_stroke_newfrombuffer (tGPsdata *p) /* ---------- 'Paint' Tool ------------ */ /* init new stroke */ -static void gp_paint_initstroke (tGPsdata *p) +static void gp_paint_initstroke (tGPsdata *p, short mousebutton) { /* get active layer (or add a new one if non-existent) */ p->gpl= gpencil_layer_getactive(p->gpd); @@ -991,8 +995,17 @@ static void gp_paint_initstroke (tGPsdata *p) } else p->gpf->flag |= GP_FRAME_PAINT; + + /* set 'eraser' for this stroke if using eraser or right-mouse in action */ + if ( get_activedevice() == 2 || (mousebutton & R_MOUSE) ) { + p->gpd->sbuffer_sflag |= GP_STROKE_ERASER; - /* check if points will need to be made in 3d-space */ + // for now: eraser isn't ready for prime-time yet, so no painting available here yet + p->status= GP_STATUS_ERROR; + return; + } + + /* check if points will need to be made in view-aligned space */ if (p->gpd->flag & GP_DATA_VIEWALIGN) { switch (p->sa->spacetype) { case SPACE_VIEW3D: @@ -1065,7 +1078,7 @@ short gpencil_paint (short mousebutton) gp_session_cleanup(&p); return 0; } - gp_paint_initstroke(&p); + gp_paint_initstroke(&p, mousebutton); if (p.status == GP_STATUS_ERROR) { gp_session_cleanup(&p); return 0; @@ -1154,10 +1167,9 @@ short gpencil_paint (short mousebutton) /* All event (loops) handling checking if stroke drawing should be initiated * should call this function. */ -short gpencil_do_paint (ScrArea *sa) +short gpencil_do_paint (ScrArea *sa, short mousebutton) { bGPdata *gpd = gpencil_data_getactive(sa); - short mousebutton = L_MOUSE; /* for now, this is always on L_MOUSE*/ short retval= 0; /* check if possible to do painting */ @@ -1173,7 +1185,7 @@ short gpencil_do_paint (ScrArea *sa) /* try to paint */ retval = gpencil_paint(mousebutton); } - else if (G.qual == LR_SHIFTKEY) { + else if (!(gpd->flag & GP_DATA_LMBPLOCK) && (G.qual == LR_SHIFTKEY)) { /* try to paint */ retval = gpencil_paint(mousebutton); } diff --git a/source/blender/src/interface_draw.c b/source/blender/src/interface_draw.c index 0403e5d5b37..83ae449b989 100644 --- a/source/blender/src/interface_draw.c +++ b/source/blender/src/interface_draw.c @@ -2351,7 +2351,6 @@ static void ui_draw_roundbox(uiBut *but) { glEnable(GL_BLEND); - //BIF_ThemeColorShadeAlpha(TH_PANEL, but->a2, but->a2); BIF_ThemeColorShadeAlpha(but->themecol, but->a2, but->a2); uiSetRoundBox(but->a1); diff --git a/source/blender/src/space.c b/source/blender/src/space.c index 723bb5205d7..f4cfaba0fda 100644 --- a/source/blender/src/space.c +++ b/source/blender/src/space.c @@ -1215,9 +1215,12 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) return; /* return if event was processed (swallowed) by handler(s) */ } - if(gpencil_do_paint(sa)) return; + if(gpencil_do_paint(sa, L_MOUSE)) return; if(BIF_do_manipulator(sa)) return; } + else if(event==RIGHTMOUSE) { + if(gpencil_do_paint(sa, R_MOUSE)) return; + } /* swap mouse buttons based on user preference */ if (U.flag & USER_LMOUSESELECT) { @@ -2720,6 +2723,8 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) case DELKEY: if(G.qual==0 || G.qual==LR_SHIFTKEY) delete_context_selected(); + if(G.qual==LR_ALTKEY) + gpencil_delete_menu(); break; case YKEY: if((G.qual==0) && (G.obedit)) { @@ -4841,8 +4846,11 @@ static void winqreadseqspace(ScrArea *sa, void *spacedata, BWinEvent *evt) if( uiDoBlocks(&curarea->uiblocks, event, 1)!=UI_NOTHING ) event= 0; /* grease-pencil defaults to leftmouse */ - if(event==LEFTMOUSE) { - if(gpencil_do_paint(sa)) return; + if (event == LEFTMOUSE) { + if(gpencil_do_paint(sa, L_MOUSE)) return; + } + else if (event == RIGHTMOUSE) { + if(gpencil_do_paint(sa, R_MOUSE)) return; } /* swap mouse buttons based on user preference */ @@ -5117,6 +5125,10 @@ static void winqreadseqspace(ScrArea *sa, void *spacedata, BWinEvent *evt) if((G.qual==0)) del_seq(); } + else if(G.qual==LR_ALTKEY) { + if(sseq->mainb) + gpencil_delete_menu(); + } break; case PAD1: case PAD2: case PAD4: case PAD8: seq_viewzoom(event, (G.qual & LR_SHIFTKEY)==0); diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index c0051657658..3f5246fd893 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -1920,10 +1920,8 @@ void BL_ConvertBlenderObjects(struct Main* maggie, gameobj->NodeUpdateGS(0,true); BL_ConvertIpos(blenderobject,gameobj,converter); - // TODO: expand to multiple ipos per mesh - Material *mat = give_current_material(blenderobject, 1); - if(mat) BL_ConvertMaterialIpos(mat, gameobj, converter); - + BL_ConvertMaterialIpos(blenderobject, gameobj, converter); + sumolist->Add(gameobj->AddRef()); BL_ConvertProperties(blenderobject,gameobj,timemgr,kxscene,isInActiveLayer); @@ -2102,9 +2100,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie, gameobj->NodeUpdateGS(0,true); BL_ConvertIpos(blenderobject,gameobj,converter); - // TODO: expand to multiple ipos per mesh - Material *mat = give_current_material(blenderobject, 1); - if(mat) BL_ConvertMaterialIpos(mat, gameobj, converter); + BL_ConvertMaterialIpos(blenderobject,gameobj, converter); sumolist->Add(gameobj->AddRef()); diff --git a/source/gameengine/Converter/KX_IpoConvert.cpp b/source/gameengine/Converter/KX_IpoConvert.cpp index 75ca59d01e7..7410beecaf4 100644 --- a/source/gameengine/Converter/KX_IpoConvert.cpp +++ b/source/gameengine/Converter/KX_IpoConvert.cpp @@ -36,6 +36,7 @@ #pragma warning (disable:4786) #endif +#include "BKE_material.h" /* give_current_material */ #include "KX_GameObject.h" #include "KX_IpoConvert.h" @@ -68,6 +69,8 @@ #include "SG_Node.h" +#include "STR_HashedString.h" + static BL_InterpolatorList *GetIpoList(struct Ipo *for_ipo, KX_BlenderSceneConverter *converter) { BL_InterpolatorList *ipoList= converter->FindInterpolatorList(for_ipo); @@ -560,16 +563,15 @@ void BL_ConvertWorldIpos(struct World* blenderworld,KX_BlenderSceneConverter *co } } - -void BL_ConvertMaterialIpos( - Material* blendermaterial, +static void ConvertMaterialIpos( + Material* blendermaterial, + dword matname_hash, KX_GameObject* gameobj, KX_BlenderSceneConverter *converter ) { if (blendermaterial->ipo) { - - KX_MaterialIpoController* ipocontr = new KX_MaterialIpoController(); + KX_MaterialIpoController* ipocontr = new KX_MaterialIpoController(matname_hash); gameobj->GetSGNode()->AddSGController(ipocontr); ipocontr->SetObject(gameobj->GetSGNode()); @@ -596,7 +598,7 @@ void BL_ConvertMaterialIpos( ipo = ipoList->GetScalarInterpolator(MA_COL_R); if (ipo) { if (!ipocontr) { - ipocontr = new KX_MaterialIpoController(); + ipocontr = new KX_MaterialIpoController(matname_hash); gameobj->GetSGNode()->AddSGController(ipocontr); ipocontr->SetObject(gameobj->GetSGNode()); } @@ -610,7 +612,7 @@ void BL_ConvertMaterialIpos( ipo = ipoList->GetScalarInterpolator(MA_COL_G); if (ipo) { if (!ipocontr) { - ipocontr = new KX_MaterialIpoController(); + ipocontr = new KX_MaterialIpoController(matname_hash); gameobj->GetSGNode()->AddSGController(ipocontr); ipocontr->SetObject(gameobj->GetSGNode()); } @@ -624,7 +626,7 @@ void BL_ConvertMaterialIpos( ipo = ipoList->GetScalarInterpolator(MA_COL_B); if (ipo) { if (!ipocontr) { - ipocontr = new KX_MaterialIpoController(); + ipocontr = new KX_MaterialIpoController(matname_hash); gameobj->GetSGNode()->AddSGController(ipocontr); ipocontr->SetObject(gameobj->GetSGNode()); } @@ -638,7 +640,7 @@ void BL_ConvertMaterialIpos( ipo = ipoList->GetScalarInterpolator(MA_ALPHA); if (ipo) { if (!ipocontr) { - ipocontr = new KX_MaterialIpoController(); + ipocontr = new KX_MaterialIpoController(matname_hash); gameobj->GetSGNode()->AddSGController(ipocontr); ipocontr->SetObject(gameobj->GetSGNode()); } @@ -653,7 +655,7 @@ void BL_ConvertMaterialIpos( ipo = ipoList->GetScalarInterpolator(MA_SPEC_R ); if (ipo) { if (!ipocontr) { - ipocontr = new KX_MaterialIpoController(); + ipocontr = new KX_MaterialIpoController(matname_hash); gameobj->GetSGNode()->AddSGController(ipocontr); ipocontr->SetObject(gameobj->GetSGNode()); } @@ -667,7 +669,7 @@ void BL_ConvertMaterialIpos( ipo = ipoList->GetScalarInterpolator(MA_SPEC_G); if (ipo) { if (!ipocontr) { - ipocontr = new KX_MaterialIpoController(); + ipocontr = new KX_MaterialIpoController(matname_hash); gameobj->GetSGNode()->AddSGController(ipocontr); ipocontr->SetObject(gameobj->GetSGNode()); } @@ -681,7 +683,7 @@ void BL_ConvertMaterialIpos( ipo = ipoList->GetScalarInterpolator(MA_SPEC_B); if (ipo) { if (!ipocontr) { - ipocontr = new KX_MaterialIpoController(); + ipocontr = new KX_MaterialIpoController(matname_hash); gameobj->GetSGNode()->AddSGController(ipocontr); ipocontr->SetObject(gameobj->GetSGNode()); } @@ -696,7 +698,7 @@ void BL_ConvertMaterialIpos( ipo = ipoList->GetScalarInterpolator(MA_HARD); if (ipo) { if (!ipocontr) { - ipocontr = new KX_MaterialIpoController(); + ipocontr = new KX_MaterialIpoController(matname_hash); gameobj->GetSGNode()->AddSGController(ipocontr); ipocontr->SetObject(gameobj->GetSGNode()); } @@ -710,7 +712,7 @@ void BL_ConvertMaterialIpos( ipo = ipoList->GetScalarInterpolator(MA_SPEC); if (ipo) { if (!ipocontr) { - ipocontr = new KX_MaterialIpoController(); + ipocontr = new KX_MaterialIpoController(matname_hash); gameobj->GetSGNode()->AddSGController(ipocontr); ipocontr->SetObject(gameobj->GetSGNode()); } @@ -725,7 +727,7 @@ void BL_ConvertMaterialIpos( ipo = ipoList->GetScalarInterpolator(MA_REF); if (ipo) { if (!ipocontr) { - ipocontr = new KX_MaterialIpoController(); + ipocontr = new KX_MaterialIpoController(matname_hash); gameobj->GetSGNode()->AddSGController(ipocontr); ipocontr->SetObject(gameobj->GetSGNode()); } @@ -739,7 +741,7 @@ void BL_ConvertMaterialIpos( ipo = ipoList->GetScalarInterpolator(MA_EMIT); if (ipo) { if (!ipocontr) { - ipocontr = new KX_MaterialIpoController(); + ipocontr = new KX_MaterialIpoController(matname_hash); gameobj->GetSGNode()->AddSGController(ipocontr); ipocontr->SetObject(gameobj->GetSGNode()); } @@ -752,3 +754,28 @@ void BL_ConvertMaterialIpos( } } +void BL_ConvertMaterialIpos( + struct Object* blenderobject, + KX_GameObject* gameobj, + KX_BlenderSceneConverter *converter + ) +{ + if (blenderobject->totcol==1) + { + Material *mat = give_current_material(blenderobject, 1); + // if there is only one material attached to the mesh then set material_index in BL_ConvertMaterialIpos to NULL + // --> this makes the UpdateMaterialData function in KX_GameObject.cpp use the old hack of using SetObjectColor + // because this yields a better performance as not all the vertex colors need to be edited + if(mat) ConvertMaterialIpos(mat, NULL, gameobj, converter); + } + else + { + for (int material_index=1; material_index <= blenderobject->totcol; material_index++) + { + Material *mat = give_current_material(blenderobject, material_index); + STR_HashedString matname = mat->id.name; + if(mat) ConvertMaterialIpos(mat, matname.hash(), gameobj, converter); + } + } +} + diff --git a/source/gameengine/Converter/KX_IpoConvert.h b/source/gameengine/Converter/KX_IpoConvert.h index afcb1b22821..4ec9bd31062 100644 --- a/source/gameengine/Converter/KX_IpoConvert.h +++ b/source/gameengine/Converter/KX_IpoConvert.h @@ -46,7 +46,7 @@ void BL_ConvertCameraIpos(struct Camera* blendercamera, class KX_GameObject* cameraobj, class KX_BlenderSceneConverter *converter); -void BL_ConvertMaterialIpos(struct Material* blendermaterial, +void BL_ConvertMaterialIpos(struct Object* blenderobject, class KX_GameObject* materialobj, class KX_BlenderSceneConverter *converter); diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index 969873abeee..3d9c7aafd70 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -442,6 +442,7 @@ void KX_GameObject::UpdateIPO(float curframetime, // IPO update void KX_GameObject::UpdateMaterialData( + dword matname_hash, MT_Vector4 rgba, MT_Vector3 specrgb, MT_Scalar hard, @@ -461,7 +462,25 @@ KX_GameObject::UpdateMaterialData( if(poly->GetFlag() & RAS_BLENDERMAT ) { KX_BlenderMaterial *m = static_cast<KX_BlenderMaterial*>(poly); - m->UpdateIPO(rgba, specrgb,hard,spec,ref,emit, alpha); + + if (matname_hash == NULL) + { + m->UpdateIPO(rgba, specrgb,hard,spec,ref,emit, alpha); + // if mesh has only one material attached to it then use original hack with no need to edit vertices (better performance) + SetObjectColor(rgba); + } + else + { + if (matname_hash == poly->GetMaterialNameHash()) + { + m->UpdateIPO(rgba, specrgb,hard,spec,ref,emit, alpha); + m_meshes[mesh]->SetVertexColor(poly,rgba); + + // no break here, because one blender material can be split into several game engine materials + // (e.g. one uvsphere material is split into one material at poles with ras_mode TRIANGLE and one material for the body + // if here was a break then would miss some vertices if material was split + } + } } } } diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h index 6051cf850b5..1d36798b12f 100644 --- a/source/gameengine/Ketsji/KX_GameObject.h +++ b/source/gameengine/Ketsji/KX_GameObject.h @@ -521,6 +521,7 @@ public: */ void UpdateMaterialData( + dword matname_hash, MT_Vector4 rgba, MT_Vector3 specrgb, MT_Scalar hard, diff --git a/source/gameengine/Ketsji/KX_MaterialIpoController.cpp b/source/gameengine/Ketsji/KX_MaterialIpoController.cpp index c0757a32b9c..2ce5d469380 100644 --- a/source/gameengine/Ketsji/KX_MaterialIpoController.cpp +++ b/source/gameengine/Ketsji/KX_MaterialIpoController.cpp @@ -37,6 +37,7 @@ bool KX_MaterialIpoController::Update(double currentTime) //kxgameobj->SetObjectColor(m_rgba); kxgameobj->UpdateMaterialData( + m_matname_hash, m_rgba, m_specrgb, m_hard, diff --git a/source/gameengine/Ketsji/KX_MaterialIpoController.h b/source/gameengine/Ketsji/KX_MaterialIpoController.h index e76ddeefb04..4d2e258bf94 100644 --- a/source/gameengine/Ketsji/KX_MaterialIpoController.h +++ b/source/gameengine/Ketsji/KX_MaterialIpoController.h @@ -7,6 +7,8 @@ #include "SG_Spatial.h" #include "KX_IInterpolator.h" +#include "STR_String.h" //typedef dword + class KX_MaterialIpoController : public SG_Controller { public: @@ -23,10 +25,12 @@ private: bool m_modified; double m_ipotime; + dword m_matname_hash; public: - KX_MaterialIpoController() : + KX_MaterialIpoController(dword matname_hash) : m_modified(true), - m_ipotime(0.0) + m_ipotime(0.0), + m_matname_hash(matname_hash) {} virtual ~KX_MaterialIpoController(); virtual SG_Controller* GetReplica(class SG_Node* destnode); diff --git a/source/gameengine/Ketsji/KX_PyMath.h b/source/gameengine/Ketsji/KX_PyMath.h index e1715c9275f..4e383e9b3d4 100644 --- a/source/gameengine/Ketsji/KX_PyMath.h +++ b/source/gameengine/Ketsji/KX_PyMath.h @@ -84,7 +84,10 @@ bool PyMatTo(PyObject* pymat, T& mat) } } else noerror = false; - + + if (noerror==false) + PyErr_SetString(PyExc_TypeError, "could not be converted to a matrix (sequence of sequences)"); + return noerror; } @@ -97,9 +100,13 @@ bool PyVecTo(PyObject* pyval, T& vec) if (PySequence_Check(pyval)) { unsigned int numitems = PySequence_Size(pyval); - if (numitems != Size(vec)) + if (numitems != Size(vec)) { + char err[128]; + sprintf(err, "error setting vector, %d args, should be %d", numitems, Size(vec)); + PyErr_SetString(PyExc_AttributeError, err); return false; - + } + for (unsigned int x = 0; x < numitems; x++) { PyObject *item = PySequence_GetItem(pyval, x); /* new ref */ @@ -107,7 +114,17 @@ bool PyVecTo(PyObject* pyval, T& vec) Py_DECREF(item); } + if (PyErr_Occurred()) { + PyErr_SetString(PyExc_AttributeError, "one or more of the items in the sequence was not a float"); + return false; + } + return true; + } else + { + char err[128]; + sprintf(err, "not a sequence type, expected a sequence of numbers size %d", Size(vec)); + PyErr_SetString(PyExc_AttributeError, err); } return false; diff --git a/source/gameengine/Ketsji/KX_TrackToActuator.cpp b/source/gameengine/Ketsji/KX_TrackToActuator.cpp index c580aa4d4e5..d4bd109de1a 100644 --- a/source/gameengine/Ketsji/KX_TrackToActuator.cpp +++ b/source/gameengine/Ketsji/KX_TrackToActuator.cpp @@ -146,19 +146,19 @@ void compatible_eulFast(float *eul, float *oldrot) { float dx, dy, dz; - /* verschillen van ong 360 graden corrigeren */ + /* angular difference of 360 degrees */ dx= eul[0] - oldrot[0]; dy= eul[1] - oldrot[1]; dz= eul[2] - oldrot[2]; - if( fabs(dx) > 5.1) { + if( fabs(dx) > MT_PI) { if(dx > 0.0) eul[0] -= MT_2_PI; else eul[0]+= MT_2_PI; } - if( fabs(dy) > 5.1) { + if( fabs(dy) > MT_PI) { if(dy > 0.0) eul[1] -= MT_2_PI; else eul[1]+= MT_2_PI; } - if( fabs(dz) > 5.1 ) { + if( fabs(dz) > MT_PI ) { if(dz > 0.0) eul[2] -= MT_2_PI; else eul[2]+= MT_2_PI; } } diff --git a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp index 6f04ce5d866..3c0014ab3ba 100644 --- a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp +++ b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp @@ -143,6 +143,11 @@ const STR_String& RAS_IPolyMaterial::GetMaterialName() const return m_materialname; } +dword RAS_IPolyMaterial::GetMaterialNameHash() const +{ + return m_materialname.hash(); +} + const STR_String& RAS_IPolyMaterial::GetTextureName() const { return m_texturename; diff --git a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h index fd5c6d5a59f..2951a21507d 100644 --- a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h +++ b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h @@ -140,6 +140,7 @@ public: unsigned int hash() const; int GetDrawingMode() const; const STR_String& GetMaterialName() const; + dword GetMaterialNameHash() const; const STR_String& GetTextureName() const; const unsigned int GetFlag() const; diff --git a/source/gameengine/Rasterizer/RAS_MeshObject.cpp b/source/gameengine/Rasterizer/RAS_MeshObject.cpp index 4420f16c56d..5087f62500e 100644 --- a/source/gameengine/Rasterizer/RAS_MeshObject.cpp +++ b/source/gameengine/Rasterizer/RAS_MeshObject.cpp @@ -201,7 +201,20 @@ void RAS_MeshObject::DebugColor(unsigned int abgr) m_debugcolor = abgr; } - +void RAS_MeshObject::SetVertexColor(RAS_IPolyMaterial* mat,MT_Vector4 rgba) +{ + RAS_TexVert* vertex = NULL; + const vecVertexArray & vertexvec = GetVertexCache(mat); + + for (vector<KX_VertexArray*>::const_iterator it = vertexvec.begin(); it != vertexvec.end(); ++it) + { + KX_VertexArray::iterator vit; + for (vit=(*it)->begin(); vit != (*it)->end(); vit++) + { + vit->SetRGBA(rgba); + } + } +} void RAS_MeshObject::SchedulePoly(const KX_VertexIndex& idx, int numverts, diff --git a/source/gameengine/Rasterizer/RAS_MeshObject.h b/source/gameengine/Rasterizer/RAS_MeshObject.h index 0d06748f91f..44ad508d1e8 100644 --- a/source/gameengine/Rasterizer/RAS_MeshObject.h +++ b/source/gameengine/Rasterizer/RAS_MeshObject.h @@ -189,6 +189,7 @@ public: ); void DebugColor(unsigned int abgr); + void SetVertexColor(RAS_IPolyMaterial* mat,MT_Vector4 rgba); /** * Sorts the polygons by their transformed z values. |