zone editor
This commit is contained in:
@@ -2,6 +2,7 @@ import type { ThreeEvent } from "@react-three/fiber";
|
||||
import mitt from "mitt";
|
||||
import type { BuildingNode, ItemNode, WallNode } from "../schema";
|
||||
import type { AnyNode } from "../schema/types";
|
||||
import type { Zone } from "../schema/zone";
|
||||
|
||||
// Base event interfaces
|
||||
export interface GridEvent {
|
||||
@@ -18,6 +19,13 @@ export interface NodeEvent<T extends AnyNode = AnyNode> {
|
||||
nativeEvent: ThreeEvent<PointerEvent>;
|
||||
}
|
||||
|
||||
export interface ZoneEvent {
|
||||
zone: Zone;
|
||||
position: [number, number, number];
|
||||
stopPropagation: () => void;
|
||||
nativeEvent: ThreeEvent<PointerEvent>;
|
||||
}
|
||||
|
||||
export type WallEvent = NodeEvent<WallNode>;
|
||||
export type ItemEvent = NodeEvent<ItemNode>;
|
||||
export type BuildingEvent = NodeEvent<BuildingNode>;
|
||||
@@ -52,10 +60,15 @@ type CameraControlEvents = {
|
||||
"camera-controls:view": CameraControlEvent;
|
||||
"camera-controls:capture": CameraControlEvent;
|
||||
};
|
||||
type ZoneEvents = {
|
||||
[K in `zone:${EventSuffix}`]: ZoneEvent;
|
||||
};
|
||||
|
||||
type EditorEvents = GridEvents &
|
||||
NodeEvents<"wall", WallEvent> &
|
||||
NodeEvents<"item", ItemEvent> &
|
||||
NodeEvents<"building", BuildingEvent> &
|
||||
ZoneEvents &
|
||||
CameraControlEvents;
|
||||
|
||||
export const emitter = mitt<EditorEvents>();
|
||||
|
||||
@@ -7,6 +7,7 @@ export type {
|
||||
ItemEvent,
|
||||
NodeEvent,
|
||||
WallEvent,
|
||||
ZoneEvent,
|
||||
} from './events/bus'
|
||||
// Events
|
||||
export { emitter, eventSuffixes } from './events/bus'
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useRegistry, useScene, type Zone } from "@pascal-app/core";
|
||||
import { emitter, useRegistry, useScene, type Zone } from "@pascal-app/core";
|
||||
|
||||
import { useMemo, useRef } from "react";
|
||||
import type { ThreeEvent } from "@react-three/fiber";
|
||||
import { useCallback, useMemo, useRef } from "react";
|
||||
import {
|
||||
BufferGeometry,
|
||||
Color,
|
||||
@@ -162,8 +163,26 @@ export const ZoneRenderer = ({ zoneId }: { zoneId: Zone["id"] }) => {
|
||||
return null;
|
||||
}
|
||||
|
||||
const emitZoneEvent = useCallback(
|
||||
(suffix: string, e: ThreeEvent<PointerEvent>) => {
|
||||
const eventKey = `zone:${suffix}` as `zone:${typeof suffix}`;
|
||||
emitter.emit(eventKey, {
|
||||
zone,
|
||||
position: [e.point.x, e.point.y, e.point.z],
|
||||
stopPropagation: () => e.stopPropagation(),
|
||||
nativeEvent: e,
|
||||
});
|
||||
},
|
||||
[zone]
|
||||
);
|
||||
|
||||
return (
|
||||
<group ref={ref}>
|
||||
<group
|
||||
ref={ref}
|
||||
onClick={(e) => emitZoneEvent("click", e)}
|
||||
onPointerEnter={(e) => emitZoneEvent("enter", e)}
|
||||
onPointerLeave={(e) => emitZoneEvent("leave", e)}
|
||||
>
|
||||
{/* Floor fill */}
|
||||
<mesh
|
||||
position={[0, Y_OFFSET, 0]}
|
||||
|
||||
@@ -25,8 +25,8 @@ type Outliner = {
|
||||
|
||||
type ViewerState = {
|
||||
selection: SelectionPath;
|
||||
hoveredId: AnyNode["id"] | null;
|
||||
setHoveredId: (id: AnyNode["id"] | null) => void;
|
||||
hoveredId: AnyNode["id"] | Zone["id"] | null;
|
||||
setHoveredId: (id: AnyNode["id"] | Zone["id"] | null) => void;
|
||||
|
||||
cameraMode: "perspective" | "orthographic";
|
||||
setCameraMode: (mode: "perspective" | "orthographic") => void;
|
||||
|
||||
Reference in New Issue
Block a user