Orbtkでのrender::RenderPipelineメモ


当方Rustはじめて2ヶ月なので間違いあれば優しく槍投げていただけると助かります。

render::RenderPipelineのdraw()をGUIに対応させるには

ボタンクリックなどでcanvasの内容を変更したりする際には以下が必要
・アクション管理担当のenum
・描画管理担当のstruct
・状態管理担当のstruct

アクション管理担当のenum

flutter風にGUIを記述している箇所のマウスクリックなどのイベント時に受け渡したいのを用意しておく

#[derive(Debug, Copy, Clone)]
enum Action {
  // Entityは渡したい値
  ValueChanged(Entity),
  PushButton,
}

描画管理担当のstruct

#[derive(Clone, PartialEq, Pipeline, Default)]
struct 描画管理担当構造体名 {
// 保持したい値をCellで包む
    変数名: Cell<型>
}
impl 描画管理担当構造体名 {
   fn set_変数名(&self, val: 型) {
       self.変数名.set(val);
   }
}
impl render::RenderPipeline for Graphic2DPipeline {
    fn draw(&self, render_target: &mut render::RenderTarget) {
        // self.test.get()で使える
    }
}

状態管理担当のstruct

#[derive(Default, AsAny)]
pub struct MainViewState {
  action: Option<Action>,
  変数名: 型,
}

もしくはimpl Default for MainViewStateでdefault()処理を用意する

impl MainViewState {
  // GUI処理記述部分からアクションを受け取る
  fn set_action(&mut self, action: impl Into<Option<Action>>) {
    self.action = action.into();
  }
}
impl State for MainViewState {
  fn update(&mut self, _: &mut Registry, ctx: &mut Context<'_>) {
    if let Some(action) = self.action {
      match action {
        Action::PushButton => {
          // アクションに対応した処理。状態管理担当クラスの変数を更新したりする。
        }
        Action::ValueChanged(entity) => {
          // アクションに対応した処理。状態管理担当クラスの変数を更新したりする。
        }
        _ => (),
      };
    }
    if let Some(canvas) = ctx
      .widget()
      .get_mut::<RenderPipeline>("render_pipeline")
      .0
      .as_any()
      .downcast_ref::<Graphic2DPipeline>()
    {
      // 状態管理担当structの変数を描画担当structに反映させる
      canvas.set_変数名(self.変数名);
    } else {
      println!("missing canvas");
    }

    // 画面更新毎に処理が行われるのでアクションを無効化する
    self.action = None;
  }
}

GUI記述箇所

impl Template for MainView {
  fn template(self, id: Entity, ctx: &mut BuildContext) -> Self {
    self
      .name("MainView")
      .render_pipeline(RenderPipeline(Box::new(Graphic2DPipeline::default())))
      // canvas
      .child(
        Canvas::create()
          .width(640.0)
          .height(800.0)
          .render_pipeline(id)
          .build(ctx),
      )
      // (その他のGUIなど)

アクション処理部分

.on_click(move |states, _| {
                states
                  .get_mut::<MainViewState>(id)
                  .set_action(Action::PushButton);
                true
              })

以上

ちなみに

render::RenderPipelineのdraw()処理は
https://developer.mozilla.org/ja/docs/Web/API/CanvasRenderingContext2D
を参考にすれば良さそう。pathを書いてからfill() or stroke()