summaryrefslogtreecommitdiff
path: root/Runtime/GameCode/CallDelayed.h
blob: e29378995f10575f0a2ea6c4596a4d70717fb2cf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#ifndef CALLDELAYED_H
#define CALLDELAYED_H

#include "Runtime/BaseClasses/GameManager.h"
#include "Runtime/Utilities/MemoryPool.h"
#include <set>



/// Delayed call is called when the specified time has been reached.
/// o is always non-NULL
typedef void DelayedCall(Object* o, void* userData);
/// CleanupUserData should be used to prevent leaking userData
/// CleanupUserData is called whenever a registered callback is erased.
/// Doing cleanup inside DelayedCall doesnt work since the object might get destroyed or the scene unloaded before a pending function is called
/// CleanupUserData is called only when userData != NULL
typedef void CleanupUserData (void* userData);

/** Class to call functions delayed in time
 */
class DelayedCallManager : public GlobalGameManager
{
	public:
	REGISTER_DERIVED_CLASS (DelayedCallManager, GlobalGameManager)

	enum  {
		kRunFixedFrameRate = 1 << 0,
		kRunDynamicFrameRate = 1 << 1,
		kRunStartupFrame = 1 << 2,
		kWaitForNextFrame = 1 << 3,
		kAfterLoadingCompleted = 1 << 4,
		kEndOfFrame = 1 << 5
	};

	DelayedCallManager (MemLabelId label, ObjectCreationMode mode);
	// virtual ~DelayedCallManager (); declared-by-macro

	/// Time is the time from now we need to exceed to call the function
	/// repeatRate determines at which intervals the call should be repeated. If repeat rate is 0.0F it will not repeat. If it is -1.0 it will repeat but you must have kWaitForNextFrame enabled
	friend void CallDelayed (DelayedCall *func, PPtr<Object> o, float time, void* userData, float repeatRate, CleanupUserData* cleanup, int mode);
	friend void CallDelayedAfterLoading  (DelayedCall *func, PPtr<Object> o, void* userData);

	/// Cancels all CallDelayed	functions on object o if
	/// - the callback is the same
	/// - ShouldCancelCall returns true. (callBackUserData is the userdata stored with CallDelayed. cancelUserData is cancelUserData)
	typedef bool ShouldCancelCall (void* callBackUserData, void* cancelUserdata);
	void CancelCallDelayed (PPtr<Object> o, DelayedCall* callback, ShouldCancelCall* shouldCancel, void* cancelUserData);
	void CancelCallDelayed2 (PPtr<Object> o, DelayedCall* callback, DelayedCall* otherCallback);
	void CancelAllCallDelayed( PPtr<Object> o );
	
	bool HasDelayedCall (PPtr<Object> o, DelayedCall* callback, ShouldCancelCall* shouldCancel, void* cancelUserData);

	virtual void Update (int mask);
	
	void ClearAll ();
	
	int GetNumCallObjects() const { return m_CallObjects.size(); }
	
	private:
	
	/// Struct used to store which functions to execute on which objects.
	struct Callback {
		float time;
		int frame;
		float repeatRate;
		bool repeat;
		void* userData;
		DelayedCall *call;			///< The function call to execute.
		CleanupUserData *cleanup;
		PPtr<Object> object;		///< The object to pass to m_Call.
		int mode;
		int timeStamp;
		
		friend bool operator < (const Callback& lhs, const Callback& rhs) { return lhs.time < rhs.time; }
	};

#if ENABLE_CUSTOM_ALLOCATORS_FOR_STDMAP
	typedef std::multiset<Callback, std::less<Callback>, memory_pool<Callback> > Container;
#else
	typedef std::multiset<Callback, std::less<Callback> > Container;
#endif

	void Remove (const Callback& cb, Container::iterator i);	
	void RemoveNoCleanup (const Callback& cb, Container::iterator i);
	Container m_CallObjects;
	Container::iterator m_NextIterator;
	int m_TimeStamp;
};

/// Calls func in time seconds from now. When o is NULL when the call happens, only cleanup is called.
/// The function call is repeated at repeatRate if repeatRate is not 0.0F
/// cleanup is called whenever userData is non-NULL and a callback is removed (After calling of the delay function without repeat, object was destroyed or Shutdown of a scene)
void CallDelayed (DelayedCall *func, PPtr<Object> o, float time = -1.0F, void* userData = NULL, float repeatRate = 0.0F, CleanupUserData* cleanup = NULL, int mode = DelayedCallManager::kRunDynamicFrameRate | DelayedCallManager::kRunFixedFrameRate);
inline void CallDelayedAfterLoading (DelayedCall *func, PPtr<Object> o, void* userData = NULL)
{
	CallDelayed(func, o, -1.0F, userData, 0.0F, NULL, DelayedCallManager::kAfterLoadingCompleted);
}


DelayedCallManager& GetDelayedCallManager ();

#endif