Code Monkey home page Code Monkey logo

art-engine's Introduction

FAQ, general questions, and help

Please check the discussions for similar issues or open a new discussion.

You can find me on twitter or Discord,

❤️ Support This generator ❤️

Eth address: 0xeB23ecf1fa9911fca08ecAbe83d426b6bd525bB0

Features

This repository is a hard-fork from the original Hashlips generator (c.2021) and makes a couple of fundamental changes to how layers are expected to be named and organized. Please read this README's Nesting Structure section and the related Advanced options for a better understanding of how things should be named and organized.

Nested Structures

Options and conditional output

Other Blockchains

Utils

Notes




Nested Layer Support and Trait Type definition modification/branch

This branch of the Hashlips generator builds on the example (v.1.0.6) and allows you to nest sub-folders within your top layer folders, and, optionally gives you a configuration option to overwrite the trait_type that is written to the metadata from those layers.

Example

The following example (included in this repository) uses multiple layer_configurations in config.js to generate male and female characters, as follows.

const layerConfigurations = [
  {
    growEditionSizeTo: 2,
    layersOrder: [
      { name: "Background" },
      { name: "Female Hair", trait: "Hair" },
    ],
  },
  {
    growEditionSizeTo: 5,
    layersOrder: [
      { name: "Background" },
      { name: "Eyeball" },
      { name: "Male Hair", trait: "Hair" },
    ],
  },
];

The Hair layers, exist as their own layers in the layers directory and use the trait key/property to overwrite the output metadata to always look like, the following, regardless of layer folder it is using–so both Male and Female art have a Hair trait.

    {
        "trait_type": "Hair",
        "value": "Rainbow Ombre"
      }

Nesting structure

In this modified repository, nesting subdirectories is supported and each directory can have it's own rarity weight WITH nested weights inside for individual PNG's.

image

For the example above, Female Hair can be read as:

Female Hair layer is required from config -> Randomly select either common or rare with a respective chance of 70% / 30%. If Common is chosen, randomly pick between Dark Long (20% chance) or Dark Short (20%)

Advanced options

Required files

Additionally, png files that ommit a rarity weight will be included always and are considered "required".

This means, that if you need multiple images to construct a single "trait", e.g., lines layer and fill layer, you could do the following:

HAIR
|-- Special Hair#10
|----- 1-line-layer.png
|----- 2-fill-layer.png

Where the containing folder will define the traits rarity and in the event that it is selected as part of the randomization, BOTH nested images will be included in the final result, in alphabetical oder–hence the 1, 2, numbering.

Options

Exclude a layer from DNA

If you want to have a layer ignored in the DNA uniqueness check, you can set bypassDNA: true in the options object. This has the effect of making sure the rest of the traits are unique while not considering the Background Layers as traits, for example. The layers are included in the final image.

layersOrder: [
      { name: "Background" },
      { name: "Background" ,
        options: {
          bypassDNA: false;
        }
      },

Use Parent folders as trait_value in attributes

In some projects, you may define a root folder in layersOrder only as a starting point in the branching structure and not want to use that folders name as the trait_value in the attributes. Rather, nested, weighted subfolders should be the trait_type for example:

layers/Headware
├── Cap#10
│   ├── cap a#6.png
│   └── cap b#6.png
└── Hair#10\
    ├── hair a#6.png
    └── hair b#6.png

Rather than the attribute data always listing Headware as the type, you can use Cap or Hair instead.

Set useRootTraitTypetofalse` in config.js to use parent folder names instead of the root.

Sublayer Options

🧪 BETA FEATURE

Rename Sublayer traits

In the case that your folder names need to include number or anything else that you do not want in the final metadata, you can clean up the trait_type by passing in the trait option to the sublayerOptions object where the nested folder lives. For example, if we are using a subfolder named 1-SubAccessory and want to rename it to Backpack Accessory, pass the following configuration

    layersOrder: [
      {
        name: "Back Accessory",
        sublayerOptions: {
          "1-SubAccessory": { trait: "Backpack Accessory" },
        },
      },
      { name: "Head" },

Blend and Opacity

By default, nested folders will inherit blend and opacity settings from the root-level layer defined in layersOrder. When you need to overwrite that on a sublayer-basis (by name of the nested folder, not by filename), you can specify a sublayerOptions object.

layersOrder: [
      { name: "Clothes" },
      {
        name: "Bases",
        blend: "destination-over", // optional
        sublayerOptions: { Hands: { blend: "source-over" } },
      },
      { name: "Holdableitems" },
    ],

Common Errors

When combining multiple sublayer options, remember that each Sublayer is an object that accepts key:value pairs for each valid option above.

For example, a single layer may have multiple sublayer options in the following format.

sublayerOptions: {
  Hands: {
    trait: 'New trait name',
    blend: 'source-over',
    opacity: 0.9,
  },
  Face: {
    trait: 'the face',
    blend: 'source-over',
    opacity: 0.9,
  }
}

In the example above: The intended stacking order is Base > Clothes > Hand > holdableItem, because Hands are a nested subfolder of Bases, this can be tricky. By defining blend: destination-over for the Base, and then source-over for the Hands, the stacking order can be controlled to draw the Base under the clothes and then the Hand above the clothes.

Metadata Name and Number

Name + Number prefix and reset for configuration sets

If you are using the generator with multiple layerConfiguration objects to generate different species/genders/types, it is possible to add a name prefix and a reset counter for the name, so the token names start at 1 for each type.

for example, if you are creating multiple animals, and each animal should start with Animal #1, but the token numbers should increment as normal, you can use the following namePrefix and resetNameIndex properties to acheive this.

    growEditionSizeTo: 10,
    namePrefix: "Lion",
    resetNameIndex: true, // this will start the Lion count at #1 instead of #6
    layersOrder: [
      { name: "Background" },
      { name: "Eyeball" },
      { name: "Male Hair", trait: "Hair" },
    ],

You may choose to omit the resetNameIndex or set it to false if you would instead like each layer set to use the token (_edition) number in the name–it does this by default.

Chance of "NONE" or skipping a trait

If you would like any given layer or sublayer to have a chance at rolling NONE, you can do this by adding a blank PNG to the folder, and giving it the name of NONE + the weight you would like to use for it's chance of being chosen–identical to any other layer.

NONE#20.png

By using this feature, the trait will not be included in the metadata. For example, rather than having trait_type: 'Hat', value: 'NONE" in the metadata, it will be skipped.

You can change the name

If you need to change the name from "NONE" to something else, you can change the following in config.js

// if you use an empty/transparent file, set the name here.
const emptyLayerName = "NONE";

⚠️ NOTE: if you would like the trait to appear as "NONE", change the empty layer name to something you are not using. e.g., 'unused'.

Controlling layer order (z-index)

Generally, layer order is defined by using layersOrder in config.js. However, when using nested folders, layer order defaults to alphanumerec sorting (0-9,a-z)

To manually define stacking order for sublayers (nested folders) use the z#, (z followed by a positive or negative number, followed bu a , commma) prefix for folder names and/or file names.

Example folders

|- z-1,folder
|-normal folder/
|-z1,foldername
|-z2,foldername/
|-- z-2,image-that-needs-to-go-under-everything.png

Folders and files without a z#, prefix default to a z-index of 0

If a file has a z#, prefix, and it's parent folder(s) does as well, the files z-index will be used, allowing you to overwrite and define an individual's layer order.

Layer order z-indexes are "global" meaning the index is relative to ALL OTHER z-indices defined in every folder/file

Flagging Incompatible layers

👉 For edge cases only Nested Folders should always be used first and can solve 90% of "if this, then not that" use cases.

To flag certain images that should never be used with another image, for this, you can use the incompatible configuration in config.js

To set incompatible items, in the incompatible object, use the layer/images cleanName (the name without rarity weight, or .png extension) as a key, and create an array of incompatible layer names (again, clean names). Layers that have space or hyphens in their names should be wrapped in quotes

⚠️ NOTE: Names are expected to be unique. if you have multiple files with the same name, you may accidentally exclude those images.

const incompatible = {
  Red: ["Dark Long"],
  "Name with spaces": ["buzz","rare-Pink-Pompadour" ]
  // directory incompatible with directory example
  White: ["rare-Pink-Pompadour"],
};

⚠️ NOTE: This relies on the layer order to set incompatible DNA sets. For example the key should be the image/layer that comes first (from top to bottom) in the layerConfiguration. in other words, IF the item (KEY) is chosen, then, the generator will know not to pick any of the items in the [Array] that it lists.

Forced Combinations

10

When you need to force/require two images to work together that are in different root-layer-folders (the layer config), you can use the forcedCombinations object in config.js.

const forcedCombinations = {
  floral: ["MetallicShades", "Golden Sakura"],
};

Using the clean Name (file name without weight and .png extension), specify the key (if names have spaces, use quotes "file name" :)

Then, create an array of names that should be required.

Note: the layer order matters here. The key (name on the left) should be a file withing a layer that comes first in the layersOrder configuration, then, files that are required (in the array), should be files in layers afterward.

Debugging:

set debugLogging = true in config to check whether files are being set and picked for the forced combinations. You should see output that looks like the following if it is wokring:

image

If not, double check your file names, layer ordering, and quotation marks.

Outputting Jpegs

If you're working with higher res, it's recommended for your storage-costs-sake to output the image to jpeg, to enable this, set outputJPEG in config.js to true.

const outputJPEG = true; // if false, the generator outputs png's

⚠️ NOTE: If you're running an M1 Mac, you may run into issues with canvas outputting jpegs and may require additional libraries (e.g. Cairo) to solve and may not work at this time.

Attribute Display Types and Overrides

If you need to add randomized values for traits and different display types supported by OpenSea, this branch re-purposes the extraAttributes configuration for that purpose.

in config.js

const extraAttributes = () => ([
  {
    // Optionally, if you need to overwrite one of your layers attributes.
    // You can include the same name as the layer, here, and it will overwrite
    //
    "trait_type": "Bottom lid",
    value:` Bottom lid # ${Math.random() * 100}`,
    },
  {
    display_type: "boost_number",
    trait_type: "Aqua Power",
    value: Math.random() * 100,
  },
  {
    display_type: "boost_number",
    trait_type: "Mana",
    value: Math.floor(Math.random() * 100),
  },

