Building GUIs With Fusion's UI Manager

User avatar
AndrewHazelden
Fusionator
Posts: 1508
Joined: Fri Apr 03, 2015 3:20 pm
Answers: 6
Location: West Dover, Nova Scotia, Canada
Been thanked: 85 times
Contact:

Re: Building GUIs With Fusion's UI Manager

#181

Post by AndrewHazelden » Mon Feb 11, 2019 8:59 am

pixelstuff wrote:
Mon Feb 11, 2019 8:33 am
I can't seem to find a solution to this and thought maybe its a bug or something else that I have installed that's causing it. The trouble is I don't know how to troubleshoot it.

Hi @pixelstuff.

When things go wrong with UI Manager there isn't a lot of ways to troubleshoot things since all users have to work with, are small fragments of details and scraps of information. :-|

If you want to see scripting functionality and API documentation improved in Resolve 15 and in Fusion Standalone 9 you need to reach out to BMD and let them know its a priority for you. The lack of official *modern* scripting documentation on features like UI Manager, Actions, and Events makes Lua and Python scripting a process of trial and error for end users that make things harder than necessary.

Tags:

User avatar
pixelstuff
Posts: 41
Joined: Sun Jul 15, 2018 11:50 am
Been thanked: 1 time

Re: Building GUIs With Fusion's UI Manager

#182

Post by pixelstuff » Mon Feb 11, 2019 9:47 am

Thanks, I'll contact them directly as its an issue with Fusion 9 and the same happens in Resolve 15, maybe they can track the cause of the problem down :)

User avatar
miaz3
Fusioneer
Posts: 219
Joined: Sat Jan 03, 2015 1:43 am
Location: Angoulême / France
Been thanked: 2 times
Contact:

Re: Building GUIs With Fusion's UI Manager

#183

Post by miaz3 » Fri Mar 01, 2019 12:48 pm

Thanks @PeterLoveday for the tab bar, didn't know !
Thanks @AndrewHazelden i'didnt' know it...i made a func to use uuid...i will integrate it directly into my script :)
  1. function uuid()
  2.     math.randomseed(os.time())
  3.     local template ='xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'
  4.     return string.gsub(template, '[xy]', function (c)
  5.         local v = (c == 'x') and math.random(0, 0xf) or math.random(8, 0xb)
  6.         return string.format('%x', v)
  7.     end)
  8. end
Added in 36 minutes 4 seconds:
I thought, we could call (since bmd.scriptapp ()) another module that 'Fusion', ip, timeout, uuid, subtype ?

User avatar
AndrewHazelden
Fusionator
Posts: 1508
Joined: Fri Apr 03, 2015 3:20 pm
Answers: 6
Location: West Dover, Nova Scotia, Canada
Been thanked: 85 times
Contact:

Re: Building GUIs With Fusion's UI Manager

#184

Post by AndrewHazelden » Mon Apr 08, 2019 6:55 am

pixelstuff wrote:
Sun Feb 03, 2019 4:14 am
A problem I'm running into is for some reason the action detection stops(see gif) after a period of time or number of iterations(both time and inputs). Would you have any idea what could possibly be causing this, as I also checked the UI Manager "List input control names" examples in Reactor and it seems to do the same in Win10 and Mac OSX.

The console "time changed" is within the function below.

Code: Select all

ui:AddNotify('Time_Set', comp)

function disp.On.Time_Set(ev)
	print('time changed')
end


There is a possibility that garbage collection in Lua is disposing of the AddNotify action after a while. If you store the pointer returned by the ui:AddNotify() function in a variable it might potentially solve your issue:

Code: Select all

notify = ui:AddNotify('Time_Set', comp)

function disp.On.Time_Set(ev)
	print('time changed')
end

User avatar
pixelstuff
Posts: 41
Joined: Sun Jul 15, 2018 11:50 am
Been thanked: 1 time

Re: Building GUIs With Fusion's UI Manager

#185

Post by pixelstuff » Sun Apr 14, 2019 2:45 pm

thanks @AndrewHazelden BMD confirmed this as a bug, and unfortunately it's still there currently with 16, but hopefully it will be fixed soon.

That makes sense what you have suggested I'll give it a try :)

User avatar
AndrewHazelden
Fusionator
Posts: 1508
Joined: Fri Apr 03, 2015 3:20 pm
Answers: 6
Location: West Dover, Nova Scotia, Canada
Been thanked: 85 times
Contact:

Fuskin Button Toolbar GUI

#186

Post by AndrewHazelden » Fri Aug 16, 2019 10:57 am

The Fuskin Button Toolbar GUI.lua script example has been added to the "UI Manager Lua & Python Examples" atom package in Reactor.

This is a Fusion 16/Resolve 16 compatible script that extracts a series of image resources from the zipped Fuskin file and generates a new UI Manager based toolbar GUI. This script uses the new "ZipFile()" functionality that is only present in Fu16+ Lua scripting.

This script was previously mentioned on the WSL thread "Fetching an image from the .fuskin file via script?" back on 2019-05-06.

Screenshot

FuskinButtonToolbarGUI.png
You do not have the required permissions to view the files attached to this post.

User avatar
AndrewHazelden
Fusionator
Posts: 1508
Joined: Fri Apr 03, 2015 3:20 pm
Answers: 6
Location: West Dover, Nova Scotia, Canada
Been thanked: 85 times
Contact:

Tree Icons Comp Browser

#187

Post by AndrewHazelden » Thu Aug 22, 2019 4:57 pm

Fusion 16 granted a UI Manager centric wish list item "ui:Icon Support in a UI Manager ui:Tree Layout" that I had requested back in 2018. This feature allows for custom PNG icons to be added to a list view, or for a photo-browser like GUI to be made with preview thumbnail images. :banana:

Tree Icons Comp Browser

Tree Icon Comp Browser.png
Here is a Comp Browser demo that has little tiny Fusion icons added next to each comp file in the uiTree view layout.

This script can be used as a Fusion "Comp Browser" window that displays a list of currently open Fusion .comp files, and the rows list summary details about each comp. Double clicking on a row in the Comp Browser ui:Tree view will open the comp file's parent folder in a desktop folder browsing window.

