Forge Viewer チュートリアル ~ その2 ~ Extension の実装

前回、作成した Node.js を使った Web サーバーがホストする Forge Viewer に、Extension(エクステンション)を追加していきます。ここで紹介する内容は、viewer-javascript-tutorial リポジトリ の Chapter 3 の Step 1 ~ Step 6 に該当するものです。

Extension とは ?

AutoCAD や Revit、Inventor のようなデスクトップ製品では、その API を使ってアドイン アプリケーションを開発して製品にロードすることで、製品自体の機能を拡張することが出来ます。Forge Viewer も、アドインと同じようなメカニズムを持っています。JavaScript で決められたルールに従って記述した機能拡張モジュール、すなわち、Extension を作成して、実行中の Forge Viewer にロードすることで利用するメカニズムです。

Extension を利用することで、管理者権限を持つメンバだけに Extension をロードして機能を利用させたり、権限のないユーザの利用時に Extension をロード解除して特定の機能を無効にするといった制御も可能になります。もちろん、利用する必要がなくなれば、ビューアから Extension をロード解除することも出来ます。


最初に Extension の基本メカニズムを理解するために、簡単な Extension のロードとロード解除を実装していきます。

  1. Adobe Brackets などの適切なテキスト エディタを使って、”Viewing.Extension.Workshop.js” 名で JavaScript ファイルを作成して、次の内容のスケルトン コードを貼り付けて www フォルダに保存します。
///////////////////////////////////////////////////////////////////////////////
// Demo Workshop Viewer Extension
// by Philippe Leefsma, April 2015
//
///////////////////////////////////////////////////////////////////////////////
AutodeskNamespace("Viewing.Extension");
Viewing.Extension.Workshop = function (viewer, options) {
    /////////////////////////////////////////////////////////////////
    //  base class constructor
    //
    /////////////////////////////////////////////////////////////////
    Autodesk.Viewing.Extension.call(this, viewer, options);
    var _self = this;
    var _viewer = viewer;
    /////////////////////////////////////////////////////////////////
    // load callback: invoked when viewer.loadExtension is called
    //
    /////////////////////////////////////////////////////////////////
    _self.load = function () {
        alert('Viewing.Extension.Workshop loaded');
        console.log('Viewing.Extension.Workshop loaded');
        return true;
    };
    /////////////////////////////////////////////////////////////////
    // unload callback: invoked when viewer.unloadExtension is called
    //
    /////////////////////////////////////////////////////////////////
    _self.unload = function () {
        console.log('Viewing.Extension.Workshop unloaded');
        return true;
    };
};
/////////////////////////////////////////////////////////////////
// sets up inheritance for extension and register
//
/////////////////////////////////////////////////////////////////
Viewing.Extension.Workshop.prototype =
    Object.create(Autodesk.Viewing.Extension.prototype);
Viewing.Extension.Workshop.prototype.constructor =
    Viewing.Extension.Workshop;
Autodesk.Viewing.theExtensionManager.registerExtension(
    'Viewing.Extension.Workshop',
    Viewing.Extension.Workshop);
  1. index.html ファイルを開いて、</head> タグの一行前に 1. で作成した Extension ファイルを参照するコードを追記します。
<script src="/Viewing.Extension.Workshop.js"></script>
  1. index.js に Extension ファイルをロードするコードを追記します。ビューアがジオメトリをロードした際に生成される GEOMETRY_LOADED_EVENT イベントを待って、Extension をロードさせるため、index.js ファイルの既存コードに、次の太字の部分を追記します。このコードで、イベント発生時に loadExtension() が呼び出されます。
        viewer.addEventListener(
            Autodesk.Viewing.GEOMETRY_LOADED_EVENT, function (event) {
                loadExtensions(viewer);
            }
        );
        viewer.load(pathInfoCollection.path3d[0].path);
    },onError);
});
  1. loadExtension() を実装します。index.js ファイルの OnError() の前に、次の太字部分を追記します。
function loadExtensions(viewer) {
    viewer.loadExtension('Viewing.Extension.Workshop');
}
function onError(error) {
    console.log('Error: ' + error);
};
  1. 実装したExtension をテストしてみます。Node.js でクライアント上の Web サーバーを起動して、WebGL 対応ブラウザで http://localhost:3000/ を開き、3D モデルを表示してみてください。ジオメトリが表示された直後に、次のようなメッセージ ボックスが表示されれば、Extension が正しくロードされたことになります。

    なお、ここで表示されたのは、Viewing.Extension.Workshop.js 内の alert(‘Viewing.Extension.Workshop loaded’); の部分となります。

続いて、作成した Extension にオブジェクト選択の処理を追加ていきします。オブジェクトの選択には、イベント処理を利用します。Forge Viewer には、オブジェクト選択を検出する SELECTION_CHANGED_EVENT イベントが用意されているので、このイベント ハンドラを宣言して実装すると、オブジェクトを選択した後の各種処理を実装していくことが可能です。

  1. 追加した Extension ファイル、Viewing.Extension.Workshop.js を Adobe Brackets などのテキスト エディタで開いて、次の太字部分を追記してください。ジオメトリをロードされた際に表示していた alert() は、コメントにし表示しないように変更してください。
