[Closed] Issues with Macroscript Toolbar buttons and fileIn/Include commands
I am building a series of tools along with a browser tool that scans my directories and builds a dynamic list based upon tools found within. I have built them inside structs to allow similar naming conventions to make them easy to understand and to prevent accidental overlap with multiple tools running.
The scripts on their own work fine when launched from the script editor, but upon making a macroscript button to launch to main browser tool, the whole project falls apart.
I’ve made macroscript launch buttons before. I have other tools already on my toolbar, but those tools’ ms files are in the plugin folder, so they are being launched as Max starts, and the button just executes a .run() command to open and close the dialog. Those toolbuttons look like this:
macroScript morphtoollauncher
category:"Dstinct Tools"
buttonText:"Morph Tool"
toolTip:"Launch/Close Morph Tool."
(
on execute do
(
mirrorVert.run()
)
)
The launcher I’m trying to make for the browser looks like this (There’s no gap in FXAssetBrowser, for some reason it’s just parsing the text like that):
macroScript fxassetbrowserlauncher
category:"Dstinct Tools"
buttonText:"FX Browser"
toolTip:"Launch/Close Material FX Browser."
(
on execute do
(
::fileIn @"C:\Users\Dstinct\Desktop\FXTD\devFXTDT\FXAssetBrowser\fxAssetBrowser.ms"
fxAssetBrowser.run()
)
)
When I click on the button, I get the error message: “–Unknown property: ‘run’ in undefined”. The macroscript then opens up in the editor window with the line it’s stuck on highlighted. If I evaluate the whole script that just opens, I get the notification “26001
OK” to show that it’s been added. If I then click the macrobutton, the tool opens, but clicking it again should close the tool because of the way the .run() script is written. What’s strange is that the fileIn commands executed by the _run and _open buttons work fine. I was also able to get the browser to open by only putting a fileIn command in the macrobutton that calls an external ms file that has the fileIn and .run() command that I originally had in the macrobutton launcher, but the _asPub button fails on launch. Even stranger, doing it this way, the _asPub button errors out and the Editor window opens. I close the window and browser tool, then repress the macrobutton to launch the tool, and then the _asPub button works.
The related part of the toolcode looks like this:
try(destroyDialog fxAssetBrowser._assetBrowserR)catch()
struct fxAssetBrowser
(
_assetBrowserR = undefined,
LibPath = @"C:\Users\Dstinct\Desktop\FXTD\devFXTDT\FXToolsLibrary\",
_assetItems = getdirectories @"C:\Users\Dstinct\Desktop\FXTD\devFXTDT\FXToolsLibrary\*",
_assetItemsUI = #(),
fn uiSort =
(
for i = 1 to _assetItems.count do
(
_assetItemsUI[i]=(filterstring _assetItems[i] @"\")[8]
)
),
fn UI =
(
rollout _assetBrowserR "FX Browser" width:125
(
local btWid=_assetBrowserR.width-6
listbox _assetList "Asset List" items:_assetItemsUI width:btWid align:#center
button _run "Run Tool" width:btWid align:#center
button _open "Open / Close Dialog" width:btWid align:#center
button _asPub "Open Asset Publisher" width:btWid align:#center
button _explLib "Open Asset Library" width:btWid align:#center
button _reset "Reload Browser" width:btWid align:#center
on _run pressed do
(
FXAssetDir = fxAssetBrowser._assetItems[_assetList.selection]
FXAssetMarkerFile = "FXS_Asset_"+fxAssetBrowser._AssetItemsUI[_assetList.selection]+"_Marker.ms"
::filein (FXAssetDir + FXAssetMarkerFile)
try
(
FXAssetRunFile = "FXS_Asset_"+fxAssetBrowser._AssetItemsUI[_assetList.selection]+"_Run.ms"
::filein (FXAssetDir + FXAssetRunFile)
)
catch()
)
on _open pressed do
(
try(FXAssetDir = fxAssetBrowser._assetItems[_assetList.selection]
FXAssetRunFile = "FXS_Asset_"+fxAssetBrowser._AssetItemsUI[_assetList.selection]+"_Run.ms"
::filein (FXAssetDir + FXAssetRunFile))
catch(messageBox "This tool does not have a Dialog Window." title:"Error")
)
on _explLib pressed do
(
shelllaunch fxAssetBrowser.LibPath ""
)
on _asPub pressed do
(
::filein "C:\Users\Dstinct\Desktop\FXTD\devFXTDT\FXAssetPublisher\assetPublisher.ms"
fxAssetPub.run()
)
on _reset pressed do
(
fxAssetBrowser.run()
::filein @"C:\Users\Dstinct\Desktop\FXTD\devFXTDT\FXAssetBrowser\fxAssetBrowser.ms"
fxAssetBrowser.run()
)
on _assetBrowserR close do
(
fxAssetBrowser._assetBrowserR=undefined
)
)
),
fn run =
(
if _assetBrowserR==undefined then
(
_assetBrowserR=ui()
fxAssetBrowser.uiSort()
viewportScreenPos = mouse.screenpos - mouse.pos
createDialog _assetBrowserR pos:[(viewportScreenPos[1]+10),(viewportScreenPos[2]+30)] style:#(#style_toolwindow,#style_sysmenu)
)
else
(
destroyDialog _assetBrowserR
fxAssetBrowser._assetBrowserR=undefined
)
)
)
fxAssetBrowser=fxAssetBrowser()
Executing this script on its own followed by the run function allows everything to work perfectly fine. It just won’t launch from the macroscript launcher. I’ve tried all kinds of variations of fileIn and Include, but nothing seems to work. While troubleshooting, I placed the ms file in the plugin folder like my other plugins. Upon doing so, the dialog opens as it should. The problem is that the button for the asset publisher, which also uses a fileIn command, doesn’t work, giving me the same error as the browser: “–Unknown property: ‘run’ in undefined”.
I’m a mid-level coder, so maybe I’m missing something really simple, but it appears that for, whatever reason, the macroscripts do not like the fileIn command, at least if it’s directly followed by a hardcoded directory as opposed to an assembled string. Is there a better way to implement these tools? Or is there a specific way you have to code the fileIn command for it to work within a macroscript?
Thanks for any help. I’m really stuck here.
Josh
Try it like this
on execute do
(
fileIn @"C:\Users\Dstinct\Desktop\FXTD\devFXTDT\FXAssetBrow ser\fxAssetBrowser.ms"
::fxAssetBrowser.run() --notice the ::
)
The reason for this problem is related to how MAXScript handles symbol resolution.
Whenever mxs enters a block of code, it immediately resolves all symbols in the code to a scoped variable.
For example
(
local a = 5
a = a + b
)
Upon entering the block, and before executing any statement, mxs will resolve ‘a’ to be a local variable, and will look for ‘b’ in any higher level scopes. If it doesn’t find it in any scope, it will look in the global scope. If it doesn’t find it there, it will resolve it to an undefined local value, because any declarations are implicitly local.
Now let’s go back to your filein example.
(
filein "C:\\myfile.ms"
MyVar.Run()
)
Upon entering the block, mxs tries to resolve the scope of MyVar. It doesn’t find it in any scope, so it resolves it to an undefined local variable.
Only then, does your filein statement define this (global) variable.
Using the :: operator, you are explicitly telling mxs that you are referring to a variable in the global scope.