[Closed] [Maxscript] Using relative paths in Include
Hi
Is there any way to use relative paths when using Include?
Let’s say we have a main tool script, and several smaller scripts that are Included into the main tool. So we have a folder structure like this:
/Project
——/MainTool.ms
——/ToolFunctions.ms
——/ToolRollout.ms
In MainTool.ms, we want to do this:
Include "ToolFunctions.ms"
Include "ToolRollout.ms"
This totally works. However, it seems like Include also looks for scripts in other folders. If we move the ToolFunctions.ms and ToolRollout.ms scripts into \AppData\Local\Autodesk\3dsMax[version]\ENU\scripts, they are also successfully included into MainTool.ms. What’s more annoying, the AppData folder has a higher priority than the Project Folder. If ToolFunctions.ms and ToolRollout.ms exist in both the Project Folder and AppData, the scripts in AppData is the one that’s actually included.
This is a problem because we want to develop the script in a version controlled (git) folder. Then, when the script is ready, we install the scripts into the AppData folder. If we then make changes in the Project Folder scripts, these scripts are not Included into the MainTool.ms (when running it from the Project Folder), because the older versions also exist in the AppData folder.
So how can we force the MainTool.ms to Include the scripts in the relative folder? We’ve tried using “.” symbols in the Include pathname, but this didn’t work.
Thanks!
Thanks, we experimented with this, and it works when we do:
scriptPath = pathConfig.removePathLeaf (getSourceFileName())
Include (scriptPath + "\\" + "ToolRollout.ms")
But now we get another issue where ToolRollout.ms is included, but not run. We have createDialog ToolRollout at the end of ToolRollout.ms, but the rollout is never created.This is an issue even if we do Include “ToolRollout.ms”, so it’s not an issue related to the whole getSourceFileName() business. Are we missing something here? How do we run the included script?
The way we fixed this before was to wrap MainTool.ms in parentheses. This actually runs the script, and creates the dialog:
(
Include ("ToolRollout.ms")
)
However, this doesn’t work when using getSourceFileName(). This returns Compile error: include expected filename string:
(
scriptPath = pathConfig.removePathLeaf (getSourceFileName())
Include (scriptPath + "\\" + "ToolRollout.ms")
)
try
Include (scriptPath + "/ToolRollout.ms")
-- or
Include (scriptPath + @"\ToolRollout.ms")
Sorry, this doesn’t work either.
No worries though, since we changed it out to use fileIn instead.
Ok, we managed to get it working using fileIn instead of Include.
We had problems with this before when using fileIn on multiple rollouts, where the first rollouts couldn’t access the later rollouts the first time the script is run per max session.
--In ToolRollout1.ms:
global rollout1
rollout rollout1 "Rollout 1"
(
button button1 "Button 1"
on button1 pressed do
print rollout2
)
createDialog rollout1
--In ToolRollout2.ms:
global rollout2
rollout rollout2 "Rollout 2"
(
button button2 "Button 2"
on button2 pressed do
print rollout1
)
createDialog rollout2
--In MainTool.ms:
fileIn "ToolRollout1.ms"
fileIn "ToolRollout2.ms"
In the above example, when pressing button1, it would print undefined. When pressing button2, it would print Rollout:rollout1. Please note, this happens the first time the script is run. If we run it again in the same max session, both buttons print correctly. Even when setting rollout1 and rollout2 = undefined and performing a gc(), it still works. I can’t wrap my head around why this is.
We took a look at the Maxscript docs, and found the page Specifying Global Variables As Global Using ::. So, using print ::rollout2 and print ::rollout1, works perfectly. Though I still feel that this just fixes the symptoms, not the actual cause.
include will insert the whole code in specific location with recpect of “Scope Of Variable” and also return value, but filein just works like execute a string in global scope, its not necessary to make anything global, you can use include pattern like this:
rollout rollout1 "Rollout 1"
(
)
createDialog rollout1
rollout1
rollout rollout2 "Rollout 2"
(
button button2 "Button 2"
on button2 pressed do print rollout1
)
createDialog rollout2
rollout2
(
rollout1 = include "ToolRollout1.ms"
rollout2 = include "ToolRollout2.ms"
)
That was how we wrote the script to begin with, only to realize that if a script with the same name is located in \AppData\Local\Autodesk\3dsMax[version]\ENU\scripts, that script is the one that’s actually Included. Hence why we would like to force Include to use relative paths, or by specifying the path directly.
Try it: copy ToolRollout1.ms and ToolRollout2.ms to \AppData\Local\Autodesk\3dsMax[version]\ENU\scripts, add some prints so you can tell them apart, and run MainTool.ms again. You will see that the AppData ones are the ones that are Included.
I don’t get the problem, assigning direct path does not work for you? for example:
include "C:/Users/Mehdi/Desktop/Temp/Test/ToolRollout1.ms"
if that works, you may have special characters in the filepath, as Denis said, you could add @ at the beginning of the path:
fn IncludeFile thePath = execute ("include @\"" + thePath + "\"")
scriptPath = pathConfig.removePathLeaf (getSourceFileName())
IncludeFile (scriptPath + "\\" + "ToolRollout1.ms")
Sorry, forget I said that (I tried getting the direct path using getSourceFileName() before, which didn’t work when using Include. Read previous posts for details)
As I said in my original post, I want them relative to where MainTool.ms is.
Thanks, this works
The same issue pops up here though:
But, we found a workaround for that, so no need to investigate further. Thanks for the help.