diff options
-rw-r--r-- | source/blender/blenkernel/BKE_blender.h | 2 | ||||
-rw-r--r-- | source/blender/blenloader/intern/readfile.c | 16 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_actuator_types.h | 8 | ||||
-rw-r--r-- | source/blender/src/buttons_logic.c | 26 | ||||
-rw-r--r-- | source/gameengine/Converter/BL_BlenderDataConversion.cpp | 7 | ||||
-rw-r--r-- | source/gameengine/Converter/KX_ConvertActuators.cpp | 6 | ||||
-rw-r--r-- | source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp | 48 | ||||
-rw-r--r-- | source/gameengine/Ketsji/KX_GameObject.cpp | 21 | ||||
-rw-r--r-- | source/gameengine/Ketsji/KX_GameObject.h | 4 | ||||
-rw-r--r-- | source/gameengine/Ketsji/KX_ParentActuator.cpp | 8 | ||||
-rw-r--r-- | source/gameengine/Ketsji/KX_ParentActuator.h | 5 | ||||
-rw-r--r-- | source/gameengine/PyDoc/GameTypes.py | 22 |
12 files changed, 120 insertions, 53 deletions
diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index d49a5425b61..aa2366661f8 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -41,7 +41,7 @@ struct ListBase; struct MemFile; #define BLENDER_VERSION 248 -#define BLENDER_SUBVERSION 4 +#define BLENDER_SUBVERSION 5 #define BLENDER_MINVERSION 245 #define BLENDER_MINSUBVERSION 15 diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 0f233410f4e..25c8a928a3b 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -8106,6 +8106,22 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } } + if (main->versionfile < 248 || (main->versionfile == 248 && main->subversionfile < 5)) { + Object *ob; + for(ob = main->object.first; ob; ob= ob->id.next) { + if(ob->parent) { + /* check if top parent has compound shape set and if yes, set this object + to compound shaper as well (was the behaviour before, now it's optional) */ + Object *parent= newlibadr(fd, lib, ob->parent); + while (parent->parent != NULL) { + parent = newlibadr(fd, lib, parent->parent); + } + if (parent->gameflag & OB_CHILD) + ob->gameflag |= OB_CHILD; + } + } + } + if (main->versionfile < 249) { Scene *sce; for (sce= main->scene.first; sce; sce= sce->id.next) diff --git a/source/blender/makesdna/DNA_actuator_types.h b/source/blender/makesdna/DNA_actuator_types.h index 81c02779cba..f713b4a8acc 100644 --- a/source/blender/makesdna/DNA_actuator_types.h +++ b/source/blender/makesdna/DNA_actuator_types.h @@ -215,7 +215,8 @@ typedef struct bTwoDFilterActuator{ }bTwoDFilterActuator; typedef struct bParentActuator { - char pad[4]; + char pad[2]; + short flag; int type; struct Object *ob; } bParentActuator; @@ -483,6 +484,11 @@ typedef struct FreeCamera { /* parentactuator->type */ #define ACT_PARENT_SET 0 #define ACT_PARENT_REMOVE 1 + +/* parentactuator->flag */ +#define ACT_PARENT_COMPOUND 1 +#define ACT_PARENT_GHOST 2 + #endif diff --git a/source/blender/src/buttons_logic.c b/source/blender/src/buttons_logic.c index 2f8933b593b..b7039673dfc 100644 --- a/source/blender/src/buttons_logic.c +++ b/source/blender/src/buttons_logic.c @@ -2747,11 +2747,22 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh if(parAct->type==ACT_PARENT_SET) { - ysize= 48; + ysize= 68; 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+40, yco-44, (width-80), 19, &(parAct->ob), "Set this object as parent"); + uiBlockBeginAlign(block); + uiDefButBitI(block, TOGN, ACT_PARENT_COMPOUND, B_REDR, + "Compound", + xco + 40, yco - 64, (width - 80)/2, 19, &parAct->flag, + 0.0, 0.0, 0, 0, + "Add this object shape to the parent shape (only if the parent shape is already compound)"); + uiDefButBitI(block, TOGN, ACT_PARENT_GHOST, B_REDR, + "Ghost", + xco + 40 + ((width - 80)/2), yco - 64, (width - 80)/2, 19, &parAct->flag, + 0.0, 0.0, 0, 0, + "Make this object ghost while parented (only if not compound)"); + uiBlockEndAlign(block); } else if(parAct->type==ACT_PARENT_REMOVE) { @@ -3480,9 +3491,14 @@ static void buttons_bullet(uiBlock *block, Object *ob) } if (ob->body_type!=OB_BODY_TYPE_SOFT) { - uiDefButBitI(block, TOG, OB_CHILD, B_REDR, "Compound", 240,105,110,19, - &ob->gameflag, 0, 0, 0, 0, - "Add Children"); + if (ob->parent) + uiDefButBitI(block, TOG, OB_CHILD, B_REDR, "Add to parent", 240,105,110,19, + &ob->gameflag, 0, 0, 0, 0, + "Add this shape to the parent compound shape"); + else + uiDefButBitI(block, TOG, OB_CHILD, B_REDR, "Compound", 240,105,110,19, + &ob->gameflag, 0, 0, 0, 0, + "Create a compound shape with the children's shape that are tagged for addition"); } } uiBlockEndAlign(block); diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index bf965f677c6..82edd4f218b 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -1377,10 +1377,11 @@ void BL_CreatePhysicsObjectNew(KX_GameObject* gameobj, } bool isCompoundChild = false; + bool hasCompoundChildren = !parent && (blenderobject->gameflag & OB_CHILD); - if (parent && (parent->gameflag & OB_DYNAMIC)) { + if (parent/* && (parent->gameflag & OB_DYNAMIC)*/) { - if ((parent->gameflag & OB_CHILD) != 0) + if ((parent->gameflag & OB_CHILD) != 0 && (blenderobject->gameflag & OB_CHILD)) { isCompoundChild = true; } @@ -1406,7 +1407,7 @@ void BL_CreatePhysicsObjectNew(KX_GameObject* gameobj, objprop.m_lockZRotaxis = (blenderobject->gameflag2 & OB_LOCK_RIGID_BODY_Z_ROT_AXIS) !=0; objprop.m_isCompoundChild = isCompoundChild; - objprop.m_hasCompoundChildren = (blenderobject->gameflag & OB_CHILD) != 0; + objprop.m_hasCompoundChildren = hasCompoundChildren; objprop.m_margin = blenderobject->margin; // ACTOR is now a separate feature objprop.m_isactor = (blenderobject->gameflag & OB_ACTOR)!=0; diff --git a/source/gameengine/Converter/KX_ConvertActuators.cpp b/source/gameengine/Converter/KX_ConvertActuators.cpp index 98df34aa4a9..2b832996c45 100644 --- a/source/gameengine/Converter/KX_ConvertActuators.cpp +++ b/source/gameengine/Converter/KX_ConvertActuators.cpp @@ -1123,6 +1123,8 @@ void BL_ConvertActuators(char* maggiename, { bParentActuator *parAct = (bParentActuator *) bact->data; int mode = KX_ParentActuator::KX_PARENT_NODEF; + bool addToCompound = true; + bool ghost = true; KX_GameObject *tmpgob = NULL; switch(parAct->type) @@ -1130,6 +1132,8 @@ void BL_ConvertActuators(char* maggiename, case ACT_PARENT_SET: mode = KX_ParentActuator::KX_PARENT_SET; tmpgob = converter->FindGameObject(parAct->ob); + addToCompound = !(parAct->flag & ACT_PARENT_COMPOUND); + ghost = !(parAct->flag & ACT_PARENT_GHOST); break; case ACT_PARENT_REMOVE: mode = KX_ParentActuator::KX_PARENT_REMOVE; @@ -1140,6 +1144,8 @@ void BL_ConvertActuators(char* maggiename, KX_ParentActuator *tmpparact = new KX_ParentActuator(gameobj, mode, + addToCompound, + ghost, tmpgob); baseact = tmpparact; break; diff --git a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp index d81b6d5a653..406339586cc 100644 --- a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp +++ b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp @@ -949,39 +949,27 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj, assert(colShape->isCompound()); btCompoundShape* compoundShape = (btCompoundShape*)colShape; - // compute the local transform from parent, this may include a parent inverse node + // compute the local transform from parent, this may include several node in the chain SG_Node* gameNode = gameobj->GetSGNode(); - SG_Node* parentInverseNode = gameNode->GetSGParent(); - if (parentInverseNode && parentInverseNode->GetSGClientObject() != NULL) - // this is not a parent inverse node, cancel it - parentInverseNode = NULL; - // now combine the parent inverse node and the game node - MT_Point3 childPos = gameNode->GetLocalPosition(); - MT_Matrix3x3 childRot = gameNode->GetLocalOrientation(); - MT_Vector3 childScale = gameNode->GetLocalScale(); - if (parentInverseNode) - { - const MT_Point3& parentInversePos = parentInverseNode->GetLocalPosition(); - const MT_Matrix3x3& parentInverseRot = parentInverseNode->GetLocalOrientation(); - const MT_Vector3& parentInverseScale = parentInverseNode->GetLocalScale(); - childRot = parentInverseRot * childRot; - childScale = parentInverseScale * childScale; - childPos = parentInversePos+parentInverseScale*(parentInverseRot*childPos); - } - - shapeInfo->m_childScale.setValue(childScale.x(),childScale.y(),childScale.z()); + SG_Node* parentNode = objprop->m_dynamic_parent->GetSGNode(); + // relative transform + MT_Vector3 parentScale = parentNode->GetWorldScaling(); + parentScale[0] = MT_Scalar(1.0)/parentScale[0]; + parentScale[1] = MT_Scalar(1.0)/parentScale[1]; + parentScale[2] = MT_Scalar(1.0)/parentScale[2]; + MT_Vector3 relativeScale = gameNode->GetWorldScaling() * parentScale; + MT_Matrix3x3 parentInvRot = parentNode->GetWorldOrientation().transposed(); + MT_Vector3 relativePos = parentInvRot*((gameNode->GetWorldPosition()-parentNode->GetWorldPosition())*parentScale); + MT_Matrix3x3 relativeRot = parentInvRot*gameNode->GetWorldOrientation(); + + shapeInfo->m_childScale.setValue(relativeScale[0],relativeScale[1],relativeScale[2]); bm->setLocalScaling(shapeInfo->m_childScale); - - shapeInfo->m_childTrans.setOrigin(btVector3(childPos.x(),childPos.y(),childPos.z())); - float rotval[12]; - childRot.getValue(rotval); - btMatrix3x3 newRot; - newRot.setValue(rotval[0],rotval[1],rotval[2],rotval[4],rotval[5],rotval[6],rotval[8],rotval[9],rotval[10]); - newRot = newRot.transpose(); - - shapeInfo->m_childTrans.setBasis(newRot); + shapeInfo->m_childTrans.getOrigin().setValue(relativePos[0],relativePos[1],relativePos[2]); + float rot[12]; + relativeRot.getValue(rot); + shapeInfo->m_childTrans.getBasis().setFromOpenGLSubMatrix(rot); + parentShapeInfo->AddShape(shapeInfo); - compoundShape->addChildShape(shapeInfo->m_childTrans,bm); //do some recalc? //recalc inertia for rigidbody diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index 63d508e6250..0c191257f41 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -224,7 +224,7 @@ KX_GameObject* KX_GameObject::GetParent() } -void KX_GameObject::SetParent(KX_Scene *scene, KX_GameObject* obj) +void KX_GameObject::SetParent(KX_Scene *scene, KX_GameObject* obj, bool addToCompound, bool ghost) { // check on valid node in case a python controller holds a reference to a deleted object if (obj && GetSGNode() && obj->GetSGNode() && GetSGNode()->GetSGParent() != obj->GetSGNode()) @@ -245,7 +245,7 @@ void KX_GameObject::SetParent(KX_Scene *scene, KX_GameObject* obj) if (m_pPhysicsController1) { - m_pPhysicsController1->SuspendDynamics(true); + m_pPhysicsController1->SuspendDynamics(ghost); } // Set us to our new scale, position, and orientation scale2[0] = 1.0/scale2[0]; @@ -266,7 +266,7 @@ void KX_GameObject::SetParent(KX_Scene *scene, KX_GameObject* obj) Release(); // if the new parent is a compound object, add this object shape to the compound shape. // step 0: verify this object has physical controller - if (m_pPhysicsController1) + if (m_pPhysicsController1 && addToCompound) { // step 1: find the top parent (not necessarily obj) KX_GameObject* rootobj = (KX_GameObject*)obj->GetSGNode()->GetRootSGParent()->GetSGClientObject(); @@ -1160,7 +1160,7 @@ PyMethodDef KX_GameObject::Methods[] = { {"disableRigidBody", (PyCFunction)KX_GameObject::sPyDisableRigidBody,METH_NOARGS}, {"applyImpulse", (PyCFunction) KX_GameObject::sPyApplyImpulse, METH_VARARGS}, {"setCollisionMargin", (PyCFunction) KX_GameObject::sPySetCollisionMargin, METH_O}, - {"setParent", (PyCFunction)KX_GameObject::sPySetParent,METH_O}, + {"setParent", (PyCFunction)KX_GameObject::sPySetParent,METH_VARARGS}, {"setVisible",(PyCFunction) KX_GameObject::sPySetVisible, METH_VARARGS}, {"setOcclusion",(PyCFunction) KX_GameObject::sPySetOcclusion, METH_VARARGS}, {"removeParent", (PyCFunction)KX_GameObject::sPyRemoveParent,METH_NOARGS}, @@ -2147,15 +2147,20 @@ PyObject* KX_GameObject::PyGetParent() Py_RETURN_NONE; } -PyObject* KX_GameObject::PySetParent(PyObject* value) +PyObject* KX_GameObject::PySetParent(PyObject* args) { KX_Scene *scene = KX_GetActiveScene(); + PyObject* pyobj; KX_GameObject *obj; + int addToCompound=1, ghost=1; - if (!ConvertPythonToGameObject(value, &obj, false, "gameOb.setParent(value): KX_GameObject")) + if (!PyArg_ParseTuple(args,"O|ii:setParent", &pyobj, &addToCompound, &ghost)) { + return NULL; // Python sets a simple error + } + if (!ConvertPythonToGameObject(pyobj, &obj, true, "gameOb.setParent(obj): KX_GameObject")) return NULL; - - this->SetParent(scene, obj); + if (obj) + this->SetParent(scene, obj, addToCompound, ghost); Py_RETURN_NONE; } diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h index 0011b8407fd..c89b8f30779 100644 --- a/source/gameengine/Ketsji/KX_GameObject.h +++ b/source/gameengine/Ketsji/KX_GameObject.h @@ -171,7 +171,7 @@ public: /** * Sets the parent of this object to a game object */ - void SetParent(KX_Scene *scene, KX_GameObject *obj); + void SetParent(KX_Scene *scene, KX_GameObject *obj, bool addToCompound=true, bool ghost=true); /** * Removes the parent of this object to a game object @@ -858,7 +858,7 @@ public: KX_PYMETHOD_VARARGS(KX_GameObject,ApplyImpulse); KX_PYMETHOD_O(KX_GameObject,SetCollisionMargin); KX_PYMETHOD_NOARGS(KX_GameObject,GetParent); - KX_PYMETHOD_O(KX_GameObject,SetParent); + KX_PYMETHOD_VARARGS(KX_GameObject,SetParent); KX_PYMETHOD_NOARGS(KX_GameObject,RemoveParent); KX_PYMETHOD_NOARGS(KX_GameObject,GetChildren); KX_PYMETHOD_NOARGS(KX_GameObject,GetChildrenRecursive); diff --git a/source/gameengine/Ketsji/KX_ParentActuator.cpp b/source/gameengine/Ketsji/KX_ParentActuator.cpp index 38ad9aec33b..cd2ed456c48 100644 --- a/source/gameengine/Ketsji/KX_ParentActuator.cpp +++ b/source/gameengine/Ketsji/KX_ParentActuator.cpp @@ -48,10 +48,14 @@ KX_ParentActuator::KX_ParentActuator(SCA_IObject *gameobj, int mode, + bool addToCompound, + bool ghost, SCA_IObject *ob, PyTypeObject* T) : SCA_IActuator(gameobj, T), m_mode(mode), + m_addToCompound(addToCompound), + m_ghost(ghost), m_ob(ob) { if (m_ob) @@ -121,7 +125,7 @@ bool KX_ParentActuator::Update() switch (m_mode) { case KX_PARENT_SET: if (m_ob) - obj->SetParent(scene, (KX_GameObject*)m_ob); + obj->SetParent(scene, (KX_GameObject*)m_ob, m_addToCompound, m_ghost); break; case KX_PARENT_REMOVE: obj->RemoveParent(scene); @@ -179,6 +183,8 @@ PyMethodDef KX_ParentActuator::Methods[] = { PyAttributeDef KX_ParentActuator::Attributes[] = { KX_PYATTRIBUTE_RW_FUNCTION("object", KX_ParentActuator, pyattr_get_object, pyattr_set_object), KX_PYATTRIBUTE_INT_RW("mode", KX_PARENT_NODEF+1, KX_PARENT_MAX-1, true, KX_ParentActuator, m_mode), + KX_PYATTRIBUTE_BOOL_RW("compound", KX_ParentActuator, m_addToCompound), + KX_PYATTRIBUTE_BOOL_RW("ghost", KX_ParentActuator, m_ghost), { NULL } //Sentinel }; diff --git a/source/gameengine/Ketsji/KX_ParentActuator.h b/source/gameengine/Ketsji/KX_ParentActuator.h index 6af0888e2ba..148375e994c 100644 --- a/source/gameengine/Ketsji/KX_ParentActuator.h +++ b/source/gameengine/Ketsji/KX_ParentActuator.h @@ -46,6 +46,9 @@ class KX_ParentActuator : public SCA_IActuator /** Mode */ int m_mode; + /** option */ + bool m_addToCompound; + bool m_ghost; /** Object to set as parent */ SCA_IObject *m_ob; @@ -63,6 +66,8 @@ class KX_ParentActuator : public SCA_IActuator KX_ParentActuator(class SCA_IObject* gameobj, int mode, + bool addToCompound, + bool ghost, SCA_IObject *ob, PyTypeObject* T=&Type); virtual ~KX_ParentActuator(); diff --git a/source/gameengine/PyDoc/GameTypes.py b/source/gameengine/PyDoc/GameTypes.py index 47c27a5c3c9..3f9b627247f 100644 --- a/source/gameengine/PyDoc/GameTypes.py +++ b/source/gameengine/PyDoc/GameTypes.py @@ -1896,12 +1896,23 @@ class KX_GameObject(SCA_IObject): @rtype: L{KX_GameObject} @return: this object's parent object, or None if this object has no parent. """ - def setParent(parent): + def setParent(parent,compound,ghost): """ - Sets this object's parent. + Sets this object's parent. + Control the shape status with the optional compound and ghost parameters: + compound=1: the object shape should be added to the parent compound shape (default) + compound=0: the object should keep its individual shape. + In that case you can control if it should be ghost or not: + ghost=1 if the object should be made ghost while parented (default) + ghost=0 if the object should be solid while parented + Note: if the object type is sensor, it stays ghost regardless of ghost parameter @type parent: L{KX_GameObject} @param parent: new parent object. + @type compound: int + @param compound: whether the shape should be added to the parent compound shape + @type ghost: int + @param ghost: whether the object should be ghost while parented """ def removeParent(): """ @@ -2937,6 +2948,13 @@ class KX_ParentActuator(SCA_IActuator): @type object: KX_GameObject or None @ivar mode: The mode of this actuator @type mode: int from 0 to 1 L{GameLogic.Parent Actuator} + @ivar compound: Whether the object shape should be added to the parent compound shape when parenting + Effective only if the parent is already a compound shape + @type compound: bool + @ivar ghost: whether the object should be made ghost when parenting + Effective only if the shape is not added to the parent compound shape + @type ghost: bool + """ def setObject(object): """ |