Skip to content

Commit

Permalink
feat: background and some pending refactors (#6)
Browse files Browse the repository at this point in the history
  • Loading branch information
jpgonzalezra authored Jan 31, 2024
1 parent 672a07d commit 3928052
Show file tree
Hide file tree
Showing 5 changed files with 265 additions and 227 deletions.
69 changes: 30 additions & 39 deletions packages/contracts/src/LucidOrigins.sol
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ contract LucidOrigins is Owned, ERC721A, Background, Face, Blob, Blush, Colors {

function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
uint16[] memory dna = getDna(uint256(keccak256(abi.encodePacked(tokenId))));
string memory name = string(abi.encodePacked("LucidOrigins #", tokenId.toString()));
string memory name = string.concat("LucidOrigins #", tokenId.toString());
string memory background = background(normalizeToRange(dna[Constants.BACKGROUND_INDEX], 0, 16));

string memory layers = "";
Expand All @@ -38,7 +38,7 @@ contract LucidOrigins is Owned, ERC721A, Background, Face, Blob, Blush, Colors {
uint256 edgesNum = normalizeToRange(dna[Constants.EDGES_NUM_INDEX] * i, 10, 15);
string memory path1 = createSvgPath(createPoints(size, 50, 0, minGrowth, edgesNum));
string memory path2 = createSvgPath(createPoints(size + 1, 50, 0, minGrowth, edgesNum));
layers = string(abi.encodePacked(layers, build(i, colorDefs, fillColor, path1, path2)));
layers = string.concat(layers, build(i, colorDefs, fillColor, path1, path2));
unchecked {
size = size - 30;
}
Expand All @@ -49,44 +49,37 @@ contract LucidOrigins is Owned, ERC721A, Background, Face, Blob, Blush, Colors {
normalizeToRange(dna[Constants.EYE_PUPIL_RADIUS_INDEX], 0, 6),
fillColor
);
string memory svgContent = string(abi.encodePacked(layers, face, blush()));
string memory svgContent = string.concat(layers, face, blush());
uint256 rotation = normalizeToRange(dna[Constants.SIZE_INDEX], 0, 3);
string memory svg = string(
abi.encodePacked(
'<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" width="400" height="400">',
background,
rotationWrapper(rotation, svgContent),
"</svg>"
)
string memory svg = string.concat(
'<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" width="400" height="400">',
background,
rotationWrapper(rotation, svgContent),
"</svg>"
);

// console2.log(svg);
return metadata(name, svg);
}

function rotationWrapper(uint256 rotation, string memory content) internal pure returns (string memory) {
string memory rotationDegree = rotation == 0 ? "0" : rotation == 1 ? "90" : rotation == 2 ? "180" : "-90";
return string(
abi.encodePacked(
'<g transform="scale(0.99) rotate(', rotationDegree, ", 50, 50) translate(0 0)\">", content, "</g>"
)
return string.concat(
'<g transform="scale(0.99) rotate(', rotationDegree, ", 50, 50) translate(0 0)\">", content, "</g>"
);
}

function metadata(string memory name, string memory svg) internal pure returns (string memory) {
string memory description = "LucidOrigins, fully on-chain NFT";
string memory json = string(
abi.encodePacked(
'{"name":"',
name,
'","description":"',
description,
'","image": "data:image/svg+xml;base64,',
Encoder.base64(bytes(svg)),
'"}'
)
string memory json = string.concat(
'{"name":"',
name,
'","description":"',
description,
'","image": "data:image/svg+xml;base64,',
Encoder.base64(bytes(svg)),
'"}'
);
return string(abi.encodePacked("data:application/json;base64,", Encoder.base64(bytes(json))));
return string.concat("data:application/json;base64,", Encoder.base64(bytes(json)));
}

function getDna(uint256 preDna) internal pure returns (uint16[] memory) {
Expand Down Expand Up @@ -139,19 +132,17 @@ contract LucidOrigins is Owned, ERC721A, Background, Face, Blob, Blush, Colors {
bool isPlain = base < 80;
string memory colorDefs = isPlain
? ""
: string(
abi.encodePacked(
"<defs>",
'<linearGradient id="linear-grad">',
'<stop offset="0" stop-color="',
colors[color1],
'"/>',
'<stop offset="1" stop-color="',
colors[color2],
'"/>',
"</linearGradient>",
"</defs>"
)
: string.concat(
"<defs>",
'<linearGradient id="linear-grad">',
'<stop offset="0" stop-color="',
colors[color1],
'"/>',
'<stop offset="1" stop-color="',
colors[color2],
'"/>',
"</linearGradient>",
"</defs>"
);

string memory fillColor = isPlain ? colors[color1] : "url(#linear-grad)";
Expand Down
109 changes: 85 additions & 24 deletions packages/contracts/src/layers/Background.sol
Original file line number Diff line number Diff line change
@@ -1,35 +1,96 @@
// SPDX-License-Identifier: GNU GPLv3
pragma solidity 0.8.23;

// import { console2 } from "forge-std/console2.sol";
import { console2 } from "forge-std/console2.sol";
import { LibString } from "solmate/utils/LibString.sol";

contract Background {
using LibString for int256;

string[20] internal bgColors = [
"#FAF4EF",
"#EFFAEF",
"#EFF4FA",
"#FAEFFA",
"#EFF4FA",
"#F4EFFA",
"#FAFAEF",
"#FAEFF4",
"#EFFAFA",
"#EFF7EB",
"#DBDBDB",
"#EDF1F7",
"#EFF7EB",
"#F7F7E9",
"#EFEFEF",
"#F0E6E6",
"#E6F0EE",
"#F0E6F0",
"#E6E6F0",
"#F0EEDB"
"#F8F8F8",
"#F0F0F0",
"#E8E8E8",
"#E0E0E0",
"#D8D8D8",
"#D0D0D0",
"#C8C8C8",
"#C0C0C0",
"#B8B8B8",
"#B0B0B0",
"#A8A8A8",
"#A0A0A0",
"#989898",
"#909090",
"#888888",
"#808080",
"#787878",
"#707070",
"#686868",
"#606060"
];

function generatePath(int256 curveVal, int256 pos, int256 index) internal pure returns (string memory) {
int256 cVal = curveVal % 100;
int256 bigC = 100 - cVal;

int256 part1x = 33 + pos + 66 * index;
int256 part3x = 66 - pos - 66 * index;
int256 part5x = 33 + pos + 66 * index;

return string.concat(
"m 50 ",
part1x.toString(),
" Q ",
bigC.toString(),
" ",
cVal.toString(),
" ",
part3x.toString(),
" 50 Q ",
bigC.toString(),
" ",
bigC.toString(),
" 50 ",
part3x.toString(),
" Q ",
cVal.toString(),
" ",
bigC.toString(),
" ",
part5x.toString(),
" 50 Q ",
cVal.toString(),
" ",
cVal.toString(),
" 50 ",
part5x.toString(),
" z"
);
}

function hydrateBlog(string[3] memory paths, string[3] memory colors) internal pure returns (string memory) {
return string.concat(
'<path d="',
paths[0],
'" fill="',
colors[1],
'" /><path d="',
paths[1],
'" fill="',
colors[2],
'" /><path d="',
paths[2],
'" fill="',
colors[0],
'" />'
);
}

function background(uint256 dnaBgLayer) internal view returns (string memory) {
return

string(abi.encodePacked('<defs><pattern id="star" fill="', bgColors[dnaBgLayer], '" viewBox="0,0,10,10" width="10%" height="10%"><polygon points="0,0 2,5 0,10 5,8 10,10 8,5 10,0 5,2" /></pattern></defs>','<rect x="0" y="0" width="100" height="100" fill="url(#star)"/>'));
string[3] memory paths = [generatePath(68, 23, 2), generatePath(11, 70, 1), generatePath(38, 67, 0)];
string[3] memory colors = ["#27b4f6", "#D84B09", "#F67094"];
console2.log(hydrateBlog(paths, colors));
return hydrateBlog(paths, colors);
}
}
74 changes: 35 additions & 39 deletions packages/contracts/src/layers/Blob.sol
Original file line number Diff line number Diff line change
Expand Up @@ -73,29 +73,27 @@ contract Blob {
string memory svgPath;
Point memory mid = Point({ x: (points[0].x + points[1].x) / 2, y: (points[0].y + points[1].y) / 2 });

svgPath = string(abi.encodePacked("M", mid.x.toString(), ",", mid.y.toString()));
svgPath = string.concat("M", mid.x.toString(), ",", mid.y.toString());

for (uint256 i = 0; i < points.length; i++) {
Point memory p1 = points[(i + 1) % points.length];
Point memory p2 = points[(i + 2) % points.length];
Point memory midPoint = Point({ x: (p1.x + p2.x) / 2, y: (p1.y + p2.y) / 2 });

svgPath = string(
abi.encodePacked(
svgPath,
"Q",
p1.x.toString(),
",",
p1.y.toString(),
",",
midPoint.x.toString(),
",",
midPoint.y.toString()
)
svgPath = string.concat(
svgPath,
"Q",
p1.x.toString(),
",",
p1.y.toString(),
",",
midPoint.x.toString(),
",",
midPoint.y.toString()
);
}

return string(abi.encodePacked(svgPath, "Z"));
return string.concat(svgPath, "Z");
}

function build(
Expand All @@ -109,31 +107,29 @@ contract Blob {
pure
returns (string memory)
{
return string(
abi.encodePacked(
colorDefs,
'<path id="',
id.toString(),
'" d="',
h1,
'Z" stroke-width="2" stroke="black" transform-origin="center" fill="',
fillColor,
'">',
'<animate attributeName="d" values="',
h1,
";",
h2,
";",
h1,
'" dur="30s" id="',
id.toString(),
'-anim" repeatCount="indefinite"',
' keysplines=".42 0 1 1; 0 0 .59 1; .42 0 1 1; 0 0 .59 1;',
' .42 0 1 1; 0 0 .59 1; .42 0 1 1; 0 0 .59 1;"/>',
'<animateTransform attributeName="transform" type="rotate" ',
'from="0" to="100" dur="1000" repeatCount="indefinite" />',
"</path>"
)
return string.concat(
colorDefs,
'<path id="',
id.toString(),
'" d="',
h1,
'Z" stroke-width="2" stroke="black" transform-origin="center" fill="',
fillColor,
'">',
'<animate attributeName="d" values="',
h1,
";",
h2,
";",
h1,
'" dur="30s" id="',
id.toString(),
'-anim" repeatCount="indefinite"',
' keysplines=".42 0 1 1; 0 0 .59 1; .42 0 1 1; 0 0 .59 1;',
' .42 0 1 1; 0 0 .59 1; .42 0 1 1; 0 0 .59 1;"/>',
'<animateTransform attributeName="transform" type="rotate" ',
'from="0" to="100" dur="1000" repeatCount="indefinite" />',
"</path>"
);
}
}
12 changes: 5 additions & 7 deletions packages/contracts/src/layers/Blush.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,11 @@ pragma solidity 0.8.23;

contract Blush {
function blush() internal pure returns (string memory) {
return string(
abi.encodePacked(
'<circle id="circle-blush" r="6" fill="rgba(255,255,255,0.4)" />',
'<animateMotion href="#circle-blush" dur="30s" begin="0s" ',
'fill="freeze" repeatCount="indefinite" rotate="auto-reverse" ',
'><mpath href="#1" /></animateMotion>'
)
return string.concat(
'<circle id="circle-blush" r="6" fill="rgba(255,255,255,0.4)" />',
'<animateMotion href="#circle-blush" dur="30s" begin="0s" ',
'fill="freeze" repeatCount="indefinite" rotate="auto-reverse" ',
'><mpath href="#1" /></animateMotion>'
);
}
}
Loading

0 comments on commit 3928052

Please sign in to comment.