Skip to content

Commit 0d8c521

Browse files
daniil-lobandaniil.lobanTrueDoctorKeavon
authored
New node: String Split (#3304)
* Add two nodes for substring * fix: number convention * Remove unnecessay allocations and add support for \n in patterns * Make split node return Vec<String> and remove count_elements node * Add Cache implementations for Vec<String> * Code review --------- Co-authored-by: daniil.loban <daniil.loban@gmail.com> Co-authored-by: Dennis Kobert <dennis@kobert.dev> Co-authored-by: Keavon Chambers <keavon@keavon.com>
1 parent c4bbb7e commit 0d8c521

File tree

6 files changed

+54
-3
lines changed

6 files changed

+54
-3
lines changed

node-graph/gcore/src/context_modification.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ async fn context_modification<T>(
3131
Context -> Vec<NodeId>,
3232
Context -> Vec<f64>,
3333
Context -> Vec<f32>,
34+
Context -> Vec<String>,
3435
Context -> Table<Vector>,
3536
Context -> Table<Graphic>,
3637
Context -> Table<Raster<CPU>>,

node-graph/gcore/src/graphic.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -451,6 +451,7 @@ fn index<T: AtIndex + Clone + Default>(
451451
Vec<u32>,
452452
Vec<u64>,
453453
Vec<DVec2>,
454+
Vec<String>,
454455
Table<Artboard>,
455456
Table<Graphic>,
456457
Table<Vector>,

node-graph/gcore/src/logic.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,17 @@ fn string_length(_: impl Ctx, string: String) -> f64 {
6969
string.chars().count() as f64
7070
}
7171

72+
#[node_macro::node(category("Text"))]
73+
fn string_split(_: impl Ctx, string: String, #[default("\\n")] delimeter: String, #[default(true)] delimeter_escaping: bool) -> Vec<String> {
74+
let delimeter = if delimeter_escaping {
75+
delimeter.replace("\\n", "\n").replace("\\r", "\r").replace("\\t", "\t").replace("\\0", "\0").replace("\\\\", "\\")
76+
} else {
77+
delimeter
78+
};
79+
80+
string.split(&delimeter).map(str::to_string).collect()
81+
}
82+
7283
/// Evaluates either the "If True" or "If False" input branch based on whether the input condition is true or false.
7384
#[node_macro::node(category("Math: Logic"))]
7485
async fn switch<T, C: Send + 'n + Clone>(

node-graph/gcore/src/vector/vector_nodes.rs

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1954,11 +1954,39 @@ fn point_inside(_: impl Ctx, source: Table<Vector>, point: DVec2) -> bool {
19541954
source.into_iter().any(|row| row.element.check_point_inside_shape(row.transform, point))
19551955
}
19561956

1957+
trait Count {
1958+
fn count(&self) -> usize;
1959+
}
1960+
impl<T> Count for Table<T> {
1961+
fn count(&self) -> usize {
1962+
self.len()
1963+
}
1964+
}
1965+
impl<T> Count for Vec<T> {
1966+
fn count(&self) -> usize {
1967+
self.len()
1968+
}
1969+
}
1970+
19571971
// TODO: Return u32, u64, or usize instead of f64 after #1621 is resolved and has allowed us to implement automatic type conversion in the node graph for nodes with generic type inputs.
19581972
// TODO: (Currently automatic type conversion only works for concrete types, via the Graphene preprocessor and not the full Graphene type system.)
19591973
#[node_macro::node(category("General"), path(graphene_core::vector))]
1960-
async fn count_elements<I>(_: impl Ctx, #[implementations(Table<Graphic>, Table<Vector>, Table<Raster<CPU>>, Table<Raster<GPU>>, Table<Color>, Table<GradientStops>)] source: Table<I>) -> f64 {
1961-
source.len() as f64
1974+
async fn count_elements<I: Count>(
1975+
_: impl Ctx,
1976+
#[implementations(
1977+
Table<Graphic>,
1978+
Table<Vector>,
1979+
Table<Raster<CPU>>,
1980+
Table<Raster<GPU>>,
1981+
Table<Color>,
1982+
Table<GradientStops>,
1983+
Vec<String>,
1984+
Vec<f64>,
1985+
Vec<DVec2>,
1986+
)]
1987+
source: I,
1988+
) -> f64 {
1989+
source.count() as f64
19621990
}
19631991

19641992
#[node_macro::node(category("Vector: Measure"), path(graphene_core::vector))]

node-graph/interpreted-executor/src/node_registry.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ fn node_registry() -> HashMap<ProtoNodeIdentifier, HashMap<NodeIOTypes, NodeCons
108108
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => graphene_std::vector::misc::PointSpacingType]),
109109
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => Option<f64>]),
110110
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => Vec<DVec2>]),
111+
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => Vec<String>]),
111112
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => [f64; 4]]),
112113
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => Vec<NodeId>]),
113114
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => Graphic]),
@@ -165,6 +166,7 @@ fn node_registry() -> HashMap<ProtoNodeIdentifier, HashMap<NodeIOTypes, NodeCons
165166
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => Vec<NodeId>]),
166167
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => Vec<f64>]),
167168
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => Vec<f32>]),
169+
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => Vec<String>]),
168170
#[cfg(feature = "gpu")]
169171
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => Arc<WasmSurfaceHandle>]),
170172
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => WindowHandle]),

node-graph/node-macro/src/codegen.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,15 @@ pub(crate) fn generate_node_code(crate_ident: &CrateIdent, parsed: &ParsedNodeFn
8888
.iter()
8989
.map(|field| match &field.ty {
9090
ParsedFieldType::Regular(RegularParsedField { value_source, .. }) => match value_source {
91-
ParsedValueSource::Default(data) => quote!(RegistryValueSource::Default(stringify!(#data))),
91+
ParsedValueSource::Default(data) => {
92+
// Check if the data is a string literal by parsing the token stream
93+
let data_str = data.to_string();
94+
if data_str.starts_with('"') && data_str.ends_with('"') && data_str.len() >= 2 {
95+
quote!(RegistryValueSource::Default(#data))
96+
} else {
97+
quote!(RegistryValueSource::Default(stringify!(#data)))
98+
}
99+
}
92100
ParsedValueSource::Scope(data) => quote!(RegistryValueSource::Scope(#data)),
93101
_ => quote!(RegistryValueSource::None),
94102
},

0 commit comments

Comments
 (0)