Auto applying a template between loader and saver

Moderator: SecondMan

RBemendo
Fusioneer
Posts: 152
Joined: Fri Dec 12, 2014 11:32 am
Been thanked: 1 time

Auto applying a template between loader and saver

#1

Post by RBemendo » Sat Aug 18, 2018 7:08 am

With Fusion Connect clips or with resolve 15 is there a way to automate a template of nodes between the loader and saver? I have projects with 600-700 composites and most of them are based off of a template. So disconnecting the loader from the saver, pasting the template in between and relinking the last node to the saver is a huge time waster.

Anyone have thoughts for this?

User avatar
ShadowMaker SdR
Fusionista
Posts: 614
Joined: Sun Sep 21, 2014 6:17 am
Answers: 3
Been thanked: 13 times

Re: Auto applying a template between loader and saver

#2

Post by ShadowMaker SdR » Sat Aug 18, 2018 1:44 pm

I am not at my Fusion computer right now, but there used to be a script that did this, I think it was called convert footage and it might be still in Reactor in the 'legacy' script department. I don't recall exactly how it worked, but you could point the script to a folder with footage and it would go through the folder one by one and use a template in the same way you describe. Have you installed Reactor yet? That's where I'd look first.

RBemendo
Fusioneer
Posts: 152
Joined: Fri Dec 12, 2014 11:32 am
Been thanked: 1 time

Re: Auto applying a template between loader and saver

#3

Post by RBemendo » Sun Aug 19, 2018 5:24 am

Thanks ShadowMaker, I do have Reactor installed and not seeing any thing resembling a script named "convert footage". A quick search started leading me down the path of the CSV script but couldn't find any updated information on it.

My current workflow is for Resolve 14 and Fusion 9, but I think the ideal workflow once I move to Resolve 15 would be to select multiple comps in the resolve timeline create individual fusion connect clips and/or the Fusion tab, and receive a a UI manager that allows you to select what template you want to include between the loader and saver. This way setting up the pipeline for what artist is working on what shot, the basic shot structure and template is automatically applied.

Or even one further, if you could log footage at the start of a project and add a metadata keyword that the script would look for when creating the template. So if you used portions of the same clip multiple times the metadata would be on the entire clip and the Fusion script would know each multiple clip gets the same template applied. Also, adding the script and having the option to automatically send it to the render farm as a preview file or final render.

User avatar
Midgardsormr
Fusionator
Posts: 1020
Joined: Wed Nov 26, 2014 8:04 pm
Answers: 1
Location: Los Angeles, CA, USA
Been thanked: 53 times
Contact:

Re: Auto applying a template between loader and saver

#4

Post by Midgardsormr » Sun Aug 19, 2018 8:08 am

Save the template's nodes as a .setting file. Upon loading your Fusion Connect comp, add the .setting to the comp as though it were a macro. Then connect the Loader and Saver to the appropriate nodes.

This line will paste the .setting file:
comp:Paste(bmd.readfile(path))

Get the Loader and Saver from your comp like so:
LDR = comp:GetToolList(false, "Loader")[1]
SVR = comp:GetToolList(false, "Saver")[1]

Supposing you had some nodes named IN and OUT, you could connect your Loader like so:
IN.Input:ConnectTo(LDR.Output)

And to connect the Saver:
SVR.Input:ConnectTo(OUT.Output)

You may then need to reposition the Loader and Saver to line them up to the template:
x, y = comp.CurrentFrame.FlowView:GetPos(IN)
comp.CurrentFrame.FlowView:SetPos(LDR, x - 1, y)
x, y = comp.CurrentFrame.FlowView:GetPos(OUT)
comp.CurrentFrame.FlowView:SetPos(SVR, x + 1, y)

User avatar
ShadowMaker SdR
Fusionista
Posts: 614
Joined: Sun Sep 21, 2014 6:17 am
Answers: 3
Been thanked: 13 times

Re: Auto applying a template between loader and saver

#5

Post by ShadowMaker SdR » Sun Aug 19, 2018 8:59 am

You can find the script in question here:

https://www.steakunderwater.com/VFXPedi ... yeonscript

