why’s that? it is located in <maxroot>/bin/assemblies folder for ages
An old question
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 .
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
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 .
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)
)
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);
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);
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 $

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
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.
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
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?
It looks like you need two separate undo records, one for the conversion operation, second for the operation on spline like outline or similar
I found a new way, but it’s not stable.Don’t know what went wrong.Whether a Notify Dependents is required
//obj is Line
int t = g.COREInterface.Time;
ISplineShape ss = g.SplineShape.Create();
IShapeObject spl = (IShapeObject)obj;
IBezierShape bz = ss.Shape;
spl.MakeBezier(t, bz);
node.ReplaceReference(1, ss, true);
I think it is a bit overkill to make a bezier out of a linear shape, but if you don’t want to mess with the edit_spline modifier it might be better. In other cases simple conversion with ConvertToType should work just fine.
You previously asked about undo/redo implementation in c#. Did you manage to make it work for shapes conversion?
... https://forums.cgsociety.org/t/how-can-i-write-a-undo-redo-using-c/2069476/8
theHo.Begin();
theHo.Put(new SRYRest(handle, all3dLines));
// convert line to splineshape
theHo.Accept("SRYundo");
theHo.Suspend();
The Undo/Redo is not particularly urgent for me, The Line converted to Spline shape is special importance thing for me .If a line is with other Modifiers,I can’t convert it in this state.Because the modifiers will disappear when I use to Collapse Node,That’s what I don’t want to see.Isn’t there an easier way?Why is my new method a bit overkill?Can you go into more detail?I also feel its instability, do not know what the problem is.ths
in this case ReplaceReference is certainly a solution
Actually, I don’t know what edit spline mod does to the line object for it to become convertible to splineshape, perhaps my assumption about makebezier being an overkill (in terms of performance) is wrong.
It is hard to tell why is it instable in your case. Try to call notify dependents on splineshape and see if it makes any difference. Although I couldn’t find much examples across sdk files where this call was needed. It could be something else.
Afaik, you can set a breakpoint where needed, compile c# dll, put in bin/assemblies, start max, attach to the process and then you’ll be able to debug your code. I did that only once, so can’t provide any help or advice here.
When it comes to low level programming for max it is preferable to switch to C++ cause it is way simpler to develop and debug.
I’m a raw recruit . I try again.