regarding the semicolon:
When i started out investing more time in maxscript coding i did exactly that, i transfered my C#/C++ coding habits over to maxscript. Most prominently, the semicolon endings
Later on i decided that it is even more confusing, because many other things in maxscript ( like braces v. curly braces ) do not fit into that C#/C++/Actionscript style regime, and thus lead to a constant impression that something is not quite correct
By leaving out the semi-colons, it immediatly gets apparent that this is maxscript and that you have to be prepared for some ugliness …
I always use function. Using fn doesn’t really save me that much time. Actually all my functionnames start with fn_, e.g. fn_retargetAssets or fn_exportCollada. This makes sure that I know I’m calling a function when I use it somewhere else in the script.
I use an abbreviation to start all my functions like so
function fn_NAME arg_a &outputmessage =
(
/*<FUNCTION>
Description
What does the method do
Arguments
<argument_type> argument_name: argument description
<value by reference> outputmessage: a message we're reporting to
Return
<return_type> Function returns (anything?).
<FUNCTION>*/
if outputmessage == undefined do outputmessage = "" as stringstream
fnBody
)
This helps me keep a consistent structure and forces me to document my code before I start coding. This usually helps me to flesh out the idea.
I always use “function” and all of my function names starts with capital letter.
All of my variables starts with small letter.
So, the same as grabjacket, I can recognize if I am calling a function or a variable.
The reason to use “function” – is more readable to me.
And “fn” is my abbreviation to start my function.
Always fn as it is sorter and easier to type. I always camelCase everything. All tools are always in a struct and the structs are always formated the same way with the same base functions. This way everything looks and feels the same and runs with all my tools and I always know how to get access to them.
I think I’ve gone a bit overboard with this example, but it shows how I use the by reference parameters. This is a typical scenario where I process a scene and export the processed file. Each step in the process is a single method which does some reporting to a stringstream. In the end I present this to the user in a log, save it to a file or use in only during development.
I really like to use the by reference parameters and use them more and more in my work.
(
function fn_setupObjects &arrObject &outputmessage =
(
/*<FUNCTION>
Description
clears the scene and creates a bunch of boxes with varying colors
Arguments
<value by reference> arrObject: pass the created set of objects into this array
<value by reference> outputmessage: a message we're reporting to
Return
<boolean> true
<FUNCTION>*/
delete objects
arrObject = for i = 1 to 100 collect box wirecolor:(random black white) pos:(random [-100,-100,-100] [100,100,100])
format "Created % objects in the scene
" arrObject.count to:outputmessage
true
)
function fn_prepObjects &arrObject &outputmessage threshold:200 =
(
/*<FUNCTION>
Description
Checks the wirecolor in an array of objects and gets rid of some based on a threshold value
Arguments
<value by reference> arrObject: edit this array of objects
<value by reference> outputmessage: a message we're reporting to
<integer> threshold: a hue value used to select objects with
Return
<boolean> false if there are no objects left, true otherwise
<FUNCTION>*/
local proceed = false
format "Prepping % objects
" arrObject.count to:outputmessage
local originalCount = arrObject.count
for i = arrObject.count to 1 by -1 do
(
if arrObject[i].wirecolor.hue > threshold then
(
arrObject[i].wirecolor = green
)else
(
arrObject[i].boxmode = true
deleteItem arrObject i
)
)
case arrObject.count of
(
0: (format "No object qualified for saving
" to:outputmessage;proceed = false)
default: (format "Excluded % objects due to wirecolor saturation
" (originalCount - arrObject.count) to:outputmessage;proceed = true)
)
proceed
)
function fn_prepOutputLocation strPath &outputFolder &outputmessage =
(
/*<FUNCTION>
Description
Creates a uniquely named folder to store a file in
Arguments
<string> strPath: the basepath to create a folder in
<value by reference> outputFolder: pass the created folderpath in here
<value by reference> outputmessage: a message we're reporting to
Return
<boolean> true if the folder has been created, false if not
<FUNCTION>*/
local proceed = false
outputFolder = strPath + @"\klaasTest\" + ((genClassID returnValue:true)[1] as string) + @"\"
proceed = makeDir outputFolder
if proceed then
(
format "Created output folder: %
" outputFolder to:outputmessage
)else
(
format "Couldn't create outputfolder
" to:outputmessage
)
proceed
)
function fn_saveObjects arrObject outputFolder &outputmessage =
(
/*<FUNCTION>
Description
Saves a bunch of objects to a max-file
Arguments
<array> arrObject: the array of objects we're saving
<string> outputFolder: the folder we're saving the file in
<value by reference> outputmessage: a message we're reporting to
Return
<boolean> true if the file has been saved, false if not
<FUNCTION>*/
local proceed = false
local strFilePath = outputFolder + "export.max"
try
(
saveNodes arrObject strFilePath
proceed = true
)catch()
if proceed then
(
format "Saving % objects to %
" arrObject.count strFilePath to:outputmessage
)else
(
format "Saving the nodes failed
" to:outputmessage
)
proceed
)
function event_demo threshold:200 =
(
/*<FUNCTION>
Description
Creates a set of objects, filters them and saves a few
Arguments
<integer> threshold: a value used as a filter
Return
<FUNCTION>*/
local strMessage = "" as stringstream --all messages from the individual methods are put in this one
local proceed = true --this variable is used to control the flow
--some variables used in the methods below
local arrObject = undefined
local strPath = getDir #temp
local outputFolder = undefined
if proceed do proceed = fn_setupObjects &arrObject &strMessage
if proceed do proceed = fn_prepObjects &arrObject &strMessage threshold:threshold
if proceed do proceed = fn_prepOutputLocation strPath &outputFolder &strMessage
if proceed do proceed = fn_saveObjects arrObject outputFolder &strMessage
format "%" (strMessage as string)
)
clearListener()
event_export threshold:200
)
In the event_export method I can break the flow by setting one of the proceed values to false. Either one of the methods does it himself, or during development I can insert it myself. This really works for me at the moment.
i also always try to design my tool as ‘one tool – one structure – one file’. of course all my tools are sharing common libraries, but it’s different story.
for function naming i always use camel-case started with lower case. never use any spacial prefix.
structures i name camel-case started with upper case
variables and parameters i name usually lower case with using underscore or camel-case with one hump maximum
Same here, fn and lots of camelCase, also I’m looking at the ECMA coding standards for c#.
fn simply because it’s shorter, further a lot of very descriptive fn names. Lots of get/set names. I do not prefix a fn with fn_ a function name should be descriptive in itself, I try to properly order my variables and fn’s.
-Johan
I did lots of Maxscript 1998-2002, but I can’t remember what I used back then.
Then I did lots of MEL for a few years, where a procedure was a “proc”. When I came back to maxscript in 2008, I guess I just kept the paradigm since “fn” is more like “proc” than “function” is.
“fn” is also used more than “function” is in the mxs reference.
you are right. you reminded me the main reason why i switched from ‘function’ to ‘fn’ in 2002… i’ve just returned back to max from maya with its ‘proc’ used with MEL.
now everything looks for me consistent:
mxs: fn instead of function
mel: proc instead of procedure
python: def instead of define (or definition)
Always interesting to read other’s opinions/experiences on coding standards.
When I started to get into maxscript in 2005 with no programming knowledge of any kind, my scripting in general was very... messy with no consistency.
I Still don't have much programming knowledge outside of maxscript, but I tend to be much more structured and consistent. For functions, I always use "fn", short and clear. I just try to give them a name that is as self-explanatory as possible and without any specific prefix or suffix.
Also, since I've read denisT's post on "one tool, one global" some time ago, I've learn about structures and tried to understand them more (this was all new to me) and converted some of my most used tools inside structures and try to do so for every new tool I create now.