Community
3ds Max Programming
Welcome to Autodesk’s 3ds Max Forums. Share your knowledge, ask questions, and explore popular 3ds Max SDK, Maxscript and Python topics.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Accessing Custom Attributes on Rootnode in C#

2 REPLIES 2
Reply
Message 1 of 3
tpeterson.fsi
709 Views, 2 Replies

Accessing Custom Attributes on Rootnode in C#

Hi,

 

 I have some custom attributes applied to the root node in a 3ds max scene.  I am trying to set and get the values in those custom attributes.  I can set and get values on custom attributes on any other node, but the root node is giving me a lot of problems.  I have tried the following code:

 

IINode root_node = coreInterface.RootNode;
IObject r_obj = root_node.ObjectRef;
IICustAttribContainer r_cont = r_obj.CustAttribContainer;

This wil crash 3ds max 2014. The above code works fine if it is a normal scene node. I tried the following code and also got a crash
IICustAttribContainer r_cont = coreInterface.RootNode.CustAttribContainer;
ICustattrib my_attrib = coreInterface.RootNode.CustAttributeContainer.GetCustAttrib(0);

This also crashes 3ds max or prevents my C# app from loading. I am working around the issue by sending the commands I need via Maxscript in C#, but would prefer to do a native C# solution. Anyone know what I am doing wrong?

Thanks

Todd
 
2 REPLIES 2
Message 2 of 3

Hi, I think the problem is that the root node does not have a object reference assigned to it. If you check in the debugger, you will see that root_node.ObjectRef is always null. Also in your second attempt it is a similar problem. Here you are trying to get the CustAttribConjatiner from the root node (but not the object referenced by the node). In this case, the container is also probably null, so the request to get the first attribute will cause the crash.

 

The crash is occuring because you are technically trying to access a NULL pointer. In C++ this is not good and is why C++ code is usually full of checks for NULL. Because the managed .NET wrappers are simply wrapping the C++ code, the problem exists there too, and is why you also get the crash. A better formed managed API would prevent this... but it is, what it is. 🙂

 

So, to fix this in your code, first you should get into the habit of using the managed API like a C++ programmer and check for null. For example, you can prevent the crash around the referenced object by doing this:

 

           IObject obj = ip.RootNode.ObjectRef;
            if (obj == null)
                Debug.Print("There is no object referenced by this node."); // do something to prevent calling the null pointer

 

Next, note that the custom attribute container can exist on any animatible derived object. This can include the node or object referenced by the node. In your second example, you are approaching it this way.  But, the Custom Attribute Container is not always allocated either. Normally it is only allocated when there is attributes present. So again, you are assuming you have a container, and probably in your test the container does not exist and the property is returning null. A better way to handle it would be like this:

 

            IICustAttribContainer cont = ip.RootNode.CustAttribContainer;
            if (cont == null) // do something to prevent a call being made on a null object.
            {
                ip.RootNode.AllocCustAttribContainer(); // here we can allocate it...
                cont = ip.RootNode.CustAttribContainer;
                if (cont == null) // double check to make sure the allocation worked well...
                    return; // something is not good, so exit routine...
            }
            

            // now we can access the container safely...
            ICustAttrib att = cont.GetCustAttrib(0);

 

            // in this logic, this will always be null because we just allocated a new container. But here you could also go ahead and add one, too.
            if (att != null)
            {
                Debug.Print("Custom Attribute Name = " + att.Name);
            }
            else
                Debug.Print("No Custom Attributes found; Probably had a new container allocated. :-)");

 

 

Hope it helps.

Kevin

 

 

 


Kevin Vandecar
Developer Technical Services
Autodesk Developer Network



Message 3 of 3

Kevin,

 

 Thanks for the response.  I will keep in mind the null pointer issue.  I have been adding more of that in my code, just not enough.   But on the custom attribute issue on the root node I am still seeing issues.  I already have the custom attributes assigned to the root node when I am running this portion of my code.  I have verified that they are there both in TrackView and in Maxscript.  There is only one set of custom attributes on the rootnode and I still cannot read or set the values via C#.  Based on what you mentioned earlier, it appears I was correct in accessing the custattrib container for this via corefinterface.RootNode.CustAttribContainer, however this is returning null to me even though the custom attributes are present.

 

I use the following code to add the custom attributes earlier in my code:

 

ManagedServices.MaxscriptSDK.ExecuteMaxscriptCommand("custattributes.add rootscene mycustomattributesCA");  

 

I replaced the name of my custom attributes in the above example, but for now that is how I am adding the attributes.

 

When I try to read them I use the following code:

 

IICustAttribContainer r_cont = coreInterface.RootNode.CustAttribContainer;

 

This returns null to me.  So I guess I am not understanding why the CustAttribContainer is null in this situation.  If I do an AllocCustAttribContainer here it replaces my custom attributes (as I would expect)

 

Any suggestions?

 

Thanks

 

Todd

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report