Skip to main content
10-Marble
December 13, 2021
Question

Load different Sequence via JS on HoloLens 2.

  • December 13, 2021
  • 2 replies
  • 3224 views

Hi all,
I have a question about Vuforia in interaction with HoloLens 2.
In my scenario, I need to switch between different sequences (that I created with Creo).
This should be done by clicking on a button. I know the underlying command via JavaScript and have already used it successfully several times - but so far only for iPad (2D) Experiences.

For this I always use:

 

$scope.view.wdg['model-1']['sequence'] = 'l-Creo%203D%20-%20sequence.pvi';

 

In the preview everything works as it should.


Now when I test my scenario on the HoloLens, it seems to me that the HoloLens does not know this command. It loads the "default sequence" of the 3D model. Generally, I can't jump between sequences....

Do you know what I am doing wrong? To me it looks like there is a bug in the HoloLens interpreter. Is there another command that makes jumping between sequences work on the HoloLens?


I am grateful for any help!

Many greetings
Jonas

2 replies

21-Topaz I
December 13, 2021

Hello @JH_9310184 ,

I see that use encoded characters in the path but this is not necessary. So to translate /encode decode you can use e.g. this web side to check if you input is correct https://meyerweb.com/eric/tools/dencoder/

  The question is where is the sequence, pvz model - is it in the project upload folder? I used some javaScript code which should also work on the HL device. Sample code of function:

 

 

 

//////////////
//definition of the function
$scope.app.playModelStep = function (sequence,modelName,step_number,play) {
//sequnece -sequnece name e.g. TestFigure1 - as shown in UI
//modelName - model name e.g. model-1
//step_number - set this number to current step
//play true/false execute play for the model

 
$scope.$applyAsync(()=>{$scope.setWidgetProp(modelName, 'sequence', '');});


 $timeout(function () {
 $scope.$applyAsync(()=>{$scope.setWidgetProp(modelName, 'sequence', 'app/resources/Uploaded/l-Creo 3D - '+sequence +'.pvi');}); 
 
 },50);

 $timeout(function () {
 
 $scope.$applyAsync(()=>{$scope.setWidgetProp(modelName, 'currentStep', parseInt(step_number));});
 
 if(play) //check if play should be applyed
 
 $timeout(function () {angular.element(document.getElementById(modelName)).scope().play(); }, 100);
 }, 500);

};
//////////////////////////////////
//==========
...
...
// later call example
$scope.app.playModelStep("Figure 1","model-1",3,true)

 

 

The example code will set sequence for specific modelWidget and will set the current step to a number and if play is true will paly the step. You can use  as define or omit some parts if do not require it (e.g. the setting of the step and playl)

 Please , let me know if this code is working for you on HL 2. Thanks

 

10-Marble
December 13, 2021

Hello Roland, 
thank you for your advice. It works on my laptop, but the HoloLens doesn't manage to open the correct Sequence even through this. Unfortunately, this also leaves me in the default sequence (-- Choose a resource --) 

 

Is there another command to change the sequence via JS?

 

Best regards 

Jonas 

 

21-Topaz I
December 13, 2021

Hi Jonas, thanks for the feedback.

let me check on the HoloLens 2 device.

I need the following info:

- is the pvi file inside the pvz file or is extracted-means - (e.g. pvz is renamed then unzip and open or extract it to folder)  Could you check project folder where is pvz file , name of pvz file and name of the pvi file and if it is extracted . e.g. to upload folder

So I will test this scenario on HL2 to see if currently is there an issue.

Thanks

16-Pearl
December 17, 2021

This post may have been answered -

 

Just some additional input - Timeouts work but they are really indeterminant, listening for the sequenceloaded event is a better approach. 

 

$scope.play_part_sequence = function(modelName,figName){

     animation_sequence = true;
     $scope.view.wdg[modelName]["sequence"] = figName;

$scope.$on('sequenceloaded', function(evt, model, type, sequence) {

   // do something 

   twx.app.fn.triggerWidgetService(model, 'playAll');
  
}); // end of event

21-Topaz I
December 20, 2021

Hi @sgreywilson ,

thanks for the feedback. Yes , I agree that with the suggested code (calling the play service form the sequenceloaded event)  we will ensure that the sequence is  complete loaded when we try to play a step (or all steps) . In some cases when the sequence is very long the small timeout could possibly will not work. So means that the sequence is not initialized yet when we try to play. Because this calls are asynchronous – in this case the play will be ignored. Therefore we can “outsource” the call of play outside the function and set some variable which will be check in the sequenceloaded  callback -  in this case my original code should be changed to some code like this:

 

 

 $scope.playSeq4Step=false
 $scope.playStepNumber=1
//////////////
//definition of the function
$scope.app.playModelStep = function (sequence,modelName,step_number,play) {
//sequnece -sequnece name e.g. TestFigure1 - as shown in UI
//modelName - model name e.g. model-1
//step_number - set this number to current step
//play true/false execute play for the model

 
$scope.$applyAsync(()=>{$scope.setWidgetProp(modelName, 'sequence', '');});


 $timeout(function () {
 $scope.$applyAsync(()=>{$scope.setWidgetProp(modelName, 'sequence', 'app/resources/Uploaded/l-Creo 3D - '+sequence +'.pvi');}); 
 
 },50);

 
 // this will be commeted , because it will be outsources in the 'sequenceloaded'
 //$timeout(function () {angular.element(document.getElementById(modelName)).scope().play(); }, 100);
 //use here the setting of variable
 $scope.playStepNumber=step_number // the current step
 $scope.playSeq4Step=play //set variable for playing in the sequenceload event
 

};
//////////////////////////////////
$scope.$on('sequenceloaded', function(evt, model, type, sequence) {
$scope.$applyAsync(()=>{$scope.setWidgetProp(modelName, 'currentStep', parseInt($scope.playStepNumber));},50);

if( $scope.playSeq4Step) { // check if variable is set to play
 //call the play with some delay to be sure that stepNumber is set
 $timeout(function () {twx.app.fn.triggerWidgetService(model, 'play');}, 200);
 $scope.playSeq4Step=false
 }
 
}); // end of event
//==========
...
...
// later call example
$scope.app.playModelStep("Figure 1","model-1",3,true)




 

 

 

I think one problem we could have with this approach . If we have many modelwidgets and different functions which will try to set a sequences and then play a step in this case  we need to check for which  modelwidget (check event callback argument) is the sequenceload event called and who (which funciton) was the caller (this could be based on passing variable settings)

Here an example for the sequenceload event where we check the arguments:

$scope.$on("sequenceloaded", function (evt, arg) {
 console.log("sequence loaded, starting play");
 console.warn("arg:");
 console.warn(arg); //this should be a model-1 means a model widget
 //where the sequence was loaded
 let metaDATA=PTC.Metadata.fromId(arg.toString())
 // ========= starting here handling of meta data for arg modelwidget
 metaDATA.then(function(meta) { console.log("success func of metaData"); 
 }) .catch(function(err) 
 {console.log("problem with the read of metadata ");console.warn(err);}); 
 //========= 
});