Graphite 如何用 node 宏创建一个带默认值、滑杆与类别的新节点? Graphite 如何用 node 宏创建一个带默认值、滑杆与类别的新节点【免费下载链接】GraphiteCommunity-built comprehensive 2D content creation appplication for graphic design, digital art, and interactive real-time motion graphics powered by a node-based procedural graphics engine项目地址: https://gitcode.com/GitHub_Trending/gr/Graphite在 Graphite 中编辑器里能拖进节点图的每个节点比如 Add、Mirror、Math都不是手写的 UI 配置而是一个普通的 Rust 函数加上#[node_macro::node]属性。按照 node-graph/README.md 的说法这个宏会自动为你生成节点结构体、Nodetrait 实现、node_registry条目、文档节点定义document node definition以及属性面板条目。你只需要把函数写进node-graph/nodes/下的某个节点 crate例如math、graphic、gstd编译通过后节点就会自动注册并出现在节点的分类目录node catalog中。本文的目标任务用一个node宏定义一个新节点让它带上类别category、参数默认值#[default]和滑杆#[range]#[soft]/#[hard]并给出编译期与运行时的核对方式。适用环境是本仓库的 Rust 工作区无需额外依赖或环境配置。宏写在哪里它会生成什么节点实现的实际位置是各节点 crate例如node-graph/nodes/math/src/lib.rs算术类节点node-graph/nodes/graphic/src/graphic.rsMirror等图形节点node-graph/nodes/gstd/src/text.rs文本节点宏本体在 node-graph/node-macro/src/lib.rs它解析函数签名并在 node-graph/node-macro/src/codegen.rs 中做代码生成。宏生成内容的对应关系见 codegen.rs结构体名为函数名的 PascalCase 再加Node后缀scale_value→ScaleValueNode显示名默认取结构体名的 Title Case可用节点级name(...)覆盖参数名在 UI 中默认取 Title Case参数上带下划线前缀_xxx的字段会从图中隐藏注册是自动的codegen 中的注释写明原生平台上register_node与register_metadata通过#[ctor]在启动时自动执行Wasm 平台上由一个extern C函数从 JS 侧调用。也就是说写完函数、编译通过不需要手工登记。带类别、默认值与滑杆的节点定义按宏自己的测试用例node-graph/node-macro/src/parsing.rs 中test_node_with_default_values与test_number_min_max_range_mode的写法拼出的最小定义如下可作为起点// 放在 node-graph/nodes/ 下任一节点 crate 中需要能引用 Ctx // 参考 node-graph/nodes/math/src/lib.rs 顶部的 use core_types::{Ctx, ...}; #[node_macro::node(category(General))] fn scale_value( _: impl Ctx, /// 参数说明文字。 #[default(50.)] #[range] #[soft(0..100)] #[hard(0..100)] value: f64, ) - f64 { value }逐个说明这些写法全部有文档或源码依据第一个参数是节点的输入call argument不是参数。它不能带#[default]或#[expose]否则宏报 Call argument cannot be given a default value / Call argument cannot be exposed。仓库中现有的节点如 math crate 的add第一个参数写作_: impl Ctx。#[default(50.)]该参数的默认值。README Properties panel 一节说明节点刚创建、或某条连线被断开时输入取的就是这个默认值。#[range]把数字输入渲染成可拖动的滑杆slider而不是默认的数字增减框。#[soft(0..100)]滑杆的建议范围suggested extent。#[hard(0..100)]强制钳制范围enforced clamp。README 明确指出手动键入的值可以超出 soft 范围但会被钳制在 hard 范围内因此#[soft]只在配合#[range]时才有意义。category(General)节点级属性决定节点在 node catalog 中的分类且必填——缺省会被宏拒绝The attribute category is required.。范围写法有两个容易踩的点parsing.rs 中的NumberRange解析逻辑端点可以省略即0..或..100都是合法的两端都是闭区间所以没有..形式写成0..100会报错 use..rather than..for number bounds。仓库中真实节点的对照带滑杆的真实例子是 node-graph/nodes/graphic/src/graphic.rs 中的mirror节点其签名节选#[node_macro::node(category(General))] async fn mirrorT: BoundingBox n Send Clone( _: impl Ctx, #[implementations(Graphic, Vector, RasterCPU, RasterGPU, Color, Gradient, String)] content: ItemT, #[default(ReferencePoint::Center)] relative_to_bounds: ItemReferencePoint, #[unit( px)] offset: Itemf64, #[range] #[soft(-90..90)] angle: ItemAngle, #[default(true)] keep_original: Itembool, ) - ListT { /* ... */ }这里同时演示了默认值ReferencePoint::Center、true、滑杆angle的#[range] #[soft(-90..90)]、单位#[unit( px)]与类别。默认值不限于数字node-graph/nodes/math/src/lib.rs 的math节点用了字符串默认值#[default(A B)] expression: ItemString。其他可用的参数属性parsing.rs 中parse_field支持的字段级属性与本场景相关的部分属性作用依据 parsing.rs 注释与代码#[name(...)]覆盖该参数在 UI 中的名称默认取参数名的 Title Case#[unit( px)]数字输入的显示单位#[step(0.1)]数字输入的步进参考 node-graph/nodes/gstd/src/text.rs#[display_decimal_places(2)]小数位显示位数#[expose]默认在节点图中以圆点形式暴露该输入#[implementations(f64, f32, ...)]参数支持的类型组合自动生成对应实现#[hard(1..)]只写一端边界的用法如 text 节点的字号size节点级属性写在#[node_macro::node(...)]内中path(...)可覆盖 Graphene 用来定位实现的完全限定路径不写时从模块路径和函数名推断每个参数上方的 doc 注释会被宏收集为参数描述文本。编译期核对宏会直接报出的错误node宏在编译期做解析与校验以下错误字符串全部来自 node-graph/node-macro/src/parsing.rs编译后可以直接对照判断是自己写错了哪一行触发写法编译期报错原文摘录漏写category(...)The attribute category is required.写了两个categoryMultiple category attributes are not allowed第一个参数带#[default]Call argument cannot be given a default value#[soft()]等空范围expected a range like0..100,..100, or0..#[soft(0..100)]use..rather than..for number bounds整型参数的边界写成了浮点字面量... is a float literal, but ... is an integer type. Use an integer literal without a decimal point.impl Node参数带默认值No default values forimpl Nodeallowed同一参数同时写default与scopeCannot have bothdefaultandscopeattributes使用未知节点级属性Unsupported attribute innode.报错信息中列出全部支持项用cargo check或整体构建编译对应 crate 时这些报错会直接指向出错的参数位置。这一步是本流程的主验证手段滑杆范围、默认值、类别是否写对编译器会明确告诉你。在编辑器里验证与调试编译通过后运行时核对点有三个node catalog节点应出现在你写的category分类下。前端目录 UI 见 NodeCatalog.svelte。注意源码注释写明空字符串category()会把节点从 catalog 中隐藏所以测试期不要误用。属性面板选中节点后#[default]的值就是节点刚创建时的输入值连线断开时同样回落到默认值#[range]的参数显示为滑杆#[soft]决定滑杆长度键入超出 soft 的值会被钳制到 hard 边界——这三点都可以在面板上直接观察。调试日志README Debugging 一节说明节点内部可以用log::debug!()打印例如文档给出的示例log::debug!(The opacity is {opacity_multiplier});。如果想对节点计算结果本身做断言README 给出了用#[test]直接构造节点并检查eval输出的文档示例文档示例针对手动实现的OpacityNode#[test] fn test_opacity_node() { let opacity_node OpacityNode { opacity_multiplier: crate::value::CopiedNode(10_f64), // set opacity to 10% }; assert_eq!(opacity_node.eval(Color::WHITE), Color::from_rgbaf32_unchecked(1., 1., 1., 0.1)); }其中CopiedNode是文档提到的取值节点求值时复制给定常量并返回。宏生成的节点结构体字段是泛型节点槽该测试模式更直接地适用于手动实现Nodetrait 的节点宏节点的验证以编译期报错 编辑器行为为主。限制与文档不一致处#[soft]离开#[range]没有意义范围两端闭区间、无..形式端点可省略0../..100。第一个参数节点输入永远不能带默认值impl Node类型的参数也不能带默认值。README Additional Macro Options 一节列出的节点级属性只有name、path、skip_impl、category四个而宏源码的报错信息列出的完整集合还包括properties、cfg、shader_node、serialize、memoize、inject_scope。两处不一致以宏源码parsing.rs 中NodeFnAttributes的解析分支为准。#[data]字段节点内部状态不能带#[default]会自动用Default::default()初始化也不能#[expose]。完成上述步骤后的可核对结果cargo check无宏报错节点在 catalog 的指定分类下可检索属性面板中默认值与滑杆行为soft 范围、hard 钳制与声明一致。再往下README 也承认创建节点涉及许多文件与概念如需扩展 GPU 实现等更复杂的能力参考同 crate 中现有节点如带#[unit]、#[step]的 text 节点是最直接的路径。【免费下载链接】GraphiteCommunity-built comprehensive 2D content creation appplication for graphic design, digital art, and interactive real-time motion graphics powered by a node-based procedural graphics engine项目地址: https://gitcode.com/GitHub_Trending/gr/Graphite创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考