Commits

Anonymous committed 4c24191

Added ComponentFactory::delete
Fixed Components from python deletion crash

Comments (0)

Files changed (10)

PolyMain/include/game/PolyComponentFactory.h

 	public:
 		virtual				~IComponentFactory() {}
 
-		virtual Component*	create(Entity entity, const StringVariantMap& values) const = 0;
+		virtual Component*	create(Entity entity, const StringVariantMap& values) = 0;
+		virtual void		destroy(Component*) = 0;
 
 	protected:
 							IComponentFactory() {}
 	template<typename T>
 	class DefaultComponentFactory : public IComponentFactory {
 	public:
-		virtual Component* create(Entity entity, const StringVariantMap& values) const {
+		virtual Component* create(Entity entity, const StringVariantMap& values) {
 			Component* component = new T();
 			component->initialize(entity, values);
 
 			return component;
 		}
+
+		virtual void destroy(Component* component) {
+			POLY_DELETE(component);
+		}
 	};
 }
 

PolyMain/include/game/PolyComponentManager.cpp

 	}
 
 	void ComponentManager::destroyComponent(Component* component) {
-		POLY_DELETE(component);
+		const String& typeName = component->getRuntimeTypeInfo().name;
+
+		TypeNameFactoryMap::const_iterator itr;
+		itr = mFactories.find(typeName);
+
+		if(itr != mFactories.end()) {
+			ComponentFactoryPtr factory = (*itr).second;
+			factory->destroy(component);
+		}
+		else {
+			POLY_LOG_WARNING("Cannot destroy Component properly, factory for type '" << typeName << "' was removed!");
+		}
 	}
 
 	ComponentFactoryPtr ComponentManager::getFactoryByName(const String& typeName) const {

PolyMain/include/game/PolyEntity.cpp

 				msEntitiesByComponentType[typeName].erase(itr);
 		}
 
-		POLY_DELETE(component);
+		gEnv.componentMgr->destroyComponent(component);
 	}
 
 	void Entity::_destroyAllComponents() {
 				pair.second->_notifyOtherComponentRemoved(component);
 			}
 
-			POLY_DELETE(component);
+			gEnv.componentMgr->destroyComponent(component);
 
 			itr = components.erase(itr);
 		}
 	}
-
-	void Entity::save(IStream& bs) const {
-		// TODO fixme
-// 		bs.write(msTypeName[mUniqueID].get());
-// 		bs.write((uint)msComponentsByFamily[mUniqueID].size());
-// 
-// 		ComponentContainer::const_iterator itr;
-// 		for(itr = msComponentsByFamily[mUniqueID].begin(); itr != msComponentsByFamily[mUniqueID].end(); ++itr) {
-// 			IComponent* component = *itr;
-// 			bs.write(component->getTypeName());
-// 			component->save(bs);
-// 		}
-	}
-
-	void Entity::load(IStream& bs) {
-// 		String val;
-// 		bs.read(val);
-// 		msTypeName[mEID] = InternString(val);
-// 
-// 		uint componentSize = 0;
-// 		bs.read(componentSize);
-// 
-// 		for(uint i = 0; i < componentSize; ++i) {
-// 			String typeName;
-// 			bs.read(typeName);
-// 
-// 			StringVariantMap params;
-// 			Component* component = getEngine()->componentMgr->createComponent(*this, typeName, params);
-// 			component->load(bs);
-// 		}
-	}
 }

PolyMain/include/game/PolyEntity.h

 		// Type name
 		const InternString&			getTypeName() const;
 
-		// Serialization
-		void						save(IStream& bs) const;
-		void						load(IStream& bs);
-
 	protected:
 		EntityID					mID;
 

PolyPython/PolyPython.vcxproj

   <ItemGroup>
     <ClInclude Include="include\PolyPython.h" />
     <ClInclude Include="include\PolyPythonBindings.h" />
+    <ClInclude Include="include\PolyPythonComponent.h" />
     <ClInclude Include="include\PolyPythonCoreBindings.h" />
     <ClInclude Include="include\PolyPythonGameBindings.h" />
     <ClInclude Include="include\PolyPythonInputBindings.h" />
     </ClCompile>
     <ClCompile Include="include\PolyPython.cpp" />
     <ClCompile Include="include\PolyPythonBindings.cpp" />
+    <ClCompile Include="include\PolyPythonComponent.cpp" />
     <ClCompile Include="include\PolyPythonPrerequisites.cpp">
       <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
       <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>

PolyPython/PolyPython.vcxproj.filters

       <Filter>python</Filter>
     </ClCompile>
     <ClCompile Include="include\PolyPython.cpp" />
+    <ClCompile Include="include\PolyPythonComponent.cpp" />
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="include\PolyPython.h" />
     <ClInclude Include="include\PolyPythonCoreBindings.h" />
     <ClInclude Include="include\PolyPythonPhysicsBindings.h" />
     <ClInclude Include="include\PolyPythonInputBindings.h" />
+    <ClInclude Include="include\PolyPythonComponent.h" />
   </ItemGroup>
   <ItemGroup>
     <Filter Include="python">

PolyPython/include/PolyPython.cpp

 #include "PolyPythonPrerequisites.h"
 #include <boost/filesystem.hpp>
 #include "PolyPythonBindings.h"
+#include "PolyPythonComponent.h"
 
 #include "PolyPython.h"
 
 			addNativeComponentType<BoxColliderComponent>();
 			addNativeComponentType<MeshColliderComponent>();
 