This script requires Fusion Standalone 16 in order to work correctly as the ability to add ui:Icon resources to a ui:Tree was added to the UI Manager library in this version.
Code: [Select all] [Expand/Collapse] [Download] (Tree Icon Comp Browser.lua)
  1. --[[--
  2. ----------------------------------------------------------------------------
  3. Comp Browser for Fusion - v1.0 2019-08-22 8.33 PM
  4. by Andrew Hazelden <andrew@andrewhazelden.com>
  5. www.andrewhazelden.com
  6. -- ----------------------------------------------------------------------------
  7.  
  8. This script is from the Reactor "UI Manager Lua & Python Examples" atom package.
  9.  
  10. It is primarily designed as a code demo for how a ui:Icon PNG image resource can be added to a ui:Tree.
  11.  
  12. This script can be used as a Fusion "Comp Browser" window that displays a list of currently open Fusion .comp files, and the rows list summary details about each comp. Double clicking on a row in the Comp Browser ui:Tree view will open the comp file's parent folder in a desktop folder browsing window.
  13.  
  14. This script requires Fusion Standalone 16 in order to work correctly as the ability to add ui:Icon resources to a ui:Tree was added to the UI Manager library in this version.
  15.  
  16. --]]--
  17.  
  18.  
  19. -- Find out the current directory from a file path
  20. -- Example: print(dirname('/Volumes/Media/image.0000.exr'))
  21. function dirname(filename)
  22.     return filename:match('(.*' .. osSeparator .. ')')
  23. end
  24.  
  25. -- Show the ui:Tree View
  26. function CompBrowser()
  27.     local ui = fu.UIManager
  28.     local disp = bmd.UIDispatcher(ui)
  29.     local width,height = 1920,600
  30.  
  31.     win = disp:AddWindow({
  32.         ID = 'CompBrowserWin',
  33.         TargetID = 'CompBrowserWin',
  34.         WindowTitle = 'Comp Browser',
  35.         Geometry = {0, 100, width, height},
  36.         Spacing = 0,
  37.  
  38.         ui:VGroup{
  39.             ID = 'root',
  40.             ui:Tree{
  41.                 ID = 'Tree',
  42.                 SortingEnabled = true,
  43.                 Events = {
  44.                     ItemDoubleClicked = true,
  45.                     ItemClicked = true,
  46.                 },
  47.             },
  48.         },
  49.     })
  50.  
  51.     -- The window was closed
  52.     function win.On.CompBrowserWin.Close(ev)
  53.         disp:ExitLoop()
  54.     end
  55.  
  56.     -- Add your GUI element based event functions here:
  57.     itm = win:GetItems()
  58.  
  59.     -- Add a header row.
  60.     hdr = itm.Tree:NewItem()
  61.     hdr.Text[0] = 'Comp Name'
  62.     hdr.Text[1] = 'Media Nodes'
  63.     hdr.Text[2] = 'Global Range'
  64.     hdr.Text[3] = 'Render Range'
  65.     hdr.Text[4] = 'Format Name'
  66.     hdr.Text[5] = 'Frame Size'
  67.     hdr.Text[6] = 'Frame Rate'
  68.     hdr.Text[7] = 'HiQ'
  69.     hdr.Text[8] = 'Rendering'
  70.     hdr.Text[9] = 'Filepath'
  71.  
  72.     itm.Tree:SetHeaderItem(hdr)
  73.  
  74.     -- Number of columns in the Tree list
  75.     itm.Tree.ColumnCount = 10
  76.  
  77.     -- Resize the Columns
  78.     itm.Tree.ColumnWidth[0] = 320
  79.     itm.Tree.ColumnWidth[1] = 90
  80.     itm.Tree.ColumnWidth[2] = 90
  81.     itm.Tree.ColumnWidth[3] = 90
  82.     itm.Tree.ColumnWidth[4] = 182
  83.     itm.Tree.ColumnWidth[5] = 100
  84.     itm.Tree.ColumnWidth[6] = 70
  85.     itm.Tree.ColumnWidth[7] = 50
  86.     itm.Tree.ColumnWidth[8] = 65
  87.     itm.Tree.ColumnWidth[9] = 600
  88.  
  89.     -- Change the sorting order of the tree
  90.     itm.Tree:SortByColumn(0, "AscendingOrder")
  91.  
  92.     -- Create a table based upon the open Fusion composites
  93.     local compList = fu:GetCompList()
  94.     for row = 1, table.getn(compList) do
  95.         -- Set cmp to the pointer of the current composite
  96.         cmp = compList[row]
  97.  
  98.         -- Add a new row entry to the list
  99.         itRow = itm.Tree:NewItem();
  100.    
  101.         -- Add an image resource to the cell
  102.         -- Make sure this is excluded from Fusion 9 since the Icon support in a tree view was added in v16.
  103.         if fu:GetVersion() and fu:GetVersion()[1] and fu:GetVersion()[1] >= 16 then
  104.             itRow.Icon[0] = ui:Icon{File = 'Scripts:/Comp/UI Manager/fusion-logo.png'}
  105.         end
  106.        
  107.         -- The Composite Tab name (comp base filename)
  108.         itRow.Text[0] = string.format('%s', tostring(cmp:GetAttrs()['COMPS_Name']))
  109.    
  110.         -- Node count
  111.         -- Should the selected nodes be listed? (Otherwise all loader/saver nodes will be listed from the comp)
  112.         --listOnlySelectedNodes = true
  113.         listOnlySelectedNodes = false
  114.  
  115.         local toollist1 = cmp:GetToolList(listOnlySelectedNodes, 'Loader')
  116.         local toollist2 = cmp:GetToolList(listOnlySelectedNodes, 'Saver')
  117.         local toollist3 = cmp:GetToolList(listOnlySelectedNodes, 'SurfaceFBXMesh')
  118.         local toollist4 = cmp:GetToolList(listOnlySelectedNodes, 'SurfaceAlembicMesh')
  119.  
  120.         -- Scan the comp to check how many media nodes are present
  121.         local totalLoaders = table.getn(toollist1)
  122.         local totalSavers = table.getn(toollist2)
  123.         local totalFBX = table.getn(toollist3)
  124.         local totalAlembic = table.getn(toollist4)
  125.    
  126.         -- Add up how many media nodes are present
  127.         local totalNodes = totalLoaders + totalSavers + totalFBX + totalAlembic
  128.         itRow.Text[1] = tostring(totalNodes)
  129.  
  130.         -- Timeline Frame Range
  131.         itRow.Text[2] = tostring(cmp:GetAttrs().COMPN_GlobalStart) .. '-' .. tostring(cmp:GetAttrs().COMPN_GlobalEnd)
  132.         itRow.Text[3] = tostring(cmp:GetAttrs().COMPN_RenderStart) .. '-' .. tostring(cmp:GetAttrs().COMPN_RenderEnd)
  133.  
  134.         -- Read the comp frame format settings
  135.         local compPrefs = cmp:GetPrefs("Comp.FrameFormat")
  136.  
  137.         -- Format Name
  138.         itRow.Text[4] = tostring(compPrefs.Name)
  139.  
  140.         -- Frame Size
  141.         itRow.Text[5] = tostring(compPrefs.Width) .. 'x' .. tostring(compPrefs.Height) .. ' px'
  142.  
  143.         -- Frame Rate
  144.         itRow.Text[6] = tostring(compPrefs.Rate) .. ' fps'
  145.  
  146.         -- HiQ High Quality Mode
  147.         itRow.Text[7] = tostring(cmp:GetAttrs().COMPB_HiQ)
  148.  
  149.         -- Render Status
  150.         itRow.Text[8] = tostring(cmp:GetAttrs().COMPB_Rendering)
  151.  
  152.         -- The Composite absolute filename
  153.         local filepath = cmp:MapPath(cmp:GetAttrs()['COMPS_FileName'])
  154.         if filepath == '' or not filepath then
  155.             filepath = '<Unsaved>'
  156.         end
  157.         itRow.Text[9] = tostring(filepath)
  158.  
  159.  
  160.         itm.Tree:AddTopLevelItem(itRow)
  161.     end
  162.  
  163.     -- A Tree view row was clicked on
  164.     function win.On.Tree.ItemClicked(ev)
  165.         print('[Single Clicked] ' .. tostring(ev.item.Text[9]))
  166.     end
  167.  
  168.     -- A Tree view row was double clicked on
  169.     function win.On.Tree.ItemDoubleClicked(ev)
  170.         -- Grab the absolute comp filepath
  171.         local compPath = dirname(tostring(ev.item.Text[9] or ''))
  172.         print('[Double Clicked] ' .. tostring(compPath))
  173.  
  174.         -- Open the comp file's parent folder in a desktop folder browsing window
  175.         if bmd.direxists(compPath) == true then
  176.             bmd.openfileexternal('Open', compPath)
  177.         end
  178.     end
  179.  
  180.     -- The app:AddConfig() command will capture the "Control + W" or "Control + F4" hotkeys so they will close the window instead of closing the foreground composite.
  181.     app:AddConfig("CompBrowserWin", {
  182.         Target
  183.         {
  184.             ID = "CompBrowserWin",
  185.         },
  186.  
  187.         Hotkeys
  188.         {
  189.             Target = "CompBrowserWin",
  190.             Defaults = true,
  191.  
  192.             CONTROL_W = "Execute{ cmd = [[ app.UIManager:QueueEvent(obj, 'Close', {}) ]] }",
  193.             CONTROL_F4 = "Execute{ cmd = [[ app.UIManager:QueueEvent(obj, 'Close', {}) ]] }",
  194.         },
  195.     })
  196.  
  197.     win:Show()
  198.     disp:RunLoop()
  199.     win:Hide()
  200. end
  201.  
  202.  
  203. -- Find out the current operating system platform. The platform local variable should be set to either "Windows", "Mac", or "Linux".
  204. local platform = (FuPLATFORM_WINDOWS and 'Windows') or (FuPLATFORM_MAC and 'Mac') or (FuPLATFORM_LINUX and 'Linux')
  205.  
  206. -- Add the platform specific folder slash character
  207. osSeparator = package.config:sub(1,1)
  208.  
  209. -- Show the ui:Tree View
  210. CompBrowser()
  211.  
  212. -- End of the script
  213. print('[Done]')
  214.  

As a quick summary, the ui:Icon resource was added to the ui:Tree item using the following snippet of code:

(The Fusion version check ensures that Fusion 16+ was found to avoid causing errors when the code is run in either Fusion 9, or Resolve 15.)

Code: Select all

		-- Add an image resource to the cell
		-- Make sure this is excluded from Fusion 9 since the Icon support in a tree view was added in v16.
		if fu:GetVersion() and fu:GetVersion()[1] and fu:GetVersion()[1] >= 16 then
			itRow.Icon[0] = ui:Icon{File = 'Scripts:/Comp/UI Manager/fusion-logo.png'}
		end
You do not have the required permissions to view the files attached to this post.

User avatar
AndrewHazelden
Fusionator
Posts: 1508
Joined: Fri Apr 03, 2015 3:20 pm
Answers: 6
Location: West Dover, Nova Scotia, Canada
Been thanked: 85 times
Contact:

Running Python Code in an Event

#188

Post by AndrewHazelden » Fri Sep 20, 2019 8:16 am

@bryanfordney recently asked if Python scripting was an option for events and callbacks. A sharp-eyed fact-checker reminded me this morning that I should always double-check things... Ahh, the things you learn. :)

Here are several approaches to create Events in Fusion that will allow you to run your own Python code when the Event is triggered. This can be handy if you are a TD that feels the need to write your Fusion based .fu code in Python.

Update your UI Manager Examples Atom Package

Reactor Atom Update.png

If you have Reactor installed, and update your "UI Manager Lua & Python Examples" atom package to version 2, you will find new Event examples in the Reactor:/Deploy/Config/UI Manager/ folder named EventPythonNative.fu.zip, EventPythonRunScript.zip, and EventPythonExecute.fu.zip.

To use one of the Python Event examples, you simply need to unzip one of these files in-place, inside the Config folder, and then restart Fusion. When you select nodes in the Node view you will see a message printed in the Console window:

Events Example.png

EventPythonNative Example

This example shows a Python native way to execute code inside an Event. No Lua code is involved. This is done with a .fu file-based Event{} entry that intercepts the "Comp_Activate_Tool" action by appending our own Python code snippet that is specified with the tag Language = "Python2",.

EventPythonNative.png

EventPythonRunScript Example

The EventPythonRunScript.zip example provides a .fu file and a .py script. It shows a way to execute an external Python script inside an Event that was created using Lua. This is done with a .fu file based Event{} entry that intercepts the native "Comp_Activate_Tool" action that will run our Python script via "comp:RunScript()".

When you select a node in the Nodes view, the active tool's name is printed in the Console window via a Python script named PythonRunScript.py. The Python script is able to access the "comp" object and its parameters.

EventPythonRunScript.png

EventPythonExecute Example

The EventPythonExecute.fu.zip example provides a .fu file that shows a way to execute a block of Python code inside an Event that was created using Lua. This is done with a .fu file-based Event{} entry that intercepts the native "Comp_Activate_Tool" action by appending our own custom Python code snippet that runs via comp:Execute().

This approach could be handy if you have existing Lua code in other parts of your .fu file and you want to add a little bit of Python code to one specific Event.

By adding "!Py:" to the start of the string passed to comp:Execute() it tells the interpreter to process the code using the default built-in Python interpreter that is found on your system.

You can specify if you want to have the Python code run via Python 2 using "!Py2:", or via Python 3 using "!Py3:" on the "cmp:Execute()" line of the code below.

When you select a node in the Nodes view, the active tool's name is printed in the Console window via an inline Python code chunk. The Python code is able to access the "comp" object and its parameters.

EventPythonExecute.png
You do not have the required permissions to view the files attached to this post.
Last edited by AndrewHazelden on Sat Sep 21, 2019 5:22 am, edited 3 times in total.

User avatar
AndrewHazelden
Fusionator
Posts: 1508
Joined: Fri Apr 03, 2015 3:20 pm
Answers: 6
Location: West Dover, Nova Scotia, Canada
Been thanked: 85 times
Contact:

.fu Based Contextual Menus - Python Print Attributes

#189

Post by AndrewHazelden » Fri Sep 20, 2019 10:27 pm

This Menu/Action example adds right-click based contextual menu entries named "Fusion Attributes", "Comp Attributes", and "Tool Attributes" to the Nodes view area. This is implemented using Python scripting in the .fu file's Action entries.

Contextual Menu Screenshots

Right click Closeup.png
Contextual Menu Entries.png

Menu Item Outputs

When you select a node in the Nodes view and right-click, the new "Tool Attributes" contextual menu entry allows you to see details like the active Node's name, the Tool's RegistryID, and more in the Fusion Console view:

Code: Select all

