Fix the Text node's Max Width/Height parameters with OptionalF64 losing the value when unticked (#3643)

* WIP

* Fix widget

* Fix migration

* Remove OptionalF64

* Custom attributes for optional f64 widget

* Code review

* Move comments to another PR

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
Adam Gerhant
2026-01-15 22:13:32 -08:00
committed by GitHub
parent 73682b482b
commit c60ddcf875
12 changed files with 254 additions and 188 deletions

View File

@@ -173,9 +173,7 @@ tagged_value! {
U64(u64),
Bool(bool),
String(String),
OptionalF64(Option<f64>),
ColorNotInTable(Color),
OptionalColorNotInTable(Option<Color>),
// ========================
// LISTS OF PRIMITIVE TYPES
// ========================
@@ -366,9 +364,9 @@ impl TaggedValue {
x if x == TypeId::of::<u32>() => FromStr::from_str(string).map(TaggedValue::U32).ok()?,
x if x == TypeId::of::<DVec2>() => to_dvec2(string).map(TaggedValue::DVec2)?,
x if x == TypeId::of::<bool>() => FromStr::from_str(string).map(TaggedValue::Bool).ok()?,
x if x == TypeId::of::<Table<Color>>() => to_color(string).map(|color| TaggedValue::Color(Table::new_from_element(color)))?,
x if x == TypeId::of::<Color>() => to_color(string).map(TaggedValue::ColorNotInTable)?,
x if x == TypeId::of::<Option<Color>>() => TaggedValue::ColorNotInTable(to_color(string)?),
x if x == TypeId::of::<Table<Color>>() => to_color(string).map(|color| TaggedValue::Color(Table::new_from_element(color)))?,
x if x == TypeId::of::<Fill>() => to_color(string).map(|color| TaggedValue::Fill(Fill::solid(color)))?,
x if x == TypeId::of::<ReferencePoint>() => to_reference_point(string).map(TaggedValue::ReferencePoint)?,
_ => return None,

View File

@@ -90,18 +90,6 @@ impl From<Table<Color>> for Graphic {
}
}
// Note: Table conversions handled by blanket impl in gcore
// Option<Color>
impl From<Option<Color>> for Graphic {
fn from(color: Option<Color>) -> Self {
if let Some(color) = color {
Graphic::Color(Table::new_from_element(color))
} else {
Graphic::default()
}
}
}
// Note: Table conversions handled by blanket impl in gcore
// Note: Table<Color> -> Option<Color> is in gcore (Color is defined there)
// GradientStops

View File

@@ -244,7 +244,6 @@ fn blending<T: SetBlendMode + MultiplyAlpha + MultiplyFill + SetClip>(
#[default(100.)]
fill: Percentage,
/// Whether the content inherits the alpha of the content beneath it.
#[default(false)]
clip: bool,
) -> T {
// TODO: Find a way to make this apply once to the table's parent (i.e. its row in its parent table or TableRow<T>) rather than applying to each row in its own table, which produces the undesired result

View File

@@ -3,41 +3,52 @@ use graph_craft::wasm_application_io::WasmEditorApi;
use graphic_types::Vector;
pub use text_nodes::*;
#[node_macro::node(category(""))]
#[node_macro::node(category("Text"))]
fn text<'i: 'n>(
_: impl Ctx,
editor: &'i WasmEditorApi,
#[scope("editor-api")] editor_resources: &'i WasmEditorApi,
#[widget(ParsedWidgetOverride::Custom = "text_area")]
#[default("Lorem ipsum")]
text: String,
font: Font,
#[widget(ParsedWidgetOverride::Custom = "text_font")] font: Font,
#[unit(" px")]
#[default(24.)]
font_size: f64,
#[hard_min(1.)]
size: f64,
#[unit("x")]
#[hard_min(0.)]
#[step(0.1)]
#[default(1.2)]
line_height_ratio: f64,
line_height: f64,
#[unit(" px")]
#[default(0.)]
#[step(0.1)]
character_spacing: f64,
#[unit(" px")] max_width: Option<f64>,
#[unit(" px")] max_height: Option<f64>,
/// Faux italic.
#[widget(ParsedWidgetOverride::Hidden)] has_max_width: bool,
#[unit(" px")]
#[hard_min(1.)]
#[widget(ParsedWidgetOverride::Custom = "optional_f64")]
max_width: f64,
#[widget(ParsedWidgetOverride::Hidden)] has_max_height: bool,
#[unit(" px")]
#[hard_min(1.)]
#[widget(ParsedWidgetOverride::Custom = "optional_f64")]
max_height: f64,
#[unit("°")]
#[default(0.)]
#[hard_min(-85.)]
#[hard_max(85.)]
tilt: f64,
align: TextAlign,
/// Splits each text glyph into its own row in the table of vector geometry.
#[default(false)]
per_glyph_instances: bool,
#[widget(ParsedWidgetOverride::Custom = "text_align")] align: TextAlign,
separate_glyph_elements: bool,
) -> Table<Vector> {
let typesetting = TypesettingConfig {
font_size,
line_height_ratio,
font_size: size,
line_height_ratio: line_height,
character_spacing,
max_width,
max_height,
max_width: has_max_width.then_some(max_width),
max_height: has_max_height.then_some(max_height),
tilt,
align,
};
to_path(&text, &font, &editor.font_cache, typesetting, per_glyph_instances)
to_path(&text, &font, &editor_resources.font_cache, typesetting, separate_glyph_elements)
}

View File

@@ -131,7 +131,7 @@ fn image_to_bytes(_: impl Ctx, image: Table<Raster<CPU>>) -> Vec<u8> {
image.element.data.iter().flat_map(|color| color.to_rgb8_srgb().into_iter()).collect::<Vec<u8>>()
}
/// Loads binary from URLs and local asset paths. Returns a transparent placeholder if the resource fails to load, allowing workflows to continue.
/// Loads binary from URLs and local asset paths. Returns a transparent placeholder if the resource fails to load, allowing rendering to continue.
#[node_macro::node(category("Web Request"))]
async fn load_resource<'a: 'n>(_: impl Ctx, _primary: (), #[scope("editor-api")] editor_resources: &'a WasmEditorApi, #[name("URL")] url: String) -> Arc<[u8]> {
let Some(api) = editor_resources.application_io.as_ref() else {

View File

@@ -405,7 +405,6 @@ fn random(
/// Seed to determine the unique variation of which number is generated.
seed: u64,
/// The smaller end of the range within which the random number is generated.
#[default(0.)]
min: f64,
/// The larger end of the range within which the random number is generated.
#[default(1.)]