right shift -> place from historical view
This commit is contained in:
parent
e4a6171666
commit
2d0c31fac6
|
@ -37,7 +37,8 @@ const HelpModal = () => (
|
||||||
<p className="modaltext">Drag mouse to move</p>
|
<p className="modaltext">Drag mouse to move</p>
|
||||||
<p className="modaltext">Scroll mouse wheel to zoom</p>
|
<p className="modaltext">Scroll mouse wheel to zoom</p>
|
||||||
<p className="modaltext">Click middle mouse button to current hovering color</p>
|
<p className="modaltext">Click middle mouse button to current hovering color</p>
|
||||||
<p className="modaltext">Hold shift for placing while moving mouse</p>
|
<p className="modaltext">Hold left shift for placing while moving mouse</p>
|
||||||
|
<p className="modaltext">Hold right shift for placing while moving mouse according to historical view</p>
|
||||||
<p className="modaltext">Pinch to zoom (on touch devices)</p>
|
<p className="modaltext">Pinch to zoom (on touch devices)</p>
|
||||||
<p className="modaltext">Pan to move (on touch devices)</p>
|
<p className="modaltext">Pan to move (on touch devices)</p>
|
||||||
<p className="modaltext">Click or tap to place a pixel</p>
|
<p className="modaltext">Click or tap to place a pixel</p>
|
||||||
|
|
|
@ -61,8 +61,13 @@ class PixelPlainterControls {
|
||||||
this.isMultiTab = false;
|
this.isMultiTab = false;
|
||||||
// on touch: timeout to detect long-press
|
// on touch: timeout to detect long-press
|
||||||
this.tapTimeout = null;
|
this.tapTimeout = null;
|
||||||
// if we are shift-hold-painting
|
/*
|
||||||
this.holdPainting = false;
|
* if we are shift-hold-painting
|
||||||
|
* 0: no
|
||||||
|
* 1: left shift
|
||||||
|
* 2: right shift
|
||||||
|
*/
|
||||||
|
this.holdPainting = 0;
|
||||||
// if we are waiting before placeing pixel via holdPainting again
|
// if we are waiting before placeing pixel via holdPainting again
|
||||||
this.coolDownDelta = false;
|
this.coolDownDelta = false;
|
||||||
|
|
||||||
|
@ -162,14 +167,20 @@ class PixelPlainterControls {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
static placePixel(store, renderer, cell) {
|
/*
|
||||||
|
* place pixel
|
||||||
|
* either with given colorIndex or with selected color if none is given
|
||||||
|
*/
|
||||||
|
static placePixel(store, renderer, cell, colorIndex = null) {
|
||||||
const state = store.getState();
|
const state = store.getState();
|
||||||
const { autoZoomIn } = state.gui;
|
const { autoZoomIn } = state.gui;
|
||||||
const {
|
const {
|
||||||
scale,
|
scale,
|
||||||
isHistoricalView,
|
isHistoricalView,
|
||||||
selectedColor,
|
|
||||||
} = state.canvas;
|
} = state.canvas;
|
||||||
|
const selectedColor = (colorIndex === null)
|
||||||
|
? state.canvas.selectedColor
|
||||||
|
: colorIndex;
|
||||||
|
|
||||||
if (isHistoricalView) return;
|
if (isHistoricalView) return;
|
||||||
|
|
||||||
|
@ -393,16 +404,42 @@ class PixelPlainterControls {
|
||||||
|| y < -maxCoords || y >= maxCoords
|
|| y < -maxCoords || y >= maxCoords
|
||||||
) {
|
) {
|
||||||
if (hover) {
|
if (hover) {
|
||||||
store.dispatch(unsetHover(screenCoor));
|
store.dispatch(unsetHover());
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hover || hover[0] !== x || hover[1] !== y) {
|
if (!hover || hover[0] !== x || hover[1] !== y) {
|
||||||
store.dispatch(setHover(screenCoor));
|
store.dispatch(setHover(screenCoor));
|
||||||
}
|
/* shift placing */
|
||||||
if (this.holdPainting && !this.coolDownDelta) {
|
if (!this.coolDownDelta) {
|
||||||
PixelPlainterControls.placePixel(store, this.renderer, screenCoor);
|
switch (this.holdPainting) {
|
||||||
|
case 1: {
|
||||||
|
/* left shift: from selected color */
|
||||||
|
PixelPlainterControls.placePixel(
|
||||||
|
store,
|
||||||
|
this.renderer,
|
||||||
|
screenCoor,
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2: {
|
||||||
|
/* right shift: from historical view */
|
||||||
|
const colorIndex = this.renderer
|
||||||
|
.getColorIndexOfPixel(x, y, true);
|
||||||
|
if (colorIndex !== null) {
|
||||||
|
PixelPlainterControls.placePixel(
|
||||||
|
store,
|
||||||
|
this.renderer,
|
||||||
|
screenCoor,
|
||||||
|
colorIndex,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -412,7 +449,7 @@ class PixelPlainterControls {
|
||||||
viewport.style.cursor = 'auto';
|
viewport.style.cursor = 'auto';
|
||||||
store.dispatch(unsetHover());
|
store.dispatch(unsetHover());
|
||||||
store.dispatch(onViewFinishChange());
|
store.dispatch(onViewFinishChange());
|
||||||
this.holdPainting = false;
|
this.holdPainting = 0;
|
||||||
this.clearTabTimeout();
|
this.clearTabTimeout();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -448,7 +485,7 @@ class PixelPlainterControls {
|
||||||
switch (event.key) {
|
switch (event.key) {
|
||||||
case 'Shift':
|
case 'Shift':
|
||||||
case 'CapsLock':
|
case 'CapsLock':
|
||||||
this.holdPainting = false;
|
this.holdPainting = 0;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
@ -496,19 +533,28 @@ class PixelPlainterControls {
|
||||||
if (event.key === 'Control') {
|
if (event.key === 'Control') {
|
||||||
// ctrl
|
// ctrl
|
||||||
const clrIndex = this.renderer.getColorIndexOfPixel(...hover);
|
const clrIndex = this.renderer.getColorIndexOfPixel(...hover);
|
||||||
if (clrIndex !== null) {
|
store.dispatch(selectColor(clrIndex));
|
||||||
store.dispatch(selectColor(clrIndex));
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (event.location === KeyboardEvent.DOM_KEY_LOCATION_LEFT) {
|
if (event.location === KeyboardEvent.DOM_KEY_LOCATION_LEFT) {
|
||||||
// left shift
|
// left shift
|
||||||
this.holdPainting = true;
|
this.holdPainting = 1;
|
||||||
PixelPlainterControls.placePixel(store, this.renderer, hover);
|
PixelPlainterControls.placePixel(store, this.renderer, hover);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (event.location === KeyboardEvent.DOM_KEY_LOCATION_RIGHT) {
|
if (event.location === KeyboardEvent.DOM_KEY_LOCATION_RIGHT) {
|
||||||
// right shift
|
// right shift
|
||||||
|
this.holdPainting = 2;
|
||||||
|
const colorIndex = this.renderer
|
||||||
|
.getColorIndexOfPixel(...hover, true);
|
||||||
|
if (colorIndex !== null) {
|
||||||
|
PixelPlainterControls.placePixel(
|
||||||
|
store,
|
||||||
|
this.renderer,
|
||||||
|
hover,
|
||||||
|
colorIndex,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -77,6 +77,46 @@ class ChunkLoader {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get color of pixel in current historical view
|
||||||
|
* @param x, y world coordiantes of pixel
|
||||||
|
* @return ColorIndex or null if chunks not loaded or historical view not set
|
||||||
|
*/
|
||||||
|
getHistoricalIndexOfPixel(
|
||||||
|
x: number,
|
||||||
|
y: number,
|
||||||
|
) {
|
||||||
|
const state: State = this.store.getState();
|
||||||
|
const { canvasSize, historicalDate, historicalTime } = state.canvas;
|
||||||
|
if (!historicalDate) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const [cx, cy] = getChunkOfPixel(canvasSize, x, y);
|
||||||
|
const px = getCellInsideChunk(canvasSize, [x, y]);
|
||||||
|
const curTime = Date.now();
|
||||||
|
|
||||||
|
if (!historicalTime || historicalTime !== '0000') {
|
||||||
|
// eslint-disable-next-line max-len
|
||||||
|
const incrementialChunkKey = `${historicalDate}${historicalTime}:${cx}:${cy}`;
|
||||||
|
const incrementialChunk = this.chunks.get(incrementialChunkKey);
|
||||||
|
if (incrementialChunk) {
|
||||||
|
const incrementialColor = incrementialChunk.getColorIndex(px);
|
||||||
|
incrementialChunk.timestamp = curTime;
|
||||||
|
if (incrementialColor !== null) {
|
||||||
|
return incrementialColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const chunkKey = `${historicalDate}:${cx}:${cy}`;
|
||||||
|
const chunk = this.chunks.get(chunkKey);
|
||||||
|
if (!chunk) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
chunk.timestamp = curTime;
|
||||||
|
return chunk.getColorIndex(px);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* preLoad chunks by generating them out of
|
* preLoad chunks by generating them out of
|
||||||
* available lower zoomlevel chunks
|
* available lower zoomlevel chunks
|
||||||
|
|
|
@ -146,8 +146,10 @@ class Renderer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getColorIndexOfPixel(cx, cy) {
|
getColorIndexOfPixel(cx, cy, historical: boolean = false) {
|
||||||
return this.chunkLoader.getColorIndexOfPixel(cx, cy);
|
return (historical)
|
||||||
|
? this.chunkLoader.getHistoricalIndexOfPixel(cx, cy)
|
||||||
|
: this.chunkLoader.getColorIndexOfPixel(cx, cy);
|
||||||
}
|
}
|
||||||
|
|
||||||
updateScale(
|
updateScale(
|
||||||
|
|
Loading…
Reference in New Issue
Block a user