Files
Yosuga_rk3566/3rdparty/Live2D/Src/LAppLive2D/Inc/LAppModel.hpp
T
Misaki 7551a85abe first
2026-06-10 00:57:54 +08:00

291 lines
11 KiB
C++

/**
* 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.
*/
#pragma once
#include <CubismFramework.hpp>
#include <Model/CubismUserModel.hpp>
#include <ICubismModelSetting.hpp>
#include <Type/csmRectF.hpp>
#include <Rendering/OpenGL/CubismOffscreenSurface_OpenGLES2.hpp>
#include "LAppWavFileHandler.hpp"
#include <map>
#include <vector>
#include <string>
/**
* @brief ユーザーが実際に使用するモデルの実装クラス<br>
* モデル生成、機能コンポーネント生成、更新処理とレンダリングの呼び出しを行う。
*
*/
class LAppModel : public Csm::CubismUserModel
{
public:
/**
* @brief コンストラクタ
*/
LAppModel();
/**
* @brief デストラクタ
*
*/
virtual ~LAppModel();
struct MotionInfo {
std::string FileName; // 动作的文件名
int SequenceId; // 组内的播放序列号
};
/**
* 获取按组分类的动作映射表
* Key: 组名 (如 "Idle"), Value: 动作信息列表
*/
std::map<std::string, std::vector<MotionInfo>> GetMotionMap();
/**
* 在控制台打印当前模型所有的动作组和序列信息
*/
void DumpMotionMap();
/**
* @brief 获得Idle动画总数量
* @author Misaki
* @return int
*/
[[nodiscard]] int getIdleMotionCount() const;
/**
* @brief 获得TapBody动画总数量
* @author Misaki
* @return int
*/
[[nodiscard]] int getTapBodyMotionCount() const;
/**
* @brief 获取 Live2D 模型的 Canvas 宽度像素 (在 Live2D 坐标系下)
* @return Canvas 宽度
*/
[[nodiscard]] Live2D::Cubism::Framework::csmFloat32 GetModelCanvasWidthPixel() const
{
// _model 是 CubismModel 的基类指针
return _model ? _model->GetCanvasWidthPixel() : 0.0f;
}
/**
* @brief 获取 Live2D 模型的 Canvas 高度像素 (在 Live2D 坐标系下)
* @return Canvas 高度
*/
[[nodiscard]] Live2D::Cubism::Framework::csmFloat32 GetModelCanvasHeightPixel() const
{
return _model ? _model->GetCanvasHeightPixel() : 0.0f;
}
/**
* @brief 启动唇形同步并播放指定的 WAV 文件
* @param filePath WAV 文件的路径(csmString 类型)
* @author Misaki
*/
void StartLipSync(const Csm::csmString& filePath);
/**
* @brief 停止唇形同步并停止播放指定的 WAV 文件
* @author Misaki
*/
void StopLipSync();
/**
* @brief 获取模型是否有命中区域定义
* @return 是否有命中区域
*/
[[nodiscard]] bool HasHitAreas() const;
/**
* @brief 检测点是否在模型的任何可见部分上
* @param x 视图坐标X
* @param y 视图坐标Y
* @return 是否命中
*/
[[nodiscard]] bool IsPointOnModel(Csm::csmFloat32 x, Csm::csmFloat32 y);
/**
* @brief model3.jsonが置かれたディレクトリとファイルパスからモデルを生成する \n
* 从 model3.json 所在的目录和文件路径生成模型
*/
void LoadAssets(const Csm::csmChar* dir, const Csm::csmChar* fileName);
/**
* @brief レンダラを再構築する
*
*/
void ReloadRenderer();
/**
* @brief モデルの更新処理。モデルのパラメータから描画状態を決定する。
*
*/
void Update();
/**
* @brief モデルを描画する処理。モデルを描画する空間のView-Projection行列を渡す。
*
* @param[in] matrix View-Projection行列
*/
void Draw(Csm::CubismMatrix44& matrix);
/**
* @brief 引数で指定したモーションの再生を開始する。
*
* @param[in] group モーショングループ名
* @param[in] no グループ内の番号
* @param[in] priority 優先度
* @param[in] onFinishedMotionHandler モーション再生終了時に呼び出されるコールバック関数。NULLの場合、呼び出されない。
* @return 開始したモーションの識別番号を返す。個別のモーションが終了したか否かを判定するIsFinished()の引数で使用する。開始できない時は「-1」
*/
Csm::CubismMotionQueueEntryHandle StartMotion(const Csm::csmChar* group, Csm::csmInt32 no, Csm::csmInt32 priority, Csm::ACubismMotion::FinishedMotionCallback onFinishedMotionHandler = NULL);
/**
* @brief 开始播放随机选择的动画。
*
* @param[in] group 动画组名称
* @param[in] priority 优先级
* @param[in] onFinishedMotionHandler 动画播放结束时被调用的回调函数。如果为NULL,则不被调用。
* @return 返回开始播放的动画的标识编号。用于作为判断特定动画是否结束的IsFinished()函数的参数。如果无法开始播放,则返回「-1」
*/
Csm::CubismMotionQueueEntryHandle StartRandomMotion(const Csm::csmChar* group, Csm::csmInt32 priority, Csm::ACubismMotion::FinishedMotionCallback onFinishedMotionHandler = NULL);
/**
* @brief 引数で指定した表情モーションをセットする
*
* @param expressionID 表情モーションのID
*/
void SetExpression(const Csm::csmChar* expressionID);
/**
* @brief ランダムに選ばれた表情モーションをセットする
*
*/
void SetRandomExpression();
/**
* @brief イベントの発火を受け取る
*
*/
virtual void MotionEventFired(const Live2D::Cubism::Framework::csmString& eventValue);
/**
* @brief 当たり判定テスト。<br>
* 指定IDの頂点リストから矩形を計算し、座標が矩形範囲内か判定する。
*
* @param[in] hitAreaName 当たり判定をテストする対象のID
* @param[in] x 判定を行うX座標
* @param[in] y 判定を行うY座標
*/
virtual Csm::csmBool HitTest(const Csm::csmChar* hitAreaName, Csm::csmFloat32 x, Csm::csmFloat32 y);
/**
* @brief 別ターゲットに描画する際に使用するバッファの取得
*/
Csm::Rendering::CubismOffscreenSurface_OpenGLES2& GetRenderBuffer();
/**
* @brief .moc3ファイルの整合性をチェックする
*
* @param[in] mocName MOC3ファイル名
* @return MOC3に整合性があれば'true'、そうでなければ'false'。
*/
Csm::csmBool HasMocConsistencyFromFile(const Csm::csmChar* mocFileName);
protected:
/**
* @brief モデルを描画する処理。モデルを描画する空間のView-Projection行列を渡す。
*
*/
void DoDraw();
private:
/**
* @brief 使用Drawable检测(当没有命中区域时使用)
* @param x 视图坐标X
* @param y 视图坐标Y
* @return 是否命中
*/
[[nodiscard]] bool IsPointOnDrawable(Csm::csmFloat32 x, Csm::csmFloat32 y);
// 辅助函数: 从完整路径提取纯文件名
std::string ExtractFileName(const std::string& fullPath);
private:
/**
* @brief model3.jsonからモデルを生成する。<br>
* model3.jsonの記述に従ってモデル生成、モーション、物理演算などのコンポーネント生成を行う。
*
* @param[in] setting ICubismModelSettingのインスタンス
*
*/
void SetupModel(Csm::ICubismModelSetting* setting);
/**
* @brief OpenGLのテクスチャユニットにテクスチャをロードする
*
*/
void SetupTextures();
/**
* @brief モーションデータをグループ名から一括でロードする。<br>
* モーションデータの名前は内部でModelSettingから取得する。
*
* @param[in] group モーションデータのグループ名
*/
void PreloadMotionGroup(const Csm::csmChar* group);
/**
* @brief モーションデータをグループ名から一括で解放する。<br>
* モーションデータの名前は内部でModelSettingから取得する。
*
* @param[in] group モーションデータのグループ名
*/
void ReleaseMotionGroup(const Csm::csmChar* group) const;
/**
* @brief すべてのモーションデータの解放
*
* すべてのモーションデータを解放する。
*/
void ReleaseMotions();
/**
* @brief すべての表情データの解放
*
* すべての表情データを解放する。
*/
void ReleaseExpressions();
Csm::ICubismModelSetting* _modelSetting; ///< モデルセッティング情報
Csm::csmString _modelHomeDir; ///< モデルセッティングが置かれたディレクトリ
Csm::csmFloat32 _userTimeSeconds; ///< デルタ時間の積算値[秒]
Csm::csmVector<Csm::CubismIdHandle> _eyeBlinkIds; ///< モデルに設定されたまばたき機能用パラメータID
Csm::csmVector<Csm::CubismIdHandle> _lipSyncIds; ///< モデルに設定されたリップシンク機能用パラメータID
Csm::csmMap<Csm::csmString, Csm::ACubismMotion*> _motions; ///< 読み込まれているモーションのリスト
Csm::csmMap<Csm::csmString, Csm::ACubismMotion*> _expressions; ///< 読み込まれている表情のリスト
Csm::csmVector<Csm::csmRectF> _hitArea;
Csm::csmVector<Csm::csmRectF> _userArea;
const Csm::CubismId* _idParamAngleX; ///< パラメータID: ParamAngleX
const Csm::CubismId* _idParamAngleY; ///< パラメータID: ParamAngleX
const Csm::CubismId* _idParamAngleZ; ///< パラメータID: ParamAngleX
const Csm::CubismId* _idParamBodyAngleX; ///< パラメータID: ParamBodyAngleX
const Csm::CubismId* _idParamEyeBallX; ///< パラメータID: ParamEyeBallX
const Csm::CubismId* _idParamEyeBallY; ///< パラメータID: ParamEyeBallXY
LAppWavFileHandler _wavFileHandler; ///< wavファイルハンドラ WAV文件处理器
// 低通滤波器参数
Live2D::Cubism::Framework::csmFloat32 alpha = 0.8f; // 滤波系数,范围在0到1之间,值越小,平滑效果越强
Live2D::Cubism::Framework::csmFloat32 filteredValue = 0.0f; // 滤波后的值
Csm::Rendering::CubismOffscreenSurface_OpenGLES2 _renderBuffer; ///< フレームバッファ以外の描画先
};