It's still the old pre-BMD version, but you can download it, change the extension to *.lua and see if it works.
If it doesn't, it shouldn't be too difficult for those of us with scripting knowledge to adapt it to work in 9.x/Resolve.
I remember using it in the past and it's really efficient and user friendly. I'm pretty sure it will do exactly what you need it to do.
Code: [Select all] [Expand/Collapse] [Download] (Convert Footage.lua)
  1. ------------------------------------------------------------------------------------------------
  2. --      Convert Footage.eyeonscript,Revision 8
  3. --
  4. --
  5. --      Comp script for Eyeon Fusion or Rotation
  6. --
  7. --      by  peter@wwfx.net
  8. --
  9. --      Created Jun 2004
  10. --      Update Nov 03 2005 - Port to Fusion 5
  11. --      Update Jul 20 2006 - include some utility functions and added convertion between all known to fusion fileformats
  12. --      Update Aug 02 2006 - can work without templates, switching views in verbose mode.
  13. --      Update Sep 27 2006 - fixed fusion crash after creating the flows.
  14. --      Update Aug 09 2007 - Can use Fusion Slave or another Full Fusion on the network, to assemble and render comps.
  15. --                 - Can be launched from Rotation and Learning Edition.
  16. --              Update Aug 06 2010 - fixed fusion crash after creating the flows. The last created flow will remain active. Results are printed in console of comp from which script was executed.
  17. --
  18. --      requires:   eyeon.scriptlib, Rotation or Fusion LE
  19. --
  20. ------------------------------------------------------------------------------------------------
  21.  
  22. --[[
  23.  
  24. The script was made to automate creating of reference clips from firewire drives with film footage.
  25. It can be used to search recursive(or not) any folder for footage that Fusion can load
  26. and convert it to any other file format fusion can write to.
  27.  
  28. Some features:
  29.  
  30.     - Template comps. You can to create custom template comps, adjust bc,size,e.t.c. and use them for batch conversions.
  31.     - Can store specific loader's settings and apply them to loaders in generated comps. This is done via list of loader inputs which can be edited (arround line 530, table "keep").
  32.     - Choice for names of new clips and comps. They can be either source sequence name or its folder. Checks for duplicate names and append parent folder to name until it become unique.
  33.     - choosing queue group for created comps and submit them to render master.
  34.     - In verbose mode - current processed footage is displayed on fusion views, while creating the comp..
  35.     - Can create single jpg still from the middle of the sequence.(i.e. for web thumbs)
  36.  
  37. ------------------------------------------------------------------------------------------------
  38.  
  39.     INSTALL
  40.  
  41.     1.  Place Convert footage.eyeonscript in your fusions script directory.
  42.     2.  If using templates - path to template comps must be provided  in ('templates_path' variable)
  43.  
  44. ------------------------------------------------------------------------------------------------
  45.  
  46.     USAGE
  47.  
  48. You can use this without woring about templates, e.t.c. Templates are valuable, when loader must have some special predefined options
  49. i.e, ByPass convertion,spec import modes, also when resizing source footage or modifying it with bc..
  50. When not using templates, simple loader->saver comp will be generated, optionaly with framecounter.
  51. In verbose mode  script prints more info about what is hapening and also shows current sequence in fu views, but that takes more time to finish.
  52. When generating names for new comps and saver clips, there is a check to escape duplicate names.
  53. Name of next parent folder is included to clip name, until name becomes uniqie.
  54. i.e. scanning c:\my docs    for *.jpg and we have found those:
  55.     c:\my docs\folder.jpg
  56.     c:\my docs\band\folder.jpg
  57. I this case output comp and clip names will be set to:
  58.     folder.jpg
  59.     band_folder.jpg
  60. This is only if script find duplicate clip names.
  61. ------------------------------------------------------------------------------------------------
  62.  
  63.     CREATING NEW TEMPLATES
  64.  
  65. Provided template can be customized assuming existing tool names are not changed:
  66. LDR,SQ,JPG,MergeCounter,Counter - those are required by the script.
  67. If you dont need counter, script will work without it and its merge.
  68. The most important to keep are the loader(LDR) and savers(SQ,JPG). Between them you can put any other tools you need.
  69.  
  70. Place new templates in template folder - they will be listed in script dialog so you can choose them from there.
  71.  
  72. If you need to make two quicktimes, leave SQ to be set by script and add saver called MOV, point it to directory of your choice. Script will change only the clipname in the second saver.
  73.  
  74. ]]
  75.  
  76.  
  77. --=========================       CONFIGURATION START    =========================--
  78.  
  79. templates_path = [[\\main\Comps\[ Templates ]\]]
  80. --templates_path = MapPath("Comps:") .. "[ Templates ]" -- i.e. C:\Program Files\Fusion\Comps\[ Templates ]
  81.  
  82. --=========================     CONFIGURATION   END     =========================--
  83.  
  84.  
  85.  
  86. if (not comp) then
  87.     print("--\nConvert Footage is COMPOSITION SCRIPT.\n"
  88.     .."To use it, please move it to:\n"
  89.     ..Fusion():GetPrefs().Global.Paths.Scripts.."\Comp"
  90.     .."\nopen new comp and look for \"Convert Footage\" in the script menu :)\n--")
  91.     do
  92.         return
  93.     end
  94. end
  95. local addslash  =   function (th)
  96.     if string.sub(th, - 1, - 1) ~= "\\" then
  97.         return
  98.         (th.. "\\")
  99.     else
  100.         return
  101.         th
  102.     end
  103. end
  104. local GetFormats    =   function()
  105.     formats,result,movs = FusionRemote:GetRegList(CT_ImageFormat),{},{}
  106.     for ik  in  pairs(formats)      do
  107.             f,ismovie = formats[ik]:GetAttrs().REGST_MediaFormat_Extension,
  108.                         formats[ik]:GetAttrs().REGB_MediaFormat_CanLoadMulti
  109.             to = table.getn(f)
  110.             for mm, to in f do
  111.                 if (ismovie == true) then
  112.                     table.insert(movs, f[mm])
  113.                 end
  114.                 table.insert(result, f[mm])
  115.             end
  116.         end
  117.         table.sort(result)
  118.     return
  119.     result, movs
  120. end
  121. local file_exists   =   function(th)  --    for unc, local dirs and files
  122.     if not th then
  123.         return false
  124.     end
  125.     if fileexists(th) then
  126.         return true
  127.     end
  128.     if string.sub(th, - 1, - 1) == "\\" then
  129.          b,s=(string.sub(th, 1, string.len(th) - 1)),(th)
  130.     else
  131.          b,s=th,th.."\\"
  132.     end
  133.     return(direxists(b) or direxists(s))
  134. end
  135. local pm = function(message)    print(string.rep('-', 50),("\n\t" .. message.."\n"))  end
  136. function ScanDir(dir, mask, recursive)
  137.     dir,    maxlen, clips = addslash(dir),  (maxlen or 0),  (clips or {})
  138.     local files = readdir(dir .. '*')
  139.     local tt,   temp = table.getn(files),   {}
  140.     if (tt > maxlen) then
  141.         maxlen = tt
  142.     end
  143.     for i = 1, tt do
  144.         --fi,       e = string.lower(dir .. files[i].Name),     nil
  145.         fi,     e = dir .. files[i].Name,   nil
  146.         if (files[i].IsDir == true and recursive == 1 and files[i].IsSystem == false) then
  147.             ScanDir(fi, mask, recursive)
  148.         else
  149.             string.gsub(fi, "^(.+)(%..+)$", function(n, E) e = E end)
  150.             if (fi and e) then
  151.                 if ((e == mask) or (mask == '*')) then
  152.                     local seq = eyeon.parseFilename(fi)
  153.                     if (eyeon.isin(movs, mask) == true) then
  154.                         t = seq.FullPath
  155.                     else
  156.                         t = seq.CleanName
  157.                     end
  158.                     if (eyeon.isin(temp, t) == false) then
  159.                         printf("%0s %8s", '->', seq.Path .. seq.FullName)
  160.                         table.insert(clips, seq)
  161.                         table.insert(temp, t)
  162.                         t = nil
  163.                     end
  164.                 end
  165.             end
  166.         end
  167.     end
  168.     scanned = (scanned or 0) + 1
  169. end
  170. myscriptprefs = function(op)
  171.  
  172.     local _scriptname=eyeon.split(debug.getinfo(1).source,[[/]])
  173.     local _scriptname=_scriptname[table.getn(_scriptname)]
  174.     local prefname  =   _scriptname..[[.ScriptPrefs]]
  175.  
  176.     cpath   =   fusion:MapPath("Profile:")..([[ScriptPrefs\]])
  177.  
  178.     local cfg       =   cpath..prefname
  179.    
  180.     pm("Using: "..cfg)
  181.    
  182.     if op and op=='write' then
  183.       if not fileexists(cpath) then
  184.         createdir(cpath)
  185.       end
  186.     file,err = io.open(cfg, "w + ")
  187.     if file then
  188.       local h="-- Script preferences for ".._scriptname.."\n-- generated by ".._scriptname.."\n\n"
  189.           file:write(h .. "_cfs = {}\n")
  190.           for i, v in _cfs do
  191.               if (type(v) == "string") then
  192.                   file:write("_cfs[\"" .. i .. "\"]= [["..v.."]]\n")
  193.               elseif (type(v) == "boolean" or type(v) == "number") then
  194.                   file:write("_cfs[\"" .. i .. "\"]= " .. v .. "\n")
  195.               end
  196.           end
  197.       end
  198.       file:close()
  199.       file = nil
  200.     else
  201.       if (fileexists(cfg)) then
  202.           dofile(cfg)
  203.           if (type("_cfs") == nil) then
  204.               return
  205.               {}
  206.           end
  207.       else
  208.           return
  209.           {}
  210.       end
  211.     end
  212. end
  213. function alert(message)
  214.     _ALERT(message)
  215.     ret = AskUser("Alert!", {{"", "Text", Wrap=false, Lines=15,Default = message,Width=2}})
  216.     return ret
  217. end
  218. function getToolPositions(c)  --Fusion 5.2 and up. returns nil if 5.1 or lower
  219.     local positions =   {}
  220.     if not c.CurrentFrame then do return nil end end
  221.     local grid      =   c.CurrentFrame.FlowView
  222.     if not grid then do return nil end end
  223.     local grattr    =   grid:GetAttrs()
  224.     if grattr.VIEWN_Top then
  225.         grid:SetScale(0.5)
  226.         for i, tool in c:GetToolList() do
  227.             name    =   tostring(tool:GetAttrs().TOOLS_Name)
  228.             x,y =   c.CurrentFrame.FlowView:GetPos(tool)
  229.             positions[name]={["x"]=x,["y"]=y}
  230.         end
  231.     return positions
  232.     end
  233.  return nil
  234. end
  235. --========================   end utils
  236. local fta=fusion:GetAttrs()
  237. _cfs={}
  238. pm('local: '..fta.FUSIONS_FileName,' version ',fta.FUSIONS_Version,' with ',_G["_VERSION"])
  239. LocalIsFusion       =   eyeon.isin(split(fta.FUSIONS_FileName,'\\'),'Fusion.exe') and not (fta.FUSIONB_IsDemo==true)
  240. remote = comp:AskUser("", {
  241. {"", "Text", Wrap=true, Lines=3,Default ='Remote or local hostname/IP address with  Fusion or Render Slave to use:',Width=1},
  242. {"host", "Text", Wrap=false, Lines=1,Default ='localhost',Width=1},
  243. })
  244. if not remote then
  245. alert('Script aborted.')
  246.     do return end
  247. end
  248. FusionRemote=Fusion(remote['host'])
  249. if not FusionRemote then
  250.     alert('Can\'t connect to fusion instance')
  251.     do return end
  252. end
  253. local fa=FusionRemote:GetAttrs()
  254. pm(fa.FUSIONS_FileName,' version ',fa.FUSIONS_Version,' with ',_G["_VERSION"])
  255. local o=split(fa.FUSIONS_FileName,'\\')
  256. IsRotation  =   eyeon.isin(o,'Rotation.exe')
  257. IsSlave     =   eyeon.isin(o,'RenderSlave.exe') or eyeon.isin(o,'ConsoleSlave.exe')
  258. IsFusion    =   eyeon.isin(o,'Fusion.exe')
  259. IsVision    =   eyeon.isin(o,'Vision.exe')
  260. --========================
  261. ccomp = fusion.GetCurrentComp() or fusion:GetCurrentComp()
  262. frame = ccomp:GetFrameList()[1]
  263. frame:SwitchMainView('ConsoleView')  -- take users attention.
  264. _cfs,   templates_path, tpl = myscriptprefs('read'),    fusion:MapPath(addslash(eyeon.trim(templates_path))),   {}
  265. local exts,movs = GetFormats()
  266. if table.getn(exts)==0 then
  267. alert('Can\'t get list of file formats, aborting the srcipt!')
  268. do return end
  269. end
  270. exts2=exts
  271. exts2[table.getn(exts) + 1] = '- none -'
  272. if (file_exists(templates_path) == false) then
  273.     _cfs.ut = 0
  274.     _ale=[[The path to templates:\n
  275. --------------------------------------------------\n
  276. ]] .. (templates_path or '') .. [[
  277. --------------------------------------------------\n
  278. set in the beginig of this script is NOT VALID!
  279. If you want to use your own templates:
  280. [1].    Configure script :
  281. ]]..debug.getinfo(1).source..[[
  282. by editing it with text editor.
  283. Type there the path to templates.
  284. [2].    Run the script without templates once.
  285. Simple loader->merge->counter->saver comps will be generated.
  286. Copy those to your templates path. Adjust them to suit your needs,
  287. without changing names of existing tools, so script can find and set them later.
  288. [3]. Run the script again - you should see menu with your template comps.
  289. If you continue script will continue
  290. with creating basic template with loader->saver
  291. ]]
  292.     alert(_ale)
  293. else
  294.     k = readdir(templates_path .. '*.comp')
  295.     if ((table.getn(k)) == 0) then
  296.         alert("No templates found in:\n" .. templates_path .. ".\n\nScript will use internal ones on the fly :)")
  297.         _cfs['ut'] = 0
  298.     else
  299.         for i = 1, table.getn(k) do
  300.             table.insert(tpl, k[i].Name)
  301.         end
  302.     end
  303. end
  304.  
  305. if ((file_exists(_cfs['Destination'])) == false) then
  306.     _cfs['Destination'] = ''
  307. end
  308.  
  309. if ((file_exists(_cfs['flws'])) == false) then
  310.     _cfs['flws'] = ''
  311. end
  312.  
  313. if ((file_exists(_cfs['sequence'])) == false) then
  314.     _cfs['sequence'] = ''
  315. end
  316. if FusionRemote.RenderManager then
  317.     g   =   FusionRemote.RenderManager:GetGroupList() or {'all'}
  318.     else
  319.     g={'all'}
  320. end
  321.  
  322. opts = {
  323.     {
  324.         "sequence",
  325.         Name = "Scan directory:",
  326.         "PathBrowse",
  327.         Default = (_cfs["sequence"]or ""),
  328.     },{
  329.         "recurse",
  330.         Name = "Recurse? ",
  331.         "Checkbox",
  332.         Default = (_cfs["recurse"]or 1),
  333.         Width = 0.5,
  334.     },{
  335.         "mask",
  336.         Name = "Search for:",
  337.         "Dropdown",
  338.         Options = exts,
  339.         Default = (_cfs["mask"]or 17),
  340.     },{
  341.         "sq",
  342.         Name = 'Convert to:',
  343.         "Dropdown",
  344.         Options = exts2,
  345.         Default = (_cfs["sq"]or 0),
  346.     },{
  347.         "Destination",
  348.         Name = "Save clips to:",
  349.         "PathBrowse",
  350.         Default = (_cfs["Destination"]or ""),
  351.     },{
  352.         "ut",
  353.         Name = "Use templates?",
  354.         "Checkbox",
  355.         NumAcross = 2,
  356.         Default = (_cfs["ut"]or 1),
  357.     },{
  358.         "Comps",
  359.         Name = "Template:",
  360.         "Dropdown",
  361.         Options = tpl,
  362.         Default = (_cfs["Comps"]or ""),
  363.     },{
  364.         "compnames",
  365.         Name = "New clip names:",
  366.         "Dropdown",
  367.         Options ={
  368.             'using sequence name',
  369.             'using folder',
  370.             'using parent folder (1 level up)',
  371.         },
  372.         Default = (_cfs["compnames"]or ""),
  373.     },{
  374.         "jpeg",
  375.         Name = "Make JPG still? ",
  376.         "Checkbox",
  377.         Default = (_cfs["jpeg"]or 1),
  378.         Width = 0.5,
  379.     },{
  380.         "jpegs",
  381.         Name = "JPG Width",
  382.         "Slider",
  383.         Default = (_cfs["jpegs"]or 720),
  384.         Integer = true,
  385.         Min = 120,
  386.         Max = 2000,
  387.         Width = 0.5
  388.     },{
  389.         "counter",
  390.         Name = "Make counter? ",
  391.         "Checkbox",
  392.         Default = (_cfs["counter"]or 1),
  393.         Width = 0.5,
  394.     },{
  395.         "flws",
  396.         Name = "Save generated comps in:",
  397.         "PathBrowse",
  398.         Default = (MapPath(_cfs["flws"]) or ""),
  399.     },{
  400.         "QueueNow",
  401.         Name = "Send to RenderManager?",
  402.         "Checkbox",
  403.         Default = (_cfs["QueueNow"]or 0),
  404.         Width = 0.7,
  405.     },{
  406.         "Submit comps paused",
  407.         Name = 'Paused?',
  408.         "Checkbox",
  409.         Default = (_cfs["Paused"]or 1),
  410.         Width = 0.3,
  411.     },{
  412.         "gs",
  413.         Name = 'Use slaves:',
  414.         "Dropdown",
  415.         Options = g,
  416.     },
  417. }
  418.  
  419. ret = comp:AskUser("Convert footage", opts)
  420. if (not ret) then
  421.     pm('Aborting the script..')
  422.     do
  423.         return
  424.     end
  425. end
  426.  
  427. if (table.getn(g)) then
  428.     groups = g[ret.gs + 1]
  429. else
  430.     groups = "local,all"
  431. end
  432.  
  433. ret.Destination,    ret.sequence,   ret.flws =  addslash(MapPath(ret.Destination)), addslash(MapPath(ret.sequence)),    addslash(MapPath(ret.flws))
  434. if (ret.sequence == [[\]])  or (ret.flws == [[\]])  or (ret.Destination == [[\]]) then
  435.     alert('\n\n\n\tAborting the script, please provide VALID PATHS.')
  436.     do
  437.         return
  438.     end
  439. elseif ((ret.jpeg == 0) and (exts2[ret.sq + 1]== '- none -')) then
  440.     alert('No output format selected.\n\n (sequence or single jpg)\n\nAborting the script.')
  441.     do
  442.         return
  443.     end
  444. elseif ((file_exists(ret.flws)) == false) then
  445.     alert('Folder for saving new comps does not exist!\n' .. ret.flws)
  446.     do
  447.         return
  448.     end
  449. end
  450. _cfs,   mask = ret, exts[ret.mask + 1]
  451. myscriptprefs('write')
  452. if (fusion:GetPrefs().Global.Network.ServerName == 'localhost') then
  453.     fusion.RenderManager:SetAttrs({ RQUEUEB_Paused = true, })
  454.     warnrm = true
  455.     pm('RenderManager : PAUSED.')
  456. end
  457.  
  458. pm('Searching for '..mask..',please wait...')
  459. if FusionRemote.CacheManager then FusionRemote.CacheManager:Purge() end
  460. local t1 = os.time()
  461. ScanDir(ret.sequence, mask, ret["recurse"])
  462. local cl, timescan = table.getn(clips), os.difftime(os.time(), t1)
  463. local secs = math.mod(timescan, 60)
  464. local mins = (timescan - secs) / 60
  465. local time1 = mins .. 'm. ' .. secs .. 's. '
  466. if (cl > 0) then
  467.     pm(cl .. ' clips found in ' .. scanned .. ' dirs.\n\tTime: ' .. time1 .. '\nLongest clip has '..maxlen..'\nCreating comps, please wait...')
  468. else
  469.     alert('No ' .. mask .. ' files found in \n' .. ret.sequence .. '\nTime to search:' .. time1)
  470.     do
  471.         return
  472.     end
  473. end
  474. local t2,   user = os.time(),   (os.getenv("USERNAME") or '')
  475. local userinfo = user .. ' at ' .. os.getenv("COMPUTERNAME")
  476. if (ret.ut == 0 or (table.getn(tpl) == 0)) then
  477.     pm('Creating base comp..')
  478.     -- NewComp([boolean quiet[, boolean: autoclose[, boolean: hidden]]])
  479.  
  480.     c = FusionRemote:NewComp(true, true, false) or false
  481.     pos =   getToolPositions(c) or nil
  482.     if not c then do return end end
  483.     SetActiveComp(c)    --SetAttrs({ COMPN_GlobalStart = 1, COMPN_RenderStart = 1 })
  484.     Lock()
  485.     UpdateMode = "All"
  486.     LDR = Loader({ Clip = '' })
  487.     LDR:SetAttrs({TOOLS_Name = "LDR"})
  488.     out = LDR.Output
  489.     if pos then
  490.         c.CurrentFrame.FlowView:SetPos(LDR,0.1,1.1)
  491.     end
  492.     if (ret.counter==1 and (not IsRotation)) then
  493.         Counter=TextPlus{ Center = { 0.9, 0.08}, StyledText=TimeCode{Mins = 0, Hrs = 0, Secs = 0, Flds = 0, Frms = 1}}
  494.         Counter:SetAttrs{ TOOLS_Name = "Counter" }
  495.         MergeCounter = Merge({Background = out, Foreground =Counter.Output})
  496.         MergeCounter:SetAttrs({TOOLS_Name = "MergeCounter"})
  497.         out = MergeCounter.Output
  498.         if pos then
  499.             c.CurrentFrame.FlowView:SetPos(MergeCounter,2,1)
  500.             c.CurrentFrame.FlowView:SetPos(Counter,2,2)
  501.         end
  502.     end
  503.     if (not(exts2[ret.sq + 1]== '- none -')) then
  504.         SQ = Saver({Clip = '', Input = out})
  505.         SQ:SetAttrs({TOOLS_Name = "SQ"})
  506.         if pos then
  507.             c.CurrentFrame.FlowView:SetPos(SQ,4,1)
  508.         end
  509.     end
  510.     if (ret.jpeg == 1) then
  511.         RSZ = BetterResize({Width = ret['jpegs'], Input = out, KeepAspect = 1, Comments = 'Web thumb size.'})
  512.         JPG = Saver({Clip = '', Input = RSZ.Output})
  513.         JPG:SetAttrs({TOOLS_Name = "JPG"})
  514.         if pos then
  515.             c.CurrentFrame.FlowView:SetPos(RSZ,3,2)
  516.             c.CurrentFrame.FlowView:SetPos(JPG,4,2)
  517.         end
  518.     end
  519.     for i, tl in c:GetToolList() do
  520.         tl.TileColor = {R = 1,G = 1,B = 1}
  521.         tl.TextColor = {R = 0,G = 0,B = 0}
  522.         tl.Comments = (tl.Comments or '') .. '\ndon\'t change my name please..'
  523.     end
  524. else
  525.     templatecomp = templates_path .. tpl[ret.Comps + 1]
  526.     pm('Loading template: ' .. templatecomp)
  527.     c = FusionRemote:LoadComp(templatecomp, true,true,true) or false
  528.  
  529.     if (c == false) then
  530.         alert('Unable to load template comp\n\nAborting the script.Please check that file exists and all tools can be loaded.')
  531.         do
  532.             return
  533.         end
  534.     end
  535.  
  536.     if ((not c.JPG) and (not c.SQ)) or(not c.LDR) then
  537.         alert('This comp can not be used as template.\n' .. 'There are missing default tools.\n' .. 'Make sure loader witn name LDR present, and saver with name SQ or JPG')
  538.         do
  539.             return
  540.         end
  541.     end
  542.     SetActiveComp(c)
  543.     c:Lock()
  544.     c.UpdateMode,setldr = "All",    {}
  545.     keep ={
  546.         "Import Mode",
  547.         "Process Mode",
  548.         "Hold First Frame",
  549.         "Hold Last Frame",
  550.         "Reverse",
  551.         "Loop",
  552.         "Missing Frames",
  553.         "Depth",
  554.         "Pixel Aspect",
  555.         "Custom Pixel Aspect",
  556.         "First Frame",
  557.         "Make Alpha solid",
  558.         "Invert Alpha",
  559.         "Post-Multiply by Alpha",
  560.         "Swap Field Dominance",
  561.         "Bypass Conversion",
  562.         "Lock R/G/B",
  563.         "Black Level",
  564.         "White Level",
  565.         "Soft Clip (Knee)",
  566.         "Film Stock Gamma",
  567.         "Conversion Gamma",
  568.         "Green Black Level",
  569.         "Green White Level",
  570.         "Green Soft Clip (Knee)",
  571.         "Green Film Stock Gamma",
  572.         "Green Conversion Gamma",
  573.         "Blue Black Level",
  574.         "Blue White Level",
  575.         "Blue Soft Clip (Knee)",
  576.         "Blue Film Stock Gamma",
  577.         "Blue Conversion Gamma",
  578.         "Conversion Table",
  579.         "Frame Render Script",
  580.         "Start/End Render Scripts",
  581.         "Start Render Script",
  582.         "End Render Script",
  583.         "Comments",
  584.         --"Clip List","Load","Replace","Insert","Import","Format Name","Detect Pulldown Sequence"
  585.         --"KeyCode","Time Code Offset","Video Track","Effect Mask",
  586.         --"Global In","Global Out","Trim In","Trim Out","Apply Mask Inverted",
  587.         --"Multiply by Mask","Blank2","Channel","High","Low","Clip","Proxy Filename",
  588.     }
  589.     for i, input in c.LDR:GetInputList() do
  590.         n = input:GetAttrs().INPS_Name
  591.         if (eyeon.isin(keep, n)) then
  592.             table.insert(setldr, i, {['name']= n,['val']= input[TIME_UNDEFINED]})
  593.         end
  594.     end
  595. end
  596. SetActiveComp(c)
  597. pos =   getToolPositions(c) or nil
  598. pm('Creating comps:')
  599. --if not pos then _ALERT('Unable to fetch tool positions. Expect comps with messed tools :-)') end
  600. cnames = {}
  601. if FusionRemote.CacheManager then FusionRemote.CacheManager:Purge() end
  602. for i, fi in clips do --main loop
  603.     SetAttrs({COMPN_GlobalStart = 1, COMPN_GlobalEnd = 500000000000})
  604.     to = (c.LDR.Output:GetConnectedInputs())
  605.     c.LDR:Delete()      --grr...
  606.     LDR = c.Loader({Clip = ''})
  607.     LDR:SetAttrs({TOOLS_Name = "LDR"})
  608.     if pos  then c.CurrentFrame.FlowView:SetPos(LDR,pos['LDR'].x,pos['LDR'].y) end
  609.     for i, x in to do   x:ConnectTo(LDR.Output) end
  610.     masp=eyeon.split(fi.Path, [[\]])
  611.     for i, line in masp do
  612.         if (tonumber(string.len(eyeon.trim(line))) > 0) then
  613.             folder = line
  614.             parent= masp[i-1]
  615.         end
  616.     end
  617.     if (ret.compnames == 0) then
  618.         shotname = fi.Name
  619.     elseif(ret.compnames ==1 )  then
  620.         shotname = folder
  621.     else
  622.         shotname = parent
  623.     end
  624.     savedcomp = ret.flws .. shotname .. '.comp'
  625.     if (eyeon.isin(cnames, savedcomp) == true) then  --> check if is uniqie.
  626.         a,j = eyeon.split(fi.FullPath,[[\]]),{}
  627.         a[1],a[table.getn(a)] = nil,nil
  628.         for xc, vv in a do
  629.             table.insert(j, vv)
  630.         end
  631.         o = table.getn(j)
  632.         for i, k in j do
  633.             if (j[o + 1 - i]) then
  634.                 shotname = j[o + 1 - i] .. '.' .. shotname
  635.                 savedcomp = ret.flws .. shotname .. '.comp'
  636.             end
  637.             if (eyeon.isin(cnames, savedcomp) == false) then
  638.                 break
  639.             end
  640.         end
  641.     end
  642.     table.insert(cnames, savedcomp)
  643.     c.LDR.Clip[TIME_UNDEFINED] = fi.FullPath
  644.     wait(0.5)
  645.     if (setldr) then
  646.         for g, input in c.LDR:GetInputList() do
  647.             for o, k in setldr do
  648.                 if (k.name == input:GetAttrs().INPS_Name) then                  --print(n,k.val)
  649.                     input[TIME_UNDEFINED] = k.val
  650.                 end
  651.             end
  652.         end
  653.     end
  654.     c:Save(savedcomp)
  655.     att     = c.LDR:GetAttrs()
  656.     start,  frames = att.TOOLNT_Clip_Start[1],  att.TOOLNT_Clip_End[1]
  657.     if (not frames) then
  658.         alert('UNABLE TO LOAD:\n' .. fi.FullPath)
  659.     else
  660.         c.CurrentTime = (math.ceil(frames / 2))
  661.         if (ret.counter==1 and c.Counter and c.MergeCounter) then
  662.             if (IsRotation) then
  663.                 c.Counter:SetAttrs({TOOLB_PassThrough = true})
  664.                 c.MergeCounter:SetAttrs({TOOLB_PassThrough = true})
  665.             else
  666.                 c.Counter.GlobalOut[TIME_UNDEFINED],c.Counter.Width,c.MergeCounter.Width,c.Counter.Height,c.MergeCounter.Height,
  667.                 c.Counter.Enabled3 = frames,att.TOOLIT_Clip_Width[1],att.TOOLIT_Clip_Width[1],att.TOOLIT_Clip_Height[1],att.TOOLIT_Clip_Height[1],1
  668.             end
  669.         end
  670.         if ((not(exts2[ret.sq + 1]== '- none -')) and c.SQ) then
  671.             c.SQ:SetAttrs({TOOLB_PassThrough = false})
  672.             c.SQ.Clip = ret.Destination .. shotname .. string.lower(exts2[ret.sq + 1])
  673.             --if exts2[ret.sq + 1]=='.omf' and (not IsRotation) then
  674.                 --c.SQ.OMFFormat.Codec[0]='AJPG'
  675.                 --c.SQ.OMFFormat.AJPG.CodecVariety[0]='AVR9s'      -- ADD ANOTHER FILE FORMAT DEFAULT SAVER SETTINGS HERE AS ABOVE FOR OMF
  676.             --end
  677.         else
  678.             if c.SQ then
  679.                 c.SQ:SetAttrs({TOOLB_PassThrough = false})
  680.             end
  681.         end
  682.         -- add another default savers here
  683.  
  684.         if c.OMF and (not IsRotation)then
  685.             if exts2[ret.sq + 1]=='.omf' then
  686.                 c.OMF:SetAttrs({TOOLB_PassThrough = true})
  687.                 pm('Skiping OMF saver, because you have SQ set  to the same OMF!')
  688.             else
  689.                 c.OMF.Clip = ret.Destination .. shotname .. '.omf'
  690.                 --c.OMF.OMFFormat.Codec[0]='AJPG'
  691.                 --c.OMF.OMFFormat.AJPG.CodecVariety[0]='AVR9s'
  692.                 pm('Setting omf saver. Format is'..c.OMF.OMFFormat.AJPG.CodecVariety[0])
  693.             end
  694.         end
  695.  
  696.  
  697.         if c.MOV then
  698.  
  699.             local sq1=eyeon.parseFilename(ret.Destination).Path
  700.             local mov1=eyeon.parseFilename(mov.Clip[TIME_UNDEFINED]).Path
  701.       print('Found custom MOV saver'..mov1)
  702.       print('The default one is '..sq1)
  703.  
  704.             if exts2[ret.sq + 1]=='.mov' then
  705.                 if sq1 == mov1 then
  706.         print('TWO SAVERS IN SAME DIR!! - ADDING _CUSTOM TO YOUR CLIP NAME_')
  707.                             c.MOV.Clip = mov1..'_custom_' .. shotname .. '.mov'
  708.                 end
  709.             else
  710.                 c.MOV.Clip = mov1 .. shotname .. '.mov'
  711.             end
  712.         end
  713.  
  714.     if ((exts2[ret.sq + 1]== '- none -') and (ret.jpeg == 1 and c.JPG)) then -- if creating  only JPG's
  715.             c:SetAttrs({ COMPN_GlobalStart = start,COMPN_GlobalEnd = frames * 2, COMPN_RenderStart = c.CurrentTime,
  716.             COMPN_RenderEnd = c.CurrentTime, COMPN_CurrentTime = c.CurrentTime })
  717.         else
  718.             c:SetAttrs({ COMPN_GlobalStart = start, COMPN_GlobalEnd = frames * 2, COMPN_RenderStart = start,
  719.             COMPN_RenderEnd = frames, COMPN_CurrentTime = c.CurrentTime })
  720.         end
  721.         if (ret.jpeg and c.JPG) and (not IsRotation) then
  722.             c.JPG:SetAttrs({TOOLB_PassThrough = false})
  723.             _j = ret.Destination .. shotname .. '.jpg'
  724.             c.JPG.Clip[0]=_j
  725.             if c.JPG.Blend then
  726.                 c.JPG.Blend =  BezierSpline()
  727.                 c.JPG.Blend[start],c.JPG.Blend[c.CurrentTime - 1],c.JPG.Blend[c.CurrentTime],c.JPG.Blend[c.CurrentTime + 1] = 0,0,1,0
  728.                 if c.JPG.ProcessWhenBlendIs00  then     c.JPG.ProcessWhenBlendIs00[1]=0 end
  729.             end
  730.             c.JPG.FrameSavedScript[0] = '\n_j=' .. '[['.._j..']]' ..
  731.             '\nf=Fusion():MapPath(filename)\n' .. 'if(fileexists(f)) then\n' ..
  732.             'h,e=os.rename(f,_j) \n' .. "if h == true then\n" .. "print(filename..' renamed to '.._j)\n" ..
  733.             "else\n" .. "_ALERT(e,'Error renaming '..filename..' please rename it manualy to '.._j)\n" ..
  734.             "end\n" .. "else\n" .. "_ALERT('Still frame NOT RENDERED !')\n" .. "end\n"
  735.         else
  736.             if c.JPG then c.JPG:SetAttrs({TOOLB_PassThrough = true}) end
  737.         end
  738.         ct = c:GetAttrs()
  739.         c:SetPrefs{
  740.             ["Comp.Info.Comments"] = 'Created using ' .. '\tConvert Footage.eyeonscript by ' ..
  741.             userinfo .. ' on ' .. os.date() .. '\n\nSource:\t' .. fi.FullPath ..
  742.             '\n\nClip:\t[' .. i .. ' from ' .. cl .. ']' .. '\n\nDestination:\t' ..
  743.             ret.Destination .. shotname .. '\n\nComp saved:\t' .. savedcomp,
  744.             ["Comp.Info.ModifyDate"] = os.date()}
  745.         c:Save(savedcomp)
  746.         eyeon.fprint('Clip ' .. i .. '/' .. cl..':' ,fi.Name,ct.COMPN_RenderStart .. '..' .. ct.COMPN_RenderEnd)
  747.         if (ret["QueueNow"]== 1) and fusion.RenderManager then
  748.             job = fusion:QueueComp({ FileName = savedcomp, Start = start, End = frames, QueuedBy = user, Groups = groups })
  749.             if (ret["Paused"]== 1) then
  750.                 job:SetAttrs{RJOBB_Paused = true}
  751.             end
  752.         end
  753.     end --if frames
  754.     collectgarbage()
  755. end -- clips loop
  756. --c:Unlock()
  757. if ccomp then
  758.     SetActiveComp(ccomp)
  759. end
  760.  
  761.  
  762. while c:IsLocked() == true do
  763. print('unlocking..')
  764.    c:Unlock()
  765. end
  766. --c:Close() --for some reason Fusion 6.0, 6.1 crashes here.
  767.  
  768. local totaltime     =   os.difftime(os.time(), t1)
  769.  
  770. if not FusionRemote.RenderManager then
  771.     _ALERT('Script is finished, but generated comps are not submitted to rendermanager.Unable to connect. Please do this manualy.')
  772. end
  773.  
  774.  
  775.  
  776. endmsg='Script Convert Footage Finished!\nSee console for details.'
  777. eyeon.fprint('Scaned folders:',scanned ,' in '..time1)
  778. eyeon.fprint('Clips found:',cl)
  779. eyeon.fprint('Total time:',((totaltime - math.mod(totaltime, 60)) / 60)..'m. '..(math.mod(totaltime, 60))..'s.')
  780. pm('Comps saved in:\t\t'..ret.flws)
  781.  
  782.  
  783.  
  784. if (cl > 0) then    executebg('explorer /e ,' ..ret.flws)end
  785. if (warnrm) then
  786.     fusion.RenderManager:SetAttrs({ RQUEUEB_Paused = false, })
  787. end
  788. collectgarbage()
  789. alert(endmsg)

