[Bf-blender-cvs] [c6659bf742b] functions-temp: experiment with more complex socket declarations

Jacques Lucke noreply at git.blender.org
Sun Mar 17 21:19:35 CET 2019


Commit: c6659bf742bdec2dbd12c8e8d32b1f2fc8d64d09
Author: Jacques Lucke
Date:   Sun Mar 17 21:19:23 2019 +0100
Branches: functions-temp
https://developer.blender.org/rBc6659bf742bdec2dbd12c8e8d32b1f2fc8d64d09

experiment with more complex socket declarations

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

M	release/scripts/startup/function_nodes/base.py
M	release/scripts/startup/function_nodes/inferencer.py
M	release/scripts/startup/function_nodes/nodes/append_to_list.py
M	release/scripts/startup/function_nodes/nodes/clamp.py
M	release/scripts/startup/function_nodes/nodes/combine_lists.py
M	release/scripts/startup/function_nodes/nodes/combine_vector.py
M	release/scripts/startup/function_nodes/nodes/float_math.py
M	release/scripts/startup/function_nodes/nodes/function_input.py
M	release/scripts/startup/function_nodes/nodes/function_output.py
M	release/scripts/startup/function_nodes/nodes/get_list_element.py
M	release/scripts/startup/function_nodes/nodes/map_range.py
M	release/scripts/startup/function_nodes/nodes/object_transforms.py
M	release/scripts/startup/function_nodes/nodes/random_number.py
M	release/scripts/startup/function_nodes/nodes/separate_vector.py
M	release/scripts/startup/function_nodes/nodes/vector_distance.py
M	release/scripts/startup/function_nodes/socket_decl.py
M	release/scripts/startup/function_nodes/sockets.py
M	release/scripts/startup/function_nodes/update_sockets.py
M	release/scripts/startup/function_nodes/utils/generic.py

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

diff --git a/release/scripts/startup/function_nodes/base.py b/release/scripts/startup/function_nodes/base.py
index 8af190b9903..c484864d475 100644
--- a/release/scripts/startup/function_nodes/base.py
+++ b/release/scripts/startup/function_nodes/base.py
@@ -1,14 +1,108 @@
 import bpy
 from bpy.props import *
 from . utils.generic import iter_subclasses_recursive
+import itertools
+from collections import defaultdict
 
-class FunctionNodeTree(bpy.types.NodeTree):
+class BaseTree:
+    def new_link(self, a, b):
+        if a.is_output:
+            self.links.new(a, b)
+        else:
+            self.links.new(b, a)
+
+class FunctionNodeTree(bpy.types.NodeTree, BaseTree):
     bl_idname = "FunctionNodeTree"
     bl_icon = "MOD_DATA_TRANSFER"
     bl_label = "Function Nodes"
 
 
+class NodeStorage:
+    def __init__(self, node):
+        self.node = node
+        self.set_current_declaration(*node.get_sockets())
+
+    def set_current_declaration(self, inputs, outputs):
+        self.inputs_decl = inputs
+        self.outputs_decl = outputs
+
+        self.inputs_per_decl = {}
+        sockets = iter(self.node.inputs)
+        for decl in self.inputs_decl:
+            group = tuple(itertools.islice(sockets, decl.amount(self.node)))
+            self.inputs_per_decl[decl] = group
+
+        self.outputs_per_decl = {}
+        sockets = iter(self.node.outputs)
+        for decl in self.outputs_decl:
+            group = tuple(itertools.islice(sockets, decl.amount(self.node)))
+            self.outputs_per_decl[decl] = group
+
+        self.sockets_per_decl = {}
+        self.sockets_per_decl.update(self.inputs_per_decl)
+        self.sockets_per_decl.update(self.outputs_per_decl)
+
+        self.decl_per_socket = {}
+        self.decl_index_per_socket = {}
+        for decl, sockets in self.sockets_per_decl.items():
+            for i, socket in enumerate(sockets):
+                self.decl_per_socket[socket] = decl
+                self.decl_index_per_socket[socket] = i
+
+_storage_per_node = {}
+
 class BaseNode:
