2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Grimoire.jsAdvent Calendar 2016

Day 2

5 分で出来るGrimoire.jsプラグイン作成

Last updated at Posted at 2016-12-02

Grimoire.jsのプラグイン制作について

オブジェクトの移動や回転はGrimoire.jsの表現を記述する際によく使用します。このような一連のロジックを一つの機能としてまとめることは開発の効率化につながります。この機能の一まとまりをGrimoire.jsではコンポーネントと呼んでいます。今回は自分がよく使うであろう機能を実際にコンポーネントととして作成してみました。

Grimoire.jsではコンポーネントはGOMLに記述することで、対象のノード(<mesh/>など)に適用することができます。

GOMLの例
<mesh geometry="cube">
  <mesh.components>
    <!-- ここに適用するコンポーネントのタグを記述する-->
  </mesh.components>
</mesh>

プラグイン制作者はコンポーネントを作成したり、GOMLに記述されるタグを自由に定義したりすることになります。

スキャフォールディングツールの使用

プラグイン制作はNode.jsの環境で行います。
Grimoire.jsにはプラグイン制作支援のためのスキャフォールディングツールが用意されているので、それを使用します。grimoirejs-cauldronを導入することで可能になります。

$ npm install -g grimoirejs-cauldron
$ mkdir grimoirejs-movement-toolkit
$ cd grimoirejs-movement-toolkit
$ cauldron init
  • Project名はgrimoirejs-のプレフィックスをつける必要があります。
  • TypeScriptを使用するか聞かれます。今回は使用するのでtrueにしました。

以上のコマンドで、開発環境は整いました。Grimoire.jsのプラグインはスキャフォールディングツールを使わなくても、プラグイン仕様に従うことで自由に作成できます。
ディレクトリ構成とpackage.jsonはこんな感じ。

root/
 ├ package.json
 ├ tsconfig.json
 ├ src/
 │└ index.ts
 │└ main.ts
 │└ raw.d.ts
 ├ .gitignore
 └ webpack.config.js

package.json
{
  "name": "grimoirejs-movement-toolkit",
  "version": "1.0.0",
  "description": "",
  "main": "./ref/index.js",
  "typings": "./ref/index.d.ts",
  "files": [
    "src",
    "ref",
    "register"
  ],
  "keywords": [
    "grimoire",
    "grimoirejs"
  ],
  "dependencies": {
    "grimoirejs": "latest",
    "grimoirejs-math": "latest",
    "grimoirejs-fundamental": "latest"
  },
  "devDependencies": {
    "babel-cli": "^6.18.0",
    "babel-core": "^6.18.2",
    "babel-loader": "^6.2.8",
    "babel-preset-es2015": "^6.18.0",
    "babel-preset-stage-2": "^6.18.0",
    "grimoirejs-cauldron": "^2.1.0",
    "raw-loader": "^0.5.1",
    "ts-loader": "^1.2.2",
    "typescript": "^2.0.9",
    "webpack": "^1.13.3",
    "webpack-shell-plugin": "^0.4.3",
    "yargs": "^6.4.0"
  },
  "repository": "",
  "scripts": {
    "start": "webpack --watch --progress",
    "test": "echo 'add your own test'",
    "prepublish": "npm run build -- --prod&&npm test",
    "build": "webpack --progress",
    "generate-expose": "cauldron generate-exposure --src ./src --dest ./src/index.ts --ts --main ./src/main.ts --dts ./ref",
    "generate-reference": "cauldron generate-reference --src ./src --dest ./src/index.ts --ts --main ./src/main.ts --dts ./ref"
  },
  "license": "MIT"
}

コンポーネントの作成について

今回はコンポーネントのみ作成します。

基本的には初めに

  • GOMLに露出させる属性の定義
  • 定義した属性をローカル変数にバインドする
  • 毎フレーム呼び出される$update()内でロジックを記述する

ことが必要になるでしょう。
その他必要なVector3Quaternionなどはプラグイン名/ref/名称の形で呼び出して使うことが可能です。

以下はコンポーネントの一例として、RotateAroundコンポーネントを取り上げています。

RotateAroundComponent.ts
import Component from "grimoirejs/ref/Node/Component";
import IAttributeDeclaration from "grimoirejs/ref/Node/IAttributeDeclaration";
import Vector3 from "grimoirejs-math/ref/Vector3";
import Quaternion from "grimoirejs-math/ref/Quaternion";
import Matrix from "grimoirejs-math/ref/Matrix";
import TransformComponent from "grimoirejs-fundamental/ref/Components/TransformComponent";
import Attribute from "grimoirejs/ref/Node/Attribute";
export default class RotateAroundComponent extends Component {

    public static componentName: string = "RotateAroundComponent";

    public static attributes: { [key: string]: IAttributeDeclaration } = {
        center: {
            defaultValue: "0,0,0",
            converter: "Vector3"
        },
        speed: {
            defaultValue: 1,
            converter: "Number"
        },
        axis: {
            defaultValue: "0,1,0",
            converter: "Vector3"
        }
    };
    private _transform: TransformComponent;
    private _center: Vector3;
    private _speed: number;
    private _axis: Vector3;
    private distance: number;
    public $awake(): void {
        this.getAttribute("center").boundTo("_center");
        this.getAttribute("speed").boundTo("_speed");
        this._speed *= 0.05;
        this.getAttribute("axis").boundTo("_axis");
        this._axis = this._axis.normalized;
        this._transform = this.node.getComponent("Transform") as TransformComponent;
    }
    public $mount(): void {
        this.distance = this._transform.localPosition
            .subtractWith(this._center)
            .magnitude;
    }
    public $update(): void {
      const rotationMat = Matrix.rotationQuaternion(Quaternion.angleAxis(this._speed, this._axis));
      this._transform.localPosition = Matrix.transformNormal(rotationMat,this._transform.localPosition.subtractWith(this._center)).addWith(this._center);
    }
}

制作したコンポーネントにはregisterComponentメソッドを使用します。main.tsにコンポーネントを適用する際のタグ名とコンポーネントを渡すだけで、登録は完了します。
あとはHTML内でregister/プラグイン名.jsを読み込むだけで実行できます。

デバッグの際にはプリセットプラグインが導入されたgrimoire-preset-basic.min.jsも同時に読み込むことが必要になるでしょう。

main.ts
import gr from "grimoirejs";
import RotateAroundComponent from "./Components/RotateAroundComponent";
export default () => {
    gr.register(async () => {
        gr.registerComponent("RotateAround", RotateAroundComponent);
};

実際につくったコンポーネントはGOMLで以下のように記述しています。

<mesh geometry="cube">
  <mesh.components>
    <RotateAround/>
  </mesh.components>
</mesh>

(使用例)
sample-cube.gif

必要なコンポーネントも簡単に自作することができました。Grimoire.jsでWebGL表現の幅を広げるためにはプラグインの作成が有効です。スキャフォールディングツールを使用すると比較的容易にプラグインを作成することできます。一度プラグインを作ってみるとその容易さを実感できると思います。

2
1
0

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
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?