An old question


#1

I want to write the plugin entirely in c#, and a lot of the functions are for spline shape. But line can’t turns into spline shape. Experts, how do you operate line. I feel line is an independent freak. Is there any way to deal with it. Thank you very much!


#2

According to sdk docs line derives from SimpleSpline, so in theory you should be able to cast/convert to it. In c# you can’t be sure whether it will work or not

SimpleSpline - This is a class used in the creation of shape plugins. Most of the 3ds Max shapes and splines are derived from this class. For example, Line, Arc, Circle, Ellipse and Star are all SimpleSplines. This class is defined in \MAXSDK\INCLUDE\SIMPSPL.H.


#3

Yes, I also see these explanations, but I get an error when I try to cast it to convert .

ISimpleSpline spl = (ISimpleSpline)obj ;


#4

try to convert it using CustomMarshalerSimpleSpline from autodesk.max.wrappers.dll I believe there should be examples of how to use it


#5

Serejah, You are my savior, I have been suffering for a long time, OK, I will read it carefully, if there is anything I don’t understand, I will report back. Thank you again


#6

@Serejah , Unfortunately I couldn’t find “autodesk.max.wrappers.dll” in the 3dsmax installation directory. So there is no way to use the method you provided . :disappointed_relieved:


#7

why’s that? it is located in <maxroot>/bin/assemblies folder for ages


#8

:grinning: I’m a raw recruit . I try again.


#9

ICustomMarshaler marshaler = Autodesk.Max.Wrappers.CustomMarshalerSplineShape.GetInstance(“what goes there?”);
System.IntPtr ptr = marshaler.MarshalManagedToNative(obj);
object sobj = Marshal.GetObjectForNativeVariant(ptr);
oldNode.ObjectRef = (IObject)sobj;
There still seems to be no way to convert Line to Spline Shape .


#10

no-no, you have to use NativePointer to cast from native to managed.
check out these threads for more info
https://forums.autodesk.com/t5/forums/searchpage/tab/message?advanced=false&allow_punctuation=false&filter=location&location=forum-board:area-b35&q=MarshalNativeToManaged




#11

These examples are a little esoteric for newcomers,Like how do you create a new managed instance.
Can you tell me directly that How to convert a line into Spline Shape .


#12


This article finally discussed also did not have a result, very regrettable


#13

It is funny, but I just found my own thread with same exact question.
And it turns out that you have to add an edit spline modifier to the line object to convert it to splineshape


make a line object, select it and run

(
	format "-> %\n" (classof $.baseobject)
-- uncomment and check if it works now ;)
-- 	if classof $.baseobject == line do
-- 	(
-- 		addModifier $ (edit_spline())
-- 	)

	g     = (dotNetClass "Autodesk.Max.GlobalInterface").Instance
	inode = g.coreinterface7.getselnode 0
	os    = inode.evalworldstate g.coreinterface7.time true
	obj   = os.obj

	cid    = g.class_id.create splineshape.classid[1] splineshape.classid[2] 
	convertible_to_splineshape = (obj.CanConvertToType cid) != 0

	if convertible_to_splineshape do
	(	
		converted = obj.ConvertToType currenttime.ticks cid
		inode.ObjectRef = converted
	)
	
	format "-> %\n" (classof $.baseobject)

)

#14

Your code will work for any shape(Shape Object) but line.Like you said,Casting to some other type is a dead end.
The only way to do that is to add the Edit_Spline modifier.But when it is refreshed, it disappears again. Whether to put it to Managed.If there are other modifier on the line, it is also a very tricky problem.

IInterface core = g.COREInterface;
int t = core.Time;
int modstyle = core.CommandPanelTaskMode;
IClass_ID EDITABLESPLINE_CLASS_ID = g.Class_ID.Create(96,0);
object objMod = core.CreateInstance(SClass_ID.Osm, EDITABLESPLINE_CLASS_ID);
IModifier mod = (IModifier)objMod;
IIDerivedObject dobj = g.CreateDerivedObject(obj);
dobj.AddModifier(mod, null, 0); // top of stack
oldNode.ObjectRef = dobj;
core.CollapseNode(oldNode, false);


