Access to remote xref object transformations

Access to remote xref object transformations

andres.hernandezB63FL
Advocate Advocate
1,375 Views
14 Replies
Message 1 of 15

Access to remote xref object transformations

andres.hernandezB63FL
Advocate
Advocate

Hi, I'm trying to overpass some of the limitations of the Xref Object and I was wondering if it's possible to access to the remote (source) object transformations. I know you can access to the object name for example in case you want to update the name with the actual name from the source file. 
I need to do this because in some cases when we do changes to a rig in a source file we would expect to have those positions overwritten but in my case more like in an skin pose fashion, that you can go to that bind pose of the original rig. Actually there is no way to restore the PRS offset if the tracks are set as local, you can do that if they are xreferred but that way you can't animate the rig. If you move from local to xref tracks you can have the original transformation but in that case the local transformations (keys) get lost, so what I need is only the information to that original transformation. 
Hope someone can give me an idea how to sort this out. 
Thanks in advance. 

0 Likes
Accepted solutions (1)
1,376 Views
14 Replies
Replies (14)
Message 2 of 15

denisT.MaxDoctor
Advisor
Advisor

if your xref object selected:

 

$ -- the object
$.transform -- current transform in the scene
$.transform.controller -- current transform controller (Controller:XRef by default)

(refs.getreference $.transform.controller 1) -- source controller from xref file

(refs.getreference $.transform.controller 1).transform -- transformation in source scene

if the transform controller is XRef we can get the source controller as:

$.controller.GetSourceCtrl off

 

 

 

Message 3 of 15

denisT.MaxDoctor
Advisor
Advisor

Of course, this is only true if you are using an XRef controller (or keep XRef controller using list controllers)...
If you are using any other controller, then the original transform data does not exist in the scene. You can temporarily reload the xref object with its xref controller, read the data, and restore the current controller... but that operation will clear all undo history.

 

What you can do (and I did it in one of my projects):
* store the original transformation (and any other necessary data) in the object's AppData channel in the source file
* because XRef object always comes with all the AppData, it's accessible in the current scene.

Message 4 of 15

denisT.MaxDoctor
Advisor
Advisor

In my other project, I used a different approach...

I referred at the same time XRef Objects and their original (usually only one) file as XRef Scene. In this case, all the original data, including the transformation, was available to me in the working file and did not need to be reloaded.

Message 5 of 15

andres.hernandezB63FL
Advocate
Advocate

Hi Denis, thanks a lot for taking the time to answer and give me all those different approaches. Sorry for the late reply but I wasn't at the office. 

I tried the first option. If I read my object controller it is indeed an xref (the scene was loaded with tracks:local)
Both (refs.getreference $.transform.controller 1) and $.controller.GetSourceCtrl off give me the exact same values for PRS, however it doesn't seems to bringing me the transformations from the source file because if I move the object the values are chainging and I'm getting the exact same values if I just try $.pos or any other transformation.

I'm going to try the second option with the Appdata, actually I didn't know you could save that kind of data, this is very useful.

About the third option I think I don't understand the structure. So you bring an Xref Scene where you already put the xref object or something like that? But in that case you can't modify your objects right? Because I need to use the xref object specifically for having rigs for animation and that's why I need to be able to restore the PRS to those based on the PRS from the source file. 

Thanks again for your time and help Denis.

0 Likes
Message 6 of 15

andres.hernandezB63FL
Advocate
Advocate

Hi Denis, 
So, I tried the second option (saving the appData) and it didn't work either. So I found that if you update the xref it doesn't update the appData. The only way I could get the information from there was by deleting and loading again the xref 😕 

0 Likes
Message 7 of 15

denisT.MaxDoctor
Advisor
Advisor

let's clarify everything again:
* you have a source file A with object ObjA

* you have a working file B with XRef Object - ObjB, which is referred to ObjA in the file A

 

Now...

What transform controller do you want to have for object ObjB?

you have two options:

1. have a XRef controller

2. have a unique PRS controller

 

If you use the option 1 your controller and animation will be "relative" to the source controller in scene A. This means any changing ObjA's transform in file A will cause changing ObjB's transform in file B.

 

If you use the option 2 the ObjB's will not depend on ObjA's transform, but the source ObjA's transform will not be accessible in scene B.

 

So... what option do you prefer? What data you want to know working in scene B?

 

Another question:
Does ObjA in scene A have any transform animation (keys)?   

 

 

 

0 Likes
Message 8 of 15

andres.hernandezB63FL
Advocate
Advocate

Hi Denis, thank you for your answer. 
I'm using option 2 because the idea is the animator can access to the rig through the xref object, so the animation should be established in the file B. 
In file A I don't have any animation but what I'm trying to achieve is to access the rest pose from file A so I can load it in file B in case any changes were done in file A, that's in our case the purpose of using Xrefs. 
Thanks again

