@ -300,92 +300,95 @@ class PlasmaNodeBase:
""" Ensures that sockets are linked appropriately and there are enough inputs """
input_defs , output_defs = self . _socket_defs
for defs , sockets in ( ( input_defs , self . inputs ) , ( output_defs , self . outputs ) ) :
done = set ( )
# Need to enumerate by hand because blendsucks has major (crashing) issues if we modify
# this swhizzle while stuff is going down.
i = 0
while i < len ( sockets ) :
socket = sockets [ i ]
node = socket . node
options = defs . get ( socket . alias , None )
if options is None or socket . bl_idname != options [ " type " ] :
sockets . remove ( socket )
continue
self . _update_extant_sockets ( defs , sockets )
self . _update_init_sockets ( defs , sockets )
def _update_init_sockets ( self , defs , sockets ) :
# Create any missing sockets and spawn any required empties.
for alias , options in defs . items ( ) :
working_sockets = [ ( i , socket ) for i , socket in enumerate ( sockets ) if socket . alias == alias ]
if not working_sockets :
self . _spawn_socket ( alias , options , sockets )
elif options . get ( " spawn_empty " , False ) :
last_socket_id = next ( reversed ( working_sockets ) ) [ 0 ]
for working_id , working_socket in working_sockets :
if working_id == last_socket_id and working_socket . is_linked :
new_socket_id = len ( sockets )
new_socket = self . _spawn_socket ( alias , options , sockets )
desired_id = last_socket_id + 1
if new_socket_id != desired_id :
sockets . move ( new_socket_id , desired_id )
elif working_id < last_socket_id and not working_socket . is_linked :
# Indices do not update until after the update() function finishes, so
# no need to decrement last_socket_id
sockets . remove ( working_socket )
def _update_extant_sockets ( self , defs , sockets ) :
# Manually enumerate the sockets that are present for their presence and for the
# validity of their links. Can't use a for because we will overrun and crash Blender.
i = 0
while i < len ( sockets ) :
socket = sockets [ i ]
node = socket . node
options = defs . get ( socket . alias , None )
if options is None or socket . bl_idname != options [ " type " ] :
sockets . remove ( socket )
continue
# Make sure the socket info is up to date
socket . name = options [ " text " ]
link_limit = options . get ( " link_limit " , None )
if link_limit is not None :
socket . link_limit = link_limit
socket . hide = options . get ( " hidden " , False )
socket . hide_value = options . get ( " hidden " , False )
# Make sure the link is good
allowed_sockets = options . get ( " valid_link_sockets " , None )
allowed_nodes = options . get ( " valid_link_nodes " , None )
# The socket may decide it doesn't want anyone linked to it.
can_link_attr = options . get ( " can_link " , None )
if can_link_attr is not None :
can_link = getattr ( node , can_link_attr )
socket . enabled = can_link
if not can_link :
for link in socket . links :
# Make sure the socket info is up to date
socket . name = options [ " text " ]
link_limit = options . get ( " link_limit " , None )
if link_limit is not None :
socket . link_limit = link_limit
socket . hide = options . get ( " hidden " , False )
socket . hide_value = options . get ( " hidden " , False )
# Make sure the link is good
allowed_sockets = options . get ( " valid_link_sockets " , None )
allowed_nodes = options . get ( " valid_link_nodes " , None )
# The socket may decide it doesn't want anyone linked to it.
can_link_attr = options . get ( " can_link " , None )
if can_link_attr is not None :
can_link = getattr ( node , can_link_attr )
socket . enabled = can_link
if not can_link :
for link in socket . links :
try :
self . _tattle ( socket , link , " (socket refused link) " )
self . id_data . links . remove ( link )
except RuntimeError :
# was already removed by someone else
pass
# Helpful default... If neither are set, require the link to be to the same socket type
if allowed_nodes is None and allowed_sockets is None :
allowed_sockets = frozenset ( ( options [ " type " ] , ) )
if allowed_sockets or allowed_nodes :
for link in socket . links :
if allowed_nodes :
to_from_node = link . to_node if socket . is_output else link . from_node
if to_from_node . bl_idname not in allowed_nodes :
try :
self . _tattle ( socket , link , " (socket refused link) " )
self . _tattle ( socket , link , " (bad node ) " )
self . id_data . links . remove ( link )
except RuntimeError :
# was already removed by someone else
pass
continue
if allowed_sockets :
to_from_socket = link . to_socket if socket . is_output else link . from_socket
if to_from_socket is None or to_from_socket . bl_idname not in allowed_sockets :
try :
self . _tattle ( socket , link , " (bad socket) " )
self . id_data . links . remove ( link )
except RuntimeError :
# was already removed by someone else
pass
continue
# Helpful default... If neither are set, require the link to be to the same socket type
if allowed_nodes is None and allowed_sockets is None :
allowed_sockets = frozenset ( ( options [ " type " ] , ) )
if allowed_sockets or allowed_nodes :
for link in socket . links :
if allowed_nodes :
to_from_node = link . to_node if socket . is_output else link . from_node
if to_from_node . bl_idname not in allowed_nodes :
try :
self . _tattle ( socket , link , " (bad node) " )
self . id_data . links . remove ( link )
except RuntimeError :
# was already removed by someone else
pass
continue
if allowed_sockets :
to_from_socket = link . to_socket if socket . is_output else link . from_socket
if to_from_socket is None or to_from_socket . bl_idname not in allowed_sockets :
try :
self . _tattle ( socket , link , " (bad socket) " )
self . id_data . links . remove ( link )
except RuntimeError :
# was already removed by someone else
pass
continue
# If this is a spawn empty socket, make sure we have exactly one empty socket
if options . get ( " spawn_empty " , False ) and not socket . alias in done :
empty_sockets = [ j for j in sockets if j . bl_idname == socket . bl_idname and not j . is_used ]
if not empty_sockets :
idx = len ( sockets )
dbg = sockets . new ( socket . bl_idname , socket . name , socket . alias )
# don't even ask...
new_idx = i + 2
if idx != new_idx :
sockets . move ( idx , new_idx )
else :
while len ( empty_sockets ) > 1 :
sockets . remove ( empty_sockets . pop ( ) )
done . add ( socket . alias )
i + = 1
# Create any new sockets
for alias in ( j for j in defs if j not in done ) :
self . _spawn_socket ( alias , defs [ alias ] , sockets )
i + = 1
def _whine ( self , msg , * args ) :
if args :