Browse Source

Working prototype of Events

Marko Pintera 11 years ago
parent
commit
1dc62ba3ce

+ 23 - 1
BansheeEditor/Source/BsEditorApplication.cpp

@@ -35,6 +35,7 @@
 #include "BsGUIArea.h"
 #include "BsGUIButton.h"
 #include "BsGUILayout.h"
+#include "BsEvent.h"
 
 namespace BansheeEngine
 {
@@ -43,6 +44,28 @@ namespace BansheeEngine
 	EditorApplication::EditorApplication(RenderSystemPlugin renderSystemPlugin)
 		:mActiveRSPlugin(renderSystemPlugin)
 	{
+		// START DEBUG
+		
+		class TmpClass
+		{
+		public:
+			void someMEthod(int a)
+			{
+				b = a;
+			}
+
+			int b;
+		};
+
+		TmpClass instance;
+		Event<void (int)> myEvent;
+		myEvent += delegate(&instance, &TmpClass::someMEthod);
+
+		int arg = 5;
+		myEvent(arg);
+
+		// END DEBUG
+
 		RENDER_WINDOW_DESC renderWindowDesc;
 		renderWindowDesc.width = 1280;
 		renderWindowDesc.height = 720;
@@ -299,7 +322,6 @@ namespace BansheeEngine
 
 		//modalArea->getLayout().addElement(modalButton);
 
-
 		/************************************************************************/
 		/* 							END DEBUG CODE                      		*/
 		/************************************************************************/

+ 1 - 0
CamelotUtility/CamelotUtility.vcxproj

@@ -266,6 +266,7 @@
     <ClCompile Include="Source\CmTexAtlasGenerator.cpp" />
     <ClCompile Include="Source\CmUUID.cpp" />
     <ClCompile Include="Source\Win32\CmTimer.cpp" />
+    <ClInclude Include="Include\BsEvent.h" />
     <ClInclude Include="Include\BsTaskScheduler.h" />
     <ClInclude Include="Include\BsThreadPool.h" />
     <ClInclude Include="Include\CmAsyncOp.h" />

+ 3 - 0
CamelotUtility/CamelotUtility.vcxproj.filters

@@ -234,6 +234,9 @@
     <ClInclude Include="Include\BsTaskScheduler.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="Include\BsEvent.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\CmMath.cpp">

+ 162 - 0
CamelotUtility/Include/BsEvent.h

@@ -0,0 +1,162 @@
+#pragma once
+
+#include "CmPrerequisitesUtil.h"
+#include "CmModule.h"
+
+namespace BansheeEngine
+{
+	/************************************************************************/
+	/* 							ABSTRACT DELEGATE	                      	*/
+	/************************************************************************/
+
+	// 1 parameter
+	template <class P0, class RetType>
+	class Delegate1Abstract
+	{
+	public:
+		virtual RetType call(P0& p0) = 0;
+		virtual bool equals(const Delegate1Abstract<P0, RetType>& other) = 0;
+	};
+
+	/************************************************************************/
+	/* 							MEMBER DELEGATE                      		*/
+	/************************************************************************/
+
+	// 1 parameter
+	template <class X, class Y, class P0, class RetType>
+	class Delegate1Member : public Delegate1Abstract<P0, RetType>
+	{
+	public:
+		Delegate1Member(Y* instance, RetType (X::*func)(P0))
+			:mInstance(instance), mFunc(func)
+		{ }
+
+		RetType call(P0& p0)
+		{
+			(mInstance->*mFunc)(p0);
+		}
+
+		bool equals(const Delegate1Abstract<P0, RetType>& other)
+		{
+			const Delegate1Member<X, Y, P0, RetType>& otherMemberDelegate = 
+				reinterpret_cast<const Delegate1Member<X, Y, P0, RetType>&>(other);
+
+			return otherMemberDelegate.mInstance == mInstance && otherMemberDelegate.mFunc == mFunc;
+		}
+
+	private:
+		X* mInstance;
+		RetType (X::*mFunc)(P0);
+	};
+
+	template <class X, class Y, class P0, class RetType>
+	std::shared_ptr<Delegate1Member<X, Y, P0, RetType>> delegate(Y* instance, RetType (X::*func)(P0))
+	{
+		return cm_shared_ptr<Delegate1Member<X, Y, P0, RetType>>(instance, func);
+	}
+
+	/************************************************************************/
+	/* 							FUNCTION DELEGATE                      		*/
+	/************************************************************************/
+
+	// 1 parameter
+	template <class P0, class RetType>
+	class Delegate1Function : public Delegate1Abstract<P0, RetType>
+	{
+	public:
+		Delegate1Function(RetType (*func)(P0))
+			:mInstance(instance), mFunc(func)
+		{ }
+
+		RetType call(P0& p0)
+		{
+			(*mFunc)(p0);
+		}
+
+		bool equals(const Delegate1Abstract<P0, RetType>& other)
+		{
+			const Delegate1Function<P0, RetType>& otherFunctionDelegate = 
+				reinterpret_cast<const Delegate1Function<P0, RetType>&>(other);
+
+			return otherMemberDelegate.mFunc == mFunc;
+		}
+
+	private:
+		RetType (*mFunc)(P0);
+	};
+
+	template <class P0, class RetType>
+	std::shared_ptr<Delegate1Function<P0, RetType>> delegate(RetType (*func)(P0))
+	{
+		return cm_shared_ptr<Delegate1Function<P0, RetType>>(func);
+	}	
+
+	/************************************************************************/
+	/* 									EVENTS					     		*/
+	/************************************************************************/
+	
+	// 1 parameter
+	template <class P0, class RetType>
+	class Event1
+	{
+		typedef Delegate1Abstract<P0, RetType> TDelegate;
+		typedef std::shared_ptr<TDelegate> TDelegatePtr;
+	public:
+		void operator+= (const TDelegatePtr& delegate)
+		{
+			// TODO - Lock
+
+			mDelegates.push_back(delegate);
+		}
+
+		void operator-= (const TDelegatePtr& delegate)
+		{
+			// TODO - Lock
+
+			for(auto& iter = mDelegates.begin(); iter != mDelegates.end(); ++iter)
+			{
+				if((*iter)->equals(*delegate))
+				{
+					mDelegates.erase(iter);
+					return;
+				}
+			}
+		}
+
+		void operator() (P0& args)
+		{
+			// TODO - Lock each call separately using a spin lock
+
+			for(auto& delegate : mDelegates)
+				delegate->call(args);
+		}
+
+		void clear()
+		{
+			// TODO - Lock
+			mDelegates.clear();
+		}
+
+		bool empty()
+		{
+			// TODO - Lock
+			return mDelegates.size() == 0;
+		}
+
+	private:
+		typename Vector<TDelegatePtr>::type mDelegates;
+	};
+
+	/************************************************************************/
+	/* 							SPECIALIZATIONS                      		*/
+	/* 	SO YOU MAY USE FUNCTION LIKE SYNTAX FOR DECLARING EVENT SIGNATURE   */
+	/************************************************************************/
+	
+	template <typename Signature>
+	class Event;
+
+	// 1 parameter
+	template <class P0, class RetType>
+	class Event<RetType(P0) > : public Event1 <P0, RetType>
+	{ };
+}