Live2D WebGLとNW.jsでデスクトップマスコット

簡単にできそうだったので、デスクトップマスコットの作り方を調べてみました。
NW.jsを使えば既存のWebアプリがさくっとデスクトップマスコットできますっ！
![001.gif](https://qiita-image-store.s3.amazonaws.com/0/15028/3f4b8d9b-1fad-599a-3163-fdfc27eb6229.gif)

# 開発環境
・Mac 10.10.5(Yosemite)
・[Live2D Cubism SDK WebGL 2.0](https://sites.google.com/a/cybernoids.jp/cubism-sdk2/webgl/webgl_dl)
・[NW.js](https://github.com/nwjs/nw.js/wiki/Downloads-of-old-versions)　→　背景透過サポートのあるv0.12.2のMac 64bit版をDL

# デスクトップマスコットの作り方
以下のページを参考に背景透過まで簡単にできました。
・[透過がサポートされたnode-webkit（NW.js）でガジェットを作ろう](http://blog.asial.co.jp/1350)
　※　Macの場合は、ターミナルからNW起動とか必要なので以下を参考に
　→　[NW.jsによるアプリ実行](http://tech.at-iroha.jp/?p=205)

**１）まずは簡単なアプリを作ってみます**
透明部分は背景がちゃんと透過されてます。
ちなみに右上の歯車アイコンクリックでconsoleログが見れて開発しやすいです。
<img width="354" alt="002.png" src="https://qiita-image-store.s3.amazonaws.com/0/15028/305a3b0e-b646-89a3-a1ff-2a5623fdef1b.png">
フォルダ構成はこんな感じにしました

```
nwjs
├── _app
│   ├── index.html　→　追加したhtml
│   └── package.json　→　追加したjson
├── credits.html
├── nwjc
└── nwjs.app
```
ヘッダータイトルは非表示にしたかったので、HTMLのtitleタグとjsonのtitleは空にしてます。

```html:index.html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <!-- タイトルなし -->
  <title></title>
  <style>
    body {
      margin: 0;
      padding: 0;
    }
    .box {
      width: 200px;
      height: 200px;
      background-color: green;
      color:white;
      font-size:60px;
      text-align: center;
      -webkit-app-region: drag;  /* ドラッグ移動用 */
    }
  </style>
</head>
<body>
<div class="box">
  test
</div>
</body>
</html>
```
確認用に一部コメントにしています

```js:package.json
{
  "name": "test",
  "main": "index.html"
  ,
  "window": {
  	"title": "",			// タイトルなし
    "width": 300,			// 幅
    "height": 300,			// 高さ
    "transparent": true//,	// 透過
    // "toolbar": false,       // ツールバーを非表示に
    // "frame": false,         // フレームを非表示に
    // "resizable": false,     // ウィンドウのリサイズを無効化
    // "always-on-top": true   // 常に最前列に表示させる,
  }
}
```

**２）Live2Dソースに差し替える**
app配下にLive2Dのソースを置きます。フォルダ構成はこのようにしました。

```
nwjs
├── app
│   ├── framework
│   │   └── Live2DFramework.js　→　モーション再生する場合は使う
│   ├── lib
│   │   └── live2d.min.js　→　Live2Dのコアライブラリ
│   ├── package.json
│   └── sample
│       └── Simple
│           ├── assets　→　モデルファイル
│           │   └── haru
│           │       ├── haru.1024
│           │       │   ├── texture_00.png
│           │       │   ├── texture_01.png
│           │       │   └── texture_02.png
│           │       └── haru.moc
│           ├── index.html　→　メインページ
│           └── src
│               └── Simple.js　→　Live2Dのメインソース
├── credits.html
├── nwjc
└── nwjs.app
```

簡単なアプリ作った時と同様にindex.htmlはtitleを消しておき、ドラッグできるようにcssにcanvasを追加します。

```html:index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<!-- タイトルなし -->
<title></title>
<style>
canvas{
  -webkit-app-region: drag;  /* ドラッグ移動用 */
}
</style>
</head>
<body>
<canvas id="glcanvas"></canvas>
<!-- Live2D Library -->
<script src="../../lib/live2d.min.js"></script>
<!-- User's Script -->
<script src="src/Simple.js"></script>
</body>
</html>
```
**========== 2016/04/03追記 ==========**
**下記の修正はせずとも1箇所直せばできる方法を本記事の最後に追記しました**

あとテクスチャ以外のバイナリファイル(.moc、.mtn)をロードする際に、既存のXMLHttpRequest経由だとロードに失敗します。
今回はnode.jsモジュールからファイルアクセスにするようにしました。
そのため、Live2Dモデルファイルはnwjsから参照するパス、テクスチャはjsから参照するパスになっています。

```js:Simple.jsのモデル定義部分
// Live2Dモデル定義
var MODEL_PATH = "sample/Simple/assets/haru/"; // nwjsから参照するパス
var IMAGE_PATH = "assets/haru/"; // jsから参照するパス
var MODEL_DEFINE = {
    "type":"Live2D Model Setting",
    "name":"haru",
    "model": MODEL_PATH + "haru.moc",
    "textures":[
        IMAGE_PATH + "haru.1024/texture_00.png",
        IMAGE_PATH + "haru.1024/texture_01.png",
        IMAGE_PATH + "haru.1024/texture_02.png",
    ],
};
```

```js:Simple.jsのモデルファイルロード処理
    //------------ Live2Dの初期化 ------------
    // mocファイルからLive2Dモデルのインスタンスを生成
    // Simple.loadBytes(modelDef.model, function(buf){
    //	live2DModel = Live2DModelWebGL.loadModel(buf);
    // });
    // nodeのファイルアクセス
    var fs = require('fs');
    // 同期的にバイナリファイルを読み込む
    var mocbuf = fs.readFileSync(modelDef.model);
    // ArrayBufferに変換
    var arrayBuf = this.toArrayBuffer(mocbuf);
    // Live2Dに読み込み
    live2DModel = Live2DModelWebGL.loadModel(arrayBuf);
```

```js:Simple.jsのArrayBufferへ変換処理
/*
 * ArrayBufferへ変換処理
 */
Simple.toArrayBuffer = function(buffer)
{
    var ab = new ArrayBuffer(buffer.length);
    var view = new Uint8Array(ab);
    for(var i = 0; i < buffer.length; ++i){
        view[i] = buffer[i];
    }
    return ab;
};
```

# ソースコード
詳細なソースコードはgithubへあげたので、デスクトップマスコット作りたい人は参考にして下さい。
・[github - Live2D-DeskTopMascot](https://github.com/naotaro0123/Live2D-DeskTopMascot)

SimpleとMotionと2つのソースがあり、package.jsonをいじれば切り替え実行できます。
（Simpleはパラメータ操作のみ、Motionはモーション再生するサンプル）

＜参考URL＞
・[Node.js でテキストファイルを読み込むサンプルコード](http://www.nilab.info/z3/20151112_01_node_js_readfile.html)
・[node.jsでBuffer経由でArrayBufferを使う](http://qiita.com/PyYoshi@github/items/899e2ce3ec636869196c)


**========== 2016/04/03追記 ==========**
XMLHttpRequest経由でロードに失敗する部分ですが、一箇所修正すれば解決しました。
→　[TyranoScript + Live2D + phonegap でiOSアプリ化したらLive2Dが動かない](https://flyingpillow.wordpress.com/2015/05/21/tyranoscript-live2d-phonegap-%E3%81%A7ios%E3%82%A2%E3%83%97%E3%83%AA%E5%8C%96%E3%81%97%E3%81%9F%E3%82%89live2d%E3%81%8C%E5%8B%95%E3%81%8B%E3%81%AA%E3%81%84/)
SampleApp1の場合は、PlatformManager.jsのloadByte部分の[case:200]→[case:0]に修正するだけでした。
![tes001.gif](https://qiita-image-store.s3.amazonaws.com/0/15028/f95c00ff-5463-5694-09f8-ec31e3d6ac60.gif)
ちなみにv0.13.2以降だとその修正もいらなかったけど、背景透過ができなかった...。

また、Unityの場合はAssetがあるのでもっと簡単にデスクトップマスコットが作れます
　→　[Unityでデスクトップマスコットを作ろう](http://panzersoft.blog.fc2.com/blog-entry-78.html)