Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/gameengine/Ketsji/KX_Scene.cpp')
-rw-r--r--source/gameengine/Ketsji/KX_Scene.cpp288
1 files changed, 190 insertions, 98 deletions
diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp
index aa7bd65f240..c0d8a7090c4 100644
--- a/source/gameengine/Ketsji/KX_Scene.cpp
+++ b/source/gameengine/Ketsji/KX_Scene.cpp
@@ -34,7 +34,7 @@
#include "KX_Scene.h"
#include "MT_assert.h"
-
+#include "SND_Scene.h"
#include "KX_KetsjiEngine.h"
#include "KX_BlenderMaterial.h"
#include "RAS_IPolygonMaterial.h"
@@ -80,6 +80,7 @@
#include "KX_BlenderSceneConverter.h"
#include "KX_MotionState.h"
+#include "BL_ModifierDeformer.h"
#include "BL_ShapeDeformer.h"
#include "BL_DeformableGameObject.h"
@@ -110,7 +111,22 @@ void* KX_SceneDestructionFunc(SG_IObject* node,void* gameobj,void* scene)
return NULL;
};
-SG_Callbacks KX_Scene::m_callbacks = SG_Callbacks(KX_SceneReplicationFunc,KX_SceneDestructionFunc,KX_GameObject::UpdateTransformFunc);
+bool KX_Scene::KX_ScenegraphUpdateFunc(SG_IObject* node,void* gameobj,void* scene)
+{
+ return ((SG_Node*)node)->Schedule(((KX_Scene*)scene)->m_sghead);
+}
+
+bool KX_Scene::KX_ScenegraphRescheduleFunc(SG_IObject* node,void* gameobj,void* scene)
+{
+ return ((SG_Node*)node)->Reschedule(((KX_Scene*)scene)->m_sghead);
+}
+
+SG_Callbacks KX_Scene::m_callbacks = SG_Callbacks(
+ KX_SceneReplicationFunc,
+ KX_SceneDestructionFunc,
+ KX_GameObject::UpdateTransformFunc,
+ KX_Scene::KX_ScenegraphUpdateFunc,
+ KX_Scene::KX_ScenegraphRescheduleFunc);
// temporarily var until there is a button in the userinterface
// (defined in KX_PythonInit.cpp)
@@ -148,7 +164,6 @@ KX_Scene::KX_Scene(class SCA_IInputDevice* keyboarddevice,
m_lightlist= new CListValue();
m_inactivelist = new CListValue();
m_euthanasyobjects = new CListValue();
- m_delayReleaseObjects = new CListValue();
m_logicmgr = new SCA_LogicManager();
@@ -192,9 +207,6 @@ KX_Scene::KX_Scene(class SCA_IInputDevice* keyboarddevice,
m_rootnode = NULL;
m_bucketmanager=new RAS_BucketManager();
-
- m_canvasDesignWidth = 0;
- m_canvasDesignHeight = 0;
m_attr_dict = PyDict_New(); /* new ref */
}
@@ -231,8 +243,6 @@ KX_Scene::~KX_Scene()
if (m_euthanasyobjects)
m_euthanasyobjects->Release();
- if (m_delayReleaseObjects)
- m_delayReleaseObjects->Release();
if (m_logicmgr)
delete m_logicmgr;
@@ -254,13 +264,6 @@ KX_Scene::~KX_Scene()
Py_DECREF(m_attr_dict);
}
-void KX_Scene::SetProjectionMatrix(MT_CmMatrix4x4& pmat)
-{
- m_projectionmat = pmat;
-}
-
-
-
RAS_BucketManager* KX_Scene::GetBucketManager()
{
return m_bucketmanager;
@@ -408,11 +411,11 @@ void KX_Scene::RemoveNodeDestructObject(class SG_IObject* node,class CValue* gam
KX_GameObject* orgobj = (KX_GameObject*)gameobj;
if (NewRemoveObject(orgobj) != 0)
{
- // object is not yet deleted (this can happen when it hangs in an add object actuator
- // last object created reference. It's a bad situation, don't know how to fix it exactly
- // The least I can do, is remove the reference to the node in the object as the node
- // will in any case be deleted. This ensures that the object will not try to use the node
- // when it is finally deleted (see KX_GameObject destructor)
+ // object is not yet deleted because a reference is hanging somewhere.
+ // This should not happen anymore since we use proxy object for Python
+ // confident enough to put an assert?
+ //assert(false);
+ printf("Zombie object! name=%s\n", orgobj->GetName().ReadPtr());
orgobj->SetSGNode(NULL);
PHY_IGraphicController* ctrl = orgobj->GetGraphicController();
if (ctrl)
@@ -477,6 +480,8 @@ KX_GameObject* KX_Scene::AddNodeReplicaObject(class SG_IObject* node, class CVal
// this is the list of object that are send to the graphics pipeline
m_objectlist->Add(newobj->AddRef());
+ if (newobj->IsLight())
+ m_lightlist->Add(newobj->AddRef());
newobj->AddMeshUser();
// logic cannot be replicated, until the whole hierarchy is replicated.
@@ -537,8 +542,9 @@ void KX_Scene::ReplicateLogic(KX_GameObject* newobj)
vector<SCA_IActuator*> linkedactuators = cont->GetLinkedActuators();
// disconnect the sensors and actuators
- cont->UnlinkAllSensors();
- cont->UnlinkAllActuators();
+ // do it directly on the list at this controller is not connected to anything at this stage
+ cont->GetLinkedSensors().clear();
+ cont->GetLinkedActuators().clear();
// now relink each sensor
for (vector<SCA_ISensor*>::iterator its = linkedsensors.begin();!(its==linkedsensors.end());its++)
@@ -716,16 +722,20 @@ void KX_Scene::DupliGroupRecurse(CValue* obj, int level)
// set the replica's relative scale with the rootnode's scale
replica->NodeSetRelativeScale(newscale);
- MT_Matrix3x3 newori = groupobj->NodeGetWorldOrientation() * gameobj->NodeGetWorldOrientation();
- replica->NodeSetLocalOrientation(newori);
MT_Point3 offset(group->dupli_ofs);
MT_Point3 newpos = groupobj->NodeGetWorldPosition() +
newscale*(groupobj->NodeGetWorldOrientation() * (gameobj->NodeGetWorldPosition()-offset));
replica->NodeSetLocalPosition(newpos);
-
+ // set the orientation after position for softbody!
+ MT_Matrix3x3 newori = groupobj->NodeGetWorldOrientation() * gameobj->NodeGetWorldOrientation();
+ replica->NodeSetLocalOrientation(newori);
+ // update scenegraph for entire tree of children
replica->GetSGNode()->UpdateWorldData(0);
replica->GetSGNode()->SetBBox(gameobj->GetSGNode()->BBox());
replica->GetSGNode()->SetRadius(gameobj->GetSGNode()->Radius());
+ // we can now add the graphic controller to the physic engine
+ replica->ActivateGraphicController(true);
+
// done with replica
replica->Release();
}
@@ -836,6 +846,8 @@ SCA_IObject* KX_Scene::AddReplicaObject(class CValue* originalobject,
replica->GetSGNode()->UpdateWorldData(0);
replica->GetSGNode()->SetBBox(originalobj->GetSGNode()->BBox());
replica->GetSGNode()->SetRadius(originalobj->GetSGNode()->Radius());
+ // the size is correct, we can add the graphic controller to the physic engine
+ replica->ActivateGraphicController(true);
// now replicate logic
vector<KX_GameObject*>::iterator git;
@@ -889,7 +901,7 @@ void KX_Scene::RemoveObject(class CValue* gameobj)
{
KX_GameObject* newobj = (KX_GameObject*) gameobj;
- // first disconnect child from parent
+ // disconnect child from parent
SG_Node* node = newobj->GetSGNode();
if (node)
@@ -903,12 +915,6 @@ void KX_Scene::RemoveObject(class CValue* gameobj)
//newobj->SetSGNode(0);
}
-void KX_Scene::DelayedReleaseObject(CValue* gameobj)
-{
- m_delayReleaseObjects->Add(gameobj->AddRef());
-}
-
-
void KX_Scene::DelayedRemoveObject(class CValue* gameobj)
{
//KX_GameObject* newobj = (KX_GameObject*) gameobj;
@@ -925,6 +931,13 @@ int KX_Scene::NewRemoveObject(class CValue* gameobj)
int ret;
KX_GameObject* newobj = (KX_GameObject*) gameobj;
+ /* Invalidate the python reference, since the object may exist in script lists
+ * its possible that it wont be automatically invalidated, so do it manually here,
+ *
+ * if for some reason the object is added back into the scene python can always get a new Proxy
+ */
+ newobj->InvalidateProxy();
+
// keep the blender->game object association up to date
// note that all the replicas of an object will have the same
// blender object, that's why we need to check the game object
@@ -954,7 +967,7 @@ int KX_Scene::NewRemoveObject(class CValue* gameobj)
for (SCA_ActuatorList::iterator ita = actuators.begin();
!(ita==actuators.end());ita++)
{
- m_logicmgr->RemoveDestroyedActuator(*ita);
+ m_logicmgr->RemoveActuator(*ita);
}
// the sensors/controllers/actuators must also be released, this is done in ~SCA_IObject
@@ -1038,6 +1051,7 @@ void KX_Scene::ReplaceMesh(class CValue* obj,void* meshobj)
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 =
@@ -1053,10 +1067,39 @@ void KX_Scene::ReplaceMesh(class CValue* obj,void* meshobj)
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= false;
+ bHasShapeKey= bHasDvert= bHasArmature=bHasModifier= false;
}
- if (bHasShapeKey)
+ if (bHasModifier)
+ {
+ BL_ModifierDeformer* modifierDeformer;
+ if (bHasShapeKey || bHasArmature)
+ {
+ modifierDeformer = new BL_ModifierDeformer(
+ newobj,
+ m_blenderScene,
+ 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,
+ m_blenderScene,
+ oldblendobj, blendobj,
+ static_cast<BL_SkinMeshObject*>(mesh),
+ false,
+ NULL
+ );
+ }
+ newobj->SetDeformer(modifierDeformer);
+ }
+ else if (bHasShapeKey)
{
BL_ShapeDeformer* shapeDeformer;
if (bHasArmature)
@@ -1066,6 +1109,7 @@ void KX_Scene::ReplaceMesh(class CValue* obj,void* meshobj)
oldblendobj, blendobj,
static_cast<BL_SkinMeshObject*>(mesh),
true,
+ true,
static_cast<BL_ArmatureObject*>( parentobj )
);
releaseParent= false;
@@ -1078,6 +1122,7 @@ void KX_Scene::ReplaceMesh(class CValue* obj,void* meshobj)
oldblendobj, blendobj,
static_cast<BL_SkinMeshObject*>(mesh),
false,
+ true,
NULL
);
}
@@ -1090,6 +1135,7 @@ void KX_Scene::ReplaceMesh(class CValue* obj,void* meshobj)
oldblendobj, blendobj,
static_cast<BL_SkinMeshObject*>(mesh),
true,
+ true,
static_cast<BL_ArmatureObject*>( parentobj )
);
releaseParent= false;
@@ -1112,24 +1158,6 @@ void KX_Scene::ReplaceMesh(class CValue* obj,void* meshobj)
gameobj->AddMeshUser();
}
-
-
-MT_CmMatrix4x4& KX_Scene::GetViewMatrix()
-{
- MT_Scalar cammat[16];
- m_active_camera->GetWorldToCamera().getValue(cammat);
- m_viewmat = cammat;
- return m_viewmat;
-}
-
-
-
-MT_CmMatrix4x4& KX_Scene::GetProjectionMatrix()
-{
- return m_projectionmat;
-}
-
-
KX_Camera* KX_Scene::FindCamera(KX_Camera* cam)
{
list<KX_Camera*>::iterator it = m_cameras.begin();
@@ -1423,24 +1451,17 @@ void KX_Scene::LogicEndFrame()
{
m_logicmgr->EndFrame();
int numobj = m_euthanasyobjects->GetCount();
- int i;
- for (i = numobj - 1; i >= 0; i--)
- {
- KX_GameObject* gameobj = (KX_GameObject*)m_euthanasyobjects->GetValue(i);
- // KX_Scene::RemoveObject will also remove the object from this list
- // that's why we start from the end
- this->RemoveObject(gameobj);
- }
- numobj= m_delayReleaseObjects->GetCount();
- for (i = numobj-1;i>=0;i--)
+ KX_GameObject* obj;
+
+ while ((numobj = m_euthanasyobjects->GetCount()) > 0)
{
- KX_GameObject* gameobj = (KX_GameObject*)m_delayReleaseObjects->GetValue(i);
- // This list is not for object removal, but just object release
- gameobj->Release();
+ // remove the object from this list to make sure we will not hit it again
+ obj = (KX_GameObject*)m_euthanasyobjects->GetValue(numobj-1);
+ m_euthanasyobjects->Remove(numobj-1);
+ obj->Release();
+ RemoveObject(obj);
}
- // empty the list as we have removed all references
- m_delayReleaseObjects->Resize(0);
}
@@ -1450,15 +1471,28 @@ void KX_Scene::LogicEndFrame()
*/
void KX_Scene::UpdateParents(double curtime)
{
-// int numrootobjects = GetRootParentList()->GetCount();
+ // we use the SG dynamic list
+ SG_Node* node;
- for (int i=0; i<GetRootParentList()->GetCount(); i++)
+ while ((node = SG_Node::GetNextScheduled(m_sghead)) != NULL)
{
- KX_GameObject* parentobj = (KX_GameObject*)GetRootParentList()->GetValue(i);
- parentobj->NodeUpdateGS(curtime);
+ node->UpdateWorldData(curtime);
}
-}
+ //for (int i=0; i<GetRootParentList()->GetCount(); i++)
+ //{
+ // KX_GameObject* parentobj = (KX_GameObject*)GetRootParentList()->GetValue(i);
+ // parentobj->NodeUpdateGS(curtime);
+ //}
+
+ // the list must be empty here
+ assert(m_sghead.Empty());
+ // some nodes may be ready for reschedule, move them to schedule list for next time
+ while ((node = SG_Node::GetNextRescheduled(m_sghead)) != NULL)
+ {
+ node->Schedule(m_sghead);
+ }
+}
RAS_MaterialBucket* KX_Scene::FindBucket(class RAS_IPolyMaterial* polymat, bool &bucketCreated)
@@ -1579,8 +1613,13 @@ double KX_Scene::getSuspendedDelta()
//Python
PyTypeObject KX_Scene::Type = {
- PyObject_HEAD_INIT(NULL)
- 0,
+#if (PY_VERSION_HEX >= 0x02060000)
+ PyVarObject_HEAD_INIT(NULL, 0)
+#else
+ /* python 2.5 and below */
+ PyObject_HEAD_INIT( NULL ) /* required py macro */
+ 0, /* ob_size */
+#endif
"KX_Scene",
sizeof(PyObjectPlus_Proxy),
0,
@@ -1604,9 +1643,9 @@ PyParentObject KX_Scene::Parents[] = {
};
PyMethodDef KX_Scene::Methods[] = {
- KX_PYMETHODTABLE(KX_Scene, getLightList),
- KX_PYMETHODTABLE(KX_Scene, getObjectList),
- KX_PYMETHODTABLE(KX_Scene, getName),
+ KX_PYMETHODTABLE_NOARGS(KX_Scene, getLightList),
+ KX_PYMETHODTABLE_NOARGS(KX_Scene, getObjectList),
+ KX_PYMETHODTABLE_NOARGS(KX_Scene, getName),
KX_PYMETHODTABLE(KX_Scene, addObject),
{NULL,NULL} //Sentinel
@@ -1624,46 +1663,81 @@ PyObject* KX_Scene::pyattr_get_objects(void *self_v, const KX_PYATTRIBUTE_DEF *a
return self->GetObjectList()->GetProxy();
}
+PyObject* KX_Scene::pyattr_get_objects_inactive(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ KX_Scene* self= static_cast<KX_Scene*>(self_v);
+ return self->GetInactiveList()->GetProxy();
+}
+
+PyObject* KX_Scene::pyattr_get_lights(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ KX_Scene* self= static_cast<KX_Scene*>(self_v);
+ return self->GetLightList()->GetProxy();
+}
+
+PyObject* KX_Scene::pyattr_get_cameras(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ /* With refcounts in this case...
+ * the new CListValue is owned by python, so its possible python holds onto it longer then the BGE
+ * however this is the same with "scene.objects + []", when you make a copy by adding lists.
+ */
+
+ KX_Scene* self= static_cast<KX_Scene*>(self_v);
+ CListValue* clist = new CListValue();
+
+ /* return self->GetCameras()->GetProxy(); */
+
+ list<KX_Camera*>::iterator it = self->GetCameras()->begin();
+ while (it != self->GetCameras()->end()) {
+ clist->Add((*it)->AddRef());
+ it++;
+ }
+
+ return clist->NewProxy(true);
+}
+
PyObject* KX_Scene::pyattr_get_active_camera(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_Scene* self= static_cast<KX_Scene*>(self_v);
return self->GetActiveCamera()->GetProxy();
}
-/* __dict__ only for the purpose of giving useful dir() results */
-PyObject* KX_Scene::pyattr_get_dir_dict(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+
+int KX_Scene::pyattr_set_active_camera(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
{
KX_Scene* self= static_cast<KX_Scene*>(self_v);
- /* Useually done by py_getattro_up but in this case we want to include m_attr_dict dict */
- PyObject *dict_str= PyString_FromString("__dict__");
- PyObject *dict= py_getattr_dict(self->PyObjectPlus::py_getattro(dict_str), Type.tp_dict);
- Py_DECREF(dict_str);
+ KX_Camera *camOb;
- PyDict_Update(dict, self->m_attr_dict);
- return dict;
+ if (!ConvertPythonToCamera(value, &camOb, false, "scene.active_camera = value: KX_Scene"))
+ return PY_SET_ATTR_FAIL;
+
+ self->SetActiveCamera(camOb);
+ return PY_SET_ATTR_SUCCESS;
}
+
PyAttributeDef KX_Scene::Attributes[] = {
- KX_PYATTRIBUTE_RO_FUNCTION("name", KX_Scene, pyattr_get_name),
- KX_PYATTRIBUTE_RO_FUNCTION("objects", KX_Scene, pyattr_get_objects),
- KX_PYATTRIBUTE_RO_FUNCTION("active_camera", KX_Scene, pyattr_get_active_camera),
- KX_PYATTRIBUTE_BOOL_RO("suspended", KX_Scene, m_suspend),
- KX_PYATTRIBUTE_BOOL_RO("activity_culling", KX_Scene, m_activity_culling),
+ KX_PYATTRIBUTE_RO_FUNCTION("name", KX_Scene, pyattr_get_name),
+ KX_PYATTRIBUTE_RO_FUNCTION("objects", KX_Scene, pyattr_get_objects),
+ KX_PYATTRIBUTE_RO_FUNCTION("objectsInactive", KX_Scene, pyattr_get_objects_inactive), KX_PYATTRIBUTE_RO_FUNCTION("lights", KX_Scene, pyattr_get_lights),
+ KX_PYATTRIBUTE_RO_FUNCTION("cameras", KX_Scene, pyattr_get_cameras),
+ KX_PYATTRIBUTE_RO_FUNCTION("lights", KX_Scene, pyattr_get_lights),
+ KX_PYATTRIBUTE_RW_FUNCTION("active_camera", KX_Scene, pyattr_get_active_camera, pyattr_set_active_camera),
+ KX_PYATTRIBUTE_BOOL_RO("suspended", KX_Scene, m_suspend),
+ KX_PYATTRIBUTE_BOOL_RO("activity_culling", KX_Scene, m_activity_culling),
KX_PYATTRIBUTE_FLOAT_RW("activity_culling_radius", 0.5f, FLT_MAX, KX_Scene, m_activity_box_radius),
- KX_PYATTRIBUTE_BOOL_RO("dbvt_culling", KX_Scene, m_dbvt_culling),
- KX_PYATTRIBUTE_RO_FUNCTION("__dict__", KX_Scene, pyattr_get_dir_dict),
+ KX_PYATTRIBUTE_BOOL_RO("dbvt_culling", KX_Scene, m_dbvt_culling),
{ NULL } //Sentinel
};
-
PyObject* KX_Scene::py_getattro__internal(PyObject *attr)
{
py_getattro_up(PyObjectPlus);
}
-int KX_Scene::py_setattro__internal(PyObject *attr, PyObject *pyvalue)
+int KX_Scene::py_setattro__internal(PyObject *attr, PyObject *value)
{
- return PyObjectPlus::py_setattro(attr, pyvalue);
+ py_setattro_up(PyObjectPlus);
}
PyObject* KX_Scene::py_getattro(PyObject *attr)
@@ -1685,6 +1759,18 @@ PyObject* KX_Scene::py_getattro(PyObject *attr)
return object;
}
+PyObject* KX_Scene::py_getattro_dict() {
+ //py_getattro_dict_up(PyObjectPlus);
+
+ PyObject *dict= py_getattr_dict(PyObjectPlus::py_getattro_dict(), Type.tp_dict);
+ if(dict==NULL)
+ return NULL;
+
+ /* normally just return this but KX_Scene has some more items */
+
+ PyDict_Update(dict, m_attr_dict);
+ return dict;
+}
int KX_Scene::py_setattro(PyObject *attr, PyObject *value)
{
@@ -1715,6 +1801,7 @@ KX_PYMETHODDEF_DOC_NOARGS(KX_Scene, getLightList,
"Returns a list of all lights in the scene.\n"
)
{
+ ShowDeprecationWarning("getLightList()", "the lights property");
return m_lightlist->GetProxy();
}
@@ -1723,7 +1810,7 @@ KX_PYMETHODDEF_DOC_NOARGS(KX_Scene, getObjectList,
"Returns a list of all game objects in the scene.\n"
)
{
- // ShowDeprecationWarning("getObjectList()", "the objects property"); // XXX Grr, why doesnt this work?
+ ShowDeprecationWarning("getObjectList()", "the objects property");
return m_objectlist->GetProxy();
}
@@ -1732,6 +1819,7 @@ KX_PYMETHODDEF_DOC_NOARGS(KX_Scene, getName,
"Returns the name of the scene.\n"
)
{
+ ShowDeprecationWarning("getName()", "the name property");
return PyString_FromString(GetName());
}
@@ -1753,5 +1841,9 @@ KX_PYMETHODDEF_DOC(KX_Scene, addObject,
SCA_IObject* replica = AddReplicaObject((SCA_IObject*)ob, other, time);
+
+ // release here because AddReplicaObject AddRef's
+ // the object is added to the scene so we dont want python to own a reference
+ replica->Release();
return replica->GetProxy();
-} \ No newline at end of file
+}