diff --git a/.gitignore b/.gitignore index 4fd2865..f2bc117 100755 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ ### Custom ### +companion/ all-traits.json gen-stats.json traits.json diff --git a/.version b/.version index e6d5cb8..30290a6 100755 --- a/.version +++ b/.version @@ -1 +1 @@ -1.0.2 \ No newline at end of file +1.1.0a \ No newline at end of file diff --git a/css/main.css b/css/main.css index 578fa24..476a338 100755 --- a/css/main.css +++ b/css/main.css @@ -47,10 +47,14 @@ h3 { } h4 { - width: 500px; + width: 100%; text-align: left; font-size: 16px; - margin: 10px 0; + margin: 10px 0 0 10px; +} + +h5 { + font-size: 16px; } a, @@ -76,6 +80,25 @@ form { justify-content: space-around; } +hr { + width: calc(100% + 10px); + height: 5px; + margin: 8px 0; + border: 1px solid #000; +} + +.hrbottom { + border-top: none; + border-radius: 0; + box-shadow: 0 3px 5px #22243a; +} + +.hrtop { + border-bottom: none; + border-radius: 0; + box-shadow: 0 -3px 5px #22243a; +} + .content { margin: 10px 0; width: 950px; diff --git a/php/edit/3.php b/php/edit/3.php index a7dc28e..3e02366 100755 --- a/php/edit/3.php +++ b/php/edit/3.php @@ -34,22 +34,25 @@ let rarities = []; // Build rarities array (rarities[t][v] = r => Trair 't', variation 'v' has rarity 'r'%) for (const input of form) { - const match = input.id.match(/trait(\d+)_(\d+)_rarity/); + const match = input.id.match(/trait(\d+)_(\d+|empty)_rarity/); if (match) { const [/*ignore*/, trait, variation] = match; if (rarities[trait] === undefined) { rarities[trait] = []; } - rarities[trait][variation-1] = parseFloat(input.value); + if (variation === 'empty') { + rarities[trait]['empty'] = parseFloat(input.value); + } else { + rarities[trait][variation-1] = parseFloat(input.value); + } } } // Iterate through rarities backwards and make sure the sum is 100, or display message const first_t = (rarities[0] === undefined) ? 1 : 0; for (let t = rarities.length - 1; t >= first_t; t--) { - console.log(t); const errorH3 = document.getElementById(`trait${t}_error`); - const sum = rarities[t].reduce((cum, el) => cum + el, 0); - if (sum !== 100) { + const sum = rarities[t].reduce((cum, el) => cum + el, 0) + rarities[t]['empty']; + if (abs(sum - 100) > 1e-6) { // Float comparison for sum == 100, avoids rounding errors errorH3.innerHTML = `The rarity percentages should add up to 100% (not ${sum}%)`; errorH3.hidden = false; window.location.hash = `trait${t}`; @@ -82,14 +85,18 @@

Setup Background Colors:

- -

Color #:

-
- -
-
-
-
-  % -
-
-
- +
+
+

Color #:

+
+
-
-
- +
+
+
+ +
+
+
+ +
+
+
+  % +
+

Setup "" Trait:

- +

Variation #:

-
-
-  % -

