Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UI Selectable Sketches #23

Merged
merged 6 commits into from
Nov 3, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions cli/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
use clap::{crate_authors, crate_description, crate_version, Parser};
use nightgraphics::render::SvgRenderer;
use nightsketch::SketchList;
use nightsketch::SketchSubcommand;
use serde::{Deserialize, Serialize};

#[derive(clap::Parser, Serialize, Deserialize)]
#[clap(about= crate_description!(), version = crate_version!(), author = crate_authors!())]
struct Opts {
#[clap(subcommand)]
sketch: SketchList,
sketch: SketchSubcommand,
}

fn main() {
Expand Down
53 changes: 2 additions & 51 deletions sketch/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,57 +1,8 @@
pub(crate) use nightgraphics::prelude::*;
pub(crate) use nightsketch_derive::sketch;

mod sketch;
pub use sketch::*;
mod metadata;
pub use metadata::*;

mod blossom;
use blossom::*;

#[cfg_attr(feature = "cli", derive(clap::Parser))]
#[cfg_attr(
feature = "serde_support",
derive(serde::Deserialize, serde::Serialize)
)]
pub enum SketchList {
Blossom(Blossom),
}

impl Default for SketchList {
fn default() -> Self {
Self::Blossom(Blossom::default())
}
}

impl SketchList {
fn inner_sketch(&self) -> &dyn Sketch {
match self {
Self::Blossom(s) => s as &dyn Sketch,
}
}
fn inner_sketch_mut(&mut self) -> &mut dyn Sketch {
match self {
Self::Blossom(s) => s as &mut dyn Sketch,
}
}
pub fn exec(&self) -> SketchResult<Canvas> {
self.inner_sketch().exec()
}
pub fn param_metadata(&self) -> Vec<ParamMetadata> {
self.inner_sketch().param_metadata()
}
pub fn mut_float_by_id(&mut self, id: u64) -> SketchResult<&mut f64> {
self.inner_sketch_mut().mut_float_by_id(id)
}
pub fn mut_int_by_id(&mut self, id: u64) -> SketchResult<&mut i64> {
self.inner_sketch_mut().mut_int_by_id(id)
}
pub fn mut_uint_by_id(&mut self, id: u64) -> SketchResult<&mut u64> {
self.inner_sketch_mut().mut_uint_by_id(id)
}

pub fn mut_bool_by_id(&mut self, id: u64) -> SketchResult<&mut bool> {
self.inner_sketch_mut().mut_bool_by_id(id)
}
}
mod sketches;
pub use sketches::*;
File renamed without changes.
6 changes: 6 additions & 0 deletions sketch/src/sketches/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
use super::*;
pub(self) use nightsketch_derive::{sketch, sketchlist};

sketchlist! {
blossom::Blossom,
}
4 changes: 4 additions & 0 deletions sketch_derive/src/codegen/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
mod sketch;
mod sketchlist;
pub use sketch::*;
pub use sketchlist::*;
File renamed without changes.
110 changes: 110 additions & 0 deletions sketch_derive/src/codegen/sketchlist.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
use crate::parse::SketchListEntry;
use quote::quote;

