From 453ad9ed353b8887696488f43341c85707d9d75a Mon Sep 17 00:00:00 2001 From: Emilia Date: Sat, 4 Jan 2025 20:07:19 -0500 Subject: [PATCH] 0 indexing is a blight --- plate-tool-eframe/src/plate.rs | 187 +++++++++++++++++---------------- plate-tool-lib/src/plate.rs | 6 ++ 2 files changed, 102 insertions(+), 91 deletions(-) diff --git a/plate-tool-eframe/src/plate.rs b/plate-tool-eframe/src/plate.rs index bce82ba..e941e95 100644 --- a/plate-tool-eframe/src/plate.rs +++ b/plate-tool-eframe/src/plate.rs @@ -69,8 +69,18 @@ fn get_hover_well( start_x: f32, start_y: f32, radius: f32, + rows: u8, + columns: u8, ) -> Option<(u8, u8)> { - get_well_from_pos(response.hover_pos(), start_x, start_y, radius) + get_well_from_pos( + response.hover_pos(), + start_x, + start_y, + radius, + rows, + columns, + true, + ) } fn get_well_from_pos( @@ -78,19 +88,35 @@ fn get_well_from_pos( start_x: f32, start_y: f32, radius: f32, + rows: u8, + columns: u8, + saturate: bool, ) -> Option<(u8, u8)> { + // cool fact: the bounds of our frame aren't actually the bounds of what counts + // as hovering. as a result, we have to make sure that we check these bounds here. + // yippee + let max_width = start_x + radius * 2.0 * columns as f32; + let max_height = start_y + radius * 2.0 * rows as f32; + // Some((row, column)) position .map(|p| Into::<(f32, f32)>::into(p)) .and_then(|(x, y)| { - // Check bounds - if x < start_x || y < start_y { + // Check bounds if no saturation + if !saturate && (x < start_x || y < start_y || x > max_width || y > max_height) { return None; } - // CHECK Bottom Right BOUND - let solved_column: u8 = (x - start_x).div_euclid(radius * 2.0) as u8; - let solved_row: u8 = (y - start_y).div_euclid(radius * 2.0) as u8; + let solved_column: u8 = match x { + x if (x < start_x) => 1, + x if (x > max_width) => columns, + _ => (x - start_x).div_euclid(radius * 2.0) as u8 + 1u8, + }; + let solved_row: u8 = match y { + y if (y < start_y) => 1, + y if (y > max_height) => rows, + _ => (y - start_y).div_euclid(radius * 2.0) as u8 + 1u8, + }; Some((solved_row, solved_column)) }) @@ -110,19 +136,24 @@ fn calculate_shading_for_wells( for transfer in transfers { let cache_result = match plate_type { plate_tool_lib::plate::PlateType::Source => cache.get_or_calculate_source(transfer), - plate_tool_lib::plate::PlateType::Destination => cache.get_or_calculate_destination(transfer), + plate_tool_lib::plate::PlateType::Destination => { + cache.get_or_calculate_destination(transfer) + } }; if let Some(wells) = cache_result { for well in wells.iter().filter(|x| x.row <= rows && x.col <= columns) { if let Some(mut x) = - well_infos[well.row as usize * columns as usize + well.col as usize] + well_infos[(well.row - 1) as usize * columns as usize + (well.col - 1) as usize] { x.volume += 5.0; x.color = PALETTE.get_ordered(transfer.id, ordered_ids); } else { - well_infos[well.row as usize * columns as usize + well.col as usize] = Some( - WellInfo::new(5.0, PALETTE.get_ordered(transfer.id, ordered_ids)), - ); + well_infos + [(well.row - 1) as usize * columns as usize + (well.col - 1) as usize] = + Some(WellInfo::new( + 5.0, + PALETTE.get_ordered(transfer.id, ordered_ids), + )); } } } @@ -166,15 +197,20 @@ fn add_plate_sub( state.drag_start_position = Some(response.hover_pos().unwrap()); } - let drag_start_well = get_well_from_pos(state.drag_start_position, start_x, start_y, radius); - let hovered_well = get_hover_well(&response, start_x, start_y, radius); + let drag_start_well = get_well_from_pos( + state.drag_start_position, + start_x, + start_y, + radius, + rows, + columns, + false, + ); + let hovered_well = get_hover_well(&response, start_x, start_y, radius, rows, columns); if response.clicked() { if let Some(cts) = current_transfer_state { - let end_well: Option = hovered_well.map(|(row, col)| Well { - row: row + 1, - col: col + 1, - }); + let end_well: Option = hovered_well.map(|(row, col)| Well { row, col }); if let Some(end_well) = end_well { let new_region = Region::new_from_wells(end_well, None); let mut cts = cts.lock().unwrap(); @@ -189,23 +225,15 @@ fn add_plate_sub( } if response.drag_stopped() { if let Some(cts) = current_transfer_state { - let start_well: Well = drag_start_well - .map(|(row, col)| Well { - // Lib uses 1-indexing! - row: row + 1, - col: col + 1, - }) - .unwrap(); - let end_well: Option = hovered_well.map(|(row, col)| Well { - row: row + 1, - col: col + 1, - }); - let new_region = Region::new_from_wells(start_well, end_well); - let mut cts = cts.lock().unwrap(); - match plate_type { - plate_tool_lib::plate::PlateType::Source => cts.source_region = new_region, - plate_tool_lib::plate::PlateType::Destination => { - cts.destination_region = new_region + if let Some(start_well) = drag_start_well.map(|(row, col)| Well { row, col }) { + let end_well: Option = hovered_well.map(|(row, col)| Well { row, col }); + let new_region = Region::new_from_wells(start_well, end_well); + let mut cts = cts.lock().unwrap(); + match plate_type { + plate_tool_lib::plate::PlateType::Source => cts.source_region = new_region, + plate_tool_lib::plate::PlateType::Destination => { + cts.destination_region = new_region + } } } } @@ -227,10 +255,11 @@ fn add_plate_sub( }; let well_infos = { // Get non-active transfer info - let mut well_infos = calculate_shading_for_wells(rows, columns, transfers, plate_type, ordered_ids, cache); + let mut well_infos = + calculate_shading_for_wells(rows, columns, transfers, plate_type, ordered_ids, cache); // Get wells in the current transfer to tack on to well_infos separately - let current_transfer_wells: Option> = { + let current_transfer_wells: Option> = { (match plate_type { plate_tool_lib::plate::PlateType::Source => current_transfer_state .and_then(|x| x.lock().ok()) @@ -239,27 +268,30 @@ fn add_plate_sub( .and_then(|x| x.lock().ok()) .map(|mut x| x.get_destination_wells()), }) - // Drop back to 0-indexing here - .map(|xs| xs.iter().map(|x| (x.row as usize - 1, x.col as usize - 1)).collect()) + .map(|xs| { + xs.iter() + .map(|x| (x.row as usize, x.col as usize)) + .collect() + }) }; if let Some(wells) = current_transfer_wells { for w in wells { - let well_info = &mut well_infos[w.0 * columns as usize + w.1]; + let well_info = &mut well_infos[(w.0 - 1) * columns as usize + (w.1 - 1)]; let volume = well_info.map(|x| x.volume).unwrap_or(0.0) - + current_transfer_state.and_then(|x| x.lock().ok()) - .map(|x| x.volume) - .unwrap_or(0.0); + + current_transfer_state + .and_then(|x| x.lock().ok()) + .map(|x| x.volume) + .unwrap_or(0.0); *well_info = Some(WellInfo { - color: [255.0,255.0,255.0], - volume: 1.0 + color: [255.0, 255.0, 255.0], + volume: 1.0, }) } } well_infos }; - // Plate Frame painter.rect_stroke( egui::Rect { @@ -274,11 +306,11 @@ fn add_plate_sub( ); // Draw wells - for c_row in 0..rows { - for c_column in 0..columns { + for c_row in 1..=rows { + for c_column in 1..=columns { let center = egui::pos2( - start_x + radius + 2.0 * radius * c_column as f32, - start_y + radius + 2.0 * radius * c_row as f32, + start_x + radius + 2.0 * radius * (c_column - 1) as f32, + start_y + radius + 2.0 * radius * (c_row - 1) as f32, ); // @@ -286,7 +318,7 @@ fn add_plate_sub( // if let Some(well_info) = - well_infos[c_row as usize * columns as usize + c_column as usize] + well_infos[(c_row - 1) as usize * columns as usize + (c_column - 1) as usize] { painter.circle_filled(center, radius * 0.80, f64_to_color32(well_info.color)); } @@ -301,8 +333,8 @@ fn add_plate_sub( if current_selection.as_ref().is_some_and(|x| { x.contains_well( &Well { - row: c_row + 1, - col: c_column + 1, + row: c_row, + col: c_column, }, None, ) @@ -364,43 +396,16 @@ pub fn add_plate( ui: &mut egui::Ui, state: &mut PlateUiState, ) { - match pf { - PlateFormat::W96 => add_plate_sub( - size, - 8, - 12, - transfers, - plate_type, - ordered_ids, - cache, - current_transfer_state, - ui, - state, - ), - PlateFormat::W384 => add_plate_sub( - size, - 16, - 24, - transfers, - plate_type, - ordered_ids, - cache, - current_transfer_state, - ui, - state, - ), - PlateFormat::W1536 => add_plate_sub( - size, - 32, - 48, - transfers, - plate_type, - ordered_ids, - cache, - current_transfer_state, - ui, - state, - ), - _ => unimplemented!(), - } + add_plate_sub( + size, + pf.rows(), + pf.columns(), + transfers, + plate_type, + ordered_ids, + cache, + current_transfer_state, + ui, + state, + ); } diff --git a/plate-tool-lib/src/plate.rs b/plate-tool-lib/src/plate.rs index d728f28..a587a20 100644 --- a/plate-tool-lib/src/plate.rs +++ b/plate-tool-lib/src/plate.rs @@ -114,4 +114,10 @@ impl PlateFormat { PlateFormat::W3456 => (48, 72), } } + pub fn rows(&self) -> u8 { + self.size().0 + } + pub fn columns(&self) -> u8 { + self.size().1 + } }