dotNet + MXS


I think it does, although maybe not in pre 3.5 frameworks. So I think you should be able to call ToArray on the IEnumerable and then maxscript will convert the resulting .net array into a maxscript array automatically.


I really don’t think it does. I’m using Max 2012, and up to date with the latest dotNet framework.

Try executing the following…

var = dotNetClass "System.Collections.Generic.IEnumerable`1[System.Int32]"

This error is returned…
– Unknown property: “toArray” in dotNetClass:System.Collections.Generic.IEnumerable`1[[System.Int32, mscorlib, Version=, Culture=neutral, PublicKeyToken=b77a5c561934e089]]

But this works just fine…

var = dotNetObject "System.Collections.Generic.List`1[System.Int32]"
   var.Add 1

Plus, even if it does have a .ToArray() extension and I’m just not seeing it, that would take care of IEnumerable to array, but not MXS array to IEnumerable.


do you want to do it nice and elegant or just do it?


I’ll have to do it a lot, so nice and elegant would be good, but really, I just want to do it. :slight_smile:


It’s like reverse Bible.
ArrayList implements IList. IList implements ICollection. ICollection implements IEnumerable…
Want is the reason to cast ArrayList to IEnumerable?


Something that inherits from IEnumerable just provides an iterator, there is no ‘Count’ property. Without a ‘count’ you cannot convert to a fixed size collection/array. You simply don’t have enough information to set the size of the destination array.

You may be able to write some C# to convert/cast your specific IEnumerable derived type to something that is fixed size if it also inherits something like ICollection, then use a ToArray() method (or perhaps the CopyTo() that ICollection provides)

If all you know is that your input is derived from an IEnumerable, you might be best to brute force it and iterate over all the elements in maxscript to build up your mxs array:

