МодуліСтруктури даних3D Конфігуратор
З коробки редактор може обробляти будь-які об’єкти JS як вузли та з’єднання, за умови, що вони містять обов’язкове поле «id» для обох. Крім того, з’єднання повинні мати поля source
та target
. Ці об’єкти можуть бути як звичайними об’єктами з даними, так і об’єктами, що містять методи. Докладніше див. у гайді Структури даних.
Поточна версія редактора не підтримує імпорт/експорт за замовчуванням через деякі обмеження:
Припустімо, у нас є простий приклад, де вузол є дійсним JSON об’єктом
import { NodeEditor, BaseSchemes, getUID } from 'rete'
const editor = new NodeEditor<BaseSchemes>()
const node = { id: getUID(), label: 'Label' }
await editor.addNode(node)
У цьому випадку ми можемо легко експортувати такі вузли в JSON, щоб зберегти їх, наприклад, у базі даних.
Об’єкти, які не є дійсними JSON, наприклад екземпляри класів, об’єкти з функціями або об’єкти з циклічними посиланнями, можуть бути викликом. Відмова від них означала б втрату переваг використання JS.
Наприклад, класи вузлів можна використовувати для створення вузлів, що забезпечує більш надійну та зручну взаємодію за допомогою методів і забезпечує гнучкість використання різних парадигм.
import { ClassicPreset } from 'rete'
const node = new ClassicPreset.Node('Label')
node.addOutput('port', new ClassicPreset.Output(socket, 'Label'))
await editor.addNode(node)
Хоча серіалізація та десеріалізація можуть бути одним із способів перетворення таких об’єктів на дійсні JSON, цей підхід може не працювати в складних сценаріях.
Якщо ви хочете експортувати граф, ви можете використовувати наступний код як довідник. Зверніть увагу, що це не повністю функціональний код, а наближений, який допоможе вам реалізувати власні функції імпорту/експорту відповідно до ваших конкретних вимог.
const data = { nodes: [] }
const nodes = editor.getNodes()
for (const node of nodes) {
data.nodes.push({
id: node.id,
label: node.label,
inputs: /// ....
controls: /// ....
outputs: /// ....
})
}
Щоб зробити зворотну трансформацію, ми повинні ініціалізувати екземпляри вузлів, входи, виходи та контроли на основі наданих об’єктів.
for (const { id, label, inputs, outputs, controls } of data.nodes) {
const node = new ClassicPreset.Node(label);
node.id = id;
/// ... inputs
/// ... controls
/// ... outputs
await editor.addNode(node)
}
Повний приклад можна знайти за посиланням. Зверніть увагу, що цей приклад було спрощено для зручності розуміння.
Крім того, імпорт або експорт входів і виходів може не завжди бути необхідним, якщо вони статичні, і ми знаємо тип вузла. У таких випадках ми можемо просто зберегти назву вузла та відповідні дані, які можна використовувати для створення екземплярів вузлів із заздалегідь визначеними портами. Перегляньте приклади 3D Конфігуратор і Модулі з реалізацією цього підходу.
Іншою проблемою під час імпорту графа може бути порядок, у якому необхідно імпортувати вузли. У простих випадках порядок буде таким же, як і порядок, у якому вони були додані до редактора.
const graph = /// завантажений з БД дійсний JSON об’єкт
for (const node of graph.nodes) {
await editor.addNode(node)
}
При роботі зі складнішими графами порядок додавання вузлів може змінюватися. Наприклад, у графі з вкладеними вузлами може знадобитися додати батьківські вузли перед дочірніми. Крім того, цілком можливо, що користувач може створити дочірній вузол перед його батьківським вузлом під час роботи в редакторі.
Давайте подивимося на приклад імпортування графа, де певні вузли мають поле parent
, що вказує на їх зв’язок з іншим вузлом. У результаті ці вузли потрібно імпортувати після того, як їх батьківський вузол буде створено.
async function importForParent(nodes, parent = undefined) {
const nodes = nodes.filter(node => node.parent === parent)
for (const node of nodes) {
await editor.addNode(node)
await importForParent(nodes, node.id)
}
}
const graph = /// завантажений з БД дійсний JSON об’єкт
await importForParent(graph.nodes)
Оскільки цей підхід складніший і існує кілька способів його виконання, метод імпорту буде різним залежно від конкретного випадку використання.