Eyeon:Script/Tutorials/Get Loader Filenames/Setting Defaults and String Parsing

From VFXPedia

< Eyeon:Script | Tutorials | Get Loader Filenames
Revision as of 03:52, 4 November 2008 by Daniel (Talk | contribs)
(diff) ← Older revision | Current revision (diff) | Newer revision → (diff)
Jump to: navigation, search

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