mirror of
https://projects.blender.org/blender/blender.git
synced 2025-01-22 07:22:12 -05:00
b3623feab2
This patch adds support for using integer sockets in compositor nodes. This involves updating the Result class, node tree compiler, implicit conversion operation, multi-function procedure operation, shader operation, and some operations that supports multiple types. Shader operation internally treats integers as floats, doing conversion to and from int when reading and writing. That's because the GPUMaterial compiler doesn't support integers. This is also the same workaround used by the shader system. Though the GPU module are eyeing adding support for integers, so we will update the code once they do that. Domain realization is not yet supported for integer types, but this is an internal limitation so far, as we do not plan to add nodes that outputs integers soon. We are not yet sure how realization should happen with regards to interpolation and we do not have base functions to sample integer images, that's why I decided to delay its implementation when it is actually needed. Pull Request: https://projects.blender.org/blender/blender/pulls/132599
489 lines
21 KiB
Python
489 lines
21 KiB
Python
# SPDX-FileCopyrightText: 2021-2023 Blender Authors
|
|
#
|
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
import pathlib
|
|
import sys
|
|
import unittest
|
|
import tempfile
|
|
|
|
import bpy
|
|
|
|
args = None
|
|
|
|
|
|
class AbstractNodeGroupInterfaceTest(unittest.TestCase):
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
cls.testdir = args.testdir
|
|
cls._tempdir = tempfile.TemporaryDirectory()
|
|
cls.tempdir = pathlib.Path(cls._tempdir.name)
|
|
|
|
def setUp(self):
|
|
self.assertTrue(self.testdir.exists(),
|
|
'Test dir {0} should exist'.format(self.testdir))
|
|
|
|
# Make sure we always start with a known-empty file.
|
|
bpy.ops.wm.open_mainfile(filepath=str(self.testdir / "empty.blend"))
|
|
|
|
def tearDown(self):
|
|
self._tempdir.cleanup()
|
|
|
|
|
|
class NodeGroupInterfaceTests:
|
|
tree_type = None
|
|
group_node_type = None
|
|
# Tree instance where node groups can be added
|
|
main_tree = None
|
|
|
|
def make_group(self):
|
|
tree = bpy.data.node_groups.new("test", self.tree_type)
|
|
return tree
|
|
|
|
def make_instance(self, tree):
|
|
group_node = self.main_tree.nodes.new(self.group_node_type)
|
|
group_node.node_tree = tree
|
|
return group_node
|
|
|
|
def make_group_and_instance(self):
|
|
tree = self.make_group()
|
|
group_node = self.make_instance(tree)
|
|
return tree, group_node
|
|
|
|
# Utility method for generating a non-zero default value.
|
|
@staticmethod
|
|
def make_default_socket_value(socket_type):
|
|
if (socket_type == "NodeSocketBool"):
|
|
return True
|
|
elif (socket_type == "NodeSocketColor"):
|
|
return (.5, 1.0, .3, .7)
|
|
elif (socket_type == "NodeSocketFloat"):
|
|
return 1.23
|
|
elif (socket_type == "NodeSocketImage"):
|
|
return bpy.data.images.new("test", 4, 4)
|
|
elif (socket_type == "NodeSocketInt"):
|
|
return -6
|
|
elif (socket_type == "NodeSocketMaterial"):
|
|
return bpy.data.materials.new("test")
|
|
elif (socket_type == "NodeSocketObject"):
|
|
return bpy.data.objects.new("test", bpy.data.meshes.new("test"))
|
|
elif (socket_type == "NodeSocketRotation"):
|
|
return (0.3, 5.0, -42)
|
|
elif (socket_type == "NodeSocketString"):
|
|
return "Hello World!"
|
|
elif (socket_type == "NodeSocketTexture"):
|
|
return bpy.data.textures.new("test", 'MAGIC')
|
|
elif (socket_type == "NodeSocketVector"):
|
|
return (4.0, -1.0, 0.0)
|
|
|
|
# Utility method returning a comparator for socket values.
|
|
# Not all socket value types are trivially comparable, e.g. colors.
|
|
@staticmethod
|
|
def make_socket_value_comparator(socket_type):
|
|
def cmp_default(test, value, expected):
|
|
test.assertEqual(value, expected, f"Value {value} does not match expected value {expected}")
|
|
|
|
def cmp_array(test, value, expected):
|
|
test.assertSequenceEqual(value[:], expected[:], f"Value {value} does not match expected value {expected}")
|
|
|
|
if (socket_type in {"NodeSocketBool",
|
|
"NodeSocketFloat",
|
|
"NodeSocketImage",
|
|
"NodeSocketInt",
|
|
"NodeSocketMaterial",
|
|
"NodeSocketObject",
|
|
"NodeSocketRotation",
|
|
"NodeSocketString",
|
|
"NodeSocketTexture"}):
|
|
return cmp_default
|
|
elif (socket_type in {"NodeSocketColor",
|
|
"NodeSocketVector"}):
|
|
return cmp_array
|
|
|
|
def test_empty_nodegroup(self):
|
|
tree, group_node = self.make_group_and_instance()
|
|
|
|
self.assertFalse(tree.interface.items_tree, "Interface not empty")
|
|
self.assertFalse(group_node.inputs)
|
|
self.assertFalse(group_node.outputs)
|
|
|
|
def do_test_invalid_socket_type(self, socket_type):
|
|
tree = self.make_group()
|
|
|
|
with self.assertRaises(TypeError):
|
|
in0 = tree.interface.new_socket("Input 0", socket_type=socket_type, in_out='INPUT')
|
|
self.assertIsNone(in0, f"Socket created for invalid type {socket_type}")
|
|
with self.assertRaises(TypeError):
|
|
out0 = tree.interface.new_socket("Output 0", socket_type=socket_type, in_out='OUTPUT')
|
|
self.assertIsNone(out0, f"Socket created for invalid type {socket_type}")
|
|
|
|
def do_test_sockets_in_out(self, socket_type):
|
|
tree, group_node = self.make_group_and_instance()
|
|
|
|
out0 = tree.interface.new_socket("Output 0", socket_type=socket_type, in_out='OUTPUT')
|
|
self.assertIsNotNone(out0, f"Could not create socket of type {socket_type}")
|
|
|
|
in0 = tree.interface.new_socket("Input 0", socket_type=socket_type, in_out='INPUT')
|
|
self.assertIsNotNone(in0, f"Could not create socket of type {socket_type}")
|
|
|
|
in1 = tree.interface.new_socket("Input 1", socket_type=socket_type, in_out='INPUT')
|
|
self.assertIsNotNone(in1, f"Could not create socket of type {socket_type}")
|
|
|
|
out1 = tree.interface.new_socket("Output 1", socket_type=socket_type, in_out='OUTPUT')
|
|
self.assertIsNotNone(out1, f"Could not create socket of type {socket_type}")
|
|
|
|
self.assertSequenceEqual([(s.name, s.bl_idname) for s in group_node.inputs], [
|
|
("Input 0", socket_type),
|
|
("Input 1", socket_type),
|
|
])
|
|
self.assertSequenceEqual([(s.name, s.bl_idname) for s in group_node.outputs], [
|
|
("Output 0", socket_type),
|
|
("Output 1", socket_type),
|
|
])
|
|
|
|
def do_test_user_count(self, value, expected_users):
|
|
if (isinstance(value, bpy.types.ID)):
|
|
self.assertEqual(
|
|
value.users,
|
|
expected_users,
|
|
f"Socket default value has user count {value.users}, expected {expected_users}")
|
|
|
|
def do_test_socket_type(self, socket_type):
|
|
default_value = self.make_default_socket_value(socket_type)
|
|
compare_value = self.make_socket_value_comparator(socket_type)
|
|
|
|
# Create the tree first, add sockets, then create a group instance.
|
|
# That way the new instance should reflect the expected default values.
|
|
tree = self.make_group()
|
|
|
|
in0 = tree.interface.new_socket("Input 0", socket_type=socket_type, in_out='INPUT')
|
|
if default_value is not None:
|
|
in0.default_value = default_value
|
|
out0 = tree.interface.new_socket("Output 0", socket_type=socket_type, in_out='OUTPUT')
|
|
self.assertIsNotNone(in0, f"Could not create socket of type {socket_type}")
|
|
self.assertIsNotNone(out0, f"Could not create socket of type {socket_type}")
|
|
|
|
# Now make a node group instance to check default values.
|
|
group_node = self.make_instance(tree)
|
|
if compare_value:
|
|
compare_value(self, group_node.inputs[0].default_value, in0.default_value)
|
|
|
|
# Test ID user count after assigning.
|
|
if (hasattr(in0, "default_value")):
|
|
# The default value is stored in both the interface and node, it should have 2 users now.
|
|
self.do_test_user_count(in0.default_value, 2)
|
|
|
|
# Copy sockets
|
|
in1 = tree.interface.copy(in0)
|
|
out1 = tree.interface.copy(out0)
|
|
self.assertIsNotNone(in1, "Could not copy socket")
|
|
self.assertIsNotNone(out1, "Could not copy socket")
|
|
# User count on default values should increment by 2 after copy,
|
|
# one user for the interface and one for the group node instance.
|
|
if (hasattr(in1, "default_value")):
|
|
self.do_test_user_count(in1.default_value, 4)
|
|
|
|
# Classic outputs..inputs socket layout
|
|
def do_test_items_order_classic(self, socket_type):
|
|
tree, group_node = self.make_group_and_instance()
|
|
|
|
tree.interface.new_socket("Output 0", socket_type=socket_type, in_out='OUTPUT')
|
|
tree.interface.new_socket("Input 0", socket_type=socket_type, in_out='INPUT')
|
|
|
|
self.assertSequenceEqual([(s.name, s.item_type) for s in tree.interface.items_tree], [
|
|
("Output 0", 'SOCKET'),
|
|
("Input 0", 'SOCKET'),
|
|
])
|
|
self.assertSequenceEqual([s.name for s in group_node.inputs], [
|
|
"Input 0",
|
|
])
|
|
self.assertSequenceEqual([s.name for s in group_node.outputs], [
|
|
"Output 0",
|
|
])
|
|
# XXX currently no panel state access on node instances.
|
|
# self.assertFalse(group_node.panels)
|
|
|
|
# Mixed sockets and panels
|
|
def do_test_items_order_mixed_with_panels(self, socket_type):
|
|
tree, group_node = self.make_group_and_instance()
|
|
|
|
tree.interface.new_panel("Panel 0")
|
|
tree.interface.new_socket("Input 0", socket_type=socket_type, in_out='INPUT')
|
|
tree.interface.new_socket("Output 0", socket_type=socket_type, in_out='OUTPUT')
|
|
tree.interface.new_panel("Panel 1")
|
|
tree.interface.new_socket("Input 1", socket_type=socket_type, in_out='INPUT')
|
|
tree.interface.new_panel("Panel 2")
|
|
tree.interface.new_socket("Output 1", socket_type=socket_type, in_out='OUTPUT')
|
|
tree.interface.new_panel("Panel 3")
|
|
|
|
# Panels after sockets
|
|
self.assertSequenceEqual([(s.name, s.item_type) for s in tree.interface.items_tree], [
|
|
("Output 0", 'SOCKET'),
|
|
("Output 1", 'SOCKET'),
|
|
("Input 0", 'SOCKET'),
|
|
("Input 1", 'SOCKET'),
|
|
("Panel 0", 'PANEL'),
|
|
("Panel 1", 'PANEL'),
|
|
("Panel 2", 'PANEL'),
|
|
("Panel 3", 'PANEL'),
|
|
])
|
|
self.assertSequenceEqual([s.name for s in group_node.inputs], [
|
|
"Input 0",
|
|
"Input 1",
|
|
])
|
|
self.assertSequenceEqual([s.name for s in group_node.outputs], [
|
|
"Output 0",
|
|
"Output 1",
|
|
])
|
|
# XXX currently no panel state access on node instances.
|
|
# self.assertSequenceEqual([p.name for p in group_node.panels], [
|
|
# "Panel 0",
|
|
# "Panel 1",
|
|
# "Panel 2",
|
|
# "Panel 3",
|
|
# ])
|
|
|
|
def do_test_add(self, socket_type):
|
|
tree, group_node = self.make_group_and_instance()
|
|
|
|
in0 = tree.interface.new_socket("Input 0", socket_type=socket_type, in_out='INPUT')
|
|
self.assertSequenceEqual(tree.interface.items_tree, [in0])
|
|
self.assertSequenceEqual([s.name for s in group_node.inputs], ["Input 0"])
|
|
self.assertSequenceEqual([s.name for s in group_node.outputs], [])
|
|
|
|
out0 = tree.interface.new_socket("Output 0", socket_type=socket_type, in_out='OUTPUT')
|
|
self.assertSequenceEqual(tree.interface.items_tree, [out0, in0])
|
|
self.assertSequenceEqual([s.name for s in group_node.inputs], ["Input 0"])
|
|
self.assertSequenceEqual([s.name for s in group_node.outputs], ["Output 0"])
|
|
|
|
panel0 = tree.interface.new_panel("Panel 0")
|
|
self.assertSequenceEqual(tree.interface.items_tree, [out0, in0, panel0])
|
|
self.assertSequenceEqual([s.name for s in group_node.inputs], ["Input 0"])
|
|
self.assertSequenceEqual([s.name for s in group_node.outputs], ["Output 0"])
|
|
|
|
# Add items to the panel.
|
|
in1 = tree.interface.new_socket("Input 1", socket_type=socket_type, in_out='INPUT', parent=panel0)
|
|
self.assertSequenceEqual(tree.interface.items_tree, [out0, in0, panel0, in1])
|
|
self.assertSequenceEqual([s.name for s in group_node.inputs], ["Input 0", "Input 1"])
|
|
self.assertSequenceEqual([s.name for s in group_node.outputs], ["Output 0"])
|
|
|
|
out1 = tree.interface.new_socket("Output 1", socket_type=socket_type, in_out='OUTPUT', parent=panel0)
|
|
self.assertSequenceEqual(tree.interface.items_tree, [out0, in0, panel0, out1, in1])
|
|
self.assertSequenceEqual([s.name for s in group_node.inputs], ["Input 0", "Input 1"])
|
|
self.assertSequenceEqual([s.name for s in group_node.outputs], ["Output 0", "Output 1"])
|
|
|
|
def do_test_remove(self, socket_type):
|
|
tree, group_node = self.make_group_and_instance()
|
|
|
|
in0 = tree.interface.new_socket("Input 0", socket_type=socket_type, in_out='INPUT')
|
|
out0 = tree.interface.new_socket("Output 0", socket_type=socket_type, in_out='OUTPUT')
|
|
panel0 = tree.interface.new_panel("Panel 0")
|
|
in1 = tree.interface.new_socket("Input 1", socket_type=socket_type, in_out='INPUT', parent=panel0)
|
|
out1 = tree.interface.new_socket("Output 1", socket_type=socket_type, in_out='OUTPUT', parent=panel0)
|
|
panel1 = tree.interface.new_panel("Panel 1")
|
|
in2 = tree.interface.new_socket("Input 2", socket_type=socket_type, in_out='INPUT', parent=panel1)
|
|
out2 = tree.interface.new_socket("Output 2", socket_type=socket_type, in_out='OUTPUT', parent=panel1)
|
|
panel2 = tree.interface.new_panel("Panel 2")
|
|
|
|
self.assertSequenceEqual(tree.interface.items_tree, [out0, in0, panel0, out1, in1, panel1, out2, in2, panel2])
|
|
self.assertSequenceEqual([s.name for s in group_node.inputs], ["Input 0", "Input 1", "Input 2"])
|
|
self.assertSequenceEqual([s.name for s in group_node.outputs], ["Output 0", "Output 1", "Output 2"])
|
|
|
|
# Remove from root panel.
|
|
tree.interface.remove(in0)
|
|
self.assertSequenceEqual(tree.interface.items_tree, [out0, panel0, out1, in1, panel1, out2, in2, panel2])
|
|
self.assertSequenceEqual([s.name for s in group_node.inputs], ["Input 1", "Input 2"])
|
|
self.assertSequenceEqual([s.name for s in group_node.outputs], ["Output 0", "Output 1", "Output 2"])
|
|
|
|
# Removing a panel should move content to the parent.
|
|
tree.interface.remove(panel0)
|
|
self.assertSequenceEqual(tree.interface.items_tree, [out0, out1, in1, panel1, out2, in2, panel2])
|
|
self.assertSequenceEqual([s.name for s in group_node.inputs], ["Input 1", "Input 2"])
|
|
self.assertSequenceEqual([s.name for s in group_node.outputs], ["Output 0", "Output 1", "Output 2"])
|
|
|
|
tree.interface.remove(out0)
|
|
self.assertSequenceEqual(tree.interface.items_tree, [out1, in1, panel1, out2, in2, panel2])
|
|
self.assertSequenceEqual([s.name for s in group_node.inputs], ["Input 1", "Input 2"])
|
|
self.assertSequenceEqual([s.name for s in group_node.outputs], ["Output 1", "Output 2"])
|
|
|
|
# Remove content from panel
|
|
tree.interface.remove(out2)
|
|
self.assertSequenceEqual(tree.interface.items_tree, [out1, in1, panel1, in2, panel2])
|
|
self.assertSequenceEqual([s.name for s in group_node.inputs], ["Input 1", "Input 2"])
|
|
self.assertSequenceEqual([s.name for s in group_node.outputs], ["Output 1"])
|
|
|
|
# Remove a panel and its content
|
|
tree.interface.remove(panel1, move_content_to_parent=False)
|
|
self.assertSequenceEqual(tree.interface.items_tree, [out1, in1, panel2])
|
|
self.assertSequenceEqual([s.name for s in group_node.inputs], ["Input 1"])
|
|
self.assertSequenceEqual([s.name for s in group_node.outputs], ["Output 1"])
|
|
|
|
# Remove empty panel
|
|
tree.interface.remove(panel2)
|
|
self.assertSequenceEqual(tree.interface.items_tree, [out1, in1])
|
|
self.assertSequenceEqual([s.name for s in group_node.inputs], ["Input 1"])
|
|
self.assertSequenceEqual([s.name for s in group_node.outputs], ["Output 1"])
|
|
|
|
def do_test_move(self, socket_type):
|
|
tree, group_node = self.make_group_and_instance()
|
|
|
|
in0 = tree.interface.new_socket("Input 0", socket_type=socket_type, in_out='INPUT')
|
|
in1 = tree.interface.new_socket("Input 1", socket_type=socket_type, in_out='INPUT', parent=panel0)
|
|
out0 = tree.interface.new_socket("Output 0", socket_type=socket_type, in_out='OUTPUT')
|
|
out1 = tree.interface.new_socket("Output 1", socket_type=socket_type, in_out='OUTPUT', parent=panel0)
|
|
panel0 = tree.interface.new_panel("Panel 0")
|
|
panel1 = tree.interface.new_panel("Panel 1")
|
|
|
|
|
|
class GeometryNodeGroupInterfaceTest(AbstractNodeGroupInterfaceTest, NodeGroupInterfaceTests):
|
|
tree_type = "GeometryNodeTree"
|
|
group_node_type = "GeometryNodeGroup"
|
|
|
|
def setUp(self):
|
|
super().setUp()
|
|
self.main_tree = bpy.data.node_groups.new("main", self.tree_type)
|
|
|
|
def test_sockets_in_out(self):
|
|
self.do_test_sockets_in_out("NodeSocketFloat")
|
|
|
|
def test_all_socket_types(self):
|
|
self.do_test_invalid_socket_type("INVALID_SOCKET_TYPE_11!1")
|
|
self.do_test_socket_type("NodeSocketBool")
|
|
self.do_test_socket_type("NodeSocketCollection")
|
|
self.do_test_socket_type("NodeSocketColor")
|
|
self.do_test_socket_type("NodeSocketFloat")
|
|
self.do_test_socket_type("NodeSocketGeometry")
|
|
self.do_test_socket_type("NodeSocketImage")
|
|
self.do_test_socket_type("NodeSocketInt")
|
|
self.do_test_socket_type("NodeSocketMaterial")
|
|
self.do_test_socket_type("NodeSocketObject")
|
|
self.do_test_socket_type("NodeSocketRotation")
|
|
self.do_test_invalid_socket_type("NodeSocketShader")
|
|
self.do_test_socket_type("NodeSocketString")
|
|
self.do_test_socket_type("NodeSocketTexture")
|
|
self.do_test_socket_type("NodeSocketVector")
|
|
self.do_test_invalid_socket_type("NodeSocketVirtual")
|
|
|
|
def test_items_order_classic(self):
|
|
self.do_test_items_order_classic("NodeSocketFloat")
|
|
|
|
def test_items_order_mixed_with_panels(self):
|
|
self.do_test_items_order_mixed_with_panels("NodeSocketFloat")
|
|
|
|
def test_add(self):
|
|
self.do_test_add("NodeSocketFloat")
|
|
|
|
def test_remove(self):
|
|
self.do_test_remove("NodeSocketFloat")
|
|
|
|
|
|
class ShaderNodeGroupInterfaceTest(AbstractNodeGroupInterfaceTest, NodeGroupInterfaceTests):
|
|
tree_type = "ShaderNodeTree"
|
|
group_node_type = "ShaderNodeGroup"
|
|
|
|
def setUp(self):
|
|
super().setUp()
|
|
self.material = bpy.data.materials.new("test")
|
|
self.material.use_nodes = True
|
|
self.main_tree = self.material.node_tree
|
|
|
|
def test_invalid_socket_type(self):
|
|
self.do_test_invalid_socket_type("INVALID_SOCKET_TYPE_11!1")
|
|
|
|
def test_sockets_in_out(self):
|
|
self.do_test_sockets_in_out("NodeSocketFloat")
|
|
|
|
def test_all_socket_types(self):
|
|
self.do_test_socket_type("NodeSocketBool")
|
|
self.do_test_invalid_socket_type("NodeSocketCollection")
|
|
self.do_test_socket_type("NodeSocketColor")
|
|
self.do_test_socket_type("NodeSocketFloat")
|
|
self.do_test_invalid_socket_type("NodeSocketGeometry")
|
|
self.do_test_invalid_socket_type("NodeSocketImage")
|
|
self.do_test_socket_type("NodeSocketInt")
|
|
self.do_test_invalid_socket_type("NodeSocketMaterial")
|
|
self.do_test_invalid_socket_type("NodeSocketObject")
|
|
self.do_test_invalid_socket_type("NodeSocketRotation")
|
|
self.do_test_socket_type("NodeSocketShader")
|
|
self.do_test_invalid_socket_type("NodeSocketString")
|
|
self.do_test_invalid_socket_type("NodeSocketTexture")
|
|
self.do_test_socket_type("NodeSocketVector")
|
|
self.do_test_invalid_socket_type("NodeSocketVirtual")
|
|
|
|
def test_items_order_classic(self):
|
|
self.do_test_items_order_classic("NodeSocketFloat")
|
|
|
|
def test_items_order_mixed_with_panels(self):
|
|
self.do_test_items_order_mixed_with_panels("NodeSocketFloat")
|
|
|
|
def test_add(self):
|
|
self.do_test_add("NodeSocketFloat")
|
|
|
|
def test_remove(self):
|
|
self.do_test_remove("NodeSocketFloat")
|
|
|
|
|
|
class CompositorNodeGroupInterfaceTest(AbstractNodeGroupInterfaceTest, NodeGroupInterfaceTests):
|
|
tree_type = "CompositorNodeTree"
|
|
group_node_type = "CompositorNodeGroup"
|
|
|
|
def setUp(self):
|
|
super().setUp()
|
|
self.scene = bpy.data.scenes.new("test")
|
|
self.scene.use_nodes = True
|
|
self.main_tree = self.scene.node_tree
|
|
|
|
def test_invalid_socket_type(self):
|
|
self.do_test_invalid_socket_type("INVALID_SOCKET_TYPE_11!1")
|
|
|
|
def test_sockets_in_out(self):
|
|
self.do_test_sockets_in_out("NodeSocketFloat")
|
|
|
|
def test_all_socket_types(self):
|
|
self.do_test_invalid_socket_type("NodeSocketBool")
|
|
self.do_test_invalid_socket_type("NodeSocketCollection")
|
|
self.do_test_socket_type("NodeSocketColor")
|
|
self.do_test_socket_type("NodeSocketFloat")
|
|
self.do_test_invalid_socket_type("NodeSocketGeometry")
|
|
self.do_test_invalid_socket_type("NodeSocketImage")
|
|
self.do_test_socket_type("NodeSocketInt")
|
|
self.do_test_invalid_socket_type("NodeSocketMaterial")
|
|
self.do_test_invalid_socket_type("NodeSocketObject")
|
|
self.do_test_invalid_socket_type("NodeSocketRotation")
|
|
self.do_test_invalid_socket_type("NodeSocketShader")
|
|
self.do_test_invalid_socket_type("NodeSocketString")
|
|
self.do_test_invalid_socket_type("NodeSocketTexture")
|
|
self.do_test_socket_type("NodeSocketVector")
|
|
self.do_test_invalid_socket_type("NodeSocketVirtual")
|
|
|
|
def test_items_order_classic(self):
|
|
self.do_test_items_order_classic("NodeSocketFloat")
|
|
|
|
def test_items_order_mixed_with_panels(self):
|
|
self.do_test_items_order_mixed_with_panels("NodeSocketFloat")
|
|
|
|
def test_add(self):
|
|
self.do_test_add("NodeSocketFloat")
|
|
|
|
def test_remove(self):
|
|
self.do_test_remove("NodeSocketFloat")
|
|
|
|
|
|
def main():
|
|
global args
|
|
import argparse
|
|
|
|
if '--' in sys.argv:
|
|
argv = [sys.argv[0]] + sys.argv[sys.argv.index('--') + 1:]
|
|
else:
|
|
argv = sys.argv
|
|
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument('--testdir', required=True, type=pathlib.Path)
|
|
args, remaining = parser.parse_known_args(argv)
|
|
|
|
unittest.main(argv=remaining)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|