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