fix(gui): reduce rendering when adjusting image controls
This commit is contained in:
parent
5d2c22a64a
commit
4615614e5e
|
@ -3,10 +3,11 @@ import { Casino } from '@mui/icons-material';
|
||||||
import { Button, Stack, TextField } from '@mui/material';
|
import { Button, Stack, TextField } from '@mui/material';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { useQuery } from 'react-query';
|
import { useQuery } from 'react-query';
|
||||||
|
import { useStore } from 'zustand';
|
||||||
|
|
||||||
import { BaseImgParams } from '../client.js';
|
import { BaseImgParams } from '../client.js';
|
||||||
import { ConfigParams, STALE_TIME } from '../config.js';
|
import { ConfigParams, STALE_TIME } from '../config.js';
|
||||||
import { ClientContext } from '../state.js';
|
import { ClientContext, OnnxState, StateContext } from '../state.js';
|
||||||
import { SCHEDULER_LABELS } from '../strings.js';
|
import { SCHEDULER_LABELS } from '../strings.js';
|
||||||
import { NumericField } from './NumericField.js';
|
import { NumericField } from './NumericField.js';
|
||||||
import { QueryList } from './QueryList.js';
|
import { QueryList } from './QueryList.js';
|
||||||
|
@ -15,7 +16,8 @@ const { useContext } = React;
|
||||||
|
|
||||||
export interface ImageControlProps {
|
export interface ImageControlProps {
|
||||||
config: ConfigParams;
|
config: ConfigParams;
|
||||||
params: BaseImgParams;
|
|
||||||
|
selector: (state: OnnxState) => BaseImgParams;
|
||||||
|
|
||||||
onChange?: (params: BaseImgParams) => void;
|
onChange?: (params: BaseImgParams) => void;
|
||||||
}
|
}
|
||||||
|
@ -24,7 +26,10 @@ export interface ImageControlProps {
|
||||||
* doesn't need to use state, the parent component knows which params to pass
|
* doesn't need to use state, the parent component knows which params to pass
|
||||||
*/
|
*/
|
||||||
export function ImageControl(props: ImageControlProps) {
|
export function ImageControl(props: ImageControlProps) {
|
||||||
const { config, params } = props;
|
const { config } = props;
|
||||||
|
|
||||||
|
const state = mustExist(useContext(StateContext));
|
||||||
|
const params = useStore(state, props.selector);
|
||||||
|
|
||||||
const client = mustExist(useContext(ClientContext));
|
const client = mustExist(useContext(ClientContext));
|
||||||
const schedulers = useQuery('schedulers', async () => client.schedulers(), {
|
const schedulers = useQuery('schedulers', async () => client.schedulers(), {
|
||||||
|
|
|
@ -24,13 +24,13 @@ export function Img2Img(props: Img2ImgProps) {
|
||||||
const { config, model, platform } = props;
|
const { config, model, platform } = props;
|
||||||
|
|
||||||
async function uploadSource() {
|
async function uploadSource() {
|
||||||
const upscale = state.getState().upscale;
|
const { img2img, upscale } = state.getState();
|
||||||
|
|
||||||
const output = await client.img2img({
|
const output = await client.img2img({
|
||||||
...params,
|
...img2img,
|
||||||
model,
|
model,
|
||||||
platform,
|
platform,
|
||||||
source: mustExist(params.source), // TODO: show an error if this doesn't exist
|
source: mustExist(img2img.source), // TODO: show an error if this doesn't exist
|
||||||
}, upscale);
|
}, upscale);
|
||||||
|
|
||||||
setLoading(output);
|
setLoading(output);
|
||||||
|
@ -43,7 +43,8 @@ export function Img2Img(props: Img2ImgProps) {
|
||||||
});
|
});
|
||||||
|
|
||||||
const state = mustExist(useContext(StateContext));
|
const state = mustExist(useContext(StateContext));
|
||||||
const params = useStore(state, (s) => s.img2img);
|
const source = useStore(state, (s) => s.img2img.source);
|
||||||
|
const strength = useStore(state, (s) => s.img2img.strength);
|
||||||
// eslint-disable-next-line @typescript-eslint/unbound-method
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||||
const setImg2Img = useStore(state, (s) => s.setImg2Img);
|
const setImg2Img = useStore(state, (s) => s.setImg2Img);
|
||||||
// eslint-disable-next-line @typescript-eslint/unbound-method
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||||
|
@ -51,21 +52,19 @@ export function Img2Img(props: Img2ImgProps) {
|
||||||
|
|
||||||
return <Box>
|
return <Box>
|
||||||
<Stack spacing={2}>
|
<Stack spacing={2}>
|
||||||
<ImageInput filter={IMAGE_FILTER} image={params.source} label='Source' onChange={(file) => {
|
<ImageInput filter={IMAGE_FILTER} image={source} label='Source' onChange={(file) => {
|
||||||
setImg2Img({
|
setImg2Img({
|
||||||
source: file,
|
source: file,
|
||||||
});
|
});
|
||||||
}} />
|
}} />
|
||||||
<ImageControl config={config} params={params} onChange={(newParams) => {
|
<ImageControl config={config} selector={(s) => s.img2img} onChange={setImg2Img} />
|
||||||
setImg2Img(newParams);
|
|
||||||
}} />
|
|
||||||
<NumericField
|
<NumericField
|
||||||
decimal
|
decimal
|
||||||
label='Strength'
|
label='Strength'
|
||||||
min={config.strength.min}
|
min={config.strength.min}
|
||||||
max={config.strength.max}
|
max={config.strength.max}
|
||||||
step={config.strength.step}
|
step={config.strength.step}
|
||||||
value={params.strength}
|
value={strength}
|
||||||
onChange={(value) => {
|
onChange={(value) => {
|
||||||
setImg2Img({
|
setImg2Img({
|
||||||
strength: value,
|
strength: value,
|
||||||
|
|
|
@ -35,27 +35,26 @@ export function Inpaint(props: InpaintProps) {
|
||||||
|
|
||||||
async function uploadSource(): Promise<void> {
|
async function uploadSource(): Promise<void> {
|
||||||
// these are not watched by the component, only sent by the mutation
|
// these are not watched by the component, only sent by the mutation
|
||||||
const outpaint = state.getState().outpaint;
|
const { inpaint, outpaint, upscale } = state.getState();
|
||||||
const upscale = state.getState().upscale;
|
|
||||||
|
|
||||||
if (outpaint.enabled) {
|
if (outpaint.enabled) {
|
||||||
const output = await client.outpaint({
|
const output = await client.outpaint({
|
||||||
...params,
|
...inpaint,
|
||||||
...outpaint,
|
...outpaint,
|
||||||
model,
|
model,
|
||||||
platform,
|
platform,
|
||||||
mask: mustExist(params.mask),
|
mask: mustExist(mask),
|
||||||
source: mustExist(params.source),
|
source: mustExist(source),
|
||||||
}, upscale);
|
}, upscale);
|
||||||
|
|
||||||
setLoading(output);
|
setLoading(output);
|
||||||
} else {
|
} else {
|
||||||
const output = await client.inpaint({
|
const output = await client.inpaint({
|
||||||
...params,
|
...inpaint,
|
||||||
model,
|
model,
|
||||||
platform,
|
platform,
|
||||||
mask: mustExist(params.mask),
|
mask: mustExist(mask),
|
||||||
source: mustExist(params.source),
|
source: mustExist(source),
|
||||||
}, upscale);
|
}, upscale);
|
||||||
|
|
||||||
setLoading(output);
|
setLoading(output);
|
||||||
|
@ -63,7 +62,10 @@ export function Inpaint(props: InpaintProps) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const state = mustExist(useContext(StateContext));
|
const state = mustExist(useContext(StateContext));
|
||||||
const params = useStore(state, (s) => s.inpaint);
|
const filter = useStore(state, (s) => s.inpaint.filter);
|
||||||
|
const noise = useStore(state, (s) => s.inpaint.noise);
|
||||||
|
const mask = useStore(state, (s) => s.inpaint.mask);
|
||||||
|
const source = useStore(state, (s) => s.inpaint.source);
|
||||||
// eslint-disable-next-line @typescript-eslint/unbound-method
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||||
const setInpaint = useStore(state, (s) => s.setInpaint);
|
const setInpaint = useStore(state, (s) => s.setInpaint);
|
||||||
// eslint-disable-next-line @typescript-eslint/unbound-method
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||||
|
@ -78,7 +80,7 @@ export function Inpaint(props: InpaintProps) {
|
||||||
<Stack spacing={2}>
|
<Stack spacing={2}>
|
||||||
<ImageInput
|
<ImageInput
|
||||||
filter={IMAGE_FILTER}
|
filter={IMAGE_FILTER}
|
||||||
image={params.source}
|
image={source}
|
||||||
label='Source'
|
label='Source'
|
||||||
onChange={(file) => {
|
onChange={(file) => {
|
||||||
setInpaint({
|
setInpaint({
|
||||||
|
@ -88,7 +90,7 @@ export function Inpaint(props: InpaintProps) {
|
||||||
/>
|
/>
|
||||||
<ImageInput
|
<ImageInput
|
||||||
filter={IMAGE_FILTER}
|
filter={IMAGE_FILTER}
|
||||||
image={params.mask}
|
image={mask}
|
||||||
label='Mask'
|
label='Mask'
|
||||||
onChange={(file) => {
|
onChange={(file) => {
|
||||||
setInpaint({
|
setInpaint({
|
||||||
|
@ -98,11 +100,11 @@ export function Inpaint(props: InpaintProps) {
|
||||||
renderImage={(image) =>
|
renderImage={(image) =>
|
||||||
<MaskCanvas
|
<MaskCanvas
|
||||||
config={config}
|
config={config}
|
||||||
base={params.source}
|
base={source}
|
||||||
source={image}
|
source={image}
|
||||||
onSave={(mask) => {
|
onSave={(file) => {
|
||||||
setInpaint({
|
setInpaint({
|
||||||
mask,
|
mask: file,
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
@ -110,7 +112,7 @@ export function Inpaint(props: InpaintProps) {
|
||||||
/>
|
/>
|
||||||
<ImageControl
|
<ImageControl
|
||||||
config={config}
|
config={config}
|
||||||
params={params}
|
selector={(s) => s.inpaint}
|
||||||
onChange={(newParams) => {
|
onChange={(newParams) => {
|
||||||
setInpaint(newParams);
|
setInpaint(newParams);
|
||||||
}}
|
}}
|
||||||
|
@ -121,10 +123,10 @@ export function Inpaint(props: InpaintProps) {
|
||||||
labels={MASK_LABELS}
|
labels={MASK_LABELS}
|
||||||
name='Mask Filter'
|
name='Mask Filter'
|
||||||
result={masks}
|
result={masks}
|
||||||
value={params.filter}
|
value={filter}
|
||||||
onChange={(filter) => {
|
onChange={(newFilter) => {
|
||||||
setInpaint({
|
setInpaint({
|
||||||
filter,
|
filter: newFilter,
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
@ -133,10 +135,10 @@ export function Inpaint(props: InpaintProps) {
|
||||||
labels={NOISE_LABELS}
|
labels={NOISE_LABELS}
|
||||||
name='Noise Source'
|
name='Noise Source'
|
||||||
result={noises}
|
result={noises}
|
||||||
value={params.noise}
|
value={noise}
|
||||||
onChange={(noise) => {
|
onChange={(newNoise) => {
|
||||||
setInpaint({
|
setInpaint({
|
||||||
noise,
|
noise: newNoise,
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -23,9 +23,9 @@ export function Txt2Img(props: Txt2ImgProps) {
|
||||||
const { config, model, platform } = props;
|
const { config, model, platform } = props;
|
||||||
|
|
||||||
async function generateImage() {
|
async function generateImage() {
|
||||||
const upscale = state.getState().upscale;
|
const { txt2img, upscale } = state.getState();
|
||||||
const output = await client.txt2img({
|
const output = await client.txt2img({
|
||||||
...params,
|
...txt2img,
|
||||||
model,
|
model,
|
||||||
platform,
|
platform,
|
||||||
}, upscale);
|
}, upscale);
|
||||||
|
@ -40,7 +40,8 @@ export function Txt2Img(props: Txt2ImgProps) {
|
||||||
});
|
});
|
||||||
|
|
||||||
const state = mustExist(useContext(StateContext));
|
const state = mustExist(useContext(StateContext));
|
||||||
const params = useStore(state, (s) => s.txt2img);
|
const height = useStore(state, (s) => s.txt2img.height);
|
||||||
|
const width = useStore(state, (s) => s.txt2img.width);
|
||||||
// eslint-disable-next-line @typescript-eslint/unbound-method
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||||
const setTxt2Img = useStore(state, (s) => s.setTxt2Img);
|
const setTxt2Img = useStore(state, (s) => s.setTxt2Img);
|
||||||
// eslint-disable-next-line @typescript-eslint/unbound-method
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||||
|
@ -48,16 +49,14 @@ export function Txt2Img(props: Txt2ImgProps) {
|
||||||
|
|
||||||
return <Box>
|
return <Box>
|
||||||
<Stack spacing={2}>
|
<Stack spacing={2}>
|
||||||
<ImageControl config={config} params={params} onChange={(newParams) => {
|
<ImageControl config={config} selector={(s) => s.txt2img} onChange={setTxt2Img} />
|
||||||
setTxt2Img(newParams);
|
|
||||||
}} />
|
|
||||||
<Stack direction='row' spacing={4}>
|
<Stack direction='row' spacing={4}>
|
||||||
<NumericField
|
<NumericField
|
||||||
label='Width'
|
label='Width'
|
||||||
min={config.width.min}
|
min={config.width.min}
|
||||||
max={config.width.max}
|
max={config.width.max}
|
||||||
step={config.width.step}
|
step={config.width.step}
|
||||||
value={params.width}
|
value={width}
|
||||||
onChange={(value) => {
|
onChange={(value) => {
|
||||||
setTxt2Img({
|
setTxt2Img({
|
||||||
width: value,
|
width: value,
|
||||||
|
@ -69,7 +68,7 @@ export function Txt2Img(props: Txt2ImgProps) {
|
||||||
min={config.height.min}
|
min={config.height.min}
|
||||||
max={config.height.max}
|
max={config.height.max}
|
||||||
step={config.height.step}
|
step={config.height.step}
|
||||||
value={params.height}
|
value={height}
|
||||||
onChange={(value) => {
|
onChange={(value) => {
|
||||||
setTxt2Img({
|
setTxt2Img({
|
||||||
height: value,
|
height: value,
|
||||||
|
|
Loading…
Reference in New Issue