Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ pub(crate) fn property_from_type(
widgets.extend_from_slice(&[
Separator::new(SeparatorStyle::Unrelated).widget_instance(),
TextLabel::new("-")
.tooltip_label(format!("Data Type: {concrete_type}"))
.tooltip_label(concrete_type.to_string())
.tooltip_description("This data can only be supplied through the node graph because no widget exists for its type.")
.widget_instance(),
]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,8 @@ impl TypeSource {
/// The type to display in the tooltip label.
pub fn resolved_type_tooltip_string(&self) -> String {
match self {
TypeSource::Compiled(compiled_type) => format!("Data Type: {}", compiled_type.nested_type()),
TypeSource::TaggedValue(value_type) => format!("Data Type: {}", value_type.nested_type()),
TypeSource::Compiled(compiled_type) => compiled_type.nested_type().to_string(),
TypeSource::TaggedValue(value_type) => value_type.nested_type().to_string(),
TypeSource::Unknown => "Unknown Data Type".to_string(),
TypeSource::Invalid => "Invalid Type Combination".to_string(),
TypeSource::Error(_) => "Error Getting Data Type".to_string(),
Expand Down Expand Up @@ -253,8 +253,8 @@ impl NodeNetworkInterface {
};
let number_of_inputs = self.number_of_inputs(node_id, network_path);
implementations
.iter()
.filter_map(|(node_io, _)| {
.keys()
.filter_map(|node_io| {
// Check if this NodeIOTypes implementation is valid for the other inputs
let valid_implementation = (0..number_of_inputs).filter(|iterator_index| iterator_index != input_index).all(|iterator_index| {
let input_type = self.input_type_not_invalid(&InputConnector::node(*node_id, iterator_index), network_path);
Expand Down Expand Up @@ -293,8 +293,8 @@ impl NodeNetworkInterface {
let valid_output_types = self.valid_output_types(&OutputConnector::node(*node_id, 0), network_path);

implementations
.iter()
.filter_map(|(node_io, _)| {
.keys()
.filter_map(|node_io| {
if !valid_output_types.iter().any(|output_type| output_type.nested_type() == node_io.return_value.nested_type()) {
return None;
}
Expand Down
22 changes: 9 additions & 13 deletions frontend/src/components/views/Graph.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -188,10 +188,6 @@
return `M-2,-2 L${nodeWidth + 2},-2 L${nodeWidth + 2},${nodeHeight + 2} L-2,${nodeHeight + 2}z ${rectangles.join(" ")}`;
}

function dataTypeTooltipLabel(value: FrontendGraphInput | FrontendGraphOutput): string {
return `Data Type: ${value.resolvedType}`;
}

function nodeNameTooltipLabel(node: FrontendNode): string {
return node.displayName === node.implementationName ? node.displayName : `${node.displayName} (${node.implementationName})`;
}
Expand Down Expand Up @@ -349,7 +345,7 @@
viewBox="0 0 8 8"
class="connector"
data-connector="output"
data-tooltip-label={dataTypeTooltipLabel(frontendOutput)}
data-tooltip-label={frontendOutput.resolvedType}
data-tooltip-description={outputConnectedToText(frontendOutput)}
data-datatype={frontendOutput.dataType}
style:--data-color={`var(--color-data-${frontendOutput.dataType.toLowerCase()})`}
Expand Down Expand Up @@ -418,7 +414,7 @@
viewBox="0 0 8 8"
class="connector"
data-connector="input"
data-tooltip-label={dataTypeTooltipLabel(frontendInput)}
data-tooltip-label={frontendInput.resolvedType}
data-tooltip-description={inputConnectedToText(frontendInput)}
data-datatype={frontendInput.dataType}
style:--data-color={`var(--color-data-${frontendInput.dataType.toLowerCase()})`}
Expand Down Expand Up @@ -556,7 +552,7 @@
viewBox="0 0 8 12"
class="connector top"
data-connector="output"
data-tooltip-label={dataTypeTooltipLabel(node.primaryOutput)}
data-tooltip-label={node.primaryOutput.resolvedType}
data-tooltip-description={outputConnectedToText(node.primaryOutput)}
data-datatype={node.primaryOutput.dataType}
style:--data-color={`var(--color-data-${node.primaryOutput.dataType.toLowerCase()})`}
Expand All @@ -578,7 +574,7 @@
viewBox="0 0 8 12"
class="connector bottom"
data-connector="input"
data-tooltip-label={node.primaryInput ? dataTypeTooltipLabel(node.primaryInput) : ""}
data-tooltip-label={node.primaryInput ? node.primaryInput.resolvedType : ""}
data-tooltip-description={node.primaryInput ? `${validTypesText(node.primaryInput).trim()}\n\n${inputConnectedToText(node.primaryInput)}` : ""}
data-datatype={node.primaryInput?.dataType}
style:--data-color={`var(--color-data-${(node.primaryInput?.dataType || "General").toLowerCase()})`}
Expand All @@ -601,7 +597,7 @@
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 8 8"
class="connector"
data-tooltip-label={dataTypeTooltipLabel(stackDataInput)}
data-tooltip-label={stackDataInput.resolvedType}
data-tooltip-description={`${validTypesText(stackDataInput).trim()}\n\n${inputConnectedToText(stackDataInput)}`}
data-connector="input"
data-datatype={stackDataInput.dataType}
Expand Down Expand Up @@ -755,7 +751,7 @@
viewBox="0 0 8 8"
class="connector primary-connector"
data-connector="input"
data-tooltip-label={dataTypeTooltipLabel(node.primaryInput)}
data-tooltip-label={node.primaryInput.resolvedType}
data-tooltip-description={`${validTypesText(node.primaryInput).trim()}\n\n${inputConnectedToText(node.primaryInput)}`}
data-datatype={node.primaryInput?.dataType}
style:--data-color={`var(--color-data-${node.primaryInput.dataType.toLowerCase()})`}
Expand All @@ -775,7 +771,7 @@
viewBox="0 0 8 8"
class="connector"
data-connector="input"
data-tooltip-label={dataTypeTooltipLabel(secondary)}
data-tooltip-label={secondary.resolvedType}
data-tooltip-description={`${validTypesText(secondary).trim()}\n\n${inputConnectedToText(secondary)}`}
data-datatype={secondary.dataType}
style:--data-color={`var(--color-data-${secondary.dataType.toLowerCase()})`}
Expand All @@ -798,7 +794,7 @@
viewBox="0 0 8 8"
class="connector primary-connector"
data-connector="output"
data-tooltip-label={dataTypeTooltipLabel(node.primaryOutput)}
data-tooltip-label={node.primaryOutput.resolvedType}
data-tooltip-description={`${outputConnectedToText(node.primaryOutput)}`}
data-datatype={node.primaryOutput.dataType}
style:--data-color={`var(--color-data-${node.primaryOutput.dataType.toLowerCase()})`}
Expand All @@ -817,7 +813,7 @@
viewBox="0 0 8 8"
class="connector"
data-connector="output"
data-tooltip-label={dataTypeTooltipLabel(secondary)}
data-tooltip-label={secondary.resolvedType}
data-tooltip-description={`${outputConnectedToText(secondary)}`}
data-datatype={secondary.dataType}
style:--data-color={`var(--color-data-${secondary.dataType.toLowerCase()})`}
Expand Down
80 changes: 68 additions & 12 deletions node-graph/libraries/core-types/src/types.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use crate::transform::Footprint;
use std::any::TypeId;
pub use std::borrow::Cow;
use std::fmt::{Display, Formatter};
Expand Down Expand Up @@ -346,8 +345,73 @@ pub fn simplify_identifier_name(ty: &str) -> String {
.join("<")
}

/// Converts a Rust-internal type name to its user-facing form.
pub fn make_type_user_readable(ty: &str) -> String {
ty.replace("Option<Arc<OwnedContextImpl>>", "Context").replace("Raster<CPU>", "Raster").replace("Raster<GPU>", "Raster")
let ty = ty
.replace("Option<Arc<OwnedContextImpl>>", "Context")
.replace("Raster<CPU>", "Raster")
.replace("Raster<GPU>", "Raster")
.replace("DAffine2", "Transform")
.replace("Affine2", "Transform")
.replace("DVec2", "Vec2")
.replace("IVec2", "Vec2")
.replace("UVec2", "Vec2")
.replace("&str", "String");

rewrite_list_as_array_brackets(&ty)
}

/// Rewrites `List<T>` as `T[]`. Handles nesting (e.g. `List<List<Vector>>` becomes `Vector[][]`).
/// Respects word boundaries so unrelated identifiers that happen to end in `List` are not affected.
fn rewrite_list_as_array_brackets(input: &str) -> String {
let bytes = input.as_bytes();
let mut result = String::with_capacity(input.len());
let mut i = 0;

while i < bytes.len() {
let at_word_boundary = i == 0 || !is_identifier_byte(bytes[i - 1]);
if at_word_boundary && bytes[i..].starts_with(b"List<") {
let inner_start = i + b"List<".len();
if let Some(close) = find_matching_angle_bracket(bytes, inner_start) {
let inner = &input[inner_start..close];
result.push_str(&rewrite_list_as_array_brackets(inner));
result.push_str("[]");
i = close + 1;
continue;
}
}
if bytes[i].is_ascii() {
result.push(bytes[i] as char);
i += 1;
} else {
let ch = input[i..].chars().next().unwrap();
result.push(ch);
i += ch.len_utf8();
}
}

result
}

fn is_identifier_byte(byte: u8) -> bool {
byte.is_ascii_alphanumeric() || byte == b'_'
}

fn find_matching_angle_bracket(bytes: &[u8], start: usize) -> Option<usize> {
let mut depth = 1_usize;
for (offset, &byte) in bytes[start..].iter().enumerate() {
match byte {
b'<' => depth += 1,
b'>' => {
depth -= 1;
if depth == 0 {
return Some(start + offset);
}
}
_ => {}
}
}
None
}

impl std::fmt::Debug for Type {
Expand All @@ -359,18 +423,10 @@ impl std::fmt::Debug for Type {
// Display
impl std::fmt::Display for Type {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
use glam::*;

match self {
Type::Generic(name) => write!(f, "{}", make_type_user_readable(name)),
Type::Concrete(ty) => match () {
() if self == &concrete!(DVec2) || self == &concrete!(Vec2) || self == &concrete!(IVec2) || self == &concrete!(UVec2) => write!(f, "Vec2"),
() if self == &concrete!(glam::DAffine2) => write!(f, "Transform"),
() if self == &concrete!(Footprint) => write!(f, "Footprint"),
() if self == &concrete!(&str) || self == &concrete!(String) => write!(f, "String"),
_ => write!(f, "{}", make_type_user_readable(&simplify_identifier_name(&ty.name))),
},
Type::Fn(call_arg, return_value) => write!(f, "{return_value} called with {call_arg}"),
Type::Concrete(ty) => write!(f, "{ty}"),
Type::Fn(_, return_value) => write!(f, "{return_value}"),
Type::Future(ty) => write!(f, "{ty}"),
}
}
Expand Down
Loading