So I've decided to put down the brush for a few weeks and wrap my head around MaxScript. Knowing a few other polycounters have taken this trip I'm wondering if there isn't some good advice that might help make the trip less bumpy. MoP suggested the
DVD's from CG Academy since they came as part of the Dom War prize pack, and he has given them a brief look. They are a little pricey but I might be able to talk my AD into picking them up for the work library.
I've ordered the
MaxScript Essentials book and of course the Reference that comes with Max is fairly helpful most of the time, even if the syntax is a bit confusing and its light on examples.
I'm at a stuck point right now in a script I'm writing, I'm trying to control the Batch Render Interface but the ref/help files are very sketching and I'm having trouble finding info on how to create/name batch render views as well as set start/end frame ranges.
Heres the script I have so far, it relays pretty heavily on some custom elements of SoundTrax. The script does work with the demo which lets you load up 4 tracks.
<font class="small">Code:</font><hr /><pre>if (soundtrax.isactive() == false) then soundtrax.init(true) soundtrax.open() soundtrax.close()
rollout SoundErrorRollout "Missing Sound Files" width:160 height:104
(
label lbl1 "Please Launch SoundTrax and Load Sound Files" pos:[16,8] width:128 height:32
Button btn1 "SoundTrax" pos:[32,64] width:96 height:24
on btn1 pressed do
(
DestroyDialog SoundErrorRollout
soundtrax.open()
)
)
if (soundtrax.numtracks() != 0) == true then
(
--Name
StxN = for i=1 to soundtrax.numtracks() collect
(
getfilenamefile (soundtrax.name(i))
)
--Length
StxL = for i=1 to soundtrax.numtracks() collect
(
soundtrax.filelength(i) as integer /320
)
--Start
StxS = for i=1 to soundtrax.numtracks() collect
(
soundtrax.start(i) as integer /320
)
--End
StxE = for i=1 to soundtrax.numtracks() collect
(
soundtrax.end(i) as integer /320
)
-- This will be our new multidimensional array
StxTrack = #()
for i = 1 to StxN.count do
(
-- Create a new array appending each value of StxN one at time
append StxTrack StxN
-- Create another array for each index of new_narr
-- This will make it a multi dimensional array holding all the relevant values for each element of narr
StxTrack = #()
append StxTrack StxL
append StxTrack StxS
append StxTrack StxE
--print the values using the format command
format "% = %\n" StxN StxTrack
)
)
else
(
CreateDialog SoundErrorRollout 160 104
)</pre><hr />Right now I have it printing using the format command (which is new to me) until I figure out how to use that data to build a Batch Render list. It prints an array for each track,(track name, start frame, end frame, total # of frames)
Specific Questions:
- How do I control the batch render interface? Or any kind of similar interface?
- Any suggestions on code layout (tabbing) and comments?
- Can anyone better explain functions?
- Is there an easy way to tell max to back one folder out of a path? How about backing out once and entering into another folder?
maybe if I explain the workflow it will help things make sense.
Using Soundtrax I import 20-100 sound files and using a script I already wrote it sequences and pads the files back to back. I then lip sync a character to the sound files. Using another script I gather into an array the name of the sound track, its start and end frame and its path. I want to create a batch render "view" for each sound file and render out to the path the frames it runs for. The issue is I can create new views in the batch render interface but I can't adjust any of the other values.
Replies
-- a function frequently used
fn f_max a b = (if (a > b) then a else b)
-- the method returns the "next" upper directory of a path
-- so "C:\\gigatexture\\europe\\" will return "C:\\gigatexture\\"
-- it will always return a minimum of "C:\\"
-- at least should I havent tested the code at all
function f_getupperdir filepath = (
local pathnames = filterString filepath "\\"
-- rebuild newname, cept last one
-- pick greater value for count
-- we always want a minimum of 1 however (the file drive)
local cnt = f_max 1 (pathnames.count-1)
local newname = ""
for i=1 to cnt do (
newname += pathnames + "\\"
)
-- last value is always returned automatically in maxscript
newname
)
-- the StxTrack array doesnt seem to be needed or ?
for i = 1 to StxN.count do
(
local filenamefull = StxN
-- some built-in max functions to get details from a full filename (as returned by getfilename)
-- e.g "C:\\soundfiles\\überzeugenderspruch.wav"
local filenameshort = getFilenameFile filenamefull -- e.g will be "überzeugenderspruch"
local filepath = getFilenamePath filenamefull -- e.g will be "C:\\soundfiles\\"
-- camnode must be spcified !
-- dont know what "camera" you need there but you should pass it somehow
local camnode
-- functions in maxscript just get the arguments written after another
-- if no argument is needed you must do funcname()
-- thats utter crap imo but w2g whosever idea it was to not always use brackets
-- like in almost every other language
local newbatch = batchRenderMgr.CreateView camnode
-- interfaces let you directly acces your variable with .interfaceproperty / func
-- set batch properties
newbatch.name = filenameshort
newbatch.startFrame = StxS
newbatch.endFrame = StxE
-- build the outfilename "go up one directory"
-- the brackets will tell that the first function's argument is only
-- filepath
newbatch.outputFilename = (f_getupperdir filepath) + "someotherdiryouwant\\" + filenameshort + ".avi"
)
</pre><hr />
however, havent tested it at all, not even compiled for syntax erros, nevertheless in theory it should work or get you started to fix issues left (personally I have 0 experience with batch render stuff). use at your own risk, might atomize a country near you.
I think the error is coming from what I have defined for "camnode" I'm using "getActiveCamera()" I might need to create a camera and use a constant name to get it working. either that or it doesn't like "local filenamefull = StxN(i)" I'll look into it deeper tomorrow. Thanks for for giving me such a great example to work off of.
Thanks a bunch!
haha, hey im maybe a bit off as far as scripting goes for max... can you kinda explain some of the advantages it offers?
Some of my personal favorites I use all the time:
JJTools: Specifically the Biped selector.
Advanced Painter: This allows you to paint/scatter objects onto another. Such as rocks on a ground plane, or trees in a scene. I also use the spaghetti and toothpaste features to make groups of wires, or paint wires running from a light bulb to a switch.
Camera Switcher: At work it isn't uncommon for our scenes to have over 50 cameras. This tool puts all the cameras in a list an lets you switch the active viewport to that camera by clicking on the camera in the list. I edited this one so I could bind to a shortcut, switching to the next/previous camera. So I can press page up/down and cycle through all the cameras.
Chunk Generator: Great for making rubble, works great with advanced painter.
E-Light Dome: Creates a light dome, and all of the lights are controlled by one panel. It works great as a quick and dirty AO light set up. You can also set up the dome to use an HDRI which also works great.
So far I've made a a script that uses soundtrax to sequence audio files back to back but can also put a frame buffer between each track. Which is handy because for each character I have about 40-70 sound clips I have to do lip sync for.
If you find yourself clicking 7 times to get to a tool there is a good chance with a simple script you can turn that into 1-2 clicks. After seeing what MaxScript has done for others you start looking around and thinking, "damn, I bet this or that could be scripted out" and eventually you start doing it, hahaha.
As for your reflection shader I bet there is very little scripting involved to fix it, if you want to send me a basic scene with it applied to a sphere I'll take a look at it. There are a few different ways to do reflections in Max it depends on which you need to pull off as to what well have to do.
Are you trying to get a shader that works in game? If so which game?
Are you trying to get a shader that just renders nicely? If so what render'er are you using? Scanline, MentalRay ect...
As far some of those scripts your talking about, I think I might look into them, I never knew you could do so many different effects with max scripts!
haha, hey im maybe a bit off as far as scripting goes for max... can you kinda explain some of the advantages it offers?
[/ QUOTE ]
Are you doing the same task over and over? Script it.
-batch applying controllers to nodes
-automatically setting up materials' map slots
-dumping info about max scenes into text files/xml files
-automating certain parts of pipeline such as setting skinning parameters and adding bones
-batch exporting a scene(s) in various ways to save much time doing it manually.
-error checking engine incompatibe skinning (invalid weights etc.) with visual feedback before leaving max
-rendering sets of assets with consistent light setup for various purposes
bunch more stuff, usually small things, but really, if its repetitive its probably script-able.
At the start i was a nubling and it was all quite tricky, but nowadays its kinda straightforward, unless I come up agains a gnarly thing (and there are a few things in maxscript which are gnarlier than most)
anyway - OP's picks for training are good, and the best learning is done by trying to get something to work, so once you get the basics down, go for it!
as an aside, you can write scripts in photoshop too, which can be neat for certain stuff which is awkward to do by actions.
have fun!
What this script does:
For each sound track loaded it creates a batch render view and sets the start/end frames and output path for each view to that of the track. It is VERY specific to my work flow, but will help anyone having to lip sync and render many audio clips. This is going to shave about 3-4 hours per character of mind numbing data entry.
<font class="small">Code:</font><hr /><pre>--*********************************************************************
-- SoundTraxBatchRenderAutomate V 0.25
-- Script written by Mark Dygert, with many thanks to Christoph Kubisch (CrazyButcher)
-- Lead Character Artist,
-- Her Interactive 8-27-07
-- This Script will create a batch render file for each sound track, including frame ranges, file path/name
-- This script requires SoundTrax from www.Boomerlabs.com
--*********************************************************************
StxN = for i=1 to soundtrax.numtracks() collect getfilenamefile (soundtrax.name(i)) -- e.g will be "soundname"
StxS = for i=1 to soundtrax.numtracks() collect soundtrax.start(i) as integer /320 -- e.g will be "start frame number"
StxE = for i=1 to soundtrax.numtracks() collect soundtrax.end(i) as integer /320 -- e.g will be "end frame number"
fn f_max a b = (if (a > b) then a else b) -- some wierd voodoo going on here
function f_getupperdir filepath = ( -- open function
local pathnames = filterString filepath "\\"
local cnt = f_max 1 (pathnames.count-1)
local newname = ""
for i=1 to cnt do ( -- open loop
newname += pathnames + "\\"
) -- close loop
newname
) -- close funtion
for i = 1 to StxN.count do ( -- open loop
makedir (getfilenamepath (soundtrax.name(i)) + "Head\\" + StxN) -- Make new folders for sounds inside the head folder
) -- close loop
for i = 1 to StxN.count do ( -- open loop
local filenamefull = StxN
local filenameshort = getFilenameFile filenamefull -- e.g will be "soundname"
local filepath = getFilenamePath (soundtrax.name(1)) -- Gathers the path of the first track. e.g will be "C:\\path\\SoundsFolder\\"
local camnode = getActiveCamera() -- Active viewport should be set to a camera
local newbatch = batchRenderMgr.CreateView camnode
newbatch.name = filenameshort -- Names the new batch render view
newbatch.overridePreset = true -- Turn on defult settings overide
newbatch.startFrame = StxS -- Set start frames
newbatch.endFrame = StxE -- Set end frames
newbatch.outputFilename = (f_getupperdir filepath) + "Head\\" + "\\" + StxN + "\\" + filenameshort + "_0000" + ".tga" -- Set OutPut Path & file name
) -- close loop</pre><hr />
Now all that is left is to have it do some checks and clean up so it doesn't keep creating views if views are already made. Then I'm off to draw up a master UI for all the scripts. Thanks again CrazyButcher, you taught me much.
the weird voodoo is just returning the "greater/maximum" of the two values, its a function as well.
maxscript allows "fn" or "function" as keyword.
in this case its useful as "pathnames.count-1" might be 0 (if the input path already is "C:\\") so we would return an empty string which isnt good for the filename we use the output function for. Hence the f_max call makes sure that at least 1 e.g C:\ is returned.
with batchRenderMgr.FindView and batchRenderMgr.GetView, you should be able to wrap the createview with a check if name is already in use
like
<font class="small">Code:</font><hr /><pre>
local newbatch
local idx = batchRenderMgr.FindView filenameshort
-- "undefined" is a special value when a variable is uninitialized, or basically has no value at all.
if (idx == undefined) then(
newbatch = batchRenderMgr.CreateView camnode
)
else (
newbatch = batchRenderMgr.GetView idx
)
</pre><hr />
But I hit a snag, I'm trying to sequence the sound files but I can't figure out how to get a loop going that will find the end frame of the last track and make that the start frame of the first track. I think I MIGHT be able to tackle it with functions but I'm still having trouble getting that to work so I tried getting it all to flow in one loop, and that isn't working. I'm almost done... so close... I'll try doing it with functions in the morning.
Here is what I have so far, which works with the demo of SoundTrax.
<font class="small">Code:</font><hr /><pre>--*********************************************************************
-- SoundTraxBatchRenderAutomate V 0.25
-- Script written by Mark Dygert, with many thanks to Christoph Kubisch (CrazyButcher)
-- Lead Character Artist,
-- Her Interactive 8-27-07
-- This Script will create a batch render file for each sound track, including frame ranges, file path/name
-- This script requires SoundTrax from www.Boomerlabs.com
Global StxN = for i=1 to soundtrax.numtracks() collect getfilenamefile (soundtrax.name(i)) -- e.g will be "soundname"
Global StxS = for i=1 to soundtrax.numtracks() collect soundtrax.start(i) as integer /320 -- e.g will be "start frame number"
Global StxE = for i=1 to soundtrax.numtracks() collect soundtrax.end(i) as integer /320 -- e.g will be "end frame number"
Global StxL = for i=1 to soundtrax.numtracks() collect soundtrax.filelength(i) as integer /320 -- e.g will be "total number of frames in track"
rollout MainUI "LipSync Helper" width:160 height:432
( -- start MainUI Rollout
GroupBox grp1 "Track Management" pos:[8,8] width:144 height:88
button btn_ResetAll "Reset All" pos:[16,24] width:64 height:16 toolTip:"Resets all Sound Tracks to Start at 0"
edittext e_frmbuff "" pos:[96,72] width:40 height:16
button btn_SeqTracks "Seq Tracks" pos:[16,48] width:64 height:16 toolTip:"Sequences each track back to back"
button btn_FBSeqTracks "Seq Tracks" pos:[16,72] width:64 height:16 toolTip:"Sequences each track and adds the specified frame buffer"
label lbl10 "+" pos:[88,72] width:8 height:16
GroupBox grp12 "Active Time Tool" pos:[8,104] width:144 height:320
listbox listsel "Click to Set Active Time" pos:[16,120] width:128 height:16 items: StxN
button btn20 "Set to All" pos:[16,360] width:56 height:24 toolTip:"Sets the active time segment to include all tracks"
button btn_Batch "Batch" pos:[16,384] width:56 height:24 toolTip:"Auto completes the batch render window"
label lbl7 "All Start 0" pos:[88,24] width:56 height:16
label lbl8 "Piggy Back" pos:[88,48] width:56 height:16
button btn_STXopen "SoundTrax" pos:[72,384] width:72 height:24 toolTip:"Auto completes the batch render window"
button btn_VOMopen "VoiceOMatic" pos:[72,360] width:72 height:24 toolTip:"Auto completes the batch render window"
on btn_Batch pressed do ( -- start of Batch
fn f_max a b = (if (a > b) then a else b) -- some wierd voodoo going on here
function f_getupperdir filepath = ( -- open function
local pathnames = filterString filepath "\\"
local cnt = f_max 1 (pathnames.count-1)
local newname = ""
for i=1 to cnt do ( -- open loop
newname += pathnames + "\\"
) -- close loop
newname
) -- close funtion
for i = 1 to StxN.count do ( -- open loop
makedir (getfilenamepath (soundtrax.name(i)) + "Head\\" + StxN) -- Make new folders for sounds inside the head folder
) -- close loop
for i = 1 to StxN.count do ( -- open loop
local filenamefull = StxN
local filenameshort = getFilenameFile filenamefull -- e.g will be "soundname"
local filepath = getFilenamePath (soundtrax.name(1)) -- Gathers the path of the first track. e.g will be "C:\\path\\SoundsFolder\\"
local camnode = getActiveCamera() -- Active viewport should be set to a camera
local newbatch
local idx = batchRenderMgr.FindView filenameshort
if (idx == undefined) then (
-- newbatch = batchRenderMgr.GetView idx
messagebox "Views already created"
)
else (
newbatch = batchRenderMgr.CreateView camnode
newbatch.name = filenameshort -- Names the new batch render view
newbatch.overridePreset = true -- Turn on defult settings overide
newbatch.startFrame = StxS -- Set start frames
newbatch.endFrame = StxE -- Set end frames
newbatch.outputFilename = (f_getupperdir filepath) + "Head\\" + "\\" + StxN + "\\" + filenameshort + "_0000" + ".tga" -- Set OutPut Path & file name
)
) -- close loop
) -- end of batch
on btn_ResetAll pressed do ( -- Start of reset tracks to 0
for i = 1 to stxN.count do ( -- open loop
soundtrax.setstart i 0
soundtrax.setend i StxL
) -- close loop
) -- End of Reset tracks to 0
on btn_SeqTracks pressed do ( -- Start of track sequence
for i = 1 to StxN.count do ( -- open loop
messagebox "This feature is broken as of right now"
) -- close loop
) -- End of track sequence
on btn_FBSeqTracks pressed do ( -- Start of track sequence + frame buffer
for i = 1 to StxN.count do ( -- open loop
local frmbuff = e_frmbuff.text as integer
local p_StxE = soundtrax.end(i) as integer /320 -- attempting to get previous track end frame
soundtrax.setstart i 0
soundtrax.setend i StxL
soundtrax.setstart i (p_StxE + frmbuff)
soundtrax.setend i (StxL + frmbuff)
messagebox "This feature is broken as of right now"
) -- close loop
)-- End of track sequence + frame buffer
on listsel selected nameIndex do ( -- Start of set active time segment
local arrnum = finditem StxN listsel.selected
animationRange = interval StxS[arrnum] StxE[arrnum]
) -- End of set active time segment
) -- End MainUI rollout
rollout SoundErrorRollout "Missing Sound Files" width:192 height:120
( -- start of SoundError rollout
button btn1 "Launch SoundTrax" pos:[24,64] width:136 height:40 toolTip:"Launches SoundTrax"
label lbl19 " Zero sound files loaded! Please launch SoundTrax and load sound files" pos:[32,8] width:128 height:40
on btn1 pressed do (
DestroyDialog SoundErrorRollout
soundtrax.close()
soundtrax.open()
)
) -- end of SoundError rollout
( -- start of script
if (soundtrax.isactive() == false) then soundtrax.init(true) SoundTrax.open() SoundTrax.close() -- initialize SoundTrax
if (soundtrax.numtracks() != 0) == true then ( -- check to see if sound files are loaded
CreateDialog MainUI 160 432
)
else (
CreateDialog SoundErrorRollout 192 120
)
) -- end of script</pre><hr />
Clean up some comments, finish off that sequencer and output some data to an excel file and I'll be well on my way to a much more productive day. Baby steps though... baby steps heh
<font class="small">Code:</font><hr /><pre>
Global StxN = for i=1 to soundtrax.numtracks() collect getfilenamefile (soundtrax.name(i)) -- e.g will be "soundname"
Global StxS = for i=1 to soundtrax.numtracks() collect soundtrax.start(i) as integer /320 -- e.g will be "start frame number"
Global StxE = for i=1 to soundtrax.numtracks() collect soundtrax.end(i) as integer /320 -- e.g will be "end frame number"
Global StxL = for i=1 to soundtrax.numtracks() collect soundtrax.filelength(i) as integer /320 -- e.g will be "total number of frames in track"
Global frmbuff = 10
(
fn f_check a b = (if (i-1) > 1 then (i=i-1) else (i=1))
for i=1 to StxN.count do (
soundtrax.setend i StxL -- resets the end frame to match the length of the track
soundtrax.setstart i 0 -- resets the track to start on frame 0, otherwise it keeps adding
)
for i=1 to StxN.count do (
soundtrax.shift i (StxE[(f_check (i-1) i)] + frmbuff)-- this should shift the track by finding the end frame of the last track and adding 10frames (the frame buffer)
)
)</pre><hr />When I run the above code it returns:
<font class="small">Code:</font><hr /><pre>#("HEN00a", "HEN00b", "HEN00c", "HEN00d") -- Sound Track Names
#(0, 0, 0, 0) -- Sound Track Start Frames
#(68, 40, 14, 14) -- Sound Track End Frames
#(68, 40, 14, 14) -- Sound Track Length
10 -- Frame Buffer
OK
OK
and if I run it again...
#("HEN00a", "HEN00b", "HEN00c", "HEN00d")-- Sound Track Names
#(78, 78, 78, 78)-- Sound Track Start Frames
#(146, 118, 92, 92) -- Sound Track End Frames
#(68, 40, 14, 14) -- Sound Track Length
10 -- Frame Buffer
OK
OK
and if I run it again...
#("HEN00a", "HEN00b", "HEN00c", "HEN00d") -- Sound Track Names
#(156, 156, 156, 156) -- Sound Track Start Frames
#(302, 274, 248, 170) -- Sound Track End Frames
#(68, 40, 14, 14) -- Sound Track Length
10 -- Frame Buffer
OK
OK
and so on ...</pre><hr />
I can sequence the tracks by tediously building a monster script that slowly process each of the 100 track but there has to be a better way to handle it than writing arrays for each track.
This is the code for the first two tracks, each of the 100 tracks will have it's own block referencing the last. It also takes a really long time to run.
<font class="small">Code:</font><hr /><pre>--StxTrack 1
t1name = getfilenamefile (soundtrax.name(1)) --Gathers sound file name
t1leg = soundtrax.filelength(1)as integer/320 --Gathers track length
--Resets the track to frame 0
t1f = soundtrax.filelength(1)as integer/320
soundtrax.setstart 1 0
soundtrax.setend 1 (t1f)
t1startf = soundtrax.start(1)as integer/320 --Regathers the new start frame
t1endf = soundtrax.end(1) as integer/320 --Regathers the new end frame
StxTrack1 = #(t1name, t1leg, t1startf, t1endf) --Track array to be used later.
--StxTrack 2
t2name = getfilenamefile (soundtrax.name(2)) --Gathers sound file name
t2leg = soundtrax.filelength(2)as integer/320 --Gathers track length
--Resets the track to frame 0
t2f = soundtrax.filelength(2)as integer/320
soundtrax.setstart 2 0
soundtrax.setend 2 (t2f)
-- Shift track 5 frames after previous track
soundtrax.shift 2 (StxTrack1[4] + frmbuff)
t2startf = soundtrax.start(2)as integer/320 --Regathers the new start frame
t2endf = soundtrax.end(2) as integer/320 --Regathers the new end frame
StxTrack2 = #(t2name, t2leg, t2startf, t2endf) --Track array to be used later.</pre><hr />
I'm totally lost and can't figure it out... I think I'm going to have to write blocks of code for each of the 100 tracks. At least I think I can write a check to see if a track is loaded and have it stop when it finds the first unloaded track.
analyze what exactly you do with the shift, especially the f_check is a bit weird
you want every start/end pair after another with a 10 frame break right ?
your stxE is only written to once (on start) so it doesn accumulate the frames as you go along,
also you dont need two loops, you can do stuff in the first. easiest would be you create a "runner" variable which you simply add lenght + 10 at the end of each loop iteration.
so
<font class="small">Code:</font><hr /><pre>
local shiftval = 0
for i=1 to cnt do(
-- set start/end to 0 and length as you did
-- and as you noticed you dont need to collect Start and End and as you overwrite them with 0 and Length anyway
-- then call shift
-- finally raise shift by length and buffer
shiftval += length + frmbuff
)
</pre><hr />
also the way you setup teh function f_check its not "typical" for how functions work
<font class="small">Code:</font><hr /><pre>
-- yours
fn f_check a b = (if (i-1) > 1 then (i=i-1) else (i=1))
-- more "sense"
-- I split in multiple lines for easier read
fn f_check a = (
-- a is the input value that is handed over when the function is called
if (a-1) > 1 then(
a-1
)
else(
1
)
-- the last values in this case "1" or "a-1" are automatically returned by the function
-- you can also write "return 1" or "return a-1" but in simple cases not using return is faster I think
)
-- now when calling the function you hand over a value and
-- the func returns the stuff like
b = f_check 5
-- b will be 4
-- or you can access the array as you wanted, or whatever
for i=1 to 5 do(
-- a function value passed is not changed (unless passed by reference with the & symbol)
-- so lets say i is 2 here
test[f_check i]
-- here i is still 2, because basically a copy of it was passed to the function and f_check returns a fresh copy as well.
--This is "by value" passing/returning is only true for basic types (numbers, strings). For structs and arrays it can be a bit more complex
-- so if you want i to change as well you do
i = f_check i
-- but this would actually cause an infinite loop
-- because now i is 1, and in the for statement above it will be raised to 2 again, then here decreased to 1 and so on
)
</pre><hr />
also I noticed you made your arrays "global" which means they will stay in memory even after the script is run and they are actually not needed ? (unless you access them with other scripts, too).
cause if you dont need the stuff declare it local, as maxscript by default makes stuff global.
<font class="small">Code:</font><hr /><pre>
(
varA = #(adasd...)
local varB = #(23,...)
local somevalue = 10
(
-- = performs a copy here
local varC = somevalue
varC += 5 -- do something
-- = basically "links/points" to varB's array
local varD = varB
varD[1] = 0
)
-- varC cannot be accessed here it is deleted at end
-- of )
-- varD was a "pointer" to the array handle, and is deleted
-- but the array is still alive
-- however varB[1] now is 0 and not 23 anymore
-- basic types however are copied directly, so
-- somevalue is still 10 here
)
-- varA now is still in memory (it is global) whilst varB was deleted as well
</pre><hr />
the key words are "by value" passing, and "scope of variables" and garbage collection (regarding local/global) if you want to searhc the maxscript help
ahh garbage collection, that explains why I would have arrays and values floating around in memory defining things causing problems. So max only holds onto these things while the scope is open, gotcha, that makes life easier.
Everything now works like it should and the script is finished! WOO HOO first script down many more to go! heh
Thank you so much Christoph for you patients, clear explanations and excellent examples.
Final Script is HERE
Note: This works with the demo of SoundTrax which will allow you to have 4 sound tracks instead of the 1 max allows. Even with just 4 tracks this tool comes in very handy.
Here is a break down of what the tool does:
Reset all -- Sets all of the sound tracks to start at frame zero
Seq Tracks -- sets each track to start where the other left off. If you want the tracks to be padded by a few frames put that number in the empty box and hit "Seq Tracks".
Active Time Tool -- This lists the tracks by name, clicking on a track will set the active time segment to the length of the track. Handy when working on one track at a time and many tracks make it impossible to work effectively in track view.
Set Active To All -- Sets the active time segment to show all tracks
Create/Update Batch -- This takes info from the tracks such as track name, start/end frame and file path, then creates a batch render file. Note: The path is gathered from the sound file path and then changed to a folder called "head". This is specific to my work flow if you would like it to go somewhere else you can edit the script. The lines containing the path are easy to find if you search for "head".
Launch SoundTrax -- launches SoundTrax