Skip to content

Commit

Permalink
Fixed several issues
Browse files Browse the repository at this point in the history
- Fixed error with transparent scattering in Blender 4.0
- Fixed issue with unscattering instances of scatter nodes
- Removed inner Scattershot utility nodes from the add group menu
- Fixed issue with baking non-PBR images
- Improved PBR auto-detection to include less false positives
  • Loading branch information
jlampel committed Mar 21, 2024
1 parent 8c09aeb commit 58a32c7
Show file tree
Hide file tree
Showing 16 changed files with 103 additions and 91 deletions.
3 changes: 1 addition & 2 deletions .gitignore
@@ -1,2 +1 @@
/__pycache__/*
assets*
/__pycache__/*
2 changes: 1 addition & 1 deletion __init__.py
Expand Up @@ -25,7 +25,7 @@
bl_info = {
"name": "Scattershot - Voronoi Image Texture Scattering",
"author": "Jonathan Lampel",
"version": (1, 10, 1),
"version": (1, 12, 0),
"blender": (3, 4, 0),
"location": "Shader Editor > Node",
"description": "Quickly distributes image textures around your model with several controls for randomization",
Expand Down
22 changes: 15 additions & 7 deletions bake.py
Expand Up @@ -72,7 +72,7 @@ def bake_scatter(self, context, objects):
nodes = selected_nodes[0].id_data.nodes
links = selected_nodes[0].id_data.links

only_displacement = self.Displacement and all(x == False for x in [
only_displacement = self.Displacement and all(x == False for x in [self.Image,
self.Albedo, self.AO, self.Metalness, self.Roughness, self.Glossiness,
self.Specular, self.Emission, self.Alpha, self.Bump, self.Normal
])
Expand All @@ -82,12 +82,12 @@ def bake_scatter(self, context, objects):
channel_outputs = scatter_node.outputs

new_textures = []
bake_outputs = [x for x in channel_outputs if x.name in texture_names.keys()]
bake_outputs = [x for x in channel_outputs if x.name == 'Image' or x.name in texture_names.keys()]

clear_bake(context)

for output_idx, output in enumerate(bake_outputs):
if getattr(self, output.name) or output.name == 'Image':
if getattr(self, output.name):
texture_node_name = f"Baked {output.name}"

texture_file_name = preferences.name.replace(
Expand Down Expand Up @@ -188,8 +188,9 @@ def bake_scatter(self, context, objects):

# Moves Displacement to the bottom
displacement_socket = get_socket(scatter_node.node_tree, 'OUTPUT', 'Baked Displacement')
output_count = len(scatter_node.outputs)
move_socket(scatter_node.node_tree, 'OUTPUT', displacement_socket, output_count -2)
if displacement_socket:
output_count = len(scatter_node.outputs)
move_socket(scatter_node.node_tree, 'OUTPUT', displacement_socket, output_count -2)

# Sets up nodes for UVs
# TODO: Make sure the right UVs are always used
Expand All @@ -208,7 +209,7 @@ def bake_scatter(self, context, objects):
# Hides unused sockets
if not only_displacement:
for output in scatter_node.outputs:
if output.name in texture_names.keys() or output.name == 'Random Color':
if output.name in texture_names.keys() or output.name == 'Random Color' or output.name == 'Image':
output.hide = True
for input in scatter_node.inputs:
if input.name != 'UV Map':
Expand Down Expand Up @@ -261,6 +262,11 @@ class NODE_OT_bake_scatter(bpy.types.Operator):
default='combined'
)

Image: bpy.props.BoolProperty(
name="Image",
description="Bake the image channel",
default = False
)
Albedo: bpy.props.BoolProperty(
name="Albedo",
description="Bake the albedo channel",
Expand Down Expand Up @@ -314,7 +320,7 @@ class NODE_OT_bake_scatter(bpy.types.Operator):
Displacement: bpy.props.BoolProperty(
name="Displacement",
description="Bake the displacement channel",
default = True
default = False
)

should_unwrap: bpy.props.BoolProperty(
Expand Down Expand Up @@ -393,6 +399,8 @@ def draw(self, context):
# layout.prop(self, "bake_type", expand = True)
if self.bake_type == 'combined':
channels_column = layout.column(heading = 'Channels')
if 'Image' in channels:
channels_column.prop(self, "Image")
if 'Albedo' in channels:
channels_column.prop(self, "Albedo")
if 'AO' in channels:
Expand Down
2 changes: 1 addition & 1 deletion clear_bake.py
Expand Up @@ -39,7 +39,7 @@ def clear_bake(context):
scatter_node.node_tree.nodes.remove(node)
# Remove baked sockets
for output in scatter_node.outputs:
if output.name in texture_names.keys():
if output.name in texture_names.keys() or output.name == 'Image':
baked_output_name = f"Baked {output.name}"
if baked_output_name in scatter_node.outputs:
to_sockets = [x.to_socket for x in scatter_node.outputs[baked_output_name].links]
Expand Down
29 changes: 17 additions & 12 deletions defaults.py
Expand Up @@ -134,20 +134,25 @@
}

# Node names
node_names = {
"tri-planar": "Tri-Planar Mapping",
"uv_normal_map": "UV Normal Map",
"tri-planar_normal_map": "Tri-Planar Normal Map",
node_tree_names = {
"tri-planar": ".tri-planar_mapping",
"uv_normal_map": ".uv_normal_map",
"tri-planar_normal_map": ".tri-planar_normal_map",
"scatter_vectors": "Scatter Vectors",
"vector_default": "Vector Default",
"scatter": "Scattershot",
"vector_default": ".vector_default",
"scatter": "Scatter Images",
"scatter_overlapping": "Scatter Overlapping",
"randomize_cell_hsv": "Randomize Cell HSV",
"randomize_noise_hsv": "Noise Randomize HSV",
"randomize_cell_value": "Randomize Cell Value",
"randomize_noise_value": "Noise Randomize Value",
"scatter_coordinates": "Scatter Voronoi Coordinates",
"randomize_cell_hsv": ".randomize_cell_hsv",
"randomize_noise_hsv": ".noise_randomize_hsv",
"randomize_cell_value": ".randomize_cell_value",
"randomize_noise_value": ".noise_randomize_value",
"scatter_coordinates": ".scatter_coordinates",
"scatter_source": ".scatter_source",
"scatter_source_empty": ".scatter_source_empty",
"scatter_layered": "Scatter Layered"
}

prev_node_tree_names = {
"scatter_source": "Scatter Source",
"scatter_source_empty": "Scatter Source Empty",
"scatter_layered": "Scatter Layered"
}
7 changes: 7 additions & 0 deletions docs/06_changelog.md
Expand Up @@ -7,6 +7,13 @@ search_exclude: false

# Changelog

## v1.12
- Fixed error with transparent scattering in Blender 4.0
- Fixed issue with unscattering instances of scatter nodes
- Removed inner Scattershot utility nodes from the add group menu
- Fixed issue with baking non-PBR images
- Improved PBR auto-detection to include less false positives

## v1.11
- Fixed issue with extra output sockets when noise blending in Blender 4.0
- Fixed poll error in search outside of shader editor
Expand Down
5 changes: 3 additions & 2 deletions randomize_color.py
Expand Up @@ -25,7 +25,7 @@
import bpy
from bpy.types import (Operator)
from .utilities.utilities import append_node, mode_toggle, is_shader
from .defaults import node_names
from .defaults import node_tree_names

def connect_vector(links, nodes, from_node, to_node):
has_coordinates = False
Expand All @@ -39,7 +39,8 @@ def create_randomize_node(self, context):
nodes = context.selected_nodes[0].id_data.nodes
links = context.selected_nodes[0].id_data.links
for node in context.selected_nodes:
randomize_node = append_node(self, nodes, node_names['randomize_noise_hsv'])
randomize_node = append_node(self, nodes, node_tree_names['randomize_noise_hsv'])
randomize_node.label = 'HSV Noise'
connect_vector(links, nodes, node, randomize_node)
randomize_node.width = 200
if is_shader(node):
Expand Down
5 changes: 3 additions & 2 deletions triplanar_mapping.py
Expand Up @@ -25,7 +25,7 @@
import bpy
from bpy.types import (Operator)
from .utilities.utilities import append_node, average_location, mode_toggle
from .defaults import node_names
from .defaults import node_tree_names

def check_vector_input(selected_nodes):
has_vector = False
Expand All @@ -41,7 +41,8 @@ def create_triplanar_node(self, context):
nodes = context.selected_nodes[0].id_data.nodes
links = context.selected_nodes[0].id_data.links
textures = context.selected_nodes
triplanar_node = append_node(self, nodes, node_names['tri-planar'])
triplanar_node = append_node(self, nodes, node_tree_names['tri-planar'])
triplanar_node.label = 'Tri-Planar Mapping'
triplanar_node.location = [
min([x.location[0] for x in textures]) - 250,
average_location(textures)[1]
Expand Down
12 changes: 6 additions & 6 deletions unscatter.py
Expand Up @@ -55,17 +55,17 @@ def extract_images(self, selected_nodes):

def remove_scatter_nodes(selected_nodes):
nodes = selected_nodes[0].id_data.nodes
trees_to_delete = []
groups = get_groups(selected_nodes)
trees_to_delete.extend(groups)

for node in selected_nodes:
if get_scatter_sources([node]):
nodes.remove(node)

for tree in [x.name for x in trees_to_delete]:
if tree in [x.name for x in bpy.data.node_groups]:
bpy.data.node_groups.remove(bpy.data.node_groups[tree])
# trees_to_delete = []
# groups = get_groups(selected_nodes)
# trees_to_delete.extend(groups)
# for tree in [x.name for x in trees_to_delete]:
# if tree in [x.name for x in bpy.data.node_groups]:
# bpy.data.node_groups.remove(bpy.data.node_groups[tree])


class NODE_OT_unscatter(Operator):
Expand Down
Binary file modified utilities/__pycache__/node_interface.cpython-310.pyc
Binary file not shown.
Binary file not shown.
Binary file modified utilities/__pycache__/utilities.cpython-310.pyc
Binary file not shown.
Binary file added utilities/__pycache__/utilities.cpython-311.pyc
Binary file not shown.
9 changes: 6 additions & 3 deletions utilities/node_interface.py
Expand Up @@ -42,11 +42,14 @@ def remove_socket(node_tree, in_out, name):

def get_socket(node_tree, in_out, name):
if in_out == 'INPUT' and bpy.app.version < (4, 0, 0):
return node_tree.inputs[name]
if name in [x.name for x in node_tree.inputs]:
return node_tree.inputs[name]
elif in_out == 'OUTPUT' and bpy.app.version < (4, 0, 0):
return node_tree.outputs[name]
if name in [x.name for x in node_tree.outputs]:
return node_tree.outputs[name]
else:
return node_tree.interface.items_tree[name]
if name in [x.name for x in node_tree.interface.items_tree]:
return node_tree.interface.items_tree[name]

def get_io_sockets(node_tree, in_out):
sockets = []
Expand Down
18 changes: 11 additions & 7 deletions utilities/utilities.py
Expand Up @@ -26,7 +26,7 @@
import re
import bpy
from copy import copy
from ..defaults import texture_names, default_view_transforms, node_names, package_name
from ..defaults import texture_names, default_view_transforms, node_tree_names, prev_node_tree_names, package_name

def append_node(self, nodes, node_tree_name):
if bpy.app.version < (4, 0, 0):
Expand All @@ -47,6 +47,7 @@ def append_node(self, nodes, node_tree_name):

appended_nodetrees = set(bpy.data.node_groups) - initial_nodetrees
appended_node = [x for x in appended_nodetrees if node_tree_name in x.name][0]

node_group.node_tree = bpy.data.node_groups[appended_node.name]
node_group.node_tree.name = node_tree_name
return node_group
Expand All @@ -67,7 +68,7 @@ def create_friendly_name(context, texture_name):
name = name.replace(extension, '')
name_array = []
# Preferences can only be accessed by dot notation, so iterating through each channel with bracket notation does not work
for word in re.split('[^a-z]', name.lower()):
for word in re.split('[^a-zA-Z0-9]', name.lower()):
if word in name_string_to_array(preferences.albedo_names):
name_array.append('Albedo')
elif word in name_string_to_array(preferences.ao_names):
Expand Down Expand Up @@ -102,13 +103,16 @@ def get_scatter_sources(selected_nodes):
selected_group_nodes = [x for x in nodes if x.select and x.type == 'GROUP']
for group_node in selected_group_nodes:
for node in group_node.node_tree.nodes:
if node.type == 'GROUP':
if node_names['scatter_source'] in node.node_tree.name:
if node.type == 'GROUP' and node.node_tree:
name = node.node_tree.name
if node_tree_names['scatter_source'] in name or prev_node_tree_names['scatter_source'] in name:
scatter_sources.append(node)
elif node_names['scatter'] in node.node_tree.name:
elif 'Scatter' in node.node_tree.name:
for inner_node in node.node_tree.nodes:
if inner_node.type == 'GROUP' and node_names['scatter_source'] in inner_node.node_tree.name:
scatter_sources.append(inner_node)
if inner_node.type == 'GROUP' and inner_node.node_tree:
inner_name = inner_node.node_tree.name
if node_tree_names['scatter_source'] in inner_name or prev_node_tree_names['scatter_source'] in inner_name:
scatter_sources.append(inner_node)
return scatter_sources


Expand Down

0 comments on commit 58a32c7

Please sign in to comment.