IMPORTANT UPDATE! May 12 13, 2026



Tomorrow Today Last Wednesday, on the 13th of May, the manual Patrons group (the one that gives you your green username AND access to dedicated Patrons spaces on WSL) will be has been DELETED.

This means that your access to those spaces will be has been revoked until you connect your Patreon account to WSL using the link below, which will give you access to the NEW, future-proof Patrons+++ group.

With the imminent release of ZEPPO BETA 2 - tentatively planned for released Friday today yesterday (!!) - I wouldn't dawdle... with Beta 2 (i.e. all my late nights in the past month), Zeppo has become something truly special, battle-tested and multi-user hardened in an actual production.

Yes, there will be a Reactor release eventually, and no, it won't have all the bells and whistles - those are for Patrons, because they are the ones keeping WSL afloat, which is still only barely these days...

I'd better get back to prepping that done did release then!

Thank you,

Pieter


How I worked around the limits of scripts (and node names) in Fusion

Tutorials and how-to's!


User avatar
JustCropIt
Fusionator
Posts: 1249
Joined: 2 years ago
Reactions score: 296
Has thanked: 264 times
Been thanked: 286 times

How I worked around the limits of scripts (and node names) in Fusion

#1

Unread post by JustCropIt »

All of this was originally part of the main post for my Loop It macro and so it references things from that macro. However upon reflecting on it all for a bit I felt that all of the below kinda made the macro post a bit more heavy than it needed to be. And so I extracted the below (non grey) part and present it here as a "stand alone" thingie instead.

TL:DR
The gist of it all is that I found a way to get around one of the fundamental "issues" (or feature if you will.. it's certainly not a bug) with scripts in Fusion.

That issue is that scripts don't update. Which makes things problematic in a world where nodes are used, the names of those nodes can change in the blink of an eye, and some things are only possible to do to those nodes using scripts. Any name change to a node will break any script referring to that node since the name of the node won't be changed in any script. So the script will be referring to a node name that doesn't exist or it exists on the wrong node. This is unlike expressions where name changes to nodes are reflected.

The solution I found is a combination of Button scripts, ExecuteOnChange scripts, expressions and possibly custom settings (not necessarily required in all cases). That might sound like a lot, and glazing over the below chunk of text, it might give the impression that it also is a lot... but it's a fairly basic concept once one get through it all.

Pinky promise.

Anyhooo, on with the show:)


Hacks Creative use of game mechanics

I promised @SecondMan the low down on one of the hacks development choices I did in my Loop It macro and so allow me to present to you:


The Script Node Name hack dance.


