refactoring the main tab

pull/348/head
Abdullah Alfaraj 2023-08-17 13:14:56 +03:00
parent b7376a61f1
commit 715e2ce6fe
55 changed files with 4783 additions and 5382 deletions

View File

@ -37,10 +37,6 @@ const BackgroundHistoryEnum = {
NoBackground: 'no_background',
}
const PresetTypeEnum = {
SDPreset: 'sd_preset',
ControlNetPreset: 'controlnet_preset',
}
module.exports = {
clickTypeEnum,
generationModeEnum,
@ -49,5 +45,4 @@ module.exports = {
RequestStateEnum,
BackgroundHistoryEnum,
PresetTypeEnum,
}

1759
index.html

File diff suppressed because it is too large Load Diff

1158
index.js

File diff suppressed because it is too large Load Diff

148
psapi.js
View File

@ -787,147 +787,6 @@ function layerNameToFileName(layer_name, layer_id, session_id) {
return file_name
}
async function silentSetInitImage(layer, session_id) {
try {
const html_manip = require('./utility/html_manip')
const io = require('./utility/io')
// const layer = await app.activeDocument.activeLayers[0]
const old_name = layer.name
// image_name = await app.activeDocument.activeLayers[0].name
//convert layer name to a file name
let image_name = layerNameToFileName(old_name, layer.id, session_id)
image_name = `${image_name}.png`
//the width and height of the exported image
const width = html_manip.getWidth()
const height = html_manip.getHeight()
//get the selection from the canvas as base64 png, make sure to resize to the width and height slider
const selectionInfo = g_generation_session.selectionInfo
// const base64_image = await io.IO.getSelectionFromCanvasAsBase64Silent(
// selectionInfo,
// true,
// width,
// height
// )
const use_silent_mode = html_manip.getUseSilentMode()
// if (use_silent_mode) {
// base64_image = await io.IO.getSelectionFromCanvasAsBase64Silent(
// selectionInfo,
// true,
// width,
// height
// )
// } else {
// base64_image = await io.IO.getSelectionFromCanvasAsBase64NonSilent(
// layer,
// image_name,
// width,
// height
// )
// }
const base64_image =
await io.IO.getSelectionFromCanvasAsBase64Interface(
width,
height,
layer,
selectionInfo,
true,
use_silent_mode,
image_name
)
//save base64 as file in the init_images directory
const init_entry = await getInitImagesDir()
await io.IO.base64PngToPngFile(base64_image, init_entry, image_name)
g_init_image_name = image_name
console.log(image_name)
const path = `${g_init_images_dir}/${image_name}`
//store the base64 init image and also set it as the active/latest init image
g_generation_session.base64initImages[path] = base64_image
g_generation_session.activeBase64InitImage = base64_image
const init_src = base64ToSrc(g_generation_session.activeBase64InitImage)
html_manip.setInitImageSrc(init_src)
return (image_info = { name: image_name, base64: base64_image })
} catch (e) {
console.error(`psapi.js silentSetInitImage error:, ${e}`)
}
}
async function silentSetInitImageMask(layer, session_id) {
try {
const html_manip = require('./utility/html_manip')
// const layer = await app.activeDocument.activeLayers[0]
const old_name = layer.name
image_name = layerNameToFileName(old_name, layer.id, session_id)
image_name = `${image_name}.png`
const width = html_manip.getWidth()
const height = html_manip.getHeight()
//get the selection from the canvas as base64 png, make sure to resize to the width and height slider
const selectionInfo = g_generation_session.selectionInfo
const use_silent_mode = html_manip.getUseSilentMode()
const base64_image =
await io.IO.getSelectionFromCanvasAsBase64Interface(
width,
height,
layer,
selectionInfo,
true,
use_silent_mode,
image_name
)
//save base64 as file in the init_images directory
const init_entry = await getInitImagesDir()
await io.IO.base64PngToPngFile(base64_image, init_entry, image_name)
g_init_image_mask_name = image_name // this is the name we will send to the server
console.log(image_name)
const path = `${g_init_images_dir}/${image_name}`
g_generation_session.base64maskImage[path] = base64_image
g_generation_session.activeBase64MaskImage = base64_image
const mask_src = base64ToSrc(g_generation_session.activeBase64MaskImage)
html_manip.setInitImageMaskSrc(mask_src)
return (image_info = { name: image_name, base64: base64_image })
} catch (e) {
console.error(`psapi.js setInitImageMask error: `, e)
}
}
// remove the generated mask related layers from the canvas and "layers" panel
// async function cleanSnapAndFill(layers){
// // we can delete this function and use cleanLayers() instead
// //delete init image group
// //delete init image (snapshot layer)
// //delete fill layer
// for (layer of layers){
// try{
// await executeAsModal(async ()=>{await layer.delete()})
// }catch(e){
// console.warn("cleanSnapAndFill, issue deleting a layer",e)
// }
// }
// return []
// }
async function cleanLayers(layers) {
// g_init_image_related_layers = {}
// g_mask_related_layers = {}
@ -1488,9 +1347,7 @@ module.exports = {
layerToFileName,
layerNameToFileName,
// cleanLayersOutpaint,
// cleanLayersInpaint,
// cleanSnapAndFill,
cleanLayers,
createClippingMaskExe,
checkIfSelectionAreaIsActive,
@ -1505,8 +1362,7 @@ module.exports = {
isSelectionValid,
snapshot_layer_no_slide_Exe,
setVisibleExe,
silentSetInitImage,
silentSetInitImageMask,
executeCommandExe,
executeDescExe,
getSelectionInfoCommand,

View File

@ -1,6 +1,6 @@
const { getDummyBase64, getDummyBase64_2 } = require('./utility/dummy')
const { base64ToBase64Url } = require('./utility/general')
const { getExtensionType } = require('./utility/html_manip')
const py_re = require('./utility/sdapi/python_replacement')
const Enum = require('./enum')
const { control_net } = require('./typescripts/dist/bundle')
@ -72,60 +72,6 @@ async function requestProgress() {
return null
}
async function requestGetModels() {
console.log('requestGetModels: ')
let json = []
const full_url = `${g_sd_url}/sdapi/v1/sd-models`
try {
let request = await fetch(full_url)
json = await request.json()
console.log('models json:')
console.dir(json)
} catch (e) {
console.warn(`issues requesting from ${full_url}`, e)
}
return json
}
async function requestGetSamplers() {
let json = null
try {
console.log('requestGetSamplers: ')
const full_url = `${g_sd_url}/sdapi/v1/samplers`
let request = await fetch(full_url)
json = await request.json()
// console.log('samplers json:', json)
} catch (e) {
console.warn(e)
}
return json
}
async function requestSwapModel(model_title) {
console.log('requestSwapModel: ')
const full_url = `${g_sd_url}/sdapi/v1/options`
payload = {
sd_model_checkpoint: model_title,
}
let request = await fetch(full_url, {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify(payload),
})
let json = await request.json()
console.log('models json:')
console.dir(json)
return json
}
async function requestInterrupt() {
const full_url = `${g_sd_url}/sdapi/v1/interrupt`
try {
@ -151,13 +97,6 @@ async function requestInterrupt() {
}
}
async function getVersionRequest() {
console.log('requestGetSamplers: ')
const current_version = g_version
return current_version
}
async function changeSdUrl(new_sd_url) {
// version = "v0.0.0"
console.log('changeSdUrl: new_sd_url:', new_sd_url)
@ -229,24 +168,6 @@ async function savePromptShortcut(prompt_shortcut) {
return json['prompt_shortcut']
}
async function setInpaintMaskWeight(value) {
const full_url = `${g_sd_url}/sdapi/v1/options`
try {
const payload = {
inpainting_mask_weight: value,
}
await fetch(full_url, {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify(payload),
})
} catch (e) {
console.warn(e)
}
}
async function requestGetConfig() {
console.log('requestGetConfig: ')
@ -439,21 +360,6 @@ async function requestExtraSingleImage(payload) {
}
}
async function requestGetUpscalers() {
console.log('requestGetUpscalers: ')
let json = []
const full_url = `${g_sd_url}/sdapi/v1/upscalers`
try {
let request = await fetch(full_url)
json = await request.json()
console.log('upscalers json:')
console.dir(json)
} catch (e) {
console.warn(`issues requesting from ${full_url}`, e)
}
return json
}
//REFACTOR: reuse the same code for (requestControlNetTxt2Img,requestControlNetImg2Img)
async function requestControlNetTxt2Img(plugin_settings) {
console.log('requestControlNetTxt2Img: ')
@ -649,26 +555,20 @@ async function isWebuiRunning() {
}
return true
}
async function requestLoraModels() {
const full_url = `${g_sd_url}/sdapi/v1/loras`
const lora_models = (await api.requestGet(full_url)) ?? []
return lora_models
}
module.exports = {
requestTxt2Img,
requestImg2Img,
requestProgress,
requestGetModels,
requestSwapModel,
requestInterrupt,
requestGetSamplers,
getVersionRequest,
changeSdUrl,
loadPromptShortcut,
savePromptShortcut,
loadHistory,
setInpaintMaskWeight,
requestGetConfig,
requestGetOptions,
imageSearch,
@ -677,9 +577,8 @@ module.exports = {
// requestHordeCheck,
// requestHordeStatus,
requestExtraSingleImage,
requestGetUpscalers,
requestControlNetTxt2Img,
requestControlNetImg2Img,
isWebuiRunning,
requestLoraModels,
}

View File

@ -767,25 +767,16 @@ class Selection {
static reselectArea(selection_info) {}
static isSameSelection(selection_info_1, selection_info_2) {}
static async getImageToSelectionDifference() {
const selectionInfo = await psapi.getSelectionInfoExe()
// const selectionInfo = await psapi.getSelectionInfoExe()
// const width = html_manip.getWidth()
// const height = html_manip.getHeight()
const width = html_manip.getWidth()
const height = html_manip.getHeight()
const scale_info_str = `${parseInt(width)}x${parseInt(
height
)} => ${parseInt(selectionInfo.width)}x${parseInt(
selectionInfo.height
)} `
const selectionInfo = session_store.data.current_selection_info
const width = sd_tab_store.data.width
const height = sd_tab_store.data.height
let ratio =
(width * height) / (selectionInfo.width * selectionInfo.height)
// const arrow = percentage >= 1 ? '↑' : '↓'
// percentage = percentage >= 1 ? percentage : 1 / percentage
// const percentage_str = `${arrow}X${percentage.toFixed(2)}`
// console.log('scale_info_str: ', scale_info_str)
// console.log('percentage_str: ', percentage_str)
return ratio
}
static {}
@ -1018,7 +1009,8 @@ async function black_white_layer_to_mask(mask_id, target_layer_id, mask_name) {
async function black_white_layer_to_mask_multi_batchplay(
mask_id,
target_layer_id,
mask_name
mask_name,
expand_by = 10
) {
let result
let psAction = require('photoshop').action
@ -1063,7 +1055,7 @@ async function black_white_layer_to_mask_multi_batchplay(
_obj: 'expand',
by: {
_unit: 'pixelsUnit',
_value: 10,
_value: expand_by,
},
selectionModifyEffectAtCanvasBounds: true,
_isCommand: true,

View File

@ -10,24 +10,20 @@ import {
SpMenu,
SpSliderWithLabel,
} from '../util/elements'
import { Collapsible } from '../util/collapsible'
// import * as sdapi from '../../sdapi_py_re'
import { api } from '../util/oldSystem'
import { AStore } from '../main/astore'
import { ui_config, model_list } from './config'
const { requestGet } = api
import { requestControlNetModelList } from '../controlnet/entry'
import { ErrorBoundary } from '../util/errorBoundary'
import { ScriptMode } from '../util/ts/enum'
import './style/after_detailer.css'
declare let g_sd_url: string
export enum ScriptMode {
Txt2Img = 'txt2img',
Img2Img = 'img2img',
Inpaint = 'inpaint',
Outpaint = 'outpaint',
}
export let script_mode = [
ScriptMode.Img2Img,
ScriptMode.Inpaint,
@ -263,77 +259,6 @@ export class AfterDetailerComponent extends React.Component<{
const domNode = document.getElementById('alwaysOnScriptsContainer')!
const root = ReactDOM.createRoot(domNode)
import { useState, ReactNode } from 'react'
import Locale from '../locale/locale'
import { ErrorBoundary } from '../util/errorBoundary'
interface CollapsibleProps {
label: string
labelStyle?: React.CSSProperties
containerStyle?: React.CSSProperties
defaultIsOpen?: boolean
checked?: boolean
checkboxCallback?: (checked: boolean) => void
children: ReactNode
}
function Collapsible({
label,
labelStyle,
containerStyle,
defaultIsOpen = false,
checkboxCallback,
checked,
children,
}: CollapsibleProps) {
const [isOpen, setIsOpen] = useState(defaultIsOpen)
const handleToggle = () => {
setIsOpen(!isOpen)
}
return (
/*useObserver(()=>*/ <div>
<div
className="collapsible"
style={containerStyle}
onClick={handleToggle}
>
<span className="truncate" style={labelStyle}>
{label}
</span>
<span
style={{ float: 'right', display: 'flex' }}
className="triangle"
>
{checkboxCallback && checked !== void 0 ? (
<input
type="checkbox"
className="minimal-checkbox"
onClick={(event) => {
event.stopPropagation()
}}
onChange={(event: any) => {
checkboxCallback(event.target.checked)
}}
checked={checked}
/>
) : (
void 0
)}
<span>{isOpen ? '' : '<'}</span>
</span>
</div>
{/* {isOpen && <div>{children}</div>} */}
<div style={{ display: isOpen ? 'block' : 'none' }}>{children}</div>
</div>
)
}
export default Collapsible
root.render(
<React.StrictMode>
<ErrorBoundary>

View File

@ -1,18 +1,19 @@
import { observer } from 'mobx-react'
import React from 'react'
import ControlNetUnit from './ControlNetUnit'
import { store as ControlNetStore } from './main'
import ControlNetStore from './store'
import { DefaultControlNetUnitData } from './store'
import {
Enum,
controlnet_preset,
note,
preset,
selection,
} from '../util/oldSystem'
import { SpMenuComponent } from '../util/elements'
import { Enum, controlnet_preset, note, selection } from '../util/oldSystem'
import { SpMenu, SpMenuComponent } from '../util/elements'
import Locale from '../locale/locale'
import Collapsible from '../after_detailer/after_detailer'
import { Collapsible } from '../util/collapsible'
import { PresetTypeEnum } from '../util/ts/enum'
import {
store as preset_store,
getAllCustomPresetsSettings,
getCustomPresetsNames,
} from '../preset/shared_ui_preset'
let g_controlnet_presets: any
declare const g_generation_session: any
@ -28,59 +29,57 @@ class ControlNetTab extends React.Component<{
// private presetMenuChildren: JSX.Element[] = []
onPresetMenuChange(evt: any) {
const preset_index = evt.target.selectedIndex
const preset_name = evt.target.options[preset_index].textContent
ControlNetStore.controlNetUnitData.forEach((dataitem, index) => {
const presetData = g_controlnet_presets[preset_name][index] || {}
// onPresetMenuChange(evt: any) {
// // const preset_index = evt.target.selectedIndex
// // const preset_name = evt.target.options[preset_index].textContent
// ControlNetStore.controlNetUnitData.forEach((dataitem, index) => {
// const presetData = g_controlnet_presets[preset_name][index] || {}
dataitem.enabled =
presetData.enabled || DefaultControlNetUnitData.enabled
dataitem.input_image =
presetData.input_image || DefaultControlNetUnitData.input_image
dataitem.mask = presetData.mask || DefaultControlNetUnitData.mask
// dataitem.enabled =
// presetData.enabled || DefaultControlNetUnitData.enabled
// dataitem.input_image =
// presetData.input_image || DefaultControlNetUnitData.input_image
// dataitem.mask = presetData.mask || DefaultControlNetUnitData.mask
dataitem.module =
presetData.module || DefaultControlNetUnitData.module
dataitem.model = presetData.model || DefaultControlNetUnitData.model
dataitem.weight =
presetData.weight || DefaultControlNetUnitData.weight
dataitem.resize_mode =
presetData.resize_mode || DefaultControlNetUnitData.resize_mode
dataitem.lowvram =
presetData.lowvram || DefaultControlNetUnitData.lowvram
dataitem.processor_res =
presetData.processor_res ||
DefaultControlNetUnitData.processor_res
dataitem.threshold_a =
presetData.threshold_a || DefaultControlNetUnitData.threshold_a
dataitem.threshold_b =
presetData.threshold_b || DefaultControlNetUnitData.threshold_b
dataitem.guidance_start =
presetData.guidance_start ||
DefaultControlNetUnitData.guidance_start
dataitem.guidance_end =
presetData.guidance_end ||
DefaultControlNetUnitData.guidance_end
dataitem.guessmode =
presetData.guessmode || DefaultControlNetUnitData.guessmode
// dataitem.module =
// presetData.module || DefaultControlNetUnitData.module
// dataitem.model = presetData.model || DefaultControlNetUnitData.model
// dataitem.weight =
// presetData.weight || DefaultControlNetUnitData.weight
// dataitem.resize_mode =
// presetData.resize_mode || DefaultControlNetUnitData.resize_mode
// dataitem.lowvram =
// presetData.lowvram || DefaultControlNetUnitData.lowvram
// dataitem.processor_res =
// presetData.processor_res ||
// DefaultControlNetUnitData.processor_res
// dataitem.threshold_a =
// presetData.threshold_a || DefaultControlNetUnitData.threshold_a
// dataitem.threshold_b =
// presetData.threshold_b || DefaultControlNetUnitData.threshold_b
// dataitem.guidance_start =
// presetData.guidance_start ||
// DefaultControlNetUnitData.guidance_start
// dataitem.guidance_end =
// presetData.guidance_end ||
// DefaultControlNetUnitData.guidance_end
// dataitem.guessmode =
// presetData.guessmode || DefaultControlNetUnitData.guessmode
dataitem.control_mode =
presetData.control_mode ||
DefaultControlNetUnitData.control_mode
dataitem.pixel_perfect =
presetData.pixel_perfect ||
DefaultControlNetUnitData.pixel_perfect
})
}
// dataitem.control_mode =
// presetData.control_mode ||
// DefaultControlNetUnitData.control_mode
// dataitem.pixel_perfect =
// presetData.pixel_perfect ||
// DefaultControlNetUnitData.pixel_perfect
// })
// }
// function to update presetMenuChildren
updatePresetMenuChildren(newChildren: any) {
this.setState({ presetMenuChildren: newChildren })
}
async updatePresetMenuEvent() {
const custom_presets = await preset.getAllCustomPresetsSettings(
Enum.PresetTypeEnum['ControlNetPreset']
)
const custom_presets = await getAllCustomPresetsSettings()
g_controlnet_presets = {
'Select CtrlNet Preset': {},
...controlnet_preset.ControlNetNativePresets,
@ -147,25 +146,25 @@ class ControlNetTab extends React.Component<{
render() {
return (
<div>
<sp-picker
title="auto fill the ControlNet with smart settings, to speed up your working process."
size="s"
label="ControlNet Preset"
style={{
width: '65%',
{/* <SpMenu
title="ControlNet Presets"
items={getCustomPresetsNames({
...preset_store.data.controlnet_native_presets,
...preset_store.data.controlnet_presets,
})}
label_item="Select a Preset"
selected_index={getCustomPresetsNames({
...preset_store.data.controlnet_native_presets,
...preset_store.data.controlnet_presets,
}).indexOf(preset_store.data.current_controlnet_preset)}
onChange={(id: any, value: any) => {
console.log('value:', value)
preset_store.data.current_controlnet_preset = value.item
// this.onPresetMenuChange()
}}
>
<SpMenuComponent
id="mControlNetPresetMenu"
value="Select CtrlNet Preset"
onChange={this.onPresetMenuChange.bind(this)}
onUpdatePresetMenuEvent={this.updatePresetMenuEvent.bind(
this
)}
>
{this.state.presetMenuChildren.map((child) => child)}
</SpMenuComponent>
</sp-picker>
></SpMenu> */}
<div></div>
{this.props.appState.maxControlNet == 0 && (
<sp-label

View File

@ -808,7 +808,7 @@ export default class ControlNetUnit extends React.Component<
)}
</div>
</div>
<div>
<div style={{ width: '50%', display: 'flex' }}>
<SpMenu
onChange={this.onFilterChange.bind(this)}
items={this.props.appState.filterKeywords}
@ -816,34 +816,38 @@ export default class ControlNetUnit extends React.Component<
selected_index={this.props.appState.filterKeywords.indexOf(
storeData.filter_keyword || 'All'
)}
style={{ width: '50%', display: 'flex' }}
// style={{ width: '50%', display: 'flex' }}
/>
</div>
<div
id={`menu-bar-control_net_${this.props.index}`}
style={{ display: 'flex' }}
>
<SpMenu
onChange={this.onPreprocsesorChange.bind(this)}
id={`mModulesMenuControlNet_${this.props.index}`}
items={storeData.module_list || ['none']}
label_item={Locale('Select Module')}
selected_index={storeData.module_list?.indexOf(
storeData.module
)}
style={{ width: '100%', display: 'flex' }}
/>
{!pd.model_free && (
<div style={{ width: '50%', display: 'flex' }}>
<SpMenu
onChange={this.onModelChange.bind(this)}
id={`mModelsMenuControlNet_${this.props.index}`}
items={storeData.model_list || []}
onChange={this.onPreprocsesorChange.bind(this)}
id={`mModulesMenuControlNet_${this.props.index}`}
items={storeData.module_list || ['none']}
label_item={Locale('Select Module')}
selected_index={storeData.model_list?.indexOf(
storeData.model
selected_index={storeData.module_list?.indexOf(
storeData.module
)}
style={{ width: '100%', display: 'flex' }}
style={{ width: '100%' }}
/>
</div>
{!pd.model_free && (
<div style={{ width: '50%', display: 'flex' }}>
<SpMenu
onChange={this.onModelChange.bind(this)}
id={`mModelsMenuControlNet_${this.props.index}`}
items={storeData.model_list || []}
label_item={Locale('Select Module')}
selected_index={storeData.model_list?.indexOf(
storeData.model
)}
style={{ width: '100%' }}
/>
</div>
)}
</div>
</div>

View File

@ -1,8 +1,14 @@
import { setControlImageSrc } from '../../utility/html_manip'
import { session_ts } from '../entry'
// import { session_ts } from '../entry'
// import * as session_ts from '../session/session'
import { store as session_store } from '../session/session_store'
import { Enum, api, python_replacement } from '../util/oldSystem'
import { GenerationModeEnum } from '../util/ts/enum'
import { store, versionCompare } from './main'
import store, {
DefaultControlNetUnitData,
DefaultPresetControlNetUnitData,
controlNetUnitData,
} from './store'
const { getExtensionUrl } = python_replacement
declare const g_sd_config_obj: any
@ -122,13 +128,11 @@ function mapPluginSettingsToControlNet(plugin_settings: any) {
let input_image = store.controlNetUnitData[index].input_image
if (
b_sync_input_image &&
[GenerationModeEnum.Txt2Img].includes(
session_ts.store.data.mode
)
[GenerationModeEnum.Txt2Img].includes(session_store.data.mode)
) {
//conditions: 1) txt2img mode 2)auto image on 3)first generation of session
input_image = session_ts.store.data.controlnet_input_image ?? ''
input_image = session_store.data.controlnet_input_image ?? ''
store.controlNetUnitData[index].input_image = input_image
}
if (
@ -138,10 +142,10 @@ function mapPluginSettingsToControlNet(plugin_settings: any) {
GenerationModeEnum.Inpaint,
GenerationModeEnum.Outpaint,
GenerationModeEnum.LassoInpaint,
].includes(session_ts.store.data.mode)
].includes(session_store.data.mode)
) {
// img2img mode
input_image = session_ts.store.data.init_image
input_image = session_store.data.init_image
store.controlNetUnitData[index].input_image = input_image
} else if (
b_sync_input_image &&
@ -160,7 +164,7 @@ function mapPluginSettingsToControlNet(plugin_settings: any) {
// const b_sync_input_image =
// store.controlNetUnitData[index].auto_image
// let mask = store.controlNetUnitData[index].mask // the user created mask
// if (b_sync_input_image && session_ts.store.data.expanded_mask) {
// if (b_sync_input_image && session_store.data.expanded_mask) {
// //use the mask from inpaint and outpaint mode
// mask = '' // this will tell controlnet to use SD mask
// store.controlNetUnitData[index].mask = ''
@ -170,7 +174,7 @@ function mapPluginSettingsToControlNet(plugin_settings: any) {
[
GenerationModeEnum.Txt2Img,
GenerationModeEnum.Img2Img,
].includes(session_ts.store.data.mode)
].includes(session_store.data.mode)
) {
//maskless mode
} else {
@ -190,7 +194,7 @@ function mapPluginSettingsToControlNet(plugin_settings: any) {
module: store.controlNetUnitData[index].module,
model: store.controlNetUnitData[index].model,
weight: store.controlNetUnitData[index].weight,
resize_mode: 'Scale to Fit (Inner Fit)',
resize_mode: 'Crop and Resize',
lowvram: store.controlNetUnitData[index].lowvram,
processor_res: store.controlNetUnitData[index].processor_res || 512,
threshold_a: store.controlNetUnitData[index].threshold_a,
@ -234,6 +238,24 @@ function getControlNetMaxModelsNumber() {
function getUnitsData() {
return store.controlNetUnitData
}
export function setUnitData(unitData: controlNetUnitData, index: number) {
try {
store.controlNetUnitData[index] = {
...store.controlNetUnitData[index],
...unitData,
}
if (!unitData?.enabled) {
store.controlNetUnitData[index] = {
...store.controlNetUnitData[index],
...DefaultPresetControlNetUnitData,
}
}
} catch (e) {
console.error(e)
}
}
function setControlDetectMapSrc(base64: string, index: number) {
// store.controlNetUnitData[index].mask = base64
store.controlNetUnitData[index].detect_map = base64

View File

@ -3,7 +3,7 @@ import React from 'react'
import ControlNetTab from './ControlNetTab'
import store from './store'
import { versionCompare } from './util'
import Collapsible from '../after_detailer/after_detailer'
import { Collapsible } from '../util/collapsible'
import Locale from '../locale/locale'
import { ErrorBoundary } from '../util/errorBoundary'
@ -48,51 +48,9 @@ if (elem2) {
}
function scrollToEnabledControlNetUnit() {}
const button = document.getElementById('scrollToControlNetUnitContainer')!
const button_root = ReactDOM.createRoot(button)
let controlnet_unit_index = 0
button_root.render(
<ErrorBoundary>
<button
className="btnSquare svgButton"
onClick={() => {
try {
const units = document.querySelectorAll(
'#controlNetTabParentContainer .collapsible'
)
const units_data = store.controlNetUnitData.map(
(data, index) => ({
enabled: data.enabled,
index,
})
)
// const button = document.getElementById('scrollToControlNetUnitContainer')!
// const button_root = ReactDOM.createRoot(button)
// Find the next enabled unit
let counter = 0
while (
!units_data[controlnet_unit_index % units.length]
.enabled &&
counter < units.length
) {
controlnet_unit_index += 1
counter += 1
}
// button_root.render(<ErrorBoundary></ErrorBoundary>)
if (counter < units.length) {
controlnet_unit_index =
controlnet_unit_index % units.length
units[controlnet_unit_index].scrollIntoView()
controlnet_unit_index += 1
}
} catch (e) {
console.warn(e)
}
}}
title="Quickly jump to the active ControlNet Unit"
>
C
</button>
</ErrorBoundary>
)
export { store, versionCompare }
export { versionCompare }

View File

@ -1,5 +1,11 @@
import { observable, reaction } from 'mobx'
type ResizeMode = 'Just Resize' | 'Crop and Resize' | 'Resize and Fill'
export const controlnetModes = [
'Balanced',
'My prompt is more important',
'ControlNet is more important',
] as const
export type ControlnetMode = (typeof controlnetModes)[number]
export const DefaultControlNetUnitData = {
enabled: false,
input_image: '',
@ -8,7 +14,7 @@ export const DefaultControlNetUnitData = {
module: '',
model: '',
weight: 1.0,
resize_mode: 'Scale to Fit (Inner Fit)',
resize_mode: 'Crop and Resize' as ResizeMode,
lowvram: true,
processor_res: 512,
threshold_a: 0,
@ -18,17 +24,37 @@ export const DefaultControlNetUnitData = {
guidance_end: 1,
guessmode: false,
control_mode: 'Balanced',
control_mode: 'Balanced' as ControlnetMode,
pixel_perfect: true,
auto_image: true,
}
export const controlnetModes = [
'Balanced',
'My prompt is more important',
'ControlNet is more important',
] as const
export type ControlnetMode = (typeof controlnetModes)[number]
export const DefaultPresetControlNetUnitData = {
enabled: false,
// input_image: '',
// mask: '',
// detect_map: '',
module: '',
model: '',
filter_keyword: 'All',
weight: 1.0,
resize_mode: 'Crop and Resize' as ResizeMode,
lowvram: true,
processor_res: 512,
threshold_a: 0,
threshold_b: 0,
guidance_start: 0,
guidance_end: 1,
guessmode: false,
control_mode: 'Balanced' as ControlnetMode,
pixel_perfect: true,
auto_image: true,
}
export interface controlNetUnitData {
enabled: boolean
@ -41,7 +67,7 @@ export interface controlNetUnitData {
model: string
filter_keyword: string
weight: number
resize_mode: 'Just Resize' | 'Crop and Resize' | 'Resize and Fill'
resize_mode: ResizeMode
lowvram: boolean
processor_res: number
threshold_a: number

View File

@ -1,24 +1,38 @@
// import { configure } from 'mobx'
// configure({
// enforceActions: 'never', // disable mobx warning temporarily
// })
import { configure } from 'mobx'
configure({
enforceActions: 'never', // disable mobx warning temporarily
})
export * as control_net from './controlnet/entry'
export * as after_detailer_script from './after_detailer/after_detailer'
export * as ultimate_sd_upscaler from './ultimate_sd_upscaler/ultimate_sd_upscaler'
export * as scripts from './ultimate_sd_upscaler/scripts'
export * as main from './main/main'
export * as controlnet_main from './controlnet/main'
export * as logger from './util/logger'
export * as image_search from './image_search/image_search'
export * as history from './history/history'
export * as viewer from './viewer/viewer'
export * as session_ts from './session/session'
export { store as session_store } from './session/session_store'
export { store as sd_tab_store } from './sd_tab/util'
export * as progress from './session/progress'
export * as preview from './viewer/preview'
export * as generate from './session/generate'
export * as sd_tab_ts from './sd_tab/sd_tab'
export * as sd_tab_util from './sd_tab/util'
export * as sam from './sam/sam'
export * as settings_tab_ts from './settings/settings'
export * as one_button_prompt from './one_button_prompt/one_button_prompt'
export * as enum_ts from './util/ts/enum'
export * as multiPrompts from './multiTextarea'
export * as preset from './preset/preset'
export * as preset_util from './preset/shared_ui_preset'
export * as ui_ts from './util/ts/ui_ts'
export * as io_ts from './util/ts/io'
export * as tool_bar from './tool_bar/tool_bar'
export * as extra_page from './extra_page/extra_page'
export * as selection_ts from './util/ts/selection'
export * as stores from './stores'
export { toJS } from 'mobx'
export { default as node_fs } from 'fs'

View File

@ -0,0 +1,267 @@
import { observer } from 'mobx-react'
import React from 'react'
import ReactDOM from 'react-dom/client'
import { ErrorBoundary } from '../util/errorBoundary'
import { Collapsible } from '../util/collapsible'
import { GenerateButtons } from '../session/generate'
import { AStore } from '../main/astore'
import { SpMenu, SpSlider } from '../util/elements'
import { mapRange } from '../controlnet/util'
import { requestGetUpscalers } from '../util/ts/sdapi'
export const store = new AStore({
upscaling_resize: 2,
upscaler_list: [] as string[],
upscaler_1: '',
upscaler_2: '',
resize_mode: 0,
show_extras_results: 0,
gfpgan_visibility: 0,
codeformer_visibility: 0,
codeformer_weight: 0,
upscaling_resize_w: 0,
upscaling_resize_h: 0,
upscaling_crop: true,
extras_upscaler_2_visibility: 0,
upscale_first: false,
})
export async function refreshExtraUpscalers() {
try {
const upscalers = await requestGetUpscalers()
if (upscalers) {
store.data.upscaler_list = upscalers.map(
(upscaler: { name: any }) => upscaler.name
)
}
} catch (e) {
console.error(e)
}
}
@observer
export class ExtraPage extends React.Component {
componentDidMount(): void {}
render(): React.ReactNode {
return (
<div>
<div style={{ paddingBottom: '5px' }}>
<SpSlider
style={{ display: 'block' }}
show-value="false"
id="slUpscaleSize"
min="10"
max="80"
value={store.data.upscaling_resize * 10}
title="Resize scale of current selection size"
onInput={(evt: any) => {
store.data.upscaling_resize = mapRange(
evt.target.value,
10,
80,
1,
8,
0.01
)
}}
>
<sp-label slot="label">Resize</sp-label>
<sp-label
class="labelNumber"
slot="label"
id="lUpscaleSize"
>
{store.data.upscaling_resize.toFixed(2)}
</sp-label>
</SpSlider>
</div>
<GenerateButtons></GenerateButtons>
<div
id="progressContainerUpscale"
style={{ paddingBottom: '5px' }}
>
<sp-label slot="label" class="lProgressLabel">
No work in progress
</sp-label>
</div>
<div style={{ paddingBottom: '5px' }}>
<sp-label
class="title"
style={{ width: '60px', display: 'inline-block' }}
>
Upscaler 1:
</sp-label>
<SpMenu
size="m"
title="Upscaler 1"
items={store.data.upscaler_list}
label_item="Select an Upscaler Model"
selected_index={store.data.upscaler_list.indexOf(
store.data.upscaler_1
)}
onChange={(id: any, value: any) => {
store.data.upscaler_1 = value.item
}}
></SpMenu>
<div></div>
<sp-label
class="title"
style={{ width: '60px', display: 'inline-block' }}
>
Upscaler 2:
</sp-label>
<SpMenu
size="m"
title="Upscaler 2"
items={store.data.upscaler_list}
label_item="Select an Upscaler Model"
selected_index={store.data.upscaler_list.indexOf(
store.data.upscaler_2
)}
onChange={(id: any, value: any) => {
store.data.upscaler_2 = value.item
}}
></SpMenu>
</div>
<div style={{ paddingBottom: '5px' }}>
<SpSlider
style={{ display: 'block' }}
show-value="false"
id="slUpscaler2Visibility"
min="0"
max="10"
value={store.data.extras_upscaler_2_visibility * 10}
onInput={(evt: any) => {
store.data.extras_upscaler_2_visibility =
evt.target.value / 10
}}
>
<sp-label
class="title"
style={{ width: '110px', display: 'inline-block' }}
slot="label"
>
Upscaler 2 visibility:
</sp-label>
<sp-label
style={{ display: 'inline-block' }}
class="labelNumber"
slot="label"
id="lUpscaler2Visibility"
>
{store.data.extras_upscaler_2_visibility.toFixed(2)}
</sp-label>
</SpSlider>
</div>
<div style={{ paddingBottom: '5px' }}>
<SpSlider
style={{ display: 'block' }}
show-value="false"
id="slGFPGANVisibility"
min="0"
max="10"
value={store.data.gfpgan_visibility * 10}
onInput={(evt: any) => {
store.data.gfpgan_visibility = evt.target.value / 10
}}
>
<sp-label
class="title"
style={{ width: '110px', display: 'inline-block' }}
slot="label"
>
GFPGAN visibility:
</sp-label>
<sp-label
style={{ display: 'inline-block' }}
class="labelNumber"
slot="label"
id="lGFPGANVisibility"
>
{store.data.gfpgan_visibility.toFixed(2)}
</sp-label>
</SpSlider>
</div>
<div style={{ paddingBottom: '5px' }}>
<SpSlider
style={{ display: 'block' }}
show-value="false"
id="slCodeFormerVisibility"
min="0"
max="10"
value={store.data.codeformer_visibility * 10}
onInput={(evt: any) => {
store.data.codeformer_visibility =
evt.target.value / 10
}}
>
<sp-label
class="title"
style={{ width: '110px', display: 'inline-block' }}
slot="label"
>
CodeFormer visibility:
</sp-label>
<sp-label
style={{ display: 'inline-block' }}
class="labelNumber"
slot="label"
id="lCodeFormerVisibility"
>
{store.data.codeformer_visibility.toFixed(2)}
</sp-label>
</SpSlider>
</div>
<div style={{ paddingBottom: '5px' }}>
<SpSlider
style={{ display: 'block' }}
show-value="false"
id="slCodeFormerWeight"
min="0"
max="10"
value={store.data.codeformer_weight * 10}
onInput={(evt: any) => {
store.data.codeformer_weight = evt.target.value / 10
}}
>
<sp-label
class="title"
style={{ width: '110px', display: 'inline-block' }}
slot="label"
>
CodeFormer weight:
</sp-label>
<sp-label
style={{ display: 'inline-block' }}
class="labelNumber"
slot="label"
id="lCodeFormerWeight"
>
{store.data.codeformer_weight.toFixed(2)}
</sp-label>
</SpSlider>
</div>
</div>
)
}
}
const containers = document.querySelectorAll('.extraPageContainer')!
containers.forEach((container) => {
const root = ReactDOM.createRoot(container)
root.render(
<React.StrictMode>
<ErrorBoundary>
<div style={{ border: '2px solid #6d6c6c', padding: '3px' }}>
<Collapsible defaultIsOpen={true} label={'Extra Page'}>
<ExtraPage />
</Collapsible>
</div>
</ErrorBoundary>
</React.StrictMode>
)
})

View File

@ -8,10 +8,11 @@ import { MoveToCanvasSvg, PenSvg } from '../util/elements'
import { ErrorBoundary } from '../util/errorBoundary'
import Locale from '../locale/locale'
import { addWithHistory } from '../viewer/viewer'
import Collapsible from '../after_detailer/after_detailer'
import { Collapsible } from '../util/collapsible'
//@ts-ignore
import { storage } from 'uxp'
import { _arrayBufferToBase64 } from '../util/ts/io'
import { sd_tab_store } from '../stores'
declare let g_ui_settings_object: any
export const store = new AStore({
images: [] as string[], //full resloution images
@ -134,7 +135,7 @@ async function moveHistoryImageToLayer(
// width,
// height
// )
debugger
const layer = await addWithHistory(
base64_image,
metadata?.expanded_mask ?? void 0,
@ -146,12 +147,12 @@ async function moveHistoryImageToLayer(
}
}
function historyMetadataToPreset(metadata: any) {}
function getHistoryMetadata(metadata_json: any) {
//auto fill the ui with metadata
// const metadata_json = JSON.parse(img.dataset.metadata_json_string)
console.log('metadata_json: ', metadata_json)
// document.querySelector('#tiSeed').value = metadata_json.Seed
//extract auto_metadata into the preset metadata
function convertAutoMetadataToPreset(metadata_json: any) {
@ -220,7 +221,7 @@ function segmentCombinedArray(combinedArray: CombinedElement[]) {
const segmentedArray: CombinedElement[][] = []
let currentSessionId = combinedArray[0].metadata_json.session_id
let currentSegment: CombinedElement[] = []
debugger
for (const element of combinedArray) {
if (element.metadata_json.session_id === currentSessionId) {
currentSegment.push(element)

View File

@ -0,0 +1,58 @@
//TODO: delete lexical_tab.js and lexica tab from html
import { observer } from 'mobx-react'
import React from 'react'
@observer
export class Lexical extends React.Component {
componentDidMount(): void {}
componentWillUnmount(): void {}
render() {
return (
<div>
<div className="subTabOptionsContainer"></div>
<div className="flexContainer">
<sp-label slot="label">
Explore Lexica for prompts and inspiration
</sp-label>
</div>
<div></div>
<div>
<sp-textfield
id="LexicaSearchField"
type="text"
placeholder="cute cats"
value=""
>
<sp-label slot="label">Search:</sp-label>
</sp-textfield>
<button
className="btnSquare search-button"
id="btnSearchLexica"
title="user prompt(text) to Search Lexica"
></button>
<button
className="btnSquare reverse_image_serach"
id="btnReverseSearchLexica"
title="User the selected area (image) on canvas to Search Lexica"
></button>
</div>
<sp-textarea
id="lexicaPrompt"
style="margin-bottom: 3px"
></sp-textarea>
<div className="viewer-container" id="divLexicaImagesContainer">
<img
className="history-image"
id="history_image_test"
data-metadata_json_string='{"a":1}'
src="https://source.unsplash.com/random"
/>
</div>
</div>
)
}
}

View File

@ -3,7 +3,7 @@ import React from 'react'
import ReactDOM from 'react-dom/client'
import { AStore } from './main/astore'
import { ErrorBoundary } from './util/errorBoundary'
import Collapsible from './after_detailer/after_detailer'
import { Collapsible } from './util/collapsible'
interface AStoreData {
positivePrompts: string[]
@ -14,8 +14,8 @@ interface AStoreData {
const defaultPositivePrompt = 'cute cat, {painterly_style_1}'
const defaultNegativePrompt = '{ugly}'
export const store = new AStore({
positivePrompts: Array(4).fill(defaultPositivePrompt),
negativePrompts: Array(4).fill(defaultNegativePrompt),
positivePrompts: [defaultPositivePrompt, ...Array(3).fill('')],
negativePrompts: [defaultNegativePrompt, ...Array(3).fill('')],
current_index: 0,
})
@ -134,20 +134,20 @@ export class MultiTextArea extends React.Component {
}
}
const containers = document.querySelectorAll('.multiPromptsContainer')!
// const containers = document.querySelectorAll('.multiPromptsContainer')!
containers.forEach((container) => {
const root = ReactDOM.createRoot(container)
// containers.forEach((container) => {
// const root = ReactDOM.createRoot(container)
root.render(
<React.StrictMode>
<ErrorBoundary>
<div style={{ border: '2px solid #6d6c6c', padding: '3px' }}>
<Collapsible defaultIsOpen={true} label={'Prompts'}>
<MultiTextArea />
</Collapsible>
</div>
</ErrorBoundary>
</React.StrictMode>
)
})
// root.render(
// <React.StrictMode>
// <ErrorBoundary>
// <div style={{ border: '2px solid #6d6c6c', padding: '3px' }}>
// <Collapsible defaultIsOpen={true} label={'Prompts'}>
// <MultiTextArea />
// </Collapsible>
// </div>
// </ErrorBoundary>
// </React.StrictMode>
// )
// })

View File

@ -1,7 +1,7 @@
import React from 'react'
import ReactDOM from 'react-dom/client'
import Collapsible from '../after_detailer/after_detailer'
import { Collapsible } from '../util/collapsible'
import { observer } from 'mobx-react'
import { AStore } from '../main/astore'
@ -154,45 +154,57 @@ class OneButtonPrompt extends React.Component {
store.data.prompt_complexity = output_value
}}
/>
<sp-label>Subject:</sp-label>
<SpMenu
title="subjects"
items={store.data.subjects}
label_item="Select a Subject"
selected_index={store.data.subjects.indexOf(
store.data.subject
)}
onChange={(id: any, value: any) => {
// console.log('onChange value: ', value)
store.updateProperty('subject', value.item)
}}
></SpMenu>
<sp-label>Artist:</sp-label>
<SpMenu
title="artists"
items={store.data.artists}
label_item="Select an Artist"
selected_index={store.data.artists.indexOf(
store.data.artist
)}
onChange={(id: any, value: any) => {
// console.log('onChange value: ', value)
store.updateProperty('artist', value.item)
}}
></SpMenu>
<sp-label>Image Type:</sp-label>
<SpMenu
title="image types"
items={store.data.imagetypes}
label_item="Select an Image Type"
selected_index={store.data.imagetypes.indexOf(
store.data.imagetype
)}
onChange={(id: any, value: any) => {
// console.log('onChange value: ', value)
store.updateProperty('imagetype', value.item)
}}
></SpMenu>
<div>
<SpMenu
title="subjects"
items={store.data.subjects}
label_item="Select a Subject"
selected_index={store.data.subjects.indexOf(
store.data.subject
)}
onChange={(id: any, value: any) => {
// console.log('onChange value: ', value)
store.updateProperty('subject', value.item)
}}
></SpMenu>
<sp-label style={{ marginLeft: '3px' }}>
Subject
</sp-label>
</div>
<div>
<SpMenu
title="artists"
items={store.data.artists}
label_item="Select an Artist"
selected_index={store.data.artists.indexOf(
store.data.artist
)}
onChange={(id: any, value: any) => {
// console.log('onChange value: ', value)
store.updateProperty('artist', value.item)
}}
></SpMenu>
<sp-label style={{ marginLeft: '3px' }}>
Artist
</sp-label>
</div>
<div>
<SpMenu
title="image types"
items={store.data.imagetypes}
label_item="Select an Image Type"
selected_index={store.data.imagetypes.indexOf(
store.data.imagetype
)}
onChange={(id: any, value: any) => {
// console.log('onChange value: ', value)
store.updateProperty('imagetype', value.item)
}}
></SpMenu>
<sp-label style={{ marginLeft: '3px' }}>
Image Type
</sp-label>
</div>
<div
style={{
display: 'flex',

View File

@ -0,0 +1,285 @@
import React from 'react'
import ReactDOM from 'react-dom/client'
import { observer } from 'mobx-react'
import { ErrorBoundary } from '../util/errorBoundary'
import { Collapsible } from '../util/collapsible'
import Locale from '../locale/locale'
import { PresetTypeEnum } from '../util/ts/enum'
import {
getAllCustomPresetsSettings,
getCustomPresetsNames,
getLoadedPresets,
// getPresetType,
loadPresetSettingsFromFile,
preset_tab_store,
store,
updatePresetMenuEvent,
// updatePresetMenuEvent,
} from './shared_ui_preset'
import { controlnet_preset, general, html_manip, io } from '../util/oldSystem'
import { AStore } from '../main/astore'
import { reaction, toJS } from 'mobx'
import { getUnitsData, setUnitData } from '../controlnet/entry'
import { SpMenu } from '../util/elements'
import { controlNetUnitData } from '../controlnet/store'
import { sd_tab_store } from '../stores'
import { storeToPreset, writePreset } from '../util/ts/io'
declare let g_ui_settings_object: any
reaction(
() => {
return preset_tab_store.data.new_preset
},
(current_preset: any) => {
try {
const text = JSON.stringify(current_preset, undefined, 7) || ''
const textarea_element = document.getElementById(
'taPresetSettings'
) as any
textarea_element.value = text
updateTextAreaHeight(textarea_element)
} catch (e) {
console.error(e)
}
}
)
function getPresetSettingsHtml() {
//@ts-ignore
const value_str = document.getElementById('taPresetSettings')!.value
const value_json = JSON.parse(value_str)
return value_json
}
function updateTextAreaHeight(textarea_element: any) {
try {
//update the height of the text area to fit the settings in
const new_lines_count = general.countNewLines(textarea_element.value)
let height = new_lines_count * 12 + 100
height = Math.max(60, height)
height = Math.min(500, height)
textarea_element.style.height = height.toString() + 'px'
} catch (e) {
console.error(e)
}
}
// function setPresetName(preset_name: string) {
// //@ts-ignore
// document.getElementById('tiPresetName')!.value = preset_name
// }
async function deletePreset() {
try {
const preset_file_name =
preset_tab_store.data.selected_preset_name + '.json'
const custom_preset_entry = await io.IOFolder.getCustomPresetFolder(
'custom_preset'
)
await io.IOJson.deleteFile(custom_preset_entry, preset_file_name)
preset_tab_store.data.selected_preset_name = ''
preset_tab_store.data.new_preset = {}
store.data.custom_presets = await getAllCustomPresetsSettings()
} catch (e) {
console.error(e)
}
}
function filterControlnetUnitData(controlnet_units_data: controlNetUnitData[]) {
const filtered_data = controlnet_units_data.map((unit) => {
const {
input_image,
mask,
detect_map,
model_list,
module_list,
...rest
} = unit
return rest
})
return filtered_data
}
export function onNewPreset() {
const sd_tab_preset = storeToPreset(sd_tab_store)
const controlnet_tab_preset = toJS(getUnitsData())
const units = controlnet_tab_preset.map((unit: controlNetUnitData) => {
if (unit.enabled === false) return {}
else {
const {
input_image,
mask,
detect_map,
model_list,
module_list,
...rest
} = unit
return rest
}
})
const plugin_preset = {
sd_tab_preset: sd_tab_preset,
controlnet_tab_preset: units,
}
preset_tab_store.data.new_preset = plugin_preset
return plugin_preset
}
async function onSavePreset() {
if (preset_tab_store.data.new_preset_name) {
const preset_settings = getPresetSettingsHtml()
const preset_name = preset_tab_store.data.new_preset_name.trim()
const preset_file_name = preset_name + '.json' // will be used as file name
//check if the file exist and prompt the user to override it or cancel
const custom_preset_entry = await io.IOFolder.getCustomPresetFolder(
'custom_preset'
)
await io.IOJson.saveJsonToFileExe(
preset_settings,
custom_preset_entry,
preset_file_name
)
store.data.custom_presets = await getAllCustomPresetsSettings()
console.log('store.data.custom_presets: ', store.data.custom_presets)
preset_tab_store.data.selected_preset_name = preset_name
}
}
@observer
class PresetTab extends React.Component<{}> {
async componentDidMount() {
// await populatePresetMenu()
try {
store.data.custom_presets = await getAllCustomPresetsSettings()
// store.data.controlnet_native_presets = {
// ...controlnet_preset.ControlNetNativePresets,
// }
} catch (e) {
console.error(e)
}
}
renderTab() {
return (
<div>
<sp-textfield
id="tiPresetName"
type="text"
placeholder="Preset Name"
value={preset_tab_store.data.new_preset_name}
style={{ width: '160px' }}
onInput={(event: any) => {
preset_tab_store.data.new_preset_name =
event.target.value
// console.log(store.data.preset_name)
}}
></sp-textfield>
<button
className="btnSquare"
id="btnGeneratePreset"
style={{ marginLeft: '5px' }}
onClick={() => {
onNewPreset()
}}
>
Generate Preset
</button>
<div style={{ marginTop: '3px' }}>
<button
className="btnSquare"
id="btnSavePreset"
style={{}}
onClick={async () => {
await onSavePreset()
}}
>
Save Preset
</button>
<button
className="btnSquare"
id="btnDeletePreset"
style={{ marginLeft: '5px' }}
onClick={async () => {
await deletePreset()
}}
>
Delete Preset
</button>
</div>
<div style={{ marginTop: '3px' }}>
<SpMenu
title="Custom Presets"
items={Object.keys(store.data.custom_presets)}
label_item="Select a Custom Preset"
selected_index={Object.keys(
store.data.custom_presets
).indexOf(preset_tab_store.data.selected_preset_name)}
onChange={(id: any, value: any) => {
// console.log('onChange value: ', value)
// store.updateProperty('subject', value.item)
console.log('value:', value)
preset_tab_store.data.selected_preset_name =
value.item
preset_tab_store.data.new_preset_name = value.item
preset_tab_store.data.new_preset =
store.data.custom_presets[value.item]
}}
></SpMenu>
</div>
<div>
<sp-label id="lPresetName">
{preset_tab_store.data.new_preset_name.trim()}
</sp-label>
</div>
<div>
<sp-textarea
id="taPresetSettings"
placeholder="{}"
value={
JSON.stringify(
preset_tab_store.data.new_preset,
undefined,
7
) || ''
}
onChange={(event: any) => {
console.log('onChange:')
updateTextAreaHeight(event.target)
}}
onInput={(event: any) => {
console.log('onInput:')
updateTextAreaHeight(event.target)
}}
></sp-textarea>
</div>
</div>
)
}
render(): React.ReactNode {
return this.renderTab()
}
}
const gridContainerNode = document.getElementById('PresetTabContainer')!
const gridRoot = ReactDOM.createRoot(gridContainerNode)
gridRoot.render(
<React.StrictMode>
<ErrorBoundary>
<div style={{ border: '2px solid #6d6c6c', padding: '3px' }}>
<Collapsible
defaultIsOpen={true}
label={Locale('Custom Preset')}
>
<PresetTab></PresetTab>
</Collapsible>
</div>
</ErrorBoundary>
</React.StrictMode>
)

View File

@ -0,0 +1,120 @@
import { AStore } from '../main/astore'
import { html_manip, io } from '../util/oldSystem'
import { PresetTypeEnum } from '../util/ts/enum'
// import { getNativeSDPresets } from '../util/ts/ui_ts'
export async function getLoadedPresets(ui_settings_obj: any) {
let customPresets
customPresets = await mapCustomPresetsToLoaders(ui_settings_obj)
console.log('customPresets: ', customPresets)
let loadedPresets = {
// ...getNativeSDPresets(),
...customPresets,
}
return loadedPresets
}
export const store = new AStore({
preset_name: '',
custom_presets: [] as any,
selected_preset_name: '',
sd_presets: [],
sd_native_presets: [],
selected_sd_preset_name: '', // the selected sd preset in sd tab
selected_sd_preset: {}, // the selected sd preset settings
})
export const preset_tab_store = new AStore({
new_preset_name: '', //for the textfield field and label
new_preset: {} as any, // settings of the current preset tab preset
selected_preset_name: '', // name of the selected in the menu
selected_preset: {}, //settings of the selected preset in the menu
})
export async function getCustomPresetEntries(preset_folder_name: string) {
const custom_preset_entry = await io.IOFolder.getCustomPresetFolder(
preset_folder_name
)
const custom_preset_entries = await io.IOJson.getJsonEntries(
custom_preset_entry
)
return custom_preset_entries
}
export async function loadPresetSettingsFromFile(preset_file_name: string) {
const custom_preset_entry = await io.IOFolder.getCustomPresetFolder(
'custom_preset'
)
let preset_settings = {}
try {
preset_settings = await io.IOJson.loadJsonFromFile(
custom_preset_entry,
preset_file_name
)
} catch (e) {
console.warn(e)
}
return preset_settings
}
export async function getAllCustomPresetsSettings() {
const custom_preset_entries = await getCustomPresetEntries('custom_preset')
let custom_presets: any = {}
for (const entry of custom_preset_entries) {
const preset_name: string = entry.name.split('.json')[0]
let preset_settings = await loadPresetSettingsFromFile(entry.name)
custom_presets[preset_name] = preset_settings
}
return custom_presets
}
const updatePresetMenuEvent = new CustomEvent('updatePresetMenuEvent', {
detail: {},
bubbles: true,
cancelable: true,
composed: false,
})
export function loadPreset(ui_settings: any, preset: any) {
console.log('preset:', preset)
ui_settings.autoFillInSettings(preset)
}
export function loadCustomPreset(
ui_settings_obj: any,
custom_preset_settings: any
) {
loadPreset(ui_settings_obj, custom_preset_settings)
}
export async function mapCustomPresetsToLoaders(ui_settings_obj: any) {
const name_to_settings_obj = await getAllCustomPresetsSettings()
const preset_name_to_loader_obj: any = {}
for (const [preset_name, preset_settings] of Object.entries(
name_to_settings_obj
)) {
preset_name_to_loader_obj[preset_name] = () => {
loadCustomPreset(ui_settings_obj, preset_settings)
}
}
return preset_name_to_loader_obj
}
export function getCustomPresetsNames(custom_presets: any) {
let presets_names: any = []
if (custom_presets) {
presets_names = Object.keys(custom_presets)
}
return presets_names
}
export function onLoadControlnetPreset() {}
export function onLoadSDPreset() {}
//sd preset = {preset_name: settings_json}
//sd_preset_loader(sd_preset)
//controlnet_preset = {preset_name: settings_json}
export { updatePresetMenuEvent }

View File

@ -1,6 +1,6 @@
import React from 'react'
import ReactDOM from 'react-dom/client'
import Collapsible from '../after_detailer/after_detailer'
import { Collapsible } from '../util/collapsible'
import { observer } from 'mobx-react'
import { isScriptInstalled } from '../util/ts/api'
import { api, general, io, psapi, selection } from '../util/oldSystem'
@ -11,14 +11,12 @@ import {
PenSvg,
ScriptInstallComponent,
} from '../util/elements'
import {
applyMaskFromBlackAndWhiteImage,
selectionFromBlackAndWhiteImage,
} from '../util/ts/selection'
import { selectionFromBlackAndWhiteImage } from '../util/ts/selection'
import { app } from 'photoshop'
import { ErrorBoundary } from '../util/errorBoundary'
import Locale from '../locale/locale'
import { settings_tab_ts } from '../entry'
// import { settings_tab_ts } from '../entry'
import * as settings_tab_ts from '../settings/settings'
import { SelectionInfoType } from '../util/ts/enum'
declare let g_sd_url: string

File diff suppressed because it is too large Load Diff

652
typescripts/sd_tab/util.ts Normal file
View File

@ -0,0 +1,652 @@
import { control_net, main } from '../entry'
import { AStore } from '../main/astore'
import { script_store } from '../ultimate_sd_upscaler/scripts'
import { ScriptMode } from '../ultimate_sd_upscaler/ultimate_sd_upscaler'
import {
dialog_box,
general,
html_manip,
sampler_data,
settings_tab,
thumbnail,
} from '../util/oldSystem'
import { requestGet } from '../util/ts/api'
import { GenerationModeEnum, SelectionInfoType } from '../util/ts/enum'
import {
getVersionRequest,
requestGetModels,
requestGetSamplers,
requestGetUpscalers,
setInpaintMaskWeight,
} from '../util/ts/sdapi'
import { store as session_store } from '../session/session_store'
import { setUnitData } from '../controlnet/entry'
import { controlNetUnitData } from '../controlnet/store'
import { presetToStore } from '../util/ts/io'
import { refreshExtraUpscalers } from '../extra_page/extra_page'
declare let g_models: any[]
declare let g_automatic_status: any
declare let g_sd_options_obj: any
declare let g_controlnet_max_models: number
declare let g_sd_url: string
export const mode_config = [
{
name: 'txt2img',
title: 'use this mode to generate images from text only',
id: '',
},
{
name: 'img2img',
title: 'use this mode to generate variation of an image',
id: '',
},
{
name: 'inpaint',
title: 'use this mode to generate variation of a small area of an image, while keeping the rest of the image intact',
id: 'rbModeInpaint',
},
{
name: 'outpaint',
title: 'use this mode to (1) fill any missing area of an image,(2) expand an image',
id: '',
},
]
export const mask_content_config = [
{
name: 'fill',
value: 0,
},
{
name: 'original',
value: 1,
},
{
name: 'latent noise',
value: 2,
},
{
name: 'latent nothing',
value: 3,
},
]
export enum SelectionModeEnum {
Ratio = 'ratio',
Precise = 'precise',
Ignore = 'ignore',
}
export const selection_mode_config = [
{
name: 'ratio',
value: 'ratio',
title: '',
},
{
name: 'precise',
value: 'precise',
title: 'use the selection area width and height to fill the width and height sliders',
},
{
name: 'ignore',
value: 'ignore',
title: 'fill the width and height sliders manually',
},
]
export const store = new AStore({
selected_model: '',
is_lasso_mode: false,
mode: GenerationModeEnum.Txt2Img,
rb_mode: ScriptMode.Txt2Img,
batch_size: 1,
batch_count: 1,
steps: 20,
width: 512,
height: 512,
ratio: 1.0,
cfg: 7.0,
b_width_height_link: true,
denoising_strength: 0.7,
hr_denoising_strength: 0.7,
inpaint_full_res: false,
enable_hr: false,
sampler_name: 'Euler a',
image_cfg_scale: 1.5,
seed: '-1' as string,
mask_blur: 0,
mask_expansion: 0,
inpaint_full_res_padding: 0,
hr_scale: 2.0,
hr_resize_x: 512,
hr_resize_y: 512,
hr_second_pass_steps: 0,
restore_faces: false,
inpainting_fill: mask_content_config[0].value,
hr_upscaler: '',
selection_mode: selection_mode_config[0].value,
})
export const default_preset = {
sd_tab_preset: {
prompt: '',
negative_prompt: '',
// is_lasso_mode: false,
batch_size: 1,
batch_count: 1,
steps: 20,
width: 512,
height: 512,
ratio: 1,
cfg: 7,
b_width_height_link: true,
denoising_strength: 0.7,
hr_denoising_strength: 0.7,
// inpaint_full_res: false,
// enable_hr: false,
sampler_name: 'Euler a',
image_cfg_scale: 1.5,
seed: '-1',
mask_blur: 0,
mask_expansion: 0,
inpaint_full_res_padding: 0,
hr_scale: 2,
hr_resize_x: 512,
hr_resize_y: 512,
hr_second_pass_steps: 0,
// restore_faces: false,
inpainting_fill: 0,
hr_upscaler: '',
selection_mode: 'ratio',
},
controlnet_tab_preset: [{}, {}, {}, {}, {}, {}, {}],
}
export const helper_store = new AStore({
b_show_sampler: false, //false when off, true when on,
models: [] as any[],
loras: [] as any[],
sampler_list: [] as any[],
hr_upscaler_list: [] as string[],
previous_width: 512,
previous_height: 512,
})
export async function refreshModels() {
let b_result = false
try {
g_models = await requestGetModels()
if (g_models.length > 0) {
b_result = true
}
helper_store.data.models = g_models
// for (let model of g_models) {
// // console.log(model.title)//Log
// // const menu_item_element = document.createElement('sp-menu-item')
// // menu_item_element.className = 'mModelMenuItem'
// menu_item_element.innerHTML = model.title
// menu_item_element.dataset.model_hash = model.hash
// menu_item_element.dataset.model_title = model.title
// // document
// // .getElementById('mModelsMenu')
// // .appendChild(menu_item_element)
// }
} catch (e) {
b_result = false
console.warn(e)
}
return b_result
}
async function promptForUpdate(header_message: any, long_message: any) {
const shell = require('uxp').shell
;(async () => {
const buttons = ['Cancel', 'OK']
const r1 = await dialog_box.prompt(
header_message,
long_message,
buttons
// 'Please Update you Plugin. it will take about 10 seconds to update',
// 'update from discord, update from github'[
// ['Cancel', 'Discord', 'Github']
// ('Cancel', 'OK')
// ]
)
let url
try {
if (r1 === 'Cancel') {
/* cancelled or No */
console.log('cancel')
} else if (r1 === 'Github') {
url =
'https://github.com/AbdullahAlfaraj/Auto-Photoshop-StableDiffusion-Plugin'
// await py_re.openUrlRequest(url)
} else if (r1 === 'Discord') {
console.log('Discord')
// url = 'https://discord.gg/3mVEtrddXJ'
// url = 'https://discord.gg/YkUJXYWK3c'
// await py_re.openUrlRequest(url)
} else if (r1 === 'Ok') {
}
// console.log('url: ', url)
} catch (e) {
console.warn(e, url)
}
})()
}
export async function updateClickEventHandler(current_version: string) {
try {
const online_data = await general.requestOnlineData()
const b_need_update = general.compareVersions(
current_version,
online_data.new_version
)
let header_message = "You're Plugin is up to date."
let long_message = ''
if (b_need_update) {
header_message = `New Version is Available (${online_data.new_version})`
long_message = online_data.update_message
}
await promptForUpdate(header_message, long_message)
} catch (e) {
console.warn(e)
}
}
export function tempDisableElement(element: any, time: number) {
element.classList.add('disableBtn')
element.disabled = true
// element.style.opacity = '0.65'
// element.style.cursor = 'not-allowed'
setTimeout(function () {
element.disabled = false
element.classList.remove('disableBtn')
// element.style.opacity = '1.0'
// element.style.cursor = 'default'
}, time)
}
async function updateVersionUI() {
let bStatus = false
try {
const version = await getVersionRequest()
document.getElementById('lVersionNumber')!.textContent = version
if (version !== 'v0.0.0') {
bStatus = true
}
} catch (e) {
console.warn(e)
document.getElementById('lVersionNumber')!.textContent = 'v0.0.0'
bStatus = false
}
return bStatus
}
//REFACTOR: move to generation_settings.js
export async function initSamplers() {
let bStatus = false
try {
// let sampler_group = document.getElementById('sampler_group')!
// sampler_group.innerHTML = ''
let samplers = await requestGetSamplers()
if (!samplers) {
//if we failed to get the sampler list from auto1111, use the list stored in sampler.js
samplers = sampler_data.samplers
}
helper_store.data.sampler_list = samplers
// for (let sampler of samplers) {
// // console.log(sampler)//Log
// // sampler.name
// // <sp-radio class="rbSampler" value="Euler">Euler</sp-radio>
// // const rbSampler = document.createElement('sp-radio')
// // rbSampler.innerHTML = sampler.name
// // rbSampler.setAttribute('class', 'rbSampler')
// // rbSampler.setAttribute('value', sampler.name)
// // sampler_group.appendChild(rbSampler)
// //add click event on radio button for Sampler radio button, so that when a button is clicked it change g_sd_sampler globally
// }
// document
// .getElementsByClassName('rbSampler')[0]
// .setAttribute('checked', '')
if (samplers.length > 0) {
bStatus = true
}
} catch (e) {
console.warn(e)
}
return bStatus
}
export async function refreshUI() {
try {
const b_proxy_server_status = await updateVersionUI()
if (b_proxy_server_status) {
html_manip.setProxyServerStatus('connected', 'disconnected')
// g_automatic_status = Enum.AutomaticStatusEnum['RunningWithApi']
} else {
html_manip.setProxyServerStatus('disconnected', 'connected')
}
//@ts-ignore
g_automatic_status = await checkAutoStatus()
//@ts-ignore
await displayNotification(g_automatic_status)
const bSamplersStatus = await initSamplers()
await refreshModels()
helper_store.data.loras = await requestLoraModels()
await refreshExtraUpscalers()
await setInpaintMaskWeight(1.0) //set the inpaint conditional mask to 1 when the on plugin start
//get the latest options
await g_sd_options_obj.getOptions()
//get the selected model
store.data.selected_model = g_sd_options_obj.getCurrentModel()
//update the ui with that model title
// const current_model_hash =
// html_manip.getModelHashByTitle(current_model_title)
// html_manip.autoFillInModel(current_model_hash)
//fetch the inpaint mask weight from sd webui and update the slider with it.
const inpainting_mask_weight =
await g_sd_options_obj.getInpaintingMaskWeight()
console.log('inpainting_mask_weight: ', inpainting_mask_weight)
html_manip.autoFillInInpaintMaskWeight(inpainting_mask_weight)
//init ControlNet Tab
helper_store.data.hr_upscaler_list = await requestGetHiResUpscalers()
g_controlnet_max_models = await control_net.requestControlNetMaxUnits()
await control_net.initializeControlNetTab(g_controlnet_max_models)
await main.populateVAE()
} catch (e) {
console.warn(e)
}
}
export async function requestGetHiResUpscalers(): Promise<string[]> {
try {
const full_url = `${g_sd_url}/sdapi/v1/upscalers`
let upscalers = await requestGet(full_url)
return [
'Latent',
'Latent (antialiased)',
'Latent (bicubic)',
'Latent (bicubic antialiased)',
'Latent (nearest)',
'Latent (nearest-exact)',
...upscalers.map((upscaler: any) => upscaler.name),
]
} catch (e) {
console.warn('requestGetHiResUpscalers:', e)
return [
'Latent',
'Latent (antialiased)',
'Latent (bicubic)',
'Latent (bicubic antialiased)',
'Latent (nearest)',
'Latent (nearest-exact)',
]
}
}
export async function requestLoraModels() {
const full_url = `${g_sd_url}/sdapi/v1/loras`
const lora_models = (await requestGet(full_url)) ?? []
return lora_models
}
export function getLoraModelPrompt(lora_model_name: string) {
return `<lora:${lora_model_name}:1>`
}
//add click event on radio button mode, so that when a button is clicked it change g_sd_mode globally
//REFACTOR: move to events.js
declare let g_sd_mode: string
export async function onModeChange(new_mode: ScriptMode) {
try {
g_sd_mode = new_mode
script_store.setMode(new_mode)
store.data.rb_mode = new_mode
store.data.mode = store.data.rb_mode as unknown as GenerationModeEnum
// console.log(`You clicked: ${g_sd_mode}`)
//@ts-ignore
await postModeSelection() // do things after selection
} catch (e) {
console.warn(e)
}
}
export function viewMaskExpansion() {
if (session_store.data.expanded_mask) {
const mask_src = general.base64ToBase64Url(
session_store.data.expanded_mask
)
html_manip.setInitImageMaskSrc(mask_src)
} else {
console.log(
'the mask has not been expanded, g_generation_session.base64maskExpansionImage is empty'
)
}
}
function viewDrawnMask() {
//this is the generated mask or user drawn mask, but it's not the mask after expansion
if (session_store.data.mask) {
const mask_src = general.base64ToBase64Url(session_store.data.mask)
html_manip.setInitImageMaskSrc(mask_src)
} else {
console.log('no mask is available')
}
}
export function initInitMaskElement() {
//make init mask image use the thumbnail class with buttons
const mask_image_html = html_manip.getInitImageMaskElement()
const mask_parent_element = mask_image_html.parentElement
const thumbnail_container = thumbnail.Thumbnail.wrapImgInContainer(
mask_image_html,
'viewer-image-container'
)
mask_parent_element.appendChild(thumbnail_container)
thumbnail.Thumbnail.addSPButtonToContainer(
thumbnail_container,
'svg_sp_btn',
'view original mask',
viewDrawnMask,
null
)
thumbnail.Thumbnail.addSPButtonToContainer(
thumbnail_container,
'svg_sp_btn_expand',
'view modified mask',
viewMaskExpansion,
null
)
// populateLoraModelMenu() // no need for await
}
function scaleToRatio(
newValue1: number,
oldValue1: number,
newValue2: undefined, //get ignored
oldValue2: number,
maxValue: number,
minValue: number
) {
const ratio = newValue1 / oldValue1
let finalNewValue2 = Math.max(
minValue,
Math.min(maxValue, oldValue2 * ratio)
)
let finalNewValue1 = newValue1
if (finalNewValue2 === maxValue || finalNewValue2 === minValue) {
finalNewValue1 = oldValue1 * (finalNewValue2 / oldValue2)
}
return [finalNewValue1, finalNewValue2]
}
export function widthSliderOnChangeEventHandler(
new_value: number,
min_value: number,
max_value: number
) {
try {
const b_link = store.data.b_width_height_link
let final_width = new_value
let final_height
if (b_link) {
;[final_width, final_height] = scaleToRatio(
new_value,
helper_store.data.previous_width,
undefined,
store.data.height,
max_value,
min_value
)
store.data.width = final_width
store.data.height = final_height
helper_store.data.previous_width = store.data.width
helper_store.data.previous_height = store.data.height
}
} catch (e) {
console.error(e)
}
}
export function heightSliderOnChangeEventHandler(
new_value: number,
min_value: number,
max_value: number
) {
try {
let new_height = new_value
const b_link = store.data.b_width_height_link
let final_height = new_height
let final_width
if (b_link) {
;[final_height, final_width] = scaleToRatio(
new_height,
helper_store.data.previous_height,
undefined,
store.data.width,
max_value,
min_value
)
store.data.width = final_width
store.data.height = final_height
helper_store.data.previous_width = store.data.width
helper_store.data.previous_height = store.data.height
}
} catch (e) {
console.error(e)
}
}
export function calcLinkedValue(new_value: number) {}
export async function initPlugin() {
try {
//*) load plugin settings
//*) load horde settings
//*)
//*) initialize the samplers
//*)
await settings_tab.loadSettings()
// await horde_native.HordeSettings.loadSettings()
const bSamplersStatus = await initSamplers() //initialize the sampler
await setInpaintMaskWeight(1.0) //set the inpaint conditional mask to 1 when the on plugin start
await refreshUI()
//@ts-ignore
await loadPromptShortcut()
//@ts-ignore
await refreshPromptMenu()
} catch (e) {
console.error(e)
}
}
export function scaleFromToLabel(width: number, height: number, scale: number) {
const hr_width = Math.ceil(width * scale)
const hr_height = Math.ceil(height * scale)
return `${width}x${height} -> ${hr_width}x${hr_height}`
}
export function onWidthSliderInput(new_value: number) {
try {
store.data.width = new_value
store.data.ratio = calcRatio(
new_value,
store.data.height,
session_store.data.current_selection_info
)
} catch (e) {
console.error(e)
}
}
export function onHeightSliderInput(new_value: number) {
try {
store.data.height = new_value
store.data.ratio = calcRatio(
store.data.width,
new_value,
session_store.data.current_selection_info
)
} catch (e) {
console.error(e)
}
}
export function calcRatio(
width: number,
height: number,
selectionInfo: SelectionInfoType | undefined
) {
let ratio = 1
if (selectionInfo) {
ratio = (width * height) / (selectionInfo.width * selectionInfo.height)
}
return ratio
}
export function loadPresetSettings(preset: any) {
if (preset?.sd_tab_preset) {
presetToStore(preset?.sd_tab_preset, store)
}
if (preset?.controlnet_tab_preset) {
preset?.controlnet_tab_preset.forEach(
(unit: controlNetUnitData, index: number) => {
try {
setUnitData(unit, index)
} catch (e) {
console.log('error at unit index: ', index)
console.error(e)
}
}
)
// io_ts.presetToStore(preset?.controlnet_tab_preset, store)
}
}

View File

@ -3,13 +3,24 @@ import ReactDOM from 'react-dom/client'
import { observer } from 'mobx-react'
import { sd_tab_ts, session_ts, viewer } from '../entry'
// import { sd_tab_ts, session_ts, viewer } from '../entry'
import { store as session_store } from '../session/session_store'
import { Session } from '../session/session'
// import * as sd_tab_ts from '../sd_tab/sd_tab'
import { store as sd_tab_store } from '../sd_tab/util'
import * as viewer from '../viewer/viewer'
import './style/generate.css'
import { io, note, psapi, selection } from '../util/oldSystem'
import { GenerationModeEnum } from '../util/ts/enum'
import { initializeBackground } from '../util/ts/document'
import Locale from '../locale/locale'
import { ErrorBoundary } from '../util/errorBoundary'
import {
store as viewer_store,
mask_store as viewer_mask_store,
// init_store as viewer_init_store,
} from '../viewer/viewer_util'
declare let g_automatic_status: any
declare let g_current_batch_index: number
//example: take 'oI' in 'LassoInpaint' and replace it with 'o I' thus creating 'Lasso Inpaint'
@ -20,7 +31,7 @@ const modeDisplayNames = Object.fromEntries(
])
)
const GenerateButtons = observer(() => {
export const GenerateButtons = observer(() => {
return (
<div>
<button
@ -28,28 +39,26 @@ const GenerateButtons = observer(() => {
className="btnSquare generateButtonMargin generateColor"
onClick={handleGenerateBatch}
style={{
display: session_ts.store.data.can_generate
? void 0
: 'none',
display: session_store.data.can_generate ? void 0 : 'none',
}}
>
Generate {modeDisplayNames[sd_tab_ts.store.data.mode]}
Generate {modeDisplayNames[sd_tab_store.data.mode]}
</button>
{session_ts.store.data.can_generate ? (
{session_store.data.can_generate ? (
<button
onClick={handleGenerateMoreBatch}
disabled={
session_ts.store.data.can_generate_more ? void 0 : true
session_store.data.can_generate_more ? void 0 : true
}
id="btnNewGenerateMore"
className={
'btnSquare generateButtonMargin generateMoreColor' +
(session_ts.store.data.can_generate_more
(session_store.data.can_generate_more
? ''
: 'disableBtn')
}
style={{
display: session_ts.store.data.can_generate_more
display: session_store.data.can_generate_more
? 'inline-block'
: 'none',
}}
@ -59,7 +68,7 @@ const GenerateButtons = observer(() => {
) : (
void 0
)}
{!session_ts.store.data.can_generate ? (
{!session_store.data.can_generate ? (
<button
onClick={handleInterrupt}
id="btnNewInterrupt"
@ -80,15 +89,14 @@ const ToolbarGenerateButtons = observer(() => {
height: '30px',
marginBottom: '3px',
}
const generate_display = session_ts.store.data.can_generate
const generate_display = session_store.data.can_generate
? 'inline-flex'
: 'none'
const generate_more_display =
session_ts.store.data.can_generate &&
session_ts.store.data.can_generate_more
session_store.data.can_generate && session_store.data.can_generate_more
? 'inline-flex'
: 'none'
const interrupt_display = session_ts.store.data.can_generate
const interrupt_display = session_store.data.can_generate
? 'none'
: 'inline-flex'
return (
@ -137,20 +145,18 @@ const canStartSession = async () => {
const selection_info = await psapi.getSelectionInfoExe()
if (selection_info) {
session_ts.Session.endSession()
Session.endSession()
can_start_session = true
} else {
can_start_session = await note.Notification.inactiveSelectionArea(
session_ts.store.data.is_active,
session_store.data.is_active,
'Reuse Selection'
)
if (can_start_session) {
//end current session and start a new one
session_ts.Session.endSession()
await psapi.reSelectMarqueeExe(
session_ts.store.data.selectionInfo
)
Session.endSession()
await psapi.reSelectMarqueeExe(session_store.data.selectionInfo)
}
}
//@ts-ignore
@ -166,7 +172,7 @@ const canStartSession = async () => {
const resetBatch = () => {
g_current_batch_index = -1
session_ts.store.data.is_interrupted = false
session_store.data.is_interrupted = false
}
// declare let g_sd_mode: any
const handleGenerate = async () => {
@ -175,15 +181,16 @@ const handleGenerate = async () => {
await selection.selectionToChannel('mask')
await initializeBackground() //fix background if there is a need
console.log('mode: ', sd_tab_ts.store.data.mode)
console.log('mode: ', sd_tab_store.data.mode)
try {
if (!(await canStartSession())) {
return void 0
}
var { output_images, response_json } =
await session_ts.Session.generate(sd_tab_ts.store.data.mode)
var { output_images, response_json } = await Session.generate(
sd_tab_store.data.mode
)
if (session_ts.store.data.is_interrupted) {
if (session_store.data.is_interrupted) {
return void 0
}
@ -193,26 +200,23 @@ const handleGenerate = async () => {
thumbnail_list.push(thumbnail)
}
viewer.store.updateProperty('thumbnails', thumbnail_list)
viewer.store.updateProperty('images', output_images)
viewer_store.updateProperty('thumbnails', thumbnail_list)
viewer_store.updateProperty('images', output_images)
if (
[
GenerationModeEnum.Inpaint,
GenerationModeEnum.LassoInpaint,
GenerationModeEnum.Outpaint,
].includes(session_ts.store.data.mode)
].includes(session_store.data.mode)
) {
viewer.mask_store.updateProperty(
viewer_mask_store.updateProperty(
'output_images_masks',
Array(output_images.length).fill(
session_ts.store.data.expanded_mask
session_store.data.expanded_mask
)
)
}
console.log(
'session_ts.store.toJsFunc(): ',
session_ts.store.toJsFunc()
)
console.log('session_store.toJsFunc(): ', session_store.toJsFunc())
} catch (e) {
console.error(e)
console.warn('output_images: ', output_images)
@ -222,10 +226,9 @@ const handleGenerate = async () => {
const handleGenerateMore = async () => {
try {
var { output_images, response_json } =
await session_ts.Session.generateMore()
var { output_images, response_json } = await Session.generateMore()
if (session_ts.store.data.is_interrupted) {
if (session_store.data.is_interrupted) {
return void 0
}
@ -234,13 +237,13 @@ const handleGenerateMore = async () => {
const thumbnail = await io.createThumbnail(base64, 300)
thumbnail_list.push(thumbnail)
}
viewer.store.data.thumbnails = [
...viewer.store.data.thumbnails,
viewer_store.data.thumbnails = [
...viewer_store.data.thumbnails,
...thumbnail_list,
]
viewer.store.data.images = [
...viewer.store.data.images,
viewer_store.data.images = [
...viewer_store.data.images,
...output_images,
]
@ -249,19 +252,19 @@ const handleGenerateMore = async () => {
GenerationModeEnum.Inpaint,
GenerationModeEnum.LassoInpaint,
GenerationModeEnum.Outpaint,
].includes(session_ts.store.data.mode)
].includes(session_store.data.mode)
) {
viewer.mask_store.updatePropertyArray(
viewer_mask_store.updatePropertyArray(
'output_images_masks',
Array(output_images.length).fill(
session_ts.store.data.expanded_mask
session_store.data.expanded_mask
)
)
}
// viewer.store.updateProperty('images', output_images)
// console.log(
// 'session_ts.store.toJsFunc(): ',
// session_ts.store.toJsFunc()
// 'session_store.toJsFunc(): ',
// session_store.toJsFunc()
// )
} catch (e) {
console.error(e)
@ -272,15 +275,14 @@ const handleGenerateMore = async () => {
const handleGenerateBatch = async () => {
try {
const numberOfBatchCount: number = parseInt(
//@ts-ignore
document.querySelector('#tiNumberOfBatchCount').value
const numberOfBatchCount: number = Math.floor(
sd_tab_store.data.batch_count
)
await handleGenerate() //first generation is always use handleGenerate
for (
let i = 1;
i < numberOfBatchCount && !session_ts.store.data.is_interrupted;
i < numberOfBatchCount && !session_store.data.is_interrupted;
i++
) {
// if (g_batch_count_interrupt_status === true) {
@ -298,15 +300,14 @@ const handleGenerateBatch = async () => {
}
const handleGenerateMoreBatch = async () => {
try {
const numberOfBatchCount: number = parseInt(
//@ts-ignore
document.querySelector('#tiNumberOfBatchCount').value
const numberOfBatchCount: number = Math.floor(
sd_tab_store.data.batch_count
)
// await handleGenerateMore() //first generation is always use handleGenerate
for (
let i = 0;
i < numberOfBatchCount && !session_ts.store.data.is_interrupted;
i < numberOfBatchCount && !session_store.data.is_interrupted;
i++
) {
// if (g_batch_count_interrupt_status === true) {
@ -325,35 +326,12 @@ const handleGenerateMoreBatch = async () => {
}
const handleInterrupt = async () => {
try {
// debugger
await session_ts.Session.interrupt()
await Session.interrupt()
} catch (e) {
console.error(e)
}
}
const container = document.getElementById('generateButtonsContainer')!
const root = ReactDOM.createRoot(container)
root.render(
<React.StrictMode>
<ErrorBoundary>
<GenerateButtons></GenerateButtons>
</ErrorBoundary>
</React.StrictMode>
)
const extraContainer = document.getElementById('extraGenerateButtonsContainer')!
const extraRoot = ReactDOM.createRoot(extraContainer)
extraRoot.render(
<React.StrictMode>
<ErrorBoundary>
<GenerateButtons></GenerateButtons>
</ErrorBoundary>
</React.StrictMode>
)
const toolBarButtonsContainer = document.getElementById(
'toolbarGenerateButtonsContainer'
)!

View File

@ -1,4 +1,8 @@
import { control_net, scripts, session_ts } from '../entry'
// import { control_net, scripts, session_ts } from '../entry'
// import * as session_ts from '../session/session'
import * as scripts from '../ultimate_sd_upscaler/scripts'
import * as control_net from '../controlnet/entry'
import { store as session_store } from '../session/session_store'
import {
html_manip,
@ -16,13 +20,15 @@ import {
getModuleDetail,
mapPluginSettingsToControlNet,
} from '../controlnet/entry'
import { store as extra_page_store } from '../extra_page/extra_page'
const executeAsModal = core.executeAsModal
declare let g_inpaint_mask_layer: any
declare let g_sd_url: any
declare let g_controlnet_max_models: any
declare let g_generation_session: any
declare let g_last_seed: any
interface SessionData {
init_image?: string
mask?: string
@ -48,7 +54,7 @@ async function saveOutputImagesToDrive(images_info: any, settings: any) {
) //save the settings
index += 1
}
g_last_seed =
session_store.data.last_seed =
images_info?.length > 0 ? images_info[0]?.auto_metadata?.Seed : '-1'
return base64OutputImages
}
@ -200,7 +206,7 @@ export class Txt2ImgMode extends Mode {
//update the mask in controlNet tab
const numOfImages = json['images'].length
let numberOfAnnotations =
numOfImages - session_ts.store.data.ui_settings.batch_size
numOfImages - session_store.data.ui_settings.batch_size
if (numberOfAnnotations < 0) numberOfAnnotations = 0
const base64_mask = json['images'].slice(
@ -243,13 +249,13 @@ export class Txt2ImgMode extends Mode {
if (b_enable_control_net) {
//use control net
if (session_ts.store.data.generation_number === 1) {
session_ts.store.data.controlnet_input_image =
if (session_store.data.generation_number === 1) {
session_store.data.controlnet_input_image =
await io.getImg2ImgInitImage()
}
// console.log(
// 'session_ts.store.data.controlnet_input_image: ',
// session_ts.store.data.controlnet_input_image
// 'session_store.data.controlnet_input_image: ',
// session_store.data.controlnet_input_image
// )
response_json = await this.requestControlNetTxt2Img(settings)
@ -343,7 +349,7 @@ export class Img2ImgMode extends Mode {
//update the mask in controlNet tab
const numOfImages = json['images'].length
let numberOfAnnotations =
numOfImages - session_ts.store.data.ui_settings.batch_size
numOfImages - session_store.data.ui_settings.batch_size
if (numberOfAnnotations < 0) numberOfAnnotations = 0
// To fix a bug: when Ultimate SD Upscale is active and running, the detection maps wont be retrieved.
@ -535,39 +541,35 @@ export class UpscaleMode extends Img2ImgMode {
let payload: any = {}
try {
const upscaling_resize = html_manip.getUpscaleSize()
const gfpgan_visibility = html_manip.getGFPGANVisibility()
const codeformer_visibility = html_manip.getCodeFormerVisibility()
const codeformer_weight = html_manip.getCodeFormerWeight()
// const selection_info = await psapi.getSelectionInfoExe()
const selection_info = session_data.selectionInfo
const upscaling_resize = extra_page_store.data.upscaling_resize
const width = selection_info.width * upscaling_resize
const height = selection_info.height * upscaling_resize
//resize_mode = 0 means "resize to upscaling_resize"
//resize_mode = 1 means "resize to width and height"
payload['resize_mode'] = 0
payload['show_extras_results'] = 0
payload['gfpgan_visibility'] = gfpgan_visibility
payload['codeformer_visibility'] = codeformer_visibility
payload['codeformer_weight'] = codeformer_weight
payload['resize_mode'] = extra_page_store.data.resize_mode
payload['show_extras_results'] =
extra_page_store.data.show_extras_results
payload['gfpgan_visibility'] =
extra_page_store.data.gfpgan_visibility
payload['codeformer_visibility'] =
extra_page_store.data.codeformer_visibility
payload['codeformer_weight'] =
extra_page_store.data.codeformer_weight
payload['upscaling_resize'] = upscaling_resize
payload['upscaling_resize_w'] = width
payload['upscaling_resize_h'] = height
payload['upscaling_crop'] = true
const upscaler1 =
//@ts-ignore
document.querySelector('#hrModelsMenuUpscale1').value
payload['upscaling_crop'] = extra_page_store.data.upscaling_crop
const upscaler1 = extra_page_store.data.upscaler_1
const upscaler2 = extra_page_store.data.upscaler_2
payload['upscaler_1'] = upscaler1 ? upscaler1 : 'None'
payload['upscaler_2'] = upscaler2 ? upscaler2 : 'None'
payload['upscaler_1'] = upscaler1 === undefined ? 'None' : upscaler1
const upscaler2 =
//@ts-ignore
document.querySelector('#hrModelsMenuUpscale2').value
payload['upscaler_2'] = upscaler2 === undefined ? 'None' : upscaler2
const extras_upscaler_2_visibility =
html_manip.getUpscaler2Visibility()
payload['extras_upscaler_2_visibility'] =
extras_upscaler_2_visibility
payload['upscale_first'] = false
extra_page_store.data.extras_upscaler_2_visibility
payload['upscale_first'] = extra_page_store.data.upscale_first
payload['image'] = session_data.init_image
} catch (e) {
@ -575,6 +577,7 @@ export class UpscaleMode extends Img2ImgMode {
}
return payload
}
static async generate(settings: any): Promise<{
output_images: any
response_json: any

View File

@ -2,7 +2,9 @@ import { reaction } from 'mobx'
import { AStore } from '../main/astore'
import { io, layer_util } from '../util/oldSystem'
import Locale from '../locale/locale'
import { session_ts } from '../entry'
import { store as session_store } from '../session/session_store'
// import { session_ts } from '../entry'
// import * as session_ts from '../session/session'
import { app, core } from 'photoshop'
const executeAsModal = core.executeAsModal
@ -16,6 +18,7 @@ export const store = new AStore({
progress_label: Locale('Progress..'),
can_update: true,
can_update_progress_layer: true,
live_progress_image: true,
})
declare let g_sd_url: string
@ -31,7 +34,7 @@ async function updateProgressImage(progress_base64: string) {
await Progress.deleteProgressLayer() // delete the old progress layer
//update the progress image
const selection_info = await session_ts.store.data.selectionInfo
const selection_info = await session_store.data.selectionInfo
const b_exsit = layer_util.Layer.doesLayerExist(
store.data.progress_layer
@ -70,12 +73,12 @@ reaction(
const { width, height } = await io.getImageSize(progress_image)
store.data.progress_image_height = height
}
const b_update_progress_layer: Boolean = (
document.querySelector('.chLiveProgressImageClass') as any
).checked
const b_update_progress_layer = store.data.live_progress_image
store.data.live_progress_image = b_update_progress_layer
if (
b_update_progress_layer &&
session_ts.store.data.ui_settings.batch_size === 1 &&
session_store.data.ui_settings.batch_size === 1 &&
store.data.can_update_progress_layer &&
store.data.can_update // progress is still active
) {

View File

@ -1,15 +1,16 @@
import { app } from 'photoshop'
import { control_net, preview, viewer, progress } from '../entry'
import Locale from '../locale/locale'
import { AStore } from '../main/astore'
// import { control_net, preview, viewer, progress } from '../entry'
import * as progress from '../session/progress'
import {
html_manip,
io,
psapi,
python_replacement,
sdapi,
} from '../util/oldSystem'
import { GenerationModeEnum, SelectionInfoType } from '../util/ts/enum'
// store as viewer_store,
mask_store as viewer_mask_store,
init_store as viewer_init_store,
} from '../viewer/viewer_util'
import Locale from '../locale/locale'
import { store } from './session_store'
import { html_manip, io, python_replacement } from '../util/oldSystem'
import { GenerationModeEnum } from '../util/ts/enum'
import {
Img2ImgMode,
InpaintMode,
@ -18,74 +19,18 @@ import {
Txt2ImgMode,
UpscaleMode,
} from './modes'
import { Progress } from './progress'
import { reaction } from 'mobx'
import {
resetViewer,
updateViewerStoreImageAndThumbnail,
} from '../viewer/viewer_util'
import { sd_tab_store } from '../stores'
declare let g_inpaint_mask_layer: any
declare const g_image_not_found_url: string
declare let g_current_batch_index: number
interface AStoreUISettings {
batch_size: number
// add other properties here as needed
}
interface AStoreData {
// other properties...
init_image: string
active_mask: string // this is the mask that is been used in the current generation
mask: string // the user inputted mask, also can be the mask generated by photoshop dependant on the generation mode
expanded_mask: string // mask after expanded
monoMask: string //monochrome mask, no gradation
preprocessed_mask: string //
sd_mask: string // mask send to sd as payload[mask]
mode: GenerationModeEnum
ui_settings: AStoreUISettings
selectionInfo: SelectionInfoType | undefined //the session selection info
current_selection_info: {} // any new selection, could be undefined too
can_generate: boolean // is generation currently in progress
can_generate_more: boolean //
is_active: boolean // is session active
is_interrupted: boolean // did we interrupt the generation
generation_number: number // generation number per session, 0 mean first generation
controlnet_input_image: string // the controlnet the image that will controlnet load
//plugin related state:
auto_photoshop_sd_extension_status: boolean
doc_uuid: string
current_session_id: number
}
export const store = new AStore<AStoreData>({
// activeBase64InitImage: '',
// activeBase64Mask: '',
init_image: '',
active_mask: '', // this is the mask that is been used in the current generation
mask: '', // the user inputted mask, also can be the mask generated by photoshop dependant on the generation mode
expanded_mask: '', // mask after expanded
monoMask: '', //monochrome mask, no gradation
preprocessed_mask: '', //
sd_mask: '', // mask send to sd as payload[mask]
mode: GenerationModeEnum.Txt2Img,
ui_settings: { batch_size: 1 },
selectionInfo: undefined, //the session selection info
current_selection_info: {}, // any new selection, could be undefined too
can_generate: true, // is generation currently in progress
can_generate_more: false, //
is_active: false, // is session active
is_interrupted: false, // did we interrupt the generation
generation_number: 0, // generation number per session, 0 mean first generation
controlnet_input_image: '', // the controlnet the image that will controlnet load
//plugin related state:
auto_photoshop_sd_extension_status: true,
doc_uuid: '',
current_session_id: 0,
})
reaction(
() => {
return [store.data.init_image, store.data.mask] as [string, string]
@ -249,8 +194,8 @@ export class Session {
store.data.init_image = init_image
// store.data.init_image = opaque_init_image
await viewer.updateViewerStoreImageAndThumbnail(
viewer.init_store,
await updateViewerStoreImageAndThumbnail(
viewer_init_store,
[store.data.init_image]
)
}
@ -262,11 +207,10 @@ export class Session {
store.data.monoMask = mask_monochrome
store.data.mask = mask
const expansion_value: number = parseInt(
//@ts-ignore
document.getElementById('slMaskExpansion').value
)
const mask_blur = html_manip.getMaskBlur()
const expansion_value: number =
sd_tab_store.data.mask_expansion
const mask_blur = sd_tab_store.data.mask_blur
store.data.expanded_mask = await getExpandedMask(
mask,
expansion_value,
@ -274,8 +218,8 @@ export class Session {
)
store.data.preprocessed_mask = mask
await viewer.updateViewerStoreImageAndThumbnail(
viewer.mask_store,
await updateViewerStoreImageAndThumbnail(
viewer_mask_store,
[
store.data.preprocessed_mask,
@ -362,11 +306,8 @@ export class Session {
GenerationModeEnum.Outpaint,
].includes(mode)
) {
const expansion_value: number = parseInt(
//@ts-ignore
document.getElementById('slMaskExpansion').value
)
const mask_blur = html_manip.getMaskBlur()
const expansion_value: number = sd_tab_store.data.mask_expansion
const mask_blur = sd_tab_store.data.mask_blur
store.data.expanded_mask = await getExpandedMask(
mask,
expansion_value,
@ -415,11 +356,8 @@ export class Session {
GenerationModeEnum.Outpaint,
].includes(store.data.mode)
) {
const expansion_value: number = parseInt(
//@ts-ignore
document.getElementById('slMaskExpansion').value
)
const mask_blur = html_manip.getMaskBlur()
const expansion_value: number = sd_tab_store.data.mask_expansion
const mask_blur = sd_tab_store.data.mask_blur
store.data.expanded_mask = await getExpandedMask(
session_data.mask,
expansion_value,
@ -491,7 +429,7 @@ export class Session {
})
}
static endSession() {
viewer.resetViewer() //may cause circular dependency
resetViewer() //may cause circular dependency
store.data.is_active = false //
store.data.init_image = ''
store.data.mask = ''

View File

@ -0,0 +1,65 @@
import { AStore } from '../main/astore'
import { GenerationModeEnum, SelectionInfoType } from '../util/ts/enum'
interface AStoreUISettings {
batch_size: number
// add other properties here as needed
}
interface AStoreData {
// other properties...
init_image: string
active_mask: string // this is the mask that is been used in the current generation
mask: string // the user inputted mask, also can be the mask generated by photoshop dependant on the generation mode
expanded_mask: string // mask after expanded
monoMask: string //monochrome mask, no gradation
preprocessed_mask: string //
sd_mask: string // mask send to sd as payload[mask]
mode: GenerationModeEnum
ui_settings: AStoreUISettings
selectionInfo: SelectionInfoType | undefined //the session selection info
current_selection_info: SelectionInfoType | undefined // any new selection, could be undefined too
can_generate: boolean // is generation currently in progress
can_generate_more: boolean //
is_active: boolean // is session active
is_interrupted: boolean // did we interrupt the generation
generation_number: number // generation number per session, 0 mean first generation
controlnet_input_image: string // the controlnet the image that will controlnet load
//plugin related state:
auto_photoshop_sd_extension_status: boolean
doc_uuid: string
current_session_id: number
last_seed: string
}
export const store = new AStore<AStoreData>({
// activeBase64InitImage: '',
// activeBase64Mask: '',
init_image: '',
active_mask: '', // this is the mask that is been used in the current generation
mask: '', // the user inputted mask, also can be the mask generated by photoshop dependant on the generation mode
expanded_mask: '', // mask after expanded
monoMask: '', //monochrome mask, no gradation
preprocessed_mask: '', //
sd_mask: '', // mask send to sd as payload[mask]
mode: GenerationModeEnum.Txt2Img,
ui_settings: { batch_size: 1 },
selectionInfo: undefined, //the session selection info
current_selection_info: undefined, // any new selection, could be undefined too
can_generate: true, // is generation currently in progress
can_generate_more: false, //
is_active: false, // is session active
is_interrupted: false, // did we interrupt the generation
generation_number: 0, // generation number per session, 0 mean first generation
controlnet_input_image: '', // the controlnet the image that will controlnet load
//plugin related state:
auto_photoshop_sd_extension_status: true,
doc_uuid: '',
current_session_id: 0,
last_seed: '-1',
})

View File

@ -11,7 +11,9 @@ import { reaction } from 'mobx'
//@ts-ignore
import { storage } from 'uxp'
import { ErrorBoundary } from '../util/errorBoundary'
import { MaskModeEnum } from '../util/ts/enum'
import { MaskModeEnum, ScriptMode } from '../util/ts/enum'
import { store as progress_store } from '../session/progress'
// import { Jimp } from '../util/oldSystem'
declare const Jimp: any // make sure you import jimp before importing settings.tsx
@ -37,11 +39,44 @@ const interpolationMethods: InterpolationMethod = {
},
}
enum ExtensionTypeEnum {
ProxyServer = 'proxy_server',
Auto1111Extension = 'auto1111_extension',
None = 'none',
}
const config = {
[ExtensionTypeEnum.ProxyServer]: {
title: "use the proxy server, need to run 'start_server.bat' ",
value: ExtensionTypeEnum.ProxyServer,
label: 'Proxy Server',
},
[ExtensionTypeEnum.Auto1111Extension]: {
title: 'use Automatic1111 Photoshop SD Extension, need to install the extension in Auto1111',
value: ExtensionTypeEnum.Auto1111Extension,
label: 'Auto1111 Extension',
},
[ExtensionTypeEnum.None]: {
title: 'Use the Plugin Only No Additional Component',
value: ExtensionTypeEnum.None,
label: 'None',
},
}
function extensionTypeName(extension_type: ExtensionTypeEnum) {
return extension_type
.split('_')
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
.join(' ')
}
interface AStoreData {
scale_interpolation_method: typeof interpolationMethods.bilinear
should_log_to_file: boolean
delete_log_file_timer_id: ReturnType<typeof setInterval> | undefined
b_borders_or_corners: MaskModeEnum
use_image_cfg_scale_slider: boolean
extension_type: ExtensionTypeEnum
use_sharp_mask: boolean
use_prompt_shortcut: boolean
}
export const store = new AStore<AStoreData>({
scale_interpolation_method: interpolationMethods.bilinear,
@ -49,6 +84,10 @@ export const store = new AStore<AStoreData>({
JSON.parse(storage.localStorage.getItem('should_log_to_file')) || false,
delete_log_file_timer_id: undefined,
b_borders_or_corners: MaskModeEnum.Transparent,
use_image_cfg_scale_slider: false,
extension_type: ExtensionTypeEnum.Auto1111Extension,
use_sharp_mask: false,
use_prompt_shortcut: true,
})
function onShouldLogToFileChange(event: any) {
@ -180,6 +219,71 @@ export class Settings extends React.Component<{}> {
)
})}
</sp-radio-group>
<SpCheckBox
style={{
marginRight: '10px',
}}
onChange={(evt: any) => {
progress_store.data.live_progress_image =
evt.target.checked
}}
checked={progress_store.data.live_progress_image}
>
{
//@ts-ignore
Locale('Live Progress Image')
}
</SpCheckBox>
<div>
<sp-checkbox
id="chUseImageCfgScaleSlider"
title="image cfg slider for pix2pix mode"
value={store.data.use_image_cfg_scale_slider}
onClick={(evt: any) => {
store.data.use_image_cfg_scale_slider =
evt.target.checked
}}
style={{ display: 'inline-flex' }}
>
Image Cfg Scale Slider
</sp-checkbox>
</div>
<div>
<sp-checkbox
id="chUseSharpMask"
checked={store.data.use_sharp_mask}
onClick={(evt: any) => {
store.data.use_sharp_mask = evt.target.checked
}}
>
use sharp mask
</sp-checkbox>
</div>
<div>
<sp-radio-group selected={store.data.extension_type}>
<sp-label slot="label">Select Extension:</sp-label>
{[
ExtensionTypeEnum.ProxyServer,
ExtensionTypeEnum.Auto1111Extension,
ExtensionTypeEnum.None,
].map((extension_type, index: number) => {
return (
<sp-radio
key={index}
title={config[extension_type].title}
class="rbExtensionType"
value={config[extension_type].value}
onClick={(evt: any) => {
store.data.extension_type =
evt.target.value
}}
>
{config[extension_type].label}
</sp-radio>
)
})}
</sp-radio-group>
</div>
</div>
)
}
@ -194,3 +298,5 @@ root.render(
</ErrorBoundary>
</React.StrictMode>
)
progress_store.data.live_progress_image

3
typescripts/stores.ts Normal file
View File

@ -0,0 +1,3 @@
export { store as session_store } from './session/session_store'
export { store as sd_tab_store } from './sd_tab/util'
export { mask_store } from './viewer/viewer_util'

View File

@ -0,0 +1,4 @@
/* styles.css */
#_tool_bar_container button:not(:last-child) {
margin-bottom: 3px;
}

View File

@ -0,0 +1,220 @@
import { observer } from 'mobx-react'
import React from 'react'
import ReactDOM from 'react-dom/client'
import { general, html_manip, io, psapi } from '../util/oldSystem'
import {
default_preset,
loadPresetSettings,
store as sd_tab_store,
} from '../sd_tab/util'
import { requestPost } from '../util/ts/api'
import ControlNetStore from '../controlnet/store'
import { AStore } from '../main/astore'
import { ErrorBoundary } from '../util/errorBoundary'
import './style/tool_bar.css'
import { presetToStore } from '../util/ts/io'
import { multiPrompts } from '../entry'
import { activateSessionSelectionArea } from '../util/ts/selection'
declare let g_sd_url: string
export const store = new AStore({
at_controlnet_unit_index: 0,
})
async function clipInterrogate() {
try {
const width = sd_tab_store.data.width
const height = sd_tab_store.data.height
const selectionInfo = await psapi.getSelectionInfoExe()
const base64 = await io.IO.getSelectionFromCanvasAsBase64Interface_New(
width,
height,
selectionInfo,
true
)
const url = `${g_sd_url}/sdapi/v1/interrogate`
const payload = {
image: base64,
model: 'clip',
}
const result_json = await requestPost(url, payload)
console.log(result_json)
return result_json
} catch (e) {
console.warn(e)
}
}
async function onInterrogate(evt: any) {
// start sudo timer after 1 seconds delay
let sudo_timer_id
setTimeout(() => {
sudo_timer_id = general.sudoTimer('Interrogate')
}, 1000)
const interrogate_result = await clipInterrogate()
if (interrogate_result.caption) {
html_manip.autoFillInPrompt(interrogate_result.caption)
}
// after the clipInterrogate finish stop the timer
html_manip.updateProgressBarsHtml(0, 'No work in progress')
clearInterval(sudo_timer_id)
sudo_timer_id = null
}
function scrollToPreview() {
try {
document
.querySelector('#search_second_panel > div.previewContainer')!
.scrollIntoView()
// document.getElementById('taPrompt').scrollIntoView()
} catch (e) {
console.error(e)
}
}
@observer
class ToolBar extends React.Component<{}> {
componentDidMount(): void {
console.log('ToolBar did mount')
}
render() {
return (
<div id="_tool_bar_container">
<button
className="btnSquare layerToSelection btnLayerToSelection"
title="Move and reSize the highlighted layer to fit into the Selection Area "
style={{ marginRight: '3px' }}
onClick={async (evt: any) => {
try {
const isSelectionAreaValid =
await psapi.checkIfSelectionAreaIsActive()
if (isSelectionAreaValid) {
const validSelection = isSelectionAreaValid
await psapi.layerToSelection(validSelection)
} else {
await psapi.promptForMarqueeTool()
}
} catch (e) {
console.error(e)
}
}}
></button>
<button
title="create a snapshot of what you see on the canvas and place on a new layer"
className="btnSquare snapshotButton"
style={{ marginRight: '3px' }}
onClick={async (evt: any) => {
try {
await psapi.snapshot_layerExe()
} catch (e) {
console.warn(e)
}
}}
></button>
<button
className="btnSquare resetButton"
id="btnResetSettings"
title="reset the ui settings to their default values"
style={{ marginRight: '3px' }}
onClick={(evt: any) => {
try {
multiPrompts.setPrompt({
positive: '',
negative: '',
})
loadPresetSettings(default_preset)
} catch (e) {
console.warn(e)
}
}}
></button>
<button
className="btnSquare interrogateButton"
id="btnInterrogate"
title="Interrogate the selected area, convert Image to Prompt"
style={{ marginRight: '3px' }}
onClick={onInterrogate}
></button>
<button
className="btnSquare svgButton selectionAreaButton"
id="btnSelectionArea"
style={{ marginRight: '3px' }}
title="Reselect the selection area for the current session"
onClick={activateSessionSelectionArea}
></button>
<button
id="scrollToPreview"
className="btnSquare svgButton"
title="Quickly jump to the preview section"
onClick={scrollToPreview}
>
P
</button>
<div id="scrollToControlNetUnitContainer">
<button
className="btnSquare svgButton"
onClick={() => {
try {
const units = document.querySelectorAll(
'#controlNetTabParentContainer .collapsible'
)
const units_data =
ControlNetStore.controlNetUnitData.map(
(data, index) => ({
enabled: data.enabled,
index,
})
)
// Find the next enabled unit
let counter = 0
while (
!units_data[
store.data.at_controlnet_unit_index %
units.length
].enabled &&
counter < units.length
) {
store.data.at_controlnet_unit_index += 1
counter += 1
}
if (counter < units.length) {
store.data.at_controlnet_unit_index =
store.data.at_controlnet_unit_index %
units.length
units[
store.data.at_controlnet_unit_index
].scrollIntoView()
store.data.at_controlnet_unit_index += 1
}
} catch (e) {
console.warn(e)
}
}}
title="Quickly jump to the active ControlNet Unit"
>
C
</button>
</div>
</div>
)
}
}
const container = document.getElementById('toolBarContainer')!
const root = ReactDOM.createRoot(container)
root.render(
<React.StrictMode>
<ErrorBoundary>
<ToolBar></ToolBar>
</ErrorBoundary>
</React.StrictMode>
)

View File

@ -0,0 +1,69 @@
import React, { CSSProperties, ComponentType } from 'react'
// import ReactDOM from 'react-dom'
import { useState, ReactNode } from 'react'
import Locale from '../locale/locale'
interface CollapsibleProps {
label: string
labelStyle?: React.CSSProperties
containerStyle?: React.CSSProperties
defaultIsOpen?: boolean
checked?: boolean
checkboxCallback?: (checked: boolean) => void
children: ReactNode
}
export function Collapsible({
label,
labelStyle,
containerStyle,
defaultIsOpen = false,
checkboxCallback,
checked,
children,
}: CollapsibleProps) {
const [isOpen, setIsOpen] = useState(defaultIsOpen)
const handleToggle = () => {
setIsOpen(!isOpen)
}
return (
/*useObserver(()=>*/ <div>
<div
className="collapsible"
style={containerStyle}
onClick={handleToggle}
>
<span className="truncate" style={labelStyle}>
{label}
</span>
<span
style={{ float: 'right', display: 'flex' }}
className="triangle"
>
{checkboxCallback && checked !== void 0 ? (
<input
type="checkbox"
className="minimal-checkbox"
onClick={(event) => {
event.stopPropagation()
}}
onChange={(event: any) => {
checkboxCallback(event.target.checked)
}}
checked={checked}
/>
) : (
void 0
)}
<span>{isOpen ? '' : '<'}</span>
</span>
</div>
{/* {isOpen && <div>{children}</div>} */}
<div style={{ display: isOpen ? 'block' : 'none' }}>{children}</div>
</div>
)
}

View File

@ -200,6 +200,7 @@ export class SpMenu extends React.Component<{
label_item?: string
onChange?: any
selected_index?: number
size?: string
}> {
state = {
selectedItem: this.props.items ? this.props.items[0] : undefined,
@ -232,49 +233,48 @@ export class SpMenu extends React.Component<{
render() {
return (
<div style={this.props.style}>
<sp-picker
title={this.props.title}
size="m"
// style={{ width: '199px', marginRight: '5px' }}
>
<sp-menu id={this.props.id} slot="options">
{this.props.label_item && (
<sp-menu-item
disabled="disabled"
key={-1}
data-index={-1}
selected
>
{this.props.label_item}
</sp-menu-item>
)}
{this.props.items?.map((item, index: number) => (
<sp-menu-item
key={item}
data-index={index}
selected={
this.props.selected_index !== undefined &&
this.props.selected_index !== null &&
this.props.selected_index === index
? 'selected'
: undefined
}
disabled={
this.props.disabled?.[index]
? 'disabled'
: undefined
}
onClick={() => {
this.handleItemClick(item, index)
}}
>
{item}
</sp-menu-item>
))}
</sp-menu>
</sp-picker>
</div>
<sp-picker
title={this.props.title}
size={this.props.size || 'm'}
style={this.props.style}
// style={{ width: '199px', marginRight: '5px' }}
>
<sp-menu id={this.props.id} slot="options">
{this.props.label_item && (
<sp-menu-item
disabled="disabled"
key={-1}
data-index={-1}
selected
>
{this.props.label_item}
</sp-menu-item>
)}
{this.props.items?.map((item, index: number) => (
<sp-menu-item
key={item}
data-index={index}
selected={
this.props.selected_index !== undefined &&
this.props.selected_index !== null &&
this.props.selected_index === index
? 'selected'
: undefined
}
disabled={
this.props.disabled?.[index]
? 'disabled'
: undefined
}
onClick={() => {
this.handleItemClick(item, index)
}}
>
{item}
</sp-menu-item>
))}
</sp-menu>
</sp-picker>
)
}
}
@ -392,6 +392,17 @@ export class SpSlider extends PhotoshopElem {
)
}
}
export class SpTextfield extends PhotoshopElem {
render() {
const [attr] = this.splitProps(this.props)
return (
<sp-textfield
ref={(elem: Element) => (this.elem = elem)}
{...attr}
></sp-textfield>
)
}
}
export class SpRadioGroup extends PhotoshopElem {
render() {
const [attr] = this.splitProps(this.props)

View File

@ -7,7 +7,7 @@ const req = window['require']
const selection = req('./selection')
const note = req('./utility/notification')
const controlnet_preset = req('./utility/presets/controlnet_preset')
const preset = req('./utility/presets/preset')
const Enum = req('./enum')
const api = req('./utility/api')
const python_replacement = req('./utility/sdapi/python_replacement')
@ -19,7 +19,10 @@ const io = req('./utility/io')
const settings_tab = req('./utility/tab/settings')
const layer_util = req('./utility/layer')
const session = req('./utility/session')
const dialog_box = req('./dialog_box')
const sampler_data = req('./utility/sampler')
const thumbnail = req('./thumbnail')
interface _Jimp extends Jimp {}
const _Jimp: typeof Jimp = (window as any)['Jimp']
@ -27,7 +30,6 @@ export {
selection,
note,
controlnet_preset,
preset,
Enum,
api,
python_replacement,
@ -39,5 +41,8 @@ export {
settings_tab,
layer_util,
session,
dialog_box,
sampler_data,
thumbnail,
_Jimp as Jimp,
}

View File

@ -8,6 +8,13 @@ export enum GenerationModeEnum {
LassoOutpaint = 'lasso_outpaint',
}
export enum ScriptMode {
Txt2Img = 'txt2img',
Img2Img = 'img2img',
Inpaint = 'inpaint',
Outpaint = 'outpaint',
}
export enum MaskModeEnum {
Transparent = 'transparent',
Borders = 'border',
@ -22,3 +29,8 @@ export interface SelectionInfoType {
width: number
height: number
}
export enum PresetTypeEnum {
SDPreset = 'sd_preset',
ControlNetPreset = 'controlnet_preset',
}

View File

@ -3,7 +3,10 @@ import { Jimp, io, psapi } from '../oldSystem'
import { base64ToFileAndGetLayer } from './document'
import { transformCurrentLayerTo } from './layer'
import { Layer } from 'photoshop/dom/Layer'
import { lstatSync, readFileSync, writeFileSync } from 'fs'
import { AStore } from '../../main/astore'
const executeAsModal = core.executeAsModal
type KeyValuePair = { [key: string]: any }
//REFACTOR: move to psapi.js
export function _arrayBufferToBase64(buffer: any) {
@ -139,3 +142,31 @@ async function getBase64FromJimp(jimp_image: Jimp) {
const base64 = dataURL.replace(/^data:image\/png;base64,/, '')
return base64
}
export function readPreset(path: string) {
try {
const content = readFileSync(path, 'utf-8')
JSON.parse(content)
} catch (e) {
console.error(e)
}
}
export function writePreset(path: string, preset: KeyValuePair) {
try {
writeFileSync(path, JSON.stringify(preset))
} catch (e) {
console.error(e)
}
}
export function storeToPreset(store: any) {
return store.toJsFunc().data
}
export function presetToStore(preset: KeyValuePair, store: any) {
store.data = {
...store.data,
...preset,
}
}

View File

@ -1,6 +1,7 @@
import { app, core, action } from 'photoshop'
import { layer_util, psapi } from '../oldSystem'
import { settings_tab_ts } from '../../entry'
// import { settings_tab_ts } from '../../entry'
import * as settings_tab_ts from '../../settings/settings'
const executeAsModal = core.executeAsModal
const { batchPlay } = action

View File

@ -0,0 +1,96 @@
declare let g_version: any
declare let g_sd_url: any
export async function getVersionRequest() {
console.log('requestGetSamplers: ')
const current_version = g_version
return current_version
}
export async function requestGetSamplers() {
let json = null
try {
console.log('requestGetSamplers: ')
const full_url = `${g_sd_url}/sdapi/v1/samplers`
let request = await fetch(full_url)
json = await request.json()
// console.log('samplers json:', json)
} catch (e) {
console.warn(e)
}
return json
}
export async function requestGetUpscalers() {
console.log('requestGetUpscalers: ')
let json = []
const full_url = `${g_sd_url}/sdapi/v1/upscalers`
try {
let request = await fetch(full_url)
json = await request.json()
console.log('upscalers json:')
console.dir(json)
} catch (e) {
console.warn(`issues requesting from ${full_url}`, e)
}
return json
}
export async function setInpaintMaskWeight(value: number) {
const full_url = `${g_sd_url}/sdapi/v1/options`
try {
const payload = {
inpainting_mask_weight: value,
}
await fetch(full_url, {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify(payload),
})
} catch (e) {
console.warn(e)
}
}
export async function requestGetModels() {
console.log('requestGetModels: ')
let json = []
const full_url = `${g_sd_url}/sdapi/v1/sd-models`
try {
let request = await fetch(full_url)
json = await request.json()
console.log('models json:')
console.dir(json)
} catch (e) {
console.warn(`issues requesting from ${full_url}`, e)
}
return json
}
export async function requestSwapModel(model_title: string) {
console.log('requestSwapModel: ')
const full_url = `${g_sd_url}/sdapi/v1/options`
const payload = {
sd_model_checkpoint: model_title,
}
let request = await fetch(full_url, {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify(payload),
})
let json = await request.json()
console.log('models json:')
console.dir(json)
return json
}

View File

@ -1,9 +1,9 @@
import { moveImageToLayer, moveImageToLayer_old } from './io'
import { io, layer_util } from '../oldSystem'
import { session_ts } from '../../entry'
import { io, layer_util, psapi } from '../oldSystem'
import { action, core } from 'photoshop'
import { MaskModeEnum } from './enum'
import { session_store } from '../../stores'
const executeAsModal = core.executeAsModal
const batchPlay = action.batchPlay
@ -11,7 +11,8 @@ export async function applyMaskFromBlackAndWhiteImage(
black_and_white_base64: string,
layer_id: any,
selectionInfo: any,
b_borders_or_corners: MaskModeEnum = MaskModeEnum.Transparent
b_borders_or_corners: MaskModeEnum = MaskModeEnum.Transparent,
expand_by = 10
) {
let mask_layer
try {
@ -50,7 +51,7 @@ export async function applyMaskFromBlackAndWhiteImage(
_obj: 'expand',
by: {
_unit: 'pixelsUnit',
_value: 10,
_value: expand_by,
},
selectionModifyEffectAtCanvasBounds: true,
_isCommand: true,
@ -156,3 +157,15 @@ export async function selectionFromBlackAndWhiteImage(
await layer_util.deleteLayers([mask_layer])
}
}
export async function activateSessionSelectionArea() {
try {
if (psapi.isSelectionValid(session_store.data.selectionInfo)) {
await psapi.reSelectMarqueeExe(session_store.data.selectionInfo)
//@ts-ignore
await eventHandler()
}
} catch (e) {
console.warn(e)
}
}

View File

@ -0,0 +1,433 @@
import { multiPrompts } from '../../entry'
import {
getAllCustomPresetsSettings,
loadCustomPreset,
loadPreset,
} from '../../preset/shared_ui_preset'
import { sd_tab_store } from '../../stores'
import { html_manip } from '../oldSystem'
import { PresetTypeEnum, ScriptMode } from './enum'
let LatentNoiseSettings = {
model: null,
prompt_shortcut: null,
positive_prompt: null,
negative_prompt: null,
generation_mode: null,
batch_size: null,
steps: null,
width: null,
height: null,
firstphase_width: null,
firstphase_height: null,
cfg: null,
denoising_strength: 0.92,
hi_res_denoising_strength: null,
mask_blur: null,
inpaint_at_full_res: null,
hi_res_fix: null,
inpaint_padding: null,
seed: null,
samplers: null,
mask_content: '2',
}
let FillSettings = {
model: null,
prompt_shortcut: null,
positive_prompt: null,
negative_prompt: null,
generation_mode: null,
batch_size: null,
steps: null,
width: null,
height: null,
firstphase_width: null,
firstphase_height: null,
cfg: null,
denoising_strength: 0.7,
hi_res_denoising_strength: null,
mask_blur: null,
inpaint_at_full_res: null,
hi_res_fix: null,
inpaint_padding: null,
seed: null,
samplers: null,
mask_content: '0',
}
let OriginalSettings = {
model: null,
prompt_shortcut: null,
positive_prompt: null,
negative_prompt: null,
generation_mode: null,
batch_size: null,
steps: null,
width: null,
height: null,
firstphase_width: null,
firstphase_height: null,
cfg: null,
denoising_strength: 0.7,
hi_res_denoising_strength: null,
mask_blur: null,
inpaint_at_full_res: null,
hi_res_fix: null,
inpaint_padding: null,
seed: null,
samplers: null,
mask_content: '1',
}
let HealBrushSettings = {
model: null,
prompt_shortcut: null,
positive_prompt: null,
negative_prompt: null,
generation_mode: null,
batch_size: null,
steps: '25',
width: null,
height: null,
firstphase_width: null,
firstphase_height: null,
cfg: '9',
denoising_strength: 0.92,
hi_res_denoising_strength: null,
mask_blur: 1,
inpaint_at_full_res: null,
hi_res_fix: null,
inpaint_padding: null,
seed: null,
samplers: null,
mask_content: '2',
mask_expansion: 2,
}
class UI {
constructor() {}
}
interface UIElements {
[key: string]: UIElement
prompt: UIElement
negative_prompt: UIElement
mode: UIElement
batch_size: UIElement
batch_count: UIElement
steps: UIElement
width: UIElement
height: UIElement
cfg: UIElement
denoising_strength: UIElement
mask_content: UIElement
seed: UIElement
mask_blur: UIElement
mask_expansion: UIElement
samplers: UIElement
}
class UIElement {
name: any
html_elem: any
sd_value: any
constructor() {
this.name
this.html_elem
this.sd_value
}
setValue(new_value: any) {}
getValue(): any {}
}
function createUIElement(getter: any, setter: any) {
let ui_element_obj = new UIElement()
ui_element_obj.getValue = getter
ui_element_obj.setValue = setter
return ui_element_obj
}
class UISettings {
prompt: UIElement
negative_prompt: UIElement
mode: UIElement
steps: UIElement
batch_size: UIElement
batch_count: UIElement
width: UIElement
height: UIElement
cfg: UIElement
denoising_strength: UIElement
mask_content: UIElement
seed: UIElement
mask_blur: UIElement
mask_expansion: UIElement
samplers: UIElement
uiElements: UIElements
// get and set the settings of the ui. the stable diffusion settings not the human friendly settings
constructor() {
const createUIElementWrapper = <T extends never>(
getter: () => T,
setter: (value: T) => void
) => {
return createUIElement(getter, setter)
}
const sdTabStoreDataWrapper = <T extends never>(
key: keyof typeof sd_tab_store.data
) => {
return createUIElementWrapper(
() => sd_tab_store.data[key] as T,
(value: T) => (sd_tab_store.data[key] = value)
)
}
this.prompt = createUIElement(
() => {
return multiPrompts.getPrompt().positive
},
(value: string) => {
multiPrompts.setPrompt({ positive: value })
}
)
this.negative_prompt = createUIElement(
() => {
return multiPrompts.getPrompt().negative
},
(value: string) => {
multiPrompts.setPrompt({ negative: value })
}
)
this.mode = sdTabStoreDataWrapper('rb_mode')
this.batch_size = sdTabStoreDataWrapper('batch_size')
this.batch_count = sdTabStoreDataWrapper('batch_count')
this.steps = sdTabStoreDataWrapper('steps')
this.width = sdTabStoreDataWrapper('width')
this.height = sdTabStoreDataWrapper('height')
this.cfg = sdTabStoreDataWrapper('cfg')
// this.mask_blur =
this.denoising_strength = createUIElement(
() => {
return sd_tab_store.data.denoising_strength
},
(value: number) => {
sd_tab_store.data.denoising_strength = value
}
)
this.mask_content = createUIElement(
html_manip.getMaskContent,
html_manip.setMaskContent
)
this.seed = createUIElement(
() => {
return sd_tab_store.data.seed
},
(value: string) => {
sd_tab_store.data.seed = value
}
)
this.mask_blur = createUIElement(
() => {
return sd_tab_store.data.mask_blur
},
(value: number) => {
sd_tab_store.data.mask_blur = value
}
)
this.mask_expansion = createUIElement(
html_manip.getMaskExpansion,
html_manip.setMaskExpansion
)
this.samplers = createUIElement(
() => {
return sd_tab_store.data.sampler_name
},
(value: string) => {
sd_tab_store.data.sampler_name = value
}
)
this.uiElements = {
// model: null,
// prompt_shortcut: null,
prompt: this.prompt,
negative_prompt: this.negative_prompt,
// selection_mode: null,
mode: this.mode,
batch_size: this.batch_size,
batch_count: this.batch_count,
steps: this.steps,
width: this.width,
height: this.height,
cfg_scale: this.cfg,
denoising_strength: this.denoising_strength,
// hi_res_denoising_strength:0.7,
mask_blur: this.mask_blur,
mask_expansion: this.mask_expansion,
// inpaint_at_full_res: false,
// hi_res_fix:false,
// inpaint_padding:0,
seed: this.seed,
sampler_index: this.samplers,
mask_content: this.mask_content,
cfg: this.cfg,
samplers: this.samplers,
}
}
autoFillInSettings(settings: any) {
for (const [name, value] of Object.entries(settings)) {
if (this.uiElements.hasOwnProperty(name) && value) {
//get the values for debugging
const old_value = this.uiElements[name].getValue()
console.log(
'(name,old_value) => newValue:',
name,
old_value,
value
)
//set the value
this.uiElements[name].setValue(value)
}
}
}
getSettings() {
let settings: any = {}
for (const [name, ui_element] of Object.entries(this.uiElements)) {
if (ui_element) {
const value = ui_element.getValue()
settings[name] = value
}
}
return settings
}
saveAsJson(json_file_name: string, settings: any) {
for (const [name, value] of Object.entries(settings)) {
if (this.uiElements.hasOwnProperty(name) && value) {
//get the values for debugging
const old_value = this.uiElements[name].getValue()
console.log(
'(name,old_value) => newValue:',
name,
old_value,
value
)
//set the value
}
}
}
}
// const ui_settings = new UISettings()
function loadLatentNoiseSettings(ui_settings: any) {
loadPreset(ui_settings, LatentNoiseSettings)
}
function loadFillSettings(ui_settings: any) {
loadPreset(ui_settings, FillSettings)
}
function loadOriginalSettings(ui_settings: any) {
loadPreset(ui_settings, OriginalSettings)
}
async function loadHealBrushSettings(ui_settings: any) {
document.getElementById('rbModeInpaint')!.click()
loadPreset(ui_settings, HealBrushSettings)
}
function loadCustomPresetsSettings() {}
async function mapCustomPresetsToLoaders(ui_settings_obj: any) {
const name_to_settings_obj = await getAllCustomPresetsSettings()
const preset_name_to_loader_obj: any = {}
for (const [preset_name, preset_settings] of Object.entries(
name_to_settings_obj
)) {
preset_name_to_loader_obj[preset_name] = () => {
loadCustomPreset(ui_settings_obj, preset_settings)
}
}
return preset_name_to_loader_obj
}
const g_nativePresets = {
fill: loadFillSettings,
original: loadOriginalSettings,
'latent noise': loadLatentNoiseSettings,
'Heal Brush': loadHealBrushSettings,
}
export function getNativeSDPresets() {
return g_nativePresets
}
let g_ui_settings_object = new UISettings()
function getUISettingsObject() {
return g_ui_settings_object
}
//REFACTOR: move to ui.js
function addPresetMenuItem(preset_title: string) {
// console.log(model_title,model_name)
const menu_item_element = document.createElement('sp-menu-item')
menu_item_element.className = 'mPresetMenuItem'
menu_item_element.innerHTML = preset_title
// menu_item_element.addEventListener('select',()=>{
// preset_func(g_ui_settings)
// })
return menu_item_element
}
//REFACTOR: move to ui.js
// async function populatePresetMenu() {
// document.getElementById('mPresetMenu')!.innerHTML = ''
// const divider_elem = document.createElement('sp-menu-divider')
// const preset_name = 'Select Smart Preset'
// // const preset_func = () => {}
// const dummy_preset_item = addPresetMenuItem(preset_name)
// dummy_preset_item.setAttribute('selected', 'selected')
// // dummy_preset_item.setAttribute('disabled')
// document.getElementById('mPresetMenu')!.appendChild(dummy_preset_item)
// document.getElementById('mPresetMenu')!.appendChild(divider_elem)
// const presets = await getLoadedPresets(g_ui_settings_object)
// for (const [key, value] of Object.entries(presets)) {
// const preset_menu_item = addPresetMenuItem(key)
// document.getElementById('mPresetMenu')!.appendChild(preset_menu_item)
// }
// }
// populatePresetMenu()
//REFACTOR: move to preset_tab.js
// document
// .getElementById('mPresetMenu')!
// .addEventListener('change', async (evt: any) => {
// const preset_index = evt.target.selectedIndex
// const preset_name: string = evt.target.options[preset_index].textContent
// const presets: any = await getLoadedPresets(g_ui_settings_object)
// if (presets.hasOwnProperty(preset_name)) {
// const loader = presets[preset_name]
// if (loader.constructor.name === 'AsyncFunction') {
// await loader(g_ui_settings_object)
// } else {
// loader(g_ui_settings_object)
// }
// }
// })
// {
// sd_tab:
// controlnet_tab:
// settings_tab:
// }
export {
UI,
UIElement,
UISettings,
loadLatentNoiseSettings,
loadFillSettings,
loadHealBrushSettings,
getUISettingsObject,
// populatePresetMenu,
}

View File

@ -1,10 +1,12 @@
import React from 'react'
import ReactDOM from 'react-dom/client'
import Collapsible from '../after_detailer/after_detailer'
import { Collapsible } from '../util/collapsible'
import { observer } from 'mobx-react'
import { AStore } from '../main/astore'
import { progress } from '../entry'
// import { progress } from '../entry'
import * as progress from '../session/progress'
import './style/preview.css'
import { reaction } from 'mobx'
import Locale from '../locale/locale'

View File

@ -16,8 +16,13 @@ import {
moveImageToLayer_old,
} from '../util/ts/io'
import { io, layer_util, psapi, selection } from '../util/oldSystem'
import Collapsible from '../after_detailer/after_detailer'
import { progress, session_ts, settings_tab_ts } from '../entry'
import { Collapsible } from '../util/collapsible'
// import { progress } from '../entry'
import * as progress from '../session/progress'
import * as settings_tab_ts from '../settings/settings'
import { store as session_store } from '../session/session_store'
import { reaction } from 'mobx'
import {
GenerationModeEnum,
@ -29,27 +34,19 @@ import { action, app, core } from 'photoshop'
import Locale from '../locale/locale'
import { applyMaskFromBlackAndWhiteImage } from '../util/ts/selection'
import { ErrorBoundary } from '../util/errorBoundary'
import { Session } from '../session/session'
import {
ClassNameEnum,
ClickTypeEnum,
init_store,
mask_store,
store,
} from './viewer_util'
const executeAsModal = core.executeAsModal
const batchPlay = action.batchPlay
declare let g_generation_session: any
enum ClickTypeEnum {
Click = 'click',
ShiftClick = 'shift_click',
AltClick = 'alt_click',
SecondClick = 'second_click', //when we click a thumbnail that is active/ has orange border
}
enum OutputImageStateEnum {
Add = 'add',
remove = 'remove',
}
enum ClassNameEnum {
Green = 'viewerImgSelected',
Orange = 'viewerImgActive',
None = '',
}
function findClickType(event: any) {
let click_type: ClickTypeEnum = ClickTypeEnum.Click
@ -61,46 +58,6 @@ function findClickType(event: any) {
return click_type
}
interface AStoreData {
images: string[]
thumbnails: string[]
metadata: any[] // metadata for each image
width: number
height: number
prev_layer: any
clicked_index: number | undefined
permanent_indices: number[]
prev_index: number
is_stored: boolean[]
layers: any[]
class_name: ClassNameEnum[]
can_click: boolean
auto_mask: boolean
}
export const store = new AStore<AStoreData>({
images: [],
thumbnails: [],
metadata: [], // metadata for each image
width: 50,
height: 50,
prev_layer: null,
clicked_index: undefined,
permanent_indices: [],
prev_index: -1,
is_stored: [],
layers: [],
class_name: [],
can_click: true,
auto_mask: true,
})
const timer = (ms: any) => new Promise((res) => setTimeout(res, ms))
//when a generation is done, add the last generated image from the viewer to tha canvas
reaction(
@ -134,71 +91,7 @@ reaction(
}
}
)
export const init_store = new AStore({
images: [],
thumbnails: [],
width: 50,
height: 50,
prev_layer: null,
clicked_index: null,
permanent_indices: [],
prev_index: -1,
output_image_obj_list: [],
is_stored: [],
layers: [],
class_name: [],
can_click: true,
})
export const mask_store = new AStore({
images: [],
thumbnails: [],
output_images_masks: [],
width: 50,
height: 50,
prev_layer: null,
clicked_index: null,
permanent_indices: [],
prev_index: -1,
output_image_obj_list: [],
is_stored: [],
layers: [],
class_name: [],
can_click: true,
})
interface AStoreDataWithImagesAndThumbnails {
images: string[]
thumbnails: string[]
}
export async function updateViewerStoreImageAndThumbnail<
T extends AStoreDataWithImagesAndThumbnails
>(store: AStore<T>, images: string[]) {
try {
if (typeof images === 'undefined' || !images) {
return null
}
store.data.images = images
const thumbnail_list = []
for (const base64 of images) {
const thumbnail = await io.createThumbnail(base64, 300)
thumbnail_list.push(thumbnail)
}
store.data.thumbnails = thumbnail_list
} catch (e) {
console.warn(e)
console.warn('images: ', images)
}
}
const add_new = async (
base64: string,
mask?: string,
@ -239,7 +132,8 @@ const add_new = async (
await selection.black_white_layer_to_mask_multi_batchplay(
mask_layer.id,
layer.id,
'mask'
'mask',
mask_store.data.expand_by
)
await layer_util.deleteLayers([mask_layer])
} else {
@ -249,7 +143,8 @@ const add_new = async (
channel_mask_monochrome.base64,
layer.id,
selectionInfo,
settings_tab_ts.store.data.b_borders_or_corners
settings_tab_ts.store.data.b_borders_or_corners,
mask_store.data.expand_by
)
}
}
@ -276,12 +171,12 @@ const add = async (
store.data.auto_mask
) {
// const base64_monochrome_mask = await io.convertGrayscaleToMonochrome(
// session_ts.store.data.selected_mask
// session_store.data.selected_mask
// )
const timer = (ms: any) => new Promise((res) => setTimeout(res, ms))
const mask_monochrome = await io.convertGrayscaleToMonochrome(
// session_ts.store.data.expanded_mask
// session_store.data.expanded_mask
mask
)
const channel_mask = mask_monochrome
@ -292,7 +187,8 @@ const add = async (
channel_mask,
layer.id,
selectionInfo,
settings_tab_ts.store.data.b_borders_or_corners
settings_tab_ts.store.data.b_borders_or_corners,
mask_store.data.expand_by
)
}
@ -339,21 +235,6 @@ const remove = async (layer: any) => {
await layer_util.deleteLayers([layer]) // delete previous layer
}
export const resetViewer = () => {
store.updateProperty('images', [])
store.data.thumbnails = []
store.data.prev_index = -1
store.data.is_stored = []
store.data.layers = []
store.data.class_name = []
store.data.can_click = true
mask_store.data.images = []
mask_store.data.thumbnails = []
init_store.data.images = []
init_store.data.thumbnails = []
}
const addAll = async () => {
let i = 0
for (let i = 0; i < store.data.images.length; i++) {
@ -366,22 +247,22 @@ const addAll = async () => {
await addWithHistory(
store.data.images[i],
mask_store.data?.output_images_masks?.[i] ?? void 0,
session_ts.store.data.selectionInfo,
session_ts.store.data.mode
session_store.data.selectionInfo,
session_store.data.mode
)
}
session_ts.Session.endSession()
Session.endSession()
}
const discardAll = async () => {
for (let i = 0; i < store.data.images.length; i++) {
await remove(store.data.layers[i])
}
session_ts.Session.endSession()
Session.endSession()
}
const onlySelected = () => {
session_ts.Session.endSession()
Session.endSession()
}
export const handleOutputImageThumbnailClick = async (
index: number,
@ -423,8 +304,8 @@ export const handleOutputImageThumbnailClick = async (
const layer = await addWithHistory(
image,
mask_store.data?.output_images_masks?.[index] ?? void 0,
session_ts.store.data.selectionInfo,
session_ts.store.data.mode
session_store.data.selectionInfo,
session_store.data.mode
)
await remove(store.data.layers[index])
console.log('layer:', layer)
@ -458,8 +339,8 @@ export const handleOutputImageThumbnailClick = async (
const layer = await addWithHistory(
image,
mask_store.data?.output_images_masks?.[index] ?? void 0,
session_ts.store.data.selectionInfo,
session_ts.store.data.mode
session_store.data.selectionInfo,
session_store.data.mode
)
await remove(store.data.layers[index])
store.data.layers[index] = layer
@ -512,7 +393,7 @@ export const handleOutputImageThumbnailClick = async (
const Viewer = observer(() => {
// console.log('rendered', store.toJsFunc())
const display_button: Boolean =
session_ts.store.data.is_active && session_ts.store.data.can_generate
session_store.data.is_active && session_store.data.can_generate
const button_style = {
display: display_button ? 'block' : 'none',
marginRight: '3px',
@ -585,7 +466,7 @@ const Viewer = observer(() => {
GenerationModeEnum.Inpaint,
GenerationModeEnum.LassoInpaint,
GenerationModeEnum.Outpaint,
].includes(session_ts.store.data.mode)
].includes(session_store.data.mode)
? void 0
: 'none',
marginRight: '10px',
@ -600,6 +481,21 @@ const Viewer = observer(() => {
Locale('Apply Auto Masking')
}
</SpCheckBox>
<SpSlider
show-value="false"
min={0}
max={300}
value={mask_store.data.expand_by}
onInput={(evt: any) => {
mask_store.data.expand_by = evt.target.value
}}
title="expand the Photoshop masking by x pixels"
>
<sp-label slot="label">{Locale('Expand by')}</sp-label>
<sp-label slot="label">
{mask_store.data.expand_by}
</sp-label>
</SpSlider>
</div>
<div style={{ border: '2px solid #6d6c6c', padding: '3px' }}>
<Grid
@ -633,7 +529,7 @@ const Viewer = observer(() => {
callback: async (index: number) => {
await moveImageToLayer(
mask_store.data.images[index],
session_ts.store.data.selectionInfo,
session_store.data.selectionInfo,
'mask'
)
},
@ -675,7 +571,7 @@ const Viewer = observer(() => {
const ToolbarViewerButtons = observer(() => {
const display_button: Boolean =
session_ts.store.data.is_active && session_ts.store.data.can_generate
session_store.data.is_active && session_store.data.can_generate
const button_style = {
display: display_button ? 'block' : 'none',

View File

@ -0,0 +1,138 @@
import { AStore } from '../main/astore'
import { io } from '../util/oldSystem'
export enum ClickTypeEnum {
Click = 'click',
ShiftClick = 'shift_click',
AltClick = 'alt_click',
SecondClick = 'second_click', //when we click a thumbnail that is active/ has orange border
}
export enum OutputImageStateEnum {
Add = 'add',
remove = 'remove',
}
export enum ClassNameEnum {
Green = 'viewerImgSelected',
Orange = 'viewerImgActive',
None = '',
}
interface AStoreData {
images: string[]
thumbnails: string[]
metadata: any[] // metadata for each image
width: number
height: number
prev_layer: any
clicked_index: number | undefined
permanent_indices: number[]
prev_index: number
is_stored: boolean[]
layers: any[]
class_name: ClassNameEnum[]
can_click: boolean
auto_mask: boolean
}
export const store = new AStore<AStoreData>({
images: [],
thumbnails: [],
metadata: [], // metadata for each image
width: 50,
height: 50,
prev_layer: null,
clicked_index: undefined,
permanent_indices: [],
prev_index: -1,
is_stored: [],
layers: [],
class_name: [],
can_click: true,
auto_mask: true,
})
export const init_store = new AStore({
images: [],
thumbnails: [],
width: 50,
height: 50,
prev_layer: null,
clicked_index: null,
permanent_indices: [],
prev_index: -1,
output_image_obj_list: [],
is_stored: [],
layers: [],
class_name: [],
can_click: true,
})
export const mask_store = new AStore({
images: [],
thumbnails: [],
output_images_masks: [],
width: 50,
height: 50,
expand_by: 0,
prev_layer: null,
clicked_index: null,
permanent_indices: [],
prev_index: -1,
output_image_obj_list: [],
is_stored: [],
layers: [],
class_name: [],
can_click: true,
})
interface AStoreDataWithImagesAndThumbnails {
images: string[]
thumbnails: string[]
}
export async function updateViewerStoreImageAndThumbnail<
T extends AStoreDataWithImagesAndThumbnails
>(store: AStore<T>, images: string[]) {
try {
if (typeof images === 'undefined' || !images) {
return null
}
store.data.images = images
const thumbnail_list = []
for (const base64 of images) {
const thumbnail = await io.createThumbnail(base64, 300)
thumbnail_list.push(thumbnail)
}
store.data.thumbnails = thumbnail_list
} catch (e) {
console.warn(e)
console.warn('images: ', images)
}
}
export const resetViewer = () => {
store.updateProperty('images', [])
store.data.thumbnails = []
store.data.prev_index = -1
store.data.is_stored = []
store.data.layers = []
store.data.class_name = []
store.data.can_click = true
mask_store.data.images = []
mask_store.data.thumbnails = []
init_store.data.images = []
init_store.data.thumbnails = []
}

View File

@ -1,13 +0,0 @@
const updatePresetMenuEvent = new CustomEvent('updatePresetMenuEvent', {
detail: {},
bubbles: true,
cancelable: true,
composed: false,
})
function triggerEvent(query_selector, event) {
document.querySelector(query_selector).dispatchEvent(event)
}
module.exports = {
updatePresetMenuEvent,
triggerEvent,
}

View File

@ -51,41 +51,6 @@ function scaleToClosestKeepRatio(
function mapRange(x, in_min, in_max, out_min, out_max) {
return ((x - in_min) * (out_max - out_min)) / (in_max - in_min) + out_min
}
function scaleToRatio(
new_value_1,
old_value_1,
new_value_2, //get ignored
old_value_2,
max_value,
min_value
) {
const ratio = new_value_1 / old_value_1 // 1000/500 = 2
let final_new_value_2 = old_value_2 * ratio // 500 * 2 = 1000
let final_new_value_1 = new_value_1
if (final_new_value_2 > max_value) {
;[_, final_new_value_1] = scaleToRatio(
max_value,
old_value_2,
new_value_1, //get ignored
old_value_1,
max_value,
min_value
)
final_new_value_2 = max_value
} else if (final_new_value_2 < min_value) {
;[_, final_new_value_1] = scaleToRatio(
min_value,
old_value_2,
new_value_1, //get ignored
old_value_1,
max_value,
min_value
)
final_new_value_2 = min_value
}
return [final_new_value_1, final_new_value_2]
}
function compareVersions(version_1, version_2) {
//remove the first character v
@ -137,7 +102,7 @@ function sudoTimer(progress_text = 'Loading ControlNet...') {
return timerId
}
function countNewLines(string) {
const count = (string.match(/\n/g) || []).length
const count = (string.match(/[\n\r]/g) || []).length
// console.log(count)
return count
}
@ -150,7 +115,7 @@ module.exports = {
base64UrlToBase64,
timer,
scaleToClosestKeepRatio,
scaleToRatio,
mapRange,
compareVersions,
requestOnlineData,

View File

@ -1,11 +1,5 @@
////// Start Prompt//////////
function getPrompt() {
// const prompt = document.getElementById('taPrompt').value
const prompt = multiPrompts.getPrompt().positive
return prompt
}
function autoFillInPrompt(prompt_value) {
// document.getElementById('taPrompt').value = prompt_value
multiPrompts.setPrompt({ positive: prompt_value })
@ -15,14 +9,6 @@ function autoFillInPrompt(prompt_value) {
////// Start Negative Prompt//////////
function getNegativePrompt() {
// const negative_prompt = document.getElementById('taNegativePrompt').value
const negative_prompt = multiPrompts.getPrompt().negative
return negative_prompt
}
function autoFillInNegativePrompt(negative_prompt_value) {
// document.getElementById('taNegativePrompt').value = negative_prompt_value
multiPrompts.setPrompt({ negative: negative_prompt_value })
@ -32,103 +18,8 @@ function autoFillInNegativePrompt(negative_prompt_value) {
////// Start Width//////////
document.getElementById('slWidth').addEventListener('input', (evt) => {
const width = evt.target.value * 64
document.getElementById('lWidth').textContent = parseInt(width)
// widthSliderOnChangeEventHandler(evt)
updateResDifferenceLabel()
})
document.getElementById('slHeight').addEventListener('input', (evt) => {
const height = evt.target.value * 64
document.getElementById('lHeight').textContent = parseInt(height)
// heightSliderOnChangeEventHandler(evt)
updateResDifferenceLabel()
})
function widthSliderOnChangeEventHandler(evt) {
let new_width = evt.target.value * 64
const b_link = getLinkWidthHeightState()
let final_width = new_width
let final_height
if (b_link) {
const current_height = html_manip.getHeight()
;[final_width, final_height] = general.scaleToRatio(
new_width,
g_old_slider_width,
_,
current_height,
parseInt(evt.target.max * 64),
parseInt(evt.target.min * 64)
)
evt.target.value = parseInt(final_width / 64)
html_manip.autoFillInHeight(final_height)
}
g_old_slider_width = final_width // update the old value, so we can use it later
document.getElementById('lWidth').textContent = parseInt(final_width)
}
document.getElementById('slWidth').addEventListener('change', (evt) => {
widthSliderOnChangeEventHandler(evt)
})
// document.getElementById('slWidth').addEventListener('change', (evt) => {
// let new_width = evt.target.value * 64
// const b_link = getLinkWidthHeightState()
// let final_width = new_width
// let final_height
// if (b_link) {
// const current_height = html_manip.getHeight()
// ;[final_width, final_height] = general.scaleToRatio(
// new_width,
// g_old_slider_width,
// _,
// current_height,
// parseInt(evt.target.max * 64),
// parseInt(evt.target.min * 64)
// )
// evt.target.value = parseInt(final_width / 64)
// html_manip.autoFillInHeight(final_height)
// }
// g_old_slider_width = final_width // update the old value, so we can use it later
// document.getElementById('lWidth').textContent = parseInt(final_width)
// })
function heightSliderOnChangeEventHandler(evt) {
let new_height = evt.target.value * 64
let final_width
let final_height = new_height
const b_link = getLinkWidthHeightState()
if (b_link) {
const current_width = html_manip.getWidth()
;[final_height, final_width] = general.scaleToRatio(
new_height,
g_old_slider_height,
_,
current_width,
parseInt(evt.target.max * 64),
parseInt(evt.target.min * 64)
)
evt.target.value = parseInt(final_height / 64)
html_manip.autoFillInWidth(final_width)
}
g_old_slider_height = final_height // update the old value, so we can use it later
document.getElementById('lHeight').textContent = parseInt(final_height)
}
document.getElementById('slHeight').addEventListener('change', (evt) => {
heightSliderOnChangeEventHandler(evt)
})
function getWidth() {
slider_width = document.getElementById('slWidth').value
const width = slider_width * 64
return width
return sd_tab_store.data.width
}
function getHrWidth() {
@ -142,147 +33,37 @@ function getHrHeight() {
const width = slider_width * 64
return width
}
function autoFillInWidth(width_value) {
const width_slider = document.getElementById('slHeight')
async function autoFillInWidth(width_value) {
sd_tab_store.data.width = width_value
sd_tab_util.helper_store.data.previous_width = width_value
// g_old_slider_width = width_slider.value * 64 //store the old value
g_old_slider_width = width_value
document.getElementById('slWidth').value = `${width_value / 64}`
//update the label
document.getElementById('lWidth').innerHTML = `${parseInt(width_value)}`
updateResDifferenceLabel()
sd_tab_store.data.ratio =
await selection.Selection.getImageToSelectionDifference()
}
////// End Width//////////
////// Start Height//////////
function getHeight() {
slider_value = document.getElementById('slHeight').value
const height = slider_value * 64
return height
// slider_value = document.getElementById('slHeight').value
// const height = slider_value * 64
return sd_tab_store.data.height
}
function autoFillInHeight(height_value) {
const height_slider = document.getElementById('slHeight')
// g_old_slider_height = height_slider.value * 64
g_old_slider_height = height_value //store the current value as old value. counterintuitive!. only use old value when the user directly manipulate the slider
height_slider.value = `${height_value / 64}`
async function autoFillInHeight(height_value) {
sd_tab_util.helper_store.data.previous_height = height_value
sd_tab_store.data.height = height_value
//update the label
document.getElementById('lHeight').innerHTML = `${parseInt(height_value)}`
updateResDifferenceLabel()
sd_tab_store.data.ratio =
await selection.Selection.getImageToSelectionDifference()
}
function autoFillInHRHeight(height_value) {
document.getElementById('hrHeight').value = `${height_value / 64}`
//update the label
document.getElementById('hHeight').innerHTML = `${height_value}`
sd_tab_store.data.hr_resize_y = height_value
}
function autoFillInHRWidth(height_value) {
document.getElementById('hrWidth').value = `${height_value / 64}`
//update the label
document.getElementById('hWidth').innerHTML = `${height_value}`
}
////// End Height//////////
////// Start Denoising Strength//////////
document
.querySelector('#slDenoisingStrength')
.addEventListener('input', (evt) => {
const label_value = evt.target.value / 100
// console.log("label_value: ", label_value)
document.getElementById(
'lDenoisingStrength'
).innerHTML = `${label_value}`
})
//get the value that is relevant to stable diffusion
function getDenoisingStrength() {
const slider_value = document.getElementById('slDenoisingStrength').value
const denoising_strength_value = slider_value / 100.0
return denoising_strength_value
}
// display the value the user need to see in all elements related to denoising strength attribute
function autoFillInDenoisingStrength(denoising_strength_value) {
//sd denoising strength value range from [0,1] slider range from [0, 100]
//update the slider
document.getElementById('slDenoisingStrength').value = `${
denoising_strength_value * 100
}`
//update the label
document.getElementById(
'lDenoisingStrength'
).innerHTML = `${denoising_strength_value}`
}
////// End Denoising Strength//////////
////// Start Hi Res Fix//////////
document.getElementById('chInpaintFullRes').addEventListener('click', (ev) => {
const inpaint_padding_slider = document.getElementById('slInpaintPadding')
if (ev.target.checked) {
inpaint_padding_slider.style.display = 'block'
} else {
inpaint_padding_slider.style.display = 'none'
}
})
document.getElementById('chHiResFixs').addEventListener('click', (ev) => {
const container = document.getElementById('hi-res-sliders-container')
if (ev.target.checked) {
container.style.display = 'flex'
} else {
container.style.display = 'none'
}
})
//get the value that is relevant to stable diffusion
function getHiResFixs() {
const isChecked = document.getElementById('chHiResFixs').checked
return isChecked
}
function setHiResFixs(isChecked) {
document.getElementById('chHiResFixs').checked = isChecked
}
function sliderAddEventListener(
slider_id,
label_id,
multiplier,
fractionDigits = 2
) {
document.getElementById(slider_id).addEventListener('input', (evt) => {
const sd_value = evt.target.value * multiplier // convert slider value to SD ready value
document.getElementById(label_id).textContent =
Number(sd_value).toFixed(fractionDigits)
})
}
function sliderAddEventListener_new(
slider_id,
label_id,
slider_start,
slider_end,
sd_start,
sd_end
) {
document.getElementById(slider_id).addEventListener('input', (evt) => {
const sd_value = general.mapRange(
evt.target.value,
slider_start,
slider_end,
sd_start,
sd_end
) // convert slider value to SD ready value
document.getElementById(label_id).textContent =
Number(sd_value).toFixed(2)
})
function autoFillInHRWidth(width_value) {
sd_tab_store.data.hr_resize_x = width_value
}
//get the stable diffusion ready value from the slider with "slider_id"
@ -383,13 +164,6 @@ function setSliderSdValueByElements(
label_element.innerHTML = sd_value.toString()
}
//hrWidth is from [1 to 32] * 64 => [64 to 2048]
sliderAddEventListener('hrWidth', 'hWidth', 64)
sliderAddEventListener('hrHeight', 'hHeight', 64)
//convert hrDenoisingStrength from [1, 100] * 0.01 => [0.01 to 1]
sliderAddEventListener('hrDenoisingStrength', 'hDenoisingStrength', 0.01)
function autoFillInHiResFixs(firstphase_width, firstphase_height) {
//update the firstphase width slider and label
autoFillInSliderUi(firstphase_width, 'hrWidth', 'hWidth', 1.0 / 64)
@ -442,23 +216,6 @@ function getSamplerElementByName(sampler_name) {
}
}
function getCheckedSamplerName() {
//we assume that the samplers exist and loaded in html
//return the name of the first checked sampler
try {
return [...document.getElementsByClassName('rbSampler')].filter(
(elm) => elm.checked == true
)[0].value
} catch (e) {
console.warn(e)
}
}
function getMode() {
return [...document.getElementsByClassName('rbMode')].filter(
(e) => e.checked == true
)[0].value
}
function getBackendType() {
return [...document.getElementsByClassName('rbBackendType')].filter(
(e) => e.checked == true
@ -525,18 +282,6 @@ function selectModelUi(model_hash) {
model_element.selected = true
}
function autoFillInModel(model_hash) {
try {
// unCheckAllSamplers()
model_element = getModelElementByHash(model_hash)
selectModelUi(model_hash)
// model_element.
const model_title = model_element.dataset.model_title
return model_title
} catch (e) {
console.warn(e)
}
}
////// End Models//////////
////// Start Init Image && Init Image Mask//////////
@ -601,105 +346,8 @@ function setProxyServerStatus(newStatusClass, oldStatusClass) {
}
////// End Servers Status //////////
////// Start Extras //////////
sliderAddEventListener('slUpscaleSize', 'lUpscaleSize', 0.1, 1)
function getUpscaleSize() {
slider_width = document.getElementById('slUpscaleSize').value
const size = slider_width / 10
return size
}
sliderAddEventListener('slUpscaler2Visibility', 'lUpscaler2Visibility', 0.1, 1)
function getUpscaler2Visibility() {
slider_width = document.getElementById('slUpscaler2Visibility').value
const size = slider_width / 10
return size
}
sliderAddEventListener('slGFPGANVisibility', 'lGFPGANVisibility', 0.1, 1)
function getGFPGANVisibility() {
slider_width = document.getElementById('slGFPGANVisibility').value
const size = slider_width / 10
return size
}
sliderAddEventListener(
'slCodeFormerVisibility',
'lCodeFormerVisibility',
0.1,
1
)
function getCodeFormerVisibility() {
slider_width = document.getElementById('slCodeFormerVisibility').value
const size = slider_width / 10
return size
}
sliderAddEventListener('slCodeFormerWeight', 'lCodeFormerWeight', 0.1, 1)
function getCodeFormerWeight() {
slider_width = document.getElementById('slCodeFormerWeight').value
const size = slider_width / 10
return size
}
////// End Extras //////////
////// Start Reset Settings Button //////////
const defaultSettings = {
model: null,
prompt_shortcut: null,
positive_prompt: '',
negative_prompt: '',
selection_mode: null,
batch_number: 1,
steps: 20,
width: 512,
height: 512,
firstphase_width: 512,
firstphase_height: 512,
cfg: 7,
denoising_strength: 0.7,
hi_res_denoising_strength: 0.7,
mask_blur: 8,
inpaint_at_full_res: false,
hi_res_fix: false,
inpaint_padding: 0,
seed: -1,
samplers: null,
mask_content: null,
}
const snapshot_btns = Array.from(
document.getElementsByClassName('snapshotButton')
)
snapshot_btns.forEach((element) =>
element.addEventListener('click', async () => {
try {
await psapi.snapshot_layerExe()
} catch (e) {
console.warn(e)
}
})
)
const reset_btns = Array.from(document.getElementsByClassName('resetButton'))
reset_btns.forEach((element) =>
element.addEventListener('click', async () => {
try {
autoFillDefaultSettings(defaultSettings)
} catch (e) {
console.warn(e)
}
})
)
function getBatchNumber() {
// return document.getElementById('tiNumberOfImages').value
return document.getElementById('tiNumberOfBatchSize').value
@ -709,67 +357,45 @@ function autoFillInBatchNumber(batch_number) {
document.getElementById('tiNumberOfBatchSize').value = String(batch_number)
}
function getSteps() {
return document.getElementById('tiNumberOfSteps').value
}
function autoFillInSteps(steps) {
document.getElementById('tiNumberOfSteps').value = String(steps)
}
function autoFillDefaultSettings(default_settings) {
autoFillSettings(default_settings)
}
function setCFG(cfg_value) {
document.getElementById('slCfgScale').value = cfg_value
sd_tab_store.data.cfg = cfg_value
}
function getCFG() {
return document.getElementById('slCfgScale').value
return sd_tab_store.data.cfg
}
function autoFillSettings(settings) {
try {
//reset all UI settings except model selection and sampler selection
autoFillInPrompt(settings['positive_prompt'])
autoFillInNegativePrompt(settings['negative_prompt'])
multiPrompts.setPrompt({ positive: settings['positive_prompt'] })
multiPrompts.setPrompt({ negative: settings['negative_prompt'] })
autoFillInBatchNumber(settings['batch_number'])
autoFillInSteps(settings['steps'])
sd_tab_store.data.steps = settings['steps']
autoFillInWidth(settings['width'])
autoFillInHeight(settings['height'])
autoFillInHiResFixs(
settings['firstphase_width'],
settings['firstphase_height']
)
document.getElementById('slCfgScale').value = settings['cfg']
autoFillInDenoisingStrength(settings['denoising_strength'])
sd_tab_store.data.cfg = settings['cfg']
sd_tab_store.data.denoising_strength = settings['denoising_strength']
autoFillInSliderUi(
settings['hi_res_denoising_strength'],
'hrDenoisingStrength',
'hDenoisingStrength',
100
)
document.getElementById('slMaskBlur').value = settings['mask_blur']
document.getElementById('chInpaintFullRes').checked =
settings['inpaint_at_full_res']
setHiResFixs(settings['hi_res_fix'])
document.getElementById('tiSeed').value = String(settings['seed'])
sd_tab_store.data.mask_blur = settings['mask_blur']
sd_tab_store.data.inpaint_full_res = settings['inpaint_at_full_res']
sd_tab_store.data.enable_hr = settings['hi_res_fix']
sd_tab_store.data.seed = String(settings['seed'])
} catch (e) {
console.warn(e)
}
}
////// End Reset Settings Button //////////
function getMaskBlur() {
const isDisabled = document
.getElementById('slMaskBlur')
.hasAttribute('disabled')
let mask_blur = 0
if (isDisabled) {
mask_blur = 0
} else {
mask_blur = document.getElementById('slMaskBlur').value
}
return mask_blur
}
function setMaskBlur(mask_blur) {
document.getElementById('slMaskBlur').value = mask_blur
}
@ -789,12 +415,6 @@ function setPromptShortcut(prompt_shortcut) {
document.getElementById('taPromptShortcut').value = JSONInPrettyFormat
}
////start selection mode/////
function getSelectionMode() {
return [...document.getElementsByClassName('rbSelectionMode')].filter(
(e) => e.checked == true
)[0].value
}
function getMaskContent() {
return [...document.getElementsByClassName('rbMaskContent')].filter(
(e) => e.checked == true
@ -851,22 +471,6 @@ function addHistoryButtonsHtml(img_html) {
return container
}
function getSeed() {
const seed = document.getElementById('tiSeed').value
return seed
}
function setSeed(new_seed) {
document.getElementById('tiSeed').value = new_seed
}
function getMaskExpansion() {
const mask_expansion = document.getElementById('slMaskExpansion').value
return mask_expansion
}
function setMaskExpansion(mask_expansion) {
document.getElementById('slMaskExpansion').value = mask_expansion
}
function updateProgressBarsHtml(new_value, progress_text = 'Progress...') {
document.querySelectorAll('.pProgressBars').forEach((bar_elm) => {
@ -888,14 +492,7 @@ function updateProgressBarsHtml(new_value, progress_text = 'Progress...') {
// document.querySelector('#pProgressBar').value
}
///end selection mode////
function getLinkWidthHeightState() {
const state_str = document.getElementById('linkWidthHeight').dataset.b_link // sometime it's true and other time it's "true"
const b_state = state_str.toString() === 'true' ? true : false
return b_state
}
function setLinkWidthHeightState(state) {
document.getElementById('linkWidthHeight').dataset.b_link = state
}
function isSquareThumbnail() {
return document.getElementById('chSquareThumbnail').checked
}
@ -1071,12 +668,10 @@ function getUseSilentMode() {
}
module.exports = {
getPrompt,
autoFillInPrompt,
getNegativePrompt,
autoFillInNegativePrompt,
getDenoisingStrength,
autoFillInDenoisingStrength,
getWidth,
autoFillInWidth,
getHeight,
@ -1084,22 +679,19 @@ module.exports = {
getSliderSdValue,
setSliderSdValue,
autoFillInHiResFixs,
getHiResFixs,
setHiResFixs,
autoFillInSliderUi,
getCheckedSamplerName,
autoFillInSampler,
autoFillInModel,
getMode,
setInitImageSrc,
setInitImageMaskSrc,
setAutomaticStatus,
setProxyServerStatus,
defaultSettings,
autoFillDefaultSettings,
autoFillSettings,
getMaskBlur,
setMaskBlur,
autoFillInHRHeight,
@ -1107,10 +699,9 @@ module.exports = {
getPromptShortcut,
setPromptShortcut,
getModelHashByTitle,
getSelectionMode,
autoFillInInpaintMaskWeight,
autoFillInSteps,
getSteps,
getBatchNumber,
autoFillInBatchNumber,
getHrWidth,
@ -1121,21 +712,11 @@ module.exports = {
setMaskContent,
addHistoryButtonsHtml,
getSeed,
setSeed,
getMaskExpansion,
setMaskExpansion,
getUpscaleSize,
getUpscaler2Visibility,
getCodeFormerVisibility,
getGFPGANVisibility,
getCodeFormerWeight,
updateProgressBarsHtml,
getBackendType,
getHordeApiKey,
setProgressImageSrc,
getLinkWidthHeightState,
setLinkWidthHeightState,
isSquareThumbnail,
setControlImageSrc,
@ -1150,7 +731,7 @@ module.exports = {
getSliderSdValue_Old,
getSelectedRadioButtonElement,
getInitImageMaskElement,
sliderAddEventListener_new,
getSliderSdValueByElement,
setSliderSdValueByElements,
populateMenuByElement,

View File

@ -6,7 +6,7 @@ class Notification {
static async webuiIsOffline() {
const r1 = await dialog_box.prompt(
'Automatic1111 is Offline',
"make sure Automatic1111 is running in the background, or select the 'native horde' option from the horde tab",
'make sure Automatic1111 is running in the background',
['Cancel', 'OK']
)
@ -93,7 +93,7 @@ class Notification {
psapi.selectMarqueeRectangularToolExe()
return false // should this be false?! what does true and false means in this context?! Yes: it should be false since boolean value represent wither we have an active selection area or not
} else if (r1 === button_label) {
await activateSessionSelectionArea()
await selection_ts.activateSessionSelectionArea()
return true
}
return false

View File

@ -1,406 +0,0 @@
const io = require('../io')
const html_manip = require('../html_manip')
const Enum = require('../../enum')
const event = require('../event')
let settings = {
model: null,
prompt_shortcut: null,
positive_prompt: null,
negative_prompt: null,
selection_mode: null,
batch_number: null,
steps: null,
width: null,
height: null,
firstphase_width: null,
firstphase_height: null,
cfg: null,
denoising_strength: null,
hi_res_denoising_strength: null,
mask_blur: null,
inpaint_at_full_res: null,
hi_res_fix: null,
inpaint_padding: null,
seed: null,
samplers: null,
mask_content: null,
}
let LatentNoiseSettings = {
model: null,
prompt_shortcut: null,
positive_prompt: null,
negative_prompt: null,
generation_mode: null,
batch_number: null,
steps: null,
width: null,
height: null,
firstphase_width: null,
firstphase_height: null,
cfg: null,
denoising_strength: 0.92,
hi_res_denoising_strength: null,
mask_blur: null,
inpaint_at_full_res: null,
hi_res_fix: null,
inpaint_padding: null,
seed: null,
samplers: null,
mask_content: '2',
}
let FillSettings = {
model: null,
prompt_shortcut: null,
positive_prompt: null,
negative_prompt: null,
generation_mode: null,
batch_number: null,
steps: null,
width: null,
height: null,
firstphase_width: null,
firstphase_height: null,
cfg: null,
denoising_strength: 0.7,
hi_res_denoising_strength: null,
mask_blur: null,
inpaint_at_full_res: null,
hi_res_fix: null,
inpaint_padding: null,
seed: null,
samplers: null,
mask_content: '0',
}
let OriginalSettings = {
model: null,
prompt_shortcut: null,
positive_prompt: null,
negative_prompt: null,
generation_mode: null,
batch_number: null,
steps: null,
width: null,
height: null,
firstphase_width: null,
firstphase_height: null,
cfg: null,
denoising_strength: 0.7,
hi_res_denoising_strength: null,
mask_blur: null,
inpaint_at_full_res: null,
hi_res_fix: null,
inpaint_padding: null,
seed: null,
samplers: null,
mask_content: '1',
}
let HealBrushSettings = {
model: null,
prompt_shortcut: null,
positive_prompt: null,
negative_prompt: null,
generation_mode: null,
batch_number: null,
steps: '25',
width: null,
height: null,
firstphase_width: null,
firstphase_height: null,
cfg: '9',
denoising_strength: 0.92,
hi_res_denoising_strength: null,
mask_blur: 1,
inpaint_at_full_res: null,
hi_res_fix: null,
inpaint_padding: null,
seed: null,
samplers: null,
mask_content: '2',
mask_expansion: 2,
}
function nullAllSettings() {}
class Preset {
constructor() {}
loadPresetFromJson(preset_path) {}
savePresetToJson(preset_path, settings) {}
}
function getPresetSettingsHtml() {
const value_str = document.getElementById('taPresetSettings').value
const value_json = JSON.parse(value_str)
return value_json
}
function setPresetSettingsHtml(preset_settings) {
const JSONInPrettyFormat = JSON.stringify(preset_settings, undefined, 7)
preset_settings_element = document.getElementById('taPresetSettings')
preset_settings_element.value = JSONInPrettyFormat
const new_lines_count = general.countNewLines(JSONInPrettyFormat)
new_lines_count
preset_settings_element.style.height =
Math.min(new_lines_count * 12 + 100, 800).toString() + 'px'
}
function getPresetName() {
const preset_name = document.getElementById('tiPresetName').value
return preset_name
}
function setPresetName(preset_name) {
document.getElementById('tiPresetName').value = preset_name
}
function getPresetSettings(preset_type) {
let preset_settings
if (preset_type === Enum.PresetTypeEnum['SDPreset']) {
preset_settings = g_ui_settings_object.getSettings()
} else if (preset_type === Enum.PresetTypeEnum['ControlNetPreset']) {
const { getUnitsData } =
require('../../typescripts/dist/bundle').control_net // only import ControlNetUnit to avoid circular dependency
preset_settings = getUnitsData()
}
return preset_settings
}
function getPresetType() {
const presetType = document.getElementById('rgPresetType').selected
return presetType
}
document.getElementById('btnNewPreset').addEventListener('click', () => {
// const g_ui_settings_object = getUISettingsObject()
const preset_type = getPresetType()
const preset_settings = getPresetSettings(preset_type)
// const settings = g_ui_settings_object.getSettings()
setPresetSettingsHtml(preset_settings)
const preset_name = getPresetName()
setPresetNameLabel(preset_name)
})
function getPresetNameLabel() {
//use presetNameLabel as the final name for a preset
const preset_name = document.getElementById('lPresetName').textContent
return preset_name
}
function setPresetNameLabel(preset_name) {
document.getElementById('lPresetName').textContent = preset_name.trim()
}
async function populatePresetMenu() {
// presets = ['preset_1', 'preset_2', 'preset_3']
const preset_type = getPresetType()
const presets = await getAllCustomPresetsSettings(preset_type)
const presets_names = Object.keys(presets)
html_manip.populateMenu(
'mSettingTabPresetMenu',
'mPresetMenuItemClass',
presets_names,
(item, item_html_element) => {
item_html_element.innerHTML = item
}
)
}
async function deletePreset() {
try {
const preset_name = html_manip.getSelectedMenuItemTextContent(
'mSettingTabPresetMenu'
)
const preset_file_name = preset_name + '.json'
const preset_type = getPresetType()
const preset_folder_name = mapPresetTypeToPresetFolder(preset_type)
const custom_preset_entry = await io.IOFolder.getCustomPresetFolder(
preset_folder_name
)
await io.IOJson.deleteFile(custom_preset_entry, preset_file_name)
html_manip.unselectMenuItem('mSettingTabPresetMenu') // unselect the custom preset menu
setPresetSettingsHtml({}) //reset preset settings text area
setPresetName('')
setPresetNameLabel('')
await populatePresetMenu() // update the custom preset Menu
triggerUpdatePresetMenu(preset_type)
} catch (e) {
console.warn(e)
}
}
async function getCustomPresetEntries(preset_folder_name) {
const custom_preset_entry = await io.IOFolder.getCustomPresetFolder(
preset_folder_name
)
const custom_preset_entries = await io.IOJson.getJsonEntries(
custom_preset_entry
)
return custom_preset_entries
}
async function loadPresetSettingsFromFile(preset_file_name, preset_type) {
// const preset_type = getPresetType()
const preset_folder_name = mapPresetTypeToPresetFolder(preset_type)
const custom_preset_entry = await io.IOFolder.getCustomPresetFolder(
preset_folder_name
)
let preset_settings = {}
try {
preset_settings = await io.IOJson.loadJsonFromFile(
custom_preset_entry,
preset_file_name
)
} catch (e) {
console.warn(e)
}
return preset_settings
}
async function getAllCustomPresetsSettings(preset_type) {
const preset_folder_name = mapPresetTypeToPresetFolder(preset_type)
const custom_preset_entries = await getCustomPresetEntries(
preset_folder_name
)
let custom_presets = {}
for (const entry of custom_preset_entries) {
const preset_name = entry.name.split('.json')[0]
let preset_settings = await loadPresetSettingsFromFile(
entry.name,
preset_type
)
custom_presets[preset_name] = preset_settings
}
return custom_presets
}
function mapPresetTypeToPresetFolder(preset_type) {
let preset_folder
if (preset_type === Enum.PresetTypeEnum['SDPreset']) {
preset_folder = 'custom_preset'
} else if (preset_type === Enum.PresetTypeEnum['ControlNetPreset']) {
preset_folder = 'controlnet_preset'
}
return preset_folder
}
function triggerUpdatePresetMenu(preset_type) {
let menu_id
if (preset_type === Enum.PresetTypeEnum['SDPreset']) {
menu_id = '#mPresetMenu'
} else if (preset_type === Enum.PresetTypeEnum['ControlNetPreset']) {
menu_id = '#mControlNetPresetMenu'
}
event.triggerEvent(menu_id, event.updatePresetMenuEvent)
}
Array.from(document.getElementsByClassName('rbPresetType')).forEach((rb) => {
rb.addEventListener('click', async () => {
const preset_type = rb.value
await populatePresetMenu()
})
})
document.getElementById('btnSavePreset').addEventListener('click', async () => {
//save preset settings from textarea to json file
//reload the preset menu
const preset_type = getPresetType()
const custom_preset_folder_name = mapPresetTypeToPresetFolder(preset_type)
const custom_preset_entry = await io.IOFolder.getCustomPresetFolder(
custom_preset_folder_name
)
const preset_settings = getPresetSettingsHtml()
const preset_name = getPresetNameLabel()
//check if the file exist and prompt the user to override it or cancel
await io.IOJson.saveJsonToFileExe(
preset_settings,
custom_preset_entry,
preset_name + '.json'
)
await populatePresetMenu()
triggerUpdatePresetMenu(preset_type)
html_manip.selectMenuItem('mSettingTabPresetMenu', preset_name)
})
document
.getElementById('btnDeletePreset')
.addEventListener('click', async () => {
await deletePreset()
})
document.getElementById('tiPresetName').addEventListener('input', () => {
//save preset settings from textarea to json file
//reload the preset menu
const preset_name = getPresetName()
setPresetNameLabel(preset_name)
//check if the file exist and prompt the user to override it or cancel
})
document
.getElementById('mSettingTabPresetMenu')
.addEventListener('input', () => {
//Note: is this correct?! why use Input and change events together
//save preset settings from textarea to json file
//reload the preset menu
const preset_name = getPresetName()
setPresetNameLabel(preset_name)
//check if the file exist and prompt the user to override it or cancel
})
document
.getElementById('mSettingTabPresetMenu')
.addEventListener('change', async (evt) => {
try {
const preset_index = evt.target.selectedIndex
const preset_name = evt.target.options[preset_index].textContent
const preset_type = getPresetType()
setPresetName(preset_name)
setPresetNameLabel(preset_name)
const preset_settings = await loadPresetSettingsFromFile(
preset_name + '.json',
preset_type
)
setPresetSettingsHtml(preset_settings)
} catch (e) {}
})
document
.getElementById('mPresetMenu')
.addEventListener('updatePresetMenuEvent', async (event) => {
// console.log("I'm listening on a custom event")
const { populatePresetMenu } = require('../ui')
await populatePresetMenu()
})
async function initializePresetTab() {
try {
await populatePresetMenu()
const selected_rb =
html_manip.getSelectedRadioButtonElement('rbPresetType')
selected_rb.click() // to trigger the click event which will update the setting preset menu according to the preset type
} catch (e) {
console.error(e)
}
}
initializePresetTab()
module.exports = {
LatentNoiseSettings,
FillSettings,
OriginalSettings,
HealBrushSettings,
populatePresetMenu,
getCustomPresetEntries,
loadPresetSettingsFromFile,
getAllCustomPresetsSettings,
initializePresetTab,
}

View File

@ -222,7 +222,7 @@ async function txt2ImgRequest(payload) {
// const request_path = '/sdapi/v1/txt2img'
}
function getExtensionUrl() {
const extension_type = settings_tab.getExtensionType()
const extension_type = settings_tab_ts.store.data.extension_type
let extension_url
if (extension_type === 'auto1111_extension') {
@ -305,31 +305,6 @@ async function img2ImgRequest(sd_url, payload) {
payload['prompt'] = new_prompt
payload['negative_prompt'] = new_negative_prompt
}
// init_img_dir = "./init_images"
// init_img_name = payload['init_image_name']
// init_img = Image.open(f"{init_img_dir}/{init_img_name}")
// init_img_str = img_2_b64(init_img)
// payload['init_images'] = [init_img_str]
// init_img_mask_name = payload.get('init_image_mask_name',"")
// #only if image exist then try to open it
// if(len(init_img_mask_name) > 0):
// init_img_mask = Image.open(f"{init_img_dir}/{init_img_mask_name}")
// if (payload['use_sharp_mask'] === false && payload['mask']) {
// //only if mask is available and sharp_mask is off
// // use blurry and expanded mask
// const iterations = payload['mask_expansion']
// const mask = await maskExpansionRequest(payload['mask'], iterations)
// if (mask) {
// payload['mask'] = mask
// }
// }
// print(type(init_img_str))
// #request the images to be generated
const endpoint = 'sdapi/v1/img2img'

View File

@ -6,6 +6,7 @@ const Enum = require('../enum')
const { base64ToBase64Url } = require('./general')
const html_manip = require('./html_manip')
const layer_util = require('./layer')
const SessionState = {
Active: 'active',
Inactive: 'inactive',
@ -181,21 +182,16 @@ async function getSettings(session_data) {
let payload = {}
try {
const extension_type = settings_tab.getExtensionType() // get the extension type
const extension_type = settings_tab_ts.store.data.extension_type // get the extension type
payload['selection_info'] = session_data.selectionInfo
const numberOfBatchSize = parseInt(
document.querySelector('#tiNumberOfBatchSize').value
)
const numberOfSteps = document.querySelector('#tiNumberOfSteps').value
const prompt = html_manip.getPrompt()
const negative_prompt = html_manip.getNegativePrompt()
const hi_res_fix = html_manip.getHiResFixs()
// console.log("prompt:",prompt)
// console.log("negative_prompt:",negative_prompt)
const model_index = document.querySelector('#mModelsMenu').selectedIndex
const upscaler = document.querySelector('#hrModelsMenu').value
const cfg_scale = document.querySelector('#slCfgScale').value
// const model_index = document.querySelector("#")
const numberOfBatchSize = parseInt(sd_tab_store.data.batch_size)
const prompt = multiPrompts.getPrompt().positive
const negative_prompt = multiPrompts.getPrompt().negative
const hi_res_fix = sd_tab_store.data.enable_hr
const upscaler = sd_tab_store.data.hr_upscaler
const cfg_scale = sd_tab_store.data.cfg
function calculateSeed(init_seed, batch_index, batch_size) {
if (init_seed === -1) return -1
@ -203,25 +199,25 @@ async function getSettings(session_data) {
return seed
}
const init_seed = parseInt(document.querySelector('#tiSeed').value)
const init_seed = parseInt(sd_tab_store.data.seed)
const seed = calculateSeed(
init_seed,
g_current_batch_index,
numberOfBatchSize
)
// const mask_blur = document.querySelector('#slMaskBlur').value
const use_sharp_mask = settings_tab.getUseSharpMask()
const mask_blur = html_manip.getMaskBlur()
const mask_expansion = document.getElementById('slMaskExpansion').value
const use_sharp_mask = settings_tab_ts.store.data.extension_type
const mask_blur = settings_tab_ts.store.data.use_sharp_mask
? 0
: sd_tab_store.data.mask_blur
const mask_expansion = sd_tab_store.data.mask_expansion
const inpaint_full_res_padding =
document.querySelector('#slInpaintPadding').value
sd_tab_store.data.inpaint_full_res_padding
// console.dir(numberOfImages)
const bUsePromptShortcut = document.getElementById(
'chUsePromptShortcut'
).checked
const bUsePromptShortcut =
settings_tab_ts.store.data.use_prompt_shortcut
let prompt_shortcut_ui_dict = {}
try {
let prompt_shortcut_string =
@ -236,46 +232,33 @@ async function getSettings(session_data) {
// const slider_width = document.getElementById("slWidth").value
// gWidth = getWidthFromSlider(slider_width)
const original_width = html_manip.getWidth()
const original_height = html_manip.getHeight()
const original_width = sd_tab_store.data.width
const original_height = sd_tab_store.data.height
const width = general.nearestMultiple(original_width, 64)
const height = general.nearestMultiple(original_height, 64)
const hWidth = html_manip.getSliderSdValue_Old('hrWidth', 64)
const hHeight = html_manip.getSliderSdValue_Old('hrHeight', 64)
const hSteps = html_manip.getSliderSdValue_Old('hrNumberOfSteps', 1)
//const hScale = html_manip.getSliderSdValue_Old('hrScale',1)
console.log('Check')
const uniqueDocumentId = await getUniqueDocumentId()
const h_denoising_strength = html_manip.getSliderSdValue_Old(
'hrDenoisingStrength',
0.01
)
console.log('Check2')
const h_denoising_strength = sd_tab_store.data.hr_denoising_strength
//Note: store the sampler names in json file if auto is offline or auto api is unmounted
const sampler_name = html_manip.getCheckedSamplerName()
const sampler_name = sd_tab_store.data.sampler_name
const mode = html_manip.getMode()
const b_restore_faces =
document.getElementById('chRestoreFaces').checked
const mode = sd_tab_store.data.rb_mode
const b_restore_faces = sd_tab_store.data.restore_faces
let denoising_strength = h_denoising_strength
if (mode == 'inpaint' || mode == 'outpaint') {
var g_use_mask_image = true
payload['inpaint_full_res'] =
document.getElementById('chInpaintFullRes').checked
payload['inpaint_full_res_padding'] = inpaint_full_res_padding * 4
payload['inpaint_full_res'] = sd_tab_store.data.inpaint_full_res
console.log('g_use_mask_image is ', g_use_mask_image)
console.log('g_init_image_mask_name is ', g_init_image_mask_name)
payload['init_image_mask_name'] = g_init_image_mask_name
payload['inpainting_fill'] = html_manip.getMaskContent()
payload['inpaint_full_res_padding'] = inpaint_full_res_padding
payload['inpainting_fill'] = sd_tab_store.data.inpainting_fill
payload['mask_expansion'] = mask_expansion
// payload['mask'] = g_generation_session.activeBase64MaskImage
payload['mask'] = session_data?.mask
payload['expanded_mask'] = session_data?.mask
if (
@ -294,16 +277,10 @@ async function getSettings(session_data) {
if (expanded_mask) {
payload['expanded_mask'] = expanded_mask
payload['mask'] = expanded_mask
session_ts.store.data.expanded_mask = expanded_mask
session_store.data.expanded_mask = expanded_mask
}
}
// viewer.store.mask = payload['mask'] // make sure
} else if (mode == 'img2img') {
var g_use_mask_image = false
delete payload['inpaint_full_res'] // inpaint full res is not available in img2img mode
delete payload['inpaint_full_res_padding']
delete payload['init_image_mask_name']
delete payload['inpainting_fill']
}
if (
@ -311,19 +288,14 @@ async function getSettings(session_data) {
g_sd_mode == 'inpaint' ||
g_sd_mode == 'outpaint'
) {
// const { init_image, mask } = io.getOutpaintInitImageAndMask()
console.log(`g_use_mask_image:? ${g_use_mask_image}`)
denoising_strength = html_manip.getDenoisingStrength()
denoising_strength = sd_tab_store.data.denoising_strength
payload['denoising_strength'] = denoising_strength
payload['init_image_name'] = g_init_image_name
payload['init_images'] = [session_data?.init_image]
// payload['init_images'] = [
// g_generation_session.activeBase64InitImage,
// // init_image,
// ]
payload['image_cfg_scale'] = sd_tab.getImageCfgScaleSDValue() // we may need to check if model is pix2pix
if (settings_tab_ts.store.data.use_image_cfg_scale_slider) {
payload['image_cfg_scale'] = sd_tab_store.data.image_cfg_scale // we may need to check if model is pix2pix
}
if (
scripts.script_store.isInstalled() &&
@ -336,13 +308,8 @@ async function getSettings(session_data) {
payload['script_name'] =
scripts.script_store.selected_script_name //'Ultimate SD upscale'
}
} else {
delete payload['script_args']
delete payload['script_name']
}
// payload['script_args'] = []
function setAlwaysOnScripts() {
const data = after_detailer_script.store.toJsFunc().data
// console.log('setAlwaysOnScripts=> data:', data)
@ -405,37 +372,13 @@ async function getSettings(session_data) {
}
if (hi_res_fix && width >= 512 && height >= 512) {
const hr_scale = sd_tab.getHrScaleSliderSDValue()
payload['enable_hr'] = hi_res_fix
// payload['firstphase_width'] = width
// payload['firstphase_height'] = height
// payload['hr_resize_x'] = hWidth
// payload['hr_resize_y'] = hHeight
payload['hr_scale'] = hr_scale // Scale
payload['hr_scale'] = sd_tab_store.data.hr_scale // Scale
payload['hr_upscaler'] = upscaler // Upscaler
payload['hr_second_pass_steps'] = hSteps // Number of Steps
} else {
//fix hi res bug: if we include firstphase_width or firstphase_height in the payload,
// sd api will use them instead of using width and height variables, even when enable_hr is set to "false"
delete payload['enable_hr']
// delete payload['firstphase_width']
// delete payload['firstphase_height']
payload['hr_second_pass_steps'] =
sd_tab_store.data.hr_second_pass_steps
}
//work with the hord
// const script_args_json = {
// model: "Anything Diffusion",
// nsfw: false,
// shared_laion: false,
// seed_variation: 1,
// post_processing_1: "None",
// post_processing_2: "None",
// post_processing_3: "None"
// }
// const script_args = Object.values(script_args_json)
const backend_type = html_manip.getBackendType()
if (backend_type === backendTypeEnum['Auto1111HordeExtension']) {
payload['script_name'] = script_horde.script_name
@ -477,7 +420,7 @@ async function getSettings(session_data) {
...payload,
// prompt: prompt,
// negative_prompt: negative_prompt,
steps: numberOfSteps,
steps: sd_tab_store.data.steps,
// n_iter: numberOfImages,
sampler_index: sampler_name,
width: width,

View File

@ -1,411 +0,0 @@
const general = require('../general')
const thumbnail = require('../../thumbnail')
const html_manip = require('../html_manip')
const api = require('../api')
const psapi = require('../../psapi')
const sdapi = require('../../sdapi_py_re')
const Enum = require('../../enum')
//REFACTOR: move to notification.js
async function requestGetHiResUpscalers() {
try {
const full_url = `${g_sd_url}/sdapi/v1/upscalers`
let upscalers = await api.requestGet(full_url)
return [
'Latent',
'Latent (antialiased)',
'Latent (bicubic)',
'Latent (bicubic antialiased)',
'Latent (nearest)',
'Latent (nearest-exact)',
...upscalers.map((upscaler) => upscaler.name),
]
} catch (e) {
console.warn('requestGetHiResUpscalers:', e)
return [
'Latent',
'Latent (antialiased)',
'Latent (bicubic)',
'Latent (bicubic antialiased)',
'Latent (nearest)',
'Latent (nearest-exact)',
]
}
}
async function promptForUpdate(header_message, long_message) {
const shell = require('uxp').shell
;(async () => {
const buttons = ['Cancel', 'OK']
const r1 = await dialog_box.prompt(
header_message,
long_message,
buttons
// 'Please Update you Plugin. it will take about 10 seconds to update',
// 'update from discord, update from github'[
// ['Cancel', 'Discord', 'Github']
// ('Cancel', 'OK')
// ]
)
try {
let url
if (r1 === 'Cancel') {
/* cancelled or No */
console.log('cancel')
} else if (r1 === 'Github') {
url =
'https://github.com/AbdullahAlfaraj/Auto-Photoshop-StableDiffusion-Plugin'
// await py_re.openUrlRequest(url)
} else if (r1 === 'Discord') {
console.log('Discord')
// url = 'https://discord.gg/3mVEtrddXJ'
// url = 'https://discord.gg/YkUJXYWK3c'
// await py_re.openUrlRequest(url)
} else if (r1 === 'Ok') {
}
// console.log('url: ', url)
} catch (e) {
console.warn(e, url)
}
})()
}
async function updateClickEventHandler(current_version) {
try {
const online_data = await general.requestOnlineData()
const b_need_update = general.compareVersions(
current_version,
online_data.new_version
)
let header_message = "You're Plugin is up to date."
let long_message = ''
if (b_need_update) {
header_message = `New Version is Available (${online_data.new_version})`
long_message = online_data.update_message
}
await promptForUpdate(header_message, long_message)
} catch (e) {
console.warn(e)
}
}
function viewMaskExpansion() {
if (session_ts.store.data.expanded_mask) {
const mask_src = general.base64ToBase64Url(
session_ts.store.data.expanded_mask
)
html_manip.setInitImageMaskSrc(mask_src)
} else {
console.log(
'the mask has not been expanded, g_generation_session.base64maskExpansionImage is empty'
)
}
}
function viewDrawnMask() {
//this is the generated mask or user drawn mask, but it's not the mask after expansion
if (session_ts.store.data.mask) {
const mask_src = general.base64ToBase64Url(session_ts.store.data.mask)
html_manip.setInitImageMaskSrc(mask_src)
} else {
console.log('no mask is available')
}
}
async function clipInterrogate() {
try {
const width = html_manip.getWidth()
const height = html_manip.getHeight()
const selectionInfo = await psapi.getSelectionInfoExe()
const base64 = await io.IO.getSelectionFromCanvasAsBase64Interface_New(
width,
height,
selectionInfo,
true
)
const url = `${g_sd_url}/sdapi/v1/interrogate`
const payload = {
image: base64,
model: 'clip',
}
const result_json = await api.requestPost(url, payload)
console.log(result_json)
return result_json
} catch (e) {
console.warn(e)
}
}
function getHrScaleSliderSDValue() {
sd_value = html_manip.getSliderSdValue('hrScaleSlider', 1, 100, 1, 4)
return sd_value
}
function setHrScaleSliderSDValue(sd_value) {
const slider_id = 'hrScaleSlider'
const label_id = 'hrScaleLabel'
html_manip.setSliderSdValue(slider_id, label_id, sd_value, 1, 100, 1, 4)
}
function getImageCfgScaleSDValue() {
sd_value = html_manip.getSliderSdValue('slImageCfgScale', 0, 30, 0, 3)
return sd_value
}
function setImageCfgScaleSDValue(sd_value) {
const slider_id = 'slImageCfgScale'
const label_id = 'lImageCfgScale'
html_manip.setSliderSdValue(slider_id, label_id, sd_value, 0, 30, 0, 3)
}
function updateHrScaleFromToLabel() {
//get width and height
//get hr scale by
//find the hr scale and height
const hr_scale = getHrScaleSliderSDValue()
const [width, height] = [html_manip.getWidth(), html_manip.getHeight()]
const [hr_width, hr_height] = [
parseInt(width * hr_scale),
parseInt(height * hr_scale),
]
document.getElementById(
'lHrScaleFromTo'
).textContent = `${width}x${height} -> ${hr_width}x${hr_height}`
}
function getLoraModelPrompt(lora_model_name) {
return `<lora:${lora_model_name}:1>`
}
async function populateLoraModelMenu() {
try {
const lora_models = await sdapi.requestLoraModels()
const lora_models_names = lora_models.map(
(model_data) => model_data.name
)
document.getElementById('mLoraModelMenu').innerHTML = ''
html_manip.populateMenu(
'mLoraModelMenu',
'mLoraModelItemClass',
lora_models_names,
(item, item_html_element) => {
item_html_element.innerHTML = item
item_html_element.onclick = () => {
const lora_prompt = getLoraModelPrompt(item)
const prompt = html_manip.getPrompt()
html_manip.autoFillInPrompt(`${prompt} ${lora_prompt}`)
}
},
false,
'Select Lora'
)
} catch (e) {
console.warn('populateLoraModelMenu error: ', e)
}
}
function displayImageCfgScaleSlider(mode) {
const b_slider_enabled = document.getElementById(
'chUseImageCfgScaleSlider'
).checked
if (b_slider_enabled) {
if (mode === Enum.generationModeEnum['Txt2Img']) {
document.getElementById('slImageCfgScale').style.display = 'none'
} else if (mode === Enum.generationModeEnum['Img2Img']) {
document.getElementById('slImageCfgScale').style.display = 'block'
} else if (mode === Enum.generationModeEnum['Inpaint']) {
document.getElementById('slImageCfgScale').style.display = 'block'
} else if (mode === Enum.generationModeEnum['Outpaint']) {
document.getElementById('slImageCfgScale').style.display = 'none'
} else {
document.getElementById('slImageCfgScale').style.display = 'none'
}
} else {
document.getElementById('slImageCfgScale').style.display = 'none'
}
}
function initInitMaskElement() {
//make init mask image use the thumbnail class with buttons
const mask_image_html = html_manip.getInitImageMaskElement()
const mask_parent_element = mask_image_html.parentElement
this.thumbnail_container = thumbnail.Thumbnail.wrapImgInContainer(
mask_image_html,
'viewer-image-container'
)
mask_parent_element.appendChild(thumbnail_container)
thumbnail.Thumbnail.addSPButtonToContainer(
this.thumbnail_container,
'svg_sp_btn',
'view original mask',
viewDrawnMask,
null
)
thumbnail.Thumbnail.addSPButtonToContainer(
this.thumbnail_container,
'svg_sp_btn_expand',
'view modified mask',
viewMaskExpansion,
null
)
populateLoraModelMenu() // no need for await
}
async function refreshSDTab() {
populateLoraModelMenu()
}
document.getElementById('hrScaleSlider').addEventListener('input', (evt) => {
const sd_value = getHrScaleSliderSDValue()
setHrScaleSliderSDValue(sd_value.toFixed(2))
updateHrScaleFromToLabel()
})
document.getElementById('btnUpdate').addEventListener('click', async () => {
await updateClickEventHandler(g_version)
})
document
.getElementById('slMaskExpansion')
.addEventListener('change', async (evt) => {
const mask = session_ts.store.data.preprocessed_mask
const iterations = parseInt(evt.target.value)
const mask_blur = html_manip.getMaskBlur()
session_ts.store.data.expanded_mask = await session_ts.getExpandedMask(
mask,
iterations,
mask_blur
)
if (session_ts.store.data.expanded_mask) {
viewMaskExpansion()
}
})
document
.getElementById('slMaskBlur')
.addEventListener('change', async (evt) => {
const mask = session_ts.store.data.preprocessed_mask
const iterations = parseInt(
document.getElementById('slMaskExpansion').value
)
const mask_blur = parseInt(evt.target.value)
session_ts.store.data.expanded_mask = await session_ts.getExpandedMask(
mask,
iterations,
mask_blur
)
if (session_ts.store.data.expanded_mask) {
viewMaskExpansion()
}
})
document
.getElementById('btnInterrogate')
.addEventListener('click', async () => {
// start sudo timer after 1 seconds delay
setTimeout(() => {
g_generation_session.sudo_timer_id =
general.sudoTimer('Interrogate')
}, 1000)
const interrogate_result = await clipInterrogate()
if (interrogate_result.caption) {
html_manip.autoFillInPrompt(interrogate_result.caption)
}
// after the clipInterrogate finish stop the timer
html_manip.updateProgressBarsHtml(0, 'No work in progress')
g_generation_session.sudo_timer_id = clearInterval(
g_generation_session.sudo_timer_id
)
})
function ctrlBackspaceDelete(text) {
try {
let index = text.indexOf(String.fromCharCode(127))
let new_text = text
if (index >= 0) {
// Ctrl + Enter pressed
console.log('Ctrl + Enter pressed')
function ctrlBackspaceDeleteLogic(string, index) {
// if (index < 1) {
// return string
// }
// let i = index - 1
// while (
// i > 0 &&
// /\s/.test(string[i - 1]) === /\s/.test(string[i])
// ) {
// i--
// }
// return string.slice(0, i) + string.slice(index)
if (index < 1) {
return string
}
let i = index - 1
if (/\s/.test(string[i])) {
while (i > 0 && /\s/.test(string[i - 1])) {
i--
}
} else {
while (
i > 0 &&
/\s/.test(string[i - 1]) === /\s/.test(string[i])
) {
i--
}
}
return string.slice(0, i) + string.slice(index)
}
new_text = ctrlBackspaceDeleteLogic(text, index + 1) //+ 1 to also delete the backspace delete char
}
return new_text
} catch (error) {
console.warn(error)
}
}
// document.getElementById('taPrompt').addEventListener('input', (event) => {
//
// const value = event.target.value
// console.log('value: ', value)
// let index = value.indexOf(String.fromCharCode(127))
// console.log('index:', index)
// const new_text = ctrlBackspaceDelete(value)
// event.target.value = new_text
// console.log('new_text: ', new_text)
// })
function initSDTab() {
initInitMaskElement()
html_manip.sliderAddEventListener_new(
'slImageCfgScale',
'lImageCfgScale',
0,
30,
0,
3
)
}
initSDTab()
module.exports = {
updateClickEventHandler,
viewMaskExpansion,
viewDrawnMask,
clipInterrogate,
getHrScaleSliderSDValue,
getLoraModelPrompt,
populateLoraModelMenu,
getImageCfgScaleSDValue,
setImageCfgScaleSDValue,
refreshSDTab,
displayImageCfgScaleSlider,
requestGetHiResUpscalers,
}

View File

@ -1,27 +1,9 @@
const io = require('../io')
function getUseSharpMask() {
const isChecked = document.getElementById('chUseSharpMask').checked
return isChecked
}
function setUseSharpMask() {
console.warn('setUseSharpMask is not setup')
}
function getUseLiveProgressImage() {
const b_live_update = document.getElementById('chLiveProgressImage').checked
return b_live_update
}
function setUseLiveProgressImage(b_live_update) {
document.getElementById('chLiveProgressImage').checked = b_live_update
}
function getExtensionType() {
return [...document.getElementsByClassName('rbExtensionType')].filter(
(e) => e.checked == true
)[0].value
}
document.getElementById('btnGetDocPath').addEventListener('click', async () => {
const docPath = await io.IOFolder.getDocumentFolderNativePath()
document.getElementById('tiDocPath').value = docPath
@ -65,8 +47,8 @@ async function changeSdUrl(sd_url) {
async function saveSettings() {
const settings_tab_settings = {
use_sharp_mask: getUseSharpMask(),
extension_type: getExtensionType(),
use_sharp_mask: settings_tab_ts.store.data.use_sharp_mask,
extension_type: settings_tab_ts.store.data.extension_type,
sd_url: getSdUrlHtml(),
}
@ -91,15 +73,6 @@ async function loadSettings() {
}
}
document.getElementById('chUseSharpMask').addEventListener('change', (ev) => {
const isChecked = ev.target.checked
if (isChecked) {
document.getElementById('slMaskBlur').setAttribute('disabled')
} else {
document.getElementById('slMaskBlur').removeAttribute('disabled')
}
})
document.getElementById('chUseSmartObject').addEventListener('change', (ev) => {
const isChecked = ev.target.checked
if (isChecked) {
@ -123,15 +96,13 @@ document
})
module.exports = {
getUseSharpMask,
setUseSharpMask,
getExtensionType,
getSdUrlHtml,
setSdUrlHtml,
changeSdUrl,
loadSettings,
saveSettings,
getUseLiveProgressImage,
setUseLiveProgressImage,
getUseOriginalPrompt,
}

View File

@ -1,17 +0,0 @@
const chLiveProgressImageElements = document.getElementsByClassName(
'chLiveProgressImageClass'
)
const default_preview_value = document.getElementById(
'chLiveProgressImage'
).checked
chLiveProgressImageElements.forEach((element) => {
element.checked = default_preview_value
element.addEventListener('click', (event) => {
value = element.checked
chLiveProgressImageElements.forEach((element) => {
element.checked = value
})
})
})

View File

@ -1,282 +0,0 @@
const html_manip = require('./html_manip')
const presets = require('./presets/preset')
const layer_util = require('../utility/layer')
const psapi = require('../psapi')
const Enum = require('../enum')
const { executeAsModal } = require('photoshop').core
class UI {
constructor() {}
}
class UIElement {
constructor() {
this.name
this.html_elem
this.sd_value
}
setValue() {}
getValue() {}
}
function createUIElement(getter, setter) {
let ui_element_obj = new UIElement()
ui_element_obj.getValue = getter
ui_element_obj.setValue = setter
return ui_element_obj
}
class UISettings {
// get and set the settings of the ui. the stable diffusion settings not the human friendly settings
constructor() {
// this.width = new ui.UIElement()
// this.width.getValue = html_manip.getWidth
// this.width.setValue = html_manip.autoFillInWidth
this.width = createUIElement(
html_manip.getWidth,
html_manip.autoFillInWidth
)
this.height = createUIElement(
html_manip.getHeight,
html_manip.autoFillInHeight
)
this.steps = createUIElement(
html_manip.getSteps,
html_manip.autoFillInSteps
)
this.batch_number = createUIElement(
html_manip.getBatchNumber,
html_manip.autoFillInBatchNumber
)
this.firstphase_width = createUIElement(
html_manip.getHrWidth,
html_manip.autoFillInHRWidth
)
this.firstphase_height = createUIElement(
html_manip.getHrHeight,
html_manip.autoFillInHRHeight
)
this.cfg = createUIElement(html_manip.getCFG, html_manip.setCFG)
this.denoising_strength = createUIElement(
html_manip.getDenoisingStrength,
html_manip.autoFillInDenoisingStrength
)
this.mask_content = createUIElement(
html_manip.getMaskContent,
html_manip.setMaskContent
)
this.seed = createUIElement(html_manip.getSeed, html_manip.setSeed)
this.prompt = createUIElement(
html_manip.getPrompt,
html_manip.autoFillInPrompt
)
this.negative_prompt = createUIElement(
html_manip.getNegativePrompt,
html_manip.autoFillInNegativePrompt
)
this.mask_blur = createUIElement(
html_manip.getMaskBlur,
html_manip.setMaskBlur
)
this.mask_expansion = createUIElement(
html_manip.getMaskExpansion,
html_manip.setMaskExpansion
)
this.samplers = createUIElement(
html_manip.getCheckedSamplerName,
html_manip.autoFillInSampler
)
this.uiElements = {
// model: null,
// prompt_shortcut: null,
prompt: this.prompt,
negative_prompt: this.negative_prompt,
// selection_mode: null,
batch_size: this.batch_number,
steps: this.steps,
width: this.width,
height: this.height,
firstphase_width: this.firstphase_width,
firstphase_height: this.firstphase_height,
cfg_scale: this.cfg,
denoising_strength: this.denoising_strength,
// hi_res_denoising_strength:0.7,
mask_blur: this.mask_blur,
mask_expansion: this.mask_expansion,
// inpaint_at_full_res: false,
// hi_res_fix:false,
// inpaint_padding:0,
seed: this.seed,
sampler_index: this.samplers,
mask_content: this.mask_content,
}
}
autoFillInSettings(settings) {
for (const [name, value] of Object.entries(settings)) {
if (this.uiElements.hasOwnProperty(name) && value) {
//get the values for debugging
const old_value = this.uiElements[name].getValue()
console.log(
'(name,old_value) => newValue:',
name,
old_value,
value
)
//set the value
this.uiElements[name].setValue(value)
}
}
}
getSettings() {
let settings = {}
for (const [name, ui_element] of Object.entries(this.uiElements)) {
if (ui_element) {
const value = ui_element.getValue()
settings[name] = value
}
}
return settings
}
saveAsJson(json_file_name, settings) {
for (const [name, value] of Object.entries(settings)) {
if (this.uiElements.hasOwnProperty(name) && value) {
//get the values for debugging
const old_value = this.uiElements[name].getValue()
console.log(
'(name,old_value) => newValue:',
name,
old_value,
value
)
//set the value
}
}
}
}
// const ui_settings = new UISettings()
function loadPreset(ui_settings, preset) {
console.log('preset:', preset)
ui_settings.autoFillInSettings(preset)
}
function loadLatentNoiseSettings(ui_settings) {
loadPreset(ui_settings, presets.LatentNoiseSettings)
}
function loadFillSettings(ui_settings) {
loadPreset(ui_settings, presets.FillSettings)
}
function loadOriginalSettings(ui_settings) {
loadPreset(ui_settings, presets.OriginalSettings)
}
async function loadHealBrushSettings(ui_settings) {
document.getElementById('rbModeInpaint').click()
loadPreset(ui_settings, presets.HealBrushSettings)
}
function loadCustomPreset(ui_settings_obj, custom_preset_settings) {
loadPreset(ui_settings_obj, custom_preset_settings)
}
function loadCustomPresetsSettings() {}
async function mapCustomPresetsToLoaders(ui_settings_obj) {
const name_to_settings_obj = await presets.getAllCustomPresetsSettings(
Enum.PresetTypeEnum['SDPreset']
)
const preset_name_to_loader_obj = {}
for (const [preset_name, preset_settings] of Object.entries(
name_to_settings_obj
)) {
preset_name_to_loader_obj[preset_name] = () => {
loadCustomPreset(ui_settings_obj, preset_settings)
}
}
return preset_name_to_loader_obj
}
const g_nativePresets = {
fill: loadFillSettings,
original: loadOriginalSettings,
'latent noise': loadLatentNoiseSettings,
'Heal Brush': loadHealBrushSettings,
}
async function getLoadedPresets(ui_settings_obj) {
let customPresets
customPresets = await mapCustomPresetsToLoaders(ui_settings_obj)
console.log('customPresets: ', customPresets)
let loadedPresets = {
...g_nativePresets,
...customPresets,
}
return loadedPresets
}
let g_ui_settings_object = new UISettings()
function getUISettingsObject() {
return g_ui_settings_object
}
//REFACTOR: move to ui.js
function addPresetMenuItem(preset_title) {
// console.log(model_title,model_name)
const menu_item_element = document.createElement('sp-menu-item')
menu_item_element.className = 'mPresetMenuItem'
menu_item_element.innerHTML = preset_title
// menu_item_element.addEventListener('select',()=>{
// preset_func(g_ui_settings)
// })
return menu_item_element
}
//REFACTOR: move to ui.js
async function populatePresetMenu() {
document.getElementById('mPresetMenu').innerHTML = ''
const divider_elem = document.createElement('sp-menu-divider')
const preset_name = 'Select Smart Preset'
const preset_func = () => {}
const dummy_preset_item = addPresetMenuItem(preset_name, preset_func)
dummy_preset_item.setAttribute('selected', 'selected')
// dummy_preset_item.setAttribute('disabled')
document.getElementById('mPresetMenu').appendChild(dummy_preset_item)
document.getElementById('mPresetMenu').appendChild(divider_elem)
const presets = await getLoadedPresets(g_ui_settings_object)
for ([key, value] of Object.entries(presets)) {
const preset_menu_item = addPresetMenuItem(key, value)
document.getElementById('mPresetMenu').appendChild(preset_menu_item)
}
}
populatePresetMenu()
//REFACTOR: move to preset_tab.js
document
.getElementById('mPresetMenu')
.addEventListener('change', async (evt) => {
const preset_index = evt.target.selectedIndex
const preset_name = evt.target.options[preset_index].textContent
const presets = await getLoadedPresets(g_ui_settings_object)
if (presets.hasOwnProperty(preset_name)) {
const loader = presets[preset_name]
if (loader.constructor.name === 'AsyncFunction') {
await loader(g_ui_settings_object)
} else {
loader(g_ui_settings_object)
}
}
})
module.exports = {
UI,
UIElement,
UISettings,
loadLatentNoiseSettings,
loadFillSettings,
loadHealBrushSettings,
getLoadedPresets,
getUISettingsObject,
populatePresetMenu,
}