[Bf-blender-cvs] [e98a352] object_nodes: Moved the conversion of bNodeTree (DNA/pynodes) to python code for simplicity.
Lukas Tönne
noreply at git.blender.org
Tue Nov 24 09:43:43 CET 2015
Commit: e98a35220de89d40685f1704f703064d392c24be
Author: Lukas Tönne
Date: Sun Nov 1 12:33:09 2015 +0100
Branches: object_nodes
https://developer.blender.org/rBe98a35220de89d40685f1704f703064d392c24be
Moved the conversion of bNodeTree (DNA/pynodes) to python code for simplicity.
This has several advantages over doing the same in C/C++ code:
- The two parts of the code are clearly separate (parsing DNA settings vs. building and evaluating)
- UI constructs with modes, special cases, etc. can be done in py, heavy lifting still happens in C
- Scripters can easily add own nodes without having to deal with internals
===================================================================
M release/scripts/startup/bl_operators/object_nodes.py
M source/blender/blenvm/BVM_api.h
M source/blender/blenvm/bvm/bvm_eval.cc
M source/blender/blenvm/intern/bvm_api.cc
M source/blender/makesrna/RNA_access.h
M source/blender/makesrna/intern/CMakeLists.txt
M source/blender/makesrna/intern/makesrna.c
A source/blender/makesrna/intern/rna_blenvm.c
M source/blender/makesrna/intern/rna_internal.h
M source/blender/makesrna/intern/rna_nodetree.c
===================================================================
diff --git a/release/scripts/startup/bl_operators/object_nodes.py b/release/scripts/startup/bl_operators/object_nodes.py
index 4d27d2f..59d55ff 100644
--- a/release/scripts/startup/bl_operators/object_nodes.py
+++ b/release/scripts/startup/bl_operators/object_nodes.py
@@ -63,7 +63,78 @@ node_categories = [
###############################################################################
-class ObjectNodeTree(NodeTree):
+class NodeCompiler:
+ def __init__(self, context, graph):
+ self.context = context
+ self.graph = graph
+ self.current_node = None
+ self.input_map = dict()
+ self.output_map = dict()
+
+ def add_node(self, type, name):
+ node = self.graph.add_node(type, name)
+ if node is None:
+ raise Exception("Can not add node of type %r" % type)
+ return node
+
+ def map_input(self, index, node, name):
+ socket = self.current_node.inputs[index]
+ key = (self.current_node, socket)
+ if key not in self.input_map:
+ pairs = set()
+ self.input_map[key] = pairs
+ else:
+ pairs = self.input_map[key]
+ pairs.add((node, name))
+
+ if isinstance(socket, bpy.types.NodeSocketFloat):
+ node.set_value_float(name, socket.default_value)
+ elif isinstance(socket, bpy.types.NodeSocketVector):
+ node.set_value_float3(name, socket.default_value)
+ elif isinstance(socket, bpy.types.NodeSocketColor):
+ node.set_value_float4(name, socket.default_value)
+ elif isinstance(socket, bpy.types.NodeSocketColor):
+ node.set_value_float4(name, socket.default_value)
+ elif isinstance(socket, bpy.types.NodeSocketInt):
+ node.set_value_int(name, socket.default_value)
+
+ def map_output(self, index, node, name):
+ socket = self.current_node.outputs[index]
+ key = (self.current_node, socket)
+ if key in self.output_map:
+ raise KeyError("Node output {}:{} is already mapped".format(self.current_node.name, socket.name))
+ self.output_map[key] = (node, name)
+
+ def add_link(self, blink):
+ (from_node, from_socket) = self.output_map.get((blink.from_node, blink.from_socket), (None, None))
+ to_set = self.input_map.get((blink.to_node, blink.to_socket), set())
+ if from_node and from_socket:
+ for (to_node, to_socket) in to_set:
+ self.graph.add_link(from_node, from_socket, to_node, to_socket)
+
+ def set_output(self, name, node, socket):
+ self.graph.set_output(name, node, socket)
+
+
+class NodeTreeBase():
+ def bvm_compile(self, context, graph):
+ comp = NodeCompiler(context, graph)
+
+ for bnode in self.nodes:
+ if not bnode.is_registered_node_type():
+ continue
+ comp.current_node = bnode
+ bnode.compile(comp)
+ comp.current_node = None
+
+ for blink in self.links:
+ if not blink.is_valid:
+ continue
+
+ comp.add_link(blink)
+
+
+class ObjectNodeTree(NodeTreeBase, NodeTree):
'''Object component nodes'''
bl_idname = 'ObjectNodeTree'
bl_label = 'Object Nodes'
@@ -98,9 +169,12 @@ class ForceFieldNode(ObjectNodeBase, ObjectNode):
def draw_buttons(self, context, layout):
layout.template_ID(self, "id", new="object_nodes.force_field_nodes_new")
+ def compile(self, compiler):
+ pass
+
###############################################################################
-class ForceFieldNodeTree(NodeTree):
+class ForceFieldNodeTree(NodeTreeBase, NodeTree):
'''Force field nodes'''
bl_idname = 'ForceFieldNodeTree'
bl_label = 'Force Field Nodes'
@@ -128,6 +202,15 @@ class ForceOutputNode(ForceNodeBase, ObjectNode):
self.inputs.new('NodeSocketVector', "Force")
self.inputs.new('NodeSocketVector', "Impulse")
+ def compile(self, compiler):
+ node = compiler.add_node("PASS_FLOAT3", self.name+"FORCE")
+ compiler.map_input(0, node, "value")
+ compiler.set_output("force", node, "value")
+
+ node = compiler.add_node("PASS_FLOAT3", self.name+"IMPULSE")
+ compiler.map_input(1, node, "value")
+ compiler.set_output("impulse", node, "value")
+
class SeparateVectorNode(ForceNodeBase, ObjectNode):
'''Separate vector into elements'''
@@ -140,6 +223,22 @@ class SeparateVectorNode(ForceNodeBase, ObjectNode):
self.outputs.new('NodeSocketFloat', "Y")
self.outputs.new('NodeSocketFloat', "Z")
+ def compile(self, compiler):
+ node = compiler.add_node("GET_ELEM_FLOAT3", self.name+"X")
+ node.set_value_int("index", 0)
+ compiler.map_input(0, node, "value")
+ compiler.map_output(0, node, "value")
+
+ node = compiler.add_node("GET_ELEM_FLOAT3", self.name+"Y")
+ node.set_value_int("index", 1)
+ compiler.map_input(0, node, "value")
+ compiler.map_output(1, node, "value")
+
+ node = compiler.add_node("GET_ELEM_FLOAT3", self.name+"Z")
+ node.set_value_int("index", 2)
+ compiler.map_input(0, node, "value")
+ compiler.map_output(2, node, "value")
+
class CombineVectorNode(ForceNodeBase, ObjectNode):
'''Combine vector from component values'''
@@ -152,6 +251,13 @@ class CombineVectorNode(ForceNodeBase, ObjectNode):
self.inputs.new('NodeSocketFloat', "Z")
self.outputs.new('NodeSocketVector', "Vector")
+ def compile(self, compiler):
+ node = compiler.add_node("SET_FLOAT3", self.name+"N")
+ compiler.map_input(0, node, "value_x")
+ compiler.map_input(1, node, "value_y")
+ compiler.map_input(2, node, "value_z")
+ compiler.map_output(0, node, "value")
+
class PointDataNode(ForceNodeBase, ObjectNode):
'''Input data of physical points'''
@@ -162,6 +268,12 @@ class PointDataNode(ForceNodeBase, ObjectNode):
self.outputs.new('NodeSocketVector', "Position")
self.outputs.new('NodeSocketVector', "Velocity")
+ def compile(self, compiler):
+ node = compiler.add_node("POINT_POSITION", self.name+"P")
+ compiler.map_output(0, node, "value")
+ node = compiler.add_node("POINT_VELOCITY", self.name+"V")
+ compiler.map_output(1, node, "value")
+
class MathNode(ForceNodeBase, ObjectNode):
'''Math '''
@@ -169,10 +281,10 @@ class MathNode(ForceNodeBase, ObjectNode):
bl_label = 'Math'
_mode_items = [
- ('ADD', 'Add', '', 'NONE', 0),
- ('SUB', 'Subtract', '', 'NONE', 1),
- ('MUL', 'Multiply', '', 'NONE', 2),
- ('DIV', 'Divide', '', 'NONE', 3),
+ ('ADD_FLOAT', 'Add', '', 'NONE', 0),
+ ('SUB_FLOAT', 'Subtract', '', 'NONE', 1),
+ ('MUL_FLOAT', 'Multiply', '', 'NONE', 2),
+ ('DIV_FLOAT', 'Divide', '', 'NONE', 3),
('SINE', 'Sine', '', 'NONE', 4),
('COSINE', 'Cosine', '', 'NONE', 5),
('TANGENT', 'Tangent', '', 'NONE', 6),
@@ -201,18 +313,29 @@ class MathNode(ForceNodeBase, ObjectNode):
self.inputs.new('NodeSocketFloat', "Value")
self.outputs.new('NodeSocketFloat', "Value")
+ def compile(self, compiler):
+ node = compiler.add_node(self.mode, self.name+"N")
-class ForceClosestPointNode(ForceNodeBase, ObjectNode):
- '''Closest point on the effector mesh'''
- bl_idname = 'ForceClosestPointNode'
- bl_label = 'Closest Point'
- bl_icon = 'FORCE_FORCE'
+ is_binary = self.mode in {'ADD_FLOAT', 'SUB_FLOAT', 'MUL_FLOAT', 'DIV_FLOAT',
+ 'POWER', 'LOGARITHM', 'MINIMUM', 'MAXIMUM',
+ 'LESS_THAN', 'GREATER_THAN', 'MODULO'}
- def init(self, context):
- self.inputs.new('NodeSocketVector', "Vector")
- self.outputs.new('NodeSocketVector', "Position")
- self.outputs.new('NodeSocketVector', "Normal")
- self.outputs.new('NodeSocketVector', "Tangent")
+ if is_binary:
+ # binary mode
+ compiler.map_input(0, node, "value_a")
+ compiler.map_input(1, node, "value_b")
+ else:
+ # unary mode
+ socket_a = self.inputs[0]
+ socket_b = self.inputs[1]
+ linked_a = (not socket_a.hide) and socket_a.is_linked
+ linked_b = (not socket_a.hide) and socket_a.is_linked
+ if linked_a or (not linked_b):
+ compiler.map_input(0, node, "value")
+ else:
+ compiler.map_input(1, node, "value")
+
+ compiler.map_output(0, node, "value")
class VectorMathNode(ForceNodeBase, ObjectNode):
@@ -221,12 +344,12 @@ class VectorMathNode(ForceNodeBase, ObjectNode):
bl_label = 'Vector Math'
_mode_items = [
- ('ADD', 'Add', '', 'NONE', 0),
- ('SUB', 'Subtract', '', 'NONE', 1),
- ('AVERAGE', 'Average', '', 'NONE', 2),
- ('DOT', 'Dot Product', '', 'NONE', 3),
- ('CROSS', 'Cross Product', '', 'NONE', 4),
- ('NORMALIZE', 'Normalize', '', 'NONE', 5),
+ ('ADD_FLOAT3', 'Add', '', 'NONE', 0),
+ ('SUB_FLOAT3', 'Subtract', '', 'NONE', 1),
+ ('AVERAGE_FLOAT3', 'Average', '', 'NONE', 2),
+ ('DOT_FLOAT3', 'Dot Product', '', 'NONE', 3),
+ ('CROSS_FLOAT3', 'Cross Product', '', 'NONE', 4),
+ ('NORMALIZE_FLOAT3', 'Normalize', '', 'NONE', 5),
]
mode = EnumProperty(name="Mode",
items=_mode_items)
@@ -240,6 +363,54 @@ class VectorMathNode(ForceNodeBase, ObjectNode):
self.outputs.new('NodeSocketVector', "Vector")
self.outputs.new('NodeSocketFloat', "Value")
+ def compile(self, compiler):
+ node = compiler.add_node(self.mode, self.name+"N")
+
+ is_binary = self.mode in {'ADD_FLOAT3', 'SUB_FLOAT3', 'AVERAGE_FLOAT3',
+ 'DOT_FLOAT3', 'CROSS_FLOAT3'}
+ has_vector_out = self.mode in {'ADD_FLOAT3', 'SUB_FLOAT3', 'AVERAGE_FLOAT3',
+ 'CROSS_FLOAT3', 'NORMALIZE_FLOAT3'}
+ has_value_out = self.mode in {'DOT_FLOAT3', 'NORMALIZE_FLOAT3'}
+
+ if is_binary:
+
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list