Convert any shape to Editable Spline

Convert any shape to Editable Spline

Anonymous
Not applicable
2,755 Views
16 Replies
Message 1 of 17

Convert any shape to Editable Spline

Anonymous
Not applicable

Hello,

 

I'm trying to convert a Shape object (Line for example) to an Editable Spline in C#.

 

Here's my code : 

 

public int ConvertToEditSpline(IINode node)
{
    if (node.ObjectRef.SuperClassID != SClass_ID.Shape) 
        return -1;

    if (node.ObjectRef.ClassID.PartA == (uint)BuiltInClassIDA.SPLINESHAPE_CLASS_ID)
        return 0;

    IObjectState objstate = node.ObjectRef.Eval(MaxInterfaces.Ip.Time);
    IShapeObject obj = objstate.Obj as IShapeObject;
    
    Console.WriteLine(obj.CanConvertToType(MaxUtils.SplineShapeClassID).ToString());
    // Print "1", so it can convert the object.

    ISplineShape newSpline = obj.ConvertToType(MaxInterfaces.Ip.Time, MaxUtils.SplineShapeClassID) as ISplineShape;
    // newSpline is null...

    if (newSpline == null)
        return -1;

    node.ObjectRef = newSpline.CollapseObject;
    return 0;
}

As you can, everytime I try to convert a ShapeObject to SplineShape, it returns null.

 

How can I solve this ?

 

Thank you.

0 Likes
2,756 Views
16 Replies
Replies (16)
Message 2 of 17

Anonymous
Not applicable

No one ? @Swordslayer maybe ? 🙂

0 Likes
Message 3 of 17

Swordslayer
Advisor
Advisor

I'm not using C# in max actively, @danielgsantana might be a better choice. You might try something along the lines of

 

ISplineShape newSpline = global.SplineShape.Marshal(obj.NativePointer);

but judging by the unanswered I can't seem to get a cast working from IShapeObject to ISplineShape thread on cgtalk, it definitely doesn't look like an easy task.

0 Likes
Message 4 of 17

Anonymous
Not applicable

@Swordslayer I just tried it, the object seems to be non-null, i can access to Shape member, but the SplineCount is equal to 0 unfortunately.

 

Maybe my function is not correct : 

 

        public static ISplineShape GetSplineShapeFromINode(IINode node, int t, ref bool deleteIt)
        {
            deleteIt = false;
            IObject obj = node.ObjectRef.Eval(t).Obj;

            if (obj.SuperClassID == SClass_ID.Shape)
            {
                ISplineShape pSplineShape = MaxInterfaces.Global.SplineShape.Marshal(obj.ConvertToType(0, SplineShapeClassID).CollapseObject.NativePointer);
                if (obj != pSplineShape)
                    deleteIt = true;
                return pSplineShape;
            }
            return null;
        }

Could be nice also to get the SplineShape of an EditableSpline which uses Modifiers.

0 Likes
Message 5 of 17

danielgsantana
Contributor
Contributor

Michael, what version of 3dsmax are you using?

 

There a lot of dead ends in Autodesk.Max .NET depending on the version used. Some methods are pure virtual with no implementation, and others don't have the interface's implemented in .NET, making them useless.

 

Have you looked at the MaxPlusDotNet.dll, it's what is actively develop as a bridge to .NET, and serves for MCG backend and Python.

 

Cheers,

Daniel

Technical Director / Co-founder
You can do it! VFX - www.ycdivfx.com
Lisbon/ Porto - Portugal
0 Likes
Message 6 of 17

Anonymous
Not applicable

hi @danielgsantana, I am currently using Max 2016 SP4 (I need SP4 for some new features in the SDK).

 

I didn't use MaxPlusDotnet because I found it very limited, and since my plugin has something like 15k lines of codes, I don't want to change everything. Maybe I can bridge both assemblies using objects Handles but can't figure out for the moment...

 

 

0 Likes
Message 7 of 17

Alfred.DeFlaminis
Alumni
Alumni

Hello @Anonymous,


This is a bit above my ability to help with, but I'm going to move this thread to the Programming forum because I think there are a number of programmers that read that forum instead of general that may be able to help you.  My best recommendation here is that you post this on the ADN Forums to see if you can get programmer help with this issue.  I do realize that doesn't solve your problem but it's my best suggestion for this particular issue.  

 

Best Regards,

0 Likes
Message 8 of 17

denisT.MaxDoctor
Advisor
Advisor

@Alfred.DeFlaminis wrote:

I'm going to move this thread to the Programming forum because I think there are a number of programmers that read that forum instead of general that may be able to help you.  My best recommendation here is that you post this on the ADN Forums to see if you can get programmer help with this issue.  


does this link not work for me only?

0 Likes
Message 9 of 17

Swordslayer
Advisor
Advisor

@Anonymous wrote:

@Alfred.DeFlaminis wrote:

I'm going to move this thread to the Programming forum because I think there are a number of programmers that read that forum instead of general that may be able to help you.  My best recommendation here is that you post this on the ADN Forums to see if you can get programmer help with this issue.  


does this link not work for me only?


Well, I certainly can't get any further than either going back through the link to the Programming forum here, or membership choice (1400 €  or 2200 €). So you are not alone.

0 Likes
Message 10 of 17

denisT.MaxDoctor
Advisor
Advisor

i don't use c# for these things but a simplified c++ code might be as:

 

