@cyclonium/editor 0.0.100

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/lib/cce.d.ts ADDED
@@ -0,0 +1,44 @@
1
+ import type { Component, Camera } from 'cc';
2
+ import type EventEmitter from 'node:events';
3
+ declare global {
4
+ namespace EditorExtends {
5
+ class ComponentManager extends EventEmitter<{
6
+ add: [componentId: string, component: Component];
7
+ remove: [componentId: string, component: Component];
8
+ }> {
9
+ }
10
+ const Component: InstanceType<typeof ComponentManager>;
11
+ }
12
+ namespace cce {
13
+ class NodeManager {
14
+ query(uuid: string): import('cc').Node | undefined;
15
+ }
16
+ const Node: InstanceType<typeof NodeManager>;
17
+ class OperationManager {
18
+ on<TEventName extends keyof Operation.EventMap>(type: TEventName, callback: ((...args: Operation.EventMap[TEventName]) => boolean | void | undefined), priority?: number): void;
19
+ removeListener<TEventName extends keyof Operation.EventMap>(type: TEventName, callback: ((...args: Operation.EventMap[TEventName]) => boolean | void | undefined)): void;
20
+ }
21
+ const Operation: InstanceType<typeof OperationManager>;
22
+ namespace Operation {
23
+ type EventMap = {
24
+ [x in 'mousedown' | 'mousemove' | 'mouseup' | 'mousewheel']: [OperationMouseEvent];
25
+ } & {
26
+ [x in 'keydown' | 'keyup']: [KeyboardEvent];
27
+ } & {
28
+ [x in 'onDragOver' | 'onDrop']: [DragEvent];
29
+ };
30
+ type OperationMouseEvent = Omit<MouseEvent, 'type'>;
31
+ }
32
+ class EngineManager {
33
+ repaintInEditMode(): boolean;
34
+ }
35
+ const Engine: InstanceType<typeof EngineManager>;
36
+ class CameraManager {
37
+ camera: Camera;
38
+ }
39
+ const Camera: InstanceType<typeof CameraManager>;
40
+ }
41
+ }
42
+ export import ccEditorExtension = globalThis.cce;
43
+ export declare function isSceneEditorEnv(): false | typeof ccEditorExtension;
44
+ //# sourceMappingURL=cce.d.ts.map
package/lib/cce.js ADDED
@@ -0,0 +1,4 @@
1
+ export var ccEditorExtension = globalThis.cce;
2
+ export function isSceneEditorEnv() {
3
+ return typeof globalThis.cce === 'object' && globalThis.cce;
4
+ }
@@ -0,0 +1,22 @@
1
+ import { Component } from 'cc';
2
+ import { SceneGuiContext } from './scene-gui-context.js';
3
+ export declare class ComponentEditor<TTarget extends Component = Component> {
4
+ constructor(target: TTarget);
5
+ get target(): TTarget;
6
+ destroy(): void;
7
+ invokeOnAttached_internal(): void;
8
+ invokeOnDetached_internal(): void;
9
+ invokeOnSceneGUI_internal(ctx: SceneGuiContext): void;
10
+ protected onAttached(): void;
11
+ protected onDetached(): void;
12
+ protected onDestroy(): void;
13
+ protected onSceneGUI(ctx: SceneGuiContext): void;
14
+ private _target;
15
+ }
16
+ export declare namespace ComponentEditor {
17
+ namespace LegacyDecorators {
18
+ function attachTo<TTarget extends Component>(targetComponentClass: new (...args: never[]) => TTarget): (componentEditorClass: new (target: TTarget) => ComponentEditor<TTarget>) => void;
19
+ }
20
+ }
21
+ export declare function startComponentEditor(): Promise<void>;
22
+ //# sourceMappingURL=component-editor.editor.d.ts.map
@@ -0,0 +1,179 @@
1
+ import { CCObject, Component, director, Node, System } from 'cc';
2
+ import EventEmitter from 'node:events';
3
+ import { SceneGuiContext } from './scene-gui-context.js';
4
+ import { HandleEditorInput } from './handle-editor-input.js';
5
+ import { isSceneEditorEnv } from './cce.js';
6
+ import { globalEditor } from './editor-global.js';
7
+ export class ComponentEditor {
8
+ constructor(target) {
9
+ this._target = target;
10
+ }
11
+ get target() {
12
+ if (!this._target) {
13
+ throw new Error(`Target is not set`);
14
+ }
15
+ return this._target;
16
+ }
17
+ destroy() {
18
+ this.onDestroy();
19
+ this._target = undefined;
20
+ }
21
+ invokeOnAttached_internal() {
22
+ this.onAttached();
23
+ }
24
+ invokeOnDetached_internal() {
25
+ this.onDetached();
26
+ }
27
+ invokeOnSceneGUI_internal(ctx) {
28
+ this.onSceneGUI(ctx);
29
+ }
30
+ onAttached() {
31
+ }
32
+ onDetached() {
33
+ }
34
+ onDestroy() {
35
+ }
36
+ onSceneGUI(ctx) {
37
+ void ctx;
38
+ }
39
+ _target = undefined;
40
+ }
41
+ const componentEditorTypeRegistry = new WeakMap();
42
+ // eslint-disable-next-line @typescript-eslint/no-namespace
43
+ (function (ComponentEditor) {
44
+ // eslint-disable-next-line @typescript-eslint/no-namespace
45
+ let LegacyDecorators;
46
+ (function (LegacyDecorators) {
47
+ function attachTo(targetComponentClass) {
48
+ return (componentEditorClass) => {
49
+ componentEditorTypeRegistry.set(targetComponentClass, {
50
+ editorClass: componentEditorClass,
51
+ });
52
+ };
53
+ }
54
+ LegacyDecorators.attachTo = attachTo;
55
+ })(LegacyDecorators = ComponentEditor.LegacyDecorators || (ComponentEditor.LegacyDecorators = {}));
56
+ })(ComponentEditor || (ComponentEditor = {}));
57
+ class ComponentEditorSystem extends System {
58
+ constructor(opts) {
59
+ super();
60
+ this._controllerOnDestroy = new AbortController();
61
+ this._handleInput = new HandleEditorInput();
62
+ this._sceneGuiContext = new SceneGuiContext(this._handleInput, {
63
+ renderer: {
64
+ node: opts.handlesRenderRoot,
65
+ },
66
+ });
67
+ }
68
+ addComponent(component) {
69
+ const componentType = component.constructor;
70
+ const componentEditorType = componentEditorTypeRegistry.get(componentType);
71
+ if (!componentEditorType) {
72
+ return;
73
+ }
74
+ const componentEditor = new componentEditorType.editorClass(component);
75
+ this._componentEditors.set(component, componentEditor);
76
+ componentEditor.invokeOnAttached_internal();
77
+ }
78
+ removeComponent(component) {
79
+ const componentEditor = this._componentEditors.get(component);
80
+ if (componentEditor) {
81
+ componentEditor.invokeOnDetached_internal();
82
+ componentEditor.destroy();
83
+ this._componentEditors.delete(component);
84
+ }
85
+ }
86
+ destroy() {
87
+ this._sceneGuiContext.destroy_internal();
88
+ this._controllerOnDestroy.abort();
89
+ this._handleInput.destroy();
90
+ for (const componentEditor of this._componentEditors.values()) {
91
+ componentEditor.invokeOnDetached_internal();
92
+ componentEditor.destroy();
93
+ }
94
+ this._componentEditors.clear();
95
+ }
96
+ update(_deltaTime) {
97
+ const sceneGuiContext = this._sceneGuiContext;
98
+ sceneGuiContext.startFrame_internal({});
99
+ const selectedNodes = getSelectedNodes();
100
+ try {
101
+ for (const [component, componentEditor] of this._componentEditors) {
102
+ const node = component.node;
103
+ if (!selectedNodes.includes(node.uuid)) {
104
+ continue;
105
+ }
106
+ sceneGuiContext.handles.pushScope(component.uuid);
107
+ try {
108
+ componentEditor.invokeOnSceneGUI_internal(sceneGuiContext);
109
+ }
110
+ finally {
111
+ sceneGuiContext.handles.popScope();
112
+ }
113
+ }
114
+ }
115
+ finally {
116
+ sceneGuiContext.endFrame_internal();
117
+ }
118
+ }
119
+ _componentEditors = new Map();
120
+ _handleInput;
121
+ _sceneGuiContext;
122
+ _controllerOnDestroy;
123
+ }
124
+ function getSelectedNodes() {
125
+ return globalEditor.Selection.getSelected('node');
126
+ }
127
+ const handlesRenderRootNodeName = '::handles-render-root::';
128
+ export async function startComponentEditor() {
129
+ if (!isSceneEditorEnv()) {
130
+ return;
131
+ }
132
+ const handlesRenderRoot = new Node(handlesRenderRootNodeName);
133
+ const flags = CCObject.Flags.DontSave | CCObject.Flags.HideInHierarchy;
134
+ handlesRenderRoot.objectFlags |= flags;
135
+ director.addPersistRootNode(handlesRenderRoot);
136
+ const componentEditorSystem = new ComponentEditorSystem({
137
+ handlesRenderRoot,
138
+ });
139
+ director.registerSystem('component-editors', componentEditorSystem, System.Priority.MEDIUM);
140
+ import.meta.hot?.signalOnDispose.addEventListener('abort', () => {
141
+ componentEditorSystem.destroy();
142
+ director.unregisterSystem(componentEditorSystem);
143
+ handlesRenderRoot.destroy();
144
+ });
145
+ (async () => {
146
+ try {
147
+ for await (const [_, component] of EventEmitter.on(EditorExtends.Component, 'add', {
148
+ signal: import.meta.hot?.signalOnDispose,
149
+ })) {
150
+ componentEditorSystem.addComponent(component);
151
+ }
152
+ }
153
+ catch (err) {
154
+ if (err instanceof Error && err.name === 'AbortError') {
155
+ // nop
156
+ }
157
+ else {
158
+ throw err;
159
+ }
160
+ }
161
+ })().catch(console.error.bind(console));
162
+ (async () => {
163
+ try {
164
+ for await (const [_, component] of EventEmitter.on(EditorExtends.Component, 'remove', {
165
+ signal: import.meta.hot?.signalOnDispose,
166
+ })) {
167
+ componentEditorSystem.removeComponent(component);
168
+ }
169
+ }
170
+ catch (err) {
171
+ if (err instanceof Error && err.name === 'AbortError') {
172
+ // nop
173
+ }
174
+ else {
175
+ throw err;
176
+ }
177
+ }
178
+ })().catch(console.error.bind(console));
179
+ }
@@ -0,0 +1,15 @@
1
+ declare global {
2
+ namespace Editor {
3
+ namespace Clipboard {
4
+ function write(type: string, text: string): void;
5
+ }
6
+ namespace Project {
7
+ const path: string;
8
+ }
9
+ namespace Selection {
10
+ function getSelected(type: string): string[];
11
+ }
12
+ }
13
+ }
14
+ export import globalEditor = globalThis.Editor;
15
+ //# sourceMappingURL=editor-global.d.ts.map
@@ -0,0 +1 @@
1
+ export var globalEditor = globalThis.Editor;
@@ -0,0 +1,7 @@
1
+ import { type HandleHostInput, type HandleHostMouseInput } from '@cyclonium/handles';
2
+ export declare class HandleEditorInput implements HandleHostInput {
3
+ get mouse(): HandleHostMouseInput;
4
+ destroy(): void;
5
+ private _mouse;
6
+ }
7
+ //# sourceMappingURL=handle-editor-input.d.ts.map
@@ -0,0 +1,100 @@
1
+ import { Vec2 } from '@cyclonium/core/math/vec2';
2
+ import { HandleContext } from '@cyclonium/handles';
3
+ import { ccEditorExtension } from './cce.js';
4
+ import { geometry, screen } from 'cc';
5
+ export class HandleEditorInput {
6
+ get mouse() {
7
+ return this._mouse;
8
+ }
9
+ destroy() {
10
+ this._mouse.destroy();
11
+ }
12
+ _mouse = new HandleEditorMouseInput();
13
+ }
14
+ class HandleEditorMouseInput {
15
+ constructor() {
16
+ const signal = this._controllerOnAbort.signal;
17
+ const intervalId = setInterval(() => {
18
+ if (signal.aborted) {
19
+ clearInterval(intervalId);
20
+ return;
21
+ }
22
+ if (typeof ccEditorExtension.Operation !== 'object' || !ccEditorExtension.Operation) {
23
+ return;
24
+ }
25
+ clearInterval(intervalId);
26
+ for (const mouseEventType of ['mousedown', 'mousemove', 'mouseup', 'mousewheel']) {
27
+ HandleEditorMouseInput._addInputEventListener(mouseEventType, this._onMouseEvent.bind(this, mouseEventType), { signal: signal });
28
+ }
29
+ });
30
+ }
31
+ get wantCapture() {
32
+ return this._wantCapture;
33
+ }
34
+ set wantCapture(value) {
35
+ this._wantCapture = value;
36
+ }
37
+ get position() {
38
+ return this._position;
39
+ }
40
+ get buttons() {
41
+ return this._buttons;
42
+ }
43
+ get altKey() {
44
+ return this._altKey;
45
+ }
46
+ get ctrlKey() {
47
+ return this._ctrlKey;
48
+ }
49
+ get shiftKey() {
50
+ return this._shiftKey;
51
+ }
52
+ mouseRay() {
53
+ const camera = ccEditorExtension.Camera.camera;
54
+ camera.screenPointToRay(this._position.x, this._position.y, this._mouseRay);
55
+ return this._mouseRay;
56
+ }
57
+ destroy() {
58
+ this._controllerOnAbort.abort();
59
+ }
60
+ static _addInputEventListener(type, callback, opts) {
61
+ ccEditorExtension.Operation.on(type, callback, 999);
62
+ opts?.signal?.addEventListener('abort', () => {
63
+ ccEditorExtension.Operation.removeListener(type, callback);
64
+ });
65
+ }
66
+ _controllerOnAbort = new AbortController();
67
+ _wantCapture = false;
68
+ _position = new Vec2();
69
+ _buttons = 0;
70
+ _altKey = false;
71
+ _ctrlKey = false;
72
+ _shiftKey = false;
73
+ _mouseRay = new geometry.Ray();
74
+ _onMouseEvent(eventType, event) {
75
+ let buttons = 0;
76
+ if (event.buttons & (1 << 0)) {
77
+ buttons |= (1 << HandleContext.MouseButton.left);
78
+ }
79
+ if (event.buttons & (1 << 1)) {
80
+ buttons |= (1 << HandleContext.MouseButton.right);
81
+ }
82
+ if (event.buttons & (1 << 2)) {
83
+ buttons |= (1 << HandleContext.MouseButton.middle);
84
+ }
85
+ this._buttons = buttons;
86
+ // Web use top 0, cocos use bottom 0
87
+ this._position.set(event.x, screen.windowSize.height - event.y);
88
+ this._altKey = event.altKey;
89
+ this._ctrlKey = event.ctrlKey;
90
+ this._shiftKey = event.shiftKey;
91
+ if (eventType === 'mousewheel') {
92
+ return true;
93
+ }
94
+ ccEditorExtension.Engine.repaintInEditMode();
95
+ if (!this._wantCapture) {
96
+ return true;
97
+ }
98
+ return false;
99
+ }
100
+ }
package/lib/index.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ export { ComponentEditor, startComponentEditor } from './component-editor.editor.js';
2
+ export { SceneGuiContext } from './scene-gui-context.js';
3
+ //# sourceMappingURL=index.d.ts.map
package/lib/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export { ComponentEditor, startComponentEditor } from './component-editor.editor.js';
2
+ export { SceneGuiContext } from './scene-gui-context.js';
@@ -0,0 +1,5 @@
1
+ import './cce.js';
2
+ import './editor-global.js';
3
+ export import Editor_legacy = globalThis.Editor;
4
+ export import cce_legacy = globalThis.cce;
5
+ //# sourceMappingURL=legacy-globals.d.ts.map
@@ -0,0 +1,4 @@
1
+ import './cce.js';
2
+ import './editor-global.js';
3
+ export var Editor_legacy = globalThis.Editor;
4
+ export var cce_legacy = globalThis.cce;
@@ -0,0 +1,10 @@
1
+ import { Handles, type HandleContext } from '@cyclonium/handles';
2
+ export declare class SceneGuiContext {
3
+ constructor(...args: ConstructorParameters<typeof Handles>);
4
+ get handles(): Handles;
5
+ destroy_internal(): void;
6
+ startFrame_internal(opts: HandleContext.FrameStartOptions): void;
7
+ endFrame_internal(): void;
8
+ private _handles;
9
+ }
10
+ //# sourceMappingURL=scene-gui-context.d.ts.map
@@ -0,0 +1,19 @@
1
+ import { Handles } from '@cyclonium/handles';
2
+ export class SceneGuiContext {
3
+ constructor(...args) {
4
+ this._handles = new Handles(...args);
5
+ }
6
+ get handles() {
7
+ return this._handles;
8
+ }
9
+ destroy_internal() {
10
+ this._handles.destroy_internal();
11
+ }
12
+ startFrame_internal(opts) {
13
+ this._handles.startFrame_internal(opts);
14
+ }
15
+ endFrame_internal() {
16
+ this._handles.endFrame_internal();
17
+ }
18
+ _handles;
19
+ }
package/package.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "name": "@cyclonium/editor",
3
+ "version": "0.0.100",
4
+ "type": "module",
5
+ "files": [
6
+ "lib/**/*{.js,.d.ts}"
7
+ ],
8
+ "exports": {
9
+ ".": {
10
+ "types": "./lib/index.d.ts",
11
+ "default": "./lib/index.js"
12
+ },
13
+ "./legacy-globals": {
14
+ "types": "./lib/legacy-globals.d.ts",
15
+ "default": "./lib/legacy-globals.js"
16
+ }
17
+ },
18
+ "dependencies": {
19
+ "@cyclonium/handles": "0.0.100"
20
+ },
21
+ "peerDependencies": {
22
+ "@cyclonium/core": "0.0.100"
23
+ },
24
+ "devDependencies": {
25
+ "@types/node": "^25.9.2",
26
+ "typescript": "^6.0.2",
27
+ "@cyclonium/workflow": "0.0.100",
28
+ "@cyclonium/types-cc": "0.0.100"
29
+ },
30
+ "scripts": {
31
+ "build": "tsc -b",
32
+ "dev": "tsc -b --watch"
33
+ }
34
+ }