diff --git a/promotion/can-you-do-zuckerberg.png b/promotion/can-you-do-zuckerberg.png deleted file mode 100644 index 14a5556..0000000 Binary files a/promotion/can-you-do-zuckerberg.png and /dev/null differ diff --git a/src/controls/VoxelPainterControls.js b/src/controls/VoxelPainterControls.js index edd63c5..c04f049 100644 --- a/src/controls/VoxelPainterControls.js +++ b/src/controls/VoxelPainterControls.js @@ -799,6 +799,13 @@ class VoxelPainterControls extends EventDispatcher { state = STATE.NONE; }; + this.setView = (view) => { + if (view.length !== 3) { + return; + } + scope.target.set(...view); + }; + // this method is exposed, but perhaps it would be better if we can make it private... this.update = (() => { const offset = new Vector3(); diff --git a/src/core/constants.js b/src/core/constants.js index 6876390..113e285 100644 --- a/src/core/constants.js +++ b/src/core/constants.js @@ -50,6 +50,7 @@ export const DEFAULT_CANVASES = { [207, 110, 228], [130, 0, 128], ], + cli: 2, size: 65536, bcd: 4000, pcd: 7000, diff --git a/src/reducers/canvas.js b/src/reducers/canvas.js index 11b3c4d..aab827a 100644 --- a/src/reducers/canvas.js +++ b/src/reducers/canvas.js @@ -43,7 +43,7 @@ export type CanvasState = { */ function getGivenCoords() { // if (window.coordx && window.coordy) return [window.coordx, window.coordy]; - return [0, 0]; + return [0, 0, 0]; } /* @@ -61,41 +61,40 @@ function getViewFromURL(canvases: Object) { // will be null if not in DEFAULT_CANVASES const canvasId = getIdFromObject(canvases, almost[0]); - let colors; - let clrIgnore; - let canvasSize; - let canvasStartDate; - let is3D; - if (canvasId == null) { - // if canvas informations are not available yet - // aka /api/me didn't load yet - colors = canvases[DEFAULT_CANVAS_ID].colors; - clrIgnore = 2; - canvasSize = 1024; - is3D = false; - canvasStartDate = null; - } else { - const canvas = canvases[canvasId]; - colors = canvas.colors; - clrIgnore = canvas.cli; - canvasSize = canvas.size; - is3D = !!canvas.v; - canvasStartDate = canvas.sd; - } + // canvasId is null if canvas data isn't loaded yet and it's not + // the default canvas. + // aka those few milliseconds before /api/me + const canvas = (canvasId === null) + ? canvases[DEFAULT_CANVAS_ID] + : canvases[canvasId]; + const { + colors, + cli: clrIgnore, + sd: canvasStartDate, + size: canvasSize, + } = canvas; + const is3D = !!canvas.v; const x = parseInt(almost[1], 10); const y = parseInt(almost[2], 10); - let urlscale = parseInt(almost[3], 10); + const z = parseInt(almost[3], 10); if (Number.isNaN(x) || Number.isNaN(y)) { - const thrown = 'NaN'; - throw thrown; + throw new Error('NaN'); } - if (!urlscale || Number.isNaN(urlscale)) { - urlscale = DEFAULT_SCALE; + const view = [x, y, z]; + + let scale = z; + if (!scale || Number.isNaN(scale)) { + scale = DEFAULT_SCALE; } else { - urlscale = 2 ** (urlscale / 10); + scale = 2 ** (scale / 10); } - urlscale = clamp(urlscale, TILE_SIZE / canvasSize, MAX_SCALE); + + if (!is3D && canvasId !== null) { + scale = clamp(scale, TILE_SIZE / canvasSize, MAX_SCALE); + view.length = 2; + } + return { canvasId, canvasIdent, @@ -105,22 +104,22 @@ function getViewFromURL(canvases: Object) { canvasMaxTiledZoom: getMaxTiledZoom(canvasSize), palette: new Palette(colors, 0), clrIgnore, - view: [x, y], - viewscale: urlscale, - scale: urlscale, + view, + viewscale: scale, + scale, canvases, }; } catch (error) { - const canvas = canvases[DEFAULT_CANVAS_ID]; + const canvasd = canvases[DEFAULT_CANVAS_ID]; return { canvasId: DEFAULT_CANVAS_ID, - canvasIdent: canvas.ident, - canvasSize: canvas.size, - is3D: !!canvas.v, + canvasIdent: canvasd.ident, + canvasSize: canvasd.size, + is3D: !!canvasd.v, canvasStartDate: null, - canvasMaxTiledZoom: getMaxTiledZoom(canvas.size), - palette: new Palette(canvas.colors, 0), - clrIgnore: canvas.cli, + canvasMaxTiledZoom: getMaxTiledZoom(canvasd.size), + palette: new Palette(canvasd.colors, 0), + clrIgnore: canvasd.cli, view: getGivenCoords(), viewscale: DEFAULT_SCALE, scale: DEFAULT_SCALE, @@ -275,7 +274,10 @@ export default function canvasReducer( } = canvas; const canvasMaxTiledZoom = getMaxTiledZoom(canvasSize); const palette = new Palette(colors, 0); - const view = (canvasId === 0) ? getGivenCoords() : [0, 0]; + const view = (canvasId === 0) ? getGivenCoords() : [0, 0, 0]; + if (!is3D) { + view.length = 2; + } return { ...state, canvasId, @@ -295,7 +297,7 @@ export default function canvasReducer( case 'RECEIVE_ME': { const { canvases } = action; - let { canvasIdent } = state; + let { canvasIdent, scale, view } = state; let canvasId = getIdFromObject(canvases, canvasIdent); if (canvasId === null) { @@ -312,6 +314,11 @@ export default function canvasReducer( const canvasMaxTiledZoom = getMaxTiledZoom(canvasSize); const palette = new Palette(colors, 0); + if (!is3D) { + scale = clamp(scale, TILE_SIZE / canvasSize, MAX_SCALE); + view = [view[0], view[1]]; + } + return { ...state, canvasId, @@ -323,6 +330,9 @@ export default function canvasReducer( palette, clrIgnore, canvases, + viewscale: scale, + scale, + view, }; } diff --git a/src/store/title.js b/src/store/title.js index 3626fef..44cbcd7 100644 --- a/src/store/title.js +++ b/src/store/title.js @@ -32,6 +32,7 @@ export default (store) => (next) => (action) => { case 'SELECT_CANVAS': + case 'RECEIVE_ME': case 'ON_VIEW_FINISH_CHANGE': { const { view, diff --git a/src/ui/Renderer3D.js b/src/ui/Renderer3D.js index 859ee37..5719e81 100644 --- a/src/ui/Renderer3D.js +++ b/src/ui/Renderer3D.js @@ -50,7 +50,6 @@ class Renderer { this.store = store; const state = store.getState(); this.objects = []; - this.loadedChunks = new Map(); this.chunkLoader = null; // camera @@ -193,6 +192,7 @@ class Renderer { updateCanvasData(state: State) { const { canvasId, + view, } = state.canvas; if (canvasId !== this.canvasId) { this.canvasId = canvasId; @@ -200,16 +200,20 @@ class Renderer { if (this.chunkLoader) { // destroy old chunks, // meshes need to get disposed - this.loadedChunks.forEach((chunk) => { - this.scene.remove(chunk); - this.objects = [this.plane]; - }); - this.chunkLoader.destructor(); + if (this.loadedChunks) { + this.loadedChunks.forEach((chunk) => { + this.scene.remove(chunk); + this.objects = [this.plane]; + }); + this.chunkLoader.destructor(); + } } + this.loadedChunks = new Map(); this.chunkLoader = new ChunkLoader(this.store); - this.forceNextRender = true; } } + this.controls.setView(view); + this.forceNextRender = true; } // eslint-disable-next-line class-methods-use-this