Skip to content
Open
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
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,27 @@ This saves a lot of time when working with large node trees.
Head over to [releases](https://github.com/jiggymoon69/node_tabber/releases) and download the zip file, but do not unzip it, just save it somewhere local.In blender preferences, go to the addon section and select "install ...", locate the downloaded zip and it will appear under the addons. Just enable it and change any preferences you wish.



## Note (November 17 2021)
This repo is probably temporary as the original author, and all credits should go for him JiggyMoon69 owns the original repository of this project.
the file is there since it works and people may need the recent changes, but this repo's changes will perhaps end up merged into original Master, which would be for the best.

https://twitter.com/jiggymoon
Thank you again, JiggyMoon for such a pleasant Addon
https://github.com/jiggymoon69/node_tabber/releases

In the meantime there is a .zip file in the pre-releases of this repo that you can install in the exact same way.
https://github.com/sazaam/node_tabber/releases


[Edit] Also in the rush of committing, I almost forgot to give a huge shout out to Olimoth
https://github.com/olimoth/node_tabber
who has a fork which fixed some very annoying bugs such as instancing the wrong node (Vector Math Add would call ToDegrees instead, for those of you that remember)
and who managed to fix the exact issue he had previously reported here :
https://github.com/jiggymoon69/node_tabber/issues/3
Thanks so much Olimoth!



[![IMAGE ALT TEXT](https://user-images.githubusercontent.com/48856925/95994231-54459f00-0e30-11eb-95b2-0fbbf1770121.png)](https://www.youtube.com/watch?v=Dd6lQCX4x3U "Preview 0.1.3")

13 changes: 7 additions & 6 deletions node_tabber/nt_extras.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
[" M MAXIMUM", "Maximum (M) MATH"], [" M LESS_THAN", "Less Than (LT) MATH"], [" M GREATER_THAN", "Greater Than (GT) MATH"], [" M SIGN", "Sign (S) MATH"],
[" M COMPARE", "Compare (C) MATH"], [" M SMOOTH_MIN", "Smooth Minimum (SM) MATH"], [" M SMOOTH_MAX", "Smooth Maximum (SM) MATH"], [" M ROUND", "Round (R) MATH"],
[" M FLOOR", "Floor (F) MATH"], [" M CEIL", "Ceiling (C) MATH"], [" M TRUNC", "Truncate (T) MATH"], [" M FRACT", "Fraction (F) MATH"],
[" M MODULO", "Modulo (M) MATH"], [" M WRAP", "Wrap (W) MATH"], [" M SNAP", "Snap (S) MATH"], [" M PINGPONG", "Ping-Pong (PP) MATH"],
[" M MODULO", "Modulo (M) MATH"], [" M WRAP", "Wrap (W) MATH"], [" M SNAP", "Snap (S) MATH"], [" M PINGPONG", "Ping Pong (PP) MATH"],
[" M SINE", "Sine (S) MATH"], [" M COSINE", "Cosine (C) MATH"], [" M TANGENT", "Tangent (T) MATH"], [" M ARCSINE", "ArcSine (AS) MATH"],
[" M ARCCOSINE", "Arccosine (AC) MATH"], [" M ARCTANGENT", "Arctangent (AT) MATH"], [" M ARCTAN2", "Arctan2 (AT) MATH"], [" M SINH", "Hyperbolic Sine (HS) MATH"],
[" M COSH", "Hyperbolic Cosine (HC) MATH"], [" M TANH", "Hyperbolic Tangent (HT) MATH"], [" M RADIANS", "To Radians (TR) MATH"], [" M DEGREES", "To Degrees (TD) MATH"],
Expand All @@ -22,10 +22,11 @@
[" VM SINE", "Sine (S) VEC MATH"], [" VM COSINE", "Cosine (C) VEC MATH"], [" VM TANGENT", "Tangent (T) VEC MATH"],
]

extra_color = [[" C VALUE", "Value (V) COLOR"], [" C COLOR", "Color (C) COLOR"], [" C SATURATION", "Saturation (S) COLOR"], [" C HUE", "Hue (H) COLOR"],
[" C DIVIDE", "Divide (D) COLOR"], [" C SUBTRACT", "Subtract (S) COLOR"], [" C DIFFERENCE", "Difference (D) COLOR"],
[" C LINEAR_LIGHT", "Linear Light (LL) COLOR"], [" C SOFT_LIGHT", "Soft Light (SL) COLOR"], [" C OVERLAY", "Overlay (O) COLOR"],
[" C ADD", "Add (A) COLOR"], [" C DODGE", "Dodge (D) COLOR"], [" C SCREEN", "Screen (S) COLOR"], [" C LIGHTEN", "Lighten (L) COLOR"],
[" C BURN", "Burn (B) COLOR"], [" C MULTIPLY", "Multiply (M) COLOR"], [" C DARKEN", "Darken (D) COLOR"], [" C MIX", "Mix (M) COLOR"],
extra_color = [[" CM VALUE", "Value (V) COLOR"], [" CM COLOR", "Color (C) COLOR"], [" CM SATURATION", "Saturation (S) COLOR"], [" CM HUE", "Hue (H) COLOR"],
[" CM DIVIDE", "Divide (D) COLOR"], [" CM SUBTRACT", "Subtract (S) COLOR"], [" CM DIFFERENCE", "Difference (D) COLOR"],
[" CM LINEAR_LIGHT", "Linear Light (LL) COLOR"], [" CM SOFT_LIGHT", "Soft Light (SL) COLOR"], [" CM OVERLAY", "Overlay (O) COLOR"],
[" CM ADD", "Add (A) COLOR"], [" CM DODGE", "Dodge (D) COLOR"], [" CM SCREEN", "Screen (S) COLOR"], [" CM LIGHTEN", "Lighten (L) COLOR"],
[" CM BURN", "Burn (B) COLOR"], [" CM MULTIPLY", "Multiply (M) COLOR"], [" CM DARKEN", "Darken (D) COLOR"], [" CM MIX", "Mix (M) COLOR"],
[" CM VECTORUNIFORM", "Mix (M) Vector"], [" CM VECTORNON_UNIFORM", "Mix (M) Vector Non Uniform"]
]

104 changes: 74 additions & 30 deletions node_tabber/operators.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,14 +85,34 @@ class NODE_OT_add_tabber_search(bpy.types.Operator):
bl_property = "node_item"

_enum_item_hack = []



def node_enum_items2(self, context):
for index, item in enumerate(nodeitems_utils.node_items_iter(context)):
if isinstance(item, nodeitems_utils.NodeItem):
print(str(index) + " : " + str(item.label))

return None


def retrieve_geo_nodes(self, context):
geonodes_extras = [ "ShaderNodeMapRange", "ShaderNodeMath", "ShaderNodeVectorMath",
"ShaderNodeValToRGB", "ShaderNodeMix", "ShaderNodeVectorCurve",
"ShaderNodeRGBCurve", "ShaderNodeFloatCurve",
"ShaderNodeVectorRotate", "ShaderNodeCombineXYZ", "ShaderNodeSeparateXYZ",
"ShaderNodeClamp", "ShaderNodeValue"]

NI = nodeitems_utils.NodeItem
geonodelist = (lambda data: [NI(i) for i in dir(data) if ((i.startswith("GeometryNode") or i.startswith("FunctionNode") or i.startswith("ShaderNodeTex")) and i!= "GeometryNode")])(bpy.types)
geonodelist += [NI(i) for i in geonodes_extras]
groups = [NI(nodetype = "GeometryNodeGroup", label=g.name, settings={"node_tree": g}) for g in list(bpy.data.node_groups) if g.type == "GEOMETRY" and g.name != bpy.context.space_data.edit_tree.name]

geonodelist += groups
#geonodelist += [NI(nodetype = "GeometryNodeGroup", label="TestNodeGroup", settings={tuple(["node_tree", "TestNodeGroup"])})] #settings={}
return (y for y in geonodelist)

def ensure_nodes(self, context):
return nodeitems_utils.node_items_iter(context) if context.space_data.edit_tree.type != "GEOMETRY" else NODE_OT_add_tabber_search.retrieve_geo_nodes(self, context)

# Create an enum list from node items
def node_enum_items(self, context):
nt_debug("DEF: node_enum_items")
Expand Down Expand Up @@ -124,12 +144,14 @@ def node_enum_items(self, context):
math_index = -1
vector_math_index = -1
mix_rgb_index = -1

for index, item in enumerate(nodeitems_utils.node_items_iter(context)):


node_items = NODE_OT_add_tabber_search.ensure_nodes(self, context)

for index, item in enumerate(node_items):
#nt_debug("DEF: node_enum_items")
if isinstance(item, nodeitems_utils.NodeItem):

#nt_debug(str(item.label))

short = ''
tally = 0
words = item.label.split()
Expand All @@ -138,22 +160,24 @@ def node_enum_items(self, context):
match = item.label+" ("+short+")"
if match in content:
tally = content[match]['tally']

enum_items.append(
(str(index) + " 0 0",
item.label+" ("+short+")",
str(tally),
index,
))
index_offset = index




if item.label == "Math":
math_index = index
if item.label == "Vector Math":
vector_math_index = index
if item.label == "MixRGB":
if item.label == "Mix":
mix_rgb_index = index

#Add sub node searching if enabled
if prefs.sub_search:
if math_index > -1:
Expand All @@ -168,10 +192,9 @@ def node_enum_items(self, context):
str(tally),
index_offset+1+index2,
))
index_offset += index2
index_offset += index2 + 1

if vector_math_index > -1:
nt_debug("Adding vector math nodes")
for index2, subname in enumerate(nt_extras.extra_vector_math):
tally = 0
if subname[1] in content:
Expand All @@ -182,10 +205,10 @@ def node_enum_items(self, context):
str(tally),
index_offset+1+index2,
))
index_offset += index2
index_offset += index2 + 1

