-
Notifications
You must be signed in to change notification settings - Fork 25
Implement Mii Selector applet #78
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
27 commits
Select commit
Hold shift + click to select a range
32db2c6
Initial mii selector implementation
Techie-Pi b33411f
Fix bug with author and impl ``From`` for ``MiiConfigIndex``
Techie-Pi 4b43561
Add ``mii_selector`` example
Techie-Pi de51d97
Cargo fmt
Techie-Pi 3c9bd8f
Implement MiiData parsing
Techie-Pi e6cc659
Rename Mii Selector example
Techie-Pi 19ebd49
Add MiiData example
Techie-Pi 0a6654a
Clippy
Techie-Pi 1dbb576
Remove comment
Techie-Pi 4b99e92
Cargo fmt & clippy
Techie-Pi 1d92f0f
Apply suggestions
Techie-Pi fe0d03c
Fix Mii Selector example
Techie-Pi be87134
Fix ``RegionLock::None`` refactor
Techie-Pi 7ca152a
Apply some suggestions
Techie-Pi a9569b5
Improve ``mii-selector`` example and a few fixes
Techie-Pi d7a6843
Clippy & cargo fmt
Techie-Pi dd5b9f7
Fix issue related to endianness and improve wording
Techie-Pi 91f65a0
Add docs
Techie-Pi 441ab93
Document values sometimes not being straight forward
Techie-Pi f8baff0
Cargo fmt
Techie-Pi 1310507
Document ``set_title`` input and NUL bytes
Techie-Pi 4d88ba9
Fix rustdoc link
Techie-Pi 7c24404
Move some styles inside the their details struct for consistency
Techie-Pi 16f8de4
Address comments
Techie-Pi accf99b
Apply cargo check suggestions
Techie-Pi 01e9c70
Address comments
Techie-Pi 42345d1
Rename a few variables and document skipped bits
Techie-Pi File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
use ctru::applets::mii_selector::MiiSelector; | ||
use ctru::prelude::*; | ||
|
||
fn main() { | ||
ctru::init(); | ||
|
||
let gfx = Gfx::init().expect("Couldn't obtain GFX controller"); | ||
let hid = Hid::init().expect("Couldn't obtain HID controller"); | ||
let apt = Apt::init().expect("Couldn't obtain APT controller"); | ||
let _console = Console::init(gfx.top_screen.borrow_mut()); | ||
|
||
let mut mii_selector = MiiSelector::init(); | ||
mii_selector.set_initial_index(3); | ||
mii_selector.blacklist_user_mii(0.into()); | ||
mii_selector.set_title("Great Mii Selector!"); | ||
|
||
let result = mii_selector.launch().unwrap(); | ||
|
||
println!("Is Mii selected?: {:?}", result.is_mii_selected); | ||
println!("Mii type: {:?}", result.mii_type); | ||
println!("Name: {:?}", result.mii_data.name); | ||
println!("Author: {:?}", result.mii_data.author_name); | ||
println!( | ||
"Does the Mii have moles?: {:?}", | ||
result.mii_data.mole_details.is_enabled | ||
); | ||
|
||
// Main loop | ||
while apt.main_loop() { | ||
//Scan all the inputs. This should be done once for each frame | ||
hid.scan_input(); | ||
|
||
if hid.keys_down().contains(KeyPad::KEY_START) { | ||
break; | ||
} | ||
// Flush and swap framebuffers | ||
gfx.flush_buffers(); | ||
gfx.swap_buffers(); | ||
|
||
//Wait for VBlank | ||
gfx.wait_for_vblank(); | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,186 @@ | ||
//! Mii Selector applet | ||
//! | ||
//! This module contains the methods to launch the Mii Selector. | ||
|
||
use crate::mii::MiiData; | ||
use bitflags::bitflags; | ||
use std::ffi::CString; | ||
|
||
/// Index of a Mii used to configure some parameters of the Mii Selector | ||
/// Can be either a single index, or _all_ Miis | ||
#[derive(Debug, Clone)] | ||
pub enum MiiConfigIndex { | ||
Index(u32), | ||
All, | ||
} | ||
|
||
/// The type of a Mii with their respective data | ||
#[derive(Debug, Clone)] | ||
pub enum MiiType { | ||
Guest { index: u32, name: String }, | ||
User, | ||
} | ||
|
||
bitflags! { | ||
/// Options for the Mii Selector | ||
pub struct Options: u32 { | ||
/// Show the cancel button | ||
const MII_SELECTOR_CANCEL = ctru_sys::MIISELECTOR_CANCEL; | ||
/// Make guest Miis selectable | ||
const MII_SELECTOR_GUESTS = ctru_sys::MIISELECTOR_GUESTS; | ||
/// Show on the top screen | ||
const MII_SELECTOR_TOP = ctru_sys::MIISELECTOR_TOP; | ||
/// Start on the guest's page | ||
const MII_SELECTOR_GUEST_START = ctru_sys::MIISELECTOR_GUESTSTART; | ||
} | ||
} | ||
|
||
/// An instance of the Mii Selector | ||
/// | ||
/// # Example | ||
/// ``` | ||
/// use ctru::applets::mii_selector::MiiSelector; | ||
/// | ||
/// let mut mii_selector = MiiSelector::init(); | ||
/// mii_selector.set_title("Example Mii selector"); | ||
/// | ||
/// let result = mii_selector.launch().unwrap(); | ||
/// ``` | ||
#[derive(Clone, Debug)] | ||
pub struct MiiSelector { | ||
config: Box<ctru_sys::MiiSelectorConf>, | ||
} | ||
|
||
/// Return value from a MiiSelector's launch | ||
#[non_exhaustive] | ||
#[derive(Clone, Debug)] | ||
pub struct MiiSelectorReturn { | ||
Techie-Pi marked this conversation as resolved.
Show resolved
Hide resolved
|
||
pub mii_data: MiiData, | ||
pub is_mii_selected: bool, | ||
pub mii_type: MiiType, | ||
} | ||
|
||
/// Error type for the Mii selector | ||
#[derive(Copy, Clone, Debug, Eq, PartialEq)] | ||
pub enum MiiLaunchError { | ||
InvalidChecksum, | ||
} | ||
Techie-Pi marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
impl MiiSelector { | ||
/// Initializes a Mii Selector | ||
pub fn init() -> Self { | ||
let mut config = Box::<ctru_sys::MiiSelectorConf>::default(); | ||
unsafe { | ||
ctru_sys::miiSelectorInit(config.as_mut()); | ||
} | ||
Self { config } | ||
} | ||
|
||
/// Set the title of the Mii Selector. | ||
/// | ||
/// This function would panic if the given ``&str`` contains NUL bytes. | ||
pub fn set_title(&mut self, text: &str) { | ||
// This can only fail if the text contains NUL bytes in the string... which seems | ||
// unlikely and is documented | ||
let c_text = CString::new(text).expect("Failed to convert the title text into a CString"); | ||
unsafe { | ||
ctru_sys::miiSelectorSetTitle(self.config.as_mut(), c_text.as_ptr()); | ||
} | ||
} | ||
|
||
/// Set the options of the Mii Selector | ||
pub fn set_options(&mut self, options: Options) { | ||
unsafe { ctru_sys::miiSelectorSetOptions(self.config.as_mut(), options.bits) } | ||
} | ||
|
||
/// Whitelist a guest Mii | ||
pub fn whitelist_guest_mii(&mut self, mii_index: MiiConfigIndex) { | ||
let index = match mii_index { | ||
MiiConfigIndex::Index(i) => i, | ||
MiiConfigIndex::All => ctru_sys::MIISELECTOR_GUESTMII_SLOTS, | ||
}; | ||
|
||
unsafe { ctru_sys::miiSelectorWhitelistGuestMii(self.config.as_mut(), index) } | ||
} | ||
|
||
/// Blacklist a guest Mii | ||
pub fn blacklist_guest_mii(&mut self, mii_index: MiiConfigIndex) { | ||
let index = match mii_index { | ||
MiiConfigIndex::Index(i) => i, | ||
MiiConfigIndex::All => ctru_sys::MIISELECTOR_GUESTMII_SLOTS, | ||
}; | ||
|
||
unsafe { ctru_sys::miiSelectorBlacklistGuestMii(self.config.as_mut(), index) } | ||
} | ||
|
||
/// Whitelist a user Mii | ||
pub fn whitelist_user_mii(&mut self, mii_index: MiiConfigIndex) { | ||
let index = match mii_index { | ||
MiiConfigIndex::Index(i) => i, | ||
MiiConfigIndex::All => ctru_sys::MIISELECTOR_USERMII_SLOTS, | ||
}; | ||
|
||
unsafe { ctru_sys::miiSelectorWhitelistUserMii(self.config.as_mut(), index) } | ||
} | ||
|
||
/// Blacklist a user Mii | ||
pub fn blacklist_user_mii(&mut self, mii_index: MiiConfigIndex) { | ||
let index = match mii_index { | ||
MiiConfigIndex::Index(i) => i, | ||
MiiConfigIndex::All => ctru_sys::MIISELECTOR_USERMII_SLOTS, | ||
}; | ||
|
||
unsafe { ctru_sys::miiSelectorBlacklistUserMii(self.config.as_mut(), index) } | ||
} | ||
|
||
/// Set where the cursor will be. | ||
/// 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: u32) { | ||
// This function is static inline in libctru | ||
// https://github.com/devkitPro/libctru/blob/af5321c78ee5c72a55b526fd2ed0d95ca1c05af9/libctru/include/3ds/applets/miiselector.h#L155 | ||
self.config.initial_index = index | ||
} | ||
|
||
/// Launch the Mii Selector. | ||
/// Returns an error when the checksum of the Mii is invalid. | ||
pub fn launch(&mut self) -> Result<MiiSelectorReturn, MiiLaunchError> { | ||
let mut return_val = Box::<ctru_sys::MiiSelectorReturn>::default(); | ||
unsafe { ctru_sys::miiSelectorLaunch(self.config.as_mut(), return_val.as_mut()) } | ||
|
||
if unsafe { ctru_sys::miiSelectorChecksumIsValid(return_val.as_mut()) } { | ||
Ok((*return_val).into()) | ||
} else { | ||
Err(MiiLaunchError::InvalidChecksum) | ||
} | ||
} | ||
} | ||
|
||
impl From<ctru_sys::MiiSelectorReturn> for MiiSelectorReturn { | ||
fn from(ret: ctru_sys::MiiSelectorReturn) -> Self { | ||
let raw_mii_data = ret.mii; | ||
let mut guest_mii_name = ret.guest_mii_name; | ||
|
||
MiiSelectorReturn { | ||
mii_data: raw_mii_data.into(), | ||
is_mii_selected: ret.no_mii_selected == 0, | ||
mii_type: if ret.guest_mii_index != 0xFFFFFFFF { | ||
MiiType::Guest { | ||
index: ret.guest_mii_index, | ||
name: { | ||
let utf16_be = &mut guest_mii_name; | ||
utf16_be.reverse(); | ||
String::from_utf16(utf16_be.as_slice()).unwrap() | ||
}, | ||
} | ||
} else { | ||
MiiType::User | ||
}, | ||
} | ||
} | ||
} | ||
|
||
impl From<u32> for MiiConfigIndex { | ||
fn from(v: u32) -> Self { | ||
Self::Index(v) | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
pub mod mii_selector; | ||
pub mod swkbd; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.