Skip to content

Commit

Permalink
Merge pull request #56 from mitoma/refactor-for-action
Browse files Browse the repository at this point in the history
Refactor for action
  • Loading branch information
mitoma authored Oct 23, 2024
2 parents 656fa93 + 6c87a72 commit 99a3773
Show file tree
Hide file tree
Showing 17 changed files with 851 additions and 464 deletions.
7 changes: 4 additions & 3 deletions font_rasterizer/examples/save_apng.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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)),
Expand All @@ -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));
Expand All @@ -153,4 +152,6 @@ impl SimpleStateCallback for SingleCharCallback {
fn render(&mut self) -> (&Camera, Vec<&GlyphInstances>) {
(&self.camera, self.glyphs.iter().collect())
}

fn shutdown(&mut self) {}
}
15 changes: 6 additions & 9 deletions font_rasterizer/examples/setup_glyphs.rs
Original file line number Diff line number Diff line change
@@ -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},
Expand Down Expand Up @@ -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',
Expand All @@ -69,21 +66,19 @@ impl SimpleStateCallback for SingleCharCallback {
'㐀'..='䶿',
]
.iter()
.map(|char_range| char_range.clone().into_iter().collect::<HashSet<char>>())
.map(|char_range| char_range.clone().into_iter().collect::<String>())
.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);
});
let end = Instant::now();
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
Expand All @@ -98,4 +93,6 @@ impl SimpleStateCallback for SingleCharCallback {
fn render(&mut self) -> (&Camera, Vec<&GlyphInstances>) {
(&self.camera, Vec::new())
}

fn shutdown(&mut self) {}
}
15 changes: 5 additions & 10 deletions font_rasterizer/examples/support_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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)),
Expand All @@ -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));
Expand Down Expand Up @@ -178,4 +171,6 @@ impl SimpleStateCallback for SingleCharCallback {
fn render(&mut self) -> (&Camera, Vec<&GlyphInstances>) {
(&self.camera, self.glyphs.iter().collect())
}

fn shutdown(&mut self) {}
}
1 change: 1 addition & 0 deletions font_rasterizer/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ pub struct StateContext {
pub char_width_calcurator: Arc<CharWidthCalculator>,
pub color_theme: ColorTheme,
pub window_size: WindowSize,
pub ui_string_sender: Sender<String>,
pub action_queue_sender: Sender<Action>,
pub post_action_queue_sender: Sender<Action>,
pub global_direction: Direction,
Expand Down
6 changes: 3 additions & 3 deletions font_rasterizer/src/layout_engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};

Expand All @@ -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;
Expand Down Expand Up @@ -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 {
Expand Down
51 changes: 51 additions & 0 deletions font_rasterizer/src/support/action/edit.rs
Original file line number Diff line number Diff line change
@@ -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);
155 changes: 155 additions & 0 deletions font_rasterizer/src/support/action/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
mod edit;
mod system;
mod world;
pub use edit::*;
pub use system::*;
pub use world::*;

use stroke_parser::{Action, ActionArgument, CommandName, CommandNamespace};

use crate::{context::StateContext, layout_engine::World};

use super::InputResult;

#[derive(Default)]
pub struct ActionProcessorStore {
processors: Vec<Box<dyn ActionProcessor>>,
}

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_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_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,
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<dyn ActionProcessor>) {
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<F>
where
F: Fn(&ActionArgument, &StateContext, &mut dyn World) -> InputResult,
{
namespace: CommandNamespace,
name: CommandName,
f: F,
}

impl ActionProcessor
for LambdaActionProcessor<fn(&ActionArgument, &StateContext, &mut dyn World) -> 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)
}
}
Loading

0 comments on commit 99a3773

Please sign in to comment.