'[Tool Attributes]'
{'TOOLB_CacheToDisk': False,
 'TOOLB_CtrlWZoom': False,
 'TOOLB_HoldOutput': False,
 'TOOLB_Locked': False,
 'TOOLB_NameSet': False,
 'TOOLB_PassThrough': False,
 'TOOLB_Selected': True,
 'TOOLB_ShowControls': True,
 'TOOLB_Visible': True,
 'TOOLI_ID': 41.0,
 'TOOLI_Number_o_Inputs': 1.0,
 'TOOLNT_EnabledRegion_End': {1.0: 1000000000.0},
 'TOOLNT_EnabledRegion_Start': {1.0: -1000000000.0},
 'TOOLNT_Region_End': {1.0: 999999999.9999},
 'TOOLNT_Region_Start': {1.0: 0.0},
 'TOOLN_LastFrameTime': 0.0,
 'TOOLS_Name': 'Equirectangular2Fisheye',
 'TOOLS_RegID': 'GroupOperator'}

The new "Comp Attributes" contextual menu prints out the composition object's details:

Code: Select all

'[Comp Attributes]'
{'COMPB_HiQ': True,
 'COMPB_Locked': False,
 'COMPB_LoopPlay': True,
 'COMPB_Modified': True,
 'COMPB_MotionBlur': True,
 'COMPB_Proxy': False,
 'COMPB_Rendering': False,
 'COMPH_ActiveTool': <PyRemoteObject object at 0x5a8f71f8>,
 'COMPI_RenderFlags': 131072.0,
 'COMPI_RenderStep': 1.0,
 'COMPN_AudioOffset': 0.0,
 'COMPN_AverageFrameTime': 0.0,
 'COMPN_CurrentTime': 0.0,
 'COMPN_ElapsedTime': 0.0,
 'COMPN_GlobalEnd': 1000.0,
 'COMPN_GlobalStart': 0.0,
 'COMPN_LastFrameRendered': -2000000000.0,
 'COMPN_LastFrameTime': 0.0,
 'COMPN_RenderEnd': 1000.0,
 'COMPN_RenderEndTime': 1000.0,
 'COMPN_RenderStart': 0.0,
 'COMPN_RenderStartTime': 0.0,
 'COMPN_TimeRemaining': 0.0,
 'COMPS_FileName': '/Users/andrew/Desktop/Composition1.comp',
 'COMPS_LoopMode': 'loop',
 'COMPS_Name': 'Composition1.comp'}

And the new "Fusion Attributes" contextual menu prints out the fusion/fu/app object details:

Code: Select all

'[Fusion Attributes]'
{'FUSIONB_IsManager': False,
 'FUSIONB_IsRenderNode': False,
 'FUSIONB_IsResolve': False,
 'FUSIONH_CurrentComp': <PyRemoteObject object at 0x5a8f7210>,
 'FUSIONI_NumProcessors': 8.0,
 'FUSIONI_PhysicalRAMFreeMB': 10256.0,
 'FUSIONI_PhysicalRAMTotalMB': 16384.0,
 'FUSIONI_SerialHi': 'Redacted-by-Andrew',
 'FUSIONI_SerialLo': 0.0,
 'FUSIONI_VersionHi': 1048577.0,
 'FUSIONI_VersionLo': 7.0,
 'FUSIONI_VirtualRAMTotalMB': 16384.0,
 'FUSIONI_VirtualRAMUsedMB': 6127.0,
 'FUSIONS_FileName': '/Applications/Blackmagic Fusion 16/Fusion.app/Contents/MacOS/Fusion',
 'FUSIONS_GLDevice': 'AMD Radeon R9 M370X OpenGL Engine',
 'FUSIONS_GLVendor': 'ATI Technologies Inc.',
 'FUSIONS_GLVersion': '2.1 ATI-1.68.23',
 'FUSIONS_MachineType': 'IA32',
 'FUSIONS_Version': '16.1'}

Download the .fu File

The ContextualMenuPythonPrintAttributes.fu file goes in your Config:/ PathMap folder.

If you've already got the UI Manager Examples atom package installed in Reactor you can update the package to the latest version, and you will find a zipped copy of this .fu file in your Reactor:/Deploy/Config/UI Manager/ Folder.
Code: [Select all] [Expand/Collapse] [Download] (ContextualMenuPythonPrintAttributes.fu)
  1. --[[--
  2. Contextual Menu - Python Print Attributes - 2019-09-21
  3. by Andrew Hazelden <andrew@andrewhazelden.com>
  4. www.andrewhazelden.com
  5.  
  6. This Menu/Action adds right-click based contextual menu entries named "Fusion Attributes", "Comp Attributes", and "Tool Attributes" to the Nodes view area. This is implemented using Python scripting in the .fu file's Action entries.
  7.  
  8. When you select a node in the Nodes view and right-click, the "Tool Attributes" contextual menu entry allows you to see details like the active Node's name, the Tool's RegistryID, and more.
  9.  
  10. -------------------------------------------------
  11.  
  12. The default Target value of "FlowView" is used to add your menu entry to the Nodes view area.
  13.  
  14. If you want to change the target zone where the Menu entries are added you can edit the line:
  15. Target = "FlowView",
  16.  
  17. And then change the Target to another value like the "Tools_RegID" value of an individual node/fuse/MacroOperator/GroupOperator so your contextual menu entry appears in the Inspector view when only that node type is selected. This can be done by entering a value such as "Camera3D" if you want your contextual menu to show up when a Camera3D node is active in the Inspector window.
  18.  
  19. If you wanted the contextual menu to show up in a specific view like the Fusion 3D viewer window area, a Target value of "GL3DViewer" will push the menu into the Fusion 3D workspace view's right-clickable contextual menu. (This Target is separate from the 2D image viewer area.)
  20.  
  21. A Target value of "Composition" will add your menu entry to the individual "Composite" tabs that list each of the open Comp names in Fusion. The Compositon tab is the horizontal bar of tabs located  that you can right-click on. It's positioned just under the Fusion main menu bar area. (There is a slight contextual menu rendering bug in Fusion 16 that is visible when using this target. You will see your new menu entries are added twice to the list.)
  22.  
  23. -------------------------------------------------
  24.  
  25. The Lua based code chunk below will list all of the active Target IDs you can possibly choose from in Fusion: (Not all of them are valid for use as contextual menu locations since it is an unfiltered raw dump from the Fusion registry)
  26.  
  27. -- Scan Target IDs
  28. targetIDList = fu.ActionManager:GetTargets()
  29.  
  30. -- Count the total number of targetIDs
  31. targetCount = 0
  32. for i, target in ipairs(targetIDList) do
  33.     print(target.ID)
  34.     targetCount = targetCount + 1
  35. end
  36. print('[' .. targetCount .. ' Target IDs Found]')
  37.  
  38. --]]--
  39. {
  40.   Language = "Python2",
  41.  
  42.   Action{
  43.     ID = "Print_Fusion_Attributes",
  44.     Category = "Utilities",
  45.     Name = "Fusion Attributes",
  46.  
  47.     Targets = {
  48.       Composition = {
  49.         Execute = _Python [=[
  50. from pprint import pprint
  51.  
  52. # Print the current Fusion program attributes
  53. pprint("[Fusion Attributes]")
  54. pprint(fu.GetAttrs())
  55. print("\n")
  56.         ]=],
  57.       },
  58.     },
  59.   },
  60.  
  61.   Action{
  62.     ID = "Print_Comp_Attributes",
  63.     Category = "Utilities",
  64.     Name = "Comp Attributes",
  65.  
  66.     Targets = {
  67.       Composition = {
  68.         Execute = _Python [=[
  69. from pprint import pprint
  70.  
  71. # Get the composition object
  72. # comp = obj.Comp()
  73.  
  74. # Get the composition object (alternative)
  75. comp = app.GetAttrs()["FUSIONH_CurrentComp"]
  76.  
  77. # Print the current composite attributes
  78. pprint("[Comp Attributes]")
  79. pprint(comp.GetAttrs())
  80. print("\n")
  81.         ]=],
  82.       },
  83.     },
  84.   },
  85.  
  86.   Action{
  87.     ID = "Print_Tool_Attributes",
  88.     Category = "Utilities",
  89.     Name = "Tool Attributes",
  90.  
  91.     Targets = {
  92.       Composition = {
  93.         Execute = _Python [=[
  94. from pprint import pprint
  95.  
  96. # Get the composition object
  97. # comp = obj.Comp()
  98.  
  99. # Get the composition object (alternative)
  100. comp = app.GetAttrs()["FUSIONH_CurrentComp"]
  101.  
  102. # Get the active node selection
  103. selection = 'None' if comp.ActiveTool is None else comp.ActiveTool.GetAttrs()
  104.  
  105. # Print the current tool attributes
  106. pprint("[Tool Attributes]")
  107. pprint(selection)
  108. print("\n")
  109.         ]=],
  110.       },
  111.     },
  112.   },
  113.  
  114.   Menus{
  115.     -- Add the menu entries to the Node view's right-click based contextual menus.
  116.     Target = "FlowView",
  117.    
  118.     -- Add the menu entries to the Fusion's 3D view's right-click based contextual menus.
  119.     -- Target = "GL3DViewer",
  120.    
  121.     -- Add the menu entries to the Composition tabs's right-click based contextual menus.
  122.     -- Note: The entries will be listed twice in this Target due to a Fusion 16 bug.
  123.     -- Target = "Composition",
  124.  
  125.     Append{
  126.       "_",
  127.       "Print_Fusion_Attributes{}",
  128.       "Print_Comp_Attributes{}",
  129.       "Print_Tool_Attributes{}",
  130.     },
  131.   },
  132. }
  133.  

Menu Targets

The default Target value of "FlowView" is used to add your menu entry to the Nodes view area. If you want to change the target zone where the Menu entries are added you can edit the line:
Target = "FlowView",


And then change the Target to another value like the "Tools_RegID" value of an individual node/fuse/MacroOperator/GroupOperator so your contextual menu entry appears in the Inspector view when only that node type is selected. This can be done by entering a value such as "Camera3D" if you want your contextual menu to show up when a Camera3D node is active in the Inspector window.

Camera3D Contextual Menu.png

If you wanted the contextual menu to show up in a specific view like the Fusion 3D viewer window area, a Target value of "GL3DViewer" will push the menu into the Fusion 3D workspace view's right-clickable contextual menu. (This Target is separate from the 2D image viewer area.)

GL3DViewer Target.png

A Target value of "Composition" will add your menu entry to the individual "Composite" tabs that list each of the open Comp names in Fusion. The Compositon tab is the horizontal bar of tabs located that you can right-click on. It's positioned just under the Fusion main menu bar area. (There is a slight contextual menu rendering bug in Fusion 16 that is visible when using this target. You will see your new menu entries are added twice to the list.)

