LoginSignup
1
0

More than 5 years have passed since last update.

three.jsで.copy()と.set()を間違えた時に警告する

Last updated at Posted at 2018-02-12

three.js の基本的なクラスであるVector*, Quaternion, Matrix* (*は3とか4とか)にはclone, copy, set, fromArrayという関数が定義されています。これらは

  • clone: 同一のプロパティをもつインスタンスを複製して返す
    • 例: const vec3_ = vec3.clone();
  • copy: ただひとつの引数(同じクラスのインスタンス)のプロパティをそのインスタンスのプロパティにコピーする
    • 例: vec3_.copy(vec3);
  • set: 引数ひとつひとつをそのインスタンスのプロパティひとつひとつにセットする
    • 例: vec3.set(1, 2, 3);
  • fromArray: ただひとつの引数(配列)の要素をそのインスタンスのプロパティひとつひとつにセットする
    • 例: vec3.fromArray([1, 2, 3]);

……と覚えるまでが大変です。
この記事では特によく使うcopysetについて引数を間違えていると即座にランタイムで警告を出せるようにします。

.copy()

const overrideCopyFunction = function(cl, args) {
    // 元のcopy関数
    const cp = cl.prototype.copy;
    cl.prototype.copy = function(from) {
        // fromの「名前がargsに含まれるプロパティ」に数値でないものが含まれる場合に例外を返す
        if(args.some(function(x) { return (typeof from[x]) != "number"; }))
            throw new Error(); // お好きなメッセージをどうぞ
        // 本来のcopy関数を呼ぶ
        return (cp.bind(this))(from);
    };
};
overrideCopyFunction(THREE.Vector3, ["x", "y", "z"]);
overrideCopyFunction(THREE.Quaternion, ["x", "y", "z", "w"]);

こんな感じにVector3copy関数を上書きします。
overrideCopyFunctionの引数には対象クラスとプロパティ名の配列を指定します。
copy関数では他の物理演算エンジンのベクトルなどを使いたい場合もあるため、ここでは「数値型の.x, .y, .zプロパティをもつオブジェクト」が渡された場合以外の際に例外を投げるようにしています。

.set()

const overrideSetFunction = function(cl) {
    const st = cl.prototype.set;
    cl.prototype.set = function(...from) {
    if(from.some(function(x) { return (typeof x) != "number"; }))
        throw new Error();
    return (st.bind(this))(...from);
    };
};
overrideSetFunction(THREE.Vector3);
overrideSetFunction(THREE.Quaternion);

setについてもcopyと同様に関数を上書きします。
新しいset関数では引数のうち数値型でないものが含まれる場合に例外を投げ、そうでない場合にはその引数をオリジナルのset関数にそのまま引き渡します。

実行例

適用前

> v
< Vector3 {x: 1, y: 2, z: 3, isVector3: true, set: function, ...}
> v2
< Vector3 {x: 4, y: 5, z: 6, isVector3: true, set: function, ...}
> v.set(7, 8, 9)
< Vector3 {x: 7, y: 8, z: 9, isVector3: true, set: function, ...}
> v.set(v2)
< Vector3 {x: Vector3, y: undefined, z: undefined, isVector3: true, set: function, ...}

2つ目のsetvが破壊されます。

> v
< Vector3 {x: 1, y: 2, z: 3, isVector3: true, set: function, ...}
> v2
< Vector3 {x: 4, y: 5, z: 6, isVector3: true, set: function, ...}
> v.copy(v2)
< Vector3 {x: 4, y: 5, z: 6, isVector3: true, set: function, ...}
> v.copy(7, 8, 9)
< Vector3 {x: undefined, y: undefined, z: undefined, isVector3: true, set: function, ...}

2つ目のcopyvが破壊されます。

適用後

> v
< Vector3 {x: 1, y: 2, z: 3, isVector3: true, set: function, ...}
> v2
< Vector3 {x: 4, y: 5, z: 6, isVector3: true, set: function, ...}
> v.set(7, 8, 9)
< Vector3 {x: 7, y: 8, z: 9, isVector3: true, set: function, ...}
> v.set(v2)
< Error
> v
< Vector3 {x: 1, y: 2, z: 3, isVector3: true, set: function, ...}
> v2
< Vector3 {x: 4, y: 5, z: 6, isVector3: true, set: function, ...}
> v.copy(v2)
< Vector3 {x: 4, y: 5, z: 6, isVector3: true, set: function, ...}
> v.copy(7, 8, 9)
< Error

ちゃんとエラーが帰ってきます。

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