+			// See _PythonInternComponent.
+			// Components from python are created each with their factory.
+			// But their type info is the same "_PythonInternComponent" for all of them.
+			// That's why we add this factory here. It will only be used to delete
+			// Components, not create them.
+			ComponentFactoryPtr factory(new PythonComponentFactory(bp::object()));
+			gEnv.componentMgr->addComponentType("_PythonInternComponent", factory);
+
 			// Add module search path
 			// TODO fixed path for now
 			boost::filesystem::path path(boost::filesystem::current_path() / boost::filesystem::path("..") / "content");

PolyPython/include/PolyPythonComponent.cpp

+/*
+    Copyright (c) Oliver 'SirPolly' Weitzel
+                                                                                  
+    Permission is hereby granted, free of charge, to any person obtaining a copy
+    of this software and associated documentation files (the "Software"), to deal
+    in the Software without restriction, including without limitation the rights
+    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+    copies of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+                                                                                  
+    The above copyright notice and this permission notice shall be included in
+    all copies or substantial portions of the Software.
+                                                                                  
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+    THE SOFTWARE. 
+    
+*/
+
+#include "PolyPythonPrerequisites.h"
+#include "PolyPython.h"
+
+#include "PolyPythonComponent.h"
+
+
+POLY_CLASS_IMPL(_PythonInternComponent,);
+
+Component* PythonComponentFactory::create(Entity entity, const StringVariantMap& values) {
+	try {
+		bp::object instance = mComponentType.attr("__call__")();
+		PythonComponent* pc = bp::extract<PythonComponent*>(instance);
+		pc->instance = instance;
+
+		return pc;
+	}
+	catch(const bp::error_already_set&) {
+		Poly::Python::_fetchError();
+
+		return POLY_NULLPTR;
+	}
+}

PolyPython/include/PolyPythonComponent.h

+/*
+    Copyright (c) Oliver 'SirPolly' Weitzel
+                                                                                  
+    Permission is hereby granted, free of charge, to any person obtaining a copy
+    of this software and associated documentation files (the "Software"), to deal
+    in the Software without restriction, including without limitation the rights
+    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+    copies of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+                                                                                  
+    The above copyright notice and this permission notice shall be included in
+    all copies or substantial portions of the Software.
+                                                                                  
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+    THE SOFTWARE. 
+    
+*/
+
+#ifndef PolyPythonComponent_h
+#define PolyPythonComponent_h
+
+/** This is the base class of all Components derived in python.
+	This is done to mark every derived Component with the type info
+	of this class.
+*/
+class _PythonInternComponent : public Component {
+public:
+	POLY_CLASS;
+};
+
+class PythonComponent : public _PythonInternComponent {
+public:
+	bp::object instance;
+
+	PythonComponent(PyObject* p)
+		:	mSelf(p) {}
+	PythonComponent(PyObject* p, const Component& self)
+		:	mSelf(p) {}
+
+protected:
+	PyObject* mSelf;
+};
+
+class PythonComponentFactory : public IComponentFactory {
+public:
+	PythonComponentFactory(bp::object componentType)
+		:	mComponentType(componentType) {
+	}
+
+	virtual Component* create(Entity entity, const StringVariantMap& values);
+
+	virtual void destroy(Component* component) {
+		// Do nothing. The Components were allocated in python and will be automatically
+		// deleted by the GC when their time has come.
+	}
+
+protected:
+	bp::object mComponentType;
+};
+
+#endif

PolyPython/include/PolyPythonGameBindings.h

 #define PolyPythonGameBindings_h
 
 #include "PolyPython.h"
+#include "PolyPythonComponent.h"
 
 
 class PythonEntityLogic : public EntityLogic {
 	PyObject* mSelf;
 };
 
-class PythonComponent : public Component {
-public:
-	bp::object instance;
-
-	PythonComponent(PyObject* p)
-	:	mSelf(p) {}
-	PythonComponent(PyObject* p, const Component& self)
-	:	mSelf(p) {}
-
-protected:
-	PyObject* mSelf;
-};
-
-class PythonComponentFactory : public IComponentFactory {
-public:
-	PythonComponentFactory(bp::object componentType)
-	:	mComponentType(componentType) {
-	}
-
-	virtual Component* create(Entity entity, const StringVariantMap& values) const {
-		try {
-			bp::object instance = mComponentType.attr("__call__")();
-			PythonComponent* pc = bp::extract<PythonComponent*>(instance);
-			pc->instance = instance;
-
-			return pc;
-		}
-		catch(const bp::error_already_set&) {
-			Poly::Python::_fetchError();
-
-			return POLY_NULLPTR;
-		}
-	}
-
-protected:
-	bp::object mComponentType;
-};
-
 bp::object Entity_GetComponent(Entity& self, const String& typeName) {
 	if(!self.hasComponent(typeName))
 		return bp::object();
 	String typeName = bp::extract<String>(componentType.attr("__name__"));
 	
 	ComponentFactoryPtr factory(new PythonComponentFactory(componentType));
-	
 	self.addComponentType(typeName, factory);
 }
 
 	bp::class_<ComponentManager, boost::noncopyable>("ComponentManager", bp::no_init)
 		.def("addComponentType", &ComponentManager_addComponentType);
 
-	bp::class_<Component, PythonComponent, boost::noncopyable>("Component", bp::init<>());
+	bp::class_<Component, boost::noncopyable>("_Component", bp::no_init);
+
+	bp::class_<_PythonInternComponent, PythonComponent, bp::bases<Component>, boost::noncopyable>("Component", bp::init<>());
 
 	bp::class_<TransformComponent, bp::bases<Component>>("TransformComponent")
 		.add_property("sceneNode", bp::make_getter(&TransformComponent::sceneNode, bp::return_internal_reference<>()));