Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion __init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "Node to Python",
"description": "Convert Blender node groups to a Python add-on!",
"author": "Brendan Parmer",
"version": (3, 0, 1),
"version": (3, 1, 0),
"blender": (3, 0, 0),
"location": "Node",
"category": "Node",
Expand Down
23 changes: 16 additions & 7 deletions compositor/node_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -261,14 +261,19 @@
],

'CompositorNodeKuwahara' : [
NTPNodeSetting("eccentricity", ST.FLOAT, min_version = (4, 0, 0)),
NTPNodeSetting("sharpness", ST.FLOAT, min_version = (4, 0, 0)),
NTPNodeSetting("size", ST.INT, min_version = (4, 0, 0)),
NTPNodeSetting("uniformity", ST.INT, min_version = (4, 0, 0)),
NTPNodeSetting("variation", ST.ENUM, min_version = (4, 0, 0))
NTPNodeSetting("eccentricity", ST.FLOAT, min_version = (4, 0, 0)),
NTPNodeSetting("sharpness", ST.FLOAT, min_version = (4, 0, 0)),
NTPNodeSetting("size", ST.INT, min_version = (4, 0, 0),
max_version = (4, 1, 0)),
NTPNodeSetting("uniformity", ST.INT, min_version = (4, 0, 0)),
NTPNodeSetting("variation", ST.ENUM, min_version = (4, 0, 0)),
NTPNodeSetting("use_high_precision", ST.BOOL, min_version = (4, 1, 0))
],

'CompositorNodePixelate' : [],
'CompositorNodePixelate' : [
NTPNodeSetting("pixel_size", ST.INT, min_version = (4, 1, 0))
],

'CompositorNodePosterize' : [],

'CompositorNodeSunBeams' : [
Expand Down Expand Up @@ -324,7 +329,7 @@
NTPNodeSetting("distance", ST.FLOAT),
NTPNodeSetting("iterations", ST.INT),
NTPNodeSetting("spin", ST.FLOAT),
NTPNodeSetting("use_wrap", ST.BOOL, max_version = (3, 4, 0)),
NTPNodeSetting("use_wrap", ST.BOOL, max_version = (3, 5, 0)),
NTPNodeSetting("zoom", ST.FLOAT)
],

Expand Down Expand Up @@ -571,6 +576,10 @@

'CompositorNodeNormalize' : [],

'CompositorNodeSplit' : [
NTPNodeSetting("axis", ST.ENUM, min_version=(4, 1, 0)),
NTPNodeSetting("factor", ST.INT, min_version=(4, 1, 0))
],

'CompositorNodeSwitch' : [
NTPNodeSetting("check", ST.BOOL)
Expand Down
21 changes: 21 additions & 0 deletions compositor/operator.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,27 @@ def _initialize_compositor_node_tree(self, ntp_nt, nt_name):
f"name = {str_to_py_str(nt_name)})"))
self._write("")

# Compositor node tree settings
#TODO: might be good to make this optional
enum_settings = ["chunk_size", "edit_quality", "execution_mode",
"precision", "render_quality"]
for enum in enum_settings:
if not hasattr(ntp_nt.node_tree, enum):
continue
setting = getattr(ntp_nt.node_tree, enum)
if setting is not None and setting is not "":
py_str = enum_to_py_str(setting)
self._write(f"{ntp_nt.var}.{enum} = {py_str}")

bool_settings = ["use_groupnode_buffer", "use_opencl", "use_two_pass",
"use_viewer_border"]
for bool_setting in bool_settings:
if not hasattr(ntp_nt.node_tree, bool_setting):
continue
if getattr(ntp_nt.node_tree, bool_setting) is True:
self._write(f"{ntp_nt.var}.{bool_setting} = True")


