How to animate something at the same time in GASP? - animation

I want to animate these two things at the same time, and not one by one.
t1.fromTo(searchForm, { scaleX: 0 }, { duration: 1, autoAlpha: 1, scaleX: 1 });
t1.fromTo(loupe, {x: '-=0'}, {duration: 1, x: '+=265'})
I want to move them together; how can I do that?

Just use the position parameter to position your tween(s) wherever you want in the timeline.
t1.fromTo(searchForm, { scaleX: 0 }, { duration: 1, autoAlpha: 1, scaleX: 1 });
t1.fromTo(loupe, {x: '-=0'}, {duration: 1, x: '+=265'}, 0);
There's more info about the position parameter at https://greensock.com/position-parameter.
Also, there's no reason to use a .fromTo() in the second case because x: "-=0" does absolutely nothing, so you can just to a normal .to() tween and omit that whole object.
Happy tweening!

Related

Get coordinate with NaN at x axis

i got the following block of code to generate a new enemy each 1.5.
each new enemy is added to an array using scan operator
i did the replace suggested.
i did a small change to be able to replicate
const enemies$ = rxjs.from([0,1])
.pipe(
rxjs.scan( (enemyArray) => {
const enemy = {
x: Math.floor(Math.random() * 100),
y: -30
}
console.log(enemy)
enemyArray.push(enemy);
console.log(enemyArray); //debug.
return enemyArray;
}, [])
);
enemies$.subscribe(
(enemies) => console.log(enemies)
);
The result in the console is the following for the first element (enemy)
{x: 312, y: -30}
But when the enemy is added to enemyArray , the following results are shown in the console
(1)[{...}]
0: {x: NaN, y: 515}
1: {x: NaN, y: 65}
length: 2
[[Prototype]]: Array(0)
parseInt() takes a string as the first argument, so it should be
parseInt(String(Math.random() * 100), 10)

googlevr/vrview Read position form onGetPosition and set its value for next init

I'm wondering if it is possible (I hope it is) to set init camera rotation read from onGetPosition?
My onGetPosition function look like this:
function onGetPosition() {
console.log({
Yaw: worldRenderer.camera.rotation.y * 180 / Math.PI,
Pitch: worldRenderer.camera.rotation.x * 180 / Math.PI,
x: worldRenderer.camera.rotation.x,
y: worldRenderer.camera.rotation.y,
z: worldRenderer.camera.rotation.z
});
...
}
https://github.com/googlevr/vrview/blob/4e8e57eaddd8e69c8e032a6b5844d4e96af02156/src/embed/main.js#L357
I use this image as a texture:
Initial view, with default_yaw set to 0 degrees looks like this:
In this position onGetPosition returns:
{Yaw: 0, Pitch: -0, x: -0, y: 0, z: -0}
Then I rotate the scene to see this position (about 90 deg to the left):
onGetPosition returns:
{Yaw: 75.66036892219512, Pitch: -42.97581864568984, x: -0.7500695341072581, y: 1.3205225509658982, z: 0.7343037709331535}
I thought that if I set camera rotation inside setDefaultYaw_ function I would see last view so I did this:
WorldRenderer.prototype.setDefaultYaw_ = function(angleRad) {
...
this.camera.setRotationFromEuler(new THREE.Euler(-0.7500695341072581, 1.3205225509658982, 0.7343037709331535, 'XYZ'));
};
https://github.com/googlevr/vrview/blob/2dd890d147f702b9c561694bda5c86575c2a3d44/src/embed/world-renderer.js#L235
Unfortunately nothing happened I still see the view from second image on init.
How can I solve it?

Animate on bézier with ScrollMagic: Initial state = first bézier point

See a jsfiddle here
I am tweening along a bézier path with 3 points.
// bezier data
var bezierData = {
curviness: 1,
autoRotate: false,
values: [
{x: 0, y: 0, rotation:"40_cw"}, /* <-- The desired state of the object before any animation has happened */
{x: 20, y: 0, rotation:"0_ccw"},
{x: 40, y:0, rotation:"-20_ccw"}
]
};
// build tween
var tween = new TimelineMax()
.add(TweenMax.to("#testobj", 1, {css:{bezier: bezierData}, ease:Power1.easeInOut}));
// create scene
var scene = new ScrollMagic.Scene({
triggerElement: "#testobj",
duration: 100,
offset: 10
})
.setTween(tween)
.addTo(ctrl)
.addIndicators();
What I want: The initial state of my object (i.e. before any animation has happened) should be the first bézier point, {x: 0, y: 0, rotation:"40_cw"}.
What's happening: The initial state is the object's default style, i.e. the equivalent of {x: 0, y: 0, rotation:"0"}. Note how in the jsfiddle the green square starts out upright while I want it to start rotated 40° clock-wise.
Tahir Ahmed's answer works!
perhaps you can use .set() before doing the .to() tween? something like this.

