var thisRef = this;
// JavaScriptで発生したエラーを取得
window.onerror = function(msg, url, line, col, error) {
var errmsg = "file:" + url + "
line:" + line + " " + msg;
l2dError(errmsg);
}
function sampleApp1()
{
this.platform = window.navigator.platform.toLowerCase();
this.live2DMgr = new LAppLive2DManager();
this.isDrawStart = false;
this.gl = null;
this.canvas = null;
this.dragMgr = null; /*new L2DTargetPoint();*/ // ドラッグによるアニメーションの管理
this.viewMatrix = null; /*new L2DViewMatrix();*/
this.projMatrix = null; /*new L2DMatrix44()*/
this.deviceToScreen = null; /*new L2DMatrix44();*/
this.drag = false; // ドラッグ中かどうか
this.oldLen = 0; // 二本指タップした時の二点間の距離
this.lastMouseX = 0;
this.lastMouseY = 0;
this.isModelShown = false;
// モデル描画用canvasの初期化
initL2dCanvas("glcanvas");
// モデル用マトリクスの初期化と描画の開始
init();
}
function initL2dCanvas(canvasId)
{
// canvasオブジェクトを取得
this.canvas = document.getElementById(canvasId);
// イベントの登録
if(this.canvas.addEventListener) {
this.canvas.addEventListener("mousewheel", mouseEvent, false);
this.canvas.addEventListener("click", mouseEvent, false);
this.canvas.addEventListener("mousedown", mouseEvent, false);
this.canvas.addEventListener("mousemove", mouseEvent, false);
this.canvas.addEventListener("mouseup", mouseEvent, false);
this.canvas.addEventListener("mouseout", mouseEvent, false);
this.canvas.addEventListener("contextmenu", mouseEvent, false);
// タッチイベントに対応
this.canvas.addEventListener("touchstart", touchEvent, false);
this.canvas.addEventListener("touchend", touchEvent, false);
this.canvas.addEventListener("touchmove", touchEvent, false);
}
btnChangeModel = document.getElementById("btnChange");
btnChangeModel.addEventListener("click", function(e) {
changeModel();
});
}
function init()
{
// 3Dバッファの初期化
var width = this.canvas.width;
var height = this.canvas.height;
this.dragMgr = new L2DTargetPoint();
// ビュー行列
var ratio = height / width;
var left = LAppDefine.VIEW_LOGICAL_LEFT;
var right = LAppDefine.VIEW_LOGICAL_RIGHT;
var bottom = -ratio;
var top = ratio;
this.viewMatrix = new L2DViewMatrix();
// デバイスに対応する画面の範囲。 Xの左端, Xの右端, Yの下端, Yの上端
this.viewMatrix.setScreenRect(left, right, bottom, top);
// デバイスに対応する画面の範囲。 Xの左端, Xの右端, Yの下端, Yの上端
this.viewMatrix.setMaxScreenRect(LAppDefine.VIEW_LOGICAL_MAX_LEFT,
LAppDefine.VIEW_LOGICAL_MAX_RIGHT,
LAppDefine.VIEW_LOGICAL_MAX_BOTTOM,
LAppDefine.VIEW_LOGICAL_MAX_TOP);
this.viewMatrix.setMaxScale(LAppDefine.VIEW_MAX_SCALE);
this.viewMatrix.setMinScale(LAppDefine.VIEW_MIN_SCALE);
this.projMatrix = new L2DMatrix44();
this.projMatrix.multScale(1, (width / height));
// マウス用スクリーン変換行列
this.deviceToScreen = new L2DMatrix44();
this.deviceToScreen.multTranslate(-width / 2.0, -height / 2.0);
this.deviceToScreen.multScale(2 / width, -2 / width);
// WebGLのコンテキストを取得する
this.gl = getWebGLContext();
if (!this.gl) {
l2dError("Failed to create WebGL context.");
return;
}
// OpenGLのコンテキストをセット
Live2D.setGL(this.gl);
// 描画エリアを白でクリア
this.gl.clearColor(0.0, 0.0, 0.0, 0.0);
changeModel();
startDraw();
}
function startDraw() {
if(!this.isDrawStart) {
this.isDrawStart = true;
(function tick() {
draw(); // 1回分描画
var requestAnimationFrame =
window.requestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.msRequestAnimationFrame;
// 一定時間後に自身を呼び出す
requestAnimationFrame(tick ,this.canvas);
})();
}
}
function draw()
{
// l2dLog("--> draw()");
MatrixStack.reset();
MatrixStack.loadIdentity();
this.dragMgr.update(); // ドラッグ用パラメータの更新
this.live2DMgr.setDrag(this.dragMgr.getX(), this.dragMgr.getY());
// Canvasをクリアする
this.gl.clear(this.gl.COLOR_BUFFER_BIT);
MatrixStack.multMatrix(projMatrix.getArray());
MatrixStack.multMatrix(viewMatrix.getArray());
MatrixStack.push();
for (var i = 0; i < this.live2DMgr.numModels(); i++)
{
var model = this.live2DMgr.getModel(i);
if(model == null) return;
if (model.initialized && !model.updating)
{
model.update();
model.draw(this.gl);
if (!this.isModelShown && i == this.live2DMgr.numModels()-1) {
this.isModelShown = !this.isModelShown;
var btnChange = document.getElementById("btnChange");
btnChange.textContent = "Change Model";
btnChange.removeAttribute("disabled");
btnChange.setAttribute("class", "active");
}
}
}
MatrixStack.pop();
}
function changeModel()
{
var btnChange = document.getElementById("btnChange");
btnChange.setAttribute("disabled","disabled");
btnChange.setAttribute("class", "inactive");
btnChange.textContent = "Now Loading...";
this.isModelShown = false;
this.live2DMgr.reloadFlg = true;
this.live2DMgr.count++;
this.live2DMgr.changeModel(this.gl);
}
/* ********** マウスイベント ********** */
/*
* マウスホイールによる拡大縮小
*/
function modelScaling(scale)
{
var isMaxScale = thisRef.viewMatrix.isMaxScale();
var isMinScale = thisRef.viewMatrix.isMinScale();
thisRef.viewMatrix.adjustScale(0, 0, scale);
// 画面が最大になったときのイベント
if (!isMaxScale)
{
if (thisRef.viewMatrix.isMaxScale())
{
thisRef.live2DMgr.maxScaleEvent();
}
}
// 画面が最小になったときのイベント
if (!isMinScale)
{
if (thisRef.viewMatrix.isMinScale())
{
thisRef.live2DMgr.minScaleEvent();
}
}
}
/*
* クリックされた方向を向く
* タップされた場所に応じてモーションを再生
*/
function modelTurnHead(event)
{
thisRef.drag = true;
var rect = event.target.getBoundingClientRect();
var sx = transformScreenX(event.clientX - rect.left);
var sy = transformScreenY(event.clientY - rect.top);
var vx = transformViewX(event.clientX - rect.left);
var vy = transformViewY(event.clientY - rect.top);
if (LAppDefine.DEBUG_MOUSE_LOG)
l2dLog("onMouseDown device( x:" + event.clientX + " y:" + event.clientY + " ) view( x:" + vx + " y:" + vy + ")");
thisRef.lastMouseX = sx;
thisRef.lastMouseY = sy;
thisRef.dragMgr.setPoint(vx, vy); // その方向を向く
// タップした場所に応じてモーションを再生
thisRef.live2DMgr.tapEvent(vx, vy);
}
/*
* マウスを動かした時のイベント
*/
function followPointer(event)
{
var rect = event.target.getBoundingClientRect();
var sx = transformScreenX(event.clientX - rect.left);
var sy = transformScreenY(event.clientY - rect.top);
var vx = transformViewX(event.clientX - rect.left);
var vy = transformViewY(event.clientY - rect.top);
if (LAppDefine.DEBUG_MOUSE_LOG)
l2dLog("onMouseMove device( x:" + event.clientX + " y:" + event.clientY + " ) view( x:" + vx + " y:" + vy + ")");
if (thisRef.drag)
{
thisRef.lastMouseX = sx;
thisRef.lastMouseY = sy;
thisRef.dragMgr.setPoint(vx, vy); // その方向を向く
}
}
/*
* 正面を向く
*/
function lookFront()
{
if (thisRef.drag)
{
thisRef.drag = false;
}
thisRef.dragMgr.setPoint(0, 0);
}
function mouseEvent(e)
{
e.preventDefault();
if (e.type == "mousewheel") {
if (e.clientX < 0 || thisRef.canvas.clientWidth < e.clientX ||
e.clientY < 0 || thisRef.canvas.clientHeight < e.clientY)
{
return;
}
if (e.wheelDelta > 0) modelScaling(1.1); // 上方向スクロール 拡大
else modelScaling(0.9); // 下方向スクロール 縮小
} else if (e.type == "mousedown") {
// 右クリック以外なら処理を抜ける
if("button" in e && e.button != 0) return;
modelTurnHead(e);
} else if (e.type == "mousemove") {
followPointer(e);
} else if (e.type == "mouseup") {
// 右クリック以外なら処理を抜ける
if("button" in e && e.button != 0) return;
lookFront();
} else if (e.type == "mouseout") {
lookFront();
} else if (e.type == "contextmenu") {
changeModel();
}
}
function touchEvent(e)
{
e.preventDefault();
var touch = e.touches[0];
if (e.type == "touchstart") {
if (e.touches.length == 1) modelTurnHead(touch);
// onClick(touch);
} else if (e.type == "touchmove") {
followPointer(touch);
if (e.touches.length == 2) {
var touch1 = e.touches[0];
var touch2 = e.touches[1];
var len = Math.pow(touch1.pageX - touch2.pageX, 2) + Math.pow(touch1.pageY - touch2.pageY, 2);
if (thisRef.oldLen - len < 0) modelScaling(1.025); // 上方向スクロール 拡大
else modelScaling(0.975); // 下方向スクロール 縮小
thisRef.oldLen = len;
}
} else if (e.type == "touchend") {
lookFront();
}
}
/* ********** マトリックス操作 ********** */
function transformViewX(deviceX)
{
var screenX = this.deviceToScreen.transformX(deviceX); // 論理座標変換した座標を取得。
return viewMatrix.invertTransformX(screenX); // 拡大、縮小、移動後の値。
}
function transformViewY(deviceY)
{
var screenY = this.deviceToScreen.transformY(deviceY); // 論理座標変換した座標を取得。
return viewMatrix.invertTransformY(screenY); // 拡大、縮小、移動後の値。
}
function transformScreenX(deviceX)
{
return this.deviceToScreen.transformX(deviceX);
}
function transformScreenY(deviceY)
{
return this.deviceToScreen.transformY(deviceY);
}
/*
* WebGLのコンテキストを取得する
*/
function getWebGLContext()
{
var NAMES = [ "webgl" , "experimental-webgl" , "webkit-3d" , "moz-webgl"];
for( var i = 0; i < NAMES.length; i++ ){
try{
var ctx = this.canvas.getContext(NAMES[i], {premultipliedAlpha : true});
if(ctx) return ctx;
}
catch(e){}
}
return null;
};
/*
* 画面ログを出力
*/
function l2dLog(msg) {
if(!LAppDefine.DEBUG_LOG) return;
var myconsole = document.getElementById("myconsole");
myconsole.innerHTML = myconsole.innerHTML + "
" + msg;
console.log(msg);
}
/*
* 画面エラーを出力
*/
function l2dError(msg)
{
if(!LAppDefine.DEBUG_LOG) return;
l2dLog( "" + msg + "");
console.error(msg);
};