Building GUIs With Fusion's UI Manager

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

Accessing Fusion's Lua Based FFI Library Support

#61

Post by AndrewHazelden » Thu Oct 12, 2017 8:38 am

Chad wrote:Neat. Now we can add copy protection to scripts and fuses.
A nice feature of Fusion 9.0.1 is that you can easily use the Lua FFI library and things like cURL from inside of your Fusion based Fuses, Lua Comp/Tool scripts, or UserControls based scripts. :)

FFI is used to allow Lua based scripts to call functions that exist in an external c-code based .so/.dll library file. You can check out the official FFI documentation here for more details on the library and how it works:
http://luajit.org/ext_ffi.html

The Lua FFI library support works in both Fusion (Free) and Fusion Studio which can help unlock a lot of custom tool development options for compositing TDs or developers that are interested in accessing the widest market of Fusion users.

Writing a Lua script that uses FFI is a great option for someone who is interested in using a pre-compiled external library with Fusion but might find the overhead of creating a compiled Fusion native plugin or OFX module daunting.

This example will download a file defined in the sourceURL variable and save it to disk at a filepath defined by the fuDestFile variable. This script is kept as simple as possible to show the concept of how FFI + cURL can be used.
  1. -- The URL for the cURL based download:
  2. local sourceURL = [[https://www.steakunderwater.com/wesuckless/index.php]]
  3.  
  4. -- The filepath for saving the downloaded asset
  5. local fuDestFile = comp:MapPath("Temp:/") .. "we-suck-less.html"
  6.  
  7. -- Set up cURL to work with Fusion 9.0.1
  8. ffi = require "ffi"
  9. curl = require "lj2curl"
  10. ezreq = require "lj2curl.CRLEasyRequest"
  11. local req = ezreq(sourceURL)
  12. local body = {}
  13. req:setOption(curl.CURLOPT_SSL_VERIFYPEER, 0)
  14. req:setOption(curl.CURLOPT_WRITEFUNCTION, ffi.cast("curl_write_callback",
  15.  function(buffer, size, nitems, userdata)
  16.   table.insert(body, ffi.string(buffer, size*nitems))
  17.   return nitems
  18.  end))
  19.  
  20. -- Download the file from the "sourceURL" address
  21. print('[Downloading] ' .. sourceURL)
  22. ok, err = req:perform()
  23. if ok then
  24.   -- Write the file to disk
  25.   local file = io.open(fuDestFile, "w")
  26.   file:write(table.concat(body));
  27.   file:close();
  28.  
  29.   -- Show the file we just downloaded in the default HTML viewer on your system:
  30.   print('[Opening File] ' .. fuDestFile)
  31.   bmd.openfileexternal('Open', fuDestFile)
  32. end
As a tip, in Fusion 9 you can drag and drop a .lua script from your desktop folder into the Fusion Console tab view and it will be run instantly. This is handy for testing out snippets of code you are editing externally to Fusion or might download from WSL.

Note: A custom UI Manager wrapper GUI could be added to this type of code snippet to allow your in-house Fusion pipeline scripts to download assets from a local or remote URL address.

Tags:

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

Debug Your Lua Code With Custom Fusion Console Printing Functions

#62

Post by AndrewHazelden » Wed Nov 01, 2017 7:21 am

The custom functions in this script provide an example of verbose debugging tools that you can copy and paste into your Lua code. :)

The debug printing functions save you from having to constantly add/remove comments from code in your scripts when you want to see debugging output in the Fusion Console tab.

This approach means you can still have access to all of the detailed diagnostic information you need during development testing on your own system, while being able to deliver the exact same file to end users for regular use.

You can write any environment variable you want in place of the words "YOUR_DEBUG_ENV_VAR".
Code: [Select all] [Expand/Collapse] [Download] (DebuggingFunctions.lua)
  1. --[[--
  2. Lua script debugging print and dump functions 2017-11-01 11.07 AM
  3. By Andrew Hazelden <andrew@andrewhazelden.com>
  4.  
  5. Overview
  6. The custom functions in this script provide an example of verbose debugging tools that you can copy and paste into your Lua code.
  7.  
  8. The debug printing functions save you from having to constantly add/remove comments from code in your scripts when you want to see debugging output in the Fusion Console tab.
  9.  
  10. This approach means you can still have access to all of the detailed diagnostic information you need during development testing on your own system, while being able to deliver the exact same file to end users for regular use.
  11.  
  12. You can write any environment variable you want in place of the words "YOUR_DEBUG_ENV_VAR".
  13. --]]--
  14.  
  15. -- Add a debug version of the print() command
  16. dprintf = (os.getenv("YOUR_DEBUG_ENV_VAR") ~= "true") and function() end or
  17. function(fmt, ...)
  18.     print(fmt:format(...))
  19. end
  20.  
  21. -- Add a debug version of the dump() command
  22. ddump = (os.getenv("YOUR_DEBUG_ENV_VAR") ~= "true") and function() end or
  23. function(val)
  24.     dump(val)
  25. end
  26.  
  27. -- Add a debug version of the bmd.openfileexternal() command
  28. dopenfileexternal = (os.getenv("YOUR_DEBUG_ENV_VAR") ~= "true") and function() end or
  29. function(...)
  30.     bmd.openfileexternal(...)
  31. end
  32.  
  33. -- Print out a message during debuggging
  34. -- These functions will only print their output in the Console tab if you have your custom environment variable enabled
  35. dprintf("[Debug Mode] This message will only be printed to the Console tab when your debugging environment variable exists.")
  36.  
  37. -- Print out a Lua table during debugging
  38. dprintf("[Debug Mode] Listing the bmd.* functions in Fusion:")
  39. ddump(bmd)
  40.  
  41. -- Open a folder browser window during debugging
  42. scriptsPath = comp:MapPath("Scripts:/Comp/")
  43. dprintf("[Debug Mode] Opening the Scripts:/Comp/ folder: " .. scriptsPath)
  44. dopenfileexternal('Open', scriptsPath)

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

OpenCL Control Script

#63

Post by AndrewHazelden » Fri Nov 03, 2017 4:18 am

About OpenCL Control

"OpenCL Control" is a simple script to help disable OpenCL acceleration in Fusion 9.0.1.

This is handy if you experience OpenCL related crashes with your GPU when trying to open the Fusion OpenCL Preferences window, or when rendering with OpenCL active on the following nodes:
  • ColorCorrector
  • GamutConvert
  • MatteControl
Note: If you want to disable OpenCL on additional nodes in your Fusion composites, you just have to add the additional node types to the OpenCLNodeList Lua table that is located near the top of the "OpenCL-Control.lua" script.

Screenshot

This preview shows what the OpenCL Control GUI looks like:
OpenCL-Control-Script.png
Download the Script
Code: [Select all] [Expand/Collapse] [Download] (OpenCL-Control.lua)
  1. -- OpenCL Control Script for Fusion 9.0.1 2017-11-03
  2. -- Created By Andrew Hazelden <andrew@andrewhazelden.com>
  3.  
  4. -- Installation:
  5. -- Place this script in the Fusion user preferences "Scripts:/Comp/" folder.
  6.  
  7. -- Disable OpenCL on the following nodes:
  8. OpenCLNodeList = {
  9.   'ColorCorrector',
  10.   'GamutConvert',
  11.   'MatteControl',
  12. }
  13.  
  14. -- Show the UI Manager based Window:
  15. local ui = fu.UIManager
  16. local disp = bmd.UIDispatcher(ui)
  17. local width,height = 400,235
  18.  
  19. win = disp:AddWindow({
  20.   ID = 'OpenCLControlWin',
  21.   TargetID = 'OpenCLControlWin',
  22.   WindowTitle = 'OpenCL Control v1.0',
  23.   Geometry = {100, 100, width, height},
  24.   Spacing = 10,
  25.  
  26.   ui:VGroup{
  27.     ID = 'root',
  28.  
  29.     -- Add your GUI elements here:
  30.     ui:TextEdit{
  31.       Weight = 0,
  32.  
  33.       ID = 'AboutText',
  34.       Alignment = {
  35.         AlignHCenter = true,
  36.         AlignTop = true,
  37.       },
  38.       HTML = [[This GUI allows you to quickly disable the Fusion 9 OpenCL controls in your Fusion Preferences and per node in the comp.]],
  39.       ReadOnly = true,
  40.     },
  41.  
  42.     ui:VGroup{
  43.       ui:Button{
  44.         ID = 'DisableOpenCLPrefButton',
  45.         Text = 'Disable OpenCL in Preferences',
  46.       },
  47.  
  48.       ui:Button{
  49.         ID = 'DisableOpenCLOnNodesButton',
  50.         Text = 'Disable OpenCL on Nodes',
  51.       },
  52.     }
  53.  
  54.   },
  55. })
  56.  
  57. -- Add your GUI element based event functions here:
  58. itm = win:GetItems()
  59.  
  60. -- The window was closed
  61. function win.On.OpenCLControlWin.Close(ev)
  62.   disp:ExitLoop()
  63. end
  64.  
  65. -- 'Disable OpenCL in Preferences' Button Clicked
  66. function win.On.DisableOpenCLPrefButton.Clicked(ev)
  67.   comp:Print('\n\n-------------------------------------------\n\n')
  68.   comp:Print('[Disabling OpenCL in Comp Preferences]\n\n')
  69.  
  70.   compList = fu:GetCompList()
  71.   for i = 1, table.getn(compList) do
  72.     -- Set cmp to the pointer of the current composite
  73.     cmp = compList[i]
  74.  
  75.     -- Print out the active composite name
  76.     comp:Print('\t[' .. cmp:GetAttrs()['COMPS_Name'] .. ']\n')
  77.     comp:Print('\t\tSet OpenCL Preference "Comp.Tweaks.OpenCL.Enable" to OFF\n')
  78.  
  79.     -- Disable the comp specific OpenCL preference
  80.     cmp:SetPrefs('Comp.Tweaks.OpenCL.Enable', 0)
  81.  
  82.     -- Add a spacer between each comp
  83.     comp:Print('\n')
  84.   end
  85.  
  86.   -- Disable the Fusion globals specific OpenCL preferences
  87.   comp:Print('[Disabling OpenCL in Global Preferences]\n\n')
  88.  
  89.   comp:Print('\tSet OpenCL Preference "Comp.Tweaks.OpenCL.Enable" to OFF\n')
  90.   fu:SetPrefs('Comp.Tweaks.OpenCL.Enable', 0)
  91.  
  92.   comp:Print('\tSet OpenCL Preference "Global.Tweaks.OpenCL.Device" to CPU\n')
  93.   fu:SetPrefs('Global.Tweaks.OpenCL.Device', 'cpu')
  94.   fu:SavePrefs()
  95.  
  96.   -- Add a spacer
  97.   comp:Print('\n')
  98.  
  99.   comp:Print('[Done]\n')
  100. end
  101.  
  102. -- 'Disable OpenCL on Nodes' Button Clicked
  103. function win.On.DisableOpenCLOnNodesButton.Clicked(ev)
  104.   comp:Print('\n\n-------------------------------------------\n\n')
  105.   comp:Print('[Disabling OpenCL in the Open Fusion Comps]\n\n')
  106.   -- Process each of the open Comps
  107.   compList = fu:GetCompList()
  108.   for i = 1, table.getn(compList) do
  109.     -- Set cmp to the pointer of the current composite
  110.     cmp = compList[i]
  111.  
  112.     -- Print out the active composite name
  113.     comp:Print('\t[' .. cmp:GetAttrs()['COMPS_Name'] .. ']\n')
  114.  
  115.     -- Scan the active comp file for OpenCL nodes
  116.     for _,id in ipairs(OpenCLNodeList) do
  117.        local node = 0
  118.        for _,t in pairs(cmp:GetToolList(false, id)) do
  119.           t.UseOpenCL[0] = 0
  120.           node = node + 1
  121.        end
  122.  
  123.       -- List the nodes that were edited
  124.       comp:Print('\t\tDisabled OpenCL on ' .. node .. ' x ' .. id .. '\n')
  125.     end
  126.  
  127.     -- Add a spacer between each comp
  128.     comp:Print('\n')
  129.   end
  130.  
  131.   comp:Print('[Done]\n')
  132. end
  133.  
  134. -- The app:AddConfig() command that will capture the 'Control + W' or 'Control + F4' hotkeys so they will close the window instead of closing the foreground composite.
  135. app:AddConfig('OpenCLControl', {
  136.   Target {
  137.     ID = 'OpenCLControlWin',
  138.   },
  139.  
  140.   Hotkeys {
  141.     Target = 'OpenCLControlWin',
  142.     Defaults = true,
  143.  
  144.     CONTROL_W  = 'Execute{cmd = [[app.UIManager:QueueEvent(obj, "Close", {})]]}',
  145.     CONTROL_F4 = 'Execute{cmd = [[app.UIManager:QueueEvent(obj, "Close", {})]]}',
  146.   },
  147. })
  148.  
  149. comp:Print('\n[OpenCL Control] v1.0\n')
  150. comp:Print('[Created By] Andrew Hazelden <andrew@andrewhazelden.com>\n')
  151.  
  152. win:Show()
  153. disp:RunLoop()
  154. win:Hide()
  155. app:RemoveConfig('OpenCLControl')
  156.  
You do not have the required permissions to view the files attached to this post.

reinier
Posts: 12
Joined: Tue Aug 05, 2014 2:57 pm

Re: Debug Your Lua Code With Custom Fusion Console Printing Functions

#64

Post by reinier » Mon Nov 06, 2017 5:00 am

"You can write any environment variable you want in place of the words "YOUR_DEBUG_ENV_VAR" "

Hi,

I seem to be missing some basic Windows knowledge, but can't get this to work.
I created an environment variable "FUSIONSCRIPT_DEBUG" with a value like this : C:\__Fu_9_Common\Scripts\__DEBUG
Changed all instances of "YOUR_DEBUG_ENV_VAR" into the above.
But nothing happens.

BTW: thanks for this 'treasure-thread' of Fusion script info!

Reinier

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

Re: Debug Your Lua Code With Custom Fusion Console Printing Functions

#65

Post by AndrewHazelden » Mon Nov 06, 2017 6:10 am

reinier wrote:I created an environment variable "FUSIONSCRIPT_DEBUG" with a value like this : C:\__Fu_9_Common\Scripts\__DEBUG
Changed all instances of "YOUR_DEBUG_ENV_VAR" into the above.
But nothing happens.
Hi Reinier.


In that example I posted the YOUR_DEBUG_ENV_VAR environment variable was simply looking for the textual word "true" as the value.

If you don't get back the printed word "true" in the Console view when you run the following code in the Fusion Console tab, then the environment variable wasn't set up as it needed to be:

Code: Select all

debugState = tostring(os.getenv("YOUR_DEBUG_ENV_VAR"))
print(debugState)
-- Result: true
On Windows you can see a list of all active environment variables by typing "set" into the Command Prompt. On Mac/Linux typing in "env" in the terminal will show you all of the active environment variables.

From a programming perspective, the reason we are looking for the variable to be set to "true" is due to the use of this part of the code that is looking literally for the environment variable string to match the exact word "true". (Also, the ~= comparison operator in that command means any other value in the environment variable other then "true" will cause the dprintf function to print nothing at all.)

Code: Select all

dprintf = (os.getenv("YOUR_DEBUG_ENV_VAR") ~= "true") and function() end or
I hope that helps clarify things a little better.

Thanks for asking your question. It will help other people as well. :)

