From f260d8d5ca55ed8f340d8446e6c8717d9e78a72f Mon Sep 17 00:00:00 2001 From: Vadim <44135514+vodemn@users.noreply.github.com> Date: Thu, 4 Sep 2025 09:45:46 +0200 Subject: [PATCH] show pinhole shutter speed (wip) --- lib/l10n/intl_de.arb | 1 + lib/l10n/intl_en.arb | 1 + lib/l10n/intl_fr.arb | 1 + lib/l10n/intl_pl.arb | 1 + lib/l10n/intl_ru.arb | 1 + lib/l10n/intl_zh.arb | 1 + .../widget_container_camera.dart | 6 +- .../widget_container_shutter_speed.dart | 32 ++++++++++ .../widget_container_readings.dart | 6 +- lib/screens/metering/screen_metering.dart | 58 +++++++++++-------- 10 files changed, 82 insertions(+), 26 deletions(-) create mode 100644 lib/screens/metering/components/shared/readings_container/components/shutter_speed_container/widget_container_shutter_speed.dart diff --git a/lib/l10n/intl_de.arb b/lib/l10n/intl_de.arb index f5c1bd0..dbe733d 100644 --- a/lib/l10n/intl_de.arb +++ b/lib/l10n/intl_de.arb @@ -62,6 +62,7 @@ "apertureValuesFilterDescription": "Wählen Sie den Blendenbereich für Ihr Objektiv", "ndFilters": "ND Filter", "ndFiltersFilterDescription": "Wählen Sie verfügbare ND-Filter", + "shutterSpeed": "Belichtungszeit", "shutterSpeedValues": "Belichtungszeiten", "shutterSpeedValue": "Belichtungszeit", "shutterSpeedValuesFilterDescription": "Wählen Sie den Verschlusszeitenbereich für Ihre Kamera", diff --git a/lib/l10n/intl_en.arb b/lib/l10n/intl_en.arb index e9447fa..6641b68 100644 --- a/lib/l10n/intl_en.arb +++ b/lib/l10n/intl_en.arb @@ -62,6 +62,7 @@ "apertureValuesFilterDescription": "Select aperture range for your lens", "ndFilters": "ND filters", "ndFiltersFilterDescription": "Select available ND filters", + "shutterSpeed": "Shutter speed", "shutterSpeedValues": "Shutter speed values", "shutterSpeedValue": "Shutter speed value", "shutterSpeedValuesFilterDescription": "Select shutter speed range for your camera", diff --git a/lib/l10n/intl_fr.arb b/lib/l10n/intl_fr.arb index 2ee7a40..2a8f1b0 100644 --- a/lib/l10n/intl_fr.arb +++ b/lib/l10n/intl_fr.arb @@ -62,6 +62,7 @@ "apertureValuesFilterDescription": "Sélectionnez la plage d'ouverture pour votre objectif", "ndFilters": "Filtres ND", "ndFiltersFilterDescription": "Sélectionnez les filtres ND disponibles", + "shutterSpeed": "Vitesse d'obturation", "shutterSpeedValues": "Valeurs de la vitesse d'obturation", "shutterSpeedValue": "Valeur de la vitesse d'obturation", "shutterSpeedValuesFilterDescription": "Sélectionnez la plage de vitesses pour votre appareil", diff --git a/lib/l10n/intl_pl.arb b/lib/l10n/intl_pl.arb index 1fe5a8d..a153890 100644 --- a/lib/l10n/intl_pl.arb +++ b/lib/l10n/intl_pl.arb @@ -62,6 +62,7 @@ "apertureValuesFilterDescription": "Wybierz zakres przysłony dla swojego obiektywu", "ndFilters": "Filtry ND", "ndFiltersFilterDescription": "Wybierz dostępne filtry ND", + "shutterSpeed": "Czas naświetlania", "shutterSpeedValues": "Czasy naświetlania", "shutterSpeedValue": "Czas naświetlania", "shutterSpeedValuesFilterDescription": "Wybierz zakres czasów naświetlania dla swojej kamery", diff --git a/lib/l10n/intl_ru.arb b/lib/l10n/intl_ru.arb index dddde32..53e9045 100644 --- a/lib/l10n/intl_ru.arb +++ b/lib/l10n/intl_ru.arb @@ -62,6 +62,7 @@ "apertureValuesFilterDescription": "Выберите диапазон диафрагмы для вашего объектива", "ndFilters": "ND фильтры", "ndFiltersFilterDescription": "Выберите доступные ND фильтры", + "shutterSpeed": "Выдержка", "shutterSpeedValues": "Значения выдержки", "shutterSpeedValue": "Значение выдержки", "shutterSpeedValuesFilterDescription": "Выберите диапазон выдержек для вашей камеры", diff --git a/lib/l10n/intl_zh.arb b/lib/l10n/intl_zh.arb index c419b11..668b364 100644 --- a/lib/l10n/intl_zh.arb +++ b/lib/l10n/intl_zh.arb @@ -62,6 +62,7 @@ "apertureValuesFilterDescription": "选择镜头光圈范围", "ndFilters": "ND 滤镜", "ndFiltersFilterDescription": "选择可用的 ND 滤镜", + "shutterSpeed": "快门速度", "shutterSpeedValues": "快门速度", "shutterSpeedValue": "快门速度", "shutterSpeedValuesFilterDescription": "选择相机快门范围", diff --git a/lib/screens/metering/components/camera_container/widget_container_camera.dart b/lib/screens/metering/components/camera_container/widget_container_camera.dart index 8dd55ef..871a41c 100644 --- a/lib/screens/metering/components/camera_container/widget_container_camera.dart +++ b/lib/screens/metering/components/camera_container/widget_container_camera.dart @@ -6,6 +6,7 @@ import 'package:lightmeter/data/models/exposure_pair.dart'; import 'package:lightmeter/data/models/feature.dart'; import 'package:lightmeter/data/models/metering_screen_layout_config.dart'; import 'package:lightmeter/platform_config.dart'; +import 'package:lightmeter/providers/equipment_profile_provider.dart'; import 'package:lightmeter/providers/remote_config_provider.dart'; import 'package:lightmeter/res/dimens.dart'; import 'package:lightmeter/screens/metering/components/camera_container/bloc_container_camera.dart'; @@ -125,7 +126,10 @@ class CameraContainer extends StatelessWidget { enabledFeaturesHeight += Dimens.readingContainerSingleValueHeight; enabledFeaturesHeight += Dimens.paddingS; } - if (context.meteringFeature(MeteringScreenLayoutFeature.extremeExposurePairs)) { + if (EquipmentProfiles.selectedOf(context) is PinholeEquipmentProfile) { + enabledFeaturesHeight += Dimens.readingContainerSingleValueHeight; + enabledFeaturesHeight += Dimens.paddingS; + } else if (context.meteringFeature(MeteringScreenLayoutFeature.extremeExposurePairs)) { enabledFeaturesHeight += Dimens.readingContainerDoubleValueHeight; enabledFeaturesHeight += Dimens.paddingS; } diff --git a/lib/screens/metering/components/shared/readings_container/components/shutter_speed_container/widget_container_shutter_speed.dart b/lib/screens/metering/components/shared/readings_container/components/shutter_speed_container/widget_container_shutter_speed.dart new file mode 100644 index 0000000..d458ad4 --- /dev/null +++ b/lib/screens/metering/components/shared/readings_container/components/shutter_speed_container/widget_container_shutter_speed.dart @@ -0,0 +1,32 @@ +import 'package:flutter/material.dart'; +import 'package:lightmeter/generated/l10n.dart'; +import 'package:lightmeter/providers/films_provider.dart'; +import 'package:lightmeter/screens/metering/components/shared/readings_container/components/shared/reading_value_container/widget_container_reading_value.dart'; +import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart'; + +class ShutterSpeedContainer extends StatelessWidget { + final ShutterSpeedValue? shutterSpeedValue; + + const ShutterSpeedContainer({ + required this.shutterSpeedValue, + super.key, + }); + + @override + Widget build(BuildContext context) { + return ReadingValueContainer.singleValue( + value: ReadingValue( + label: S.of(context).shutterSpeed, + value: _shutterSpeed(context), + ), + ); + } + + String _shutterSpeed(BuildContext context) { + if (shutterSpeedValue case final shutterSpeedValue?) { + return Films.selectedOf(context).reciprocityFailure(shutterSpeedValue).toString(); + } else { + return '-'; + } + } +} diff --git a/lib/screens/metering/components/shared/readings_container/widget_container_readings.dart b/lib/screens/metering/components/shared/readings_container/widget_container_readings.dart index fe8c8b0..034ece1 100644 --- a/lib/screens/metering/components/shared/readings_container/widget_container_readings.dart +++ b/lib/screens/metering/components/shared/readings_container/widget_container_readings.dart @@ -11,6 +11,7 @@ import 'package:lightmeter/screens/metering/components/shared/readings_container import 'package:lightmeter/screens/metering/components/shared/readings_container/components/iso_picker/widget_picker_iso.dart'; import 'package:lightmeter/screens/metering/components/shared/readings_container/components/lightmeter_pro_badge/widget_badge_lightmeter_pro.dart'; import 'package:lightmeter/screens/metering/components/shared/readings_container/components/nd_picker/widget_picker_nd.dart'; +import 'package:lightmeter/screens/metering/components/shared/readings_container/components/shutter_speed_container/widget_container_shutter_speed.dart'; import 'package:lightmeter/utils/context_utils.dart'; import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart'; @@ -45,7 +46,10 @@ class ReadingsContainer extends StatelessWidget { const EquipmentProfilePicker(), const _InnerPadding(), ], - if (context.meteringFeature(MeteringScreenLayoutFeature.extremeExposurePairs)) ...[ + if (EquipmentProfiles.selectedOf(context) is PinholeEquipmentProfile) ...[ + ShutterSpeedContainer(shutterSpeedValue: fastest?.shutterSpeed), + const _InnerPadding(), + ] else if (context.meteringFeature(MeteringScreenLayoutFeature.extremeExposurePairs)) ...[ ExtremeExposurePairsContainer( fastest: fastest, slowest: slowest, diff --git a/lib/screens/metering/screen_metering.dart b/lib/screens/metering/screen_metering.dart index 4f81e4a..7d504e3 100644 --- a/lib/screens/metering/screen_metering.dart +++ b/lib/screens/metering/screen_metering.dart @@ -169,12 +169,22 @@ class MeteringContainerBuidler extends StatelessWidget { static List buildExposureValues( double ev, StopType stopType, - EquipmentProfile equipmentProfile, + IEquipmentProfile equipmentProfile, ) { if (ev.isNaN || ev.isInfinite) { return List.empty(); } + if (equipmentProfile.id != "" && equipmentProfile is PinholeEquipmentProfile) { + final t = pow(equipmentProfile.aperture, 2) / pow(2, ev); + return [ + ExposurePair( + ApertureValue(equipmentProfile.aperture, StopType.full), + ShutterSpeedValue(t, false, StopType.full), + ), + ]; + } + /// Depending on the `stopType` the exposure pairs list length is multiplied by 1,2 or 3 final int evSteps = (ev * (stopType.index + 1)).round(); @@ -236,31 +246,31 @@ class MeteringContainerBuidler extends StatelessWidget { ); /// Full equipment profile, nothing to cut - if (equipmentProfile.id == "") { - return exposurePairs; + if (equipmentProfile.id != "" && equipmentProfile is EquipmentProfile) { + final equipmentApertureValues = equipmentProfile.apertureValues.whereStopType(stopType); + final equipmentShutterSpeedValues = equipmentProfile.shutterSpeedValues.whereStopType(stopType); + + final startCutEV = max( + exposurePairs.first.aperture.difference(equipmentApertureValues.first), + exposurePairs.first.shutterSpeed.difference(equipmentShutterSpeedValues.first), + ); + final endCutEV = max( + equipmentApertureValues.last.difference(exposurePairs.last.aperture), + equipmentShutterSpeedValues.last != ShutterSpeedValue.values.last + ? equipmentShutterSpeedValues.last.difference(exposurePairs.last.shutterSpeed) + : double.negativeInfinity, + ); + + final startCut = (startCutEV * (stopType.index + 1)).round().clamp(0, itemsCount); + final endCut = (endCutEV * (stopType.index + 1)).round().clamp(0, itemsCount); + + if (startCut > itemsCount - endCut) { + return const []; + } + return exposurePairs.sublist(startCut, itemsCount - endCut); } - final equipmentApertureValues = equipmentProfile.apertureValues.whereStopType(stopType); - final equipmentShutterSpeedValues = equipmentProfile.shutterSpeedValues.whereStopType(stopType); - - final startCutEV = max( - exposurePairs.first.aperture.difference(equipmentApertureValues.first), - exposurePairs.first.shutterSpeed.difference(equipmentShutterSpeedValues.first), - ); - final endCutEV = max( - equipmentApertureValues.last.difference(exposurePairs.last.aperture), - equipmentShutterSpeedValues.last != ShutterSpeedValue.values.last - ? equipmentShutterSpeedValues.last.difference(exposurePairs.last.shutterSpeed) - : double.negativeInfinity, - ); - - final startCut = (startCutEV * (stopType.index + 1)).round().clamp(0, itemsCount); - final endCut = (endCutEV * (stopType.index + 1)).round().clamp(0, itemsCount); - - if (startCut > itemsCount - endCut) { - return const []; - } - return exposurePairs.sublist(startCut, itemsCount - endCut); + return exposurePairs; } }