@thanhthbm/scene-editor 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +169 -0
- package/dist/index.css +921 -0
- package/dist/index.js +14076 -0
- package/package.json +49 -0
- package/src/editor/css/main.css +1030 -0
- package/src/editor/js/Animation.js +618 -0
- package/src/editor/js/AnimationResizer.js +73 -0
- package/src/editor/js/Command.js +40 -0
- package/src/editor/js/Config.js +86 -0
- package/src/editor/js/Editor.js +1006 -0
- package/src/editor/js/EditorControls.js +489 -0
- package/src/editor/js/GLTFImportDialog.js +112 -0
- package/src/editor/js/History.js +321 -0
- package/src/editor/js/Loader.js +1162 -0
- package/src/editor/js/LoaderUtils.js +90 -0
- package/src/editor/js/Menubar.Add.js +559 -0
- package/src/editor/js/Menubar.Edit.js +155 -0
- package/src/editor/js/Menubar.File.js +585 -0
- package/src/editor/js/Menubar.Help.js +73 -0
- package/src/editor/js/Menubar.Render.js +858 -0
- package/src/editor/js/Menubar.Status.js +51 -0
- package/src/editor/js/Menubar.View.js +193 -0
- package/src/editor/js/Menubar.js +29 -0
- package/src/editor/js/Player.js +53 -0
- package/src/editor/js/Resizer.js +65 -0
- package/src/editor/js/Script.js +532 -0
- package/src/editor/js/Selector.js +129 -0
- package/src/editor/js/Sidebar.Geometry.BoxGeometry.js +121 -0
- package/src/editor/js/Sidebar.Geometry.BufferGeometry.js +124 -0
- package/src/editor/js/Sidebar.Geometry.CapsuleGeometry.js +109 -0
- package/src/editor/js/Sidebar.Geometry.CircleGeometry.js +97 -0
- package/src/editor/js/Sidebar.Geometry.CylinderGeometry.js +121 -0
- package/src/editor/js/Sidebar.Geometry.DodecahedronGeometry.js +73 -0
- package/src/editor/js/Sidebar.Geometry.ExtrudeGeometry.js +196 -0
- package/src/editor/js/Sidebar.Geometry.IcosahedronGeometry.js +73 -0
- package/src/editor/js/Sidebar.Geometry.LatheGeometry.js +98 -0
- package/src/editor/js/Sidebar.Geometry.Modifiers.js +73 -0
- package/src/editor/js/Sidebar.Geometry.OctahedronGeometry.js +74 -0
- package/src/editor/js/Sidebar.Geometry.PlaneGeometry.js +97 -0
- package/src/editor/js/Sidebar.Geometry.RingGeometry.js +121 -0
- package/src/editor/js/Sidebar.Geometry.ShapeGeometry.js +76 -0
- package/src/editor/js/Sidebar.Geometry.SphereGeometry.js +133 -0
- package/src/editor/js/Sidebar.Geometry.TetrahedronGeometry.js +74 -0
- package/src/editor/js/Sidebar.Geometry.TextGeometry.js +136 -0
- package/src/editor/js/Sidebar.Geometry.TorusGeometry.js +109 -0
- package/src/editor/js/Sidebar.Geometry.TorusKnotGeometry.js +121 -0
- package/src/editor/js/Sidebar.Geometry.TubeGeometry.js +135 -0
- package/src/editor/js/Sidebar.Geometry.js +471 -0
- package/src/editor/js/Sidebar.Material.BooleanProperty.js +60 -0
- package/src/editor/js/Sidebar.Material.ColorProperty.js +87 -0
- package/src/editor/js/Sidebar.Material.ConstantProperty.js +62 -0
- package/src/editor/js/Sidebar.Material.MapProperty.js +277 -0
- package/src/editor/js/Sidebar.Material.NumberProperty.js +60 -0
- package/src/editor/js/Sidebar.Material.Program.js +73 -0
- package/src/editor/js/Sidebar.Material.RangeValueProperty.js +63 -0
- package/src/editor/js/Sidebar.Material.js +751 -0
- package/src/editor/js/Sidebar.Object.js +892 -0
- package/src/editor/js/Sidebar.Project.App.js +218 -0
- package/src/editor/js/Sidebar.Project.Materials.js +82 -0
- package/src/editor/js/Sidebar.Project.Renderer.js +193 -0
- package/src/editor/js/Sidebar.Project.Resources.js +242 -0
- package/src/editor/js/Sidebar.Project.js +21 -0
- package/src/editor/js/Sidebar.Properties.js +73 -0
- package/src/editor/js/Sidebar.Scene.js +643 -0
- package/src/editor/js/Sidebar.Script.js +129 -0
- package/src/editor/js/Sidebar.Settings.History.js +146 -0
- package/src/editor/js/Sidebar.Settings.Shortcuts.js +198 -0
- package/src/editor/js/Sidebar.Settings.js +58 -0
- package/src/editor/js/Sidebar.js +41 -0
- package/src/editor/js/Storage.js +98 -0
- package/src/editor/js/Strings.js +2718 -0
- package/src/editor/js/TextureParametersDialog.js +293 -0
- package/src/editor/js/Toolbar.js +75 -0
- package/src/editor/js/Viewport.Controls.js +98 -0
- package/src/editor/js/Viewport.Info.js +144 -0
- package/src/editor/js/Viewport.Pathtracer.js +27 -0
- package/src/editor/js/Viewport.ViewHelper.js +41 -0
- package/src/editor/js/Viewport.XR.js +7 -0
- package/src/editor/js/Viewport.js +982 -0
- package/src/editor/js/commands/AddObjectCommand.js +68 -0
- package/src/editor/js/commands/AddScriptCommand.js +75 -0
- package/src/editor/js/commands/Commands.js +24 -0
- package/src/editor/js/commands/MoveObjectCommand.js +117 -0
- package/src/editor/js/commands/MultiCmdsCommand.js +85 -0
- package/src/editor/js/commands/RemoveObjectCommand.js +88 -0
- package/src/editor/js/commands/RemoveScriptCommand.js +81 -0
- package/src/editor/js/commands/SetColorCommand.js +73 -0
- package/src/editor/js/commands/SetGeometryCommand.js +86 -0
- package/src/editor/js/commands/SetGeometryValueCommand.js +70 -0
- package/src/editor/js/commands/SetMaterialColorCommand.js +87 -0
- package/src/editor/js/commands/SetMaterialCommand.js +80 -0
- package/src/editor/js/commands/SetMaterialMapCommand.js +144 -0
- package/src/editor/js/commands/SetMaterialRangeCommand.js +92 -0
- package/src/editor/js/commands/SetMaterialValueCommand.js +91 -0
- package/src/editor/js/commands/SetMaterialVectorCommand.js +88 -0
- package/src/editor/js/commands/SetPositionCommand.js +84 -0
- package/src/editor/js/commands/SetRotationCommand.js +84 -0
- package/src/editor/js/commands/SetScaleCommand.js +84 -0
- package/src/editor/js/commands/SetSceneCommand.js +104 -0
- package/src/editor/js/commands/SetScriptValueCommand.js +80 -0
- package/src/editor/js/commands/SetShadowValueCommand.js +73 -0
- package/src/editor/js/commands/SetTextureParametersCommand.js +143 -0
- package/src/editor/js/commands/SetUuidCommand.js +70 -0
- package/src/editor/js/commands/SetValueCommand.js +75 -0
- package/src/editor/js/libs/acorn/acorn.js +3236 -0
- package/src/editor/js/libs/acorn/acorn_loose.js +1299 -0
- package/src/editor/js/libs/acorn/walk.js +344 -0
- package/src/editor/js/libs/app/index.html +51 -0
- package/src/editor/js/libs/app.js +14 -0
- package/src/editor/js/libs/codemirror/addon/dialog.css +32 -0
- package/src/editor/js/libs/codemirror/addon/dialog.js +163 -0
- package/src/editor/js/libs/codemirror/addon/show-hint.css +36 -0
- package/src/editor/js/libs/codemirror/addon/show-hint.js +529 -0
- package/src/editor/js/libs/codemirror/addon/tern.css +87 -0
- package/src/editor/js/libs/codemirror/addon/tern.js +750 -0
- package/src/editor/js/libs/codemirror/codemirror.css +344 -0
- package/src/editor/js/libs/codemirror/codemirror.js +9849 -0
- package/src/editor/js/libs/codemirror/mode/glsl.js +233 -0
- package/src/editor/js/libs/codemirror/mode/javascript.js +959 -0
- package/src/editor/js/libs/codemirror/theme/monokai.css +41 -0
- package/src/editor/js/libs/esprima.js +6401 -0
- package/src/editor/js/libs/jsonlint.js +453 -0
- package/src/editor/js/libs/signals.min.js +14 -0
- package/src/editor/js/libs/tern-threejs/build-defs.js +233 -0
- package/src/editor/js/libs/ternjs/comment.js +87 -0
- package/src/editor/js/libs/ternjs/def.js +588 -0
- package/src/editor/js/libs/ternjs/doc_comment.js +401 -0
- package/src/editor/js/libs/ternjs/infer.js +1635 -0
- package/src/editor/js/libs/ternjs/polyfill.js +80 -0
- package/src/editor/js/libs/ternjs/signal.js +26 -0
- package/src/editor/js/libs/ternjs/tern.js +993 -0
- package/src/editor/js/libs/ui.js +1305 -0
- package/src/editor/js/libs/ui.three.js +946 -0
- package/src/events.js +273 -0
- package/src/index.js +284 -0
- package/src/presets/machines.js +239 -0
package/README.md
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
# scene-editor
|
|
2
|
+
|
|
3
|
+
Embeddable [three.js editor](https://github.com/mrdoob/three.js/tree/dev/editor) packaged as an installable npm library. It is designed to be **mounted into a Frappe Desk page / FormView (Vue)** to edit a single **Machine** figure or to assemble a **factory floor layout** from machine presets, and to receive live status updates from the outside (websocket / Frappe REST API).
|
|
4
|
+
|
|
5
|
+
The library exposes a framework-agnostic `SceneEditor` class that mounts into any DOM container. All heavy third-party code (`three`, `three/addons/*`, `signals`) is **externalized** so your host bundler (Vite, webpack, Parcel) dedupes the single `three` instance in your app.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install scene-editor three
|
|
11
|
+
# peer dependency
|
|
12
|
+
npm install three@">=0.165"
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Optional runtime dep installed automatically: `signals`.
|
|
16
|
+
|
|
17
|
+
## Quick start
|
|
18
|
+
|
|
19
|
+
```js
|
|
20
|
+
import { SceneEditor, registerBuiltinPresets } from 'scene-editor';
|
|
21
|
+
import 'scene-editor/style.css'; // editor UI stylesheet (also auto-injected by the bundle)
|
|
22
|
+
|
|
23
|
+
registerBuiltinPresets(); // registers press-machine, single-press, amada, compressor, coil-line
|
|
24
|
+
|
|
25
|
+
const editor = new SceneEditor();
|
|
26
|
+
editor.mount(document.getElementById('editor-host'));
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Public API
|
|
30
|
+
|
|
31
|
+
| Method | Returns | Description |
|
|
32
|
+
| --- | --- | --- |
|
|
33
|
+
| `new SceneEditor(options?)` | `SceneEditor` | Construct (does not touch the DOM yet). |
|
|
34
|
+
| `mount(containerOrSelector)` | `this` | Append the editor UI into a host element. |
|
|
35
|
+
| `destroy()` | – | Disconnect observers / websocket, remove DOM, dispatch `editorCleared`. |
|
|
36
|
+
| `getEditor()` | `Editor` | The upstream three.js `Editor` instance (full control). |
|
|
37
|
+
| `getScene()` | `THREE.Scene` | Current scene. |
|
|
38
|
+
| `getSceneJSON()` | `object` | Full editor state (scene + camera + history). Persist this in your DocType field. |
|
|
39
|
+
| `setSceneJSON(json)` | `Promise<this>` | `editor.clear()` + `editor.fromJSON(json)`. |
|
|
40
|
+
| `addObject(obj)` | `obj` | Add object through the undo history (`AddObjectCommand`). |
|
|
41
|
+
| `addPreset(name, x=0, z=0, params?)` | `THREE.Object3D\|null` | Add a registered machine preset (see below). |
|
|
42
|
+
| `registerPreset(name, factory)` | `PRESETS` | Register a custom preset factory `(x,z,params) => Object3D`. |
|
|
43
|
+
| `getObjectByUuid(uuid)` | `Object3D` | Lookup. |
|
|
44
|
+
| `selectByUuid(uuid)` | `this` | Select an object. |
|
|
45
|
+
| `getSelected()` | `Object3D` | Current selection. |
|
|
46
|
+
| `exportGLB(rootObject?)` | `Promise<ArrayBuffer>` | GLB binary of the object (or whole scene). Uses `GLTFExporter`. |
|
|
47
|
+
| `exportGLBFile(rootObject?, filename?)` | `Promise<Blob>` | Same, triggers a browser download. |
|
|
48
|
+
| `exportGLTF(rootObject?)` | `Promise<string>` | Pretty-printed glTF JSON. |
|
|
49
|
+
| `on(signalName, fn)` | `unsubscribe()` | Subscribe to any `editor.signals.*` (e.g. `objectSelected`, `sceneGraphChanged`, `objectChanged`). |
|
|
50
|
+
| `off(signalName, fn)` | – | Unsubscribe. |
|
|
51
|
+
| `editor.events` | `EventBridge` | External event/data bindings (see below). |
|
|
52
|
+
|
|
53
|
+
## Event binding — live data from Frappe / websocket
|
|
54
|
+
|
|
55
|
+
`editor.events` is an `EventBridge` that maps scene objects to external data sources and pushes payloads into `object.userData` (and recolors a `beacon` mesh by status by default).
|
|
56
|
+
|
|
57
|
+
```js
|
|
58
|
+
const g = editor.addPreset('press-machine', 0, 0, { ton: 800, status: 'run', name: 'Press #12' });
|
|
59
|
+
editor.events.bind(g, { topic: 'machine-status' });
|
|
60
|
+
|
|
61
|
+
// Push from Frappe REST (polling / SSE / fetch):
|
|
62
|
+
editor.events.dispatch(g.uuid, { status: 'err', curr: 412, oee: 24 });
|
|
63
|
+
|
|
64
|
+
// Or open a shared websocket and route by { uuid, topic }:
|
|
65
|
+
editor.events.connectWS('wss://frappe.example/socket', { reconnectMs: 3000 });
|
|
66
|
+
// server -> { "uuid": "<machine uuid>", "status": "run", "oee": 88 }
|
|
67
|
+
// or -> { "topic": "machine-status", "status": "idle" } (broadcasts to all bound objects of that topic)
|
|
68
|
+
// or -> { ... } (broadcasts to ALL bindings)
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Signals dispatched to refresh the sidebar when data changes: `objectChanged` + `sceneGraphChanged`.
|
|
72
|
+
|
|
73
|
+
## Machine presets (built-in)
|
|
74
|
+
|
|
75
|
+
`press-machine`, `single-press`, `amada`, `compressor`, `coil-line`. Each returns a `THREE.Group` placed at `(x, 0, z)` with a status beacon mesh tagged `userData.role === 'beacon'` (the bridge recolors it on `status` change). The group's `userData` carries `{ type:'machine', name, status, ... }`.
|
|
76
|
+
|
|
77
|
+
```js
|
|
78
|
+
editor.registerPreset('my-robot', (x, z, params) => {
|
|
79
|
+
const g = new THREE.Group();
|
|
80
|
+
// ...build geometry...
|
|
81
|
+
g.position.set(x, 0, z);
|
|
82
|
+
g.userData = { type: 'machine', name: params?.name || 'Robot' };
|
|
83
|
+
return g;
|
|
84
|
+
});
|
|
85
|
+
editor.addPreset('my-robot', 4, 4, { name: 'R2' });
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Frappe integration (Desk page + Vue)
|
|
89
|
+
|
|
90
|
+
The editor is a plain DOM widget — wrap it in a Vue component:
|
|
91
|
+
|
|
92
|
+
```vue
|
|
93
|
+
<!-- frappe_custom/scene_editor/scene_editor_page.vue -->
|
|
94
|
+
<template>
|
|
95
|
+
<div ref="host" class="se-host" />
|
|
96
|
+
</template>
|
|
97
|
+
|
|
98
|
+
<script setup>
|
|
99
|
+
import { onMounted, onBeforeUnmount, ref } from 'vue';
|
|
100
|
+
import { SceneEditor, registerBuiltinPresets } from 'scene-editor';
|
|
101
|
+
import 'scene-editor/style.css';
|
|
102
|
+
|
|
103
|
+
const props = defineProps({ machineDoc: Object });
|
|
104
|
+
const emit = defineEmits(['save']);
|
|
105
|
+
const host = ref(null);
|
|
106
|
+
let editor;
|
|
107
|
+
|
|
108
|
+
onMounted(() => {
|
|
109
|
+
registerBuiltinPresets();
|
|
110
|
+
|
|
111
|
+
editor = new SceneEditor();
|
|
112
|
+
editor.mount(host.value);
|
|
113
|
+
|
|
114
|
+
// load existing figure/config from the Machine document
|
|
115
|
+
frappe.model.with_doc('Machine', props.machineDoc.name, (doc) => {
|
|
116
|
+
if (doc.scene_json) editor.setSceneJSON(JSON.parse(doc.scene_json));
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
editor.events.connectWS(frappe.boot?.ws_url + '/machine-status', { reconnectMs: 5000 });
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
onBeforeUnmount(() => editor?.destroy());
|
|
123
|
+
|
|
124
|
+
function persist() {
|
|
125
|
+
const json = JSON.stringify(editor.getSceneJSON());
|
|
126
|
+
frappe.db.set_value('Machine', props.machineDoc.name, 'scene_json', json);
|
|
127
|
+
}
|
|
128
|
+
defineExpose({ persist, exportGlb: () => editor.exportGLBFile() });
|
|
129
|
+
</script>
|
|
130
|
+
|
|
131
|
+
<style scoped>
|
|
132
|
+
.se-host { width: 100%; height: calc(100vh - 96px); }
|
|
133
|
+
</style>
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Register a Vue-based Desk page via a Frappe custom app `page_js`, or render the component inside an HTML field / `_page` container. The host element just needs a fixed height.
|
|
137
|
+
|
|
138
|
+
### Suggested DocType fields
|
|
139
|
+
|
|
140
|
+
- **Machine**: `scene_json` (Long Text) — the editor state for that machine's figure; `glb_file` (Attach) — exported GLB.
|
|
141
|
+
- **Factory Layout** (a separate DocType): `scene_json` (Long Text) — the factory-floor arrangement referencing placed machines.
|
|
142
|
+
|
|
143
|
+
### Save / load workflow
|
|
144
|
+
|
|
145
|
+
1. Open Machine doc → mount editor → `setSceneJSON(doc.scene_json)`.
|
|
146
|
+
2. Edit geometry / material / transforms; Add menu adds primitives + your presets.
|
|
147
|
+
3. On Save: `getSceneJSON()` → write to `scene_json`. On Export: `exportGLBFile()` → upload to `glb_file`.
|
|
148
|
+
4. Open Factory Layout doc → mount editor → add machine presets (`addPreset`) → arrange on ground → save.
|
|
149
|
+
|
|
150
|
+
## Development
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
npm run dev # parcel dev server with a playground at src/index.html
|
|
154
|
+
npm run build # emits dist/index.js (ESM, externalized) + dist/index.css
|
|
155
|
+
npm run clean
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
## Notes / current scope
|
|
159
|
+
|
|
160
|
+
This build trims upstream-only features to keep the embed lean:
|
|
161
|
+
- WebGPU renderer + GPU pathtracer (realistic viewport shading) — stubbed out.
|
|
162
|
+
- WebXR session control — stubbed out.
|
|
163
|
+
- CodeMirror/Tern script editor subsystem — not bundled (the script tab's "Edit" button is inert; add your own scripting UI via the `editScript` signal if needed).
|
|
164
|
+
|
|
165
|
+
Everything else (Viewport, Toolbar, Sidebar *Scene/Properties/Project/Settings*, Menubar *File/Edit/Add/View/Render/Help/Status*, History, TransformControls, GLTF/3MF/FBX/OBJ/STL/etc. loaders via drag-&-drop, GLB/GLTF/OBJ/PLY/STL export, environment/fog/background) is intact upstream code.
|
|
166
|
+
|
|
167
|
+
## License
|
|
168
|
+
|
|
169
|
+
MIT — three.js editor code © three.js contributors (MIT); presets in `src/presets/` are project-specific.
|