find upper face of cube on demand

The general problem I'm trying to solve is to find out what face of a cube faces upwards. The cube can be rolled 90° at a time and in any direction. If a certain face faces up, the cube disappears. I'm working with tweens to rotate the cube and change the position of it.
I'm currently trying to solve this by creating a new ray, with its origin set just above the cube and its direction going downwards for a short distance, so it intersects with the upper face of the cube only.
violet thingy on top of die is ray cast downward into the cube
So far so good. I get my cube as the object of intersection when I check per console.log(), but as soon as I try to access the face of intersection by faceIntersect.face it seems to be undefined.
Function in question:
function checkUpperFace(posX, posZ) {
// get position from passed x- and z-values (y is always above cube)
// and set direction and length of ray
var position = new THREE.Vector3( posX, 3, posZ );
var direction = new THREE.Vector3(0, -1, 0);
var far = 2;
// create ray, that goes downwards from above the cube
var cubeRaycaster = new THREE.Raycaster( position, direction, 0, far );
// get intersection with upper face of rolled cube
var faceIntersect = cubeRaycaster.intersectObject( currentCube );
// add a helper to see the ray
var arrowHelper = new THREE.ArrowHelper( direction, position, far, 0x770077 );
scene.add( arrowHelper );
console.log(faceIntersect); // object is shown with everything I want to know
console.log(faceIntersect.face); // is shown to be undefined
}
In the end I did it in a way #unx recommended but I really wanted to avoid the huge if-else statement, so I did it with an array rotationLibrary that has all possible rotations with the corresponding top face of the die. But because of the tween I use to rotate and move the die its rotation values are not really on point and therefore hard to compare to fixed rotation values as I use them in the array.
So I "normalize" the rotation values of the die to values I can use to compare them to my values in rotationLibrary. The last step is to store/update the result on what face is on top in the cube object itself, so I can get it whenever I want.
// spawn condition:
// 1 on top, 2 facing camera, 3 facing right (seen from camera),
// 4 facing left (see 3), 5 facing away from camera, 6 facing down
var rotationLibrary = [
{x: 0, y: 0, z: 0, face: 1},
{x: 0, y: 90, z: 0, face: 1},
{x: 180, y: 0, z: 180, face: 1},
{x: 0, y: -90, z: 0, face: 1},
{x: -90, y: 0, z: 0, face: 2},
{x: -90, y: 0, z: 90, face: 2},
{x: -90, y: 0, z: 180, face: 2},
{x: -90, y: 0, z: -90, face: 2},
{x: 0, y: 0, z: 90, face: 3},
{x: 90, y: 90, z: 0, face: 3},
{x: -90, y: -90, z: 0, face: 3},
{x: -90, y: 90, z: 180, face: 3},
{x: 180, y: 0, z: -90, face: 3},
{x: 0, y: 0, z: -90, face: 4},
{x: 90, y: -90, z: 0, face: 4},
{x: -90, y: 90, z: 0, face: 4},
{x: 180, y: 0, z: 90, face: 4},
{x: 90, y: 0, z: 0, face: 5},
{x: 90, y: 0, z: -90, face: 5},
{x: 90, y: 0, z: 180, face: 5},
{x: 90, y: 0, z: 90, face: 5},
{x: 90, y: 90, z: 90, face: 5},
{x: 0, y: 0, z: 180, face: 6},
{x: 180, y: -90, z: 0, face: 6},
{x: 180, y: 90, z: 0, face: 6},
{x: 180, y: 0, z: 0, face: 6}
];
function checkRotationsToGetUpperFace(cube) {
// create object with "normalized" (brought to quarter-circle-degree-values) degrees
var normalizedRotation = {
x: 0,
y: 0,
z: 0
};
normalizedRotation.x = getNormalizedDegree(cube.rotation._x);
normalizedRotation.y = getNormalizedDegree(cube.rotation._y);
normalizedRotation.z = getNormalizedDegree(cube.rotation._z);
// go through the library that has all the degrees with the corresponding upper face
for (var i = 0; i < rotationLibrary.length; i++) {
// check if the objects match, then get the face
if (rotationLibrary[i].x == normalizedRotation.x &&
rotationLibrary[i].y == normalizedRotation.y &&
rotationLibrary[i].z == normalizedRotation.z) {
cube.face = rotationLibrary[i].face;
}
}
// reattach cube for correct movement later
THREE.SceneUtils.attach(cube, scene, pivot);
}
function getNormalizedDegree(rotationValue) {
// transform rotation value into degree value
var rotValue = rotationValue / (Math.PI / 180);
// default value is 0, so only check if it should be 90°, 180° or -90°
var normalizedDegree = 0;
// x between 45° and 135° ( ~ 90)
if (rotValue > 45 && rotValue < 135) {
normalizedDegree = 90;
}
// x between -45° and -135° ( ~ -90)
else if (rotValue < -45 && rotValue > -135) {
normalizedDegree = -90;
}
// x between 135° and 215° or x between -135° and -215° ( ~ 180)
else if ((rotValue > 135 && rotValue < 215) || (rotValue < -135 && rotValue > -215)) {
normalizedDegree = 180;
}
return normalizedDegree;
}
(http://jsfiddle.net/b2an3pq7/3/)
Might not be the solution to your raycast problem but another approach: Why don't you simply detect the upper face by comparing the rotation euler angles? E.g. (pseudo code):
if(cube.rotation.x % 360 == 0)
{
// upper face upwards
}
else if(cube.rotation.x % 360 == 90)
{
// left face upwards
}
You would have to deal with value tolerance (85° - 95°) negative rotation values and values out of the range of PI*2 but other than that, isn't that much easier?

Why can't I do an equality test of a synth parameter?

I'm mystified. In this code:
SynthDef(\acid,
{
|out, gate = 1, freq, myParam, amp, cutoff, resonance, filtEnvAmt|
var env, audio, filtEnv;
if (myParam == \something, { freq = 200; });
env = Linen.kr(gate, 0, 1, 0, doneAction: 2);
audio = LFSaw.ar(freq, mul: amp);
filtEnv = Line.kr(midicps(cutoff + filtEnvAmt), midicps(cutoff), 0.2);
audio = RLPFD.ar(audio, ffreq: filtEnv + MouseX.kr(0, 5000), res: MouseY.kr(0, 1), dist: 0);
Out.ar(out, audio * env);
}
).add;
b = Pbind(*[
out: 0,
instrument: \acid,
stepsPerOctave: 19,
scale: [0, 3, 5, 8, 11, 14, 17],
octave: 3,
degree: Pseq([0, \, 3, 3, 4, 4, 9, 4, 4]),
myParam: \something,
//prevFreq: Pseq([0, 0, 0, 0, 9, 0, 0, 0, 0]),
dur: Pseq([0.4, 0.4, 0.1, 0.1, 0.1, 0.1, 0.2, 0.1, 0.1]),
cutoff: Pseq([60, \, 50, 60, 80, 60, 90, 80, 50]),
filtEnvAmt: Pseq([20, \, 20, 20, 20, 20, -10, 20, 20]),
resonance: Pseq([0.5, \, 0.5, 0.5, 0.5, 0.5, 0.3, 0.5, 0.5])
]);
b.play;
..the equality test myParam == \something never returns true, despite the fact that the Pbind is clearly sending \something each time. No other value will work either: 0, nil etc.
The equality tests myParam == myParam and \something == \something do work however, so in these cases I get a monotone melody.
I can only guess that a Pbind sends each value in some kind of wrapper, but I've no idea how to then check them from inside the synth. Can anyone help?
First: you can't send symbols to a synth control. You can only send numbers.
Second: your example doesn't say what freq should be if the test is false. In fact, you should write it in more of a dataflow style such as:
freq = if(testcondition, 200, 300);
That's the kind of thing that will work in a synthdef.
Third is a slightly frustrating thing in sc language, which is that the == message is always evaluated at synthdef compile time - the equality is checked once, and then never again. In order to have "live" equality checking, you can use this slightly clunky expression:
BinaryOpUGen("==", thinga, thingb)
So in summary you might write
freq = if(BinaryOpUGen("==", myParam, 1), 200, 300);

Resources