if mix_rgb_index > -1:
nt_debug("Adding mix rgb nodes")

for index2, subname in enumerate(nt_extras.extra_color):
tally = 0
if subname[1] in content:
Expand All @@ -196,7 +219,7 @@ def node_enum_items(self, context):
str(tally),
index_offset+1+index2,
))
index_offset += index2
index_offset += index2 + 1



Expand All @@ -216,15 +239,17 @@ def find_node_item(self, context):
nt_debug("DEF: find_node_item")
tmp = int(self.node_item.split()[0])
nt_debug("FIND_NODE_ITEM: Tmp : " + str(self.node_item.split()))

node_item = tmp
extra = [self.node_item.split()[1], self.node_item.split()[2]]
#nt_debug ("First extra :" + str(extra))
#nt_debug ("Third ? :" + str(self.node_item.split()[3:]))
nice_name = ' '.join(self.node_item.split()[3:])


for index, item in enumerate(nodeitems_utils.node_items_iter(context)):

node_items = NODE_OT_add_tabber_search.ensure_nodes(self, context)

for index, item in enumerate(node_items):
#nt_debug("DEF: find_node_item")
if index == node_item:
return [item, extra, nice_name]
Expand All @@ -237,7 +262,8 @@ def execute(self, context):
startTime = time.perf_counter()
addon = bpy.context.preferences.addons['node_tabber']
prefs = addon.preferences