Composition Target.png

Scanning for Menu Target IDs

The Lua based code chunk below will list all of the active Target IDs you can possibly choose from in Fusion:
(Not all of them are valid for use as contextual menu locations since it is an unfiltered raw dump from the Fusion registry)
Code: [Select all] [Expand/Collapse] [Download] (ScanTargetIDs.lua)
  1. -- Scan Target IDs
  2. targetIDList = fu.ActionManager:GetTargets()
  3.  
  4. -- Count the total number of targetIDs
  5. targetCount = 0
  6. for i, target in ipairs(targetIDList) do
  7.     print(target.ID)
  8.     targetCount = targetCount + 1
  9. end
  10. print('[' .. targetCount .. ' Target IDs Found]')
You do not have the required permissions to view the files attached to this post.

User avatar
AndrewHazelden
Fusionator
Posts: 1508
Joined: Fri Apr 03, 2015 3:20 pm
Answers: 6
Location: West Dover, Nova Scotia, Canada
Been thanked: 85 times
Contact:

Common Variables Found in a .fu Event Execute Scope

#190

Post by AndrewHazelden » Sat Sep 21, 2019 7:00 am

This post has a Python based example that shows the common variables like args that are present in to your .fu files' Action/Event Execute entries.

If your Event was run in the scope of "Composition", which is what the Nodes view in Fusion is called, the args variable would return a Python dict with information about the active tool like:

Code: Select all

{'tool': <PyRemoteObject object at 0x60aad1c8>}
or args might return a dict with both the active tool, and the previously active tool listed:

Code: Select all

{'prev': <PyRemoteObject object at 0x626551f8>,
'tool': <PyRemoteObject object at 0x626551e0>}

Download the .fu File

Code: [Select all] [Expand/Collapse] [Download] (EventPythonPrintArgs.fu)
  1. --[[--
  2. Printing Python Args in an Event - 2019-09-21
  3. by Andrew Hazelden <andrew@andrewhazelden.com>
  4. www.andrewhazelden.com
  5.  
  6. Use Python to list the common variables that are found in an Event's "Execute" scope when you select a node in the Nodes view in Fusion.
  7.  
  8. The Console window output looks like:
  9.  
  10. ---------------------------------
  11.  
  12. '[self Default]'
  13.  
  14.  
  15. '[rets]'
  16. {}
  17.  
  18.  
  19. '[ctx Attributes]'
  20. <PyRemoteObject object at 0x5880f1b0>
  21.  
  22.  
  23. '[args Attributes]'
  24. {'prev': <PyRemoteObject object at 0x5880f258>,
  25.  'tool': <PyRemoteObject object at 0x5880f240>}
  26.  
  27.  
  28. '[args.tool Attributes]'
  29. {'TOOLBT_AltClip_IsMultiFrame': {1.0: False},
  30.  'TOOLBT_Clip_IsMultiFrame': {1.0: False},
  31.  'TOOLBT_Clip_IsPreviewSaver': {1.0: False},
  32.  'TOOLBT_Clip_Loop': {1.0: False},
  33.  'TOOLBT_Clip_Reverse': {1.0: False},
  34.  'TOOLBT_Clip_Saving': {1.0: False},
  35.  'TOOLB_CacheToDisk': False,
  36.  'TOOLB_CtrlWZoom': True,
  37.  'TOOLB_HoldOutput': False,
  38.  'TOOLB_Locked': False,
  39.  'TOOLB_NameSet': False,
  40.  'TOOLB_PassThrough': False,
  41.  'TOOLB_Selected': True,
  42.  'TOOLB_ShowControls': False,
  43.  'TOOLB_Visible': True,
  44.  'TOOLIT_AltClip_Height': {1.0: 0.0},
  45.  'TOOLIT_AltClip_Length': {1.0: 1.0},
  46.  'TOOLIT_AltClip_StartFrame': {1.0: 4294967295.0},
  47.  'TOOLIT_AltClip_Width': {1.0: 0.0},
  48.  'TOOLIT_Clip_AspectMode': {1.0: 0.0},
  49.  'TOOLIT_Clip_ExtendFirst': {1.0: 0.0},
  50.  'TOOLIT_Clip_ExtendLast': {1.0: 0.0},
  51.  'TOOLIT_Clip_Height': {1.0: 1920.0},
  52.  'TOOLIT_Clip_ImportMode': {1.0: 0.0},
  53.  'TOOLIT_Clip_InitialFrame': {1.0: 4294967295.0},
  54.  'TOOLIT_Clip_Length': {1.0: 1.0},
  55.  'TOOLIT_Clip_PullOffset': {1.0: 0.0},
  56.  'TOOLIT_Clip_StartFrame': {1.0: 4294967295.0},
  57.  'TOOLIT_Clip_TimeCode': {1.0: 0.0},
  58.  'TOOLIT_Clip_TrimIn': {1.0: 0.0},
  59.  'TOOLIT_Clip_TrimOut': {1.0: 0.0},
  60.  'TOOLIT_Clip_Width': {1.0: 3840.0},
  61.  'TOOLI_ID': 1.0,
  62.  'TOOLI_ImageDepth': 5.0,
  63.  'TOOLI_ImageField': -1.0,
  64.  'TOOLI_ImageHeight': 1920.0,
  65.  'TOOLI_ImageWidth': 3840.0,
  66.  'TOOLI_Number_o_Inputs': 0.0,
  67.  'TOOLNT_Clip_End': {1.0: 0.0},
  68.  'TOOLNT_Clip_Start': {1.0: 0.0},
  69.  'TOOLNT_EnabledRegion_End': {1.0: 1000000000.0},
  70.  'TOOLNT_EnabledRegion_Start': {1.0: -1000000000.0},
  71.  'TOOLNT_Region_End': {1.0: 999999999.9999},
  72.  'TOOLNT_Region_Start': {1.0: 0.0},
  73.  'TOOLN_ImageAspectX': 1.0,
  74.  'TOOLN_ImageAspectY': 1.0,
  75.  'TOOLN_LastFrameTime': 0.07738699999999987,
  76.  'TOOLST_AltClip_FormatID': {},
  77.  'TOOLST_AltClip_FormatName': {},
  78.  'TOOLST_AltClip_Name': {1.0: ''},
  79.  'TOOLST_Clip_FormatID': {1.0: 'JpegFormat'},
  80.  'TOOLST_Clip_FormatName': {1.0: 'JpegFormat'},
  81.  'TOOLST_Clip_KeyCode': {1.0: ''},
  82.  'TOOLST_Clip_Name': {1.0: 'Reactor:/Deploy/Macros/KartaVR/Images/latlong_wide_ar.jpg'},
  83.  'TOOLS_Name': 'Loader1',
  84.  'TOOLS_RegID': 'Loader'}
  85.  
  86.  
  87. '[args.prev Attributes]'
  88. {'TOOLB_CacheToDisk': False,
  89.  'TOOLB_CtrlWZoom': False,
  90.  'TOOLB_HoldOutput': False,
  91.  'TOOLB_Locked': False,
  92.  'TOOLB_NameSet': False,
  93.  'TOOLB_PassThrough': False,
  94.  'TOOLB_Selected': True,
  95.  'TOOLB_ShowControls': True,
  96.  'TOOLB_Visible': True,
  97.  'TOOLI_ID': 2.0,
  98.  'TOOLI_Number_o_Inputs': 1.0,
  99.  'TOOLNT_EnabledRegion_End': {1.0: 1000000000.0},
  100.  'TOOLNT_EnabledRegion_Start': {1.0: -1000000000.0},
  101.  'TOOLNT_Region_End': {1.0: 999999999.9999},
  102.  'TOOLNT_Region_Start': {1.0: 0.0},
  103.  'TOOLN_LastFrameTime': 0.0,
  104.  'TOOLS_Name': 'Equirectangular2Fisheye',
  105.  'TOOLS_RegID': 'GroupOperator'}
  106.  
  107.  
  108. ---------------------------------
  109.  
  110. --]]--
  111. {
  112.         Language = "Python2",
  113.      
  114.         Event {
  115.                 -- Add a new event that intercepts the Action
  116.                 Action = "Comp_Activate_Tool",
  117.                 Targets = {
  118.                         Composition = {
  119.                                 Execute = _Python [=[
  120. from pprint import pprint
  121.  
  122. pprint("[self Default]")
  123. rets = self.Default(ctx, args)
  124. print("\n")
  125.  
  126.  
  127. pprint("[rets]")
  128. pprint(rets)
  129. print("\n")
  130.  
  131.  
  132. pprint("[ctx Attributes]")
  133. pprint(ctx)
  134. print("\n")
  135.  
  136.  
  137. pprint("[args Attributes]")
  138. pprint(args)
  139. print("\n")
  140.  
  141.  
  142. pprint("[args.tool Attributes]")
  143. if "tool" in args:
  144.         tool = args["tool"].GetAttrs()
  145. else:
  146.         tool = "None"
  147.  
  148. pprint(tool)
  149. print("\n")
  150.  
  151.  
  152. pprint("[args.prev Attributes]")
  153. if "prev" in args:
  154.         prev = args["prev"].GetAttrs()
  155. else:
  156.         prev = "None"
  157.  
  158. pprint(prev)
  159. print("\n")
  160.  
  161. print("---------------------------------\n")
  162. ]=],
  163.                         },
  164.                 },
  165.         },
  166. }
  167.  

Example Console Output

Code: Select all

---------------------------------
 
'[self Default]'
 
 
'[rets]'
{}
 
 
'[ctx Attributes]'
<PyRemoteObject object at 0x5880f1b0>
 
 
'[args Attributes]'
{'prev': <PyRemoteObject object at 0x5880f258>,
 'tool': <PyRemoteObject object at 0x5880f240>}
 
 
