From purely selfish needs and from what I learned from talking with others, I decided to start a MaxScript knowledge and question thread, where we can post all the resources for MaxScript we got and post any scripting questions we have, without cluttering up the
Tech Artist - What are you working on: FOREVER Edition! thread.
The Tech Artist thread is great for posting overall stuff related to MaxScript, such as releases of new scripts and so on, but it would be nice with a official thread (would be nice if it was sticky), where we can discuss and question/answer stuff about MaxScript without clutting up the thread with specific and general scripting questions.
It will also be easier for those who dabbling in MaxScript to find any info they want, without going though the whole (so far) 39 pages in the Tech thread, and post any simple or complex questions they might have.
If you have any additions to the links below, or suggestions, please send me a IM and I'll add them as soon as possible.
Sites, tutorials and examples:Using DotNet In MAXScript by Bobo
Some examples using DotNet with maxscript and DotNet referances
Maxscript one-liners for artists
Scripts examples of how to script something into one line, which you might normally use several.
CGTalk - 3dsMax SDK and MaxScript subforum
MaxScript forum on CGTalk where there is lot of information to get.
CG++ Chinese MaxScript forum
A forum for MaxScript, in Chinese
Paul Neale and PEN Productions Inc. tutorials (not just MaxScript)
Some good tutorials and discussions about MaxScript. Also have tutorials to different areas of 3D.
ScriptAttack.com - Maxscript Snippets
A bunch of snippets of example codes
Homme 3D MaxScripts
Script examples and snippets
Emrah gunduz's maxscripts
A bunch of 'random' script examples
Enrico Gullotti - MaxScript
Some articles and scripts snippets for MaxScript
Ruben Garza - MaxScript
Some tutorials and scripts example for MaxScript
Raphael Steves - MaxScript
Lot of scripts examples and snippets
MaxScript made easy, a blog by Dave Wortley
Blog with script examples and explanations
Max Editor Tips: Abbreviations
How to make use of abbreviations to insert code blocks
Tools and resources:Autodesk's official maxscript documentation
Official documentation for 3DS Max MaxScript
3ds Max Python API Documentation
Official documentation for 3ds Max Python API
3ds Max 2014 Python thread, with some help for first time user
Forum thread with good information about using Python and installing
Microsoft .NET Framework for referencing
Official documentation for DotNet
Using Notepad++ or VS as a maxscript IDE (External MaxScript IDE)
Develop Scripts and Manipulate 3dsMax from your favorite IDE or application
Sublime Text editor
Another alternative editor to edit maxscripts in. Use the link below to get it work with MaxScript.
Sublime Text Editor MXS Support
Thread on scriptspot with help and files for using Sublime Text editor to edit and run maxscript files
Autocomplete in the MaxScript Editor
How to use and enable autocomplete in 3DS Max Maxscript Editor
DarkScintilla color scheme for MaxScript Editor
A dark color scheme for the editor in MAX, that is more relaxing for your eyes, then the bright background there is normally.
Scripts (outside Polycount):Scriptspot.com
Proberly the biggest collection of scripts, free/paid/open/closed source.
Jim Jagger's JJTools
Scripts by Jim Jagger, mainly aiming towards animation
Polycount MaxScripts threads:Outliner 2.0
The Outliner 2.0 is a fast and easy to use scene management tool.
Handplane
Handplane is a new tool being developed by Luke Hodorwicz and Alec Moody with the goal of solving tangent basis mismatch issues across multiple game engines.
miauu's Script Pack vol. 2
miauu's Script Pack vol.2 is a set of scripts that will help you to make faster and easier some of the tedious task when you use 3ds Max.
Replies
http://docs.autodesk.com/3DSMAX/16/ENU/3ds-Max-Python-API-Documentation/index.html
http://tech-artists.org/forum/showthread.php?4257-3dsmax-2014-Python-is-out
http://www.scriptspot.com/3ds-max/scripts/external-maxscript-ide
http://www.illusioncatalyst.com/mxs.php
http://rubengarza.com/index_MaxScripts.htm
http://graph.net84.net/index.php?/Page=Code-Maxscript
http://www.jonseagull.com/downloads.shtml
http://davewortley.wordpress.com/
Got a question as well, I got a dialog window with some spinners, and I got a custom helper object which contains some parameters which can animated. Got two example scripts below, which can be used to show the function I want to achive.
At the moment, if I change the spinner, it does change the parameter in the helper, but it's not automatic and if its animated, the spinner are not linked to the parameter and will not change value. I would like to link the dialog boxs UI to the parameters in the helper object, so if you change the spinners, the parameters automatic change, and the other way around as well (in case of animation).
Using those two scripts below, just run both, put the helper in the scene from the Helper tab, keep the helper selected, change the spinner, then press "Update" on either the dialog or the Helper, and you see the text update. Now, turn AutoKey on and do an animation range from 1 to 50. If you move the time to 25 and the press the "Update" button, you can see the value is properly updated in the text, meaning that the parameter is animated.
But the problem is that the spinner doesn't show this, and doesn't change since it's not linked. Currently the script update the parameters whenever I change the spinners.
Helper script Dialog script
See the help for an example:
MAXScript Spinner UI Control
spinner pointPosX "X:" pos:[38,8] width:75 height:16 type:#worldunits controller: ($.pointPos.x)
but I get this error:
-- Unable to convert: 0.0 to type: Controller
[controller:(<controller>)]
Dont have a working max at home but take a look at this example:
Here's one more:
Max Editor Tips: Abbreviations
by JHN's techart blog
http://www.scriptspot.com/3ds-max/scripts/darkscintilla-maxscript-editor-dark-scheme
From the docs:
Will try and see if i can get something to work. Havent used controllers much though thats probably my lack of indepth max knowledge.
Also +1 to dark interface. Had to change some stuff around but love it.
Ahh that does look more comfortable to work with, added to list and to MAX now.
@haiddasalami
Yeah, that's my problem as well, I never really done anything with animation or controllers so far with maxscript, so are stumbling a bit. Would appericate if you could get any workable example to show, so I know what might be wrong, or if its not possible at all.
I still believe it might be possible to get it to work by using bezier_point3(), but maybe not. Until then, I will split it up as you suggested and take it from there. If I figure out how to keep it in a point3, I'll post it. Cheers.
Oh a little thing, I noticed the controller is created by on rollout open, however what if the rollout never opens. With this example it does, because I used $, however I will be using named variables to get the object, which means the rollout is never open except when you manipulate the helper. So the controller won't initialize, would it? Wouldn't I need to create some kind of callback function?
EDIT: Ah never mind the last part, on my walk to work, my brain started to work again and I realised that I could just put it into a function on the helper, and when my dialog box opens, it just calls it.
Anyone got a working version of it?
Just take the file below and save the file on your harddisk. Then in Notepad++, go to the menu Languages and pick "Define your language...". In there, choose "Import" and pick the file you just saved and you should now have a MaxScript option in the Language menu.
I changed the background color from white to a grey-bluish one, but you can just do a search and replace on the XML file to replace with one you prefer. Easier then to manually change it in Notepad menu.
Download this file and follow the instructions above:
https://dl.dropboxusercontent.com/u/997277/3d/MaxScript.xml
While importing data from an xml I have to link the data to pre-referenced node
So....
as I import the xml string value I get "Ctrl_l_foot"
but i need to convert that string to a variable and be Ctrl_l_foot_node.node ( remove the string)
so basically transform "Ctrl_l_foot" into Ctrl_l_foot_node.node or
something like $modifiers[1].myattributes.Ctrl_l_foot_node.node so I can access it
myNode = GetNodeByName("Ctrl_l_foot")
I'm not quite sure what you mean with the last part.
All my controllers are stored and referenced inside a custom attribute... All i need to do is to access the stored node using the string from my xml
That way I can copy the rig, merge it, rename controller and evrything still works (except for the xml part)
If that is the case, the only way I can come up right now is to use the "execute" command.
So you have to put together the string before execute it, this little example might work:
select whateverIWant_node.node I need to stay away from the $ and the usual selection stuff as I can not refer directly to the name of the object but rather to a variable ( which is not a string)
shhh.... converting that string to a variable seemed so easy at first
I'm about to redo/rethink my whole xml format in order to not store the controller name as a string
EDIT: possible solution: use matchpattern and try to retrieve the #maxObject parameters stored in the CA
EDIT #2:
a= "a = 1"
execute a
returns 1
but this logic wont work with the weak reference (sigh....)
objName = "mybone_node.node"
instead of
objName = mybone_node.node
Which makes a huge difference.It should work if you execute the 5th line like this:
Then your targetCtrl would contain a node and not a string.
Just do what you would normally do if you have a static name (ignoring the xml and hardcode the file), and then 'convert' the line into one you use execute.
Through I still feel like that there is something I'm missing with your issue/example.
If anyone else have some input, we can always use that.
however, that command doesn't work either, everything that usually works throws error when I put it in my function (arghh..)
Whatver, I found a workaround using matchpattern
Mrfred, I know what you are trying to do. Use Weak References to avoid hard coding object names.
If you format your data in something other than XML you can probably just ReadExp through the whole file very fast. Although, if your rig isn't complex this may not be an issue.
In any case, heres an example of using both. Just change/build the myNode string.
@monster
I never thought about using it like that, in my head it was just related to reading from files, so I didn't really need it, but neat enough. Any idea though, which one is most efficient in execution/resources?
Also, I ran into an annoying problem, that would explain lot of the headaches I had earlier when testing. When I have certain variable like this:
myVar1 = myVar2
It points to the variable instead of the content of the variable. Any idea what I need to look up to know when and where this happens? I know it will happen with arrays, from what I found so far, and I seem to have the same issue with I'm dealing with matrixs. Also, any idea how to avoid it, because I had only partial success by using "myVar1 = copy myVar2" ?
The issues gives me problems when I'm trying to multiply two matrixs (newMatrix = nMatrix1 + nMatrix2), sometimes it works and only my position and rotation is affected (as I would expect with the values in them), however half the time the scale gets doubled, with the same values. Its driving me nuts. I can show an example if needed.
and inside the rollout control declaration I was able to initialize a struct but as soon as I put it into a macroscript, there were scope issues. Though I just moved everything to a
and initialize the struct, pointing a variable self to the new variable. Kinda reminds me of oop way of thinking. Wonder what approached you guys use for tools and what not. A lot of what I've seen has been the way I've been working which is functions rollouts etc within a macroscript.
@McGreed: Post up an example probably easier to see what's happening and people can chime in. I know I probably sound like a hypocrite after what I just talked about. Hoping to release the tool soon.
Here is an example script of what I'm trying to do. The problem I have right now is that the two first objects will be placed correctly in relation to each another, but the ones afterwards don't (the take the same position as the second one) Also, they don't do it properly, if the dummy is rotated:
EDIT: Added a picture of what I mean.
Found a solution on
http://forums.cgsociety.org/showthread.php?t=1023731.
Basically put the struct into the dotnet control tag. So what I have is a self variable (cant use this as im inside a rollout. Need to test this but I assign the initialized variable to self so the struct knows about it. Hopefully I made sense :S
myNewTool = newTool()
myNewTool.self = myNewTool
myNewTool.run()
Dumping this in case someone encounters this.
However, to me it seems the script is too complex for what you are trying to do, and if sourceNodes[1] is scaled you get some odd behavior.
The code below gives me the same result as your script when sourceNode[1] isn't scaled, but I think it does what you want when it is. The idea is to "remove" the sourceNode[1] transform then multiply it by the dummies. Of course I could be misunderstanding your goal. I just need more information.
You are right, the script kinda of evolved into that, because I couldn't get it to work, so I tried to work around it. My original script was actually exactly like yours, the only difference is that you used * and inverse, and I tried getting + and - to work with it.
I guess that math with matrixs is different then doing it with ordinary math, and I must admit it doesn't make sense to me, that you multiply instead of add. But cheers, that does work and I can now trim the fat of my script and get it back to something like 1/10 the size.... and working.
I'm trying to manipulate and animate a lot of objects, and I want to store the (animated) positions of them into a dummy.
However, since the amount of objects varies and is dynamic, I cannot create a predefined amount of parameters, for example like myParaObjPos1, myParaObjPos2, myParaObjPos3 ect.
So I want to store the positions into one array (or floattab as I was told would work on CGTalk), and that works fine, as long as I have the dummy parameters and UI the same place, however since I want to manipulate the values using a dialogbox, I cannot figure out how to link a single value in an array to a specific UI spinner in a dialog box.
I got an example from denis on CGTalk where he used attributes, however it was for when parameters and UI was in the same place, and not in a dummy. When I try to use attribute on the dummy, I get an error.
The script example would take one position in the floatTab and link it to the UI spinner, so that when either changed, they would both reflect that. It especially important because I want to store the animated values.
This is my test example scripts, one for the dummy:
and one for the dialog (which isn't complete since I can't get past getting attribute to work):
Any help would be appreciated, I feel like I'm missing something here. :poly127:
I haven't tried the attributes, might check it, however my question would be, how was it suppose to work? Link the parameter to a global attribute variable or something?
I am stuck on that last part; the changing the animation key curves, I get an error when i run this saying "type error: array index must be positive number, got 0.. I can't for the life of me figure out where the error lies. All help is hugely appreciated.
Below is my code so far:
resetmaxfile #noPrompt
resetmaxfile #noPrompt
try (destroydialog myrollout) catch()
rollout class_actions "class_actions" width:310 height:158
(
button move_class "Apply" pos:[120,91] width:60 height:40
edittext x_class "X:" pos:[20,26] width:70 height:30
edittext y_class "Y:" pos:[120,26] width:70 height:30
edittext z_class "Z:" pos:[220,26] width:70 height:30
on move_class pressed do
(
for obj in $* do (if classof selection[1] == classof obj
then obj.pos +=[x_class.text as float,y_class.text as float, z_class.text as float]
)
)
)
fn findcurvetype in_out_curve =
(
case (in_out_curve) of
(
1: in_out_curve = #smooth
2: in_out_curve = #fast
3: in_out_curve = #slow
4: in_out_curve = #linear
5: in_out_curve = #step
6: in_out_curve = #flat
default: messagebox "Error"
)
return in_out_curve )
rollout myrollout "myrollout" width:422 height:724
(
dropdownList Objectcreate "Select Object" pos:[36,17] width:76 height:40 items:#("box", "cylinder", "sphere", "pyramid", "torus")
label lbl1 "Move Object" pos:[36,77] width:65 height:14
label lbl3 "X Position:" pos:[23,101] width:53 height:16
label lbl4 "Y Position:" pos:[23,136] width:57 height:16
label lbl5 "Z Position:" pos:[23,169] width:58 height:19
label lbl13 "X Rotation:" pos:[231,101] width:58 height:19
label lbl14 "Y Rotation:" pos:[231,136] width:58 height:19
label lbl15 "Z Rotation:" pos:[231,169] width:58 height:19
label lbl93 "Parent Class :" pos:[122,411] width:73 height:15
label classname "undefined" pos:[190,394] width:137 height:15
label superclassname "undefined" pos:[191,411] width:137 height:15
label translbl "Translation:" pos:[30,259] width:70 height:25
label scalelbl "Scale:" pos:[30,301] width:70 height:25
label rotlbl "Rotation:" pos:[30,343] width:70 height:25
label lbl92 "Class :" pos:[123,394] width:43 height:15
label lbl43 "Create a Matrix" pos:[36,223] width:82 height:18
label lbl44 "Create Animation" pos:[36,465] width:96 height:27
label animatexyz "Rotate:" pos:[31,487] width:45 height:22
label lbl165 "Translate:" pos:[24,527] width:51 height:20
label lbl238 "Edit Curve" pos:[28,586] width:68 height:17
edittext move_x "" pos:[75,103] width:60 height:20
edittext move_y "" pos:[75,136] width:60 height:20
edittext move_z "" pos:[75,169] width:60 height:20
edittext rotate_x "" pos:[283,103] width:60 height:20
edittext rotate_y "" pos:[283,136] width:60 height:20
edittext rotate_z "" pos:[283,169] width:60 height:20
edittext xtrans "X:" pos:[100,259] width:50 height:25
edittext ytrans "Y:" pos:[170,259] width:50 height:25
edittext ztrans "Z:" pos:[240,259] width:50 height:25
edittext xscale "1" pos:[100,301] width:50 height:25
edittext yscale "1" pos:[170,301] width:50 height:25
edittext zscale "1" pos:[240,301] width:50 height:25
edittext xrot "X:" pos:[99,343] width:50 height:25
edittext yrot "Y:" pos:[170,343] width:50 height:25
edittext zrot "Z:" pos:[240,343] width:50 height:25
edittext animate_x "X:" pos:[81,488] width:55 height:25
edittext animate_y "Y:" pos:[148,487] width:55 height:25
edittext animate_z "Z:" pos:[216,487] width:55 height:25
edittext translate_x "X:" pos:[81,527] width:55 height:25
edittext translate_y "Y:" pos:[148,527] width:55 height:25
edittext translate_z "Z:" pos:[216,527] width:55 height:25
edittext frame_number "Frame No:" pos:[282,486] width:98 height:21
edittext edt53 "" pos:[336,466] width:0 height:0
button apply_move "Apply" pos:[139,128] width:60 height:39
button apply_rotation "Apply" pos:[347,128] width:60 height:39
button delete_selection "Delete" pos:[159,676] width:99 height:32
button creatematrix "Create Matrix" pos:[302,259] width:87 height:108
button findclass "Find Class" pos:[58,392] width:61 height:36
button classactions "Class Actions" pos:[254,392] width:128 height:37
button apply_animation "Apply" pos:[286,518] width:97 height:35
radiobuttons matrix_opt "" pos:[253,223] width:129 height:16 labels:#("identity", "blank") default:1 columns:2
radiobuttons in_curve "In Curve" pos:[91,596] width:118 height:62 labels:#("Smooth", "Fast", "Slow", "Linear", "Step", "Flat") columns:2
radiobuttons out_curve "Out" pos:[229,596] width:118 height:62 labels:#("Smooth", "Fast", "Slow", "Linear", "Step", "Flat") columns:2
on Objectcreate selected sel do
(
print Objectcreate.selected
case (Objectcreate.selected) of
(
"box": box isselected:on
"cylinder": cylinder isselected:on
"sphere": sphere isselected:on
"pyramid": pyramid isselected:on
"torus": torus isselected:on
)
)
on apply_move pressed do
(
for obj in selection do obj.pos += [move_x.text as float,move_y.text as float, move_z.text as float]
)
on apply_rotation pressed do
(
obrot = eulerangles (rotate_x.text as float) (rotate_y.text as float) (rotate_z.text as float)
for obj in selection do rotate obj obrot
)
on delete_selection pressed do
(
for obj in selection do delete $selection
)
on creatematrix pressed do
(
if matrix_opt.state == 1 then mymatrix = matrix3 1
else mymatrix = matrix3 0
mymatrix.row1.x = (xscale.text as float)
mymatrix.row2.y = (yscale.text as float)
mymatrix.row3.z = (zscale.text as float)
mymatrix.row4.x = (xtrans.text as float)
mymatrix.row4.y = (ytrans.text as float)
mymatrix.row4.z = (ztrans.text as float)
xrota = rotatexmatrix (xrot.text as float)
yrota = rotateymatrix (yrot.text as float)
zrota = rotatezmatrix (zrot.text as float)
mymatrix = mymatrix*xrota*yrota*zrota
for obj in selection do
(
obj.transform = mymatrix
)
)
on findclass pressed do
(
classname.text = (classof selection[1]) as stringd
superclassname.text = (superclassof selection[1]) as string
)
on classactions pressed do
(
createdialog class_actions
)
on apply_animation pressed do
(
with animate on
(
at time (frame_number.text as integer)
(
findcurvetype
curve_in = findcurvetype in_curve.state
curve_out = findcurvetype out_curve.state
)
for obj in selection do
(
rotval = eulerangles (animate_x.text as float)(animate_y.text as float)(animate_z.text as float)
rotate obj rotval
mykey = getkeyindex obj.pos.controller.x_position.controller (frame_number.text as time)
obj.pos = [translate_x.text as float,translate_y.text as float,translate_z.text as float]
obj.pos.controller.x_position.controller.keys[mykey].intangenttype =curve_in
obj.pos.controller.y_position.controller.keys[mykey].intangenttype =curve_in
obj.pos.controller.z_position.controller.keys[mykey].intangenttype =curve_in
obj.pos.controller.x_position.controller.keys[mykey].intangenttype =curve_out
obj.pos.controller.y_position.controller.keys[mykey].intangenttype =curve_out
obj.pos.controller.z_position.controller.keys[mykey].intangenttype =curve_out
)
)
)
)
createdialog myrollout
Don't know if there is any reason for this, because I was sure that you could have keyframes in the -minus area.
Never dealt with animations but i don't think your "with animate on" is working.
Also you try to access the position key before moving your object ? It certainly didn't create it.
Why not use addNewKey ?
edit: "at time" works only for the rest of the line, so you have to write something like
I got a strange problem with Max 2014.
Render to Texture Wont open. Not over the menue bar as well the shortkey 0 doesen't work. I tried it in new files, in old ones. and I haven't the singles clue why this specific window won't open. All other render windows open probebly. I hope anyone could help.
Thanks
Roca
I want to export some model information to a xml file.
Currently I'm using a simple code like this to add new elements:
format "<element>" to:example_file
format "<\element>" to:example_file
This works for most of the time, but now I want to add an attribute-entry (you know, those red dots in xml notepad) but I don't know if i can resemble this with my current approach?
I recommend using dotNET in MaxScript for reading / writing XML. It's not very hard, and it's way faster than printing out an xml with format.
Reading:
http://paulneale.com/tutorials/dotNet/xml/xmlReading.htm
Writing:
http://paulneale.com/tutorials/dotNet/xml/xml.htm
But in theory - would it even be possible to replicate the xml tree with format?
I'm struggling with this simple script right now. I'd like to create a script that assigns a smoothing group to any face that has no smoothing groups assigned, in all selected objects, while ignoring any modifiers.
I tried it with a for loop and a function but I can't figure out how to make it work with multiple objects.
I'm probably doing this all wrong but I'm still quite inexperienced with maxscript.
SelArray is basically your selection of objects passed into the function and you just cycle through each using the temp variable obj.
The script is supposed to collapse the bottom modifier. It also seems to struggle with edit poly modifiers.
This will collapse everything below the top Meshsmooth. There's not really a way to make it faster. If you've got a lot of objects you can switch to the Creation tab to avoid UI updates.
All it's supposed to do is collapse the modifier with the highest index to the base node. so for example in this image
bend = index 1
symmetry = index 2
and unwrap = index 3.
I only want to collapse the unwrap(lowest)modifier so to find the index of the bottom modifier I count the number of modifiers and then collapse the modifier with that index. As I said it's probably a very backwards way of doing it but it's the only way I could get it to work. The script does work, though there's a bit of a delay. And I was just wondering if there's a smarter way of doing it. (which there almost definitely is)
I feel like this constantly when it comes to maxscript :poly142: