After Effects Script - Expression Controller Coordinates - javascript

Writing a script for After Effects 2015. Trying to copy coordinate data from a point expression controller to a layer's position data. I can't seem to find a way to point to the Expression Controller values.
for (i = 1; i <= app.project.activeItem.selectedLayers[0].property("Effects").numProperties; i++) {
app.project.items[2].layer(i).property("position").setValue(app.project.activeItem.selectedLayers[0].property("Effects").property(i).value);
}
I've also tried this:
for (i = 1; i <= app.project.activeItem.selectedLayers[0].property("Effects").numProperties; i++) {
app.project.items[2].layer(i).property("position").setValue(app.project.activeItem.selectedLayers[0].property("Effects").property(i).property("Point").value);
}
Any help would be appreciated. I'm hoping I didn't make any typos...

This should get you going. You need a layer with an expression point controler and it needs to be selected. I'm using here the match names of the effects. You can use the names from interface as well. I suggest getting the rd_GimmePropPath script from redefinery.com. Helps me every time.
function main() {
app.beginUndoGroup("XXX");
var curComp = app.project.activeItem; // get the current comp
if (!curComp || !(curComp instanceof CompItem)) {
// doulble check
alert("noComp");
return;
};
var layerwithpointcontroller = curComp.selectedLayers[0]; // the first selected layer
// get the value of the expression controler
var pointvalue = layerwithpointcontroller.property("ADBE Effect Parade")
.property("ADBE Point Control")
.property("ADBE Point Control-0001")
.value;
$.writeln(pointvalue); // take a look at it
var nullobject = curComp.layers.addNull();// add a null
nullobject.position.setValue(pointvalue);// set its position
app.endUndoGroup();
}
main();

Related

How can I get the particular point in a THREE.Points object to change his position?

I work on a personal project to try out equations to try to simulate the behavior of a galaxy. I have so far managed to place the Points as I wanted, but now I want to take each point individually to change its position.
The goal for now is just to successfully try to apply a Random Vector to each of the points.
I tried:
var direction = new THREE.Vector3(0.00003, 0.000005, 0);
points.position.add(direction);
but this applies to all Points.
Then I tried something like that:
for (let i = 0; i < points.geometry.attributes.position.count; i++) {
points.geometry.attributes.position[i] = Math.random() * 500
}
points.geometry.attributes.position.needsUpdate = true;
But nothing append :( I thing I missed something but I dind't know what
Here the full code on codepen:
Codepen
When you access:
points.geometry.attributes.position[i]
you're not getting the array of the vertex positions. You're getting the BufferAttribute. What you probably want is the array inside the BufferAttribute:
points.geometry.attributes.position.array[i]
However, this is still not the recommended approach. Three.js recommends you use the .getAttribute() method:
// Get the attribute
const posAttribute = points.geometry.getAttribute("position");
// Get the array inside the attribute
const posArray = posAttribute.array;
// Increment by 3 at a time to access XYZ separately
for(let i3 = 0; i3 < posArray.length; i3 += 3) {
posArray[i3 + 0] = xPosition;
posArray[i3 + 1] = yPosition;
posArray[i3 + 2] = zPosition;
}
// Tell the attribute it needs updatin
posAttribute.needsUpdate = true;

Dynamic variable declaration. Is this even the right method?

A little new to JS so be gentle :)
I'm trying to create a program that holds 5000+ boolean values that dynamically change based on other vars.
const chars = "abcdefghijklmnopqrstuvwxyz0";
const charsC = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0"
const maxNum = 48;
const maxTile = 6;
var tile1, tile2, tile3, tile4, tile5, tile6
// test vars
var tile4 = "A27"
var t4a27 = false
// this snippet will be in an interval loop
for (let i = 1; i <= maxTile; ++i) {
for (let n = 0; n < chars.length; ++n) {
for (let j = 1; j <= maxNum; ++j) {
// this obviously doesnt work
var t[i][`${chars[n]}`][j];
// ^ ^ ^
if (tile[i] == `${charsC[n]}${j}`) {
t[i][h][j] = true;
console.log(t4a27)
} else {
t[i][h][j] = false;
}
}
}
}
For clarification a better word than "tile" for the vars could be "sprite" rather because its a point on the sprite.
The basic concept is the tile vars are designed to output their current position as a string value e.g. "A27". Then this loop will take that information and scan each tile subset to be true/false. So if the sprite lower right quadrant is inside "A27" the output would be t4a27 = true
In practice I can do this with just a lot of code (over 20,000 lines) but I figured their has to be an easier way that requires far less code.
This is probably not the right approach for your problem.
If you really need to store this amount of variables, it is probably best to put them in an object like so:
var tiles = {}
var tileName = 'abc'
// Dynamic setting:
tile[tileName] = true
// Dynamic reading:
console.log(tile[tileName])
I am wondering if you really want to store 5000 variables or if there is another way to calculate them at the time you need time, but that requires a bit more knowledge of the problem.
Javascript doesn't have this kind of ability to reflect local variables.
What you can do is attach all those variables to a global object, and proceed with: Object.keys(your_object) and your_object[key_name_here] = ...
I think you should use a 2-dim array for this. Or use a regular array of booleans with the appropriate size and do the index-magic yourself.
As you said, you are running on coordinates. A-27 is the same as row(1)+field(27) -- considering A is 1
If your field is 500x100, you create an Array as such: let gamefield = Array(500*100);
Warning: I have not tested this for syntax errors, but you should get the idea.
let gamefield = Array(500*100);
// optional gamefield.fill(true);
let row = idx => idx * 500;
let posIdx = (r, c) => row(r) + c;
// there is a sprite with a tiles property that returns
// 4 index positions for the sprite's quadrants as [r,c]
let quadrants = sprite.tiles.reportPositions()
// filter the quadrants where the gamefield at r,c is true
// this might also be a good case for some() instead of filter()
let collisions = quadrants.filter(pos => return gamefield[posIdx(...pos)]);
// if there is any of these, you can kill the sprite.
if(collisions.length > 0) sprite.kill();