User avatar
Protean
Posts: 40
Joined: Mon Nov 03, 2014 12:37 pm
Location: www.axisanimation.com

Re: Building GUIs With Fusion's UI Manager

#66

Post by Protean » Mon Nov 06, 2017 9:08 am

Hi,

Regarding the combobox, I didn't see a list of functions anywhere. There is addItem() but I am looking for a way to replace all items and any other available functions.

Cheers,

J

User avatar
Protean
Posts: 40
Joined: Mon Nov 03, 2014 12:37 pm
Location: www.axisanimation.com

Re: Building GUIs With Fusion's UI Manager

#67

Post by Protean » Mon Nov 06, 2017 9:14 am

Oh well, I found Clear() in a script from this thread.

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

Re: Building GUIs With Fusion's UI Manager

#68

Post by AndrewHazelden » Mon Nov 06, 2017 11:48 am

Protean wrote:Regarding the combobox, I didn't see a list of functions anywhere. There is addItem() but I am looking for a way to replace all items and any other available functions.
Hi Protean.

Check out the FusionScript Help Browser tool. After you download and run the script in Fusion, scroll down in the class section in the GUI to the items starting with "UI" in their name near the very bottom of the list.

You will be able to visually see a list of all of the member items for each class. This gives you information about pretty much every GUI control creation and editing function you have access to in the UI Manager system.

