9
5

More than 5 years have passed since last update.

ForgeによるExtensionsの作成とViewerからのEventの取得

Last updated at Posted at 2018-07-08

Autodesk ForgeはAutodesk.Viewing.Viewer3Dクラスから取得できる多様なイベント扱うことができます。イ今回はExtensionsと呼ばれる、機能拡張の仕組みと、Eventハンドリングについて説明します。

Extensionsについて

Extensionsを使うことで、Viewerの要素(Viewerに指定したDIV要素)外から、Viewerに対する操作が可能になります。
例えば、HTMLのボタンからViewerのカメラ制御のEnable/Disableを切り替えるといったことです。
基本的なExtensionの作り方としては、追加したいExtensionファイルを作成し、

  1. Autodesk.Viewing.Extensionを継承したクラスを作成
  2. boolenを返すload()メソッドを定義
  3. boolenを返すunload()メソッドを定義
  4. ユニークなIDを使って自身を登録する

といった手順で実現できます。今回はAutodeskのチュートリアルに従って、Viewer内のオブジェクトを選択状態と、ナビゲーションツールの状態を取得するExtensionを作って、取得した情報を画面上に表示するといったことを試してみます。

Viewerの準備

前のエントリを参考に基本的なビューワを作ります。Autodeskのチュートリアルが一番シンプルです。

ViewerからのEventを受け取るExtensionの作成

まずは、クライアントから参照できる位置に、eventhandler.jsという名前のファイルを作ります。(クラス名はEventTutorialですが)

eventhandler.js
function EventsTutorial(viewer, options) {
    Autodesk.Viewing.Extension.call(this, viewer, options);
}

EventsTutorial.prototype = Object.create(Autodesk.Viewing.Extension.prototype);
EventsTutorial.prototype.constructor = EventsTutorial;

EventsTutorial.prototype.onNavigationModeEvent = function (event) {
    var domElem = document.getElementById('MyToolValue');
    domElem.innerText = event.id;
};

EventsTutorial.prototype.onSelectionEvent = function (event) {
    var currSelection = this.viewer.getSelection();
    var domElem = document.getElementById('MySelectionValue');
    domElem.innerText = currSelection.length;
};

EventsTutorial.prototype.load = function () {
    this.onSelectionBinded = this.onSelectionEvent.bind(this);
    this.onNavigationModeBinded = this.onNavigationModeEvent.bind(this);
    this.viewer.addEventListener(Autodesk.Viewing.SELECTION_CHANGED_EVENT, this.onSelectionBinded);
    this.viewer.addEventListener(Autodesk.Viewing.NAVIGATION_MODE_CHANGED_EVENT, this.onNavigationModeBinded);
    return true;
};

EventsTutorial.prototype.unload = function () {
    this.viewer.removeEventListener(Autodesk.Viewing.SELECTION_CHANGED_EVENT, this.onSelectionBinded);
    this.viewer.removeEventListener(Autodesk.Viewing.NAVIGATION_MODE_CHANGED_EVENT, this.onNavigationModeBinded);
    this.onSelectionBinded = null;
    this.onNavigationModeBinded = null;
    return true;
};

Autodesk.Viewing.theExtensionManager.registerExtension('EventsTutorial', EventsTutorial);

重要なのは、先に述べたようにAutodesk.Viewing.Extensionを拡張したクラスを作っているということです。prototype拡張を使って、loadやunloadメソッドを実装しています。onSelectionEvent, onNavigationModeEventがイベントハンドラです。HTML内のMyToolValue要素,MySekectionValue要素のinnerTextの情報を更新しています。これらのハンドラは、loadメソッド内のaddEventListenerで登録されますが、Extensionをunloadした時点でハンドラの登録を解除するように実装を工夫しています。
最後にregisterExtensionに作成したクラスを登録しています。第一引数は呼び出す際のIDですが、別にクラス名と揃っていなくても構いません。

表示用のHTMLファイルの更新

Extensionで補足した情報を表示するためのDIV要素(MySelectionValue,MyToolValue)を追加します。私はExpressのテンプレートで作っているので、PUGでの記載となります。作成したExtensionのJSファイルも忘れずにインポートしましょう。

layout.pug
doctype html
html
  head
    title= title
    meta(name='viewport', content='width=device-width, minimum-scale=1.0, initial-scale=1, user-scalable=no')
    link(rel='stylesheet', href='/stylesheets/main.css')
    link(rel='stylesheet', href='https://developer.api.autodesk.com/modelderivative/v2/viewers/style.min.css', type='text/css')

  body
    block content
    script(src='https://developer.api.autodesk.com/modelderivative/v2/viewers/viewer3D.min.js')
    script(src='javascripts/viewer.js')
    script(src='javascripts/eventhandler.js')
index.pug
extends layout

block content
  div#Buttons
    button#MyAwesomeLockButton Lock it!
    button#MyAwesomeUnlockButton Unlock it!
  div#MyViewerDiv
  div.my-custom-ui
    div Items selected:
        span#MySelectionValue 0
    div Navigaton tool:
        span#MyToolValue Unknown

ExtensionをViewer3Dに読み込む

Viewerへの登録はregisterViewerの引数に、上記で指定したExtensionの登録名のリストを入れることで行います。リストなので、Extentionsの中に、カンマで区切って追加するのに加えて、上記の手順でJavascriptファイルの作成とインポートを行います。簡単ですね。

