Skip to content
This repository has been archived by the owner on Mar 8, 2023. It is now read-only.

Commit

Permalink
Merge branch 'master' into release_0_17_0
Browse files Browse the repository at this point in the history
  • Loading branch information
ninok committed Jun 24, 2020
2 parents a6851df + 9a0a736 commit 1325606
Show file tree
Hide file tree
Showing 12 changed files with 248 additions and 65 deletions.
4 changes: 2 additions & 2 deletions @here/harp-mapview-decoder/lib/TileLoader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
TileInfo
} from "@here/harp-datasource-protocol";
import { TileKey } from "@here/harp-geoutils";
import { DataSource, TileLoaderState } from "@here/harp-mapview";
import { DataSource, ITileLoader, TileLoaderState } from "@here/harp-mapview";
import { LoggerManager } from "@here/harp-utils";

import { DataProvider } from "./DataProvider";
Expand All @@ -26,7 +26,7 @@ const logger = LoggerManager.instance.create("TileLoader");
* The [[TileLoader]] manages the different states of loading and decoding for a [[Tile]]. Used by
* the [[TileDataSource]].
*/
export class TileLoader {
export class TileLoader implements ITileLoader {
/**
* Current state of `TileLoader`.
*/
Expand Down
22 changes: 14 additions & 8 deletions @here/harp-mapview/lib/MapView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,10 @@ export enum MapViewEventNames {
AfterRender = "didrender",
/** Called after the first frame has been rendered. */
FirstFrame = "first-render",
/** Called when the first view has all the necessary tiles loaded and rendered. */
/**
* Called when the rendered frame was complete, i.e. all the necessary tiles and resources
* are loaded and rendered.
*/
FrameComplete = "frame-complete",
/** Called when the theme has been loaded with the internal {@link ThemeLoader}. */
ThemeLoaded = "theme-loaded",
Expand Down Expand Up @@ -3293,6 +3296,7 @@ export class MapView extends THREE.EventDispatcher {
this.storageLevel,
Math.floor(this.zoomLevel),
this.getEnabledTileDataSources(),
this.m_frameNumber,
this.m_elevationRangeSource
);
// View ranges has changed due to features (with elevation) that affects clip planes
Expand Down Expand Up @@ -3471,16 +3475,18 @@ export class MapView extends THREE.EventDispatcher {
// frame, with no more tiles, geometry and labels waiting to be added, and no animation
// running. The initial placement of text in this render call may have changed the loading
// state of the TextElementsRenderer, so this has to be checked again.
// HARP-10919: Fading is currently ignored by the frame complete event.
if (
!this.m_firstFrameComplete &&
!this.textElementsRenderer.loading &&
this.m_visibleTiles.allVisibleTilesLoaded &&
this.m_initialTextPlacementDone &&
!this.isDynamicFrame &&
!this.textElementsRenderer.loading
!this.m_animatedExtrusionHandler.isAnimating
) {
this.m_firstFrameComplete = true;

if (gatherStatistics) {
stats.appResults.set("firstFrameComplete", frameStartTime);
if (this.m_firstFrameComplete === false) {
this.m_firstFrameComplete = true;
if (gatherStatistics) {
stats.appResults.set("firstFrameComplete", frameStartTime);
}
}

FRAME_COMPLETE_EVENT.time = frameStartTime;
Expand Down
43 changes: 31 additions & 12 deletions @here/harp-mapview/lib/VisibleTileSet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,7 @@ export class VisibleTileSet {
storageLevel: number,
zoomLevel: number,
dataSources: DataSource[],
frameNumber: number,
elevationRangeSource?: ElevationRangeSource
): { viewRanges: ViewRanges; viewRangesChanged: boolean } {
let allVisibleTilesLoaded: boolean = true;
Expand Down Expand Up @@ -537,7 +538,12 @@ export class VisibleTileSet {
) {
const tileEntry = visibleTileKeys[i];

const tile = this.getTile(dataSource, tileEntry.tileKey, tileEntry.offset);
const tile = this.getTile(
dataSource,
tileEntry.tileKey,
tileEntry.offset,
frameNumber
);
if (tile === undefined) {
continue;
}
Expand All @@ -553,7 +559,7 @@ export class VisibleTileSet {

if (tile.frameNumVisible < 0) {
// Store the fist frame the tile became visible.
tile.frameNumVisible = dataSource.mapView.frameNumber;
tile.frameNumVisible = frameNumber;
}
}
// Update the visible area of the tile. This is used for those tiles that are
Expand Down Expand Up @@ -635,11 +641,17 @@ export class VisibleTileSet {
* @param dataSource - The data source the tile belongs to.
* @param tileKey - The key identifying the tile.
* @param offset - Tile offset.
* @param frameNumber - Frame in which the tile was requested
* @return The tile if it was found or created, undefined otherwise.
*/
getTile(dataSource: DataSource, tileKey: TileKey, offset: number = 0): Tile | undefined {
getTile(
dataSource: DataSource,
tileKey: TileKey,
offset: number,
frameNumber: number
): Tile | undefined {
const cacheOnly = false;
return this.getTileImpl(dataSource, tileKey, offset, cacheOnly);
return this.getTileImpl(dataSource, tileKey, offset, cacheOnly, frameNumber);
}

/**
Expand All @@ -648,12 +660,18 @@ export class VisibleTileSet {
* @param dataSource - The data source the tile belongs to.
* @param tileKey - The key identifying the tile.
* @param offset - Tile offset.
* @param frameNumber - Frame in which the tile was requested
* @return The tile if found in cache, undefined otherwise.
*/
getCachedTile(dataSource: DataSource, tileKey: TileKey, offset: number = 0): Tile | undefined {
getCachedTile(
dataSource: DataSource,
tileKey: TileKey,
offset: number,
frameNumber: number
): Tile | undefined {
assert(dataSource.cacheable);
const cacheOnly = true;
return this.getTileImpl(dataSource, tileKey, offset, cacheOnly);
return this.getTileImpl(dataSource, tileKey, offset, cacheOnly, frameNumber);
}

/**
Expand Down Expand Up @@ -1086,27 +1104,28 @@ export class VisibleTileSet {
dataSource: DataSource,
tileKey: TileKey,
offset: number,
cacheOnly: boolean
cacheOnly: boolean,
frameNumber: number
): Tile | undefined {
function updateTile(tileToUpdate?: Tile) {
function touchTile(tileToUpdate?: Tile) {
if (tileToUpdate === undefined) {
return;
}
// Keep the tile from being removed from the cache.
tileToUpdate.frameNumLastRequested = dataSource.mapView.frameNumber;
tileToUpdate.frameNumLastRequested = frameNumber;
}

if (!dataSource.cacheable && !cacheOnly) {
const resultTile = dataSource.getTile(tileKey);
updateTile(resultTile);
touchTile(resultTile);
return resultTile;
}

const tileCache = this.m_dataSourceCache;
let tile = tileCache.get(tileKey.mortonCode(), offset, dataSource);

if (tile !== undefined && tile.offset === offset) {
updateTile(tile);
touchTile(tile);
return tile;
}

Expand All @@ -1118,7 +1137,7 @@ export class VisibleTileSet {
// TODO: Update all tile information including area, min/max elevation from TileKeyEntry
if (tile !== undefined) {
tile.offset = offset;
updateTile(tile);
touchTile(tile);
tileCache.set(tileKey.mortonCode(), offset, dataSource, tile);
this.m_tileGeometryManager.initTile(tile);
}
Expand Down
12 changes: 11 additions & 1 deletion @here/harp-mapview/lib/text/RenderState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,12 +125,22 @@ export class RenderState {
* unchanged.
*
* @param time - Current time.
* @param disableFading - Optional flag to disable fading.
*/
startFadeIn(time: number) {
startFadeIn(time: number, disableFading?: boolean) {
if (this.m_state === FadingState.FadingIn || this.m_state === FadingState.FadedIn) {
return;
}

if (disableFading === true) {
this.value = 1;
this.opacity = 1;
this.m_state = FadingState.FadedIn;
this.startTime = time;

return;
}

if (this.m_state === FadingState.FadingOut) {
// The fadeout is not complete: compute the virtual fadingStartTime in the past, to get
// a correct end time:
Expand Down
6 changes: 3 additions & 3 deletions @here/harp-mapview/lib/text/TextElementsRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1684,7 +1684,7 @@ export class TextElementsRenderer {

if (textNeedsDraw) {
if (!textRejected) {
textRenderState!.startFadeIn(renderParams.time);
textRenderState!.startFadeIn(renderParams.time, this.m_options.disableFading);
}
renderParams.fadeAnimationRunning =
renderParams.fadeAnimationRunning || textRenderState!.isFading();
Expand All @@ -1707,7 +1707,7 @@ export class TextElementsRenderer {
if (iconRejected) {
iconRenderState!.startFadeOut(renderParams.time);
} else {
iconRenderState!.startFadeIn(renderParams.time);
iconRenderState!.startFadeIn(renderParams.time, this.m_options.disableFading);
}

renderParams.fadeAnimationRunning =
Expand Down Expand Up @@ -1952,7 +1952,7 @@ export class TextElementsRenderer {
return false;
}

labelState.textRenderState!.startFadeIn(renderParams.time);
labelState.textRenderState!.startFadeIn(renderParams.time, this.m_options.disableFading);

let opacity = pathLabel.renderStyle!.opacity;

Expand Down
31 changes: 30 additions & 1 deletion @here/harp-mapview/test/FakeOmvDataSource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* SPDX-License-Identifier: Apache-2.0
*/

import { DecodedTile } from "@here/harp-datasource-protocol";
import {
mercatorProjection,
Projection,
Expand All @@ -12,8 +13,34 @@ import {
webMercatorTilingScheme
} from "@here/harp-geoutils";
import { DataSource, DataSourceOptions } from "../lib/DataSource";
import { Tile } from "../lib/Tile";
import { ITileLoader, Tile, TileLoaderState } from "../lib/Tile";

export class FakeTileLoader implements ITileLoader {
state: TileLoaderState = TileLoaderState.Initialized;
payload?: ArrayBufferLike | {};
decodedTile?: DecodedTile = {
techniques: [],
geometries: []
};

isFinished: boolean = false;

loadAndDecode(): Promise<TileLoaderState> {
return Promise.resolve(TileLoaderState.Ready);
}

waitSettled(): Promise<TileLoaderState> {
return Promise.resolve(TileLoaderState.Ready);
}

updatePriority(area: number): void {
// Not covered with tests yet
}

cancel(): void {
// Not covered with tests yet
}
}
export class FakeOmvDataSource extends DataSource {
constructor(options: DataSourceOptions) {
super(options);
Expand All @@ -32,6 +59,8 @@ export class FakeOmvDataSource extends DataSource {
/** @override */
getTile(tileKey: TileKey): Tile {
const tile = new Tile(this, tileKey);
tile.tileLoader = new FakeTileLoader();
tile.load();
return tile;
}
/** @override */
Expand Down
33 changes: 32 additions & 1 deletion @here/harp-mapview/test/MapViewTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,9 @@ describe("MapView", function() {
const theGlobal: any = global;
theGlobal.window = { window: { devicePixelRatio: 10 } };
theGlobal.navigator = {};
theGlobal.requestAnimationFrame = () => {};
theGlobal.requestAnimationFrame = (callback: (time: DOMHighResTimeStamp) => void) => {
setTimeout(callback, 0);
};
}
addEventListenerSpy = sinon.stub();
removeEventListenerSpy = sinon.stub();
Expand Down Expand Up @@ -1008,4 +1010,33 @@ describe("MapView", function() {
});
});
});

describe("frame complete", function() {
it("MapView emits frame complete for empty map", async function() {
this.timeout(100);
mapView = new MapView({ canvas });
return waitForEvent(mapView, MapViewEventNames.FrameComplete);
});
it("MapView emits frame complete after map initialized", async function() {
this.timeout(100);
mapView = new MapView({ canvas });

const dataSource = new FakeOmvDataSource({ name: "omv" });
mapView.addDataSource(dataSource);

return waitForEvent(mapView, MapViewEventNames.FrameComplete);
});
it("MapView emits frame complete again after map update", async function() {
this.timeout(100);
mapView = new MapView({ canvas });

const dataSource = new FakeOmvDataSource({ name: "omv" });
mapView.addDataSource(dataSource);

await waitForEvent(mapView, MapViewEventNames.FrameComplete);

mapView.update();
return waitForEvent(mapView, MapViewEventNames.FrameComplete);
});
});
});
10 changes: 10 additions & 0 deletions @here/harp-mapview/test/RenderStateTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,16 @@ describe("RenderState", function() {
expect(renderState.opacity).to.equal(0.0);
});

it("fade in transitions to final state if fading disabled", function() {
const renderState = new RenderState();
renderState.startFadeIn(100, true);

expect(renderState.isFadedIn()).to.be.true;
expect(renderState.startTime).to.equal(100);
expect(renderState.value).to.equal(1.0);
expect(renderState.opacity).to.equal(1.0);
});

it("does not change an already fading in state", function() {
const renderState = new RenderState();
renderState.startFadeIn(100);
Expand Down
Loading

0 comments on commit 1325606

Please sign in to comment.