KCL: [number; 3] to RGB hex string color function (#7184)
Closes https://github.com/KittyCAD/modeling-app/issues/6805. Enables users to programatically construct colors, which will be helpful for - Applying color to visualize program execution and help debugging - Doing weird cool shit
This commit is contained in:
93
docs/kcl-std/functions/std-appearance-hexString.md
Normal file
93
docs/kcl-std/functions/std-appearance-hexString.md
Normal file
File diff suppressed because one or more lines are too long
64
docs/kcl-std/functions/std-appearance-rgb.md
Normal file
64
docs/kcl-std/functions/std-appearance-rgb.md
Normal file
File diff suppressed because one or more lines are too long
@ -16,6 +16,8 @@ layout: manual
|
|||||||
* [`helix`](/docs/kcl-std/functions/std-helix)
|
* [`helix`](/docs/kcl-std/functions/std-helix)
|
||||||
* [`offsetPlane`](/docs/kcl-std/functions/std-offsetPlane)
|
* [`offsetPlane`](/docs/kcl-std/functions/std-offsetPlane)
|
||||||
* [`patternLinear2d`](/docs/kcl-std/patternLinear2d)
|
* [`patternLinear2d`](/docs/kcl-std/patternLinear2d)
|
||||||
|
* [**std::appearance**](/docs/kcl-std/modules/std-appearance)
|
||||||
|
* [`appearance::hexString`](/docs/kcl-std/functions/std-appearance-hexString)
|
||||||
* [**std::array**](/docs/kcl-std/modules/std-array)
|
* [**std::array**](/docs/kcl-std/modules/std-array)
|
||||||
* [`map`](/docs/kcl-std/functions/std-array-map)
|
* [`map`](/docs/kcl-std/functions/std-array-map)
|
||||||
* [`pop`](/docs/kcl-std/functions/std-array-pop)
|
* [`pop`](/docs/kcl-std/functions/std-array-pop)
|
||||||
|
16
docs/kcl-std/modules/std-appearance.md
Normal file
16
docs/kcl-std/modules/std-appearance.md
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
---
|
||||||
|
title: "appearance"
|
||||||
|
subtitle: "Module in std"
|
||||||
|
excerpt: ""
|
||||||
|
layout: manual
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Functions and constants
|
||||||
|
|
||||||
|
* [`appearance::hexString`](/docs/kcl-std/functions/std-appearance-hexString)
|
||||||
|
|
@ -15,6 +15,7 @@ You might also want the [KCL language reference](/docs/kcl-lang) or the [KCL gui
|
|||||||
|
|
||||||
## Modules
|
## Modules
|
||||||
|
|
||||||
|
* [`appearance::appearance`](/docs/kcl-std/modules/std-appearance)
|
||||||
* [`array`](/docs/kcl-std/modules/std-array)
|
* [`array`](/docs/kcl-std/modules/std-array)
|
||||||
* [`math`](/docs/kcl-std/modules/std-math)
|
* [`math`](/docs/kcl-std/modules/std-math)
|
||||||
* [`sketch`](/docs/kcl-std/modules/std-sketch)
|
* [`sketch`](/docs/kcl-std/modules/std-sketch)
|
||||||
|
@ -42,7 +42,10 @@ pub fn do_for_all_example_test(item: proc_macro2::TokenStream) -> proc_macro2::T
|
|||||||
item.into_token_stream()
|
item.into_token_stream()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const TEST_NAMES: [&str; 93] = [
|
pub const TEST_NAMES: &[&str] = &[
|
||||||
|
"std-appearance-hexString-0",
|
||||||
|
"std-appearance-hexString-1",
|
||||||
|
"std-appearance-hexString-2",
|
||||||
"std-array-map-0",
|
"std-array-map-0",
|
||||||
"std-array-map-1",
|
"std-array-map-1",
|
||||||
"std-array-pop-0",
|
"std-array-pop-0",
|
||||||
|
@ -97,6 +97,7 @@ pub(crate) fn read_std(mod_name: &str) -> Option<&'static str> {
|
|||||||
"units" => Some(include_str!("../std/units.kcl")),
|
"units" => Some(include_str!("../std/units.kcl")),
|
||||||
"array" => Some(include_str!("../std/array.kcl")),
|
"array" => Some(include_str!("../std/array.kcl")),
|
||||||
"sweep" => Some(include_str!("../std/sweep.kcl")),
|
"sweep" => Some(include_str!("../std/sweep.kcl")),
|
||||||
|
"appearance" => Some(include_str!("../std/appearance.kcl")),
|
||||||
"transform" => Some(include_str!("../std/transform.kcl")),
|
"transform" => Some(include_str!("../std/transform.kcl")),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,10 @@ use rgba_simple::Hex;
|
|||||||
use super::args::TyF64;
|
use super::args::TyF64;
|
||||||
use crate::{
|
use crate::{
|
||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
execution::{types::RuntimeType, ExecState, KclValue, SolidOrImportedGeometry},
|
execution::{
|
||||||
|
types::{ArrayLen, RuntimeType},
|
||||||
|
ExecState, KclValue, SolidOrImportedGeometry,
|
||||||
|
},
|
||||||
std::Args,
|
std::Args,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -18,6 +21,34 @@ lazy_static::lazy_static! {
|
|||||||
static ref HEX_REGEX: Regex = Regex::new(r"^#[0-9a-fA-F]{6}$").unwrap();
|
static ref HEX_REGEX: Regex = Regex::new(r"^#[0-9a-fA-F]{6}$").unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Construct a color from its red, blue and green components.
|
||||||
|
pub async fn hex_string(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
|
let rgb: [TyF64; 3] = args.get_unlabeled_kw_arg_typed(
|
||||||
|
"rgb",
|
||||||
|
&RuntimeType::Array(Box::new(RuntimeType::count()), ArrayLen::Known(3)),
|
||||||
|
exec_state,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
// Make sure the color if set is valid.
|
||||||
|
if let Some(component) = rgb.iter().find(|component| component.n < 0.0 || component.n > 255.0) {
|
||||||
|
return Err(KclError::Semantic(KclErrorDetails::new(
|
||||||
|
format!("Colors are given between 0 and 255, so {} is invalid", component.n),
|
||||||
|
vec![args.source_range],
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
inner_hex_string(rgb, exec_state, args).await
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn inner_hex_string(rgb: [TyF64; 3], _: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
|
let [r, g, b] = rgb.map(|n| n.n.floor() as u32);
|
||||||
|
let s = format!("#{r:02x}{g:02x}{b:02x}");
|
||||||
|
Ok(KclValue::String {
|
||||||
|
value: s,
|
||||||
|
meta: args.into(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// Set the appearance of a solid. This only works on solids, not sketches or individual paths.
|
/// Set the appearance of a solid. This only works on solids, not sketches or individual paths.
|
||||||
pub async fn appearance(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
pub async fn appearance(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let solids = args.get_unlabeled_kw_arg_typed(
|
let solids = args.get_unlabeled_kw_arg_typed(
|
||||||
|
@ -286,7 +286,13 @@ pub(crate) fn std_fn(path: &str, fn_name: &str) -> (crate::std::StdFn, StdFnProp
|
|||||||
|e, a| Box::pin(crate::std::patterns::pattern_transform_2d(e, a)),
|
|e, a| Box::pin(crate::std::patterns::pattern_transform_2d(e, a)),
|
||||||
StdFnProps::default("std::sketch::patternTransform2d"),
|
StdFnProps::default("std::sketch::patternTransform2d"),
|
||||||
),
|
),
|
||||||
_ => unreachable!(),
|
("appearance", "hexString") => (
|
||||||
|
|e, a| Box::pin(crate::std::appearance::hex_string(e, a)),
|
||||||
|
StdFnProps::default("std::appearance::hexString"),
|
||||||
|
),
|
||||||
|
(module, fn_name) => {
|
||||||
|
panic!("No implementation found for {module}::{fn_name}, please add it to this big match statement")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
64
rust/kcl-lib/std/appearance.kcl
Normal file
64
rust/kcl-lib/std/appearance.kcl
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
/// Build a color from its red, green and blue components.
|
||||||
|
/// These must be between 0 and 255.
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// startSketchOn(-XZ)
|
||||||
|
/// |> circle(center = [0, 0], radius = 10)
|
||||||
|
/// |> extrude(length = 4)
|
||||||
|
/// |> appearance(color = appearance::hexString([50, 160, 160]))
|
||||||
|
/// ```
|
||||||
|
/// ```
|
||||||
|
/// sideLen = 30
|
||||||
|
/// n = 10
|
||||||
|
///
|
||||||
|
/// // The cubes become more green and less blue with each instance.
|
||||||
|
/// fn cube(i, center) {
|
||||||
|
/// g = 255 / n * i
|
||||||
|
/// b = 255 / n * (n - i)
|
||||||
|
/// return startSketchOn(XY)
|
||||||
|
/// |> polygon(radius = sideLen / 2, numSides = 4, center = [center, 0])
|
||||||
|
/// |> extrude(length = sideLen)
|
||||||
|
/// |> appearance(color = appearance::hexString([0, g, b]), metalness = 80, roughness = 20)
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// // Create n cubes, shifting each one over in a line.
|
||||||
|
/// map(
|
||||||
|
/// [0..n],
|
||||||
|
/// f = fn(@i) {
|
||||||
|
/// return cube(i, center = sideLen * i * 1.5)
|
||||||
|
/// },
|
||||||
|
/// )
|
||||||
|
/// ```
|
||||||
|
/// ```
|
||||||
|
/// sideLen = 30
|
||||||
|
/// n = 6
|
||||||
|
///
|
||||||
|
/// fn cube(offset, i, red) {
|
||||||
|
/// x = floor(i / n)
|
||||||
|
/// y = rem(i, divisor = n)
|
||||||
|
/// g = 255 / n * x
|
||||||
|
/// b = 255 / n * y
|
||||||
|
/// return startSketchOn(offsetPlane(XZ, offset))
|
||||||
|
/// |> circle(diameter = sideLen, center = [sideLen * x * 1.5, sideLen * y * 1.5])
|
||||||
|
/// |> extrude(length = sideLen)
|
||||||
|
/// |> appearance(color = appearance::hexString([red, g, b]), metalness = 80, roughness = 40)
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// fn grid(offset, red) {
|
||||||
|
/// return map(
|
||||||
|
/// [0 ..< n * n],
|
||||||
|
/// f = fn(@i) {
|
||||||
|
/// return cube(offset, i, red)
|
||||||
|
/// },
|
||||||
|
/// )
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// grid(offset = 0, red = 0)
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
@(impl = std_rust)
|
||||||
|
export fn hexString(
|
||||||
|
/// The red, blue and green components of the color.
|
||||||
|
/// Must be between 0 and 255.
|
||||||
|
@rgb: [number(_); 3],
|
||||||
|
): string {}
|
@ -22,6 +22,7 @@ export import * from "std::solid"
|
|||||||
export import * from "std::transform"
|
export import * from "std::transform"
|
||||||
export import "std::turns"
|
export import "std::turns"
|
||||||
export import "std::sweep"
|
export import "std::sweep"
|
||||||
|
export import "std::appearance"
|
||||||
|
|
||||||
/// An abstract 3d plane aligned with the X and Y axes. Its normal is the positive Z axis.
|
/// An abstract 3d plane aligned with the X and Y axes. Its normal is the positive Z axis.
|
||||||
export XY = {
|
export XY = {
|
||||||
|
Binary file not shown.
After Width: | Height: | Size: 76 KiB |
Binary file not shown.
After Width: | Height: | Size: 55 KiB |
Binary file not shown.
After Width: | Height: | Size: 190 KiB |
Binary file not shown.
After Width: | Height: | Size: 76 KiB |
Binary file not shown.
After Width: | Height: | Size: 55 KiB |
Binary file not shown.
After Width: | Height: | Size: 190 KiB |
Reference in New Issue
Block a user