-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathnode_system.py
225 lines (171 loc) · 6.27 KB
/
node_system.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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
import time
import bpy
# runtime
# NOOOOOOOOOOOOO node_groups is readonly
# qtmd readonly 浪费老子时间
# node system
class PearlNodeTree(bpy.types.NodeTree):
bl_idname = 'PearlNodeTree'
bl_label = 'Pearl Node Editor'
bl_icon = 'NODETREE'
# 储存所有的节点
tree_nodes = {}
# 储存所有要执行的节点
process_nodes = []
# 储存所有socket
socket_values = {}
# 储存所有节点所有的值
tree_values = {}
# 需要清理的临时数据
tree_temp = []
'''
node-name{
input-socket-name:value
output-socket-name:value
}
'''
def initTreeValues(self):
self.tree_values.clear()
# node_name 为节点字典的key,也就是节点的名字
for node_name in self.tree_nodes:
# 为每个节点添加tree的引用,以便节点运算值的修改
self.tree_nodes[node_name].tree = self
# 初始化节点字典
self.tree_values.setdefault(node_name,{})
for input in self.tree_nodes[node_name].inputs:
self.tree_values[node_name].setdefault(input.name,None)
for output in self.tree_nodes[node_name].outputs:
self.tree_values[node_name].setdefault(output.name,None)
def printNodes(self):
print("-------------- nodes")
for node in self.tree_nodes:
print(self.tree_nodes[node].name)
def printSockets(self):
print("-------------- sockets")
for socket in self.socket_values:
print(socket, \
self.socket_values[socket].name)
def printProcessNodes(self):
for node in self.process_nodes:
print(node.name)
def addExecuteNodes(self):
self.socket_values.clear()
self.tree_nodes.clear()
self.process_nodes.clear()
# 遍历节点
for node in self.nodes:
node.check_init()
self.tree_nodes.setdefault(node.name, node)
# 能够立即执行的节点 加入执行队列
if node.is_prepared():
self.process_nodes.append(node)
'''
# 遍历socket
for node in self.tree_nodes:
for input in self.tree_nodes[node].inputs:
self.socket_values.setdefault(input.name, input)
for output in self.tree_nodes[node].outputs:
self.socket_values.setdefault(output.name, output)
'''
def executeNodes(self):
self.tree_temp.clear()
print("\n-------------- ",self.name)
self.addExecuteNodes()
self.initTreeValues()
# TODO 多线程执行process_node列表
# 执行队列不空,则一直执行第一个节点
print("\n-------------- process start")
while self.process_nodes:
# 执行节点
# TODO 节点返回True时才执行transfer以及link_num检查
self.process_nodes[0].process()
# 传递数据
self.process_nodes[0].transfer()
# TODO process return True/False -> transfer do/not
# 检查可执行的节点
for output in self.process_nodes[0].outputs:
for link in output.links:
self.tree_nodes[link.to_node.name].link_num -= 1
if self.tree_nodes[link.to_node.name].is_prepared() == True:
self.process_nodes.append(self.tree_nodes[link.to_node.name])
# 删除执行完的节点
self.process_nodes.remove(self.process_nodes[0])
# finished
class PearlNodeSocket(bpy.types.NodeSocket):
bl_idname = 'PearlNodeSocket'
bl_label = 'Pearl Node Socket'
socket_color = (0.5, 0.5, 0.5, 1)
socket_value : bpy.props.StringProperty()
def draw(self, context, layout, node, text):
layout.label(text=text)
def draw_color(self, context, node):
return self.socket_color
class PearlNode(bpy.types.Node):
bl_idname = "PearlNode"
bl_label = "PearlNode"
prepare_num = None
link_num = None
# 将在runtime时获得所在节点树的引用
tree = None
@classmethod
def poll(cls, ntree):
return (ntree.bl_idname == PearlNodeTree.bl_idname)
def initSocketValues(self):
for input in self.inputs:
input.socket_value = input.name
for output in self.inputs:
output.socket_value = output.name
def process(self):
print("process: ",id(self), self.name)
return True
def transfer(self):
# print("transfer: ",self.name)
# 遍历所有输出socket
for output in self.outputs:
# 遍历每个socket连接的link
for link in output.links:
# 值传递
self.tree.tree_values[link.to_node.name][link.to_socket.name] = self.tree.tree_values[link.from_node.name][link.from_socket.name]
'''
新的入度算法
以连接的link数来判断执行时机,每次执行前置节点,link_num都减1,当link_num为0时,该节点可以执行
除此之外还有一个最小执行要求,即is_prepared()函数中需要定义的必须连接的socket,否则不执行
'''
def is_prepared(self):
# return self.prepare_num==0
return self.link_num == 0
def check_init(self):
self.prepare_num = len(self.inputs)
# 目前连接的所有link,即前置需要执行的所有socket
self.link_num = 0
for input in self.inputs:
self.link_num += len(input.links)
def copy(self,node):
pass
def free(self):
pass
'''
# update(self)????每次增加删除、连线节点都执行?
def update(self):
pass
def todo(self):
for input in self.inputs:
# print(output.links)
if input.links:
for link in input.links:
node = link.from_node
print(" link from:",node)
# output link to_node
'''
classes = [
PearlNodeTree,
PearlNodeSocket,
PearlNode,
]
# register -------
def register():
for c in classes:
bpy.utils.register_class(c)
def unregister():
for c in reversed(classes):
bpy.utils.unregister_class(c)