I noticed a question on the BMD Fusion forum today by Nick Verlinden that asked how to use a script to add a macro to a composite after a specific tool. Here's a look at a few of the different ways that task could be achieved.
Adding a Macro Using a .fu Hotkeys Entry
A Config:/ .fu hotkeys entry can be used to add a macro to your comp when a specific hotkey is pressed. This hotkey entry will place the newly added macro right after your currently selected node and connect them together automatically.
{
Hotkeys
{
Target = "FlowView",
Y = "AddSetting{filename = 'Macros:/YourMacroFile.setting'}",
},
}
When you restart Fusion this new Hotkeys entry is visible in the Hotkeys Manager window's
Views > Flow
section:
Hotkeys Manager view.png
Adding a Macro Using comp:Paste()
A Lua scripted approach can be used to add a new macro to your composite right after a specific tool:
-- Set Blur1 to be the actively selected tool
comp:SetActiveTool(comp:FindTool("Blur1"))
-- Load the macro by reading the file off disk as a Lua table and then paste it into the comp
comp:Paste(bmd.readfile(comp:MapPath("Macros:/YourMacroFile.setting")))
Finding the Node
This script snippet starts out by finding the "Blur1" node using its name in the comp. Then it translates that node name into the pointer value in memory for the node:
Code: Select all
==comp:FindTool("Blur1")
-- Blur (0x0x7f84b20c0000) [App: 'Fusion' on 127.0.0.1, UUID: b59420bf-962b-4971-be37-4cab2c24119c]
Setting the Active Tool
The
comp:SetActiveTool()
function then selects this node in the flow view in Fusion. This makes the Blur1 node the active tool.
Selected Blur Node.png
Translating the Macro:/
PathMap
The next line of the script snippet starts out by using
comp:MapPath()
to translate the relative PathMap location of
Macros:/
into an absolute filepath. In my system, this command turns the relative
Macros:/YourMacroFile.setting
filepath into the expanded absolute filepath location of:
/Users/andrew/Library/Application Support/Blackmagic Design/Fusion/Macros/YourMacroFile.setting
PathMap Translation.png
Reading in the Macro File Contents
Then the
bmd.readfile()
function loads the macro's text file based .settings contents from disk into a new Lua table element. We can use the dump command which is written in short form as
==
to print this Lua table out in the console if we want.
bmd.readfile.png
Pasting in the Macro
Finally the
comp:Paste()
function pastes the Lua table element of the macro data into the comp as a new node that is visible in the flow view.
Added a new Macro.png
If you have the Reactor package manager based "UI Manager Lua & Python Examples" atom package installed there is a script called the "FusionScript Help Browser" that can give you help information about the Fusion specific commands that can be run from Lua like
comp:Paste()
:
FusionScript Help Browser Composition Paste.png
The "Fusion 8 Script Manual.pdf" guide covers the
composition.paste()
command on page 82.
Locking and Unlocking a Comp
When you add a macro node to a comp using a scripted approach, you have the option of suppressing any of the file dialogs that would appear. These dialogs occur when a Loader/Saver/Alembic Mesh3D/FBX Mesh3D/FBX Exporter node is present in a Macro and those nodes have an empty
Filename
field.
This dialog suppression technique is done by adding a pair of matching Lock and Unlock commands at the top and end of your script. The lock command is run before you add a new node to the comp, and the unlock command is run after the node has been added.
-- Lock the comp flow area
comp:Lock()
-- Do something in the script that would show a file dialog
-- ..
-- Unlock the comp flow area
comp:Unlock()
Adding a Macro Using Python
If you prefer to do Python scripting in Fusion, here is a version of the same "Add Macro Using Paste" script:
# Set Blur1 to be the actively selected tool
comp.SetActiveTool(comp.FindTool("Blur1"))
# Load the macro by reading the file off disk and then paste it into the comp
comp.Paste(bmd.readfile(comp.MapPath('Macros:/YourMacroFile.setting')))
Adding a Macro Using an Action
If you wanted to get really fancy with adding a macro to a composite, you could also use a Lua scripted "action" based approach to carry out the same task of adding a macro after a selected node:
-- Set Blur1 to be the actively selected tool
comp:SetActiveTool(comp:FindTool("Blur1"))
-- Use the AddSetting action to load the macro
comp:DoAction("AddSetting", {filename = "Macros:/YourMacroFile.setting"})
Setting the Active Tool
This code snippet starts by useing
comp:FindTool()
to translate the node name to it's pointer. Then it selects the node in the comp using
comp:SetActiveTool()
.
Selected Blur Node.png
Using Actions
Next we come to an interesting function called
DoAction()
which might be completely new to you.
At this point, I'd like to recommend you install the Reactor package manager based "UI Manager Lua & Python Examples" atom package. This will give you access to a script called "Action Listener.lua". This script can be used to get a live display of the actions that happen in Fusion while you are creating a comp as an end user.
This screenshot shows the Action Listener script's output that is displayed after you press the key combination required to run the Config:/ based
AddSettings Hotkey.fu
entry that was listed at the very top of this post.
Fusion Action Listener AddSetting.png
This Action Listener output looks quite cryptic at first. Let's break it down and explore what it is saying.
Code: Select all
[Event]
table: 0x0a9836a0
when = 1529257074.013
sender = Composition (0x0x7feb4db52e00) [App: 'Fusion' on 127.0.0.1, UUID: 851363ce-6d45-461f-a230-55bedabe7be4]
Args = table: 0x0a983788
filename = Macros:/YourMacroFile.setting
_sxpos = 1639
__flags = 1048832
_wypos = 252
_wxpos = 914
_sypos = 1034
what = AddSetting
Rets = table: 0x0a9837d0
Sender Event Result
When an action is listed in Action Listener it typically has an entry like
sender = Composition
in the output. This means you would need to write in
comp:DoAction()
as the function to run it if you want to mimic the recorded action in your own script.
Otherwise, if an action runs in the Fusion wide scope (and not the comp level) then you would need to use the Fusion scope based
fusion:DoAction()
or
app:DoAction()
function to run it. This typically happens when you need to run Actions for new comp creation commands, or importing geometry.
What Event Result
The Action we want to inspect is listed in the Action Listener tool under the heading of
what = AddSetting
. This AddSetting command is the exact same item we had in our Config: .fu hotkeys file.
Args Event Result
The next thing to look at in the Action Listener window is the
Args = table:
result. In this section we can see a list of the items that are able to be specified as parameters to the DoAction function.
The Args table lists entries for
filename
,
_sxpos
,
__flags
,
_wypos
,
_wxpos
,
_sypos
. We are interested in the
filename = Macros:/YourMacroFile.setting
entry since this is where the name of the macro we want to use is specified.
The syntax of the DoAction() function goes something like this:
comp:DoAction("TheActionName", { argName1 = "YourArgValue1", argName2 = "YourArgValue2", argName3 = "YourArgValue3",}
The element "TheActionName" is where you write in the name of the actual action you want to run like "AddSetting".
The next item is a Lua table that is defined with curly braces
{}
. Inside this section you can list each of the arguments by name followed by their value and then a comma. If there are multiple args you want to add, a comma is used to separate each of the individual args entries. Numbers are written in as values directly without quotes, while strings can be written in using either single quotes
' '
, double quotes
" "
, or double square brackets
[[ ]]
.
So for our needs, we would run the
AddSetting
action using this Lua command:
comp:DoAction("AddSetting", {filename = "Macros:/YourMacroFile.setting"})
Added a new Macro.png
Listing All of the Actions
If you want to get a complete listing of all the actions that are present in your copy of Fusion 9/Resolve 15, this Lua script can be used to do a Console view based print-out from the ActionManager:
--[[--
Action Printout v1.0 - 2018-06-17
by Andrew Hazelden <andrew@andrewhazelden.com>
www.andrewhazelden.com
Print a copy of the actions list to the Console.
--]]--
-- Track the actions that are available in Fusion
local actionList = fu.ActionManager:GetActions()
-- Count the total number of actions
actionCount = 0
for i, act in ipairs(actionList) do
if not act:Get('Parent') then
actionCount = actionCount + 1
end
end
print('[' .. actionCount .. ' Actions Found]')
-- List each action sequentially
for i, act in ipairs(actionList) do
if not act:Get('Parent') then
print(act.ID)
end
end
After you run this script, will see a Console result similar to this output that displays both the Fusion wide, and comp specific actions.
Console Actions Printout.png
Like many things in Fusion 9 and Resolve 15, actions have very little documentation at the moment besides what you can find by searching the scripting discussion threads on the WSL forum, or from code examples that can be discovered in Reactor atom packages.
As far as the process of learning how to script things in Fusion goes, the
FusionScript Help Browser tool is a pretty good research tool for listing the existence of under-documented features you can access.
If we open up the
FusionScript Help Browser
tool and look at the
ActionManager
class we will see the
DoAction
member is listed.
FusionScript Help Browser Do Action.png
Scanning a Comp for Existing Macros
The following Lua code snippet scans the current Fusion comp to look for all of the
GroupOperator and
MacroOperator node RegIDs. Then it looks up their node names:
--[[--
Scan Comp for Macro Nodes - 1.0 2018-06-18
By Andrew Hazelden <andrew@andrewhazelden.com>
--]]--
-- Should only the currently selected nodes be displayed
local showSelected = false
print('[Listing Macros]')
-- List the macros that are stored as groups
print('\n[GroupOperator Based Macros]')
local toollist1 = comp:GetToolList(showSelected, 'GroupOperator')
for i, tool in ipairs(toollist1) do
nodeID = tool:GetAttrs().TOOLS_RegID
nodeName = tool:GetAttrs().TOOLS_Name
print('\t[' .. nodeName .. ' Macro] ' .. nodeID)
end
-- List the macros that have their controls exposed but the group expandable option disabled
print('\n[MacroOperator Based Macros]')
local toollist2 = comp:GetToolList(showSelected, 'MacroOperator')
for i, tool in ipairs(toollist2) do
nodeID = tool:GetAttrs().TOOLS_RegID
nodeName = tool:GetAttrs().TOOLS_Name
print('\t[' .. nodeName .. ' Macro] ' .. nodeID)
end
This gives an output in the Console that looks like this:
Code: Select all
[Listing Macros]
[GroupOperator Based Macros]
[Z360Extract Macro] GroupOperator
[Angular2Equirectangular Macro] GroupOperator
[MayaBackgroundGradientEquirectangular Macro] GroupOperator
[Group1 Macro] GroupOperator
[MacroOperator Based Macros]
[Z360Render_1 Macro] MacroOperator
You do not have the required permissions to view the files attached to this post.