fn IEnumerableToMXSArray yourEnumerable = (	
	ret = #()
	iter = yourEnumerable.getEnumerator()
	while iter.MoveNext()  do 
		-- Careful this loop may never terminate!
		-- Consider an IEnumerable that generates all positive integers
		-- or consecutive digits of Pi...
		append ret iter.Current

var = dotNetObject "System.Collections.Generic.List`1[System.Int32]"
for i = 1 to 10 do var.add i
IEnumerableToMXSArray var

I usually try to do my ‘work’ inside the while loop and don’t bother to build up an array.


i would do it with c#. IEnumerable is not really supported by mxs, why i have to stay with the script?


Hello !

I’m a dotNet beginner, and i’m trying to learn all that stuff when I have time… I just recently succeeded in creating a treeView… yay :P…

Well, that’s not the point ^^

I’m experiencing a pair of issues with my treeView, and I wandered if there was a solution or if it’s a “normal problem” with dotNet. Because I didn’t find a thing about these yet.

The first problem, is that I can’t keep my selected node highlighted when I click on another button of my rollout or when I click outside of the rollout… is there a way to always show what node is selected ?

The second one, is that since I integrated the treeView, when I run my rollout script or when I click on the treeView, all 3dsMax shortcuts are disabled and it only beeps when I press a key. And well… it’s a bit annoying ^^’. I must click back on my viewport if I want to use any shortcut. It doesn’t even work when I only click on 3dsMax interface.


Does anyone know how to get layerinformation (name) into a dotnet list column?

I am using Paul Neales dotnet list script and I want to add a column that displays the layername of the objects in a scene.

Using the following snippet:

li.subitems.add (try((LayerManager.getLayerFromName as string)catch("--")) --Add layername

But the column just fills up with undefined.

This is the populatelist snippet:

fn populateList theLv=
		rows=#()		--Empty array to collect rows of data
		layerNames = for x = 0 to (layerManager.count-1) collect (LayerManager.getLayer x).name

		for x in objects do		--Loop through all the objects in the scene.
			li=dotNetObject "System.Windows.Forms.ListViewItem"		--Create a listViewItem object and name it.
			li.subitems.add (try((LayerManager.getLayerFromName as string)catch("--")) --Add layername
			--			 li.subitems.add ((TotalArray) as string)		--Add total polycount data
			li.Tag = dotnetMXSValue x
			append rows li		--Added the listViewItem to the rows array
		theLv.items.addRange rows		--Add the array of rows to the listView control.


try adding this on open/initializing:
myTreeView.HideSelection = false

Im not sure how to change the very light grey colour though… would like to know!


have a look here for the answer to that from DenisT


hello, im trying to use backgroundworkers for multithreaded world generating but it allways ends with application error on random part of code :sad:

better description of my problem:
this is my small project on which im trying to learn maxscript. with only input - textures, heightmap and few other parameters it will generate terrain like in Minecraft:

the main problem is that it will took about 1h to generate region 250x250 blocks, so i have decided to slice terrain to smaller chunks and generate each chunk via own thread on multiple cpu cores.
this is example of my code with one bgworker: pastebin
everything works fine when i call functions in listener, but when bgworker call same function it allways ends by application error on random time and random line
for example:

<loop x, y> do(
local box_instance = instance $Grass
box_instance.pos = [ BlockSize*x, -BlockSize*y, BlockSize*(GetHeight x y) ]

it will create 50instances and 51st instance is app error on line “local box_instance = instance $Grass” because $Grass is undefined :surprised
as i mentioned im new to maxscript so i have no clue how to make this work
thank you for every idea


does anyone know how to create LookAndFeel in max 2012

  treeList = dotnetobject "DevExpress.XtraTreeList.TreeList"
  a = dotnetobject "DevExpress.LookAndFeel.UserLookAndFeel" treeList

works fine in 2010 and gives the error in 2012:

  -- Runtime error: dotNet runtime exception: MethodInfo must be a runtime MethodInfo object.
  Parameter name: method



i don’t have 2012 to test but maybe try the CreateInstance method of the Activator class?


the same error:

(dotnetclass "Activator").CreateInstance (dotnetclass "DevExpress.LookAndFeel.UserLookAndFeel") #(dotnetobject "DevExpress.XtraTreeList.TreeList")
-- Runtime error: dotNet runtime exception: MethodInfo must be a runtime MethodInfo object.
Parameter name: method

it works for 2010 and doesn’t work for 2012… could anyone try it for 2011 please?


2011 works fine


I don’t have 2012 to experiment with, but you could try different flavours of the constructor:

treeList = dotnetobject "DevExpress.XtraTreeList.TreeList"
a = dotnetobject "DevExpress.LookAndFeel.UserLookAndFeel"  treelist
b = dotnetobject "DevExpress.LookAndFeel.UserLookAndFeel"  treelist.LookandFeel
c = dotnetobject "DevExpress.LookAndFeel.UserLookAndFeel"  (treelist.get_LookandFeel())
format "'treelist.lookandfeel' is a %
" (treelist.lookandfeel.tostring())
format "'a' is a %
" (a.tostring())
format "'b' is a %
" (a.tostring())
format "'c' is a %
" (a.tostring())

These all run in for me in 2011, but I don’t know that what I get back for a,b, & c are useful to you.

My output is:

‘treelist.lookandfeel’ is a DevExpress.LookAndFeel.Helpers.ControlUserLookAndFeel
‘a’ is a DevExpress.LookAndFeel.UserLookAndFeel
‘b’ is a DevExpress.LookAndFeel.UserLookAndFeel
‘c’ is a DevExpress.LookAndFeel.UserLookAndFeel


all of these don’t work in 2012 anymore.
the problem is that max 2012 creates TreeList with undefined LookAndFeel :frowning:


Remember that dotNetObject calls the constructor of the class with the parameters given if any.
dotNetClass returns the class object itself, which can be usefull if you have static methods on it.

you also have dotNetMethod which allows you to put a method desc into a maxscript variable.
at least that what I found out for 3dsmax 2012.

Not sure if its the same for earlier versions.

I used a background thread as well and ManagedServices.dll to run the majority of the plugin in a .Net assembly, and communicate with 3dsmax by sending maxscript commands.
In my own plugin




With reference DenisT’s reply on how to reload in 3dsMax a recently re-compiled dll without having to restart that session of 3dsMax, I’m still a little confused if this is possible? Here’s some sample code. Perhaps someone could explain if this is possible and what I’m doing wrong?

try(destroyDialog theRollout)catch()
Testdll = "C:/Testdll.dll"
local assembly = (dotNetClass "System.Reflection.Assembly").Load ((dotNetClass "System.IO.File").ReadAllBytes Testdll)
myClass = assembly.CreateInstance "TestNamespace.TreeView"

rollout theRollout "Test" width:600 height:600
	dotNetControl myClass "TestNamespace.TreeView" pos:[0,50] width:500 height:500
	on theRollout open do
createDialog theRollout