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

Thread-safe events, adjustment Matrix for polygon picking

Ivan Safrin 13 лет назад
Родитель
Сommit
6e1940bf25

+ 1 - 0
Core/Contents/CMakeLists.txt

@@ -75,6 +75,7 @@ SET(polycore_SRCS
     Source/PolySoundManager.cpp
     Source/PolyString.cpp
     Source/PolyTexture.cpp
+    Source/PolyThreaded.cpp
     Source/PolyTimer.cpp
     Source/PolyTimerManager.cpp
     Source/PolyTween.cpp

+ 4 - 1
Core/Contents/Include/PolyCore.h

@@ -121,7 +121,7 @@ namespace Polycode {
 		* @param target Target threaded class.
 		* @see Threaded
 		*/		
-		virtual void createThread(Threaded *target) = 0;
+		virtual void createThread(Threaded *target);
 
 		/**
 		* Locks a mutex.
@@ -338,6 +338,9 @@ namespace Polycode {
 		
 		unsigned int lastSleepFrameTicks;
 		
+		std::vector<Threaded*> threads;
+		CoreMutex *threadedEventMutex;
+		
 		int xRes;
 		int yRes;	
 		

+ 2 - 0
Core/Contents/Include/PolyEvent.h

@@ -63,6 +63,8 @@ namespace Polycode {
 			
 			static const int COMPLETE_EVENT = 0;
 			static const int CHANGE_EVENT = 1;
+			
+			bool deleteOnDispatch;
 						
 		protected:
 			

+ 2 - 2
Core/Contents/Include/PolyEventDispatcher.h

@@ -82,8 +82,8 @@ typedef struct {
 			* @see Event
 			* @see EventHandler			
 			*/														
-			void dispatchEvent(Event *event, int eventCode);
-			void dispatchEventNoDelete(Event *event, int eventCode);
+			virtual void dispatchEvent(Event *event, int eventCode);
+			virtual void dispatchEventNoDelete(Event *event, int eventCode);
 		
 		protected:
 	

+ 1 - 1
Core/Contents/Include/PolyRenderer.h

@@ -212,7 +212,7 @@ namespace Polycode {
 		
 		void addShaderModule(PolycodeShaderModule *module);
 		
-		virtual bool test2DCoordinateInPolygon(Number x, Number y, Polygon *poly, const Matrix4 &matrix, bool testBackfacing, bool ortho, bool billboardMode);
+		virtual bool test2DCoordinateInPolygon(Number x, Number y, Polygon *poly, const Matrix4 &matrix, bool testBackfacing, bool ortho, bool billboardMode, Matrix4 *adjustMatrix = NULL);
 		
 		virtual Matrix4 getProjectionMatrix() = 0;
 		virtual Matrix4 getModelviewMatrix() = 0;

+ 19 - 6
Core/Contents/Include/PolyThreaded.h

@@ -22,8 +22,12 @@ THE SOFTWARE.
 
 #pragma once
 #include "PolyGlobals.h"
+#include "PolyEventDispatcher.h"
 
 namespace Polycode{
+
+	class Core;
+	class CoreMutex;
 	
 	/**
 	* An easy way to create threaded processes. If you subclass this class, you can implement the updateThread method, which will be called in its own thread repeatedly until threadRunning is false once the thread is created. If you only need to run through something once, make sure to set threadRunning to avoid it being called again. 
@@ -31,24 +35,33 @@ namespace Polycode{
 		To create the thread, pass your Threaded subclass to createThread method of Core.
 		@see Core
 	*/
-	class _PolyExport Threaded {
+	class _PolyExport Threaded : public EventDispatcher {
 	public:
-		Threaded(){ threadRunning = true; }
+		Threaded();
 		virtual ~Threaded(){}
 		
 		/**
 		* Sets the thread running flag to false.
 		*/ 
-		virtual void killThread() { threadRunning = false; }		
-		
-		virtual void runThread(){while(threadRunning) updateThread(); }
+		virtual void killThread();	
+		virtual void runThread();
 		
 		/**
 		* Implement this method with your own code.
 		*/
-		virtual void updateThread() = 0;
+		virtual void updateThread() {};
+		
+		void dispatchEvent(Event *event, int eventCode);		
+		void dispatchEventNoDelete(Event *event, int eventCode);
 		
 		bool threadRunning;
+		
+		Core *core;
+		
+		bool scheduledForRemoval;
+		
+		CoreMutex *eventMutex;		
+		std::vector<Event*> eventQueue;
 	};
 	
 }

+ 2 - 0
Core/Contents/Source/PolyCocoaCore.mm

@@ -262,10 +262,12 @@ CocoaCore::~CocoaCore() {
 void *ManagedThreadFunc(void *data) {
 	Threaded *target = static_cast<Threaded*>(data);
 	target->runThread();
+	target->scheduledForRemoval = true;
 	return NULL;
 }
 
 void CocoaCore::createThread(Threaded *target) {
+	Core::createThread(target);
 	pthread_t thread;
 	pthread_create( &thread, NULL, ManagedThreadFunc, (void*)target);
 }

+ 35 - 1
Core/Contents/Source/PolyCore.cpp

@@ -67,7 +67,8 @@ namespace Polycode {
 		
 		this->monitorIndex = monitorIndex;
 		
-		refreshInterval = 1000 / frameRate;
+		refreshInterval = 1000 / frameRate;		
+		threadedEventMutex = NULL;
 	}
 	
 	void Core::enableMouse(bool newval) {
@@ -123,6 +124,18 @@ namespace Polycode {
 		setVideoMode(resList[index].w, resList[index].h, fullScreen, vSync, aaLevel, anisotropyLevel);
 	}
 	
+	void Core::createThread(Threaded *target) {
+		if(!threadedEventMutex) {
+			threadedEventMutex = createMutex();
+		}
+		target->eventMutex = threadedEventMutex;
+		target->core = this;
+		
+		lockMutex(threadedEventMutex);
+		threads.push_back(target);
+		unlockMutex(threadedEventMutex);			
+	}
+			
 	void Core::updateCore() {
 		frames++;
 		frameTicks = getTicks();
@@ -139,6 +152,27 @@ namespace Polycode {
 		}
 		lastFrameTicks = frameTicks;
 		
+		if(threadedEventMutex){ 
+		lockMutex(threadedEventMutex);
+
+		std::vector<Threaded*>::iterator iter = threads.begin();
+		while (iter != threads.end()) {		
+			for(int j=0; j < (*iter)->eventQueue.size(); j++) {
+				Event *event = (*iter)->eventQueue[j];
+				(*iter)->__dispatchEvent(event, event->getEventCode());
+				if(event->deleteOnDispatch)
+					delete event;
+			}
+			(*iter)->eventQueue.clear();
+			if((*iter)->scheduledForRemoval) {
+				iter = threads.erase(iter);
+			} else {
+				++iter;
+			}
+		}
+		
+		unlockMutex(threadedEventMutex);
+		}
 	}
 	
 	void Core::doSleep() {

+ 1 - 0
Core/Contents/Source/PolyEvent.cpp

@@ -26,6 +26,7 @@ namespace Polycode {
 	
 	Event::Event() {
 			eventType = "Event";
+			deleteOnDispatch = true;
 	}
 	
 	Event::Event(int eventCode) {

+ 5 - 1
Core/Contents/Source/PolyRenderer.cpp

@@ -78,7 +78,7 @@ void Renderer::setExposureLevel(Number level) {
 }
 
 
-bool Renderer::test2DCoordinateInPolygon(Number x, Number y, Polycode::Polygon *poly, const Matrix4 &matrix, bool ortho, bool testBackfacing, bool billboardMode) {
+bool Renderer::test2DCoordinateInPolygon(Number x, Number y, Polycode::Polygon *poly, const Matrix4 &matrix, bool ortho, bool testBackfacing, bool billboardMode, Matrix4 *adjustMatrix) {
 
 	Vector3 dirVec;
 	Vector3 origin;
@@ -118,6 +118,10 @@ bool Renderer::test2DCoordinateInPolygon(Number x, Number y, Polycode::Polygon *
 		dirVec = camInverse.rotateVector(dirVec);
 	}
 	
+	if(adjustMatrix) {
+			fullMatrix = (*adjustMatrix) * fullMatrix;
+	}	
+		
 	bool retStatus = false;	
 	
 	

+ 35 - 0
Core/Contents/Source/PolyThreaded.cpp

@@ -0,0 +1,35 @@
+
+#include "PolyThreaded.h"
+#include "PolyCore.h"
+
+using namespace Polycode;
+
+Threaded::Threaded() : EventDispatcher() {
+	threadRunning = true;
+	scheduledForRemoval = false;
+}
+
+void Threaded::killThread() {
+	threadRunning = false;
+}
+
+void Threaded::runThread(){
+	while(threadRunning) {
+		updateThread();
+	}
+}
+
+void Threaded::dispatchEvent(Event *event, int eventCode) {
+	core->lockMutex(eventMutex);
+	event->setEventCode(eventCode);
+	eventQueue.push_back(event);
+	core->unlockMutex(eventMutex);	
+}
+		
+void Threaded::dispatchEventNoDelete(Event *event, int eventCode) {
+	core->lockMutex(eventMutex);
+	event->setEventCode(eventCode);
+	event->deleteOnDispatch = false;
+	eventQueue.push_back(event);	
+	core->unlockMutex(eventMutex);			
+}

+ 2 - 0
Modules/Contents/3DPhysics/Include/PolyPhysicsSceneEntity.h

@@ -50,6 +50,8 @@ namespace Polycode {
 		void setFriction(Number friction);		
 		int getType() { return type; }	
 		
+		void setMass(Number mass);
+		
 			void setVelocity(Vector3 velocity);
 			void warpTo(Vector3 position, bool resetRotation);
 			

+ 4 - 0
Modules/Contents/3DPhysics/Source/PolyPhysicsSceneEntity.cpp

@@ -223,6 +223,10 @@ void PhysicsSceneEntity::setFriction(Number friction) {
 		rigidBody->setFriction(friction);
 }
 
+void PhysicsSceneEntity::setMass(Number mass) {
+	rigidBody->setMassProps(mass, btVector3(0.0, 0.0, 0.0));
+}
+
 void PhysicsSceneEntity::Update() {		
 	Matrix4 m;
 		

+ 5 - 3
Modules/Contents/Curl/PolycodeDownloader.cpp

@@ -23,11 +23,13 @@ String PolycodeDownloader::getDataAsString() {
 	return ret;
 }
 		
-PolycodeDownloader::PolycodeDownloader(String url) {
-	
+PolycodeDownloader::PolycodeDownloader(String url) : Threaded() {
+	this->url = url;
 	data = (char*)malloc(0);
 	size = 0;
-	
+}
+
+void PolycodeDownloader::runThread() {
 	curl = curl_easy_init();
 		
 	curl_easy_setopt(curl, CURLOPT_URL, url.c_str());	

+ 5 - 2
Modules/Contents/Curl/PolycodeDownloader.h

@@ -1,20 +1,23 @@
+#pragma once
 
 #include <Polycode.h>
 #include <curl/curl.h>
 
 using namespace Polycode;
 
-class PolycodeDownloader : public EventDispatcher {
+class PolycodeDownloader : public Threaded {
 	public:
 		PolycodeDownloader(String url);
 		~PolycodeDownloader();		
 		
+		void runThread();
+		
 		String getDataAsString();
 		
 		char *data;
 		size_t size;
 				
 	protected:
-		
+		String url;		
 		CURL *curl;
 };

+ 1 - 1
Modules/Contents/Networking/Include/PolyPeer.h

@@ -70,7 +70,7 @@ namespace Polycode {
 		Address address;
 	};
 		
-	class _PolyExport Peer : public Threaded, public EventDispatcher {
+	class _PolyExport Peer : public Threaded {
 		public:
 			Peer(unsigned int port);
 			~Peer();

+ 1 - 1
Modules/Contents/Networking/Source/PolyPeer.cpp

@@ -36,7 +36,7 @@ void PeerConnection::ackPackets(unsigned int ack) {
 	}
 }
 
-Peer::Peer(unsigned int port) : EventDispatcher(), Threaded() {
+Peer::Peer(unsigned int port) : Threaded() {
 	socket = new Socket(port);
 	socket->addEventListener(this, SocketEvent::EVENT_DATA_RECEIVED);