Skip to content

Commit

Permalink
Merge pull request #224 from rewbs/rendered-values-in-grid
Browse files Browse the repository at this point in the history
Optionally show rendered prompts and interpolated values in grid.
  • Loading branch information
rewbs authored Oct 10, 2023
2 parents 4c1d0f3 + e593713 commit 01a8cf2
Show file tree
Hide file tree
Showing 7 changed files with 197 additions and 19 deletions.
6 changes: 5 additions & 1 deletion src/FunctionDoc.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,11 @@ const MiniParseq = ({ keyframes, fields }: MiniParseqProps) => {
bpm={120}
agGridStyle={{ width: '100%', minHeight: '50px', maxHeight: '500px', }}
agGridProps={{ domLayout: 'autoHeight' }}
managedFields={fields} />
managedFields={fields}
renderedData={renderedData||null}
showPrompt={false}
showInterpolatedValues={true}
/>

const graph = graphableData && renderedData ? <ParseqGraph
editingDisabled={true}
Expand Down
6 changes: 5 additions & 1 deletion src/Labs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,11 @@ const MiniParseq = ({ keyframes, fields }: MiniParseqProps) => {
bpm={120}
agGridStyle={{ width: '100%', minHeight: '50px', maxHeight: '500px', }}
agGridProps={{ domLayout: 'autoHeight' }}
managedFields={fields} />
managedFields={fields}
renderedData={null}
showPrompt={false}
showInterpolatedValues={false}
/>

const graph = graphableData && renderedData ? <ParseqGraph
editingDisabled={true}
Expand Down
64 changes: 57 additions & 7 deletions src/ParseqUI.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ const ParseqUI = (props) => {
const [graphAsPercentages, setGraphAsPercentages] = useState(false);
const [showPromptMarkers, setShowPromptMarkers] = useState(false);
const [showCursors, setShowCursors] = useState(false);
const [showInterpolatedValues, setShowInterpolatedValues] = useState(true);
const [showPrompts, setShowPrompts] = useState(true);
const [beatMarkerInterval, setBeatMarkerInterval] = useState(0);
const [showFlatSparklines, setShowFlatSparklines] = useState(false);
const [keyframes, setKeyframes] = useState();
Expand Down Expand Up @@ -253,7 +255,7 @@ const ParseqUI = (props) => {
setTimeout(() => {
gridRef.current.columnApi.setColumnsVisible(allColumnIds, false);
gridRef.current.columnApi.setColumnsVisible(columnsToShow, true);
gridRef.current.columnApi.setColumnsVisible(['frame', 'info'], true);
gridRef.current.columnApi.setColumnsVisible(['frame', 'info', 'prompt'], true);
gridRef.current.api.onSortChanged();
});

Expand Down Expand Up @@ -944,6 +946,8 @@ const ParseqUI = (props) => {





// Grid ------------------------

const grid = useMemo(() => <ParseqGrid
Expand All @@ -961,7 +965,10 @@ const ParseqUI = (props) => {
fps={options?.output_fps}
bpm={options?.bpm}
agGridStyle={{ width: '100%', minHeight: '150px', height: '150px', maxHeight: '1150px', }}
/>, [rangeSelection, options, onCellValueChanged, onCellKeyPress, onGridReady, onFirstDataRendered, keyframeLock, showCursors, managedFields]);
renderedData={renderedData}
showPrompt={showPrompts}
showInterpolatedValues={showInterpolatedValues}
/>, [rangeSelection, options, onCellValueChanged, onCellKeyPress, onGridReady, onFirstDataRendered, keyframeLock, showCursors, managedFields, renderedData, showInterpolatedValues, showPrompts]);


const gridHeightToggle = useMemo(() => <Stack direction="row" alignItems="center" justifyContent={"flex-start"} gap={1}>
Expand Down Expand Up @@ -1027,6 +1034,52 @@ const ParseqUI = (props) => {
))}
</Select></Stack>, [displayedFields, handleChangeDisplayedFields, managedFields])


const gridOptions = useMemo(
() => (
<Stack direction="row" justifyContent={"space-between"} fullWidth>
{displayedFieldSelector}
<FormControlLabel
control={
<Checkbox
padding={0}
margin={0}
checked={showPrompts}
onChange={(e) => setShowPrompts(e.target.checked)}
/>
}
label={
<Box component="div" fontSize="0.75em">
Show computed prompts at keyframes
</Box>
}
/>
<FormControlLabel
control={
<Checkbox
padding={0}
margin={0}
checked={showInterpolatedValues}
onChange={(e) => setShowInterpolatedValues(e.target.checked)}
/>
}
label={
<Box component="div" fontSize="0.75em">
Show interpolated values
</Box>
}
/>
{gridHeightToggle}
</Stack>
),
[
displayedFieldSelector,
showPrompts,
showInterpolatedValues,
gridHeightToggle,
]
);

// Editable Graph ------------------------

// Prompt markers (also used on audio graph)
Expand Down Expand Up @@ -1329,7 +1382,7 @@ const ParseqUI = (props) => {
// Footer ------------------------

const debugStatus = useMemo(() => {
if (process.env.NODE_ENV === 'development' || debugMode) {
if (debugMode) {
return <Alert severity="info">
Active version: {activeVersionId?.split("-")[1]}
<ul>
Expand Down Expand Up @@ -1581,10 +1634,7 @@ const ParseqUI = (props) => {
// TODO: we always have to render the grid currently, else we lose keyframes because they reference grid data.
renderChildrenWhenCollapsed={true}
title="Keyframe grid">
<Stack direction='row' justifyContent={'space-between'} fullWidth>
{displayedFieldSelector}
{gridHeightToggle}
</Stack>
{gridOptions}
{grid}
<Stack direction='row' justifyContent={'space-between'} fullWidth>
<Stack direction='row' gap={1} id='gridControls' fullWidth>
Expand Down
76 changes: 66 additions & 10 deletions src/components/ParseqGrid.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import { experimental_extendTheme as extendTheme, useColorScheme } from "@mui/material/styles";
import { ValueFormatterParams, ValueGetterParams, ValueParserParams, ValueSetterParams } from 'ag-grid-community';
import { AgGridReact } from 'ag-grid-react';
import _ from 'lodash';
import { all, create } from 'mathjs';
import { forwardRef, useCallback, useMemo } from 'react';
import { frameToXAxisType, xAxisTypeToFrame } from '../utils/maths';
import { useHotkeysContext } from 'react-hotkeys-hook';
import { RenderedData } from '../ParseqUI';
import { themeFactory } from "../theme";
import { frameToXAxisType, isValidNumber, xAxisTypeToFrame } from '../utils/maths';
import { fieldNametoRGBa } from '../utils/utils';
import { GridTooltip } from './GridToolTip';
import { ValueParserParams, ValueSetterParams } from 'ag-grid-community';
import { experimental_extendTheme as extendTheme, useColorScheme } from "@mui/material/styles";
import { themeFactory } from "../theme";
import { useHotkeysContext } from 'react-hotkeys-hook';
import { PromptCellEditor } from './PromptCellEditor';

const config = {}
const mathjs = create(all, config)
Expand All @@ -32,12 +34,14 @@ type ParseqGridProps = {
fps: number,
bpm: number,
managedFields: string[],
agGridProps: {}
agGridStyle: {}

agGridProps: {},
agGridStyle: {},
renderedData: RenderedData|null,
showPrompt: boolean,
showInterpolatedValues: boolean,
};

export const ParseqGrid = forwardRef(({ rangeSelection, onSelectRange, onGridReady, onCellValueChanged, onCellKeyPress, onFirstDataRendered, onChangeGridCursorPosition, showCursors, keyframeLock, fps, bpm, managedFields, agGridProps, agGridStyle }: ParseqGridProps, gridRef) => {
export const ParseqGrid = forwardRef(({ rangeSelection, onSelectRange, onGridReady, onCellValueChanged, onCellKeyPress, onFirstDataRendered, onChangeGridCursorPosition, showCursors, keyframeLock, fps, bpm, managedFields, agGridProps, agGridStyle, renderedData, showPrompt, showInterpolatedValues }: ParseqGridProps, gridRef) => {

const theme = extendTheme(themeFactory());
// eslint-disable-next-line @typescript-eslint/no-unused-vars
Expand Down Expand Up @@ -128,6 +132,42 @@ export const ParseqGrid = forwardRef(({ rangeSelection, onSelectRange, onGridRea
flex: 1,

},
...(renderedData && showPrompt ? [{
headerName: 'Prompt',
field: 'prompt',
valueGetter: (params: ValueGetterParams) => {
const frame = params.data['frame'];
if (renderedData && renderedData.rendered_frames && renderedData.rendered_frames[frame]) {
return renderedData.rendered_frames[frame].deforum_prompt || '⚠️ EMPTY prompt!! This is probably a mistake. Check the prompt section and make sure prompts cover the full duration of the animation.';
} else {
return '';
}
},
readOnly: true,
pinned: 'left',
suppressMovable: true,
cellEditor: PromptCellEditor,
cellEditorPopup: true,
cellEditorPopupPosition: 'under',
cellEditorParams: {
},
cellStyle: (params: any): any => {
if (isInRangeSelection(params)) {
return {
color: theme.vars.palette.text.secondary,
backgroundColor: theme.vars.palette.gridPromptField.dark,
borderRight: isSameCellPosition(params, params.api.getFocusedCell()) ? '' : '1px solid ' + theme.vars.palette.gridColSeparatorMajor.main
}
} else {
return {
color: theme.vars.palette.text.secondary,
backgroundColor: theme.vars.palette.gridPromptField.light,
borderRight: isSameCellPosition(params, params.api.getFocusedCell()) ? '' : '1px solid '+ theme.vars.palette.gridColSeparatorMajor.main
}
}
},
flex: 2,
}] : []),
{
headerName: 'Info',
field: 'info',
Expand Down Expand Up @@ -162,6 +202,19 @@ export const ParseqGrid = forwardRef(({ rangeSelection, onSelectRange, onGridRea
...(managedFields ? managedFields.flatMap((field: string) => [
{
field: field,
valueFormatter: (params: ValueFormatterParams) => {
const frame = params.data['frame'];
if (showInterpolatedValues
&& !isValidNumber(params.data[field])
&& renderedData
&& renderedData.rendered_frames
) {
const renderedValue = renderedData.rendered_frames[frame][field];
return isValidNumber(renderedValue) ? `(${renderedValue})` : '';
} else {
return params.data[field];
}
},
valueSetter: (params: ValueSetterParams) => {
if (!params.newValue) {
params.data[field] = '';
Expand All @@ -185,11 +238,13 @@ export const ParseqGrid = forwardRef(({ rangeSelection, onSelectRange, onGridRea
cellStyle: (params: any) => {
if (isInRangeSelection(params)) {
return {
color: isValidNumber(params.data[field]) ? theme.vars.palette.text.primary : theme.vars.palette.greyedText.main,
backgroundColor: fieldNametoRGBa(field, 0.4),
borderRight: isSameCellPosition(params, params.api.getFocusedCell()) ? '' : '1px solid ' + theme.vars.palette.gridColSeparatorMinor.main
}
} else {
return {
color: isValidNumber(params.data[field]) ? theme.vars.palette.text.primary : theme.vars.palette.greyedText.main,
backgroundColor: fieldNametoRGBa(field, 0.1),
borderRight: isSameCellPosition(params, params.api.getFocusedCell()) ? '' : '1px solid ' + theme.vars.palette.gridColSeparatorMinor.main
}
Expand Down Expand Up @@ -231,7 +286,7 @@ export const ParseqGrid = forwardRef(({ rangeSelection, onSelectRange, onGridRea
]) : [])
]

}, [managedFields, isInRangeSelection, keyframeLock, fps, bpm, theme]);
}, [managedFields, isInRangeSelection, keyframeLock, fps, bpm, theme, renderedData, showInterpolatedValues, showPrompt]);

const defaultColDef = useMemo(() => ({
editable: true,
Expand Down Expand Up @@ -277,6 +332,7 @@ export const ParseqGrid = forwardRef(({ rangeSelection, onSelectRange, onGridRea
navigateToNextCell={navigateToNextCell}
suppressColumnVirtualisation={process.env?.NODE_ENV === "test"}
suppressRowVirtualisation={process.env?.NODE_ENV === "test"}
stopEditingWhenCellsLoseFocus={true}
onCellKeyDown={(e: any) => {
if (e.event.keyCode === 46 || e.event.keyCode === 8) {
if (rangeSelection.anchor && rangeSelection.tip) {
Expand Down
52 changes: 52 additions & 0 deletions src/components/PromptCellEditor.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@

import { Typography } from '@mui/material';
import { experimental_extendTheme as extendTheme } from "@mui/material/styles";
import {
forwardRef,
useImperativeHandle,
useRef
} from 'react';
import { themeFactory } from "../theme";

// This is an "editor" from ag-grid's perspective, but is actually
// a read-only view of the prompt at this cell.
export const PromptCellEditor = forwardRef((props: any, ref) => {
const refText = useRef<HTMLDivElement | null>(null);
const theme = extendTheme(themeFactory());

/* Component Editor Lifecycle methods */
useImperativeHandle(ref, () => {
return {
getValue() {
return props.value;
},
};
});


const [positivePrompt, negativePrompt] = props.value.split('--neg');

return (
<div
ref={refText}
className='ag-custom-component-popup prompt-details'
style={{
border: '1px solid #00c',
padding: '2px',
background: theme.vars.palette.background.paper,
overflow: 'wrap',
}}
>
<div
style = {{userSelect: 'text'}}>
<Typography fontSize={'1.1em'} fontFamily={'monospace'} color={theme.vars.palette.positive.main}> {positivePrompt}</Typography>
{
negativePrompt && <>
<Typography fontSize={'1.1em'} fontFamily={'monospace'} color={theme.vars.palette.text.primary }>--neg</Typography>
<Typography fontSize={'1.1em'} fontFamily={'monospace'} color={theme.vars.palette.negative.main} >{negativePrompt}</Typography>
</>
}
</div>
</div>
);
});
4 changes: 4 additions & 0 deletions src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,8 @@ p {
display: inline-block;
font-size: 1em;
line-height: .85em;
}

div.ag-popup-child:has(div.prompt-details) {
width: 50% !important
}
Loading

0 comments on commit 01a8cf2

Please sign in to comment.