Home Technical Talk

3D Max scripting dilemma (Calling multiple scripts via functions).

polycounter lvl 9
Offline / Send Message
Baj Singh polycounter lvl 9
Hey,

I've been searching through some of these threads for a solution, and whilst i've found some variation of the issue i'm having trouble getting my head around the answers given.

At the moment, I have a .mcr container script that look like this:
/* Load .ms files */
fileIn "fn01_backfaceToggle.ms"
fileIn "fn02_centerPivot.ms"
fileIn "fn03_zeroPivot.ms"
fileIn "fn04_zeroMesh.ms"
fileIn "fn05_sceneLighting.ms"
fileIn "fn06_connect_edge_vert.ms"
fileIn "fn08_bottom_pivot.ms"

macroScript backface_cull_toggle category: "Baj - Custom Max Tools" toolTip:"backface cull toggle"
(
	fn01_backfaceToggle()
)

macroScript center_pivot category: "Baj - Custom Max Tools" toolTip:"center pivot to mesh"
(
	fn02_centerPivot()
)

macroScript zero_pivot category: "Baj - Custom Max Tools" toolTip:"zero pivot to (0,0,0)"
(
	fn03_zeroPivot()
)

macroScript zero_mesh category: "Baj - Custom Max Tools" toolTip:"move mesh to (0,0,0)"
(
	fn04_zeroMesh()
)

macroScript toggle_lighting category: "Baj - Custom Max Tools" toolTip:"toggle scene lighting"
(
	fn05_sceneLighting()
)

macroScript new_connect category: "Baj - Custom Max Tools" toolTip:"connect edge vert"
(
	fn06_connect_edge_vert()
)

macroScript bottom_pivot category: "Baj - Custom Max Tools" toolTip:"move pivot to bottom-center of bounding box"
(
	fn08_bottom_pivot()
)

Each of these call a function in the relevant .ms file. E.g.
fn fn06_connect_edge_vert =
(
	/*Set up keyboard shortcut to create an edge between verts or edges*/	
		if subobjectLevel==1 then
		(
			macros.run "Editable Polygon Object" "EPoly_Connect"
		)
		else if subobjectLevel==2 then
		(
			macros.run "Editable Polygon Object" "EPoly_Connect2"
		)
)

Currently, these files are all saved under the same folder ("3D Max 2014\scripts\Baj-CustomMaxTools").

Now, it seems that when I start up Max, it is creating .mcr scripts in the "ENU/usermacros" folder (which, I think that judging from the documentation is the first place scripts are called when Max is started up).

However, if I have assigned one of the macroscripts above (in the .mcr file) to a keyboard shortcut, I get the following error:

"--Type error: Call needs function or class, got: undefined"

This occurs until I manually execute the main .mcr script and then everything is fine until I restart Max.

