Skip to content

Commit

Permalink
fix: overriding timeline behavior on reearth/core (#532)
Browse files Browse the repository at this point in the history
fix: overridding timeline behavior on reearth/core
  • Loading branch information
keiya01 committed Mar 10, 2023
1 parent 5726783 commit 890daef
Show file tree
Hide file tree
Showing 8 changed files with 72 additions and 28 deletions.
2 changes: 1 addition & 1 deletion src/core/Crust/Widgets/Widget/Timeline/hooks.ts
Expand Up @@ -162,7 +162,7 @@ export const useTimeline = ({
}, [clock, onSpeedChange, onTick]);

const overriddenStart = overriddenClock?.start?.getTime();
const overriddenStop = overriddenClock?.start?.getTime();
const overriddenStop = overriddenClock?.stop?.getTime();
// Sync cesium clock.
useEffect(() => {
setRange(prev => {
Expand Down
16 changes: 7 additions & 9 deletions src/core/Crust/context.ts
@@ -1,15 +1,14 @@
import { RefObject, useMemo } from "react";

import { convertTime } from "@reearth/util/time";

import { Camera, MapRef, SceneProperty } from "./types";
import { Camera, Clock, MapRef, SceneProperty } from "./types";
import { Context as WidgetContext } from "./Widgets";

export const useWidgetContext = ({
mapRef,
camera,
selectedLayerId,
sceneProperty,
overriddenClock,
}: Parameters<typeof widgetContextFromMapRef>[0]) =>
useMemo(
() =>
Expand All @@ -18,15 +17,17 @@ export const useWidgetContext = ({
camera,
selectedLayerId,
sceneProperty,
overriddenClock,
}),
[camera, mapRef, sceneProperty, selectedLayerId],
[camera, mapRef, sceneProperty, selectedLayerId, overriddenClock],
);

export function widgetContextFromMapRef({
mapRef,
camera,
selectedLayerId,
sceneProperty,
overriddenClock,
}: {
mapRef?: RefObject<MapRef>;
camera?: Camera;
Expand All @@ -35,6 +36,7 @@ export function widgetContextFromMapRef({
featureId?: string;
};
sceneProperty?: SceneProperty;
overriddenClock: Clock;
}): WidgetContext {
const engine = () => mapRef?.current?.engine;
const layers = () => mapRef?.current?.layers;
Expand All @@ -44,11 +46,7 @@ export function widgetContextFromMapRef({
get clock() {
return engine()?.getClock();
},
overriddenClock: {
current: convertTime(sceneProperty?.timeline?.current),
start: convertTime(sceneProperty?.timeline?.start),
stop: convertTime(sceneProperty?.timeline?.stop),
},
overriddenClock,
initialCamera: sceneProperty?.default?.camera,
is2d: sceneProperty?.default?.sceneMode === "2d",
selectedLayerId,
Expand Down
12 changes: 10 additions & 2 deletions src/core/Crust/index.tsx
Expand Up @@ -3,7 +3,7 @@ import type { ReactNode, RefObject } from "react";
import type { SelectedFeatureInfo, Tag } from "@reearth/core/mantle";

import type { ComputedFeature, ComputedLayer, Feature } from "../mantle";
import type { LayerEditEvent, LayerSelectionReason } from "../Map";
import type { Clock, LayerEditEvent, LayerSelectionReason } from "../Map";
import type { Viewport } from "../Visualizer";

import { useWidgetContext } from "./context";
Expand Down Expand Up @@ -52,6 +52,7 @@ export type Props = {
isMobile?: boolean;
mapRef?: RefObject<MapRef>;
sceneProperty?: SceneProperty;
overriddenClock: Clock;
viewport?: Viewport;
camera?: Camera;
selectedComputedLayer?: ComputedLayer;
Expand Down Expand Up @@ -116,6 +117,7 @@ export default function Crust({
isMobile,
mapRef,
sceneProperty,
overriddenClock,
viewport,
camera,
tags,
Expand Down Expand Up @@ -158,7 +160,13 @@ export default function Crust({
pluginPopupContainerRef,
} = useHooks({ mapRef, ...externalPlugin });
const theme = usePublishTheme(sceneProperty?.theme);
const widgetContext = useWidgetContext({ mapRef, camera, sceneProperty, selectedLayerId });
const widgetContext = useWidgetContext({
mapRef,
camera,
sceneProperty,
selectedLayerId,
overriddenClock,
});

return (
<Plugins
Expand Down
1 change: 1 addition & 0 deletions src/core/Map/types/index.ts
Expand Up @@ -102,6 +102,7 @@ export type EngineProps = {
isEditable?: boolean;
isBuilt?: boolean;
property?: SceneProperty;
overriddenClock?: Clock;
camera?: Camera;
small?: boolean;
children?: ReactNode;
Expand Down
39 changes: 39 additions & 0 deletions src/core/Visualizer/hooks.ts
@@ -1,6 +1,7 @@
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { useWindowSize } from "react-use";

import { convertTime } from "@reearth/util/time";
import { type DropOptions, useDrop } from "@reearth/util/use-dnd";

import type { Block, BuiltinWidgets } from "../Crust";
Expand Down Expand Up @@ -143,6 +144,43 @@ export default function useHooks({
// scene
const [overriddenSceneProperty, overrideSceneProperty] = useOverriddenProperty(sceneProperty);

// clock
const overriddenClock = useMemo(() => {
const { start, stop, current } = overriddenSceneProperty.timeline || {};
const startTime = convertTime(start)?.getTime();
const stopTime = convertTime(stop)?.getTime();
const currentTime = convertTime(current)?.getTime();

const DEFAULT_NEXT_RANGE = 86400000; // a day
const MAX_RANGE_DIFFERENCE = 2592000000; // 30 days

// To avoid out of range error in Cesium, we need to turn back a hour.
const now = Date.now() - 3600000;

const convertedStartTime = startTime
? Math.min(now, startTime)
: stopTime
? Math.min(now, stopTime - DEFAULT_NEXT_RANGE)
: now - DEFAULT_NEXT_RANGE;

const convertedStopTime = stopTime
? Math.min(stopTime, convertedStartTime + MAX_RANGE_DIFFERENCE)
: startTime
? Math.min(now, startTime + DEFAULT_NEXT_RANGE)
: now;

return {
start: new Date(convertedStartTime),
stop: new Date(convertedStopTime),
current: new Date(
Math.max(
Math.min(convertedStopTime, currentTime || convertedStartTime),
convertedStartTime,
),
),
};
}, [overriddenSceneProperty]);

// block
const [selectedBlock, selectBlock] = useValue(initialSelectedBlockId, onBlockSelect);

Expand Down Expand Up @@ -210,6 +248,7 @@ export default function useHooks({
camera,
isMobile,
overriddenSceneProperty,
overriddenClock,
isDroppable,
infobox,
isLayerDragging,
Expand Down
2 changes: 2 additions & 0 deletions src/core/Visualizer/index.tsx
Expand Up @@ -158,6 +158,7 @@ export default function Visualizer({
camera,
isMobile,
overriddenSceneProperty,
overriddenClock,
isDroppable,
isLayerDragging,
infobox,
Expand Down Expand Up @@ -202,6 +203,7 @@ export default function Visualizer({
inEditor={inEditor}
sceneProperty={overriddenSceneProperty}
overrideSceneProperty={overrideSceneProperty}
overriddenClock={overriddenClock}
blocks={infobox?.blocks}
camera={camera}
isMobile={isMobile}
Expand Down
25 changes: 10 additions & 15 deletions src/core/engines/Cesium/core/Clock.tsx
Expand Up @@ -2,32 +2,27 @@ import { Clock as CesiumClock, ClockRange, ClockStep, JulianDate } from "cesium"
import { useCallback, useEffect, useMemo } from "react";
import { Clock, useCesium } from "resium";

import { convertTime } from "@reearth/util/time";

import type { SceneProperty } from "../..";
import type { Clock as ClockType, SceneProperty } from "../..";

export type Props = {
property?: SceneProperty;
clock?: ClockType;
onTick?: (d: Date) => void;
};

export default function ReearthClock({ property, onTick }: Props): JSX.Element | null {
const { animation, visible, start, stop, current, stepType, rangeType, multiplier, step } =
property?.timeline ?? {};
const dateStart = useMemo(() => convertTime(start), [start]);
const dateStop = useMemo(() => convertTime(stop), [stop]);
const dateCurrent = useMemo(() => convertTime(current), [current]);
export default function ReearthClock({ property, clock, onTick }: Props): JSX.Element | null {
const { animation, visible, stepType, rangeType, multiplier, step } = property?.timeline ?? {};
const startTime = useMemo(
() => (dateStart ? JulianDate.fromDate(dateStart) : undefined),
[dateStart],
() => (clock?.start ? JulianDate.fromDate(clock.start) : undefined),
[clock?.start],
);
const stopTime = useMemo(
() => (dateStop ? JulianDate.fromDate(dateStop) : undefined),
[dateStop],
() => (clock?.stop ? JulianDate.fromDate(clock?.stop) : undefined),
[clock?.stop],
);
const currentTime = useMemo(
() => (dateCurrent ? JulianDate.fromDate(dateCurrent) : undefined),
[dateCurrent],
() => (clock?.current ? JulianDate.fromDate(clock?.current) : undefined),
[clock],
);
const clockStep =
stepType === "fixed" ? ClockStep.TICK_DEPENDENT : ClockStep.SYSTEM_CLOCK_MULTIPLIER;
Expand Down
3 changes: 2 additions & 1 deletion src/core/engines/Cesium/index.tsx
Expand Up @@ -31,6 +31,7 @@ const Cesium: React.ForwardRefRenderFunction<EngineRef, EngineProps> = (
className,
style,
property,
overriddenClock,
camera,
small,
ready,
Expand Down Expand Up @@ -128,7 +129,7 @@ const Cesium: React.ForwardRefRenderFunction<EngineRef, EngineProps> = (
onMouseLeave={mouseEventHandles.mouseleave}
onWheel={mouseEventHandles.wheel}>
<Event onMount={handleMount} onUnmount={handleUnmount} />
<Clock property={property} onTick={handleTick} />
<Clock property={property} clock={overriddenClock} onTick={handleTick} />
<ImageryLayers tiles={property?.tiles} cesiumIonAccessToken={cesiumIonAccessToken} />
<Indicator property={property} />
<ScreenSpaceEventHandler useDefault>
Expand Down

0 comments on commit 890daef

Please sign in to comment.