Spaces:
Build error
Build error
Commit
β’
58cb97c
1
Parent(s):
fd46ec1
work in progress
Browse files- package-lock.json +0 -0
- package.json +3 -3
- src/app/main.tsx +31 -18
- src/components/editors/FilterEditor/FilterTree/index.tsx +74 -0
- src/components/editors/FilterEditor/FilterTree/useFilterTree.ts +147 -0
- src/components/editors/FilterEditor/FilterViewer/index.tsx +33 -0
- src/components/editors/FilterEditor/index.tsx +17 -0
- src/components/editors/ProjectEditor/index.tsx +0 -1
- src/components/editors/SegmentEditor/index.tsx +0 -1
- src/components/editors/WorkflowEditor/WorkflowViewer/ReactFlowCanvas/formats/comfyui/types.ts +12 -12
- src/components/editors/WorkflowEditor/WorkflowViewer/ReactFlowCanvas/samples/comfyicu.ts +394 -0
- src/components/editors/WorkflowEditor/WorkflowViewer/index.tsx +1 -1
- src/experiments/grading/types.ts +0 -7
- src/lib/core/constants.ts +1 -1
- src/services/debug.ts +2 -0
- src/services/editors/entity-editor/getDefaultEntityEditorState.ts +2 -1
- src/{experiments/grading β services/editors/filter-editor}/README.md +0 -0
- src/{experiments/grading/applyColorGradingDemo.ts β services/editors/filter-editor/demo.ts} +2 -2
- src/{experiments/grading β services/editors/filter-editor}/filters/DEPRECATED_analogFilm.ts +4 -3
- src/{experiments/grading β services/editors/filter-editor}/filters/analogLens.ts +4 -3
- src/{experiments/grading β services/editors/filter-editor}/filters/cinematic.ts +4 -3
- src/{experiments/grading β services/editors/filter-editor}/filters/colorMapping.ts +4 -3
- src/{experiments/grading β services/editors/filter-editor}/filters/colorTemperature.ts +4 -3
- src/{experiments/grading β services/editors/filter-editor}/filters/crossProcessing.ts +4 -3
- src/{experiments/grading β services/editors/filter-editor}/filters/filmDegradation.ts +4 -3
- src/services/editors/filter-editor/filters/index.ts +137 -0
- src/{experiments/grading β services/editors/filter-editor}/filters/infrared.ts +4 -3
- src/{experiments/grading β services/editors/filter-editor}/filters/lomography.ts +4 -3
- src/{experiments/grading β services/editors/filter-editor}/filters/splitToning.ts +4 -3
- src/{experiments/grading β services/editors/filter-editor}/filters/toneMapping.ts +4 -3
- src/{experiments/grading β services/editors/filter-editor}/filters/vintageFilm.ts +4 -3
- src/services/editors/filter-editor/getDefaultFilterEditorState.ts +29 -0
- src/{experiments/grading/applyColorGrading.ts β services/editors/filter-editor/runFilterPipeline.ts} +9 -8
- src/services/editors/filter-editor/useFilterEditor.ts +52 -0
- src/services/editors/index.ts +1 -0
- src/services/editors/project-editor/getDefaultProjectEditorState.ts +2 -1
- src/services/editors/script-editor/getDefaultScriptEditorState.ts +2 -1
- src/services/editors/segment-editor/getDefaultSegmentEditorState.ts +2 -1
- src/services/editors/workflow-editor/getDefaultWorkflowtEditorState.ts +2 -1
- src/services/index.ts +1 -0
- src/services/plugins/usePlugins.ts +2 -0
package-lock.json
CHANGED
The diff for this file is too large to render.
See raw diff
|
|
package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
{
|
2 |
"name": "clapper",
|
3 |
-
"version": "0.0.
|
4 |
"private": true,
|
5 |
"description": "π¬ Clapper",
|
6 |
"license": "GPL-3.0-only",
|
@@ -38,9 +38,9 @@
|
|
38 |
"dependencies": {
|
39 |
"@aitube/broadway": "0.1.2",
|
40 |
"@aitube/clap": "0.1.2",
|
41 |
-
"@aitube/clapper-services": "0.1.2-
|
42 |
"@aitube/engine": "0.1.2",
|
43 |
-
"@aitube/timeline": "0.1.2-
|
44 |
"@fal-ai/serverless-client": "^0.13.0",
|
45 |
"@ffmpeg/ffmpeg": "^0.12.10",
|
46 |
"@ffmpeg/util": "^0.12.1",
|
|
|
1 |
{
|
2 |
"name": "clapper",
|
3 |
+
"version": "0.0.7",
|
4 |
"private": true,
|
5 |
"description": "π¬ Clapper",
|
6 |
"license": "GPL-3.0-only",
|
|
|
38 |
"dependencies": {
|
39 |
"@aitube/broadway": "0.1.2",
|
40 |
"@aitube/clap": "0.1.2",
|
41 |
+
"@aitube/clapper-services": "0.1.2-14",
|
42 |
"@aitube/engine": "0.1.2",
|
43 |
+
"@aitube/timeline": "0.1.2-3",
|
44 |
"@fal-ai/serverless-client": "^0.13.0",
|
45 |
"@ffmpeg/ffmpeg": "^0.12.10",
|
46 |
"@ffmpeg/util": "^0.12.1",
|
src/app/main.tsx
CHANGED
@@ -26,6 +26,7 @@ import { ScriptEditor } from '@/components/editors/ScriptEditor'
|
|
26 |
import { SegmentEditor } from '@/components/editors/SegmentEditor'
|
27 |
import { EntityEditor } from '@/components/editors/EntityEditor'
|
28 |
import { WorkflowEditor } from '@/components/editors/WorkflowEditor'
|
|
|
29 |
|
30 |
type DroppableThing = { files: File[] }
|
31 |
|
@@ -117,7 +118,7 @@ function MainContent() {
|
|
117 |
<FruityDesktop>
|
118 |
<FruityWindow
|
119 |
id="ScriptEditor"
|
120 |
-
title="
|
121 |
defaultWidth={375}
|
122 |
minWidth={200}
|
123 |
defaultHeight={370}
|
@@ -131,7 +132,7 @@ function MainContent() {
|
|
131 |
|
132 |
<FruityWindow
|
133 |
id="SegmentEditor"
|
134 |
-
title="
|
135 |
defaultWidth={342}
|
136 |
minWidth={200}
|
137 |
defaultHeight={395}
|
@@ -145,7 +146,7 @@ function MainContent() {
|
|
145 |
|
146 |
<FruityWindow
|
147 |
id="EntityEditor"
|
148 |
-
title="
|
149 |
defaultWidth={544}
|
150 |
minWidth={200}
|
151 |
defaultHeight={318}
|
@@ -157,21 +158,33 @@ function MainContent() {
|
|
157 |
<EntityEditor />
|
158 |
</FruityWindow>
|
159 |
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
175 |
|
176 |
<FruityWindow
|
177 |
id="Monitor"
|
|
|
26 |
import { SegmentEditor } from '@/components/editors/SegmentEditor'
|
27 |
import { EntityEditor } from '@/components/editors/EntityEditor'
|
28 |
import { WorkflowEditor } from '@/components/editors/WorkflowEditor'
|
29 |
+
import { FilterEditor } from '@/components/editors/FilterEditor'
|
30 |
|
31 |
type DroppableThing = { files: File[] }
|
32 |
|
|
|
118 |
<FruityDesktop>
|
119 |
<FruityWindow
|
120 |
id="ScriptEditor"
|
121 |
+
title="Screenplay"
|
122 |
defaultWidth={375}
|
123 |
minWidth={200}
|
124 |
defaultHeight={370}
|
|
|
132 |
|
133 |
<FruityWindow
|
134 |
id="SegmentEditor"
|
135 |
+
title="Segments"
|
136 |
defaultWidth={342}
|
137 |
minWidth={200}
|
138 |
defaultHeight={395}
|
|
|
146 |
|
147 |
<FruityWindow
|
148 |
id="EntityEditor"
|
149 |
+
title="Entities"
|
150 |
defaultWidth={544}
|
151 |
minWidth={200}
|
152 |
defaultHeight={318}
|
|
|
158 |
<EntityEditor />
|
159 |
</FruityWindow>
|
160 |
|
161 |
+
<FruityWindow
|
162 |
+
id="WorkflowEditor"
|
163 |
+
title="Workflows"
|
164 |
+
defaultWidth={459}
|
165 |
+
minWidth={200}
|
166 |
+
defaultHeight={351}
|
167 |
+
minHeight={100}
|
168 |
+
defaultX={536}
|
169 |
+
defaultY={3}
|
170 |
+
canBeClosed={false}
|
171 |
+
>
|
172 |
+
<WorkflowEditor />
|
173 |
+
</FruityWindow>
|
174 |
+
|
175 |
+
<FruityWindow
|
176 |
+
id="FilterEditor"
|
177 |
+
title="Filters"
|
178 |
+
defaultWidth={459}
|
179 |
+
minWidth={200}
|
180 |
+
defaultHeight={351}
|
181 |
+
minHeight={100}
|
182 |
+
defaultX={936}
|
183 |
+
defaultY={400}
|
184 |
+
canBeClosed={false}
|
185 |
+
>
|
186 |
+
<FilterEditor />
|
187 |
+
</FruityWindow>
|
188 |
|
189 |
<FruityWindow
|
190 |
id="Monitor"
|
src/components/editors/FilterEditor/FilterTree/index.tsx
ADDED
@@ -0,0 +1,74 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
'use client'
|
2 |
+
|
3 |
+
import { useEffect } from 'react'
|
4 |
+
|
5 |
+
import { cn } from '@/lib/utils'
|
6 |
+
import { isClapEntity } from '@/components/tree-browsers/utils/isSomething'
|
7 |
+
import { TreeNodeItem, LibraryNodeType } from '@/components/tree-browsers/types'
|
8 |
+
import { Tree } from '@/components/core/tree'
|
9 |
+
|
10 |
+
import { useFilterTree } from './useFilterTree'
|
11 |
+
import { useFilterEditor } from '@/services/editors/filter-editor/useFilterEditor'
|
12 |
+
|
13 |
+
export function FilterTree({
|
14 |
+
className = '',
|
15 |
+
}: {
|
16 |
+
className?: string
|
17 |
+
} = {}) {
|
18 |
+
const libraryTreeRoot = useFilterTree((s) => s.libraryTreeRoot)
|
19 |
+
const selectTreeNode = useFilterTree((s) => s.selectTreeNode)
|
20 |
+
const selectedTreeNodeId = useFilterTree((s) => s.selectedTreeNodeId)
|
21 |
+
const setAvailableFilters = useFilterTree((s) => s.setAvailableFilters)
|
22 |
+
|
23 |
+
const availableFilters = useFilterEditor((s) => s.availableFilters)
|
24 |
+
const activeFilters = useFilterEditor((s) => s.activeFilters)
|
25 |
+
const current = useFilterEditor((s) => s.current)
|
26 |
+
|
27 |
+
useEffect(() => {
|
28 |
+
console.log('TODO: populate the filter tree')
|
29 |
+
}, [availableFilters.map((f) => f.id).join(',')])
|
30 |
+
/**
|
31 |
+
* handle click on tree node
|
32 |
+
* yes, this is where the magic happens!
|
33 |
+
*
|
34 |
+
* @param id
|
35 |
+
* @param nodeType
|
36 |
+
* @param node
|
37 |
+
* @returns
|
38 |
+
*/
|
39 |
+
const handleOnChange = async (
|
40 |
+
id: string | null,
|
41 |
+
nodeType?: LibraryNodeType,
|
42 |
+
nodeItem?: TreeNodeItem
|
43 |
+
) => {
|
44 |
+
console.log(`calling selectTreeNodeById(id)`)
|
45 |
+
selectTreeNode(id, nodeType, nodeItem)
|
46 |
+
|
47 |
+
if (!nodeType || !nodeItem) {
|
48 |
+
console.log('tree-browser: clicked on an undefined node')
|
49 |
+
return
|
50 |
+
}
|
51 |
+
if (isClapEntity(nodeType, nodeItem)) {
|
52 |
+
// ClapEntity
|
53 |
+
} else {
|
54 |
+
console.log(
|
55 |
+
`tree-browser: no action attached to ${nodeType}, so skipping`
|
56 |
+
)
|
57 |
+
return
|
58 |
+
}
|
59 |
+
console.log(`tree-browser: clicked on a ${nodeType}`, nodeItem)
|
60 |
+
}
|
61 |
+
|
62 |
+
return (
|
63 |
+
<Tree.Root<LibraryNodeType, TreeNodeItem>
|
64 |
+
value={selectedTreeNodeId}
|
65 |
+
onChange={handleOnChange}
|
66 |
+
className={cn(`not-prose h-full w-full px-2 pt-2`, className)}
|
67 |
+
label="Filters"
|
68 |
+
>
|
69 |
+
{libraryTreeRoot.map((node) => (
|
70 |
+
<Tree.Node node={node} key={node.id} />
|
71 |
+
))}
|
72 |
+
</Tree.Root>
|
73 |
+
)
|
74 |
+
}
|
src/components/editors/FilterEditor/FilterTree/useFilterTree.ts
ADDED
@@ -0,0 +1,147 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
'use client'
|
2 |
+
|
3 |
+
import { create } from 'zustand'
|
4 |
+
import { ClapEntity, UUID } from '@aitube/clap'
|
5 |
+
import { Filter } from '@aitube/clapper-services'
|
6 |
+
|
7 |
+
import {
|
8 |
+
LibraryTreeNode,
|
9 |
+
TreeNodeItem,
|
10 |
+
LibraryNodeType,
|
11 |
+
} from '@/components/tree-browsers/types'
|
12 |
+
import { icons } from '@/components/icons'
|
13 |
+
import {
|
14 |
+
collectionClassName,
|
15 |
+
libraryClassName,
|
16 |
+
} from '@/components/tree-browsers/style/treeNodeStyles'
|
17 |
+
|
18 |
+
export const useFilterTree = create<{
|
19 |
+
availableFiltersLibraryTreeNodeId: string
|
20 |
+
|
21 |
+
// activeFiltersLibraryTreeNodeId: string
|
22 |
+
|
23 |
+
libraryTreeRoot: LibraryTreeNode[]
|
24 |
+
init: () => void
|
25 |
+
|
26 |
+
/**
|
27 |
+
* Load available filters into the tree
|
28 |
+
*
|
29 |
+
* @param collections
|
30 |
+
* @returns
|
31 |
+
*/
|
32 |
+
setAvailableFilters: (filters: Filter[]) => void
|
33 |
+
|
34 |
+
// we support those all selection modes for convenience - please keep them!
|
35 |
+
selectedNodeItem?: TreeNodeItem
|
36 |
+
selectedNodeType?: LibraryNodeType
|
37 |
+
selectTreeNode: (
|
38 |
+
treeNodeId?: string | null,
|
39 |
+
nodeType?: LibraryNodeType,
|
40 |
+
nodeItem?: TreeNodeItem
|
41 |
+
) => void
|
42 |
+
selectedTreeNodeId: string | null
|
43 |
+
}>((set, get) => ({
|
44 |
+
availableFiltersLibraryTreeNodeId: '',
|
45 |
+
|
46 |
+
// activeFiltersLibraryTreeNodeId: '',
|
47 |
+
|
48 |
+
libraryTreeRoot: [],
|
49 |
+
init: () => {
|
50 |
+
const availableFilterLibrary: LibraryTreeNode = {
|
51 |
+
id: UUID(),
|
52 |
+
nodeType: 'TREE_ROOT_PROJECT',
|
53 |
+
label: 'Available filters',
|
54 |
+
icon: icons.project,
|
55 |
+
className: libraryClassName,
|
56 |
+
isExpanded: true,
|
57 |
+
children: [
|
58 |
+
{
|
59 |
+
id: UUID(),
|
60 |
+
nodeType: 'DEFAULT_TREE_NODE_EMPTY',
|
61 |
+
label: 'Empty',
|
62 |
+
icon: icons.project,
|
63 |
+
className: collectionClassName,
|
64 |
+
},
|
65 |
+
],
|
66 |
+
}
|
67 |
+
|
68 |
+
const libraryTreeRoot = [availableFilterLibrary]
|
69 |
+
|
70 |
+
set({
|
71 |
+
availableFiltersLibraryTreeNodeId: availableFilterLibrary.id,
|
72 |
+
libraryTreeRoot,
|
73 |
+
selectedNodeItem: undefined,
|
74 |
+
selectedTreeNodeId: null,
|
75 |
+
})
|
76 |
+
},
|
77 |
+
|
78 |
+
setAvailableFilters: (filters: Filter[]) => {
|
79 |
+
const availableFilterLibrary: LibraryTreeNode = {
|
80 |
+
id: UUID(),
|
81 |
+
nodeType: 'TREE_ROOT_PROJECT',
|
82 |
+
label: 'Filters',
|
83 |
+
icon: icons.project,
|
84 |
+
className: libraryClassName,
|
85 |
+
isExpanded: true,
|
86 |
+
children: [
|
87 |
+
{
|
88 |
+
id: UUID(),
|
89 |
+
nodeType: 'DEFAULT_TREE_NODE_EMPTY',
|
90 |
+
label: 'Empty',
|
91 |
+
icon: icons.project,
|
92 |
+
className: collectionClassName,
|
93 |
+
},
|
94 |
+
],
|
95 |
+
}
|
96 |
+
|
97 |
+
const libraryTreeRoot = [availableFilterLibrary]
|
98 |
+
|
99 |
+
set({
|
100 |
+
availableFiltersLibraryTreeNodeId: availableFilterLibrary.id,
|
101 |
+
libraryTreeRoot,
|
102 |
+
selectedNodeItem: undefined,
|
103 |
+
selectedTreeNodeId: null,
|
104 |
+
})
|
105 |
+
},
|
106 |
+
|
107 |
+
/*
|
108 |
+
setCommunityCollections: (collections: CommunityEntityCollection[]) => {
|
109 |
+
// TODO: implement this
|
110 |
+
|
111 |
+
},
|
112 |
+
*/
|
113 |
+
|
114 |
+
selectedNodeItem: undefined,
|
115 |
+
selectEntity: (entity?: ClapEntity) => {
|
116 |
+
if (entity) {
|
117 |
+
console.log(
|
118 |
+
'TODO julian: change this code to search in the entity collections'
|
119 |
+
)
|
120 |
+
const selectedTreeNode = get().libraryTreeRoot.find(
|
121 |
+
(node) => node.data?.id === entity.id
|
122 |
+
)
|
123 |
+
|
124 |
+
// set({ selectedTreeNode })
|
125 |
+
set({ selectedTreeNodeId: selectedTreeNode?.id || null })
|
126 |
+
set({ selectedNodeItem: entity })
|
127 |
+
} else {
|
128 |
+
// set({ selectedTreeNode: undefined })
|
129 |
+
set({ selectedTreeNodeId: null })
|
130 |
+
set({ selectedNodeItem: undefined })
|
131 |
+
}
|
132 |
+
},
|
133 |
+
|
134 |
+
// selectedTreeNode: undefined,
|
135 |
+
selectedTreeNodeId: null,
|
136 |
+
selectTreeNode: (
|
137 |
+
treeNodeId?: string | null,
|
138 |
+
nodeType?: LibraryNodeType,
|
139 |
+
nodeItem?: TreeNodeItem
|
140 |
+
) => {
|
141 |
+
set({ selectedTreeNodeId: treeNodeId ? treeNodeId : undefined })
|
142 |
+
set({ selectedNodeType: nodeType ? nodeType : undefined })
|
143 |
+
set({ selectedNodeItem: nodeItem ? nodeItem : undefined })
|
144 |
+
},
|
145 |
+
}))
|
146 |
+
|
147 |
+
useFilterTree.getState().init()
|
src/components/editors/FilterEditor/FilterViewer/index.tsx
ADDED
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { FormSection } from '@/components/forms'
|
2 |
+
import { useFilterEditor, useUI } from '@/services'
|
3 |
+
|
4 |
+
export function FilterViewer() {
|
5 |
+
const current = useFilterEditor((s) => s.current)
|
6 |
+
const setCurrent = useFilterEditor((s) => s.setCurrent)
|
7 |
+
const undo = useFilterEditor((s) => s.undo)
|
8 |
+
const redo = useFilterEditor((s) => s.redo)
|
9 |
+
|
10 |
+
const hasBetaAccess = useUI((s) => s.hasBetaAccess)
|
11 |
+
|
12 |
+
if (!hasBetaAccess) {
|
13 |
+
return (
|
14 |
+
<FormSection label={'Filter Editor'} className="p-4">
|
15 |
+
Storyboard filters are WIP and not available yet.
|
16 |
+
</FormSection>
|
17 |
+
)
|
18 |
+
}
|
19 |
+
|
20 |
+
if (!current) {
|
21 |
+
return (
|
22 |
+
<FormSection label={'Filter Editor'} className="p-4">
|
23 |
+
No filter selected.
|
24 |
+
</FormSection>
|
25 |
+
)
|
26 |
+
}
|
27 |
+
|
28 |
+
return (
|
29 |
+
<FormSection label={'Filter Editor'} className="p-4">
|
30 |
+
<p>Put filter parameters</p>
|
31 |
+
</FormSection>
|
32 |
+
)
|
33 |
+
}
|
src/components/editors/FilterEditor/index.tsx
ADDED
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { ReflexContainer, ReflexElement, ReflexSplitter } from 'react-reflex'
|
2 |
+
import { FilterTree } from './FilterTree'
|
3 |
+
import { FilterViewer } from './FilterViewer'
|
4 |
+
|
5 |
+
export function FilterEditor() {
|
6 |
+
return (
|
7 |
+
<ReflexContainer orientation="vertical">
|
8 |
+
<ReflexElement minSize={70} size={200}>
|
9 |
+
<FilterTree />
|
10 |
+
</ReflexElement>
|
11 |
+
<ReflexSplitter />
|
12 |
+
<ReflexElement minSize={70}>
|
13 |
+
<FilterViewer />
|
14 |
+
</ReflexElement>
|
15 |
+
</ReflexContainer>
|
16 |
+
)
|
17 |
+
}
|
src/components/editors/ProjectEditor/index.tsx
CHANGED
@@ -12,7 +12,6 @@ export function ProjectEditor() {
|
|
12 |
|
13 |
const current = useProjectEditor((s) => s.current)
|
14 |
const setCurrent = useProjectEditor((s) => s.setCurrent)
|
15 |
-
const history = useProjectEditor((s) => s.history)
|
16 |
const undo = useProjectEditor((s) => s.undo)
|
17 |
const redo = useProjectEditor((s) => s.redo)
|
18 |
|
|
|
12 |
|
13 |
const current = useProjectEditor((s) => s.current)
|
14 |
const setCurrent = useProjectEditor((s) => s.setCurrent)
|
|
|
15 |
const undo = useProjectEditor((s) => s.undo)
|
16 |
const redo = useProjectEditor((s) => s.redo)
|
17 |
|
src/components/editors/SegmentEditor/index.tsx
CHANGED
@@ -13,7 +13,6 @@ export function SegmentEditor() {
|
|
13 |
)
|
14 |
const current = useSegmentEditor((s) => s.current)
|
15 |
const setCurrent = useSegmentEditor((s) => s.setCurrent)
|
16 |
-
const history = useSegmentEditor((s) => s.history)
|
17 |
const undo = useSegmentEditor((s) => s.undo)
|
18 |
const redo = useSegmentEditor((s) => s.redo)
|
19 |
|
|
|
13 |
)
|
14 |
const current = useSegmentEditor((s) => s.current)
|
15 |
const setCurrent = useSegmentEditor((s) => s.setCurrent)
|
|
|
16 |
const undo = useSegmentEditor((s) => s.undo)
|
17 |
const redo = useSegmentEditor((s) => s.redo)
|
18 |
|
src/components/editors/WorkflowEditor/WorkflowViewer/ReactFlowCanvas/formats/comfyui/types.ts
CHANGED
@@ -2,7 +2,7 @@ export type ComfyuiWorkflow = {
|
|
2 |
extra: {
|
3 |
ds: {
|
4 |
scale: number
|
5 |
-
offset: number
|
6 |
}
|
7 |
}
|
8 |
links: [number, number, number, number, number, string][]
|
@@ -18,37 +18,37 @@ export type ComfyuiWorkflowNode = {
|
|
18 |
id: number
|
19 |
pos: number[]
|
20 |
mode: number
|
21 |
-
size: number
|
22 |
type: string
|
23 |
-
color?: string
|
24 |
flags: {
|
25 |
-
collapsed?: boolean
|
26 |
}
|
27 |
order: number
|
28 |
inputs?: ComfyuiWorkflowNodeInput[]
|
29 |
outputs?: ComfyuiWorkflowNodeOutput[]
|
30 |
properties: Record<string, any>
|
31 |
-
widgets_values?: any
|
32 |
}
|
33 |
|
34 |
export type ComfyuiWorkflowNodeInput = {
|
35 |
-
link?: number
|
36 |
name: string
|
37 |
type: string
|
38 |
-
label?: string
|
39 |
widget?: {
|
40 |
name: string
|
41 |
-
}
|
42 |
-
slot_index?: number
|
43 |
}
|
44 |
|
45 |
export type ComfyuiWorkflowNodeOutput = {
|
46 |
name: string
|
47 |
type: string
|
48 |
-
label?: string
|
49 |
-
links?: number[]
|
50 |
shape: number
|
51 |
-
slot_index?: number
|
52 |
}
|
53 |
|
54 |
export type ComfyuiWorkflowGroup = {
|
|
|
2 |
extra: {
|
3 |
ds: {
|
4 |
scale: number
|
5 |
+
offset: { '0': number; '1': number }
|
6 |
}
|
7 |
}
|
8 |
links: [number, number, number, number, number, string][]
|
|
|
18 |
id: number
|
19 |
pos: number[]
|
20 |
mode: number
|
21 |
+
size: { '0': number; '1': number }
|
22 |
type: string
|
23 |
+
color?: string | null
|
24 |
flags: {
|
25 |
+
collapsed?: boolean | null
|
26 |
}
|
27 |
order: number
|
28 |
inputs?: ComfyuiWorkflowNodeInput[]
|
29 |
outputs?: ComfyuiWorkflowNodeOutput[]
|
30 |
properties: Record<string, any>
|
31 |
+
widgets_values?: any | null
|
32 |
}
|
33 |
|
34 |
export type ComfyuiWorkflowNodeInput = {
|
35 |
+
link?: number | null
|
36 |
name: string
|
37 |
type: string
|
38 |
+
label?: string | null
|
39 |
widget?: {
|
40 |
name: string
|
41 |
+
} | null
|
42 |
+
slot_index?: number | null
|
43 |
}
|
44 |
|
45 |
export type ComfyuiWorkflowNodeOutput = {
|
46 |
name: string
|
47 |
type: string
|
48 |
+
label?: string | null
|
49 |
+
links?: number[] | null
|
50 |
shape: number
|
51 |
+
slot_index?: number | null
|
52 |
}
|
53 |
|
54 |
export type ComfyuiWorkflowGroup = {
|
src/components/editors/WorkflowEditor/WorkflowViewer/ReactFlowCanvas/samples/comfyicu.ts
ADDED
@@ -0,0 +1,394 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { ComfyuiWorkflow } from '../formats/comfyui/types'
|
2 |
+
|
3 |
+
// live portrait
|
4 |
+
export const comfyicu: ComfyuiWorkflow[] = [
|
5 |
+
{
|
6 |
+
extra: {
|
7 |
+
ds: {
|
8 |
+
scale: 0.8264462809917354,
|
9 |
+
offset: {
|
10 |
+
'0': 173.4048767089844,
|
11 |
+
'1': -0.9636010527610779,
|
12 |
+
},
|
13 |
+
},
|
14 |
+
},
|
15 |
+
links: [
|
16 |
+
[30, 8, 0, 19, 0, 'IMAGE'],
|
17 |
+
[32, 19, 0, 18, 0, 'IMAGE'],
|
18 |
+
[58, 1, 0, 30, 0, 'LIVEPORTRAITPIPE'],
|
19 |
+
[59, 4, 0, 30, 1, 'IMAGE'],
|
20 |
+
[60, 8, 0, 30, 2, 'IMAGE'],
|
21 |
+
[64, 18, 0, 23, 0, 'IMAGE'],
|
22 |
+
[67, 30, 1, 18, 1, 'IMAGE'],
|
23 |
+
[68, 30, 1, 19, 1, 'IMAGE'],
|
24 |
+
],
|
25 |
+
nodes: [
|
26 |
+
{
|
27 |
+
id: 4,
|
28 |
+
pos: [138, 323],
|
29 |
+
mode: 0,
|
30 |
+
size: {
|
31 |
+
'0': 272.85791015625,
|
32 |
+
'1': 331.6089477539062,
|
33 |
+
},
|
34 |
+
type: 'LoadImage',
|
35 |
+
flags: {},
|
36 |
+
order: 0,
|
37 |
+
outputs: [
|
38 |
+
{
|
39 |
+
name: 'IMAGE',
|
40 |
+
type: 'IMAGE',
|
41 |
+
links: [59],
|
42 |
+
shape: 3,
|
43 |
+
slot_index: 0,
|
44 |
+
},
|
45 |
+
{
|
46 |
+
name: 'MASK',
|
47 |
+
type: 'MASK',
|
48 |
+
links: null,
|
49 |
+
shape: 3,
|
50 |
+
},
|
51 |
+
],
|
52 |
+
properties: {
|
53 |
+
'Node name for S&R': 'LoadImage',
|
54 |
+
},
|
55 |
+
widgets_values: ['monolisa.jpg', 'image'],
|
56 |
+
},
|
57 |
+
{
|
58 |
+
id: 19,
|
59 |
+
pos: [507, 675],
|
60 |
+
mode: 0,
|
61 |
+
size: {
|
62 |
+
'0': 315,
|
63 |
+
'1': 242,
|
64 |
+
},
|
65 |
+
type: 'ImageResizeKJ',
|
66 |
+
flags: {},
|
67 |
+
order: 4,
|
68 |
+
inputs: [
|
69 |
+
{
|
70 |
+
link: 30,
|
71 |
+
name: 'image',
|
72 |
+
type: 'IMAGE',
|
73 |
+
},
|
74 |
+
{
|
75 |
+
link: 68,
|
76 |
+
name: 'get_image_size',
|
77 |
+
type: 'IMAGE',
|
78 |
+
},
|
79 |
+
{
|
80 |
+
link: null,
|
81 |
+
name: 'width_input',
|
82 |
+
type: 'INT',
|
83 |
+
widget: {
|
84 |
+
name: 'width_input',
|
85 |
+
},
|
86 |
+
},
|
87 |
+
{
|
88 |
+
link: null,
|
89 |
+
name: 'height_input',
|
90 |
+
type: 'INT',
|
91 |
+
widget: {
|
92 |
+
name: 'height_input',
|
93 |
+
},
|
94 |
+
},
|
95 |
+
],
|
96 |
+
outputs: [
|
97 |
+
{
|
98 |
+
name: 'IMAGE',
|
99 |
+
type: 'IMAGE',
|
100 |
+
links: [32],
|
101 |
+
shape: 3,
|
102 |
+
slot_index: 0,
|
103 |
+
},
|
104 |
+
{
|
105 |
+
name: 'width',
|
106 |
+
type: 'INT',
|
107 |
+
links: null,
|
108 |
+
shape: 3,
|
109 |
+
},
|
110 |
+
{
|
111 |
+
name: 'height',
|
112 |
+
type: 'INT',
|
113 |
+
links: null,
|
114 |
+
shape: 3,
|
115 |
+
},
|
116 |
+
],
|
117 |
+
properties: {
|
118 |
+
'Node name for S&R': 'ImageResizeKJ',
|
119 |
+
},
|
120 |
+
widgets_values: [512, 512, 'nearest-exact', false, 2, 0, 0],
|
121 |
+
},
|
122 |
+
{
|
123 |
+
id: 18,
|
124 |
+
pos: [860, 679],
|
125 |
+
mode: 0,
|
126 |
+
size: {
|
127 |
+
'0': 210,
|
128 |
+
'1': 150,
|
129 |
+
},
|
130 |
+
type: 'ImageConcatMulti',
|
131 |
+
flags: {},
|
132 |
+
order: 5,
|
133 |
+
inputs: [
|
134 |
+
{
|
135 |
+
link: 32,
|
136 |
+
name: 'image_1',
|
137 |
+
type: 'IMAGE',
|
138 |
+
},
|
139 |
+
{
|
140 |
+
link: 67,
|
141 |
+
name: 'image_2',
|
142 |
+
type: 'IMAGE',
|
143 |
+
},
|
144 |
+
],
|
145 |
+
outputs: [
|
146 |
+
{
|
147 |
+
name: 'images',
|
148 |
+
type: 'IMAGE',
|
149 |
+
links: [64],
|
150 |
+
shape: 3,
|
151 |
+
slot_index: 0,
|
152 |
+
},
|
153 |
+
],
|
154 |
+
properties: {
|
155 |
+
'Node name for S&R': 'ImageConcatMulti',
|
156 |
+
},
|
157 |
+
widgets_values: [2, 'right', false, null],
|
158 |
+
},
|
159 |
+
{
|
160 |
+
id: 1,
|
161 |
+
pos: [142, 205],
|
162 |
+
mode: 0,
|
163 |
+
size: {
|
164 |
+
'0': 252,
|
165 |
+
'1': 58,
|
166 |
+
},
|
167 |
+
type: 'DownloadAndLoadLivePortraitModels',
|
168 |
+
flags: {},
|
169 |
+
order: 1,
|
170 |
+
outputs: [
|
171 |
+
{
|
172 |
+
name: 'live_portrait_pipe',
|
173 |
+
type: 'LIVEPORTRAITPIPE',
|
174 |
+
links: [58],
|
175 |
+
shape: 3,
|
176 |
+
slot_index: 0,
|
177 |
+
},
|
178 |
+
],
|
179 |
+
properties: {
|
180 |
+
'Node name for S&R': 'DownloadAndLoadLivePortraitModels',
|
181 |
+
},
|
182 |
+
widgets_values: ['auto'],
|
183 |
+
},
|
184 |
+
{
|
185 |
+
id: 30,
|
186 |
+
pos: [500, 249],
|
187 |
+
mode: 0,
|
188 |
+
size: {
|
189 |
+
'0': 367.7999877929688,
|
190 |
+
'1': 362,
|
191 |
+
},
|
192 |
+
type: 'LivePortraitProcess',
|
193 |
+
flags: {},
|
194 |
+
order: 3,
|
195 |
+
inputs: [
|
196 |
+
{
|
197 |
+
link: 58,
|
198 |
+
name: 'pipeline',
|
199 |
+
type: 'LIVEPORTRAITPIPE',
|
200 |
+
},
|
201 |
+
{
|
202 |
+
link: 59,
|
203 |
+
name: 'source_image',
|
204 |
+
type: 'IMAGE',
|
205 |
+
},
|
206 |
+
{
|
207 |
+
link: 60,
|
208 |
+
name: 'driving_images',
|
209 |
+
type: 'IMAGE',
|
210 |
+
},
|
211 |
+
],
|
212 |
+
outputs: [
|
213 |
+
{
|
214 |
+
name: 'cropped_images',
|
215 |
+
type: 'IMAGE',
|
216 |
+
links: [],
|
217 |
+
shape: 3,
|
218 |
+
slot_index: 0,
|
219 |
+
},
|
220 |
+
{
|
221 |
+
name: 'full_images',
|
222 |
+
type: 'IMAGE',
|
223 |
+
links: [67, 68],
|
224 |
+
shape: 3,
|
225 |
+
slot_index: 1,
|
226 |
+
},
|
227 |
+
],
|
228 |
+
properties: {
|
229 |
+
'Node name for S&R': 'LivePortraitProcess',
|
230 |
+
},
|
231 |
+
widgets_values: [
|
232 |
+
512,
|
233 |
+
2.3,
|
234 |
+
0,
|
235 |
+
-0.11,
|
236 |
+
true,
|
237 |
+
false,
|
238 |
+
1,
|
239 |
+
false,
|
240 |
+
1,
|
241 |
+
true,
|
242 |
+
true,
|
243 |
+
'CPU',
|
244 |
+
],
|
245 |
+
},
|
246 |
+
{
|
247 |
+
id: 8,
|
248 |
+
pos: [161, 714],
|
249 |
+
mode: 0,
|
250 |
+
size: [235.1999969482422, 491.1999969482422],
|
251 |
+
type: 'VHS_LoadVideo',
|
252 |
+
flags: {},
|
253 |
+
order: 2,
|
254 |
+
inputs: [
|
255 |
+
{
|
256 |
+
link: null,
|
257 |
+
name: 'meta_batch',
|
258 |
+
type: 'VHS_BatchManager',
|
259 |
+
},
|
260 |
+
{
|
261 |
+
link: null,
|
262 |
+
name: 'vae',
|
263 |
+
type: 'VAE',
|
264 |
+
},
|
265 |
+
],
|
266 |
+
outputs: [
|
267 |
+
{
|
268 |
+
name: 'IMAGE',
|
269 |
+
type: 'IMAGE',
|
270 |
+
links: [30, 60],
|
271 |
+
shape: 3,
|
272 |
+
slot_index: 0,
|
273 |
+
},
|
274 |
+
{
|
275 |
+
name: 'frame_count',
|
276 |
+
type: 'INT',
|
277 |
+
links: null,
|
278 |
+
shape: 3,
|
279 |
+
},
|
280 |
+
{
|
281 |
+
name: 'audio',
|
282 |
+
type: 'VHS_AUDIO',
|
283 |
+
links: null,
|
284 |
+
shape: 3,
|
285 |
+
},
|
286 |
+
{
|
287 |
+
name: 'video_info',
|
288 |
+
type: 'VHS_VIDEOINFO',
|
289 |
+
links: null,
|
290 |
+
shape: 3,
|
291 |
+
},
|
292 |
+
],
|
293 |
+
properties: {
|
294 |
+
'Node name for S&R': 'VHS_LoadVideo',
|
295 |
+
},
|
296 |
+
widgets_values: {
|
297 |
+
video: 'd1.mp4',
|
298 |
+
force_rate: 0,
|
299 |
+
force_size: 'Disabled',
|
300 |
+
custom_width: 512,
|
301 |
+
videopreview: {
|
302 |
+
hidden: false,
|
303 |
+
params: {
|
304 |
+
type: 'input',
|
305 |
+
format: 'video/mp4',
|
306 |
+
filename: 'd1.mp4',
|
307 |
+
force_rate: 0,
|
308 |
+
frame_load_cap: 0,
|
309 |
+
select_every_nth: 1,
|
310 |
+
skip_first_frames: 0,
|
311 |
+
},
|
312 |
+
paused: false,
|
313 |
+
},
|
314 |
+
custom_height: 512,
|
315 |
+
frame_load_cap: 0,
|
316 |
+
select_every_nth: 1,
|
317 |
+
skip_first_frames: 0,
|
318 |
+
'choose video to upload': 'image',
|
319 |
+
},
|
320 |
+
},
|
321 |
+
{
|
322 |
+
id: 23,
|
323 |
+
pos: [1098, 240],
|
324 |
+
mode: 0,
|
325 |
+
size: [1253.234130859375, 940.6170654296875],
|
326 |
+
type: 'VHS_VideoCombine',
|
327 |
+
flags: {},
|
328 |
+
order: 6,
|
329 |
+
inputs: [
|
330 |
+
{
|
331 |
+
link: 64,
|
332 |
+
name: 'images',
|
333 |
+
type: 'IMAGE',
|
334 |
+
},
|
335 |
+
{
|
336 |
+
link: null,
|
337 |
+
name: 'audio',
|
338 |
+
type: 'VHS_AUDIO',
|
339 |
+
},
|
340 |
+
{
|
341 |
+
link: null,
|
342 |
+
name: 'meta_batch',
|
343 |
+
type: 'VHS_BatchManager',
|
344 |
+
},
|
345 |
+
{
|
346 |
+
link: null,
|
347 |
+
name: 'vae',
|
348 |
+
type: 'VAE',
|
349 |
+
},
|
350 |
+
],
|
351 |
+
outputs: [
|
352 |
+
{
|
353 |
+
name: 'Filenames',
|
354 |
+
type: 'VHS_FILENAMES',
|
355 |
+
links: null,
|
356 |
+
shape: 3,
|
357 |
+
},
|
358 |
+
],
|
359 |
+
properties: {
|
360 |
+
'Node name for S&R': 'VHS_VideoCombine',
|
361 |
+
},
|
362 |
+
widgets_values: {
|
363 |
+
crf: 19,
|
364 |
+
format: 'video/h264-mp4',
|
365 |
+
pix_fmt: 'yuv420p',
|
366 |
+
pingpong: false,
|
367 |
+
frame_rate: 24,
|
368 |
+
loop_count: 0,
|
369 |
+
save_output: true,
|
370 |
+
videopreview: {
|
371 |
+
hidden: false,
|
372 |
+
params: {
|
373 |
+
src: 'http://comfy.icu/api/v1/view/workflows/mV51t3g_DcTcIHhwBU7p1/temp/LivePortrait_00001.mp4',
|
374 |
+
type: 'temp',
|
375 |
+
format: 'video/h264-mp4',
|
376 |
+
filename:
|
377 |
+
'/workflows/mV51t3g_DcTcIHhwBU7p1/temp/LivePortrait_00001.mp4',
|
378 |
+
subfolder: '',
|
379 |
+
frame_rate: 24,
|
380 |
+
},
|
381 |
+
paused: false,
|
382 |
+
},
|
383 |
+
save_metadata: true,
|
384 |
+
filename_prefix: 'LivePortrait',
|
385 |
+
},
|
386 |
+
},
|
387 |
+
],
|
388 |
+
config: {},
|
389 |
+
groups: [],
|
390 |
+
version: 0.4,
|
391 |
+
last_link_id: 68,
|
392 |
+
last_node_id: 31,
|
393 |
+
},
|
394 |
+
]
|
src/components/editors/WorkflowEditor/WorkflowViewer/index.tsx
CHANGED
@@ -16,7 +16,7 @@ export function WorkflowViewer({
|
|
16 |
<ReactFlowCanvas />
|
17 |
) : !current ? (
|
18 |
<FormSection label={'Workflow Editor'} className="p-4">
|
19 |
-
Workflows are not
|
20 |
</FormSection>
|
21 |
) : (
|
22 |
<FormSection label={'Workflow Editor'} className="p-4">
|
|
|
16 |
<ReactFlowCanvas />
|
17 |
) : !current ? (
|
18 |
<FormSection label={'Workflow Editor'} className="p-4">
|
19 |
+
Workflows are WIP and not available yet.
|
20 |
</FormSection>
|
21 |
) : (
|
22 |
<FormSection label={'Workflow Editor'} className="p-4">
|
src/experiments/grading/types.ts
DELETED
@@ -1,7 +0,0 @@
|
|
1 |
-
import { ClapInputField } from '@aitube/clap/dist/types'
|
2 |
-
|
3 |
-
export type ColorGradingFilter = {
|
4 |
-
name: string
|
5 |
-
parameters: Array<ClapInputField>
|
6 |
-
shader: string // WGSL shader code for the filter
|
7 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/lib/core/constants.ts
CHANGED
@@ -3,7 +3,7 @@
|
|
3 |
export const HARD_LIMIT_NB_MAX_ASSETS_TO_GENERATE_IN_PARALLEL = 32
|
4 |
|
5 |
export const APP_NAME = 'Clapper.app'
|
6 |
-
export const APP_REVISION = '20240729+
|
7 |
|
8 |
export const APP_DOMAIN = 'Clapper.app'
|
9 |
export const APP_LINK = 'https://clapper.app'
|
|
|
3 |
export const HARD_LIMIT_NB_MAX_ASSETS_TO_GENERATE_IN_PARALLEL = 32
|
4 |
|
5 |
export const APP_NAME = 'Clapper.app'
|
6 |
+
export const APP_REVISION = '20240729+2245'
|
7 |
|
8 |
export const APP_DOMAIN = 'Clapper.app'
|
9 |
export const APP_LINK = 'https://clapper.app'
|
src/services/debug.ts
CHANGED
@@ -6,6 +6,7 @@ import { useBroadcast } from './broadcast/useBroadcast'
|
|
6 |
import {
|
7 |
useEditors,
|
8 |
useEntityEditor,
|
|
|
9 |
useProjectEditor,
|
10 |
useScriptEditor,
|
11 |
useSegmentEditor,
|
@@ -31,6 +32,7 @@ if (typeof window !== 'undefined') {
|
|
31 |
w.useBroadcast = useBroadcast
|
32 |
w.useEditors = useEditors
|
33 |
w.useEntityEditor = useEntityEditor
|
|
|
34 |
w.useProjectEditor = useProjectEditor
|
35 |
w.useScriptEditor = useScriptEditor
|
36 |
w.useSegmentEditor = useSegmentEditor
|
|
|
6 |
import {
|
7 |
useEditors,
|
8 |
useEntityEditor,
|
9 |
+
useFilterEditor,
|
10 |
useProjectEditor,
|
11 |
useScriptEditor,
|
12 |
useSegmentEditor,
|
|
|
32 |
w.useBroadcast = useBroadcast
|
33 |
w.useEditors = useEditors
|
34 |
w.useEntityEditor = useEntityEditor
|
35 |
+
w.useFilterEditor = useFilterEditor
|
36 |
w.useProjectEditor = useProjectEditor
|
37 |
w.useScriptEditor = useScriptEditor
|
38 |
w.useSegmentEditor = useSegmentEditor
|
src/services/editors/entity-editor/getDefaultEntityEditorState.ts
CHANGED
@@ -2,9 +2,10 @@ import { EntityEditorState } from '@aitube/clapper-services'
|
|
2 |
|
3 |
export function getDefaultEntityEditorState(): EntityEditorState {
|
4 |
const state: EntityEditorState = {
|
|
|
5 |
current: undefined,
|
|
|
6 |
version: 0,
|
7 |
-
history: [],
|
8 |
|
9 |
draft: undefined,
|
10 |
showEntityList: false,
|
|
|
2 |
|
3 |
export function getDefaultEntityEditorState(): EntityEditorState {
|
4 |
const state: EntityEditorState = {
|
5 |
+
before: [],
|
6 |
current: undefined,
|
7 |
+
after: [],
|
8 |
version: 0,
|
|
|
9 |
|
10 |
draft: undefined,
|
11 |
showEntityList: false,
|
src/{experiments/grading β services/editors/filter-editor}/README.md
RENAMED
File without changes
|
src/{experiments/grading/applyColorGradingDemo.ts β services/editors/filter-editor/demo.ts}
RENAMED
@@ -1,4 +1,4 @@
|
|
1 |
-
import {
|
2 |
|
3 |
import { analogLensSimulator } from './filters/analogLens'
|
4 |
import { cinematic } from './filters/cinematic'
|
@@ -12,7 +12,7 @@ import { hdrToneMapping } from './filters/toneMapping'
|
|
12 |
import { vintageFilm } from './filters/vintageFilm'
|
13 |
|
14 |
export async function demo() {
|
15 |
-
const base64DataUriImages = await
|
16 |
images: [
|
17 |
{
|
18 |
image: 'data:image/png....',
|
|
|
1 |
+
import { runFilterPipeline } from './runFilterPipeline'
|
2 |
|
3 |
import { analogLensSimulator } from './filters/analogLens'
|
4 |
import { cinematic } from './filters/cinematic'
|
|
|
12 |
import { vintageFilm } from './filters/vintageFilm'
|
13 |
|
14 |
export async function demo() {
|
15 |
+
const base64DataUriImages = await runFilterPipeline({
|
16 |
images: [
|
17 |
{
|
18 |
image: 'data:image/png....',
|
src/{experiments/grading β services/editors/filter-editor}/filters/DEPRECATED_analogFilm.ts
RENAMED
@@ -1,7 +1,8 @@
|
|
1 |
-
import {
|
2 |
|
3 |
-
export const analogFilmSimulator:
|
4 |
-
|
|
|
5 |
parameters: [
|
6 |
{
|
7 |
id: 'preset',
|
|
|
1 |
+
import { Filter } from '@aitube/clapper-services'
|
2 |
|
3 |
+
export const analogFilmSimulator: Filter = {
|
4 |
+
id: 'analog_film_simulator',
|
5 |
+
label: 'Analog Film Simulator',
|
6 |
parameters: [
|
7 |
{
|
8 |
id: 'preset',
|
src/{experiments/grading β services/editors/filter-editor}/filters/analogLens.ts
RENAMED
@@ -1,7 +1,8 @@
|
|
1 |
-
import {
|
2 |
|
3 |
-
export const analogLensSimulator:
|
4 |
-
|
|
|
5 |
parameters: [
|
6 |
{
|
7 |
id: 'chromaticAberration',
|
|
|
1 |
+
import { Filter } from '@aitube/clapper-services'
|
2 |
|
3 |
+
export const analogLensSimulator: Filter = {
|
4 |
+
id: 'analog_lens_simulator',
|
5 |
+
label: 'Analog Lens Simulator',
|
6 |
parameters: [
|
7 |
{
|
8 |
id: 'chromaticAberration',
|
src/{experiments/grading β services/editors/filter-editor}/filters/cinematic.ts
RENAMED
@@ -1,7 +1,8 @@
|
|
1 |
-
import {
|
2 |
|
3 |
-
export const cinematic:
|
4 |
-
|
|
|
5 |
parameters: [
|
6 |
{
|
7 |
id: 'preset',
|
|
|
1 |
+
import { Filter } from '@aitube/clapper-services'
|
2 |
|
3 |
+
export const cinematic: Filter = {
|
4 |
+
id: 'cinematic_color_grading',
|
5 |
+
label: 'Cinematic Color Grading',
|
6 |
parameters: [
|
7 |
{
|
8 |
id: 'preset',
|
src/{experiments/grading β services/editors/filter-editor}/filters/colorMapping.ts
RENAMED
@@ -1,8 +1,9 @@
|
|
1 |
-
import {
|
2 |
|
3 |
// Example filter implementations
|
4 |
-
export const colorMapping:
|
5 |
-
|
|
|
6 |
parameters: [
|
7 |
{
|
8 |
id: 'redMultiplier',
|
|
|
1 |
+
import { Filter } from '@aitube/clapper-services'
|
2 |
|
3 |
// Example filter implementations
|
4 |
+
export const colorMapping: Filter = {
|
5 |
+
id: 'color_mapping',
|
6 |
+
label: 'Color Mapping',
|
7 |
parameters: [
|
8 |
{
|
9 |
id: 'redMultiplier',
|
src/{experiments/grading β services/editors/filter-editor}/filters/colorTemperature.ts
RENAMED
@@ -1,7 +1,8 @@
|
|
1 |
-
import {
|
2 |
|
3 |
-
export const colorTemperature:
|
4 |
-
|
|
|
5 |
parameters: [
|
6 |
{
|
7 |
id: 'temperature',
|
|
|
1 |
+
import { Filter } from '@aitube/clapper-services'
|
2 |
|
3 |
+
export const colorTemperature: Filter = {
|
4 |
+
id: 'color_temperature_adjustment',
|
5 |
+
label: 'Color Temperature Adjustment',
|
6 |
parameters: [
|
7 |
{
|
8 |
id: 'temperature',
|
src/{experiments/grading β services/editors/filter-editor}/filters/crossProcessing.ts
RENAMED
@@ -1,7 +1,8 @@
|
|
1 |
-
import {
|
2 |
|
3 |
-
export const crossProcessing:
|
4 |
-
|
|
|
5 |
parameters: [
|
6 |
{
|
7 |
id: 'intensity',
|
|
|
1 |
+
import { Filter } from '@aitube/clapper-services'
|
2 |
|
3 |
+
export const crossProcessing: Filter = {
|
4 |
+
id: 'cross_processing',
|
5 |
+
label: 'Cross-Processing',
|
6 |
parameters: [
|
7 |
{
|
8 |
id: 'intensity',
|
src/{experiments/grading β services/editors/filter-editor}/filters/filmDegradation.ts
RENAMED
@@ -1,7 +1,8 @@
|
|
1 |
-
import {
|
2 |
|
3 |
-
export const filmDegradation:
|
4 |
-
|
|
|
5 |
parameters: [
|
6 |
{
|
7 |
id: 'scratchesIntensity',
|
|
|
1 |
+
import { Filter } from '@aitube/clapper-services'
|
2 |
|
3 |
+
export const filmDegradation: Filter = {
|
4 |
+
id: 'film_degradation',
|
5 |
+
label: 'Film Degradation',
|
6 |
parameters: [
|
7 |
{
|
8 |
id: 'scratchesIntensity',
|
src/services/editors/filter-editor/filters/index.ts
ADDED
@@ -0,0 +1,137 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { Filter, FilterWithParams } from '@aitube/clapper-services'
|
2 |
+
|
3 |
+
export { analogLensSimulator } from './analogLens'
|
4 |
+
export { cinematic } from './cinematic'
|
5 |
+
export { colorMapping } from './colorMapping'
|
6 |
+
export { colorTemperature } from './colorTemperature'
|
7 |
+
export { crossProcessing } from './crossProcessing'
|
8 |
+
export { filmDegradation } from './filmDegradation'
|
9 |
+
export { infraredBlackAndWhite } from './infrared'
|
10 |
+
export { lomography } from './lomography'
|
11 |
+
export { splitToning } from './splitToning'
|
12 |
+
export { hdrToneMapping } from './toneMapping'
|
13 |
+
export { vintageFilm } from './vintageFilm'
|
14 |
+
|
15 |
+
import { analogLensSimulator } from './analogLens'
|
16 |
+
import { cinematic } from './cinematic'
|
17 |
+
import { colorMapping } from './colorMapping'
|
18 |
+
import { colorTemperature } from './colorTemperature'
|
19 |
+
import { crossProcessing } from './crossProcessing'
|
20 |
+
import { filmDegradation } from './filmDegradation'
|
21 |
+
import { infraredBlackAndWhite } from './infrared'
|
22 |
+
import { lomography } from './lomography'
|
23 |
+
import { splitToning } from './splitToning'
|
24 |
+
import { hdrToneMapping } from './toneMapping'
|
25 |
+
import { vintageFilm } from './vintageFilm'
|
26 |
+
|
27 |
+
export const filters: Filter[] = [
|
28 |
+
analogLensSimulator,
|
29 |
+
cinematic,
|
30 |
+
colorMapping,
|
31 |
+
colorTemperature,
|
32 |
+
crossProcessing,
|
33 |
+
filmDegradation,
|
34 |
+
infraredBlackAndWhite,
|
35 |
+
lomography,
|
36 |
+
splitToning,
|
37 |
+
hdrToneMapping,
|
38 |
+
vintageFilm,
|
39 |
+
]
|
40 |
+
|
41 |
+
export const presets: FilterWithParams[] = [
|
42 |
+
{
|
43 |
+
filter: analogLensSimulator,
|
44 |
+
parameters: {
|
45 |
+
chromaticAberration: 0.003,
|
46 |
+
vignetteStrength: 0.4,
|
47 |
+
vignetteRadius: 0.8,
|
48 |
+
distortion: 0.15,
|
49 |
+
bloomStrength: 0.2,
|
50 |
+
bloomRadius: 4,
|
51 |
+
dofFocusDistance: 0.6,
|
52 |
+
dofFocusRange: 0.1,
|
53 |
+
dofBlurStrength: 3,
|
54 |
+
},
|
55 |
+
},
|
56 |
+
{
|
57 |
+
filter: infraredBlackAndWhite,
|
58 |
+
parameters: {
|
59 |
+
contrast: 1.3,
|
60 |
+
grain: 0.25,
|
61 |
+
glow: 0.4,
|
62 |
+
},
|
63 |
+
},
|
64 |
+
{
|
65 |
+
filter: filmDegradation,
|
66 |
+
parameters: {
|
67 |
+
scratchesIntensity: 0.35,
|
68 |
+
dustIntensity: 0.25,
|
69 |
+
colorFading: 0.4,
|
70 |
+
lightLeakIntensity: 0.3,
|
71 |
+
},
|
72 |
+
},
|
73 |
+
{
|
74 |
+
filter: crossProcessing,
|
75 |
+
parameters: {
|
76 |
+
intensity: 0.6,
|
77 |
+
contrastBoost: 0.4,
|
78 |
+
colorShift: 'Cool',
|
79 |
+
},
|
80 |
+
},
|
81 |
+
{
|
82 |
+
filter: lomography,
|
83 |
+
parameters: {
|
84 |
+
saturation: 1.4,
|
85 |
+
contrast: 1.3,
|
86 |
+
vignetteIntensity: 0.6,
|
87 |
+
lightLeakIntensity: 0.4,
|
88 |
+
},
|
89 |
+
},
|
90 |
+
{
|
91 |
+
filter: cinematic,
|
92 |
+
parameters: {
|
93 |
+
preset: 'Blade Runner',
|
94 |
+
intensity: 0.6,
|
95 |
+
contrast: 1.3,
|
96 |
+
},
|
97 |
+
},
|
98 |
+
{
|
99 |
+
filter: splitToning,
|
100 |
+
parameters: {
|
101 |
+
highlightColor: 'Yellow',
|
102 |
+
shadowColor: 'Blue',
|
103 |
+
balance: 0.1,
|
104 |
+
intensity: 0.5,
|
105 |
+
},
|
106 |
+
},
|
107 |
+
|
108 |
+
{
|
109 |
+
filter: hdrToneMapping,
|
110 |
+
parameters: {
|
111 |
+
exposure: 0.5,
|
112 |
+
contrast: 1.2,
|
113 |
+
saturation: 1.1,
|
114 |
+
highlights: -0.2,
|
115 |
+
shadows: 0.3,
|
116 |
+
},
|
117 |
+
},
|
118 |
+
{
|
119 |
+
filter: colorTemperature,
|
120 |
+
parameters: {
|
121 |
+
temperature: 5500,
|
122 |
+
tint: 10,
|
123 |
+
},
|
124 |
+
},
|
125 |
+
{
|
126 |
+
filter: vintageFilm,
|
127 |
+
parameters: {
|
128 |
+
preset: 'Kodachrome 64',
|
129 |
+
intensity: 0.8,
|
130 |
+
grain: 0.3,
|
131 |
+
ageEffect: 0.2,
|
132 |
+
colorShift: 0.05,
|
133 |
+
contrast: 1.1,
|
134 |
+
saturation: 1.2,
|
135 |
+
},
|
136 |
+
},
|
137 |
+
]
|
src/{experiments/grading β services/editors/filter-editor}/filters/infrared.ts
RENAMED
@@ -1,7 +1,8 @@
|
|
1 |
-
import {
|
2 |
|
3 |
-
export const infraredBlackAndWhite:
|
4 |
-
|
|
|
5 |
parameters: [
|
6 |
{
|
7 |
id: 'contrast',
|
|
|
1 |
+
import { Filter } from '@aitube/clapper-services'
|
2 |
|
3 |
+
export const infraredBlackAndWhite: Filter = {
|
4 |
+
id: 'infrared_black_and_white',
|
5 |
+
label: 'Infrared Black and White',
|
6 |
parameters: [
|
7 |
{
|
8 |
id: 'contrast',
|
src/{experiments/grading β services/editors/filter-editor}/filters/lomography.ts
RENAMED
@@ -1,7 +1,8 @@
|
|
1 |
-
import {
|
2 |
|
3 |
-
export const lomography:
|
4 |
-
|
|
|
5 |
parameters: [
|
6 |
{
|
7 |
id: 'saturation',
|
|
|
1 |
+
import { Filter } from '@aitube/clapper-services'
|
2 |
|
3 |
+
export const lomography: Filter = {
|
4 |
+
id: 'lomography',
|
5 |
+
label: 'Lomography',
|
6 |
parameters: [
|
7 |
{
|
8 |
id: 'saturation',
|
src/{experiments/grading β services/editors/filter-editor}/filters/splitToning.ts
RENAMED
@@ -1,7 +1,8 @@
|
|
1 |
-
import {
|
2 |
|
3 |
-
export const splitToning:
|
4 |
-
|
|
|
5 |
parameters: [
|
6 |
{
|
7 |
id: 'highlightColor',
|
|
|
1 |
+
import { Filter } from '@aitube/clapper-services'
|
2 |
|
3 |
+
export const splitToning: Filter = {
|
4 |
+
id: 'split_toning',
|
5 |
+
label: 'Split Toning',
|
6 |
parameters: [
|
7 |
{
|
8 |
id: 'highlightColor',
|
src/{experiments/grading β services/editors/filter-editor}/filters/toneMapping.ts
RENAMED
@@ -1,7 +1,8 @@
|
|
1 |
-
import {
|
2 |
|
3 |
-
export const hdrToneMapping:
|
4 |
-
|
|
|
5 |
parameters: [
|
6 |
{
|
7 |
id: 'exposure',
|
|
|
1 |
+
import { Filter } from '@aitube/clapper-services'
|
2 |
|
3 |
+
export const hdrToneMapping: Filter = {
|
4 |
+
id: 'hd_tone_mapping',
|
5 |
+
label: 'HDR Tone Mapping',
|
6 |
parameters: [
|
7 |
{
|
8 |
id: 'exposure',
|
src/{experiments/grading β services/editors/filter-editor}/filters/vintageFilm.ts
RENAMED
@@ -1,7 +1,8 @@
|
|
1 |
-
import {
|
2 |
|
3 |
-
export const vintageFilm:
|
4 |
-
|
|
|
5 |
parameters: [
|
6 |
{
|
7 |
id: 'preset',
|
|
|
1 |
+
import { Filter } from '@aitube/clapper-services'
|
2 |
|
3 |
+
export const vintageFilm: Filter = {
|
4 |
+
id: 'enhanced_vintage_film_stocks',
|
5 |
+
label: 'Enhanced Vintage Film Stocks',
|
6 |
parameters: [
|
7 |
{
|
8 |
id: 'preset',
|
src/services/editors/filter-editor/getDefaultFilterEditorState.ts
ADDED
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { FilterEditorState } from '@aitube/clapper-services'
|
2 |
+
|
3 |
+
import { cinematic, filters } from './filters'
|
4 |
+
|
5 |
+
export function getDefaultFilterEditorState(): FilterEditorState {
|
6 |
+
const state: FilterEditorState = {
|
7 |
+
before: [],
|
8 |
+
current: undefined,
|
9 |
+
after: [],
|
10 |
+
version: 0,
|
11 |
+
|
12 |
+
isEnabled: true,
|
13 |
+
|
14 |
+
availableFilters: [...filters],
|
15 |
+
|
16 |
+
activeFilters: [
|
17 |
+
{
|
18 |
+
filter: cinematic,
|
19 |
+
parameters: {
|
20 |
+
preset: 'Blade Runner',
|
21 |
+
intensity: 0.6,
|
22 |
+
contrast: 1.3,
|
23 |
+
},
|
24 |
+
},
|
25 |
+
],
|
26 |
+
}
|
27 |
+
|
28 |
+
return state
|
29 |
+
}
|
src/{experiments/grading/applyColorGrading.ts β services/editors/filter-editor/runFilterPipeline.ts}
RENAMED
@@ -1,16 +1,17 @@
|
|
1 |
import { decode, encode } from 'base64-arraybuffer'
|
2 |
|
3 |
-
import {
|
|
|
|
|
|
|
|
|
4 |
|
5 |
-
export async function
|
6 |
images,
|
7 |
filters,
|
8 |
}: {
|
9 |
images: Array<{ image: string; depthMap?: string }>
|
10 |
-
filters:
|
11 |
-
filter: ColorGradingFilter
|
12 |
-
parameters?: Record<string, string | number>
|
13 |
-
}>
|
14 |
}): Promise<string[]> {
|
15 |
if (!navigator.gpu) {
|
16 |
throw new Error('WebGPU is not supported in this browser.')
|
@@ -105,8 +106,8 @@ async function applyFilter(
|
|
105 |
device: GPUDevice,
|
106 |
inputTexture: GPUTexture,
|
107 |
depthTexture: GPUTexture | null,
|
108 |
-
filter:
|
109 |
-
parameters?:
|
110 |
): Promise<GPUTexture> {
|
111 |
const shader = createShaderModule(device, filter.shader)
|
112 |
const pipeline = device.createComputePipeline({
|
|
|
1 |
import { decode, encode } from 'base64-arraybuffer'
|
2 |
|
3 |
+
import {
|
4 |
+
Filter,
|
5 |
+
FilterParams,
|
6 |
+
FilterWithParams,
|
7 |
+
} from '@aitube/clapper-services'
|
8 |
|
9 |
+
export async function runFilterPipeline({
|
10 |
images,
|
11 |
filters,
|
12 |
}: {
|
13 |
images: Array<{ image: string; depthMap?: string }>
|
14 |
+
filters: FilterWithParams[]
|
|
|
|
|
|
|
15 |
}): Promise<string[]> {
|
16 |
if (!navigator.gpu) {
|
17 |
throw new Error('WebGPU is not supported in this browser.')
|
|
|
106 |
device: GPUDevice,
|
107 |
inputTexture: GPUTexture,
|
108 |
depthTexture: GPUTexture | null,
|
109 |
+
filter: Filter,
|
110 |
+
parameters?: FilterParams
|
111 |
): Promise<GPUTexture> {
|
112 |
const shader = createShaderModule(device, filter.shader)
|
113 |
const pipeline = device.createComputePipeline({
|
src/services/editors/filter-editor/useFilterEditor.ts
ADDED
@@ -0,0 +1,52 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
'use client'
|
2 |
+
|
3 |
+
import { create } from 'zustand'
|
4 |
+
import {
|
5 |
+
FilterEditorStore,
|
6 |
+
FilterWithParams,
|
7 |
+
redo,
|
8 |
+
undo,
|
9 |
+
} from '@aitube/clapper-services'
|
10 |
+
|
11 |
+
import { getDefaultFilterEditorState } from './getDefaultFilterEditorState'
|
12 |
+
import { runFilterPipeline } from './runFilterPipeline'
|
13 |
+
|
14 |
+
export const useFilterEditor = create<FilterEditorStore>()((set, get) => ({
|
15 |
+
...getDefaultFilterEditorState(),
|
16 |
+
|
17 |
+
setEnabled: (isEnabled: boolean) => {
|
18 |
+
set({ isEnabled })
|
19 |
+
},
|
20 |
+
|
21 |
+
runFilterPipeline: async (input: string) => {
|
22 |
+
const { activeFilters } = get()
|
23 |
+
const results = await runFilterPipeline({
|
24 |
+
images: [{ image: input }],
|
25 |
+
filters: activeFilters,
|
26 |
+
})
|
27 |
+
|
28 |
+
const result = results[0]
|
29 |
+
|
30 |
+
return result
|
31 |
+
},
|
32 |
+
|
33 |
+
setCurrent: (current?: FilterWithParams[]) => {
|
34 |
+
set({ current })
|
35 |
+
},
|
36 |
+
|
37 |
+
undo: () => {
|
38 |
+
set({
|
39 |
+
...undo<FilterWithParams[]>({
|
40 |
+
...get(),
|
41 |
+
}),
|
42 |
+
})
|
43 |
+
},
|
44 |
+
|
45 |
+
redo: () => {
|
46 |
+
set({
|
47 |
+
...redo<FilterWithParams[]>({
|
48 |
+
...get(),
|
49 |
+
}),
|
50 |
+
})
|
51 |
+
},
|
52 |
+
}))
|
src/services/editors/index.ts
CHANGED
@@ -1,4 +1,5 @@
|
|
1 |
export { useEntityEditor } from './entity-editor/useEntityEditor'
|
|
|
2 |
export { useProjectEditor } from './project-editor/useProjectEditor'
|
3 |
export { useSegmentEditor } from './segment-editor/useSegmentEditor'
|
4 |
export { useScriptEditor } from './script-editor/useScriptEditor'
|
|
|
1 |
export { useEntityEditor } from './entity-editor/useEntityEditor'
|
2 |
+
export { useFilterEditor } from './filter-editor/useFilterEditor'
|
3 |
export { useProjectEditor } from './project-editor/useProjectEditor'
|
4 |
export { useSegmentEditor } from './segment-editor/useSegmentEditor'
|
5 |
export { useScriptEditor } from './script-editor/useScriptEditor'
|
src/services/editors/project-editor/getDefaultProjectEditorState.ts
CHANGED
@@ -2,9 +2,10 @@ import { ProjectEditorState } from '@aitube/clapper-services'
|
|
2 |
|
3 |
export function getDefaultProjectEditorState(): ProjectEditorState {
|
4 |
const state: ProjectEditorState = {
|
|
|
5 |
current: undefined,
|
|
|
6 |
version: 0,
|
7 |
-
history: [],
|
8 |
}
|
9 |
|
10 |
return state
|
|
|
2 |
|
3 |
export function getDefaultProjectEditorState(): ProjectEditorState {
|
4 |
const state: ProjectEditorState = {
|
5 |
+
before: [],
|
6 |
current: undefined,
|
7 |
+
after: [],
|
8 |
version: 0,
|
|
|
9 |
}
|
10 |
|
11 |
return state
|
src/services/editors/script-editor/getDefaultScriptEditorState.ts
CHANGED
@@ -15,9 +15,10 @@ export function getDefaultScriptEditorState(): ScriptEditorState {
|
|
15 |
scrollWidth: 0,
|
16 |
scrollTopInMs: 0,
|
17 |
|
|
|
18 |
current: undefined,
|
|
|
19 |
version: 0,
|
20 |
-
history: [],
|
21 |
}
|
22 |
|
23 |
return state
|
|
|
15 |
scrollWidth: 0,
|
16 |
scrollTopInMs: 0,
|
17 |
|
18 |
+
before: [],
|
19 |
current: undefined,
|
20 |
+
after: [],
|
21 |
version: 0,
|
|
|
22 |
}
|
23 |
|
24 |
return state
|
src/services/editors/segment-editor/getDefaultSegmentEditorState.ts
CHANGED
@@ -2,9 +2,10 @@ import { SegmentEditorState } from '@aitube/clapper-services'
|
|
2 |
|
3 |
export function getDefaultSegmentEditorState(): SegmentEditorState {
|
4 |
const state: SegmentEditorState = {
|
|
|
5 |
current: undefined,
|
|
|
6 |
version: 0,
|
7 |
-
history: [],
|
8 |
}
|
9 |
|
10 |
return state
|
|
|
2 |
|
3 |
export function getDefaultSegmentEditorState(): SegmentEditorState {
|
4 |
const state: SegmentEditorState = {
|
5 |
+
before: [],
|
6 |
current: undefined,
|
7 |
+
after: [],
|
8 |
version: 0,
|
|
|
9 |
}
|
10 |
|
11 |
return state
|
src/services/editors/workflow-editor/getDefaultWorkflowtEditorState.ts
CHANGED
@@ -2,9 +2,10 @@ import { WorkflowEditorState } from '@aitube/clapper-services'
|
|
2 |
|
3 |
export function getDefaultWorkflowEditorState(): WorkflowEditorState {
|
4 |
const state: WorkflowEditorState = {
|
|
|
5 |
current: undefined,
|
|
|
6 |
version: 0,
|
7 |
-
history: [],
|
8 |
}
|
9 |
|
10 |
return state
|
|
|
2 |
|
3 |
export function getDefaultWorkflowEditorState(): WorkflowEditorState {
|
4 |
const state: WorkflowEditorState = {
|
5 |
+
before: [],
|
6 |
current: undefined,
|
7 |
+
after: [],
|
8 |
version: 0,
|
|
|
9 |
}
|
10 |
|
11 |
return state
|
src/services/index.ts
CHANGED
@@ -4,6 +4,7 @@ export { useAudio } from './audio/useAudio'
|
|
4 |
export { useBroadcast } from './broadcast/useBroadcast'
|
5 |
export {
|
6 |
useEntityEditor,
|
|
|
7 |
useProjectEditor,
|
8 |
useSegmentEditor,
|
9 |
useScriptEditor,
|
|
|
4 |
export { useBroadcast } from './broadcast/useBroadcast'
|
5 |
export {
|
6 |
useEntityEditor,
|
7 |
+
useFilterEditor,
|
8 |
useProjectEditor,
|
9 |
useSegmentEditor,
|
10 |
useScriptEditor,
|
src/services/plugins/usePlugins.ts
CHANGED
@@ -27,6 +27,7 @@ import {
|
|
27 |
useSegmentEditor,
|
28 |
useScriptEditor,
|
29 |
useWorkflowEditor,
|
|
|
30 |
} from '../editors'
|
31 |
import { useSimulator } from '../simulator/useSimulator'
|
32 |
import { useIO } from '../io/useIO'
|
@@ -67,6 +68,7 @@ export const usePlugins = create<PluginsStore>((set, get) => ({
|
|
67 |
mic: useMic,
|
68 |
segmentEditor: useSegmentEditor,
|
69 |
entityEditor: useEntityEditor,
|
|
|
70 |
projectEditor: useProjectEditor,
|
71 |
scriptEditor: useScriptEditor,
|
72 |
workflowEditor: useWorkflowEditor,
|
|
|
27 |
useSegmentEditor,
|
28 |
useScriptEditor,
|
29 |
useWorkflowEditor,
|
30 |
+
useFilterEditor,
|
31 |
} from '../editors'
|
32 |
import { useSimulator } from '../simulator/useSimulator'
|
33 |
import { useIO } from '../io/useIO'
|
|
|
68 |
mic: useMic,
|
69 |
segmentEditor: useSegmentEditor,
|
70 |
entityEditor: useEntityEditor,
|
71 |
+
filterEditor: useFilterEditor,
|
72 |
projectEditor: useProjectEditor,
|
73 |
scriptEditor: useScriptEditor,
|
74 |
workflowEditor: useWorkflowEditor,
|