The Setup
In the Seam Helpers section there’s a button called “Reset Lerps”. Seems to do nothing special. Click it and the settings above it resets to their default value. This is however pretty special (IMO) due to the following:

  • To set a value by clicking a button, a script has to be used. Scripts in Fusion, unlike expressions, are "set in stone”. If a node is referred to by name in a script, and that name of the node changes, it won’t be reflected in the script. The script will still be using the old node name. For example if you make a copy of the macro, all the nodes in it (and the macro name) will be renamed by a number being added to the end of each name. Or if you just rename a node willy-nilly. Any expressions used will be updated with the new names, but no script will. And so you don’t usually want to refer to specific node names in scripts. Speaking of which...
  • The controls that the button “resets” are on three different nodes. If all the controls had been on the same node as the button control then no node names would have been needed, the script could simply refer to each control as being on the “tool” (“tool" in scripts being, AFAIK the equivalent of “self” in expressions). But since Center and Pivot are on two different nodes (due to another hack work around) and Size, Angle and the Button being on a third node, well, that’s where things gets interesting.

The Rules

  • There’s a way when using a script to find a named setting/control in a node (inside a macro/group) that was shared to me by fellow redditor, Fusion scripting wizard and Custom Poly modifier aficionado Glad-Parking3315. To my non coding eyes, the script seemed very technical. It basically searches through every node in a macro until it finds one that matches the name of the setting it looks for (if I understood it correctly). And that’s super cool. But I felt that maybe if I banged my head 50 times at random (Fusion) stuff I might come up with something my monkey brain could understand. And if it could, and if the alternative did the same as the script, then I’d go with what monkey gets. And so some head banging ensued.
  • No modifiers. My macros don't do modifiers. That's a 98% true fact. I do have standards.

The Dance
Here’s what happens when clicking the button:

  1. The button (called "LerpReset") sets the value on the settings that are on the same node as itself (Size and Angle). Since they are on the same node (called "LI_ctrl") as the script itself, no node names are needed.
  2. The node that has the Center control has a checkbox. This checkbox has an expression that checks the button. It’s literally just LI_ctrl.LerpReset (and since it’s an expression, if this name changes it’ll get updated here). Which seems like… nothing. And it is nothing. Well. Almost nothing. That "almost" being key here.
  3. The checkbox also has an ExecuteOnChange script attached to it that triggers when anything happens to the control itself. Anything. So when the checkbox looks at the Button and it gets clicked… while in a sense nothing happens, to the ExecuteOnChange “function” something did happen. And so it fires away its script. And that script, being on the same node as the Center control, has no need for any node names to complete its task of resetting the value of the Center control.
  4. The same thing happens on the node that has the Pivot control. There’s a checkbox on that node with the exact same expression and the exact same ExecuteOnChange script.

All of the above results in the macro being able to be copied and have its node names change and still have the button work. Cool.

For ExecuteOnChange to trigger, the control that is being “changed” (and so triggering the execution) has to be physically visible in the inspector. For example, if instead of the button being the “triggering” device I used a slider/checkbox/whatever and that wasn’t visible, then the ExecuteOnChange doesn’t trigger. As in, if when I click the button it updates a slider and the ExecuteOnChange is looking at the slider… if the slider is on another tab or in a “hidden” nest (and so not visible) then nothing happens. If the slider is visible, then the ExecuteOnChange will trigger. And so having the ExecuteOnChange look at the button, and the button being clicked seen as a “change”, and the button needed to be visible to actually be clicked… well… that’s just perfect.

And there you go. That is, in my opinion, one of my finer Fusion hacks solutions. And if BMD is looking… it’s a feature, not a bug! No need to update anything<3

Other hack techniques used in the macro:

  • The Center/Pivot Replacement hack strategy
  • The Widgets hack expedition

Honorable mention: The Keyframeable Speed on a TimeSpeed Node hack manoeuvre (the TimeSpeed node got replaced by a TimeStretcher node and so this hack is not part of the macro anymore)



User avatar
SecondMan
Site Admin
Posts: 11603
Joined: 11 years ago
Reactions score: 474
Location: Brussels, Sprouts
Mood:
Has thanked: 289 times
Been thanked: 293 times

Re: How I worked around the limits of scripts (and node names) in Fusion

#2

Unread post by SecondMan »

I’m going to have to read this again…


User avatar
JustCropIt
Fusionator
Posts: 1249
Joined: 2 years ago
Reactions score: 296
Has thanked: 264 times
Been thanked: 286 times

Re: How I worked around the limits of scripts (and node names) in Fusion

#3

Unread post by JustCropIt »

SecondMan wrote: 1 month ago

I’m going to have to read this again…

  • Node A has a Button (but it could be any type of control as long as it is something the user interacts with).
  • Node B (and C and so on) has a control (not super relevant what kind of control it is I think) with an expression that refers to the button (NodeA.Button).
  • The control on Node B (and C and so on) has an ExecuteOnChange script that does whatever you want done on Node B whenever the button on Node A is clicked.

Clicking the Button (Node A) → triggers the expression on the control (Node B) → which triggers the ExecuteOnChange script (Node B).

In my macro the button changes some settings on the node the button is on and settings on other nodes gets changed too due to the setup I just mentioned getting triggered. These changes (setting a value) can only be done using scripts, and the scripts requires node names to not change, and the setup works around nodes changing names when for example the nodes are copied.


User avatar
AndrewHazelden
Fusius Of Borg
Posts: 2907
Joined: 11 years ago
Reactions score: 279
Location: West Dover, Nova Scotia, Canada
Has thanked: 72 times
Been thanked: 170 times

Re: How I worked around the limits of scripts (and node names) in Fusion

#4

Unread post by AndrewHazelden »

JustCropIt wrote: 1 month ago

The Script Node Name hack dance.

Is it wrong for me to consider it strange you are fine with ExecuteOnChange usage in a macro but flee away from modifiers? IDK man... I will have to revisit this topic in a few years time with you. Personally, I consider intool scripts and ExecuteOnChange to be risky non-deterministic gremlins lurking in the shadows ready to wreak havoc on any non-trivial comp. I trust those elements like you trust piperouters… :)

