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

205 lines
5.7 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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;
}
}
}