Skip to content

Commit

Permalink
[chore] Validate parameters for effects (#2450)
Browse files Browse the repository at this point in the history
Signed-off-by: Ihor Dykhta <[email protected]>
  • Loading branch information
igorDykhta authored Nov 20, 2023
1 parent d60ef31 commit 8405378
Show file tree
Hide file tree
Showing 9 changed files with 221 additions and 54 deletions.
7 changes: 6 additions & 1 deletion src/components/src/map-container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,12 @@ const DatasetAttributions = ({
{datasetAttributions?.length ? (
<StyledDatasetAttributionsContainer isPalm={isPalm}>
{datasetAttributions.map((ds, idx) => (
<a href={ds.url} target="_blank" rel="noopener noreferrer" key={`${ds.title}_${idx}`}>
<a
{...(ds.url ? {href: ds.url} : null)}
target="_blank"
rel="noopener noreferrer"
key={`${ds.title}_${idx}`}
>
{ds.title}
{idx !== datasetAttributions.length - 1 ? ', ' : null}
</a>
Expand Down
133 changes: 96 additions & 37 deletions src/constants/src/default-settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1192,11 +1192,7 @@ export const DEFAULT_LIGHT_COLOR: [number, number, number] = [255, 255, 255];
export const DEFAULT_LIGHT_INTENSITY = 1;
export const DEFAULT_SHADOW_INTENSITY = 0.5;
export const DEFAULT_SHADOW_COLOR: [number, number, number] = [0, 0, 0];
export const LIGHT_AND_SHADOW_EFFECT: EffectDescription = {
type: 'lightAndShadow',
name: 'Light & Shadow',
parameters: []
};

export const LIGHT_AND_SHADOW_EFFECT_TIME_MODES = {
pick: 'pick' as 'pick',
current: 'current' as 'current',
Expand All @@ -1223,51 +1219,79 @@ export const DEFAULT_LIGHT_AND_SHADOW_PROPS: {
ambientLightIntensity: DEFAULT_LIGHT_INTENSITY
};

export const LIGHT_AND_SHADOW_EFFECT: EffectDescription = {
type: 'lightAndShadow',
name: 'Light & Shadow',
parameters: [
{name: 'timestamp', min: 0, max: Number.MAX_SAFE_INTEGER},
{name: 'shadowIntensity', min: 0, max: 1, defaultValue: DEFAULT_SHADOW_INTENSITY},
{name: 'sunLightIntensity', min: 0, max: 1, defaultValue: DEFAULT_LIGHT_INTENSITY},
{name: 'ambientLightIntensity', min: 0, max: 1, defaultValue: DEFAULT_LIGHT_INTENSITY},
{name: 'shadowColor', type: 'color', min: 0, max: 255, defaultValue: DEFAULT_SHADOW_COLOR},
{name: 'sunLightColor', type: 'color', min: 0, max: 255, defaultValue: DEFAULT_LIGHT_COLOR},
{name: 'ambientLightColor', type: 'color', min: 0, max: 255, defaultValue: DEFAULT_LIGHT_COLOR}
]
};

export const POSTPROCESSING_EFFECTS: {[key: string]: EffectDescription} = {
ink: {
type: 'ink',
name: 'Ink',
parameters: [{name: 'strength'}]
parameters: [{name: 'strength', min: 0, max: 1}]
},
brightnessContrast: {
type: 'brightnessContrast',
name: 'Brightness & Contrast',
parameters: [{name: 'brightness'}, {name: 'contrast'}]
parameters: [
{name: 'brightness', min: -1, max: 1},
{name: 'contrast', min: -1, max: 1}
]
},
hueSaturation: {
type: 'hueSaturation',
name: 'Hue & Saturation',
parameters: [{name: 'hue'}, {name: 'saturation', default: 0.25}]
parameters: [
{name: 'hue', min: -1, max: 1},
{name: 'saturation', defaultValue: 0.25, min: -1, max: 1}
]
},
vibrance: {
type: 'vibrance',
name: 'Vibrance',
parameters: [{name: 'amount', default: 0.5}]
parameters: [{name: 'amount', defaultValue: 0.5, min: -1, max: 1}]
},
sepia: {
type: 'sepia',
name: 'Sepia',
parameters: [{name: 'amount'}]
parameters: [{name: 'amount', min: 0, max: 1}]
},
dotScreen: {
type: 'dotScreen',
name: 'Dot Screen',
parameters: [
{
name: 'angle'
name: 'angle',
min: 0,
max: Math.PI / 2
},
{
name: 'size'
name: 'size',
min: 1,
max: 20
},
{
name: 'center',
label: 'Center X',
index: 0
index: 0,
min: 0,
max: 1
},
{
name: 'center',
label: 'Center Y',
index: 1
index: 1,
min: 0,
max: 1
}
]
},
Expand All @@ -1276,50 +1300,64 @@ export const POSTPROCESSING_EFFECTS: {[key: string]: EffectDescription} = {
name: 'Color Halftone',
parameters: [
{
name: 'angle'
name: 'angle',
min: 0,
max: Math.PI / 2
},
{
name: 'size'
name: 'size',
min: 1,
max: 20
},
{
name: 'center',
label: 'Center X',
index: 0
index: 0,
min: 0,
max: 1
},
{
name: 'center',
label: 'Center Y',
index: 1
index: 1,
min: 0,
max: 1
}
]
},
noise: {
type: 'noise',
name: 'Noise',
parameters: [{name: 'amount'}]
parameters: [{name: 'amount', min: 0, max: 1}]
},
triangleBlur: {
type: 'triangleBlur',
name: 'Blur (Triangle)',
parameters: [{name: 'radius'}, {name: 'delta'}]
parameters: [{name: 'radius', min: 0, max: 100}]
},
zoomBlur: {
type: 'zoomBlur',
name: 'Blur (Zoom)',
parameters: [
{
name: 'strength',
default: 0.05
defaultValue: 0.05,
min: 0,
max: 1
},
{
name: 'center',
label: 'Center X',
index: 0
index: 0,
min: 0,
max: 1
},
{
name: 'center',
label: 'Center Y',
index: 1
index: 1,
min: 0,
max: 1
}
]
},
Expand All @@ -1329,41 +1367,56 @@ export const POSTPROCESSING_EFFECTS: {[key: string]: EffectDescription} = {
parameters: [
{
name: 'blurRadius',
label: 'Blur'
label: 'Blur',
min: 0,
max: 50
},
{
name: 'gradientRadius',
label: 'Gradient'
label: 'Gradient',
min: 0,
max: 400
},
{
name: 'start',
index: 0
index: 0,
min: 0,
max: 1
},
{
name: 'start',
label: false,
index: 1
index: 1,
min: 0,
max: 1
},
{
name: 'end',
index: 0
index: 0,
min: 0,
max: 1
},
{
name: 'end',
label: false,
index: 1
index: 1,
min: 0,
max: 1
}
]
},
edgeWork: {
type: 'edgeWork',
name: 'Edge work',
parameters: [{name: 'radius'}, {name: 'delta'}]
parameters: [{name: 'radius', min: 1, max: 50}]
},
vignette: {
type: 'vignette',
name: 'Vignette',
parameters: [{name: 'amount'}, {name: 'radius'}]
parameters: [
{name: 'amount', min: 0, max: 1},
{name: 'radius', min: 0, max: 1}
]
},
magnify: {
type: 'magnify',
Expand All @@ -1373,18 +1426,23 @@ export const POSTPROCESSING_EFFECTS: {[key: string]: EffectDescription} = {
name: 'screenXY',
label: 'Position X',
index: 0,
default: 0.5
defaultValue: 0.5,
min: 0,
max: 1
},
{
name: 'screenXY',
label: 'Position Y',
index: 1,
default: 0.5
defaultValue: 0.5,
min: 0,
max: 1
},
{
name: 'radiusPixels',
label: 'Size',
min: 10
min: 10,
max: 500
},
{
name: 'zoom',
Expand All @@ -1394,15 +1452,16 @@ export const POSTPROCESSING_EFFECTS: {[key: string]: EffectDescription} = {
{
name: 'borderWidthPixels',
label: 'Border Width',
default: 3,
max: 100
defaultValue: 3,
min: 0,
max: 50
}
]
},
hexagonalPixelate: {
type: 'hexagonalPixelate',
name: 'Hexagonal Pixelate',
parameters: [{name: 'scale', default: 20}]
parameters: [{name: 'scale', defaultValue: 20, min: 0, max: 50}]
}
};

Expand Down
20 changes: 15 additions & 5 deletions src/effects/src/effect.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import {generateHashId} from '@kepler.gl/utils';
import {generateHashId, validateEffectParameters} from '@kepler.gl/utils';
import {
Effect as EffectInterface,
EffectProps,
EffectPropsPartial,
EffectParameterDescription
} from '@kepler.gl/types';
import {DEFAULT_POST_PROCESSING_EFFECT_TYPE, POSTPROCESSING_EFFECTS} from '@kepler.gl/constants';
import {
DEFAULT_POST_PROCESSING_EFFECT_TYPE,
POSTPROCESSING_EFFECTS,
LIGHT_AND_SHADOW_EFFECT
} from '@kepler.gl/constants';

export class Effect implements EffectInterface {
id: string;
Expand All @@ -27,9 +31,12 @@ export class Effect implements EffectInterface {
this.isEnabled = _props.isEnabled;
this.isConfigActive = _props.isConfigActive;
this.isJsonEditorActive = _props.isJsonEditorActive;
this.parameters = _props.parameters;

this._uiConfig = POSTPROCESSING_EFFECTS[this.type]?.parameters || [];
this._uiConfig =
LIGHT_AND_SHADOW_EFFECT.type === this.type
? LIGHT_AND_SHADOW_EFFECT.parameters
: POSTPROCESSING_EFFECTS[this.type]?.parameters || [];
this.parameters = validateEffectParameters(_props.parameters, this._uiConfig);

this.deckEffect = null;
this._initializeEffect();
Expand All @@ -56,7 +63,10 @@ export class Effect implements EffectInterface {
this.isEnabled = props.isEnabled ?? this.isEnabled;
this.isConfigActive = props.isConfigActive ?? this.isConfigActive;
this.isJsonEditorActive = props.isJsonEditorActive ?? this.isJsonEditorActive;
this.parameters = {...this.parameters, ...props.parameters};
this.parameters = {
...this.parameters,
...validateEffectParameters(props.parameters, this._uiConfig)
};
}

isValidToSave() {
Expand Down
6 changes: 2 additions & 4 deletions src/effects/src/post-processing-effect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,8 @@ const POSTPROCESSING_EFFECTS_DESCS = [
*/
const getDefaultValueForParameter = (name, effectDescription) => {
const rec = effectDescription.filter(param => param.name === name);
if (rec.length === 1) return rec[0].default;
else if (rec.length === 2 && rec[0].default !== undefined && rec[1].default !== undefined) {
return [rec[0].default, rec[1].default];
}
if (rec.length === 1) return rec[0].defaultValue;
else if (rec.length === 2) return [rec[0].defaultValue, rec[1].defaultValue];
};

class PostProcessingEffect extends Effect {
Expand Down
3 changes: 2 additions & 1 deletion src/schemas/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ export {
filterPropsV1,
default as visStateSchema,
layerPropsV1,
layerPropsV0
layerPropsV0,
effectPropsV1
} from './vis-state-schema';
export type {
SavedField,
Expand Down
7 changes: 4 additions & 3 deletions src/types/effects.d.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
export type EffectParameterDescription = {
name: string;
type?: 'number' | 'color';
label?: string | false;
index?: number;
min?: number;
max?: number;
default?: number;
min: number;
max: number;
defaultValue?: number | number[];
};

export type EffectDescription = {
Expand Down
Loading

0 comments on commit 8405378

Please sign in to comment.