[Bf-blender-cvs] [fae338bf7ce] functions: initial variadic list declaration

Jacques Lucke noreply at git.blender.org
Tue Mar 19 12:03:59 CET 2019


Commit: fae338bf7ce7e9fb7f7e8abc7921095a4a861308
Author: Jacques Lucke
Date:   Tue Mar 19 12:03:47 2019 +0100
Branches: functions
https://developer.blender.org/rBfae338bf7ce7e9fb7f7e8abc7921095a4a861308

initial variadic list declaration

===================================================================

M	release/scripts/startup/function_nodes/inferencer.py
A	release/scripts/startup/function_nodes/nodes/create_list.py
M	release/scripts/startup/function_nodes/socket_decl.py
M	release/scripts/startup/function_nodes/test_inferencer.py
M	release/scripts/startup/function_nodes/update_sockets.py

===================================================================

diff --git a/release/scripts/startup/function_nodes/inferencer.py b/release/scripts/startup/function_nodes/inferencer.py
index 925f46dcd72..e720f1fb179 100644
--- a/release/scripts/startup/function_nodes/inferencer.py
+++ b/release/scripts/startup/function_nodes/inferencer.py
@@ -1,6 +1,7 @@
+from . sockets import type_infos
+
 class Inferencer:
-    def __init__(self, type_infos):
-        self.type_infos = type_infos
+    def __init__(self):
         self.finalized_ids = dict()
         self.constraints = set()
         self.decisions = dict()
@@ -13,13 +14,17 @@ class Inferencer:
         self.constraints.add(constraint)
 
     def insert_list_constraint(self, list_ids, base_ids=tuple(), decision_id=None):
-        constraint = ListConstraint(list_ids, base_ids, decision_id, self.type_infos)
+        constraint = ListConstraint(list_ids, base_ids, decision_id)
         self.constraints.add(constraint)
 
     def insert_union_constraint(self, ids, allowed_types, decision_id=None):
         constraint = UnionConstraint(ids, decision_id, allowed_types)
         self.constraints.add(constraint)
 
+    def insert_list_or_base_constraint(self, id, base_type, decision_id=None):
+        constraint = ListOrBaseConstraint(id, decision_id, base_type)
+        self.constraints.add(constraint)
+
     def finalize_id(self, id, data_type):
         if id in self.finalized_ids:
             if self.finalized_ids[id] != data_type:
@@ -33,6 +38,8 @@ class Inferencer:
             self.finalize_id(id, data_type)
 
     def make_decision(self, decision_id, value):
+        if decision_id is None:
+            return
         assert decision_id not in self.decisions
         self.decisions[decision_id] = value
 
@@ -79,8 +86,7 @@ class EqualityConstraint(Constraint):
             if id in finalized_ids:
                 data_type = finalized_ids[id]
                 finalize_do(self.ids, data_type)
-                if self.decision_id is not None:
-                    make_decision(self.decision_id, data_type)
+                make_decision(self.decision_id, data_type)
                 return True
         return False
 
@@ -97,43 +103,61 @@ class UnionConstraint(Constraint):
                 if data_type not in self.allowed_types:
                     raise InferencingError()
                 finalize_do(self.ids, data_type)
-                if self.decision_id is not None:
-                    make_decision(self.decision_id, data_type)
+                make_decision(self.decision_id, data_type)
                 return True
         return False
 
 class ListConstraint(Constraint):
-    def __init__(self, list_ids, base_ids, decision_id, type_infos):
+    def __init__(self, list_ids, base_ids, decision_id):
         self.list_ids = set(list_ids)
         self.base_ids = set(base_ids)
         self.decision_id = decision_id
-        self.type_infos = type_infos
 
     def try_finalize(self, finalized_ids, finalize_do, make_decision):
         for id in self.list_ids:
             if id in finalized_ids:
                 list_type = finalized_ids[id]
-                if not self.type_infos.is_list(list_type):
+                if not type_infos.is_list(list_type):
                     raise NoListTypeError()
-                base_type = self.type_infos.to_base(list_type)
+                base_type = type_infos.to_base(list_type)
                 finalize_do(self.list_ids, list_type)
                 finalize_do(self.base_ids, base_type)
-                if self.decision_id is not None:
-                    make_decision(self.decision_id, base_type)
+                make_decision(self.decision_id, base_type)
                 return True
         for id in self.base_ids:
             if id in finalized_ids:
                 base_type = finalized_ids[id]
-                if not self.type_infos.is_base(base_type):
+                if not type_infos.is_base(base_type):
                     raise NoBaseTypeError()
-                list_type = self.type_infos.to_list(base_type)
+                list_type = type_infos.to_list(base_type)
                 finalize_do(self.base_ids, base_type)
                 finalize_do(self.list_ids, list_type)
-                if self.decision_id is not None:
-                    make_decision(self.decision_id, base_type)
+                make_decision(self.decision_id, base_type)
+                return True
+        return False
+
+class ListOrBaseConstraint(Constraint):
+    def __init__(self, id, decision_id, base_type):
+        self.id = id
+        self.decision_id = decision_id
+        self.base_type = base_type
+        self.list_type = type_infos.to_list(base_type)
+
+    def try_finalize(self, finalized_ids, finalize_do, make_decision):
+        if self.id in finalized_ids:
+            data_type = finalized_ids[self.id]
+            if data_type == self.base_type:
+                make_decision(self.decision_id, "BASE")
                 return True