viewer.js(抜粋)
var viewerApp;
var options = {
    env: 'AutodeskProduction',
    getAccessToken: function (onGetAccessToken) {
        var accessToken = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
        var expireTimeSeconds = 60 * 30;
        onGetAccessToken(accessToken, expireTimeSeconds);
    }
};
var documentId = 'urn:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';

Autodesk.Viewing.Initializer(options, function onInitialized() {
    viewerApp = new Autodesk.Viewing.ViewingApplication('MyViewerDiv');
    // 追加のExtensionを指定
    var config3d = {
        extensions: ['EventsTutorial']
    };
    // Viewerに登録
    viewerApp.registerViewer(viewerApp.k3D, Autodesk.Viewing.Private.GuiViewer3D, config3d);
    viewerApp.loadDocument(documentId, onDocumentLoadSuccess, onDocumentLoadFailure);
});

npm startなどで実行すると以下のようになります。画面上で選択したオブジェクトの数をSELECTION_CHANGED_EVENTでとらえ表示するとともに、NAVIGATION_MODE_CHANGED_EVENTで画面下部のナビゲーションツールの選択中のモード名を取得・表示しています。

viewer.png

Viewer3Dで取得できるEventの種類

ベントはViewer3DのDocで確認できますが、表示に関するかなり細かいレベルでイベントが取れるようです。

イベント名 説明
AGGREGATE_SELECTION_CHANGED_EVENT マルチモデルコンテキストの中で選択されたオブジェクトのリストが変わったときに発火
ANIMATION_READY_EVENT animationsが正しく初期化されたときに発火
CAMERA_CHANGE_EVENT カメラが変化したときに発火
CUTPLANES_CHANGE_EVENT Cutting planesが変化したときに発火
ESCAPE_EVENT ESCキーが押されたときに発火
EXPLODE_CHANGE_EVENT Explode toolが使われたときはどんなときも発火
EXTENSION_LOADED_EVENT Viewer Extentionが読み込まれたときに発火
EXTENSION_UNLOADED_EVENT Viewer ExtentionがUnloadされたときに発火
FINAL_FRAME_RENDERED_CHANGED_EVENT Viewerが表示すべきフレームをすべて表示しきったときに発火(ペンディングしているジオメトリや適用しようとしているEffectなどがなくなったということ)
FIT_TO_VIEW_EVENT fitToViewオペレーションがなされたときに発火
FRAGMENTS_LOADED_EVENT fragmentsが要求に応じて読み込まれたときに発火
FULLSCREEN_MODE_EVENT スクリーンモードが変わったときに発火
GEOMETRY_LOADED_EVENT Model / Drawingの読み込みが終わったときに発火
HIDE_EVENT Viwerがオブジェクトを隠したときに発火
HYPERLINK_EVENT モデル中に埋め込まれているハイパーリンクがクリックされたときに発火
ISOLATE_EVENT Viewerがオブジェクトを隔離したときに発火(不可視やghostedの状態にしたとき)
LAYER_VISIBILITY_CHANGED_EVENT 2DレイヤーのVisubilityが変化したときに発火
LOAD_MISSING_GEOMETRY 欠損したジオメトリが見えるような変化が何かしらviewに生じたときに発火
MODEL_ROOT_LOADED_EVENT 初期モデルのマニフェストの取得と解析が終わったときに発火
MODEL_UNLOADED_EVENT モデルがViewerから取り残されたときに発火
NAVIGATION_MODE_CHANGED_EVENT ナビゲーションツールが変更されたときに発火
OBJECT_TREE_CREATED_EVENT インスタンスツリー生成が成功したときに発火
OBJECT_TREE_UNAVAILABLE_EVENT インスタンスツリーの解析に失敗したときに発火
PREF_CHANGED_EVENT ユーザパフォーマンスプロパティが変化したときに発火
PREF_RESET_EVENT ユーザパフォーマンスプロパティがリセットされたときに発火
PROGRESS_UPDATE_EVENT Model / Drawingが読み込まれているときに継続的に発火(読み込みのパーセントが出せる)
RENDER_OPTION_CHANGED_EVENT レンダリングオプションが変化したときに発火
RENDER_PRESENTED_EVENT レンダラが準備完了(presented)になったときには発火
RESET_EVENT モデルが初期状態にリセットされたときに発火
RESTORE_DEFAULT_SETTINGS_EVENT UIを使って、ユーザがデフォルトセッティングにリストアしたときに発火。他のAutodesk.Viewing.PREF_CHANGED_EVENTがすべて呼ばれたときに発火する
SELECTION_CHANGED_EVENT 選択されたオブジェクトが変化したときに発火
SHOW_EVENT Viewerがオブジェクトのセットを表示したときに発火
TEXTURES_LOADED_EVENT Model / Drawingのテクスチャのダウンロードが終わったときに発火
TEXTURES_LOADED_EVENT ツールがActivate/Deactivate状態に変化したときに発火
VIEWER_INITIALIZED Viewerが初期化を完全に終えたときに発火
VIEWER_RESIZE_EVENT Viewerのサイズが変わったときに発火
VIEWER_STATE_RESTORED_EVENT Viewerの状態がリストアされたときに発火
VIEWER_UNINITIALIZED ViewerがUninitializeの状態のときに発火
9
5
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
5