How to get loop animation progress in scripts (Spark AR) - spark-ar-studio

I need to get loop animation progress (and looped) information (if it will be in patch editor, it 's the outputs). But I can't find this information on documentation. How can I get needed information?

For "looped" you can use onAfterIteration event on the TimeDriver:
https://sparkar.facebook.com/ar-studio/learn/documentation/reference/classes/animationmodule.timedriver
For progress, unfortunately there isn't a progress available on the TimeDriver, but you can use a multiTrigger event listener on the animation signal. Depending on what exactly you are trying to achieve, there are a few different ways of doing it:
https://sparkar.facebook.com/ar-studio/learn/documentation/reference/classes/reactivemodule.scalarsignal
For example:
//setup your animation
const Animation = require('Animation');
let driver = Animation.timeDriver({durationMilliseconds:1000, loopCount:Infinity});
let sampler = Animation.samplers.linear(0,1);
let animation = Animation.animate(driver, sampler);
//add listener for "looped" to the driver
driver.onAfterIteration().subscribe(function(e){
//do stuff on here...
});
//add listener for progress to the animation signal
//this will trigger when the animation signal goes above .5
animation.multiTrigger(.5).subscribe(function(e){
//do stuff here...
})

Related

How to know that fitToView() has finished completely

I want to know that fitToView() finished completely.
Some program procedures do not work after fitToView() without setTimeout().
For example, the following code not work.
const dbid = [1141]
this.viewer.select(dbid)
this.viewer.fitToView(dbid, viewer.model)
zoom() //This will not work
//code from:
function zoom (){
var nav = viewer.navigation
var pos = nav.getPosition()
var target = nav.getTarget()
var viewdir = new THREE.Vector3()
viewdir.subVectors (pos, target).normalize()
// zooms out by 100 along the view direction
viewdir.multiplyScalar (1000)
pos.add(viewdir)
nav.setPosition(pos)
}
The following code work well.
this.viewer.fitToView(dbid, viewer.model)
setTimeout(function(){
zoom() //This will work fine
}, 2000)
However, I don't want to use the setTimeout as much as possible.
Is there a way to know that fitToView () is finished completely?
If you use version 3.2.1 of the viewer a new event Autodesk.Viewing.CAMERA_TRANSITION_COMPLETED, it will be fired while following transitions are finished:
Go Home transition
Focus / Fit to View transition
Restore State transition
Named Views transition
Any other camera transitions
// Hook the event
viewer.addEventListener(Autodesk.Viewing.CAMERA_TRANSITION_COMPLETED, function(){
console.log('camera is no longer moving');
});
// Trigger an action that will move the camera and fire the event
viewer.fitToView();
You can see more about the Viewer Version changes here.
https://developer.autodesk.com/en/docs/viewer/v2/overview/changelog/3.2.1/

How do I overwrite a delay in TweenMax?

I am working in actionscript 3 using a Greensock TweenMax timeline. I have a one page scroller with two buttons (back to the top, and stop/play button).
The scroller automatically plays onLoad with a delay of 4 seconds. When I press stop/play button, it doesn't stop the delay. I have to wait the full four seconds before it functions. Also the 4 second delay only happens when the scroller runs for the first time. How can I get the 4 second delay to happen everytime the scroller repeats? How can I get the stop/play button to override the delay and play? I have worked on this for two days, and tried various techniques (for loops, timers, delayed calls, etc.) with no success. If anyone has ideas I will greatly appreciate it.
1) Code that starts the timeline:
myTween = new TweenMax(content_mc, 60, {delay:4, y:22, ease: Power0.easeNone, onComplete: restartFromTop });
2) This function controls the stop/play button
private function toggler(e:MouseEvent = null):void
{
if (playState == true){
toggleBtn.gotoAndStop(2);
myTween.pause();
playState = false;
trace("MC is now paused and stopped");
}
else if(playState == false) {
myTween.resume();
toggleBtn.gotoAndStop(1);
playState = true;
trace("MC is resumed from pause");
}
}
3) This function controls the restarting of the scroller when it repeats.
private function restartFromTop():void
{
myTween.restart()
playState = true;
}
4) This function controls the back to the top button
private function backToTop(event:MouseEvent):void
{
myTween.reverse();
if (playState == true){
myTween.restart();
myTween.resume();//stop animation
//toggleBtn.gotoAndStop(2);//changes button to pause
toggleBtn.buttonMode = true;
trace("page is scrolling");
}
if (playState == false){
myTween.restart();
myTween.pause();//stop animation
trace("play button is paused");
trace(timer);
}
//Adds a hand cursor on the button and adds a click event to the button.
toggleBtn.buttonMode = true;
toggleBtn.addEventListener(MouseEvent.CLICK, toggler);
}
I could not reproduce the first issue you are facing, that is the issue of delay with pause and resume. I tried a simple tween with 4 seconds delay and was able to pause and resume the tween without any delay.
For the other issue with restart, the TweenMax restart function takes a couple of arguments, and the first one being includeDelay:Boolean which is set to false by default. Setting this property to true fixes the issue.
Excerpt from the docs :
includeDelay:Boolean (default = false) — Determines whether or not the
delay (if any) is honored when restarting. For example, if a tween has
a delay of 1 second, like new TweenLite(mc, 2, {x:100, delay:1}); and
then later restart() is called, it will begin immediately, but
restart(true) will cause the delay to be honored so that it won't
begin for another 1 second.
Full docs can be found here
So, the following code should fix your restarting problem:
myTween.restart(true);
For your first issue, I would recommend you create a minimal scenario to reproduce it, and if it does, please do post a comment on my answer here.
Hope this helps. Cheers.

