XRef Object and Custom Attributes

XRef Object and Custom Attributes

lightcube
Advisor Advisor
1,354 Views
7 Replies
Message 1 of 8

XRef Object and Custom Attributes

lightcube
Advisor
Advisor

I've got a situation I cannot figure out easily. Maybe someone has some input.

 

I've got Files where specific objects need to be used as XRef Objects in other scenes. I need to be able to access custom attribute data applied to the original object in the original file. How do you access the original custom attribute data on an XREF Object?

 

I've tried using the methods in the MAXScript XREF docs like GetSrcItem(), GetNodes(), GetSourceObject() and the actualBaseObject property ... but they do not seem to have this.

 

Hopefully someone has some advice.

 



Shawn Olson

Developer of Wall Worm
3ds Max plugins and Scripts

3ds Max 4/Gmax - 3ds Max 2020
Mudbox 2009-2019

Windows 10 x64
i7 8700K
64GB RAM
Geforce 1080ti
0 Likes
Accepted solutions (1)
1,355 Views
7 Replies
Replies (7)
Message 2 of 8

kevinvandecar
Community Manager
Community Manager
Accepted solution

Hi Shawn,

 

Custom Attributes and Xrefs each have their own curiosities and depending on the place of access (C++ SDK vs. MAXScript) it can be different. In your post I did not see exactly whether you were trying this from C++ SDK or MAXScript (you mentioned MAXScript APIs towards end, so assume that is your ideal)... So, I tested a simple case using MAXScript and it seems to work. Here is what I tried:

 

1. In base scene file I created a box

2. Using the "Parameter Editor", I created two parameters, which will be stored as Custom Attributes. These were called Param1 and Param2, and I set the values on the box to some test values

3. Save the scene and create a new scene, then xref the box from the base scene as an XRefObject into new scene.

4. Select that XRefObject node

5. in MAXScript: run xref_item=$.GetSrcItem()

6. in MAXScript: run xref_item.Param1 and I find the value that was originally set in the base scene file. Param2 alsio tests correctly in this example

 

hope it helps,

kevin

 

 


Kevin Vandecar
Developer Technical Services
Autodesk Developer Network



0 Likes
Message 3 of 8

lightcube
Advisor
Advisor

Thanks for the feedback. I had been testin GetSrcItem() but somehow it wasn't working in the test scenes I was using. I tried from fresh scenarios just now and it's indeed working.

 

There is another piece of XRef Voodoo in http://forums.autodesk.com/t5/programming/re-xref-object-problems/td-p/5536063 I'm about to update and beg for some insight. I'm going to update that thread right now.



Shawn Olson

Developer of Wall Worm
3ds Max plugins and Scripts

3ds Max 4/Gmax - 3ds Max 2020
Mudbox 2009-2019

Windows 10 x64
i7 8700K
64GB RAM
Geforce 1080ti
0 Likes
Message 4 of 8

lightcube
Advisor
Advisor

Actually, this is not as resolved as I expected. I went back to my original situation and was reminded of the specifics of what led me to this dilemma.

 

While most of the custom attribute properties do seem to be accessible, there are some problems. Namely, the one property I actually needed in the process was a Material parameter. The CA (Custom Attribute) is storing a MultiMaterial for model skins. In this case, the attribute is named #wwmtSkinMaterial.

 

When I open the original scene, the Node with the CA has a MultiMaterial stored in the #wwmtSkinMaterial param. So if I select it and then hit $.wwmtSkinMaterial I get the material. But when the node is used as an XRef Object in another scene, the XREF always returns undefined for #wwmtSkinMaterial -- even though it can see the values of the other parameters.

 

This is what let me to believe initally that XRefObject.GetSrcItem() did not have access to the CA params... because the one parameter I needed and was trying to access is always undefined.

 