I suspect there is a way to use a wireless input like UserControl added on the internal nodes inside a macro / group to get dynamically tracked node names fed into your other nodes button controls code blocks without ExecuteOnChange level (IMHO) jank usage.

Code: Select all


UserControls = ordered() {
  MetadataSource = {
    LINKID_DataType = "Image",
    INP_Default = 0,
    IC_ControlPage = 1,
    INPID_InputControl = "ImageControl",
    LINKS_Name = "MetadataSource",
  }
}

WSL topic reference for some of the ImageControl block grafting:
Rendering Text From Metadata Tags


User avatar
aelineau
Posts: 6
Joined: 2 years ago
Reactions score: 2
Has thanked: 1 time

Re: How I worked around the limits of scripts (and node names) in Fusion

#5

Unread post by aelineau »

Glad-Parking315 Here :-)

It took me a while to understand the trick (it was 1am when I dug into it). What you're actually benefiting from is what I believe to be a bug. tool and self:GetTool() are in principle synonymous — and indeed they are in BTNCS_Execute. For some obscure reason, that's not the case in INPS_ExecuteOnChange. Easy to demonstrate inside a macro. Let's hope BMD never fixes it, because once you can access the parent tool (the original node, not the macro), you're saved.

Let me offer two alternative tricks that are even more convoluted, but have one key advantage over ExecuteOnChange: they preserve the spirit of Execute, which only fires once on press. For a reset that's no big deal, but in other scenarios the double-trigger of OnChange (press AND release) can make it completely unusable.

Trick 1 — The self-registering name (riding the bug)
Create two hidden controls: a single-line text control named MyName, and any other control with the following ExecuteOnChange:

Code: Select all

self:GetTool().MyName[0] = self:GetTool().Name

ExecuteOnChange always fires at the birth of the macro in the flow. So MyName gets populated automatically, without any user interaction. From that point on, every button in the macro can use:

Code: Select all

local mytool = comp[self:GetTool().MyName[0]]

inside its BTNCS_Execute — giving full access to the parent node, with the name always up to date even after copies and renames.