def _set_color_balance_settings(self, node: CompositorNodeColorBalance
) -> None:
"""
Expand Down
38 changes: 32 additions & 6 deletions geometry/node_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@
# Input > Scene
'GeometryNodeTool3DCursor' : [],

'GeometryNodeInputActiveCamera' : [],

'GeometryNodeCollectionInfo' : [
NTPNodeSetting("transform_space", ST.ENUM)
],
Expand Down Expand Up @@ -138,6 +140,10 @@
'GeometryNodeToolSetSelection' : [],

# Geometry > Operations
'GeometryNodeBake' : [
NTPNodeSetting("bake_items", ST.BAKE_ITEMS, min_version = (4, 1, 0))
],

'GeometryNodeBoundBox' : [],
'GeometryNodeConvexHull' : [],

Expand All @@ -154,6 +160,10 @@
NTPNodeSetting("mode", ST.ENUM, min_version = (3, 1, 0))
],

'GeometryNodeSortElements' : [
NTPNodeSetting("domain", ST.ENUM, min_version = (4, 1, 0))
],

'GeometryNodeTransform' : [],
'GeometryNodeSeparateComponents' : [],

Expand Down Expand Up @@ -279,7 +289,7 @@

'GeometryNodeRealizeInstances' : [
NTPNodeSetting("legacy_behavior", ST.BOOL, min_version = (3, 1, 0),
max_version = (3, 6, 0))
max_version = (4, 0, 0))
],

'GeometryNodeRotateInstances' : [],
Expand Down Expand Up @@ -472,12 +482,14 @@
],

'ShaderNodeTexMusgrave' : [
NTPNodeSetting("musgrave_dimensions", ST.ENUM),
NTPNodeSetting("musgrave_type", ST.ENUM)
NTPNodeSetting("musgrave_dimensions", ST.ENUM, max_version = (4, 1, 0)),
NTPNodeSetting("musgrave_type", ST.ENUM, max_version = (4, 1, 0))
],

'ShaderNodeTexNoise' : [
NTPNodeSetting("noise_dimensions", ST.ENUM)
NTPNodeSetting("noise_dimensions", ST.ENUM),
NTPNodeSetting("noise_type", ST.ENUM, min_version=(4, 1, 0)),
NTPNodeSetting("normalize", ST.BOOL, min_version=(4, 0, 0)),
],

'ShaderNodeTexVoronoi' : [
Expand All @@ -499,6 +511,16 @@


# UTILITIES
'GeometryNodeIndexSwitch' : [
NTPNodeSetting("data_type", ST.ENUM, min_version = (4, 1, 0)),
NTPNodeSetting("index_switch_items", ST.INDEX_SWITCH_ITEMS, min_version = (4, 1, 0))
],

'GeometryNodeMenuSwitch' : [
NTPNodeSetting("data_type", ST.ENUM, min_version = (4, 1, 0)),
NTPNodeSetting("enum_definition", ST.ENUM_DEFINITION, min_version = (4, 1, 0))
],

'ShaderNodeMix' : [
NTPNodeSetting("blend_type", ST.ENUM, min_version = (3, 4, 0)),
NTPNodeSetting("clamp_factor", ST.BOOL, min_version = (3, 4, 0)),
Expand Down Expand Up @@ -610,7 +632,7 @@
],

'FunctionNodeCompareFloats' : [
NTPNodeSetting("operation", ST.ENUM, max_version = (3, 0, 0))
NTPNodeSetting("operation", ST.ENUM, max_version = (3, 2, 0))
],

'ShaderNodeFloatCurve' : [
Expand Down Expand Up @@ -641,7 +663,11 @@
'FunctionNodeAxisAngleToRotation' : [],
'FunctionNodeEulerToRotation' : [],
'FunctionNodeInvertRotation' : [],


'FunctionNodeRotateRotation' : [
NTPNodeSetting("rotation_space", ST.ENUM, min_version = (4, 1, 0))
],

'FunctionNodeRotateEuler' : [
NTPNodeSetting("space", ST.ENUM),
NTPNodeSetting("type", ST.ENUM)
Expand Down
6 changes: 4 additions & 2 deletions geometry/operator.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,14 +139,16 @@ def _set_geo_tree_properties(self, node_tree: GeometryNodeTree) -> None:
if is_tool:
self._write(f"{nt_var}.is_tool = True")

tool_flags = ["is_mode_edit",
tool_flags = ["is_mode_object",
"is_mode_edit",
"is_mode_sculpt",
"is_type_curve",
"is_type_mesh",
"is_type_point_cloud"]

for flag in tool_flags:
self._write(f"{nt_var}.{flag} = {getattr(node_tree, flag)}")
if hasattr(node_tree, flag) is True:
self._write(f"{nt_var}.{flag} = {getattr(node_tree, flag)}")
self._write("")

def _process_node_tree(self, node_tree: GeometryNodeTree) -> None:
Expand Down
7 changes: 4 additions & 3 deletions material/node_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -194,13 +194,14 @@
],

'ShaderNodeTexMusgrave' : [
NTPNodeSetting("musgrave_dimensions", ST.ENUM),
NTPNodeSetting("musgrave_type", ST.ENUM)
NTPNodeSetting("musgrave_dimensions", ST.ENUM, max_version = (4, 1, 0)),
NTPNodeSetting("musgrave_type", ST.ENUM, max_version = (4, 1, 0))
],

'ShaderNodeTexNoise' : [
NTPNodeSetting("noise_dimensions", ST.ENUM),
NTPNodeSetting("normalize", ST.BOOL, min_version = (4, 0, 0))
NTPNodeSetting("noise_type", ST.ENUM, min_version=(4, 1, 0)),
NTPNodeSetting("normalize", ST.BOOL, min_version=(4, 0, 0)),
],

'ShaderNodeTexPointDensity' : [
Expand Down
67 changes: 66 additions & 1 deletion ntp_operator.py
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ def _set_settings_defaults(self, node: Node) -> None:

if not hasattr(node, attr_name):
if (bpy.app.version >= setting.min_version and
bpy.app.version <= setting.max_version):
bpy.app.version < setting.max_version):
self.report({'WARNING'},
f"NodeToPython: Couldn't find attribute "
f"\"{attr_name}\" for node {node.name} of type "
Expand Down Expand Up @@ -345,6 +345,12 @@ def _set_settings_defaults(self, node: Node) -> None:
self._load_image(attr, f"{node_var}.{attr_name}")
elif st == ST.IMAGE_USER:
self._image_user_settings(attr, f"{node_var}.{attr_name}")
elif st == ST.INDEX_SWITCH_ITEMS:
self._index_switch_items(attr, f"{node_var}.{attr_name}")
elif st == ST.ENUM_DEFINITION:
self._enum_definition(attr, f"{node_var}.{attr_name}")
elif st == ST.BAKE_ITEMS:
self._bake_items(attr, f"{node_var}.{attr_name}")

if bpy.app.version < (4, 0, 0):
def _set_group_socket_defaults(self, socket_interface: NodeSocketInterface,
Expand Down Expand Up @@ -703,6 +709,10 @@ def _set_input_defaults(self, node: Node) -> None:
elif input.bl_idname == 'NodeSocketString':
default_val = str_to_py_str(input.default_value)

#menu
elif input.bl_idname == 'NodeSocketMenu':
default_val = enum_to_py_str(input.default_value)

# images
elif input.bl_idname == 'NodeSocketImage':
img = input.default_value
Expand Down Expand Up @@ -1043,6 +1053,61 @@ def _image_user_settings(self, img_user: bpy.types.ImageUser,
self._write(f"{img_user_var}.{img_usr_attr} = "
f"{getattr(img_user, img_usr_attr)}")

if bpy.app.version >= (4, 1, 0):
def _index_switch_items(self, switch_items: bpy.types.NodeIndexSwitchItems,
items_str: str) -> None:
"""
Set the proper amount of index switch items