RBemendo
Fusioneer
Posts: 152
Joined: Fri Dec 12, 2014 11:32 am
Been thanked: 1 time

Re: Auto applying a template between loader and saver

#6

Post by RBemendo » Mon Aug 20, 2018 7:47 am

Thanks Guys!! this is a great start and will work on adapting this to my workflow. The convertFootage script isn't working in Fusion 9 after changing to LUA. I'll try to mess around with Bryan's resources and see what I can do. I'm pretty awful at scripting so i"ll try to hack my way through it.

Added in 20 minutes 42 seconds:
So after getting a script to successfully paste the copied setting I get the error:

[string "???"]:5: attempt to index global 'IN' (a nil value)

do I need to define the tool named "IN"?

as of now I'm just copy and pasting this into the console:

Code: Select all

Lua> LDR = comp:GetToolList(false, "Loader")[1]

SVR = comp:GetToolList(false, "Saver")[1]

IN_.Input:ConnectTo(LDR.Output)

SVR.Input:ConnectTo(OUT.Output)

x, y = comp.CurrentFrame.FlowView:GetPos(IN)
comp.CurrentFrame.FlowView:SetPos(LDR, x - 1, y)
x, y = comp.CurrentFrame.FlowView:GetPos(OUT)
comp.CurrentFrame.FlowView:SetPos(SVR, x + 1, y)

