diff --git a/lib/features/analysis/analysis_provider.dart b/lib/features/analysis/analysis_provider.dart index 156a5dbb..b6dbfb0a 100644 --- a/lib/features/analysis/analysis_provider.dart +++ b/lib/features/analysis/analysis_provider.dart @@ -50,6 +50,9 @@ class AnalysisProvider extends ChangeNotifier { String? _imagePath; TargetType? _targetType; + // AJOUT PROTECTION DU PLOTTING : Stockage permanent de la rotation du Crop + double _cropRotation = 0.0; + // Target detection results double _targetCenterX = 0.5; double _targetCenterY = 0.5; @@ -82,6 +85,7 @@ class AnalysisProvider extends ChangeNotifier { String? get errorMessage => _errorMessage; String? get imagePath => _imagePath; TargetType? get targetType => _targetType; + double get cropRotation => _cropRotation; // Getter pour le Plotting double get targetCenterX => _targetCenterX; double get targetCenterY => _targetCenterY; double get targetRadius => _targetRadius; @@ -112,6 +116,12 @@ class AnalysisProvider extends ChangeNotifier { ? _correctedImagePath : _imagePath; + /// Modifie et mémorise la rotation de l'image pour le Plotting + void setCropRotation(double rotation) { + _cropRotation = rotation; + notifyListeners(); + } + /// Analyze an image /// /// [autoAnalyze] determines if we should run automatic detection immediately. @@ -778,6 +788,7 @@ class AnalysisProvider extends ChangeNotifier { _errorMessage = null; _imagePath = null; _targetType = null; + _cropRotation = 0.0; // Reset de la rotation _targetCenterX = 0.5; _targetCenterY = 0.5; _targetRadius = 0.4; diff --git a/lib/features/analysis/analysis_screen.dart b/lib/features/analysis/analysis_screen.dart index bb463aac..9df82f02 100644 --- a/lib/features/analysis/analysis_screen.dart +++ b/lib/features/analysis/analysis_screen.dart @@ -23,11 +23,8 @@ import '../crop/crop_screen.dart'; import '../capture/capture_screen.dart'; import 'widgets/target_overlay.dart'; import 'widgets/target_calibration.dart'; -import 'widgets/target_overlay.dart'; import 'widgets/score_card.dart'; import 'widgets/grouping_stats.dart'; -import '../capture/capture_screen.dart'; // Si ton écran principal s'appelle comme ça -import '../crop/crop_screen.dart'; class AnalysisScreen extends StatelessWidget { final String imagePath; @@ -57,12 +54,20 @@ class AnalysisScreen extends StatelessWidget { : null; return ChangeNotifierProvider( - create: (context) => AnalysisProvider( - detectionService: context.read(), - scoreCalculatorService: context.read(), - groupingAnalyzerService: context.read(), - sessionRepository: context.read(), - )..analyzeImage(imagePath, targetType, autoAnalyze: false, manualCenter: manualCenterOffset), + create: (context) { + final p = AnalysisProvider( + detectionService: context.read(), + scoreCalculatorService: context.read(), + groupingAnalyzerService: context.read(), + sessionRepository: context.read(), + ); + // Sauvegarde de l'angle de rotation d'origine directement dans l'état global + if (cropRotation != null) { + p.setCropRotation(cropRotation!); + } + p.analyzeImage(imagePath, targetType, autoAnalyze: false, manualCenter: manualCenterOffset); + return p; + }, child: _AnalysisScreenContent( cropScale: cropScale, cropOffset: cropOffset, @@ -207,7 +212,7 @@ class _AnalysisScreenContentState extends State<_AnalysisScreenContent> { ), ), - // SECTION CORRIGÉE : Utilise maintenant widget.cropRotation sans aucune erreur ! + // SECTION CORRIGÉE : Utilise maintenant la réactivité du provider globale AspectRatio( aspectRatio: provider.imageAspectRatio, child: _isCalibrating @@ -217,19 +222,15 @@ class _AnalysisScreenContentState extends State<_AnalysisScreenContent> { ClipRect( child: Builder( builder: (context) { - final double rotationAngle = widget.cropRotation ?? 0.0; - return Transform( transform: Matrix4.identity() - ..translate(widget.cropOffset?.dx ?? 0.0, widget.cropOffset?.dy ?? 0.0) - ..scale(1.0, 1.0), // Zoom ignoré au plotting pour rester en vue globale + ..setTranslationRaw(widget.cropOffset?.dx ?? 0.0, widget.cropOffset?.dy ?? 0.0, 0.0) + ..scale(1.0, 1.0) // Zoom ignoré au plotting pour rester en vue globale + ..rotateZ((provider.cropRotation) * (math.pi / 180)), // FIX : Utilisation du provider dynamique alignment: Alignment.center, - child: Transform.rotate( - angle: rotationAngle * (math.pi / 180), - child: Image.file( - File(provider.imagePath!), - fit: BoxFit.contain, - ), + child: Image.file( + File(provider.imagePath!), + fit: BoxFit.contain, ), ); } @@ -486,10 +487,18 @@ class _AnalysisScreenContentState extends State<_AnalysisScreenContent> { }, child: Stack( children: [ - Image.file( - File(provider.imagePath!), - key: _imageKey, - fit: BoxFit.fill, + // FIX CRITIQUE PLOTTING : L'image de fond doit appliquer exactement le même angle de rotation qu'en calibration ! + Transform( + transform: Matrix4.identity() + ..setTranslationRaw(widget.cropOffset?.dx ?? 0.0, widget.cropOffset?.dy ?? 0.0, 0.0) + ..scale(1.0, 1.0) + ..rotateZ((provider.cropRotation) * (math.pi / 180)), + alignment: Alignment.center, + child: Image.file( + File(provider.imagePath!), + key: _imageKey, + fit: BoxFit.contain, // Remplace BoxFit.fill pour s'aligner sur la Calibration + ), ), TargetOverlay( targetCenterX: provider.targetCenterX, @@ -568,6 +577,7 @@ class _AnalysisScreenContentState extends State<_AnalysisScreenContent> { ), ); } + void _showSaveSessionDialog(BuildContext context, AnalysisProvider provider) { showDialog( context: context, @@ -645,7 +655,7 @@ class _AnalysisScreenContentState extends State<_AnalysisScreenContent> { weaponName: sessionProvider.currentWeapon, weaponId: sessionProvider.currentWeaponId, distance: sessionProvider.distance, - date: sessionProvider.sessionDate, // <-- CORRECTION : Prise en compte de la date ici aussi ! + date: sessionProvider.sessionDate, ); if (context.mounted) { @@ -667,4 +677,4 @@ class _AnalysisScreenContentState extends State<_AnalysisScreenContent> { ), ); } - } \ No newline at end of file +} \ No newline at end of file