ReplaceMesh Actuator option to replace the physics mesh and display mesh + python api options.

When the mesh field is left blank and Physics option is enabled, it reinstances the physics mesh from the existing mesh.
like calling gameOb.reinstancePhysicsMesh() from python.
This commit is contained in:
Campbell Barton 2009-07-26 01:32:37 +00:00
parent e9ca43521f
commit dd918da8de
11 changed files with 162 additions and 120 deletions

@ -405,6 +405,10 @@ typedef struct FreeCamera {
/* editObjectActuator->flag */
#define ACT_TRACK_3D 1
/* editObjectActuator->flag for replace mesh actuator */
#define ACT_EDOB_REPLACE_MESH_NOGFX 2 /* use for replace mesh actuator */
#define ACT_EDOB_REPLACE_MESH_PHYS 4
/* SceneActuator->type */
#define ACT_SCENE_RESTART 0
#define ACT_SCENE_SET 1

@ -2177,7 +2177,10 @@ 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_meshpoin_but, ID_ME, 1, "ME:", xco+40, yco-44, (width-80), 19, &(eoa->me), "replace the existing mesh with this one");
uiDefIDPoinBut(block, test_meshpoin_but, ID_ME, 1, "ME:", xco+40, yco-44, (width-80)/2, 19, &(eoa->me), "replace the existing, when left blank 'Phys' will remake the existing physics mesh");
uiDefButBitS(block, TOGN, ACT_EDOB_REPLACE_MESH_NOGFX, B_NOP, "Gfx", xco+40 + (width-80)/2, yco-44, (width-80)/4, 19, &eoa->flag, 0, 0, 0, 0, "Replace the display mesh");
uiDefButBitS(block, TOG, ACT_EDOB_REPLACE_MESH_PHYS, B_NOP, "Phys", xco+40 + (width-80)/2 +(width-80)/4, yco-44, (width-80)/4, 19, &eoa->flag, 0, 0, 0, 0, "Replace the physics mesh (triangle bounds only. compound shapes not supported)");
}
else if(eoa->type==ACT_EDOB_TRACK_TO) {
ysize= 48;

@ -638,7 +638,10 @@ void BL_ConvertActuators(char* maggiename,
= new KX_SCA_ReplaceMeshActuator(
gameobj,
tmpmesh,
scene
scene,
(editobact->flag & ACT_EDOB_REPLACE_MESH_NOGFX)==0,
(editobact->flag & ACT_EDOB_REPLACE_MESH_PHYS)!=0
);
baseact = tmpreplaceact;

@ -55,7 +55,7 @@ public:
//virtual void DelayedReleaseObject(class CValue* gameobj)=0;
virtual void ReplaceMesh(class CValue* gameobj,
void* meshobj)=0;
void* meshobj, bool use_gfx, bool use_phys)=0;
std::vector<SCA_DebugProp*>& GetDebugProperties();
void AddDebugProperty(class CValue* debugprop,
const STR_String &name);

@ -1182,7 +1182,7 @@ PyMethodDef KX_GameObject::Methods[] = {
{"getChildrenRecursive", (PyCFunction)KX_GameObject::sPyGetChildrenRecursive,METH_NOARGS},
{"getPhysicsId", (PyCFunction)KX_GameObject::sPyGetPhysicsId,METH_NOARGS},
{"getPropertyNames", (PyCFunction)KX_GameObject::sPyGetPropertyNames,METH_NOARGS},
{"replaceMesh",(PyCFunction) KX_GameObject::sPyReplaceMesh, METH_O},
{"replaceMesh",(PyCFunction) KX_GameObject::sPyReplaceMesh, METH_VARARGS},
{"endObject",(PyCFunction) KX_GameObject::sPyEndObject, METH_NOARGS},
{"reinstancePhysicsMesh", (PyCFunction)KX_GameObject::sPyReinstancePhysicsMesh,METH_VARARGS},
@ -1260,15 +1260,21 @@ bool KX_GameObject::ConvertPythonVectorArgs(PyObject* args,
}
*/
PyObject* KX_GameObject::PyReplaceMesh(PyObject* value)
PyObject* KX_GameObject::PyReplaceMesh(PyObject* args)
{
KX_Scene *scene = KX_GetActiveScene();
RAS_MeshObject* new_mesh;
PyObject *value;
int use_gfx= 1, use_phys= 0;
RAS_MeshObject *new_mesh;
if (!PyArg_ParseTuple(args,"O|ii:replaceMesh", &value, &use_gfx, &use_phys))
return NULL;
if (!ConvertPythonToMesh(value, &new_mesh, false, "gameOb.replaceMesh(value): KX_GameObject"))
return NULL;
scene->ReplaceMesh(this, new_mesh);
scene->ReplaceMesh(this, new_mesh, (bool)use_gfx, (bool)use_phys);
Py_RETURN_NONE;
}

@ -865,7 +865,7 @@ public:
KX_PYMETHOD_VARARGS(KX_GameObject,GetMesh);
KX_PYMETHOD_NOARGS(KX_GameObject,GetPhysicsId);
KX_PYMETHOD_NOARGS(KX_GameObject,GetPropertyNames);
KX_PYMETHOD_O(KX_GameObject,ReplaceMesh);
KX_PYMETHOD_VARARGS(KX_GameObject,ReplaceMesh);
KX_PYMETHOD_NOARGS(KX_GameObject,EndObject);
KX_PYMETHOD_DOC(KX_GameObject,rayCastTo);
KX_PYMETHOD_DOC(KX_GameObject,rayCast);

@ -96,6 +96,8 @@ PyMethodDef KX_SCA_ReplaceMeshActuator::Methods[] = {
PyAttributeDef KX_SCA_ReplaceMeshActuator::Attributes[] = {
KX_PYATTRIBUTE_RW_FUNCTION("mesh", KX_SCA_ReplaceMeshActuator, pyattr_get_mesh, pyattr_set_mesh),
KX_PYATTRIBUTE_BOOL_RW ("useDisplayMesh", KX_SCA_ReplaceMeshActuator, m_use_gfx),
KX_PYATTRIBUTE_BOOL_RW ("usePhysicsMesh", KX_SCA_ReplaceMeshActuator, m_use_phys),
{ NULL } //Sentinel
};
@ -179,11 +181,15 @@ KX_PYMETHODDEF_DOC(KX_SCA_ReplaceMeshActuator, instantReplaceMesh,
KX_SCA_ReplaceMeshActuator::KX_SCA_ReplaceMeshActuator(SCA_IObject *gameobj,
class RAS_MeshObject *mesh,
SCA_IScene* scene,
bool use_gfx,
bool use_phys,
PyTypeObject* T) :
SCA_IActuator(gameobj, T),
m_mesh(mesh),
m_scene(scene)
m_scene(scene),
m_use_gfx(use_gfx),
m_use_phys(use_phys)
{
} /* End of constructor */
@ -205,7 +211,8 @@ bool KX_SCA_ReplaceMeshActuator::Update()
if (bNegativeEvent)
return false; // do nothing on negative events
if (m_mesh) m_scene->ReplaceMesh(GetParent(),m_mesh);
if (m_mesh || m_use_phys) /* NULL mesh is ok if were updating physics */
m_scene->ReplaceMesh(GetParent(),m_mesh, m_use_gfx, m_use_phys);
return false;
}
@ -227,7 +234,7 @@ CValue* KX_SCA_ReplaceMeshActuator::GetReplica()
void KX_SCA_ReplaceMeshActuator::InstantReplaceMesh()
{
if (m_mesh) m_scene->ReplaceMesh(GetParent(),m_mesh);
if (m_mesh) m_scene->ReplaceMesh(GetParent(),m_mesh, m_use_gfx, m_use_phys);
}
/* eof */

@ -50,12 +50,16 @@ class KX_SCA_ReplaceMeshActuator : public SCA_IActuator
// mesh reference (mesh to replace)
RAS_MeshObject* m_mesh;
SCA_IScene* m_scene;
bool m_use_phys;
bool m_use_gfx;
public:
KX_SCA_ReplaceMeshActuator(
SCA_IObject* gameobj,
RAS_MeshObject *mesh,
SCA_IScene* scene,
bool use_gfx,
bool use_phys,
PyTypeObject* T=&Type
);

@ -1017,92 +1017,119 @@ int KX_Scene::NewRemoveObject(class CValue* gameobj)
void KX_Scene::ReplaceMesh(class CValue* obj,void* meshobj)
void KX_Scene::ReplaceMesh(class CValue* obj,void* meshobj, bool use_gfx, bool use_phys)
{
KX_GameObject* gameobj = static_cast<KX_GameObject*>(obj);
RAS_MeshObject* mesh = static_cast<RAS_MeshObject*>(meshobj);
if(!gameobj || !mesh)
{
std::cout << "warning: invalid object, mesh will not be replaced" << std::endl;
if(!gameobj) {
std::cout << "KX_Scene::ReplaceMesh Warning: invalid object, doing nothing" << std::endl;
return;
}
gameobj->RemoveMeshes();
gameobj->AddMesh(mesh);
if (gameobj->m_isDeformable)
{
BL_DeformableGameObject* newobj = static_cast<BL_DeformableGameObject*>( gameobj );
if(use_gfx && mesh != NULL)
{
gameobj->RemoveMeshes();
gameobj->AddMesh(mesh);
if (newobj->GetDeformer())
if (gameobj->m_isDeformable)
{
delete newobj->GetDeformer();
newobj->SetDeformer(NULL);
}
if (mesh->IsDeformed())
{
// we must create a new deformer but which one?
KX_GameObject* parentobj = newobj->GetParent();
// this always return the original game object (also for replicate)
Object* blendobj = newobj->GetBlenderObject();
// object that owns the new mesh
Object* oldblendobj = static_cast<struct Object*>(m_logicmgr->FindBlendObjByGameMeshName(mesh->GetName()));
Mesh* blendmesh = mesh->GetMesh();
bool bHasModifier = BL_ModifierDeformer::HasCompatibleDeformer(blendobj);
bool bHasShapeKey = blendmesh->key != NULL && blendmesh->key->type==KEY_RELATIVE;
bool bHasDvert = blendmesh->dvert != NULL;
bool bHasArmature =
parentobj && // current parent is armature
parentobj->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE &&
oldblendobj && // needed for mesh deform
blendobj->parent && // original object had armature (not sure this test is needed)
blendobj->parent->type == OB_ARMATURE &&
blendobj->partype==PARSKEL &&
blendmesh->dvert!=NULL; // mesh has vertex group
bool releaseParent = true;
BL_DeformableGameObject* newobj = static_cast<BL_DeformableGameObject*>( gameobj );
if (oldblendobj==NULL) {
std::cout << "warning: ReplaceMesh() new mesh is not used in an object from the current scene, you will get incorrect behavior" << std::endl;
bHasShapeKey= bHasDvert= bHasArmature=bHasModifier= false;
if (newobj->GetDeformer())
{
delete newobj->GetDeformer();
newobj->SetDeformer(NULL);
}
if (bHasModifier)
if (mesh->IsDeformed())
{
BL_ModifierDeformer* modifierDeformer;
if (bHasShapeKey || bHasArmature)
{
modifierDeformer = new BL_ModifierDeformer(
newobj,
oldblendobj, blendobj,
static_cast<BL_SkinMeshObject*>(mesh),
true,
static_cast<BL_ArmatureObject*>( parentobj )
);
releaseParent= false;
modifierDeformer->LoadShapeDrivers(blendobj->parent);
// we must create a new deformer but which one?
KX_GameObject* parentobj = newobj->GetParent();
// this always return the original game object (also for replicate)
Object* blendobj = newobj->GetBlenderObject();
// object that owns the new mesh
Object* oldblendobj = static_cast<struct Object*>(m_logicmgr->FindBlendObjByGameMeshName(mesh->GetName()));
Mesh* blendmesh = mesh->GetMesh();
bool bHasModifier = BL_ModifierDeformer::HasCompatibleDeformer(blendobj);
bool bHasShapeKey = blendmesh->key != NULL && blendmesh->key->type==KEY_RELATIVE;
bool bHasDvert = blendmesh->dvert != NULL;
bool bHasArmature =
parentobj && // current parent is armature
parentobj->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE &&
oldblendobj && // needed for mesh deform
blendobj->parent && // original object had armature (not sure this test is needed)
blendobj->parent->type == OB_ARMATURE &&
blendobj->partype==PARSKEL &&
blendmesh->dvert!=NULL; // mesh has vertex group
bool releaseParent = true;
if (oldblendobj==NULL) {
std::cout << "warning: ReplaceMesh() new mesh is not used in an object from the current scene, you will get incorrect behavior" << std::endl;
bHasShapeKey= bHasDvert= bHasArmature=bHasModifier= false;
}
else
if (bHasModifier)
{
modifierDeformer = new BL_ModifierDeformer(
newobj,
oldblendobj, blendobj,
static_cast<BL_SkinMeshObject*>(mesh),
false,
NULL
);
BL_ModifierDeformer* modifierDeformer;
if (bHasShapeKey || bHasArmature)
{
modifierDeformer = new BL_ModifierDeformer(
newobj,
oldblendobj, blendobj,
static_cast<BL_SkinMeshObject*>(mesh),
true,
static_cast<BL_ArmatureObject*>( parentobj )
);
releaseParent= false;
modifierDeformer->LoadShapeDrivers(blendobj->parent);
}
else
{
modifierDeformer = new BL_ModifierDeformer(
newobj,
oldblendobj, blendobj,
static_cast<BL_SkinMeshObject*>(mesh),
false,
NULL
);
}
newobj->SetDeformer(modifierDeformer);
}
else if (bHasShapeKey)
{
BL_ShapeDeformer* shapeDeformer;
if (bHasArmature)
{
shapeDeformer = new BL_ShapeDeformer(
newobj,
oldblendobj, blendobj,
static_cast<BL_SkinMeshObject*>(mesh),
true,
true,
static_cast<BL_ArmatureObject*>( parentobj )
);
releaseParent= false;
shapeDeformer->LoadShapeDrivers(blendobj->parent);
}
else
{
shapeDeformer = new BL_ShapeDeformer(
newobj,
oldblendobj, blendobj,
static_cast<BL_SkinMeshObject*>(mesh),
false,
true,
NULL
);
}
newobj->SetDeformer( shapeDeformer);
}
newobj->SetDeformer(modifierDeformer);
}
else if (bHasShapeKey)
{
BL_ShapeDeformer* shapeDeformer;
if (bHasArmature)
else if (bHasArmature)
{
shapeDeformer = new BL_ShapeDeformer(
BL_SkinDeformer* skinDeformer = new BL_SkinDeformer(
newobj,
oldblendobj, blendobj,
static_cast<BL_SkinMeshObject*>(mesh),
@ -1111,49 +1138,28 @@ void KX_Scene::ReplaceMesh(class CValue* obj,void* meshobj)
static_cast<BL_ArmatureObject*>( parentobj )
);
releaseParent= false;
shapeDeformer->LoadShapeDrivers(blendobj->parent);
newobj->SetDeformer(skinDeformer);
}
else
else if (bHasDvert)
{
shapeDeformer = new BL_ShapeDeformer(
newobj,
oldblendobj, blendobj,
static_cast<BL_SkinMeshObject*>(mesh),
false,
true,
NULL
BL_MeshDeformer* meshdeformer = new BL_MeshDeformer(
newobj, oldblendobj, static_cast<BL_SkinMeshObject*>(mesh)
);
newobj->SetDeformer(meshdeformer);
}
newobj->SetDeformer( shapeDeformer);
// release parent reference if its not being used
if( releaseParent && parentobj)
parentobj->Release();
}
else if (bHasArmature)
{
BL_SkinDeformer* skinDeformer = new BL_SkinDeformer(
newobj,
oldblendobj, blendobj,
static_cast<BL_SkinMeshObject*>(mesh),
true,
true,
static_cast<BL_ArmatureObject*>( parentobj )
);
releaseParent= false;
newobj->SetDeformer(skinDeformer);
}
else if (bHasDvert)
{
BL_MeshDeformer* meshdeformer = new BL_MeshDeformer(
newobj, oldblendobj, static_cast<BL_SkinMeshObject*>(mesh)
);
newobj->SetDeformer(meshdeformer);
}
// release parent reference if its not being used
if( releaseParent && parentobj)
parentobj->Release();
}
gameobj->AddMeshUser();
}
if(use_phys) { /* update the new assigned mesh with the physics mesh */
KX_ReInstanceBulletShapeFromMesh(gameobj, NULL, use_gfx?NULL:mesh);
}
gameobj->AddMeshUser();
}
KX_Camera* KX_Scene::FindCamera(KX_Camera* cam)
@ -1844,4 +1850,4 @@ KX_PYMETHODDEF_DOC(KX_Scene, addObject,
// the object is added to the scene so we dont want python to own a reference
replica->Release();
return replica->GetProxy();
}
}

@ -323,7 +323,7 @@ public:
int NewRemoveObject(CValue* gameobj);
void ReplaceMesh(CValue* gameobj,
void* meshobj);
void* meshob, bool use_gfx, bool use_phys);
/**
* @section Logic stuff
* Initiate an update of the logic system.

@ -1642,10 +1642,14 @@ class KX_GameObject(SCA_IObject):
Delete this object, can be used inpace of the EndObject Actuator.
The actual removal of the object from the scene is delayed.
"""
def replaceMesh(mesh):
def replaceMesh(mesh, useDisplayMesh=True, usePhysicsMesh=False):
"""
Replace the mesh of this object with a new mesh. This works the same was as the actuator.
@type mesh: L{KX_MeshProxy} or mesh name
@type useDisplayMesh: bool
@param useDisplayMesh: when enabled the display mesh will be replaced (optional argument).
@type usePhysicsMesh: bool
@param usePhysicsMesh: when enabled the physics mesh will be replaced (optional argument).
"""
def getVisible():
"""
@ -3791,6 +3795,11 @@ class KX_SCA_ReplaceMeshActuator(SCA_IActuator):
@ivar mesh: L{KX_MeshProxy} or the name of the mesh that will replace the current one
Set to None to disable actuator
@type mesh: L{KX_MeshProxy} or None if no mesh is set
@ivar useDisplayMesh: when true the displayed mesh is replaced.
@type useDisplayMesh: boolean
@ivar usePhysicsMesh: when true the physics mesh is replaced.
@type usePhysicsMesh: boolean
"""
def setMesh(name):
"""