Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: canvas v2 #6771

Merged
merged 678 commits into from
Sep 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
678 commits
Select commit Hold shift + click to select a range
62eb00a
feat(ui): rework settings menu
psychedelicious Aug 22, 2024
fef70fd
fix(ui): memory leak when getting image DTO
psychedelicious Aug 22, 2024
5ba15d0
feat(ui): add canvas autosave checkbox
psychedelicious Aug 22, 2024
70bcca2
feat(ui): rough out canvas mode
psychedelicious Aug 22, 2024
9badbb8
feat(ui): transform tool ux
psychedelicious Aug 22, 2024
4b65d91
tidy(ui): removed unused transform methods from canvasmanager
psychedelicious Aug 22, 2024
90b3ebb
feat(ui): add SyncableMap
psychedelicious Aug 22, 2024
76bc2cf
feat(ui): canvas layer preview, revised reactivity for adapters
psychedelicious Aug 23, 2024
d32526f
feat(ui): refine canvas entity list items & menus
psychedelicious Aug 23, 2024
7b1a533
tidy(ui): reduce use of `parseify` util
psychedelicious Aug 23, 2024
bb4eb70
tidy(ui): remove unused stuff
psychedelicious Aug 23, 2024
f628b8a
tidy(ui): remove unused stuff 2
psychedelicious Aug 23, 2024
f8d4d5e
feat(ui): use unique id for metadata in Graph class
psychedelicious Aug 23, 2024
aa4be01
feat(ui): revise graph building for control layers, fix issues w/ inv…
psychedelicious Aug 23, 2024
f47e1af
tidy(ui): remove unused pkg @chakra-ui/react-use-size
psychedelicious Aug 23, 2024
f4e3f87
tidy(ui): remove unused stuff 3
psychedelicious Aug 23, 2024
05052fd
tidy(ui): remove unused stuff 4
psychedelicious Aug 23, 2024
68bf445
chore(ui): eslint
psychedelicious Aug 23, 2024
ab7b9c4
chore(ui): prettier
psychedelicious Aug 23, 2024
5797797
chore(ui): lint
psychedelicious Aug 23, 2024
87150b7
feat(ui): add log debug button
psychedelicious Aug 23, 2024
bc8bf98
feat(ui): update entity list menu
psychedelicious Aug 23, 2024
51cd435
tidy(ui): regional guidance buttons
psychedelicious Aug 23, 2024
cff871e
tidy(ui): "eye dropper" -> "color picker"
psychedelicious Aug 23, 2024
66424c3
feat(ui): fix delete layer hotkey
psychedelicious Aug 23, 2024
9486c50
fix(ui): select next entity in the list when deleting
psychedelicious Aug 23, 2024
e826f8a
fix(ui): sdxl graph builder
psychedelicious Aug 23, 2024
e0e8165
fix(ui): upscale tab graph
psychedelicious Aug 23, 2024
18d9263
tidy(ui): more cleanup
psychedelicious Aug 23, 2024
64f7c7b
fix(ui): staging area actions
psychedelicious Aug 23, 2024
84aa2b9
fix(ui): staging area interaction scopes
psychedelicious Aug 23, 2024
c069981
chore(ui): lint
psychedelicious Aug 23, 2024
9b1ee63
fix(ui): rip out broken recall logic, NO TS ERRORS
psychedelicious Aug 23, 2024
2ca5aed
feat(ui): use singleton for clear q confirm dialog
psychedelicious Aug 23, 2024
143c47c
tidy(app): clean up app changes for canvas v2
psychedelicious Aug 23, 2024
4f9c4f7
chore(ui): typegen
psychedelicious Aug 23, 2024
da5b99c
feat(ui): tweak layout of staging area toolbar
psychedelicious Aug 23, 2024
f355d90
fix(ui): filter preview offset
psychedelicious Aug 23, 2024
5ea3c11
feat(ui): disable most interaction while filtering
psychedelicious Aug 23, 2024
7c68b88
chore: bump version v4.2.9.dev20240823
psychedelicious Aug 23, 2024
a040d1d
fix(ui): new rectangles don't trigger rerender
psychedelicious Aug 23, 2024
20a0ed8
feat(ui): colored mask preview image
psychedelicious Aug 23, 2024
9b8d814
feat(ui): better color picker
psychedelicious Aug 24, 2024
6cbaf7e
fix(ui): calculate renderable entities correctly in tool module
psychedelicious Aug 24, 2024
12a00de
fix(ui): color picker ignores alpha
psychedelicious Aug 24, 2024
a22bf4c
feat(ui): add crosshair to color picker
psychedelicious Aug 24, 2024
e013aff
fix(ui): newly-added entities are selected
psychedelicious Aug 24, 2024
775353f
fix(ui): extraneous entity preview updates
psychedelicious Aug 24, 2024
e696032
feat(nodes): CanvasV2MaskAndCropInvocation can paste generated image …
psychedelicious Aug 24, 2024
44b8480
chore(ui): typegen
psychedelicious Aug 24, 2024
03b3139
feat(ui): paste canvas gens back on source in generate mode
psychedelicious Aug 24, 2024
ee94b0c
feat(ui): autocomplete on getPrefixeId
psychedelicious Aug 24, 2024
86a5e25
feat(ui): duplicate entity
psychedelicious Aug 24, 2024
51663c5
feat(ui): add knipignore tag
psychedelicious Aug 24, 2024
bc75b02
fix(ui): lint & fix issues with adding regional ip adapters
psychedelicious Aug 24, 2024
b91f79b
chore: release v4.2.9.dev20240824
psychedelicious Aug 24, 2024
a5e2e78
feat(ui): add Result type & helpers
psychedelicious Aug 24, 2024
112d6ea
fix(ui): graph building issue w/ controlnet
psychedelicious Aug 24, 2024
4b488de
feat(ui): use new Result utils for enqueueing
psychedelicious Aug 24, 2024
839248c
chore: release v4.2.9.dev3
psychedelicious Aug 24, 2024
af638cf
fix(ui): missing vae precision in graph builders
psychedelicious Aug 24, 2024
8a56702
chore(ui): bump @invoke-ai/ui-library
psychedelicious Aug 24, 2024
8d0a75c
feat(ui): add context menu to entity list
psychedelicious Aug 24, 2024
a733d72
fix(ui): scaled bbox loses sync
psychedelicious Aug 25, 2024
b4d0165
fix(ui): color picker resets brush opacity
psychedelicious Aug 25, 2024
72f304b
feat(ui): move events into modules who care about them
psychedelicious Aug 26, 2024
463f3db
feat(ui): normalize all actions to accept an entityIdentifier
psychedelicious Aug 26, 2024
9480691
feat(ui): move ephemeral state into canvas classes
psychedelicious Aug 26, 2024
85eff56
feat(ui): move selected tool and tool buffer out of redux
psychedelicious Aug 26, 2024
ff8bc93
feat(ui): add CanvasModuleBase class to standardize canvas APIs
psychedelicious Aug 26, 2024
6b75ea3
feat(ui): split out params/compositing state from canvas rendering state
psychedelicious Aug 26, 2024
2b1e930
feat(ui): split out tool state from canvas rendering state
psychedelicious Aug 26, 2024
a07346b
feat(ui): split out settings state from canvas rendering state
psychedelicious Aug 26, 2024
4670f82
feat(ui): split out session state from canvas rendering state
psychedelicious Aug 26, 2024
a33d1b9
feat(ui): split out loras state from canvas rendering state
psychedelicious Aug 26, 2024
9056f44
fix(ui): handle error from internal konva method
psychedelicious Aug 26, 2024
36604f7
chore: release v4.2.9.dev4
psychedelicious Aug 26, 2024
04d4108
feat(ui): rough out undo/redo on canvas
psychedelicious Aug 27, 2024
fe672ba
perf(ui): optimize all selectors 1
psychedelicious Aug 27, 2024
d209652
perf(ui): optimize all selectors 2
psychedelicious Aug 27, 2024
e32fa8b
fix(ui): canvas entity opacity scale
psychedelicious Aug 27, 2024
0e31cca
fix(ui): dnd image count
psychedelicious Aug 27, 2024
4354cd7
tidy(ui): move all undoable reducers back to canvas slice
psychedelicious Aug 27, 2024
77125be
feat(ui): tuned canvas undo/redo
psychedelicious Aug 27, 2024
11bc318
tidy(ui): rename some classes to be consistent
psychedelicious Aug 27, 2024
c74b130
feat(ui): collapsible entity groups
psychedelicious Aug 27, 2024
478daf8
feat(ui): iterate on layer actions
psychedelicious Aug 27, 2024
97414f1
feat(ui): implement interaction locking on layers
psychedelicious Aug 27, 2024
b69b001
feat(ui): generalize mask fill, add to action bar
psychedelicious Aug 27, 2024
69d1edc
chore(ui): lint
psychedelicious Aug 27, 2024
c1a039e
chore: release v4.2.9.dev5
psychedelicious Aug 27, 2024
ec9fdac
fix(ui): randomize seed toggle linked to prompt concat
psychedelicious Aug 27, 2024
1497afc
tidy(ui): use helper to sync scaled bbox size on model change
psychedelicious Aug 27, 2024
1749abb
feat(ui): add flip & reset to transform
psychedelicious Aug 27, 2024
f4a031a
feat(ui): tweak filter styling
psychedelicious Aug 27, 2024
d6b8cb9
feat(ui): tweak enabled/locked toggle styles
psychedelicious Aug 27, 2024
697c81b
feat(ui): tweak regional prompt box styles
psychedelicious Aug 27, 2024
784a615
fix(ui): layer preview image sometimes not rendering
psychedelicious Aug 27, 2024
931a4dd
fix(ui): disable opacity slider fully when no valid entity selected
psychedelicious Aug 27, 2024
5abad87
revert(ui): roll back flip, doesn't work with rotate yet
psychedelicious Aug 28, 2024
a99ff46
fix(ui): opacity reset value incorrect
psychedelicious Aug 28, 2024
61f9ba5
feat(ui): revised viewer toggle @joshistoast
psychedelicious Aug 28, 2024
a8079e5
feat(ui): tidy canvas toolbar buttons
psychedelicious Aug 28, 2024
93b9792
fix(ui): transparency effect not updating
psychedelicious Aug 28, 2024
eeca521
feat(ui): fix queue item count badge positioning
psychedelicious Aug 28, 2024
2df0056
perf(ui): disable `useInert` on modals
psychedelicious Aug 28, 2024
be58b03
feat(ui): split settings modal
psychedelicious Aug 28, 2024
db0b97c
fix(ui): unnecessary z-index on invoke button
psychedelicious Aug 28, 2024
4463e6d
fix(app): node_pack not added to openapi schema correctly
psychedelicious Aug 28, 2024
4129cdd
chore(ui): typegen
psychedelicious Aug 28, 2024
28feb01
fix(ui): schema parsing now that node_pack is guaranteed to be present
psychedelicious Aug 28, 2024
ac34957
feat(ui): migrate add node popover to cmdk
psychedelicious Aug 28, 2024
42c7dde
chore: release v4.2.9.dev6
psychedelicious Aug 28, 2024
79168b6
chore(ui): lint
psychedelicious Aug 28, 2024
a95fbfe
fix(ui): pending node connection stuck
psychedelicious Aug 28, 2024
300ecd9
chore: release v4.2.9.dev7
psychedelicious Aug 28, 2024
cd2a80c
fix(ui): add node cmdk only enabled on workflows tab
psychedelicious Aug 28, 2024
e57ee8d
fix(ui): queue count badge positioning
psychedelicious Aug 28, 2024
e3c0c63
feat(ui): move canvas undo/redo to hook
psychedelicious Aug 28, 2024
16eede4
fix(ui): floating params panel invoke button loading state
psychedelicious Aug 28, 2024
057b5ec
fix(ui): more fiddly queue count layout stuff
psychedelicious Aug 28, 2024
86d10ca
feat(ui): do not select layer on staging accept
psychedelicious Aug 28, 2024
ce4948e
feat(ui): tweak brush fill UI
psychedelicious Aug 28, 2024
cfa22b3
feat(ui): add + buttons to entity categories
psychedelicious Aug 29, 2024
913912d
feat(ui): add delete button to each layer
psychedelicious Aug 29, 2024
79d7f02
feat(ui): restore context menu for entity list
psychedelicious Aug 29, 2024
1a5dc20
feat(ui): tweak add entity button layout
psychedelicious Aug 29, 2024
f078e32
feat(ui): alt quick switches to color picker
psychedelicious Aug 29, 2024
b0414a8
tidy(ui): ViewerToggleMenu -> ViewerToggle
psychedelicious Aug 29, 2024
9ced9ef
feat(app): add `destination` column to `session_queue`
psychedelicious Aug 29, 2024
14dea8b
chore(ui): typegen
psychedelicious Aug 29, 2024
87bc3f5
feat(ui): revise generation mode logic
psychedelicious Aug 29, 2024
a0be7c4
chore: release v4.2.9.dev8
psychedelicious Aug 29, 2024
87b2947
chore(ui): lint
psychedelicious Aug 29, 2024
908f411
feat(ui): remove unused `asPreview` for `StageComponent`
psychedelicious Aug 29, 2024
ad7919b
feat(ui): restore minimal HUD
psychedelicious Aug 29, 2024
e911491
fix(ui): incorrect batch origin preventing progress/staging
psychedelicious Aug 29, 2024
70e27d6
fix(ui): staging hotkeys enabled at wrong times
psychedelicious Aug 29, 2024
5512f80
tidy(ui): organise tool module
psychedelicious Aug 29, 2024
28db39a
fix(ui): context menu doesn't work for new entities
psychedelicious Aug 30, 2024
221c51b
fix(ui): correct labels for generation tab origin
psychedelicious Aug 30, 2024
5126ec1
fix(ui): modals not staying open
psychedelicious Aug 30, 2024
6096c8e
fix(ui): fix getRectUnion util, add some tests
psychedelicious Aug 30, 2024
fd6de78
feat(ui): add save to gallery button
psychedelicious Aug 30, 2024
c9e396b
fix(ui): canvasToBlob not raising error correctly
psychedelicious Aug 30, 2024
fa80452
fix(ui): save to gallery rect too large
psychedelicious Aug 30, 2024
d5e5cae
feat(ui): add merge visible for raster and inpaint mask layers
psychedelicious Aug 30, 2024
d11251f
fix(ui): entity opacity number input focus prevents slider from opening
psychedelicious Aug 30, 2024
33d25c7
chore: release v4.2.9.dev9
psychedelicious Aug 30, 2024
243e7c9
fix(ui): entity groups not collapsing
psychedelicious Aug 30, 2024
6f85743
feat(ui): remove entity list context menu (again)
psychedelicious Aug 30, 2024
f4e8799
chore: release v4.2.9.dev10
psychedelicious Aug 30, 2024
b1673b9
fix(ui): correctly set last cursor pos to null
psychedelicious Aug 30, 2024
fd7f005
fix(ui): reject on dataURLToImageData
psychedelicious Aug 30, 2024
9cd5107
feat(ui): split canvas tool previews into modules
psychedelicious Aug 31, 2024
fd22ff7
feat(ui): revised canvas module base class
psychedelicious Sep 1, 2024
b24f8e2
docs(ui): docstrings for classes (wip)
psychedelicious Sep 1, 2024
487422a
tidy(ui): misc cleanup
psychedelicious Sep 1, 2024
eb4d447
feat(ui): remove object count from entity title
psychedelicious Sep 1, 2024
0d94a89
tidy(ui): organise files
psychedelicious Sep 1, 2024
58064a1
feat(ui): use default IP adapter when creating IP adapter
psychedelicious Sep 1, 2024
8f6e696
feat(ui): hotkeys for brush/eraser size
psychedelicious Sep 1, 2024
fd6d080
tidy(ui): canvas scale & entity opacity sliders
psychedelicious Sep 1, 2024
cb9d0bc
feat(ui): brush & eraser width ui/ux
psychedelicious Sep 1, 2024
b0eddd1
fix(ui): select nonexistent entity
psychedelicious Sep 1, 2024
874b96c
feat(ui): bbox hotkey is c
psychedelicious Sep 1, 2024
75ecc56
feat(ui): add layer quick switch
psychedelicious Sep 1, 2024
420178c
feat(ui): add alt+[ and alt+] hotkeys to cycle through layers
psychedelicious Sep 1, 2024
2538b34
tidy(ui): canvas hotkey hooks
psychedelicious Sep 1, 2024
d019dbd
feat(ui): "IP Adapter" -> "Global IP Adapter"
psychedelicious Sep 1, 2024
0c3e2c4
feat(ui): "Control Layers" -> "Layers"
psychedelicious Sep 1, 2024
d3c2432
fix(ui): force dims on scaled bbox when manual scaling + locked aspec…
psychedelicious Sep 1, 2024
a4fb8eb
feat(ui): add bookmark for quick switch
psychedelicious Sep 1, 2024
02061fa
chore(ui): lint
psychedelicious Sep 1, 2024
277708d
fix(ui): edge cases in quick switch, simpler logic
psychedelicious Sep 2, 2024
c38b05c
chore(ui): lint
psychedelicious Sep 2, 2024
921ade4
feat(ui): brush preview opacity at 0.5 when drawing on mask
psychedelicious Sep 2, 2024
92c754d
fix(ui): disable merge visible when 1 or fewer layers of type
psychedelicious Sep 2, 2024
1628eb5
tidy(ui): transformer organisation
psychedelicious Sep 2, 2024
4f4eee7
feat(ui): add fit to bbox as transform helper
psychedelicious Sep 2, 2024
618473d
fix(ui): transform should ignore konva filters (e.g. transparency eff…
psychedelicious Sep 2, 2024
2e4a48b
feat(ui): move transformer state to nanostores
psychedelicious Sep 2, 2024
437129c
feat(ui): tweak bookmark verbiage
psychedelicious Sep 2, 2024
44be058
docs(ui): docstrings for $canvasCache
psychedelicious Sep 2, 2024
dbff929
tidy(ui): remove unused $isProcessingTransform atom
psychedelicious Sep 2, 2024
4b75394
feat(ui): streamline manager -> react transform interface
psychedelicious Sep 2, 2024
3ed4cf6
feat(ui): tidy stateApi atoms & add docstrings
psychedelicious Sep 2, 2024
fcacc0f
chore: release v4.2.9.dev11
psychedelicious Sep 2, 2024
397038e
tidy(ui): mark canvas module attrs readonly
psychedelicious Sep 3, 2024
ff12f16
feat(ui): update default logging context path to be string
psychedelicious Sep 3, 2024
bb6b5c4
feat(ui): better types on CanvasStateApiModule.getEntity
psychedelicious Sep 3, 2024
5074c97
feat(ui): tool buttons are only disabled when currently selected
psychedelicious Sep 3, 2024
f7e68ac
feat(ui): clean up tool preview rendering
psychedelicious Sep 3, 2024
6161c71
build(ui): add csstype dev dependency
psychedelicious Sep 3, 2024
7c29caa
tidy(ui): merge tool slice, `sendToCanvas` into settings slice
psychedelicious Sep 3, 2024
3ed85d8
feat(ui): add compositeMaskedRegions setting
psychedelicious Sep 3, 2024
5d089ec
feat(ui): prevent layer interactions when transforming or filtering
psychedelicious Sep 3, 2024
376a626
fix(ui): unable to drag while transforming after switching tools
psychedelicious Sep 3, 2024
5eb9e2b
tidy(ui): disable isDebugging flag on root component
psychedelicious Sep 3, 2024
0a22e6b
feat(ui): clean up unused tool module state
psychedelicious Sep 3, 2024
ad53169
tidy(ui): remove extraneous docstrings
psychedelicious Sep 4, 2024
736fabe
tidy(ui): remove commented code
psychedelicious Sep 4, 2024
6ba78e7
tidy(ui): remove unused id on konva nodes
psychedelicious Sep 4, 2024
73e8837
feat(ui): revise entity rendering flow
psychedelicious Sep 4, 2024
5a30ff6
feat(ui): abstract out CanvasEntityAdapterBase
psychedelicious Sep 4, 2024
200dbbb
tidy(ui): rename some classes to better represent their responsibilities
psychedelicious Sep 4, 2024
34554f8
tidy(ui): remove unnecessary awaits in rendering module
psychedelicious Sep 4, 2024
8266c10
feat(ui): restore size of invoke button
psychedelicious Sep 4, 2024
f1525c2
feat(ui): make rendering methods not need args
psychedelicious Sep 4, 2024
c75a933
feat(ui): background and staging area modules have own store subscrip…
psychedelicious Sep 4, 2024
0b1dc36
fix(ui): handle optimal dimension when resetting canvas
psychedelicious Sep 5, 2024
fe257e3
feat(ui): streamlined state flow
psychedelicious Sep 5, 2024
6e6629a
feat(ui): clean up adapter API
psychedelicious Sep 5, 2024
0bfdd5a
feat(ui): slight layout change for staging area toolbar
psychedelicious Sep 5, 2024
27b00ce
feat(ui): iterate on state flow and rendering
psychedelicious Sep 5, 2024
7888b49
feat(ui): iterate on state flow and rendering 2
psychedelicious Sep 5, 2024
10bba49
chore(ui): lint
psychedelicious Sep 5, 2024
013414e
fix(ui): cancel transform/filter when deleting entity
psychedelicious Sep 5, 2024
07cf580
fix(ui): save to gallery uses auto-add board
psychedelicious Sep 5, 2024
cc9cc62
fix(ui): missing translation
psychedelicious Sep 5, 2024
96786ed
chore: release v4.2.9.dev12
psychedelicious Sep 5, 2024
f96148c
feat(ui): improved transparency effect
psychedelicious Sep 5, 2024
a0ed7ba
fix(ui): filter preview accidentally committed to layer
psychedelicious Sep 5, 2024
c047901
fix(ui): ignore Konva filters when previewing filter
psychedelicious Sep 6, 2024
c4b9ba8
feat(ui): use black bg when rasterizing control images
psychedelicious Sep 6, 2024
5a69b62
fix(ui): scaled size not correctly reset when canvas reset
psychedelicious Sep 6, 2024
f6a703c
feat(app): cancel by destination, not origin
psychedelicious Sep 6, 2024
1dd521a
chore(ui): typegen
psychedelicious Sep 6, 2024
615b09d
feat(ui): cancel by destination, not origin
psychedelicious Sep 6, 2024
dce488c
fix(ui): ignore filters when calculating bbox
psychedelicious Sep 6, 2024
b193bc7
feat(ui): inverted shift behavior for transformer
psychedelicious Sep 6, 2024
63a2b6c
fix(ui): transformer rendered behind layer objects
psychedelicious Sep 6, 2024
8cb1584
feat(ui): restore aspect ratio preview component
psychedelicious Sep 6, 2024
788e03f
feat(ui): reworked image context menu
psychedelicious Sep 6, 2024
ce93fdd
chore(ui): lint
psychedelicious Sep 6, 2024
5a251a4
feat(ui): fit bbox to stage on canvas reset
psychedelicious Sep 6, 2024
ea19390
feat(ui): revised entity list action bars
psychedelicious Sep 6, 2024
81060ee
feat(ui): filter UI layout
psychedelicious Sep 6, 2024
640af85
fix(ui): do not save filtered previews to gallery
psychedelicious Sep 6, 2024
3e3e00b
fix(ui): prevent stage scale/size from being invalid
psychedelicious Sep 6, 2024
c0db830
feat(ui): do not allow transform, filter or merge while staging
psychedelicious Sep 6, 2024
3c5bf48
feat(ui): do not allow invoke while transforming or filtering
psychedelicious Sep 6, 2024
c57966e
fix(ui): tidy incorrect component name
psychedelicious Sep 6, 2024
f326bfe
feat(ui): add fit bbox to layers
psychedelicious Sep 6, 2024
2b9f9f3
feat(ui): move delete entity button down to entity list item
psychedelicious Sep 6, 2024
2f98c87
feat(ui): use plurals for entity group header hidden tooltip
psychedelicious Sep 6, 2024
918ed5c
feat(ui): tweak padding on entity group header
psychedelicious Sep 6, 2024
d434e80
chore(ui): lint
psychedelicious Sep 6, 2024
d421eae
feat(ui): move seed out of advanced, hide HRF settings
psychedelicious Sep 6, 2024
f8dadc8
chore: release v5.0.0.dev13
psychedelicious Sep 6, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
16 changes: 16 additions & 0 deletions invokeai/app/api/routers/session_queue.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
Batch,
BatchStatus,
CancelByBatchIDsResult,
CancelByDestinationResult,
ClearResult,
EnqueueBatchResult,
PruneResult,
Expand Down Expand Up @@ -105,6 +106,21 @@ async def cancel_by_batch_ids(
return ApiDependencies.invoker.services.session_queue.cancel_by_batch_ids(queue_id=queue_id, batch_ids=batch_ids)


@session_queue_router.put(
"/{queue_id}/cancel_by_destination",
operation_id="cancel_by_destination",
responses={200: {"model": CancelByBatchIDsResult}},
)
async def cancel_by_destination(
queue_id: str = Path(description="The queue id to perform this operation on"),
destination: str = Query(description="The destination to cancel all queue items for"),
) -> CancelByDestinationResult:
"""Immediately cancels all queue items with the given origin"""
return ApiDependencies.invoker.services.session_queue.cancel_by_destination(
queue_id=queue_id, destination=destination
)


@session_queue_router.put(
"/{queue_id}/clear",
operation_id="clear",
Expand Down
54 changes: 23 additions & 31 deletions invokeai/app/invocations/baseinvocation.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
Type,
TypeVar,
Union,
cast,
)

import semver
Expand Down Expand Up @@ -80,7 +79,7 @@ class UIConfigBase(BaseModel):
version: str = Field(
description='The node\'s version. Should be a valid semver string e.g. "1.0.0" or "3.8.13".',
)
node_pack: Optional[str] = Field(default=None, description="Whether or not this is a custom node")
node_pack: str = Field(description="The node pack that this node belongs to, will be 'invokeai' for built-in nodes")
classification: Classification = Field(default=Classification.Stable, description="The node's classification")

model_config = ConfigDict(
Expand Down Expand Up @@ -230,18 +229,16 @@ def get_output_annotation(cls) -> BaseInvocationOutput:
@staticmethod
def json_schema_extra(schema: dict[str, Any], model_class: Type[BaseInvocation]) -> None:
"""Adds various UI-facing attributes to the invocation's OpenAPI schema."""
uiconfig = cast(UIConfigBase | None, getattr(model_class, "UIConfig", None))
if uiconfig is not None:
if uiconfig.title is not None:
schema["title"] = uiconfig.title
if uiconfig.tags is not None:
schema["tags"] = uiconfig.tags
if uiconfig.category is not None:
schema["category"] = uiconfig.category
if uiconfig.node_pack is not None:
schema["node_pack"] = uiconfig.node_pack
schema["classification"] = uiconfig.classification
schema["version"] = uiconfig.version
if title := model_class.UIConfig.title:
schema["title"] = title
if tags := model_class.UIConfig.tags:
schema["tags"] = tags
if category := model_class.UIConfig.category:
schema["category"] = category
if node_pack := model_class.UIConfig.node_pack:
schema["node_pack"] = node_pack
schema["classification"] = model_class.UIConfig.classification
schema["version"] = model_class.UIConfig.version
if "required" not in schema or not isinstance(schema["required"], list):
schema["required"] = []
schema["class"] = "invocation"
Expand Down Expand Up @@ -312,7 +309,7 @@ def invoke_internal(self, context: InvocationContext, services: "InvocationServi
json_schema_extra={"field_kind": FieldKind.NodeAttribute},
)

UIConfig: ClassVar[Type[UIConfigBase]]
UIConfig: ClassVar[UIConfigBase]

model_config = ConfigDict(
protected_namespaces=(),
Expand Down Expand Up @@ -441,30 +438,25 @@ def wrapper(cls: Type[TBaseInvocation]) -> Type[TBaseInvocation]:
validate_fields(cls.model_fields, invocation_type)

# Add OpenAPI schema extras
uiconfig_name = cls.__qualname__ + ".UIConfig"
if not hasattr(cls, "UIConfig") or cls.UIConfig.__qualname__ != uiconfig_name:
cls.UIConfig = type(uiconfig_name, (UIConfigBase,), {})
cls.UIConfig.title = title
cls.UIConfig.tags = tags
cls.UIConfig.category = category
cls.UIConfig.classification = classification

# Grab the node pack's name from the module name, if it's a custom node
is_custom_node = cls.__module__.rsplit(".", 1)[0] == "invokeai.app.invocations"
if is_custom_node:
cls.UIConfig.node_pack = cls.__module__.split(".")[0]
else:
cls.UIConfig.node_pack = None
uiconfig: dict[str, Any] = {}
uiconfig["title"] = title
uiconfig["tags"] = tags
uiconfig["category"] = category
uiconfig["classification"] = classification
# The node pack is the module name - will be "invokeai" for built-in nodes
uiconfig["node_pack"] = cls.__module__.split(".")[0]

if version is not None:
try:
semver.Version.parse(version)
except ValueError as e:
raise InvalidVersionError(f'Invalid version string for node "{invocation_type}": "{version}"') from e
cls.UIConfig.version = version
uiconfig["version"] = version
else:
logger.warn(f'No version specified for node "{invocation_type}", using "1.0.0"')
cls.UIConfig.version = "1.0.0"
uiconfig["version"] = "1.0.0"

cls.UIConfig = UIConfigBase(**uiconfig)

if use_cache is not None:
cls.model_fields["use_cache"].default = use_cache
Expand Down
67 changes: 66 additions & 1 deletion invokeai/app/invocations/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,19 @@
import numpy
from PIL import Image, ImageChops, ImageFilter, ImageOps

from invokeai.app.invocations.baseinvocation import BaseInvocation, Classification, invocation
from invokeai.app.invocations.baseinvocation import (
BaseInvocation,
Classification,
invocation,
invocation_output,
)
from invokeai.app.invocations.constants import IMAGE_MODES
from invokeai.app.invocations.fields import (
ColorField,
FieldDescriptions,
ImageField,
InputField,
OutputField,
WithBoard,
WithMetadata,
)
Expand Down Expand Up @@ -1007,3 +1013,62 @@ def invoke(self, context: InvocationContext) -> ImageOutput:
image_dto = context.images.save(image=mask, image_category=ImageCategory.MASK)

return ImageOutput.build(image_dto)


@invocation_output("canvas_v2_mask_and_crop_output")
class CanvasV2MaskAndCropOutput(ImageOutput):
offset_x: int = OutputField(description="The x offset of the image, after cropping")
offset_y: int = OutputField(description="The y offset of the image, after cropping")


@invocation(
"canvas_v2_mask_and_crop",
title="Canvas V2 Mask and Crop",
tags=["image", "mask", "id"],
category="image",
version="1.0.0",
classification=Classification.Prototype,
)
class CanvasV2MaskAndCropInvocation(BaseInvocation, WithMetadata, WithBoard):
"""Handles Canvas V2 image output masking and cropping"""

source_image: ImageField | None = InputField(
default=None,
description="The source image onto which the masked generated image is pasted. If omitted, the masked generated image is returned with transparency.",
)
generated_image: ImageField = InputField(description="The image to apply the mask to")
mask: ImageField = InputField(description="The mask to apply")
mask_blur: int = InputField(default=0, ge=0, description="The amount to blur the mask by")

def _prepare_mask(self, mask: Image.Image) -> Image.Image:
mask_array = numpy.array(mask)
kernel = numpy.ones((self.mask_blur, self.mask_blur), numpy.uint8)
dilated_mask_array = cv2.erode(mask_array, kernel, iterations=3)
dilated_mask = Image.fromarray(dilated_mask_array)
if self.mask_blur > 0:
mask = dilated_mask.filter(ImageFilter.GaussianBlur(self.mask_blur))
return ImageOps.invert(mask.convert("L"))

def invoke(self, context: InvocationContext) -> CanvasV2MaskAndCropOutput:
mask = self._prepare_mask(context.images.get_pil(self.mask.image_name))

if self.source_image:
generated_image = context.images.get_pil(self.generated_image.image_name)
source_image = context.images.get_pil(self.source_image.image_name)
source_image.paste(generated_image, (0, 0), mask)
image_dto = context.images.save(image=source_image)
else:
generated_image = context.images.get_pil(self.generated_image.image_name)
generated_image.putalpha(mask)
image_dto = context.images.save(image=generated_image)

# bbox = image.getbbox()
# image = image.crop(bbox)

return CanvasV2MaskAndCropOutput(
image=ImageField(image_name=image_dto.image_name),
offset_x=0,
offset_y=0,
width=image_dto.width,
height=image_dto.height,
)
16 changes: 14 additions & 2 deletions invokeai/app/services/events/events_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,15 +88,15 @@ class QueueItemEventBase(QueueEventBase):

item_id: int = Field(description="The ID of the queue item")
batch_id: str = Field(description="The ID of the queue batch")
origin: str | None = Field(default=None, description="The origin of the queue item")
destination: str | None = Field(default=None, description="The destination of the queue item")


class InvocationEventBase(QueueItemEventBase):
"""Base class for invocation events"""

session_id: str = Field(description="The ID of the session (aka graph execution state)")
queue_id: str = Field(description="The ID of the queue")
item_id: int = Field(description="The ID of the queue item")
batch_id: str = Field(description="The ID of the queue batch")
session_id: str = Field(description="The ID of the session (aka graph execution state)")
invocation: AnyInvocation = Field(description="The ID of the invocation")
invocation_source_id: str = Field(description="The ID of the prepared invocation's source node")
Expand All @@ -114,6 +114,8 @@ def build(cls, queue_item: SessionQueueItem, invocation: AnyInvocation) -> "Invo
queue_id=queue_item.queue_id,
item_id=queue_item.item_id,
batch_id=queue_item.batch_id,
origin=queue_item.origin,
destination=queue_item.destination,
session_id=queue_item.session_id,
invocation=invocation,
invocation_source_id=queue_item.session.prepared_source_mapping[invocation.id],
Expand Down Expand Up @@ -147,6 +149,8 @@ def build(
queue_id=queue_item.queue_id,
item_id=queue_item.item_id,
batch_id=queue_item.batch_id,
origin=queue_item.origin,
destination=queue_item.destination,
session_id=queue_item.session_id,
invocation=invocation,
invocation_source_id=queue_item.session.prepared_source_mapping[invocation.id],
Expand Down Expand Up @@ -184,6 +188,8 @@ def build(
queue_id=queue_item.queue_id,
item_id=queue_item.item_id,
batch_id=queue_item.batch_id,
origin=queue_item.origin,
destination=queue_item.destination,
session_id=queue_item.session_id,
invocation=invocation,
invocation_source_id=queue_item.session.prepared_source_mapping[invocation.id],
Expand Down Expand Up @@ -216,6 +222,8 @@ def build(
queue_id=queue_item.queue_id,
item_id=queue_item.item_id,
batch_id=queue_item.batch_id,
origin=queue_item.origin,
destination=queue_item.destination,
session_id=queue_item.session_id,
invocation=invocation,
invocation_source_id=queue_item.session.prepared_source_mapping[invocation.id],
Expand Down Expand Up @@ -253,6 +261,8 @@ def build(
queue_id=queue_item.queue_id,
item_id=queue_item.item_id,
batch_id=queue_item.batch_id,
origin=queue_item.origin,
destination=queue_item.destination,
session_id=queue_item.session_id,
status=queue_item.status,
error_type=queue_item.error_type,
Expand All @@ -279,12 +289,14 @@ class BatchEnqueuedEvent(QueueEventBase):
description="The number of invocations initially requested to be enqueued (may be less than enqueued if queue was full)"
)
priority: int = Field(description="The priority of the batch")
origin: str | None = Field(default=None, description="The origin of the batch")

@classmethod
def build(cls, enqueue_result: EnqueueBatchResult) -> "BatchEnqueuedEvent":
return cls(
queue_id=enqueue_result.queue_id,
batch_id=enqueue_result.batch.batch_id,
origin=enqueue_result.batch.origin,
enqueued=enqueue_result.enqueued,
requested=enqueue_result.requested,
priority=enqueue_result.priority,
Expand Down
6 changes: 6 additions & 0 deletions invokeai/app/services/session_queue/session_queue_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
Batch,
BatchStatus,
CancelByBatchIDsResult,
CancelByDestinationResult,
CancelByQueueIDResult,
ClearResult,
EnqueueBatchResult,
Expand Down Expand Up @@ -95,6 +96,11 @@ def cancel_by_batch_ids(self, queue_id: str, batch_ids: list[str]) -> CancelByBa
"""Cancels all queue items with matching batch IDs"""
pass

@abstractmethod
def cancel_by_destination(self, queue_id: str, destination: str) -> CancelByDestinationResult:
"""Cancels all queue items with the given batch destination"""
pass

@abstractmethod
def cancel_by_queue_id(self, queue_id: str) -> CancelByQueueIDResult:
"""Cancels all queue items with matching queue ID"""
Expand Down
28 changes: 28 additions & 0 deletions invokeai/app/services/session_queue/session_queue_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,14 @@ class BatchDatum(BaseModel):

class Batch(BaseModel):
batch_id: str = Field(default_factory=uuid_string, description="The ID of the batch")
origin: str | None = Field(
default=None,
description="The origin of this queue item. This data is used by the frontend to determine how to handle results.",
)
destination: str | None = Field(
default=None,
description="The origin of this queue item. This data is used by the frontend to determine how to handle results",
)
data: Optional[BatchDataCollection] = Field(default=None, description="The batch data collection.")
graph: Graph = Field(description="The graph to initialize the session with")
workflow: Optional[WorkflowWithoutID] = Field(
Expand Down Expand Up @@ -195,6 +203,14 @@ class SessionQueueItemWithoutGraph(BaseModel):
status: QUEUE_ITEM_STATUS = Field(default="pending", description="The status of this queue item")
priority: int = Field(default=0, description="The priority of this queue item")
batch_id: str = Field(description="The ID of the batch associated with this queue item")
origin: str | None = Field(
default=None,
description="The origin of this queue item. This data is used by the frontend to determine how to handle results.",
)
destination: str | None = Field(
default=None,
description="The origin of this queue item. This data is used by the frontend to determine how to handle results",
)
session_id: str = Field(
description="The ID of the session associated with this queue item. The session doesn't exist in graph_executions until the queue item is executed."
)
Expand Down Expand Up @@ -294,6 +310,8 @@ class SessionQueueStatus(BaseModel):
class BatchStatus(BaseModel):
queue_id: str = Field(..., description="The ID of the queue")
batch_id: str = Field(..., description="The ID of the batch")
origin: str | None = Field(..., description="The origin of the batch")
destination: str | None = Field(..., description="The destination of the batch")
pending: int = Field(..., description="Number of queue items with status 'pending'")
in_progress: int = Field(..., description="Number of queue items with status 'in_progress'")
completed: int = Field(..., description="Number of queue items with status 'complete'")
Expand Down Expand Up @@ -328,6 +346,12 @@ class CancelByBatchIDsResult(BaseModel):
canceled: int = Field(..., description="Number of queue items canceled")


class CancelByDestinationResult(CancelByBatchIDsResult):
"""Result of canceling by a destination"""

pass


class CancelByQueueIDResult(CancelByBatchIDsResult):
"""Result of canceling by queue id"""

Expand Down Expand Up @@ -433,6 +457,8 @@ class SessionQueueValueToInsert(NamedTuple):
field_values: Optional[str] # field_values json
priority: int # priority
workflow: Optional[str] # workflow json
origin: str | None
destination: str | None


ValuesToInsert: TypeAlias = list[SessionQueueValueToInsert]
Expand All @@ -453,6 +479,8 @@ def prepare_values_to_insert(queue_id: str, batch: Batch, priority: int, max_new
json.dumps(field_values, default=to_jsonable_python) if field_values else None, # field_values (json)
priority, # priority
json.dumps(workflow, default=to_jsonable_python) if workflow else None, # workflow (json)
batch.origin, # origin
batch.destination, # destination
)
)
return values_to_insert
Expand Down
Loading
Loading