diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml deleted file mode 100644 index a2b06a67..00000000 --- a/.github/FUNDING.yml +++ /dev/null @@ -1 +0,0 @@ -patreon: lpghatguy \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index a8e82bfb..df9875bf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,8 @@ * Better settings controls ([#725]) * Rework patch visualizer with many fixes and improvements ([#726]) * Added support for syncing in `.toml` files ([#633]) +* Add `plugin` flag to the `build` command that outputs to the local plugins folder ([#735]) +* Added better support for `Font` properties ([#731]) [#631]: https://github.com/rojo-rbx/rojo/pull/631 [#668]: https://github.com/rojo-rbx/rojo/pull/668 @@ -36,6 +38,8 @@ [#725]: https://github.com/rojo-rbx/rojo/pull/725 [#726]: https://github.com/rojo-rbx/rojo/pull/726 [#633]: https://github.com/rojo-rbx/rojo/pull/633 +[#735]: https://github.com/rojo-rbx/rojo/pull/735 +[#731]: https://github.com/rojo-rbx/rojo/pull/731 ## [7.3.0] - April 22, 2023 * Added `$attributes` to project format. ([#574]) diff --git a/README.md b/README.md index f87b5057..fb318f3f 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,6 @@ Actions status Latest server version Rojo Documentation - Patreon
diff --git a/benches/build.rs b/benches/build.rs index 456a5339..87d33e44 100644 --- a/benches/build.rs +++ b/benches/build.rs @@ -31,11 +31,12 @@ fn bench_build_place(c: &mut Criterion, name: &str, path: &str) { fn place_setup>(input_path: P) -> (TempDir, BuildCommand) { let dir = tempdir().unwrap(); let input = input_path.as_ref().to_path_buf(); - let output = dir.path().join("output.rbxlx"); + let output = Some(dir.path().join("output.rbxlx")); let options = BuildCommand { project: input, watch: false, + plugin: None, output, }; diff --git a/src/cli/build.rs b/src/cli/build.rs index d6c3f349..8f705d37 100644 --- a/src/cli/build.rs +++ b/src/cli/build.rs @@ -4,10 +4,11 @@ use std::{ path::{Path, PathBuf}, }; -use anyhow::Context; -use clap::Parser; +use anyhow::{bail, Context}; +use clap::{CommandFactory, Parser}; use fs_err::File; use memofs::Vfs; +use roblox_install::RobloxStudio; use tokio::runtime::Runtime; use crate::serve_session::ServeSession; @@ -16,6 +17,8 @@ use super::resolve_path; const UNKNOWN_OUTPUT_KIND_ERR: &str = "Could not detect what kind of file to build. \ Expected output file to end in .rbxl, .rbxlx, .rbxm, or .rbxmx."; +const UNKNOWN_PLUGIN_KIND_ERR: &str = "Could not detect what kind of file to build. \ + Expected plugin file to end in .rbxm or .rbxmx."; /// Generates a model or place file from the Rojo project. #[derive(Debug, Parser)] @@ -28,7 +31,13 @@ pub struct BuildCommand { /// /// Should end in .rbxm, .rbxl, .rbxmx, or .rbxlx. #[clap(long, short)] - pub output: PathBuf, + pub output: Option, + + /// Alternative to the output flag that outputs the result in the local plugins folder. + /// + /// Should end in .rbxm or .rbxl. + #[clap(long, short)] + pub plugin: Option, /// Whether to automatically rebuild when any input files change. #[clap(long)] @@ -37,18 +46,52 @@ pub struct BuildCommand { impl BuildCommand { pub fn run(self) -> anyhow::Result<()> { - let project_path = resolve_path(&self.project); + let (output_path, output_kind) = match (self.output, self.plugin) { + (Some(_), Some(_)) => { + BuildCommand::command() + .error( + clap::ErrorKind::ArgumentConflict, + "the argument '--output ' cannot be used with '--plugin '", + ) + .exit(); + } + (None, None) => { + BuildCommand::command() + .error( + clap::ErrorKind::MissingRequiredArgument, + "one of the following arguments must be provided: \n --output \n --plugin ", + ) + .exit(); + } + (Some(output), None) => { + let output_kind = + OutputKind::from_output_path(&output).context(UNKNOWN_OUTPUT_KIND_ERR)?; - let output_kind = detect_output_kind(&self.output).context(UNKNOWN_OUTPUT_KIND_ERR)?; + (output, output_kind) + } + (None, Some(plugin)) => { + if plugin.is_absolute() { + bail!("plugin flag path cannot be absolute.") + } + + let output_kind = + OutputKind::from_plugin_path(&plugin).context(UNKNOWN_PLUGIN_KIND_ERR)?; + let studio = RobloxStudio::locate()?; + + (studio.plugins_path().join(&plugin), output_kind) + } + }; + + let project_path = resolve_path(&self.project); log::trace!("Constructing in-memory filesystem"); let vfs = Vfs::new_default(); vfs.set_watch_enabled(self.watch); - let session = ServeSession::new(vfs, &project_path)?; + let session = ServeSession::new(vfs, project_path)?; let mut cursor = session.message_queue().cursor(); - write_model(&session, &self.output, output_kind)?; + write_model(&session, &output_path, output_kind)?; if self.watch { let rt = Runtime::new().unwrap(); @@ -58,7 +101,7 @@ impl BuildCommand { let (new_cursor, _patch_set) = rt.block_on(receiver).unwrap(); cursor = new_cursor; - write_model(&session, &self.output, output_kind)?; + write_model(&session, &output_path, output_kind)?; } } @@ -86,15 +129,27 @@ enum OutputKind { Rbxl, } -fn detect_output_kind(output: &Path) -> Option { - let extension = output.extension()?.to_str()?; +impl OutputKind { + fn from_output_path(output: &Path) -> Option { + let extension = output.extension()?.to_str()?; - match extension { - "rbxlx" => Some(OutputKind::Rbxlx), - "rbxmx" => Some(OutputKind::Rbxmx), - "rbxl" => Some(OutputKind::Rbxl), - "rbxm" => Some(OutputKind::Rbxm), - _ => None, + match extension { + "rbxlx" => Some(OutputKind::Rbxlx), + "rbxmx" => Some(OutputKind::Rbxmx), + "rbxl" => Some(OutputKind::Rbxl), + "rbxm" => Some(OutputKind::Rbxm), + _ => None, + } + } + + fn from_plugin_path(output: &Path) -> Option { + let extension = output.extension()?.to_str()?; + + match extension { + "rbxmx" => Some(OutputKind::Rbxmx), + "rbxm" => Some(OutputKind::Rbxm), + _ => None, + } } } diff --git a/src/resolution.rs b/src/resolution.rs index 56889145..c667080c 100644 --- a/src/resolution.rs +++ b/src/resolution.rs @@ -2,7 +2,7 @@ use std::borrow::Borrow; use anyhow::{bail, format_err}; use rbx_dom_weak::types::{ - Attributes, CFrame, Color3, Content, Enum, Matrix3, Tags, Variant, VariantType, Vector2, + Attributes, CFrame, Color3, Content, Enum, Font, Matrix3, Tags, Variant, VariantType, Vector2, Vector3, }; use rbx_reflection::{DataType, PropertyDescriptor}; @@ -49,6 +49,7 @@ pub enum AmbiguousValue { Array4([f64; 4]), Array12([f64; 12]), Attributes(Attributes), + Font(Font), } impl AmbiguousValue { @@ -139,6 +140,8 @@ impl AmbiguousValue { (VariantType::Attributes, AmbiguousValue::Attributes(value)) => Ok(value.into()), + (VariantType::Font, AmbiguousValue::Font(value)) => Ok(value.into()), + (_, unresolved) => Err(format_err!( "Wrong type of value for property {}.{}. Expected {:?}, got {}", class_name, @@ -176,6 +179,7 @@ impl AmbiguousValue { AmbiguousValue::Array4(_) => "an array of four numbers", AmbiguousValue::Array12(_) => "an array of twelve numbers", AmbiguousValue::Attributes(_) => "an object containing attributes", + AmbiguousValue::Font(_) => "an object describing a Font", } } } @@ -328,4 +332,23 @@ mod test { Variant::Enum(Enum::from_u32(1)), ); } + + #[test] + fn font() { + use rbx_dom_weak::types::{FontStyle, FontWeight}; + + assert_eq!( + resolve( + "TextLabel", + "FontFace", + r#"{"family": "rbxasset://fonts/families/RobotoMono.json", "weight": "Thin", "style": "Normal"}"# + ), + Variant::Font(Font { + family: "rbxasset://fonts/families/RobotoMono.json".into(), + weight: FontWeight::Thin, + style: FontStyle::Normal, + cached_face_id: None, + }) + ) + } }