Skip to content

Commit

Permalink
feat: support entity base flyTo on reearth/core (#419)
Browse files Browse the repository at this point in the history
* feat: support entity base flyTo

* fix: flyto

* type: fix type error

* Update src/core/Crust/Plugins/plugin_types.ts

Co-authored-by: rot1024 <aayhrot@gmail.com>

* type: some internal types for flyTo

---------

Co-authored-by: rot1024 <aayhrot@gmail.com>
  • Loading branch information
keiya01 and rot1024 committed Feb 7, 2023
1 parent c10a671 commit 3060cfd
Show file tree
Hide file tree
Showing 13 changed files with 78 additions and 53 deletions.
4 changes: 2 additions & 2 deletions src/core/Crust/Plugins/hooks.ts
Expand Up @@ -82,8 +82,8 @@ export default function ({
);

const flyTo = useCallback(
(dest: FlyToDestination, options?: CameraOptions) => {
engineRef?.flyTo(dest, options);
(target: string | FlyToDestination, options?: CameraOptions | undefined) => {
engineRef?.flyTo(target, options);
},
[engineRef],
);
Expand Down
2 changes: 1 addition & 1 deletion src/core/Crust/Plugins/plugin_types.ts
Expand Up @@ -121,7 +121,7 @@ export type Camera = {
readonly zoomIn: (amount: number, options?: CameraOptions) => void;
readonly zoomOut: (amount: number, options?: CameraOptions) => void;
/** Moves the camera position to the specified destination. */
readonly flyTo: (destination: FlyToDestination, options?: CameraOptions) => void;
readonly flyTo: (destination: string | FlyToDestination, options?: CameraOptions) => void;
/** Moves the camera position to look at the specified destination. */
readonly lookAt: (destination: LookAtDestination, options?: CameraOptions) => void;
/** Rotate the camera around the center of earth. */
Expand Down
2 changes: 1 addition & 1 deletion src/core/Crust/Widgets/Widget/Button/MenuButton.tsx
Expand Up @@ -38,7 +38,7 @@ export type Props = {
};
align?: "end" | "start" | "centered";
theme?: Theme;
onFlyTo?: (camera: FlyToDestination, options?: { duration?: number }) => void;
onFlyTo?: (target: string | FlyToDestination, options?: { duration?: number }) => void;
};

export default function MenuButton({
Expand Down
2 changes: 1 addition & 1 deletion src/core/Crust/Widgets/Widget/LegacyMenu/MenuButton.tsx
Expand Up @@ -40,7 +40,7 @@ export type Props = {
menuItems?: MenuItem[];
pos: Position;
theme?: Theme;
onFlyTo?: (camera: FlyToDestination, options?: { duration?: number }) => void;
onFlyTo?: (target: string | FlyToDestination, options?: { duration?: number }) => void;
};

export default function MenuButton({
Expand Down
2 changes: 1 addition & 1 deletion src/core/Crust/Widgets/Widget/Navigator/hooks.ts
Expand Up @@ -19,7 +19,7 @@ export default function ({
onZoomOut?: (amount: number) => void;
onCameraOrbit?: (orbit: number) => void;
onCameraRotateRight?: (radian: number) => void;
onFlyTo?: (camera: FlyToDestination, options?: { duration?: number }) => void;
onFlyTo?: (target: string | FlyToDestination, options?: { duration?: number }) => void;
}) {
const [degree, setDegree] = useState(0);
const [isHelpOpened, setIsHelpOpened] = useState(false);
Expand Down
4 changes: 2 additions & 2 deletions src/core/Crust/Widgets/Widget/Storytelling/hooks.ts
Expand Up @@ -44,7 +44,7 @@ export default function ({
layerId?: string;
featureId?: string;
};
onFlyTo?: (camera: FlyToDestination, options?: { duration?: number }) => void;
onFlyTo?: (target: string | FlyToDestination, options?: { duration?: number }) => void;
onLookAt?: (camera: LookAtDestination, options?: { duration?: number }) => void;
onLayerSelect?: (
layerId: string | undefined,
Expand Down Expand Up @@ -123,7 +123,7 @@ export default function ({
}, [selectedLayer]);

useEffect(() => {
const id = selectedLayerId;
const id = selectedLayerId?.layerId;
const index = id ? stories?.findIndex(l => l.layer === id) : undefined;
select(
typeof index === "number" && index >= 0
Expand Down
2 changes: 1 addition & 1 deletion src/core/Crust/Widgets/Widget/index.tsx
Expand Up @@ -40,7 +40,7 @@ export type Context = {
featureId?: string;
};
is2d?: boolean;
onFlyTo?: (camera: FlyToDestination, options?: { duration?: number }) => void;
onFlyTo?: (target: string | FlyToDestination, options?: { duration?: number }) => void;
onLookAt?: (camera: LookAtDestination, options?: { duration?: number }) => void;
onLayerSelect?: (
layerId: string | undefined,
Expand Down
15 changes: 6 additions & 9 deletions src/core/Crust/context.ts
Expand Up @@ -47,19 +47,16 @@ export function widgetContextFromMapRef({
selectedLayerId,
findPhotooverlayLayer: (id: string) => {
const l = layers()?.findById(id);
if (
!l ||
l.type !== "simple" ||
!l.photooverlay?.location ||
!("lat" in l.photooverlay.location)
) {
if (!l || l.type !== "simple") {
return undefined;
}
// For compat
const location = l.property?.default?.location ?? l.property?.default?.position;
return {
title: l.title,
lat: l.photooverlay.location.lat,
lng: l.photooverlay.location.lng,
height: typeof l.photooverlay?.height === "number" ? l.photooverlay.height : 0,
lat: location?.lat,
lng: location?.lng,
height: location?.height ?? 0,
};
},
onCameraOrbit: (...args) => engine()?.orbit(...args),
Expand Down
2 changes: 1 addition & 1 deletion src/core/Map/types/index.ts
Expand Up @@ -43,7 +43,7 @@ export type EngineRef = {
getViewport: () => Rect | undefined;
getCamera: () => Camera | undefined;
getLocationFromScreen: (x: number, y: number, withTerrain?: boolean) => LatLngHeight | undefined;
flyTo: (destination: FlyToDestination, options?: CameraOptions) => void;
flyTo: (target: string | FlyToDestination, options?: CameraOptions) => void;
lookAt: (destination: LookAtDestination, options?: CameraOptions) => void;
lookAtLayer: (layerId: string) => void;
zoomIn: (amount: number, options?: CameraOptions) => void;
Expand Down
2 changes: 1 addition & 1 deletion src/core/engines/Cesium/Feature/context.ts
Expand Up @@ -7,7 +7,7 @@ import type { Camera, FlyToDestination, CameraOptions, LayerSelectionReason } fr
export type Context = {
selectionReason?: LayerSelectionReason;
getCamera?: () => Camera | undefined;
flyTo?: (camera: FlyToDestination, options?: CameraOptions) => void;
flyTo?: (target: string | FlyToDestination, options?: CameraOptions) => void;
onLayerEdit?: (e: LayerEditEvent) => void;
};

Expand Down
26 changes: 2 additions & 24 deletions src/core/engines/Cesium/hooks.ts
Expand Up @@ -23,7 +23,7 @@ import { useCameraLimiter } from "./cameraLimiter";
import { getCamera, isDraggable, isSelectable, getLocationFromScreen } from "./common";
import { getTag, type Context as FeatureContext } from "./Feature";
import useEngineRef from "./useEngineRef";
import { convertCartesian3ToPosition } from "./utils";
import { convertCartesian3ToPosition, findEntity } from "./utils";

export default ({
ref,
Expand Down Expand Up @@ -149,7 +149,7 @@ export default ({
const viewer = cesium.current?.cesiumElement;
if (!viewer || viewer.isDestroyed()) return;

const entity = findEntity(viewer, selectedLayerId?.featureId ?? selectedLayerId?.layerId);
const entity = findEntity(viewer, selectedLayerId?.layerId, selectedLayerId?.featureId);
if (viewer.selectedEntity === entity) return;

const tag = getTag(entity);
Expand Down Expand Up @@ -374,28 +374,6 @@ function tileProperties(t: Cesium3DTileFeature): { key: string; value: any }[] {
);
}

function findEntity(viewer: CesiumViewer, layerId: string | undefined): Entity | undefined {
if (!layerId) return;

let entity = viewer.entities.getById(layerId);
if (entity) return entity;

entity = viewer.entities.values.find(e => getTag(e)?.layerId === layerId);
if (entity) return entity;

for (const ds of [viewer.dataSourceDisplay.dataSources, viewer.dataSources]) {
for (let i = 0; i < ds.length; i++) {
const entities = ds.get(i).entities.values;
const e = entities.find(e => getTag(e)?.layerId === layerId);
if (e) {
return e;
}
}
}

return;
}

function getLayerId(target: RootEventTarget): string | undefined {
if (target && "id" in target && target.id instanceof Entity) {
return getTag(target.id)?.layerId;
Expand Down
37 changes: 28 additions & 9 deletions src/core/engines/Cesium/useEngineRef.ts
Expand Up @@ -27,6 +27,7 @@ import {
zoom,
lookAtWithoutAnimation,
} from "./common";
import { findEntity } from "./utils";

export default function useEngineRef(
ref: Ref<EngineRef>,
Expand Down Expand Up @@ -68,15 +69,33 @@ export default function useEngineRef(
if (!viewer || viewer.isDestroyed()) return;
return getLocationFromScreen(viewer.scene, x, y, withTerrain);
},
flyTo: (camera, options) => {
const viewer = cesium.current?.cesiumElement;
if (!viewer || viewer.isDestroyed()) return;
cancelCameraFlight.current?.();
cancelCameraFlight.current = flyTo(
viewer.scene?.camera,
{ ...getCamera(viewer), ...camera },
options,
);
flyTo: (target, options) => {
if (target && typeof target === "object") {
const viewer = cesium.current?.cesiumElement;
if (!viewer || viewer.isDestroyed()) return;

cancelCameraFlight.current?.();
cancelCameraFlight.current = flyTo(
viewer.scene?.camera,
{ ...getCamera(viewer), ...target },
options,
);
}
if (target && typeof target === "string") {
const viewer = cesium.current?.cesiumElement;
if (!viewer || viewer.isDestroyed()) return;

const layerOrFeatureId = target;
const entityFromFeatureId = findEntity(viewer, undefined, layerOrFeatureId);
if (entityFromFeatureId) {
viewer.flyTo(entityFromFeatureId, options);
} else {
const entityFromLayerId = findEntity(viewer, layerOrFeatureId);
if (entityFromLayerId) {
viewer.flyTo(entityFromLayerId, options);
}
}
}
},
lookAt: (camera, options) => {
const viewer = cesium.current?.cesiumElement;
Expand Down
31 changes: 31 additions & 0 deletions src/core/engines/Cesium/utils.ts
Expand Up @@ -4,8 +4,11 @@ import {
Math as CesiumMath,
TranslationRotationScale,
Cartographic,
Entity,
} from "cesium";

import { getTag } from "./Feature";

export const convertCartesian3ToPosition = (
cesium?: CesiumViewer,
pos?: Cartesian3,
Expand Down Expand Up @@ -35,3 +38,31 @@ export const translationWithClamping = (
}
}
};

export function findEntity(
viewer: CesiumViewer,
layerId?: string,
featureId?: string,
): Entity | undefined {
const id = featureId ?? layerId;
const keyName = featureId ? "featureId" : "layerId";
if (!id) return;

let entity = viewer.entities.getById(id);
if (entity) return entity;

entity = viewer.entities.values.find(e => getTag(e)?.[keyName] === id);
if (entity) return entity;

for (const ds of [viewer.dataSourceDisplay.dataSources, viewer.dataSources]) {
for (let i = 0; i < ds.length; i++) {
const entities = ds.get(i).entities.values;
const e = entities.find(e => getTag(e)?.[keyName] === id);
if (e) {
return e;
}
}
}

return;
}

0 comments on commit 3060cfd

Please sign in to comment.