Trick 2 — The ghost expression (riding a feature, ahah)
When you need a button to act on controls from another node, first create it as a slider and enter an expression like FastNoise1.Comments (never mind if it's semantically meaningless). Then convert the control to a button. The expression disappears from the Inspector but Fusion keeps it alive and updated — when FastNoise1 gets renamed, manually or inside a macro, the expression is silently updated too. From Lua, it's then straightforward to retrieve just the node name from self:GetExpression().

Both tricks can be combined: each node involved auto-registers its own name into a hidden field, and the node holding the buttons collects them all — no hardcoding, no comp-wide search, no hierarchy dependency, copy-safe by design.

What would make all of this unnecessary? If Fusion simply exposed a Parent property on inputs (the way Children already exists). The notion of Parent/Child navigation is fundamental in every object-oriented language or framework — JavaScript DOM, Python, Qt, C#... An Input.ParentTool property, consistent across all execution contexts, would make all these workarounds instantly obsolete.

Because while we're tinkering with workarounds, we're not developing our awesome tools. :lol:

The last solution — the one I actually use — is to search for a node by name, ID, or a dedicated "tag control" inside the macro:

Code: Select all

-- Check if a tool is a macro or group operator
function isMacro(tool)
    return tool.ID == "MacroOperator" or tool.ID == "GroupOperator"
end

-- Find an internal tool by ID (e.g. "TextPlus") or name (e.g. "Text1")
function findInternalTool(macroTool, target)
    local children = macroTool:GetChildrenList()
    for _, subtool in ipairs(children) do
        if subtool.ID == target or subtool.Name == target then
            return subtool
        end
    end
    return nil
end

-- Find an internal tool by the presence of a named control (e.g. "tag202604191521")
-- The control just needs to exist on the subtool -- its value is irrelevant
function findToolByTag(macroTool, tagName)
    local children = macroTool:GetChildrenList()
    for _, subtool in ipairs(children) do
        if subtool[tagName] then
            return subtool
        end
    end
    return nil
end

-- Auto-detection : if we are inside a macro, locate the target subtool by tag
-- otherwise the current tool is the target
local myTool = nil
if isMacro(tool) then
    myTool = findToolByTag(tool, "tag202604191521")
else
    myTool = tool
end
Last edited by aelineau 1 month ago, edited 1 time in total.

User avatar
JustCropIt
Fusionator
Posts: 1249
Joined: 2 years ago
Reactions score: 296
Has thanked: 264 times
Been thanked: 286 times

Re: How I worked around the limits of scripts (and node names) in Fusion

#6

Unread post by JustCropIt »

AndrewHazelden wrote: 1 month ago

Is it wrong for me to consider it strange you are fine with ExecuteOnChange usage in a macro but flee away from modifiers? IDK man... I will have to revisit this topic in a few years time with you.

Can't wait! Won't wait!

In the context of my macros, I don't like modifiers as they litter stuff "outside" the macro itself. I want the macro to be just by itself, not adding things in menus elsewhere.

As for modifiers in general, I just don't gel with the UX. Having them "hidden" and stacked in that modifier menu in the inspector is a mess. And while I'd like to think that just exposing them as a kind of "special" node (make them look like pill shaped nodes!) would solve everything, I bet it's not that easy. Or maybe it is. But probably not:/

In general I don't like working with scripts overall (ExecuteOnChange or not) since I find scripting confusing. All those curly brackets and whatnots. Urgh. But from the end user perspective, they don't leave a "footprint" in the way modifiers do and so I'm not really bothered. Again, this is in the context of my macros.

Outside of my macros I dislike using scripts since I'm not a coder and I dislike using modifiers since the UX is a mess. But I do use them if/when it makes sense to me:)


As for the ImageControl thingie you shared, my smooth brain really needs to see a practical working example (with some related explaining) to understand these type of things:)


User avatar
DanielKoch
Fusioneer
Posts: 68
Joined: 11 years ago
Reactions score: 5
Location: Sydney, Australia
Has thanked: 1 time
Been thanked: 3 times

Re: How I worked around the limits of scripts (and node names) in Fusion

#7

Unread post by DanielKoch »

aelineau wrote: 1 month ago

What would make all of this unnecessary? If Fusion simply exposed a Parent property on inputs (the way Children already exists).

But it does, that's what GetTool() returns (in scripts; in FFI expressions it's Owner). And of course the tool's own current name is just Name, in both.

The tricks for using expression auto-renaming in your non-auto-renaming scripts are clever. Maybe one day we can extend auto-renaming to OnChange scripts, they can be a little more problematic in some cases but perhaps doable safely.


User avatar
JustCropIt
Fusionator
Posts: 1249
Joined: 2 years ago
Reactions score: 296
Has thanked: 264 times
Been thanked: 286 times

Re: How I worked around the limits of scripts (and node names) in Fusion

#8

