Notifications
Clear all

[Closed] Cast Scene Object to IINode

 MZ1

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.

11 Replies

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

1 Reply
 MZ1
(@mz1)
Joined: 11 months ago

Posts: 0

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

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

1 Reply
 MZ1
(@mz1)
Joined: 11 months ago

Posts: 0

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

 MZ1

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

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

1 Reply
(@aaandres)
Joined: 11 months ago

Posts: 0

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.

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]

)
1 Reply
 MZ1
(@mz1)
Joined: 11 months ago

Posts: 0

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.

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

)

1 Reply
 MZ1
(@mz1)
Joined: 11 months ago

Posts: 0

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

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