Remove the UVec2 and IVec2 graph data types and have Artboard use DVec2 (#2894)
Some checks are pending
Editor: Dev & CI / build (push) Waiting to run
Editor: Dev & CI / cargo-deny (push) Waiting to run

This commit is contained in:
Keavon Chambers 2025-07-16 18:45:10 -07:00 committed by GitHub
parent 99966d848d
commit 8f26c5c2ad
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 49 additions and 87 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -97,7 +97,7 @@ impl<'a> ModifyInputsContext<'a> {
};
}
let layer_input_connector = post_node_input_connector.clone();
let layer_input_connector = post_node_input_connector;
// Sink post_node down to the end of the non layer chain that feeds into post_node, such that pre_node is the layer node at insert_index + 1, or None if insert_index is the last layer
loop {
@ -132,8 +132,8 @@ impl<'a> ModifyInputsContext<'a> {
let artboard_node_template = resolve_document_node_type("Artboard").expect("Node").node_template_input_override([
Some(NodeInput::value(TaggedValue::ArtboardGroup(graphene_std::ArtboardGroupTable::default()), true)),
Some(NodeInput::value(TaggedValue::GraphicGroup(graphene_std::GraphicGroupTable::default()), true)),
Some(NodeInput::value(TaggedValue::IVec2(artboard.location), false)),
Some(NodeInput::value(TaggedValue::IVec2(artboard.dimensions), false)),
Some(NodeInput::value(TaggedValue::DVec2(artboard.location.into()), false)),
Some(NodeInput::value(TaggedValue::DVec2(artboard.dimensions.into()), false)),
Some(NodeInput::value(TaggedValue::Color(artboard.background), false)),
Some(NodeInput::value(TaggedValue::Bool(artboard.clip), false)),
]);
@ -486,8 +486,8 @@ impl<'a> ModifyInputsContext<'a> {
dimensions.y *= -1;
location.y -= dimensions.y;
}
self.set_input_with_refresh(InputConnector::node(artboard_node_id, 2), NodeInput::value(TaggedValue::IVec2(location), false), false);
self.set_input_with_refresh(InputConnector::node(artboard_node_id, 3), NodeInput::value(TaggedValue::IVec2(dimensions), false), false);
self.set_input_with_refresh(InputConnector::node(artboard_node_id, 2), NodeInput::value(TaggedValue::DVec2(location.into()), false), false);
self.set_input_with_refresh(InputConnector::node(artboard_node_id, 3), NodeInput::value(TaggedValue::DVec2(dimensions.into()), false), false);
}
/// Set the input, refresh the properties panel, and run the document graph if skip_rerender is false

View file

@ -378,8 +378,8 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
inputs: vec![
NodeInput::value(TaggedValue::ArtboardGroup(ArtboardGroupTable::default()), true),
NodeInput::value(TaggedValue::GraphicGroup(GraphicGroupTable::default()), true),
NodeInput::value(TaggedValue::IVec2(glam::IVec2::ZERO), false),
NodeInput::value(TaggedValue::IVec2(glam::IVec2::new(1920, 1080)), false),
NodeInput::value(TaggedValue::DVec2(DVec2::ZERO), false),
NodeInput::value(TaggedValue::DVec2(DVec2::new(1920., 1080.)), false),
NodeInput::value(TaggedValue::Color(Color::WHITE), false),
NodeInput::value(TaggedValue::Bool(false), false),
],
@ -396,6 +396,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
x: "X".to_string(),
y: "Y".to_string(),
unit: " px".to_string(),
is_integer: true,
..Default::default()
}),
),
@ -406,6 +407,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
x: "W".to_string(),
y: "H".to_string(),
unit: " px".to_string(),
is_integer: true,
..Default::default()
}),
),
@ -1953,8 +1955,20 @@ fn static_input_properties() -> InputProperties {
.network_interface
.input_data(&node_id, index, "min", context.selection_network_path)
.and_then(|value| value.as_f64());
let is_integer = context
.network_interface
.input_data(&node_id, index, "is_integer", context.selection_network_path)
.and_then(|value| value.as_bool())
.unwrap_or_default();
Ok(vec![node_properties::coordinate_widget(ParameterWidgetsInfo::new(node_id, index, true, context), &x, &y, &unit, min)])
Ok(vec![node_properties::coordinate_widget(
ParameterWidgetsInfo::new(node_id, index, true, context),
&x,
&y,
&unit,
min,
is_integer,
)])
}),
);
map.insert(

View file

@ -7,7 +7,7 @@ use crate::messages::portfolio::document::utility_types::network_interface::Inpu
use crate::messages::prelude::*;
use choice::enum_choice;
use dyn_any::DynAny;
use glam::{DAffine2, DVec2, IVec2, UVec2};
use glam::{DAffine2, DVec2};
use graph_craft::Type;
use graph_craft::document::value::TaggedValue;
use graph_craft::document::{DocumentNode, DocumentNodeImplementation, NodeId, NodeInput};
@ -160,8 +160,7 @@ pub(crate) fn property_from_type(
Some("Fraction") => number_widget(default_info, number_input.mode_range().min(min(0.)).max(max(1.))).into(),
Some("IntegerCount") => number_widget(default_info, number_input.int().min(min(1.))).into(),
Some("SeedValue") => number_widget(default_info, number_input.int().min(min(0.))).into(),
Some("Resolution") => coordinate_widget(default_info, "W", "H", unit.unwrap_or(" px"), Some(64.)),
Some("PixelSize") => coordinate_widget(default_info, "X", "Y", unit.unwrap_or(" px"), None),
Some("PixelSize") => coordinate_widget(default_info, "X", "Y", unit.unwrap_or(" px"), None, false),
Some("TextArea") => text_area_widget(default_info).into(),
// For all other types, use TypeId-based matching
@ -176,9 +175,7 @@ pub(crate) fn property_from_type(
Some(x) if x == TypeId::of::<u64>() => number_widget(default_info, number_input.int().min(min(0.))).into(),
Some(x) if x == TypeId::of::<bool>() => bool_widget(default_info, CheckboxInput::default()).into(),
Some(x) if x == TypeId::of::<String>() => text_widget(default_info).into(),
Some(x) if x == TypeId::of::<DVec2>() => coordinate_widget(default_info, "X", "Y", "", None),
Some(x) if x == TypeId::of::<UVec2>() => coordinate_widget(default_info, "X", "Y", "", Some(0.)),
Some(x) if x == TypeId::of::<IVec2>() => coordinate_widget(default_info, "X", "Y", "", None),
Some(x) if x == TypeId::of::<DVec2>() => coordinate_widget(default_info, "X", "Y", "", None, false),
// ==========================
// PRIMITIVE COLLECTION TYPES
// ==========================
@ -507,7 +504,7 @@ pub fn footprint_widget(parameter_widgets_info: ParameterWidgetsInfo, extra_widg
last.clone()
}
pub fn coordinate_widget(parameter_widgets_info: ParameterWidgetsInfo, x: &str, y: &str, unit: &str, min: Option<f64>) -> LayoutGroup {
pub fn coordinate_widget(parameter_widgets_info: ParameterWidgetsInfo, x: &str, y: &str, unit: &str, min: Option<f64>, is_integer: bool) -> LayoutGroup {
let ParameterWidgetsInfo { document_node, node_id, index, .. } = parameter_widgets_info;
let mut widgets = start_widgets(parameter_widgets_info);
@ -526,6 +523,7 @@ pub fn coordinate_widget(parameter_widgets_info: ParameterWidgetsInfo, x: &str,
.unit(unit)
.min(min.unwrap_or(-((1_u64 << f64::MANTISSA_DIGITS) as f64)))
.max((1_u64 << f64::MANTISSA_DIGITS) as f64)
.is_integer(is_integer)
.on_update(update_value(move |input: &NumberInput| TaggedValue::DVec2(DVec2::new(input.value.unwrap(), dvec2.y)), node_id, index))
.on_commit(commit_value)
.widget_holder(),
@ -535,63 +533,12 @@ pub fn coordinate_widget(parameter_widgets_info: ParameterWidgetsInfo, x: &str,
.unit(unit)
.min(min.unwrap_or(-((1_u64 << f64::MANTISSA_DIGITS) as f64)))
.max((1_u64 << f64::MANTISSA_DIGITS) as f64)
.is_integer(is_integer)
.on_update(update_value(move |input: &NumberInput| TaggedValue::DVec2(DVec2::new(dvec2.x, input.value.unwrap())), node_id, index))
.on_commit(commit_value)
.widget_holder(),
]);
}
Some(&TaggedValue::IVec2(ivec2)) => {
let update_x = move |input: &NumberInput| TaggedValue::IVec2(IVec2::new(input.value.unwrap() as i32, ivec2.y));
let update_y = move |input: &NumberInput| TaggedValue::IVec2(IVec2::new(ivec2.x, input.value.unwrap() as i32));
widgets.extend_from_slice(&[
Separator::new(SeparatorType::Unrelated).widget_holder(),
NumberInput::new(Some(ivec2.x as f64))
.int()
.label(x)
.unit(unit)
.min(min.unwrap_or(-((1_u64 << f64::MANTISSA_DIGITS) as f64)))
.max((1_u64 << f64::MANTISSA_DIGITS) as f64)
.on_update(update_value(update_x, node_id, index))
.on_commit(commit_value)
.widget_holder(),
Separator::new(SeparatorType::Related).widget_holder(),
NumberInput::new(Some(ivec2.y as f64))
.int()
.label(y)
.unit(unit)
.min(min.unwrap_or(-((1_u64 << f64::MANTISSA_DIGITS) as f64)))
.max((1_u64 << f64::MANTISSA_DIGITS) as f64)
.on_update(update_value(update_y, node_id, index))
.on_commit(commit_value)
.widget_holder(),
]);
}
Some(&TaggedValue::UVec2(uvec2)) => {
let update_x = move |input: &NumberInput| TaggedValue::UVec2(UVec2::new(input.value.unwrap() as u32, uvec2.y));
let update_y = move |input: &NumberInput| TaggedValue::UVec2(UVec2::new(uvec2.x, input.value.unwrap() as u32));
widgets.extend_from_slice(&[
Separator::new(SeparatorType::Unrelated).widget_holder(),
NumberInput::new(Some(uvec2.x as f64))
.int()
.label(x)
.unit(unit)
.min(min.unwrap_or(0.))
.max((1_u64 << f64::MANTISSA_DIGITS) as f64)
.on_update(update_value(update_x, node_id, index))
.on_commit(commit_value)
.widget_holder(),
Separator::new(SeparatorType::Related).widget_holder(),
NumberInput::new(Some(uvec2.y as f64))
.int()
.label(y)
.unit(unit)
.min(min.unwrap_or(0.))
.max((1_u64 << f64::MANTISSA_DIGITS) as f64)
.on_update(update_value(update_y, node_id, index))
.on_commit(commit_value)
.widget_holder(),
]);
}
Some(&TaggedValue::F64(value)) => {
widgets.extend_from_slice(&[
Separator::new(SeparatorType::Unrelated).widget_holder(),
@ -600,6 +547,7 @@ pub fn coordinate_widget(parameter_widgets_info: ParameterWidgetsInfo, x: &str,
.unit(unit)
.min(min.unwrap_or(-((1_u64 << f64::MANTISSA_DIGITS) as f64)))
.max((1_u64 << f64::MANTISSA_DIGITS) as f64)
.is_integer(is_integer)
.on_update(update_value(move |input: &NumberInput| TaggedValue::DVec2(DVec2::new(input.value.unwrap(), value)), node_id, index))
.on_commit(commit_value)
.widget_holder(),
@ -609,6 +557,7 @@ pub fn coordinate_widget(parameter_widgets_info: ParameterWidgetsInfo, x: &str,
.unit(unit)
.min(min.unwrap_or(-((1_u64 << f64::MANTISSA_DIGITS) as f64)))
.max((1_u64 << f64::MANTISSA_DIGITS) as f64)
.is_integer(is_integer)
.on_update(update_value(move |input: &NumberInput| TaggedValue::DVec2(DVec2::new(value, input.value.unwrap())), node_id, index))
.on_commit(commit_value)
.widget_holder(),
@ -1178,7 +1127,7 @@ pub(crate) fn grid_properties(node_id: NodeId, context: &mut NodePropertiesConte
if let Some(&TaggedValue::GridType(grid_type)) = grid_type_input.as_non_exposed_value() {
match grid_type {
GridType::Rectangular => {
let spacing = coordinate_widget(ParameterWidgetsInfo::new(node_id, SpacingInput::<f64>::INDEX, true, context), "W", "H", " px", Some(0.));
let spacing = coordinate_widget(ParameterWidgetsInfo::new(node_id, SpacingInput::<f64>::INDEX, true, context), "W", "H", " px", Some(0.), false);
widgets.push(spacing);
}
GridType::Isometric => {
@ -1188,7 +1137,7 @@ pub(crate) fn grid_properties(node_id: NodeId, context: &mut NodePropertiesConte
NumberInput::default().label("H").min(0.).unit(" px"),
),
};
let angles = coordinate_widget(ParameterWidgetsInfo::new(node_id, AnglesInput::INDEX, true, context), "", "", "°", None);
let angles = coordinate_widget(ParameterWidgetsInfo::new(node_id, AnglesInput::INDEX, true, context), "", "", "°", None, false);
widgets.extend([spacing, angles]);
}
}

View file

@ -23,8 +23,6 @@ impl FrontendGraphDataType {
TaggedValue::U32(_)
| TaggedValue::U64(_)
| TaggedValue::F64(_)
| TaggedValue::UVec2(_)
| TaggedValue::IVec2(_)
| TaggedValue::DVec2(_)
| TaggedValue::OptionalDVec2(_)
| TaggedValue::F64Array4(_)

View file

@ -6473,6 +6473,7 @@ pub struct Vec2InputSettings {
pub y: String,
pub unit: String,
pub min: Option<f64>,
pub is_integer: bool,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
@ -6547,6 +6548,7 @@ impl InputPersistentMetadata {
self.input_data.insert("x".to_string(), json!(vec2_properties.x));
self.input_data.insert("y".to_string(), json!(vec2_properties.y));
self.input_data.insert("unit".to_string(), json!(vec2_properties.unit));
self.input_data.insert("is_integer".to_string(), Value::Bool(vec2_properties.is_integer));
if let Some(min) = vec2_properties.min {
self.input_data.insert("min".to_string(), json!(min));
}

View file

@ -326,8 +326,7 @@ pub mod test_prelude {
pub use crate::node_graph_executor::NodeRuntime;
pub use crate::test_utils::EditorTestUtils;
pub use core::f64;
pub use glam::DVec2;
pub use glam::IVec2;
pub use glam::{DVec2, IVec2};
pub use graph_craft::document::DocumentNode;
pub use graphene_std::raster::{Color, Image};
pub use graphene_std::transform::Footprint;

View file

@ -466,11 +466,14 @@ async fn to_artboard<Data: Into<GraphicGroupTable> + 'n>(
)]
contents: impl Node<Context<'static>, Output = Data>,
label: String,
location: IVec2,
dimensions: IVec2,
location: DVec2,
dimensions: DVec2,
background: Color,
clip: bool,
) -> Artboard {
let location = location.as_ivec2();
let dimensions = dimensions.as_ivec2().max(IVec2::ONE);
let footprint = ctx.try_footprint().copied();
let mut new_ctx = OwnedContextImpl::from(ctx);
if let Some(mut footprint) = footprint {

View file

@ -26,8 +26,6 @@ pub mod types {
pub type IntegerCount = u32;
/// Unsigned integer to be used for random seeds
pub type SeedValue = u32;
/// Non-negative integer coordinate with px unit
pub type Resolution = glam::UVec2;
/// DVec2 with px unit
pub type PixelSize = glam::DVec2;
/// String with one or more than one line

View file

@ -165,8 +165,7 @@ tagged_value! {
U64(u64),
Bool(bool),
String(String),
UVec2(UVec2),
IVec2(IVec2),
#[serde(alias = "IVec2", alias = "UVec2")]
DVec2(DVec2),
DAffine2(DAffine2),
OptionalF64(Option<f64>),