Zum Inhalt

src/ui/SpeciesPanel.tsx

import { type Component, Show } from 'solid-js';
import type { SpeciesParams } from '~/engine/types';
import { ColorRow } from './ColorRow';
import { ParamSlider } from './ParamSlider';

interface Props {
  species: SpeciesParams;
  onChange: <K extends keyof SpeciesParams>(key: K, value: SpeciesParams[K]) => void;
  /** When provided, each slider shows a reset-to-preset-default button. */
  onReset?: <K extends keyof SpeciesParams>(key: K) => void;
  /** Hide the population-share slider — used in the "All" tab, where
   *  writing the same value to all three species would just normalise
   *  to a 1/3 / 1/3 / 1/3 distribution regardless of the value. */
  hidePopulationShare?: boolean;
}

export const SpeciesPanel: Component<Props> = (props) => {
  const reset = <K extends keyof SpeciesParams>(key: K): (() => void) | undefined =>
    props.onReset ? () => props.onReset?.(key) : undefined;

  return (
    <div style={{ display: 'flex', 'flex-direction': 'column', gap: '18px' }}>
      <ColorRow
        label="Species color"
        color={props.species.color}
        onChange={(c) => props.onChange('color', c)}
      />
      <Show when={!props.hidePopulationShare}>
        <ParamSlider
          name="Population share"
          value={props.species.populationShare}
          min={0}
          max={1}
          onChange={(v) => props.onChange('populationShare', v)}
          onReset={reset('populationShare')}
        />
      </Show>
      <ParamSlider
        name="Move speed"
        value={props.species.moveSpeed}
        min={0}
        max={10}
        unit=" px/frame"
        ticks={6}
        onChange={(v) => props.onChange('moveSpeed', v)}
        onReset={reset('moveSpeed')}
      />
      <ParamSlider
        name="Turn speed"
        value={props.species.turnSpeed}
        min={0}
        max={2}
        unit=" rad"
        onChange={(v) => props.onChange('turnSpeed', v)}
        onReset={reset('turnSpeed')}
      />
      <ParamSlider
        name="Sensor angle"
        value={props.species.sensorAngle * (180 / Math.PI)}
        min={0}
        max={180}
        unit="°"
        onChange={(v) => props.onChange('sensorAngle', v * (Math.PI / 180))}
        onReset={reset('sensorAngle')}
      />
      <ParamSlider
        name="Sensor distance"
        value={props.species.sensorDistance}
        min={1}
        max={80}
        unit=" px"
        onChange={(v) => props.onChange('sensorDistance', v)}
        onReset={reset('sensorDistance')}
      />
      <ParamSlider
        name="Deposit amount"
        value={props.species.depositAmount}
        min={0}
        max={100}
        onChange={(v) => props.onChange('depositAmount', v)}
        onReset={reset('depositAmount')}
      />
    </div>
  );
};