You are free to define extra traits that you want each generated image to include in it's metadata, e.g., health.

Be sure to pass in a randomization function here, otherwise every json file will result in the same value passed here.

Optional

This also supports overwriting a trait normally assigned by the layer Name/folder and file name. If you'd like to overwrite it with some other value, adding the same trait in extraMetadata will overwrite the default trait/value in the generated metadata.

Trait Value Overrides

🧪 BETA FEATURE

When you need to override the trait_value generated in the metadata.

By default trait values come from the file name or subfolder that is chosen (the last one in a nested structure with a weight delimiter). Because many options require the filenames to be unique, there may be a situation where you need to overwrite the default value. To do this, set the overrides in config.js

/**
 * In the event that a filename cannot be the trait value name, for example when
 * multiple items should have the same value, specify
 * clean-filename: trait-value override pairs. Wrap filenames with spaces in quotes.
 */
const traitValueOverrides = {
  Helmet: "Space Helmet",
  "gold chain": "GOLDEN NECKLACE",
};

Provenance Hash Generation

If you need to generate a provenance hash (and, yes, you should, read about it here ), make sure the following in config.js is set to true

//IF you need a provenance hash, turn this on
const hashImages = true;

Then… After generating images and data, each metadata file will include an imageHash property, which is a Keccak256 hash of the output image.

To generate the Provenance Hash

run the following util

  node utils/provenance.js

The Provenance information is saved to the build directory in _prevenance.json. This file contains the final hash as well as the (long) concatednated hash string.

*Note, if you regenerate the images, You will also need to regenerate this hash.

Remove Trait Util

If you need to remove a trait from the generated attributes for ALL the generated metadata .json files, you can use the removeTrait util command.

node utils/removeTrait.js "Trait Name"

If you would like to print additional logging, use the -d flag

node utils/removeTrait.js "Background" -d

Randomly Insert Rare items - Replace Util

If you would like to manually add 'hand drawn' or unique versions into the pool of generated items, this utility takes a source folder (of your new artwork) and inserts it into the build directory, assigning them to random id's.

Requirements

  • create a source directory with an images and json folder (any name, you will specify later)
  • Name images sequentially from 1.png/jpeg (order does not matter) and place in the images folder.
  • Put matching, sequential json files in the json folder

example:

├── ultraRares
│   ├── images
│   │   ├── 1.png
│   │   └── 2.png
│   └── json
│       ├── 1.json
│       └── 2.json

You must have matching json files for each of your images.

Setting up the JSON.

Because this script randomizes which tokens to replace/place, it is important to update the metadata properly with the resulting tokenId #.

Everywhere you need the edition number in the metadata should use the ## identifier.

  "edition": "##",

Don't forget the image URI!

  "name": "## super rare sunburn ",
  "image": "ipfs://NewUriToReplace/##.png",
  "edition": "##",

if you need #num with the # in the name for example, use a different symbol other than ##. see the --replacementSymbol flag below

Running

Run the script with the following command, passing in the source directory name, (relateive to the current working dir)

node utils/replace.js [Source Directory]

example

node utils/replace.js ./ultraRares

Flags

--help

