Skip to content

Commit

Permalink
#763 Hide source min/max for trigger-like sources and hide target min…
Browse files Browse the repository at this point in the history
…/max for relative targets
  • Loading branch information
helgoboss committed Nov 23, 2022
1 parent a5b03b0 commit 09151fe
Show file tree
Hide file tree
Showing 11 changed files with 115 additions and 63 deletions.
2 changes: 1 addition & 1 deletion main/lib/helgoboss-learn
4 changes: 2 additions & 2 deletions main/src/application/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ use std::fmt::Debug;

use crate::domain;
use core::iter;
use helgoboss_learn::{AbsoluteValue, ControlResult, ControlValue, SourceContext, UnitValue};
use helgoboss_learn::{ControlResult, ControlValue, SourceContext, UnitValue};
use itertools::Itertools;
use playtime_clip_engine::base::ClipMatrixEvent;
use realearn_api::persistence::{FxDescriptor, TrackDescriptor};
Expand Down Expand Up @@ -455,7 +455,7 @@ impl Session {
/// Instructs the main processor to hit the target directly.
///
/// This doesn't invoke group interaction because it's meant to totally skip the mode.
pub fn hit_target(&self, id: QualifiedMappingId, value: AbsoluteValue) {
pub fn hit_target(&self, id: QualifiedMappingId, value: ControlValue) {
self.normal_main_task_sender
.send_complaining(NormalMainTask::HitTarget { id, value });
}
Expand Down
6 changes: 3 additions & 3 deletions main/src/application/source_model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -537,21 +537,21 @@ impl SourceModel {
VirtualControlElement::Multi(_) => vec![
DetailedSourceCharacter::MomentaryVelocitySensitiveButton,
DetailedSourceCharacter::MomentaryOnOffButton,
DetailedSourceCharacter::PressOnlyButton,
DetailedSourceCharacter::Trigger,
DetailedSourceCharacter::RangeControl,
DetailedSourceCharacter::Relative,
],
VirtualControlElement::Button(_) => vec![
DetailedSourceCharacter::MomentaryOnOffButton,
DetailedSourceCharacter::PressOnlyButton,
DetailedSourceCharacter::Trigger,
],
},
CompoundMappingSource::Reaper(s) => s.possible_detailed_characters(),
// Can be anything, depending on the mapping that uses the group interaction.
CompoundMappingSource::Never => vec![
DetailedSourceCharacter::MomentaryVelocitySensitiveButton,
DetailedSourceCharacter::MomentaryOnOffButton,
DetailedSourceCharacter::PressOnlyButton,
DetailedSourceCharacter::Trigger,
DetailedSourceCharacter::RangeControl,
DetailedSourceCharacter::Relative,
],
Expand Down
4 changes: 2 additions & 2 deletions main/src/domain/main_processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2646,7 +2646,7 @@ impl<EH: DomainEventHandler> MainProcessor<EH> {
relevant_map.insert(m.id(), m);
}

fn hit_target(&mut self, id: QualifiedMappingId, value: AbsoluteValue) {
fn hit_target(&mut self, id: QualifiedMappingId, value: ControlValue) {
let control_result = if let Some(m) =
self.collections.mappings[id.compartment].get_mut(&id.id)
{
Expand Down Expand Up @@ -2723,7 +2723,7 @@ pub enum NormalMainTask {
/// This doesn't invoke group interaction because it's meant to totally skip the mode.
HitTarget {
id: QualifiedMappingId,
value: AbsoluteValue,
value: ControlValue,
},
/// This should be sent on events such as track list change, FX focus etc.
///
Expand Down
8 changes: 2 additions & 6 deletions main/src/domain/mapping.rs
Original file line number Diff line number Diff line change
Expand Up @@ -884,7 +884,7 @@ impl MainMapping {
// TODO-low Strictly spoken, this is not necessary, because control_internal uses this only
// if target refresh is enforced, which is not the case here.
processor_context: ExtendedProcessorContext,
value: AbsoluteValue,
value: ControlValue,
log_mode_control_result: impl Fn(ControlLogEntry),
) -> MappingControlResult {
self.control_internal(
Expand All @@ -894,11 +894,7 @@ impl MainMapping {
processor_context,
false,
log_mode_control_result,
|_, _, _, _| {
Some(ModeControlResult::hit_target(ControlValue::from_absolute(
value,
)))
},
|_, _, _, _| Some(ModeControlResult::hit_target(value)),
)
}

Expand Down
4 changes: 2 additions & 2 deletions main/src/domain/reaper_source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,12 +149,12 @@ impl ReaperSource {
match self {
MidiDeviceChanges => vec![DetailedSourceCharacter::MomentaryOnOffButton],
RealearnInstanceStart => vec![DetailedSourceCharacter::MomentaryOnOffButton],
Timer(_) => vec![DetailedSourceCharacter::PressOnlyButton],
Timer(_) => vec![DetailedSourceCharacter::Trigger],
RealearnParameter(_) => vec![
DetailedSourceCharacter::RangeControl,
DetailedSourceCharacter::MomentaryVelocitySensitiveButton,
DetailedSourceCharacter::MomentaryOnOffButton,
DetailedSourceCharacter::PressOnlyButton,
DetailedSourceCharacter::Trigger,
],
Speech(_) => vec![DetailedSourceCharacter::RangeControl],
}
Expand Down
12 changes: 10 additions & 2 deletions main/src/domain/reaper_target.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,19 +55,27 @@ use crate::domain::{

/// This target character is just used for GUI and auto-correct settings! It doesn't have influence
/// on control/feedback.
///
/// This relates more to the character of the target value, actually. Not the way the target wants
/// to be controlled. That's why introducing a "Relative" character is not a good idea. The value
/// can still be discrete or continuous, it's orthogonal.
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum TargetCharacter {
/// "Fire-only", so like switch but whenever it only makes sense to send "on", not "off".
///
/// Rendered as one button.
/// Rendered as one trigger button.
Trigger,
/// When there are just two states: "on" and "off".
///
/// Rendered as two buttons.
/// Rendered as on/off buttons.
Switch,
/// Whenever there's a certain, discrete number of target values (steps).
///
/// Rendered as slider or -/+ buttons (if target type is relative).
Discrete,
/// Whenever the step size between two target values can get arbitrarily small.
///
/// Rendered as slider or -/+ buttons (if target type is relative).
Continuous,
/// When the target is a virtual control element that allows for more than 2 states.
VirtualMulti,
Expand Down
2 changes: 1 addition & 1 deletion main/src/domain/targets/browse_group_mappings_target.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ impl RealearnTarget for BrowseGroupMappingsTarget {
context.control_context,
context.logger,
context.processor_context,
AbsoluteValue::Continuous(v),
ControlValue::AbsoluteContinuous(v),
context.basic_settings.target_control_logger(
context.processor_context.control_context.instance_state,
ControlLogContext::GroupNavigation,
Expand Down
2 changes: 1 addition & 1 deletion main/src/domain/targets/load_mapping_snapshot_target.rs
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ impl LoadMappingSnapshotInstruction {
context.control_context,
context.logger,
context.processor_context,
snapshot_value,
ControlValue::from_absolute(snapshot_value),
context.basic_settings.target_control_logger(
context.processor_context.control_context.instance_state,
ControlLogContext::LoadingMappingSnapshot,
Expand Down
113 changes: 80 additions & 33 deletions main/src/infrastructure/ui/mapping_panel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3318,10 +3318,33 @@ impl<'a> MutableMappingPanel<'a> {
}

impl<'a> ImmutableMappingPanel<'a> {
// For hitting target with on/off or -/+ depending on target character.
fn hit_target_special(&self, state: bool) -> Result<(), &'static str> {
let target = self
.first_resolved_target()
.ok_or("couldn't resolve to target")?;
let target_is_relative = target
.control_type(self.session.control_context())
.is_relative();
let value = if target_is_relative {
let amount = if state { 1 } else { -1 };
ControlValue::RelativeDiscrete(DiscreteIncrement::new(amount))
} else {
let value = if state {
UnitValue::MAX
} else {
UnitValue::MIN
};
ControlValue::AbsoluteContinuous(value)
};
self.session.hit_target(self.mapping.qualified_id(), value);
Ok(())
}

fn hit_target(&self, value: UnitValue) {
self.session.hit_target(
self.mapping.qualified_id(),
AbsoluteValue::Continuous(value),
ControlValue::AbsoluteContinuous(value),
);
}

Expand Down Expand Up @@ -5406,7 +5429,7 @@ impl<'a> ImmutableMappingPanel<'a> {
fn invalidate_target_value_controls(&self) {
// TODO-low This might set the value slider to the wrong value because it only takes the
// first resolved target into account.
let (error_msg, read_enabled, write_enabled, character) =
let (error_msg, read_enabled, write_enabled, character, is_relative) =
if let Some(t) = self.first_resolved_target() {
let control_context = self.session.control_context();
let (error_msg, read_enabled, write_enabled) = if t.is_virtual() {
Expand All @@ -5416,20 +5439,21 @@ impl<'a> ImmutableMappingPanel<'a> {
} else if t.can_report_current_value() {
let value = t.current_value(control_context).unwrap_or_default();
self.invalidate_target_value_controls_with_value(value);
let write_enabled = !t.control_type(control_context).is_relative();
(None, true, write_enabled)
(None, true, true)
} else {
// Target is real but can't report values (e.g. load mapping snapshot)
(None, false, true)
};
let is_relative = t.control_type(control_context).is_relative();
(
error_msg,
read_enabled,
write_enabled,
Some(t.character(control_context)),
is_relative,
)
} else {
(Some("Target inactive!"), false, false, None)
(Some("Target inactive!"), false, false, None, false)
};
self.show_if(
read_enabled,
Expand All @@ -5440,36 +5464,45 @@ impl<'a> ImmutableMappingPanel<'a> {
],
);
// Slider or buttons
let off_button = self.view.require_control(root::ID_TARGET_VALUE_OFF_BUTTON);
let on_button = self.view.require_control(root::ID_TARGET_VALUE_ON_BUTTON);
let button_1 = self.view.require_control(root::ID_TARGET_VALUE_OFF_BUTTON);
let button_2 = self.view.require_control(root::ID_TARGET_VALUE_ON_BUTTON);
let slider_control = self
.view
.require_control(root::ID_TARGET_VALUE_SLIDER_CONTROL);
if write_enabled {
use TargetCharacter::*;
match character {
Some(Trigger) => {
slider_control.hide();
off_button.hide();
on_button.show();
on_button.set_text("Trigger!");
}
Some(Switch) => {
slider_control.hide();
off_button.show();
on_button.show();
on_button.set_text("On");
}
_ => {
off_button.hide();
on_button.hide();
slider_control.show();
if is_relative {
slider_control.hide();
button_1.show();
button_2.show();
button_1.set_text("-");
button_2.set_text("+");
} else {
use TargetCharacter::*;
match character {
Some(Trigger) => {
slider_control.hide();
button_1.hide();
button_2.show();
button_2.set_text("Trigger!");
}
Some(Switch) => {
slider_control.hide();
button_1.show();
button_2.show();
button_1.set_text("Off");
button_2.set_text("On");
}
_ => {
button_1.hide();
button_2.hide();
slider_control.show();
}
}
}
} else {
slider_control.hide();
off_button.hide();
on_button.hide();
button_1.hide();
button_2.hide();
}
// Maybe display grey error message instead of value text
let value_text = self.view.require_control(root::ID_TARGET_VALUE_TEXT);
Expand Down Expand Up @@ -5655,6 +5688,11 @@ impl<'a> ImmutableMappingPanel<'a> {
.as_ref()
.map(|t| t.can_report_current_value())
.unwrap_or_default();
let target_wants_relative_control = real_target
.as_ref()
.map(|t| t.control_type(self.session.control_context()).is_relative())
.unwrap_or_default();
let feedback_is_on = self.mapping.feedback_is_enabled_and_supported();
// For all source characters
{
let show_source_min_max = is_relevant(ModeParameter::SourceMinMax);
Expand Down Expand Up @@ -5690,17 +5728,26 @@ impl<'a> ImmutableMappingPanel<'a> {
root::ID_MODE_GROUP_INTERACTION_COMBO_BOX,
],
);
let show_target_value_sequence =
is_relevant(ModeParameter::TargetValueSequence) && real_target.is_some();
let target_controls_make_sense = if target_wants_relative_control
&& (!feedback_is_on || !target_can_report_current_value)
{
false
} else {
true
};
let show_target_value_sequence = target_controls_make_sense
&& is_relevant(ModeParameter::TargetValueSequence)
&& real_target.is_some();
self.enable_if(
show_target_value_sequence,
&[
root::ID_SETTINGS_TARGET_SEQUENCE_LABEL_TEXT,
root::ID_MODE_TARGET_SEQUENCE_EDIT_CONTROL,
],
);
let show_target_min_max =
is_relevant(ModeParameter::TargetMinMax) && real_target.is_some();
let show_target_min_max = target_controls_make_sense
&& is_relevant(ModeParameter::TargetMinMax)
&& real_target.is_some();
self.enable_if(
show_target_min_max,
&[
Expand Down Expand Up @@ -6486,10 +6533,10 @@ impl View for MappingPanel {
let _ = self.handle_target_line_4_button_press();
}
root::ID_TARGET_VALUE_OFF_BUTTON => {
let _ = self.read(|p| p.hit_target(UnitValue::MIN));
let _ = self.read(|p| p.hit_target_special(false));
}
root::ID_TARGET_VALUE_ON_BUTTON => {
let _ = self.read(|p| p.hit_target(UnitValue::MAX));
let _ = self.read(|p| p.hit_target_special(true));
}
root::ID_TARGET_UNIT_BUTTON => self.write(|p| p.handle_target_unit_button_press()),
_ => unreachable!(),
Expand Down
21 changes: 11 additions & 10 deletions resources/test-projects/issue-763-specific-program-change.RPP
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<REAPER_PROJECT 0.1 "6.69+dev1111/macOS-arm64" 1668797091
<REAPER_PROJECT 0.1 "6.69+dev1111/macOS-arm64" 1669189353
<NOTES 0 2
>
RIPPLE 0
Expand Down Expand Up @@ -69,7 +69,7 @@
MASTERTRACKVIEW 0 0.6667 0.5 0.5 -1 -1 -1 0 0 0 -1 -1 0
MASTERHWOUT 0 0 1 0 0 0 0 -1
MASTER_NCH 2 2
MASTER_VOLUME 0.000084926661 0 -1 -1 1
MASTER_VOLUME 1.16135142141719 0 -1 -1 1
MASTER_PANMODE 3
MASTER_FX 1
MASTER_SEL 0
Expand Down Expand Up @@ -116,7 +116,7 @@
MAINSEND 1 0
<FXCHAIN
WNDRECT 417 159 983 703
SHOW 0
SHOW 2
LASTSEL 1
DOCKED 0
BYPASS 0 0 0
Expand All @@ -129,7 +129,7 @@
YWx1ZSI6MC4wMzkzNzAwNzg3NDAxNTc0OCwibWF4VGFyZ2V0VmFsdWUiOjAuNDcyNDQwOTQ0ODgxODg5NzYsIm1heFN0ZXBTaXplIjowLjA1LCJtaW5TdGVwRmFjdG9y
IjoxLCJtYXhTdGVwRmFjdG9yIjo1fSwidGFyZ2V0Ijp7InR5cGUiOjI5LCJmeEFuY2hvciI6ImlkIiwidXNlU2VsZWN0aW9uR2FuZ2luZyI6ZmFsc2UsInVzZVRyYWNr
R3JvdXBpbmciOmZhbHNlLCJzZWVrQmVoYXZpb3IiOiJJbW1lZGlhdGUiLCJ1c2VQcm9qZWN0Ijp0cnVlLCJtb3ZlVmlldyI6dHJ1ZSwic2Vla1BsYXkiOnRydWUsInJh
d01pZGlQYXR0ZXJuIjoiQzAgWzBnZmUgZGNiYV0gMDAiLCJvc2NBcmdJbmRleCI6MCwibW91c2VBY3Rpb24iOnsia2luZCI6Ik1vdmVUbyIsImF4aXMiOiJZIn0sInRh
d01pZGlQYXR0ZXJuIjoiQzEgWzBnZmUgZGNiYV0gMDAiLCJvc2NBcmdJbmRleCI6MCwibW91c2VBY3Rpb24iOnsia2luZCI6Ik1vdmVUbyIsImF4aXMiOiJZIn0sInRh
a2VNYXBwaW5nU25hcHNob3QiOnsia2luZCI6Ikxhc3RMb2FkZWQifX19XSwiaW5zdGFuY2VGeCI6eyJhZGRyZXNzIjoiRm9jdXNlZCJ9fQ==
AFByb2dyYW0gMQAQAAAA
>
Expand All @@ -138,14 +138,15 @@
WAK 0 0
BYPASS 0 0 0
<VST "VSTi: ReaLearn (Helgoboss)" realearn.vst.dylib 0 "" 1751282284<5653546862726C7265616C6561726E00> ""
bHJiaO5e7f4CAAAAAQAAAAAAAAACAAAAAAAAAAAAAACQAgAAAQAAAAAAEAA=
bHJiaO5e7f4CAAAAAQAAAAAAAAACAAAAAAAAAAAAAADGAgAAAQAAAAAAEAA=
eyJ2ZXJzaW9uIjoiMi4xNC4wLXByZS4xMSIsImlkIjoiQnNpOXZ6cC0iLCJzdGF5QWN0aXZlV2hlblByb2plY3RJbkJhY2tncm91bmQiOiJPbmx5SWZCYWNrZ3JvdW5k
UHJvamVjdElzUnVubmluZyIsInNlbmRGZWVkYmFja09ubHlJZkFybWVkIjp0cnVlLCJkZWZhdWx0R3JvdXAiOnt9LCJkZWZhdWx0Q29udHJvbGxlckdyb3VwIjp7fSwi
bWFwcGluZ3MiOlt7ImlkIjoiZ01zakZDbXdiZXBhVnlwcjdRYmlaIiwibmFtZSI6IjEiLCJzb3VyY2UiOnsidHlwZSI6MTN9LCJtb2RlIjp7Im1heFN0ZXBTaXplIjow
LjA1LCJtaW5TdGVwRmFjdG9yIjoxLCJtYXhTdGVwRmFjdG9yIjo1LCJlZWxDb250cm9sVHJhbnNmb3JtYXRpb24iOiJ5ID0gcmFuZCgpIn0sInRhcmdldCI6eyJ0eXBl
IjoyLCJ0cmFja0dVSUQiOiJtYXN0ZXIiLCJmeEFuY2hvciI6ImlkIiwidXNlU2VsZWN0aW9uR2FuZ2luZyI6ZmFsc2UsInVzZVRyYWNrR3JvdXBpbmciOmZhbHNlLCJz
ZWVrQmVoYXZpb3IiOiJJbW1lZGlhdGUiLCJtb3VzZUFjdGlvbiI6eyJraW5kIjoiTW92ZVRvIiwiYXhpcyI6IlkifSwicG9sbEZvckZlZWRiYWNrIjpmYWxzZSwidGFr
ZU1hcHBpbmdTbmFwc2hvdCI6eyJraW5kIjoiQnlJZCIsImlkIjoiIn19fV0sImluc3RhbmNlRngiOnsiYWRkcmVzcyI6IkZvY3VzZWQifX0=
bWFwcGluZ3MiOlt7ImlkIjoiZ01zakZDbXdiZXBhVnlwcjdRYmlaIiwibmFtZSI6IjEiLCJzb3VyY2UiOnsidHlwZSI6MTMsImNoYW5uZWwiOjEsIm51bWJlciI6NjB9
LCJtb2RlIjp7Im1heFN0ZXBTaXplIjowLjA1LCJtaW5TdGVwRmFjdG9yIjoxLCJtYXhTdGVwRmFjdG9yIjo1LCJlZWxDb250cm9sVHJhbnNmb3JtYXRpb24iOiJ5ID0g
cmFuZCgpIiwib3V0T2ZSYW5nZUJlaGF2aW9yIjoiaWdub3JlIn0sInRhcmdldCI6eyJ0eXBlIjoyLCJ0cmFja0dVSUQiOiJtYXN0ZXIiLCJmeEFuY2hvciI6ImlkIiwi
dXNlU2VsZWN0aW9uR2FuZ2luZyI6ZmFsc2UsInVzZVRyYWNrR3JvdXBpbmciOmZhbHNlLCJzZWVrQmVoYXZpb3IiOiJJbW1lZGlhdGUiLCJtb3VzZUFjdGlvbiI6eyJr
aW5kIjoiTW92ZVRvIiwiYXhpcyI6IlkifSwicG9sbEZvckZlZWRiYWNrIjpmYWxzZSwidGFrZU1hcHBpbmdTbmFwc2hvdCI6eyJraW5kIjoiQnlJZCIsImlkIjoiIn19
fV0sImluc3RhbmNlRngiOnsiYWRkcmVzcyI6IkZvY3VzZWQifX0=
AFByb2dyYW0gMQAQAAAA
>
FLOATPOS 385 219 752 675
Expand Down

0 comments on commit 09151fe

Please sign in to comment.