+            elif data_type == self.list_type:
+                make_decision(self.decision_id, "LIST")
+                return True
+            else:
+                msg = f"{data_type} is not {self.base_type} or {self.list_type}"
+                raise ConflictingTypesError(msg)
         return False
 
+
 class InferencingError(Exception):
     pass
 
diff --git a/release/scripts/startup/function_nodes/nodes/create_list.py b/release/scripts/startup/function_nodes/nodes/create_list.py
new file mode 100644
index 00000000000..0216f36f3ea
--- /dev/null
+++ b/release/scripts/startup/function_nodes/nodes/create_list.py
@@ -0,0 +1,19 @@
+import bpy
+from bpy.props import *
+from .. base import FunctionNode
+from .. socket_decl import VariadicListDecl, FixedSocketDecl
+from .. sockets import type_infos
+
+class CreateListNode(bpy.types.Node, FunctionNode):
+    bl_idname = "fn_CreateListNode"
+    bl_label = "Create List"
+
+    active_type: StringProperty(default="Float")
+    variadic: VariadicListDecl.Property()
+
+    def get_sockets(self):
+        return [
+            VariadicListDecl("inputs", "variadic", self.active_type),
+        ], [
+            FixedSocketDecl("output", "List", type_infos.to_list(self.active_type)),
+        ]
\ No newline at end of file
diff --git a/release/scripts/startup/function_nodes/socket_decl.py b/release/scripts/startup/function_nodes/socket_decl.py
index c49bfb858ea..a89e18f301b 100644
--- a/release/scripts/startup/function_nodes/socket_decl.py
+++ b/release/scripts/startup/function_nodes/socket_decl.py
@@ -103,6 +103,77 @@ class AnyOfDecl(SocketDeclBase):
     def Property(cls, default_type):
         return StringProperty(default=default_type)
 
+class VariadicListDecl(SocketDeclBase):
+    def __init__(self, identifier: str, prop_name: str, base_type: str):
+        self.identifier_suffix = identifier
+        self.prop_name = prop_name
+        self.base_type = base_type
+        self.list_type = type_infos.to_list(base_type)
+
+    def build(self, node, node_sockets):
+        return list(self._build(node, node_sockets))
+
+    def _build(self, node, node_sockets):
+        for item in self.get_collection(node):
+            data_type = self.base_type if item.state == "BASE" else self.list_type
+            yield type_infos.build(
+                data_type,
+                node_sockets,
+                "",
+                item.identifier_prefix + self.identifier_suffix)
+        yield node_sockets.new("fn_OperatorSocket", "Operator")
+
+    def draw_socket(self, layout, node, socket, index):
+        if isinstance(socket, OperatorSocket):
+            layout.label(text="New")
+        else:
+            socket.draw_self(layout, node)
+
+    def operator_socket_call(self, node, own_socket, other_socket):
+        if not isinstance(other_socket, DataSocket):
+            return
+
+        is_output = own_socket.is_output
+        data_type = other_socket.data_type
+
+        if type_infos.is_base(data_type):
+            if data_type != self.base_type:
+                return
+            state = "BASE"
+        elif type_infos.is_list(data_type):
+            if data_type != self.list_type:
+                return
+            state = "LIST"
+        else:
+            return
+
+        collection = self.get_collection(node)
+        item = collection.add()
+        item.state = state
+        item.identifier_prefix = str(uuid.uuid4())
+
+        node.rebuild_and_try_keep_state()
+
+        identifier = item.identifier_prefix + self.identifier_suffix
+        new_socket = node.find_socket(identifier, is_output)
+        node.tree.new_link(other_socket, new_socket)
+
+    def amount(self, node):
+        return len(self.get_collection(node)) + 1
+
+    def get_collection(self, node):
+        return getattr(node, self.prop_name)
+
+    @classmethod
+    def Property(cls):
+        return CollectionProperty(type=VariadicListPropertyGroup)
+
+class VariadicListPropertyGroup(bpy.types.PropertyGroup):
+    bl_idname = "fn_VariadicListPropertyGroup"
+
+    state: StringProperty(default="BASE")
+    identifier_prefix: StringProperty()
+
 class AnyVariadicDecl(SocketDeclBase):
     def __init__(self, identifier: str, prop_name: str, message: str):
         self.identifier_suffix = identifier
@@ -113,7 +184,7 @@ class AnyVariadicDecl(SocketDeclBase):
         return list(self._build(node, node_sockets))
 
     def _build(self, node, node_sockets):
-        for item in getattr(node, self.prop_name):
+        for item in self.get_collection(node):
             yield type_infos.build(
                 item.data_type,
                 node_sockets,
@@ -122,7 +193,7 @@ class AnyVariadicDecl(SocketDeclBase):
         yield node_sockets.new("fn_OperatorSocket", "Operator")
 
     def amount(self, node):
-        return len(getattr(node, self.prop_name)) + 1
+        return len(self.get_collection(node)) + 1
 
     def draw_socket(self, layout, node, socket, index):
         if isinstance(socket, OperatorSocket):
@@ -149,7 +220,7 @@ class AnyVariadicDecl(SocketDeclBase):
         is_output = own_socket.is_output
         data_type = other_socket.data_type
 
-        collection = getattr(node, self.prop_name)
+        collection = self.get_collection(no

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list