Outputs command help.

--Debug

-d outputs additional logging information

--replacementSymbol

If you need the output data to have #12 for example, with the leading #, the default ## in the metadata is a problem. use this flag in combination with a different symbol in the metadata json files to replace the passed in symbol with the appropriate edition number

node index.js ./ultraRares -r '@@'

This will replace all instances of @@ with the item number

--identifier

-i Change the default object identifier/location for the edition/id number. defaults to "edition". This is used when the metadata object does not have "edition" in the top level, but may have it nested in "properties", for example, in which case you can use the following to locate the proper item in _metadata.json

node utils/replace.js ./ultraRares -i properties.edition

⚠️ This step should be done BEFORE generating a provenance hash. Each new, replaced image generates a new hash and is inserted into the metadata used for generating the provenance hash.

⚠️ This util requires the build directory to be complete (after generation)


Solana Metadata

🧪 BETA FEATURE

If you are building for Solana, all the image generation options in config are available and are the same.

To setup your Solana specific metadata

Configure the solona_config.js file located in the Solana/ folder. Here, enter in all the necessary information for your collection.

You can run the generator AND output Solana data by running the following command from your terminal

yarn generate:solana

If you are using npm,

npm run generate:solana

After running, your Solana ready files will be in build/solana

If you need to convert existing images/json to solana metadata standards, you can run the util by itself with,

node utils/metaplex.js

Cardano Metadata

🧪 BETA FEATURE: Work in progress ⚠️ Check the output metadata for cardano standards accuracy

If you are generating for Cardano, you can generate and output cardano formatted data at the same time, or run the util script separately after generation (or to an existing collection with proper data)

First, edit the cardano_config.js file in the Cardano/ folder with your information.

Then, to generate images and cardano data at once, run:

yarn generate:cardano

or if you're using npm

npm run generate:cardano

running the standalone cardano util

If you have an existing set of generated images and data, and you have a configured Cardano/cardano_config.js file, you can run the cardano conversion script with:

node utils/cardano.js

GIF compatibility

This tool currently does not support gif layers or outputting gifs. If you want to GIF generative tool, check out Jalagar's GIF Engine. It supports most of the same functionality as this repo (if-then, z-index, layering, Tezos, Solana, legendary replace). If you have any questions or issues, please create a issue/discussion on Jalagar's repo.

incompatibilities

⚠️ This was forked originally from hashlips 1.0.6 and may have different syntax/options. Be sure to read this readme for how to use each feature in this branch.

Example:

For example, if you are using a Backgrounds layer and would prefer to remove that as a trait from the generated json, First, generate the images and json as usual, then, running the remove trait util


node utils/removeTrait.js "Background"

Will remove the background trait from all metadata files.

Breaking Changes

  1. extraMetadata in prior version of this repo/branch, extraMetadata was used for attributes, it has been renamed extraAttributes






Basic Setup

This is fork/combination of the original hashlips generator, for basic configuration Check the Basic Configuration readme


art-engine's People

Contributors

flowerpower avatar hashlips avatar instavivek avatar j-greig avatar jalagar avatar joebalancio avatar mediavrog avatar mexitek avatar nftchef avatar seibelj avatar solanajax avatar sturench avatar thoerner avatar vivekascoder avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

art-engine's Issues

RarityData.js fails Cannot read properties of undefined

known Issue reading traits when anything has been modified or added.

rarityDataTraits.elements.forEach((rarityDataTrait) => { ^

TypeError: Cannot read properties of undefined (reading 'elements')

I am currently in the process of rewriting the rarity data util with an expected release by the first week of Feb 2022 🤞

One set of image & json will be missing

There is always one set of image and json missing when we have multiple layer configuration and shuffleLayerConfiguration.

For example , with the setting below :

const layerConfigurations = [
  {
    growEditionSizeTo: 2,
    layersOrder: [ ...]
   },
  {
    growEditionSizeTo: 5,
    layersOrder: [ ...]
   }
];

const shuffleLayerConfigurations = true;

The 2.png & 2.json will always be missing in the build.

Define max_value for extraAttributes?

Is it possible to set a max_value for randomised values created using extraAttributes?

As per the metadata standards on OpenSea: "Adding an optional max_value sets a ceiling for a numerical trait's possible values. It defaults to the maximum that OpenSea has seen so far on the assets on your contract. If you set a max_value, make sure not to pass in a higher value."

https://docs.opensea.io/docs/metadata-standards#numeric-traits

In our case we'd set max_value to 100 and be generating a number between 0 and 100.

Thanks! :)

"bypassDNA" equivalent within nested folders?

I've switched from defining layers in the config to nesting them.

Previously I had an "Ears" layer that was bypassed and removed from the traits so that for all intents and purposes it was part of the "Head" layer below it.

Is there a way to achieve this within a nested folder structure — imagine you could prefix a layer so that it wasn't included in the metadata, but an image layer inside it was still picked and included at random in the image output....

typo in blendMode.js

in BlendMode.js

it is stated as:

sourceOut: "source-out",
sourceAtop: "source-out",

so whenever someone tries to use sourceAtop feature, it results in sourceOut instead. It was a little confusing till i figured out where the problem was. Please update it to:

sourceAtop: "source-atop", so others won't have the same problem.

Thanks a lot for your work, this is a great repo!

Issue once running script: Symbol not found: ____chkstk_darwin

Hello everyone and hello NFT Chef,

I just tried to build my collection but im running into a problem:

(node:19510) [DEP0147] DeprecationWarning: In future versions of Node.js, fs.rmdir(path, { recursive: true }) will be removed. Use fs.rm(path, { recursive: true }) instead
(Use node --trace-deprecation ... to show where the warning was created)

Clearing canvas
dyld: lazy symbol binding failed: Symbol not found: ____chkstk_darwin
Referenced from: /.../node_modules/canvas/build/Release/libpixman-1.0.40.0.dylib (which was built for Mac OS X 10.15)
Expected in: /usr/lib/libSystem.B.dylib

dyld: Symbol not found: ____chkstk_darwin
Referenced from: /.../node_modules/canvas/build/Release/libpixman-1.0.40.0.dylib (which was built for Mac OS X 10.15)
Expected in: /usr/lib/libSystem.B.dylib

Abort trap: 6

My operating System is IOS 10.13, but i cannot really upgrade to Catalina.
I've seen that this problem came up once at the issues of the HAE, and supposedly it was due to some dependencies, I wonder if you could also have a look at this in your fork?
If anybody has other ideas how to solve this issue I would be glad to hear them.

Here the link to the older thread referring to the same issue:
HashLips#1

Thank you!

Duplicates when using bypassDNA

Hi, when I tried using the code to generate a collection with bypassDNA on the background layers, I get some duplicates with no error. However, when I remove the bypassDNA factor, I am able to generate all unique images.

Not sure what is the issue and need some help.
Thank you.

Question: Why do images generate 1 extra

Hello, Thank you for this generator!

Just a question not sure if this is an issue.
I want to generate 20 images, I get 21 images instead. I changed the start index to 1, as I assumed this maybe because the images started with a 0 but the generator is still producing an extra image.

Thank you =)