verify when a clipAction animation finished playing in three.js

I’ve made an animated mesh in Blender containing two animations clips that I named intro and idle. I’ve export it with the Blender exporter in JSON. Everything works great. I can toggle which animation I want to play. My problem is that I want to play the first animation entirely and then switch to the second animation that I’ll set to loop.
Here is the parts of the code I use for the JSON and animation part :
var jsonLoader = new THREE.JSONLoader();
jsonLoader.load('models/feuille(19fevrier).json',
function (geometry, materials) {
mesh = new THREE.SkinnedMesh(geometry,
new THREE.MeshLambertMaterial({
skinning: true
}));
mixer = new THREE.AnimationMixer(mesh);
action.intro = mixer.clipAction(geometry.animations[ 0 ]);
action.idle = mixer.clipAction(geometry.animations[ 1 ]);
action.intro.setEffectiveWeight(1);
action.idle.setEffectiveWeight(1);
action.intro.enabled = true;
action.idle.enabled = true;
action.intro.setLoop(THREE.LoopOnce, 0);
scene.add(mesh);
scene.traverse(function(children){
objects.push(children);
});
action.intro.play();
});
What I was looking for is a function that tells me that the action is complete, somethings like onComplete event when a clipAction finished playing. I found this response on the three.js GitHub :
mesh.mixer.addEventListener('finished',function(e){
// some code
});
It seems to work but I don’t really understand the addEventListener in that context and neither what function(e) means.
There is the link of the code I found on GitHub
addEventListener is part of the standard JavaScript dispatchEvent/addEventListener concept for handling events. The three.js Animation subsystem dispatches an event whenever the animation is finished. From AnimationAction.js:
this._mixer.dispatchEvent( {
type: 'finished', action: this,
direction: deltaTime < 0 ? -1 : 1
} );
As you can see, the e event argument provides you with the complete AnimationAction object (e.action), as well as an integer representing the direction of the animation (e.direction).
Do not feel discouraged by the fact that this is undocumented behavior (three.js has grown a lot faster than Mr Doob could ever properly document). Make use of the available functionality, but do keep an eye open for possible changes in feature releases.

Resetting a countdown timer whenever the user interacts with the SPA

