dotNet + MXS


#501

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.


#502

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]"
   var.ToArray()

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

But this works just fine…

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

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.


#503

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


#504

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:


#505

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


#506

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
	)
	ret
)

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.


#507

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


#508

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.


#509

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 x.name) 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" x.name		--Create a listViewItem object and name it.
						   
			li.subitems.add (try((LayerManager.getLayerFromName x.name) 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.
	)

#510

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!


#511

have a look here for the answer to that from DenisT
http://forums.cgsociety.org/showpost.php?p=6234202&postcount=417


#512

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


#513

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
  

thanks


#514

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


#515

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?


#516

2011 works fine


#517

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


#518

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


#519

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 http://forums.cgsociety.org/showthread.php?p=7118556#post7118556


#520

Hi,

ref: http://forums.cgsociety.org/showpost.php?p=6868022&postcount=483

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
 		(
		myClass.PopulateTreeView()
		)
	)
createDialog theRollout
)

Thanks,
Mike