SceneGraph.establish()   A
last analyzed

Complexity

Conditions 3

Size

Total Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 3
dl 0
loc 12
rs 9.4285
c 1
b 0
f 1
1
from gem import matrix
2
from ed2d import idgen
3
4
class BaseNode(object):
5
    def __init__(self, obj):
6
        self.nodeID = None
7
        self.isRoot = False
8
        self.root = None
9
        self.parent = None
10
        self.children = [self]
11
        self.obj = obj
12
13
    def attach(self, parent):
14
        self.root = parent.root
15
        self.parent = parent
16
        nodeID = self.root.add_tree_child(self)
17
        self.nodeID = nodeID
18
        self.parent.children.append(self)
19
        return nodeID
20
21
    def detach(self):
22
        self.parent.children.remove(self)
23
        self.root.del_tree_child(self)
24
        self.parent = None
25
        self.root = None
26
        self.nodeID = None
27
28
    def recurse(self, callback):
29
        for i in self.children[1:]:
30
            callback(self, i)
31
            i.recurse(callback)
32
33
    def recurse_up(self, callback):
34
        callback(self)
35
        if not self.parent.isRoot:
36
            self.parent.recurse_up(callback)
37
38
    def reparent(self, parent):
39
        self.detach()
40
        self.attach(parent)
41
42
    def __repr__(self):
43
        templ = (type(self).__name__, self.nodeID, hex(id(self)))
44
        return "<SceneGraph {0} (NodeID {1}) object at {2}>".format(*templ)
45
46
47
class RootNode(BaseNode):
48
    def __init__(self, obj):
49
        self.nodeID = 0
50
        self.treeChildren = [self]
51
        self.children = [self]
52
        self.root = self
53
        self.isRoot = True
54
        self.ids = idgen.IdGenerator()
55
56
    def reparent(self, parent):
57
        print('Error can\'t reparent root node.')
58
59
    def attach(self, parent):
60
        print('Error can\'t attach root node.')
61
62
    def dettach(self, parent):
63
        print('Error can\'t dettach root node.')
64
65
    def add_tree_child(self, obj):
66
        nodeID = self.ids.gen_id()
67
68
        idgen.set_uid_list(self.treeChildren, nodeID, obj)
69
70
        return nodeID
71
72
    def del_tree_child(self, obj):
73
        nodeID = obj.nodeID
74
        self.treeChildren[nodeID] = None
75
        obj.nodeID = None
76
        self.ids.del_id(nodeID)
77
78
79
class GraphicsNode(BaseNode):
80
    def __init__(self, obj, matrix=None):
81
        super(GraphicsNode, self).__init__(obj)
82
        if matrix is None:
83
            self.matrix = matrix.Matrix(4)
84
        else:
85
            self.matrix = matrix
86
        self.appliedMatrix = self.matrix
87
88
    def bind_matrix(self, matrix):
89
        self.matrix = matrix
90
91
class SceneGraph(object):
92
    def __init__(self):
93
        self.root = RootNode(None)
94
        self.root.matrix = matrix.Matrix(4)
95
        self.root.appliedMatrix = self.root.matrix
96
97
    def establish(self, obj, parent=None):
98
        if hasattr(obj, 'matrix'):
99
            node = GraphicsNode(obj, obj.matrix)
100
        else:
101
            node = GraphicsNode(obj)
102
103
        if parent is None:
104
            parent = self.root
105
        else:
106
            parent = self.aquire(parent)
107
        nodeID = node.attach(parent)
108
        return nodeID
109
110
    def reparent(self, nodeID, parentID):
111
        node = self.aquire(nodeID)
112
        parent = self.aquire(parentID)
113
        node.reparent(parent)
114
115
    def aquire(self, nodeID):
116
        return self.root.treeChildren[nodeID]
117
118
    def aquire_root(self):
119
        return self.root
120
121
    @classmethod
122
    def _recurse_update(self, parent, obj):
123
        obj.obj.update()
124
        obj.matrix = obj.obj.matrix
125
        obj.appliedMatrix = parent.appliedMatrix * obj.matrix
126
127
    def update(self):
128
        self.root.recurse(self._recurse_update)
129
130
    @classmethod
131
    def _recurse_render(self, parent, obj):
132
        obj.obj.render()
133
134
    def render(self):
135
        self.root.recurse(self._recurse_render)
136