The problem of filtering pictures after generation

Hello, when you need to filter some wrong pictures or unwanted pictures after generation, do you want to modify the json after deleting the pictures? For example, I deleted the 5th picture, do I have to manually delete the json? Can it be reordered once after deleting the filter?

Solana build does not output jpeg's

When using the Solana script with const outputJPEG = true the jpegs are not being renamed/regenerated in the Solana folder.

Issue: Solana script is not reading the variable to change file type

Is there a way to make a part add 2 objects in the metadata?

I have a part of a hair and a hat but the hair passes the hat, I would like to know if there is a way I can make a specific design for that hat with the hair, it would just be an image containing 2 parts of the metadata example:

Hair1 + Hat1 = HAIR1andHAT1

Subfolder layering order

Is there a way to dictate in which order a sublayer is chosen. I know files within folders that don't have rarity will be selected alpha but what about subfolders that don't have rarity?

Provenance Hash Questions

I have a questions about provenance hash.

Projects such as Bored Ape Yacht Club have a webpage like this. Picture:
154821685-f279004f-7715-493f-8962-c54fffecd05e-1
Screen Shot 2022-02-23 at 10 58 01 PM

I'm not sure how one would recreate this Bored Ape Yacht Club webpage when using this library. Some questions I have are:

  1. How does one choose a starting index? Is this randomly chosen by us and set here in library as shown here with const startIndex = 0;? Some projects like Invisible Friends seem to do complicated things to get a starting index as shown in link.
  2. Is this formula (tokenId + startingIndex) % 10000 → Initial Sequence Index used at all in this library? Not sure if this is something done somewhere else.
  3. I generated the provenance hash with node utils/provenance.js using sample artwork. However, I don't see the hashes of individual images. Are these provided?
  4. Is the Bored Ape Yacht Club webpage overkill?

I can't generate images with layers without weight (Nested folders don't work)

If I have one .png without weight (example: Body.png) I receive this error:

TypeError: Cannot read properties of undefined (reading 'split')
at cleanDna (C:\Users\Abi\OneDrive\Desktop\MfersKittens\artengine\src\main.js:54:25)
at C:\Users\Abi\OneDrive\Desktop\MfersKittens\artengine\src\main.js:151:22
at Array.find ()
at C:\Users\Abi\OneDrive\Desktop\MfersKittens\artengine\src\main.js:150:42
at Array.map ()
at constructLayerToDna (C:\Users\Abi\OneDrive\Desktop\MfersKittens\artengine\src\main.js:149:35)
at startCreating (C:\Users\Abi\OneDrive\Desktop\MfersKittens\artengine\src\main.js:248:23)
at C:\Users\Abi\OneDrive\Desktop\MfersKittens\artengine\index.js:13:3
at Object. (C:\Users\Abi\OneDrive\Desktop\MfersKittens\artengine\index.js:14:3)
at Module._compile (node:internal/modules/cjs/loader:1103:14)

Also I have the exact problem If I have one file with a "space" in the name, example: Black Shirt.png (I receive the same error)

Issue with shuffleLayerConfigurations when startIndex = 0

The problem is when shuffleLayerConfigurations is set to true, the length of abstractedIndexes is actually off by one, so the numbering is off.

For example, set growth edition to 10 and set shuffleLayerConfigurations to true, and set startIndex to 0, the resulting JSON has a chance that it will not start at 0 and include 1,2,3,4,5 or it will start at 0 and skip a number ex. 0,1,2,4,5. This is an easy fix, just set the loop to:

  for (
    let i = startIndex;
    i <=
    startIndex +
      layerConfigurations[layerConfigurations.length - 1].growEditionSizeTo - 1;
    i++

and subtract 1 if startIndex = 0. This may have to be changed for startIndex = 1 (or some other number) but still a bug

Multiple layer configurations not working

It only generates the one of the two, here is my config

const layerConfigurations = [
  {
    growEditionSizeTo: 1,
    namePrefix: "Male", // Use to add a name to Metadata `name:`
    layersOrder: [
      // { name: "Background" },
      { name: "Offhand" },
      { name: "Base - Male", trait: "Base" },
      // { name: "special" },
      { name: "Clothing - Male", trait: "Clothing" },
      { name: "Mouth" },
      { name: "Ear" },
      { name: "Eyes - Male", trait: "Eyes" },
      // { name: "Face - Male", trait: "Face" },
      { name: "Neckwear - Male", trait: "Neckwear" },
      { name: "Hair - Male", trait: "Hair" },   
      { name: "Headgear" }
    ],
  },
  {
    growEditionSizeTo: 1,
    namePrefix: "Female",
    resetNameIndex: false, // this will start the Lion count at #1 instead of #6
    layersOrder: [
      // { name: "Background" },
      { name: "Offhand" },
      { name: "Base - Female", trait: "Base" },
      // { name: "special" },
      // { name: "Clothing - Female", trait: "Clothing" },
      { name: "Mouth" },
      { name: "Ear" },
      { name: "Eyes - Female", trait: "Eyes" },
      // { name: "Face - Female" },
      { name: "Neckwear - Female" },
      { name: "Hair - Female", trait: "Hair" },   
      { name: "Headgear" }
    ],
  }
];

Tezos Support??

Hi Chef! Wondering, in case anyone else is interested, can we please get Tezos support in your fork?

Another Dev came up with this: https://github.com/tqtezos/minter

but it's missing all the awesome sauce of your fork (nested structure, omitting metadata during generation, etc)

Thanks in advance :)

One image missing and one additional at the end?

Discussed in #85

Originally posted by ultraviolet007rainbow March 1, 2022
Hi,

I just generated 10K again starting with 1, and ended up with 10,001 as the final image.
I went through and found out that there was a missing image at 7630.
So I edited the JSON of 10,001 to become 7630 instead as it should have been and made sure all the filenames were changed as well (JSON and Image). Will this affect the _dna.json in any way? I did identify the correct DNA line in the _dna.json that corresponds to image 10,0001 which is now image 7630. But I do not see anything in the _dna.json that would directly link it other than the traits to a specific filename (JSON or image). So is there a way to regenerate the _dna.json from the JSON files now that I have fixed the problem manually?

In addition, I found an oddity looking at the _dna.json where one of my background images I used has a numerical filename, none of the other layer files have numerical names other than this one. So in the _dna.json each one of those that has that specific background layer has 0.0 at the head of the line, which clearly is wrong. So for some reason the 0.0 was set because of the numerical layer name, is my assumption.

