Просмотр исходного кода

Added safe_delete to Lua API which deletes passed object on next frame, added stopTrackingChild to PhysicsScreen, contact events now dispatched after box2d step completes.

Ivan Safrin 12 лет назад
Родитель
Сommit
9f0a1f1905

+ 13 - 0
Bindings/Contents/LUA/API/defaults.lua

@@ -89,6 +89,19 @@ function delete(c)
 	c:__delete()
 end
 
+__safe_delete_list = {}
+
+function __process_safe_delete()
+	for i=1,count(__safe_delete_list) do
+		__safe_delete_list[i]:__delete()
+	end
+	__safe_delete_list = {}
+end
+
+function safe_delete(c)
+	__safe_delete_list[count(__safe_delete_list)+1] = c
+end
+
 function onKeyDown(key)
 end
 

+ 1 - 1
Bindings/Scripts/create_lua_library/create_lua_library.py

@@ -122,7 +122,7 @@ def createLUABindings(inputPath, prefix, mainInclude, libSmallName, libName, api
 
 	# list of classes that don't get the garbage collection in their meta table
 
-	disable_gc = ["Entity", "ScreenEntity", "ScreenShape", "ScreenMesh", "ScreenLabel", "SceneLabel", "SceneMesh", "Screen", "Scene", "Texture", "Image", "Camera", "ScreenParticleEmitter", "SceneParticleEmitter", "Mesh", "Vertex", "Polygon", "Polycode::Polygon", "Material", "ScenePrimitive", "SceneLine", "SceneLight", "SceneSound", "ScreenImage", "SceneEntity"]
+	disable_gc = ["Entity", "ScreenEntity", "ScreenShape", "ScreenMesh", "ScreenLabel", "SceneLabel", "SceneMesh", "Screen", "Scene", "Texture", "Image", "Camera", "ScreenParticleEmitter", "SceneParticleEmitter", "Mesh", "Vertex", "Polygon", "Polycode::Polygon", "Material", "ScenePrimitive", "SceneLine", "SceneLight", "SceneSound", "ScreenImage", "SceneEntity", "ScreenEntityInstance"]
 
 	# Special case: If we are building the Polycode library itself, inject the LuaEventHandler class.
 	# Note: so that event callbacks can work, any object inheriting from EventHandler will secretly

+ 10 - 2
Modules/Contents/2DPhysics/Include/PolyPhysicsScreen.h

@@ -200,6 +200,13 @@ public:
 	*/
 	PhysicsScreenEntity *trackPhysicsChild(ScreenEntity *newEntity, int entType, bool isStatic, Number friction=0.1, Number density=1, Number restitution = 0, bool isSensor = false, bool fixedRotation = false, int groupIndex = 0);
     
+	
+	/**
+	* Stops physics tracking for this entity but does not remove from screen.
+	* @param entity Entity to stop tracking for.
+	*/
+	void stopTrackingChild(ScreenEntity *entity);
+		
 	/**
 	* Removes a physics child from the screen.
 	* @param entityToRemove Entity to remove from the screen.
@@ -401,8 +408,9 @@ protected:
 	
     Number worldScale;
     
-    std::vector <PhysicsScreenEntity*> physicsChildren;		
-	
+    std::vector <PhysicsScreenEntity*> physicsChildren;
+	std::vector<PhysicsScreenEvent*> eventsToDispatch;
+			
 	void init(Number worldScale, Number physicsTimeStep, int velIterations, int posIterations, Vector2 physicsGravity);
 
 	std::vector<b2Contact*> contacts;

+ 25 - 7
Modules/Contents/2DPhysics/Source/PolyPhysicsScreen.cpp

@@ -92,7 +92,8 @@ void PhysicsScreen::BeginContact (b2Contact *contact) {
 
     newEvent->contact = contact;
     
-	dispatchEvent(newEvent, PhysicsScreenEvent::EVENT_NEW_SHAPE_COLLISION);
+	newEvent->setEventCode(PhysicsScreenEvent::EVENT_NEW_SHAPE_COLLISION);
+	eventsToDispatch.push_back(newEvent);
 	
 	contacts.push_back(contact);
 }
@@ -140,7 +141,9 @@ void PhysicsScreen::PostSolve(b2Contact* contact, const b2ContactImpulse* impuls
 			newEvent->frictionStrength = impulse->tangentImpulses[i];		
 	}
 
-	dispatchEvent(newEvent, PhysicsScreenEvent::EVENT_SOLVE_SHAPE_COLLISION);
+	newEvent->setEventCode(PhysicsScreenEvent::EVENT_SOLVE_SHAPE_COLLISION);
+	eventsToDispatch.push_back(newEvent);
+
 }
 
 void PhysicsScreen::EndContact (b2Contact *contact) {
@@ -155,8 +158,9 @@ void PhysicsScreen::EndContact (b2Contact *contact) {
 			break;
 		}
 	}
-	
-	dispatchEvent(newEvent, PhysicsScreenEvent::EVENT_END_SHAPE_COLLISION);
+	newEvent->setEventCode(PhysicsScreenEvent::EVENT_END_SHAPE_COLLISION);
+	eventsToDispatch.push_back(newEvent);
+
 }
 
 bool PhysicsScreen::isEntityColliding(ScreenEntity *ent1) {
@@ -478,18 +482,26 @@ PhysicsScreenEntity *PhysicsScreen::trackPhysicsChild(ScreenEntity *newEntity, i
 	return newPhysicsEntity;
 }
 
-void PhysicsScreen::removePhysicsChild(ScreenEntity *entityToRemove) {
-	PhysicsScreenEntity *physicsEntityToRemove = getPhysicsByScreenEntity(entityToRemove);
+void PhysicsScreen::stopTrackingChild(ScreenEntity *entity) {
+	PhysicsScreenEntity *physicsEntityToRemove = getPhysicsByScreenEntity(entity);
 	if(!physicsEntityToRemove) {
 		return;
 	}
+	
 	world->DestroyBody(physicsEntityToRemove->body);
-    physicsEntityToRemove->body = NULL;
+	physicsEntityToRemove->body = NULL;	
+				
 	for(int i=0;i<physicsChildren.size();i++) {
 		if(physicsChildren[i] == physicsEntityToRemove) {
 			physicsChildren.erase(physicsChildren.begin()+i);
 		}
 	}
+	
+	delete physicsEntityToRemove;
+}
+
+void PhysicsScreen::removePhysicsChild(ScreenEntity *entityToRemove) {
+	stopTrackingChild(entityToRemove);
 	Screen::removeChild(entityToRemove);	
 }
 
@@ -547,6 +559,12 @@ void PhysicsScreen::Update() {
 		}
 		world->Step(timeStep, velocityIterations,positionIterations);
 	}
+	
+	for(int i=0; i < eventsToDispatch.size(); i++) {
+		dispatchEvent(eventsToDispatch[i], eventsToDispatch[i]->getEventCode());
+	}
+	eventsToDispatch.clear();
+	
 	cyclesLeftOver = elapsed;
 	Screen::Update();
 }

+ 5 - 2
Player/Contents/Source/PolycodePlayer.cpp

@@ -891,9 +891,12 @@ bool PolycodePlayer::Update() {
 			doCodeInject = false;			
 			report(L, luaL_loadstring(L, injectCodeString.c_str()));
 			lua_pcall(L, 0,0,errH);		
-		}
-	
+		}	
 		if(!crashed) {
+		
+			lua_getfield(L, LUA_GLOBALSINDEX, "__process_safe_delete");
+			lua_pcall(L, 0,0,errH);	
+		
 			lua_getfield(L, LUA_GLOBALSINDEX, "Update");
 			lua_pushnumber(L, core->getElapsed());
 			lua_pcall(L, 1,0,errH);