_self.load = function () {
    _viewer.addEventListener(
        Autodesk.Viewing.SELECTION_CHANGED_EVENT,
        _self.onSelectionChanged);

    //alert('Viewing.Extension.Workshop loaded');    console.log('Viewing.Extension.Workshop loaded');
    return true;
};
/////////////////////////////////////////////////////////////////
// selection changed callback
//
/////////////////////////////////////////////////////////////////
_self.onSelectionChanged = function (event) {
    // event is triggered also when component is unselected
    // in that case event.dbIdArray is an empty array
    if (event.dbIdArray.length) {
        var dbId = event.dbIdArray[0];
        // do stuff with selected component
    }
    else {
        // all components unselected
    }
}
  1. Viewing.Extension.Workshop.js を上書き保存して、Node.js で Web サーバーを再起動してから、Web ブラウザで localhost:3000 を表示してください。モデル表示後にオブジェクト選択が可能になりますが、現在のコードではオブジェクトを選択しても何も起こりません。イベント ハンドラが正しく動作しているかは、Web ブラウザのデバッグ環境で確かめることができます。例えば、Google Chrome をお使いの場合には、3D モデルの表示後に F12 キーを押すことで、デベロッパー ツールを表示させることが可能です。あとは、Viewing.Extension.Workshop.js の適切な位置にブレーク ポイントを置いて、オブジェクトを選択するだけです。このコードでは、選択したオブジェクトの ID が変数 dbId に代入される過程を把握することが出来るはずです。
Screenshot of a development environment displaying a 3D model of a chair on the left and code debugging tools on the right, showcasing JavaScript code and breakpoints.

次に、オブジェクト選択の機能で拡張した Extension に、選択したオブジェクトのプロパティを表示するパネル表示機能を実装していきます。

  1. Viewing.Extension.Workshop.js を Adobe Brackets などで開いて、次の太字部分を追記します。
/////////////////////////////////////////////////////////////////
//  base class constructor
//
/////////////////////////////////////////////////////////////////
Autodesk.Viewing.Extension.call(this, viewer, options);
var _self = this;
var _viewer = viewer;
/////////////////////////////////////////////////////////////////
// create panel and set up inheritance
//
/////////////////////////////////////////////////////////////////
Viewing.Extension.Workshop.WorkshopPanel = function (
    parentContainer,
    id,
    title,
    options) {
    Autodesk.Viewing.UI.PropertyPanel.call(
        this,
        parentContainer,
        id, title);
};
Viewing.Extension.Workshop.WorkshopPanel.prototype = Object.create(
    Autodesk.Viewing.UI.PropertyPanel.prototype);
Viewing.Extension.Workshop.WorkshopPanel.prototype.constructor =
    Viewing.Extension.Workshop.WorkshopPanel;

/////////////////////////////////////////////////////////////////
// load callback: invoked when viewer.loadExtension is called
//
/////////////////////////////////////////////////////////////////
_self.load = function () {
  1. Extension のロードとロード解除を担当する load() と unload() 関数で、定義したパネルのインスタンス化と後処理を追記します。load() と unload() 関数内の太字部分を追記してください。
/////////////////////////////////////////////////////////////////
// load callback: invoked when viewer.loadExtension is called
//
/////////////////////////////////////////////////////////////////
_self.load = function () {
    _viewer.addEventListener(
        Autodesk.Viewing.SELECTION_CHANGED_EVENT,
        _self.onSelectionChanged);
    _self.panel = new Viewing.Extension.Workshop.WorkshopPanel(
        _viewer.container,
        'WorkshopPanelId',
        'Workshop Panel');
    console.log('Viewing.Extension.Workshop loaded');
    return true;
};

/////////////////////////////////////////////////////////////////
// unload callback: invoked when viewer.unloadExtension is called
//
/////////////////////////////////////////////////////////////////
_self.unload = function () {
    _self.panel.setVisible(false);
    _self.panel.uninitialize();
    console.log('Viewing.Extension.Workshop unloaded');
    return true;
};
  1. 前回、オブジェクト選択で利用した SELECTION_CHANGED イベントのイベント ハンドラ関数である onSelectionChanged() の中身を次の内容で置き換えます。このコードは、選択したオブジェクトをビュー内に拡大表示して、そのプロパティをインスタンス化したパネルに表示します。
/////////////////////////////////////////////////////////////////
// selection changed callback
//
/////////////////////////////////////////////////////////////////
_self.onSelectionChanged = function (event) {
    function propertiesHandler(result) {
        if (result.properties) {
            _self.panel.setProperties(
                result.properties);
            _self.panel.setVisible(true);
        }
    }
    if (event.dbIdArray.length) {
        var dbId = event.dbIdArray[0];
        _viewer.getProperties(
            dbId,
            propertiesHandler);
        _viewer.fitToView(dbId);
        _viewer.isolateById(dbId);
    }
    else {
        _viewer.isolateById([]);
        _viewer.fitToView();
        _self.panel.setVisible(false);
    }
}
  1. Viewing.Extension.Workshop.js を上書き保存してから、Node.js で構築してある Web サーバーを localhost:3000 のURLで表示してみてください。選択したオブジェクトが拡大表示され、同時にプロパティが Workshop Panel のタイトルを持つパネルに表示されるはずです。
3D model of a workshop panel made of stainless steel, displayed with a transparent blue appearance. The panel includes specifications like mass, volume, area, and density in an information panel.

    ここまでの実装で、オブジェクト選択とパネル表示を Extension としてモジュール化する実装が完了しました。このように、Extension 単位でさまざまな機能を盛り込んでいくことができます。Extension には、オートデスクが用意した標準の Extension も存在します。過去のブログ記事 Forge Viewer で利用可能な Extension でもご紹介していますのでご確認ください。

    By Toshiaki Isezaki

    Discover more from Autodesk Developer Blog

    Subscribe now to keep reading and get access to the full archive.

    Continue reading