Is there a good way to fix this problem?

My only idea is to rename the layer to something else in every JSON file as well as the actual layer name of that specific background PNG.

And also replace all instances in the _dna.json file of that numerical layer name.

Once again will this break anything, can I regenerate the _dna.json from the altered JSON files?

Thank you for your great improvements and enhancements to the original code.

Regards.

Improvement request/help

I need to make a specific file to be incompatible with an entire folder
For example I'm creating an avatar that has folder with clothes, then another folder with necklaces
I need to add to incompatible object a single piece of clothing by its filename, then say that it wont be compatible with any file on necklace folder
lets say I have inside Clothes folder, the files clothes_01, clothes_02, clothes_03 and so on...
This is how the incompatible object would be represented

const incompatible = { Clothes_03: ["Necklace"], };

Could you suggest the right approach to achieve this? I can totally do that just on my side of the code if you don't plan to support this

Thanks!

Layers and Blending

Hello, are there any in depth examples or walkthroughs for sublayers and blending modes? I have a configuration of 11 traits. I have some effects that will show up over everything else so that is listed to generate last. There are a few layering issues with my Effects and other traits. I need to separate pieces of the Effects to appear behind everything else and over the Background trait.

  { name: "Background" },
  { name: "Hand" },
  { name: "Race" },
  { name: "Face" },
  { name: "Clothing" },
  { name: "Eyes" },
  { name: "Hair" },
  { name: "Mouth" },
  { name: "Ear" },
  { name: "Hat" },
  { name: "Effect" },

Inconsistent layer order sorting when using nested folders

When using nested folders, layers are sometimes ordered wrong.

Example case; subfolders are named as: 1-Layer, 2-Layer, 3-Layer, etc.
See how they are listed out of order in the DNA:
image
While the expected outcome would be:
image

This issue does not occur if z indexes are used. Let me know if you need any further details to replicate the issue, and thanks for making such an awesome fork @nftchef!

bypassDNA is not working

When adding bypassDNA to one of the layers it is not removing it from the dna.
For example:
Background - 20 items
Body - 10 items (bypassDNA true)
it is still able to make more than 20 NFTs.

if you have any idea what could cause the issue and how to solve it will be a life safer !

Nested Layer Order Not Respected

Hello All,

I'd like to start by saying, fantastic work on this art engine. I've been putting together a project and it's mostly going well. However there is one big problem. Nested layer order is not respected, i.e. In a nested folder layers are not added in the right order.

Here's an example of the nested folder structure for cloths

Cloths
|--Cloth_01#15
|----1_Base
|------Base_01#10.png
|------Base_02#10.png
|----2_Secondary
|------Secondary_01#10.png
|----3_Tertiary 
|------Tertiary_01#10.png
|----4_LineArt
|------Line_Art#100.png

and here is an example of the config

 {
    growEditionSizeTo: 10,
    layersOrder: [
      { name: "Base Body" },
      { name: "Cloths",
    },

For the output I would expect something like below (and that is why i have numbered the folders). Where the line art is the last layer

Base_01#10.png
Secondary_01#10.png
Tertiary_01#10.png
Line_Art#100.png

Some images will generate with the correct ordering however some will not and i'll get some other layer at the top (not the lineart) like below.

Base_01#10.png
Secondary_01#10.png
Line_Art#100.png

Tertiary_01#10.png

Any ideas on why this happens? Going by the docs, all the folders are named correctly.

npm run preview

The previous version had a run preview. I'm wondering when their project was forked and it included this. I got the following message when I tried to run it.

npm ERR! missing script: preview

multiple reset name indexing produces negative numbers

line 749 acc += layer.growEditionSizeTo;

change to acc = layer.growEditionSizeTo;

acc value persists with the original += and results in negative numbers if you have multiple different layer configurations that should reset the name index. Was really throwing me off for a while. Please update for future users, fantastic tool

Question - GIF Creations Instead Of Only Images

Hi @nftchef ,

I have been searching far and wide, but not getting any direction on this topic. I have a user that would like to be able to use a layer setup where they have both gifs and png files as their layer items, all with transparent backgrounds, apart from the backgrounds folder, and would like to build a new gif that is made up of the combination of these layers.

Have you been able to build this on your side before or have seen anyone one build it or can perhaps assist me in building this out? I am attaching a layer configuration set if you would like to take a stab at it.

Layer.zip

Thanks for all your work on the code repo, much appreciated!

Kind Regards,
Rohan (ThePeanutGalleryAndCo) ;)

Is it possible to shuffle the order of multiple `layerConfigurations`?

Hi, I was wondering if it is possible to shuffle the order of multiple layerConfigurations instead of placing them consecutively. Say I have my layerConfigurations set like the following:

const layerConfigurations = [
  {
    growEditionSizeTo: 10,
    layersOrder: [
      { name: "Female Hair", trait: "Hair" },
    ],
  },
  {
    growEditionSizeTo: 20,
    layersOrder: [
      { name: "Male Hair", trait: "Hair" },
    ],
  },
];

By default, only the first 10 images will have "Female Hair" and the next 10 will have "Male Hair". However, is it instead possible for image #0, #1 and #4 to have "Female Hair" and #2, #3 and #5 to have "Male Hair"? I would like it to be in a randomised order to avoid images with similar layers being grouped together in the final collection.

Thanks in advance

Cannot run any utils at all, weird, plz help :)

Discussed in #59

Originally posted by ultraviolet007rainbow February 23, 2022
Hi,

For some reason I try running any util and none of them are found by name.

npm run rarityData

npm run provenance

etc.

I generated all my art, JSONs and the main JSON, all in the correct default folders.

So why does it keep failing?

Any ideas would be appreciated.

Thanks.

Using incompatible / forced

Hi there, I've been using this fork and it is very impressive, but I haven't been able to put either the incompatible or forced constraints. I've tried doing it with the cleannames of the traits I want to not pair up and with folder names. Whenever I put that string of code in my IDE will no longer run index.js.

I thought maybe it was because of where I placed the "const incompatible " before or after the layer config or any number of incorrect syntax but it doesn't seem to be the issue. Do I need to put it inside the layer order brackets, or within something else?