bool ConvertSplineShape(INode* node)
{
	ReferenceTarget* ref = node->GetObjectRef();
	if (ref && ((Object*)ref)->CanConvertToType(splineShapeClassID)) 
	{ 
		TimeValue t = GetCOREInterface()->GetTime();
		ObjectState os = node->EvalWorldState(t);
		Object* obj = (Object*)os.obj->ConvertToType(t, splineShapeClassID);

		node->SetObjectRef(obj);
		node->NotifyDependents(FOREVER,0,REFMSG_SUBANIM_STRUCTURE_CHANGED);
		node->NotifyDependents(FOREVER,PART_ALL,REFMSG_CHANGE);

		return true;
	}
	return false;
}

 

0 Likes
Message 11 of 17

Alfred.DeFlaminis
Alumni
Alumni

Hello @denisT.MaxDoctor and @Swordslayer,

 

That may be a mistake on my end if that link is broken.  It's weird because it works in Chrome for me but not IE.  I've updated it with a new link and my apologies for the problem there.

 

There is a free version of the ADN, so hopefully that can help @Swordslayer.   I don't see a Max specific API forum so the free version may not work for this issue, but the 3ds Max SDK Blog has a comments section where you may be able to get an answer if there is a related blog post.  I have links below:

 

ADN Base page

 

The 3ds Max SDK Blog 

 

Best Regards, 

0 Likes
Message 12 of 17

Swordslayer
Advisor
Advisor

@Alfred.DeFlaminis It's kind of confusing, when I click the first link or when I click the free ADN option from the second link, I always get this page which redirects back here when I click any of the forums (i.e. to subforums accessible directly from the main Autodesk forums page).

 

ADN.png

Message 13 of 17

danielgsantana
Contributor
Contributor
Here is a simple conversion of the Dennis code to C#, the notification
isn't right, since I need to go the headers in the SDK to see the right
values for the parts.

public bool ConvertSplineShape(INode node)
{
var objRef = node.ObjectRef;
if (objRef != null &&
objRef.CanConvertToType(GlobalInterface.Instance.SplineShapeClassID) != 0)
{
var t = GlobalInterface.Instance.COREInterface.Time;
var os = node.EvalWorldState(t, true);
var obj = os.Obj.ConvertToType(t,
GlobalInterface.Instance.SplineShapeClassID);
node.ObjectRef = obj;

node.NotifyDependents(GlobalInterface.Instance.Interval.Create(-1, -1),
(UIntPtr)0, RefMessage.SubanimStructureChanged, (SClass_ID)0xfffffff0,
true, null, NotifyDependentsOption.AllowOptimizations);

node.NotifyDependents(GlobalInterface.Instance.Interval.Create(-1, -1),
(UIntPtr)0, RefMessage.Change, (SClass_ID)0xfffffff0, true, null,
NotifyDependentsOption.AllowOptimizations);
return true;
}
return false;
}
Technical Director / Co-founder
You can do it! VFX - www.ycdivfx.com
Lisbon/ Porto - Portugal
Message 14 of 17

Swordslayer
Advisor
Advisor

You can use Autodesk.Max.MaxPlus.Constants, there is NotifyAll which works well when cast to SClass_ID. I've used it elsewhere but in the end had to find a non-C# way as the NotifyDependents call (or rather NotifyDependents_) worked in 2016 and errored in 2017 (might be just me not being good enough with C#, gave up at that point).

Message 15 of 17

Alfred.DeFlaminis
Alumni
Alumni

I see what you mean @Swordslayer.  I'm not much of a programmer so I haven't spent much time in there, but it does seem to be mostly blogs and a link to the programming forum.  I have the relevant blogs below, which I found by clicking Autodesk Platform Technologies on that page, then 3ds Max.  It does seem rather limited, so I may not suggest it in the future for such a specific topic.  

 

Blogs

 

Get news, expert tips and insider resources directly from Autodesk software engineers

3ds Max related blogs:

GetCoreInterface” (3ds Max SDK) – Kevin Vandecar

3D SDK and Scripting Mayhem” – Christopher Diggins blog that often refers to 3ds Max, but also considers many other technologies.

Max Station”: Learn Tips and tricks from the Autodesk product support team.

Louis Marcoux Tutorials”: A great series of tutorial style entries from a true expert, Louis Marcoux.

 

Best Regards,

0 Likes
Message 16 of 17

Alfred.DeFlaminis
Alumni
Alumni

Hello @Anonymous,

 

I'm a bit out of my depth in this thread but I wanted to check in to see if any of these suggestions helped with your issue.  If so, would you please mark any posts that helped with the solution, and thank you for doing so!

Best Regards,

0 Likes
Message 17 of 17

mmoraisdois
Participant
Participant

Works!!  

node.NotifyDependents(IntervalFOREVER, (UIntPtr)0, RefMessage.SubanimStructureChanged, (SClass_ID)Constants.NotifyAll, true, null,
     NotifyDependentsOption.AllowOptimizations);

 node.NotifyDependents(IntervalFOREVER, (UIntPtr)0, RefMessage.Change, (SClass_ID)Constants.NotifyAll, true, null,
     NotifyDependentsOption.AllowOptimizations);

 ip.RedrawViews(ip.Time, RedrawFlags.Normal, null);  // Redraw the views to reflect any changes made to the object  

Add   using Constants = Autodesk.Max.MaxPlus.Constants;    on top 
only works after adding the (SClass_ID)Constants.NotifyAll

Thanks to Swordslayer.

0 Likes