Files
mtgcount-rs-2/src/touch.rs
2025-12-01 00:23:08 -06:00

406 lines
17 KiB
Rust

use crate::{display::ColorScheme, state::{CommanderDamage, Game, MainScreenItem, Screen, SettingScreenEntry, SettingScreenItem, SystemState}};
const CMDDMGLIST: [MainScreenItem;6] = [
MainScreenItem::Dmg1,
MainScreenItem::Dmg2,
MainScreenItem::Dmg3,
MainScreenItem::Dmg4,
MainScreenItem::Dmg5,
MainScreenItem::Dmg6,
];
pub fn get_touch_action(x: f32, y: f32, gesture: u8, ctx: &mut SystemState) -> () {
let x = x - 120.;
let y = -(y - 120.);
let touch_rad = (x*x)+(y*y);
let angle;
let next_state;
if (gesture == 0x3) | (gesture == 0x4) {
ctx.screen = match &ctx.screen {
Screen::Main(_) => Screen::Settings(SettingScreenItem { entry: SettingScreenEntry::NewGame, inner: false , prev: None}),
Screen::Settings(_) => Screen::Main(MainScreenItem::Life),
};
return;
}
match &ctx.screen {
Screen::Main(selected) => {
let mut bottom_selectable_list: [Option<MainScreenItem>;5] = [const {None};5];
let mut pos = 0;
if ctx.settings.show_cmd_tax {
bottom_selectable_list[pos] = Some(crate::state::MainScreenItem::Tax);
pos += 1;
}
if ctx.settings.show_energy {
bottom_selectable_list[pos] = Some(crate::state::MainScreenItem::Energy);
pos+=1;
};
if ctx.settings.show_experience {
bottom_selectable_list[pos] = Some(crate::state::MainScreenItem::Experience);
pos+=1;
};
if ctx.settings.show_tickets {
bottom_selectable_list[pos] = Some(crate::state::MainScreenItem::Tickets);
pos+=1;
};
if ctx.settings.show_infect {
bottom_selectable_list[pos] = Some(crate::state::MainScreenItem::Poison);
};
let bottom_count = bottom_selectable_list.iter().fold(0, |acc, x| acc+x.is_some() as u8);
if touch_rad > (70.*70.) {
angle = atan2_norm(y, x)*90.;
//ctx.game.life = angle as i32; //debug
let top;
let check_angles = if y >= 0. {
if ctx.settings.opponenets == 0 {
return;
}
top = true;
ctx.positions.get_top_list(ctx.settings.opponenets)
} else {
if bottom_count == 0 {
return;
}
top = false;
ctx.positions.get_bottom_list(bottom_count)
};
let touch_item = match check_angles.iter().position(|x| (x.angle.to_degrees()-angle).abs()<15.) {
Some(loc) => loc,
None => return,
};
let sel_match = if top {
Some(CMDDMGLIST.into_iter().nth(touch_item).unwrap_or(MainScreenItem::Dmg1))
} else {
bottom_selectable_list[touch_item]
};
if let Some(selected_item) = sel_match {
if selected_item == *selected {
next_state = Screen::Main(MainScreenItem::Life);
} else {
next_state = Screen::Main(selected_item);
}
} else {
next_state = Screen::Main(MainScreenItem::Life);
}
} else {
match selected {
crate::state::MainScreenItem::Life => {
let d = touch_inc_dec(y, gesture);
ctx.game.life = ctx.game.life.saturating_add(d as i32);
},
crate::state::MainScreenItem::Dmg1 => {
cmd_dmg_w_swap(ctx, x, y, gesture, 0);
},
crate::state::MainScreenItem::Dmg2 => {
cmd_dmg_w_swap(ctx, x, y, gesture, 1);
},
crate::state::MainScreenItem::Dmg3 => {
cmd_dmg_w_swap(ctx, x, y, gesture, 2);
},
crate::state::MainScreenItem::Dmg4 => {
cmd_dmg_w_swap(ctx, x, y, gesture, 3);
},
crate::state::MainScreenItem::Dmg5 => {
cmd_dmg_w_swap(ctx, x, y, gesture, 4);
},
crate::state::MainScreenItem::Dmg6 => {
cmd_dmg_w_swap(ctx, x, y, gesture, 5);
},
crate::state::MainScreenItem::Tax => {
cmd_tax_w_swap(ctx, x, y, gesture);
},
crate::state::MainScreenItem::Energy => {
let d = touch_inc_dec(y, gesture);
ctx.game.energy = ctx.game.energy.saturating_add_signed(d.into());
},
crate::state::MainScreenItem::Experience => {
let d = touch_inc_dec(y, gesture);
ctx.game.experience = ctx.game.experience.saturating_add_signed(d.into());
},
crate::state::MainScreenItem::Tickets => {
let d = touch_inc_dec(y, gesture);
ctx.game.tickets = ctx.game.tickets.saturating_add_signed(d.into());
},
crate::state::MainScreenItem::Poison => {
let d = touch_inc_dec(y, gesture);
ctx.game.infect = ctx.game.infect.saturating_add_signed(d.into());
},
};
next_state = ctx.screen;
};
},
Screen::Settings(selected) => {
if !selected.inner {
if gesture == 0x01_u8 {
next_state = Screen::Settings(SettingScreenItem { entry: selected.entry.prev(), inner: false, prev: selected.prev });
} else if gesture == 0x02_u8 {
next_state = Screen::Settings(SettingScreenItem { entry: selected.entry.next(), inner: false, prev: selected.prev });
} else {
if y > 55. {
next_state = Screen::Settings(SettingScreenItem { entry: selected.entry.prev(), inner: false, prev: selected.prev});
} else if y < -55. {
next_state = Screen::Settings(SettingScreenItem { entry: selected.entry.next(), inner: false, prev: selected.prev });
} else {
let prev = match selected.entry {
SettingScreenEntry::NewGame => None,
SettingScreenEntry::Opponents => Some(ctx.settings.opponenets as u32),
SettingScreenEntry::StartingLife => Some(ctx.settings.starting_life as u32),
SettingScreenEntry::Colors => Some(Into::<u8>::into(ctx.settings.color_scheme) as u32),
SettingScreenEntry::Brightness => Some(ctx.settings.brightness.into()),
SettingScreenEntry::ShowTax => Some(ctx.settings.show_cmd_tax as u32),
SettingScreenEntry::ShowEnergy => Some(ctx.settings.show_energy as u32),
SettingScreenEntry::ShowExperience => Some(ctx.settings.show_experience as u32),
SettingScreenEntry::ShowTickets => Some(ctx.settings.show_tickets as u32),
SettingScreenEntry::ShowPoison => Some(ctx.settings.show_infect as u32),
};
next_state = Screen::Settings(SettingScreenItem { entry: selected.entry, inner: true, prev: prev});
}
}
} else {
if x < -75. {
match selected.entry {
SettingScreenEntry::NewGame => {
ctx.game = Game {
life: ctx.settings.starting_life,
cmd_dmg: [CommanderDamage{main: 0, partner: 0, is_partner: false};6],
cmd_tax: CommanderDamage { main: 0, partner: 0, is_partner: false },
infect: 0,
energy: 0,
experience: 0,
tickets: 0,
monarch: false,
};
next_state = Screen::Main(MainScreenItem::Life);
},
_ => {
next_state = Screen::Settings(SettingScreenItem { entry: selected.entry, inner: false, prev: None })
}
}
} else if x > 75. {
match selected.entry {
SettingScreenEntry::NewGame => {},
SettingScreenEntry::Opponents => {
ctx.settings.opponenets = selected.prev.unwrap_or(0) as u8;
},
SettingScreenEntry::StartingLife => {
ctx.settings.starting_life = selected.prev.unwrap_or(0) as i32;
},
SettingScreenEntry::Colors => {
ctx.settings.color_scheme =Into::<ColorScheme>::into(selected.prev.unwrap_or(0) as u8);
},
SettingScreenEntry::Brightness => {
ctx.settings.brightness = selected.prev.unwrap_or(0).into();
},
SettingScreenEntry::ShowTax => {
ctx.settings.show_cmd_tax = selected.prev.unwrap_or_default() != 0;
},
SettingScreenEntry::ShowEnergy => {
ctx.settings.show_energy = selected.prev.unwrap_or_default() != 0;
},
SettingScreenEntry::ShowExperience => {
ctx.settings.show_experience = selected.prev.unwrap_or_default() != 0;
},
SettingScreenEntry::ShowTickets => {
ctx.settings.show_tickets = selected.prev.unwrap_or_default() != 0;
},
SettingScreenEntry::ShowPoison => {
ctx.settings.show_infect = selected.prev.unwrap_or_default() != 0;
},
}
next_state = Screen::Settings(SettingScreenItem { entry: selected.entry, inner: false, prev: None })
} else {
match selected.entry {
SettingScreenEntry::NewGame => {
},
SettingScreenEntry::Opponents => {
ctx.settings.opponenets = ctx.settings.opponenets.saturating_add_signed(touch_inc_dec(y, gesture));
},
SettingScreenEntry::StartingLife => {
ctx.settings.starting_life = ctx.settings.starting_life.saturating_add(touch_inc_dec(y, gesture) as i32);
},
SettingScreenEntry::Colors => {
if y > 40. {
ctx.settings.color_scheme = ctx.settings.color_scheme.dec();
} else if y < -40. {
ctx.settings.color_scheme = ctx.settings.color_scheme.inc();
}
},
SettingScreenEntry::Brightness => {
let tmp = touch_inc_dec(y, gesture);
if tmp > 0 {
ctx.settings.brightness = ctx.settings.brightness.inc();
} else {
ctx.settings.brightness = ctx.settings.brightness.dec();
}
},
SettingScreenEntry::ShowTax => {
let det = select_button(x, y, gesture);
if let Some(i) = det {
ctx.settings.show_cmd_tax = i;
}
},
SettingScreenEntry::ShowEnergy => {
let det = select_button(x, y, gesture);
if let Some(i) = det {
ctx.settings.show_energy = i;
}
},
SettingScreenEntry::ShowExperience => {
let det = select_button(x, y, gesture);
if let Some(i) = det {
ctx.settings.show_experience = i;
}
},
SettingScreenEntry::ShowTickets => {
let det = select_button(x, y, gesture);
if let Some(i) = det {
ctx.settings.show_tickets = i;
}
},
SettingScreenEntry::ShowPoison => {
let det = select_button(x, y, gesture);
if let Some(i) = det {
ctx.settings.show_infect = i;
}
},
}
next_state = Screen::Settings(SettingScreenItem { entry: selected.entry, inner: selected.inner, prev: selected.prev })
}
}
}
}
ctx.screen = next_state;
}
/// Approximates `atan2(y,x)` normalized to the `[0, 4)` range with a maximum
/// error of `0.1620` degrees.
fn atan2_norm(lhs: f32, rhs: f32) -> f32 {
const SIGN_MASK: u32 = 0x8000_0000;
const B: f32 = 0.596_227;
let y = lhs;
let x = rhs;
// Extract sign bits from floating point values
let ux_s = SIGN_MASK & x.to_bits();
let uy_s = SIGN_MASK & y.to_bits();
// Determine quadrant offset
let q = ((!ux_s & uy_s) >> 29 | ux_s >> 30) as f32;
// Calculate arctangent in the first quadrant
let bxy_a = (B * x * y).abs();
let n = bxy_a + y * y;
let atan_1q = n / (x * x + bxy_a + n);
// Translate it to the proper quadrant
let uatan_2q = (ux_s ^ uy_s) | atan_1q.to_bits();
q + f32::from_bits(uatan_2q)
}
fn touch_inc_dec(y: f32, gesture: u8) -> i8 {
if gesture == 0x05 {
if y >= 0. {
1
} else {
-1
}
} else if gesture == 0x02 {
5
} else if gesture == 0x01 {
-5
} else {
0
}
}
fn touch_left_right(x: f32, y: f32, gesture: u8) -> (i8, bool) {
if x <= 0. {
(touch_inc_dec(y, gesture), true)
} else {
(touch_inc_dec(y, gesture), false)
}
}
fn cmd_dmg_calc(ctx: &mut SystemState, x: f32, y: f32, gesture: u8, pos: usize) {
if ctx.game.cmd_dmg[pos].is_partner {
let (d, left) = touch_left_right(x, y, gesture);
if left {
ctx.game.cmd_dmg[pos].main = ctx.game.cmd_dmg[pos].main.saturating_add_signed(d);
} else {
ctx.game.cmd_dmg[pos].partner = ctx.game.cmd_dmg[pos].partner.saturating_add_signed(d);
}
} else {
let d = touch_inc_dec(y, gesture);
ctx.game.cmd_dmg[pos].main = ctx.game.cmd_dmg[pos].main.saturating_add_signed(d);
}
}
fn cmd_tax_calc(ctx: &mut SystemState, x: f32, y: f32, gesture: u8) {
if ctx.game.cmd_tax.is_partner {
let (mut d, left) = touch_left_right(x, y, gesture);
if d >= 0 {
d = 2;
} else {
d =-2;
}
if left {
ctx.game.cmd_tax.main = ctx.game.cmd_tax.main.saturating_add_signed(d);
} else {
ctx.game.cmd_tax.partner = ctx.game.cmd_tax.partner.saturating_add_signed(d);
}
} else {
let mut d = touch_inc_dec(y, gesture);
if d >= 0 {
d = 2;
} else {
d =-2;
}
ctx.game.cmd_tax.main = ctx.game.cmd_tax.main.saturating_add_signed(d);
}
}
/// true is left selection false is right selection
fn select_button(x: f32, y: f32, _gesture: u8) -> Option<bool> {
if (y<60.) & (y>-60.) {
if x<=0. {
Some(true)
} else {
Some(false)
}
} else {
None
}
}
fn cmd_dmg_w_swap(ctx: &mut SystemState, x: f32, y: f32, gesture: u8, pos: usize) {
if (x>-20.) & (x<20.) & (y< -30.)&(y>-50.) {
ctx.game.cmd_dmg[pos].is_partner = !ctx.game.cmd_dmg[pos].is_partner;
} else {
cmd_dmg_calc(ctx, x, y, gesture, pos);
}
}
fn cmd_tax_w_swap(ctx: &mut SystemState, x: f32, y: f32, gesture: u8) {
if (x>-20.) & (x<20.) & (y< -30.)&(y>-50.) {
ctx.game.cmd_tax.is_partner = !ctx.game.cmd_tax.is_partner;
} else {
cmd_tax_calc(ctx, x, y, gesture);
}
}