diff --git a/packages/inspector/hooks/useNFT.tsx b/packages/inspector/hooks/useNFT.tsx index 1e17bee..01d7b79 100644 --- a/packages/inspector/hooks/useNFT.tsx +++ b/packages/inspector/hooks/useNFT.tsx @@ -18,6 +18,7 @@ export const useNFT = (tokenURI: string) => { useEffect(() => { if (tokenURI == null) return; // decode and parse metadata + console.log(decodeBase64(tokenURI)) const metadata = JSON.parse(decodeBase64(tokenURI)); const tokenId = metadata.tokenId; diff --git a/rarity.txt b/rarity.txt index c7818b6..85ba5c7 100644 --- a/rarity.txt +++ b/rarity.txt @@ -2,9 +2,9 @@ strategy: derive all traits from a single bytes32 seed 1 -export const refractivityTypes = [ - 'Light', // 80% - 'Dark', // 20% +export const densityTypes = [ + 'High', // 80% + 'Low', // 20% ] 2 diff --git a/src/dev/PaletteUncompressed.sol b/src/dev/PaletteUncompressed.sol index 9dd6d79..3951c43 100644 --- a/src/dev/PaletteUncompressed.sol +++ b/src/dev/PaletteUncompressed.sol @@ -211,4 +211,214 @@ library PaletteUncompressed { ]; return darkestPaletteValues[_value % 64]; } + + function invertedLightestPalette(uint256 _value) internal pure returns (string memory) { + string[64] memory invertedLightestPaletteValues = [ + "#3e4545", + "#3c3e3e", + "#383838", + "#313334", + "#2a2e32", + "#232832", + "#1d2233", + "#191c34", + "#161635", + "#141136", + "#120b37", + "#120637", + "#140638", + "#170738", + "#1b0938", + "#1f0a39", + "#230c39", + "#280e3a", + "#2d103b", + "#32123b", + "#37143c", + "#3c163e", + "#3f183d", + "#3e1837", + "#3c1832", + "#3b182d", + "#3a1929", + "#391925", + "#391821", + "#39181d", + "#391719", + "#3a1717", + "#3b1614", + "#3b1814", + "#3b1b15", + "#3b1f17", + "#3c2319", + "#3d281b", + "#3f2c1e", + "#413220", + "#443722", + "#473d23", + "#4a4325", + "#4d4a26", + "#4a4a26", + "#454a25", + "#414924", + "#3c4922", + "#384921", + "#344920", + "#30491f", + "#2c491e", + "#29481e", + "#27481d", + "#25481d", + "#254820", + "#264824", + "#274829", + "#29482d", + "#2b4732", + "#2d4737", + "#30463b", + "#34463f", + "#384542" + ]; + return invertedLightestPaletteValues[_value % 64]; + } + + function invertedLightPalette(uint256 _value) internal pure returns (string memory) { + string[64] memory invertedLightPaletteValues = [ + "#50f0f0", + "#4ddcf0", + "#4bc8f0", + "#4ab5f0", + "#49a2f0", + "#498ef0", + "#4a7af0", + "#4b66f0", + "#4c52f0", + "#4e41f1", + "#4f33f1", + "#502bf1", + "#552cf1", + "#5d2df1", + "#6a2ff1", + "#7831f1", + "#8933f1", + "#9b36f0", + "#ac39f0", + "#bf3cf0", + "#d23ff0", + "#e642f0", + "#f244e9", + "#f243d5", + "#f242c1", + "#f241af", + "#f3419b", + "#f34087", + "#f43f72", + "#f43f5e", + "#f53e4a", + "#f53e38", + "#f53e28", + "#f64123", + "#f54924", + "#f55625", + "#f56528", + "#f4772a", + "#f48a2d", + "#f39d30", + "#f3af33", + "#f2c336", + "#f2d73a", + "#f2ea3d", + "#e4ef3d", + "#d0f03d", + "#bdf03c", + "#abf03c", + "#98f03c", + "#87f03b", + "#76f03b", + "#67f03b", + "#5cf03b", + "#53f13b", + "#4ff13b", + "#4ef141", + "#4ef14b", + "#4df15a", + "#4cf16b", + "#4cf07e", + "#4bf091", + "#4bf0a3", + "#4cf0b7", + "#4df0ca" + ]; + return invertedLightPaletteValues[_value % 64]; + } + + function invertedDarkestPalette(uint256 _value) internal pure returns (string memory) { + string[64] memory invertedDarkestPaletteValues = [ + "#f9f5f9", + "#f9f2f8", + "#f9eff8", + "#f9ebf8", + "#f9e6f8", + "#fae1f8", + "#fbdcf9", + "#fdd7fa", + "#f9f5f7", + "#f9f2f5", + "#f9eff3", + "#f9ebf1", + "#f9e6ef", + "#fae1ec", + "#fbdcea", + "#fdd7e8", + "#f9f6f5", + "#f9f2f2", + "#f9efef", + "#f9ebeb", + "#f9e7e6", + "#fae2e1", + "#fbdedc", + "#fdd8d7", + "#f9f7f5", + "#f9f6f2", + "#f9f4ef", + "#f9f2eb", + "#f9f0e6", + "#faeee1", + "#fbeddc", + "#fdebd7", + "#f9f9f5", + "#f9f9f2", + "#f9f9ef", + "#f9f9eb", + "#f9f9e6", + "#fafae1", + "#fbfbdc", + "#fdfdd7", + "#f7f9f5", + "#f6f9f2", + "#f4f9ef", + "#f2f9eb", + "#f0f9e6", + "#eefae1", + "#edfbdc", + "#ebfdd7", + "#f6f9f5", + "#f2f9f2", + "#eff9ef", + "#ebf9eb", + "#e7f9e6", + "#e2fae1", + "#defbdc", + "#d8fdd7", + "#f5f9f7", + "#f2f9f5", + "#eff9f3", + "#ebf9f1", + "#e6f9ef", + "#e1faec", + "#dcfbea", + "#d7fde8" + ]; + return invertedDarkestPaletteValues[_value % 64]; + } } diff --git a/src/dev/PaletteUtil.sol b/src/dev/PaletteUtil.sol index 5b489d0..db98751 100644 --- a/src/dev/PaletteUtil.sol +++ b/src/dev/PaletteUtil.sol @@ -40,6 +40,39 @@ library PaletteUtil { return result; } + function getInvertedLightest() internal pure returns (string memory) { + string memory result; + uint256 i; + for (; i < 64; ) { + string memory strHex = slice7CharColor(PaletteUncompressed.invertedLightestPalette(i)); + result = string.concat(result, strHex); + ++i; + } + return result; + } + + function getInvertedLight() internal pure returns (string memory) { + string memory result; + uint256 i; + for (; i < 64; ) { + string memory strHex = slice7CharColor(PaletteUncompressed.invertedLightPalette(i)); + result = string.concat(result, strHex); + ++i; + } + return result; + } + + function getInvertedDarkest() internal pure returns (string memory) { + string memory result; + uint256 i; + for (; i < 64; ) { + string memory strHex = slice7CharColor(PaletteUncompressed.invertedDarkestPalette(i)); + result = string.concat(result, strHex); + ++i; + } + return result; + } + function slice7CharColor(string memory _rgb) internal pure returns (string memory result) { assembly { result := add(_rgb, 1) diff --git a/src/libraries/Body.sol b/src/libraries/Body.sol index c495ad3..a3474f9 100644 --- a/src/libraries/Body.sol +++ b/src/libraries/Body.sol @@ -1,7 +1,8 @@ // SPDX-License-Identifier: Unlicense pragma solidity >=0.8.0; -import {Palette} from "./Palette.sol"; +import {Palette, DensityType, PolarityType} from "./Palette.sol"; +import {Traits} from "./Traits.sol"; import {Data} from "./Data.sol"; import {Util} from "./Util.sol"; import {SVG} from "./SVG.sol"; @@ -30,7 +31,11 @@ library Body { string memory reverse = bodySeed % 2 == 0 ? 'keyPoints="1;0" keyTimes="0;1" ' : ""; bodySeed /= 2; - result = addBodyCircle(result, radius, coords, fill, dur, reverse); + string memory mixBlendMode = Traits.getPolarityType(_seed) == PolarityType.POSITIVE + ? "lighten" + : "multiply"; + + result = addBodyCircle(result, radius, coords, fill, dur, reverse, mixBlendMode); } return string.concat('', result, ""); @@ -42,16 +47,16 @@ library Body { string[2] memory _coords, string memory _fill, string memory _dur, - string memory _reverse + string memory _reverse, + string memory _mixBlendMode ) internal pure returns (string memory) { - string memory mixMode = "lighten"; string memory mpath = ''; string memory opacity = "1"; return string.concat( _result, - SVG.circle(_radius, _coords, mixMode, _fill, opacity), + SVG.circle(_radius, _coords, _mixBlendMode, _fill, opacity), SVG.animateMotion(_reverse, _dur, "linear", mpath), "" ); diff --git a/src/libraries/Cheeks.sol b/src/libraries/Cheeks.sol index 35adcc5..a2654c3 100644 --- a/src/libraries/Cheeks.sol +++ b/src/libraries/Cheeks.sol @@ -24,20 +24,20 @@ library Cheeks { function circular() internal pure returns (string memory) { return string.concat( - "", - "" + "", + "" ); } function freckles() internal pure returns (string memory) { return string.concat( - "", - "", - "", - "", - "", - "" + "", + "", + "", + "", + "", + "" ); } } diff --git a/src/libraries/Data.sol b/src/libraries/Data.sol index 773b294..39bd496 100644 --- a/src/libraries/Data.sol +++ b/src/libraries/Data.sol @@ -65,6 +65,18 @@ library Data { return _getRGBString(darkestPaletteBytes, _i % length); } + function invertedLightestPalette(uint256 _i) external pure returns (string memory) { + return _getRGBString(invertedLightestPaletteBytes, _i % length); + } + + function invertedLightPalette(uint256 _i) external pure returns (string memory) { + return _getRGBString(invertedLightPaletteBytes, _i % length); + } + + function invertedDarkestPalette(uint256 _i) external pure returns (string memory) { + return _getRGBString(invertedDarkestPaletteBytes, _i % length); + } + function _getRGBString(bytes memory _palette, uint256 _pos) internal pure returns (string memory result) { return string.concat( @@ -89,6 +101,9 @@ library Data { '', '', "", + '', + '', + "", '', '', "" @@ -116,4 +131,10 @@ library Data { hex"ffb3b3ffbab3ffc1b3ffc8b3ffcfb3ffd6b3ffddb3ffe4b3ffebb3fff2b3fff9b3feffb3f7ffb3f0ffb3e8ffb3e1ffb3daffb3d3ffb3ccffb3c5ffb3beffb3b7ffb3b3ffb5b3ffbcb3ffc3b3ffcab3ffd1b3ffd8b3ffe0b3ffe7b3ffeeb3fff5b3fffcb3fbffb3f4ffb3edffb3e6ffb3dfffb3d8ffb3d1ffb3caffb3c3ffb3bbffb3b4ffb8b3ffbfb3ffc6b3ffcdb3ffd4b3ffdbb3ffe2b3ffe9b3fff0b3fff7b3fffeb3ffffb3f9ffb3f1ffb3eaffb3e3ffb3dcffb3d5ffb3ceffb3c7ffb3c0"; bytes public constant darkestPaletteBytes = hex"060a06060d07061007061407061907051e07042306022805060a08060d0a06100c06140e061910051e1304231502281706090a060d0d061010061414061819051d1e04212302272806080a06090d060b10060d14060f1905111e04122302142806060a06060d06061006061406061905051e04042302022808060a09060d0b06100d06140f061911051e12042314022809060a0d060d1006101406141806191d051e2104232702280a06080d060a10060c14060e1906101e0513230415280217"; + bytes public constant invertedLightPaletteBytes = + hex"50f0f04ddcf04bc8f04ab5f049a2f0498ef04a7af04b66f04c52f04e41f14f33f1502bf1552cf15d2df16a2ff17831f18933f19b36f0ac39f0bf3cf0d23ff0e642f0f244e9f243d5f242c1f241aff3419bf34087f43f72f43f5ef53e4af53e38f53e28f64123f54924f55625f56528f4772af48a2df39d30f3af33f2c336f2d73af2ea3de4ef3dd0f03dbdf03cabf03c98f03c87f03b76f03b67f03b5cf03b53f13b4ff13b4ef1414ef14b4df15a4cf16b4cf07e4bf0914bf0a34cf0b74df0ca"; + bytes public constant invertedLightestPaletteBytes = + hex"3e45453c3e3e3838383133342a2e322328321d2233191c34161635141136120b371206371406381707381b09381f0a39230c39280e3a2d103b32123b37143c3c163e3f183d3e18373c18323b182d3a192939192539182139181d3917193a17173b16143b18143b1b153b1f173c23193d281b3f2c1e413220443722473d234a43254d4a264a4a26454a254149243c492238492134492030491f2c491e29481e27481d25481d25482026482427482929482d2b47322d473730463b34463f384542"; + bytes public constant invertedDarkestPaletteBytes = + hex"f9f5f9f9f2f8f9eff8f9ebf8f9e6f8fae1f8fbdcf9fdd7faf9f5f7f9f2f5f9eff3f9ebf1f9e6effae1ecfbdceafdd7e8f9f6f5f9f2f2f9efeff9ebebf9e7e6fae2e1fbdedcfdd8d7f9f7f5f9f6f2f9f4eff9f2ebf9f0e6faeee1fbeddcfdebd7f9f9f5f9f9f2f9f9eff9f9ebf9f9e6fafae1fbfbdcfdfdd7f7f9f5f6f9f2f4f9eff2f9ebf0f9e6eefae1edfbdcebfdd7f6f9f5f2f9f2eff9efebf9ebe7f9e6e2fae1defbdcd8fdd7f5f9f7f2f9f5eff9f3ebf9f1e6f9efe1faecdcfbead7fde8"; } diff --git a/src/libraries/Eyes.sol b/src/libraries/Eyes.sol index 1d300af..385a27b 100644 --- a/src/libraries/Eyes.sol +++ b/src/libraries/Eyes.sol @@ -21,7 +21,7 @@ enum EyeType { library Eyes { function render(bytes32 _seed) internal pure returns (string memory) { - string memory fill = Palette.getBackgroundFill(_seed); + string memory fill = "black"; EyeType eyeType = Traits.getEyeType(_seed); if (eyeType == EyeType.OPEN) return open(fill); diff --git a/src/libraries/Face.sol b/src/libraries/Face.sol index 8f72551..0d6361e 100644 --- a/src/libraries/Face.sol +++ b/src/libraries/Face.sol @@ -19,6 +19,8 @@ library Face { rotation, ")'>", SVG.rect("200", "200", "#00000000"), + SVG.circleFilter("80", ["100", "100"], "lighten", "white", "0.2", "bibo-blur-lg"), + "", Eyes.render(_seed), Mouth.render(_seed), Cheeks.render(_seed), diff --git a/src/libraries/Mouth.sol b/src/libraries/Mouth.sol index 30da756..68d9ad7 100644 --- a/src/libraries/Mouth.sol +++ b/src/libraries/Mouth.sol @@ -16,7 +16,7 @@ enum MouthType { library Mouth { function render(bytes32 _seed) internal pure returns (string memory) { - string memory fill = Palette.getBackgroundFill(_seed); + string memory fill = "black"; MouthType mouthType = Traits.getMouthType(_seed); if (mouthType == MouthType.SMILE) return smile(fill); diff --git a/src/libraries/Palette.sol b/src/libraries/Palette.sol index 121e040..f35b718 100644 --- a/src/libraries/Palette.sol +++ b/src/libraries/Palette.sol @@ -2,9 +2,14 @@ pragma solidity >=0.8.0; import {Traits} from "libraries/Traits.sol"; import {Data} from "libraries/Data.sol"; -enum RefractivityType { - LIGHT, - DARK +enum DensityType { + HIGH, + LOW +} + +enum PolarityType { + POSITIVE, + NEGATIVE } library Palette { @@ -13,7 +18,7 @@ library Palette { function getOpacity(uint256 _glintSeed, bytes32 _seed) internal pure returns (string memory) { return ( - Traits.getRefractivityType(_seed) == RefractivityType.LIGHT + Traits.getDensityType(_seed) == DensityType.HIGH ? ["0.3", "0.4", "0.5", "0.6", "0.7"] : ["0.6", "0.7", "0.8", "0.9", "1.0"] )[_glintSeed % opacityLength]; @@ -22,15 +27,37 @@ library Palette { function getBodyFill(bytes32 _seed, uint256 _i) internal pure returns (string memory) { uint256 bodyFillValue = uint256(keccak256(abi.encodePacked(_seed, "bodyFill", _i))); - if (Traits.getRefractivityType(_seed) == RefractivityType.LIGHT) return lightPalette(bodyFillValue); - else return lightestPalette(bodyFillValue); + if (Traits.getDensityType(_seed) == DensityType.HIGH) { + if (Traits.getPolarityType(_seed) == PolarityType.POSITIVE) { + return lightPalette(bodyFillValue); + } else { + return invertedLightPalette(bodyFillValue); + } + } else { + if (Traits.getPolarityType(_seed) == PolarityType.POSITIVE) { + return lightestPalette(bodyFillValue); + } else { + return invertedLightestPalette(bodyFillValue); + } + } } function getBackgroundFill(bytes32 _seed) internal pure returns (string memory) { uint256 backgroundFillValue = uint256(keccak256(abi.encodePacked(_seed, "backgroundFill"))); - if (Traits.getRefractivityType(_seed) == RefractivityType.LIGHT) return darkestPalette(backgroundFillValue); - else return darkestPalette(backgroundFillValue); + if (Traits.getDensityType(_seed) == DensityType.HIGH) { + if (Traits.getPolarityType(_seed) == PolarityType.POSITIVE) { + return darkestPalette(backgroundFillValue); + } else { + return invertedDarkestPalette(backgroundFillValue); + } + } else { + if (Traits.getPolarityType(_seed) == PolarityType.POSITIVE) { + return darkestPalette(backgroundFillValue); + } else { + return invertedDarkestPalette(backgroundFillValue); + } + } } function lightestPalette(uint256 _value) internal pure returns (string memory) { @@ -44,4 +71,16 @@ library Palette { function darkestPalette(uint256 _value) internal pure returns (string memory) { return Data.darkestPalette(_value); } + + function invertedLightestPalette(uint256 _value) internal pure returns (string memory) { + return Data.invertedLightestPalette(_value); + } + + function invertedLightPalette(uint256 _value) internal pure returns (string memory) { + return Data.invertedLightPalette(_value); + } + + function invertedDarkestPalette(uint256 _value) internal pure returns (string memory) { + return Data.invertedDarkestPalette(_value); + } } diff --git a/src/libraries/Traits.sol b/src/libraries/Traits.sol index b6d6eab..8084422 100644 --- a/src/libraries/Traits.sol +++ b/src/libraries/Traits.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: Unlicense pragma solidity >=0.8.0; -import {RefractivityType} from "./Palette.sol"; +import {DensityType, PolarityType} from "./Palette.sol"; import {MoteType} from "./Motes.sol"; import {EyeType} from "./Eyes.sol"; import {CheekType} from "./Cheeks.sol"; @@ -16,8 +16,9 @@ library Traits { function getTraits(bytes32 _seed) internal pure returns (string memory) { string memory result = "["; - - result = string.concat(result, trait("Refractivity", getRefractivityTrait(_seed))); + result = string.concat(result, trait("Density", getDensityTrait(_seed))); + result = string.concat(result, ",", trait("Polarity", getPolarityTrait(_seed))); + result = string.concat(result, ",", trait("Glint", getGlintTrait(_seed))); result = string.concat(result, ",", trait("Mote", getMoteTrait(_seed))); result = string.concat(result, ",", trait("Eyes", getEyeTrait(_seed))); result = string.concat(result, ",", trait("Mouth", getMouthTrait(_seed))); @@ -31,19 +32,35 @@ library Traits { } /*////////////////////////////////////////////////////////////// - REFRACTIVITY + DENSITY + //////////////////////////////////////////////////////////////*/ + + function getDensityTrait(bytes32 _seed) internal pure returns (string memory) { + DensityType densityType = getDensityType(_seed); + return densityType == DensityType.HIGH ? "High" : "Low"; + } + + function getDensityType(bytes32 _seed) internal pure returns (DensityType) { + uint256 densitySeed = uint256(keccak256(abi.encodePacked(_seed, "density"))) % 100; + + if (densitySeed < 80) return DensityType.HIGH; + return DensityType.LOW; + } + + /*////////////////////////////////////////////////////////////// + POLARITY //////////////////////////////////////////////////////////////*/ - function getRefractivityTrait(bytes32 _seed) internal pure returns (string memory) { - RefractivityType refractivityType = getRefractivityType(_seed); - return refractivityType == RefractivityType.LIGHT ? "Light" : "Dark"; + function getPolarityTrait(bytes32 _seed) internal pure returns (string memory) { + PolarityType polarityType = getPolarityType(_seed); + return polarityType == PolarityType.POSITIVE ? "Positive" : "Negative"; } - function getRefractivityType(bytes32 _seed) internal pure returns (RefractivityType) { - uint256 refractivitySeed = uint256(keccak256(abi.encodePacked(_seed, "refractivity"))) % 100; + function getPolarityType(bytes32 _seed) internal pure returns (PolarityType) { + uint256 polaritySeed = uint256(keccak256(abi.encodePacked(_seed, "polarity"))) % 100; - if (refractivitySeed < 80) return RefractivityType.LIGHT; - return RefractivityType.DARK; + if (polaritySeed < 80) return PolarityType.POSITIVE; + return PolarityType.NEGATIVE; } /*////////////////////////////////////////////////////////////// diff --git a/src/scripts/encode_palettes.sol b/src/scripts/encode_palettes.sol index 5082927..950ca9a 100644 --- a/src/scripts/encode_palettes.sol +++ b/src/scripts/encode_palettes.sol @@ -12,9 +12,19 @@ contract encode_palettes is Script { returns ( string memory light, string memory lightest, - string memory darkest + string memory darkest, + string memory invertedLight, + string memory invertedLightest, + string memory invertedDarkest ) { - return (PaletteUtil.getLight(), PaletteUtil.getLightest(), PaletteUtil.getDarkest()); + return ( + PaletteUtil.getLight(), + PaletteUtil.getLightest(), + PaletteUtil.getDarkest(), + PaletteUtil.getInvertedLight(), + PaletteUtil.getInvertedLightest(), + PaletteUtil.getInvertedDarkest() + ); } }