Eyeon:Script/Tutorials/Slate Manipulation/Slate Manipulation Intro
From VFXPedia
Lesson 3.1 : Slate Manipulation
One of the most commonly requested scripts is one that will load and manipulate a slate composition based on (primarily) an existing composition's name, or a file sequence. The first lesson will show you how to open a comp using script, and will ask the user for input in the fields that are common in slates. The second major lesson will be a tool script that creates a composition entirely from scratch that will be used as a slate, which will be appended to the beginning of a sequence of frames.
The most common fields that are used in a slate are:
- Project Name
- Shot Name with version number
- Artist Name
- Date
- Frame Range
- Additional Comments
With that in mind, you can download an example composition that's been set up with all of these fields from the comps\examples\ folder called "ScriptExampleSlate.comp".
The first step is going to be to attempt to determine some of these variables.
Project Name: There's not really any easy way for us to predict the project name, so the suggestion is to make a new script / slate for each new project so that the user doesn't have to input any data. This also allows for custom plate background images if something more interesting than a black background is desired.
Shot Name with Version Number: This can be derived from the currently active comp's attributes as we did in the previous lesson.
Artist Name: This is probably the login name of the user by default. To determine this, we can use the fusion:GetEnv() function.
Date: This can be determined from the os.date function.
Frame Range: The render range can be used for this.
Additional Comments: the user will have to input this.
Let's go over some familiar territory first. We'll derive the composition's name from its attributes:
shotDefaultName = composition:GetAttrs().COMPS_Name
Even though it's old territory, this code shows a couple of different types of syntax. First off, I didn't first store the attributes in a variable. Although this is useful if the variable is used many times, it's not really needed. Both are technically correct, so really it's just a matter of preference.
The second is that a period was used to refer to a table index name. ".COMPS_Name" is the same thing as "['COMPS_Name']". Square brackets can only be used when the index field's name has spaces in it, but, again, both are technically correct.
Of course, like the previous example, this will leave the ".comp" at the end of the string. To solve this, we can do as we did 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 shotDefaultName = stripExtension(composition:GetAttrs().COMPS_Name)
Again, I put all that data into one line. The order of operations used by Fusion would go like this:
- 1) composition:GetAttrs() returning only COMPS_Name
- 2) stripExtension
- 3) define shotDefaultName with returned values.
In order to determine the artist's names, the fusion:GetEnv() function will have to be used. Looking at the documentation, we can see how the function is called: ===
GetEnv( envname )
- envname (required, string)
the name of the process environment variable to retrieve
The environment name we're after in this case is "USERNAME".
==fusion:GetEnv("USERNAME") sean
In this case it returned "sean". It's likely different for you. Unless your login name is also "sean".
There are many built-in environment variables that are accessible:
==fusion:GetEnv("OS") Windows_NT ==fusion:GetEnv("NUMBER_OF_PROCESSORS") 2
And so on. In this case, though, "USERNAME" is all we need.
usernameDefault=fusion:GetEnv("USERNAME")
The next step is to get the date. There are a number of functions that are directly tied to the operating
system. One of them is called os.date(). Essentially it returns a string filled with the text that's input into it. However, there are a number of special formatting options that can be added in to derive months, days, and so on.
In this case, the options that are of use are:
%b - Abbreviated month name %d - Day of month as decimal number (01 - 31) %Y - Year with century, as decimal number
=os.date("%b%d%Y") Jun132005
We can also include some of our own formatting when we call this function.
=os.date("%b. %d, %Y.") Jun. 13, 2005.
However, it'll look silly if there's a period after "May", whose abbreviated month name is also "May".
if os.date("%b") == "May" then dateDefault = os.date("%b %d, %Y.") else dateDefault = os.date("%b. %d, %Y.") end
The frame range is available through the attributes in the same way that the composition's name is.
framerangeDefault = composition:GetAttrs().COMPN_RenderStart.." - "..composition:GetAttrs().COMPN_RenderEnd
The user will also probably want to specify the output location. This should probably be set to the output location of one of the savers in the composition. There's no way of knowing what saver the user will want to export the slate to, so if there are multiple savers, we should pop up a dialog box before the main one is popped up asking us what saver to base the slate output on.
if saverlist then if table.getn(saverlist) 1 then saverNames = {} -- Insert all of the saver names into a table that can be read by the user. for i, tool in saverlist do saverNames[i] = tool:GetAttrs().TOOLS_Name end -- Ask the user for their saver preference. ret = composition:AskUser("Choose Your Saver Output", {{"Saver", "Dropdown", Options = saverNames}}) if ret == nil then print("Cancelled!") return end -- The saver in the list table will be equal to the returned index + 1 saverDefault = saverlist[ret["Saver"]+1] else if table.getn(saverlist) == 1 then saverDefault = saverlist[1] else -- set up the Saver list's filename for situations without savers saverDefault = {} saverDefault.Clip = {} saverDefault.Clip[TIME_UNDEFINED] = "" end end end
In the case of a dropdown menu, the options category needs to be set to a table with a list of all possible options. The returned value of a dropdown menu is a set of numbers that starts with 0 (as opposed to one). The saverlist variable begins with the number 1. To reconcile this, the appropriate index number will be the number returned in ret plus 1. If there's one saver, it will default to the first index number in the saverlist table.
If there are no savers, we'll have to make the default output location equal to no text at all and let the user define it.
The last step is to set up the height and width of the slate composition as well as allow the user to specify their own slate location in case they want had to modify it in some way. There's no way to predict the height and width accurately, so the best idea would be to set up the defaults for the script before it's distributed to the artists.
I set up the Slate composition so that it's located directly on my C drive, you're free to change the default as you see fit.
Now we can put it all together and ask the user what they want to do.
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 shotnameDefault = stripExtension(composition:GetAttrs().COMPS_Name) usernameDefault=fusion:GetEnv("USERNAME") if os.date("%b") == "May" then dateDefault = os.date("%b %d, %Y.") else dateDefault = os.date("%b. %d, %Y.") end framerangeDefault = composition:GetAttrs().COMPN_RenderStart.." - "..composition:GetAttrs().COMPN_RenderEnd -- Get a list of all the savers. saverlist = GetSavers(composition) -- Check to see if there are more than one. if saverlist then if table.getn(saverlist) 1 then saverNames = {} -- Insert all of the saver names into a table that can be read by the user. for i, tool in saverlist do saverNames[i] = tool:GetAttrs().TOOLS_Name end -- Ask the user for their saver preference. ret = composition:AskUser("Choose Your Saver Output", {{"Saver", "Dropdown", Options = saverNames}}) if ret == nil then print("Cancelled!") return end -- The saver in the list table will be equal to the returned index + 1 saverDefault = saverlist[ret["Saver"]+1] else if table.getn(saverlist) == 1 then saverDefault = saverlist[1] else -- set up the Saver list's filename for situations without savers saverDefault = {} saverDefault.Clip = {} saverDefault.Clip[TIME_UNDEFINED] = "" end end end ret = AskUser("Slate Options", {{"Slate Location", "FileBrowse", Default = "c:\\Slate.comp"}, {"Project Name", "Text", Default = "Example Project", Lines = 1}, {"Shot Name", "Text", Default = shotnameDefault, Lines = 1 }, {"Date", "Text", Default = dateDefault, Lines = 1}, {"Artist", "Text", Default = usernameDefault, Lines =1}, {"Frame Range", "Text", Default = framerangeDefault, Lines =1}, {"Output", "FileBrowse", Default = saverDefault.Clip[TIME_UNDEFINED]}, {"Height", "Slider", Min = 0, Max = 6000, Default =2048}, {"Width", "Slider", Min = 0, Max = 6000, Default = 1556} })
That's good for now.
The next lesson will show us how to apply this information to the tools in question.
Tips for Slate Manipulation Intro (edit)
Command to request start & end frame is :
frameDefaultRange = composition:GetAttrs().COMPN_RenderStartTime.."-"..composition:GetAttrs().COMPN_RenderEndTime
not :
framerangeDefault = composition:GetAttrs().COMPS_RenderStart.." - "..composition:GetAttrs().COMPS_RenderEndTime
In first part, to define a Drop Down menu use :
ret = composition:AskUser("Choose your saver output", {{"paramtypeN", Name = "Saver :", "Dropdown", Options = saverNames},})
instead of :
ret = composition:AskUser("Choose Your Saver Output", Template:"Saver", "Dropdown", Options = saverNames)
--
- Mathieu Laussel :: *Mel/Fusion Scripting & Network Render*
- Renegade Pixel's : +324 94 34 41 03 ::