I have an ember Single Page Application. The application has an auto-logout feature: whenever the timer expires, it will automatically logout. I would like to reset the timer every time that the user interacts with the page:
whenever keyboard input is entered
whenever any component of the page is clicked, including for example dropdown-opening, which is not triggering any ember action
Is it possible to add any code to catch any mouse / keyboard event before it is sent to ember? After resetting the timer, the event should be passed to ember or the CSS pipeline for further processing.
I would like to consider a special case: whenever the user clicks in a non-active area (background, for example), I am not sure of whether it is better to reset the timer or not, so I would like to be able to catch that, in order to decide later what to do. I am not sure how to define non-active area: from the point of view of the user, is clicking anywhere where no CSS effects or any other kind of effect is triggered.
Here's what we're using, I most definitely stole it from someone else and worked it into Ember, but I'm not going to find out where. It really just tells you if they've interacted with the page in any way, not necessarily if any component etc has been clicked.
App.idleTime = 0;
$(document).ready(function () {
//Increment the idle time counter every minute.
var idleInterval = setInterval(function() {
App.idleTime = App.idleTime + 1;
}, 60000); // 1 minute
//Zero the idle timer on mouse movement.
$(this).mousemove(function (e) {
App.idleTime = 0;
});
$(this).keypress(function (e) {
App.idleTime = 0;
});
});
And then I have a schedule task in my application route that watches the idle time and goes haywire with it when appropriate. The code below is made up, but should give you an idea.
App.ApplicationRoute = Em.Route.extend({
idleMax: 10,
setupBatman: function(){
this.watchJoker();
}.on('init'),
watchJoker: function(){
Ember.run.later(this, this.watchJoker, 1000);
if (App.idleTime >= this.get('idleMax')) {
console.log("You are looking idle, I'm gonna kick you.");
// kick
}
}
});
Update: I felt guilt, it came from here: Detecting idle time in JavaScript elegantly

Fake mouseclick on hover AS3

This morning I stumbled to this question:
When hovering a button, is it possible to click it automatically after X seconds? So the user doesn't need to click it with his mouse?
How can I let Flash believe my mouse really clicked some button on the stage or brought up with as3?
I have a lot of buttons in my movie. So I prefer to use some code which will cover this function for all existing or coming up buttons in my movie.
I would normally use a code like this but is there some workaround to accomplish this in a different way? I do no want to add code to every button.
this.addEventListener(MouseEvent.OVER, onMouseClickEvent);
public function onMouseClickEvent(event:Event)
{
trace(event);
if(event.buttonDown) // if button goes down normally
trace("MOUSE CLICKED NORMALLY");
else
trace("left button was not down");
}
The easiest way i think, is to subclass Button.
Then you should add mouse over/out listeners, add click listener that looks like that
:public function clickListener(event:MouseEvent = null){...}
When the mouse is hovering, raise a flag that the mouse is on the object, start a timer and when the timer callback function is called, you check the if the flag (you turn the flag down, when the mouse is out) is true and just call clickListener()
Listen for MouseEvent.MOUSE_OVER and start a timer, at the end of which the button will send the MouseEvent.CLICK event. In the mouseover handler, use the SystemManager to add a listener for MouseEvent.MOUSE_OUT which cancels the timer. The timer removes the listener using the SystemManager as well. So does clicking the button.
Finally! Solved!
This did the trick:
public function runOnce(event:TimerEvent):void {
btnSignal.dispatch("KEYBOARD", btnCode);
}
Robusto & Radoslav Georgiev: Thank you for pointing the right direction!
(I'm answering this a little late but would like to give input for future people).
One way to 'skin this cat' is to simply let your hover event trigger a timer (i.e. 3 seconds). In an EnterFrame or other function let a number or Boolean change when 3 seconds is reached.
//Pseudo code
if(timer == 3)
{ numberVar = 1;
//or
BooleanVar = True;
}
else
{
numberVar = 0;
//or
BooleanVar = false;
}
//end
Then just as you connected your methods to a mouseEvent, connect those same methods to fire when numberVar == 1 or BooleanVar == True. That's it.
For super simplicity and readability let your MouseClickEvent just be numberVar = 1 or BooleanVar = True.
These become super simple to implement over time and in my experience are 'very' error proof. Easy to fix also in the case of a typo or something else. No super elusive imports either. Hope that helped.
Great question by the way (+ 1)
:D