Cast Scene Object to IINode


#1

I wanna convert this function to the c# version:


fn DotNet_InterpCurve3D theShape Prm =
(
   maxGlobal = (dotnetclass "autodesk.max.globalinterface").instance
   inode = maxGlobal.COREInterface14.GetINodeByHandle theShape.inode.handle asdotnetobject:true
   iobj  = (inode.EvalWorldState maxGlobal.COREInterface.Time true asdotnetobject:true).Obj
   pos = iobj.interpCurve3D 0 0 Prm 0
   [pos.x,pos.y,pos.z]
)

At the beginning I just want to know how we can cast a max object to IINode? I got error with this code:
– Runtime error: No ‘MyFunction’ method found which matched argument list


using Autodesk.Max;
namespace MyProject
{
    public static class MyClass
    {
        public static void MyFunction(IINode node)
        {


        }
    }
}


I also tested IValue but no chance to work.


#2

I suppose it is due to the fact that maxscript INode is actually a wrapper and not an IINode your c# function expects.
You can either pass the handle to get the node or you can execute maxscript on c# side using ExecuteMAXScriptScript to get FPValue


#3

It works fine for me… What’s the problem? What are you passing as parameter?


   maxGlobal = (dotnetclass "autodesk.max.globalinterface").instance
   inode = maxGlobal.COREInterface14.GetINodeByHandle theShape.inode.handle --asdotnetobject:true (don't need it)

   test = dotnetClass "MyProject.MyClass"
   test.MyFunction inode


#4

I didn’t get what you said about ExecuteMAXScriptScript, but handler works perfect:


using Autodesk.Max;
namespace MyProject
{
    public static class MyClass
    {
        public static IPoint3 InterpCurve3D(uint handle,float param)
        {
            var g = GlobalInterface.Instance;
            var i = g.COREInterface14;
            IINode node = i.GetINodeByHandle(handle);
            IObject obj = node.EvalWorldState(g.COREInterface.Time, true).Obj;
            ISplineShape shape = obj as ISplineShape;
            return shape.InterpCurve3D(0, 0, param, 0);
        }
    }
}


_InterpCurve3D = (dotnetclass "MyProject.MyClass").InterpCurve3D

fn MyInterpCurve3D Spline Param:.5 =
(
   Pos = _InterpCurve3D Spline.inode.handle Param
   [pos.x,pos.y,pos.z]
)

MyInterpCurve3D Spline


#5

I didn’t know we should send the handler, and I was trying to pass the object directly as IINode, that was not correct.


#6

Comparing to Max version is 80 times slower and seek much more memory:

.Net >> time:878 memory:764872L
Max >> time:10 memory:196L


#7

I’ve just checked it and it is indeed works ok with INode


(

local source = "using Autodesk.Max;
                public class Test2 {
                    static public void toggleNode( IINode node ){ node.Hide(!node.IsObjectHidden);}                                
                }
                "


compilerParams = dotnetobject "System.CodeDom.Compiler.CompilerParameters"
compilerParams.ReferencedAssemblies.Add "System.dll"
compilerParams.ReferencedAssemblies.Add (getdir #maxroot + "autodesk.max.dll")

compilerParams.GenerateInMemory = on
csharpProvider = dotnetobject "Microsoft.CSharp.CSharpCodeProvider"
compilerResults = csharpProvider.CompileAssemblyFromSource compilerParams #( source )

if (compilerResults.Errors.Count > 0 ) then
(
    local errs = stringstream ""
    for i = 0 to (compilerResults.Errors.Count-1) do
    (
        local err = compilerResults.Errors.Item[i]
        format "Error:% Line:% Column:% %
" err.ErrorNumber err.Line err.Column err.ErrorText to:errs
    )
    format "%
" errs
    return undefined
)



compilerResults.CompiledAssembly.createInstance "Test2"



    delete objects
    gc()
        
    t = Teapot isSelected:true

    g = (dotNetClass "Autodesk.Max.GlobalInterface").Instance
    inode = g.COREInterface.GetINodeByHandle t.inode.handle

    try (destroydialog X ) catch ()
    rollout X "" (

        button btn "toggle"
        
        on btn pressed do (
            (dotnetclass "Test2").toggleNode inode
            redrawViews()
        )
    )
    createDialog X pos:[100,100]

)

#8

Of course works, because you converted .inode to the IINode before passing to the function. I want to do minimal code in MaxScript, So I prefer to pass handler.


#9

and here’s the fpvalue. Not sure if it is useful, but it may help you pass some arbitrary data to c# side


(

local source = "using Autodesk.Max;
                public class Test3 {
                    static public string getMXSvariable( string nodeVar ){
                        var g = Autodesk.Max.GlobalInterface.Instance;
                        IFPValue fpv = g.FPValue.Create();
    
                        g.ExecuteMAXScriptScript( (\"::\" + nodeVar), true, fpv);
    
                        return fpv.N.Name;
    
                    }                                
                }
                "


compilerParams = dotnetobject "System.CodeDom.Compiler.CompilerParameters"
compilerParams.ReferencedAssemblies.Add "System.dll"
compilerParams.ReferencedAssemblies.Add (getdir #maxroot + "autodesk.max.dll")

compilerParams.GenerateInMemory = on
csharpProvider = dotnetobject "Microsoft.CSharp.CSharpCodeProvider"
compilerResults = csharpProvider.CompileAssemblyFromSource compilerParams #( source )

if (compilerResults.Errors.Count > 0 ) then
(
    local errs = stringstream ""
    for i = 0 to (compilerResults.Errors.Count-1) do
    (
        local err = compilerResults.Errors.Item[i]
        format "Error:% Line:% Column:% %
" err.ErrorNumber err.Line err.Column err.ErrorText to:errs
    )
    format "%
" errs
    return undefined
)



compilerResults.CompiledAssembly.createInstance "Test3"



    delete objects
    gc()
        
    t = Teapot()
    tt = Teapot name:"SomeName"

    g = (dotNetClass "Autodesk.Max.GlobalInterface").Instance
    inode = g.COREInterface.GetINodeByHandle t.inode.handle

    
    global tmpVar = t

    format ">> % - %
" t ((dotnetclass "Test3").getMXSvariable "tmpVar")
    format ">> % - %
" tt ((dotnetclass "Test3").getMXSvariable "tt") -- will fail because[b] tt [/b]is local

)


#10

It’s not needed in this case, but yes it’s useful Thank You.


#11

To take advantage of C #, you have to code the more possible in C#, specially loops and calculations. If not, you lose all the advantages when calling the functions from maxscript and converting back the returned data to maxscript.


#12

I’ve found this thread where, at its end, I shew a curious method to send maxscript entities to C# using rootnode custom attributes:
http://forums.cgsociety.org/showthread.php?p=8172164#post8172164