Parameters:
switch_items (bpy.types.NodeIndexSwitchItems): switch items to copy
items_str (str): string for the generated switch items attribute
"""
num_items = len(switch_items)
self._write(f"{items_str}.clear()")
for i in range(num_items):
self._write(f"{items_str}.new()")

def _enum_definition(self, enum_def: bpy.types.NodeEnumDefinition,
enum_def_str: str) -> None:
"""
Set enum definition item for a node

Parameters:
enum_def (bpy.types.NodeEnumDefinition): enum definition to replicate
enum_def_str (str): string for the generated enum definition
"""
self._write(f"{enum_def_str}.enum_items.clear()")
for i, enum_item in enumerate(enum_def.enum_items):
name = str_to_py_str(enum_item.name)
self._write(f"{enum_def_str}.enum_items.new({name})")
if enum_item.description != "":
self._write(f"{enum_def_str}.enum_items[{i}].description = "
f"{str_to_py_str(enum_item.description)}")

def _bake_items(self, bake_items: bpy.types.NodeGeometryBakeItems,
bake_items_str: str) -> None:
"""
Set bake items for a node

Parameters:
bake_items (bpy.types.NodeGeometryBakeItems): bake items to replicate
bake_items_str (str): string for the generated bake items
"""
self._write(f"{bake_items_str}.clear()")
for i, bake_item in enumerate(bake_items):
socket_type = enum_to_py_str(bake_item.socket_type)
name = str_to_py_str(bake_item.name)
self._write(f"{bake_items_str}.new({socket_type}, {name})")

ad = enum_to_py_str(bake_item.attribute_domain)
self._write(f"{bake_items_str}[{i}].attribute_domain = {ad}")

if bake_item.is_attribute:
self._write(f"{bake_items_str}[{i}].is_attribute = True")



def _set_parents(self, node_tree: NodeTree) -> None:
"""
Sets parents for all nodes, mostly used to put nodes in frames
Expand Down
6 changes: 5 additions & 1 deletion utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ class ST(Enum):
CURVE_MAPPING = auto()
NODE_TREE = auto()

ENUM_DEFINITION = auto()
INDEX_SWITCH_ITEMS = auto()
BAKE_ITEMS = auto()

# Asset Library
MATERIAL = auto() # Handle with asset library
OBJECT = auto() # Handle with asset library
Expand All @@ -53,7 +57,7 @@ class NTPNodeSetting(NamedTuple):
name: str
st: ST
min_version: tuple = (3, 0, 0)
max_version: tuple = (4, 1, 0)
max_version: tuple = (4, 2, 0) #first version where a setting is invalid


def clean_string(string: str, lower: bool = True) -> str:
Expand Down