55
66if bpy .app .version < (4 , 0 , 0 ):
77 from bpy .types import NodeSocketInterface
8+ else :
9+ from bpy .types import NodeTreeInterfacePanel , NodeTreeInterfaceItem
810
911import os
1012from typing import TextIO
@@ -465,114 +467,149 @@ def _set_group_socket_default_v4(self, socket_interface: bpy.types.NodeTreeInter
465467 max_val = socket_interface .max_value
466468 self ._write ((f"{ inner } { socket_var } .max_value = { max_val } \n " ))
467469
468- def _group_io_settings_v4 (self , node : bpy .types .Node , inner : str ,
469- io : str , # TODO: convert to enum
470- ntp_node_tree : NTP_NodeTree ) -> None :
470+ def _tree_interface_settings_v4 (self , inner : str ,
471+ ntp_nt : NTP_NodeTree ) -> None :
471472 """
472473 Set the settings for group input and output sockets
473474
474475 Parameters:
475- node (bpy.types.Node) : group input/output node
476476 inner (str): indentation string
477- io (str): whether we're generating the input or output settings
478- node_tree_var (str): variable name of the generated node tree
479- node_tree (bpy.types.NodeTree): node tree that we're generating
480- input and output settings for
477+ ntp_nt (NTP_NodeTree): the node tree to set the interface for
481478 """
482- node_tree_var = ntp_node_tree .var
483- node_tree = ntp_node_tree .node_tree
484-
485- if io == "input" :
486- io_sockets = node .outputs # Might be removeable,
487- # think we can get all the info from the inouts
488- # from the socket interfaces, need to double check.
489- # If so, then we can just run these at the initialization
490- # of the node tree, meaning we can clean up the clunky
491- # Group Input/Group Output node reliance, two calls
492- # Should be pretty easy to add in panels afterwards,
493- # looks like those are tied fairly close to the new socket
494- # system
495- items_tree = node_tree .interface .items_tree
496- io_socket_interfaces = [item for item in items_tree
497- if item .item_type == 'SOCKET'
498- and item .in_out == 'INPUT' ]
499- else :
500- io_sockets = node .inputs
501- items_tree = node_tree .interface .items_tree
502- io_socket_interfaces = [item for item in items_tree
503- if item .item_type == 'SOCKET'
504- and item .in_out == 'OUTPUT' ]
505-
506- self ._write (f"{ inner } #{ node_tree_var } { io } s\n " )
507- for i , socket_interface in enumerate (io_socket_interfaces ):
508- self ._write (f"{ inner } #{ io } { socket_interface .name } \n " )
509-
510- socket_interface : bpy .types .NodeTreeInterfaceSocket = io_socket_interfaces [i ]
511-
512- # initialization
513- socket_var = clean_string (socket_interface .name ) + "_socket"
514- name = str_to_py_str (socket_interface .name )
515- in_out_enum = enum_to_py_str (socket_interface .in_out )
516-
517- socket_type = enum_to_py_str (socket_interface .bl_socket_idname )
518- """
519- I might be missing something, but the Python API's set up a bit
520- weird here now. The new socket initialization only accepts types
521- from a list of basic ones, but there doesn't seem to be a way of
522- retrieving just this basic typewithout the subtype information.
523- """
524- if 'Float' in socket_type :
525- socket_type = enum_to_py_str ('NodeSocketFloat' )
526- elif 'Int' in socket_type :
527- socket_type = enum_to_py_str ('NodeSocketInt' )
528- elif 'Vector' in socket_type :
529- socket_type = enum_to_py_str ('NodeSocketVector' )
530-
531- self ._write (f"{ inner } { socket_var } = "
532- f"{ node_tree_var } .interface.new_socket("
533- f"name = { name } , in_out={ in_out_enum } , "
534- f"socket_type = { socket_type } )\n " )
535-
536- # subtype
537- if hasattr (socket_interface , "subtype" ):
538- subtype = enum_to_py_str (socket_interface .subtype )
539- self ._write (f"{ inner } { socket_var } .subtype = { subtype } \n " )
540-
541- self ._set_group_socket_default_v4 (socket_interface , inner ,
542- socket_var )
543-
544- # default attribute name
545- if socket_interface .default_attribute_name != "" :
546- dan = str_to_py_str (
547- socket_interface .default_attribute_name )
548- self ._write (
549- (f"{ inner } { socket_var } .default_attribute_name = { dan } \n " ))
550479
551- # attribute domain
552- ad = enum_to_py_str (socket_interface .attribute_domain )
553- self ._write (f"{ inner } { socket_var } .attribute_domain = { ad } \n " )
554-
555- # tooltip
556- if socket_interface .description != "" :
557- description = str_to_py_str (socket_interface .description )
558- self ._write (
559- (f"{ inner } { socket_var } .description = { description } \n " ))
560-
561- # hide_value
562- if socket_interface .hide_value is True :
563- self ._write (f"{ inner } { socket_var } .hide_value = True\n " )
564-
565- # hide in modifier
566- if socket_interface .hide_in_modifier is True :
567- self ._write (
568- f"{ inner } { socket_var } .hide_in_modifier = True\n " )
480+ self ._write (f"{ inner } #{ ntp_nt .var } interface\n " )
481+ panel_dict : dict [NodeTreeInterfacePanel , str ] = {}
482+ items_processed : set [NodeTreeInterfaceItem ] = set ()
569483
570- # force non field
571- if socket_interface .force_non_field is True :
572- self ._write (
573- f"{ inner } { socket_var } .force_non_field = True\n " )
484+ def _process_items (parent : NodeTreeInterfacePanel ):
485+ if parent is None :
486+ items = ntp_nt .node_tree .interface .items_tree
487+ else :
488+ items = parent .interface_items
489+
490+ for item in items :
491+ if item .parent .index != - 1 and item .parent not in panel_dict :
492+ continue # child of panel not processed yet
493+ if item in items_processed :
494+ continue
495+
496+ items_processed .add (item )
497+
498+ print (item .name , items_processed )
499+
500+ if item .item_type == 'SOCKET' :
501+ self ._write (f"{ inner } #Socket { item .name } \n " )
502+ # initialization
503+ socket_var = clean_string (item .name ) + "_socket"
504+ name = str_to_py_str (item .name )
505+ in_out_enum = enum_to_py_str (item .in_out )
506+
507+ socket_type = enum_to_py_str (item .bl_socket_idname )
508+ """
509+ I might be missing something, but the Python API's set up a bit
510+ weird here now. The new socket initialization only accepts types
511+ from a list of basic ones, but there doesn't seem to be a way of
512+ retrieving just this basic type without the subtype information.
513+ """
514+ if 'Float' in socket_type :
515+ socket_type = enum_to_py_str ('NodeSocketFloat' )
516+ elif 'Int' in socket_type :
517+ socket_type = enum_to_py_str ('NodeSocketInt' )
518+ elif 'Vector' in socket_type :
519+ socket_type = enum_to_py_str ('NodeSocketVector' )
520+
521+ if parent is None :
522+ optional_parent_str = ""
523+ else :
524+ optional_parent_str = f", parent = { panel_dict [parent ]} "
525+
526+ self ._write (f"{ inner } { socket_var } = "
527+ f"{ ntp_nt .var } .interface.new_socket("
528+ f"name = { name } , in_out={ in_out_enum } , "
529+ f"socket_type = { socket_type } "
530+ f"{ optional_parent_str } )\n " )
531+
532+ # subtype
533+ if hasattr (item , "subtype" ):
534+ subtype = enum_to_py_str (item .subtype )
535+ self ._write (f"{ inner } { socket_var } .subtype = { subtype } \n " )
536+
537+ self ._set_group_socket_default_v4 (item , inner ,
538+ socket_var )
539+
540+ # default attribute name
541+ if item .default_attribute_name != "" :
542+ dan = str_to_py_str (
543+ item .default_attribute_name )
544+ self ._write (
545+ (f"{ inner } { socket_var } .default_attribute_name = { dan } \n " ))
546+
547+ # attribute domain
548+ ad = enum_to_py_str (item .attribute_domain )
549+ self ._write (f"{ inner } { socket_var } .attribute_domain = { ad } \n " )
550+
551+ # hide_value
552+ if item .hide_value is True :
553+ self ._write (f"{ inner } { socket_var } .hide_value = True\n " )
554+
555+ # hide in modifier
556+ if item .hide_in_modifier is True :
557+ self ._write (
558+ f"{ inner } { socket_var } .hide_in_modifier = True\n " )
559+
560+ # force non field
561+ if item .force_non_field is True :
562+ self ._write (
563+ f"{ inner } { socket_var } .force_non_field = True\n " )
564+
565+ # tooltip
566+ if item .description != "" :
567+ description = str_to_py_str (item .description )
568+ self ._write (
569+ (f"{ inner } { socket_var } .description = { description } \n " ))
570+
571+ self ._write ("\n " )
572+
573+ elif item .item_type == 'PANEL' :
574+
575+ self ._write (f"{ inner } #Panel { item .name } \n " )
576+
577+ panel_var = clean_string (item .name ) + "_panel"
578+ panel_dict [item ] = panel_var
579+
580+ description_str = ""
581+ if item .description != "" :
582+ description_str = f", description = { str_to_py_str (item .description )} "
583+
584+ closed_str = ""
585+ if item .default_closed is True :
586+ closed_str = f", default_closed=True"
587+
588+ parent_str = ""
589+ if parent is not None :
590+ parent_str = f", parent = { panel_dict [parent ]} "
591+
592+
593+ self ._write (f"{ inner } { panel_var } = "
594+ f"{ ntp_nt .var } .interface.new_panel("
595+ f"{ str_to_py_str (item .name )} { description_str } "
596+ f"{ closed_str } { parent_str } )\n " )
597+
598+ # tooltip
599+ if item .description != "" :
600+ description = str_to_py_str (item .description )
601+ self ._write (
602+ (f"{ inner } { panel_var } .description = { description } \n " ))
603+
604+ panel_dict [item ] = panel_var
605+
606+ if len (item .interface_items ) > 0 :
607+ _process_items (item )
608+
609+ self ._write ("\n " )
610+
611+ _process_items (None )
574612
575- self ._write ("\n " )
576613 self ._write ("\n " )
577614
578615 def _group_io_settings (self , node : bpy .types .Node , inner : str ,
@@ -591,8 +628,6 @@ def _group_io_settings(self, node: bpy.types.Node, inner: str,
591628 """
592629 if bpy .app .version < (4 , 0 , 0 ):
593630 self ._group_io_settings_v3 (node , inner , io , ntp_node_tree )
594- else :
595- self ._group_io_settings_v4 (node , inner , io , ntp_node_tree )
596631
597632 def _set_input_defaults (self , node : bpy .types .Node , inner : str ,
598633 node_var : str ) -> None :
0 commit comments