August 12, 2010 2:44 AM
Posted By James Haywood
There are three key components to getting .Net 4.0 working inside of Max 2011...
- Recompile the mxsdotNet.dlx file using Visual Studio 2010.
- Modify the 3dsMax.exe.config file.
- Install the Visual C++ 2010 components.
I'll describe each in detail below, but first I should mention that this is not officially supported by Autodesk. So if you run into trouble because of it, you're on your own. Kind of like hacking your video card to make it run faster.
I've been running Max 2011 with .Net 4.0 WPF tools running within it for a couple months now without any noticable issues. But I can't gaurantee that this will be the case for everyone. And I've only been using the 64-bit version, although I can't think of why this wouldn't work with the 32-bit version as well. As for versions of Max before 2011, I have no idea if this will work or not.
So, on to the instructions...
1. Recompiling the mxsdotNet plugin is pretty straighforward. Just install the SDK, open the ...\samples\maxscript\mxsdotNet\mxsdotNet.sln file and compile. If you don't have Visual Studio 2010, you can download the already recompiled 64-bit version below.
2. Open the ...\Autodesk\3ds Max 2011\3dsmax.exe.config file in a text editor and add the following lines right before the closing </configuration> tag...
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
3. Lastly, if you haven't already installed Visual Studio 2010, you'll need to manually install the Visual C++ 2010 components. But if you have, then these should be installed for you already. You can download the installers here...
And that's it. Once you've got all the necessary files modified correctly, you'll be able to load and use .Net 4.0 assemblies directly in Max. The DataGridView control alone is worth the effort.
Download 64-bit .Net plugin and config file here.
July 13, 2010 11:12 AM
Posted By James Haywood
You may or may not know about the autocomplete feature available in the MaxScript Editor (as of version 9 or so, I forget when it was changed exactly). It's very helpful when scripting to cut down on typos and to speed things up over all (for another way to speed up script creation, check out Johan's blog post about using abbreviations).
To enable it, select "Open Global Options File" in the "Tools" menu. Then do a search for "autocomplete" and change or insert the following lines...
You can see what each line actually does by reading the MaxScript help doc. After you save the file, you'll see the autocomplete popup menu as you type when there is only one other word in the current script that mathces what you've typed up to that point. Then just press Enter to fill out the rest of the word. You can also press Ctrl-Enter at any time while you're typing to bring up a list of possible matches which you can then select from using the up/down arrow keys.
While that alone is pretty handy, wouldn't it be useful if autocomplete didn't just look for words within the current script, but was able to match against any MaxScript command too? Well it can. You just need to provide an api file for it to use which lists all of the commands. Unfortunately, Autodesk doesn't provide one with Max, but I've made a script that will create one for you.
Download the script below and run it to create the api file. It will try to save it to your Max root folder, but if you run into trouble becuase of Windows UAC settings, just modify the script to save it somewhere else, shut down Max, and then move it to the root. Then add the following lines to the global options file...
You can actually add more than one api file, for things like custom functions and such. Just create a text file with one word on each line, or a word/period/word combination for functions within scructs, and save it to the Max root. Then and add the file name to the above line following a semicolon, like so...
The one problem with using an api file is that it takes precedent over the current script, so that you no longer get words from the script you're working on in the autocomplete list. What you can do, though, is if you're beginning to type the name of a local function or something that you know already exists in the current script, press Ctrl-Enter and you'll see your local word matches.
One last thing, I'm posting the script to create the api file instead of the api file itself because different versions of Max will have different commands available. So this lets you create a new list for every new version of Max.
Download the script here.
June 30, 2010 4:36 PM
Posted By James Haywood
I recently came across a nasty issue that comes up when hosting a WPF control inside of a docked Max rollout. The problem is that anything that causes the entire Max UI to redraw (like docking/undocking a rollout or changing the minimized state of the Graphite ribbon while it's docked) makes the WPF control completely disappear. The elements of the control pop back into existence as you mouse over them, but of course it's a pain to have to keep waving your arrow over a section of the screen to get your controls back.
Fortunately, there's a fairly easy work around to keep it from disappearing.
So, execute the following script and you'll see a row of WPF buttons in a stackpanel docked to the left side of the screen like so...
dotNet.loadAssembly @"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\v3.0\WindowsFormsIntegration.dll"
rollout wpfRefresh_RLT "" width:70 height:220
dotNetControl eh "Integration.ElementHost" width:70 height:500 align:#left offset:[-14,-5]
on wpfRefresh_RLT open do
uc = dotNetObject "System.Windows.Controls.UserControl"
eh.child = uc
sp = dotNetObject "System.Windows.Controls.StackPanel"
for i = 1 to 10 do
btn = dotNetObject "System.Windows.Controls.Button"
btn.height = 20
btn.content = "button " + i as string
uc.content = sp
createDialog wpfRefresh_RLT style:#(#style_toolwindow,#style_sysmenu,#style_resizing)
cui.RegisterDialogBar wpfRefresh_RLT style:#(#cui_floatable,#cui_dock_left,#cui_handles)
cui.DockDialogBar wpfRefresh_RLT #cui_dock_left
And now if you do something to make the UI redraw, like I mentioned above, you get this...
Wave the mouse arrow over the controls and you'll see them reappear one at a time.
The way to keep this from happening is to catch the Paint event on the ElementHost and manually force it to redraw by calling it's Refresh() method. That's easy enough, but it turns out that calling Refresh() causes the Paint event to trigger again. So it gets into a nice little infinite loop and really messes with Max's overall performance.
So we need to add one more step, which is to use a boolean variable to make sure that it only refreshes once and then stops.
Add the following to the rollout to make these changes:
local doRefresh = true
on eh Paint args do
if doRefresh then
doRefresh = false
doRefresh = true
Now the WPF control will redraw itself whenever it needs to. The full script can be downloaded here.
June 24, 2010 12:28 PM
Posted By James Haywood
Torus on the highway
I was recently directed to a great HDR toolset called Smart IBL. It's basically a system for creating HDR images with a bunch of imbedded information that makes it really easy to set up a realistic rendering environment inside of any (well most) 3D apps.
The main application is called sIBL-GUI. It's a browser for your sIBL set, and the interface for connecting to the 3D app. It's really easy to set up with Max so that all you have to do is download or create some sIBL files, add them to the sIBL-GUI database, select one, and then click a button to have a light (or lights), a ground plane, and environment settings all created automatically.
The other tool, sIBL-Edit, is also useful, but the automated script for creating the Max environment isn't as up to date as the sIBL-GUI version. So use GUI for 3D app interop, and Edit for modifying the embedded information.
I've been having a lot of fun with both of these lately, and have even contributed to the Max template in the GUI app. So if you're doing any HDR rendering, give it a shot.
HDR Labs Home
June 14, 2010 6:29 PM
Posted By James Haywood
This will be a short post. I just wanted to finish up this series about hosting a WPF control inside of Max by showing how, as one final method, you can also use a WPF window instead of either the MaxForm window or the rollout. The script code is basically the same as the MaxForm version, minus the ElementHost. You don't need it because the WPF control is being loaded into a WPF window. No host needed.
dotNet.loadAssembly @"<folder name>\ProgressBar\ProgressBar\bin\Debug\ProgressBar.dll"
bar = dotNetObject "ProgressBar.UserControl1"
frm = dotnetobject "System.Windows.Window"
frm.title = "Progress"
frm.width = bar.width + 16
frm.height = bar.height + 34
frm.windowStartupLocation = frm.windowStartupLocation.centerScreen
frm.windowStyle = frm.windowStyle.toolWindow
frm.content = bar
There are a couple of extra drawbacks though. One, you need to manage all of the foreground and background colors yourself if you want it to look like it's part of Max. Same goes for assigning the parent window as Max itself, so that it will follow along with Max as you maximize/minimize or navigate away to different programs. Otherwise it just kinds of floats off by itself and is easy to lose.
Finally, and probably most importantly, you need to set the "accelerators" state depending on whether the window has focus or not. Accelerators are just another name for hotkeys. And if don't manually manage this, the user won't be able to type into any text boxes in your tool. So in the "GotFocus" event you'll want to turn hotkeys off with "enableAccelerators = false". And then turn them back on in the "LostFocus" event.
So overall, unless you're planning on doing something that you can't do with a regular window, like changing the shape or something crazy like that, I don't see any benefit to using a WPF window over either of the other two methods.