1. 优化了音频输出输出模块的内容
2. 新增了对模型动作组管理的接口,方便后续模型的动作管理
This commit is contained in:
+23
-4
@@ -14,7 +14,9 @@
|
||||
#include <Rendering/OpenGL/CubismOffscreenSurface_OpenGLES2.hpp>
|
||||
|
||||
#include "LAppWavFileHandler.hpp"
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
/**
|
||||
* @brief ユーザーが実際に使用するモデルの実装クラス<br>
|
||||
* モデル生成、機能コンポーネント生成、更新処理とレンダリングの呼び出しを行う。
|
||||
@@ -34,19 +36,35 @@ public:
|
||||
*/
|
||||
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
|
||||
*/
|
||||
int getIdleMotionCount();
|
||||
[[nodiscard]] int getIdleMotionCount() const;
|
||||
|
||||
/**
|
||||
* @brief 获得TapBody动画总数量
|
||||
* @author Misaki
|
||||
* @return int
|
||||
*/
|
||||
int getTapBodyMotionCount();
|
||||
[[nodiscard]] int getTapBodyMotionCount() const;
|
||||
|
||||
/**
|
||||
* @brief 获取 Live2D 模型的 Canvas 宽度像素 (在 Live2D 坐标系下)
|
||||
@@ -198,6 +216,8 @@ private:
|
||||
*/
|
||||
[[nodiscard]] bool IsPointOnDrawable(Csm::csmFloat32 x, Csm::csmFloat32 y);
|
||||
|
||||
// 辅助函数: 从完整路径提取纯文件名
|
||||
std::string ExtractFileName(const std::string& fullPath);
|
||||
private:
|
||||
/**
|
||||
* @brief model3.jsonからモデルを生成する。<br>
|
||||
@@ -266,6 +286,5 @@ private:
|
||||
Live2D::Cubism::Framework::csmFloat32 alpha = 0.8f; // 滤波系数,范围在0到1之间,值越小,平滑效果越强
|
||||
Live2D::Cubism::Framework::csmFloat32 filteredValue = 0.0f; // 滤波后的值
|
||||
|
||||
|
||||
Csm::Rendering::CubismOffscreenSurface_OpenGLES2 _renderBuffer; ///< フレームバッファ以外の描画先
|
||||
};
|
||||
|
||||
+1
-1
@@ -38,7 +38,7 @@ namespace LAppDefine {
|
||||
// const csmChar* PowerImageName = "close.png";
|
||||
|
||||
// モデル定義------------------------------------------
|
||||
// 外部定義ファイル(json)と合わせる
|
||||
// 外部定義ファイル(json)と合わせる [要注意:部分模型可能缺失下面的某个字段或者全部缺失]
|
||||
const csmChar* MotionGroupIdle = "Idle"; // アイドリング
|
||||
const csmChar* MotionGroupTapBody = "TapBody"; // 体をタップしたとき
|
||||
|
||||
|
||||
@@ -72,6 +72,9 @@ LAppLive2DManager::LAppLive2DManager()
|
||||
// Resources/Haru/ Haru.model3.json
|
||||
LoadModelFromPath("Resources/Live2DModels/KITU17/", "KITU17.model3.json"); // 默认加载的模型
|
||||
//ChangeScene(_sceneIndex);
|
||||
if (DebugLogEnable) {
|
||||
_models[0]->DumpMotionMap();
|
||||
}
|
||||
}
|
||||
|
||||
LAppLive2DManager::~LAppLive2DManager()
|
||||
@@ -217,11 +220,10 @@ void LAppLive2DManager::OnTap(csmFloat32 x, csmFloat32 y)
|
||||
|
||||
void LAppLive2DManager::OnUpdate() const
|
||||
{
|
||||
int width, height;
|
||||
//glfwGetWindowSize(LAppDelegate::GetInstance()->GetWindow(), &width, &height);
|
||||
|
||||
width = LAppDelegate::GetInstance()->GetWindow()->width();
|
||||
height = LAppDelegate::GetInstance()->GetWindow()->height();
|
||||
int width = LAppDelegate::GetInstance()->GetWindow()->width();
|
||||
int height = LAppDelegate::GetInstance()->GetWindow()->height();
|
||||
|
||||
csmUint32 modelCount = _models.GetSize();
|
||||
for (csmUint32 i = 0; i < modelCount; ++i)
|
||||
@@ -263,7 +265,6 @@ void LAppLive2DManager::OnUpdate() const
|
||||
}
|
||||
}
|
||||
#include <AppContext.h>
|
||||
|
||||
void LAppLive2DManager::ModelSizeChange(const int Sacle = 15)
|
||||
{
|
||||
// 加载完后根据模型大小来重新设置当前窗口大小
|
||||
@@ -346,6 +347,10 @@ void LAppLive2DManager::MountLoadedModel(LAppModel* model)
|
||||
// 加入新模型
|
||||
_models.PushBack(model);
|
||||
|
||||
if (DebugLogEnable) {
|
||||
_models[0]->DumpMotionMap(); // 打印模型动作列表
|
||||
}
|
||||
|
||||
// 加载完后根据模型大小来重新设置当前窗口大小
|
||||
const int width = static_cast<int>(_models[0]->GetModel()->GetCanvasWidthPixel() / 15.0);
|
||||
const int height = static_cast<int>(_models[0]->GetModel()->GetCanvasHeightPixel() / 15.0);
|
||||
|
||||
+98
-4
@@ -660,6 +660,102 @@ CubismMotionQueueEntryHandle LAppModel::StartRandomMotion(const csmChar* group,
|
||||
return StartMotion(group, no, priority, onFinishedMotionHandler);
|
||||
}
|
||||
|
||||
std::map<std::string, std::vector<LAppModel::MotionInfo>> LAppModel::GetMotionMap()
|
||||
{
|
||||
std::map<std::string, std::vector<MotionInfo>> motionMap;
|
||||
if (_modelSetting == nullptr)
|
||||
{
|
||||
return motionMap;
|
||||
}
|
||||
// 获取组总数
|
||||
const int groupCount = _modelSetting->GetMotionGroupCount();
|
||||
for (int i = 0; i < groupCount; i++)
|
||||
{
|
||||
// 获取组名 (从 const char* 转 std::string)
|
||||
const char* groupNameChar = _modelSetting->GetMotionGroupName(i);
|
||||
std::string groupName(groupNameChar);
|
||||
// 获取该组动作数
|
||||
const int motionCount = _modelSetting->GetMotionCount(groupNameChar);
|
||||
|
||||
std::vector<MotionInfo> motionList;
|
||||
for (int j = 0; j < motionCount; j++)
|
||||
{
|
||||
MotionInfo info;
|
||||
info.SequenceId = j;
|
||||
// 获取路径并处理
|
||||
const char* filePath = _modelSetting->GetMotionFileName(groupNameChar, j);
|
||||
if (filePath)
|
||||
{
|
||||
info.FileName = ExtractFileName(std::string(filePath));
|
||||
}
|
||||
motionList.push_back(info);
|
||||
}
|
||||
motionMap[groupName] = motionList;
|
||||
}
|
||||
return motionMap;
|
||||
}
|
||||
|
||||
void LAppModel::DumpMotionMap()
|
||||
{
|
||||
if (_modelSetting == nullptr)
|
||||
{
|
||||
LAppPal::PrintLogLn("[Live2D Debug] Cannot dump MotionMap: Model assets not loaded yet.");
|
||||
return;
|
||||
}
|
||||
// 获取映射表
|
||||
const std::map<std::string, std::vector<MotionInfo>> motionMap = GetMotionMap();
|
||||
|
||||
if (motionMap.empty())
|
||||
{
|
||||
// 模型动作栏目为空,大概率是模型本身没带动作
|
||||
printf("[Live2D Debug] MotionMap is empty. Make sure the model is loaded correctly.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
printf("\n================ [Live2D Motion Dump] =================\n");
|
||||
|
||||
// 遍历 Map (组)
|
||||
for (auto & it : motionMap)
|
||||
{
|
||||
const std::string& groupName = it.first;
|
||||
const std::vector<MotionInfo>& motions = it.second;
|
||||
|
||||
printf("Group: [%s] (%zu motions)\n", groupName.c_str(), motions.size());
|
||||
|
||||
// 遍历 Vector (组内动作)
|
||||
for (const auto& info : motions)
|
||||
{
|
||||
// 打印 序列号 和 处理后的文件名
|
||||
printf(" ├── ID: %d | Name: %s\n",
|
||||
info.SequenceId,
|
||||
info.FileName.c_str());
|
||||
}
|
||||
printf(" └── (End of %s)\n", groupName.c_str());
|
||||
}
|
||||
printf("=======================================================\n\n");
|
||||
}
|
||||
|
||||
// 辅助函数:处理 csmString 路径截取
|
||||
std::string LAppModel::ExtractFileName(const std::string& fullPath)
|
||||
{
|
||||
// 提取带后缀的文件名 (例如从 "motions/special_03.motion3.json" 变为 "special_03.motion3.json")
|
||||
const size_t lastSlash = fullPath.find_last_of("/\\");
|
||||
std::string fileName = (lastSlash == std::string::npos) ? fullPath : fullPath.substr(lastSlash + 1);
|
||||
// 循环去掉后缀,直到名字中不再包含 ".json" 或 ".motion3"
|
||||
// Live2D 动作文件通常以 .motion3.json 结尾
|
||||
const std::string extensions[] = { ".json", ".motion3" };
|
||||
|
||||
for (const std::string& ext : extensions)
|
||||
{
|
||||
const size_t pos = fileName.find(ext);
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
fileName = fileName.substr(0, pos);
|
||||
}
|
||||
}
|
||||
return fileName;
|
||||
}
|
||||
|
||||
|
||||
/** 讲一下两种动画的不同
|
||||
* MotionGroupIdle:
|
||||
@@ -678,13 +774,11 @@ CubismMotionQueueEntryHandle LAppModel::StartRandomMotion(const csmChar* group,
|
||||
* 下面的两个函数分别就是获取这两种动作的数量的,不同的动作对应着一个序号,播放的序号不可以超过下面函数返回的最大值
|
||||
* 要注意的是部分模型可能没有动画
|
||||
*/
|
||||
int LAppModel::getIdleMotionCount()
|
||||
{
|
||||
int LAppModel::getIdleMotionCount() const {
|
||||
return _modelSetting->GetMotionCount(MotionGroupIdle);
|
||||
}
|
||||
|
||||
int LAppModel::getTapBodyMotionCount()
|
||||
{
|
||||
int LAppModel::getTapBodyMotionCount() const {
|
||||
return _modelSetting->GetMotionCount(MotionGroupTapBody);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user