@@ -154,9 +166,23 @@
+
+
+  % +
+
+
+
Skip layer:
+
+ +  % +
+
+ @@ -182,6 +208,7 @@ array_push($new_traits["image_layers"][$t]['weights'], (float)$_POST["trait${trait_var}_rarity"]); $v = $v + 1; } + $new_traits["image_layers"][$t]['weights_total'] = (float)$_POST["trait${s}_empty_rarity"] + array_sum($new_traits["image_layers"][$t]['weights']); // Should be 100 } else { $v = 1; $new_traits["image_layers"][$t]['filenames'] = array(); @@ -189,7 +216,7 @@ while ($v <= $new_traits['image_layers'][$t]['variations']) { $trait_var = $s . "_" . $v; $var_name = $_POST["trait${trait_var}_name"]; - $var_weight =(float)$_POST["trait${trait_var}_rarity"]; + $var_weight = (float)$_POST["trait${trait_var}_rarity"]; if (isset($_FILES["trait${trait_var}_file"])) { // New file was uploaded $filename = $_FILES["trait${trait_var}_file"]['name']; @@ -205,6 +232,7 @@ array_push($new_traits["image_layers"][$t]['weights'], $var_weight); // Add weights to weight array $v = $v + 1; } + $new_traits["image_layers"][$t]['weights_total'] = (float)$_POST["trait${s}_empty_rarity"] + array_sum($new_traits["image_layers"][$t]['weights']); // Should be 100 } $t = $t + 1; $s = $s + 1; diff --git a/php/mint.php b/php/mint.php index c247f15..026f1ac 100755 --- a/php/mint.php +++ b/php/mint.php @@ -21,7 +21,7 @@ if (empty($_GET['run']) and (empty($_POST['cid']) or empty($_POST['amount']))) { ?> -

You will not receive estimated fees, this runs the commands with current prices.

+

You will receive estimated fees in the review screen

Current Gas: Gwei

Minter Options

diff --git a/php/setup/3.php b/php/setup/3.php index c339c1e..3e8eecd 100755 --- a/php/setup/3.php +++ b/php/setup/3.php @@ -1,7 +1,7 @@ Trair 't', variation 'v' has rarity 'r'%) for (const input of form) { - const match = input.id.match(/trait(\d+)_(\d+)_rarity/); + const match = input.id.match(/trait(\d+)_(\d+|empty)_rarity/); if (match) { const [/*ignore*/, trait, variation] = match; if (rarities[trait] === undefined) { rarities[trait] = []; } - rarities[trait][variation-1] = parseFloat(input.value); + if (variation === 'empty') { + rarities[trait]['empty'] = parseFloat(input.value); + } else { + rarities[trait][variation-1] = parseFloat(input.value); + } } } // Iterate through rarities backwards and make sure the sum is 100, or display message @@ -46,8 +50,8 @@ for (let t = rarities.length - 1; t >= first_t; t--) { console.log(t); const errorH3 = document.getElementById(`trait${t}_error`); - const sum = rarities[t].reduce((cum, el) => cum + el, 0); - if (sum !== 100) { + const sum = rarities[t].reduce((cum, el) => cum + el, 0) + rarities[t]['empty']; + if (abs(sum - 100) > 1e-6) { // Float comparison for sum == 100, avoids rounding errors errorH3.innerHTML = `The rarity percentages should add up to 100% (not ${sum}%)`; errorH3.hidden = false; window.location.hash = `trait${t}`; @@ -77,61 +81,118 @@ nameInput.value = name; }; - + + if ($t == 0 and $traits['background_color'] === true) { // Background color layer + unset($layer); + $weights_empty = false; + if (($traits['background_color'] === true) and isset($traits['image_layers'][$s])) { + $layer = $traits["image_layers"][$s]; + if (isset($layer['weights_total']) && isset($layer['weights'])) { + $weights_empty = $layer['weights_total'] - array_sum($layer['weights']); + } + } ?>

Setup Background Colors:

- -

Color #:

-
-
-
-
-  % + +
+
+

Color #:

+
+
-
-
- -
-
-
- +
+
+
+ +
+
+
+ +
+
+
+  % +
+
-

Setup "" Trait:

