Skip to main content
12-Amethyst
November 29, 2023
Question

Dynamic elements in Hololens experiences

  • November 29, 2023
  • 1 reply
  • 2483 views

Hello community, is there a way to emulate the 2D repeater in the 3D Canvas ?

I mean, I have a dynamic list coming from a TW service and I would like to add a dynamic number of 3D elements (could be 3D buttons, etc.) based on the number of rows from the output of the TW service.

 

Is it possible?

 

Thanks

1 reply

21-Topaz I
November 29, 2023

Hi @aletenti ,

so far I know there is no direct way to do this - via standard widget on HoloLens 2 or general in 3D space. Possibly there are some development  customized extension but I do not know such extension. Possibly somebody else could share here if he/she has information about other techniques.

For me -there should be 2 possible ways to try to implement it - what I consider there is only   the display of the data. Ok the data should be received by e.g. Thingworx service first and then need to be displayed . And I consider here only the display of e.g. Table but there we need to call the service and in the service -complete event we need then to call the function to display the data on e.g. 3D panel - so to update the data. Then possibly we need a timer or event setting e.g. call every 5 minutes to update the data this is also a think what we need to implement if we want to have an repeater functionality there in the 3D area. So the options I see are:

1.) use tmlText widget to define a shader and then  to display the data as shader on image panel. The data need to be passed to the shader as shaders parameter something like this  https://stackoverflow.com/questions/8847899/how-to-draw-text-using-only-opengl-methods for GLSL  ... But ! ... we need for HoloLens2 to use HLSL and I could not find a relevant example ... I did not search very detailed because I think the point 2 is that I prefer as option

2.) use the data to generate a dynamic table in SVG format and display it on e.g. Image widget. E.g. the following table from stack overflow... forum I used as example : https://stackoverflow.com/questions/6987005/create-a-table-in-svg

 

$scope.sampleSVG1 = function(text) { console.log("$scope.sampleSVG1")
 // Name of image widget to edit
 let sampleImgWidget = '3DImage-2'; 

 let svgData = `<?xml version='1.0' standalone='no'?>
<!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN'
 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'>
<svg width='80%' height='80%' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'>

 <title>SVG Table</title>

 <g id='columnGroup'>
 <rect x='65' y='10' width='75' height='110' fill='gainsboro'/>
 <rect x='265' y='10' width='75' height='110' fill='gainsboro'/>

 <text x='30' y='30' font-size='18px' font-weight='bold' fill='crimson'>
 <tspan x='30' dy='1.5em'>Q1</tspan>
 <tspan x='30' dy='1em'>Q2</tspan>
 <tspan x='30' dy='1em'>Q3</tspan>
 <tspan x='30' dy='1em'>Q4</tspan>
 </text>

 <text x='100' y='30' font-size='18px' text-anchor='middle'>
 <tspan x='100' font-weight='bold' fill='crimson'>Sales</tspan>
 <tspan x='100' dy='1.5em'>$ 223</tspan>
 <tspan x='100' dy='1em'>$ 183</tspan>
 <tspan x='100' dy='1em'>$ 277</tspan>
 <tspan x='100' dy='1em'>$ 402</tspan>
 </text>

 <text x='200' y='30' font-size='18px' text-anchor='middle'>
 <tspan x='200' font-weight='bold' fill='crimson'>Expenses</tspan>
 <tspan x='200' dy='1.5em'>$ 195</tspan>
 <tspan x='200' dy='1em'>$ 70</tspan>
 <tspan x='200' dy='1em'>$ 88</tspan>
 <tspan x='200' dy='1em'>$ 133</tspan>
 </text>

 <text x='300' y='30' font-size='18px' text-anchor='middle'>
 <tspan x='300' font-weight='bold' fill='crimson'>Net</tspan>
 <tspan x='300' dy='1.5em'>$ 28</tspan>
 <tspan x='300' dy='1em'>$ 113</tspan>
 <tspan x='300' dy='1em'>$ 189</tspan>
 <tspan x='300' dy='1em'>$ 269</tspan>
 </text>
 </g>
</svg>`;
 

 let svgURL = "data&colon;image/svg+xml;base64," + btoa(svgData);
 
 $scope.setWidgetProp(sampleImgWidget,'src',svgURL)
}

 

Here I consider it as static table but you can of course generate it dynamical using the data sets. So the mentioned code example in preview:

2023-11-29_15-41-49.jpg

I attached the test project , possibly could be helpful for you. Thanks

 

aletenti12-AmethystAuthor
12-Amethyst
November 30, 2023

Hi Roland,

thank you very much for your example and explanation, it's useful.

Anyway, I was thinking about more on dynamic 3D buttons.

I mean, I have a 3D image as a panel and I would like to fill this panel with a dynamic number of 3D buttons.

 

Do you have any idea? 🙂 

21-Topaz I
November 30, 2023

Hi @aletenti ,

unfortunately I did not have idea how to do this with  the image widget (SVG) - because , I do not know how to interpret the click with the 3D coordinates on the 3DImage. So if somebody know how to do this, so in this case this could work and we can check  in which ratio the click was on the 3DWidget - in this case we can interpret the click and find out which row/column was indented  to be selected by the click. I believe that this should be possible but have no idea how to do this.

What I did in similar case - I did have a panel with specific number of widgets as rows and columns which I used to display a list of sequences (12 where I have a list of 5 rows) and tried to use some fake  "scroll" where I change already existing element depending what they should display. So possibly this approach could be a solution but it requires  more intensive program coding:

2023-11-30_16-17-57.jpg

I attached a test project. there is watch construct which is looking for  app parameter "CurrentStep" and when there is an change it will change the display of the list accordingly. It check the step number and will calculate dynamically the widget display

$scope.$watch('app.params.CurrentStep', (step)=>{
 let tS=step
 let numberOfSteps=$scope.app.NumbersOfSteps
 if(step <=2) return;
 
 else if(step >= numberOfSteps-1) return;
 
 else{
 $scope.app.prevStep2=tS-2
 $scope.app.prevStep=tS-1
 $scope.app.nextStep=tS+1
 $scope.app.nextStep2=tS+2
 }
 
 console.warn("changed::")
 console.log("$scope.app.params.CurrentStep="+$scope.app.params.CurrentStep)
console.log("$scope.app.prevStep="+$scope.app.prevStep)
console.log("$scope.app.nextStep="+$scope.app.nextStep)
console.log(" $scope.app.NumbersOfSteps="+ $scope.app.NumbersOfSteps)
 $scope.app.updateProps($scope.app.prevStep,$scope.app.params.CurrentStep,$scope.app.nextStep, $scope.myFile)

})

In your case you can watch for another parameter where for example a TWX service will write there  a json list 

When there is a change you need to set the widgets names - and also the action what the widget will do according to the list content. Such solution could be implemented  , no problem, but  I think  it will require significant more programming