Unread post by JustCropIt »

DanielKoch wrote: 1 month ago

The tricks for using expression auto-renaming in your non-auto-renaming scripts are clever. Maybe one day we can extend auto-renaming to OnChange scripts, they can be a little more problematic in some cases but perhaps doable safely.

Since you have a bit of an inside view, would you say that any of the "hacks" here in this thread would/could be seen as exploiting bugs (as @aelineau suggested my thing might be)?

I've done other questionable things before in my macros and having to find alternatives when things gets patched is something I'd like to avoid:)


User avatar
SecondMan
Site Admin
Posts: 11603
Joined: 11 years ago
Reactions score: 474
Location: Brussels, Sprouts
Mood:
Has thanked: 289 times
Been thanked: 293 times

Re: How I worked around the limits of scripts (and node names) in Fusion

#9

Unread post by SecondMan »

@JustCropIt All I have to add here at this time of the day is that I come from an era where masks were embedded in the Inspector like Modifiers are now (perhaps that should be my one moment that changed everything Fusion in that other topic) so good things may be afoot!

Also, isn’t finding a way to make something that everyone says can’t be done work, crazy satisfying indeed! :cheers:


User avatar
aelineau
Posts: 6
Joined: 2 years ago
Reactions score: 2
Has thanked: 1 time

Re: How I worked around the limits of scripts (and node names) in Fusion

#10

Unread post by aelineau »

DanielKoch wrote: 1 month ago
aelineau wrote: 1 month ago

What would make all of this unnecessary? If Fusion simply exposed a Parent property on inputs (the way Children already exists).

But it does, that's what GetTool() returns (in scripts; in FFI expressions it's Owner). And of course the tool's own current name is just Name, in both.

The tricks for using expression auto-renaming in your non-auto-renaming scripts are clever. Maybe one day we can extend auto-renaming to OnChange scripts, they can be a little more problematic in some cases but perhaps doable safely.

The problem is easy to see her, I added two event managers in a customtool.

One on a button exec :

Code: Select all

 print(self:GetTool().Name.."/"..tool.Name.. ": event Execute")

the other on a slider on change.

Code: Select all

 print(self:GetTool().Name.."/"..tool.Name.. ": event On Change")

Simple script printing the name of the tool and the event.

Then I created a macro with the Customtool.

In the macro case that did not the name of the direct Parent tool, but the name of the Macro, and on the OnChange I have two different prints at once.

image.webp

Code: Select all