If you also take a look at the QT window manager documentation as well for the matching type of GUI element you can often find the details needed. I typically go back and forth between the QT docs and the information in the FusionScript Help Browser to find out anything extra I need when writing a new script.

Also, if you download all of the example .lua files on the "Building GUIs With Fusion's UI Manager" posts and do a directory based content search in your programmer's text editor like Notepad++ (Windows) or BBEdit (Mac), you will find practical usage demos of most of the UI manager controls.

Cheers,
Andrew

User avatar
Protean
Posts: 40
Joined: Mon Nov 03, 2014 12:37 pm
Location: www.axisanimation.com

Re: Building GUIs With Fusion's UI Manager

#69

Post by Protean » Tue Nov 07, 2017 1:43 am

Brilliant, thanks Andrew,

That will teach me to just skim read the thread :oops:

Thanks,

John

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

Re: Building GUIs With Fusion's UI Manager

#70

Post by AndrewHazelden » Tue Nov 07, 2017 2:10 am

Protean wrote:Brilliant, thanks Andrew,
I do aim to please. :)

If you need a practical demo of any specific concept or GUI layout done using UI Manager, just post a rough sketch image of what you are trying to do and I can try to throw a basic mockup together of that layout in a .lua script.

My personal goal is that I'd really like to see WSL users succeed in porting all of their older IUP based Fusion 6.4 - 7 era GUIs over to Fusion 9 + UI Manager ASAP. It really is a beautiful and elegant GUI building system once you get to use it a bit.