Based on my reading I assume there is a way to only use a particular trait (let's say a body) with a certain type of hair just with the nesting of the folders but I haven't been able to figure that out either.

Since I probably screwed up some of the proper terms it should be apparent I'm very new to all this so any help is greatly appreciated, forgive my ignorance!

Force Combination Error

Hello,

Every time the engine attempts to create a forced combination that includes a nested layer after a previous layer it errors back like when you miss type a clean name. If I list it first and then any layers after it will work perfectly fine.

How can I fix this issue?

Error when build with forcedCombinations

When trying to force combination i got the error:

Setting up the folling forced combinations for floral:  MetallicShades Golden Sakura
Force picking MetallicShades/n
(node:10936) [DEP0147] DeprecationWarning: In future versions of Node.js, fs.rmdir(path, { recursive: true }) will be removed. Use fs.rm(path, { recursive: true }) instead
(Use `node --trace-deprecation ...` to show where the warning was created)
C:\Users\Raul Tribuzi\Documents\GitHub\art-engine\src\main.js:466
    let dnaString = `${parentId}.${forcedPick.id}:${element.zindex}${forcedPick.filename}${bypassDNA}`;

So on line 466 i made the change from:

let dnaString = `${parentId}.${forcedPick.id}:${element.zindex}${forcedPick.filename}${bypassDNA}`;

to:
let dnaString = ${parentId}.${forcedPick.id}:${forcedPick.zindex}${forcedPick.filename}${bypassDNA};

and worked for me.

SyntaxError when building: "Unexpected token ." in main.js

Running the build compile on the default package gave the error below.

I have manually installed eslint as NPM was complaining it was missing when I ran the install.

My Node version is v11.15.0

Sorry if this is an obvious fix I've not done anything from the command line for a long time!

[UPDATE: the build script works fine if I comment out anything related to layer.sublayerOptions in main.js]

/strongbots-generator/src/main.js:126
  if (layer.sublayerOptions?.[sublayer]) {
                            ^

SyntaxError: Unexpected token .
    at Module._compile (internal/modules/cjs/loader.js:760:23)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:827:10)
    at Module.load (internal/modules/cjs/loader.js:685:32)
    at Function.Module._load (internal/modules/cjs/loader.js:620:12)
    at Module.require (internal/modules/cjs/loader.js:723:19)
    at require (internal/modules/cjs/helpers.js:14:16)
    at Object.<anonymous> (/strongbots-generator/index.js:6:39)
    at Module._compile (internal/modules/cjs/loader.js:816:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:827:10)
    at Module.load (internal/modules/cjs/loader.js:685:32)
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] build: `node index.js`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] build script

Hitting duplicate DNA images several times - no error

I am using nftchef with multiple layer sets
Windows 7. Packages, dependencies are upto date
PS C:\Users...\nftchef\art-engine-nested-folder-structure> node --version
v16.13.2
PS C:\Users..\nftchef\art-engine-nested-folder-structure> npm --version
8.1.2
No nested layers - all flat. rarities allocations r there though.
Check out the attachments. spreadsheet has the dups highlighted in pink. Its snipped - full version with 1000 nfts has many dups
Hit this multiple times. Just rebooted the laptop to try again.
If someone hit this and found something, do update.

Config.js

"use strict";

const path = require("path");
const isLocal = typeof process.pkg === "undefined";
const basePath = isLocal ? process.cwd() : path.dirname(process.execPath);
const { MODE } = require(path.join(basePath, "src/blendMode.js"));

const buildDir = path.join(basePath, "/build");
const layersDir = path.join(basePath, "/layers");

const description =
"BTTTTMTTTT";
const baseUri = "ipfs://UPDATE";

const outputJPEG = false; // if false, the generator outputs png's
/**
duplicate-dna-snip.xlsx
layers-pic-dna-err

  • Set your tokenID index start number.
  • ⚠️ Be sure it matches your smart contract!
    */
    const startIndex = 0;

// if you use an empty/transparent file, set the name here.
const emptyLayerName = "NONE";

//IF you need a provenance hash, turn this on
const hashImages = false;

const layerConfigurations = [
// Rangers group layers
{
growEditionSizeTo: 300,

layersOrder: [
  
  { 
    name: "BeeClan",   //dummylayer
    options: {
      bypassDNA: true,
    }
  },      
  { name: "Island" },

  { name: "BeeWings" },

  //this is dummy layer
  { name: "Holstered" },

  { name: "BeeCore"  },
  { name: "BeeFamilyStyle" },  // This is body pattern
  { 
    name: "BeeFamily", 
    options: {
      bypassDNA: true,
    }
  },   

  { name: "SpectrumAntennae" },
  { name: "VisorGear"  },
  { name: "Weapons" },
  { name: "RightArmOver" },
  
],

},
// Brawnies LayerGroup2
{
growEditionSizeTo: 450,
layersOrder: [

  { 
    name: "BeeClan",   //dummylayer
    options: {
      bypassDNA: true,
    }
  },      
  { name: "Island" },

  { name: "BeeWings" },
  { name: "Holstered" },
  { name: "BeeCore"  },
  { name: "BeeFamilyStyle" },  // This is body pattern
  { 
    name: "BeeFamily", 
    options: {
      bypassDNA: true,
    }
  },


  { name: "ManaVacCannister" },
  // remove this in metadata
  { name: "BrawnyShield" },
  { name: "SpectrumAntennae" },
  { name: "VisorGear"  },

],

},

// Diviners LayerGroup3
{
growEditionSizeTo: 500,
layersOrder: [

  { 
    name: "BeeClan",   //dummylayer
    options: {
      bypassDNA: true,
    }
  },    
  { name: "Island" },

  { name: "BeeWings" },
  { name: "Holstered" },  
  { name: "BeeCore"  },

  { name: "BeeFamilyStyle" },  // This is body pattern
  { 
    name: "BeeFamily", 
    options: {
      bypassDNA: true,
    }
  },

  { name: "ManaExtractor"  },
  { 
    name: "SpectrumXSAntennae", trait: "SpectrumAntennae" 
  },
  { name: "VisorGear"  },
  { name: "Tools" },
  { name: "RightArmOver" },
],

},
];

/**

  • Incompatible items can be added to this object by a files cleanName
  • This works in layer order, meaning, you need to define the layer that comes
  • first as the Key, and the incompatible items that may come after.
  • The current version requires all layers to have unique names, or you may
  • accidentally set incompatibilities for the wrong item.
    */
    const incompatible = {
    // Red: ["Dark Long"],
    // // directory incompatible with directory example
    // White: ["rare-Pink-Pompadour"],
    };

/**

  • Require combinations of files when constructing DNA, this bypasses the
  • randomization and weights.
  • The layer order matters here, the key (left side) is an item within
  • the layer that comes first in the stack.
  • the items in the array are "required" items that should be pulled from folders
  • further in the stack
    */