User avatar
Midgardsormr
Fusionator
Posts: 1020
Joined: Wed Nov 26, 2014 8:04 pm
Answers: 1
Location: Los Angeles, CA, USA
Been thanked: 53 times
Contact:

Re: Auto applying a template between loader and saver

#7

Post by Midgardsormr » Mon Aug 20, 2018 8:22 am

Yes, IN and OUT need to be tools in the template. Thus the preface "Supposing you had some nodes named IN and OUT…"

And come to think of it, you'll probably need to reference them in terms of the composition, so change them all to comp.IN and comp.OUT

It will work as-is in the console, but a script needs the extra information.

RBemendo
Fusioneer
Posts: 152
Joined: Fri Dec 12, 2014 11:32 am
Been thanked: 1 time

Re: Auto applying a template between loader and saver

#8

Post by RBemendo » Mon Aug 20, 2018 12:38 pm

when copying and pasting the code into the consule, I get: [string "???"]:3: attempt to index field 'Input' (a nil value)

I've tried naming a channelBooleans to "IN" but it auto changes it to "IN_" I've tried changing the naming to just using the default names of ChannelBooleans1.IN and ChannelBooleans2.out to see if I could troubleshoot but no luck. Also, tried changing to comp.ChannelBooleans1.IN without luck again.