#15

When I used OutlineMove in ISplineShape state.It goes back to a line.Miracle!!Do I have to update it, or there is an important step missing

ISplineShape spl = (ISplineShape)sobj;
spl.OutlineMove(t,10);


#16

just a quick dirty test code

static public ISplineShape GetSplineShape(uint handle)
        {

            IGlobal global = GlobalInterface.Instance;
            var node = global.COREInterface7.GetINodeByHandle(handle);
            IObject obj = node.EvalWorldState(global.COREInterface.Time, true).Obj;


            if (obj.CanConvertToType(global.SplineShapeClassID) > 0)
            {

                IInterface core = global.COREInterface;
                int t = core.Time;
                int modstyle = core.CommandPanelTaskMode;
                IClass_ID EDITABLESPLINE_CLASS_ID = global.Class_ID.Create(96, 0);
                object objMod = core.CreateInstance(SClass_ID.Osm, EDITABLESPLINE_CLASS_ID);
                IModifier mod = (IModifier)objMod;
                IIDerivedObject dobj = global.CreateDerivedObject(obj);
                dobj.AddModifier(mod, null, 0); // top of stack
                node.ObjectRef = dobj;
                core.CollapseNode(node, false);


                ISplineShape ss = (ISplineShape)node.ObjectRef.ConvertToType(global.COREInterface.Time, global.SplineShapeClassID);


                return ss;
            }

            return null;

        }

mxs test code

classof $
x = getsplineshape $.inode.handle -- c# method
setSplineSelection $ #(1)
max modify mode
x.BeginOutlineMove currenttime.ticks;
x.outlinemove currenttime.ticks 10.0
x.EndOutlineMove currenttime.ticks true
redrawViews()
classof $

o6jTXfQ29W


#17
using Autodesk.Max;
namespace SRYShapeTools
{
    public class SRYSplineShape
    {
        static public ISplineShape GetSplineShape(uint handle)
        {

            IGlobal global = GlobalInterface.Instance;
            var node = global.COREInterface7.GetINodeByHandle(handle);
            IObject obj = node.EvalWorldState(global.COREInterface.Time, true).Obj;


            if (obj.CanConvertToType(global.SplineShapeClassID) > 0)
            {

                IInterface core = global.COREInterface;
                int t = core.Time;
                int modstyle = core.CommandPanelTaskMode;
                IClass_ID EDITABLESPLINE_CLASS_ID = global.Class_ID.Create(96, 0);
                object objMod = core.CreateInstance(SClass_ID.Osm, EDITABLESPLINE_CLASS_ID);
                IModifier mod = (IModifier)objMod;
                IIDerivedObject dobj = global.CreateDerivedObject(obj);
                dobj.AddModifier(mod, null, 0); // top of stack
                node.ObjectRef = dobj;
                core.CollapseNode(node, false);


                ISplineShape ss = (ISplineShape)node.ObjectRef.ConvertToType(global.COREInterface.Time, global.SplineShapeClassID);


                return ss;
            }

            return null;

        }
    }
}

mxs code

dotNet.loadAssembly @"c:\SRYShapeTools.dll"
SRYgroupClass = dotNetObject "SRYShapeTools.SRYSplineShape"
classof $
x = SRYgroupClass.GetSplineShape $.inode.handle -- c# method
setSplineSelection $ #(1)
max modify mode
x.BeginOutlineMove currenttime.ticks;
x.outlinemove currenttime.ticks 10.0
x.EndOutlineMove currenttime.ticks true
>RedrawViews()
classof $

Same code, different results, very strange


#18

x.BeginOutlineMove currenttime.ticks;
x.outlinemove currenttime.ticks 10.0
x.EndOutlineMove currenttime.ticks true

These three lines run, and it goes back to line.


#19

maybe it is something undo related? it is worth checking with undo off
try it with different max versions and different line objects to ensure that it isn’t a bug


#20

That’s exactly what you said, I add “with undo on” in mxs code.If I don’t have to undo the function, it’s not Complete function.Do you have any good suggestions?