224 lines
6.6 KiB
Python
224 lines
6.6 KiB
Python
import mathutils
|
|
|
|
MOVE_UNIT = 1
|
|
|
|
|
|
def global_loc(node):
|
|
if node.parent:
|
|
return global_loc(node.parent) + node.location
|
|
else:
|
|
return node.location
|
|
|
|
|
|
def calc_node(node, nodes, influence, slide_vec, relax_power, collide_power, collide_dist, pull_non_siblings):
|
|
if node.type == 'FRAME':
|
|
return False
|
|
|
|
loc = global_loc(node)
|
|
size = node.dimensions
|
|
|
|
offset = mathutils.Vector(slide_vec)
|
|
|
|
if relax_power > 0:
|
|
# Relax
|
|
tar_y = 0
|
|
link_cnt = 0
|
|
tar_x_in = loc.x
|
|
has_input = False
|
|
for socket in node.inputs: # Input links
|
|
for link in socket.links:
|
|
other = link.from_node
|
|
if not pull_non_siblings and node.parent != other.parent:
|
|
continue
|
|
loc_other = global_loc(other)
|
|
size_other = other.dimensions
|
|
|
|
x = loc_other.x + size_other.x + collide_dist.x
|
|
if has_input > 0:
|
|
tar_x_in = max(tar_x_in, x)
|
|
else:
|
|
tar_x_in = x
|
|
has_input = True
|
|
|
|
tar_y += loc_other.y - size_other.y / 2
|
|
link_cnt += 1
|
|
|
|
tar_x_out = loc.x
|
|
has_output = False
|
|
for socket in node.outputs: # Output links
|
|
for link in socket.links:
|
|
other = link.to_node
|
|
if not pull_non_siblings and node.parent != other.parent:
|
|
continue
|
|
loc_other = global_loc(other)
|
|
size_other = other.dimensions
|
|
|
|
x = loc_other.x - size.x - collide_dist.x
|
|
if has_output > 0:
|
|
tar_x_out = min(tar_x_out, x)
|
|
else:
|
|
tar_x_out = x
|
|
has_output = True
|
|
|
|
tar_y += loc_other.y - size_other.y / 2
|
|
link_cnt += 1
|
|
|
|
if link_cnt > 0:
|
|
tar_x = tar_x_in * int(has_input) + tar_x_out * int(has_output)
|
|
tar_x /= int(has_input) + int(has_output)
|
|
tar_y /= link_cnt
|
|
tar_y += size.y / 2
|
|
offset.x += (tar_x - loc.x) * relax_power
|
|
offset.y += (tar_y - loc.y) * relax_power
|
|
|
|
if collide_power > 0:
|
|
# Collision
|
|
for other in nodes:
|
|
if other == node:
|
|
continue
|
|
if other.type == 'FRAME':
|
|
continue
|
|
collide(loc, global_loc(other), size, other.dimensions,
|
|
offset, collide_power, collide_dist)
|
|
|
|
if abs(offset.x) > MOVE_UNIT or abs(offset.y) > MOVE_UNIT:
|
|
node.location += offset * influence
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
|
|
def socket_pos(socket, sockets, size):
|
|
i = 0
|
|
sockets_filtered = []
|
|
for s in sockets:
|
|
if len(s.links) > 0:
|
|
sockets_filtered.append(s)
|
|
|
|
for s in sockets_filtered:
|
|
if s == socket:
|
|
return (i / len(sockets_filtered)) * size
|
|
|
|
i += 1
|
|
return size / 2
|
|
|
|
|
|
def calc_collision_y(node, nodes, collide_power, collide_dist):
|
|
if node.type == 'FRAME':
|
|
return False
|
|
|
|
loc = global_loc(node)
|
|
size = node.dimensions
|
|
|
|
offset = mathutils.Vector((0, 0))
|
|
|
|
# Collision
|
|
for other in nodes:
|
|
if other == node:
|
|
continue
|
|
if other.type == 'FRAME':
|
|
continue
|
|
collide(loc, global_loc(other), size, other.dimensions,
|
|
offset, 1, collide_dist, True)
|
|
|
|
if abs(offset.y) > MOVE_UNIT:
|
|
node.location += offset * collide_power
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
|
|
def arrange_relax(node, influence, relax_power, distance, clamped_pull):
|
|
if node.type == 'FRAME':
|
|
return False
|
|
|
|
loc = global_loc(node)
|
|
size = node.dimensions
|
|
|
|
offset = mathutils.Vector((0, 0))
|
|
|
|
# Relax
|
|
tar_y = 0
|
|
tar_x_in = loc.x if clamped_pull else 0
|
|
link_cnt = 0
|
|
has_input = False
|
|
for socket in node.inputs: # Input links
|
|
for link in socket.links:
|
|
other = link.from_node
|
|
# if node.parent != other.parent: continue
|
|
loc_other = global_loc(other)
|
|
size_other = other.dimensions
|
|
|
|
x = loc_other.x + size_other.x + distance
|
|
if clamped_pull:
|
|
if has_input > 0:
|
|
tar_x_in = max(tar_x_in, x)
|
|
else:
|
|
tar_x_in = x
|
|
else:
|
|
tar_x_in += x
|
|
has_input = True
|
|
|
|
tar_y += loc_other.y + socket_pos(socket, node.inputs, size.y) - socket_pos(link.from_socket, other.outputs,
|
|
size_other.y)
|
|
link_cnt += 1
|
|
|
|
tar_x_out = loc.x if clamped_pull else 0
|
|
has_output = False
|
|
for socket in node.outputs: # Output links
|
|
for link in socket.links:
|
|
other = link.to_node
|
|
# if node.parent != other.parent: continue
|
|
loc_other = global_loc(other)
|
|
size_other = other.dimensions
|
|
|
|
x = loc_other.x - size.x - distance
|
|
if clamped_pull:
|
|
if has_output > 0:
|
|
tar_x_out = min(tar_x_out, x)
|
|
else:
|
|
tar_x_out = x
|
|
else:
|
|
tar_x_out += x
|
|
has_output = True
|
|
|
|
tar_y += loc_other.y + socket_pos(socket, node.outputs, size.y) - socket_pos(link.to_socket, other.inputs,
|
|
size_other.y)
|
|
link_cnt += 1
|
|
|
|
if link_cnt > 0:
|
|
if clamped_pull:
|
|
tar_x = tar_x_in * int(has_input) + tar_x_out * int(has_output)
|
|
tar_x /= int(has_input) + int(has_output)
|
|
else:
|
|
tar_x = (tar_x_in + tar_x_out) / link_cnt
|
|
tar_y /= link_cnt
|
|
offset.x += (tar_x - loc.x) * relax_power
|
|
offset.y += (tar_y - loc.y) * relax_power
|
|
|
|
if abs(offset.x) > MOVE_UNIT or abs(offset.y) > MOVE_UNIT:
|
|
node.location += offset * influence
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
|
|
def collide(loc0, loc1, size0, size1, offset, power, dist, only_y=False):
|
|
pos0 = loc0 + size0 / 2
|
|
pos1 = loc1 + size1 / 2
|
|
pos0.y -= size0.y
|
|
pos1.y -= size1.y
|
|
|
|
size = (size0 + size1) / 2 + dist
|
|
delta = pos1 - pos0
|
|
inters = size - mathutils.Vector((abs(delta.x), abs(delta.y)))
|
|
|
|
if inters.x > 0 and inters.y > 0:
|
|
if inters.y < inters.x or only_y:
|
|
if delta.y > 0:
|
|
inters.y *= -1
|
|
offset.y += inters.y / 2 * power
|
|
else:
|
|
if delta.x > 0:
|
|
inters.x *= -1
|
|
offset.x += inters.x / 2 * power |