Merge branch 'feature/color-parameter-sliders' of https://github.com/corinna000/mystic-symbolic into corinna000-feature/color-parameter-sliders
						commit
						aaf8d2e1f8
					
				| 
						 | 
				
			
			@ -60,17 +60,18 @@ const EYE_CREATURE = (
 | 
			
		|||
);
 | 
			
		||||
 | 
			
		||||
const RandomColorSampling: React.FC<{}> = () => {
 | 
			
		||||
  const [paletteConfig, setPaletteConfig] = useState({})
 | 
			
		||||
  const [paletteAlg, setPaletteAlg] = useState<RandomPaletteAlgorithm>(
 | 
			
		||||
    DEFAULT_RANDOM_PALETTE_ALGORITHM
 | 
			
		||||
  );
 | 
			
		||||
  const [seed, setSeed] = useState(Date.now());
 | 
			
		||||
  const NUM_COLORS = 100;
 | 
			
		||||
  const rng = new Random(seed);
 | 
			
		||||
  const palette = createRandomColorPalette(NUM_COLORS, rng, paletteAlg);
 | 
			
		||||
  const palette = createRandomColorPalette(NUM_COLORS, rng, paletteAlg, paletteConfig);
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <>
 | 
			
		||||
      <PaletteAlgorithmWidget value={paletteAlg} onChange={setPaletteAlg} />
 | 
			
		||||
      <PaletteAlgorithmWidget value={paletteAlg} onChange={setPaletteAlg} onPaletteConfigChange={setPaletteConfig} />
 | 
			
		||||
      <div className="thingy">
 | 
			
		||||
        <div style={{ fontSize: 0 }}>
 | 
			
		||||
          {range(NUM_COLORS).map((i) => (
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,22 +1,55 @@
 | 
			
		|||
import React from "react";
 | 
			
		||||
import React, {useEffect, useState} from "react";
 | 
			
		||||
import {
 | 
			
		||||
  RandomPaletteAlgorithm,
 | 
			
		||||
  RANDOM_PALETTE_ALGORITHMS,
 | 
			
		||||
  RANDOM_PALETTE_ALGORITHMS, PaletteAlgorithmConfig,
 | 
			
		||||
} from "./random-colors";
 | 
			
		||||
 | 
			
		||||
export type PaletteAlgorithmWidgetProps = {
 | 
			
		||||
  value: RandomPaletteAlgorithm;
 | 
			
		||||
  onChange: (value: RandomPaletteAlgorithm) => void;
 | 
			
		||||
  onPaletteConfigChange: (value: PaletteAlgorithmConfig) => void;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const PaletteAlgorithmWidget: React.FC<PaletteAlgorithmWidgetProps> = ({
 | 
			
		||||
  value,
 | 
			
		||||
  onChange,
 | 
			
		||||
  onPaletteConfigChange = () => {}
 | 
			
		||||
}) => {
 | 
			
		||||
  const id = "algorithm";
 | 
			
		||||
  const [paletteConfig, setPaletteConfig] = useState<PaletteAlgorithmConfig>({
 | 
			
		||||
    hue: 120,
 | 
			
		||||
    hueInterval: 15,
 | 
			
		||||
    saturation: 50,
 | 
			
		||||
    valueMin: 20,
 | 
			
		||||
    valueMax: 80,
 | 
			
		||||
  });
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    onPaletteConfigChange(paletteConfig);
 | 
			
		||||
  }, [paletteConfig])
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <div className="flex-widget thingy">
 | 
			
		||||
      {value === "threevals" && (
 | 
			
		||||
        <div className="flex-widget thingy">
 | 
			
		||||
          <label>Hue {paletteConfig.hue}</label>
 | 
			
		||||
          <input type="range" min="0" max="360" value={paletteConfig.hue}
 | 
			
		||||
                 onChange={(e) => setPaletteConfig({...paletteConfig, hue: Number(e.target.value) }) } />
 | 
			
		||||
          <label>Hue Interval {paletteConfig.hueInterval}</label>
 | 
			
		||||
          <input type="range" min="0" max="120" value={paletteConfig.hueInterval}
 | 
			
		||||
                 onChange={(e) => setPaletteConfig({...paletteConfig, hueInterval: Number(e.target.value) }) }
 | 
			
		||||
          />
 | 
			
		||||
          <label>Value min {paletteConfig.valueMin}</label>
 | 
			
		||||
          <input type="range" min="0" max="100" value={paletteConfig.valueMin}
 | 
			
		||||
                 onChange={(e) => setPaletteConfig({...paletteConfig, valueMin: Number(e.target.value) }) }
 | 
			
		||||
          />
 | 
			
		||||
          <label>Value Max {paletteConfig.valueMax}</label>
 | 
			
		||||
          <input type="range" min="0" max="100" value={paletteConfig.valueMax}
 | 
			
		||||
                 onChange={(e) => setPaletteConfig({...paletteConfig, valueMax: Number(e.target.value) }) }
 | 
			
		||||
          />
 | 
			
		||||
          <label>Saturation {paletteConfig.saturation}</label>
 | 
			
		||||
          <input type="range" min="0" max="100" value={paletteConfig.saturation}
 | 
			
		||||
                 onChange={(e) => setPaletteConfig({...paletteConfig, saturation: Number(e.target.value) }) }
 | 
			
		||||
          /></div>)}
 | 
			
		||||
      <label htmlFor={id}>Palette algorithm: </label>
 | 
			
		||||
      <select
 | 
			
		||||
        id={id}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,8 +4,18 @@ import * as colorspaces from "colorspaces";
 | 
			
		|||
import { ColorTuple, hsluvToHex } from "hsluv";
 | 
			
		||||
import { clampedBytesToRGBColor } from "./color-util";
 | 
			
		||||
 | 
			
		||||
type RandomPaletteGenerator = (numEntries: number, rng: Random) => string[];
 | 
			
		||||
//type ColorFunction = (rng: Random) => string[];
 | 
			
		||||
export interface PaletteAlgorithmConfig {
 | 
			
		||||
  valueMin?: number,
 | 
			
		||||
  valueMax?: number,
 | 
			
		||||
  hue?: number,
 | 
			
		||||
  hueInterval?: number
 | 
			
		||||
  saturation?: number
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type RandomPaletteGenerator = (numEntries: number, rng: Random, config: PaletteAlgorithmConfig) => string[];
 | 
			
		||||
// type ColorFunction = (rng: Random) => string[];
 | 
			
		||||
// type ColorFunctionConfig = () => string[];
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
export type RandomPaletteAlgorithm = "RGB" | "CIELUV" | "threevals";
 | 
			
		||||
//  | "randgrey"
 | 
			
		||||
| 
						 | 
				
			
			@ -80,23 +90,21 @@ function createRandGrey(rng: Random): string[] {
 | 
			
		|||
}
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
function create3V180(angle1: number): ColorFunction {
 | 
			
		||||
  return (rng: Random): string[] => {
 | 
			
		||||
    let Ls = [25, 50, 75];
 | 
			
		||||
function create3Vconfig() {
 | 
			
		||||
  return (rng: Random, config: PaletteAlgorithmConfig): string[] => {
 | 
			
		||||
    const LMin = config.valueMin ? config.valueMin : 25;
 | 
			
		||||
    const LMax = config.valueMax? config.valueMax: 75;
 | 
			
		||||
    let Ls = [LMin, 50, LMax];
 | 
			
		||||
 | 
			
		||||
    //Now we have 3 lightness values, pick a random hue and sat
 | 
			
		||||
    let h1 = rng.inInterval({ min: 0, max: 360 }),
 | 
			
		||||
      h2 = 360 * (((h1 + angle1) / 360) % 1),
 | 
			
		||||
      h3 = 360 * (((h1 + 180) / 360) % 1);
 | 
			
		||||
    let h1 = config.hue ? config.hue : rng.inInterval({ min: 0, max: 360 }),
 | 
			
		||||
      h2 = 360 * (((h1 + (config.hueInterval ? config.hueInterval : 120)) / 360) % 1),
 | 
			
		||||
      h3 = 360 * (((h2 + (config.hueInterval ? config.hueInterval : 240)) / 360) % 1);
 | 
			
		||||
 | 
			
		||||
    let Hs = [h1, h2, h3];
 | 
			
		||||
 | 
			
		||||
    let Ss = [
 | 
			
		||||
      rng.fromGaussian({ mean: 100, stddev: 40 }),
 | 
			
		||||
      rng.fromGaussian({ mean: 100, stddev: 40 }),
 | 
			
		||||
      rng.fromGaussian({ mean: 100, stddev: 40 }),
 | 
			
		||||
    ];
 | 
			
		||||
    const sat = config.saturation ? config.saturation : rng.fromGaussian({ mean: 100, stddev: 40 });
 | 
			
		||||
    let Ss = [ sat, sat, sat ];
 | 
			
		||||
    Ss = Ss.map((x) => clamp(x, 0, 100));
 | 
			
		||||
 | 
			
		||||
    //zip
 | 
			
		||||
| 
						 | 
				
			
			@ -108,41 +116,40 @@ function create3V180(angle1: number): ColorFunction {
 | 
			
		|||
    return hexcolors;
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
function threeVColor(rng: Random): string[] {
 | 
			
		||||
  let L1 = rng.inInterval({ min: 10, max: 25 });
 | 
			
		||||
  let L2 = rng.inInterval({ min: L1 + 25, max: 60 });
 | 
			
		||||
  let L3 = rng.inInterval({ min: L2 + 25, max: 85 });
 | 
			
		||||
 | 
			
		||||
  let Ls = [L1, L2, L3];
 | 
			
		||||
 | 
			
		||||
  let angleI = rng.inInterval({ min: 0, max: 120 });
 | 
			
		||||
 | 
			
		||||
  //Now we have 3 lightness values, pick a random hue and sat
 | 
			
		||||
  let h1 = rng.inInterval({ min: 0, max: 360 }),
 | 
			
		||||
    h2 = h1 + angleI,
 | 
			
		||||
    h3 = 360 * ((((h1 + h2) / 2 + 180) / 360) % 1);
 | 
			
		||||
 | 
			
		||||
  h2 = 360 * ((h2 / 360) % 1);
 | 
			
		||||
 | 
			
		||||
  let Hs = [h1, h2, h3];
 | 
			
		||||
 | 
			
		||||
  let Ss = [
 | 
			
		||||
    rng.fromGaussian({ mean: 100, stddev: 40 }),
 | 
			
		||||
    rng.fromGaussian({ mean: 100, stddev: 40 }),
 | 
			
		||||
    rng.fromGaussian({ mean: 100, stddev: 40 }),
 | 
			
		||||
  ];
 | 
			
		||||
  Ss = Ss.map((x) => clamp(x, 0, 100));
 | 
			
		||||
 | 
			
		||||
  //zip
 | 
			
		||||
  let hsls = Ls.map((k, i) => [Hs[i], Ss[i], k]);
 | 
			
		||||
  let hexcolors = hsls.map((x) => hsluvToHex(x as ColorTuple));
 | 
			
		||||
 | 
			
		||||
  //scramble order
 | 
			
		||||
  hexcolors = rng.uniqueChoices(hexcolors, hexcolors.length);
 | 
			
		||||
  return hexcolors;
 | 
			
		||||
}
 | 
			
		||||
// function threeVColor(rng: Random): string[] {
 | 
			
		||||
//   let L1 = rng.inInterval({ min: 10, max: 25 });
 | 
			
		||||
//   let L2 = rng.inInterval({ min: L1 + 25, max: 60 });
 | 
			
		||||
//   let L3 = rng.inInterval({ min: L2 + 25, max: 85 });
 | 
			
		||||
//
 | 
			
		||||
//   let Ls = [L1, L2, L3];
 | 
			
		||||
//
 | 
			
		||||
//   let angleI = rng.inInterval({ min: 0, max: 120 });
 | 
			
		||||
//
 | 
			
		||||
//   //Now we have 3 lightness values, pick a random hue and sat
 | 
			
		||||
//   let h1 = rng.inInterval({ min: 0, max: 360 }),
 | 
			
		||||
//     h2 = h1 + angleI,
 | 
			
		||||
//     h3 = 360 * ((((h1 + h2) / 2 + 180) / 360) % 1);
 | 
			
		||||
//
 | 
			
		||||
//   h2 = 360 * ((h2 / 360) % 1);
 | 
			
		||||
//
 | 
			
		||||
//   let Hs = [h1, h2, h3];
 | 
			
		||||
//
 | 
			
		||||
//   let Ss = [
 | 
			
		||||
//     rng.fromGaussian({ mean: 100, stddev: 40 }),
 | 
			
		||||
//     rng.fromGaussian({ mean: 100, stddev: 40 }),
 | 
			
		||||
//     rng.fromGaussian({ mean: 100, stddev: 40 }),
 | 
			
		||||
//   ];
 | 
			
		||||
//   Ss = Ss.map((x) => clamp(x, 0, 100));
 | 
			
		||||
//
 | 
			
		||||
//   //zip
 | 
			
		||||
//   let hsls = Ls.map((k, i) => [Hs[i], Ss[i], k]);
 | 
			
		||||
//   let hexcolors = hsls.map((x) => hsluvToHex(x as ColorTuple));
 | 
			
		||||
//
 | 
			
		||||
//   //scramble order
 | 
			
		||||
//   hexcolors = rng.uniqueChoices(hexcolors, hexcolors.length);
 | 
			
		||||
//   return hexcolors;
 | 
			
		||||
// }
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
function threeVColor(rng: Random): string[] {
 | 
			
		||||
| 
						 | 
				
			
			@ -203,16 +210,16 @@ function createSimplePaletteGenerator(
 | 
			
		|||
 */
 | 
			
		||||
 | 
			
		||||
function createTriadPaletteGenerator(
 | 
			
		||||
  createTriad: (rng: Random) => string[]
 | 
			
		||||
  createTriad: (rng: Random, config: PaletteAlgorithmConfig) => string[]
 | 
			
		||||
): RandomPaletteGenerator {
 | 
			
		||||
  return (numEntries: number, rng: Random): string[] => {
 | 
			
		||||
  return (numEntries: number, rng: Random, config?): string[] => {
 | 
			
		||||
    let colors: string[] = [];
 | 
			
		||||
    let n = Math.floor(numEntries / 3) + 1;
 | 
			
		||||
 | 
			
		||||
    if (numEntries == 3) {
 | 
			
		||||
      colors = colors.concat(createTriad(rng));
 | 
			
		||||
      colors = colors.concat(createTriad(rng, config));
 | 
			
		||||
    } else {
 | 
			
		||||
      for (let i = 0; i < n; i++) colors = colors.concat(createTriad(rng));
 | 
			
		||||
      for (let i = 0; i < n; i++) colors = colors.concat(createTriad(rng, config));
 | 
			
		||||
      colors = colors.slice(0, numEntries);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -225,7 +232,8 @@ const PALETTE_GENERATORS: {
 | 
			
		|||
} = {
 | 
			
		||||
  RGB: createSimplePaletteGenerator(createRandomRGBColor),
 | 
			
		||||
  CIELUV: createSimplePaletteGenerator(createRandomCIELUVColor),
 | 
			
		||||
  threevals: createTriadPaletteGenerator(threeVColor),
 | 
			
		||||
  threevals: createTriadPaletteGenerator(create3Vconfig()),
 | 
			
		||||
  // threevals: createTriadPaletteGenerator(threeVColor),
 | 
			
		||||
  //randgrey: createTriadPaletteGenerator(createRandGrey),
 | 
			
		||||
  //threev15: createTriadPaletteGenerator(create3V180(15)),
 | 
			
		||||
  //threev30: createTriadPaletteGenerator(create3V180(15)),
 | 
			
		||||
| 
						 | 
				
			
			@ -250,7 +258,8 @@ export const RANDOM_PALETTE_ALGORITHMS = Object.keys(
 | 
			
		|||
export function createRandomColorPalette(
 | 
			
		||||
  numEntries: number,
 | 
			
		||||
  rng: Random = new Random(),
 | 
			
		||||
  algorithm: RandomPaletteAlgorithm = DEFAULT_RANDOM_PALETTE_ALGORITHM
 | 
			
		||||
  algorithm: RandomPaletteAlgorithm = DEFAULT_RANDOM_PALETTE_ALGORITHM,
 | 
			
		||||
  config: PaletteAlgorithmConfig = {},
 | 
			
		||||
): string[] {
 | 
			
		||||
  return PALETTE_GENERATORS[algorithm](numEntries, rng);
 | 
			
		||||
  return PALETTE_GENERATORS[algorithm](numEntries, rng, config);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,7 +3,7 @@ import { PaletteAlgorithmWidget } from "./palette-algorithm-widget";
 | 
			
		|||
import { Random } from "./random";
 | 
			
		||||
import {
 | 
			
		||||
  createRandomColorPalette,
 | 
			
		||||
  DEFAULT_RANDOM_PALETTE_ALGORITHM,
 | 
			
		||||
  DEFAULT_RANDOM_PALETTE_ALGORITHM, PaletteAlgorithmConfig,
 | 
			
		||||
  RandomPaletteAlgorithm,
 | 
			
		||||
} from "./random-colors";
 | 
			
		||||
import { SvgCompositionContext } from "./svg-composition-context";
 | 
			
		||||
| 
						 | 
				
			
			@ -14,12 +14,14 @@ type SvgCompositionColors = Pick<
 | 
			
		|||
>;
 | 
			
		||||
 | 
			
		||||
function createRandomCompositionColors(
 | 
			
		||||
  alg: RandomPaletteAlgorithm
 | 
			
		||||
  alg: RandomPaletteAlgorithm,
 | 
			
		||||
  config?: PaletteAlgorithmConfig
 | 
			
		||||
): SvgCompositionColors {
 | 
			
		||||
  const [background, stroke, fill] = createRandomColorPalette(
 | 
			
		||||
    3,
 | 
			
		||||
    undefined,
 | 
			
		||||
    alg
 | 
			
		||||
    alg,
 | 
			
		||||
    config
 | 
			
		||||
  );
 | 
			
		||||
  return { background, stroke, fill };
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -34,10 +36,11 @@ export const RandomizerWidget: React.FC<RandomizerWidgetProps> = (props) => {
 | 
			
		|||
  const [paletteAlg, setPaletteAlg] = useState<RandomPaletteAlgorithm>(
 | 
			
		||||
    DEFAULT_RANDOM_PALETTE_ALGORITHM
 | 
			
		||||
  );
 | 
			
		||||
  const [paletteConfig, setPaletteConfig] = useState({})
 | 
			
		||||
  const [randType, setRandType] = useState<RandType>("colors and symbols");
 | 
			
		||||
  const randomize = () => {
 | 
			
		||||
    if (randType === "colors" || randType === "colors and symbols") {
 | 
			
		||||
      props.onColorsChange(createRandomCompositionColors(paletteAlg));
 | 
			
		||||
      props.onColorsChange(createRandomCompositionColors(paletteAlg, paletteConfig));
 | 
			
		||||
    }
 | 
			
		||||
    if (randType === "symbols" || randType === "colors and symbols") {
 | 
			
		||||
      props.onSymbolsChange(new Random(Date.now()));
 | 
			
		||||
| 
						 | 
				
			
			@ -63,7 +66,7 @@ export const RandomizerWidget: React.FC<RandomizerWidgetProps> = (props) => {
 | 
			
		|||
      {makeRadio("symbols")}
 | 
			
		||||
      {makeRadio("colors and symbols")}
 | 
			
		||||
      {randType !== "symbols" && (
 | 
			
		||||
        <PaletteAlgorithmWidget value={paletteAlg} onChange={setPaletteAlg} />
 | 
			
		||||
        <PaletteAlgorithmWidget value={paletteAlg} onChange={setPaletteAlg} onPaletteConfigChange={setPaletteConfig} />
 | 
			
		||||
      )}
 | 
			
		||||
      {props.children}
 | 
			
		||||
      <button accessKey="r" onClick={randomize}>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
										
											
												Plik diff jest za duży
												Load Diff
											
										
									
								
							
		Ładowanie…
	
		Reference in New Issue