Compare commits

..

15 Commits

Author SHA1 Message Date
Lincoln Stein
2af511c98a release 2.3.4 2023-04-09 13:31:45 -04:00
Lincoln Stein
f0039cc70a [Bugfix] truncate filenames in invokeai batch that exceed max filename length (#3143)
- This prevents `invokeai-batch` from trying to create image files whose
names would exceed PC_NAME_MAX.
- Closes #3115
2023-04-09 12:36:10 -04:00
Lincoln Stein
8fa7d5ca64 Merge branch 'v2.3' into bugfix/truncate-filenames-in-invokeai-batch 2023-04-09 12:16:06 -04:00
Lincoln Stein
d90aa42799 [WebUI] 2.3.4 UI Bug Fixes (#3139)
Some quick bug fixes related to the UI for the 2.3.4. release.

**Features:**

- Added the ability to now add Textual Inversions to the Negative Prompt
using the UI.
- Added the ability to clear Textual Inversions and Loras from Prompt
and Negative Prompt with a single click.
- Textual Inversions now have status pips - indicating whether they are
used in the Main Prompt, Negative Prompt or both.

**Fixes**

- Fixes #3138
- Fixes #3144
- Fixed `usePrompt` not updating the Lora and TI count in prompt /
negative prompt.
- Fixed the TI regex not respecting names in substrings.
- Fixed trailing spaces when adding and removing loras and TI's.
- Fixed an issue with the TI regex not respecting the `<` and `>` used
by HuggingFace concepts.
- Some other minor bug fixes.
2023-04-09 12:07:41 -04:00
Lincoln Stein
c5b34d21e5 Merge branch 'v2.3' into bugfix/truncate-filenames-in-invokeai-batch 2023-04-09 11:29:32 -04:00
blessedcoolant
40a4867143 Merge branch 'v2.3' into 234-ui-bugfixes 2023-04-09 15:56:44 +12:00
Lincoln Stein
4b25f80427 [Bugfix] Pass extra_conditioning_info in inpaint, so lora can be initialized (#3151) 2023-04-08 21:17:53 -04:00
StAlKeR7779
894e2e643d Pass extra_conditioning_info in inpaint 2023-04-09 00:50:30 +03:00
blessedcoolant
a38ff1a16b build(ui): Test Build (2.3.4 Feat Updates) 2023-04-09 07:37:41 +12:00
blessedcoolant
41f268b475 feat(ui): Improve TI & Lora UI 2023-04-09 07:35:19 +12:00
blessedcoolant
b3ae3f595f fix(ui): Fixed Use Prompt not detecting Loras / TI Count 2023-04-09 03:44:17 +12:00
blessedcoolant
29962613d8 chore(ui): Move Lora & TI Managers to Prompt Extras 2023-04-08 22:47:30 +12:00
blessedcoolant
1170cee1d8 fix(ui): Options panel sliding because of long Lora or TI names 2023-04-08 16:48:28 +12:00
Lincoln Stein
5983e65b22 invokeai-batch: truncate image filenames that exceed filesystem's max filename size
- Closes #3115
2023-04-07 18:20:32 -04:00
blessedcoolant
bc724fcdc3 fix(ui): Fix Main Width Slider being read only. 2023-04-08 04:15:55 +12:00
20 changed files with 377 additions and 165 deletions

File diff suppressed because one or more lines are too long

View File

@@ -5,7 +5,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>InvokeAI - A Stable Diffusion Toolkit</title>
<link rel="shortcut icon" type="icon" href="./assets/favicon-0d253ced.ico" />
<script type="module" crossorigin src="./assets/index-c1535364.js"></script>
<script type="module" crossorigin src="./assets/index-f56b39bc.js"></script>
<link rel="stylesheet" href="./assets/index-2ab0eb58.css">
</head>

View File

@@ -328,8 +328,11 @@
"updateModel": "Update Model",
"availableModels": "Available Models",
"addLora": "Add Lora",
"clearLoras": "Clear Loras",
"noLoraModels": "No Loras Found",
"addTextualInversionTrigger": "Add Textual Inversion",
"addTIToNegative": "Add To Negative",
"clearTextualInversions": "Clear Textual Inversions",
"noTextualInversionTriggers": "No Textual Inversions Found",
"search": "Search",
"load": "Load",

View File

@@ -328,8 +328,11 @@
"updateModel": "Update Model",
"availableModels": "Available Models",
"addLora": "Add Lora",
"clearLoras": "Clear Loras",
"noLoraModels": "No Loras Found",
"addTextualInversionTrigger": "Add Textual Inversion",
"addTIToNegative": "Add To Negative",
"clearTextualInversions": "Clear Textual Inversions",
"noTextualInversionTriggers": "No Textual Inversions Found",
"search": "Search",
"load": "Load",

View File

@@ -92,7 +92,8 @@ export default function IAISimpleMenu(props: IAIMenuProps) {
zIndex={15}
padding={0}
borderRadius="0.5rem"
overflowY="scroll"
overflow="scroll"
maxWidth={'22.5rem'}
maxHeight={500}
backgroundColor="var(--background-color-secondary)"
color="var(--text-color-secondary)"

View File

@@ -34,7 +34,6 @@ export default function MainWidth() {
withSliderMarks
sliderMarkRightOffset={-8}
inputWidth="6.2rem"
inputReadOnly
sliderNumberInputProps={{ max: 15360 }}
/>
) : (

View File

@@ -1,10 +1,15 @@
import { Box } from '@chakra-ui/react';
import { Box, Flex } from '@chakra-ui/react';
import { getLoraModels } from 'app/socketio/actions';
import { useAppDispatch, useAppSelector } from 'app/storeHooks';
import IAIIconButton from 'common/components/IAIIconButton';
import IAISimpleMenu, { IAIMenuItem } from 'common/components/IAISimpleMenu';
import { setLorasInUse } from 'features/parameters/store/generationSlice';
import {
setClearLoras,
setLorasInUse,
} from 'features/parameters/store/generationSlice';
import { useEffect } from 'react';
import { useTranslation } from 'react-i18next';
import { MdClear } from 'react-icons/md';
export default function LoraManager() {
const dispatch = useAppDispatch();
@@ -53,11 +58,20 @@ export default function LoraManager() {
};
return foundLoras && foundLoras?.length > 0 ? (
<IAISimpleMenu
menuItems={makeLoraItems()}
menuType="regular"
buttonText={`${t('modelManager.addLora')} (${numOfActiveLoras()})`}
/>
<Flex columnGap={2}>
<IAISimpleMenu
menuItems={makeLoraItems()}
menuType="regular"
buttonText={`${t('modelManager.addLora')} (${numOfActiveLoras()})`}
menuButtonProps={{ width: '100%', padding: '0 1rem' }}
/>
<IAIIconButton
icon={<MdClear />}
tooltip={t('modelManager.clearLoras')}
aria-label={t('modelManager.clearLoras')}
onClick={() => dispatch(setClearLoras())}
/>
</Flex>
) : (
<Box
background="var(--btn-base-color)"

View File

@@ -0,0 +1,12 @@
import { Flex } from '@chakra-ui/react';
import LoraManager from './LoraManager/LoraManager';
import TextualInversionManager from './TextualInversionManager/TextualInversionManager';
export default function PromptExtras() {
return (
<Flex flexDir="column" rowGap={2}>
<LoraManager />
<TextualInversionManager />
</Flex>
);
}

View File

@@ -1,17 +1,28 @@
import { Box } from '@chakra-ui/react';
import { Box, Flex } from '@chakra-ui/react';
import { getTextualInversionTriggers } from 'app/socketio/actions';
import { RootState } from 'app/store';
import { useAppDispatch, useAppSelector } from 'app/storeHooks';
import IAIIconButton from 'common/components/IAIIconButton';
import IAISimpleMenu, { IAIMenuItem } from 'common/components/IAISimpleMenu';
import { setTextualInversionsInUse } from 'features/parameters/store/generationSlice';
import {
setAddTIToNegative,
setClearTextualInversions,
setTextualInversionsInUse,
} from 'features/parameters/store/generationSlice';
import { useEffect } from 'react';
import { useTranslation } from 'react-i18next';
import { MdArrowDownward, MdClear } from 'react-icons/md';
export default function TextualInversionManager() {
const dispatch = useAppDispatch();
const textualInversionsInUse = useAppSelector(
(state: RootState) => state.generation.textualInversionsInUse
);
const negativeTextualInversionsInUse = useAppSelector(
(state: RootState) => state.generation.negativeTextualInversionsInUse
);
const foundLocalTextualInversionTriggers = useAppSelector(
(state) => state.system.foundLocalTextualInversionTriggers
);
@@ -31,6 +42,10 @@ export default function TextualInversionManager() {
(state) => state.ui.shouldShowHuggingFaceConcepts
);
const addTIToNegative = useAppSelector(
(state) => state.generation.addTIToNegative
);
const { t } = useTranslation();
useEffect(() => {
@@ -41,14 +56,25 @@ export default function TextualInversionManager() {
dispatch(setTextualInversionsInUse(textual_inversion));
};
const renderTextualInversionOption = (textual_inversion: string) => {
const thisTIExists = textualInversionsInUse.includes(textual_inversion);
const tiExistsStyle = {
fontWeight: 'bold',
color: 'var(--context-menu-active-item)',
};
const TIPip = ({ color }: { color: string }) => {
return (
<Box style={thisTIExists ? tiExistsStyle : {}}>{textual_inversion}</Box>
<Box width={2} height={2} borderRadius={9999} backgroundColor={color}>
{' '}
</Box>
);
};
const renderTextualInversionOption = (textual_inversion: string) => {
return (
<Flex alignItems="center" columnGap={1}>
{textual_inversion}
{textualInversionsInUse.includes(textual_inversion) && (
<TIPip color="var(--context-menu-active-item)" />
)}
{negativeTextualInversionsInUse.includes(textual_inversion) && (
<TIPip color="var(--status-bad-color)" />
)}
</Flex>
);
};
@@ -56,8 +82,10 @@ export default function TextualInversionManager() {
const allTextualInversions = localTextualInversionTriggers.concat(
huggingFaceTextualInversionConcepts
);
return allTextualInversions.filter((ti) =>
textualInversionsInUse.includes(ti)
return allTextualInversions.filter(
(ti) =>
textualInversionsInUse.includes(ti) ||
negativeTextualInversionsInUse.includes(ti)
).length;
};
@@ -93,13 +121,34 @@ export default function TextualInversionManager() {
(foundHuggingFaceTextualInversionTriggers &&
foundHuggingFaceTextualInversionTriggers?.length > 0 &&
shouldShowHuggingFaceConcepts)) ? (
<IAISimpleMenu
menuItems={makeTextualInversionItems()}
menuType="regular"
buttonText={`${t(
'modelManager.addTextualInversionTrigger'
)} (${numOfActiveTextualInversions()})`}
/>
<Flex columnGap={2}>
<IAISimpleMenu
menuItems={makeTextualInversionItems()}
menuType="regular"
buttonText={`${t(
'modelManager.addTextualInversionTrigger'
)} (${numOfActiveTextualInversions()})`}
menuButtonProps={{
width: '100%',
padding: '0 1rem',
}}
/>
<IAIIconButton
icon={<MdArrowDownward />}
style={{
backgroundColor: addTIToNegative ? 'var(--btn-delete-image)' : '',
}}
tooltip={t('modelManager.addTIToNegative')}
aria-label={t('modelManager.addTIToNegative')}
onClick={() => dispatch(setAddTIToNegative(!addTIToNegative))}
/>
<IAIIconButton
icon={<MdClear />}
tooltip={t('modelManager.clearTextualInversions')}
aria-label={t('modelManager.clearTextualInversions')}
onClick={() => dispatch(setClearTextualInversions())}
/>
</Flex>
) : (
<Box
background="var(--btn-base-color)"

View File

@@ -1,24 +1,43 @@
import { FormControl, Textarea } from '@chakra-ui/react';
import type { RootState } from 'app/store';
import { useAppDispatch, useAppSelector } from 'app/storeHooks';
import { setNegativePrompt } from 'features/parameters/store/generationSlice';
import {
handlePromptCheckers,
setNegativePrompt,
} from 'features/parameters/store/generationSlice';
import { useTranslation } from 'react-i18next';
import { ChangeEvent, useState } from 'react';
const NegativePromptInput = () => {
const negativePrompt = useAppSelector(
(state: RootState) => state.generation.negativePrompt
);
const [promptTimer, setPromptTimer] = useState<number | undefined>(undefined);
const dispatch = useAppDispatch();
const { t } = useTranslation();
const handleNegativeChangePrompt = (e: ChangeEvent<HTMLTextAreaElement>) => {
dispatch(setNegativePrompt(e.target.value));
// Debounce Prompt UI Checking
clearTimeout(promptTimer);
const newPromptTimer = window.setTimeout(() => {
dispatch(
handlePromptCheckers({ prompt: e.target.value, toNegative: true })
);
}, 500);
setPromptTimer(newPromptTimer);
};
return (
<FormControl>
<Textarea
id="negativePrompt"
name="negativePrompt"
value={negativePrompt}
onChange={(e) => dispatch(setNegativePrompt(e.target.value))}
onChange={handleNegativeChangePrompt}
background="var(--prompt-bg-color)"
placeholder={t('parameters.negativePrompts')}
_placeholder={{ fontSize: '0.8rem' }}

View File

@@ -51,7 +51,9 @@ const PromptInput = () => {
// Debounce Prompt UI Checking
clearTimeout(promptTimer);
const newPromptTimer = window.setTimeout(() => {
dispatch(handlePromptCheckers(e.target.value));
dispatch(
handlePromptCheckers({ prompt: e.target.value, toNegative: false })
);
}, 500);
setPromptTimer(newPromptTimer);
};

View File

@@ -3,7 +3,11 @@ import { getPromptAndNegative } from 'common/util/getPromptAndNegative';
import * as InvokeAI from 'app/invokeai';
import promptToString from 'common/util/promptToString';
import { useAppDispatch } from 'app/storeHooks';
import { setNegativePrompt, setPrompt } from '../store/generationSlice';
import {
handlePromptCheckers,
setNegativePrompt,
setPrompt,
} from '../store/generationSlice';
// TECHDEBT: We have two metadata prompt formats and need to handle recalling either of them.
// This hook provides a function to do that.
@@ -20,6 +24,10 @@ const useSetBothPrompts = () => {
dispatch(setPrompt(prompt));
dispatch(setNegativePrompt(negativePrompt));
dispatch(handlePromptCheckers({ prompt: prompt, toNegative: false }));
dispatch(
handlePromptCheckers({ prompt: negativePrompt, toNegative: true })
);
};
};

View File

@@ -18,9 +18,11 @@ export interface GenerationState {
prompt: string;
negativePrompt: string;
lorasInUse: string[];
localTextualInversionTriggers: string[];
huggingFaceTextualInversionConcepts: string[];
localTextualInversionTriggers: string[];
textualInversionsInUse: string[];
negativeTextualInversionsInUse: string[];
addTIToNegative: boolean;
sampler: string;
seamBlur: number;
seamless: boolean;
@@ -53,9 +55,11 @@ const initialGenerationState: GenerationState = {
prompt: '',
negativePrompt: '',
lorasInUse: [],
localTextualInversionTriggers: [],
huggingFaceTextualInversionConcepts: [],
localTextualInversionTriggers: [],
textualInversionsInUse: [],
negativeTextualInversionsInUse: [],
addTIToNegative: false,
sampler: 'k_lms',
seamBlur: 16,
seamless: false,
@@ -85,15 +89,86 @@ const loraExists = (state: GenerationState, lora: string) => {
return false;
};
const getTIRegex = (textualInversion: string) => {
if (textualInversion.includes('<' || '>')) {
return new RegExp(`${textualInversion}`);
} else {
return new RegExp(`\\b${textualInversion}\\b`);
}
};
const textualInversionExists = (
state: GenerationState,
textualInversion: string
) => {
const textualInversionRegex = new RegExp(textualInversion);
if (state.prompt.match(textualInversionRegex)) return true;
const textualInversionRegex = getTIRegex(textualInversion);
if (!state.addTIToNegative) {
if (state.prompt.match(textualInversionRegex)) return true;
} else {
if (state.negativePrompt.match(textualInversionRegex)) return true;
}
return false;
};
const handleTypedTICheck = (
state: GenerationState,
newPrompt: string,
toNegative: boolean
) => {
let textualInversionsInUse = !toNegative
? [...state.textualInversionsInUse]
: [...state.negativeTextualInversionsInUse]; // Get Words In Prompt
const textualInversionRegex = /([\w<>!@%&*_-]+)/g; // Scan For Each Word
const textualInversionMatches = [
...newPrompt.matchAll(textualInversionRegex),
]; // Match All Words
if (textualInversionMatches.length > 0) {
textualInversionsInUse = []; // Reset Textual Inversions In Use
textualInversionMatches.forEach((textualInversionMatch) => {
const textualInversionName = textualInversionMatch[0];
if (
(!textualInversionsInUse.includes(textualInversionName) &&
state.localTextualInversionTriggers.includes(textualInversionName)) ||
state.huggingFaceTextualInversionConcepts.includes(textualInversionName)
) {
textualInversionsInUse.push(textualInversionName); // Add Textual Inversions In Prompt
}
});
} else {
textualInversionsInUse = []; // If No Matches, Remove Textual Inversions In Use
}
if (!toNegative) {
state.textualInversionsInUse = textualInversionsInUse;
} else {
state.negativeTextualInversionsInUse = textualInversionsInUse;
}
};
const handleTypedLoraCheck = (state: GenerationState, newPrompt: string) => {
let lorasInUse = [...state.lorasInUse]; // Get Loras In Prompt
const loraRegex = /withLora\(([^\\)]+)\)/g; // Scan For Lora Syntax
const loraMatches = [...newPrompt.matchAll(loraRegex)]; // Match All Lora Syntaxes
if (loraMatches.length > 0) {
lorasInUse = []; // Reset Loras In Use
loraMatches.forEach((loraMatch) => {
const loraName = loraMatch[1].split(',')[0];
if (!lorasInUse.includes(loraName)) lorasInUse.push(loraName); // Add Loras In Prompt
});
} else {
lorasInUse = []; // If No Matches, Remove Loras In Use
}
state.lorasInUse = lorasInUse;
};
export const generationSlice = createSlice({
name: 'generation',
initialState,
@@ -118,6 +193,20 @@ export const generationSlice = createSlice({
state.negativePrompt = promptToString(newPrompt);
}
},
handlePromptCheckers: (
state,
action: PayloadAction<{
prompt: string | InvokeAI.Prompt;
toNegative: boolean;
}>
) => {
const newPrompt = action.payload.prompt;
if (typeof newPrompt === 'string') {
if (!action.payload.toNegative) handleTypedLoraCheck(state, newPrompt);
handleTypedTICheck(state, newPrompt, action.payload.toNegative);
}
},
setLorasInUse: (state, action: PayloadAction<string>) => {
const newLora = action.payload;
const loras = [...state.lorasInUse];
@@ -128,94 +217,99 @@ export const generationSlice = createSlice({
'g'
);
const newPrompt = state.prompt.replaceAll(loraRegex, '');
state.prompt = newPrompt;
state.prompt = newPrompt.trim();
if (loras.includes(newLora)) {
const newLoraIndex = loras.indexOf(newLora);
if (newLoraIndex > -1) loras.splice(newLoraIndex, 1);
}
} else {
state.prompt = `${state.prompt} withLora(${newLora},0.75)`;
state.prompt = `${state.prompt.trim()} withLora(${newLora},0.75)`;
if (!loras.includes(newLora)) loras.push(newLora);
}
state.lorasInUse = loras;
},
handlePromptCheckers: (
state,
action: PayloadAction<string | InvokeAI.Prompt>
) => {
const newPrompt = action.payload;
setClearLoras: (state) => {
const lorasInUse = [...state.lorasInUse];
// Tackle User Typed Lora Syntax
let lorasInUse = [...state.lorasInUse]; // Get Loras In Prompt
const loraRegex = /withLora\(([^\\)]+)\)/g; // Scan For Lora Syntax
if (typeof newPrompt === 'string') {
const loraMatches = [...newPrompt.matchAll(loraRegex)]; // Match All Lora Syntaxes
if (loraMatches.length > 0) {
lorasInUse = []; // Reset Loras In Use
loraMatches.forEach((loraMatch) => {
const loraName = loraMatch[1].split(',')[0];
if (!lorasInUse.includes(loraName)) lorasInUse.push(loraName); // Add Loras In Prompt
});
} else {
lorasInUse = []; // If No Matches, Remove Loras In Use
}
}
state.lorasInUse = lorasInUse;
lorasInUse.forEach((lora) => {
const loraRegex = new RegExp(
`withLora\\(${lora},?\\s*([^\\)]+)?\\)`,
'g'
);
const newPrompt = state.prompt.replaceAll(loraRegex, '');
state.prompt = newPrompt.trim();
});
// Tackle User Typed Textual Inversion
let textualInversionsInUse = [...state.textualInversionsInUse]; // Get Words In Prompt
const textualInversionRegex = /([\w<>!@%&*_-]+)/g; // Scan For Each Word
if (typeof newPrompt === 'string') {
const textualInversionMatches = [
...newPrompt.matchAll(textualInversionRegex),
]; // Match All Words
if (textualInversionMatches.length > 0) {
textualInversionsInUse = []; // Reset Textual Inversions In Use
console.log(textualInversionMatches);
textualInversionMatches.forEach((textualInversionMatch) => {
const textualInversionName = textualInversionMatch[0];
console.log(textualInversionName);
if (
!textualInversionsInUse.includes(textualInversionName) &&
(state.localTextualInversionTriggers.includes(
textualInversionName
) ||
state.huggingFaceTextualInversionConcepts.includes(
textualInversionName
))
)
textualInversionsInUse.push(textualInversionName); // Add Textual Inversions In Prompt
});
} else {
textualInversionsInUse = []; // If No Matches, Remove Textual Inversions In Use
}
}
console.log([...state.huggingFaceTextualInversionConcepts]);
state.textualInversionsInUse = textualInversionsInUse;
state.lorasInUse = [];
},
setTextualInversionsInUse: (state, action: PayloadAction<string>) => {
const newTextualInversion = action.payload;
const textualInversions = [...state.textualInversionsInUse];
const negativeTextualInversions = [
...state.negativeTextualInversionsInUse,
];
if (textualInversionExists(state, newTextualInversion)) {
const textualInversionRegex = new RegExp(newTextualInversion, 'g');
const newPrompt = state.prompt.replaceAll(textualInversionRegex, '');
state.prompt = newPrompt;
const textualInversionRegex = getTIRegex(newTextualInversion);
if (!state.addTIToNegative) {
const newPrompt = state.prompt.replace(textualInversionRegex, '');
state.prompt = newPrompt.trim();
if (textualInversions.includes(newTextualInversion)) {
const newTIIndex = textualInversions.indexOf(newTextualInversion);
if (newTIIndex > -1) textualInversions.splice(newTIIndex, 1);
} else {
const newPrompt = state.negativePrompt.replace(
textualInversionRegex,
''
);
state.negativePrompt = newPrompt.trim();
const newTIIndex =
negativeTextualInversions.indexOf(newTextualInversion);
if (newTIIndex > -1) negativeTextualInversions.splice(newTIIndex, 1);
}
} else {
state.prompt = `${state.prompt} ${newTextualInversion}`;
if (!textualInversions.includes(newTextualInversion))
if (!state.addTIToNegative) {
state.prompt = `${state.prompt.trim()} ${newTextualInversion}`;
textualInversions.push(newTextualInversion);
} else {
state.negativePrompt = `${state.negativePrompt.trim()} ${newTextualInversion}`;
negativeTextualInversions.push(newTextualInversion);
}
}
state.lorasInUse = textualInversions;
state.textualInversionsInUse = textualInversions;
state.negativeTextualInversionsInUse = negativeTextualInversions;
},
setClearTextualInversions: (state) => {
const textualInversions = [...state.textualInversionsInUse];
const negativeTextualInversions = [
...state.negativeTextualInversionsInUse,
];
textualInversions.forEach((ti) => {
const textualInversionRegex = getTIRegex(ti);
const newPrompt = state.prompt.replace(textualInversionRegex, '');
state.prompt = newPrompt.trim();
});
negativeTextualInversions.forEach((ti) => {
const textualInversionRegex = getTIRegex(ti);
const newPrompt = state.negativePrompt.replace(
textualInversionRegex,
''
);
state.negativePrompt = newPrompt.trim();
});
state.textualInversionsInUse = [];
state.negativeTextualInversionsInUse = [];
},
setAddTIToNegative: (state, action: PayloadAction<boolean>) => {
state.addTIToNegative = action.payload;
},
setLocalTextualInversionTriggers: (
state,
@@ -509,11 +603,14 @@ export const {
setPerlin,
setPrompt,
setNegativePrompt,
setLorasInUse,
setLocalTextualInversionTriggers,
setHuggingFaceTextualInversionConcepts,
setTextualInversionsInUse,
handlePromptCheckers,
setLorasInUse,
setClearLoras,
setHuggingFaceTextualInversionConcepts,
setLocalTextualInversionTriggers,
setTextualInversionsInUse,
setAddTIToNegative,
setClearTextualInversions,
setSampler,
setSeamBlur,
setSeamless,

View File

@@ -18,8 +18,7 @@ import PromptInput from 'features/parameters/components/PromptInput/PromptInput'
import InvokeOptionsPanel from 'features/ui/components/InvokeParametersPanel';
import { useTranslation } from 'react-i18next';
import ImageToImageOptions from './ImageToImageOptions';
import LoraManager from 'features/parameters/components/LoraManager/LoraManager';
import TextualInversionManager from 'features/parameters/components/TextualInversionManager/TextualInversionManager';
import PromptExtras from 'features/parameters/components/PromptInput/Extras/PromptExtras';
export default function ImageToImagePanel() {
const { t } = useTranslation();
@@ -65,8 +64,7 @@ export default function ImageToImagePanel() {
<Flex flexDir="column" rowGap="0.5rem">
<PromptInput />
<NegativePromptInput />
<LoraManager />
<TextualInversionManager />
<PromptExtras />
</Flex>
<ProcessButtons />
<MainSettings />

View File

@@ -10,8 +10,6 @@ import UpscaleSettings from 'features/parameters/components/AdvancedParameters/U
import UpscaleToggle from 'features/parameters/components/AdvancedParameters/Upscale/UpscaleToggle';
import GenerateVariationsToggle from 'features/parameters/components/AdvancedParameters/Variations/GenerateVariations';
import VariationsSettings from 'features/parameters/components/AdvancedParameters/Variations/VariationsSettings';
import LoraManager from 'features/parameters/components/LoraManager/LoraManager';
import TextualInversionManager from 'features/parameters/components/TextualInversionManager/TextualInversionManager';
import MainSettings from 'features/parameters/components/MainParameters/MainParameters';
import ParametersAccordion from 'features/parameters/components/ParametersAccordion';
import ProcessButtons from 'features/parameters/components/ProcessButtons/ProcessButtons';
@@ -19,6 +17,7 @@ import NegativePromptInput from 'features/parameters/components/PromptInput/Nega
import PromptInput from 'features/parameters/components/PromptInput/PromptInput';
import InvokeOptionsPanel from 'features/ui/components/InvokeParametersPanel';
import { useTranslation } from 'react-i18next';
import PromptExtras from 'features/parameters/components/PromptInput/Extras/PromptExtras';
export default function TextToImagePanel() {
const { t } = useTranslation();
@@ -64,8 +63,7 @@ export default function TextToImagePanel() {
<Flex flexDir="column" rowGap="0.5rem">
<PromptInput />
<NegativePromptInput />
<LoraManager />
<TextualInversionManager />
<PromptExtras />
</Flex>
<ProcessButtons />
<MainSettings />

View File

@@ -10,8 +10,6 @@ import SymmetryToggle from 'features/parameters/components/AdvancedParameters/Ou
import SeedSettings from 'features/parameters/components/AdvancedParameters/Seed/SeedSettings';
import GenerateVariationsToggle from 'features/parameters/components/AdvancedParameters/Variations/GenerateVariations';
import VariationsSettings from 'features/parameters/components/AdvancedParameters/Variations/VariationsSettings';
import LoraManager from 'features/parameters/components/LoraManager/LoraManager';
import TextualInversionManager from 'features/parameters/components/TextualInversionManager/TextualInversionManager';
import MainSettings from 'features/parameters/components/MainParameters/MainParameters';
import ParametersAccordion from 'features/parameters/components/ParametersAccordion';
import ProcessButtons from 'features/parameters/components/ProcessButtons/ProcessButtons';
@@ -19,6 +17,7 @@ import NegativePromptInput from 'features/parameters/components/PromptInput/Nega
import PromptInput from 'features/parameters/components/PromptInput/PromptInput';
import InvokeOptionsPanel from 'features/ui/components/InvokeParametersPanel';
import { useTranslation } from 'react-i18next';
import PromptExtras from 'features/parameters/components/PromptInput/Extras/PromptExtras';
export default function UnifiedCanvasPanel() {
const { t } = useTranslation();
@@ -75,8 +74,7 @@ export default function UnifiedCanvasPanel() {
<Flex flexDir="column" rowGap="0.5rem">
<PromptInput />
<NegativePromptInput />
<LoraManager />
<TextualInversionManager />
<PromptExtras />
</Flex>
<ProcessButtons />
<MainSettings />

File diff suppressed because one or more lines are too long

View File

@@ -1 +1 @@
__version__='2.3.4rc1'
__version__='2.3.4'

View File

@@ -99,8 +99,9 @@ def expand_prompts(
sequence = 0
for command in commands:
sequence += 1
format = _get_fn_format(outdir, sequence)
parent_conn.send(
command + f' --fnformat="dp.{sequence:04}.{{prompt}}.png"'
command + f' --fnformat="{format}"'
)
parent_conn.close()
else:
@@ -110,7 +111,17 @@ def expand_prompts(
for p in children:
p.terminate()
def _get_fn_format(directory:str, sequence:int)->str:
"""
Get a filename that doesn't exceed filename length restrictions
on the current platform.
"""
max_length = os.pathconf(directory,'PC_NAME_MAX')
prefix = f'dp.{sequence:04}.'
suffix = '.png'
max_length -= len(prefix)+len(suffix)
return f'{prefix}{{prompt:0.{max_length}}}{suffix}'
class MessageToStdin(object):
def __init__(self, connection: Connection):
self.connection = connection

View File

@@ -255,8 +255,8 @@ class Inpaint(Img2Img):
pipeline.scheduler = sampler
# todo: support cross-attention control
uc, c, _ = conditioning
conditioning_data = (ConditioningData(uc, c, cfg_scale)
uc, c, extra_conditioning_info = conditioning
conditioning_data = (ConditioningData(uc, c, cfg_scale, extra_conditioning_info)
.add_scheduler_args_if_applicable(pipeline.scheduler, eta=ddim_eta))