Cheers,
Andrew

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

GetScriptDir.lua Example

#71

Post by AndrewHazelden » Tue Nov 14, 2017 5:22 am

Here is a Lua script example that returns the current directory name that the Lua script was run from.

This is a very handy approach to use if you want to make it possible for your Fusion based Lua UI Manager tool to be installed anywhere by the end user. Then the script is able to find the other assets (images, text files, macros, etc...) that it relies on and the GUI will work as intended.

Download the Script
GetScriptDir.lua
Installation

Step 1. Place the "GetScriptDir.lua" script in a location like your Fusion user prefs based "Script:/Comp/" pathmap folder.

Step 2. Run this script from the Fusion Script > GetScriptDir menu item.

You will see a result similar to this output printed in your Fusion Console tab:


[Lua Script Filename Table]
table: 0x0d238800
Path = /Users/andrew/Library/Application Support/Blackmagic Design/Fusion/Scripts/Comp/
FullName = GetScriptDir.lua
UNC = false
CleanName = GetScriptDir
SNum =
Extension = .lua
Name = GetScriptDir
FullPath = /Users/andrew/Library/Application Support/Blackmagic Design/Fusion/Scripts/Comp/GetScriptDir.lua

[Current Lua Script Filepath] /Users/andrew/Library/Application Support/Blackmagic Design/Fusion/Scripts/Comp/GetScriptDir.lua
[Current Lua Script Folder] /Users/andrew/Library/Application Support/Blackmagic Design/Fusion/Scripts/Comp/
[Current Lua Script File Name] GetScriptDir.lua
[Current Lua Script Basename No Extension] GetScriptDir
You do not have the required permissions to view the files attached to this post.

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

