Blender动画节点插件开发文档-动态套接字

推荐:将NSDT场景编辑器加入你的3D工具链
到目前为止,您所看到的开发方法效果很好,应该始终 尽可能使用,因为它可以保持代码干净。然而它有 一个很大的缺点是,它仅在插座数量保持 一直都一样。这是因为该函数具有固定的 参数数。execute
不过,许多更高级的节点支持多种模式。例如,数学节点支持许多不同的操作,其中一些 需要不同的套接字。为了展示节点如何具有多个 操作工作,我们会忘记我们上次开发的节点 零件并专注于新的。
我们现在想要开发一个名为生成点的节点(也许你应该 尝试找到一个更具体的名字...它有两种模式:
- 线:
采用两个向量(起点和方向)和一个整数(数量) 作为输入并计算线上有点的向量列表。 - 圆:
将浮点数(半径)和整数(金额)作为输入,并且 计算圆上带有点的向量列表。
显然,旧方法在这里不再有效,因为两种模式都 具有不同数量的输入。但在你了解另一个之前 关于节点执行如何在AN中工作的方法,我们将重点介绍如何创建 首先是具有动态套接字的节点。
对于我们的示例,我们将使用 a 允许用户 在两种模式之间切换。此外,我们必须告诉动画节点 当模式改变时,它必须重新创建套接字。有 AN中的许多节点也必须这样做。将军 代码的结构如下所示:EnumProperty
import bpy
from bpy.props import *
from animation_nodes.base_types import AnimationNode
# first define the modes the node can have
# item tuple: (identifier, display name, description, icon, value)
# the value should be different for each item and should not change later
modeItems = [
("LINE", "Line", "Distribute points on line", "", 0),
("CIRCLE", "Circle", "Distribute points on circle", "", 1)
]
class GeneratePointsNode(bpy.types.Node, AnimationNode):
bl_idname = "an_GeneratePointsNode"
bl_label = "Generate Points"
# AnimationNode.refresh will cause AN to remove all sockets
# and to call the create method again.
mode: EnumProperty(name = "Mode", default = "LINE",
items = modeItems, update = AnimationNode.refresh)
def create(self):
self.newInput("Integer", "Amount", "amount")
if self.mode == "LINE":
self.newInput("Vector", "Start", "start")
self.newInput("Vector", "Direction", "direction")
elif self.mode == "CIRCLE":
self.newInput("Float", "Radius", "radius")
self.newOutput("Vector List", "Points", "points")
def draw(self, layout):
layout.prop(self, "mode")
因此,既然您知道如何使用更改套接字制作节点,那么现在就是 是时候展示在这种情况下如何编写执行代码了。解决方案 是定义一个名为 的新函数。它 返回一个字符串,其中包含名称以及应为 就在这时叫了起来。基本上它看起来像这样:getExecutionFunctionName(self)
def getExecutionFunctionName(self):
if self.mode == "LINE":
return "execute_Line"
elif self.mode == "CIRCLE":
return "execute_Circle"
def execute_Line(self, amount, start, radius):
# do something
def execute_Circle(self, amount, radius):
# do something different
With that new knowledge it is easy to fill in the missing code in the correct functions to get the final node. I’ll just skip forward to the end now because how to calculate points on lines and circles is not part of this tutorial. However here is the code:
import bpy
from bpy.props import *
from math import sin, cos, pi
from animation_nodes.data_structures import Vector3DList
from animation_nodes.base_types import AnimationNode
modeItems = [
("LINE", "Line", "Distribute points on line", "", 0),
("CIRCLE", "Circle", "Distribute points on circle", "", 1)
]
class GeneratePointsNode(bpy.types.Node, AnimationNode):
bl_idname = "an_GeneratePointsNode"
bl_label = "Generate Points"
mode: EnumProperty(name = "Mode", default = "LINE",
items = modeItems, update = AnimationNode.refresh)
def create(self):
self.newInput("Integer", "Amount", "amount")
if self.mode == "LINE":
self.newInput("Vector", "Start", "start")
self.newInput("Vector", "Direction", "direction")
elif self.mode == "CIRCLE":
self.newInput("Float", "Radius", "radius")
self.newOutput("Vector List", "Points", "points")
def draw(self, layout):
layout.prop(self, "mode")
def getExecutionFunctionName(self):
if self.mode == "LINE":
return "execute_Line"
elif self.mode == "CIRCLE":
return "execute_Circle"
def execute_Line(self, amount, start, direction):
points = Vector3DList()
for i in range(amount):
points.append(start + i * direction)
return points
def execute_Circle(self, amount, radius):
points = Vector3DList()
if amount <= 0: return points
factor = 2 * pi / amount
for i in range(amount):
points.append((cos(i * factor) * radius, sin(i * factor) * radius, 0))
return points

