こんにちは、ナレコム前川です。
今回は、Amazon Sumerian の公式チュートリアルの
SumerianRunner Events を進めていきたいと思います。
ここで学ぶことは
・Event Listeners
・sumerianRunner Event Listeners
・Events
・Intersection marker
の4つです。
また、今回のイベントリスナーは通常の DOM イベントリスナーよりも重いようなので
必要最低限のアクションを起こすことがおすすめされています。
それでは、進めていきましょう。
1. シーンの作成
① ダッシュボードからDefault Lightingを選択。
① ダッシュボードからDefault Lightingを選択。
② シーン名を「SumerianRunner Events」に設定し、作成。
今回、私は Box を追加しました。
追加できたらシーンの設定は終わりです。
2. Entity に Event Listeners を追加する
ここからは、主に Script を編集する作業を行っていきたいと思います。
① Create Entity から Empty を追加。
① Create Entity から Empty を追加。
② 追加した Entity に Script Component を追加し、Custom を選択。
1var setup = function(args, ctx) {2 ctx.runnerListeners = {3 click: function(evt) {4 console.log('Click event', evt);5 }6 };78 for (var l in ctx.runnerListeners) {9 ctx.world.sumerianRunner.addEventListener(l, ctx.runnerListeners[l]);10 }11};1213// Remember to clean up after ourselves14var cleanup = function(args, ctx) {15 for (var l in ctx.runnerListeners) {16 ctx.world.sumerianRunner.removeEventListener(l, ctx.runnerListeners[l]);17 }18};シーンを公開し、Iframe のやり方と同様に動作確認を行っていきます。
シーン上でマウスをクリックするとコンソールにメッセージと座標などの情報が表示されます。
3. ちょっとした GUI の追加
ここからは、イベントの情報を表示する HTML Entity を作成していきます。
① Create Entity から HTML</> を追加。
② Move with Transform のチェックを外す。
1Screen coords: (?, ?)23 Entity: ?45 Point: ?67 Depth: ?置き換えると、シーンの左上に intersection-info 内で定義して文字が表示されると思います。
1var displayIntersectionInfo = function(screenCoords, entity, point, depth) {2 var coordsDiv = document.getElementById('intersection-screen');3 var entityDiv = document.getElementById('intersection-entity');4 var pointDiv = document.getElementById('intersection-point');5 var depthDiv = document.getElementById('intersection-depth');6 coordsDiv.innerHTML = '(' + screenCoords[0] + ', ' + screenCoords[1] + ')';7 entityDiv.innerHTML = entity;8 pointDiv.innerHTML = '(' + point[0].toFixed(2) + ', ' +9 point[1].toFixed(2) + ', ' + point[2].toFixed(2) + ')';10 depthDiv.innerHTML = depth.toFixed(2);11};
1ctx.runnerListeners = {2 click: function(evt) {3 console.log('Click event', evt);4 var name, point, depth;5 if (evt.entity && evt.intersection) {6 name = evt.entity.name;7 point = evt.intersection ? evt.intersection.toArray() : [0, 0, 0];8 depth = evt.depth;9 } else {10 name = 'None';11 depth = 0;12 point = [0, 0, 0];13 }14 displayIntersectionInfo([evt.x, evt.y], name, point, depth);15 }16};シーンを実行して、値がどのように変化するか確認してください。
以下のようになると思います。
4. Intersection Marker
ここからは、Sphere を使ってシンプルな Intersection Marker を追加していきたいと思います。
① Create Entity から Sphere を追加。
1var setup = function(args, ctx) {2 console.clear();34 ctx.markerMeshData = new sumerian.Sphere(16, 16, 0.14);5 ctx.markerMaterial = new sumerian.Material(sumerian.ShaderLib.uber);6 ctx.markerMaterial.uniforms.materialDiffuse = [1, 0, 0, 1];7 ctx.markerMaterial.uniforms.materialEmissive = [0.7, 0, 0, 1];8 ctx.markerMaterial.uniforms.materialSpecular = [0, 0, 0, 1];910//...④ 以下の関数を追加。
1var showMarker = function(ctx, pos) {2 if (!ctx.markerEntity) {3 ctx.markerEntity = ctx.world.createEntity(4 ctx.markerMeshData,5 ctx.markerMaterial,6 'Intersection Marker');7 }8 ctx.markerEntity.addToWorld();9 ctx.markerEntity.setTranslation(pos);10};1112var hideMarker = function(ctx) {13 if (ctx.markerEntity) ctx.markerEntity.removeFromWorld();14};⑤ 最後に setup 関数の runnerListeners を以下に変更。
1ctx.runnerListeners = {2 click: function(evt) {3 console.log('Click event', evt);4 var name, point, depth;5 if (evt.entity && evt.intersection) {6 showMarker(ctx, evt.intersection); // <----- here7 name = evt.entity.name;8 point = evt.intersection ? evt.intersection.toArray() : [0, 0, 0];9 depth = evt.depth;10 } else {11 hideMarker(ctx); // <----- and here12 name = 'None';13 depth = 0;14 point = [0, 0, 0];15 }16 displayIntersectionInfo([evt.x, evt.y], name, point, depth);17 }18};Script を保存して、シーンを実行してみてください。
以下のように動作するはずです。
5. 完成版Script
うまく動作しなかった場合には、以下のコードと置き換えるか見比べてみてください。
以下のコードは、完成したコードになっています。
1var setup = function(args, ctx) {2 console.clear();34 ctx.markerMeshData = new sumerian.Sphere(16, 16, 0.14);5 ctx.markerMaterial = new sumerian.Material(sumerian.ShaderLib.uber);6 ctx.markerMaterial.uniforms.materialDiffuse = [1, 0, 0, 1];7 ctx.markerMaterial.uniforms.materialEmissive = [0.7, 0, 0, 1];8 ctx.markerMaterial.uniforms.materialSpecular = [0, 0, 0, 1];910 ctx.runnerListeners = {11 click: function(evt) {12 console.log('Click event', evt);13 var name, point, depth;14 if (evt.entity && evt.intersection) {15 console.log(evt);16 showMarker(ctx, evt.intersection);17 name = evt.entity.name;18 point = evt.intersection ? evt.intersection.toArray() : [0, 0, 0];19 depth = evt.depth;20 } else {21 hideMarker(ctx);22 name = 'None';23 depth = 0;24 point = [0, 0, 0];25 }26 displayIntersectionInfo(27 [evt.x, evt.y], name, point, depth);28 }29 };3031 for (var l in ctx.runnerListeners) {32 ctx.world.sumerianRunner.addEventListener(l, ctx.runnerListeners[l]);33 }34};3536var cleanup = function(args, ctx) {37 for (var l in ctx.runnerListeners) {38 ctx.world.sumerianRunner.removeEventListener(l, ctx.runnerListeners[l]);39 }40 if (ctx.markerEntity) ctx.markerEntity.removeFromWorld();41};4243var showMarker = function(ctx, pos) {44 if (!ctx.markerEntity) {45 ctx.markerEntity = ctx.world.createEntity(46 ctx.markerMeshData,47 ctx.markerMaterial,48 'Intersection Marker');49 }50 ctx.markerEntity.addToWorld();51 ctx.markerEntity.setTranslation(pos);52};5354var hideMarker = function(ctx) {55 if (ctx.markerEntity) ctx.markerEntity.removeFromWorld();56};5758var displayIntersectionInfo = function(screenCoords, entity, point, depth) {59 var coordsDiv = document.getElementById('intersection-screen');60 var entityDiv = document.getElementById('intersection-entity');61 var pointDiv = document.getElementById('intersection-point');62 var depthDiv = document.getElementById('intersection-depth');63 coordsDiv.innerHTML = '(' + screenCoords[0] + ', ' + screenCoords[1] + ')';64 entityDiv.innerHTML = entity;65 pointDiv.innerHTML = '(' + point[0].toFixed(2) + ', ' +66 point[1].toFixed(2) + ', ' + point[2].toFixed(2) + ')';67 depthDiv.innerHTML = depth.toFixed(2);68};今回のチュートリアルは以上です。
お疲れ様でした。