bt-editor
v0.1.3
Published
A browser-based Behavior Tree editor inspired by Groot2, built with Vite, React, and TypeScript.
Readme
bt-editor
A browser-based Behavior Tree editor inspired by Groot2, built with Vite, React, and TypeScript.
The project provides two delivery modes:
- Standalone web editor for direct browser use
- Embeddable
BTEditorReact component for integration into other applications
It targets BehaviorTree.CPP XML workflows (BTCPP_format="3" and BTCPP_format="4") and runs fully on the client side.
What's New (Current Main)
Recent updates focused on practical editing speed, XML workflow improvements, and integration readiness:
- Dual delivery mode maintained and published as
bt-editor - XML format switch (
v3/v4) in toolbar, with safety lock once tree content exists - Live XML panel upgraded with:
- Per-tab preview mode and full-project main-tree mode
- Copy, inline edit, XML validation, and save-back workflow
- Resizable + collapsible panel behavior
- Improved subtree workflow:
- Better subtree drag/move interactions (Ctrl/Alt drag)
- SubTree references generated from project trees in palette
- SubTree target editing and auto-remap support
- Better layout readability with auto-layout and beautify-style compaction
- Favorites panel for reusable node templates and quick drag-back to canvas
- Readonly/view mode for model inspection from node palette
- PNG export from toolbar for quick sharing/review
- Live debug connection (Groot2 bridge) + log replay tooling in one panel
- Missing node model importer flow after XML import
Feature Overview
Canvas and Editing
- GRoot2-style drag-and-drop node editing
- Connect nodes through typed handles with rule validation
- Double-click node editing (instance-level fields, ports, conditions)
- Node picker and node search for quick insertion at cursor/drop position
Multi-Tree Management
- Create, rename, switch, and delete trees
- Main-tree designation and tree tabs for parallel editing
- SubTree reference workflow across trees
XML Workflow
- Import BehaviorTree.CPP XML projects
- Export XML from the current project
- Toggle XML target format (
v3orv4) - Live XML preview with local/main mode switch
- Edit XML in place with parse validation before apply
Debug and Replay
- Replay text/JSON logs to visualize node status transitions
- Step/play through timeline and inspect current entry details
- Connect to runtime through Groot2 bridge (
ws://) for live status updates
UX and Productivity
- Light/dark theme toggle
- English/Chinese language toggle
- Keyboard shortcuts help panel
- Favorites, model search/filter, and import-assist dialogs
Quick Start
Prerequisites
- Node.js 20+
- pnpm 10+
Install
pnpm installRun standalone editor
pnpm devOpen the URL printed by Vite (typically http://localhost:5173).
Build
Build standalone web app
pnpm build:webBuild embeddable library
pnpm build:libBuild both
pnpm buildUse as a React Component
Install the package in your host app and render BTEditor inside a sized container.
import { BTEditor } from "bt-editor";
export function Example() {
return (
<div style={{ width: 960, height: 640 }}>
<BTEditor storageKey="bt-editor-demo" />
</div>
);
}Notes:
BTEditorfills the parent container, so parent width/height are requiredstorageKeyisolates persisted editor state between instances- Library output externalizes
react,react-dom, andreact/jsx-runtime
Integration API (MVP)
BTEditor now supports controlled/uncontrolled project state, readonly mode, feature flags, adapter injection, callbacks, and an imperative ref API.
import { useRef, useState } from 'react';
import { BTEditor, type BTEditorRef, type BTProject } from 'bt-editor';
export function Host() {
const editorRef = useRef<BTEditorRef>(null);
const [project, setProject] = useState<BTProject | undefined>(undefined);
return (
<div style={{ width: 1100, height: 700 }}>
<BTEditor
ref={editorRef}
value={project}
mode="edit"
features={{ treeTabs: true, importExport: true, pngExport: true }}
onChange={(next, ctx) => {
// ctx.origin: 'user' | 'api' | 'import' | 'system'
setProject(next);
}}
onTreeChange={(action, ctx) => {
// action.type includes add-tree / rename-tree / set-main-tree / tab actions
console.log(action.type, action.treeId, ctx.origin);
}}
onReady={(api) => {
// Imperative APIs: getProject/setProject/importXml/exportXml/undo/redo/getState
editorRef.current = api;
}}
/>
</div>
);
}Adapters
Use adapters to integrate host-side storage, notifications, clipboard, and logging behavior.
<BTEditor
adapters={{
storageAdapter: {
getItem: (k) => sessionStorage.getItem(k),
setItem: (k, v) => sessionStorage.setItem(k, v),
removeItem: (k) => sessionStorage.removeItem(k),
},
notifyAdapter: {
alert: (msg) => myToast.error(msg),
confirm: (msg) => window.confirm(msg),
},
clipboardAdapter: {
writeText: (text) => navigator.clipboard.writeText(text),
},
loggerAdapter: {
info: (msg, ...args) => console.info(msg, ...args),
warn: (msg, ...args) => console.warn(msg, ...args),
error: (msg, ...args) => console.error(msg, ...args),
},
}}
/>Readonly Behavior
- In
mode="readonly", model/tree/canvas mutations are blocked. - Navigation behavior remains available (for example, opening referenced SubTrees).
- Child components receive readonly state through integration context for consistent UI disabling.
Debug Log Format
One entry per line:
<timestamp_ms> <nodeUid> <nodeType> <nodeName> <STATUS> [treeId]Example:
0 1 Sequence Root RUNNING MainTree
10 2 Condition CheckBattery SUCCESS MainTree
20 3 Action MoveToGoal RUNNING MainTreeSupported statuses: IDLE, RUNNING, SUCCESS, FAILURE
Scripts
| Script | Description |
| ---------------- | --------------------------------- |
| pnpm dev | Start the Vite development server |
| pnpm build:web | Build the standalone web app |
| pnpm build:lib | Build the component library |
| pnpm build | Build both outputs |
| pnpm lint | Run ESLint |
| pnpm test | Start Vitest |
| pnpm test:run | Run Vitest once |
| pnpm test:e2e | Run Playwright end-to-end tests |
| pnpm preview | Preview production web build |
Tech Stack
- React 19
- TypeScript
- Vite
@xyflow/reactfor graph rendering- Zustand for state management
@dagrejs/dagrefor layout- i18next for localization
- Vitest + Playwright for tests
Documentation
See the docs/ folder for architecture and implementation details:
docs/ARCHITECTURE.mddocs/DEVELOPER_GUIDE.mddocs/CHANGELOG.mddocs/NODE_EDITING.mddocs/GRoot2_NODE_EDITING.md
Status
Current package version: 0.1.2
This README describes the current main branch behavior.