item = self.find_node_item(context)[0]
extra = self.find_node_item(context)[1]
nice_name = self.find_node_item(context)[2]
Expand Down Expand Up @@ -269,15 +295,25 @@ def execute(self, context):

# no need to keep
self._enum_item_hack.clear()



if item:
node_tree_type = None

if "node_tree" in item.settings :
node_tree_type = item.settings["node_tree"] if item.nodetype == 'GeometryNodeGroup' else eval(item.settings["node_tree"])
# apply settings from the node item
for setting in item.settings.items():
ops = self.settings.add()
ops.name = setting[0]
ops.value = setting[1]

self.create_node(context, item.nodetype)
# !!! this was breaking on custom node groups and not sure what it does
try:
for setting in item.settings.items():
if setting[0] != "node_tree":
ops = self.settings.add()
ops.name = setting[0]
ops.value = setting[1]
except AttributeError as e:
print("NodeTabber:: An AttributeError exception occurred: " + e)

self.create_node(context, item.nodetype, node_tree_type)
#print("Added node in node tabber")

nt_debug(str(item.nodetype))
Expand All @@ -297,8 +333,13 @@ def execute(self, context):
if (extra[0] == "VM"):
node_active.operation = extra[1]

if (extra[0] == "C"):
node_active.blend_type = extra[1]
if (extra[0] == "CM"):
if(extra[1].startswith("VECTOR")) :
node_active.data_type = "VECTOR"
node_active.factor_mode = str(extra[1]).replace("VECTOR", "")
else:
node_active.data_type = "RGBA"
node_active.blend_type = extra[1]

if not prefs.quick_place:
bpy.ops.node.translate_attach_remove_on_cancel('INVOKE_DEFAULT')
Expand All @@ -308,7 +349,7 @@ def execute(self, context):
else:
return {'CANCELLED'}

def create_node(self, context, node_type=None):
def create_node(self, context, node_type=None, node_tree_type=None):
nt_debug("DEF: create_node")
space = context.space_data
tree = space.edit_tree
Expand All @@ -322,7 +363,10 @@ def create_node(self, context, node_type=None):
n.select = False

node = tree.nodes.new(type=node_type)


if node_tree_type != None:
node.node_tree = node_tree_type

node.select = True
tree.nodes.active = node
node.location = space.cursor_location
Expand Down