pub fn sketch_subcommand_enum_tokens(sketches: &[SketchListEntry]) -> proc_macro2::TokenStream {
// For each sketch, create an enum variant with its name and the struct
// associated with it. For example, if module `doop` has sketch `Doop`,
// a variant `Doop(Doop)` is created.
let sketch_enum_entries: Vec<proc_macro2::TokenStream> = sketches
.iter()
.map(|sketch| {
let s = &sketch.sketch;
let m = &sketch.module;
quote!(#s(#m::#s))
})
.collect();

let exec_match_arms: Vec<proc_macro2::TokenStream> = sketches
.iter()
.map(|sketch| {
let s = &sketch.sketch;
quote!(Self::#s(s) => s.exec())
})
.collect();

let serde_derive_attr = if cfg!(feature = "serde_support") {
Some(quote!(#[derive(serde::Deserialize, serde::Serialize)]))
} else {
None
};

let sketch_subcommand_tokens = if cfg!(feature = "cli") {
Some(quote! {
#serde_derive_attr
#[derive(clap::Parser)]
pub enum SketchSubcommand {
#(#sketch_enum_entries),*
}

impl SketchSubcommand {
pub fn exec(&self) -> SketchResult<nightgraphics::prelude::Canvas> {
match self {
#(#exec_match_arms),*,
_ => Err(SketchError::Todo("TODO".to_string())),
}
}
}
})
} else {
None
};

quote!( #sketch_subcommand_tokens )
}

pub fn sketch_mod_stmts_tokens(sketches: &[SketchListEntry]) -> proc_macro2::TokenStream {
let mod_stmts: Vec<proc_macro2::TokenStream> = sketches
.iter()
.map(|sketch| {
let m = &sketch.module;
quote!(mod #m)
})
.collect();

quote! {
#(#mod_stmts);*;
}
}

pub fn sketchlist_struct_tokens(sketches: &[SketchListEntry]) -> proc_macro2::TokenStream {
let sketch_by_name_match_arms: Vec<proc_macro2::TokenStream> = sketches
.iter()
.map(|sketch| {
let m = &sketch.module;
let s = &sketch.sketch;
let s_name = s.to_string();
quote! {
#s_name => Ok(Box::new(#m::#s::default()))
}
})
.collect();

let sketch_names: Vec<proc_macro2::TokenStream> = sketches
.iter()
.map(|sketch| {
let s_name = sketch.sketch.to_string();
quote! { #s_name.to_string() }
})
.collect();

quote! {
pub struct SketchList {}

impl SketchList {
pub fn default_sketch() -> Box<dyn Sketch> {
Box::new(blossom::Blossom::default())
}
pub fn sketch_by_name(name: &str) -> SketchResult<Box<dyn Sketch>> {
match name {
#(#sketch_by_name_match_arms),*,
_ => Err(SketchError::Todo("sdfs".to_string())),
}
}
pub fn sketch_names() -> Vec<String> {
vec![
#(#sketch_names),*
]
}
}
}
}
19 changes: 18 additions & 1 deletion sketch_derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,27 @@ pub fn sketch(_attr: TokenStream, input: TokenStream) -> TokenStream {
let impl_sketchaccess = impl_sketchaccess_tokens(name, params);
let impl_default = impl_default_tokens(name, params);

quote! (
quote!(
#struct_tokens
#impl_default
#impl_sketchaccess
)
.into()
}

#[proc_macro]
pub fn sketchlist(input: TokenStream) -> TokenStream {
let sketchlist: SketchList = parse_macro_input!(input);
let sketches = &sketchlist.sketches;

let sketch_mod_stmts = sketch_mod_stmts_tokens(sketches);
let sketch_subcommand_enum = sketch_subcommand_enum_tokens(sketches);
let sketchlist_struct = sketchlist_struct_tokens(sketches);

quote!(
#sketch_mod_stmts
#sketch_subcommand_enum
#sketchlist_struct
)
.into()
}
3 changes: 3 additions & 0 deletions sketch_derive/src/parse/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ pub use param::SketchParam;
mod param_attr;
pub use param_attr::{ParamAttr, ParamAttrs};

mod sketchlist;
pub use sketchlist::{SketchList, SketchListEntry};

mod utils;

/* /// Doc string
Expand Down
37 changes: 37 additions & 0 deletions sketch_derive/src/parse/sketchlist.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
use syn::parse::{Parse, ParseStream};
use syn::punctuated::Punctuated;
use syn::{Ident, Path, Result, Token};

#[derive(Debug)]
pub struct SketchListEntry {
pub module: Punctuated<syn::PathSegment, Token![::]>,
pub sketch: Ident,
}

impl Parse for SketchListEntry {
fn parse(input: ParseStream) -> Result<Self> {
let path: syn::Path = input.call(Path::parse_mod_style)?;
let mut seg_vec: Vec<syn::PathSegment> = path.segments.into_iter().collect();
let sketch = seg_vec.pop().unwrap().ident;
let mut module = Punctuated::new();
for seg in seg_vec {
module.push(seg);
}
Ok(SketchListEntry { module, sketch })
}
}

#[derive(Debug)]
pub struct SketchList {
pub sketches: Vec<SketchListEntry>,
}

impl Parse for SketchList {
fn parse(input: ParseStream) -> Result<Self> {
let sketches: Punctuated<SketchListEntry, Token![,]> =
input.parse_terminated(SketchListEntry::parse)?;
let sketches: Vec<SketchListEntry> = sketches.into_iter().collect();

Ok(SketchList { sketches })
}
}
2 changes: 1 addition & 1 deletion ui/src/app/drawing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ pub struct SketchData {

impl Default for Drawing {
fn default() -> Self {
let (sketch_size, shapes) = SketchList::default().exec().unwrap().render_egui();
let (sketch_size, shapes) = SketchList::default_sketch().exec().unwrap().render_egui();
let sketch_rect = egui::Rect::from_min_size(Pos2::ZERO, sketch_size);
Self {
shapes,
Expand Down
33 changes: 29 additions & 4 deletions ui/src/app/sketch_control.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,49 @@ use nightgraphics::render::EguiRenderer;
use nightsketch::*;

pub struct SketchControl {
sketch: SketchList,
sketch: Box<dyn Sketch>,
sketch_name: String,
params: Vec<ParamMetadata>,
sketch_names: Vec<String>,
pub needs_render: bool,
}

impl Default for SketchControl {
fn default() -> Self {
let sketch = SketchList::default();
let sketch = SketchList::default_sketch();
let sketch_name = "Blossom".to_string();
let params = sketch.param_metadata();
let sketch_names = SketchList::sketch_names();
SketchControl {
sketch: SketchList::default(),
params: sketch.param_metadata(),
sketch,
sketch_name,
params,
sketch_names,
needs_render: true,
}
}
}

impl SketchControl {
fn param_grid_contents(&mut self, ui: &mut egui::Ui) {
ui.label("Sketch");
let val = self.sketch_name.to_string();
egui::ComboBox::from_label("")
.selected_text(self.sketch_name.to_string())
.show_ui(ui, |ui| {
for n in &self.sketch_names {
ui.selectable_value(&mut self.sketch_name, n.to_string(), n);
}
});
if val != self.sketch_name {
self.sketch = SketchList::sketch_by_name(&self.sketch_name).unwrap();
self.needs_render = true;
self.params = self.sketch.param_metadata();
}
ui.end_row();
// Leave some visual space without a separator
ui.end_row();

for param in &self.params {
let sketch = &mut self.sketch;
let id = param.id;
Expand Down