# Trouble reading / writing linked nodes when creating a custom node

I've tried to figure this out for quite some time, with no luck. If anyone can help, that would be awesome! I'm essentially trying to convert the X and Y outputs of the Separate XYZ node into a radius value using the Pythagorean Theorem. Seems like it should be easy, but I don't think I'm getting the proper values from the Inputs, nor am I setting the proper value in the outputs.

When getting the values of the inputs using default_value, they always come up 0.0 for both x and y. When setting the output, I get the error: ValueError: bpy_struct: item.attr = val: sequence expected at dimension 1, not 'float'

I based my code off of the custom_nodes.py template and from a tutorial I found online. I have no idea how correct it is and there seems to be a dearth of other samples out there for me to compare against. Any help would be much appreciated! ^_^

# Implementation of custom nodes from Python
class MyCustomTree(NodeTree):
'''some stuff'''
bl_idname = 'CustomTreeType'
bl_label = 'Custom Node Tree'

# Mix-in class for all custom nodes in this tree type.
# Defines a poll function to enable instantiation.
class MyCustomTreeNode:
@classmethod
def poll(cls, ntree):
return ntree.bl_idname == 'ShaderNodeTree'

# Derived from the Node base type.
# === Basics ===
# Description string
'''XY coordinates to radius'''
# Optional identifier string. If not explicitly defined, the python class name is used.
# Label for nice name display
bl_label = 'XY To Radius'

def update_value(self, context):
print("updatevalue");
inX = self.inputs["X"]
inY = self.inputs["Y"]

self.radius = math.sqrt(pow(x_val, 2.) + pow(y_val, 2.))
else:

# === Optional Functions ===
# Initialization function, called when a new node is created.
# This is the most common place to create the sockets for a node, as shown below.
# NOTE: this is not the same as the standard __init__ function in Python, which is
#       a purely internal Python method and unknown to the node system!
def init(self, context):
print("init")
self.inputs.new('NodeSocketFloat', "X")
self.inputs.new('NodeSocketFloat', "Y")

# Additional buttons displayed on the node.
def draw_buttons(self, context, layout):
return

# Optional: custom label
# Explicit user label overrides this, but here we can define a label dynamically
def draw_label(self):
return "XY to Radius"

def update(self):
print("update")
try:
inY = self.inputs["Y"]
inX = self.inputs["X"]
can_continue = True
except:
can_continue = False
if can_continue:
for o in out.links:
if o.is_valid:
self.update_value(None)

### Node Categories ###
# Node categories are a python system for automatically
# extending the Add menu, toolbar panels and search operator.
# For more examples see release/scripts/startup/nodeitems_builtins.py

import nodeitems_utils
from nodeitems_utils import NodeCategory, NodeItem

# our own base class with an appropriate poll function,
# so the categories only show up in our own tree type
class MyNodeCategory(NodeCategory):
@classmethod
def poll(cls, context):
return context.space_data.tree_type == 'ShaderNodeTree'

# all categories in a list
node_categories = [
# identifier, label, items list
MyNodeCategory("MY_NODES", "My Nodes", items=[
# our basic node
])]

def register():
nodeitems_utils.register_node_categories("MY_NODES", node_categories)

def unregister():
nodeitems_utils.unregister_node_categories("MY_NODES")

def pre_frame_change(scene):
if scene.render.engine == 'CYCLES':
for m in bpy.data.materials:
if m.node_tree != None:
for n in m.node_tree.nodes:
if n.bl_idname == 'XYToRadius':
print(n.bl_idname)

So x.radius = (1.0, 1.0) will make a round skin vertex, while x.radius = (1.0, 2.0) will make it elliptical, etc.