Code: Select all

Lua> LDR = comp:GetToolList(false, "Loader")[1]
SVR = comp:GetToolList(false, "Saver")[1]
comp.ChannelBooleans1.Input:ConnectTo(LDR.Output)
SVR.Input:ConnectTo(comp.ChannelBooleans2.Output)
x, y = comp.CurrentFrame.FlowView:GetPos(IN)
comp.CurrentFrame.FlowView:SetPos(LDR, x - 1, y)
x, y = comp.CurrentFrame.FlowView:GetPos(OUT)
comp.CurrentFrame.FlowView:SetPos(SVR, x + 1, y)

User avatar
Midgardsormr
Fusionator
Posts: 1020
Joined: Wed Nov 26, 2014 8:04 pm
Answers: 1
Location: Los Angeles, CA, USA
Been thanked: 53 times
Contact:

Re: Auto applying a template between loader and saver

#9

Post by Midgardsormr » Mon Aug 20, 2018 12:54 pm

A ChannelBooleans doesn't have an input called Input. Its image inputs are called Foreground and Background. So you'd need
comp.ChannelBooleans1.Background:ConnectTo(LDR.Output)

You can query the name of a given input by mousing over it and observing the name in the status bar in the lower left corner of your Flow View. Or hover there for a few moment, and a tool tip should appear showing the name.