// Clan 3
const forcedCombinations = {

ChiefDiamondStonerWing: ["ChiefDiamondStoner", "DegenStoners"],
AmethystStonerWing: ["AmethystStoner", "DegenStoners"],
GoldStonerWing: ["GoldStoner", "DegenStoners"],
RubyStonerWing: ["RubyStoner", "DegenStoners"],
SaphireStonerWing: ["SaphireStoner", "DegenStoners"],
EmeraldStonerWing: ["EmeraldStoner", "DegenStoners"],

ChiefSpookySpiritWing: ["ChiefSpookySpirit", "SpookySpirits"],
EarthSpiritWing: ["EarthSpirit", "SpookySpirits"],
WindSpiritWing: ["WindSpirit", "SpookySpirits"],
WaterSpiritWing: ["WaterSpirit", "SpookySpirits"],
FireSpiritWing: ["FireSpirit", "SpookySpirits"],
EtherSpiritWing: ["EtherSpirit", "SpookySpirits"],

ChiefFlamingFuryWing: ["ChiefFlamingFury", "FlamingFury"],
NightfallFuryWing: ["NightfallFury", "FlamingFury"],
GoldFuryWing: ["GoldFury", "FlamingFury"],
SmokyFuryWing: ["SmokyFury", "FlamingFury"],
PurpleFuryWing: ["PurpleFury", "FlamingFury"],
ForestFuryWing: ["ForestFury", "FlamingFury"],

};

/* Clan 2
const forcedCombinations = {

CocktailBoozyWing: ["CocktailBoozy", "BoozyBand"],
VinoBoozyWing: ["VinoBoozy", "BoozyBand"],
BeerBoozyWing: ["BeerBoozy", "BoozyBand"],
WhiskeyBoozyWing: ["WhiskeyBoozy", "BoozyBand"],
SakeBoozyWing: ["SakeBoozy", "BoozyBand"],
VodkaBoozyWing: ["VodkaBoozy", "BoozyBand"],
TequilaBoozyWing: ["TequilaBoozy", "BoozyBand"],

RainbowFizzWing: ["RainbowFizz", "FruityFizzFam"],
BlueberryFizzWing: ["BlueberryFizz", "FruityFizzFam"],
CherryFizzWing: ["CherryFizz", "FruityFizzFam"],
PineappleFizzWing: ["PineappleFizz", "FruityFizzFam"],
FigFizzWing: ["FigFizz", "FruityFizzFam"],
KiwiFizzWing: ["KiwiFizz", "FruityFizzFam"],
GrapeFizzWing: ["GrapeFizz", "FruityFizzFam"],

BouquetOFlowersWing: [ "BouquetOFlowers", "FloraBrigade"],
PassionFlowerWing: [ "PassionFlower", "FloraBrigade"],
MarigoldFlowerWing: [ "MarigoldFlower", "FloraBrigade"],
LavenderFlowerWing: [ "LavenderFlower", "FloraBrigade"],
DahliaFlowerWing: [ "DahliaFlower", "FloraBrigade"],
RedRoseFlowerWing: [ "RedRoseFlower", "FloraBrigade"],
IrisFlowerWing: [ "IrisFlower", "FloraBrigade"],

};
*/

const shuffleLayerConfigurations = false;

/**

  • In the event that a filename cannot be the trait value name, for example when
  • multiple items should have the same value, specify
  • clean-filename: trait-value override pairs. Wrap filenames with spaces in quotes.
    */

const traitValueOverrides = {
// Helmet: "Space Helmet",
// "gold chain": "GOLDEN NECKLACE",
};

const debugLogs = false;

const format = {
width: 1024,
height: 1024,
};

const background = {
generate: false,
brightness: "80%",
};

const extraMetadata = {};

const extraAttributes = () => [
// Optionally, if you need to overwrite one of your layers attributes.
// You can include the same name as the layer, here, and it will overwrite
//
// {
// trait_type: "Bottom lid",
// value: Bottom lid # ${Math.random() * 100},
// },
// {
// display_type: "boost_number",
// trait_type: "Aqua Power",
// value: Math.random() * 100,
// },
// {
// display_type: "boost_number",
// trait_type: "Health",
// value: Math.random() * 100,
// },
// {
// display_type: "boost_number",
// trait_type: "Mana",
// value: Math.floor(Math.random() * 100),
// },
];

const rarityDelimiter = "#";

const uniqueDnaTorrance = 10000;

/**

  • Set to true to always use the root folder as trait_tybe
  • Set to false to use weighted parent folders as trait_type
  • Default is true.
    */
    const useRootTraitType = true;

const preview = {
thumbPerRow: 5,
thumbWidth: 50,
imageRatio: format.width / format.height,
imageName: "preview.png",
};

module.exports = {
background,
baseUri,
buildDir,
debugLogs,
description,
emptyLayerName,
extraAttributes,
extraMetadata,
forcedCombinations,
format,
hashImages,
incompatible,
layerConfigurations,
layersDir,
outputJPEG,
preview,
rarityDelimiter,
shuffleLayerConfigurations,
startIndex,
traitValueOverrides,
uniqueDnaTorrance,
useRootTraitType,
};

multiple configurations rarityData pull issue

When using multiple configurations similar to the example below, when I run 'node utils/rarityData.js' only the traits within the "Male Hair" folder are showing up as a "Hair" trait. The traits inside the "Female Hair" folder are missing from the readout.

const layerConfigurations = [
{
growEditionSizeTo: 2,
layersOrder: [
{ name: "Background" },
{ name: "Female Hair", trait: "Hair" },
],
},
{
growEditionSizeTo: 5,
layersOrder: [
{ name: "Background" },
{ name: "Eyeball" },
{ name: "Male Hair", trait: "Hair" },
],
},
];

An error with Zindex

Hello! recently i start to test this amazing feature, and works perfectly but today i cant stop of get this error. I thought maybe i insert a wrong z# number or i have a name problem but try to catch and nothing.

return z ? parseInt(z[0].match(/-?\d+/)[0]) : null;
^

TypeError: Cannot read properties of null (reading '0')
at parseZIndex (D:\trabajo\DESURE\NFT\Changos\Generacion Nfts\Programacion\art-engine-nested-folder-structure\src\main.js:140:42)
at D:\trabajo\DESURE\NFT\Changos\Generacion Nfts\Programacion\art-engine-nested-folder-structure\src\main.js:602:20
at Array.reduce ()
at sortLayers (D:\trabajo\DESURE\NFT\Changos\Generacion Nfts\Programacion\art-engine-nested-folder-structure\src\main.js:601:22)
at D:\trabajo\DESURE\NFT\Changos\Generacion Nfts\Programacion\art-engine-nested-folder-structure\src\main.js:655:26
at Array.forEach ()
at createDna (D:\trabajo\DESURE\NFT\Changos\Generacion Nfts\Programacion\art-engine-nested-folder-structure\src\main.js:644:11)
at startCreating (D:\trabajo\DESURE\NFT\Changos\Generacion Nfts\Programacion\art-engine-nested-folder-structure\src\main.js:814:20)
at processTicksAndRejections (node:internal/process/task_queues:96:5)

