diff --git a/assets/targets/Target10.jpg b/assets/targets/Target10.jpg new file mode 100644 index 0000000..1f680b4 Binary files /dev/null and b/assets/targets/Target10.jpg differ diff --git a/assets/targets/Target11.jpg b/assets/targets/Target11.jpg index 953cd7f..bf545e8 100644 Binary files a/assets/targets/Target11.jpg and b/assets/targets/Target11.jpg differ diff --git a/assets/targets/Target12.jpg b/assets/targets/Target12.jpg new file mode 100644 index 0000000..19e91ca Binary files /dev/null and b/assets/targets/Target12.jpg differ diff --git a/assets/targets/Target13.jpg b/assets/targets/Target13.jpg new file mode 100644 index 0000000..1c228ba Binary files /dev/null and b/assets/targets/Target13.jpg differ diff --git a/assets/targets/Target14.jpg b/assets/targets/Target14.jpg index 4249d0c..71710b6 100644 Binary files a/assets/targets/Target14.jpg and b/assets/targets/Target14.jpg differ diff --git a/assets/targets/Target15.jpg b/assets/targets/Target15.jpg index 4b1b024..c4ae48f 100644 Binary files a/assets/targets/Target15.jpg and b/assets/targets/Target15.jpg differ diff --git a/assets/targets/Target16.jpg b/assets/targets/Target16.jpg new file mode 100644 index 0000000..3d1d201 Binary files /dev/null and b/assets/targets/Target16.jpg differ diff --git a/assets/targets/Target17.jpg b/assets/targets/Target17.jpg new file mode 100644 index 0000000..7498e0d Binary files /dev/null and b/assets/targets/Target17.jpg differ diff --git a/assets/targets/Target18.jpg b/assets/targets/Target18.jpg new file mode 100644 index 0000000..8f979ab Binary files /dev/null and b/assets/targets/Target18.jpg differ diff --git a/assets/targets/Target19.jpg b/assets/targets/Target19.jpg new file mode 100644 index 0000000..66471aa Binary files /dev/null and b/assets/targets/Target19.jpg differ diff --git a/assets/targets/Target20.jpg b/assets/targets/Target20.jpg new file mode 100644 index 0000000..b17a5d8 Binary files /dev/null and b/assets/targets/Target20.jpg differ diff --git a/assets/targets/Target21.jpg b/assets/targets/Target21.jpg new file mode 100644 index 0000000..b16af08 Binary files /dev/null and b/assets/targets/Target21.jpg differ diff --git a/assets/targets/Target22.jpg b/assets/targets/Target22.jpg new file mode 100644 index 0000000..20a528b Binary files /dev/null and b/assets/targets/Target22.jpg differ diff --git a/assets/targets/Target23.jpg b/assets/targets/Target23.jpg new file mode 100644 index 0000000..f54669e Binary files /dev/null and b/assets/targets/Target23.jpg differ diff --git a/assets/targets/Target24.jpg b/assets/targets/Target24.jpg new file mode 100644 index 0000000..d36f3dc Binary files /dev/null and b/assets/targets/Target24.jpg differ diff --git a/assets/targets/Target3.jpg b/assets/targets/Target3.jpg index 0389def..82aff72 100644 Binary files a/assets/targets/Target3.jpg and b/assets/targets/Target3.jpg differ diff --git a/assets/targets/Target5.jpg b/assets/targets/Target5.jpg index 9cfa545..fe9a919 100644 Binary files a/assets/targets/Target5.jpg and b/assets/targets/Target5.jpg differ diff --git a/assets/targets/Target6.jpg b/assets/targets/Target6.jpg index 398c947..4ecf3a1 100644 Binary files a/assets/targets/Target6.jpg and b/assets/targets/Target6.jpg differ diff --git a/assets/targets/Target7.jpg b/assets/targets/Target7.jpg index ff3f7b4..1c911c7 100644 Binary files a/assets/targets/Target7.jpg and b/assets/targets/Target7.jpg differ diff --git a/assets/targets/Target8.jpg b/assets/targets/Target8.jpg new file mode 100644 index 0000000..820abce Binary files /dev/null and b/assets/targets/Target8.jpg differ diff --git a/assets/targets/Target9.jpg b/assets/targets/Target9.jpg new file mode 100644 index 0000000..59d7a3c Binary files /dev/null and b/assets/targets/Target9.jpg differ diff --git a/lib/screens/book_screen.dart b/lib/screens/book_screen.dart index 7b00b20..d48f69c 100644 --- a/lib/screens/book_screen.dart +++ b/lib/screens/book_screen.dart @@ -6,6 +6,7 @@ import 'package:path_provider/path_provider.dart'; // For getApplicationDocument import 'target_view.dart'; // Import the TargetViewScreen import 'package:shared_preferences/shared_preferences.dart'; import '../utils/translations.dart'; +import '../utils/target_colors.dart'; class BookScreen extends StatefulWidget { const BookScreen({super.key}); @@ -25,13 +26,17 @@ class _BookScreenState extends State with WidgetsBindingObserver { String _sortMode = 'date'; // or 'score' String _selectedLanguage = 'English'; String? _expandedFolder; // Track which folder is expanded + late Color _backgroundColor; @override void initState() { super.initState(); WidgetsBinding.instance.addObserver(this); // Register to listen for lifecycle events + // Initialize with default target background color + _backgroundColor = TargetColors.getBackgroundColor('assets/target.png'); _loadBulletColor(); _loadLanguage(); + _loadSelectedTargetColor(); _loadTargetDataFiles(); // Initial load when the screen is first created } @@ -46,6 +51,14 @@ class _BookScreenState extends State with WidgetsBindingObserver { }); } + Future _loadSelectedTargetColor() async { + final prefs = await SharedPreferences.getInstance(); + final selectedTarget = prefs.getString('selectedTarget') ?? 'assets/target.png'; + setState(() { + _backgroundColor = TargetColors.getBackgroundColor(selectedTarget); + }); + } + @override void dispose() { WidgetsBinding.instance.removeObserver(this); // Unregister from lifecycle events when disposed @@ -895,6 +908,7 @@ Widget _buildTargetsList(String folderName) { @override Widget build(BuildContext context) { return Scaffold( + backgroundColor: _backgroundColor, body: Column( children: [ // šŸ”½ Filter dropdown at the top (styled like tab bar) diff --git a/lib/screens/calendar_screen.dart b/lib/screens/calendar_screen.dart index d8e7062..ce2bdd1 100644 --- a/lib/screens/calendar_screen.dart +++ b/lib/screens/calendar_screen.dart @@ -6,6 +6,7 @@ import 'package:shared_preferences/shared_preferences.dart'; import 'package:url_launcher/url_launcher.dart'; import '../services/google_calendar_service.dart'; import '../utils/translations.dart'; +import '../utils/target_colors.dart'; class Contact { final String firstName; @@ -45,6 +46,7 @@ class _CalendarScreenState extends State { String _selectedLanguage = 'English'; bool _showContacts = false; bool _showDebugPreview = false; + late Color _backgroundColor; // Members contact list final List _contacts = [ @@ -69,8 +71,11 @@ class _CalendarScreenState extends State { void initState() { super.initState(); initializeDateFormatting('sl_SI', null); // Initialize Slovenian locale + // Initialize with default target background color + _backgroundColor = TargetColors.getBackgroundColor('assets/target.png'); _loadBulletColor(); _loadLanguage(); + _loadSelectedTargetColor(); _loadEvents(); } @@ -85,6 +90,14 @@ class _CalendarScreenState extends State { }); } + Future _loadSelectedTargetColor() async { + final prefs = await SharedPreferences.getInstance(); + final selectedTarget = prefs.getString('selectedTarget') ?? 'assets/target.png'; + setState(() { + _backgroundColor = TargetColors.getBackgroundColor(selectedTarget); + }); + } + void _toggleDebugPreview() { setState(() { _showDebugPreview = !_showDebugPreview; @@ -490,12 +503,12 @@ class _CalendarScreenState extends State { Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - // Grey header bar with white text (matching book screen style) + // Header bar with bullet color and transparency Container( width: double.infinity, padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), decoration: BoxDecoration( - color: Colors.grey[900], + color: accentColor.withValues(alpha: 0.6), borderRadius: const BorderRadius.only( topLeft: Radius.circular(12), topRight: Radius.circular(12), @@ -733,7 +746,7 @@ class _CalendarScreenState extends State { } return Scaffold( - backgroundColor: Colors.white, + backgroundColor: _backgroundColor, body: Column( children: [ // Tab buttons diff --git a/lib/screens/camera_screen.dart b/lib/screens/camera_screen.dart index 04e9162..8ae900a 100644 --- a/lib/screens/camera_screen.dart +++ b/lib/screens/camera_screen.dart @@ -6,6 +6,7 @@ import 'package:shared_preferences/shared_preferences.dart'; import 'yolo_detector.dart'; import 'preview_screen.dart'; import '../utils/translations.dart'; +import '../utils/target_colors.dart'; class CameraScreen extends StatefulWidget { const CameraScreen({super.key}); @@ -23,6 +24,7 @@ class _CameraScreenState extends State { // The variable to hold the number of bullets entered by the user (default set to 5) int _numberOfBullets = 5; String _selectedLanguage = 'English'; + late Color _backgroundColor; // Brightness and contrast controls double _brightness = 0.0; // -1.0 to 1.0 @@ -31,10 +33,13 @@ class _CameraScreenState extends State { @override void initState() { super.initState(); + // Initialize with default target background color + _backgroundColor = TargetColors.getBackgroundColor('assets/target.png'); _loadBulletCount(); _initCamera(); _loadBulletColor(); // šŸ‘ˆ _loadLanguage(); + _loadSelectedTargetColor(); _loadBrightnessContrast(); YOLODetector.create().then((detector) => _yoloDetector = detector); } @@ -64,6 +69,14 @@ class _CameraScreenState extends State { }); } + Future _loadSelectedTargetColor() async { + final prefs = await SharedPreferences.getInstance(); + final selectedTarget = prefs.getString('selectedTarget') ?? 'assets/target.png'; + setState(() { + _backgroundColor = TargetColors.getBackgroundColor(selectedTarget); + }); + } + Future _loadBulletColor() async { final prefs = await SharedPreferences.getInstance(); final selected = prefs.getString('bulletColor') ?? 'Blue'; @@ -445,6 +458,7 @@ Color _getColorFromName(String colorName) { } return Scaffold( + backgroundColor: _backgroundColor, extendBody: true, appBar: AppBar( backgroundColor: Colors.grey[900], diff --git a/lib/screens/home_screen.dart b/lib/screens/home_screen.dart index 7c2bb1b..d990926 100644 --- a/lib/screens/home_screen.dart +++ b/lib/screens/home_screen.dart @@ -8,6 +8,7 @@ import '../widgets/bottom_nav.dart'; import 'camera_screen.dart'; import 'package:shared_preferences/shared_preferences.dart'; import '../utils/translations.dart'; +import '../utils/target_colors.dart'; class HomeScreen extends StatefulWidget { @@ -20,6 +21,8 @@ class HomeScreen extends StatefulWidget { class _HomeScreenState extends State { int _selectedIndex = 1; // Default to Shooting Screen String _selectedLanguage = 'English'; + String _selectedTarget = 'assets/target.png'; + late Color _backgroundColor; static final List _pages = [ BookScreen(), @@ -40,7 +43,10 @@ class _HomeScreenState extends State { @override void initState() { super.initState(); + // Initialize with default target background color + _backgroundColor = TargetColors.getBackgroundColor('assets/target.png'); _loadLanguage(); + _loadSelectedTarget(); } String _t(String key) { @@ -54,6 +60,15 @@ class _HomeScreenState extends State { }); } + Future _loadSelectedTarget() async { + final prefs = await SharedPreferences.getInstance(); + final selectedTarget = prefs.getString('selectedTarget') ?? 'assets/target.png'; + setState(() { + _selectedTarget = selectedTarget; + _backgroundColor = TargetColors.getBackgroundColor(selectedTarget); + }); + } + void _onItemTapped(int index) { if (index == 2) { _openCameraScan(); @@ -114,6 +129,7 @@ class _HomeScreenState extends State { ), ], ), + backgroundColor: _backgroundColor, body: _pages[_selectedIndex], bottomNavigationBar: BottomNavBar( selectedIndex: _selectedIndex, diff --git a/lib/screens/preview_screen.dart b/lib/screens/preview_screen.dart index 0d6079e..0528c24 100644 --- a/lib/screens/preview_screen.dart +++ b/lib/screens/preview_screen.dart @@ -25,7 +25,7 @@ enum PreviewMode { cameraWithDetections, mappedTarget } class _PreviewScreenState extends State { bool _isLoading = true; - PreviewMode _mode = PreviewMode.mappedTarget; + PreviewMode _mode = PreviewMode.cameraWithDetections; List _mappedBullets = []; late List _realImageDetections; @@ -134,20 +134,62 @@ class _PreviewScreenState extends State { return const Color(0xFF02050A); // Very dark blue/black case 'assets/targets/Target6.jpg': - return const Color(0xFF000000); // Black + return const Color(0xFFF3E7D1); // Light beige case 'assets/targets/Target7.jpg': return const Color(0xFFFFD454); // Bright yellow - case 'assets/targets/Target11.jpg': + case 'assets/targets/Target8.jpg': return const Color(0xFF1E5E81); // Dark teal blue - case 'assets/targets/Target14.jpg': + case 'assets/targets/Target9.jpg': return const Color(0xFFFEFEFC); // Off-white - case 'assets/targets/Target15.jpg': + case 'assets/targets/Target10.jpg': return const Color(0xFF98926E); // Olive green + case 'assets/targets/Target11.jpg': + return const Color(0xFF13132B); // Dark blue + + case 'assets/targets/Target12.jpg': + return const Color(0xFFF5F4EF); // Off-white + + case 'assets/targets/Target13.jpg': + return const Color(0xFF174AA5); // Blue + + case 'assets/targets/Target14.jpg': + return const Color(0xFFFEE05E); // Light yellow + + case 'assets/targets/Target15.jpg': + return const Color(0xFFFFFFFF); // White + + case 'assets/targets/Target16.jpg': + return const Color(0xFF000000); // Black + + case 'assets/targets/Target17.jpg': + return const Color(0xFF13132B); // Dark blue + + case 'assets/targets/Target18.jpg': + return const Color(0xFF050608); // Very dark gray + + case 'assets/targets/Target19.jpg': + return const Color(0xFFC32534); // Dark red + + case 'assets/targets/Target20.jpg': + return const Color(0xFFFCF3EE); // Light beige + + case 'assets/targets/Target21.jpg': + return const Color(0xFFDA6868); // Muted red + + case 'assets/targets/Target22.jpg': + return const Color(0xFFFDFAF3); // Off-white + + case 'assets/targets/Target23.jpg': + return const Color(0xFFFFFFFD); // White + + case 'assets/targets/Target24.jpg': + return const Color(0xFFFFC4C6); // Light pink + default: return Colors.grey[900]!; // Fallback to dark gray } diff --git a/lib/screens/settings_screen.dart b/lib/screens/settings_screen.dart index b9791d1..299dac1 100644 --- a/lib/screens/settings_screen.dart +++ b/lib/screens/settings_screen.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:shared_preferences/shared_preferences.dart'; import '../utils/translations.dart'; +import '../utils/target_colors.dart'; class SettingsScreen extends StatefulWidget { const SettingsScreen({super.key}); @@ -10,6 +11,7 @@ class SettingsScreen extends StatefulWidget { } class _SettingsScreenState extends State { + Color _backgroundColor = Colors.grey[900]!; List _cameraIPs = List.generate(6, (index) => 'Not Set'); final List _defaultIPs = [ @@ -57,9 +59,23 @@ class _SettingsScreenState extends State { 'assets/targets/Target5.jpg', 'assets/targets/Target6.jpg', 'assets/targets/Target7.jpg', + 'assets/targets/Target8.jpg', + 'assets/targets/Target9.jpg', + 'assets/targets/Target10.jpg', 'assets/targets/Target11.jpg', + 'assets/targets/Target12.jpg', + 'assets/targets/Target13.jpg', 'assets/targets/Target14.jpg', 'assets/targets/Target15.jpg', + 'assets/targets/Target16.jpg', + 'assets/targets/Target17.jpg', + 'assets/targets/Target18.jpg', + 'assets/targets/Target19.jpg', + 'assets/targets/Target20.jpg', + 'assets/targets/Target21.jpg', + 'assets/targets/Target22.jpg', + 'assets/targets/Target23.jpg', + 'assets/targets/Target24.jpg', ]; @override @@ -155,22 +171,27 @@ Future _loadSelectedTarget() async { setState(() { _selectedTarget = savedTarget; + _backgroundColor = TargetColors.getBackgroundColor(savedTarget); }); } Future _saveSelectedTarget(String target) async { final prefs = await SharedPreferences.getInstance(); await prefs.setString('selectedTarget', target); - setState(() => _selectedTarget = target); + setState(() { + _selectedTarget = target; + _backgroundColor = TargetColors.getBackgroundColor(target); + }); } String _getTargetDisplayName(String targetPath) { if (targetPath == 'assets/target.png') { - return 'Default Target'; + return _t('Default Target'); } - return targetPath + final targetName = targetPath .replaceAll('assets/targets/', '') .replaceAll('.jpg', ''); + return _t(targetName); } Future _loadCameraIPs() async { @@ -345,7 +366,7 @@ String _getTargetDisplayName(String targetPath) { @override Widget build(BuildContext context) { return Scaffold( - + backgroundColor: _backgroundColor, body: SingleChildScrollView( padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16), child: Column( @@ -952,6 +973,12 @@ void _showTargetPopup() { padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14), decoration: BoxDecoration( color: Colors.grey[300], + borderRadius: index == 5 + ? const BorderRadius.only( + bottomLeft: Radius.circular(12), + bottomRight: Radius.circular(12), + ) + : null, border: index < 5 ? Border( bottom: BorderSide( @@ -984,15 +1011,6 @@ void _showTargetPopup() { ], ), ), - if (index == 5) - Container( - decoration: BoxDecoration( - borderRadius: const BorderRadius.only( - bottomLeft: Radius.circular(12), - bottomRight: Radius.circular(12), - ), - ), - ), ], ), ); diff --git a/lib/screens/spectator_screen.dart b/lib/screens/spectator_screen.dart index 1a314e8..a3f2705 100644 --- a/lib/screens/spectator_screen.dart +++ b/lib/screens/spectator_screen.dart @@ -251,7 +251,7 @@ class _SpectatorScreenState extends State { ), ) : ListView.builder( - padding: const EdgeInsets.fromLTRB(8, 8, 8, 24), + padding: const EdgeInsets.fromLTRB(4, 4, 4, 16), itemCount: visibleCameras.length, itemBuilder: (context, index) { final camera = visibleCameras[index]; @@ -262,16 +262,16 @@ class _SpectatorScreenState extends State { ? cameraIp : "http://$cameraIp"; - // 16:9 aspect ratio = width / height + // 4:3 aspect ratio = width / height (640x480 stream) return Container( - margin: const EdgeInsets.only(bottom: 8), + margin: const EdgeInsets.only(bottom: 4), decoration: BoxDecoration( color: Colors.black, borderRadius: BorderRadius.circular(8), border: Border.all(color: Colors.grey[800]!, width: 1), ), child: AspectRatio( - aspectRatio: 16 / 9, + aspectRatio: 4 / 3, child: ClipRRect( borderRadius: BorderRadius.circular(8), child: Stack( @@ -279,7 +279,7 @@ class _SpectatorScreenState extends State { Mjpeg( stream: streamUrl, isLive: true, - fit: BoxFit.contain, + fit: BoxFit.cover, error: (context, error, stackTrace) { return Container( color: Colors.grey[700], diff --git a/lib/screens/target_screen.dart b/lib/screens/target_screen.dart index 93b26a5..4ac744e 100644 --- a/lib/screens/target_screen.dart +++ b/lib/screens/target_screen.dart @@ -3,6 +3,7 @@ import 'package:shared_preferences/shared_preferences.dart'; import 'stream_screen.dart'; // Import the camera stream screen import 'spectator_screen.dart'; import '../utils/translations.dart'; +import '../utils/target_colors.dart'; class TargetScreen extends StatefulWidget { const TargetScreen({super.key}); @@ -15,11 +16,15 @@ class _TargetScreenState extends State { List _cameraButtonsEnabled = List.generate(6, (_) => false); // Initially, all buttons are disabled String _selectedLanguage = 'English'; + late Color _backgroundColor; @override void initState() { super.initState(); + // Initialize with default target background color + _backgroundColor = TargetColors.getBackgroundColor('assets/target.png'); _loadLanguage(); + _loadSelectedTargetColor(); _loadCameraData(); } @@ -34,6 +39,14 @@ class _TargetScreenState extends State { }); } + Future _loadSelectedTargetColor() async { + final prefs = await SharedPreferences.getInstance(); + final selectedTarget = prefs.getString('selectedTarget') ?? 'assets/target.png'; + setState(() { + _backgroundColor = TargetColors.getBackgroundColor(selectedTarget); + }); + } + /// Load the camera IPs from SharedPreferences and update button status Future _loadCameraData() async { final prefs = await SharedPreferences.getInstance(); @@ -67,6 +80,7 @@ class _TargetScreenState extends State { @override Widget build(BuildContext context) { return Scaffold( + backgroundColor: _backgroundColor, body: Padding( padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 32), child: Column( diff --git a/lib/screens/target_view.dart b/lib/screens/target_view.dart index f5e8db2..520f093 100644 --- a/lib/screens/target_view.dart +++ b/lib/screens/target_view.dart @@ -26,6 +26,7 @@ class TargetViewScreen extends StatefulWidget { class _TargetViewScreenState extends State { int _currentIndex = 0; List _bullets = []; + List _scaledBullets = []; // Bullets scaled to display target size int _totalScore = 0; Offset? _targetCenter; Uint8List? _targetImageBytes; @@ -35,7 +36,10 @@ class _TargetViewScreenState extends State { int? _pressedScoreGroup; late String _targetFilePath; late String targetAssetPath; + late String _selectedTargetPath; // For display final double bulletSize = 19; + double _scaleFactorX = 1.0; // Scale factor for X coordinate + double _scaleFactorY = 1.0; // Scale factor for Y coordinate Color _bulletColor = Colors.blue; // default/fallback bullet color String _selectedLanguage = 'English'; @@ -72,7 +76,10 @@ class _TargetViewScreenState extends State { Future _loadSelectedTarget() async { final prefs = await SharedPreferences.getInstance(); final selectedTarget = prefs.getString('selectedTarget') ?? 'assets/target.png'; - targetAssetPath = selectedTarget; + // Always use default target for bullet positioning + targetAssetPath = 'assets/target.png'; + // Store selected target for display + _selectedTargetPath = selectedTarget; _backgroundColor = _getBackgroundColorForTarget(selectedTarget); } @@ -81,37 +88,54 @@ class _TargetViewScreenState extends State { switch (targetPath) { case 'assets/target.png': return const Color(0xFFFFFFFF); // White - case 'assets/targets/Target1.jpg': return const Color(0xFFE8ECD5); // Light beige - case 'assets/targets/Target2.jpg': return const Color(0xFFC1DF87); // Light green - case 'assets/targets/Target3.jpg': return const Color(0xFFFEFEFE); // Off-white - case 'assets/targets/Target4.jpg': return const Color(0xFFD42931); // Red - case 'assets/targets/Target5.jpg': return const Color(0xFF02050A); // Very dark blue/black - case 'assets/targets/Target6.jpg': - return const Color(0xFF000000); // Black - + return const Color(0xFFF3E7D1); // Light beige case 'assets/targets/Target7.jpg': return const Color(0xFFFFD454); // Bright yellow - - case 'assets/targets/Target11.jpg': + case 'assets/targets/Target8.jpg': return const Color(0xFF1E5E81); // Dark teal blue - - case 'assets/targets/Target14.jpg': + case 'assets/targets/Target9.jpg': return const Color(0xFFFEFEFC); // Off-white - - case 'assets/targets/Target15.jpg': + case 'assets/targets/Target10.jpg': return const Color(0xFF98926E); // Olive green - + case 'assets/targets/Target11.jpg': + return const Color(0xFF13132B); // Dark blue + case 'assets/targets/Target12.jpg': + return const Color(0xFFF5F4EF); // Off-white + case 'assets/targets/Target13.jpg': + return const Color(0xFF174AA5); // Blue + case 'assets/targets/Target14.jpg': + return const Color(0xFFFEE05E); // Light yellow + case 'assets/targets/Target15.jpg': + return const Color(0xFFFFFFFF); // White + case 'assets/targets/Target16.jpg': + return const Color(0xFF000000); // Black + case 'assets/targets/Target17.jpg': + return const Color(0xFF13132B); // Dark blue + case 'assets/targets/Target18.jpg': + return const Color(0xFF050608); // Very dark gray + case 'assets/targets/Target19.jpg': + return const Color(0xFFC32534); // Dark red + case 'assets/targets/Target20.jpg': + return const Color(0xFFFCF3EE); // Light beige + case 'assets/targets/Target21.jpg': + return const Color(0xFFDA6868); // Muted red + case 'assets/targets/Target22.jpg': + return const Color(0xFFFDFAF3); // Off-white + case 'assets/targets/Target23.jpg': + return const Color(0xFFFFFFFD); // White + case 'assets/targets/Target24.jpg': + return const Color(0xFFFFC4C6); // Light pink default: return Colors.white; // Fallback to white } @@ -167,20 +191,33 @@ class _TargetViewScreenState extends State { Future _loadJsonAndImage() async { try { - final byteData = await rootBundle.load(targetAssetPath); - final bytes = byteData.buffer.asUint8List(); - _targetImageDecoded = img.decodeImage(bytes); + // Load default target for bullet positioning reference + final defaultByteData = await rootBundle.load(targetAssetPath); + final defaultBytes = defaultByteData.buffer.asUint8List(); + img.Image? defaultTargetDecoded = img.decodeImage(defaultBytes); + + if (defaultTargetDecoded == null) { + print("Failed to decode default target image."); + return; + } + + // Calculate target center from default target (for bullet positioning) + _targetCenter = Offset( + defaultTargetDecoded.width / 2, + defaultTargetDecoded.height / 2 - 1, + ); + + // Load selected target for display + final displayByteData = await rootBundle.load(_selectedTargetPath); + final displayBytes = displayByteData.buffer.asUint8List(); + _targetImageDecoded = img.decodeImage(displayBytes); if (_targetImageDecoded == null) { - print("Failed to decode image."); + print("Failed to decode display target image."); return; } _targetImageBytes = Uint8List.fromList(img.encodePng(_targetImageDecoded!)); - _targetCenter = Offset( - _targetImageDecoded!.width / 2, - _targetImageDecoded!.height / 2 - 1, - ); final currentFile = widget.jsonFiles[_currentIndex]; final jsonString = await currentFile.readAsString(); @@ -210,6 +247,18 @@ class _TargetViewScreenState extends State { _targetFilePath = currentFile.path; + // Calculate scale factors based on image dimensions + _scaleFactorX = _targetImageDecoded!.width / defaultTargetDecoded.width; + _scaleFactorY = _targetImageDecoded!.height / defaultTargetDecoded.height; + + // Scale bullets to match display target size + _scaledBullets = _bullets.map((bullet) { + return Offset( + bullet.dx * _scaleFactorX, + bullet.dy * _scaleFactorY, + ); + }).toList(); + _totalScore = _bullets .map((b) => _scoreForBullet(b, _targetCenter!)) .fold(0, (sum, score) => sum + score); @@ -386,12 +435,15 @@ class _TargetViewScreenState extends State { height: displayHeight, child: Image.memory(_targetImageBytes!, fit: BoxFit.fill), ), - ..._bullets.asMap().entries.map((entry) { + ..._scaledBullets.asMap().entries.map((entry) { final i = entry.key; - final bullet = entry.value; - final dx = bullet.dx * scaleX + offsetX; - final dy = bullet.dy * scaleY + offsetY; - final score = _scoreForBullet(bullet, _targetCenter ?? Offset.zero); + final scaledBullet = entry.value; + // Scaled bullets are already scaled to display target dimensions + final dx = scaledBullet.dx * scaleX + offsetX; + final dy = scaledBullet.dy * scaleY + offsetY; + // Score is calculated using original bullet position and default target center + final originalBullet = _bullets[i]; + final score = _scoreForBullet(originalBullet, _targetCenter ?? Offset.zero); final isHighlighted = widget.isCombinedView ? (_pressedScoreGroup == score) : (i == _highlightedBulletIndex); diff --git a/lib/utils/target_colors.dart b/lib/utils/target_colors.dart new file mode 100644 index 0000000..c2014bf --- /dev/null +++ b/lib/utils/target_colors.dart @@ -0,0 +1,35 @@ +import 'package:flutter/material.dart'; + +class TargetColors { + static const Map targetBackgroundColors = { + 'assets/target.png': Color(0xFFFFFFFF), // White + 'assets/targets/Target1.jpg': Color(0xFFE8ECD5), // Light beige + 'assets/targets/Target2.jpg': Color(0xFFC1DF87), // Light green + 'assets/targets/Target3.jpg': Color(0xFFFEFEFE), // Off-white + 'assets/targets/Target4.jpg': Color(0xFFD42931), // Red + 'assets/targets/Target5.jpg': Color(0xFF02050A), // Very dark blue/black + 'assets/targets/Target6.jpg': Color(0xFFF3E7D1), // Light beige + 'assets/targets/Target7.jpg': Color(0xFFFFD454), // Bright yellow + 'assets/targets/Target8.jpg': Color(0xFF1E5E81), // Dark teal blue + 'assets/targets/Target9.jpg': Color(0xFFFEFEFC), // Off-white + 'assets/targets/Target10.jpg': Color(0xFF98926E), // Olive green + 'assets/targets/Target11.jpg': Color(0xFF13132B), // Dark blue + 'assets/targets/Target12.jpg': Color(0xFFF5F4EF), // Off-white + 'assets/targets/Target13.jpg': Color(0xFF174AA5), // Blue + 'assets/targets/Target14.jpg': Color(0xFFFEE05E), // Light yellow + 'assets/targets/Target15.jpg': Color(0xFFFFFFFF), // White + 'assets/targets/Target16.jpg': Color(0xFF000000), // Black + 'assets/targets/Target17.jpg': Color(0xFF13132B), // Dark blue + 'assets/targets/Target18.jpg': Color(0xFF050608), // Very dark gray + 'assets/targets/Target19.jpg': Color(0xFFC32534), // Dark red + 'assets/targets/Target20.jpg': Color(0xFFFCF3EE), // Light beige + 'assets/targets/Target21.jpg': Color(0xFFDA6868), // Muted red + 'assets/targets/Target22.jpg': Color(0xFFFDFAF3), // Off-white + 'assets/targets/Target23.jpg': Color(0xFFFFFFFD), // White + 'assets/targets/Target24.jpg': Color(0xFFFFC4C6), // Light pink + }; + + static Color getBackgroundColor(String targetPath) { + return targetBackgroundColors[targetPath] ?? Colors.grey[900]!; + } +} diff --git a/lib/utils/translations.dart b/lib/utils/translations.dart index 1ed7351..f0f61fe 100644 --- a/lib/utils/translations.dart +++ b/lib/utils/translations.dart @@ -24,6 +24,112 @@ class AppTranslations { 'Slovenian': 'Izberi barvo zadetka', }, + // Target selection + 'Select Target': { + 'English': 'Select Target', + 'Slovenian': 'Izberi tarčo', + }, + 'Default Target': { + 'English': 'Default Target', + 'Slovenian': 'Privzeta tarča', + }, + 'Target1': { + 'English': 'Target 1', + 'Slovenian': 'Tarča 1', + }, + 'Target2': { + 'English': 'Target 2', + 'Slovenian': 'Tarča 2', + }, + 'Target3': { + 'English': 'Target 3', + 'Slovenian': 'Tarča 3', + }, + 'Target4': { + 'English': 'Target 4', + 'Slovenian': 'Tarča 4', + }, + 'Target5': { + 'English': 'Target 5', + 'Slovenian': 'Tarča 5', + }, + 'Target6': { + 'English': 'Target 6', + 'Slovenian': 'Tarča 6', + }, + 'Target7': { + 'English': 'Target 7', + 'Slovenian': 'Tarča 7', + }, + 'Target8': { + 'English': 'Target 8', + 'Slovenian': 'Tarča 8', + }, + 'Target9': { + 'English': 'Target 9', + 'Slovenian': 'Tarča 9', + }, + 'Target10': { + 'English': 'Target 10', + 'Slovenian': 'Tarča 10', + }, + 'Target11': { + 'English': 'Target 11', + 'Slovenian': 'Tarča 11', + }, + 'Target12': { + 'English': 'Target 12', + 'Slovenian': 'Tarča 12', + }, + 'Target13': { + 'English': 'Target 13', + 'Slovenian': 'Tarča 13', + }, + 'Target14': { + 'English': 'Target 14', + 'Slovenian': 'Tarča 14', + }, + 'Target15': { + 'English': 'Target 15', + 'Slovenian': 'Tarča 15', + }, + 'Target16': { + 'English': 'Target 16', + 'Slovenian': 'Tarča 16', + }, + 'Target17': { + 'English': 'Target 17', + 'Slovenian': 'Tarča 17', + }, + 'Target18': { + 'English': 'Target 18', + 'Slovenian': 'Tarča 18', + }, + 'Target19': { + 'English': 'Target 19', + 'Slovenian': 'Tarča 19', + }, + 'Target20': { + 'English': 'Target 20', + 'Slovenian': 'Tarča 20', + }, + 'Target21': { + 'English': 'Target 21', + 'Slovenian': 'Tarča 21', + }, + 'Target22': { + 'English': 'Target 22', + 'Slovenian': 'Tarča 22', + }, + 'Target23': { + 'English': 'Target 23', + 'Slovenian': 'Tarča 23', + }, + 'Target24': { + 'English': 'Target 24', + 'Slovenian': 'Tarča 24', + }, + // Camera settings 'Camera Settings': { 'English': 'Camera Settings',