Skip to content

Commit

Permalink
Complex Presets as Partial Scenes: Blender
Browse files Browse the repository at this point in the history
  • Loading branch information
YeonV committed Nov 14, 2024
1 parent 46eccbd commit 08a8e9f
Show file tree
Hide file tree
Showing 4 changed files with 202 additions and 12 deletions.
9 changes: 3 additions & 6 deletions src/pages/Device/Device.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useEffect } from 'react'
import { Card, Grid, Stack, Typography } from '@mui/material'
import { Grid, Stack, Typography } from '@mui/material'
import { Link, useNavigate, useParams } from 'react-router-dom'
import useStore from '../../store/useStore'
import EffectsCard from './Effects'
Expand All @@ -10,6 +10,7 @@ import StreamToCard from './StreamTo'
import EffectsComplex from './EffectsComplex'
import { Virtual } from '../../store/api/storeVirtuals'
import { defaultEffects } from '../Home/BladeScene'
import PresetsComplex from './PresetsComplex'

const Device = () => {
const navigate = useNavigate()
Expand Down Expand Up @@ -212,11 +213,7 @@ const Device = () => {
<EffectsComplex virtId={`${virtId}-mask`} key={`${virtId}-mask`} initMatix={matrixOpen} />
<EffectsComplex virtId={`${virtId}-foreground`} key={`${virtId}-foreground`} initMatix={matrixOpen} />
<EffectsComplex virtId={`${virtId}-background`} key={`${virtId}-background`} initMatix={matrixOpen} />
<Card sx={{ padding: '16px'}} variant="outlined">
<Typography variant="body2" color="textSecondary">
No presets available for complex effects. Please use scenes to save your configuration.
</Typography>
</Card>
<PresetsComplex virtId={virtId} />
</Stack>
</Grid>}

Expand Down
190 changes: 190 additions & 0 deletions src/pages/Device/PresetsComplex.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
import {
Button,
Card,
CardContent,
CardHeader,
Grid,
Menu,
TextField,
Typography,
useTheme
} from '@mui/material'
import { Add } from '@mui/icons-material'
import Popover from '../../components/Popover/Popover'
import useStore from '../../store/useStore'
import { useState } from 'react'

const PresetsComplex = ({virtId}: {virtId: string}) => {
const theme = useTheme()
const [name, setName] = useState('')
const [valid, setValid] = useState(true)
const [anchorEl, setAnchorEl] = useState<any>(null)
const [sceneToDelete, setSceneToDelete] = useState<string | null>(null)

const virtuals = useStore((state) => state.virtuals)
const scenes = useStore((state) => state.scenes)
const addScene = useStore((state) => state.addScene)
const getScenes = useStore((state) => state.getScenes)
const activateScene = useStore((state) => state.activateScene)
const deleteScene = useStore((state) => state.deleteScene)

const sceneBlenderFilter = (sc: string) => (scenes[sc].scene_tags?.split(',')?.includes('blender') && virtId && sc.startsWith(virtId))

const handleAddScene = () => {
if (!virtId || name.length === 0) return
addScene(
`${virtId}-${name}`,
'yz:logo3',
'blender',
null,
null,
null,
{
[virtId]: virtuals[virtId].effect,
[`${virtId}-mask`]: virtuals[`${virtId}-mask`].effect,
[`${virtId}-foreground`]: virtuals[`${virtId}-foreground`].effect,
[`${virtId}-background`]: virtuals[`${virtId}-background`].effect,
}
).then(() => {
getScenes()
})
setName('')
}

return (
<Card sx={{ padding: '16px' }} variant="outlined">
<CardHeader
style={{ margin: '0' }}
title="Presets"
subheader="complex effects utilize partial scenes for presets."
/>
<CardContent>
<Grid spacing={2} container>
{Object.keys(scenes).filter(sceneBlenderFilter).length > 0 &&
Object.keys(scenes)
.filter(sceneBlenderFilter)
.map((scene) => (
<Grid item key={scene}>
<Button
onContextMenu={(e) => {
e.preventDefault()
setSceneToDelete(scene)
setAnchorEl(e.currentTarget || e.target)
}}
onClick={() => {
activateScene(scene?.toLowerCase().replaceAll(' ', '-'))
}}
>
{scene.replace(virtId + '-', '')}
</Button>
</Grid>
))}
<Grid item key={'newPartialScene'}>
<Popover
icon={<Add />}
content={
<TextField
onKeyDown={(e: any) => e.key === 'Enter' && handleAddScene()}
error={
scenes &&
(Object.keys(scenes).indexOf(name) > -1 ||
Object.values(scenes).filter((p: any) => p.name === name)
.length > 0)
}
size="small"
id="presetNameInput"
label={
scenes &&
(Object.keys(scenes).indexOf(name) > -1 ||
Object.values(scenes).filter((p: any) => p.name === name)
.length > 0)
? 'Partial Scene already exsisting'
: 'Add Partial Scene'
}
style={{ marginRight: '1rem', flex: 1 }}
value={name}
onChange={(e) => {
setName(e.target.value)
if (
scenes &&
(Object.keys(scenes).indexOf(e.target.value) > -1 ||
Object.values(scenes).filter(
(p: any) => p.name === e.target.value
).length > 0)
) {
setValid(false)
} else {
setValid(true)
}
}}
/>
}
footer={
<div style={{ margin: '0 0 0.5rem 1rem' }}>
<Typography
variant="body2"
sx={{ color: theme.palette.text.disabled }}
>
Save the current effect configuration as a new preset.
</Typography>
</div>
}
confirmDisabled={
name.length === 0 ||
(scenes &&
(Object.keys(scenes).indexOf(name) > -1 ||
Object.values(scenes).filter((p: any) => p.name === name)
.length > 0)) ||
!valid
}
onConfirm={handleAddScene}
size="medium"
/>
</Grid>
</Grid>
</CardContent>
<Menu
id="basic-menu"
anchorEl={anchorEl}
open={Boolean(anchorEl)}
onClose={() => setAnchorEl(null)}
// className={classes.bladeMenu}
MenuListProps={{
'aria-labelledby': 'basic-button'
}}
anchorOrigin={{
vertical: 'bottom',
horizontal: 'center'
}}
transformOrigin={{
vertical: 'top',
horizontal: 'center'
}}
>
<div>
<Popover
type="menuItem"
onConfirm={() =>
sceneToDelete &&
deleteScene(sceneToDelete).then(() => {
getScenes()
setAnchorEl(null)
})
}
label="Delete Preset"
anchorOrigin={{
vertical: 'top',
horizontal: 'center'
}}
transformOrigin={{
vertical: 'bottom',
horizontal: 'center'
}}
/>
</div>
</Menu>
</Card>
)
}

export default PresetsComplex
5 changes: 4 additions & 1 deletion src/pages/Scenes/Scenes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ const Scenes = () => {
?.split(',')
.some((sce: string) => sceneActiveTags.includes(sce))

const sceneBlenderFilter = (sc: string) => !(scenes[sc].scene_tags?.split(',')?.includes('blender'))
return (
<>
<div
Expand Down Expand Up @@ -186,7 +187,9 @@ const Scenes = () => {
(sceneActiveTags.length
? Object.keys(scenes).filter(sceneFilter)
: Object.keys(scenes)
).map((s, i) => {
)
.filter(sceneBlenderFilter)
.map((s, i) => {
return (
<Grid
item
Expand Down
10 changes: 5 additions & 5 deletions src/store/api/storeScenes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -197,11 +197,11 @@ const storeScenes = (set: any) => ({
},
addScene: async (
name: string,
scene_image?: string,
scene_tags?: string,
scene_puturl?: string,
scene_payload?: string,
scene_midiactivate?: string,
scene_image?: string | null,
scene_tags?: string | null,
scene_puturl?: string | null,
scene_payload?: string | null,
scene_midiactivate?: string | null,
virtuals?: Record<string, any>
) =>
virtuals
Expand Down

0 comments on commit 08a8e9f

Please sign in to comment.