'[args.tool Attributes]'
{'TOOLBT_AltClip_IsMultiFrame': {1.0: False},
 'TOOLBT_Clip_IsMultiFrame': {1.0: False},
 'TOOLBT_Clip_IsPreviewSaver': {1.0: False},
 'TOOLBT_Clip_Loop': {1.0: False},
 'TOOLBT_Clip_Reverse': {1.0: False},
 'TOOLBT_Clip_Saving': {1.0: False},
 'TOOLB_CacheToDisk': False,
 'TOOLB_CtrlWZoom': True,
 'TOOLB_HoldOutput': False,
 'TOOLB_Locked': False,
 'TOOLB_NameSet': False,
 'TOOLB_PassThrough': False,
 'TOOLB_Selected': True,
 'TOOLB_ShowControls': False,
 'TOOLB_Visible': True,
 'TOOLIT_AltClip_Height': {1.0: 0.0},
 'TOOLIT_AltClip_Length': {1.0: 1.0},
 'TOOLIT_AltClip_StartFrame': {1.0: 4294967295.0},
 'TOOLIT_AltClip_Width': {1.0: 0.0},
 'TOOLIT_Clip_AspectMode': {1.0: 0.0},
 'TOOLIT_Clip_ExtendFirst': {1.0: 0.0},
 'TOOLIT_Clip_ExtendLast': {1.0: 0.0},
 'TOOLIT_Clip_Height': {1.0: 1920.0},
 'TOOLIT_Clip_ImportMode': {1.0: 0.0},
 'TOOLIT_Clip_InitialFrame': {1.0: 4294967295.0},
 'TOOLIT_Clip_Length': {1.0: 1.0},
 'TOOLIT_Clip_PullOffset': {1.0: 0.0},
 'TOOLIT_Clip_StartFrame': {1.0: 4294967295.0},
 'TOOLIT_Clip_TimeCode': {1.0: 0.0},
 'TOOLIT_Clip_TrimIn': {1.0: 0.0},
 'TOOLIT_Clip_TrimOut': {1.0: 0.0},
 'TOOLIT_Clip_Width': {1.0: 3840.0},
 'TOOLI_ID': 1.0,
 'TOOLI_ImageDepth': 5.0,
 'TOOLI_ImageField': -1.0,
 'TOOLI_ImageHeight': 1920.0,
 'TOOLI_ImageWidth': 3840.0,
 'TOOLI_Number_o_Inputs': 0.0,
 'TOOLNT_Clip_End': {1.0: 0.0},
 'TOOLNT_Clip_Start': {1.0: 0.0},
 'TOOLNT_EnabledRegion_End': {1.0: 1000000000.0},
 'TOOLNT_EnabledRegion_Start': {1.0: -1000000000.0},
 'TOOLNT_Region_End': {1.0: 999999999.9999},
 'TOOLNT_Region_Start': {1.0: 0.0},
 'TOOLN_ImageAspectX': 1.0,
 'TOOLN_ImageAspectY': 1.0,
 'TOOLN_LastFrameTime': 0.07738699999999987,
 'TOOLST_AltClip_FormatID': {},
 'TOOLST_AltClip_FormatName': {},
 'TOOLST_AltClip_Name': {1.0: ''},
 'TOOLST_Clip_FormatID': {1.0: 'JpegFormat'},
 'TOOLST_Clip_FormatName': {1.0: 'JpegFormat'},
 'TOOLST_Clip_KeyCode': {1.0: ''},
 'TOOLST_Clip_Name': {1.0: 'Reactor:/Deploy/Macros/KartaVR/Images/latlong_wide_ar.jpg'},
 'TOOLS_Name': 'Loader1',
 'TOOLS_RegID': 'Loader'}

'[args.prev Attributes]'
{'TOOLB_CacheToDisk': False,
 'TOOLB_CtrlWZoom': False,
 'TOOLB_HoldOutput': False,
 'TOOLB_Locked': False,
 'TOOLB_NameSet': False,
 'TOOLB_PassThrough': False,
 'TOOLB_Selected': True,
 'TOOLB_ShowControls': True,
 'TOOLB_Visible': True,
 'TOOLI_ID': 2.0,
 'TOOLI_Number_o_Inputs': 1.0,
 'TOOLNT_EnabledRegion_End': {1.0: 1000000000.0},
 'TOOLNT_EnabledRegion_Start': {1.0: -1000000000.0},
 'TOOLNT_Region_End': {1.0: 999999999.9999},
 'TOOLNT_Region_Start': {1.0: 0.0},
 'TOOLN_LastFrameTime': 0.0,
 'TOOLS_Name': 'Equirectangular2Fisheye',
 'TOOLS_RegID': 'GroupOperator'}

---------------------------------

User avatar
AndrewHazelden
Fusionator
Posts: 1508
Joined: Fri Apr 03, 2015 3:20 pm
Answers: 6
Location: West Dover, Nova Scotia, Canada
Been thanked: 85 times
Contact:

Action Listener v2 Released

#191

Post by AndrewHazelden » Tue Oct 01, 2019 5:30 am

What's new in V2?

Version 2 of Action listener now tracks "Fusion" scope actions, in addition to the previous "comp" scope actions. This means creating a new comps, saving comps, and other tasks are captured more accurately now. Also, "comp:DoAction() is used for translating generic actions.

The difference in the quality of the recorded action results is like night and day. :)

If you have Action Listener installed via Reactor, now is the time to go back and update the "UI Manager Lua & Python Examples" atom package in the "Scripts/Comp" category.

User avatar
AndrewHazelden
Fusionator
Posts: 1508
Joined: Fri Apr 03, 2015 3:20 pm
Answers: 6
Location: West Dover, Nova Scotia, Canada
Been thanked: 85 times
Contact:

Building GUIs With Fusion's UI Manager V3 Atom Package Update

#192

Post by AndrewHazelden » Sat Nov 02, 2019 3:30 pm

A new v3 update to the "UI Manager Lua & Python Examples" atom package is available in Reactor. The new changes have been synced with the Reactor GitLab repository this morning so it is available for immediate download. When you update your existing copy of the atom package in Reactor you will have access to all the new improvements in mere seconds. :)




What's new?

This update includes revisions to literally all the Lua and Python "Comp" scripts that adds better formatting for the scripts and nice QOL (quality of life) refinements like Control + W/F4 window close hotkey handling where required, and Lua garbage collection when the more complex scripts exit.

Also, this update improves the support for Resolve v16.1.1 and Fusion Standalone v16.1.1 so you won't get Console errors when the Lua scripts are run in a freshly installed copy of Resolve or Fusion. This is kind of important as Resolve now includes an automatic update checker when the program starts so a lot of people will be installing Resolve v16.1.1 over the next few weeks.

User avatar
AndrewHazelden
Fusionator
Posts: 1508
Joined: Fri Apr 03, 2015 3:20 pm
Answers: 6
Location: West Dover, Nova Scotia, Canada
Been thanked: 85 times
Contact:

Adjusting Fusion/Resolve Views Layouts With Actions

#193

Post by AndrewHazelden » Mon Nov 18, 2019 7:11 pm

Action Listener Toggling Views.png
The latest version 2 update to the Action Listener.lua script in the "UI Manager Lua Examples" package in Reactor has the ability to vomit back an incredible amount of detail into the Fusion Console view if you enable the [x] "Print Action Log to Console" checkbox.

Here are a few Fusion Studio/Resolve v16.1 compatible Lua snippets that show how to individually toggle the visibility of the different view contexts. All this information was derived from the Action Listener v2 script's Console view output text which everyone has access to.


Hide or Show the Fusion 16 toolbar:

Code: Select all

comp:DoAction("Fusion_View_Show", {view = "ActionStrip", show = false}) -- Hide the "ActionStrip"
bmd.wait(3) -- Pause 3 seconds
comp:DoAction("Fusion_View_Show", {view = "ActionStrip", show = true}) -- show the "ActionStrip" 

Hide or Show the Console window:

Code: Select all

comp:DoAction("ACTION_SHOW_CONSOLE", {is_visible = false}) -- Hide the console window
bmd.wait(3) -- Pause 3 seconds
comp:DoAction("ACTION_SHOW_CONSOLE", {is_visible = true}) -- Show the console window

Hide or Show the Clips view:

Code: Select all

comp:DoAction("Fusion_View_Show", {view = "Clips", show = false}) -- Hide the "Clips" view in single monitor mode
bmd.wait(3) -- Pause 3 seconds
comp:DoAction("Fusion_View_Show", {view = "Clips", show = true}) -- Show the "Clips" view in single monitor mode

Hide or Show the Effects view:

Code: Select all

comp:DoAction("Fusion_View_Show", {view = "Effects", show = false}) -- Hide the "Effects" view
bmd.wait(3) -- Pause 3 seconds
comp:DoAction("Fusion_View_Show", {view = "Effects", show = true}) -- Show the "Effects" view

Hide or Show the Inspector view:

Code: Select all

comp:DoAction("Fusion_View_Show", {view = "Inspector", show = false}) -- Hide the "Inspector" view
bmd.wait(3) -- Pause 3 seconds
comp:DoAction("Fusion_View_Show", {view = "Inspector", show = hide}) -- Show the "Inspector" view

Hide or Show the Inspector view (Dual Screen Mode):

Code: Select all

comp:DoAction("Fusion_View_Show", {view = "Inspector", show = false, screen_mode = "DUAL_SCREEN"}) -- Hide the "Inspector" view
bmd.wait(3) -- Pause 3 seconds
comp:DoAction("Fusion_View_Show", {view = "Inspector", show = hide, screen_mode = "DUAL_SCREEN"}) -- Show the "Inspector" view

Hide or Show the Keyframes view:

Code: Select all

comp:DoAction("Fusion_View_Show", {view = "Keyframes", show = false}) -- Hide the "Keyframes" view
bmd.wait(3) -- Pause 3 seconds
comp:DoAction("Fusion_View_Show", {view = "Keyframes", show = true}) -- Show the "Keyframes" view

Hide or Show the (Resolve Fusion Page) MediaPool view:

Code: Select all

comp:DoAction("Fusion_View_Show", {view = "MediaPool", show = false}) -- Hide the "MediaPool" view
bmd.wait(3) -- Pause 3 seconds
comp:DoAction("Fusion_View_Show", {view = "MediaPool", show = true}) -- Show the "MediaPool" view

Hide or Show the Nodes view:

Code: Select all

comp:DoAction("Fusion_View_Show", {view = "Nodes", show = false}) -- Hide the "Nodes" view in single monitor mode
bmd.wait(3) -- Pause 3 seconds
comp:DoAction("Fusion_View_Show", {view = "Nodes", show = true}) -- Show the "Nodes" view in single monitor mode

Hide or Show the Spline view:

Code: Select all

comp:DoAction("Fusion_View_Show", {view = "Spline", show = false}) -- Hide the "Spline" view
bmd.wait(3) -- Pause 3 seconds
comp:DoAction("Fusion_View_Show", {view = "Spline", show = true}) -- Show the "Spline" view

Toggle the display of the Left and Right image viewers:

Code: Select all

comp:DoAction("Fusion_View_Show", {view = "Viewer1"}) -- Toggle the visibility of the Right view
comp:DoAction("Fusion_View_Show", {view = "Viewer2"}) -- Toggle the visibility of the Left viewer
bmd.wait(3) -- Pause 3 seconds
comp:DoAction("Fusion_View_Show", {view = "Viewer1"}) -- Toggle the visibility of the Right view
comp:DoAction("Fusion_View_Show", {view = "Viewer2"}) -- Toggle the visibility of the Left viewer