Javascript Invalid left-hand side in assignment

In an attempt to add queue type functionality to nodejs's Buffer class, I have constructed the following function:
Buffer.prototype.popleft = function(n) {
tRet = this.slice(0,n);
this = this.slice(n,this.length-1); // error here
return tRet;
};
however, this code yields the following error:
"ReferenceError: Invalid left-hand side in assignment"
I know that the issue is with the assignment of 'this' within the function, what I dont know is better way of accomplishing this same type of logic.
EDIT:
Ended up writing an object around the Buffer as shown below:
sPort.vBuffer = {}
sPort.vBuffer.buff = new Buffer(0);
sPort.vBuffer.off = 0;
sPort.vBuffer.expect = -1;
sPort.vBuffer.ReadChr = function() {
this.off ++;
return this.buff[this.off - 1];
};
sPort.vBuffer.ReadUInt32LE = function() {
this.off += 4;
return this.buff.readUInt32LE(this.off - 4);
}
sPort.vBuffer.ReadInt32LE = function() {
this.off += 4;
return this.buff.readInt32LE(this.off - 4);
}
sPort.vBuffer.Write = function(aData) {
this.buff = Buffer.concat([this.buff.slice(this.off),aData])
this.off = 0;
};
You can't assign to this. You can assign to a copy of it, but in your case it looks like that won't do any good.
According to the Node documentation, Buffer instances cannot be resized. Now, whether that's because Node simply provides no APIs to do that, or because of some set of internal implementation assumptions/dependencies, I don't know. There sure doesn't look like any way to alter the length of a Buffer instance.
You could use .copy to shift the contents, and then fill the last position(s) with some dummy value (null or undefined I guess).

String control in loops