And if ChannelBooleans1/2 are what you're connecting to, you'd need to also change the IN and OUT in the GetPos lines to also reference those tools.

RBemendo
Fusioneer
Posts: 152
Joined: Fri Dec 12, 2014 11:32 am
Been thanked: 1 time

Re: Auto applying a template between loader and saver

#10

Post by RBemendo » Tue Aug 21, 2018 9:17 am

Thanks again Bryan! this saves soo much time on my end. I got the script working as a drag and drop method to the console, i'll keep working on trying to turn it into a proper script. Is there a way to copy/paste from a .setting file, or insert a setting file? So I could write separate scripts for different setting files?

Code: Select all

comp:Paste(('Y:\Original_LAUNCH_stockLibrary\Applications_Templates_Plugins\Fusion_NetworkLocation_Pathmaps\Settings\Ep25_Comps\readfromFile_test1.setting'))

User avatar
Midgardsormr
Fusionator
Posts: 1020
Joined: Wed Nov 26, 2014 8:04 pm
Answers: 1
Location: Los Angeles, CA, USA
Been thanked: 53 times
Contact:

Re: Auto applying a template between loader and saver

#11

Post by Midgardsormr » Tue Aug 21, 2018 1:36 pm

There are at least a couple of different ways you might handle it, depending on your workflow.