I've tried modifying the .mcr file in the "ENU/usermacros" folder to include the .ms file but i'm still coming up with the same issue.
fileIn ((getdir #scripts) + "\\Baj-CustomMaxTools\\fn06_connect_edge_vert.ms")

macroScript new_connect category: "Baj - Custom Max Tools" toolTip:"connect edge vert"
(
	fn06_connect_edge_vert()
)

I didn't want to make the script file structure too convoluted as my aim is to roll this out to 2 other modellers and make changes as and when needed (which is why I separated the functions into different files so I can modify them separately).

If I needed to do this, I guess the best way would be to pack as a .mzp and then create a new .mzp file each time I have updates to the scripts?

Cheers.

Replies

  • Baj Singh
    Options
    Offline / Send Message
    Baj Singh polycounter lvl 9
    Cheers Perna, will take another look.
  • monster
    Options
    Offline / Send Message
    monster polycounter
    I typically organize this way. On install I add a new path the plugin.ini and put a struct ms file in that path. Then I put a file in the UserMacro folder. I know Perna said not too. :) But I like to keep them all in one file, and they won't duplicate if it's evaluated inside that folder. I do this because the MZP files I create have an install and uninstall buttons. I guess it's not hard to predict the MCR names on uninstall, but if I only have to deal with two files and one INI entry it's easy.
    struct newToolStruct
    (
    	fn Function1 =
    	(
    	),
    	
    	fn Function2 =
    	(
    	),
    	
    	fn Function3 =
    	(
    	)
    )
    
    global newTool = newToolStruct()
    
    macroScript NewToolOperation1 category: "New Tool Operation1"
    (
    	newTool.Function1()
    )
    
    macroScript NewToolOperation2 category: "New Tool Operation2"
    (
    	newTool.Function2()
    )
    
    macroScript NewToolOperation3 category: "New Tool Operation3"
    (
    	newTool.Function3()
    )
    


    On your tools specifically, something seems inefficient about running a macro that runs a function, that runs a macro. Why not just put the operation in the macro? I think the macros.run may be language dependant.
    macroScript new_connect category: "Baj - Custom Max Tools" toolTip:"connect edge vert"
    (
    	/*Set up keyboard shortcut to create an edge between verts or edges*/	
    	if Filters.Is_EPoly() do
    	(
    		obj = modPanel.getCurrentObject()
    		
    		if subobjectLevel == 1 then
    		(
    			obj.buttonOp #ConnectVertices
    		)
    		else if subobjectLevel == 2 then
    		(
    			obj.buttonOp #ConnectEdges
    		)
    	)
    )
    
  • Baj Singh
    Options
    Offline / Send Message
    Baj Singh polycounter lvl 9
    Hey Juan, unfortunately my maxscript knowledge is still pretty barebones so issues such as efficiency are still pretty lost on me (so I do need to spend more time reading through the Maxscript intro rather than thumbing through it trying to find the relevant sections).

    My reasoning for having the function in a separate file to the macroscript was to keep all functions separate for organisational purposes rather than traipsing through a list of functions to find the one I need to modify.

    The evaluation order was confusing me the most, until Perna pointed out that I was trying to call the function before trying to initialise it. I'm still trying to get it to work, however I guess I need to look deeper into "local vs global" as when I try to define the functions within the macroscript as global, Maxscript crashes at startup.

    I havn't seen struct yet within Maxscript. I assume its somewhat similar to the class system in C# (The way you have called it looks very similar).

    So do you define all your functions within a struct (within a .ms file) and then create a .mcr file that allows the functions to be set as a keyboard/interface shortcut?
  • monster
    Options
    Offline / Send Message
    monster polycounter
    Separate files is a valid way to organize files. I just got used to fewer longer files because the MaxScript Editor only autocompletes the current file.

    If you just do operations in the macros, and not use global functions, you don't have to worry about evaluation order. I only use functions if the code is going to run more than once or from different places. But to address your issue, the global functions need to be defined before the macro is evaluated. Number one or two in this link: Start up

    Structs are nice because you can have one global for all your functions. Instead of a bunch. You'll keep hearing that it's best to avoid globals, but one or two per complex tool is necessary.
    So do you define all your functions within a struct (within a .ms file) and then create a .mcr file that allows the functions to be set as a keyboard/interface shortcut?

    Yeah, they just go in an MS file inside a Standard Script or Plugin path. But again, I only create functions if the code will be reused or executed from different locations (like a hotkey or UI). I would never create a macro that just runs a function without arguments.

    BTW, this is just how I work. I think it's mostly the right way, but with small adjustments to make it faster to iterate on tools.
  • Lamont
    Options
    Offline / Send Message
    Lamont polycounter lvl 15
    Oh man, thank for the information Juan! MaxScript is just so strange...
  • Baj Singh
    Options
    Offline / Send Message
    Baj Singh polycounter lvl 9
    Cheers chaps, this has been extremely insightful and will update this thread with my results and code (might be of help to others).
  • MoP
    Options
    Offline / Send Message
    MoP polycounter lvl 18
    Wait, what? The MAXScript Editor has autocomplete? I feel like an utter dunce now...
  • McGreed
    Options
    Offline / Send Message
    McGreed polycounter lvl 15
    Yeah, there is a tutorial about it and I added the link to my thread about MaxScript, however here is the direct one:
    http://apps.jhaywood.com/Blog/?e=51577&d=07/13/2010&s=Autocomplete%20in%20the%20MaxScript%20Editor
  • haiddasalami
    Options
    Offline / Send Message
    haiddasalami polycounter lvl 14
    MoP wrote: »
    Wait, what? The MAXScript Editor has autocomplete? I feel like an utter dunce now...

    it can be hit and miss sometimes :( Maybe just my copy of max hmmm
  • monster
    Options
    Offline / Send Message
    monster polycounter
    It does autocomplete. I didn't do the API style because I find it more useful to autocomplete my file's variables and apparently it can only do either or.

    Although, the past month or so I've been using Sublime Text 2, with a package I found on Scriptspot that lets you execute scripts remotely. Then I edited JHaywood's API script to output a sublime text autocomplete file. It's a very nice setup.
  • monster
    Options
    Offline / Send Message
    monster polycounter
    I've never done it, but it's possible with a Properties file and an API file:

    See "How to install a Properties / API" section here: https://code.google.com/p/scite-files/wiki/Customization#How_to_install_a_.properties_file
Sign In or Register to comment.