Hide and Show the Left and Right image viewers:

Code: Select all

comp:DoAction("Fusion_View_Show", {view = "Viewer1", show = false}) -- Hide the Right view
comp:DoAction("Fusion_View_Show", {view = "Viewer2", show = false}) -- Hide the Left viewer
bmd.wait(3) -- Pause 3 seconds
comp:DoAction("Fusion_View_Show", {view = "Viewer2", show = true}) -- Show the Left viewer
comp:DoAction("Fusion_View_Show", {view = "Viewer1", show = true}) -- Show the Right view

Adjust the height of the (Resolve Edit Page) left and right side panel areas to full height:

Code: Select all

comp:DoAction("Fusion_Zone_Expand", {zone = "AuxLeft", expand = false}) -- Show the left side panel at full height
bmd.wait(3) -- Pause 3 seconds
comp:DoAction("Fusion_Zone_Expand", {zone = "AuxRight", expand = false}) -- Show the right side panel at full height

Code: Select all

comp:DoAction("Fusion_Zone_Expand", {zone = "AuxLeft", expand = false, screen_mode = "DUAL_SCREEN"}) -- Show the 2nd monitor left side panel at full height
bmd.wait(3) -- Pause 3 seconds
comp:DoAction("Fusion_Zone_Expand", {zone = "AuxRight", expand = false, screen_mode = "DUAL_SCREEN"}) -- Show the 2nd monitor right side panel at full height

Adjust the height of the left and right zones areas:

Code: Select all

comp:DoAction("Fusion_Zone_Expand", {zone = "Left", expand = false}) -- Hide the left side panel at full height
bmd.wait(3) -- Pause 3 seconds
comp:DoAction("Fusion_Zone_Expand", {zone = "Left", expand = true}) -- Show the left side panel at full height

Code: Select all

comp:DoAction("Fusion_Zone_Expand", {zone = "Right", expand = false}) -- Hide the right side panel at full height
bmd.wait(3) -- Pause 3 seconds
comp:DoAction("Fusion_Zone_Expand", {zone = "Right", expand = true}) -- Show the right side panel at full height

Hide the Layout Strip (which is the top bar in the UI that has buttons labeled Effects, Nodes, Console, Spline, Keyframes, Inspector):

Code: Select all

comp:DoAction("Fusion_View_Show", {view = "LayoutStrip", show = false}) -- Hide the LayoutStrip
bmd.wait(3) -- Pause 3 seconds
comp:DoAction("Fusion_View_Show", {view = "LayoutStrip", show = true}) -- Show the LayoutStrip

Hide the Timeline bar:

Code: Select all

comp:DoAction("Fusion_View_Show", {view = "Time", show = false}) -- Hide the Timeline bar control
bmd.wait(3) -- Pause 3 seconds
comp:DoAction("Fusion_View_Show", {view = "Time", show = true}) -- Show the Timeline bar control

Reset the (Resolve Fusion page) GUI to its default layout:

Code: Select all

comp:DoAction("Comp_Reset", {}) -- Reset the Fusion composite view layout in Resolve
You do not have the required permissions to view the files attached to this post.

User avatar
AndrewHazelden
Fusionator
Posts: 1508
Joined: Fri Apr 03, 2015 3:20 pm
Answers: 6
Location: West Dover, Nova Scotia, Canada
Been thanked: 85 times
Contact:

Discovering A Unicode Ellipsis in Menu Names

#194

Post by AndrewHazelden » Mon Nov 18, 2019 7:44 pm

Here's a small tip for anyone who might be trying to add their own menu items to Fusion's menu system:

  • Fusion v9 uses a series of three period characters to add the "..." effect to the end of menu entries.
  • Fusion v16.x uses a single Unicode ellipsis character (U+2026 HORIZONTAL ELLIPSIS) to add the "…" effect to the end of menu entries.

This means a .fu file you might have tested with Fusion v9 will need to be modified to support both approaches for menu names.

An example of why this is important would be if you are trying to place your own custom menu entries just before or after an existing menu entry that has the "..." characters in it like File > Open....

Menus with Ellipsis.png

You'd also need to know about this issue if you are doing something mischievous like trying to add something new and custom to the File > Import > menu section via Lua or Python scripted .fu entries. :)

Import Menus.png

A Real World Example

