3DMultiple 3D editorsThree.jsPlugin
This guide outlines how to incorporate the node editor into a 3D scene. It can be achieved by rete-area-3d-plugin
, which substitutes the standard rete-area-plugin
.
Powered by Three.js, this plugin creates a scene that contains a camera and two renderers - CSS3DRenderer
and WebGLRenderer
. Consequently, 3D objects and native HTML elements are rendered together in a single viewport, enabling overlapping. The primary advantage of utilizing native elements (as opposed to rendering to texture) is the preservation of full interactivity.
Prior to using this plugin, three
peer dependency must be installed separately.
npm i rete-area-3d-plugin three @types/three
If you have followed the basic guide, you will need to replace the initialization of Area2DPlugin with Area3DPlugin and change some type definitions.
import { Area3D, Area3DPlugin } from 'rete-area-3d-plugin';
type AreaExtra =
| Area3D<Schemes>
const area = new Area3DPlugin<Schemes, AreaExtra>(container);
editor.use(area);
Consequently, the container will incorporate both the <canvas>
element and a container for HTML elements that undergo 3D transformation.
In case your editor has nodes, you can see them in the viewport, but they will not be interactive. To provide visual feedback for node interaction, it should be part of an animation loop and be linked to Object3D
, which is directly responsible for dragging.
Area3DExtensions.animate(area)
This extension adopts the typical three.js approach to animation loops, utilizing the render()
function along with the requestAnimationFrame()
.
Additionally, we need to link our nodes and connections with the geometry in the 3D scene to allow for interactive functionality and prevent unwanted overlapping with other objects.
Area3DExtensions.forms.connection(render);
Area3DExtensions.forms.node(area);
During rendering, these extensions produce geometry that accurately replicates the form of nodes and connections.
Now you can interact with the nodes and rotate or move the camera around them. Check out the complete result on the 3D example page.
Some extensions available in the rete-area-plugin
can be utilized solely within the editor, disregarding the viewport and similar factors.
import { AreaExtensions } from 'rete-area-plugin'
AreaExtensions.showInputControl(area)
AreaExtensions.simpleNodesOrder(area)
AreaExtensions.snapGrid(area, { size: 30 })
AreaExtensions.selectableNodes(area, AreaExtensions.selector(), { accumulating: AreaExtensions.accumulateOnCtrl() });
In this plugin, the following extensions are available:
import { Area3DExtensions } from 'rete-area-3d-plugin'
Area3DExtensions.forms.comment(area) // creates geometry for comments plugin
Area3DExtensions.forms.reroute(area) // creates geometry for reroute plugin
Area3DExtensions.lookAt(area, editor.getNodes()) // alternative to zoomAt from rete-area-plugin
As previously stated, this plugin creates a scene complete with camera and renderers. To access them, you can use the following code:
const { scene } = area.area
scene.root // three.js' Scene
scene.camera // PerspectiveCamera
scene.renderer.css3d // CSS3DRenderer
scene.renderer.webgl // WebGLRenderer
scene.orbit // OrbitControls
For instance, you have the option to deactivate orbital control (scene.orbit.enabled = false
) and add an alternative one, or adjust the settings of renderers or camera.
You can add 3D objects by accessing the scene.root
, which is a Scene
instance in Three.js.
If you want to include HTML elements within the scene, specifically within the editor's canvas, use the following code:
area.area.content.add(element)
An HTML element will be added to the editor canvas at position zero. To ensure it doesn't overlap with other scene elements, it should have geometry that mirrors its form.
area.area.content.updateGeometry(element, bufferGeometry)
Check out more examples in the source code
With regard to other HTML elements, it will maintain its own order, and you can modify it as follows:
area.area.content.reorder(element, nextElement)
Removing element:
area.area.content.remove(element)
In case you have customized your nodes or connections, you might discover that they don't match the placeholder in the 3D scene. To adapt them to new forms, you can either implement your own geometry or reuse existing with various arguments.
Example of modifying the border radius of a node:
Area3DExtensions.forms.node(area, {
customize(node) {
return Area3DExtensions.forms.createClassicNodeGeometry(node, {
borderRadius: 0
})
}
})
Example of a connection geometry featuring increased width:
Area3DExtensions.forms.connection(reactRender, {
customize(path) {
return Area3DExtensions.forms.createClassicConnectionGeometry(path, 10)
}
})
Additionally, the plugin offers the capability to include several editors in a single scene. You can achieve this by creating a main Area3DPlugin
instance and sharing it with other editors.
const mainEditor = new NodeEditor<Schemes>();
const mainArea = new Area3DPlugin<Schemes, AreaExtra>(container)
mainEditor.use(mainArea)
const secondaryEditor = new NodeEditor<Schemes>();
const secondaryArea = mainArea.share()
secondaryEditor.use(secondaryArea)
Within a certain scene, you'll encounter two editors, placed in the same plane and overlapping each other. To separate them, you can change the position and orientation of the second editor.
const canvas = secondaryArea.area.getCanvas()
canvas.rotateY(Math.PI / 2)
canvas.get(sharedArea)?.translateX(500)
Check out the complete result on the Multiple 3D editors example page.