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-16 06:13:32 +00:00
committed by GitHub
co-authored by Keavon Chambers
parent 73682b482b
commit c60ddcf875
12 changed files with 254 additions and 188 deletions
@@ -388,23 +388,49 @@ pub fn get_grid_id(layer: LayerNodeIdentifier, network_interface: &NodeNetworkIn
pub fn get_text(layer: LayerNodeIdentifier, network_interface: &NodeNetworkInterface) -> Option<(&String, &Font, TypesettingConfig, bool)> {
let inputs = NodeGraphLayer::new(layer, network_interface).find_node_inputs(&DefinitionIdentifier::ProtoNode(graphene_std::text::text::IDENTIFIER))?;
let Some(TaggedValue::String(text)) = &inputs[1].as_value() else { return None };
let Some(TaggedValue::Font(font)) = &inputs[2].as_value() else { return None };
let Some(&TaggedValue::F64(font_size)) = inputs[3].as_value() else { return None };
let Some(&TaggedValue::F64(line_height_ratio)) = inputs[4].as_value() else { return None };
let Some(&TaggedValue::F64(character_spacing)) = inputs[5].as_value() else { return None };
let Some(&TaggedValue::OptionalF64(max_width)) = inputs[6].as_value() else { return None };
let Some(&TaggedValue::OptionalF64(max_height)) = inputs[7].as_value() else { return None };
let Some(&TaggedValue::F64(tilt)) = inputs[8].as_value() else { return None };
let Some(&TaggedValue::TextAlign(align)) = inputs[9].as_value() else { return None };
let Some(&TaggedValue::Bool(per_glyph_instances)) = inputs[10].as_value() else { return None };
let Some(TaggedValue::String(text)) = &inputs[graphene_std::text::text::TextInput::INDEX].as_value() else {
return None;
};
let Some(TaggedValue::Font(font)) = &inputs[graphene_std::text::text::FontInput::INDEX].as_value() else {
return None;
};
let Some(&TaggedValue::F64(font_size)) = inputs[graphene_std::text::text::SizeInput::INDEX].as_value() else {
return None;
};
let Some(&TaggedValue::F64(line_height_ratio)) = inputs[graphene_std::text::text::LineHeightInput::INDEX].as_value() else {
return None;
};
let Some(&TaggedValue::F64(character_spacing)) = inputs[graphene_std::text::text::CharacterSpacingInput::INDEX].as_value() else {
return None;
};
let Some(&TaggedValue::Bool(has_max_width)) = inputs[graphene_std::text::text::HasMaxWidthInput::INDEX].as_value() else {
return None;
};
let Some(&TaggedValue::F64(max_width)) = inputs[graphene_std::text::text::MaxWidthInput::INDEX].as_value() else {
return None;
};
let Some(&TaggedValue::Bool(has_max_height)) = inputs[graphene_std::text::text::HasMaxHeightInput::INDEX].as_value() else {
return None;
};
let Some(&TaggedValue::F64(max_height)) = inputs[graphene_std::text::text::MaxHeightInput::INDEX].as_value() else {
return None;
};
let Some(&TaggedValue::F64(tilt)) = inputs[graphene_std::text::text::TiltInput::INDEX].as_value() else {
return None;
};
let Some(&TaggedValue::TextAlign(align)) = inputs[graphene_std::text::text::AlignInput::INDEX].as_value() else {
return None;
};
let Some(&TaggedValue::Bool(per_glyph_instances)) = inputs[graphene_std::text::text::SeparateGlyphElementsInput::INDEX].as_value() else {
return None;
};
let typesetting = TypesettingConfig {
font_size,
line_height_ratio,
max_width,
max_width: has_max_width.then_some(max_width),
max_height: has_max_height.then_some(max_height),
character_spacing,
max_height,
tilt,
align,
};
@@ -18,10 +18,10 @@ use crate::messages::tool::common_functionality::utility_functions::text_boundin
use crate::messages::tool::utility_types::ToolRefreshOptions;
use graph_craft::document::value::TaggedValue;
use graph_craft::document::{NodeId, NodeInput};
use graphene_std::Color;
use graphene_std::renderer::Quad;
use graphene_std::text::{Font, FontCache, TextAlign, TypesettingConfig, lines_clipping};
use graphene_std::vector::style::Fill;
use graphene_std::{Color, NodeInputDecleration};
#[derive(Default, ExtractField)]
pub struct TextTool {
@@ -800,13 +800,22 @@ impl Fsm for TextToolFsmState {
// Find the translation necessary from the original position in viewport space
let translation_viewport = bounds.original_bound_transform.transform_vector2(translation_bounds_space);
// TODO: Don't set both max_width and max_height to true at the same time, only do one based on which edge is being dragged (or both if a corner is being dragged)
responses.add(NodeGraphMessage::SetInput {
input_connector: InputConnector::node(node_id, 6),
input: NodeInput::value(TaggedValue::OptionalF64(Some(size_layer.x)), false),
input_connector: InputConnector::node(node_id, graphene_std::text::text::HasMaxWidthInput::INDEX),
input: NodeInput::value(TaggedValue::Bool(true), false),
});
responses.add(NodeGraphMessage::SetInput {
input_connector: InputConnector::node(node_id, 7),
input: NodeInput::value(TaggedValue::OptionalF64(Some(size_layer.y)), false),
input_connector: InputConnector::node(node_id, graphene_std::text::text::MaxWidthInput::INDEX),
input: NodeInput::value(TaggedValue::F64(size_layer.x), false),
});
responses.add(NodeGraphMessage::SetInput {
input_connector: InputConnector::node(node_id, graphene_std::text::text::HasMaxHeightInput::INDEX),
input: NodeInput::value(TaggedValue::Bool(true), false),
});
responses.add(NodeGraphMessage::SetInput {
input_connector: InputConnector::node(node_id, graphene_std::text::text::MaxHeightInput::INDEX),
input: NodeInput::value(TaggedValue::F64(size_layer.y), false),
});
responses.add(GraphOperationMessage::TransformSet {
layer: dragging_layer.id,