@ -1,11 +1,11 @@
//! Mii Selector applet.
//! Mii Selector applet.
//!
//!
//! This applet opens a window on the console's bottom screen which lets the player/user choose a Mii from the ones present on their console.
//! This applet opens a window on the console's bottom screen which lets the player/user choose a Mii from the ones present on their console.
//! The application can access the selected Mii's data via the use of the [`mii`](crate::mii) module .
//! The selected Mii is readable as a [`MiiData`](crate::mii::MiiData) .
use crate ::mii ::MiiData ;
use crate ::mii ::MiiData ;
use bitflags ::bitflags ;
use bitflags ::bitflags ;
use std ::ffi ::CString ;
use std ::{ ffi ::CString , error ::Error , fmt } ;
/// Index of a Mii used to configure some parameters of the Mii Selector.
/// Index of a Mii used to configure some parameters of the Mii Selector.
#[ derive(Debug, Clone, Copy, Eq, PartialEq) ]
#[ derive(Debug, Clone, Copy, Eq, PartialEq) ]
@ -16,7 +16,7 @@ pub enum Index {
All ,
All ,
}
}
/// The type of a Mii with their respective data
/// The type of a Mii.
#[ derive(Debug, Clone, Eq, PartialEq) ]
#[ derive(Debug, Clone, Eq, PartialEq) ]
pub enum MiiType {
pub enum MiiType {
/// Guest Mii.
/// Guest Mii.
@ -31,29 +31,56 @@ pub enum MiiType {
}
}
bitflags ! {
bitflags ! {
/// Options for the Mii Selector
/// Options to configure the [MiiSelector].
///
/// <h1>Example</h1>
///
/// ```no_run
/// # use std::error::Error;
/// # fn main() -> Result<(), Box<dyn Error>> {
/// #
/// use ctru::applets::mii_selector::{MiiSelector, Options};
///
/// // Setup a `MiiSelector` that can be cancelled and that makes Guest Miis available to select.
/// let opts = Options::ENABLE_CANCEL & Options::ENABLE_GUESTS;
///
/// let mut mii_selector = MiiSelector::new();
/// mii_selector.set_options(opts);
///
/// let result = mii_selector.launch()?;
/// #
/// # Ok(())
/// # }
/// ```
#[ derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone, Copy) ]
pub struct Options : u32 {
pub struct Options : u32 {
/// Show the cancel button
/// Show the cancel button.
const MII_SELECTOR_CANCEL = ctru_sys ::MIISELECTOR_CANCEL ;
const ENAB LE_CANCEL = ctru_sys ::MIISELECTOR_CANCEL ;
/// Make guest Miis selectable
/// Make guest Miis available to select.
const MII_SELECTOR_GUESTS = ctru_sys ::MIISELECTOR_GUESTS ;
const ENAB LE_GUESTS = ctru_sys ::MIISELECTOR_GUESTS ;
/// Show on the top screen
/// Show on the top screen.
const MII_SELECTOR_TOP = ctru_sys ::MIISELECTOR_TOP ;
const USE_TOP_SCREEN = ctru_sys ::MIISELECTOR_TOP ;
/// Start on the guest's page
/// Start on the guests ' page. Requires [Options::ENABLE_GUESTS].
const MII_SELECTOR_GUEST_START = ctru_sys ::MIISELECTOR_GUESTSTART ;
const START_WITH_GUESTS = ctru_sys ::MIISELECTOR_GUESTSTART ;
}
}
}
}
/// An instance of the Mii Selector
/// Configuration object to setup the Mii Selector applet.
///
///
/// # Example
/// # Example
/// ```
/// ```no_run
/// # use std::error::Error;
/// # fn main() -> Result<(), Box<dyn Error>> {
/// #
/// use ctru::applets::mii_selector::MiiSelector;
/// use ctru::applets::mii_selector::MiiSelector;
///
///
/// let mut mii_selector = MiiSelector::new();
/// let mut mii_selector = MiiSelector::new();
/// mii_selector.set_title("Example Mii selector");
/// mii_selector.set_title("Example Mii S elector");
///
///
/// let result = mii_selector.launch().unwrap();
/// let result = mii_selector.launch()?;
/// #
/// # Ok(())
/// # }
/// ```
/// ```
#[ doc(alias = " MiiSelectorConf " ) ]
#[ doc(alias = " MiiSelectorConf " ) ]
#[ derive(Clone, Debug) ]
#[ derive(Clone, Debug) ]
@ -61,27 +88,27 @@ pub struct MiiSelector {
config : Box < ctru_sys ::MiiSelectorConf > ,
config : Box < ctru_sys ::MiiSelectorConf > ,
}
}
/// Return value from a MiiSelector's launch
/// Return value of a successful [MiiSelector::launch()].
#[ non_exhaustive ]
#[ non_exhaustive ]
#[ derive(Clone, Debug) ]
#[ derive(Clone, Debug) ]
pub struct SelectionResult {
pub struct Selection {
/// Data regarding the selected Mii.
/// Data of the selected Mii.
pub mii_data : MiiData ,
pub mii_data : MiiData ,
/// Type of the selected Mii.
/// Type of the selected Mii.
pub mii_type : MiiType ,
pub mii_type : MiiType ,
}
}
/// Error type for the Mii selector
/// Error returned by an unsuccessful [MiiSelector::launch()].
#[ derive(Copy, Clone, Debug, Eq, PartialEq) ]
#[ derive(Copy, Clone, Debug, Eq, PartialEq) ]
pub enum LaunchError {
pub enum LaunchError {
/// The selected Mii's data is corrupt in some way
/// The selected Mii's data is corrupt in some way.
InvalidChecksum ,
InvalidChecksum ,
/// Either the user cancelled the selection (see [Options::MII_S ELECTOR _CANCEL]), or no valid Miis were available to select
/// Either the user cancelled the selection (see [Options::ENAB LE_CANCEL]), or no valid Miis were available to select.
NoMiiSelected ,
NoMiiSelected ,
}
}
impl MiiSelector {
impl MiiSelector {
/// Initializes a Mii Selector
/// Initialize a new configuration for the Mii Selector applet.
#[ doc(alias = " miiSelectorInit " ) ]
#[ doc(alias = " miiSelectorInit " ) ]
pub fn new ( ) -> Self {
pub fn new ( ) -> Self {
let mut config = Box ::< ctru_sys ::MiiSelectorConf > ::default ( ) ;
let mut config = Box ::< ctru_sys ::MiiSelectorConf > ::default ( ) ;
@ -91,9 +118,9 @@ impl MiiSelector {
Self { config }
Self { config }
}
}
/// Set the title of the Mii Selector.
/// Set the title of the Mii Selector window .
///
///
/// This function would panic if the given ``&str` ` contains NUL bytes.
/// This function will panic if the given `&str ` contains NUL bytes.
#[ doc(alias = " miiSelectorSetTitle " ) ]
#[ doc(alias = " miiSelectorSetTitle " ) ]
pub fn set_title ( & mut self , text : & str ) {
pub fn set_title ( & mut self , text : & str ) {
// This can only fail if the text contains NUL bytes in the string... which seems
// This can only fail if the text contains NUL bytes in the string... which seems
@ -104,13 +131,15 @@ impl MiiSelector {
}
}
}
}
/// Set the options of the Mii Selector
/// Set the options of the Mii Selector.
///
/// This will overwrite any previously saved options.
#[ doc(alias = " miiSelectorSetOptions " ) ]
#[ doc(alias = " miiSelectorSetOptions " ) ]
pub fn set_options ( & mut self , options : Options ) {
pub fn set_options ( & mut self , options : Options ) {
unsafe { ctru_sys ::miiSelectorSetOptions ( self . config . as_mut ( ) , options . bits ) }
unsafe { ctru_sys ::miiSelectorSetOptions ( self . config . as_mut ( ) , options . bits ( ) ) }
}
}
/// Whitelist a guest Mii
/// Whitelist a guest Mii based on its index.
#[ doc(alias = " miiSelectorWhitelistGuestMii " ) ]
#[ doc(alias = " miiSelectorWhitelistGuestMii " ) ]
pub fn whitelist_guest_mii ( & mut self , mii_index : Index ) {
pub fn whitelist_guest_mii ( & mut self , mii_index : Index ) {
let index = match mii_index {
let index = match mii_index {
@ -121,7 +150,7 @@ impl MiiSelector {
unsafe { ctru_sys ::miiSelectorWhitelistGuestMii ( self . config . as_mut ( ) , index ) }
unsafe { ctru_sys ::miiSelectorWhitelistGuestMii ( self . config . as_mut ( ) , index ) }
}
}
/// Blacklist a guest Mii
/// Blacklist a guest Mii based on its index.
#[ doc(alias = " miiSelectorBlacklistGuestMii " ) ]
#[ doc(alias = " miiSelectorBlacklistGuestMii " ) ]
pub fn blacklist_guest_mii ( & mut self , mii_index : Index ) {
pub fn blacklist_guest_mii ( & mut self , mii_index : Index ) {
let index = match mii_index {
let index = match mii_index {
@ -132,7 +161,7 @@ impl MiiSelector {
unsafe { ctru_sys ::miiSelectorBlacklistGuestMii ( self . config . as_mut ( ) , index ) }
unsafe { ctru_sys ::miiSelectorBlacklistGuestMii ( self . config . as_mut ( ) , index ) }
}
}
/// Whitelist a user Mii
/// Whitelist a user Mii based on its index.
#[ doc(alias = " miiSelectorWhitelistUserMii " ) ]
#[ doc(alias = " miiSelectorWhitelistUserMii " ) ]
pub fn whitelist_user_mii ( & mut self , mii_index : Index ) {
pub fn whitelist_user_mii ( & mut self , mii_index : Index ) {
let index = match mii_index {
let index = match mii_index {
@ -143,7 +172,7 @@ impl MiiSelector {
unsafe { ctru_sys ::miiSelectorWhitelistUserMii ( self . config . as_mut ( ) , index ) }
unsafe { ctru_sys ::miiSelectorWhitelistUserMii ( self . config . as_mut ( ) , index ) }
}
}
/// Blacklist a user Mii
/// Blacklist a user Mii based on its index.
#[ doc(alias = " miiSelectorBlacklistUserMii " ) ]
#[ doc(alias = " miiSelectorBlacklistUserMii " ) ]
pub fn blacklist_user_mii ( & mut self , mii_index : Index ) {
pub fn blacklist_user_mii ( & mut self , mii_index : Index ) {
let index = match mii_index {
let index = match mii_index {
@ -154,8 +183,9 @@ impl MiiSelector {
unsafe { ctru_sys ::miiSelectorBlacklistUserMii ( self . config . as_mut ( ) , index ) }
unsafe { ctru_sys ::miiSelectorBlacklistUserMii ( self . config . as_mut ( ) , index ) }
}
}
/// Set where the cursor will be.
/// Set where the cursor will start at.
/// If there's no Mii at that index, the cursor will start at the Mii with the index 0
///
/// If there's no Mii at that index, the cursor will start at the Mii with the index 0.
pub fn set_initial_index ( & mut self , index : usize ) {
pub fn set_initial_index ( & mut self , index : usize ) {
// This function is static inline in libctru
// This function is static inline in libctru
// https://github.com/devkitPro/libctru/blob/af5321c78ee5c72a55b526fd2ed0d95ca1c05af9/libctru/include/3ds/applets/miiselector.h#L155
// https://github.com/devkitPro/libctru/blob/af5321c78ee5c72a55b526fd2ed0d95ca1c05af9/libctru/include/3ds/applets/miiselector.h#L155
@ -163,9 +193,10 @@ impl MiiSelector {
}
}
/// Launch the Mii Selector.
/// Launch the Mii Selector.
/// Returns an error when the checksum of the Mii is invalid.
///
/// Depending on the configuration, the Mii Selector window will appear either on the bottom screen (default behaviour) or the top screen (see [Options::USE_TOP_SCREEN]).
#[ doc(alias = " miiSelectorLaunch " ) ]
#[ doc(alias = " miiSelectorLaunch " ) ]
pub fn launch ( & mut self ) -> Result < SelectionResult , LaunchError > {
pub fn launch ( & mut self ) -> Result < Selection , LaunchError > {
let mut return_val = Box ::< ctru_sys ::MiiSelectorReturn > ::default ( ) ;
let mut return_val = Box ::< ctru_sys ::MiiSelectorReturn > ::default ( ) ;
unsafe { ctru_sys ::miiSelectorLaunch ( self . config . as_mut ( ) , return_val . as_mut ( ) ) }
unsafe { ctru_sys ::miiSelectorLaunch ( self . config . as_mut ( ) , return_val . as_mut ( ) ) }
@ -187,12 +218,23 @@ impl Default for MiiSelector {
}
}
}
}
impl From < ctru_sys ::MiiSelectorReturn > for SelectionResult {
impl fmt ::Display for LaunchError {
fn fmt ( & self , f : & mut std ::fmt ::Formatter < ' _ > ) -> std ::fmt ::Result {
match self {
Self ::InvalidChecksum = > write! ( f , "selected mii has invalid checksum" ) ,
Self ::NoMiiSelected = > write! ( f , "no mii was selected" ) ,
}
}
}
impl Error for LaunchError { }
impl From < ctru_sys ::MiiSelectorReturn > for Selection {
fn from ( ret : ctru_sys ::MiiSelectorReturn ) -> Self {
fn from ( ret : ctru_sys ::MiiSelectorReturn ) -> Self {
let raw_mii_data = ret . mii ;
let raw_mii_data = ret . mii ;
let mut guest_mii_name = ret . guest_mii_name ;
let mut guest_mii_name = ret . guest_mii_name ;
SelectionResult {
Selection {
mii_data : raw_mii_data . into ( ) ,
mii_data : raw_mii_data . into ( ) ,
mii_type : if ret . guest_mii_index ! = 0xFFFFFFFF {
mii_type : if ret . guest_mii_index ! = 0xFFFFFFFF {
MiiType ::Guest {
MiiType ::Guest {