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;
|
|
}
|
|
}
|
|
}
|