Posted By James Haywood

MaxScript Editor Autocomplete

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...

autocompleteword.automatic=1
autocomplete.*.ignorecase=1
autocomplete.choose.single=0

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...

autocomplete.*.start.characters=$(chars.alpha)$(chars.numeric)$_@#.
api.*.ms=maxscript.api

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...

api.*.ms=maxscript.api;mytools.api

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.


 
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...

WPF refresh issue 1

------------------
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
       sp.children.add btn
     )
     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...

WPF refresh issue 2

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
       eh.refresh()
       doRefresh = true
     )
)
-------------------


Now the WPF control will redraw itself whenever it needs to.  The full script can be downloaded here.


 

 

 
Google

User Profile
James Haywood
Seattle, WA

 
Category
 
Archives
 
Links
 
Visitors

You have 455478 hits.

 
Navigation