Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/examples/ui/text/ime_support.rs
30635 views
1
//! Demonstrates IME (Input Method Editor) support for text input.
2
//!
3
//! IME allows users to input characters that aren't directly on their keyboard,
4
//! such as Chinese, Japanese, and Korean characters.
5
//!
6
//! To use IME input, the system must have fonts installed that support the target script.
7
//! This example uses [`FontSource::SansSerif`], which resolves to a system sans-serif font.
8
//! On systems without e.g. CJK fonts installed, CJK input will render as boxes or question marks.
9
use bevy::color::palettes::css::DARK_GREY;
10
use bevy::color::palettes::tailwind::SLATE_300;
11
use bevy::input_focus::{
12
tab_navigation::{TabGroup, TabIndex, TabNavigationPlugin},
13
InputFocus,
14
};
15
use bevy::prelude::*;
16
use bevy::text::{EditableText, TextCursorStyle};
17
18
fn main() {
19
App::new()
20
.add_plugins(DefaultPlugins)
21
.add_plugins(TabNavigationPlugin)
22
.add_systems(Startup, setup)
23
.add_systems(Update, text_submission)
24
.run();
25
}
26
27
#[derive(Component)]
28
struct TextOutput;
29
30
fn setup(mut commands: Commands) {
31
commands.spawn(Camera2d);
32
33
let instructions = commands
34
.spawn((
35
Text::new("Type using your IME, then press Ctrl+Enter to submit. Your system default sans-serif font will be used, so make sure you have fonts installed that support the characters you want to input!"),
36
TextFont {
37
font_size: FontSize::Px(20.0),
38
..default()
39
},
40
))
41
.id();
42
43
let text_input = commands
44
.spawn((
45
Node {
46
width: px(400),
47
height: px(250),
48
border: px(3).all(),
49
padding: px(8).all(),
50
..default()
51
},
52
// SansSerif resolves to a system sans-serif font, which on most CJK systems
53
// includes support for Chinese, Japanese, and Korean characters.
54
// Note that using system fonts requires the "bevy/system-fonts" feature to be enabled.
55
TextFont {
56
font: FontSource::SansSerif,
57
font_size: FontSize::Px(32.0),
58
..default()
59
},
60
BorderColor::from(Color::from(SLATE_300)),
61
EditableText {
62
allow_newlines: true,
63
..default()
64
},
65
TextCursorStyle::default(),
66
TabIndex(0),
67
BackgroundColor(DARK_GREY.into()),
68
))
69
.id();
70
71
let text_output = commands
72
.spawn((
73
Text::new("Your text here!"),
74
TextFont {
75
font: FontSource::SansSerif,
76
font_size: FontSize::Px(32.0),
77
..default()
78
},
79
TextOutput,
80
))
81
.id();
82
83
commands
84
.spawn((
85
Node {
86
flex_direction: FlexDirection::Column,
87
padding: px(24.0).all(),
88
row_gap: px(16),
89
..default()
90
},
91
TabGroup::new(0),
92
))
93
.add_children(&[instructions, text_input, text_output]);
94
}
95
96
fn text_submission(
97
input_focus: Res<InputFocus>,
98
keyboard_input: Res<ButtonInput<KeyCode>>,
99
mut text_input: Query<&mut EditableText>,
100
mut text_output: Single<&mut Text, With<TextOutput>>,
101
) {
102
if keyboard_input.just_pressed(KeyCode::Enter)
103
&& (keyboard_input.pressed(KeyCode::ControlLeft)
104
|| keyboard_input.pressed(KeyCode::ControlRight))
105
&& let Some(focused_entity) = input_focus.get()
106
&& let Ok(mut input) = text_input.get_mut(focused_entity)
107
{
108
text_output.0 = input.value().to_string();
109
input.clear();
110
}
111
}
112
113