One and done

Hey @nftchef

I hope you are having a great start to your weekend. I was just wondering if it's possible to only use a trait once? Lets say I have 1000 images I want only used once for each one. Would that be possible? Thank you in advance to anyone who helps if I do not respond promptly.

Issue with shuffleLayerConfigurations

Discussed in #64

Originally posted by AC1AN February 24, 2022
Hi, I noticed that when I turn on theshuffleLayerConfigurations the generator always skip a number, for example if I ask for 5 images I'll have a result like 1 2 4 5 6 , with a gape in it
In this example I asked for 10 and the number 2 is missing I have instead number 11
shuffleissue
.

Thank you

The problem of filtering pictures after generation

Hello, when you need to filter some wrong pictures or unwanted pictures after generation, do you want to modify the json after deleting the pictures? For example, I deleted the 5th picture, do I have to manually delete the json? Can it be reordered once after deleting the filter?

rarityData.js non-functional

upon running it seems to be looking for an undefined 'elemnts' any insight on this error?

j@Js-MacBook-Pro NFT Chef LG % node '/Users/j/Desktop/LonerGirl/NFT Chef LG/utils/rarityData.js'
/Users/j/Desktop/LonerGirl/NFT Chef LG/src/config.js
/Users/j/Desktop/LonerGirl/NFT Chef LG/src/config.js
/Users/j/Desktop/LonerGirl/NFT Chef LG/utils/rarityData.js:134
      rarityDataTraits.elements.forEach((rarityDataTrait) => {
                       ^

TypeError: Cannot read properties of undefined (reading 'elements')
    at /Users/j/Desktop/LonerGirl/NFT Chef LG/utils/rarityData.js:134:24
    at Array.forEach (<anonymous>)
    at /Users/j/Desktop/LonerGirl/NFT Chef LG/utils/rarityData.js:127:6
    at Array.forEach (<anonymous>)
    at Object.<anonymous> (/Users/j/Desktop/LonerGirl/NFT Chef LG/utils/rarityData.js:122:6)
    at Module._compile (node:internal/modules/cjs/loader:1101:14)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1153:10)
    at Module.load (node:internal/modules/cjs/loader:981:32)
    at Function.Module._load (node:internal/modules/cjs/loader:822:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
j@Js-MacBook-Pro NFT Chef LG % 

Inconsistencies not working

Hey! I've set a lot of inconsistencies (30 lines) and it seems to work but not 100% of the time. This is my config line:

const incompatible = {
orange_cat_blue_tee: ["yellow_balaclava", "green_balaclava", "yellow_flower", "pink_flower", "black_braids_with_headphones", "peach_braids"],

and one of my images has this metadata, but these can't be together, right? (outfit comes before hair)

{
"trait_type": "Outfit",
"value": "orange_cat_blue_tee"
},
{
"trait_type": "Hair",
"value": "peach_braids"
},

I don't have a lot of coding experience btw :)

Distributing a trait like Gender

I have a pretty simple build that's generating a collection of 2222 pfps split by gender

const layerConfigurations = [
  {
    growEditionSizeTo: 1111,
    layersOrder: [
      { name: "MaleGender", trait: "Gender" },
      { name: "MaleBackground", trait: "Background" },
      { name: "MaleBody", trait: "Body" },
      { name: "MaleClothing", trait: "Clothing" },
      { name: "MaleHead", trait: "Head" },
      { name: "MaleEyes", trait: "Eyes" },
      { name: "MaleGlasses", trait: "Glasses" },
      { name: "MaleMouth", trait: "Mouth" },
      { name: "MaleJewelry", trait: "Jewelry" },
    ],
  },
  {
    growEditionSizeTo: 2222,
    namePrefix: "Female",
    layersOrder: [
      { name: "FemaleGender", trait: "Gender" },
      { name: "FemaleBackground", trait: "Background" },
      { name: "FemaleBody", trait: "Body" },
      { name: "FemaleHead", trait: "Head" },
      { name: "FemaleEyes", trait: "Eyes" },
      { name: "FemaleClothing", trait: "Clothing" },
      { name: "FemaleMouth", trait: "Mouth" },
      { name: "FemaleJewelry", trait: "Jewelry" },
      { name: "FemaleHand", trait: "Hand" },
    ],
  },
]

But I'd like the genders to be shuffled at random.

  1. At first, I was hoping I could this, but doesn't seem like how it's supposed to work
layers
  - Male#50
  - - Background
  - - Body
  - Female#50
  - - Background
  - - Body
  1. I considered doing 2 separate builds, then running a 3rd build using them all with "Randomly Insert Rare items". Seems doable but a little funky.

  2. Using js to randomly create a massive 2222 item layerConfigurations array, and _.shuffle() it with lodash 😅

Is there a way to do this that I'm missing?

Forced Combination error

Error being thrown in the latest version when forced combination is not empty, using the sample layers

Setting up the folling forced combinations for floral:  MetallicShades Golden Sakura
Force picking MetallicShades/n
(node:92974) UnhandledPromiseRejectionWarning: ReferenceError: element is not defined
    at pickRandomElement (/Users/lk-user/Documents/hashlips_art_engine/4/art-engine/src/main.js:466:53)
    at /Users/lk-user/Documents/hashlips_art_engine/4/art-engine/src/main.js:641:5
    at Array.forEach (<anonymous>)
    at createDna (/Users/lk-user/Documents/hashlips_art_engine/4/art-engine/src/main.js:639:11)
    at startCreating (/Users/lk-user/Documents/hashlips_art_engine/4/art-engine/src/main.js:807:20)
    at /Users/lk-user/Documents/hashlips_art_engine/4/art-engine/index.js:13:3
    at Object.<anonymous> (/Users/lk-user/Documents/hashlips_art_engine/4/art-engine/index.js:14:3)
    at Module._compile (internal/modules/cjs/loader.js:1063:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1092:10)
    at Module.load (internal/modules/cjs/loader.js:928:32)

Nested folders doesn't work for me

If I create subfolders inside "Backgrounds" for example:
Background
-Normal#70
--Image1#2
--Image2#2

-Rare#25
--Image3#2
--Image4#1

-Legendary#5
--image5#2
--image6#1

node index.js doesn't work, it gives a "TypeError: Cannot read properties of undefined (reading 'split')". The thing is, this issue happen when I put all the images, inside the subfolders. If I leave 1 image in the root "Background" node index.js works and generates every image... but always with that same background and didn't use the ones on the subfolders.

ImageSmoothing setting does not work

The Image smoothing setting no longer works after the mainCanvas was decoupled from the layers canvas.

also, the config.js is missing this setting.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.