Skip to content

Commit 3211a6a

Browse files
committed
Add node for executing rhai scripts
1 parent 7e7e88f commit 3211a6a

File tree

15 files changed

+341
-15
lines changed

15 files changed

+341
-15
lines changed

Cargo.lock

+88
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

editor/src/messages/dialog/simple_dialogs/close_all_documents_dialog.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ impl DialogLayoutHolder for CloseAllDocumentsDialog {
3030

3131
impl LayoutHolder for CloseAllDocumentsDialog {
3232
fn layout(&self) -> Layout {
33-
let unsaved_list = "• ".to_string() + &self.unsaved_document_names.join("\n• ");
33+
let unsaved_list = "• ".to_string() + self.unsaved_document_names.join("\n• ").as_str();
3434

3535
Layout::WidgetLayout(WidgetLayout::new(vec![
3636
LayoutGroup::Row {

editor/src/messages/portfolio/document/node_graph/document_node_definitions.rs

+20
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,25 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
130130
description: Cow::Borrowed("The identity node passes its data through. You can use this to organize your node graph."),
131131
properties: Some("identity_properties"),
132132
},
133+
DocumentNodeDefinition {
134+
identifier: "Script",
135+
category: "General",
136+
node_template: NodeTemplate {
137+
document_node: DocumentNode {
138+
implementation: DocumentNodeImplementation::proto("graphene_std::rhai::RhaiNode"),
139+
manual_composition: Some(concrete!(Context)),
140+
inputs: vec![NodeInput::value(TaggedValue::F64(0.), true), NodeInput::value(TaggedValue::String("input".into()), false)],
141+
..Default::default()
142+
},
143+
persistent_node_metadata: DocumentNodePersistentMetadata {
144+
input_properties: vec!["In".into(), "String".into()],
145+
output_names: vec!["Out".to_string()],
146+
..Default::default()
147+
},
148+
},
149+
description: Cow::Borrowed(""),
150+
properties: Some("script_properties"),
151+
},
133152
// TODO: Auto-generate this from its proto node macro
134153
DocumentNodeDefinition {
135154
identifier: "Monitor",
@@ -2897,6 +2916,7 @@ fn static_node_properties() -> NodeProperties {
28972916
"monitor_properties".to_string(),
28982917
Box::new(|_node_id, _context| node_properties::string_properties("The Monitor node is used by the editor to access the data flowing through it.")),
28992918
);
2919+
map.insert("script_properties".to_string(), Box::new(node_properties::script_properties));
29002920
map
29012921
}
29022922

editor/src/messages/portfolio/document/node_graph/node_properties.rs

+14
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,7 @@ pub(crate) fn property_from_type(
264264
}
265265
}
266266
Type::Generic(_) => vec![TextLabel::new("Generic type (not supported)").widget_holder()].into(),
267+
Type::Dynamic => vec![TextLabel::new("Dynamic type (not supported)").widget_holder()].into(),
267268
Type::Fn(_, out) => return property_from_type(node_id, index, out, number_options, context),
268269
Type::Future(out) => return property_from_type(node_id, index, out, number_options, context),
269270
};
@@ -2516,3 +2517,16 @@ pub fn math_properties(node_id: NodeId, context: &mut NodePropertiesContext) ->
25162517
LayoutGroup::Row { widgets: operand_a_hint }.with_tooltip(r#""A" is fed by the value from the previous node in the primary data flow, or it is 0 if disconnected"#),
25172518
]
25182519
}
2520+
2521+
pub(crate) fn script_properties(node_id: NodeId, context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
2522+
let document_node = match get_document_node(node_id, context) {
2523+
Ok(document_node) => document_node,
2524+
Err(err) => {
2525+
log::error!("Could not get document node in script_properties: {err}");
2526+
return Vec::new();
2527+
}
2528+
};
2529+
let source = text_area_widget(document_node, node_id, 1, "Code", false);
2530+
2531+
vec![LayoutGroup::Row { widgets: source }]
2532+
}

editor/src/messages/portfolio/document/overlays/grid_overlays.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ fn grid_overlay_rectangular(document: &DocumentMessageHandler, overlay_context:
3939
overlay_context.line(
4040
document_to_viewport.transform_point2(start),
4141
document_to_viewport.transform_point2(end),
42-
Some(&("#".to_string() + &grid_color.rgba_hex())),
42+
Some(&("#".to_string() + grid_color.rgba_hex().as_str())),
4343
);
4444
}
4545
}
@@ -82,7 +82,7 @@ fn grid_overlay_rectangular_dot(document: &DocumentMessageHandler, overlay_conte
8282
let exact_x = x_per_dot * dot_index as f64;
8383
overlay_context.pixel(
8484
document_to_viewport.transform_point2(DVec2::new(start.x + exact_x, start.y)).round(),
85-
Some(&("#".to_string() + &grid_color.rgba_hex())),
85+
Some(&("#".to_string() + grid_color.rgba_hex().as_str())),
8686
)
8787
}
8888
}
@@ -115,7 +115,7 @@ fn grid_overlay_isometric(document: &DocumentMessageHandler, overlay_context: &m
115115
overlay_context.line(
116116
document_to_viewport.transform_point2(start),
117117
document_to_viewport.transform_point2(end),
118-
Some(&("#".to_string() + &grid_color.rgba_hex())),
118+
Some(&("#".to_string() + grid_color.rgba_hex().as_str())),
119119
);
120120
}
121121

@@ -133,7 +133,7 @@ fn grid_overlay_isometric(document: &DocumentMessageHandler, overlay_context: &m
133133
overlay_context.line(
134134
document_to_viewport.transform_point2(start),
135135
document_to_viewport.transform_point2(end),
136-
Some(&("#".to_string() + &grid_color.rgba_hex())),
136+
Some(&("#".to_string() + grid_color.rgba_hex().as_str())),
137137
);
138138
}
139139
}
@@ -180,7 +180,7 @@ fn grid_overlay_isometric_dot(document: &DocumentMessageHandler, overlay_context
180180
overlay_context.dashed_line(
181181
document_to_viewport.transform_point2(start),
182182
document_to_viewport.transform_point2(end),
183-
Some(&("#".to_string() + &grid_color.rgba_hex())),
183+
Some(&("#".to_string() + grid_color.rgba_hex().as_str())),
184184
Some(1.),
185185
Some((spacing_x / cos_a) * document_to_viewport.matrix2.x_axis.length() - 1.),
186186
None,

editor/src/messages/tool/tool_messages/text_tool.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -464,7 +464,7 @@ impl Fsm for TextToolFsmState {
464464
if far.x != 0. && far.y != 0. {
465465
let quad = Quad::from_box([DVec2::ZERO, far]);
466466
let transformed_quad = document.metadata().transform_to_viewport(tool_data.layer) * quad;
467-
overlay_context.quad(transformed_quad, Some(&("#".to_string() + &fill_color)));
467+
overlay_context.quad(transformed_quad, Some(&("#".to_string() + fill_color.as_str())));
468468
}
469469
}
470470

@@ -479,11 +479,11 @@ impl Fsm for TextToolFsmState {
479479
for layer in document.intersect_quad_no_artboards(quad, input) {
480480
overlay_context.quad(
481481
Quad::from_box(document.metadata().bounding_box_viewport(layer).unwrap_or([DVec2::ZERO; 2])),
482-
Some(&("#".to_string() + &fill_color)),
482+
Some(&("#".to_string() + fill_color.as_str())),
483483
);
484484
}
485485

486-
overlay_context.quad(quad, Some(&("#".to_string() + &fill_color)));
486+
overlay_context.quad(quad, Some(&("#".to_string() + fill_color.as_str())));
487487
}
488488

489489
// TODO: implement bounding box for multiple layers

editor/src/node_graph_executor.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -562,10 +562,10 @@ impl NodeGraphExecutor {
562562
..
563563
} = export_config;
564564

565-
let file_suffix = &format!(".{file_type:?}").to_lowercase();
565+
let file_suffix = format!(".{file_type:?}").to_lowercase();
566566
let name = match file_name.ends_with(FILE_SAVE_SUFFIX) {
567-
true => file_name.replace(FILE_SAVE_SUFFIX, file_suffix),
568-
false => file_name + file_suffix,
567+
true => file_name.replace(FILE_SAVE_SUFFIX, &file_suffix),
568+
false => file_name + file_suffix.as_str(),
569569
};
570570

571571
if file_type == FileType::Svg {

node-graph/gcore/src/registry.rs

+25
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,31 @@ impl<I, O> DowncastBothNode<I, O> {
197197
}
198198
}
199199
}
200+
/// Boxes the input and downcasts the output.
201+
/// Wraps around a node taking Box<dyn DynAny> and returning Box<dyn DynAny>
202+
#[derive(Clone)]
203+
pub struct DowncastNoneNode {
204+
node: SharedNodeContainer,
205+
}
206+
impl<'input> Node<'input, Any<'input>> for DowncastNoneNode {
207+
type Output = FutureAny<'input>;
208+
#[inline]
209+
fn eval(&'input self, input: Any<'input>) -> Self::Output {
210+
self.node.eval(input)
211+
}
212+
fn reset(&self) {
213+
self.node.reset();
214+
}
215+
216+
fn serialize(&self) -> Option<std::sync::Arc<dyn core::any::Any + Send + Sync>> {
217+
self.node.serialize()
218+
}
219+
}
220+
impl DowncastNoneNode {
221+
pub const fn new(node: SharedNodeContainer) -> Self {
222+
Self { node }
223+
}
224+
}
200225
pub struct FutureWrapperNode<Node> {
201226
node: Node,
202227
}