0 Likes
Message 9 of 15

denisT.MaxDoctor
Advisor
Advisor

Well... with option 2 we lose access to the original animation. 

How is about to save the Skin Pose in the source file? You can access it in the working scene.

0 Likes
Message 10 of 15

andres.hernandezB63FL
Advocate
Advocate

Asume skin pose doesn't work, happens the same with the others, you have to remove the record and load it again for it to properly load the updated data. It's incredible but there is no way to get updated data. 

0 Likes
Message 11 of 15

denisT.MaxDoctor
Advisor
Advisor
Accepted solution

@andres.hernandezB63FL wrote:

Asume skin pose doesn't work, happens the same with the others, you have to remove the record and load it again for it to properly load the updated data.


You are right... 

Let's try the AppData idea.

fn storeAppDataTM node ch:1212 = 
(
	setappdata node.baseobject ch (node.transform as string)
)	
fn restoreAppDataTM node ch:1212 = 
(
	node.transform = execute (getappdata node.baseobject ch)
)	
fn restoreXrefAppDataTM node ch:1212 = 
(
	node.transform = execute (getappdata node.actualBaseObject ch)
)

 

1. save a pose tm in the source file using  storeAppDataTM

2. we can restore tm in source file using restoreAppDataTM

3. restore tm in the working file using restoreXrefAppDataTM

...

4. change the pose tm in the source file and repeat steps 1..3

 

 

it works for me

 

Message 12 of 15

andres.hernandezB63FL
Advocate
Advocate

I just tested it and it works perfectly. I was missing the baseObject and actualbaseObject in my previous test, I didn't know that I have to save it there. 
So this is a very good solution, I have to create a code for it (like the asume skin pose as I said before), still I really hope AD fix the reference system because I noticed that sometimes if I change an object in the source file (for example replacing it by another) the xref file doesn't get updated properly. 
Thanks again for the time you dedicated to help me Denis, I really appreciate it. 

0 Likes
Message 13 of 15

denisT.MaxDoctor
Advisor
Advisor

here is another way that might be more suitable:

 

 

ReferenceTM_CA = attributes ReferenceTM_CA attribid:#(177711,171177)
(
	fn getNode = (refs.dependentnodes (custattributes.getowner this))[1]
	fn storeTM tm: = if isvalidnode (node = getNode()) do
	(
		if tm == unsupplied do tm = node.transform
		owner = custattributes.getowner this
		if not iskindof owner XRefOBject do
		(
			this.nodeTM = tm
			this.inParentTM = if isvalidnode node.parent then tm * (inverse node.parent.transform) else tm  
		)
	)
	fn restoreTM relative:off = if isvalidnode (node = getNode()) do
	(
		owner = custattributes.getowner this
		if relative and isvalidnode node.parent then
		(
			node.transform = this.inParentTM * node.parent.transform 
		)
		else 
		(
			node.transform = this.nodeTM
		)
	)
	parameters params 
	(
		nodeTM type:#matrix3 
		inParentTM type:#matrix3 
	)
	rollout params "Reference TM" autoLayoutOnResize:on
	(
		button store_bt "Store" width:72 align:#right offset:[-1,0] across:2 \
			tooltip:"Store Current Transform"
		button restore_bt "Restore" width:72 align:#left offset:[1,0] \
			tooltip:"Restore Absolute Transform\n +CTRL\t- Relative Transform"

		on store_bt pressed do undo "Store TM" on storeTM()
		on restore_bt pressed do undo "Restore TM" on restoreTM relative:keyboard.controlPressed
	)
)

custattributes.add $ ReferenceTM_CA baseobject:on

 

 

 

The CA will be available and will be automatically updated for XRef objects. It has both manual UI and the scripted interface. 

 

PS. the code was changed... (-- 12.10.22) 

Message 14 of 15

denisT.MaxDoctor
Advisor
Advisor

Both methods - CA and AppData - have both advantages and disadvantages.
Of the advantages of the AppData method, I would include its “confidentiality”, which means the better “foolproof”.
The CA method is more intuitive and visual. Also, usually when using an XRef rig, you still need to pass additional data from the reference file to the animation file (initial rigging and skin settings, export data, etc.).

I would probably use the CA method.

Message 15 of 15

andres.hernandezB63FL
Advocate
Advocate

Hi Denis, thank you for the complete solution. 
I've tested both methods and they seem to be working correctly, they are also getting updated when the file gets saved. 
The only problem I'm facing now is with objects that are using position or rotation constraint in the list controller because the transformations seems to occur in a coordsys relative to the object they are constrained to or something like that. If I get the transformations from the object, I move the object and reapply the transform it won't work even though the transformations are in world space. I know it's a different subject all this 🙂
Thanks again for taking the time to write the whole script Denis. 

0 Likes