Skip to content

Commit

Permalink
Fix clipping, fix shave, POC weighted random
Browse files Browse the repository at this point in the history
  • Loading branch information
tomkennedy22 committed May 18, 2024
1 parent e6bc8b1 commit 4babb02
Show file tree
Hide file tree
Showing 31 changed files with 145 additions and 185 deletions.
7 changes: 3 additions & 4 deletions public/editor/ColorPicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
PopoverContent,
Popover,
} from "@nextui-org/react";
import { ColorFormat } from "./types";

const rgbaObjToRgbaStr = (rgbaObj: {
r: number;
Expand All @@ -22,15 +23,13 @@ export const ColorPicker = ({
style,
value,
colorFormat = "hex",
allowAlpha = false,
presetColors,
}: {
onClick?: () => void;
onChange: (hex: string) => void;
style?: CSSProperties;
value: string;
colorFormat: "hex" | "rgba";
allowAlpha: boolean;
colorFormat: ColorFormat;
presetColors: string[];
}) => {
return (
Expand All @@ -48,7 +47,7 @@ export const ColorPicker = ({
<PopoverContent className="p-0">
<Sketch
color={value}
allowAlpha={allowAlpha}
colorFormat={colorFormat}
presetColors={presetColors}
onChange={(color) => {
if (colorFormat === "rgba") {
Expand Down
5 changes: 1 addition & 4 deletions public/editor/FeatureGallery.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -248,9 +248,7 @@ const FeatureSelector = ({
});
};

let colorFormat = gallerySectionConfig.colorFormat
? gallerySectionConfig.colorFormat
: "hex";
const colorFormat = gallerySectionConfig.colorFormat || "hex";

return (
<div
Expand Down Expand Up @@ -288,7 +286,6 @@ const FeatureSelector = ({
}}
colorFormat={colorFormat}
presetColors={presetColors}
allowAlpha={gallerySectionConfig.allowAlpha}
value={selectedColor}
/>
<Input
Expand Down
21 changes: 15 additions & 6 deletions public/editor/Sketch.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
validHex,
type HsvaColor,
rgbaStringToHsva,
hsvaToHexa,
hsvaToHex,
hexToHsva,
color as handleColor,
Expand All @@ -16,6 +17,7 @@ import {
import Swatch from "@uiw/react-color-swatch";
import { useEffect } from "react";
import { roundTwoDecimals } from "./utils";
import { ColorFormat } from "./types";

// Similar to https://github.com/uiwjs/react-color/blob/632d4e9201e26b42ee7d5bfeda407144e9a6e2f3/packages/color-sketch/src/index.tsx but with EyeDropper added

Expand Down Expand Up @@ -62,7 +64,7 @@ const EyeDropperButton = ({

return (
<button
className="btn pt-0 ps-2 pe-1"
className="btn pt-1 ps-2 pe-1 h-fit"
type="button"
onClick={async () => {
const eyeDropper = new window.EyeDropper!();
Expand All @@ -85,7 +87,7 @@ export interface SketchProps
width?: number;
color?: string | HsvaColor;
presetColors: string[];
allowAlpha: boolean;
colorFormat: ColorFormat;
onChange?: (newShade: ColorResult) => void;
}

Expand Down Expand Up @@ -113,11 +115,18 @@ export const Sketch = React.forwardRef<HTMLDivElement, SketchProps>(
width = 240,
color,
style,
allowAlpha,
colorFormat,
presetColors,
...other
} = props;

let formattedPresetColors = presetColors;
if (colorFormat === "rgba") {
formattedPresetColors = presetColors.map((rgbaColor) =>
hsvaToHexa(rgbaStringToHsva(rgbaColor)),
);
}

const [hsva, setHsva] = useState({ h: 209, s: 36, v: 90, a: 1 });
useEffect(() => {
if (typeof color === "string" && validHex(color)) {
Expand Down Expand Up @@ -200,7 +209,7 @@ export const Sketch = React.forwardRef<HTMLDivElement, SketchProps>(
/>
</div>
</div>
{allowAlpha && (
{colorFormat === "rgba" && (
<div style={{ display: "flex", marginTop: 4 }}>
<div style={{ flex: 1 }}>
<Alpha
Expand Down Expand Up @@ -229,14 +238,14 @@ export const Sketch = React.forwardRef<HTMLDivElement, SketchProps>(
<RGBA
hsva={hsva}
style={{ marginLeft: 6 }}
aProps={allowAlpha ? undefined : false}
aProps={colorFormat === "rgba" ? undefined : false}
onChange={(result) => handleChange(result.hsva)}
/>
<EyeDropperButton onChange={handleHex} />
</div>
<Swatch
style={styleSwatch}
colors={presetColors}
colors={formattedPresetColors}
color={hsvaToHex(hsva)}
onChange={(hsvColor) => handleChange(hsvColor)}
rectProps={{
Expand Down
6 changes: 0 additions & 6 deletions public/editor/stateStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,13 @@ const gallerySectionInfos: (Pick<
| {
selectionType: "color";
colorFormat: "rgba" | "hex";
allowAlpha: boolean;
renderOptions: {
valuesToRender: string[];
};
}
| {
selectionType: "colors";
colorFormat: "rgba" | "hex";
allowAlpha: boolean;
renderOptions: {
colorCount: number;
valuesToRender: string[][];
Expand Down Expand Up @@ -53,7 +51,6 @@ const gallerySectionInfos: (Pick<
isSelected: true,
selectionType: "color",
colorFormat: "hex",
allowAlpha: false,
renderOptions: {
valuesToRender: distinctSkinColors,
},
Expand Down Expand Up @@ -194,7 +191,6 @@ const gallerySectionInfos: (Pick<
text: "Hair Color",
selectionType: "color",
colorFormat: "hex",
allowAlpha: false,
renderOptions: {
valuesToRender: distinctHairColors,
},
Expand All @@ -214,7 +210,6 @@ const gallerySectionInfos: (Pick<
text: "Shave Style",
selectionType: "color",
colorFormat: "rgba",
allowAlpha: true,
renderOptions: {
valuesToRender: [
"rgba(0,0,0,0)",
Expand Down Expand Up @@ -383,7 +378,6 @@ const gallerySectionInfos: (Pick<
text: "Team Colors",
selectionType: "colors",
colorFormat: "hex",
allowAlpha: false,
renderOptions: {
colorCount: 3,
valuesToRender: jerseyColorOptions,
Expand Down
2 changes: 0 additions & 2 deletions public/editor/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ type GallerySectionConfigColor = GallerySectionConfigBase & {
selectionType: "color";
selectedValue: string;
colorFormat: ColorFormat;
allowAlpha: boolean;
renderOptions: {
valuesToRender: string[];
};
Expand All @@ -62,7 +61,6 @@ type GallerySectionConfigColors = GallerySectionConfigBase & {
selectionType: "colors";
selectedValue: string[];
colorFormat: ColorFormat;
allowAlpha: boolean;
renderOptions: {
colorCount: number;
valuesToRender: string[][];
Expand Down
31 changes: 18 additions & 13 deletions src/display.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,7 @@ const clipToParent = (
let childElement = getChildElement(fullSvg, insertLocation) as SVGSVGElement;
let clippedItem = paper.project.importSVG(childElement);
fullSvg.removeChild(childElement);
let baseShape = new paper.CompoundPath({
children: findPathItems(parentElement.clone()),
});
let baseShape = unitePaths(findPathItems(parentElement.clone()));

let smallChildren = findPathItems(clippedItem);
let childGroup = new paper.Group();
Expand Down Expand Up @@ -70,15 +68,8 @@ const findPathItems = (item: paper.Item): paper.PathItem[] => {
return paths;
};

const getOuterStroke = (svgElement: SVGElement): string => {
paper.setup(document.createElement("canvas"));

const importedItem = paper.project.importSVG(svgElement);

const pathItems = findPathItems(importedItem);

// Unite all the path items into a single path
const unitedPath = pathItems.reduce(
const unitePaths = (paths: paper.PathItem[]): paper.Path => {
let unitedPath = paths.reduce(
(result, path) => {
if (result) {
result = result.unite(path);
Expand All @@ -90,6 +81,19 @@ const getOuterStroke = (svgElement: SVGElement): string => {
null as paper.PathItem | null,
) as paper.Path;

return unitedPath;
};

const getOuterStroke = (svgElement: SVGElement): string => {
paper.setup(document.createElement("canvas"));

const importedItem = paper.project.importSVG(svgElement);

const pathItems = findPathItems(importedItem);

// Unite all the path items into a single path
const unitedPath = unitePaths(pathItems);

unitedPath.strokeColor = new paper.Color("black");
unitedPath.strokeWidth = 5;
unitedPath.fillColor = new paper.Color("transparent");
Expand Down Expand Up @@ -476,7 +480,7 @@ const drawFeature = (
// @ts-ignore
if (feature.shave) {
// @ts-ignore
featureSVGString = featureSVGString.replace("$[headShave]", feature.shave);
featureSVGString = featureSVGString.replace("$[headShave]", "none");
}

featureSVGString = featureSVGString.replace("$[skinColor]", face.body.color);
Expand Down Expand Up @@ -776,6 +780,7 @@ export const display = (
baseFace = paper.project.importSVG(insideSVG);
}

console.log({ metadata, info, feature });
if (metadata.clip) {
clipToParent(insideSVG, baseFace, "beforeend");
}
Expand Down
33 changes: 27 additions & 6 deletions src/generate.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
import { colors, jerseyColorOptions } from "./globals.js";
import override from "./override.js";
import { svgsGenders, svgsIndex } from "./svgs-index.js";
import { svgsGenders, svgsIndex, svgsMetadata } from "./svgs-index.js";
import { Feature, Gender, Overrides, Race, TeamColors } from "./types.js";
import { pickRandom, randomGaussian, randomInt } from "./utils.js";
import {
pickRandom,
randomGaussian,
randomInt,
weightedRandomChoice,
} from "./utils";

const getID = (type: Feature, gender: Gender): string => {
const validIDs = svgsIndex[type].filter((_id, index) => {
Expand All @@ -14,6 +19,21 @@ const getID = (type: Feature, gender: Gender): string => {
return validIDs[randomInt(0, validIDs.length)];
};

const getIDWithOccurance = (type: Feature, gender: Gender): string => {
const validIDsWeightMap: [any, number][] = svgsIndex[type]
.filter((_id, index) => {
return (
svgsMetadata[type][index].gender === "both" ||
svgsGenders[type][index] === gender
);
})
.map((_id, index) => {
return [svgsIndex[type][index], svgsMetadata[type][index].occurance];
});

return weightedRandomChoice(validIDsWeightMap);
};

const roundTwoDecimals = (x: number) => Math.round(x * 100) / 100;

export const generate = (
Expand Down Expand Up @@ -93,10 +113,11 @@ export const generate = (
},
head: {
id: getID("head", gender),
shaveOpacity:
gender === "male" && Math.random() < 0.35
shave: `rgba(0,0,0,${
gender === "male" && Math.random() < 0.25
? roundTwoDecimals(Math.random() / 5)
: 0,
: 0
})`,
},
eyeLine: {
id: getID("eyeLine", gender),
Expand Down Expand Up @@ -137,7 +158,7 @@ export const generate = (
angle: randomInt(-15, 20, true),
},
hair: {
id: getID("hair", gender),
id: getIDWithOccurance("hair", gender),
color: hairColor,
flip: isFlipped(),
},
Expand Down
15 changes: 15 additions & 0 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,18 @@ export const randomInt = (
}
return Math.floor(Math.random() * (max - minInclusive)) + minInclusive;
};

export const weightedRandomChoice = (list: [any, number][]): any => {
const totalWeight = list.reduce((sum, [_, weight]) => sum + weight, 0);
const randomWeight = Math.random() * totalWeight;

let cumulativeWeight = 0;
for (const [item, weight] of list) {
cumulativeWeight += weight;
if (randomWeight < cumulativeWeight) {
return item;
}
}

return list[0][0];
};
28 changes: 12 additions & 16 deletions svgs/hair/crop-fade.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 4babb02

Please sign in to comment.