ProgressGUI Example

#72

Post by AndrewHazelden » Sat Nov 18, 2017 12:48 pm

This Lua script example creates a progress window using Fusion 9's UI Manager library.

I think the example is interesting because it shows how you can use two functions to interact with the window. One function creates the new window and returns pointers to the window, and to the win:GetItems() based controls in the view. Then the 2nd function allows you to update the view as you run through a loop in your script.

The two progress bar cell "on" and "off" image elements in the script were created from PNG images that were converted into base64 encoded strings. This was done using a technique presented by Dunn that was discussed on the "HTML Image Source Example" UI Manager post here:
viewtopic.php?f=6&t=1411&p=10500#p10500

Animated Screenshot
ProgressGUI.gif
Usage

Step 1. Copy this script to the Fusion user prefs Scripts:/Comp folder.

Step 2. Run the script in Fusion by selecting the "Script > ProgressGUI" menu item.

Download ProgressGUI
ProgressGUI.lua
You do not have the required permissions to view the files attached to this post.

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

RandomizeNodeColors.fu Event Example

#73

Post by AndrewHazelden » Mon Nov 20, 2017 6:20 am

randomized-node-colors.png
Overview
The "RandomizeNodeColors.fu" config file applies a random TileColor setting to every new node that is added to the comp. This is done with a new .fu file based Event{} entry that intercepts the native AddTool action by appending our own custom Lua code.

