/** * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. */ #include "LAppView.hpp" #include "LAppLive2DManager.hpp" #include "LAppDefine.hpp" #include "LAppPal.hpp" #include "LAppModel.hpp" using namespace Csm; using namespace LAppDefine; USING_NS_AX; LAppView::LAppView(): DrawNode() , _debugRects(NULL) { } void LAppView::onEnter() { DrawNode::onEnter(); // タッチ関係のイベント管理 touchMgr = new TouchManager(); // デバイス座標からスクリーン座標に変換するための deviceToScreen = new CubismMatrix44(); // 画面の表示の拡大縮小や移動の変換を行う行列 viewMatrix = new CubismViewMatrix(); Size size = Director::getInstance()->getWinSize(); float width = size.width; float height = size.height; // 縦サイズを基準とする float ratio = width / height; float left = -ratio; float right = ratio; float bottom = ViewLogicalLeft; float top = ViewLogicalRight; viewMatrix->SetScreenRect(left, right, bottom, top); // デバイスに対応する画面の範囲。 Xの左端, Xの右端, Yの下端, Yの上端 viewMatrix->Scale(ViewScale, ViewScale); deviceToScreen->LoadIdentity(); // サイズが変わった際などリセット必須 if (width > height) { float screenW = fabsf(right - left); deviceToScreen->ScaleRelative(screenW / width, -screenW / width); } else { float screenH = fabsf(top - bottom); deviceToScreen->ScaleRelative(screenH / height, -screenH / height); } deviceToScreen->TranslateRelative(-width / 2.0f, -height / 2.0f); // 表示範囲の設定 viewMatrix->SetMaxScale(ViewMaxScale); // 限界拡大率 viewMatrix->SetMinScale(ViewMinScale); // 限界縮小率 // 表示できる最大範囲 viewMatrix->SetMaxScreenRect( ViewLogicalMaxLeft, ViewLogicalMaxRight, ViewLogicalMaxBottom, ViewLogicalMaxTop ); // イベントリスナー作成 EventListenerTouchAllAtOnce* listener = EventListenerTouchAllAtOnce::create(); // タッチメソッド設定 listener->onTouchesBegan = AX_CALLBACK_2(LAppView::onTouchesBegan, this); listener->onTouchesMoved = AX_CALLBACK_2(LAppView::onTouchesMoved, this); listener->onTouchesEnded = AX_CALLBACK_2(LAppView::onTouchesEnded, this); // 優先度100でディスパッチャーに登録 this->getEventDispatcher()->addEventListenerWithFixedPriority(listener, 100); } void LAppView::onExit() { DrawNode::onExit(); delete touchMgr; delete deviceToScreen; delete viewMatrix; } void LAppView::draw(ax::Renderer* renderer, const ax::Mat4& transform, uint32_t flags) { DrawNode::draw(renderer, transform, flags); onDraw(transform, flags); } void LAppView::onDraw(const ax::Mat4& transform, uint32_t flags) { _commandBuffer.PushCommandGroup(); Director::getInstance()->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW); Director::getInstance()->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, transform); LAppLive2DManager* Live2DMgr = LAppLive2DManager::GetInstance(); Live2DMgr->SetViewMatrix(viewMatrix); // Cubism更新・描画 Live2DMgr->OnUpdate(&_commandBuffer); if (_debugRects) { drawDebugRects(Live2DMgr); } Director::getInstance()->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW); _commandBuffer.PopCommandGroup(); } void LAppView::onTouchesBegan(const std::vector& touches, Event* event) { // タッチ開始 size_t touchNum = touches.size(); if (touchNum == 1) { Point pt = touches[0]->getLocationInView(); if (DebugTouchLogEnable)LAppPal::PrintLog("[APP]touchesBegan x:%.0f y:%.0f", pt.x, pt.y); touchMgr->touchesBegan(pt.x, pt.y); } } void LAppView::onTouchesMoved(const std::vector& touches, Event* event) { // タッチ中 size_t touchNum = touches.size(); float screenX = this->transformScreenX(touchMgr->getX()); float screenY = this->transformScreenY(touchMgr->getY()); float viewX = this->transformViewX(touchMgr->getX()); float viewY = this->transformViewY(touchMgr->getY()); if (touchNum == 1) { Point pt = touches[0]->getLocationInView(); if (DebugTouchLogEnable) LAppPal::PrintLog("[APP]touchesMoved device{x:%.0f y:%.0f} screen{x:%.2f y:%.2f} view{x:%.2f y:%.2f}", pt.x, pt.y, screenX, screenY, viewX, viewY); touchMgr->touchesMoved(pt.x, pt.y); } LAppLive2DManager* live2DMgr = LAppLive2DManager::GetInstance(); live2DMgr->OnDrag(viewX, viewY); } void LAppView::onTouchesEnded(const std::vector& touches, ax::Event* event) { // タッチ終了 LAppLive2DManager* live2DMgr = LAppLive2DManager::GetInstance(); live2DMgr->OnDrag(0, 0); if (touches.size() == 1) { // シングルタップ float x = deviceToScreen->TransformX(touchMgr->getX()); // 論理座標変換した座標を取得。 float y = deviceToScreen->TransformY(touchMgr->getY()); // 論理座標変換した座標を取得。 if (DebugTouchLogEnable) LAppPal::PrintLog("[APP]touchesEnded x:%.2f y:%.2f", x, y); live2DMgr->OnTap(x, y); } } void LAppView::updateViewMatrix(float dx, float dy, float cx, float cy, float scale) { LAppLive2DManager* live2DMgr = LAppLive2DManager::GetInstance(); // 拡大縮小 viewMatrix->AdjustScale(cx, cy, scale); // 移動 viewMatrix->AdjustTranslate(dx, dy); live2DMgr->SetViewMatrix(viewMatrix); } float LAppView::transformViewX(float deviceX) { float screenX = deviceToScreen->TransformX(deviceX); // 論理座標変換した座標を取得。 return viewMatrix->InvertTransformX(screenX); // 拡大、縮小、移動後の値。 } float LAppView::transformViewY(float deviceY) { float screenY = deviceToScreen->TransformY(deviceY); // 論理座標変換した座標を取得。 return viewMatrix->InvertTransformY(screenY); // 拡大、縮小、移動後の値。 } float LAppView::transformScreenX(float deviceX) { return deviceToScreen->TransformX(deviceX); } float LAppView::transformScreenY(float deviceY) { return deviceToScreen->TransformY(deviceY); } void LAppView::setDebugRectsNode(DrawNode* debugRects) { _debugRects = debugRects; } void LAppView::drawDebugRects(LAppLive2DManager* manager) const { const Color4F hitAreaColor = Color4F(1.0f, 0, 0, 0.2f); const Color4F userDataAreaColor = Color4F(0, 0, 1.0f, 0.2f); CubismMatrix44 projection; const Size window = Director::getInstance()->getWinSize(); const CubismVector2 windowSize = CubismVector2(window.width, window.height); projection.Scale(1, window.width / window.height); if (viewMatrix != NULL) { projection.MultiplyByMatrix(viewMatrix); } for (csmUint32 i = 0; i < manager->GetModelCount(); ++i) { _debugRects->clear(); LAppModel* model = manager->GetModel(i); const Csm::csmVector& userDataAreas = model->GetUserDataAreas(projection, windowSize); for (csmUint32 j = 0; j < userDataAreas.GetSize(); ++j) { _debugRects->drawSolidRect(Vec2(userDataAreas[j].X, userDataAreas[j].Y) , Vec2(userDataAreas[j].GetRight(), userDataAreas[j].GetBottom()) , userDataAreaColor); } const Csm::csmVector& hitAreas = model->GetHitAreas(projection, windowSize); for (csmUint32 j = 0; j < hitAreas.GetSize(); ++j) { _debugRects->drawSolidRect(Vec2(hitAreas[j].X, hitAreas[j].Y) , Vec2(hitAreas[j].GetRight(), hitAreas[j].GetBottom()) , hitAreaColor); } } } LAppView* LAppView::createDrawNode() { LAppView* ret = new(std::nothrow) LAppView(); if (ret && ret->init()) { ret->autorelease(); return ret; } AX_SAFE_DELETE(ret); return nullptr; }