205 lines
5.7 KiB
Dart
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;
|
||
}
|
||
}
|
||
}
|