Files
cup_edit/examples/flutter/animations/lib/utils/model_manager.dart
T
jingyun 1c07d576d3 init
2025-08-22 15:14:09 +08:00

205 lines
5.7 KiB
Dart

import 'dart:io';
import 'package:flutter/services.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:path/path.dart' as p;
import 'package:path_provider/path_provider.dart';
class ModelManager {
/// 当前应用版本(用于初始化检查)
static String? _currentVersion;
/// 获取当前应用版本
static Future<String> _getCurrentVersion() async {
if (_currentVersion == null) {
final packageInfo = await PackageInfo.fromPlatform();
_currentVersion = '${packageInfo.version}+${packageInfo.buildNumber}';
}
return _currentVersion!;
}
/// 检查3D模型资源是否已完成初始化(基于版本号)
static Future<bool> isInitialized() async {
final supportDir = await getApplicationSupportDirectory();
final currentVersion = await _getCurrentVersion();
final initMarker = File(
p.join(supportDir.path, '3d_models', '.initialized_$currentVersion'),
);
return await initMarker.exists();
}
/// 标记3D模型资源初始化完成
static Future<void> markInitialized() async {
final supportDir = await getApplicationSupportDirectory();
final currentVersion = await _getCurrentVersion();
final modelsDir = Directory(p.join(supportDir.path, '3d_models'));
if (!await modelsDir.exists()) {
await modelsDir.create(recursive: true);
}
final initMarker = File(
p.join(modelsDir.path, '.initialized_$currentVersion'),
);
await initMarker.writeAsString('${DateTime.now().toIso8601String()}\n');
}
/// 从assets目录提取文件到指定路径
static Future<void> _extractAsset(String assetPath, String localPath) async {
final localFile = File(localPath);
final localDir = Directory(p.dirname(localPath));
// 确保目录存在
if (!await localDir.exists()) {
await localDir.create(recursive: true);
}
try {
// 从assets中读取数据
final ByteData data = await rootBundle.load(assetPath);
final List<int> bytes = data.buffer.asUint8List();
// 写入本地文件
await localFile.writeAsBytes(bytes);
print('成功提取3D模型文件: $assetPath -> $localPath');
} catch (e) {
print('提取3D模型资源文件失败 $assetPath: $e');
rethrow;
}
}
/// 初始化3D模型资源
static Future<void> initializeAppResources() async {
final currentVersion = await _getCurrentVersion();
if (await isInitialized()) {
print('3D模型资源已初始化,当前版本: $currentVersion');
return;
}
try {
// 迁移模型文件
await _migrateModels();
// 标记初始化完成
await markInitialized();
print('3D模型资源初始化完成');
} catch (e) {
print('3D模型资源初始化失败: $e');
rethrow;
}
}
/// 迁移3D模型文件
/// 迁移3D模型文件
static Future<void> _migrateModels() async {
print('开始迁移3D模型文件...');
final supportDir = await getApplicationSupportDirectory();
final modelsDir = Directory(p.join(supportDir.path, 'models'));
// 创建3D模型目录
if (!await modelsDir.exists()) {
await modelsDir.create(recursive: true);
}
// 创建cup子目录
final cupDir = Directory(p.join(modelsDir.path, 'cup'));
if (!await cupDir.exists()) {
await cupDir.create(recursive: true);
}
// 3D模型文件列表 - 修正路径
final modelFiles = [
'cup/model.gltf',
'cup/model.bin',
'cup/texture.jpg',
];
// 迁移所有3D模型文件
for (final modelFile in modelFiles) {
try {
// 确保源文件路径正确
final assetPath = 'assets/$modelFile';
// 检查资源是否存在
try {
await rootBundle.load(assetPath);
} catch (e) {
print('资源文件不存在: $assetPath');
continue;
}
await _extractAsset(
assetPath,
p.join(modelsDir.path, modelFile),
);
} catch (e) {
print('迁移3D模型文件失败 $modelFile: $e');
// 继续迁移其他模型文件
}
}
print('3D模型文件迁移完成');
}
/// 获取3D模型文件目录路径
static Future<String> getModelsPath() async {
final supportDir = await getApplicationSupportDirectory();
return p.join(supportDir.path, 'models/cup/');
}
/// 获取特定3D模型文件的路径
static Future<String> getModelFilePath(String relativePath) async {
final modelsPath = await getModelsPath();
final filePath = p.join(modelsPath, relativePath);
final file = File(filePath);
if (!await file.exists()) {
throw FileSystemException(
'3D模型文件不存在: $filePath\n请确保应用程序已正确初始化3D模型资源',
filePath,
);
}
return filePath;
}
/// 获取GLTF模型文件路径
static Future<String> getGltfModelPath() async {
return getModelFilePath('cup/model.gltf');
}
/// 获取BIN模型文件路径
static Future<String> getBinModelPath() async {
return getModelFilePath('cup/model.bin');
}
/// 获取纹理文件路径
static Future<String> getTexturePath() async {
return getModelFilePath('cup/texture.jpg');
}
/// 更新纹理文件
static Future<void> updateTexture(File newTextureFile) async {
try {
final texturePath = await getTexturePath();
final textureFile = File(texturePath);
// 删除旧纹理文件
if (await textureFile.exists()) {
await textureFile.delete();
}
// 复制新纹理文件
await newTextureFile.copy(texturePath);
print('纹理文件更新成功: $texturePath');
} catch (e) {
print('更新纹理文件失败: $e');
rethrow;
}
}
}