+    def init(self, context):
+        inputs, outputs = self.get_sockets()
+        for decl in inputs:
+            decl.build(self, self.inputs)
+        for decl in outputs:
+            decl.build(self, self.outputs)
+
+    def rebuild_and_try_keep_state(self):
+        state = self._get_state()
+        self.rebuild()
+        self._try_set_state(state)
+
+    def rebuild(self):
+        self.inputs.clear()
+        self.outputs.clear()
+
+        inputs, outputs = self.get_sockets()
+        for decl in self.storage.inputs_decl:
+            decl.build(self, self.inputs)
+        for decl in self.storage.outputs_decl:
+            decl.build(self, self.outputs)
+        self.storage.set_current_declaration(inputs, outputs)
+
+    def _get_state(self):
+        links_per_input = defaultdict(set)
+        links_per_output = defaultdict(set)
+
+        for link in self.tree.links:
+            if link.from_node == self:
+                links_per_output[link.from_socket.identifier].add(link.to_socket)
+            if link.to_node == self:
+                links_per_input[link.to_socket.identifier].add(link.from_socket)
+
+        return (links_per_input, links_per_output)
+
+    def _try_set_state(self, state):
+        tree = self.tree
+        for socket in self.inputs:
+            for from_socket in state[0][socket.identifier]:
+                tree.links.new(socket, from_socket)
+        for socket in self.outputs:
+            for to_socket in state[1][socket.identifier]:
+                tree.links.new(to_socket, socket)
+
+    @property
+    def tree(self):
+        return self.id_data
+
+    def get_sockets():
+        return [], []
+
     def draw_buttons(self, context, layout):
         self.draw(layout)
 
@@ -25,54 +119,77 @@ class BaseNode:
         props.function_name = function_name
         props.settings_repr = repr(settings)
 
-    def draw_socket(self, socket, layout, text):
-        socket.draw_self(layout, self, text)
+    def draw_socket(self, socket, layout):
+        decl = self.storage.decl_per_socket[socket]
+        index = self.storage.decl_index_per_socket[socket]
+        decl.draw_socket(layout, self, socket, index)
 
     @classmethod
     def iter_final_subclasses(cls):
         yield from filter(lambda x: issubclass(x, bpy.types.Node), iter_subclasses_recursive(cls))
 
-class BaseSocketDecl:
+    def find_input(self, identifier):
+        for socket in self.inputs:
+            if socket.identifier == identifier:
+                return socket
+        else:
+            return None
+
+    def find_output(self, identifier):
+        for socket in self.outputs:
+            if socket.identifier == identifier:
+                return socket
+        else:
+            return None
+
+    def find_socket(self, identifier, is_output):
+        if is_output:
+            return self.find_output(identifier)
+        else:
+            return self.find_input(identifier)
+
+    def iter_sockets(self):
+        yield from self.inputs
+        yield from self.outputs
+
+    # Storage
+    #########################
+
+    @property
+    def storage(self):
+        if self not in _storage_per_node:
+            _storage_per_node[self] = NodeStorage(self)
+        return _storage_per_node[self]
+
+
+
+class BaseSocket:
     color = (0, 0, 0, 0)
 
     def draw_color(self, context, node):
         return self.color
 
     def draw(self, context, layout, node, text):
-        node.draw_socket(self, layout, text)
-
-    def draw_self(self, layout, node, text):
-        layout.label(text=text)
-
-class FunctionNode(BaseNode):
-    def init(self, context):
-        self.rebuild()
+        node.draw_socket(self, layout)
 
-    def rebuild(self):
-        self.inputs.clear()
-        self.outputs.clear()
+    def draw_self(self, layout, node):
+        layout.label(text=self.name)
 
-        inputs, outputs = self.get_sockets()
-        for socket_decl in inputs:
-            socket_decl.build(self, self.inputs)
-        for socket_decl in outputs:
-            socket_decl.build(self, self.outputs)
-
-    def rebuild_existing_sockets(self):
-        amount_in = len(self.inputs)
-        amount_out = len(self.outputs)
-        self.rebuild()
-        assert amount_in == len(self.inputs)
-        assert amount_out == len(self.outputs)
+    def get_index(self, node):
+        if self.is_output:
+            return tuple(node.outputs).index(self)
+        else:
+            return tuple(node.inputs).index(self)
 