The key part of this event example is the line:

rets = self:Default(ctx, args)

If you place your own custom code above that line in the Event{} block, Fusion will run your Lua command just before it carries out the action. If you place your own custom code after the that line in the Event{} block, Fusion will run your Lua commands just after the action occurs.

A .fu file based Event{} entry is the new Fusion 9 centric replacement for the previous Fusion 7.x era "Events and Callbacks" technique. The older event system was described in the "Fusion 8 Scripting Guide.pdf" file on page 25.

Installation

Copy the RandomizeNodeColors.fu file to the Fusion user prefs "Config:/RandomizeNodeColors.fu" PathMap folder.

Restart Fusion for the example to be activated.

When you add new nodes to your composite they will be created with a new node TileColor each time.
Code: [Select all] [Expand/Collapse] [Download] (RandomizeNodeColors.fu)
  1. --[[--
  2. ==============================================================================
  3. RandomizeNodeColors.fu - v1.0 2017-11-20
  4. ==============================================================================
  5. Created by : Andrew Hazelden [andrew@andrewhazelden]
  6.  
  7. ==============================================================================
  8. Overview
  9. ==============================================================================
  10. The "RandomizeNodeColors.fu" config file applies a random TileColor setting to every new node that is added to the comp. This is done with a new .fu file based Event{} entry that intercepts the native AddTool action by appending our own custom Lua code.
  11.  
  12. The key part of this event example is the line:
  13.  
  14. rets = self:Default(ctx, args)
  15.  
  16. If you place your own custom code above that line in the Event{} block, Fusion will run your Lua command just before it carries out the action. If you place your own custom code after the that line in the Event{} block, Fusion will run your Lua commands just after the action occurs.
  17.  
  18. A .fu file based Event{} entry is the new Fusion 9 centric replacement for the previous Fusion 7.x era "Events and Callbacks" technique. The older event system was described in the "Fusion 8 Scripting Guide.pdf" file on page 25.
  19.  
  20. ==============================================================================
  21. Installation
  22. ==============================================================================
  23. Copy the RandomizeNodeColors.fu file to the Fusion user prefs "Config:/RandomizeNodeColors.fu" PathMap folder.
  24.  
  25. Restart Fusion for the example to be activated.
  26.  
  27. When you add new nodes to your composite they will be created with a new node TileColor each time.
  28.  
  29. ==============================================================================
  30. Listing all of the Actions
  31. ==============================================================================
  32. Here is a short code chunk you can use to print out a list of all the actions that exist in Fusion. This is handy information to know if you want to try adding a new event that is used to override the normal operaton of a action:
  33.  
  34. -- Track the actions that are available in Fusion
  35. local actionList = fu.ActionManager:GetActions()
  36.  
  37. -- List each action sequentially
  38. actionCount = 0
  39. for i, act in ipairs(actionList) do
  40.     if not act:Get('Parent') then
  41.         print(act.ID)
  42.         actionCount = actionCount + 1
  43.     end
  44. end
  45.  
  46. -- Count the total number of actions
  47. print('[' .. actionCount .. ' Actions Found]')
  48.  
  49. ==============================================================================
  50. Further Action Reference Material
  51. ==============================================================================
  52. You can take the Event {} action intercepting concept that is demonstrated in this example file further by applying it to any other action that exists in Fusion.
  53.  
  54. The We Suck Less Forum based UI Manager Thread has a script called Action Listener that lets you inspect actions as they happen in your composite:
  55. https://www.steakunderwater.com/wesuckless/viewtopic.php?f=6&t=1411&p=11465#p11465
  56.  
  57. ==============================================================================
  58. --]]--
  59.  
  60. {
  61.     Event {
  62.         -- Add a new event that intercepts the AddTool{} Action
  63.         Action = "AddTool",
  64.         Targets = {
  65.             Composition = {
  66.                 Execute =
  67.                     [[
  68.                     -- Generate a random value from 0-1 that fits within a threshold zone
  69.                     -- This is used to limit the color palette possibilites and reduce the contrast
  70.                     -- Example: ColorRange(0.25)
  71.                     function ColorRange(threshold)
  72.                         val = (math.random() * tonumber(threshold)) + (1-tonumber(threshold))
  73.                         return val
  74.                     end
  75.  
  76.                     -- Randomize the Node TileColor
  77.                     -- Example: RandomColor(tool, 0.5)
  78.                     function RandomColor(node, range)
  79.                         node.TileColor = {R=ColorRange(range), G=ColorRange(range), B=ColorRange(range)}
  80.                         node.TextColor = {R=0, G=0, B=0}
  81.                     end
  82.                    
  83.                     -- Print out details for the newly created node
  84.                     function PrintDetails(node)
  85.                         color = string.format("{R=%.04f, G=%.04f, B=%.04f}", node.TileColor.R, node.TileColor.G, node.TileColor.B)
  86.                         print("[Name] " .. tostring(node.Name) .. " [Type] " .. tostring(node:GetAttrs().TOOLS_RegID) .. " [Tile Color] " .. color)
  87.                     end
  88.  
  89.                     -- Run the AddTool Action
  90.                     rets = self:Default(ctx, args)
  91.                    
  92.                     -- Adjust the Node Color
  93.                     tool = rets.tool
  94.                     RandomColor(tool, 0.5)
  95.                     -- PrintDetails(tool)
  96.  
  97.                     -- If AddTool{} creates an extra node like a Merge or Merge3D node randomize its color as well
  98.                     selectedNode = obj:Comp().ActiveTool
  99.                     if selectedNode ~= tool then
  100.                         RandomColor(selectedNode, 0.5)
  101.                         -- PrintDetails(selectedNode)
  102.                     end
  103.                     ]]
  104.             },
  105.         },
  106.     },
  107. }