{
	Tools = ordered() {
		MacroTool1 = MacroOperator {
			CtrlWZoom = false,
			Inputs = ordered() {
				CustomTool1_NumberIn1 = InstanceInput {
					SourceOp = "CustomTool1_1",
					Source = "NumberIn1",
					Page = "Controls",
					Default = 0.169,
				},
				CustomTool1_NumberIn2 = InstanceInput {
					SourceOp = "CustomTool1_1",
					Source = "NumberIn2",
					Page = "Controls",
					Default = 0,
				}
			},
			Outputs = {
				MainOutput1 = InstanceOutput {
					SourceOp = "CustomTool1_1",
					Source = "Output",
				}
			},
			ViewInfo = GroupInfo { Pos = { -880, -49.5 } },
			Tools = ordered() {
				CustomTool1_1 = Custom {
					CtrlWZoom = false,
					CtrlWShown = false,
					Inputs = {
						LUTIn1 = Input {
							SourceOp = "CustomTool1_1LUTIn1",
							Source = "Value",
						},
						LUTIn2 = Input {
							SourceOp = "CustomTool1_1LUTIn2",
							Source = "Value",
						},
						LUTIn3 = Input {
							SourceOp = "CustomTool1_1LUTIn3",
							Source = "Value",
						},
						LUTIn4 = Input {
							SourceOp = "CustomTool1_1LUTIn4",
							Source = "Value",
						},
						NumberIn1 = Input { Value = 0.167, }
					},
					ViewInfo = OperatorInfo { Pos = { 0, 8.75758 } },
					UserControls = ordered() {
						NumberIn1 = {
							INP_MaxAllowed = 1000000,
							INP_Integer = false,
							INPID_InputControl = "ScrewControl",
							INP_MaxScale = 1,
							INP_MinScale = 0,
							INP_MinAllowed = -1000000,
							LINKID_DataType = "Number",
							INPS_ExecuteOnChange = "print(self:GetTool().Name..\"/\"..tool.Name.. \": event On Change\")",
							ICS_ControlPage = "Controls",
							INP_SplineType = "Default",
							LINKS_Name = "Number In 1"
						},
						NumberIn2 = {
							INP_MaxAllowed = 1000000,
							INP_Integer = false,
							INPID_InputControl = "ButtonControl",
							BTNCS_Execute = "print(self:GetTool().Name..\"/\"..tool.Name.. \": event Execute\")",
							INP_MaxScale = 1,
							INP_MinScale = 0,
							INP_MinAllowed = -1000000,
							LINKID_DataType = "Number",
							ICS_ControlPage = "Controls",
							INP_SplineType = "Default",
							LINKS_Name = "Number In 2"
						}
					}
				},
				CustomTool1_1LUTIn1 = LUTBezier {
					KeyColorSplines = {
						[0] = {
							[0] = { 0, RH = { 0.333333333333333, 0.333333333333333 }, Flags = { Linear = true } },
							[1] = { 1, LH = { 0.666666666666667, 0.666666666666667 }, Flags = { Linear = true } }
						}
					},
					SplineColor = { Red = 255, Green = 255, Blue = 0 },
					CtrlWZoom = false,
					NameSet = true,
				},
				CustomTool1_1LUTIn2 = LUTBezier {
					KeyColorSplines = {
						[0] = {
							[0] = { 0, RH = { 0.333333333333333, 0.333333333333333 }, Flags = { Linear = true } },
							[1] = { 1, LH = { 0.666666666666667, 0.666666666666667 }, Flags = { Linear = true } }
						}
					},
					SplineColor = { Red = 255, Green = 0, Blue = 255 },
					CtrlWZoom = false,
					NameSet = true,
				},
				CustomTool1_1LUTIn3 = LUTBezier {
					KeyColorSplines = {
						[0] = {
							[0] = { 0, RH = { 0.333333333333333, 0.333333333333333 }, Flags = { Linear = true } },
							[1] = { 1, LH = { 0.666666666666667, 0.666666666666667 }, Flags = { Linear = true } }
						}
					},
					SplineColor = { Red = 0, Green = 180, Blue = 255 },
					CtrlWZoom = false,
					NameSet = true,
				},
				CustomTool1_1LUTIn4 = LUTBezier {
					KeyColorSplines = {
						[0] = {
							[0] = { 0, RH = { 0.333333333333333, 0.333333333333333 }, Flags = { Linear = true } },
							[1] = { 1, LH = { 0.666666666666667, 0.666666666666667 }, Flags = { Linear = true } }
						}
					},
					SplineColor = { Red = 180, Green = 255, Blue = 0 },
					CtrlWZoom = false,
					NameSet = true,
				}
			},
		},
		CustomTool1 = Custom {
			Inputs = {
				LUTIn1 = Input {
					SourceOp = "CustomTool1LUTIn1_1",
					Source = "Value",
				},
				LUTIn2 = Input {
					SourceOp = "CustomTool1LUTIn2_1",
					Source = "Value",
				},
				LUTIn3 = Input {
					SourceOp = "CustomTool1LUTIn3_1",
					Source = "Value",
				},
				LUTIn4 = Input {
					SourceOp = "CustomTool1LUTIn4_1",
					Source = "Value",
				},
				NumberIn1 = Input { Value = 0.169, }
			},
			ViewInfo = OperatorInfo { Pos = { -880, -115.5 } },
			UserControls = ordered() {
				NumberIn1 = {
					LINKS_Name = "Number In 1",
					LINKID_DataType = "Number",
					INPID_InputControl = "ScrewControl",
					INP_Integer = false,
					INP_MinScale = 0,
					INP_MaxScale = 1,
					INP_MinAllowed = -1000000,
					INP_MaxAllowed = 1000000,
					INP_SplineType = "Default",
					ICS_ControlPage = "Controls",
					INPS_ExecuteOnChange = "print(self:GetTool().Name..\"/\"..tool.Name.. \": event On Change\")"
				},
				NumberIn2 = {
					LINKS_Name = "Number In 2",
					LINKID_DataType = "Number",
					INPID_InputControl = "ButtonControl",
					INP_Integer = false,
					INP_MinScale = 0,
					INP_MaxScale = 1,
					INP_MinAllowed = -1000000,
					INP_MaxAllowed = 1000000,
					INP_SplineType = "Default",
					BTNCS_Execute = "print(self:GetTool().Name..\"/\"..tool.Name.. \": event Execute\")",
					ICS_ControlPage = "Controls"
				}
			}
		},
		CustomTool1LUTIn1_1 = LUTBezier {
			KeyColorSplines = {
				[0] = {
					[0] = { 0, RH = { 0.333333333333333, 0.333333333333333 }, Flags = { Linear = true } },
					[1] = { 1, LH = { 0.666666666666667, 0.666666666666667 }, Flags = { Linear = true } }
				}
			},
			SplineColor = { Red = 255, Green = 255, Blue = 0 },
			NameSet = true,
		},
		CustomTool1LUTIn2_1 = LUTBezier {
			KeyColorSplines = {
				[0] = {
					[0] = { 0, RH = { 0.333333333333333, 0.333333333333333 }, Flags = { Linear = true } },
					[1] = { 1, LH = { 0.666666666666667, 0.666666666666667 }, Flags = { Linear = true } }
				}
			},
			SplineColor = { Red = 255, Green = 0, Blue = 255 },
			NameSet = true,
		},
		CustomTool1LUTIn3_1 = LUTBezier {
			KeyColorSplines = {
				[0] = {
					[0] = { 0, RH = { 0.333333333333333, 0.333333333333333 }, Flags = { Linear = true } },
					[1] = { 1, LH = { 0.666666666666667, 0.666666666666667 }, Flags = { Linear = true } }
				}
			},
			SplineColor = { Red = 0, Green = 180, Blue = 255 },
			NameSet = true,
		},
		CustomTool1LUTIn4_1 = LUTBezier {
			KeyColorSplines = {
				[0] = {
					[0] = { 0, RH = { 0.333333333333333, 0.333333333333333 }, Flags = { Linear = true } },
					[1] = { 1, LH = { 0.666666666666667, 0.666666666666667 }, Flags = { Linear = true } }
				}
			},
			SplineColor = { Red = 180, Green = 255, Blue = 0 },
			CtrlWZoom = false,
			NameSet = true,
		}
	},
	ActiveTool = "MacroTool1"
}
You do not have the required permissions to view the files attached to this post.

User avatar
aelineau
Posts: 6
Joined: 2 years ago
Reactions score: 2
Has thanked: 1 time

Re: How I worked around the limits of scripts (and node names) in Fusion

#11

Unread post by aelineau »

aelineau wrote: 1 month ago

Trick 1 — The self-registering name (riding the bug)
Create two hidden controls: a single-line text control named MyName, and any other control with the following ExecuteOnChange:

Code: Select all

self:GetTool().MyName[0] = self:GetTool().Name

ExecuteOnChange always fires at the birth of the macro in the flow. So MyName gets populated automatically, without any user interaction. From that point on, every button in the macro can use:

Code: Select all

local mytool = comp[self:GetTool().MyName[0]]

inside its BTNCS_Execute — giving full access to the parent node, with the name always up to date even after copies and renames.

😥
Doesn't work anymore !