I have a big question.
I have many Strings in my Programm and want to check these Strings on there values.
I wrote a Loop for it, but insted of the Definition of an String he is creating a new value. It's basicly really difficult to discribe, also because i am basicly German.
But i can give you my current code, so maybee you will see what I mean:
{
var Loch1G = $('#m1-Rundenanalyse-Datum').val(); //In the strings just the number is changing
var Loch2G = $('#m1-Rundenanalyse-Turnier').val();
x=1
while (x <= 2) {
if ("Loch" + x + "G" == ""){ //Next String is genrated (x=x+1)
alert("Eingabe war leer");
}
x=x+1
}
}
How can I solve this?
I'd suggest using an array to store the values you want to check:
var lochs = [];
lochs.push($('#m1-Rundenanalyse-Datum').val());
lochs.push($('#m1-Rundenanalyse-Turnier').val());
for (var i = 0, len = lochs.length; i < len; i++){
if (lochs[i] == ''){
alert("Eingabe war leer");
}
}
JS Fiddle demos: passes (no alert), fails (alert)
This suggestion is based on my presumption that you're trying to create the names of the vars you want to check, which won't work, whereas this approach lets you store all values (however many) in the same array and then iterate over that array to find any values that are equal to an empty string.
If you really want to stick with your current approach, you could do the following:
{
window.Loch1G = $('#m1-Rundenanalyse-Datum').val(); //In the strings just the number is changing
window.Loch2G = $('#m1-Rundenanalyse-Turnier').val();
var x=1;
while (x <= 2) {
if (window["Loch" + x + "G"] == ""){ //Next String is genrated (x=x+1)
alert("Eingabe war leer");
}
x=x+1;
}
}
But I can't think why you'd want to; plus the use of global variables is poor practice as it explicitly makes those variables available to every closure within the document, which allows them to be easily, and accidentally, overwritten.
In a reasonably up-to-date browser, that implements Array.prototype.every, you could dispense with the explicit iteration:
var lochs = [];
lochs.push($('#m1-Rundenanalyse-Datum').val());
lochs.push($('#m1-Rundenanalyse-Turnier').val());
if (!lochs.every(function(a){ return a !== ''; })) {
alert("Eingabe war leer");
}
JS Fiddle demos: passes (no alert), fails (alerts).

Trouble with Variable value in function

I have the following script where a variable gets its value from an input field, however when I run my function its not working, returns nothing. Im new to JS so im unsure if it needs to be part of a function *even though Ive tried this with no luck) or what...
/////////////////////////////////////////////////////////////////////
// Variables
// Content/SLA
var ContentMinutes = '';
var ContentMinutesSelector; // Switch Case
var ServiceLevel = 5;
var NoOfFrames = 2;
// Render Time (Hairier the Better)
var AvgFrameRenderTime = '';
var AvgFrameRenderTimeSelector = 10; // Switch Case
var CoresInTest = document.getElementById('CoresInTest').value;
// Other
var EstimatedCoreHours = NoOfFrames * CoresInTest * AvgFrameRenderTimeSelector;
// Cost Estimate
var CostEstimate = ServiceLevel * EstimatedCoreHours;
/////////////////////////////////////////////////////////////////////
// Functions
function CalculateEstimate() {
// Estimate Cost
parseInt(document.getElementById("PriceEstimate").innerHTML=CostEstimate.toFixed(2));
// Estimate Core Hours
parseInt(document.getElementById("EstimatedCoreHours").innerHTML=EstimatedCoreHours.toFixed( 2));
}
my PriceEstimate and EstimatedCoreHours fields are both just empty divs, <div id="EstimatedCoreHours"></div>, My calculations work if i define a value for the variable as opposed to document.getElementById so I believe I must need to run a function or something to update all the vartiables?
But if I set...
var CoresInTest = document.getElementById('CoresInTest').value;
to
var CoresInTest = 10;
Then it works fine...
Its not actually my return, the problem is my variables arent calling, IF i define them with a number then it works.
I guess you need to do something like this, if you are looking to get calculated data in your div.
document.getElementById("PriceEstimate").innerHTML=parseInt(CostEstimate.toFixed(2));
// Estimate Core Hours
document.getElementById("EstimatedCoreHours").innerHTML=parseInt(EstimatedCoreHours.toFixed(2));
If var CoresInTest = 10; works fine, then your code is placed wrong.
What element is CoresInTest? is it a text field? and if so is this script placed or called before the element renders? then you will have to reinitialize that variable.
If PriceEstimate and EstimatedCoreHours are elements you should use the value property
this might work for you:
document.getElementById("PriceEstimate").value=parseInt(CostEstimate.toFixed(2),10);
document.getElementById("EstimatedCoreHours").value=parseInt(EstimatedCoreHours.toFixed(2),10);
If var CoresInTest = 10; makes it work fine, then it must be something to do with document.getElementById('CoresInTest').value - so why isn't that working? Is it a drop down list? Instead of us guessing, tell us.

Categories