-
Notifications
You must be signed in to change notification settings - Fork 19
/
Copy pathmovement_record.py
85 lines (78 loc) · 3.41 KB
/
movement_record.py
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
from __future__ import print_function
import itertools
import logging
class MovementRecord:
def __init__(self, objects, total_frames):
"""
Args:
objects (list of blender objects)
"""
# initialize a list for each object
self.total_frames = total_frames
self.timeline = {}
self.contains = {}
for obj in objects:
self.timeline[obj] = []
# store for each frame, what is contained
self.contains[obj] = list(itertools.repeat(None, total_frames + 1))
def insert(self, obj, action, other_obj, start_frame, end_frame):
"""
Args:
obj: The blender object that was acted upon
action: The function/action op that was executed
other_obj: Other blender obj involved in this.
Only useful for contains op
start_frame: The start_frame of the action
end_frame: The end_frame of the action
"""
self.timeline[obj].append((
action,
other_obj,
start_frame, end_frame))
logging.debug('Recorded action for {}: {}'.format(
obj, self.human_readable_interval(self.timeline[obj][-1])))
# If contains, also update the contains data structure
if action.__name__ == '_contain':
# Assume it will be contained for ever, until the same object hits
# a pick_place
assert obj != other_obj, '{} can not contain itself!'.format(
obj) # will lead to infinite recursion when checking
for frame_id in range(start_frame, self.total_frames + 1):
# Nothing should already be contained
assert self.contains[obj][frame_id] is None, \
'{} already contains {} at frame {}. ' \
'Cant contain {} (btw {} and {}) now also..?' \
'This may be because I use generous timing for contains ' \
'op, i.e. since the the cone picks up, it is counted as ' \
'contains. Anyway, ignore this setup.'.format(
obj, self.contains[obj][frame_id], frame_id,
other_obj, start_frame, end_frame)
self.contains[obj][frame_id] = other_obj
logging.debug('{} contains {} as of {}'.format(
obj, other_obj, start_frame))
elif action.__name__ == '_pick_place':
# If something was contained, it will no longer be
for frame_id in range(end_frame, self.total_frames + 1):
self.contains[obj][frame_id] = None
def get_dict(self):
"""
Return the record in a human readable dictionary format
"""
res = {}
for ob, intervals in self.timeline.items():
res[ob.name] = [
self.human_readable_interval(interval) for interval
in intervals]
return res
def human_readable_interval(self, interval):
return (
interval[0].__name__,
interval[1].name if interval[1] else None,
interval[2], interval[3])
def was_contained(self, ob1, ob2, frame_id):
""" Return true/false, based on whether ob2 was contained in ob1. """
if ob1 is None:
return False
if ob1 == ob2:
return True
return self.was_contained(self.contains[ob1][frame_id], ob2, frame_id)