You do not have the required permissions to view the files attached to this post.

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

Window Snap

#74

Post by AndrewHazelden » Sun Nov 26, 2017 8:10 am

Overview

A Lua script example that uses several ui:Button controls to quickly snap a UI Manager based window to the top/bottom/left/right/center edges of the Fusion window.

Download
Window-Snap-v1.zip
Screenshot
Window-Snap-Screenshot.png
Demo Video



Usage

Step 1. Copy the "Window Snap" folder to the Fusion user prefs "Scripts:/Comp/Window Snap/" location.

Step 2. Open the Fusion Preferences. Switch to the "Global and Default Settings > Layout" Section. At the top of the window is a Program layout area. Click on the "Grab program layout" button. Then click the "Save" button to close the Preferences window. This saves out a "Global.Main.Window" preference entry.
Fusion Layout - Grab Program Layout.png
Step 3. Run the script in Fusion by selecting the "Script > Window Snap > Window Snap" menu item.

Development Notes

The icon images displayed in the window are loaded relative to the Window Snap script's filepath location using the technique presented in the "GetScriptDir.lua" script:

Code: Select all

-- Read the parent folder that holds the current "Window Snap.lua" script
------------------------------------------------------------------------
-- Return a string with the directory path where the Lua script was run from
-- scriptTable = GetScriptDir()
function GetScriptDir()
  return bmd.parseFilename(string.sub(debug.getinfo(1).source, 2))
