Need Help modifying the Duik's Connector Code

Rigging, animation, import/export of characters, props and cameras comprehensive tool set for After Effects.
Forum rules
Please read these rules and advices before posting.
  • Before you ask any question about a tool, to avoid duplicates, please:
    1. Search for a solution in the available official user guide.
    2. Some video tutorials are available.
    3. Maybe you can find an answer in the frequently asked questions (FAQ).
    4. You can make a search to see if your question has already been asked.
    • Thank you for giving a detailed and precise title to your topics, to help searching in the future.
    • We're very few people to manage this forum, please be patient if we're a bit long to answer.
    • Don't hesitate to answer to other people's questions! The goal of this forum is not only to have the Rainbox team answer users' questions, but to have everyone sharing and helping each other.
    • Finally, please always be polite, and keep in mind that all we want is sharing techniques and knowledge, helping each other.
Post Reply
jetrotal
Posts: 3
Joined: Sun Apr 28, 2019 3:57 pm

Need Help modifying the Duik's Connector Code

Post by jetrotal » Sat May 04, 2019 7:02 pm

Image

It is Known that Duik's Connector cycles through every keyframe that is connected to a controller. It works like using Time Remap on a Property.

I Thought that would be useful if we had an "Absolute" animation mode. That interpolates only the values between the two nearest keyframes from a controller, ignoring all the other keyframes that the connected propriety has. The example above explains a little better what am i trying to do.

That said, i started tinkering the Connector's code and found a way to do this "Absolute" animation with it:

Here's what i wrote:

Code: Select all

//Duik.connector "absolute animation" mod
var ctrlLayer =thisComp.layer("C | Slider 2");

var ctrlValue = ctrlLayer.effect("Slider")(18);
var ctrlEffect = ctrlLayer.effect("Value Connector");
var useVelocity = ctrlEffect(1).value == 2;
if (useVelocity) ctrlValue = ctrlValue.velocity;
else ctrlValue = ctrlValue.value;

var tHasKeys = ctrlLayer.transform.xPosition.numKeys > 1;

function connect(keyF){



var ctrlMin = ctrlEffect(2).value; //0
var ctrlMax = ctrlEffect(3).value; //100
var result = value;
if (numKeys >= 2 && ctrlEffect.enabled)
{

var t = 0;
var beginTime = key(1).time;
var endTime = key(numKeys).time;
if (ctrlMin > ctrlMax)
{
t = linear(keyF, ctrlMin, ctrlMax, endTime, beginTime);
// t = linear(time, 0, 100, 0.5, 0.0); ????????
}
else
{
t = linear(keyF, ctrlMin, ctrlMax, beginTime, endTime);
}
result = valueAtTime(t);
}
var driver = Math.floor(result);

//
return driver;
}


sliderController = ctrlLayer.transform.xPosition;

poses = [];
temp = 1;

while ( temp <= thisComp.marker.numKeys ) {
	poses.push ( this.value );
	i = temp++ ;
}


function getValues(){
	
var obj_A = sliderController
var ID_A = obj_A.nearestKey(time).index;
var value_A;
var time_A;
var keyF_A;
var keyF_B;

if (obj_A.nearestKey(time).time <= time ){
 value_A = obj_A.key(ID_A).value;
 time_A = obj_A.key(ID_A).time;  
  
} else {

try{
  obj_A.key(ID_A-1).value;
  value_A = obj_A.key(ID_A-1).value;
  time_A = obj_A.key(ID_A-1).time;  
  
}catch(err){
  value_A = obj_A.key(ID_A).value;
  time_A = obj_A.key(ID_A).time;  
}


}




var obj_B = sliderController
var ID_B = obj_B.nearestKey(time).index;
var value_B;
var time_B;

if (obj_B.nearestKey(time).time >= time ){
 value_B = obj_B.key(ID_B).value;
 time_B = obj_B.key(ID_B).time;
} else {

try{
 obj_B.key(ID_B+1).value;
 value_B = obj_B.key(ID_B+1).value;
 time_B = obj_B.key(ID_B+1).time;
}catch(err){
value_B = obj_B.key(ID_B).value;
time_B = obj_B.key(ID_B).time;
}


}

keyF_A = connect(value_A);
keyF_B = connect(value_B);
return linear(time,time_A, time_B, keyF_A, keyF_B);
// time value can't read the easing from the slider keyframes, I must discover a way to mimic the ctrlEffect + UseVelocity shenanigans from the original code.
}

if(tHasKeys) getValues() else key(1).value;
I added an img attachment file, comparing both original code (left/red) and the code that i wrote (right/green).



The code kinda works as intended.
I only have three issues with it:

- I can't translate the connector's speed and easing from the connector to the to the connected properties.
Somehow the original code can do it, i believe it's because of how the linear that determines the current value was built

OG CODE:

Code: Select all

t = linear(ctrlValue, ctrlMin, ctrlMax, endTime, beginTime);
result = valueAtTime(t);
MODDED CODE:

Code: Select all

keyF_A = connect(value_A);
keyF_B = connect(value_B);
return linear(time,time_A, time_B, keyF_A, keyF_B);
The thing is that i couldn't think any other way to capture and interpolate the values from both nearest keyframes.


- It Can't work natively with shape layers.
The OG code can because it is written based on the valueAtTime() function.
To avoid cycling through every frame i had base myself on the .value property instead. This is not a big deal to me, since i can work with points follow nulls or something similar.


- The code has tons of ugly and unnecessaries sintaxes.
Well, i'm not a programmer. I can't read very cleary what i'm doing with my code.
I know some of the issues listed above could be solved if i wrote the code more likely to how the original was written, but I burned out all my knowledge about expressions trying to figure out the solutions i wrote.

I can't argue about the last two issues, the easing issue could already make the code 100% usable.
With it done, we could have a powerfull LipSync/Facial expressions Rig that can jump straight to desired poses on an animation.


Thanks in advance and sorry if i did not made clear what i'm trying to do. English is not my native language...
Attachments
DuikConnectorMod_codeDifferences.png
DuikConnectorMod_codeDifferences.png (427.23 KiB) Viewed 2191 times

jetrotal
Posts: 3
Joined: Sun Apr 28, 2019 3:57 pm

Re: Need Help modifying the Duik's Connector Code

Post by jetrotal » Tue May 14, 2019 7:04 pm

I did it! Thanks to Filip Vandueren, from CreativeCow.
https://github.com/jetrotal/Duik.Connec ... poseMOD.js


I had to add

Code: Select all

	ctrlNearK = ctrlFrames.nearestKey(time);

	try{
		ctrlPrevK = ctrlNearK.time&lt;time ? ctrlNearK : ctrlFrames.key(ctrlNearK.index-1);
	}catch(err){
		ctrlPrevK = ctrlNearK.time&lt;time ? ctrlNearK : ctrlFrames.key(ctrlNearK.index);
	
	}try{
		ctrlNextK = ctrlFrames.key(ctrlPrevK.index+1);
	}catch(err){
		ctrlNextK = ctrlFrames.key(ctrlPrevK.index)
	}

and change the last linear(); function to:

Code: Select all

keyF_A = connect(value_A);
keyF_B = connect(value_B);


	if (ctrlPrevK.value<ctrlNextK.value) {
		return linear(ctrlFrames.value, ctrlPrevK.value, ctrlNextK.value, keyF_A, keyF_B);
	} else {
		return linear(ctrlFrames.value, (ctrlNextK.value+0.1), ctrlPrevK.value, keyF_B, keyF_A);
	}

}

My code is a messy hell, with tons of try and catch, but at least it works.
If you guys have any advise to clean it up, would be welcome...

Post Reply