openscad-playground/src/components/CustomizerPanel.tsx

208 lines
6.6 KiB
TypeScript
Raw Normal View History

2024-07-08 02:21:33 +01:00
// Portions of this file are Copyright 2021 Google LLC, and licensed under GPL2+. See COPYING.
import { CSSProperties, useContext } from 'react';
🌈 Colorful Playground (#37) * glb (color-assimp2 branch) + model-viewer * color support + customizable output format * cleanup * disable monaco on iOS * reinstate STL viewer when output is stl * default to stl * fix iOS editor * script to build openscad-wasm from a branch / local repo * update fork link + build instructions * Update build-openscad-wasm.sh * Update initial-state.ts * update openscad3 refs * update wasm build script * Update Dockerfile.wasm * add jszip dep * multimaterial: color conversion + 3MF face painting * ignore ts error about compression apis * Update tsconfig.json * multimaterial support w/ extruder colors input component * fix wasm build script * symlinks for openscad.{js,wasm} under src * fix error line shift for bundled files * remove obsolete build script * set OPENSCADPATH env var * render-colors feature renamed * Customizer + prepare Multi-asset support * hide customizer button if unselected, hide it if no params, * Create build-openscad-wasm.sh * update build script * complete sound * fetchSource util * wider rotation allowance * use CSG-modules.scad as default * Update CustomizerPanel.tsx * Update index.html * capture save, allow Ctrl+Shift+Save to save project * customizer: fieldsets are better than accordion * expand customizer tabs by default * tooltip for reset buttons * pretty c++ exceptions * Delete inline-openscad-worker.ts * shuffle ux * use uzip instead of jszip for 3mf materialization * handle legacy links * update links to fork * use render-modifiers feature from color-assimp2 in preview mode * include NopSCADlib's STL files in archive * bind global f5 / f6 * update homepage back to openscad2 * styling fixes (editor alpha, customizer margins) * Add help link for customizer * fix customizer sliders (also need to show value input) * fix vector customizer component * style fallback editor * shorter logs button * customizer: rm reset button tooltip * customizer: allow dnd on viewer below, tweak background * add lights to modelviewer using an env image (gltf lights hard to plug across assimp for now) * update customizer styles * Update .gitignore * add license for UZIP.js (MIT) * Update skybox-lights.jpg * Update actions.ts * include NopSCADlib's STLs * Update LICENSE.md * include YAPP_Box examples * limit customizer height * Update skybox-lights.jpg * Update skybox-lights.jpg * Update openscad-worker.ts * build-openscad-wasm.sh fix: docker won't mount files outside home directory * Use Google CDN instead of unpkg for modelviewer * tmp updates before merge * Add ccache support to build-openscad-wasm.sh * Fix makefile * Update README.md * Fix ts imports * Delete build-openscad-wasm.sh * Crude off -> glb converter * Remove assimp related code * gltf diffs * Build using head openscad * readme: Update build prerequisites * make: attempt to build wasm binary in parallel first * Remove 3mf extruder color mapping & fix render / export flows (render all 3d to off) * off2glb: triangulate faces + add default color * Add simple e2e puppeteer test * ci: update pinned build to master output artefact * Update Makefile * Update test.yml * Update test.yml * Update test.yml * Update test.yml * ci: use relative node version names * Update test.yml * state: Remove renderFormat, introduce is2D * disable service worker in devel mode * remove dead code * build: fix NODE_ENV define * ci: simplify env vars * cleanups * Update README.md
2024-12-22 22:41:35 +00:00
import { ModelContext } from './contexts';
2024-07-08 02:21:33 +01:00
import { Dropdown } from 'primereact/dropdown';
import { Slider } from 'primereact/slider';
import { Checkbox } from 'primereact/checkbox';
import { InputNumber } from 'primereact/inputnumber';
import { InputText } from 'primereact/inputtext';
import { Fieldset } from 'primereact/fieldset';
import { Parameter } from '../state/customizer-types';
import { Button } from 'primereact/button';
export default function CustomizerPanel({className, style}: {className?: string, style?: CSSProperties}) {
const model = useContext(ModelContext);
if (!model) throw new Error('No model');
const state = model.state;
const handleChange = (name: string, value: any) => {
model.setVar(name, value);
};
const groupedParameters = (state.parameterSet?.parameters ?? []).reduce((acc, param) => {
if (!acc[param.group]) {
acc[param.group] = [];
}
acc[param.group].push(param);
return acc;
}, {} as { [key: string]: any[] });
const groups = Object.entries(groupedParameters);
const collapsedTabSet = new Set(state.view.collapsedCustomizerTabs ?? []);
const setTabOpen = (name: string, open: boolean) => {
if (open) {
collapsedTabSet.delete(name);
} else {
collapsedTabSet.add(name)
}
model.mutate(s => s.view.collapsedCustomizerTabs = Array.from(collapsedTabSet));
}
return (
<div
className={className}
style={{
display: 'flex',
flexDirection: 'column',
🌈 Colorful Playground (#37) * glb (color-assimp2 branch) + model-viewer * color support + customizable output format * cleanup * disable monaco on iOS * reinstate STL viewer when output is stl * default to stl * fix iOS editor * script to build openscad-wasm from a branch / local repo * update fork link + build instructions * Update build-openscad-wasm.sh * Update initial-state.ts * update openscad3 refs * update wasm build script * Update Dockerfile.wasm * add jszip dep * multimaterial: color conversion + 3MF face painting * ignore ts error about compression apis * Update tsconfig.json * multimaterial support w/ extruder colors input component * fix wasm build script * symlinks for openscad.{js,wasm} under src * fix error line shift for bundled files * remove obsolete build script * set OPENSCADPATH env var * render-colors feature renamed * Customizer + prepare Multi-asset support * hide customizer button if unselected, hide it if no params, * Create build-openscad-wasm.sh * update build script * complete sound * fetchSource util * wider rotation allowance * use CSG-modules.scad as default * Update CustomizerPanel.tsx * Update index.html * capture save, allow Ctrl+Shift+Save to save project * customizer: fieldsets are better than accordion * expand customizer tabs by default * tooltip for reset buttons * pretty c++ exceptions * Delete inline-openscad-worker.ts * shuffle ux * use uzip instead of jszip for 3mf materialization * handle legacy links * update links to fork * use render-modifiers feature from color-assimp2 in preview mode * include NopSCADlib's STL files in archive * bind global f5 / f6 * update homepage back to openscad2 * styling fixes (editor alpha, customizer margins) * Add help link for customizer * fix customizer sliders (also need to show value input) * fix vector customizer component * style fallback editor * shorter logs button * customizer: rm reset button tooltip * customizer: allow dnd on viewer below, tweak background * add lights to modelviewer using an env image (gltf lights hard to plug across assimp for now) * update customizer styles * Update .gitignore * add license for UZIP.js (MIT) * Update skybox-lights.jpg * Update actions.ts * include NopSCADlib's STLs * Update LICENSE.md * include YAPP_Box examples * limit customizer height * Update skybox-lights.jpg * Update skybox-lights.jpg * Update openscad-worker.ts * build-openscad-wasm.sh fix: docker won't mount files outside home directory * Use Google CDN instead of unpkg for modelviewer * tmp updates before merge * Add ccache support to build-openscad-wasm.sh * Fix makefile * Update README.md * Fix ts imports * Delete build-openscad-wasm.sh * Crude off -> glb converter * Remove assimp related code * gltf diffs * Build using head openscad * readme: Update build prerequisites * make: attempt to build wasm binary in parallel first * Remove 3mf extruder color mapping & fix render / export flows (render all 3d to off) * off2glb: triangulate faces + add default color * Add simple e2e puppeteer test * ci: update pinned build to master output artefact * Update Makefile * Update test.yml * Update test.yml * Update test.yml * Update test.yml * ci: use relative node version names * Update test.yml * state: Remove renderFormat, introduce is2D * disable service worker in devel mode * remove dead code * build: fix NODE_ENV define * ci: simplify env vars * cleanups * Update README.md
2024-12-22 22:41:35 +00:00
maxHeight: '80vh',
2024-07-08 02:21:33 +01:00
overflow: 'scroll',
...style,
bottom: 'unset',
}}>
{groups.map(([group, params]) => (
<Fieldset
style={{
margin: '5px 10px 5px 10px',
// backgroundColor: 'transparent',
backgroundColor: 'rgba(255,255,255,0.4)',
}}
onCollapse={() => setTabOpen(group, false)}
onExpand={() => setTabOpen(group, true)}
collapsed={collapsedTabSet.has(group)}
key={group}
legend={group}
toggleable={true}>
{params.map((param) => (
<ParameterInput
key={param.name}
value={(state.params.vars ?? {})[param.name]}
param={param}
handleChange={handleChange} />
))}
</Fieldset>
))}
</div>
);
};
function ParameterInput({param, value, className, style, handleChange}: {param: Parameter, value: any, className?: string, style?: CSSProperties, handleChange: (key: string, value: any) => void}) {
return (
<div
style={{
flex: 1,
...style,
display: 'flex',
flexDirection: 'column',
}}>
<div
style={{
flex: 1,
display: 'flex',
margin: '10px -10px 10px 5px',
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
}}>
<div
style={{
flex: 1,
display: 'flex',
flexDirection: 'column',
}}>
<label><b>{param.name}</b></label>
<div>{param.caption}</div>
</div>
<div
style={{
display: 'flex',
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
}}>
{param.type === 'number' && 'options' in param && (
<Dropdown
style={{flex: 1}}
value={value || param.initial}
options={param.options}
onChange={(e) => handleChange(param.name, e.value)}
optionLabel="name"
optionValue="value"
/>
)}
{param.type === 'string' && param.options && (
<Dropdown
value={value || param.initial}
options={param.options}
onChange={(e) => handleChange(param.name, e.value)}
optionLabel="name"
optionValue="value"
/>
)}
{param.type === 'boolean' && (
<Checkbox
checked={value ?? param.initial}
onChange={(e) => handleChange(param.name, e.checked)}
/>
)}
{!Array.isArray(param.initial) && param.type === 'number' && !('options' in param) && (
<InputNumber
value={value || param.initial}
showButtons
size={5}
onValueChange={(e) => handleChange(param.name, e.value)}
/>
)}
{param.type === 'string' && !param.options && (
<InputText
style={{flex: 1}}
value={value || param.initial}
onChange={(e) => handleChange(param.name, e.target.value)}
/>
)}
{Array.isArray(param.initial) && 'min' in param && (
<div style={{
flex: 1,
display: 'flex',
flexDirection: 'row',
}}>
{param.initial.map((_, index) => (
<InputNumber
style={{flex: 1}}
key={index}
value={value?.[index] ?? (param.initial as any)[index]}
min={param.min}
max={param.max}
showButtons
size={5}
step={param.step}
onValueChange={(e) => {
const newArray = [...(value ?? param.initial)];
newArray[index] = e.value;
handleChange(param.name, newArray);
}}
/>
))}
</div>
)}
<Button
onClick={() => handleChange(param.name, param.initial)}
style={{
marginRight: '0',
visibility: value === undefined || (JSON.stringify(value) === JSON.stringify(param.initial)) ? 'hidden' : 'visible',
}}
tooltipOptions={{position: 'left'}}
icon='pi pi-refresh'
className='p-button-text'/>
</div>
</div>
{!Array.isArray(param.initial) && param.type === 'number' && param.min !== undefined && (
<Slider
style={{
flex: 1,
minHeight: '5px',
margin: '5px 40px 5px 5px',
}}
value={value || param.initial}
min={param.min}
max={param.max}
step={param.step}
onChange={(e) => handleChange(param.name, e.value)}
/>
)}
</div>
);
}