Eyeon:Script/Tutorials/Get Loader Filenames/Setting Defaults and String Parsing
From VFXPedia
Lesson 2.7 : Setting Defaults and String Parsing
In the previous lesson we created a UI input that allowed a user to specify where they wanted their text file to output and whether or not they wanted to append the data. If we left it like that, we could easily call the script "done" but the less the user has to input the better because 1) it's less hassle for them and 2) there's a smaller chance of error. Let's assume that they want it in the same directory as the comp, and they want it named the same way the comp is named.
How do we determine what the comp's name and path is?
==composition:GetAttrs() table: 0261F238 COMPN_GlobalStart = 0 COMPN_RenderEndTime =55 COMPN_GlobalEnd =1000 COMPN_LastFrameTime =0.093 COMPB_Modified =false COMPN_CurrentTime =55 COMPN_RenderStartTime= 0 COMPN_AverageFrameTime= 46.575272 COMPN_ElapsedTime =2561.64 COMPB_Rendering =false COMPI_RenderStep = 1 COMPI_RenderFlags = 0 COMPS_FileName = C:\Program Files\Fusion\Comps\Composition3.comp COMPN_TimeRemaining = 0 COMPN_RenderStart = 0 COMPN_LastFrameRendered = 55 COMPS_Name = Composition3.comp COMPB_HiQ = true COMPN_RenderEnd = 55 === COMPN_AudioOffset = 0 === COMPB_Proxy = false === COMPB_Locked = false ===
The composition object has an attributes table in the same way that any object in Fusion has an attributes table. The field we want is in the category COMPS_FileName. Its value is the entire path of the composition that will need to be accessed. It would be reasonably easy just to stick a ".txt" on to the end of that and be done with it, but some attempt should be made to strip out the ".comp".
In order to do this properly, a function that counts backwards from the last character looking for a period would be useful. We can even extend that and make it a function that strips out an extension altogether.
function stripExtension(stringVal) end
A number of functions exist in Fusion Script that will help with this task. The first is one called "string.len" that will return the total number of characters in a string. This will indicate where to start the "for" loop's count. The second is a function called string.sub[].
string.sub returns a string based on two numbers passed along to the function (as well as the string that is to be parsed) that show what characters the user wants to have returned. For instance, if we wanted the information between the second and fourth characters of "hello" (inclusive), the following would serve that
purpose:
=string.sub("hello",2,4) ell
In this function, the string.sub function can be used to grab one character at a time, starting with the last one, checking to see if the returned string's value is equal to a period character.
It would then return all characters before the one just found.
function stripExtension(stringVal) startScan = string.len(stringVal) for i = startScan, 1,-1 do -- for the length of the string to one, stepping at a -1 interval if string.sub(stringVal,i,i) == "." then -- if the character being checked was a period toreturn = string.sub(stringVal,1,i-1) -- take all characters before the character just checked return toreturn -- return it end end end compAttrs = comp:GetAttrs() print(stripExtension(compAttrs.COMPS_FileName))
The next step is to take the output from the function and pipe it into the AskUser function from before.
function stripExtension(stringVal) startScan = string.len(stringVal) for i = startScan, 1, -1 do -- for the length of the string to one, stepping at a -1 interval if string.sub(stringVal,i,i) == "." then -- if the character being checked was a period toreturn = string.sub(stringVal,1,i-1) -- take all characters before the character just checked return toreturn -- return it end end end compAttrs = comp:GetAttrs() textName = stripExtension(compAttrs.COMPS_FileName)..".txt" -- add .txt to the end ret = AskUser("Choose Export Options.",{ {"Filename", "FileBrowse", Save = true, Default = textName}, {"Append data?", "Checkbox", Default = 1} })
Now we can integrate this with our code.
If the user has decided that they don't want to append the data, then the mode should be set to write but not preserve data ("w+"). The output location should be put into the io.open and the io.output calls. First check to see if the user hit cancel or not. If they didn't, use the return command to end the script:
-- Check to see if the user cancelled if not ret then print("Cancelled!") return end -- Define Write Mode if ret["Append data?"] == 1 then writeMode = "+a" else writeMode = "w+" end -- Define the output location textOutput = ret["Filename"] -- declare the "isin" function. function isin(t, val) if type(t) == "table" then for i,v in t do if (type(v) == "string") and (type(val) == "string") then if string.lower(v) == string.lower(val) then return true end else if v == val then return true end end end end return false end -- header break print("\n\n----------------------------------------------\nLIST LOADER FOOTAGE:\n----------------------------------------------\n\n") -- create the clip table clipTable = {} -- Define the file to write to. Check to see if it exists. if fileexists(textOutput) == true then -- If it does exist, append new information to the end of the file. fh, errormessage = io.open(textOutput,writeMode) -- Print all the information in the text file. print("TEXT FROM FILE:\n") -- Cycle through the text file until the line returned is equal to nil -- (meaning there is no text on the line ) line = fh:read("*l") if line then while line do print(line) table.insert(clipTable,line) line = fh:read("*l") end end -- Divide the Script print("\n\nLOADERS:") else -- Set the output fh, errormessage = io.output(textOutput) end -- check to see if it returned a value for fh if not fh then -- if fh is equal to nil print(errormessage) return end -- Get a list of all loaders loaderlist = eyeon.GetLoaders(composition) -- Cycle through all the loaders for i, tool in loaderlist do -- Get the tool's Clip List attribute attrs = tool:GetAttrs() -- check to see if there's a clip list if attrs["TOOLST_Clip_Name"] then -- print the loader's name print(attrs.TOOLS_Name) -- cycle through that table for j = 1, table.getn(attrs["TOOLST_Clip_Name"]) do -- print each entry to the console. we should still do this -- even if the text file already has the loader in it print("--"..attrs["TOOLST_Clip_Name"][j]) --Check to see if it's already been written to the file. if isin(clipTable, attrs["TOOLST_Clip_Name"][j]) == false then --Write the data. fh:write("\n"..attrs["TOOLST_Clip_Name"][j]) table.insert(clipTable,attrs["TOOLST_Clip_Name"][j]) end end end end fh:close() print("\n----------------------------------------------\nSCRIPT COMPLETE\n----------------------------------------------\n")
We could go on adding features ad infinitum, but the code is essentially complete.
Tips for Setting Defaults and String Parsing (edit)
EyeonTips:Script/Tutorials/Get Loader Filenames/Setting Defaults and String Parsing
