m3_lightmeter/lib/screens/metering/bloc_metering.dart

163 lines
5.2 KiB
Dart
Raw Normal View History

import 'dart:async';
2022-10-29 18:02:45 +00:00
import 'dart:math';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:lightmeter/data/models/photography_values/aperture_value.dart';
2022-12-16 08:08:12 +00:00
import 'package:lightmeter/data/models/exposure_pair.dart';
import 'package:lightmeter/data/models/photography_values/photography_value.dart';
import 'package:lightmeter/data/models/photography_values/shutter_speed_value.dart';
2022-12-16 08:08:12 +00:00
import 'package:lightmeter/data/shared_prefs_service.dart';
import 'package:lightmeter/interactors/haptics_interactor.dart';
import 'package:lightmeter/screens/metering/communication/event_communication_metering.dart' as communication_events;
import 'package:lightmeter/screens/metering/communication/state_communication_metering.dart' as communication_states;
2022-12-04 19:00:43 +00:00
import 'package:lightmeter/utils/log_2.dart';
2022-10-29 18:02:45 +00:00
import 'communication/bloc_communication_metering.dart';
import 'event_metering.dart';
import 'state_metering.dart';
2022-10-29 18:02:45 +00:00
class MeteringBloc extends Bloc<MeteringEvent, MeteringState> {
final MeteringCommunicationBloc _communicationBloc;
2022-12-16 08:08:12 +00:00
final UserPreferencesService _userPreferencesService;
final HapticsInteractor _hapticsInteractor;
late final StreamSubscription<communication_states.ScreenState> _communicationSubscription;
List<ApertureValue> get _apertureValues => apertureValues.whereStopType(stopType);
List<ShutterSpeedValue> get _shutterSpeedValues => shutterSpeedValues.whereStopType(stopType);
2022-10-29 18:02:45 +00:00
StopType stopType;
2022-12-16 08:08:12 +00:00
MeteringBloc(
this._communicationBloc,
this._userPreferencesService,
this._hapticsInteractor,
2022-12-16 08:08:12 +00:00
this.stopType,
) : super(
MeteringState(
2022-12-16 08:08:12 +00:00
iso: _userPreferencesService.iso,
2022-12-15 11:00:28 +00:00
ev: 0.0,
2022-10-29 18:02:45 +00:00
evCompensation: 0.0,
2022-12-16 08:08:12 +00:00
nd: _userPreferencesService.ndFilter,
2022-10-29 18:02:45 +00:00
exposurePairs: [],
),
) {
_communicationSubscription = _communicationBloc.stream
.where((state) => state is communication_states.ScreenState)
.map((state) => state as communication_states.ScreenState)
.listen(_onCommunicationState);
on<StopTypeChangedEvent>(_onStopTypeChanged);
2022-12-04 19:00:43 +00:00
on<IsoChangedEvent>(_onIsoChanged);
on<NdChangedEvent>(_onNdChanged);
on<MeasureEvent>(_onMeasure);
on<MeasuredEvent>(_onMeasured);
2022-10-29 18:02:45 +00:00
add(const MeasureEvent());
}
@override
Future<void> close() async {
await _communicationSubscription.cancel();
return super.close();
}
void _onCommunicationState(communication_states.ScreenState communicationState) {
if (communicationState is communication_states.MeasuredState) {
add(MeasuredEvent(communicationState.ev100));
}
}
void _onStopTypeChanged(StopTypeChangedEvent event, Emitter emit) {
stopType = event.stopType;
emit(MeteringState(
iso: state.iso,
ev: state.ev,
evCompensation: state.evCompensation,
nd: state.nd,
exposurePairs: _buildExposureValues(state.ev),
));
}
2022-12-04 19:00:43 +00:00
void _onIsoChanged(IsoChangedEvent event, Emitter emit) {
2022-12-16 08:08:12 +00:00
_userPreferencesService.iso = event.isoValue;
2022-12-04 19:00:43 +00:00
final ev = state.ev + log2(event.isoValue.value / state.iso.value);
emit(MeteringState(
iso: event.isoValue,
ev: ev,
evCompensation: state.evCompensation,
nd: state.nd,
exposurePairs: _buildExposureValues(ev),
));
}
void _onNdChanged(NdChangedEvent event, Emitter emit) {
2022-12-16 08:08:12 +00:00
_userPreferencesService.ndFilter = event.ndValue;
final ev = state.ev - event.ndValue.stopReduction + state.nd.stopReduction;
emit(MeteringState(
iso: state.iso,
ev: ev,
evCompensation: state.evCompensation,
nd: event.ndValue,
exposurePairs: _buildExposureValues(ev),
));
}
void _onMeasure(_, __) {
_hapticsInteractor.quickVibration();
_communicationBloc.add(const communication_events.MeasureEvent());
}
void _onMeasured(MeasuredEvent event, Emitter emit) {
_hapticsInteractor.responseVibration();
final ev = event.ev100 + log2(state.iso.value / 100);
2022-10-29 18:02:45 +00:00
emit(MeteringState(
iso: state.iso,
ev: ev,
evCompensation: state.evCompensation,
nd: state.nd,
2022-12-04 19:00:43 +00:00
exposurePairs: _buildExposureValues(ev),
2022-10-29 18:02:45 +00:00
));
}
List<ExposurePair> _buildExposureValues(double ev) {
late final int evSteps;
switch (stopType) {
2022-10-30 18:06:51 +00:00
case StopType.full:
2022-10-29 18:02:45 +00:00
evSteps = ev.floor();
break;
2022-10-30 18:06:51 +00:00
case StopType.half:
2022-10-29 18:02:45 +00:00
evSteps = (ev / 0.5).floor();
break;
2022-10-30 18:06:51 +00:00
case StopType.third:
2022-10-29 18:02:45 +00:00
evSteps = (ev / 0.3).floor();
break;
}
2022-10-30 18:06:51 +00:00
final evOffset = _shutterSpeedValues.indexOf(const ShutterSpeedValue(1, false, StopType.full)) - evSteps;
2022-10-29 18:02:45 +00:00
late final int apertureOffset;
late final int shutterSpeedOffset;
if (evOffset >= 0) {
apertureOffset = 0;
shutterSpeedOffset = evOffset;
} else {
apertureOffset = -evOffset;
shutterSpeedOffset = 0;
}
int itemsCount = min(_apertureValues.length + shutterSpeedOffset, _shutterSpeedValues.length + apertureOffset) -
max(apertureOffset, shutterSpeedOffset);
2022-10-29 18:04:06 +00:00
if (itemsCount < 0) {
return List.empty(growable: false);
}
2022-10-29 18:02:45 +00:00
return List.generate(
itemsCount,
(index) => ExposurePair(
_apertureValues[index + apertureOffset],
_shutterSpeedValues[index + shutterSpeedOffset],
),
growable: false,
);
}
}