If you have a script for each template, you could hard-code the file path. The bmd.readfile() part is important, because that's how you'll get the .setting file into the copy buffer. To break it out a little bit, you could do something like this:

  1. path = [[Y:\Original_LAUNCH_stockLibrary\Applications_Templates_Plugins\Fusion_NetworkLocation_Pathmaps\Settings\Ep25_Comps\readfromFile_test1.setting]]
  2.     -- the [[ ]] structure is a Lua literal. Everything inside will be treated as a string, as long as it's not ']]'.
  3.     -- That prevents you from needing to do any handling for most special characters, such as the '\',
  4.     -- which is Lua's escape character.
  5.  
  6. myfile = bmd.readfile(path)   -- Puts the .setting file into memory
  7. comp:Paste(myfile)    -- Pastes the .setting file into the Flow

That would probably work as a first iteration of your pipeline. Eventually you'll probably want to improve the flexibility in some manner, allowing you to use one script for any template. You could get the path variable by popping up a dialog with a list of choices, perhaps. Let's suppose you put all of the templates into a folder together. You'd scan the contents of that folder and offer an interface of some kind presenting each .setting file. You'd need a routine to extract the list of files, which would populate a Lua table and that would be used to create the interface. The user selects the desired template from the combo box, and when they hit OK, that template's path is fed to the path variable.

