先建立整体图景:卡片和数据流怎么运作、为什么值得二次开发。
遇到特殊的计算逻辑、专属的数据处理,找不到对应卡片就卡住。
把自己的算法封装成卡片,像积木一样复用到任意工作流中。
麻雀虽小五脏俱全 —— 走通这一张卡片,你就掌握了所有自定义卡片的骨架。
看清“自定义卡片到底是什么”:一个类库、两个依赖、四个抽象成员、一套加载机制。
跟着一步步敲代码:新建项目 → 加引用 → 继承实现 → 写核心逻辑。
using ProjectPenguin.Cards;
public class Class1 : ProcessorCardBase
{
public Class1() : base(
"基本名称", // 画布中显示
"缩写", // 太长时用
"描述信息", // 悬停提示
"大类", // 分类
"子类")
{
}
}
public override Guid
CardGuid =>
Guid.Parse(
"{95FAD3CB-…}");
helper. AddWellKnownType OfDataCard( typeof(string), "出口","出口", "描述…", DataProcessingMode .OneByOne);
public override
void Build(
IDataDelivery idd)
{
idd.SetDataItem(
0,
"Hello, world!");
}
Copy "$(TargetPath)" "C:\Users\<用户名>\AppData\Roaming \nonstructure\Penguin\Cards\<你的工程名>.crd"
看到输出的这一刻,你已经完整走通了自定义卡片的全流程。
DataProcessingMode.OneByOne 是什么含义?多端口如何编号?
关注官方公众号与《二次开发指南》,加入交流群一起玩。
F:\repos\GamaCardDemo\
├─ GamaCardDemo.csproj SDK · net472
├─ TwoNumberAdditionCard.cs 卡片类
└─ bin\Debug\
└─ GamaCardDemo.dll 编译产物
%AppData%\nonstructure\Penguin\Cards\
└─ GamaCardDemo.crd 生成后自动复制
using System;
using ProjectPenguin.Cards;
using ProjectPenguin.Cards.Enums;
using ProjectPenguin.Cards.ProcessorCardHelpers;
namespace GamaCardDemo;
public class TwoNumberAdditionCard : ProcessorCardBase
{
public TwoNumberAdditionCard()
: base("两数相加","相加","计算 A + B","数学","数学运算符") { }
public override string EnglishAlias => "Add Two Numbers";
private static readonly Guid sc_guid =
Guid.Parse("{344AD618-F33D-48C4-8E77-68B8BA49383C}");
public override Guid CardGuid => sc_guid;
protected override void AddInputSideDataCards(IDataCardEmbedmentHelper h) {
h.AddWellKnownTypeOfDataCard(typeof(double),"第一个数","A","加数A",DataProcessingMode.OneByOne);
h.AddWellKnownTypeOfDataCard(typeof(double),"第二个数","B","加数B",DataProcessingMode.OneByOne);
}
protected override void AddOutputSideDataCards(IDataCardEmbedmentHelper h) {
h.AddWellKnownTypeOfDataCard(typeof(double),"结果","结果","A + B",DataProcessingMode.OneByOne);
}
public override void Build(IDataDelivery idd) {
double a = 0, b = 0;
if (!idd.GetDataItem(0, ref a)) return;
if (!idd.GetDataItem(1, ref b)) return;
idd.SetDataItem(0, a + b);
}
}
using System;
using System.Collections.Generic;
using ProjectPenguin.Cards;
using ProjectPenguin.Cards.Enums;
using ProjectPenguin.Cards.ProcessorCardHelpers;
using NSGeo.Geometry;
namespace GamaCardDemo;
public class TrussCard : ProcessorCardBase
{
public TrussCard() : base("带斜撑桁架","桁架",
"在 XZ 平面生成带斜撑的桁架直线","直线和曲线","结构生成") { }
public override string EnglishAlias => "Braced Truss";
private static readonly Guid sc_guid =
Guid.Parse("{BC7783E8-AC26-4F55-BA90-EE7B3DCC0613}");
public override Guid CardGuid => sc_guid;
// 三个输入端口:高度 / 总长 / 分割长度(OneByOne)
protected override void AddInputSideDataCards(IDataCardEmbedmentHelper h) {
h.AddWellKnownTypeOfDataCard(typeof(double),"高度","高度","桁架高度Z",DataProcessingMode.OneByOne);
h.AddWellKnownTypeOfDataCard(typeof(double),"总长","总长","桁架总长X",DataProcessingMode.OneByOne);
h.AddWellKnownTypeOfDataCard(typeof(double),"分割长度","分割","每节间目标长度",DataProcessingMode.OneByOne);
}
// 输出:构成桁架的所有直线(一整列)
protected override void AddOutputSideDataCards(IDataCardEmbedmentHelper h) {
h.AddWellKnownTypeOfDataCard(typeof(Line),"直线集合","直线","桁架的所有直线",DataProcessingMode.ListByList);
}
public override void Build(IDataDelivery idd) {
double height = 0, totalLength = 0, segmentLength = 0;
if (!idd.GetDataItem(0, ref height)) return;
if (!idd.GetDataItem(1, ref totalLength)) return;
if (!idd.GetDataItem(2, ref segmentLength)) return;
if (height <= 0 || totalLength <= 0 || segmentLength <= 0) {
LogMessage(BuildLogLevel.Warning,"三个参数都必须为正数"); return;
}
// 均分为整数节间,避免残缺节间
int n = (int)Math.Round(totalLength / segmentLength);
if (n < 1) n = 1;
double step = totalLength / n;
var bottom = new Point3d[n + 1];
var top = new Point3d[n + 1];
for (int i = 0; i <= n; i++) {
double x = i * step;
bottom[i] = new Point3d(x, 0, 0); // XZ 平面 → y = 0
top[i] = new Point3d(x, 0, height);
}
var lines = new List<Line>();
for (int i = 0; i < n; i++) { // 上下弦
lines.Add(new Line(bottom[i], bottom[i + 1]));
lines.Add(new Line(top[i], top[i + 1]));
}
for (int i = 0; i <= n; i++) // 竖杆(含两端)
lines.Add(new Line(bottom[i], top[i]));
for (int i = 0; i < n; i++) // 斜撑:下弦左→上弦右
lines.Add(new Line(bottom[i], top[i + 1]));
idd.SetDataList(0, lines); // 一次性写出整列直线
}
}