ya2 · news · projects · code · about

first commit
[pmachines.git] / lib / lib / p3d / pause.py
1 from os import pardir # pardir is .. (parent directory)
2 from os.path import dirname, abspath, join
3 from sys import modules
4 from direct.task import Task
5 from direct.interval.IntervalGlobal import ivalMgr
6 from lib.gameobject import GameObject
7
8
9 class TaskDec:
10
11 paused_taskchain = 'paused tasks'
12
13 def __init__(self, tsk):
14 self.tsk = tsk
15 path = dirname(modules[Task.__name__].__file__)
16 self.__direct_dir = abspath(join(path, pardir)) # path of direct.*
17
18 def process(self):
19 func = self.tsk.get_function() # ordinary tasks
20 mod = func.__module__
21 modfile = ''
22 if "from '" in str(modules[mod]):
23 modfile = str(modules[mod]).split("from '")[1][:-2]
24 sys_mod = modfile.find(self.__direct_dir) < 0
25 actor_ival = False
26 if hasattr(func, 'im_class'):
27 actor_ival = func.im_class.__name__ == 'ActorInterval'
28 if mod.find('direct.interval') == 0 and not actor_ival:
29 self.tsk.interval.pause() # python-based intervals
30 return self.tsk
31 if mod not in modules or sys_mod: return self.tsk
32 return None
33
34 def pause(self):
35 tsk = self.tsk
36 has_args = hasattr(tsk, 'getArgs')
37 tsk.stored_extraArgs = tsk.get_args() if has_args else None
38 if hasattr(tsk, 'getFunction'): tsk.stored_call = tsk.get_function()
39 has_p = hasattr(tsk, '_priority')
40 tsk.stored_priority = tsk._priority if has_p else tsk.get_sort()
41 if hasattr(tsk, 'remainingTime'): tsk.remove() # do_later tasks
42 else: # ordinary tasks
43 tsk.lastactivetime = -tsk.time if hasattr(tsk, 'time') else 0
44 tsk.setTaskChain(TaskDec.paused_taskchain)
45
46 def __resume_do_later(self):
47 tsk = self.tsk
48 d_t = globalClock.get_real_time() - globalClock.get_frame_time()
49 tmp_delay = tsk.remainingTime - d_t
50 upon_death = tsk.uponDeath if hasattr(tsk, 'uponDeath') else None
51 new_task = taskMgr.doMethodLater(
52 tmp_delay, tsk.stored_call, tsk.name, uponDeath=upon_death,
53 priority=tsk.stored_priority, extraArgs=tsk.stored_extraArgs)
54 if hasattr(tsk, 'remainingTime'): new_task.delayTime = tsk.delayTime
55
56 def resume(self):
57 tsk = self.tsk
58 if hasattr(tsk, 'interval'):
59 tsk.interval.resume()
60 if hasattr(tsk, 'stored_call'): tsk.set_function(tsk.stored_call)
61 return
62 if hasattr(tsk, 'remainingTime'):
63 self.__resume_do_later()
64 return
65 tsk.set_delay(tsk.lastactivetime) # ordinary tasks
66 tsk.set_task_chain('default')
67 tsk.clear_delay() # to avoid assertion error on resume
68
69
70 class P3dPause(GameObject):
71
72 def __init__(self):
73 GameObject.__init__(self)
74 taskMgr.setupTaskChain(TaskDec.paused_taskchain, frameBudget=0)
75 self.__paused_ivals = []
76 self.__paused_tasks = []
77
78 @property
79 def paused(self):
80 tsk = taskMgr.getTasksNamed('__on_frame')[0]
81 return tsk.getTaskChain() == TaskDec.paused_taskchain
82
83 def pause_tasks(self):
84 is_tsk = lambda tsk: tsk and hasattr(tsk, 'getFunction')
85 tasks = [TaskDec(tsk) for tsk in taskMgr.getTasks() if is_tsk(tsk)]
86 tasks = [tsk for tsk in tasks
87 if tsk.tsk.get_task_chain() != 'unpausable']
88 namefilter = ['igLoop', 'dataLoop', 'ivalLoop', 'collisionLoop',
89 'garbageCollectStates', 'audioLoop',
90 'resetPrevTransform', 'eventManager']
91 tasks = [tsk for tsk in tasks
92 if tsk.tsk.get_name_prefix() not in namefilter]
93 not_none = lambda tsk: tsk is not None
94 paused_tasks = list(filter(not_none, [tsk.process() for tsk in tasks]))
95 self.__paused_tasks = list(map(TaskDec, paused_tasks))
96 for tsk in list(filter(is_tsk, taskMgr.getDoLaters())):
97 self.__paused_tasks += [TaskDec(tsk)]
98 tsk.remainingTime = tsk.wakeTime - globalClock.get_frame_time()
99 list(map(lambda tsk: tsk.pause(), self.__paused_tasks))
100
101 def remove_task(self, tsk):
102 list(map(self.__paused_tasks.remove, [ptsk for ptsk in self.__paused_tasks if ptsk.tsk == tsk]))
103
104 def pause(self):
105 self.__paused_ivals = ivalMgr.getIntervalsMatching('*')
106 self.pause_tasks()
107 return self.paused
108
109 def resume(self):
110 list(map(lambda ival: ival.resume(), self.__paused_ivals))
111 list(map(lambda tsk: tsk.resume(), self.__paused_tasks))
112 return self.paused
113
114 def destroy(self): GameObject.destroy(self)