Here is a snippet of .fu menu code that comes from the "Open in Script Editor.fu" file from Reactor that shows an IRL example of the Fu v9 vs Fu v16 ellipsis menu issue at the very bottom of the .fu file:
Code: [Select all] [Expand/Collapse] [Download] (Open in Script Editor.fu)
  1. --[[--
  2. Open in Script Editor - v2 2018-05-09
  3. By Andrew Hazelden <andrew@andrewhazelden.com>
  4.  
  5. ## Overview ##
  6.  
  7. The "Open in Script Editor.fu" file creates a pair of "File > Open Comp in Script Editor" and "File > Open All Comps in Script Editor" menu entries in Fusion. This allows you to quickly tweak your your comp externally in a programmer's text editor which is a handy way to do raw find and replace editing operations, or to edit a node based element by hand.
  8.  
  9. This menu entry opens your current Fusion composite document in the external Script Editor that is defined in the Fusion Preferences "Global and Default Settings > Script > Editor Path" section.
  10.  
  11. ## Installation ##
  12.  
  13. Step 1. Move the "Open in Script Editor.fu" file into the Fusion user prefs "Config:/" folder.
  14.  
  15. Step 2. Open the Fusion Preferences "Global and Default Settings > Script > Editor Path" section and link to your favorite text editor. If you don't have a text editor installed yet consider BBEdit on MacOS, or Notepad++ on Windows.
  16.  
  17. (Note: In Reactor's "Bin" category there is a "custom "Notepad++ for Fusion" atom.)
  18.  
  19. Step 3. Restart Fusion so the .fu config file is loaded.
  20.  
  21. --]]--
  22.  
  23. {
  24.     Action
  25.     {
  26.         ID = "Open_Comp_in_Script_Editor",
  27.         Category = "File",
  28.         Name = "Open Comp in Script Editor",
  29.  
  30.         Targets =
  31.         {
  32.             Composition =
  33.             {
  34.                 Execute = _Lua [=[
  35. platform = (FuPLATFORM_WINDOWS and 'Windows') or (FuPLATFORM_MAC and 'Mac') or (FuPLATFORM_LINUX and 'Linux')
  36.  
  37. function OpenDocument(title, appPath, docPath)
  38.     if platform == 'Windows' then
  39.         -- Running on Windows
  40.         command = 'start "" "' .. appPath .. '" "' .. docPath .. '" &'
  41.     elseif platform == 'Mac' then
  42.         -- Running on Mac
  43.         command = 'open -a "' .. appPath .. '" "' .. docPath .. '" &'
  44.      elseif platform == "Linux" then
  45.         -- Running on Linux
  46.         command = '"' .. appPath .. '" "' .. docPath .. '" &'
  47.     else
  48.         print('[Error] There is an invalid Fusion platform detected')
  49.         return
  50.     end
  51.  
  52.     obj:Comp():Print('[' .. title .. '] [App] "' .. appPath .. '" [Document] "' .. docPath .. '"\n')
  53.     -- obj:Comp():Print('[Launch Command] ' .. tostring(command) .. '\n')
  54.     os.execute(command)
  55. end
  56.  
  57. editorPath = fu:GetPrefs('Global.Script.EditorPath')
  58. if editorPath == nil or editorPath == "" then
  59.     obj:Comp():Print('[Open Comp in Script Editor] The "Editor Path" is empty. Please choose a text editor in the Fusion Preferences "Global and Default Settings > Script > Editor Path" section.\n')
  60.     app:ShowPrefs("PrefsScript")
  61. else
  62.     -- Save the existing comp
  63.     obj:Comp():Save()
  64.  
  65.     -- Get the active comp filename
  66.     sourceComp = app:MapPath(obj:Comp():GetAttrs().COMPS_FileName)
  67.  
  68.     -- Send the comp to the ScriptEditor
  69.     if sourceComp ~= '' then
  70.         OpenDocument('Open Comp in Script Editor', editorPath, sourceComp)
  71.     else
  72.         obj:Comp():Print('[Open Comp in Script Editor] Please save the untitled comp to disk first.\n')
  73.     end
  74. end
  75.                 ]=],
  76.             },
  77.         },
  78.     },
  79.     Action
  80.     {
  81.         ID = "Open_All_Comps_In_Script_Editor",
  82.         Category = "File",
  83.         Name = "Open All Comps in Script Editor",
  84.  
  85.         Targets =
  86.         {
  87.             Composition =
  88.             {
  89.                 Execute = _Lua [=[
  90. platform = (FuPLATFORM_WINDOWS and 'Windows') or (FuPLATFORM_MAC and 'Mac') or (FuPLATFORM_LINUX and 'Linux')
  91.  
  92. function OpenDocument(title, appPath, docPath)
  93.     if platform == 'Windows' then
  94.         -- Running on Windows
  95.         command = 'start "" "' .. appPath .. '" ' .. docPath .. ' &'
  96.     elseif platform == 'Mac' then
  97.         -- Running on Mac
  98.         command = 'open -a "' .. appPath .. '" ' .. docPath .. ' &'
  99.      elseif platform == "Linux" then
  100.         -- Running on Linux
  101.         command = '"' .. appPath .. '" ' .. docPath .. ' &'
  102.     else
  103.         obj:Comp():Print('[Error] There is an invalid Fusion platform detected\n')
  104.         return
  105.     end
  106.     obj:Comp():Print('[' .. title .. '] [App] "' .. appPath .. '" [Documents] ' .. docPath .. '\n')
  107.     -- obj:Comp():Print('[Launch Command] ' .. tostring(command) .. '\n')
  108.     os.execute(command)
  109. end
  110.  
  111. editorPath = fu:GetPrefs('Global.Script.EditorPath')
  112. if editorPath == nil or editorPath == "" then
  113.     obj:Comp():Print('[Open in Script Editor] The "Editor Path" is empty. Please choose a text editor in the Fusion Preferences "Global and Default Settings > Script > Editor Path" section.\n')
  114.     app:ShowPrefs("PrefsScript")
  115. else
  116.     local sourceCompList = ''
  117.     obj:Comp():Print('[Open Documents] ' .. '\n')
  118.    
  119.     compList = fu:GetCompList()
  120.     for i = 1, #compList do
  121.         -- Set cmp to the pointer of the current composite
  122.         cmp = compList[i]
  123.        
  124.         -- Read the comp filename
  125.         local sourceComp = cmp:GetAttrs().COMPS_FileName
  126.         if sourceComp ~= '' then
  127.             -- Print out the active composite name
  128.             obj:Comp():Print('\t[' .. sourceComp .. ']\n')
  129.  
  130.             -- Save the existing comp
  131.             cmp:Save()
  132.  
  133.             -- Get the active comp filename
  134.             sourceCompList = sourceCompList .. '"' .. app:MapPath(sourceComp) .. '" '
  135.         end
  136.     end
  137.    
  138.     -- Send the comp to the ScriptEditor
  139.     if sourceCompList ~= '' then
  140.         OpenDocument('Open All Comps in Script Editor', editorPath, sourceCompList)
  141.     else
  142.         obj:Comp():Print('[Open All Comps in Script Editor] Please save the untitled comp to disk first.\n')
  143.     end
  144. end
  145.                 ]=],
  146.             },
  147.         },
  148.     },
  149.     -- Fusion 9 menus with three period characters
  150.     Menus
  151.     {
  152.         Target = "ChildFrame",
  153.  
  154.         After "File\\Open..."
  155.         {
  156.             "Open_Comp_in_Script_Editor{}",
  157.             "Open_All_Comps_In_Script_Editor{}",
  158.         },
  159.     },
  160.     -- Fusion 16 menus with a Unicode elipsis character
  161.     Menus
  162.     {
  163.         Target = "ChildFrame",
  164.  
  165.         After "File\\Open…"
  166.         {
  167.             "Open_Comp_in_Script_Editor{}",
  168.             "Open_All_Comps_In_Script_Editor{}",
  169.         },
  170.     },
  171. }
  172.  
  173.  
You do not have the required permissions to view the files attached to this post.

User avatar
AndrewHazelden
Fusionator
Posts: 1508
Joined: Fri Apr 03, 2015 3:20 pm
Answers: 6
Location: West Dover, Nova Scotia, Canada
Been thanked: 85 times
Contact:

Exploring the "ACTION_GET_UI_LAYOUT" Action

#195

Post by AndrewHazelden » Tue Nov 19, 2019 3:41 am

From looking at a list of the actions that exist in Fusion v16 there are few additions that look interesting and could take things further into uncharted waters for UI modding:

  • ACTION_GET_UI_LAYOUT
  • ACTION_GET_TEMPLATES_LIST
  • ACTION_SET_EDITPAGE_INSPECTOR_COMP_PARAMS
  • ACTION_SET_UI_LAYOUT

These new actions were found using the following Lua script that will prints out a Console view based list of the actions that are present in Resolve and Fusion:

Code: [Select all] [Expand/Collapse] [Download] (List Actions.lua)
  1. -- Track the actions that are available in Fusion
  2. local actionList = fu.ActionManager:GetActions()
  3.  
  4. -- Count the total number of actions
  5. actionCount = 0
  6. for i, act in ipairs(actionList) do
  7.   if not act:Get('Parent') then
  8.     actionCount = actionCount + 1
  9.   end
  10. end
  11. print('[' .. actionCount .. ' Actions Found]')
  12.  
  13. -- List each action sequentially
  14. for i, act in ipairs(actionList) do
  15.   if not act:Get('Parent') then
  16.     print(act.ID)
  17.   end
  18. end

Get the Current UI Layout

The ACTION_GET_UI_LAYOUT action can be used to dump a list of all the Fusion/Resolve window element parameters.

I think you can optionally specify the screen_mode as either "SINGLE_SCREEN" or "DUAL_SCREEN". I'm not 100% sure about the differences in what you get back in the resulting table between those two screen modes. Overall the "DUAL_SCREEN" value is likely more of a Resolve UI thing than Fusion Studio Standalone relevant. Who knows? :)

Code: [Select all] [Expand/Collapse] [Download] (Get UI Layout1.lua)
  1. -- Return a lua table with the active UI element values
  2. viewLayout = comp:DoAction("ACTION_GET_UI_LAYOUT", {screen_mode = "SINGLE_SCREEN"})
  3. dump(viewLayout)

or

Code: [Select all] [Expand/Collapse] [Download] (Get UI Layout2.lua)
  1. -- Return a lua table with the active UI element values
  2. viewLayout = comp:DoAction("ACTION_GET_UI_LAYOUT", {screen_mode = "DUAL_SCREEN"})
  3. dump(viewLayout)

Running the above code snippet gives you back a Lua table result like this:

Note: This example was hand-reindented to improve readability so it's not 100% perfectly formatted on the tab indent levels. Clearly I'm going to have to hunt down a macOS compatible automatic Lua code reformatter soon to cut down on this type of massive human time wasting effort. LOL. :lol:
Code: [Select all] [Expand/Collapse] [Download] (ACTION_GET_UI_LAYOUT_Lua_Table.lua)
  1. table: 0x01d23795e0
  2.     BYTE_ARRAY = {
  3.         Single = {
  4.             {
  5.                 ViewInfo = {
  6.                     Viewer1 = {
  7.                         Show = true,
  8.                         RatioY = 0.00856531049250535,
  9.                         RatioX = 0.502392344497608
  10.                     },
  11.                     InnerLeft = {
  12.                         RatioY = 551,
  13.                         PixelX = 420
  14.                     },
  15.                     MainSplit = {
  16.                         RatioX = 1,
  17.                         RatioY = 0.477845351867941
  18.                     },
  19.                     CenterSplit = {
  20.                         RatioX = 0.817787418655098,
  21.                         RatioY = 1324
  22.                     },
  23.                     Viewer2 = {
  24.                         Show = true,
  25.                         RatioY = 0.00856531049250535,
  26.                         RatioX = 0.497607655502392
  27.                     },
  28.                     Comments = {
  29.                         Show = false
  30.                     },
  31.                     Time = {
  32.                         Show = true,
  33.                         RatioX = 1
  34.                     },
  35.                     InnerColumns = {
  36.                         RatioX = 1,
  37.                         RatioY = 0.47871416159861
  38.                     },
  39.                     Keyframes = {
  40.                         Show = false,
  41.                         RatioY = 0.00188323917137476,
  42.                         RatioX = 0.333461835003855
  43.                     },
  44.                     LayoutStrip = {
  45.                         Show = true,
  46.                         RatioX = 1
  47.                     },
  48.                     Inspector = {
  49.                         Show = true,
  50.                         RatioX = 1,
  51.                         RatioY = 1,
  52.                         MRU = 2,
  53.                         Adjust = false
  54.                     },
  55.                     InnerRight = {
  56.                         RatioY = 0.00188323917137476
  57.                     },
  58.                     Effects = {
  59.                         Show = false,
  60.                         RatioY = 0.5,
  61.                         RatioX = 1
  62.                     },
  63.                     OuterColumns = {
  64.                         RatioX = 1,
  65.                         RatioY = 1
  66.                     },
  67.                     Metadata = {
  68.                         Show = false,
  69.                         RatioY = 0.5,
  70.                         RatioX = 1
  71.                     },
  72.                     Clips = {
  73.                         Show = false,
  74.                         RatioX = 1
  75.                     },
  76.                     ActionStrip = {
  77.                         Show = true,
  78.                         RatioX = 1
  79.                     },
  80.                     OuterLeft = {
  81.                         RatioY = 0.000784313725490196,
  82.                         PixelX = 420
  83.                     },
  84.                     ViewerSplit = {
  85.                         RatioX = 1,
  86.                         RatioY = 0.849090909090909
  87.                     },
  88.                     Nodes = {
  89.                         Show = true,
  90.                         RatioY = 1,
  91.                         RatioX = 1
  92.                     },
  93.                     OuterRight = {
  94.                         RatioY = 1324
  95.                     },
  96.                     MediaPool = {
  97.                         Show = true,
  98.                         RatioX = 1,
  99.                         RatioY = 1,
  100.                         MRU = 1,
  101.                         Adjust = false
  102.                     },
  103.                     Spline = {
  104.                         Show = false,
  105.                         RatioY = 0.00188323917137476,
  106.                         RatioX = 0.33307632999229
  107.                     }
  108.                 },
  109.                 Layout = {
  110.                     {
  111.                         {
  112.                             {
  113.                                 ID = "MediaPool",
  114.                                 RatioY = 1,
  115.                                 RatioX = 1
  116.                             },
  117.                             {
  118.                                 {
  119.                                     {
  120.                                         ID = "Viewer1",
  121.                                         RatioY = 0.00856531049250535,
  122.                                         RatioX = 0.502392344497608
  123.                                     },
  124.                                     {
  125.                                         ID = "Viewer2",
  126.                                         RatioX = 0.497607655502392
  127.                                     },
  128.                                         RatioX = 1,
  129.                                         RatioY = 0.849090909090909,
  130.                                         Columns = 2
  131.                                     },
  132.                                     {
  133.                                         ID = "Time",
  134.                                         FixedY = 83,
  135.                                         Flat = true
  136.                                     },
  137.                                     RatioX = 0.777070063694268,
  138.                                     Rows = 2
  139.                                 },
  140.                                 RatioX = 1,
  141.                                 RatioY = 0.47871416159861,
  142.                                 Columns = 2
  143.                                 },
  144.                                 {
  145.                                     ID = "ActionStrip",
  146.                                     FixedY = 50,
  147.                                     Flat = true
  148.                                 },
  149.                                 {
  150.                                     ID = "Nodes",
  151.                                     RatioY = 1,
  152.                                     RatioX = 1
  153.                                 },
  154.                                     RatioX = 0.817787418655098,
  155.                                     Rows = 3,
  156.                                     RatioY = 1324
  157.                                 },
  158.                                 {
  159.                                     ID = "Inspector",
  160.                                     RatioY = 1,
  161.                                     RatioX = 1
  162.                                 },
  163.                                 RatioX = 1,
  164.                                 RatioY = 1,
  165.                                 Columns = 2
  166.                             },
  167.                             Left = 0,
  168.                             Width = 2308,
  169.                             Top = 0,
  170.                             ZoneInfo = {
  171.                                 AuxLeft = {
  172.                                     Expanded = true
  173.                                 },
  174.                                 Right = {
  175.                                     Expanded = true
  176.                                 },
  177.                                 Left = {
  178.                                     Expanded = false
  179.                                 },
  180.                                 AuxRight = {
  181.                                     Expanded = true
  182.                                 }
  183.                             },
  184.                             LayoutPreset = 0,
  185.                             Height = 1155,
  186.                             Mode = 3,
  187.                             FrameTypeID = "ChildFrame",
  188.                             Views = ordered() {
  189.                                 MediaPool = "MediaPoolView",
  190.                                 Effects = MultiView {
  191.                                     ViewList = ordered() {
  192.                                         EffectView = "EffectView"
  193.                                     },
  194.                                     Active = "EffectView"
  195.                                 },
  196.                                 Nodes = MultiView {
  197.                                     ViewList = ordered() {
  198.                                     FlowView = "FlowView"
  199.                                 },
  200.                                 Active = "FlowView",
  201.                                     Names = {
  202.                                         FlowView = "FlowView"
  203.                                     }
  204.                                 },
  205.                                 Keyframes = MultiView {
  206.                                     ViewList = ordered() {
  207.                                         TimelineView = "TimelineView"
  208.                                 },
  209.                                 Active = "TimelineView",
  210.                                     Names = {
  211.                                         TimelineView = "TimelineView"
  212.                                     }
  213.                                 },
  214.                                 Spline = MultiView {
  215.                                 ViewList = ordered() {
  216.                                     SplineView = "SplineEditorView"
  217.                                 },
  218.                                 Active = "SplineView",
  219.                                 Names = {
  220.                                     SplineView = "SplineView"
  221.                                 }
  222.                             },
  223.                             Inspector = MultiView {
  224.                                 ViewList = ordered() {
  225.                                     Tools = "ControlView",
  226.                                     Modifiers = "ModifierView"
  227.                                 },
  228.                             Active = "Tools"
  229.                             },
  230.                             Viewer1 = MultiView {
  231.                                 ViewList = ordered() {
  232.                                     LeftView = "PreviewContainer"
  233.                             },
  234.                             Active = "LeftView",
  235.                                 Names = {
  236.                                     LeftView = "LeftView"
  237.                                 }
  238.                             },
  239.                             Viewer2 = MultiView {
  240.                                 ViewList = ordered() {
  241.                                     RightView = "PreviewContainer"
  242.                                 },
  243.                                 Active = "RightView",
  244.                                     Names = {
  245.                                         RightView = "RightView"
  246.                                     }
  247.                                 },
  248.                                 Time = "TimeView",
  249.                                 ActionStrip = "ActionStripView",
  250.                                 LayoutStrip = "LayoutStripView",
  251.                                 Clips = "ClipsView",
  252.                                 Metadata = "MetadataView"
  253.                                 }
  254.                             }
  255.                         },
  256.                         Dual = {
  257.                             {
  258.                                 Views = ordered() {
  259.                                     Nodes = {
  260.                                         Tabs = false,
  261.                                         ViewList = {
  262.                                             FlowView = "FlowView"
  263.                                         }
  264.                                     },
  265.                                     Inspector = MultiView {
  266.                                         ViewList = ordered() {
  267.                                             Tools = "ControlView",
  268.                                             Modifiers = "ModifierView"
  269.                                         },
  270.                                         Active = "Tools"
  271.                                     },
  272.                                     Viewer1 = {
  273.                                         ViewList = {
  274.                                             LeftView = "PreviewContainer"
  275.                                         },
  276.                                         Tabs = false,
  277.                                             Label = false
  278.                                         },
  279.                                         Viewer2 = {
  280.                                             ViewList = {
  281.                                                 RightView = "PreviewContainer"
  282.                                             },
  283.                                             Tabs = false,
  284.                                             Label = false
  285.                                         },
  286.                                         Time = TimeView {},
  287.                                         ActionStrip = ActionStripView {},
  288.                                         LayoutStrip = LayoutStripView {},
  289.                                         Clips = ClipsView {}
  290.                                     },
  291.                                     Mode = 2,
  292.                                     FrameTypeID = "ChildFrame",
  293.                                     Layout = {
  294.                                         {
  295.                                             ID = "LayoutStrip",
  296.                                             FixedY = 32,
  297.                                             Flat = true,
  298.                                             Resolve = false
  299.                                         },
  300.                                         {
  301.                                             {
  302.                                                 {
  303.                                                     {
  304.                                                         {
  305.                                                             {
  306.                                                                 ID = "Viewer1",
  307.                                                                 RatioX = 0.5
  308.                                                             },
  309.                                                             {
  310.                                                                 ID = "Viewer2",
  311.                                                                 RatioX = 0.5
  312.                                                             },
  313.                                                                 RatioY = 1,
  314.                                                                 Columns = 2,
  315.                                                                 PaneID = "ViewerSplit"
  316.                                                             },
  317.                                                             {
  318.                                                                 ID = "Time",
  319.                                                                 FixedY = 83,
  320.                                                                 Flat = true
  321.                                                             },
  322.                                                             RatioX = 1,
  323.                                                             Rows = 2
  324.                                                         },
  325.                                                         {
  326.                                                             ID = "Inspector",
  327.                                                             FixedX = 420,
  328.                                                             Zone = "!Right"
  329.                                                         },
  330.                                                         RatioY = 1,
  331.                                                         Columns = 2,
  332.                                                         PaneID = "InnerColumns"
  333.                                                     },
  334.                                                     {
  335.                                                         ID = "ActionStrip",
  336.                                                         FixedY = 50,
  337.                                                         Flat = true
  338.                                                     },
  339.                                                     {
  340.                                                         ID = "Nodes",
  341.                                                         RatioY = 1
  342.                                                     },
  343.                                                     {
  344.                                                         MEDIUM_FixedY = 160,
  345.                                                         FixedY = 160,
  346.                                                         ID = "Clips",
  347.                                                         Fusion = false,
  348.                                                         LARGE_FixedY = 160,
  349.                                                         SMALL_FixedY = 160
  350.                                                     },
  351.                                                     RatioX = 1,
  352.                                                     Rows = 4,
  353.                                                     PaneID = "CenterSplit"
  354.                                                     },
  355.                                                     {
  356.                                                         ID = "Inspector",
  357.                                                         FixedX = 420,
  358.                                                         Zone = "Right"
  359.                                                     },
  360.                                                     RatioY = 1,
  361.                                                     Columns = 2,
  362.                                                     PaneID = "OuterColumns"
  363.                                                 },
  364.                                                 RatioX = 1,
  365.                                                 Rows = 2,
  366.                                                 RatioY = 1
  367.                                             }
  368.                                         },
  369.                                         {
  370.                                             Views = ordered() {
  371.                                                 MediaPool = MediaPoolView {
  372.                                             },
  373.                                             Spline = {
  374.                                                 Tabs = false,
  375.                                                 ViewList = {
  376.                                                     SplineView = "SplineEditorView"
  377.                                                 }
  378.                                             },
  379.                                             Keyframes = {
  380.                                                 Tabs = false,
  381.                                                 ViewList = {
  382.                                                     TimelineView = "TimelineView"
  383.                                                 }
  384.                                             },
  385.                                             Effects = {
  386.                                                 Tabs = false,
  387.                                                 ViewList = {
  388.                                                     EffectView = "EffectView"
  389.                                                 }
  390.                                             },
  391.                                             Metadata = Metadata {}
  392.                                             },
  393.                                             Mode = 2,
  394.                                             FrameTypeID = "FloatViewFrame",
  395.                                             Layout = {
  396.                                             {
  397.                                                 ID = "LayoutStrip",
  398.                                                 FixedY = 32,
  399.                                                 Flat = true,
  400.                                                 Resolve = false
  401.                                             },
  402.                                             {
  403.                                                 {
  404.                                                     PixelX = 420,
  405.                                                     ID = "MediaPool",
  406.                                                     Fusion = false,
  407.                                                     RatioX = 0.3,
  408.                                                     Zone = "AuxLeft"
  409.                                                 },
  410.                                                 {
  411.                                                     {
  412.                                                         {
  413.                                                             PixelX = 420,
  414.                                                             ID = "MediaPool",
  415.                                                             Fusion = false,
  416.                                                             RatioX = 0.3,
  417.                                                             Zone = "!AuxLeft"
  418.                                                         },
  419.                                                         {
  420.                                                             ID = "Spline",
  421.                                                             RatioX = 1
  422.                                                         },
  423.                                                         {
  424.                                                             {
  425.                                                             ID = "Metadata",
  426.                                                             RatioY = 1,
  427.                                                             Fusion = false
  428.                                                         },
  429.                                                         {
  430.                                                             ID = "Effects",
  431.                                                             RatioY = 1
  432.                                                         },
  433.                                                             FixedX = 420,
  434.                                                             Rows = 2,
  435.                                                             PaneID = "InnerRight",
  436.                                                             Zone = "!AuxRight"
  437.                                                         },
  438.                                                             RatioY = 2,
  439.                                                             Columns = 3,
  440.                                                             PaneID = "InnerColumns"
  441.                                                         },
  442.                                                         {
  443.                                                             ID = "Keyframes",
  444.                                                             RatioY = 1
  445.                                                         },
  446.                                                         RatioX = 1,
  447.                                                         Rows = 2,
  448.                                                         PaneID = "CenterSplit"
  449.                                                     },
  450.                                                     {
  451.                                                         {
  452.                                                             ID = "Metadata",
  453.                                                             RatioY = 1,
  454.                                                             Fusion = false
  455.                                                         },
  456.                                                         {
  457.                                                             ID = "Effects",
  458.                                                             RatioY = 1
  459.                                                         },
  460.                                                         FixedX = 420,
  461.                                                         Rows = 2,
  462.                                                         PaneID = "OuterRight",
  463.                                                         Zone = "AuxRight"
  464.                                                     },
  465.                                                     RatioY = 1,
  466.                                                     Columns = 3,
  467.                                                     PaneID = "OuterColumns"
  468.                                                 },
  469.                                                 RatioX = 1,
  470.                                                 Rows = 2,
  471.                                                 RatioY = 1
  472.                                             }
  473.                                         }
  474.                                     },
  475.                                 }

Tracking ACTION_GET_UI_LAYOUT in Action Listener

Besides grabbing the dumped output from comp:DoAction(), this information is also visible if you look at the Rets variable in Action Listener when the ACTION_GET_UI_LAYOUT action is run. That's pretty neat. 👍

Resolve 16.1 ACTION_GET_UI_LAYOUT.png

What about ACTION_SET_UI_LAYOUT?

As far as I can tell, the ACTION_SET_UI_LAYOUT action is part of the way that the Fusion page and Resolve app are able to talk to each other. It's got the potential to be a really fun way for comp TDs to force in their own customized view layouts and achieve a lot of UI modding zanynesss.

That's something that will require another post all on its own.
You do not have the required permissions to view the files attached to this post.