From 27f880467aa77ca08a3252921392c21ab9596ec6 Mon Sep 17 00:00:00 2001 From: mitoma Date: Sun, 20 Oct 2024 11:32:05 +0900 Subject: [PATCH 01/11] =?UTF-8?q?new=20=E3=81=8C=E9=9D=A2=E5=80=92?= =?UTF-8?q?=E3=81=AA=E3=81=AE=E3=81=A7=20From=20trait=20=E3=82=92=E5=AE=9F?= =?UTF-8?q?=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- stroke_parser/src/lib.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/stroke_parser/src/lib.rs b/stroke_parser/src/lib.rs index 5e75412a..3b599d17 100644 --- a/stroke_parser/src/lib.rs +++ b/stroke_parser/src/lib.rs @@ -125,6 +125,12 @@ impl CommandNamespace { } } +impl From<&str> for CommandNamespace { + fn from(value: &str) -> Self { + Self::new(String::from(value)) + } +} + #[derive(Debug, Hash, Ord, PartialOrd, PartialEq, Eq, Clone, Serialize, Deserialize)] pub struct CommandName(String); @@ -142,6 +148,12 @@ impl CommandName { } } +impl From<&str> for CommandName { + fn from(value: &str) -> Self { + Self::new(String::from(value)) + } +} + #[derive(Debug, Hash, Ord, PartialOrd, PartialEq, Eq, Clone, Serialize, Deserialize, Default)] pub(crate) struct Stroke { keys: Vec, From 3a2678cb07b570a89b7f6c105188067a62be938d Mon Sep 17 00:00:00 2001 From: mitoma Date: Sun, 20 Oct 2024 15:18:03 +0900 Subject: [PATCH 02/11] =?UTF-8?q?action=20processor=20store=20=E3=81=AE?= =?UTF-8?q?=E6=96=B0=E8=A8=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/support/action_processor.rs | 242 ++++++++++++++++++ font_rasterizer/src/support/mod.rs | 2 + 2 files changed, 244 insertions(+) create mode 100644 font_rasterizer/src/support/action_processor.rs diff --git a/font_rasterizer/src/support/action_processor.rs b/font_rasterizer/src/support/action_processor.rs new file mode 100644 index 00000000..c83874d4 --- /dev/null +++ b/font_rasterizer/src/support/action_processor.rs @@ -0,0 +1,242 @@ +use stroke_parser::{Action, ActionArgument, CommandName, CommandNamespace}; + +use crate::{ + camera::CameraAdjustment, color_theme::ColorTheme, context::StateContext, font_buffer::Direction, layout_engine::World, ui::{SelectBox, SelectOption} +}; + +use super::InputResult; + +#[derive(Default)] +pub struct ActionProcessorStore { + processors: Vec>, +} + +impl ActionProcessorStore { + pub fn add_default_system_processors(&mut self) { + self.add_processor(Box::new(SystemExit)); + self.add_processor(Box::new(SystemToggleFullscreen)); + self.add_processor(Box::new(SystemChangeGlobalDirection)); + self.add_processor(Box::new(SystemChangeThemeUi)); + self.add_processor(Box::new(SystemChangeTheme)); + } + + pub fn add_processor(&mut self, processor: Box) { + self.processors.push(processor); + } + + pub fn remove_processor(&mut self, namespace: &CommandNamespace, name: &CommandName) { + self.processors + .retain(|processor| processor.namespace() != *namespace || processor.name() != *name); + } + + pub fn process( + &self, + action: &Action, + context: &StateContext, + world: &mut dyn World, + ) -> InputResult { + if let Action::Command(namespace, name, argument) = action { + for processor in &self.processors { + if processor.namespace() == *namespace && processor.name() == *name { + return processor.process(argument, context, world); + } + } + } + InputResult::Noop + } +} + +trait ActionProcessor { + fn namespace(&self) -> CommandNamespace; + fn name(&self) -> CommandName; + fn process( + &self, + arg: &ActionArgument, + context: &StateContext, + world: &mut dyn World, + ) -> InputResult; +} + +// ----- impl system ----- +pub struct SystemExit; +impl ActionProcessor for SystemExit { + fn namespace(&self) -> CommandNamespace { + "system".into() + } + + fn name(&self) -> CommandName { + "exit".into() + } + + fn process( + &self, + _arg: &ActionArgument, + _context: &StateContext, + _world: &mut dyn World, + ) -> InputResult { + InputResult::SendExit + } +} + +pub struct SystemToggleFullscreen; +impl ActionProcessor for SystemToggleFullscreen { + fn namespace(&self) -> CommandNamespace { + "system".into() + } + + fn name(&self) -> CommandName { + "toggle-fullscreen".into() + } + + fn process( + &self, + _arg: &ActionArgument, + _context: &StateContext, + _world: &mut dyn World, + ) -> InputResult { + InputResult::ToggleFullScreen + } +} + +pub struct SystemToggleTitlebar; +impl ActionProcessor for SystemToggleTitlebar { + fn namespace(&self) -> CommandNamespace { + "system".into() + } + + fn name(&self) -> CommandName { + "toggle-titlebar".into() + } + + fn process( + &self, + _arg: &ActionArgument, + _context: &StateContext, + _world: &mut dyn World, + ) -> InputResult { + InputResult::ToggleDecorations + } +} + +pub struct SystemChangeThemeUi; +impl ActionProcessor for SystemChangeThemeUi { + fn namespace(&self) -> CommandNamespace { + "system".into() + } + + fn name(&self) -> CommandName { + "change-theme-ui".into() + } + + fn process( + &self, + _arg: &ActionArgument, + context: &StateContext, + world: &mut dyn World, + ) -> InputResult { + let options = vec![ + SelectOption::new( + "Solarized Blackback".to_string(), + Action::new_command_with_argument("system", "change-theme", "black"), + ), + SelectOption::new( + "Solarized Dark".to_string(), + Action::new_command_with_argument("system", "change-theme", "dark"), + ), + SelectOption::new( + "Solarized Light".to_string(), + Action::new_command_with_argument("system", "change-theme", "light"), + ), + ]; + let model = SelectBox::new( + context, + "カラーテーマを選択して下さい".to_string(), + options, + None, + ); + world.add_next(Box::new(model)); + world.re_layout(); + let adjustment = if context.global_direction == Direction::Horizontal { + CameraAdjustment::FitWidth + } else { + CameraAdjustment::FitHeight + }; + world.look_next(adjustment); + + InputResult::InputConsumed + } +} + +pub struct SystemChangeTheme; +impl ActionProcessor for SystemChangeTheme { + fn namespace(&self) -> CommandNamespace { + "system".into() + } + + fn name(&self) -> CommandName { + "change-theme".into() + } + + fn process( + &self, + arg: &ActionArgument, + _context: &StateContext, + _world: &mut dyn World, + ) -> InputResult { + if let ActionArgument::String(theme) = arg { + let theme = match theme.as_str() { + "light" => ColorTheme::SolarizedLight, + "dark" => ColorTheme::SolarizedDark, + "black" => ColorTheme::SolarizedBlackback, + _ => return InputResult::Noop, + }; + InputResult::ChangeColorTheme(theme) + } else { + InputResult::Noop + } + } +} + +pub struct SystemChangeGlobalDirection; +impl ActionProcessor for SystemChangeGlobalDirection { + fn namespace(&self) -> CommandNamespace { + "system".into() + } + + fn name(&self) -> CommandName { + "change-global-direction".into() + } + + fn process( + &self, + _arg: &ActionArgument, + context: &StateContext, + _world: &mut dyn World, + ) -> InputResult { + InputResult::ChangeGlobalDirection(context.global_direction.toggle()) + } +} + +// ----- impl edit ----- +/* +pub struct EditForward; +impl ActionProcessor for EditForward { + fn namespace(&self) -> CommandNamespace { + "edit".into() + } + + fn name(&self) -> CommandName { + "forward".into() + } + + fn process( + &self, + _arg: &ActionArgument, + _context: &StateContext, + world: &mut dyn World, + ) -> Option { + world.editor_operation(&EditorOperation::Forward); + Some(InputResult::InputConsumed) + } +} + */ diff --git a/font_rasterizer/src/support/mod.rs b/font_rasterizer/src/support/mod.rs index 23ca1c7a..f4a2f203 100644 --- a/font_rasterizer/src/support/mod.rs +++ b/font_rasterizer/src/support/mod.rs @@ -1,3 +1,4 @@ +pub mod action_processor; mod metrics_counter; mod render_rate_adjuster; @@ -301,6 +302,7 @@ pub async fn run_support(support: SimpleStateSupport) { .unwrap(); } +#[derive(PartialEq)] pub enum InputResult { InputConsumed, ToggleFullScreen, From 8f6376f666b5a0e1956c38c6ec8b91da1dc75599 Mon Sep 17 00:00:00 2001 From: mitoma Date: Sun, 20 Oct 2024 17:24:59 +0900 Subject: [PATCH 03/11] =?UTF-8?q?system=20=E3=82=92=20ActionProcessorStore?= =?UTF-8?q?=20=E3=81=AB=E7=BD=AE=E3=81=8D=E6=8F=9B=E3=81=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - shutdown hook を追加 --- font_rasterizer/examples/save_apng.rs | 2 + font_rasterizer/examples/setup_glyphs.rs | 2 + font_rasterizer/examples/support_test.rs | 2 + .../src/support/action_processor.rs | 2 +- font_rasterizer/src/support/mod.rs | 19 ++++- font_rasterizer_example/src/lib.rs | 2 + kashikishi/src/main.rs | 81 ++++++++++++++----- rokid_3dof/examples/rokid_test.rs | 2 + sample_codes/showcase/src/lib.rs | 2 + sample_codes/slideshow/src/lib.rs | 2 + 10 files changed, 92 insertions(+), 24 deletions(-) diff --git a/font_rasterizer/examples/save_apng.rs b/font_rasterizer/examples/save_apng.rs index 97839a5f..eff39ffc 100644 --- a/font_rasterizer/examples/save_apng.rs +++ b/font_rasterizer/examples/save_apng.rs @@ -153,4 +153,6 @@ impl SimpleStateCallback for SingleCharCallback { fn render(&mut self) -> (&Camera, Vec<&GlyphInstances>) { (&self.camera, self.glyphs.iter().collect()) } + + fn shutdown(&mut self) {} } diff --git a/font_rasterizer/examples/setup_glyphs.rs b/font_rasterizer/examples/setup_glyphs.rs index 89e47461..dbd85f18 100644 --- a/font_rasterizer/examples/setup_glyphs.rs +++ b/font_rasterizer/examples/setup_glyphs.rs @@ -98,4 +98,6 @@ impl SimpleStateCallback for SingleCharCallback { fn render(&mut self) -> (&Camera, Vec<&GlyphInstances>) { (&self.camera, Vec::new()) } + + fn shutdown(&mut self) {} } diff --git a/font_rasterizer/examples/support_test.rs b/font_rasterizer/examples/support_test.rs index e417b55f..81e1b864 100644 --- a/font_rasterizer/examples/support_test.rs +++ b/font_rasterizer/examples/support_test.rs @@ -178,4 +178,6 @@ impl SimpleStateCallback for SingleCharCallback { fn render(&mut self) -> (&Camera, Vec<&GlyphInstances>) { (&self.camera, self.glyphs.iter().collect()) } + + fn shutdown(&mut self) {} } diff --git a/font_rasterizer/src/support/action_processor.rs b/font_rasterizer/src/support/action_processor.rs index c83874d4..42add590 100644 --- a/font_rasterizer/src/support/action_processor.rs +++ b/font_rasterizer/src/support/action_processor.rs @@ -46,7 +46,7 @@ impl ActionProcessorStore { } } -trait ActionProcessor { +pub trait ActionProcessor { fn namespace(&self) -> CommandNamespace; fn name(&self) -> CommandName; fn process( diff --git a/font_rasterizer/src/support/mod.rs b/font_rasterizer/src/support/mod.rs index f4a2f203..d2ee5b51 100644 --- a/font_rasterizer/src/support/mod.rs +++ b/font_rasterizer/src/support/mod.rs @@ -149,6 +149,7 @@ pub async fn run_support(support: SimpleStateSupport) { } InputResult::SendExit => { print_metrics_to_stdout(); + state.shutdown(); control_flow.exit() } InputResult::ToggleFullScreen => { @@ -174,6 +175,7 @@ pub async fn run_support(support: SimpleStateSupport) { match event { WindowEvent::CloseRequested => { print_metrics_to_stdout(); + state.shutdown(); control_flow.exit() } WindowEvent::KeyboardInput { @@ -187,6 +189,7 @@ pub async fn run_support(support: SimpleStateSupport) { } => { if support.flags.contains(Flags::EXIT_ON_ESC) { print_metrics_to_stdout(); + state.shutdown(); control_flow.exit(); } } @@ -239,7 +242,11 @@ pub async fn run_support(support: SimpleStateSupport) { wgpu::SurfaceError::Lost | wgpu::SurfaceError::Outdated, ) => state.redraw(), // The system is out of memory, we should probably quit - Err(wgpu::SurfaceError::OutOfMemory) => control_flow.exit(), + Err(wgpu::SurfaceError::OutOfMemory) => { + print_metrics_to_stdout(); + state.shutdown(); + control_flow.exit() + } // We're ignoring timeouts Err(wgpu::SurfaceError::Timeout) => { log::warn!("Surface timeout") @@ -275,6 +282,7 @@ pub async fn run_support(support: SimpleStateSupport) { } InputResult::SendExit => { print_metrics_to_stdout(); + state.shutdown(); control_flow.exit() } InputResult::ToggleFullScreen => { @@ -320,6 +328,7 @@ pub trait SimpleStateCallback { fn input(&mut self, context: &StateContext, event: &WindowEvent) -> InputResult; fn action(&mut self, context: &StateContext, action: Action) -> InputResult; fn render(&mut self) -> (&Camera, Vec<&GlyphInstances>); + fn shutdown(&mut self); } pub struct SimpleState { @@ -539,6 +548,10 @@ impl SimpleState { Ok(()) } + + fn shutdown(&mut self) { + self.simple_state_callback.shutdown(); + } } pub struct ImageState { @@ -762,6 +775,10 @@ impl ImageState { Ok(buffer) } + + fn shutdown(&mut self) { + self.simple_state_callback.shutdown(); + } } pub async fn generate_images( diff --git a/font_rasterizer_example/src/lib.rs b/font_rasterizer_example/src/lib.rs index 80ec5687..36333475 100644 --- a/font_rasterizer_example/src/lib.rs +++ b/font_rasterizer_example/src/lib.rs @@ -169,4 +169,6 @@ impl SimpleStateCallback for SingleCharCallback { fn render(&mut self) -> (&Camera, Vec<&GlyphInstances>) { (&self.camera, self.glyphs.iter().collect()) } + + fn shutdown(&mut self) {} } diff --git a/kashikishi/src/main.rs b/kashikishi/src/main.rs index 25d420c5..ae93ea59 100644 --- a/kashikishi/src/main.rs +++ b/kashikishi/src/main.rs @@ -11,7 +11,10 @@ use arboard::Clipboard; use clap::{command, Parser}; use font_collector::FontCollector; use rokid_3dof::RokidMax; -use stroke_parser::{action_store_parser::parse_setting, Action, ActionArgument, ActionStore}; +use stroke_parser::{ + action_store_parser::parse_setting, Action, ActionArgument, ActionStore, CommandName, + CommandNamespace, +}; use text_buffer::action::EditorOperation; use world::{CategorizedMemosWorld, HelpWorld, ModalWorld, NullWorld, StartWorld}; @@ -21,9 +24,12 @@ use font_rasterizer::{ context::{StateContext, WindowSize}, font_buffer::{Direction, GlyphVertexBuffer}, instances::GlyphInstances, - layout_engine::{Model, ModelOperation}, + layout_engine::{Model, ModelOperation, World}, rasterizer_pipeline::Quarity, - support::{run_support, Flags, InputResult, SimpleStateCallback, SimpleStateSupport}, + support::{ + action_processor::{ActionProcessor, ActionProcessorStore}, + run_support, Flags, InputResult, SimpleStateCallback, SimpleStateSupport, + }, time::set_clock_mode, ui::{caret_char, ime_chars, ImeInput}, }; @@ -69,6 +75,39 @@ pub struct Args { const COLOR_THEME: ColorTheme = ColorTheme::SolarizedDark; +struct SystemCommandPalette; +impl ActionProcessor for SystemCommandPalette { + fn namespace(&self) -> CommandNamespace { + "system".into() + } + + fn name(&self) -> CommandName { + "command-palette".into() + } + + fn process( + &self, + arg: &ActionArgument, + context: &StateContext, + world: &mut dyn World, + ) -> InputResult { + let narrow = match arg { + ActionArgument::String(value) => Some(value.to_owned()), + _ => None, + }; + let modal = command_palette_select(context, narrow); + world.add_next(Box::new(modal)); + world.re_layout(); + let adjustment = if context.global_direction == Direction::Horizontal { + CameraAdjustment::FitWidth + } else { + CameraAdjustment::FitHeight + }; + world.look_next(adjustment); + InputResult::InputConsumed + } +} + #[cfg_attr(target_arch = "wasm32", wasm_bindgen(start))] pub async fn run(args: Args) { // setup icon @@ -122,6 +161,7 @@ struct KashikishiCallback { store: ActionStore, world: Box, ime: ImeInput, + action_processor_store: ActionProcessorStore, new_chars: HashSet, rokid_max: Option, ar_mode: bool, @@ -138,12 +178,17 @@ impl KashikishiCallback { .for_each(|k| store.register_keybind(k.clone())); let ime = ImeInput::new(); + let mut action_processor_store = ActionProcessorStore::default(); + action_processor_store.add_default_system_processors(); + action_processor_store.add_processor(Box::new(SystemCommandPalette)); + let rokid_max = RokidMax::new().ok(); Self { store, world: Box::new(NullWorld::new(window_size)), ime, + action_processor_store, new_chars: HashSet::new(), rokid_max, ar_mode: false, @@ -392,27 +437,15 @@ impl SimpleStateCallback for KashikishiCallback { } fn action(&mut self, context: &StateContext, action: Action) -> InputResult { + let result = self + .action_processor_store + .process(&action, context, self.world.get_mut()); + if result != InputResult::Noop { + return result; + } + match action { Action::Command(category, name, argument) => match &*category.to_string() { - "system" => match self.execute_system_action(&name, argument, context) { - SystemActionResult::Exit => { - self.world.graceful_exit(); - InputResult::SendExit - } - SystemActionResult::ToggleFullScreen => InputResult::ToggleFullScreen, - SystemActionResult::ToggleTitlebar => InputResult::ToggleDecorations, - SystemActionResult::ChangeColorTheme(theme) => { - InputResult::ChangeColorTheme(theme) - } - SystemActionResult::ChangeGlobalDirection(direction) => { - InputResult::ChangeGlobalDirection(direction) - } - SystemActionResult::AddModal(modal) => { - self.world.add_modal(context, &mut self.new_chars, modal); - InputResult::InputConsumed - } - SystemActionResult::Noop => InputResult::InputConsumed, - }, "edit" => { let op = Self::execute_editor_action(&name, &mut self.new_chars); self.world.get_mut().editor_operation(&op); @@ -482,4 +515,8 @@ impl SimpleStateCallback for KashikishiCallback { world_instances.append(&mut ime_instances); (self.world.get().camera(), world_instances) } + + fn shutdown(&mut self) { + self.world.graceful_exit(); + } } diff --git a/rokid_3dof/examples/rokid_test.rs b/rokid_3dof/examples/rokid_test.rs index c931a39e..c614d9e2 100644 --- a/rokid_3dof/examples/rokid_test.rs +++ b/rokid_3dof/examples/rokid_test.rs @@ -196,4 +196,6 @@ impl SimpleStateCallback for SingleCharCallback { fn render(&mut self) -> (&Camera, Vec<&GlyphInstances>) { (&self.camera, self.glyphs.iter().collect()) } + + fn shutdown(&mut self) {} } diff --git a/sample_codes/showcase/src/lib.rs b/sample_codes/showcase/src/lib.rs index 4e348e62..798ce682 100644 --- a/sample_codes/showcase/src/lib.rs +++ b/sample_codes/showcase/src/lib.rs @@ -388,4 +388,6 @@ impl SimpleStateCallback for SingleCharCallback { world_instances.append(&mut ime_instances); (self.world.camera(), world_instances) } + + fn shutdown(&mut self) {} } diff --git a/sample_codes/slideshow/src/lib.rs b/sample_codes/slideshow/src/lib.rs index ba2fdcb0..8c327913 100644 --- a/sample_codes/slideshow/src/lib.rs +++ b/sample_codes/slideshow/src/lib.rs @@ -179,4 +179,6 @@ impl SimpleStateCallback for SingleCharCallback { let instances = self.world.glyph_instances(); (self.world.camera(), instances) } + + fn shutdown(&mut self) {} } From 65e6d1296312601b409ee0b58657f9081590d68f Mon Sep 17 00:00:00 2001 From: mitoma Date: Mon, 21 Oct 2024 23:42:40 +0900 Subject: [PATCH 04/11] =?UTF-8?q?system=20=E3=82=A2=E3=82=AF=E3=82=B7?= =?UTF-8?q?=E3=83=A7=E3=83=B3=E3=82=92=E7=A7=BB=E5=8B=95=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/support/action_processor.rs | 21 ++++++- font_rasterizer/src/support/mod.rs | 1 + kashikishi/src/kashikishi_actions.rs | 23 -------- kashikishi/src/main.rs | 56 +++---------------- 4 files changed, 28 insertions(+), 73 deletions(-) diff --git a/font_rasterizer/src/support/action_processor.rs b/font_rasterizer/src/support/action_processor.rs index 42add590..445b0e0d 100644 --- a/font_rasterizer/src/support/action_processor.rs +++ b/font_rasterizer/src/support/action_processor.rs @@ -1,7 +1,14 @@ +use std::collections::HashSet; + use stroke_parser::{Action, ActionArgument, CommandName, CommandNamespace}; use crate::{ - camera::CameraAdjustment, color_theme::ColorTheme, context::StateContext, font_buffer::Direction, layout_engine::World, ui::{SelectBox, SelectOption} + camera::CameraAdjustment, + color_theme::ColorTheme, + context::StateContext, + font_buffer::Direction, + layout_engine::{Model, World}, + ui::{SelectBox, SelectOption}, }; use super::InputResult; @@ -15,6 +22,7 @@ impl ActionProcessorStore { pub fn add_default_system_processors(&mut self) { self.add_processor(Box::new(SystemExit)); self.add_processor(Box::new(SystemToggleFullscreen)); + self.add_processor(Box::new(SystemToggleTitlebar)); self.add_processor(Box::new(SystemChangeGlobalDirection)); self.add_processor(Box::new(SystemChangeThemeUi)); self.add_processor(Box::new(SystemChangeTheme)); @@ -34,11 +42,12 @@ impl ActionProcessorStore { action: &Action, context: &StateContext, world: &mut dyn World, + new_chars: &mut HashSet, ) -> InputResult { if let Action::Command(namespace, name, argument) = action { for processor in &self.processors { if processor.namespace() == *namespace && processor.name() == *name { - return processor.process(argument, context, world); + return processor.process(argument, context, world, new_chars); } } } @@ -54,6 +63,7 @@ pub trait ActionProcessor { arg: &ActionArgument, context: &StateContext, world: &mut dyn World, + new_chars: &mut HashSet, ) -> InputResult; } @@ -73,6 +83,7 @@ impl ActionProcessor for SystemExit { _arg: &ActionArgument, _context: &StateContext, _world: &mut dyn World, + _new_chars: &mut HashSet, ) -> InputResult { InputResult::SendExit } @@ -93,6 +104,7 @@ impl ActionProcessor for SystemToggleFullscreen { _arg: &ActionArgument, _context: &StateContext, _world: &mut dyn World, + _new_chars: &mut HashSet, ) -> InputResult { InputResult::ToggleFullScreen } @@ -113,6 +125,7 @@ impl ActionProcessor for SystemToggleTitlebar { _arg: &ActionArgument, _context: &StateContext, _world: &mut dyn World, + _new_chars: &mut HashSet, ) -> InputResult { InputResult::ToggleDecorations } @@ -133,6 +146,7 @@ impl ActionProcessor for SystemChangeThemeUi { _arg: &ActionArgument, context: &StateContext, world: &mut dyn World, + new_chars: &mut HashSet, ) -> InputResult { let options = vec![ SelectOption::new( @@ -154,6 +168,7 @@ impl ActionProcessor for SystemChangeThemeUi { options, None, ); + new_chars.extend(model.to_string().chars()); world.add_next(Box::new(model)); world.re_layout(); let adjustment = if context.global_direction == Direction::Horizontal { @@ -182,6 +197,7 @@ impl ActionProcessor for SystemChangeTheme { arg: &ActionArgument, _context: &StateContext, _world: &mut dyn World, + _new_chars: &mut HashSet, ) -> InputResult { if let ActionArgument::String(theme) = arg { let theme = match theme.as_str() { @@ -212,6 +228,7 @@ impl ActionProcessor for SystemChangeGlobalDirection { _arg: &ActionArgument, context: &StateContext, _world: &mut dyn World, + _new_chars: &mut HashSet, ) -> InputResult { InputResult::ChangeGlobalDirection(context.global_direction.toggle()) } diff --git a/font_rasterizer/src/support/mod.rs b/font_rasterizer/src/support/mod.rs index d2ee5b51..6f42411b 100644 --- a/font_rasterizer/src/support/mod.rs +++ b/font_rasterizer/src/support/mod.rs @@ -803,6 +803,7 @@ pub async fn generate_images( let mut frame = 0; loop { if frame > num_of_frame { + state.shutdown(); break; } state.update(); diff --git a/kashikishi/src/kashikishi_actions.rs b/kashikishi/src/kashikishi_actions.rs index d1efdd09..6a2ad244 100644 --- a/kashikishi/src/kashikishi_actions.rs +++ b/kashikishi/src/kashikishi_actions.rs @@ -70,29 +70,6 @@ pub(crate) fn insert_date_select(context: &StateContext) -> SelectBox { SelectBox::new(context, "挿入したい日付を選択".to_string(), options, None) } -pub(crate) fn change_theme_ui(context: &StateContext) -> SelectBox { - let options = vec![ - SelectOption::new( - "Solarized Blackback".to_string(), - Action::new_command_with_argument("system", "change-theme", "black"), - ), - SelectOption::new( - "Solarized Dark".to_string(), - Action::new_command_with_argument("system", "change-theme", "dark"), - ), - SelectOption::new( - "Solarized Light".to_string(), - Action::new_command_with_argument("system", "change-theme", "light"), - ), - ]; - SelectBox::new( - context, - "カラーテーマを選択して下さい".to_string(), - options, - None, - ) -} - pub(crate) fn move_category_ui( context: &StateContext, categorized_memos: &CategorizedMemos, diff --git a/kashikishi/src/main.rs b/kashikishi/src/main.rs index ae93ea59..4833179f 100644 --- a/kashikishi/src/main.rs +++ b/kashikishi/src/main.rs @@ -33,7 +33,6 @@ use font_rasterizer::{ time::set_clock_mode, ui::{caret_char, ime_chars, ImeInput}, }; -use kashikishi_actions::change_theme_ui; use log::info; use std::collections::HashSet; use winit::event::WindowEvent; @@ -90,12 +89,14 @@ impl ActionProcessor for SystemCommandPalette { arg: &ActionArgument, context: &StateContext, world: &mut dyn World, + new_chars: &mut HashSet, ) -> InputResult { let narrow = match arg { ActionArgument::String(value) => Some(value.to_owned()), _ => None, }; let modal = command_palette_select(context, narrow); + new_chars.extend(modal.to_string().chars()); world.add_next(Box::new(modal)); world.re_layout(); let adjustment = if context.global_direction == Direction::Horizontal { @@ -195,40 +196,6 @@ impl KashikishiCallback { } } - fn execute_system_action( - &mut self, - command_name: &str, - argument: ActionArgument, - context: &StateContext, - ) -> SystemActionResult { - match command_name { - "exit" => SystemActionResult::Exit, - "command-palette" => { - let narrow = match argument { - ActionArgument::String(value) => Some(value), - _ => None, - }; - SystemActionResult::AddModal(Box::new(command_palette_select(context, narrow))) - } - "toggle-fullscreen" => SystemActionResult::ToggleFullScreen, - "toggle-titlebar" => SystemActionResult::ToggleTitlebar, - "change-theme-ui" => SystemActionResult::AddModal(Box::new(change_theme_ui(context))), - "change-theme" => match argument { - ActionArgument::String(value) => match &*value.to_string() { - "black" => SystemActionResult::ChangeColorTheme(ColorTheme::SolarizedBlackback), - "dark" => SystemActionResult::ChangeColorTheme(ColorTheme::SolarizedDark), - "light" => SystemActionResult::ChangeColorTheme(ColorTheme::SolarizedLight), - _ => SystemActionResult::Noop, - }, - _ => SystemActionResult::Noop, - }, - "change-global-direction" => { - SystemActionResult::ChangeGlobalDirection(context.global_direction.toggle()) - } - _ => SystemActionResult::Noop, - } - } - fn execute_editor_action(command_name: &str, chars: &mut HashSet) -> EditorOperation { match command_name { "return" => EditorOperation::InsertEnter, @@ -363,16 +330,6 @@ impl KashikishiCallback { } } -enum SystemActionResult { - Exit, - ToggleFullScreen, - ToggleTitlebar, - ChangeColorTheme(ColorTheme), - ChangeGlobalDirection(Direction), - AddModal(Box), - Noop, -} - impl SimpleStateCallback for KashikishiCallback { fn init(&mut self, glyph_vertex_buffer: &mut GlyphVertexBuffer, context: &StateContext) { // 初期状態で表示するワールドを設定する @@ -437,9 +394,12 @@ impl SimpleStateCallback for KashikishiCallback { } fn action(&mut self, context: &StateContext, action: Action) -> InputResult { - let result = self - .action_processor_store - .process(&action, context, self.world.get_mut()); + let result = self.action_processor_store.process( + &action, + context, + self.world.get_mut(), + &mut self.new_chars, + ); if result != InputResult::Noop { return result; } From db5f1b443579da54b97ee0e0655cf04a7f72cb56 Mon Sep 17 00:00:00 2001 From: mitoma Date: Tue, 22 Oct 2024 00:44:18 +0900 Subject: [PATCH 05/11] =?UTF-8?q?glyph=5Fvertex=5Fbuffer=20=E3=82=92?= =?UTF-8?q?=E9=9C=B2=E5=87=BA=E3=81=97=E3=81=AA=E3=81=84=E3=82=88=E3=81=86?= =?UTF-8?q?=E3=81=AB=20refactor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- font_rasterizer/examples/save_apng.rs | 5 +- font_rasterizer/examples/setup_glyphs.rs | 13 ++-- font_rasterizer/examples/support_test.rs | 13 +--- font_rasterizer/src/context.rs | 1 + font_rasterizer/src/layout_engine.rs | 6 +- .../src/support/action_processor.rs | 14 +--- font_rasterizer/src/support/mod.rs | 36 ++++++++--- font_rasterizer_example/src/lib.rs | 9 +-- kashikishi/src/main.rs | 64 ++++++++----------- rokid_3dof/examples/rokid_test.rs | 13 +--- sample_codes/showcase/src/lib.rs | 54 ++++++---------- sample_codes/slideshow/src/lib.rs | 9 ++- 12 files changed, 98 insertions(+), 139 deletions(-) diff --git a/font_rasterizer/examples/save_apng.rs b/font_rasterizer/examples/save_apng.rs index eff39ffc..9f001ddb 100644 --- a/font_rasterizer/examples/save_apng.rs +++ b/font_rasterizer/examples/save_apng.rs @@ -7,7 +7,6 @@ use font_rasterizer::{ camera::{Camera, CameraController}, color_theme::ColorTheme, context::{StateContext, WindowSize}, - font_buffer::GlyphVertexBuffer, instances::{GlyphInstance, GlyphInstances}, motion::{EasingFuncType, MotionDetail, MotionFlags, MotionTarget, MotionType}, rasterizer_pipeline::Quarity, @@ -108,7 +107,7 @@ impl SingleCharCallback { } impl SimpleStateCallback for SingleCharCallback { - fn init(&mut self, _glyph_vertex_buffer: &mut GlyphVertexBuffer, context: &StateContext) { + fn init(&mut self, context: &StateContext) { let value = GlyphInstance::new( (0.0, 0.0, 0.0).into(), cgmath::Quaternion::from_axis_angle(cgmath::Vector3::unit_z(), cgmath::Deg(0.0)), @@ -131,7 +130,7 @@ impl SimpleStateCallback for SingleCharCallback { debug!("init!"); } - fn update(&mut self, _glyph_vertex_buffer: &mut GlyphVertexBuffer, context: &StateContext) { + fn update(&mut self, context: &StateContext) { self.glyphs .iter_mut() .for_each(|i| i.update_buffer(&context.device, &context.queue)); diff --git a/font_rasterizer/examples/setup_glyphs.rs b/font_rasterizer/examples/setup_glyphs.rs index dbd85f18..ebfceae3 100644 --- a/font_rasterizer/examples/setup_glyphs.rs +++ b/font_rasterizer/examples/setup_glyphs.rs @@ -1,11 +1,8 @@ -use std::collections::HashSet; - use font_collector::FontCollector; use font_rasterizer::{ camera::Camera, color_theme::ColorTheme, context::{StateContext, WindowSize}, - font_buffer::GlyphVertexBuffer, instances::GlyphInstances, rasterizer_pipeline::Quarity, support::{run_support, Flags, InputResult, SimpleStateCallback, SimpleStateSupport}, @@ -56,7 +53,7 @@ struct SingleCharCallback { } impl SimpleStateCallback for SingleCharCallback { - fn init(&mut self, glyph_vertex_buffer: &mut GlyphVertexBuffer, context: &StateContext) { + fn init(&mut self, context: &StateContext) { let start = Instant::now(); let _char_ranges = [ 'a'..='z', @@ -69,13 +66,11 @@ impl SimpleStateCallback for SingleCharCallback { '㐀'..='䶿', ] .iter() - .map(|char_range| char_range.clone().into_iter().collect::>()) + .map(|char_range| char_range.clone().into_iter().collect::()) .for_each(|c| { let start = Instant::now(); println!("c len: {}", c.len()); - glyph_vertex_buffer - .append_glyph(&context.device, &context.queue, c) - .unwrap(); + context.ui_string_sender.send(c).unwrap(); let end = Instant::now(); println!("init: {:?}", end - start); }); @@ -83,7 +78,7 @@ impl SimpleStateCallback for SingleCharCallback { println!("init: {:?}", end - start); } - fn update(&mut self, _glyph_vertex_buffer: &mut GlyphVertexBuffer, _context: &StateContext) {} + fn update(&mut self, _context: &StateContext) {} fn input(&mut self, _context: &StateContext, _event: &WindowEvent) -> InputResult { InputResult::Noop diff --git a/font_rasterizer/examples/support_test.rs b/font_rasterizer/examples/support_test.rs index 81e1b864..bf6b79e8 100644 --- a/font_rasterizer/examples/support_test.rs +++ b/font_rasterizer/examples/support_test.rs @@ -8,7 +8,6 @@ use font_rasterizer::{ camera::{Camera, CameraController}, color_theme::ColorTheme::{self, SolarizedDark}, context::{StateContext, WindowSize}, - font_buffer::GlyphVertexBuffer, instances::{GlyphInstance, GlyphInstances}, motion::{EasingFuncType, MotionDetail, MotionFlags, MotionTarget, MotionType}, rasterizer_pipeline::Quarity, @@ -102,7 +101,7 @@ impl SingleCharCallback { } impl SimpleStateCallback for SingleCharCallback { - fn init(&mut self, glyph_vertex_buffer: &mut GlyphVertexBuffer, context: &StateContext) { + fn init(&mut self, context: &StateContext) { let value = GlyphInstance::new( (0.0, 0.0, 0.0).into(), cgmath::Quaternion::from_axis_angle(cgmath::Vector3::unit_z(), cgmath::Deg(0.0)), @@ -117,16 +116,10 @@ impl SimpleStateCallback for SingleCharCallback { let mut instance = GlyphInstances::new('あ', &context.device); instance.push(value); self.glyphs.push(instance); - glyph_vertex_buffer - .append_glyph( - &context.device, - &context.queue, - ['あ'].iter().cloned().collect(), - ) - .unwrap(); + context.ui_string_sender.send("あ".to_string()).unwrap(); } - fn update(&mut self, _glyph_vertex_buffer: &mut GlyphVertexBuffer, context: &StateContext) { + fn update(&mut self, context: &StateContext) { self.glyphs .iter_mut() .for_each(|i| i.update_buffer(&context.device, &context.queue)); diff --git a/font_rasterizer/src/context.rs b/font_rasterizer/src/context.rs index 27087611..97aa5592 100644 --- a/font_rasterizer/src/context.rs +++ b/font_rasterizer/src/context.rs @@ -19,6 +19,7 @@ pub struct StateContext { pub char_width_calcurator: Arc, pub color_theme: ColorTheme, pub window_size: WindowSize, + pub ui_string_sender: Sender, pub action_queue_sender: Sender, pub post_action_queue_sender: Sender, pub global_direction: Direction, diff --git a/font_rasterizer/src/layout_engine.rs b/font_rasterizer/src/layout_engine.rs index 36e8647d..4fa17811 100644 --- a/font_rasterizer/src/layout_engine.rs +++ b/font_rasterizer/src/layout_engine.rs @@ -11,7 +11,7 @@ use text_buffer::{action::EditorOperation, editor::CharWidthResolver}; use crate::{ camera::{Camera, CameraAdjustment, CameraController, CameraOperation}, context::{StateContext, WindowSize}, - font_buffer::{Direction, GlyphVertexBuffer}, + font_buffer::Direction, instances::GlyphInstances, }; @@ -27,7 +27,7 @@ pub trait World { // 再レイアウトする update するときに呼び出すとよさそう fn re_layout(&mut self); - fn update(&mut self, glyph_vertex_buffer: &mut GlyphVertexBuffer, context: &StateContext); + fn update(&mut self, context: &StateContext); // この World にいくつモデルを配置されているかを返す fn model_length(&self) -> usize; @@ -198,7 +198,7 @@ impl World for HorizontalWorld { .collect() } - fn update(&mut self, _glyph_vertex_buffer: &mut GlyphVertexBuffer, context: &StateContext) { + fn update(&mut self, context: &StateContext) { let range = if self.world_updated { 0..self.models.len() } else { diff --git a/font_rasterizer/src/support/action_processor.rs b/font_rasterizer/src/support/action_processor.rs index 445b0e0d..73ed55b1 100644 --- a/font_rasterizer/src/support/action_processor.rs +++ b/font_rasterizer/src/support/action_processor.rs @@ -1,5 +1,3 @@ -use std::collections::HashSet; - use stroke_parser::{Action, ActionArgument, CommandName, CommandNamespace}; use crate::{ @@ -42,12 +40,11 @@ impl ActionProcessorStore { action: &Action, context: &StateContext, world: &mut dyn World, - new_chars: &mut HashSet, ) -> InputResult { if let Action::Command(namespace, name, argument) = action { for processor in &self.processors { if processor.namespace() == *namespace && processor.name() == *name { - return processor.process(argument, context, world, new_chars); + return processor.process(argument, context, world); } } } @@ -63,7 +60,6 @@ pub trait ActionProcessor { arg: &ActionArgument, context: &StateContext, world: &mut dyn World, - new_chars: &mut HashSet, ) -> InputResult; } @@ -83,7 +79,6 @@ impl ActionProcessor for SystemExit { _arg: &ActionArgument, _context: &StateContext, _world: &mut dyn World, - _new_chars: &mut HashSet, ) -> InputResult { InputResult::SendExit } @@ -104,7 +99,6 @@ impl ActionProcessor for SystemToggleFullscreen { _arg: &ActionArgument, _context: &StateContext, _world: &mut dyn World, - _new_chars: &mut HashSet, ) -> InputResult { InputResult::ToggleFullScreen } @@ -125,7 +119,6 @@ impl ActionProcessor for SystemToggleTitlebar { _arg: &ActionArgument, _context: &StateContext, _world: &mut dyn World, - _new_chars: &mut HashSet, ) -> InputResult { InputResult::ToggleDecorations } @@ -146,7 +139,6 @@ impl ActionProcessor for SystemChangeThemeUi { _arg: &ActionArgument, context: &StateContext, world: &mut dyn World, - new_chars: &mut HashSet, ) -> InputResult { let options = vec![ SelectOption::new( @@ -168,7 +160,7 @@ impl ActionProcessor for SystemChangeThemeUi { options, None, ); - new_chars.extend(model.to_string().chars()); + context.ui_string_sender.send(model.to_string()).unwrap(); world.add_next(Box::new(model)); world.re_layout(); let adjustment = if context.global_direction == Direction::Horizontal { @@ -197,7 +189,6 @@ impl ActionProcessor for SystemChangeTheme { arg: &ActionArgument, _context: &StateContext, _world: &mut dyn World, - _new_chars: &mut HashSet, ) -> InputResult { if let ActionArgument::String(theme) = arg { let theme = match theme.as_str() { @@ -228,7 +219,6 @@ impl ActionProcessor for SystemChangeGlobalDirection { _arg: &ActionArgument, context: &StateContext, _world: &mut dyn World, - _new_chars: &mut HashSet, ) -> InputResult { InputResult::ChangeGlobalDirection(context.global_direction.toggle()) } diff --git a/font_rasterizer/src/support/mod.rs b/font_rasterizer/src/support/mod.rs index 6f42411b..f250062e 100644 --- a/font_rasterizer/src/support/mod.rs +++ b/font_rasterizer/src/support/mod.rs @@ -322,9 +322,9 @@ pub enum InputResult { } pub trait SimpleStateCallback { - fn init(&mut self, glyph_vertex_buffer: &mut GlyphVertexBuffer, context: &StateContext); + fn init(&mut self, context: &StateContext); fn resize(&mut self, size: WindowSize); - fn update(&mut self, glyph_vertex_buffer: &mut GlyphVertexBuffer, context: &StateContext); + fn update(&mut self, context: &StateContext); fn input(&mut self, context: &StateContext, event: &WindowEvent) -> InputResult; fn action(&mut self, context: &StateContext, action: Action) -> InputResult; fn render(&mut self) -> (&Camera, Vec<&GlyphInstances>); @@ -344,6 +344,7 @@ pub struct SimpleState { simple_state_callback: Box, + ui_string_receiver: Receiver, action_queue_receiver: Receiver, post_action_queue_receiver: Receiver, } @@ -425,9 +426,10 @@ impl SimpleState { let font_binaries = Arc::new(font_binaries); let char_width_calcurator = Arc::new(CharWidthCalculator::new(font_binaries.clone())); - let mut glyph_vertex_buffer = + let glyph_vertex_buffer = GlyphVertexBuffer::new(font_binaries, char_width_calcurator.clone()); + let (ui_string_sender, ui_string_receiver) = std::sync::mpsc::channel(); let (action_queue_sender, action_queue_receiver) = std::sync::mpsc::channel(); let (post_action_queue_sender, post_action_queue_receiver) = std::sync::mpsc::channel(); @@ -437,12 +439,13 @@ impl SimpleState { char_width_calcurator, color_theme, window_size, + ui_string_sender, action_queue_sender, post_action_queue_sender, global_direction: Direction::Horizontal, }; - simple_state_callback.init(&mut glyph_vertex_buffer, &context); + simple_state_callback.init(&context); Self { context, @@ -456,6 +459,7 @@ impl SimpleState { glyph_vertex_buffer, simple_state_callback, + ui_string_receiver, action_queue_receiver, post_action_queue_receiver, } @@ -501,11 +505,22 @@ impl SimpleState { } pub fn update(&mut self) { - self.simple_state_callback - .update(&mut self.glyph_vertex_buffer, &self.context); + self.simple_state_callback.update(&self.context); } pub fn render(&mut self) -> Result<(), wgpu::SurfaceError> { + record_start_of_phase("render 0: append glyph"); + self.ui_string_receiver + .try_recv() + .into_iter() + .for_each(|s| { + let _ = self.glyph_vertex_buffer.append_glyph( + &self.context.device, + &self.context.queue, + s.chars().collect(), + ); + }); + record_start_of_phase("render 1: setup encoder"); let mut encoder = self.context @@ -652,10 +667,11 @@ impl ImageState { let font_binaries = Arc::new(font_binaries); let char_width_calcurator = Arc::new(CharWidthCalculator::new(font_binaries.clone())); - let mut glyph_vertex_buffer = + let glyph_vertex_buffer = GlyphVertexBuffer::new(font_binaries.clone(), char_width_calcurator.clone()); // 実際には使われない sender + let (ui_string_sender, _ui_string_receiver) = std::sync::mpsc::channel(); let (action_queue_sender, _action_queue_receiver) = std::sync::mpsc::channel(); let (post_action_queue_sender, _post_action_queue_receiver) = std::sync::mpsc::channel(); @@ -665,12 +681,13 @@ impl ImageState { char_width_calcurator, color_theme, window_size: size, + ui_string_sender, action_queue_sender, post_action_queue_sender, global_direction: Direction::Horizontal, }; - simple_state_callback.init(&mut glyph_vertex_buffer, &context); + simple_state_callback.init(&context); simple_state_callback.resize(context.window_size); Self { @@ -687,8 +704,7 @@ impl ImageState { } pub fn update(&mut self) { - self.simple_state_callback - .update(&mut self.glyph_vertex_buffer, &self.context); + self.simple_state_callback.update(&self.context); } pub fn render(&mut self) -> Result, Vec>, wgpu::SurfaceError> { diff --git a/font_rasterizer_example/src/lib.rs b/font_rasterizer_example/src/lib.rs index 36333475..a457129a 100644 --- a/font_rasterizer_example/src/lib.rs +++ b/font_rasterizer_example/src/lib.rs @@ -9,7 +9,6 @@ use font_rasterizer::{ camera::{Camera, CameraController}, color_theme::ColorTheme, context::{StateContext, WindowSize}, - font_buffer::GlyphVertexBuffer, instances::{GlyphInstance, GlyphInstances}, motion::{EasingFuncType, MotionDetail, MotionFlags, MotionTarget, MotionType}, rasterizer_pipeline::Quarity, @@ -100,7 +99,7 @@ impl SingleCharCallback { } impl SimpleStateCallback for SingleCharCallback { - fn init(&mut self, glyph_vertex_buffer: &mut GlyphVertexBuffer, context: &StateContext) { + fn init(&mut self, context: &StateContext) { let value = GlyphInstance { color: context.color_theme.cyan().get_color(), motion: self.motion.motion_flags(), @@ -112,12 +111,10 @@ impl SimpleStateCallback for SingleCharCallback { instance.push(value); self.glyphs.push(instance); let chars = vec!['あ'].into_iter().collect(); - glyph_vertex_buffer - .append_glyph(&context.device, &context.queue, chars) - .unwrap(); + context.ui_string_sender.send(chars).unwrap(); } - fn update(&mut self, _glyph_vertex_buffer: &mut GlyphVertexBuffer, context: &StateContext) { + fn update(&mut self, context: &StateContext) { self.glyphs .iter_mut() .for_each(|i| i.update_buffer(&context.device, &context.queue)); diff --git a/kashikishi/src/main.rs b/kashikishi/src/main.rs index 4833179f..7d40b304 100644 --- a/kashikishi/src/main.rs +++ b/kashikishi/src/main.rs @@ -22,7 +22,7 @@ use font_rasterizer::{ camera::{Camera, CameraAdjustment, CameraOperation}, color_theme::ColorTheme, context::{StateContext, WindowSize}, - font_buffer::{Direction, GlyphVertexBuffer}, + font_buffer::Direction, instances::GlyphInstances, layout_engine::{Model, ModelOperation, World}, rasterizer_pipeline::Quarity, @@ -34,7 +34,6 @@ use font_rasterizer::{ ui::{caret_char, ime_chars, ImeInput}, }; use log::info; -use std::collections::HashSet; use winit::event::WindowEvent; use crate::kashikishi_actions::command_palette_select; @@ -89,14 +88,13 @@ impl ActionProcessor for SystemCommandPalette { arg: &ActionArgument, context: &StateContext, world: &mut dyn World, - new_chars: &mut HashSet, ) -> InputResult { let narrow = match arg { ActionArgument::String(value) => Some(value.to_owned()), _ => None, }; let modal = command_palette_select(context, narrow); - new_chars.extend(modal.to_string().chars()); + context.ui_string_sender.send(modal.to_string()).unwrap(); world.add_next(Box::new(modal)); world.re_layout(); let adjustment = if context.global_direction == Direction::Horizontal { @@ -163,7 +161,6 @@ struct KashikishiCallback { world: Box, ime: ImeInput, action_processor_store: ActionProcessorStore, - new_chars: HashSet, rokid_max: Option, ar_mode: bool, } @@ -190,13 +187,12 @@ impl KashikishiCallback { world: Box::new(NullWorld::new(window_size)), ime, action_processor_store, - new_chars: HashSet::new(), rokid_max, ar_mode: false, } } - fn execute_editor_action(command_name: &str, chars: &mut HashSet) -> EditorOperation { + fn execute_editor_action(command_name: &str, context: &StateContext) -> EditorOperation { match command_name { "return" => EditorOperation::InsertEnter, "backspace" => EditorOperation::Backspace, @@ -216,7 +212,7 @@ impl KashikishiCallback { "buffer-last" => EditorOperation::BufferLast, "paste" => match Clipboard::new().and_then(|mut context| context.get_text()) { Ok(text) => { - chars.extend(text.chars()); + context.ui_string_sender.send(text.clone()).unwrap(); EditorOperation::InsertString(text) } Err(_) => EditorOperation::Noop, @@ -331,23 +327,20 @@ impl KashikishiCallback { } impl SimpleStateCallback for KashikishiCallback { - fn init(&mut self, glyph_vertex_buffer: &mut GlyphVertexBuffer, context: &StateContext) { + fn init(&mut self, context: &StateContext) { // 初期状態で表示するワールドを設定する self.world = Box::new(StartWorld::new(context)); // world にすでに表示されるグリフを追加する let mut chars = self.world.world_chars(); - // キャレットのグリフを追加する chars.insert(caret_char(text_buffer::caret::CaretType::Primary)); chars.insert(caret_char(text_buffer::caret::CaretType::Mark)); - // IME のグリフを追加する - chars.extend(ime_chars().iter().cloned()); - - // グリフバッファに追加する - glyph_vertex_buffer - .append_glyph(&context.device, &context.queue, chars) + chars.extend(ime_chars()); + context + .ui_string_sender + .send(chars.into_iter().collect::()) .unwrap(); // カメラを初期化する @@ -361,16 +354,8 @@ impl SimpleStateCallback for KashikishiCallback { self.world.get_mut().change_window_size(window_size); } - fn update(&mut self, glyph_vertex_buffer: &mut GlyphVertexBuffer, context: &StateContext) { - // 入力などで新しい char が追加されたら、グリフバッファに追加する - if !self.new_chars.is_empty() { - let new_chars = self.new_chars.clone(); - glyph_vertex_buffer - .append_glyph(&context.device, &context.queue, new_chars) - .unwrap(); - self.new_chars.clear(); - } - self.world.get_mut().update(glyph_vertex_buffer, context); + fn update(&mut self, context: &StateContext) { + self.world.get_mut().update(context); self.ime.update(context); // AR モードが有効な場合はカメラの向きを変える。少し雑だが良い場所が見つかるまでここで。 @@ -394,12 +379,9 @@ impl SimpleStateCallback for KashikishiCallback { } fn action(&mut self, context: &StateContext, action: Action) -> InputResult { - let result = self.action_processor_store.process( - &action, - context, - self.world.get_mut(), - &mut self.new_chars, - ); + let result = self + .action_processor_store + .process(&action, context, self.world.get_mut()); if result != InputResult::Noop { return result; } @@ -407,7 +389,7 @@ impl SimpleStateCallback for KashikishiCallback { match action { Action::Command(category, name, argument) => match &*category.to_string() { "edit" => { - let op = Self::execute_editor_action(&name, &mut self.new_chars); + let op = Self::execute_editor_action(&name, context); self.world.get_mut().editor_operation(&op); InputResult::InputConsumed } @@ -428,7 +410,10 @@ impl SimpleStateCallback for KashikishiCallback { if let Some(world) = world { self.world.graceful_exit(); self.world = world; - self.new_chars.extend(self.world.world_chars()); + context + .ui_string_sender + .send(self.world.world_chars().into_iter().collect()) + .unwrap(); context .post_action_queue_sender .send(Action::new_command("world", "fit-by-direction")) @@ -440,18 +425,21 @@ impl SimpleStateCallback for KashikishiCallback { let (result, chars) = self .world .apply_action(context, Action::Command(category, name, argument)); - self.new_chars.extend(chars); + context + .ui_string_sender + .send(chars.into_iter().collect()) + .unwrap(); result } }, Action::Keytype(c) => { - self.new_chars.insert(c); + context.ui_string_sender.send(c.to_string()).unwrap(); let action = EditorOperation::InsertChar(c); self.world.get_mut().editor_operation(&action); InputResult::InputConsumed } Action::ImeInput(value) => { - self.new_chars.extend(value.chars()); + context.ui_string_sender.send(value.clone()).unwrap(); self.ime .apply_ime_event(&Action::ImeInput(value.clone()), context); self.world @@ -460,7 +448,7 @@ impl SimpleStateCallback for KashikishiCallback { InputResult::InputConsumed } Action::ImePreedit(value, position) => { - self.new_chars.extend(value.chars()); + context.ui_string_sender.send(value.clone()).unwrap(); self.ime .apply_ime_event(&Action::ImePreedit(value, position), context); InputResult::InputConsumed diff --git a/rokid_3dof/examples/rokid_test.rs b/rokid_3dof/examples/rokid_test.rs index c614d9e2..7b9f29c0 100644 --- a/rokid_3dof/examples/rokid_test.rs +++ b/rokid_3dof/examples/rokid_test.rs @@ -9,7 +9,6 @@ use font_rasterizer::{ camera::{Camera, CameraController}, color_theme::ColorTheme::{self, SolarizedDark}, context::{StateContext, WindowSize}, - font_buffer::GlyphVertexBuffer, instances::{GlyphInstance, GlyphInstances}, motion::{EasingFuncType, MotionDetail, MotionFlags, MotionTarget, MotionType}, rasterizer_pipeline::Quarity, @@ -107,7 +106,7 @@ impl SingleCharCallback { } impl SimpleStateCallback for SingleCharCallback { - fn init(&mut self, glyph_vertex_buffer: &mut GlyphVertexBuffer, context: &StateContext) { + fn init(&mut self, context: &StateContext) { let value = GlyphInstance::new( (0.0, 0.0, 0.0).into(), cgmath::Quaternion::from_axis_angle(cgmath::Vector3::unit_z(), cgmath::Deg(0.0)), @@ -122,16 +121,10 @@ impl SimpleStateCallback for SingleCharCallback { let mut instance = GlyphInstances::new('あ', &context.device); instance.push(value); self.glyphs.push(instance); - glyph_vertex_buffer - .append_glyph( - &context.device, - &context.queue, - ['あ'].iter().cloned().collect(), - ) - .unwrap(); + context.ui_string_sender.send("あ".to_string()).unwrap(); } - fn update(&mut self, _glyph_vertex_buffer: &mut GlyphVertexBuffer, context: &StateContext) { + fn update(&mut self, context: &StateContext) { let q = self.rokid_max.quaternion(); self.camera_controller .update_eye_quatanion(&mut self.camera, Some(q)); diff --git a/sample_codes/showcase/src/lib.rs b/sample_codes/showcase/src/lib.rs index 798ce682..9eb73861 100644 --- a/sample_codes/showcase/src/lib.rs +++ b/sample_codes/showcase/src/lib.rs @@ -1,7 +1,4 @@ -use std::{ - collections::HashSet, - sync::{mpsc::Sender, LazyLock, Mutex}, -}; +use std::sync::{mpsc::Sender, LazyLock, Mutex}; use font_collector::FontCollector; use stroke_parser::{action_store_parser::parse_setting, Action, ActionArgument, ActionStore}; @@ -13,7 +10,7 @@ use font_rasterizer::{ camera::{Camera, CameraAdjustment, CameraOperation}, color_theme::ColorTheme, context::{StateContext, TextContext, WindowSize}, - font_buffer::{Direction, GlyphVertexBuffer}, + font_buffer::Direction, instances::GlyphInstances, layout_engine::{HorizontalWorld, Model, ModelOperation, World}, rasterizer_pipeline::Quarity, @@ -124,7 +121,6 @@ struct SingleCharCallback { world: HorizontalWorld, store: ActionStore, ime: ImeInput, - new_chars: HashSet, } impl SingleCharCallback { @@ -144,17 +140,8 @@ impl SingleCharCallback { world.add(Box::new(textedit)); world.look_current(CameraAdjustment::FitBothAndCentering); let ime = ImeInput::new(); - let mut new_chars = HashSet::new(); - // キャレットのグリフを追加する - new_chars.insert(caret_char(text_buffer::caret::CaretType::Primary)); - new_chars.insert(caret_char(text_buffer::caret::CaretType::Mark)); - - Self { - world, - store, - ime, - new_chars, - } + + Self { world, store, ime } } fn execute_system_action( @@ -292,11 +279,20 @@ impl SingleCharCallback { } impl SimpleStateCallback for SingleCharCallback { - fn init(&mut self, glyph_vertex_buffer: &mut GlyphVertexBuffer, context: &StateContext) { + fn init(&mut self, context: &StateContext) { set_action_sender(context.action_queue_sender.clone()); - glyph_vertex_buffer - .append_glyph(&context.device, &context.queue, self.world.chars()) + context + .ui_string_sender + .send(caret_char(text_buffer::caret::CaretType::Primary).to_string()) + .unwrap(); + context + .ui_string_sender + .send(caret_char(text_buffer::caret::CaretType::Mark).to_string()) + .unwrap(); + context + .ui_string_sender + .send(self.world.chars().into_iter().collect::()) .unwrap(); [ Action::new_command_with_argument("system", "change-theme", "light"), @@ -310,16 +306,8 @@ impl SimpleStateCallback for SingleCharCallback { }); } - fn update(&mut self, glyph_vertex_buffer: &mut GlyphVertexBuffer, context: &StateContext) { - // 入力などで新しい char が追加されたら、グリフバッファに追加する - if !self.new_chars.is_empty() { - let new_chars = self.new_chars.clone(); - glyph_vertex_buffer - .append_glyph(&context.device, &context.queue, new_chars) - .unwrap(); - self.new_chars.clear(); - } - self.world.update(glyph_vertex_buffer, context); + fn update(&mut self, context: &StateContext) { + self.world.update(context); self.ime.update(context); } @@ -355,13 +343,13 @@ impl SimpleStateCallback for SingleCharCallback { _ => InputResult::Noop, }, Action::Keytype(c) => { - self.new_chars.insert(c); + context.ui_string_sender.send(c.to_string()).unwrap(); let action = EditorOperation::InsertChar(c); self.world.editor_operation(&action); InputResult::InputConsumed } Action::ImeInput(value) => { - self.new_chars.extend(value.chars()); + context.ui_string_sender.send(value.clone()).unwrap(); self.ime .apply_ime_event(&Action::ImeInput(value.clone()), context); self.world @@ -369,7 +357,7 @@ impl SimpleStateCallback for SingleCharCallback { InputResult::InputConsumed } Action::ImePreedit(value, position) => { - self.new_chars.extend(value.chars()); + context.ui_string_sender.send(value.clone()).unwrap(); self.ime .apply_ime_event(&Action::ImePreedit(value, position), context); InputResult::InputConsumed diff --git a/sample_codes/slideshow/src/lib.rs b/sample_codes/slideshow/src/lib.rs index 8c327913..c72a8640 100644 --- a/sample_codes/slideshow/src/lib.rs +++ b/sample_codes/slideshow/src/lib.rs @@ -7,7 +7,6 @@ use font_rasterizer::{ camera::{Camera, CameraAdjustment, CameraOperation}, color_theme::ColorTheme, context::{StateContext, WindowSize}, - font_buffer::GlyphVertexBuffer, instances::GlyphInstances, layout_engine::{HorizontalWorld, World}, motion::{MotionDetail, MotionFlags, MotionTarget}, @@ -109,17 +108,17 @@ impl SingleCharCallback { } impl SimpleStateCallback for SingleCharCallback { - fn init(&mut self, glyph_vertex_buffer: &mut GlyphVertexBuffer, context: &StateContext) { - self.update(glyph_vertex_buffer, context); + fn init(&mut self, context: &StateContext) { + self.update(context); } fn resize(&mut self, window_size: WindowSize) { self.world.change_window_size(window_size); } - fn update(&mut self, glyph_vertex_buffer: &mut GlyphVertexBuffer, context: &StateContext) { + fn update(&mut self, context: &StateContext) { self.world.re_layout(); - self.world.update(glyph_vertex_buffer, context); + self.world.update(context); } fn input(&mut self, _context: &StateContext, event: &WindowEvent) -> InputResult { From ebeb699e9b4786785d90279e6f93b916bbd9fb88 Mon Sep 17 00:00:00 2001 From: mitoma Date: Wed, 23 Oct 2024 19:49:57 +0900 Subject: [PATCH 06/11] =?UTF-8?q?lambda=20=E3=81=AA=20action=20processor?= =?UTF-8?q?=20=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/support/action_processor.rs | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/font_rasterizer/src/support/action_processor.rs b/font_rasterizer/src/support/action_processor.rs index 73ed55b1..9a0ebabc 100644 --- a/font_rasterizer/src/support/action_processor.rs +++ b/font_rasterizer/src/support/action_processor.rs @@ -26,6 +26,19 @@ impl ActionProcessorStore { self.add_processor(Box::new(SystemChangeTheme)); } + pub fn add_lambda_processor( + &mut self, + namespace: &str, + name: &str, + f: fn(&ActionArgument, &StateContext, &mut dyn World) -> InputResult, + ) { + self.processors.push(Box::new(LambdaActionProcessor { + namespace: CommandNamespace::from(namespace), + name: CommandName::from(name), + f, + })); + } + pub fn add_processor(&mut self, processor: Box) { self.processors.push(processor); } @@ -63,6 +76,36 @@ pub trait ActionProcessor { ) -> InputResult; } +pub struct LambdaActionProcessor +where + F: Fn(&ActionArgument, &StateContext, &mut dyn World) -> InputResult, +{ + namespace: CommandNamespace, + name: CommandName, + f: F, +} + +impl ActionProcessor + for LambdaActionProcessor InputResult> +{ + fn namespace(&self) -> CommandNamespace { + self.namespace.clone() + } + + fn name(&self) -> CommandName { + self.name.clone() + } + + fn process( + &self, + arg: &ActionArgument, + context: &StateContext, + world: &mut dyn World, + ) -> InputResult { + (self.f)(arg, context, world) + } +} + // ----- impl system ----- pub struct SystemExit; impl ActionProcessor for SystemExit { From 16a1a49a41643e325331f085ecda27918f8532a7 Mon Sep 17 00:00:00 2001 From: mitoma Date: Wed, 23 Oct 2024 20:10:21 +0900 Subject: [PATCH 07/11] =?UTF-8?q?action=20=E3=81=AE=E5=A0=B4=E6=89=80?= =?UTF-8?q?=E3=82=92=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- font_rasterizer/src/support/action/mod.rs | 129 ++++++++++++++++++ .../{action_processor.rs => action/system.rs} | 123 +---------------- font_rasterizer/src/support/mod.rs | 2 +- kashikishi/src/main.rs | 2 +- 4 files changed, 133 insertions(+), 123 deletions(-) create mode 100644 font_rasterizer/src/support/action/mod.rs rename font_rasterizer/src/support/{action_processor.rs => action/system.rs} (57%) diff --git a/font_rasterizer/src/support/action/mod.rs b/font_rasterizer/src/support/action/mod.rs new file mode 100644 index 00000000..2af93a6f --- /dev/null +++ b/font_rasterizer/src/support/action/mod.rs @@ -0,0 +1,129 @@ +mod system; +pub use system::*; + +use stroke_parser::{Action, ActionArgument, CommandName, CommandNamespace}; + +use crate::{context::StateContext, layout_engine::World}; + +use super::InputResult; + +#[derive(Default)] +pub struct ActionProcessorStore { + processors: Vec>, +} + +impl ActionProcessorStore { + pub fn add_default_system_processors(&mut self) { + self.add_processor(Box::new(SystemExit)); + self.add_processor(Box::new(SystemToggleFullscreen)); + self.add_processor(Box::new(SystemToggleTitlebar)); + self.add_processor(Box::new(SystemChangeGlobalDirection)); + self.add_processor(Box::new(SystemChangeThemeUi)); + self.add_processor(Box::new(SystemChangeTheme)); + } + + pub fn add_lambda_processor( + &mut self, + namespace: &str, + name: &str, + f: fn(&ActionArgument, &StateContext, &mut dyn World) -> InputResult, + ) { + self.processors.push(Box::new(LambdaActionProcessor { + namespace: CommandNamespace::from(namespace), + name: CommandName::from(name), + f, + })); + } + + pub fn add_processor(&mut self, processor: Box) { + self.processors.push(processor); + } + + pub fn remove_processor(&mut self, namespace: &CommandNamespace, name: &CommandName) { + self.processors + .retain(|processor| processor.namespace() != *namespace || processor.name() != *name); + } + + pub fn process( + &self, + action: &Action, + context: &StateContext, + world: &mut dyn World, + ) -> InputResult { + if let Action::Command(namespace, name, argument) = action { + for processor in &self.processors { + if processor.namespace() == *namespace && processor.name() == *name { + return processor.process(argument, context, world); + } + } + } + InputResult::Noop + } +} + +pub trait ActionProcessor { + fn namespace(&self) -> CommandNamespace; + fn name(&self) -> CommandName; + fn process( + &self, + arg: &ActionArgument, + context: &StateContext, + world: &mut dyn World, + ) -> InputResult; +} + +pub struct LambdaActionProcessor +where + F: Fn(&ActionArgument, &StateContext, &mut dyn World) -> InputResult, +{ + namespace: CommandNamespace, + name: CommandName, + f: F, +} + +impl ActionProcessor + for LambdaActionProcessor InputResult> +{ + fn namespace(&self) -> CommandNamespace { + self.namespace.clone() + } + + fn name(&self) -> CommandName { + self.name.clone() + } + + fn process( + &self, + arg: &ActionArgument, + context: &StateContext, + world: &mut dyn World, + ) -> InputResult { + (self.f)(arg, context, world) + } +} + +// ----- impl system ----- + +// ----- impl edit ----- +/* +pub struct EditForward; +impl ActionProcessor for EditForward { + fn namespace(&self) -> CommandNamespace { + "edit".into() + } + + fn name(&self) -> CommandName { + "forward".into() + } + + fn process( + &self, + _arg: &ActionArgument, + _context: &StateContext, + world: &mut dyn World, + ) -> Option { + world.editor_operation(&EditorOperation::Forward); + Some(InputResult::InputConsumed) + } +} + */ diff --git a/font_rasterizer/src/support/action_processor.rs b/font_rasterizer/src/support/action/system.rs similarity index 57% rename from font_rasterizer/src/support/action_processor.rs rename to font_rasterizer/src/support/action/system.rs index 9a0ebabc..b38b7edd 100644 --- a/font_rasterizer/src/support/action_processor.rs +++ b/font_rasterizer/src/support/action/system.rs @@ -6,107 +6,12 @@ use crate::{ context::StateContext, font_buffer::Direction, layout_engine::{Model, World}, + support::InputResult, ui::{SelectBox, SelectOption}, }; -use super::InputResult; +use super::ActionProcessor; -#[derive(Default)] -pub struct ActionProcessorStore { - processors: Vec>, -} - -impl ActionProcessorStore { - pub fn add_default_system_processors(&mut self) { - self.add_processor(Box::new(SystemExit)); - self.add_processor(Box::new(SystemToggleFullscreen)); - self.add_processor(Box::new(SystemToggleTitlebar)); - self.add_processor(Box::new(SystemChangeGlobalDirection)); - self.add_processor(Box::new(SystemChangeThemeUi)); - self.add_processor(Box::new(SystemChangeTheme)); - } - - pub fn add_lambda_processor( - &mut self, - namespace: &str, - name: &str, - f: fn(&ActionArgument, &StateContext, &mut dyn World) -> InputResult, - ) { - self.processors.push(Box::new(LambdaActionProcessor { - namespace: CommandNamespace::from(namespace), - name: CommandName::from(name), - f, - })); - } - - pub fn add_processor(&mut self, processor: Box) { - self.processors.push(processor); - } - - pub fn remove_processor(&mut self, namespace: &CommandNamespace, name: &CommandName) { - self.processors - .retain(|processor| processor.namespace() != *namespace || processor.name() != *name); - } - - pub fn process( - &self, - action: &Action, - context: &StateContext, - world: &mut dyn World, - ) -> InputResult { - if let Action::Command(namespace, name, argument) = action { - for processor in &self.processors { - if processor.namespace() == *namespace && processor.name() == *name { - return processor.process(argument, context, world); - } - } - } - InputResult::Noop - } -} - -pub trait ActionProcessor { - fn namespace(&self) -> CommandNamespace; - fn name(&self) -> CommandName; - fn process( - &self, - arg: &ActionArgument, - context: &StateContext, - world: &mut dyn World, - ) -> InputResult; -} - -pub struct LambdaActionProcessor -where - F: Fn(&ActionArgument, &StateContext, &mut dyn World) -> InputResult, -{ - namespace: CommandNamespace, - name: CommandName, - f: F, -} - -impl ActionProcessor - for LambdaActionProcessor InputResult> -{ - fn namespace(&self) -> CommandNamespace { - self.namespace.clone() - } - - fn name(&self) -> CommandName { - self.name.clone() - } - - fn process( - &self, - arg: &ActionArgument, - context: &StateContext, - world: &mut dyn World, - ) -> InputResult { - (self.f)(arg, context, world) - } -} - -// ----- impl system ----- pub struct SystemExit; impl ActionProcessor for SystemExit { fn namespace(&self) -> CommandNamespace { @@ -266,27 +171,3 @@ impl ActionProcessor for SystemChangeGlobalDirection { InputResult::ChangeGlobalDirection(context.global_direction.toggle()) } } - -// ----- impl edit ----- -/* -pub struct EditForward; -impl ActionProcessor for EditForward { - fn namespace(&self) -> CommandNamespace { - "edit".into() - } - - fn name(&self) -> CommandName { - "forward".into() - } - - fn process( - &self, - _arg: &ActionArgument, - _context: &StateContext, - world: &mut dyn World, - ) -> Option { - world.editor_operation(&EditorOperation::Forward); - Some(InputResult::InputConsumed) - } -} - */ diff --git a/font_rasterizer/src/support/mod.rs b/font_rasterizer/src/support/mod.rs index f250062e..62ce9413 100644 --- a/font_rasterizer/src/support/mod.rs +++ b/font_rasterizer/src/support/mod.rs @@ -1,4 +1,4 @@ -pub mod action_processor; +pub mod action; mod metrics_counter; mod render_rate_adjuster; diff --git a/kashikishi/src/main.rs b/kashikishi/src/main.rs index 7d40b304..035f6d3e 100644 --- a/kashikishi/src/main.rs +++ b/kashikishi/src/main.rs @@ -27,7 +27,7 @@ use font_rasterizer::{ layout_engine::{Model, ModelOperation, World}, rasterizer_pipeline::Quarity, support::{ - action_processor::{ActionProcessor, ActionProcessorStore}, + action::{ActionProcessor, ActionProcessorStore}, run_support, Flags, InputResult, SimpleStateCallback, SimpleStateSupport, }, time::set_clock_mode, From 09bf4c220aff1b8b8485c028fa21770af9ddbdca Mon Sep 17 00:00:00 2001 From: mitoma Date: Wed, 23 Oct 2024 20:55:32 +0900 Subject: [PATCH 08/11] =?UTF-8?q?=E7=B7=A8=E9=9B=86=E7=B3=BB=E3=81=AE?= =?UTF-8?q?=E3=82=A2=E3=82=AF=E3=82=B7=E3=83=A7=E3=83=B3=E3=82=82=E6=95=B4?= =?UTF-8?q?=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- font_rasterizer/src/support/action/edit.rs | 51 +++++++++++++++++ font_rasterizer/src/support/action/mod.rs | 23 ++++++++ kashikishi/src/main.rs | 66 ++++++++-------------- 3 files changed, 98 insertions(+), 42 deletions(-) create mode 100644 font_rasterizer/src/support/action/edit.rs diff --git a/font_rasterizer/src/support/action/edit.rs b/font_rasterizer/src/support/action/edit.rs new file mode 100644 index 00000000..9ab33839 --- /dev/null +++ b/font_rasterizer/src/support/action/edit.rs @@ -0,0 +1,51 @@ +use stroke_parser::{ActionArgument, CommandName, CommandNamespace}; +use text_buffer::action::EditorOperation; + +use crate::{context::StateContext, layout_engine::World, support::InputResult}; + +use super::ActionProcessor; + +macro_rules! edit_processor { + ( $proc_name:ident, $name:expr, $editor_operation:ident ) => { + pub struct $proc_name; + impl ActionProcessor for $proc_name { + fn namespace(&self) -> CommandNamespace { + "edit".into() + } + + fn name(&self) -> CommandName { + $name.into() + } + + fn process( + &self, + _arg: &ActionArgument, + _context: &StateContext, + world: &mut dyn World, + ) -> InputResult { + world.editor_operation(&EditorOperation::$editor_operation); + InputResult::InputConsumed + } + } + }; +} + +// 編集系の処理。Copy, Paste, Cut は OS 依存の処理なのでここでは定義しない。 +edit_processor!(EditReturn, "return", InsertEnter); +edit_processor!(EditBackspace, "backspace", Backspace); +edit_processor!(EditBackspaceWord, "backspace-word", BackspaceWord); +edit_processor!(EditDelete, "delete", Delete); +edit_processor!(EditDeleteWord, "delete-word", DeleteWord); +edit_processor!(EditPrevious, "previous", Previous); +edit_processor!(EditNext, "next", Next); +edit_processor!(EditBack, "back", Back); +edit_processor!(EditForward, "forward", Forward); +edit_processor!(EditBackWord, "back-word", BackWord); +edit_processor!(EditForwardWord, "forward-word", ForwardWord); +edit_processor!(EditHead, "head", Head); +edit_processor!(EditLast, "last", Last); +edit_processor!(EditUndo, "undo", Undo); +edit_processor!(EditBufferHead, "buffer-head", BufferHead); +edit_processor!(EditBufferLast, "buffer-last", BufferLast); +edit_processor!(EditMark, "mark", Mark); +edit_processor!(EditUnmark, "unmark", UnMark); diff --git a/font_rasterizer/src/support/action/mod.rs b/font_rasterizer/src/support/action/mod.rs index 2af93a6f..44288dbc 100644 --- a/font_rasterizer/src/support/action/mod.rs +++ b/font_rasterizer/src/support/action/mod.rs @@ -1,4 +1,6 @@ +mod edit; mod system; +pub use edit::*; pub use system::*; use stroke_parser::{Action, ActionArgument, CommandName, CommandNamespace}; @@ -22,6 +24,27 @@ impl ActionProcessorStore { self.add_processor(Box::new(SystemChangeTheme)); } + pub fn add_default_edit_processors(&mut self) { + self.add_processor(Box::new(EditReturn)); + self.add_processor(Box::new(EditBackspace)); + self.add_processor(Box::new(EditBackspaceWord)); + self.add_processor(Box::new(EditDelete)); + self.add_processor(Box::new(EditDeleteWord)); + self.add_processor(Box::new(EditPrevious)); + self.add_processor(Box::new(EditNext)); + self.add_processor(Box::new(EditBack)); + self.add_processor(Box::new(EditForward)); + self.add_processor(Box::new(EditBackWord)); + self.add_processor(Box::new(EditForwardWord)); + self.add_processor(Box::new(EditHead)); + self.add_processor(Box::new(EditLast)); + self.add_processor(Box::new(EditUndo)); + self.add_processor(Box::new(EditBufferHead)); + self.add_processor(Box::new(EditBufferLast)); + self.add_processor(Box::new(EditMark)); + self.add_processor(Box::new(EditUnmark)); + } + pub fn add_lambda_processor( &mut self, namespace: &str, diff --git a/kashikishi/src/main.rs b/kashikishi/src/main.rs index 035f6d3e..cba585e1 100644 --- a/kashikishi/src/main.rs +++ b/kashikishi/src/main.rs @@ -179,6 +179,30 @@ impl KashikishiCallback { let mut action_processor_store = ActionProcessorStore::default(); action_processor_store.add_default_system_processors(); action_processor_store.add_processor(Box::new(SystemCommandPalette)); + action_processor_store.add_default_edit_processors(); + // clipboard を使う処理はプラットフォーム依存なのでここで追加する + action_processor_store.add_lambda_processor("edit", "paste", |_, context, world| { + match Clipboard::new().and_then(|mut context| context.get_text()) { + Ok(text) => { + context.ui_string_sender.send(text.clone()).unwrap(); + world.editor_operation(&EditorOperation::InsertString(text)); + InputResult::InputConsumed + } + Err(_) => InputResult::Noop, + } + }); + action_processor_store.add_lambda_processor("edit", "copy", |_, _, world| { + world.editor_operation(&EditorOperation::Copy(|text| { + let _ = Clipboard::new().and_then(|mut context| context.set_text(text)); + })); + InputResult::InputConsumed + }); + action_processor_store.add_lambda_processor("edit", "cut", |_, _, world| { + world.editor_operation(&EditorOperation::Cut(|text| { + let _ = Clipboard::new().and_then(|mut context| context.set_text(text)); + })); + InputResult::InputConsumed + }); let rokid_max = RokidMax::new().ok(); @@ -192,43 +216,6 @@ impl KashikishiCallback { } } - fn execute_editor_action(command_name: &str, context: &StateContext) -> EditorOperation { - match command_name { - "return" => EditorOperation::InsertEnter, - "backspace" => EditorOperation::Backspace, - "backspace-word" => EditorOperation::BackspaceWord, - "delete" => EditorOperation::Delete, - "delete-word" => EditorOperation::DeleteWord, - "previous" => EditorOperation::Previous, - "next" => EditorOperation::Next, - "back" => EditorOperation::Back, - "forward" => EditorOperation::Forward, - "back-word" => EditorOperation::BackWord, - "forward-word" => EditorOperation::ForwardWord, - "head" => EditorOperation::Head, - "last" => EditorOperation::Last, - "undo" => EditorOperation::Undo, - "buffer-head" => EditorOperation::BufferHead, - "buffer-last" => EditorOperation::BufferLast, - "paste" => match Clipboard::new().and_then(|mut context| context.get_text()) { - Ok(text) => { - context.ui_string_sender.send(text.clone()).unwrap(); - EditorOperation::InsertString(text) - } - Err(_) => EditorOperation::Noop, - }, - "copy" => EditorOperation::Copy(|text| { - let _ = Clipboard::new().and_then(|mut context| context.set_text(text)); - }), - "cut" => EditorOperation::Cut(|text| { - let _ = Clipboard::new().and_then(|mut context| context.set_text(text)); - }), - "mark" => EditorOperation::Mark, - "unmark" => EditorOperation::UnMark, - _ => EditorOperation::Noop, - } - } - fn execute_world_action( &mut self, command_name: &str, @@ -388,11 +375,6 @@ impl SimpleStateCallback for KashikishiCallback { match action { Action::Command(category, name, argument) => match &*category.to_string() { - "edit" => { - let op = Self::execute_editor_action(&name, context); - self.world.get_mut().editor_operation(&op); - InputResult::InputConsumed - } "world" => { self.execute_world_action(&name, argument, context); InputResult::InputConsumed From a8a1b2e09202f6af47ae8446dee776c389799a83 Mon Sep 17 00:00:00 2001 From: mitoma Date: Thu, 24 Oct 2024 00:17:27 +0900 Subject: [PATCH 09/11] =?UTF-8?q?world=20=E7=B3=BB=E3=81=AE=E3=82=A2?= =?UTF-8?q?=E3=82=AF=E3=82=B7=E3=83=A7=E3=83=B3=E3=82=82=E6=95=B4=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- font_rasterizer/src/support/action/mod.rs | 29 +++ font_rasterizer/src/support/action/world.rs | 222 ++++++++++++++++++++ kashikishi/src/main.rs | 70 +----- 3 files changed, 258 insertions(+), 63 deletions(-) create mode 100644 font_rasterizer/src/support/action/world.rs diff --git a/font_rasterizer/src/support/action/mod.rs b/font_rasterizer/src/support/action/mod.rs index 44288dbc..b134d56d 100644 --- a/font_rasterizer/src/support/action/mod.rs +++ b/font_rasterizer/src/support/action/mod.rs @@ -1,7 +1,9 @@ mod edit; mod system; +mod world; pub use edit::*; pub use system::*; +pub use world::*; use stroke_parser::{Action, ActionArgument, CommandName, CommandNamespace}; @@ -45,6 +47,33 @@ impl ActionProcessorStore { self.add_processor(Box::new(EditUnmark)); } + pub fn add_default_world_processors(&mut self) { + self.add_processor(Box::new(WorldRemoveCurrent)); + self.add_processor(Box::new(WorldResetZoom)); + self.add_processor(Box::new(WorldLookCurrent)); + self.add_processor(Box::new(WorldLookNext)); + self.add_processor(Box::new(WorldLookPrev)); + self.add_processor(Box::new(WorldSwapNext)); + self.add_processor(Box::new(WorldSwapPrev)); + self.add_processor(Box::new(WorldFitWidth)); + self.add_processor(Box::new(WorldFitHeight)); + self.add_processor(Box::new(WorldFitByDirection)); + self.add_processor(Box::new(WorldForward)); + self.add_processor(Box::new(WorldBack)); + self.add_processor(Box::new(WorldChangeDirection)); + self.add_processor(Box::new(WorldIncreaseRowInterval)); + self.add_processor(Box::new(WorldDecreaseRowInterval)); + self.add_processor(Box::new(WorldIncreaseColInterval)); + self.add_processor(Box::new(WorldDecreaseColInterval)); + self.add_processor(Box::new(WorldIncreaseRowScale)); + self.add_processor(Box::new(WorldDecreaseRowScale)); + self.add_processor(Box::new(WorldIncreaseColScale)); + self.add_processor(Box::new(WorldDecreaseColScale)); + self.add_processor(Box::new(WorldTogglePsychedelic)); + self.add_processor(Box::new(WorldMoveToClick)); + self.add_processor(Box::new(WorldMoveToClickWithMark)); + } + pub fn add_lambda_processor( &mut self, namespace: &str, diff --git a/font_rasterizer/src/support/action/world.rs b/font_rasterizer/src/support/action/world.rs new file mode 100644 index 00000000..f97921be --- /dev/null +++ b/font_rasterizer/src/support/action/world.rs @@ -0,0 +1,222 @@ +use stroke_parser::{ActionArgument, CommandName, CommandNamespace}; +use text_buffer::action::EditorOperation; + +use crate::{ + camera::{CameraAdjustment, CameraOperation}, + context::StateContext, + font_buffer::Direction, + layout_engine::{ModelOperation, World}, + support::InputResult, +}; + +use super::ActionProcessor; + +macro_rules! world_processor { + ( $proc_name:ident, $name:expr, $world_operation:ident ) => { + pub struct $proc_name; + impl ActionProcessor for $proc_name { + fn namespace(&self) -> CommandNamespace { + "world".into() + } + + fn name(&self) -> CommandName { + $name.into() + } + + fn process( + &self, + arg: &ActionArgument, + context: &StateContext, + world: &mut dyn World, + ) -> InputResult { + $world_operation(arg, context, world); + InputResult::InputConsumed + } + } + }; +} + +world_processor!(WorldRemoveCurrent, "remove-current", remove_current); +fn remove_current(_arg: &ActionArgument, _context: &StateContext, world: &mut dyn World) { + world.remove_current(); + world.re_layout(); + world.look_prev(CameraAdjustment::NoCare); +} + +world_processor!(WorldResetZoom, "reset-zoom", reset_zoom); +fn reset_zoom(_arg: &ActionArgument, _context: &StateContext, world: &mut dyn World) { + world.look_current(CameraAdjustment::FitBoth); +} + +world_processor!(WorldLookCurrent, "look-current", look_current); +fn look_current(_arg: &ActionArgument, _context: &StateContext, world: &mut dyn World) { + world.look_current(CameraAdjustment::NoCare); +} + +world_processor!(WorldLookNext, "look-next", look_next); +fn look_next(_arg: &ActionArgument, _context: &StateContext, world: &mut dyn World) { + world.look_next(CameraAdjustment::NoCare); +} + +world_processor!(WorldLookPrev, "look-prev", look_prev); +fn look_prev(_arg: &ActionArgument, _context: &StateContext, world: &mut dyn World) { + world.look_prev(CameraAdjustment::NoCare); +} + +world_processor!(WorldSwapNext, "swap-next", swap_next); +fn swap_next(_arg: &ActionArgument, _context: &StateContext, world: &mut dyn World) { + world.swap_next(); +} + +world_processor!(WorldSwapPrev, "swap-prev", swap_prev); +fn swap_prev(_arg: &ActionArgument, _context: &StateContext, world: &mut dyn World) { + world.swap_prev(); +} + +world_processor!(WorldFitWidth, "fit-width", fit_width); +fn fit_width(_arg: &ActionArgument, _context: &StateContext, world: &mut dyn World) { + world.look_current(CameraAdjustment::FitWidth); +} + +world_processor!(WorldFitHeight, "fit-height", fit_height); +fn fit_height(_arg: &ActionArgument, _context: &StateContext, world: &mut dyn World) { + world.look_current(CameraAdjustment::FitHeight); +} + +world_processor!(WorldFitByDirection, "fit-by-direction", fit_by_direction); +fn fit_by_direction(_arg: &ActionArgument, context: &StateContext, world: &mut dyn World) { + if context.global_direction == Direction::Horizontal { + world.look_current(CameraAdjustment::FitWidth) + } else { + world.look_current(CameraAdjustment::FitHeight) + } +} + +world_processor!(WorldForward, "forward", forward); +fn forward(_arg: &ActionArgument, _context: &StateContext, world: &mut dyn World) { + world.camera_operation(CameraOperation::Forward); +} + +world_processor!(WorldBack, "back", back); +fn back(_arg: &ActionArgument, _context: &StateContext, world: &mut dyn World) { + world.camera_operation(CameraOperation::Backward); +} + +world_processor!(WorldChangeDirection, "change-direction", change_direction); +fn change_direction(_arg: &ActionArgument, _context: &StateContext, world: &mut dyn World) { + world.model_operation(&ModelOperation::ChangeDirection(None)); +} + +world_processor!( + WorldIncreaseRowInterval, + "increase-row-interval", + increase_row_interval +); +fn increase_row_interval(_arg: &ActionArgument, _context: &StateContext, world: &mut dyn World) { + world.model_operation(&ModelOperation::IncreaseRowInterval); +} + +world_processor!( + WorldDecreaseRowInterval, + "decrease-row-interval", + decrease_row_interval +); +fn decrease_row_interval(_arg: &ActionArgument, _context: &StateContext, world: &mut dyn World) { + world.model_operation(&ModelOperation::DecreaseRowInterval); +} + +world_processor!( + WorldIncreaseColInterval, + "increase-col-interval", + increase_col_interval +); +fn increase_col_interval(_arg: &ActionArgument, _context: &StateContext, world: &mut dyn World) { + world.model_operation(&ModelOperation::IncreaseColInterval); +} + +world_processor!( + WorldDecreaseColInterval, + "decrease-col-interval", + decrease_col_interval +); +fn decrease_col_interval(_arg: &ActionArgument, _context: &StateContext, world: &mut dyn World) { + world.model_operation(&ModelOperation::DecreaseColInterval); +} + +world_processor!( + WorldIncreaseColScale, + "increase-col-scale", + increase_col_scale +); +fn increase_col_scale(_arg: &ActionArgument, _context: &StateContext, world: &mut dyn World) { + world.model_operation(&ModelOperation::IncreaseColScale); +} + +world_processor!( + WorldDecreaseColScale, + "decrease-col-scale", + decrease_col_scale +); +fn decrease_col_scale(_arg: &ActionArgument, _context: &StateContext, world: &mut dyn World) { + world.model_operation(&ModelOperation::DecreaseColScale); +} + +world_processor!( + WorldIncreaseRowScale, + "increase-row-scale", + increase_row_scale +); +fn increase_row_scale(_arg: &ActionArgument, _context: &StateContext, world: &mut dyn World) { + world.model_operation(&ModelOperation::IncreaseRowScale); +} + +world_processor!( + WorldDecreaseRowScale, + "decrease-row-scale", + decrease_row_scale +); +fn decrease_row_scale(_arg: &ActionArgument, _context: &StateContext, world: &mut dyn World) { + world.model_operation(&ModelOperation::DecreaseRowScale); +} + +world_processor!( + WorldTogglePsychedelic, + "toggle-psychedelic", + toggle_psychedelic +); +fn toggle_psychedelic(_arg: &ActionArgument, _context: &StateContext, world: &mut dyn World) { + world.model_operation(&ModelOperation::TogglePsychedelic); +} + +world_processor!(WorldMoveToClick, "move-to-click", move_to_click); +fn move_to_click(arg: &ActionArgument, context: &StateContext, world: &mut dyn World) { + match arg { + ActionArgument::Point((x, y)) => { + let (x_ratio, y_ratio) = ( + (x / context.window_size.width as f32 * 2.0) - 1.0, + 1.0 - (y / context.window_size.height as f32 * 2.0), + ); + world.move_to_position(x_ratio, y_ratio); + } + _ => { /* noop */ } + } +} + +world_processor!( + WorldMoveToClickWithMark, + "move-to-click-with-mark", + move_to_click_with_mark +); +fn move_to_click_with_mark(arg: &ActionArgument, context: &StateContext, world: &mut dyn World) { + match arg { + ActionArgument::Point((x, y)) => { + let (x_ratio, y_ratio) = ( + (x / context.window_size.width as f32 * 2.0) - 1.0, + 1.0 - (y / context.window_size.height as f32 * 2.0), + ); + world.move_to_position(x_ratio, y_ratio); + world.editor_operation(&EditorOperation::Mark); + } + _ => { /* noop */ } + } +} diff --git a/kashikishi/src/main.rs b/kashikishi/src/main.rs index cba585e1..cbe90416 100644 --- a/kashikishi/src/main.rs +++ b/kashikishi/src/main.rs @@ -178,8 +178,9 @@ impl KashikishiCallback { let mut action_processor_store = ActionProcessorStore::default(); action_processor_store.add_default_system_processors(); - action_processor_store.add_processor(Box::new(SystemCommandPalette)); action_processor_store.add_default_edit_processors(); + action_processor_store.add_default_world_processors(); + action_processor_store.add_processor(Box::new(SystemCommandPalette)); // clipboard を使う処理はプラットフォーム依存なのでここで追加する action_processor_store.add_lambda_processor("edit", "paste", |_, context, world| { match Clipboard::new().and_then(|mut context| context.get_text()) { @@ -219,79 +220,22 @@ impl KashikishiCallback { fn execute_world_action( &mut self, command_name: &str, - argument: ActionArgument, + _argument: ActionArgument, context: &StateContext, ) { let world = self.world.get_mut(); match command_name { - "remove-current" => { - world.remove_current(); - world.re_layout(); - world.look_prev(CameraAdjustment::NoCare); - } - "reset-zoom" => world.look_current(CameraAdjustment::FitBoth), - "look-current-and-centering" => { - if let Some(rokid_max) = self.rokid_max.as_mut() { - let _ = rokid_max.reset(); - } - world.look_current(CameraAdjustment::FitBothAndCentering) - } - "look-current" => world.look_current(CameraAdjustment::NoCare), - "look-next" => world.look_next(CameraAdjustment::NoCare), - "look-prev" => world.look_prev(CameraAdjustment::NoCare), - "swap-next" => world.swap_next(), - "swap-prev" => world.swap_prev(), - "fit-width" => world.look_current(CameraAdjustment::FitWidth), - "fit-height" => world.look_current(CameraAdjustment::FitHeight), - "fit-by-direction" => { - if context.global_direction == Direction::Horizontal { - world.look_current(CameraAdjustment::FitWidth) - } else { - world.look_current(CameraAdjustment::FitHeight) - } - } - "forward" => world.camera_operation(CameraOperation::Forward), - "back" => world.camera_operation(CameraOperation::Backward), - "change-direction" => world.model_operation(&ModelOperation::ChangeDirection(None)), - "increase-row-interval" => world.model_operation(&ModelOperation::IncreaseRowInterval), - "decrease-row-interval" => world.model_operation(&ModelOperation::DecreaseRowInterval), - "increase-col-interval" => world.model_operation(&ModelOperation::IncreaseColInterval), - "decrease-col-interval" => world.model_operation(&ModelOperation::DecreaseColInterval), - "increase-col-scale" => world.model_operation(&ModelOperation::IncreaseColScale), - "decrease-col-scale" => world.model_operation(&ModelOperation::DecreaseColScale), - "increase-row-scale" => world.model_operation(&ModelOperation::IncreaseRowScale), - "decrease-row-scale" => world.model_operation(&ModelOperation::DecreaseRowScale), "copy-display" => world.model_operation(&ModelOperation::CopyDisplayString( context.char_width_calcurator.clone(), |text| { let _ = Clipboard::new().and_then(|mut context| context.set_text(text)); }, )), - "toggle-psychedelic" => world.model_operation(&ModelOperation::TogglePsychedelic), - "move-to-click" => { - match argument { - ActionArgument::Point((x, y)) => { - let (x_ratio, y_ratio) = ( - (x / context.window_size.width as f32 * 2.0) - 1.0, - 1.0 - (y / context.window_size.height as f32 * 2.0), - ); - world.move_to_position(x_ratio, y_ratio); - } - _ => { /* noop */ } - } - } - "move-to-click-with-mark" => { - match argument { - ActionArgument::Point((x, y)) => { - let (x_ratio, y_ratio) = ( - (x / context.window_size.width as f32 * 2.0) - 1.0, - 1.0 - (y / context.window_size.height as f32 * 2.0), - ); - world.move_to_position(x_ratio, y_ratio); - world.editor_operation(&EditorOperation::Mark); - } - _ => { /* noop */ } + "look-current-and-centering" => { + if let Some(rokid_max) = self.rokid_max.as_mut() { + let _ = rokid_max.reset(); } + world.look_current(CameraAdjustment::FitBothAndCentering) } // AR 系はアクションのカテゴリを変えるべきだろうか? "reset-rokid" => { From ae8fbe84df6797b157fbd58e2e2b553aae3b99fc Mon Sep 17 00:00:00 2001 From: mitoma Date: Thu, 24 Oct 2024 00:48:54 +0900 Subject: [PATCH 10/11] =?UTF-8?q?showcase=20=E3=81=AE=E3=82=B3=E3=83=BC?= =?UTF-8?q?=E3=83=89=E3=82=92=E3=82=B3=E3=83=94=E3=83=9A=E3=81=98=E3=82=83?= =?UTF-8?q?=E3=81=AA=E3=81=8F=E3=81=9B=E3=81=9F=E3=81=A8=E3=81=93=E3=82=8D?= =?UTF-8?q?=E3=82=92=E5=85=B1=E9=80=9A=E5=8C=96=E3=81=95=E3=82=8C=E3=81=9F?= =?UTF-8?q?=E3=82=B3=E3=83=BC=E3=83=89=E3=81=AB=E7=BD=AE=E3=81=8D=E6=8F=9B?= =?UTF-8?q?=E3=81=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sample_codes/showcase/src/lib.rs | 191 +++++-------------------------- 1 file changed, 31 insertions(+), 160 deletions(-) diff --git a/sample_codes/showcase/src/lib.rs b/sample_codes/showcase/src/lib.rs index 9eb73861..453e04b9 100644 --- a/sample_codes/showcase/src/lib.rs +++ b/sample_codes/showcase/src/lib.rs @@ -1,20 +1,22 @@ use std::sync::{mpsc::Sender, LazyLock, Mutex}; use font_collector::FontCollector; -use stroke_parser::{action_store_parser::parse_setting, Action, ActionArgument, ActionStore}; +use stroke_parser::{action_store_parser::parse_setting, Action, ActionStore}; use text_buffer::action::EditorOperation; #[cfg(target_arch = "wasm32")] use wasm_bindgen::prelude::*; use font_rasterizer::{ - camera::{Camera, CameraAdjustment, CameraOperation}, + camera::{Camera, CameraAdjustment}, color_theme::ColorTheme, context::{StateContext, TextContext, WindowSize}, - font_buffer::Direction, instances::GlyphInstances, - layout_engine::{HorizontalWorld, Model, ModelOperation, World}, + layout_engine::{HorizontalWorld, Model, World}, rasterizer_pipeline::Quarity, - support::{run_support, Flags, InputResult, SimpleStateCallback, SimpleStateSupport}, + support::{ + action::ActionProcessorStore, run_support, Flags, InputResult, SimpleStateCallback, + SimpleStateSupport, + }, ui::{caret_char, ImeInput, TextEdit}, }; use winit::event::WindowEvent; @@ -111,15 +113,10 @@ pub fn send_log(message: &str) { log::warn!("{}", message); } -enum SystemActionResult { - ChangeColorTheme(ColorTheme), - ChangeGlobalDirection(Direction), - Noop, -} - struct SingleCharCallback { world: HorizontalWorld, store: ActionStore, + action_processor_store: ActionProcessorStore, ime: ImeInput, } @@ -141,141 +138,19 @@ impl SingleCharCallback { world.look_current(CameraAdjustment::FitBothAndCentering); let ime = ImeInput::new(); - Self { world, store, ime } - } - - fn execute_system_action( - &mut self, - command_name: &str, - argument: ActionArgument, - context: &StateContext, - ) -> SystemActionResult { - match command_name { - "change-theme" => match argument { - ActionArgument::String(value) => match &*value.to_string() { - "black" => SystemActionResult::ChangeColorTheme(ColorTheme::SolarizedBlackback), - "dark" => SystemActionResult::ChangeColorTheme(ColorTheme::SolarizedDark), - "light" => SystemActionResult::ChangeColorTheme(ColorTheme::SolarizedLight), - _ => SystemActionResult::Noop, - }, - _ => SystemActionResult::Noop, - }, - "change-global-direction" => { - SystemActionResult::ChangeGlobalDirection(context.global_direction.toggle()) - } - _ => SystemActionResult::Noop, + let mut action_processor_store = ActionProcessorStore::default(); + action_processor_store.add_default_system_processors(); + action_processor_store.add_default_world_processors(); + action_processor_store.add_default_edit_processors(); + action_processor_store.remove_processor(&"system".into(), &"exit".into()); + + Self { + world, + store, + action_processor_store, + ime, } } - - fn execute_editor_action(command_name: &str) -> EditorOperation { - match command_name { - "return" => EditorOperation::InsertEnter, - "backspace" => EditorOperation::Backspace, - "backspace-word" => EditorOperation::BackspaceWord, - "delete" => EditorOperation::Delete, - "delete-word" => EditorOperation::DeleteWord, - "previous" => EditorOperation::Previous, - "next" => EditorOperation::Next, - "back" => EditorOperation::Back, - "forward" => EditorOperation::Forward, - "back-word" => EditorOperation::BackWord, - "forward-word" => EditorOperation::ForwardWord, - "head" => EditorOperation::Head, - "last" => EditorOperation::Last, - "undo" => EditorOperation::Undo, - "buffer-head" => EditorOperation::BufferHead, - "buffer-last" => EditorOperation::BufferLast, - "mark" => EditorOperation::Mark, - "unmark" => EditorOperation::UnMark, - _ => EditorOperation::Noop, - } - } - - fn execute_world_action( - &mut self, - command_name: &str, - argument: ActionArgument, - context: &StateContext, - ) { - match command_name { - "reset-zoom" => self.world.look_current(CameraAdjustment::FitBoth), - "look-current-and-centering" => self - .world - .look_current(CameraAdjustment::FitBothAndCentering), - "look-current" => self.world.look_current(CameraAdjustment::NoCare), - "look-next" => self.world.look_next(CameraAdjustment::NoCare), - "look-prev" => self.world.look_prev(CameraAdjustment::NoCare), - "swap-next" => self.world.swap_next(), - "swap-prev" => self.world.swap_prev(), - "fit-width" => self.world.look_current(CameraAdjustment::FitWidth), - "fit-height" => self.world.look_current(CameraAdjustment::FitHeight), - "fit-by-direction" => { - if context.global_direction == Direction::Horizontal { - self.world.look_current(CameraAdjustment::FitWidth) - } else { - self.world.look_current(CameraAdjustment::FitHeight) - } - } - "forward" => self.world.camera_operation(CameraOperation::Forward), - "back" => self.world.camera_operation(CameraOperation::Backward), - "change-direction" => self - .world - .model_operation(&ModelOperation::ChangeDirection(None)), - "increase-row-interval" => self - .world - .model_operation(&ModelOperation::IncreaseRowInterval), - "decrease-row-interval" => self - .world - .model_operation(&ModelOperation::DecreaseRowInterval), - "increase-col-interval" => self - .world - .model_operation(&ModelOperation::IncreaseColInterval), - "decrease-col-interval" => self - .world - .model_operation(&ModelOperation::DecreaseColInterval), - "increase-col-scale" => self - .world - .model_operation(&ModelOperation::IncreaseColScale), - "decrease-col-scale" => self - .world - .model_operation(&ModelOperation::DecreaseColScale), - "increase-row-scale" => self - .world - .model_operation(&ModelOperation::IncreaseRowScale), - "decrease-row-scale" => self - .world - .model_operation(&ModelOperation::DecreaseRowScale), - "toggle-psychedelic" => self - .world - .model_operation(&ModelOperation::TogglePsychedelic), - "move-to-click" => { - match argument { - ActionArgument::Point((x, y)) => { - let (x_ratio, y_ratio) = ( - (x / context.window_size.width as f32 * 2.0) - 1.0, - 1.0 - (y / context.window_size.height as f32 * 2.0), - ); - self.world.move_to_position(x_ratio, y_ratio); - } - _ => { /* noop */ } - } - } - "move-to-click-with-mark" => { - match argument { - ActionArgument::Point((x, y)) => { - let (x_ratio, y_ratio) = ( - (x / context.window_size.width as f32 * 2.0) - 1.0, - 1.0 - (y / context.window_size.height as f32 * 2.0), - ); - self.world.move_to_position(x_ratio, y_ratio); - self.world.editor_operation(&EditorOperation::Mark); - } - _ => { /* noop */ } - } - } - _ => {} - }; - } } impl SimpleStateCallback for SingleCharCallback { @@ -320,24 +195,20 @@ impl SimpleStateCallback for SingleCharCallback { } fn action(&mut self, context: &StateContext, action: Action) -> InputResult { + let result = self + .action_processor_store + .process(&action, context, &mut self.world); + if result != InputResult::Noop { + return result; + } + match action { - Action::Command(category, name, argument) => match &*category.to_string() { - "system" => match self.execute_system_action(&name, argument, context) { - SystemActionResult::ChangeColorTheme(theme) => { - InputResult::ChangeColorTheme(theme) - } - SystemActionResult::ChangeGlobalDirection(direction) => { - InputResult::ChangeGlobalDirection(direction) - } - SystemActionResult::Noop => InputResult::InputConsumed, - }, - "edit" => { - let op = Self::execute_editor_action(&name); - self.world.editor_operation(&op); - InputResult::InputConsumed - } + Action::Command(category, name, _) => match &*category.to_string() { "world" => { - self.execute_world_action(&name, argument, context); + if name.as_str() == "look-current-and-centering" { + self.world + .look_current(CameraAdjustment::FitBothAndCentering); + } InputResult::InputConsumed } _ => InputResult::Noop, From 6c87a72f713ac9fbaf91f916ea04172ca081d914 Mon Sep 17 00:00:00 2001 From: mitoma Date: Thu, 24 Oct 2024 00:52:46 +0900 Subject: [PATCH 11/11] =?UTF-8?q?=E4=B8=8D=E8=A6=81=E3=82=B3=E3=83=A1?= =?UTF-8?q?=E3=83=B3=E3=83=88=E3=81=AE=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- font_rasterizer/src/support/action/mod.rs | 26 ----------------------- 1 file changed, 26 deletions(-) diff --git a/font_rasterizer/src/support/action/mod.rs b/font_rasterizer/src/support/action/mod.rs index b134d56d..b5133e81 100644 --- a/font_rasterizer/src/support/action/mod.rs +++ b/font_rasterizer/src/support/action/mod.rs @@ -153,29 +153,3 @@ impl ActionProcessor (self.f)(arg, context, world) } } - -// ----- impl system ----- - -// ----- impl edit ----- -/* -pub struct EditForward; -impl ActionProcessor for EditForward { - fn namespace(&self) -> CommandNamespace { - "edit".into() - } - - fn name(&self) -> CommandName { - "forward".into() - } - - fn process( - &self, - _arg: &ActionArgument, - _context: &StateContext, - world: &mut dyn World, - ) -> Option { - world.editor_operation(&EditorOperation::Forward); - Some(InputResult::InputConsumed) - } -} - */