+ } else { // Image layers + $s_offset = 0; + if ($traits['background_color'] === false) { $s_offset = -1; } + unset($layer); + $weights_empty = false; + if (isset($traits['image_layers'][$s + $s_offset])) { + $layer = $traits["image_layers"][$s + $s_offset]; + if (isset($layer['weights_total']) && isset($layer['weights'])) { + $weights_empty = $layer['weights_total'] - array_sum($layer['weights']); + } + } ?> +

Setup "" Trait:

- + +

Variation #:

-
+
+ +
-
-
-  % +
+
+ + + + +
-
-
- +
+
+  %
+
+
+
Skip layer:
+
+ +  % +
+
+ -
-

You will not receive estimated fees, this runs the commands with current prices.

+

You will receive estimated fees in the review screen

Current Gas: Gwei

Transfer Options

diff --git a/python/generate.py b/python/generate.py index 8bdd349..0ffd321 100755 --- a/python/generate.py +++ b/python/generate.py @@ -28,9 +28,9 @@ def __init__(self, layers: list, seed: str, prev_batches: list, dup_cnt_limit: i self.seed = seed # Keep trait properties only, to make comparison to new image easier self.prev_batches = [] + layer_names = [l["layer_name"] for l in self.layers] for image in prev_batches: - layer_names = [l["layer_name"] for l in self.layers] - self.prev_batches.append({name: image[name] for name in layer_names}) + self.prev_batches.append({name: image[name] for name in layer_names if name in image}) self.this_batch = [] self.dup_cnt_limit = dup_cnt_limit @@ -46,7 +46,9 @@ def create_new_image(self, id: int, dup_cnt: int = 0): # For each trait category, select a random trait based on the weightings for l in self.layers: - new_image[l["layer_name"]] = random.choices(l["names"], l["weights"])[0] + random_variation_name = random.choices(l["variation_names"], l["weights"])[0] + if random_variation_name is not None: + new_image[l["layer_name"]] = random_variation_name if new_image in self.this_batch or new_image in self.prev_batches: if dup_cnt > self.dup_cnt_limit: @@ -118,7 +120,10 @@ def make_directories(paths: utils.Struct, traits: utils.Struct, empty: bool): async def build_and_save_image(paths: utils.Struct, traits: utils.Struct, item: dict, task_id: int): with ImageBuilder(animated_format=traits.animated_format) as img_builder: for l in traits.image_layers: - layer_pretty_name = item[l["layer_name"]] + if l["layer_name"] in item: + layer_pretty_name = item[l["layer_name"]] + else: # Skip empty layers + continue if l["type"] == "filenames": layer_file = os.path.join(l["path"], l["filenames"][layer_pretty_name]) @@ -244,10 +249,17 @@ def main(): first_layer = 0 if traits.background_color else 1 for i, l in enumerate(traits.image_layers): l["type"] = "filenames" if "filenames" in l else "rgba" - l["names"] = list(l[l["type"]].keys()) + l["variation_names"] = list(l[l["type"]].keys()) l["path"] = os.path.join(paths.source, f"layer{(first_layer + i):02}") + if "weights_total" in l: # If weights_total is defined, add a chance to skip the layer + weight_skip = l["weights_total"] - sum(l["weights"]) + l["weights"].append(weight_skip) + l["variation_names"].append(None) + else: # Backward compatibility + l["weights_total"] = sum(l["weights"]) + # Generate the unique combinations based on layer weightings img_gen = ImageGenerator(layers=traits.image_layers, seed=args.seed, prev_batches=prev_batches, dup_cnt_limit=utils.get_variation_cnt(traits.image_layers)) this_batch = img_gen.generate_images(starting_id=starting_id, image_cnt=total_image) @@ -266,13 +278,13 @@ def main(): print("How many of each trait exist?") for l in traits.image_layers: - l["count"] = {item: 0 for item in l["names"]} + l["count"] = {item: 0 for item in l["variation_names"] if item is not None} for image in all_images: - n = 1 for l in traits.image_layers: - item = image[l["layer_name"]] - l["count"][item] += 1 + if l["layer_name"] in image: + item = image[l["layer_name"]] + l["count"][item] += 1 for i, l in enumerate(traits.image_layers): print(f"Layer {i:02}: {l['count']}") diff --git a/python/metadata.py b/python/metadata.py index 5a33b4e..6ac76ef 100755 --- a/python/metadata.py +++ b/python/metadata.py @@ -166,7 +166,7 @@ def main(): # Get trait properties only (remove ID, CID, etc...) layer_names = [l["layer_name"] for l in traits.image_layers] - properties = {name: image[name] for name in layer_names} + properties = {name: image[name] for name in layer_names if name in image} # Create all new info token = {