node-graph/gcore/src/types.rs

+15
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,7 @@ pub enum Type {
207207
Fn(Box<Type>, Box<Type>),
208208
/// Represents a future which promises to return the inner type.
209209
Future(Box<Type>),
210+
Dynamic,
210211
}
211212

212213
impl Default for Type {
@@ -258,6 +259,15 @@ impl Type {
258259
_ => None,
259260
}
260261
}
262+
pub fn fn_fut_output(&self) -> Option<&Type> {
263+
match self {
264+
Type::Fn(_, second) => match second.as_ref() {
265+
Type::Future(fut) => Some(fut),
266+
_ => None,
267+
},
268+
_ => None,
269+
}
270+
}
261271

262272
pub fn function(input: &Type, output: &Type) -> Type {
263273
Type::Fn(Box::new(input.clone()), Box::new(output.clone()))
@@ -281,6 +291,7 @@ impl Type {
281291
Self::Concrete(ty) => Some(ty.size),
282292
Self::Fn(_, _) => None,
283293
Self::Future(_) => None,
294+
Self::Dynamic => None,
284295
}
285296
}
286297

@@ -290,6 +301,7 @@ impl Type {
290301
Self::Concrete(ty) => Some(ty.align),
291302
Self::Fn(_, _) => None,
292303
Self::Future(_) => None,
304+
Self::Dynamic => None,
293305
}
294306
}
295307

@@ -299,6 +311,7 @@ impl Type {
299311
Self::Concrete(_) => self,
300312
Self::Fn(_, output) => output.nested_type(),
301313
Self::Future(output) => output.nested_type(),
314+
Self::Dynamic => self,
302315
}
303316
}
304317
}
@@ -320,6 +333,7 @@ impl core::fmt::Debug for Type {
320333
Self::Concrete(arg0) => write!(f, "Concrete<{}>", format_type(&arg0.name)),
321334
Self::Fn(arg0, arg1) => write!(f, "{arg0:?} → {arg1:?}"),
322335
Self::Future(arg0) => write!(f, "Future<{arg0:?}>"),
336+
Self::Dynamic => write!(f, "Dynamic"),
323337
}
324338
}
325339
}
@@ -331,6 +345,7 @@ impl std::fmt::Display for Type {
331345
Type::Concrete(ty) => write!(f, "{}", format_type(&ty.name)),
332346
Type::Fn(input, output) => write!(f, "{input} → {output}"),
333347
Type::Future(ty) => write!(f, "Future<{ty}>"),
348+
Self::Dynamic => write!(f, "Dynamic"),
334349
}
335350
}
336351
}

0 commit comments

Comments
 (0)