-    def get_sockets():
-        return [], []
+class FunctionNode(BaseNode):
+    pass
 
-class DataSocket(BaseSocketDecl):
+class DataSocket(BaseSocket):
     data_type: StringProperty(
         maxlen=64)
 
-    def draw_self(self, layout, node, text):
+    def draw_self(self, layout, node):
+        text = self.name
         if not (self.is_linked or self.is_output) and hasattr(self, "draw_property"):
             self.draw_property(layout, node, text)
         else:
diff --git a/release/scripts/startup/function_nodes/inferencer.py b/release/scripts/startup/function_nodes/inferencer.py
index 45131c30f59..1505a7c4dc4 100644
--- a/release/scripts/startup/function_nodes/inferencer.py
+++ b/release/scripts/startup/function_nodes/inferencer.py
@@ -8,8 +8,8 @@ class Inferencer:
     def insert_final_type(self, id, data_type):
         self.finalized_ids[id] = data_type
 
-    def insert_equality_constraint(self, ids):
-        constraint = EqualityConstraint(ids)
+    def insert_equality_constraint(self, ids, decision_id=None):
+        constraint = EqualityConstraint(ids, decision_id)
         self.constraints.add(constraint)
 
     def insert_list_constraint(self, list_ids, base_ids=tuple(), decision_id=None):
@@ -66,8 +66,9 @@ class Constraint:
         raise NotImplementedError()
 
 class EqualityConstraint(Constraint):
-    def __init__(self, ids):
+    def __init__(self, ids, decision_id):
         self.ids = set(ids)
+        self.decision_id = decision_id
 
     def can_be_finalized(self, finalized_ids):
         return any(id in finalized_ids for id in self.ids)
@@ -75,7 +76,10 @@ class EqualityConstraint(Constraint):
     def try_finalize(self, finalized_ids, finalize_do, make_decision):
         for id in self.ids:
             if id in finalized_ids:
-                finalize_do(self.ids, finalized_ids[id])
+                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)
                 return True
         return False
 
diff --git a/release/scripts/startup/function_nodes/nodes/append_to_list.py b/release/scripts/startup/function_nodes/nodes/append_to_list.py
index 390acb68dfb..c52d679faef 100644
--- a/release/scripts/startup/function_nodes/nodes/append_to_list.py
+++ b/release/scripts/startup/function_nodes/nodes/append_to_list.py
@@ -10,8 +10,8 @@ class AppendToListNode(bpy.types.Node, FunctionNode):
 
     def get_sockets(self):
         return [
-            ListSocketDecl("List", "active_type"),
-            BaseSocketDecl("Value", "active_type"),
+            ListSocketDecl("list", "List", "active_type"),
+            BaseSocketDecl("value", "Value", "active_type"),
         ], [
-            ListSocketDecl("List", "active_type"),
+            ListSocketDecl("list", "List", "active_type"),
         ]
\ No newline at end of file
diff --git a/release/scripts/startup/function_nodes/nodes/clamp.py b/release/scripts/startup/function_nodes/nodes/clamp.py
index 3c94de53688..e4c646703a9 100644
--- a/release/scripts/startup/function_nodes/nodes/clamp.py
+++ b/release/scripts/startup/function_nodes/nodes/clamp.py
@@ -8,9 +8,9 @@ class ClampNode(bpy.types.Node, FunctionNode):
 
     def get_sockets(self):
         return [
-            FixedSocketDecl("Value", "Float"),
-            FixedSocketDecl("Min", "Float"),
-            FixedSocketDecl("Max", "Float"),
+            FixedSocketDecl("value", "Value", "Float"),
+            FixedSocketDecl("min", "Min", "Float"),
+            FixedSocketDecl("max", "Max", "Float"),
         ], [
-            FixedSocketDecl("R

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list