end

local fileTable = GetScriptDir()
print("[Lua Script Filename Table]")
dump(fileTable)
Result:

Code: Select all

[Lua Script Filename Table]
table: 0x0d238800
  Path = /Users/andrew/Library/Application Support/Blackmagic Design/Fusion/Scripts/Comp/Window Snap/
  FullName = Window Snap.lua
  UNC = false
  CleanName = Window Snap
  SNum = 
  Extension = .lua
  Name = Window Snap
  FullPath = /Users/andrew/Library/Application Support/Blackmagic Design/Fusion/Scripts/Comp/Window Snap/Window Snap.lua
You can read the previously saved Fusion window position using:

Code: Select all

mainWindow = fusion:GetPrefs("Global.Main.Window")
dump(mainWindow)
--  table: 0x534f6cb0
--    Left = 1542
--    Width = 1835
--    Top = 45
--    UseWindowsDefaults = false
--    Mode = 1
--    Height = 1214
The "CenterIconButton" ui:Button icon image is updated on the fly using:

Code: Select all

-- Generate a table with the absolute filepaths for the icons
local icons = IconsTable()
  
-- Toggle the center icon to a collapse icon
itm.CenterIconButton:SetIcon(ui:Icon{
  ID = "CollapseIcon", 
  File = icons.collapse
})
You do not have the required permissions to view the files attached to this post.

User avatar
SirEdric
Fusionator
Posts: 1756
Joined: Tue Aug 05, 2014 10:04 am
Answers: 1
Real name: Eric Westphal
Been thanked: 80 times
Contact:

Re: Building GUIs With Fusion's UI Manager

#75

Post by SirEdric » Sun Dec 17, 2017 2:33 am

Sorry for asking stooopidly, but is there any chance to set the height of (e.g.) a button to a fixed value?
When I just create a window with two buttons, they basically fill the entire window (which looks odd).
On adding more elements, all elements are scaled to the same height to fill the window.

But I want to tell each element exactly how much space it should consume.
There has to be a way, but neither "Height=" or "Weight=" seem to do the trick.

Cheers.

Eric.