hook up settings
This commit is contained in:
parent
47b4db2602
commit
ff7ec9b0e9
|
@ -3,21 +3,38 @@
|
|||
*/
|
||||
|
||||
import React, { useState, useCallback, useRef } from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { useSelector, useDispatch, shallowEqual } from 'react-redux';
|
||||
import fileDownload from 'js-file-download';
|
||||
import { t } from 'ttag';
|
||||
import { c, t } from 'ttag';
|
||||
|
||||
import TemplateItem from './TemplateItem';
|
||||
import TemplateItemEdit from './TemplateItemEdit';
|
||||
import SettingsItem from './SettingsItem';
|
||||
import templateLoader from '../ui/templateLoader';
|
||||
import {
|
||||
toggleOVEnabled,
|
||||
toggleSmallPxls,
|
||||
setOvOpacity,
|
||||
} from '../store/actions/templates';
|
||||
|
||||
|
||||
const TemplateSettings = () => {
|
||||
const [showAdd, setShowAdd] = useState(false);
|
||||
const list = useSelector((state) => state.templates.list);
|
||||
const [
|
||||
list,
|
||||
oVEnabled,
|
||||
oSmallPxls,
|
||||
oOpacity,
|
||||
] = useSelector((state) => [
|
||||
state.templates.list,
|
||||
state.templates.ovEnabled,
|
||||
state.templates.oSmallPxls,
|
||||
state.templates.oOpacity,
|
||||
], shallowEqual);
|
||||
const [editingIndices, setEditingIndices] = useState([]);
|
||||
const close = useCallback(() => setShowAdd(false), []);
|
||||
const importRef = useRef();
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const toggleEditing = useCallback((title) => {
|
||||
const index = list.findIndex((t) => t.title === title);
|
||||
|
@ -32,10 +49,48 @@ const TemplateSettings = () => {
|
|||
|
||||
return (
|
||||
<>
|
||||
<h3>{t`Templates`}</h3>
|
||||
<h2>{t`Templates`}</h2>
|
||||
<p>
|
||||
{t`Tired of always spaming one single color? Want to create art instead, but you have to count pixels from some other image? Templates can help you with that! Templates can show as overlay and you can draw over them. One pixel on the template, should be one pixel on the canvas.`}
|
||||
</p>
|
||||
<SettingsItem
|
||||
title={t`Enable Overlay`}
|
||||
keyBind={c('keybinds').t`T`}
|
||||
value={oVEnabled}
|
||||
onToggle={() => dispatch(toggleOVEnabled())}
|
||||
>
|
||||
{t`Show templates as overlays ingame.`}
|
||||
</SettingsItem>
|
||||
<SettingsItem
|
||||
title={t`Small Pixels Overlay`}
|
||||
value={oSmallPxls}
|
||||
deactivated={!oVEnabled}
|
||||
onToggle={() => dispatch(toggleSmallPxls())}
|
||||
>
|
||||
{t`Show overlay as small individual pixels (will only show in high zoomlevels).`}
|
||||
</SettingsItem>
|
||||
|
||||
<div className="setitem">
|
||||
<div className="setrow">
|
||||
<h3 className="settitle">
|
||||
{t`Overlay Opacity`}
|
||||
</h3>
|
||||
<div style={{ textAlign: 'right' }}>
|
||||
<input
|
||||
type="number"
|
||||
value={oOpacity}
|
||||
style={{ maxWidth: '6em' }}
|
||||
step="1"
|
||||
min="10"
|
||||
max="100"
|
||||
onChange={(evt) => dispatch(setOvOpacity(evt.target.value))}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="modaldesc">{t`Opacity of Overlay in percent.`}</div>
|
||||
<div className="modaldivider" />
|
||||
</div>
|
||||
|
||||
<div className="content">
|
||||
{list.map(({
|
||||
enabled, imageId, canvasId, title, x, y, width, height,
|
||||
|
|
|
@ -16,9 +16,11 @@ const PencilButton = () => {
|
|||
const [
|
||||
holdPaint,
|
||||
showMvmCtrls,
|
||||
easterEgg,
|
||||
] = useSelector((state) => [
|
||||
state.gui.holdPaint,
|
||||
state.gui.showMvmCtrls,
|
||||
state.gui.easterEgg,
|
||||
], shallowEqual);
|
||||
const dispatch = useDispatch();
|
||||
|
||||
|
@ -34,7 +36,7 @@ const PencilButton = () => {
|
|||
}
|
||||
// eslint-disable-next-line no-fallthrough
|
||||
case HOLD_PAINT.HISTORY:
|
||||
if (window.let_me_cheat) {
|
||||
if (easterEgg) {
|
||||
nextMode = HOLD_PAINT.OVERLAY;
|
||||
dispatch(notify(t`Overlay Pencil ON`));
|
||||
break;
|
||||
|
|
|
@ -21,6 +21,7 @@ import {
|
|||
import {
|
||||
HOLD_PAINT,
|
||||
} from '../core/constants';
|
||||
import templateLoader from '../ui/templateLoader';
|
||||
|
||||
class PixelPainterControls {
|
||||
store;
|
||||
|
@ -413,6 +414,13 @@ class PixelPainterControls {
|
|||
if (state.gui.holdPaint === HOLD_PAINT.HISTORY) {
|
||||
return renderer.getColorIndexOfPixel(...cell, true);
|
||||
}
|
||||
if (state.gui.holdPaint === HOLD_PAINT.OVERLAY) {
|
||||
const rgb = templateLoader.getColorOfPixel(...cell);
|
||||
if (!rgb) {
|
||||
return null;
|
||||
}
|
||||
return state.canvas.palette.getIndexOfColor(...rgb);
|
||||
}
|
||||
return state.canvas.selectedColor;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,10 +17,13 @@ import {
|
|||
setMoveV,
|
||||
setMoveW,
|
||||
} from '../store/actions';
|
||||
import {
|
||||
toggleOVEnabled,
|
||||
} from '../store/actions/templates';
|
||||
import { HOLD_PAINT } from '../core/constants';
|
||||
import { notify } from '../store/actions/thunks';
|
||||
|
||||
const charKeys = ['g', 'h', 'x', 'm', 'r', 'z', '+', '-'];
|
||||
const charKeys = ['g', 'h', 'x', 'm', 't', 'r', 'z', '+', '-'];
|
||||
|
||||
export function createKeyUpHandler(store) {
|
||||
return (event) => {
|
||||
|
@ -149,7 +152,10 @@ export function createKeyDownHandler(store) {
|
|||
}
|
||||
if (event.location === KeyboardEvent.DOM_KEY_LOCATION_RIGHT) {
|
||||
// right shift
|
||||
store.dispatch(selectHoldPaint(HOLD_PAINT.HISTORY, true));
|
||||
store.dispatch(selectHoldPaint(
|
||||
(store.getState().gui.easterEgg) ? HOLD_PAINT.OVERLAY : HOLD_PAINT.HISTORY,
|
||||
true,
|
||||
));
|
||||
return;
|
||||
}
|
||||
return;
|
||||
|
@ -204,6 +210,13 @@ export function createKeyDownHandler(store) {
|
|||
store.dispatch(notify(t`Copied!`));
|
||||
return;
|
||||
}
|
||||
case 't': {
|
||||
store.dispatch(toggleOVEnabled());
|
||||
store.dispatch(notify((store.getState().templates.ovEnabled)
|
||||
? t`Overlay ON`
|
||||
: t`Overlay OFF`));
|
||||
return;
|
||||
}
|
||||
case 'z':
|
||||
store.dispatch(toggleEasterEgg());
|
||||
store.dispatch(notify((store.getState().gui.easterEgg)
|
||||
|
|
|
@ -696,7 +696,7 @@ export function bufferToBase64(array) {
|
|||
|
||||
reader.onload = (event) => {
|
||||
const dataUrl = event.target.result;
|
||||
const [_, base64] = dataUrl.split(',');
|
||||
const [, base64] = dataUrl.split(',');
|
||||
|
||||
resolve(base64);
|
||||
};
|
||||
|
|
|
@ -15,7 +15,7 @@ export function listTemplate(imageId, title, canvasId, x, y, width, height) {
|
|||
};
|
||||
}
|
||||
|
||||
export function templatesReady(title) {
|
||||
export function templatesReady() {
|
||||
return {
|
||||
type: 'TEMPLATES_READY',
|
||||
};
|
||||
|
@ -36,8 +36,32 @@ export function changeTemplate(title, props) {
|
|||
};
|
||||
}
|
||||
|
||||
export function toggleOVEnabled() {
|
||||
return {
|
||||
type: 's/TGL_OVENABLED',
|
||||
};
|
||||
}
|
||||
|
||||
export function toggleSmallPxls() {
|
||||
return {
|
||||
type: 's/TGL_SMALLPXLS',
|
||||
};
|
||||
}
|
||||
|
||||
export function setOvOpacity(opacity) {
|
||||
return {
|
||||
type: 's/SET_O_OPACITY',
|
||||
opacity,
|
||||
};
|
||||
}
|
||||
|
||||
export function receivedTemplate() {
|
||||
return {
|
||||
type: 'REC_TEMPLATE',
|
||||
};
|
||||
}
|
||||
|
||||
export function updatedTemplateImage(imageId, width, height) {
|
||||
console.log('update', width, height, 'store');
|
||||
return {
|
||||
type: 's/UPD_TEMPLATE_IMG',
|
||||
imageId,
|
||||
|
|
|
@ -105,6 +105,13 @@ export default (store) => (next) => (action) => {
|
|||
break;
|
||||
}
|
||||
|
||||
case 's/CHG_TEMPLATE':
|
||||
case 's/TGL_OVENABLED':
|
||||
case 's/TGL_SMALLPXLS':
|
||||
case 's/REM_TEMPLATE':
|
||||
case 's/UPD_TEMPLATE_IMG':
|
||||
case 's/SET_O_OPACITY':
|
||||
//
|
||||
case 'REQ_BIG_CHUNK':
|
||||
case 'PRE_LOADED_BIG_CHUNK':
|
||||
case 'REC_BIG_CHUNK':
|
||||
|
|
|
@ -7,7 +7,7 @@ const initialState = {
|
|||
// prefix o: overlay, m: minimap
|
||||
ovEnabled: false,
|
||||
mEnabled: false,
|
||||
oOpacity: 1.0,
|
||||
oOpacity: 70,
|
||||
oSmallPxls: false,
|
||||
/*
|
||||
* [{
|
||||
|
@ -100,6 +100,24 @@ export default function templates(
|
|||
};
|
||||
}
|
||||
|
||||
case 's/TGL_OVENABLED':
|
||||
return {
|
||||
...state,
|
||||
ovEnabled: !state.ovEnabled,
|
||||
};
|
||||
|
||||
case 's/TGL_SMALLPXLS':
|
||||
return {
|
||||
...state,
|
||||
oSmallPxls: !state.oSmallPxls,
|
||||
};
|
||||
|
||||
case 's/SET_O_OPACITY':
|
||||
return {
|
||||
...state,
|
||||
oOpacity: action.opacity,
|
||||
};
|
||||
|
||||
case 'TEMPLATES_READY':
|
||||
return {
|
||||
...state,
|
||||
|
|
|
@ -422,8 +422,8 @@ class Renderer2D extends Renderer {
|
|||
}
|
||||
}
|
||||
context.restore();
|
||||
// TODO conditions
|
||||
if (false) {
|
||||
|
||||
if (state.templates.ovEnabled && !state.templates.oSmallPxls) {
|
||||
renderOverlay(
|
||||
state, this.canvas, chunkPosition, scale,
|
||||
this.tiledScale, this.scaleThreshold,
|
||||
|
@ -554,8 +554,9 @@ class Renderer2D extends Renderer {
|
|||
);
|
||||
}
|
||||
|
||||
// TODO conditions
|
||||
if (viewscale >= 5) {
|
||||
if (viewscale >= 5 && state.templates.ovEnabled
|
||||
&& state.templates.oSmallPxls
|
||||
) {
|
||||
renderSmallPOverlay(viewport, _view, viewscale);
|
||||
}
|
||||
|
||||
|
|
|
@ -113,6 +113,7 @@ export function renderOverlay(
|
|||
tiledScale,
|
||||
scaleThreshold,
|
||||
) {
|
||||
if (!templateLoader.ready) return;
|
||||
const { canvasSize } = state.canvas;
|
||||
// world coordinates of center of center chunk
|
||||
const [x, y] = centerChunk
|
||||
|
@ -135,6 +136,7 @@ export function renderOverlay(
|
|||
|
||||
context.save();
|
||||
context.scale(offscreenScale, offscreenScale);
|
||||
context.globalAlpha = state.templates.oOpacity / 100;
|
||||
for (const template of templates) {
|
||||
const image = templateLoader.getTemplateSync(template.imageId);
|
||||
if (!image) continue;
|
||||
|
@ -156,6 +158,7 @@ export function renderSmallPOverlay(
|
|||
view,
|
||||
scale,
|
||||
) {
|
||||
if (!templateLoader.ready) return;
|
||||
const [x, y] = view;
|
||||
const { width, height } = $viewport;
|
||||
const horizontalRadius = width / 2 / scale;
|
||||
|
|
|
@ -9,6 +9,7 @@ import {
|
|||
updatedTemplateImage,
|
||||
changeTemplate,
|
||||
templatesReady,
|
||||
receivedTemplate,
|
||||
} from '../store/actions/templates';
|
||||
import { bufferToBase64, base64ToBuffer } from '../core/utils';
|
||||
import Template from './Template';
|
||||
|
@ -76,21 +77,39 @@ class TemplateLoader {
|
|||
return null;
|
||||
}
|
||||
|
||||
getColorOfPixel(x, y) {
|
||||
const templatesInView = this.#store.getState().templates.list
|
||||
.filter((template) => (
|
||||
template.enabled && template.x < x && template.y < y
|
||||
&& template.x + template.width > x
|
||||
&& template.y + template.height > y
|
||||
));
|
||||
|
||||
for (const tData of templatesInView) {
|
||||
const image = this.getTemplateSync(tData.imageId);
|
||||
if (!image) {
|
||||
continue;
|
||||
}
|
||||
const ctx = image.getContext('2d');
|
||||
const rgb = ctx.getImageData(x - tData.x, y - tData.y, 1, 1).data;
|
||||
if (rgb[3] > 200) {
|
||||
return [rgb[0], rgb[1], rgb[2]];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
getTemplatesInView(x, y, horizontalRadius, verticalRadius) {
|
||||
const topX = x - horizontalRadius;
|
||||
const topY = y - verticalRadius;
|
||||
const bottomX = x + horizontalRadius;
|
||||
const bottomY = y + verticalRadius;
|
||||
|
||||
const templates = [];
|
||||
this.#store.getState().templates.list.forEach((template) => {
|
||||
if (x < bottomX && y < bottomY
|
||||
&& x + template.width > topX && y + template.height > topY
|
||||
) {
|
||||
templates.push(template);
|
||||
}
|
||||
});
|
||||
return templates;
|
||||
return this.#store.getState().templates.list.filter((template) => (
|
||||
template.enabled && template.x < bottomX && template.y < bottomY
|
||||
&& template.x + template.width > topX
|
||||
&& template.y + template.height > topY
|
||||
));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -141,6 +160,7 @@ class TemplateLoader {
|
|||
const template = new Template(imageId);
|
||||
await template.fromBuffer(buffer, mimetype);
|
||||
this.#templates.set(imageId, template);
|
||||
this.#store.dispatch(receivedTemplate());
|
||||
return template;
|
||||
} catch (err) {
|
||||
// eslint-disable-next-line no-console
|
||||
|
|
Loading…
Reference in New Issue
Block a user