From f24d97c18bd679e5a917096a1a54674c7cfd797b Mon Sep 17 00:00:00 2001 From: Exelo Date: Tue, 16 Jun 2026 00:19:24 +0900 Subject: [PATCH] feat: add shape drag and drop --- src/lib/client/event/event-emitter.ts | 6 ++++++ src/lib/client/event/event-handler.ts | 17 ++++++++++++++++- src/lib/client/event/events/core-events.ts | 8 +++++--- src/lib/client/event/events/editor-events.ts | 10 ++++++---- .../event/listeners/move-component.listener.ts | 13 +++++++++++++ src/lib/client/project/project.ts | 2 ++ src/lib/client/project/save-handler.ts | 2 ++ .../entity-inspector/component-param-row.svelte | 8 ++++++++ .../Widget/entity-inspector/widget.svelte | 9 +-------- 9 files changed, 59 insertions(+), 16 deletions(-) create mode 100644 src/lib/client/event/listeners/move-component.listener.ts diff --git a/src/lib/client/event/event-emitter.ts b/src/lib/client/event/event-emitter.ts index 09e5956..8aa727d 100644 --- a/src/lib/client/event/event-emitter.ts +++ b/src/lib/client/event/event-emitter.ts @@ -9,6 +9,11 @@ export class EventEmitter< } = {}; public eventQueue: QueuedEvent[] = []; + private readonly _dequeueOnEmit: boolean; + + constructor(dequeueOnEmit = false) { + this._dequeueOnEmit = dequeueOnEmit; + } runEvents(): void { this.eventQueue.forEach((e) => { @@ -23,6 +28,7 @@ export class EventEmitter< event, args, }); + if (this._dequeueOnEmit) this.runEvents(); } addListener( event: K, diff --git a/src/lib/client/event/event-handler.ts b/src/lib/client/event/event-handler.ts index 7da6483..9f3f71b 100644 --- a/src/lib/client/event/event-handler.ts +++ b/src/lib/client/event/event-handler.ts @@ -1,11 +1,26 @@ +import { get, writable } from 'svelte/store'; + +import { moveComponentListener } from '$lib/client/event/listeners/move-component.listener'; + import { EventEmitter } from './event-emitter'; import type { CoreEvents, CoreEventsMap } from './events/core-events'; import type { EditorEvents, EditorEventsMap } from './events/editor-events'; import type { ListenerType } from './types'; +const listeners = writable<(() => void)[]>([]); + export class EventHandler { public readonly _coreEvents = new EventEmitter(); - public readonly _editorEvents = new EventEmitter(); + public readonly _editorEvents = new EventEmitter(true); + + static reset() { + get(listeners).forEach((unsub) => unsub()); + listeners.set([]); + } + + async init() { + listeners.set([moveComponentListener(this)]); + } emit(event: K, ...args: CoreEventsMap[K]) { this._coreEvents.emitEvent(event, ...args); diff --git a/src/lib/client/event/events/core-events.ts b/src/lib/client/event/events/core-events.ts index fda6f18..4d96e5c 100644 --- a/src/lib/client/event/events/core-events.ts +++ b/src/lib/client/event/events/core-events.ts @@ -1,3 +1,5 @@ +import type { Save } from '@utils/types'; + export enum CoreEvents { HOT_RELOAD = 'hot-reload', HARD_RELOAD = 'hard-reload', @@ -7,9 +9,9 @@ export enum CoreEvents { } export interface CoreEventsMap { - [CoreEvents.HOT_RELOAD]: []; - [CoreEvents.HARD_RELOAD]: []; - [CoreEvents.PAUSE_GAME]: [duration: number]; + [CoreEvents.HOT_RELOAD]: [save: Save]; + [CoreEvents.HARD_RELOAD]: [save: Save]; + [CoreEvents.PAUSE_GAME]: []; [CoreEvents.STOP_GAME]: []; [CoreEvents.UNPAUSE_GAME]: []; } diff --git a/src/lib/client/event/events/editor-events.ts b/src/lib/client/event/events/editor-events.ts index 85b6752..20c3c32 100644 --- a/src/lib/client/event/events/editor-events.ts +++ b/src/lib/client/event/events/editor-events.ts @@ -1,9 +1,11 @@ -// ! Please do not remove this event unless a new one replaces it, it causes types issues - export enum EditorEvents { - EMPTY = 'empty', + MOVE_COMPONENT = 'move-component', } export interface EditorEventsMap { - [EditorEvents.EMPTY]: []; + [EditorEvents.MOVE_COMPONENT]: [ + entityId: string, + componentId: string, + position: { x: number; y: number }, + ]; } diff --git a/src/lib/client/event/listeners/move-component.listener.ts b/src/lib/client/event/listeners/move-component.listener.ts new file mode 100644 index 0000000..cda54a2 --- /dev/null +++ b/src/lib/client/event/listeners/move-component.listener.ts @@ -0,0 +1,13 @@ +import { EditorEvents, type EventHandler } from '$lib/client/event'; +import { useProject } from '$lib/client/project'; + +export const moveComponentListener = (handler: EventHandler): (() => void) => { + handler.on(EditorEvents.MOVE_COMPONENT, (entityId, _componentId, { x, y }) => { + const { ecs } = useProject(); + const entity = ecs.scenes.activeData.entities.get(entityId); + const component = entity.components.get('Position2D'); + component.params.get('x').value.set(x); + component.params.get('y').value.set(y); + }); + return () => {}; +}; diff --git a/src/lib/client/project/project.ts b/src/lib/client/project/project.ts index 537a6bb..1787306 100644 --- a/src/lib/client/project/project.ts +++ b/src/lib/client/project/project.ts @@ -21,6 +21,7 @@ export class Project { static reset(): void { InfoHandler.reset(); + EventHandler.reset(); } constructor(public id: string) { @@ -33,6 +34,7 @@ export class Project { await this.ecs.init(); await this.save.init(); await this.packages.init(); + await this.event.init(); this._inited = true; return this; } diff --git a/src/lib/client/project/save-handler.ts b/src/lib/client/project/save-handler.ts index f1ae48a..01c9cac 100644 --- a/src/lib/client/project/save-handler.ts +++ b/src/lib/client/project/save-handler.ts @@ -1,5 +1,6 @@ import { type Writable, get, writable } from 'svelte/store'; +import { CoreEvents } from '$lib/client/event'; import type { Project } from '$lib/client/project'; import type { Save } from '@utils/types'; @@ -27,6 +28,7 @@ export class SaveHandler { this._save.subscribe(() => { this.syncToServer(); + this._project.event.emit(CoreEvents.HOT_RELOAD, this.save); }); } diff --git a/src/lib/components/Widget/entity-inspector/component-param-row.svelte b/src/lib/components/Widget/entity-inspector/component-param-row.svelte index ece7346..e8ab40b 100644 --- a/src/lib/components/Widget/entity-inspector/component-param-row.svelte +++ b/src/lib/components/Widget/entity-inspector/component-param-row.svelte @@ -3,6 +3,7 @@ import { Input } from '$lib/components/ui/input'; import { TristateSwitch } from '$lib/components/ui/tristate-switch'; import { Select, SelectContent, SelectItem, SelectTrigger } from '$lib/components/ui/select'; + import { untrack } from 'svelte'; interface Props { handle: ComponentParamHandle; @@ -15,6 +16,13 @@ let value = $state($defaultValue); + $effect(() => { + defaultValue.subscribe(() => { + const v = untrack(() => value); + if (v !== $defaultValue) value = $defaultValue; + }); + }); + const handleChange = () => { handle.value.set(value); }; diff --git a/src/lib/components/Widget/entity-inspector/widget.svelte b/src/lib/components/Widget/entity-inspector/widget.svelte index 8890d63..f1be0b2 100644 --- a/src/lib/components/Widget/entity-inspector/widget.svelte +++ b/src/lib/components/Widget/entity-inspector/widget.svelte @@ -1,6 +1,5 @@