So the next question is how do you bring in an XRef Object via MAXScript and ensure that you also bring in all the parameters? Is there a specific command in the xrefs.addNewXRefObject() method to ensure this? I experimented with various values in the modifiers/manipulators.dupMtlNameActions and none seemed to make the material property of the CA accessible.

 

I can think of ways to accomplish by creating a new node in the scene that has that material stored on the object itself and XRef that node... but it would take rewriting many tools and changing who knows how many existing asset files... which is certainly not what I'd like. I'd like to figure out a solution with the tools at hand.



Shawn Olson

Developer of Wall Worm
3ds Max plugins and Scripts

3ds Max 4/Gmax - 3ds Max 2020
Mudbox 2009-2019

Windows 10 x64
i7 8700K
64GB RAM
Geforce 1080ti
0 Likes
Message 5 of 8

Anonymous
Not applicable

Hi,

 

sorry to bring up an old post, but I have a very similar problem. kevinvandecar asked whether the problem is in maxscript or in the C++ SDK. For me the problem is in the C++ SDK. I have no luck in accessing the custom attributes on an XRef'd object via the SDK.

I resolve the object using the IXRefItem::GetSrcItem call. That works fine, but no matter what I try, the GetCustAttribContainer() call always returns null. Is there any example which works for this scenario? I didn't manage to find any. Maxscript can do that, so obviously there must be some way. In worst case scenario, I would be able to embed a maxscript call into the C++ code, but I would like to avoid that.

0 Likes
Message 6 of 8

denisT.MaxDoctor
Advisor
Advisor

it's probably because you don't resolve the object right, and look for attributes a wrong object.

 

you have to get last object in the hierarchy if you descend from INode for example ...

 

the code might be:

Object* obj = node->GetObjectRef();

if (obj && obj->ClassID() == XREFOBJ_CLASS_ID) 
{
	IXRefItem* xi = NULL;
	RefTargetHandle ref = (RefTargetHandle)obj;
	while (ref && (xi = IXRefItem::GetInterface(*ref)))
	{
		ref = xi->GetSrcItem();
	}
}

in this case ref will get the right reference object.

 

after that all should be good.. if it will be not, i will show how to get attributes

 

PS. i forgot to say... of course we are talking about a cust attributes originally added to the baseobject

0 Likes
Message 7 of 8

Anonymous
Not applicable

Hi, thanks for your reply. I have tried to glue your code to mine like this:

BaseObject* obj = SavedObject->Node->GetObjectRef();

    if (obj && obj->ClassID() == XREFOBJ_CLASS_ID)
    {
        IXRefItem* xi = NULL;
        RefTargetHandle ref = (RefTargetHandle)obj;
        while (ref && (xi = IXRefItem::GetInterface(*ref)))
        {
            ref = xi->GetSrcItem();
            BaseObject *bobj = ((IDerivedObject*)ref);
            BaseObject *objRef = bobj;
            IDerivedObject *pDerObj = (IDerivedObject *)objRef;
            int scid = objRef->SuperClassID();
            int modifierCount(scid == GEN_DERIVOB_CLASS_ID ? pDerObj->NumModifiers() : 0);

            for (int m = -1; m < modifierCount; m++)
            {
                if (objRef->SuperClassID() == GEN_DERIVOB_CLASS_ID && (m > -1))
                {
                    bobj = pDerObj->GetModifier(m);
                }

                ICustAttribContainer* cc = bobj->GetCustAttribContainer();
                if (cc)
                {
                    // OK
                    int dbg = 0;
                }
            }

        }

It does iterate over all the modifiers the XRef has (I was able to do that even before I have posted this), but the cc is always null despite the fact that there are custom attributes present in both the base Editable Mesh and in a Bend modifier the object has.

0 Likes
Message 8 of 8

Anonymous
Not applicable

OK, nevermind. There must be something wrong with my scene, because when I recreate the testing scene from scratch with only one object, the cc does not return null. I will try to narrow it down to find out what causes it.

0 Likes