Another method would be to key from some data that is known about the comp or the Loader. I have quite a few scripts that are based on the location and name of the comp file. That may not work out for you, though, if you're using Fusion Connect. It could if you stay in Resolve, though—some metadata about the clip or a pattern in its name or filename could be used to select the correct template.

There are probably other ways you could go about it, but those are the ones that come to my mind immediately.

RBemendo
Fusioneer
Posts: 152
Joined: Fri Dec 12, 2014 11:32 am
Been thanked: 1 time

Re: Auto applying a template between loader and saver

#12

Post by RBemendo » Wed Aug 22, 2018 7:31 am

Again, this is such invaluable information for me. Not even fine turning anything it has significantly increase productivity. Thank you again.

The past from the .setting file works great, and everything is working as expected except for aligning the tools. The loader and save just don't end up on the front and back end of the defined tools. When I change the X, Y coordinates it does start shifting the LDR and SVR around in the flow, they just don't want to stay by the two defined tools. Here's what the working console code looks like:

Code: Select all

path = [[Y:\Original_LAUNCH_stockLibrary\Applications_Templates_Plugins\Fusion_NetworkLocation_Pathmaps\Settings\Ep25_Comps\readFromFile_ch1_3shot01.setting]]
comp:Paste(bmd.readfile(path))
LDR = comp:GetToolList(false, "Loader")[1]
SVR = comp:GetToolList(false, "Saver")[1]
comp.IN_.Input:ConnectTo(LDR.Output)
SVR.Input:ConnectTo(comp.OUT.Output)
x, y = comp.CurrentFrame.FlowView:GetPos(IN_)
comp.CurrentFrame.FlowView:SetPos(LDR, x - 1, y)
x, y = comp.CurrentFrame.FlowView:GetPos(OUT)
comp.CurrentFrame.FlowView:SetPos(SVR, x + 1, y)

User avatar
Midgardsormr
Fusionator
Posts: 1020
Joined: Wed Nov 26, 2014 8:04 pm
Answers: 1
Location: Los Angeles, CA, USA
Been thanked: 53 times
Contact:

Re: Auto applying a template between loader and saver

#13

Post by Midgardsormr » Wed Aug 22, 2018 8:10 am

When you say they don't want to stay by the defined tools, are they in the ballpark, just not quite lined up? Or are they in completely the wrong place?

I think the grid lines are actually half a unit apart, and it may do some unexpected rounding of the coordinate. Sometimes I have to offset Y by +/- 0.5.

Anyway, now all you need to do is save that code in a document with the extension .lua and put it in Fusion's Scripts/Comp folder. It will appear in the Script menu. You can, by the way, put a Script menu item on your toolbar in Fusion standalone to save a click.

RBemendo
Fusioneer
Posts: 152
Joined: Fri Dec 12, 2014 11:32 am
Been thanked: 1 time

Re: Auto applying a template between loader and saver

#14

Post by RBemendo » Wed Aug 22, 2018 9:59 am

unfortunately it's way off.....

I also get this error: attempt to perform arithmetic on global 'x' (a nil value) error. Maybe that has something to with it?

User avatar
Midgardsormr
Fusionator
Posts: 1020
Joined: Wed Nov 26, 2014 8:04 pm
Answers: 1
Location: Los Angeles, CA, USA
Been thanked: 53 times
Contact:

Re: Auto applying a template between loader and saver

#15

Post by Midgardsormr » Wed Aug 22, 2018 11:13 am

Yep, that would be the problem. It's not getting the values for x and y. I think the problem is the name of the node; it doesn't work for me that way, either, but if I change it to 'tool' it works. Try changing the name of the IN_ node to something else and update all the references to it elsewhere in the script.

I should try to figure out why IN is a reserved word.