Code Monkey home page Code Monkey logo

owmo-dev / token-art-tools Goto Github PK

View Code? Open in Web Editor NEW
73.0 2.0 10.0 17.99 MB

Static web application for generative artists to explore creative concepts via mappable hashpair control sliders, automate image generation and capture features information to CSV in order to analyze probability of outcomes.

Home Page: https://owmo-dev.github.io/token-art-tools/

License: MIT License

Makefile 0.20% JavaScript 99.49% CSS 0.31%
generative-art token-art-tools artblocks static-sites artist-tool fxhash

token-art-tools's Introduction

token-art-tools

Static webapp for generative artists to explore a script's creative domain via sliders mapped to hashpairs, automate image generation for a sample set, and capture features as a CSV for analyzing probability of outcomes. Developed in React using Gatsby and Semantic UI libraries.

https://owmo-dev.github.io/token-art-tools/

screenshot

Project Configuration

This webapp expects a localhost web server hosting your script and that you have referenced the lib/connector.js script before executing your sketch. Global variables hash and number are available for your sketch to use, as well as some platform sepcific implementations.

Boilerplate Setup

The following boilerplate project setup supports all of Token Art Tool's features

https://github.com/owmo-dev/token-art-tools-boilerplate

Manual Setup

The lib/connector.js script must be referenced in your project before your artwork sketch executes. Either copy it into your repo or use this CDN.

<script src="https://cdn.jsdelivr.net/gh/owmo-dev/[email protected]/lib/connector.js"></script>

Host Locally

You can run this webapp locally if you want by doing the following:

  1. npm install
  2. make run-server
  3. http://localhost:8000

Platform Specific Features

The global variable tokenData is made available by the lib/connector.js script by using the hash directly provided by the webapp. All 32 hashpairs are used in the hash and the edition number simulates project "0" with a possitble edition range of "0 to 1000", smaller than the possible million for practical UI purposes.

tokenData = {
    hash: '0x0000000000000000000000000000000000000000000000000000000000000000',
    tokenId: 1000000,
};

Please refer to Art Block's 101 Docs for more information.

The global variable fxhash and function fxrand are made available by the lib/connector.js script by using a slice of the hash provided by the webapp. The script simply overrides the code snippet required by the fx(hash) creator minting process. If you are including this snippet in your project setup (recommended), please ensure that the reference to lib/connector.js is made AFTER the fx(hash) code snippet to have them properly overriden. Also, please don't forget to remove it when you are ready to mint.

fxhash = 'oo89fd946ca9ce6b038b4434c205da26767bf632748f5cf8292';

console.log('new random number between 0 and 1', fxrand());

Please refer to the fxhash publish docs for more inforamtion.

Technical Requirements

Canvas is Required

Artwork must be displayed within a canvas element for all features to work as expected.

preserveDrawingBuffer: true

The preserveDrawingBuffer must be true for screenshots to work.

ThreeJS
let renderer = new THREE.WebGLRenderer({preserveDrawingBuffer: true});
WebGL
const gl = canvas.getContext('webgl', {preserveDrawingBuffer: true});

Tips & Tricks

Use HTTPS

Some browsers will require that you serve your artwork locally via https rather than http

Share Hosted URL & Hash

If your URL is publicly accessible, you can share a Token Art Tools initialization by using url, hash and number variables in the URL for the application (click the "shared" button next to the address bar to copy the current to clipboard). Not that a valid url is required for anything to be set.

https://owmo-dev.github.io/token-art-tools//?url={URL}&hash={HASH}&number={NUMBER}

Hashpairs for Exploration

The hashpair sliders are best used early on while exploring ranges and mixes of different creative features.

function mpd(n, a1, b1, a2, b2) {
    return ((n - a1) / (b1 - a1)) * (b2 - a2) + a2;
}

let hs = [];

for (j = 0; j < 32; j++) {
    hs.push(hash.slice(2 + j * 2, 4 + j * 2));
}

let rns = hs.map(x => {
    return parseInt(x, 16);
});

let features = {
    hue: mpd(rns[0], 0, 255, 0, 360),
    size: mpd(rns[1], 0, 255, 0.5, 1.8),
    offset: mpd(rns[2], 0, 255, -2.0, 2.0),
};

Hash to Seed Randomd

While I have used hashparis directly in projects, I wouldn't recommend it because the hash produced by external services (such as minting on chain) may not produce a sufficient randomization and it's more difficult to control probabilities. The best way to use the hash is simply to use it as a seed in a random function you trust.

Below is an excellent Random function Piter Pasma made available for everyone to use.

let S = Uint32Array.from([0, 0, 0, 0]).map(i => parseInt(hash.substr(i * 8 + 5, 8), 16));

let R = (a = 1) => {
    let t = S[3];
    S[3] = S[2];
    S[2] = S[1];
    let s = (S[1] = S[0]);
    t ^= t << 11;
    S[0] ^= t ^ (t >>> 8) ^ (s >>> 19);
    return (a * S[0]) / 2 ** 32;
};

console.log('random value between 0 and 1', R());

let myArray = ['a', 'b', 'c', 'd'];

console.log('pick from array', myArray[(R() * myArray.length) | 0]);

Longer Delays for Reliable Screenshots & CSV Capture

The automated process can sometimes produce unreliable results, especially if your artwork is particularly taxing. I simply suggest increasing the wait time between capturing and testing on smaller sample sizes before commiting to a larger set to run overnight.

Define Features as Early as Possible

The lib/connector.js script defines a global features variable as an empty object which you can then assign key-value pairs to display in the webapp. You must set the features variables no later than 500ms because the webapp will attempt to retrieve them at about 600ms.

features = {
    Palette: 'Blue Sky',
    Style: 'Shadow',
};
features['Size'] = 10;

You can only assign int, float, and string values as a feature entry.

Known Issues

  • When using a simple web server (ex: python -m http.server 5500), Chrome will block HTML files within iframes. At the time of writing, Firefox will still allow this, but it's much better to simple use a node project setup.

token-art-tools's People

Contributors

csb324 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

Watchers

 avatar  avatar

token-art-tools's Issues

Chrome blocking "index.html"

There was an update to Chrome which is causing iframes to block HTML files from being served to it. The following error is what needs to be resolved.

crbug/1173575, non-JS module files deprecated.

It's possible a simple local server using these files won't be allowable, in favour of using something like npm run dev but I want to look into it and see if there's a way to get it working.

adjustable variables from script

Copy/pasting a suggestion from the Artblocks Discord server...

Often times I have some variables that I need to tweak to have specific effects (think like a multiplier for noise increments) and having a slider allowing to adjust them as I go would be an amazing feature as they sometimes need to be readjusted based on another setting.

Idk if I am clear but that’d require basically to have some sort of setting passed from custom code to the app (that indicates variable name + base range) and back to the code the slider value

The way I thought of doing this app btw was to use a code editor (there are libs for that) as it would save the hassle of having another code editor open (assuming the in-browser editor is good, better than the one provided on editor.p5js.org!)

trigger features

The script creating the art should trigger the image capture - via the connector script - rather than wait a certain amount of time.

  • Add a small buffer from when "image capture" is initiated to when the next artwork is triggered
  • Add an emitter that says "frame is done" so script with variable time to completion can be more efficient
  • Continue to allow entering a millisecond timing as an option (toggle between MS and Event, MS by default)

automate hash list

After releasing a project on-chain, artists sometimes like to provide high resolution PNG copies of the artwork for collectors to print. It would be great if the automation setup allowed for - instead of randomly generating - a method of providing a comma (or newline) separated list of hashes that it would use to cycle through. You could then choose to just generate images or create the CSV file in addition if you wanted to do some meta analysis after releasing.

pop-out iframe for viewing on second monitor

Make the iframe viewer "pop out" so it can be resized / positioned however the user wants. This may end up being the desired UX rather than having it embedded in the page (leave a small embed to be popped out). This will allow for more room on the page as well, ideally.

get access to actively purge jsdeliver urls

Right now it takes days for the jsdeliver URL to update after a commit (they cache the scripts). Need to request access to the API that will force purge the cache so it gets the update immediately.

custom resolution in iframe

Ability to set a custom X and Y resolution for the iframe, but have it visually scale back to fit the window. This would allow for screenshots to be taken at a pre-defined resolution.

simulate tokenID number

Some artists use the tokenID to drive certain features of their work (for example CryptoVenetians uses it to change the time of day as the mints increment towards the final tally). Simulating this with a project ID base and upper bound of 1M should work.

connector script

If the connector script fails to get a hash from the application, it should return a null object rather than an incomplete one

add features display

Make the provider aware of the features variable and display them on the web interface as an optional overlay to the viewer.

update deps

Should probably update the dependencies, do a bit of cleanup to reduce GH vulnerability warnings (even though it doesn't really matter, since it's not hosting anything important, just annoying to read)

screenshot current

Ability to screenshot the current artwork being displayed, ideally downloading a PNG with both the date and hash.

add provider loading check

Add a message that calls back to the webapp to let it know it's loaded / ready. Then use that response to disable/enable the features that rely on it (ex: screenshot). This helps improve the UX for anyone using the tool.

GIF Recording

Would be nice if GIF recording could be done, might be too complicated. Investigate.

Add support for fx(hash)

Ideally, try to generalize the solution given both ArtBlocks and fx(hash) both use hash-based randomization seeds. Maybe just set the hash range and number to match, then allow the user to select from a drop-down as to which token wrapper they want to use.

automation collage view

After rendering automated outputs, combine very small thumbnails into a collage view so you can get an at a glance view of diversity.

destroy command

It would be nice to have a destroy command sent to the iframe before a new generation is created (slight delay). This would be helpful when automating, because the artwork could implement a cleanup function that helps reduce memory impacts between generations. Would probably need a slight delay, likely could wrap this into another ticket (capturing the idea for now)

Fragile features, make more reliable

Right now capturing features can be a bit fragile, depending on how computationally expensive initial frame render can be. It can cause the delayed request for features on frontend to hang and not get result. This means that CSV capture may miss a feature occasionally when capturing sets.

Manual resolutions include:

  • Reducing resolution
  • Turning off animation
  • Increasing capture time

It would be ideal to come up with a better solution than "just wait 600ms and try" - perhaps a loop that will continue to try iteratively until it succeeds? Maybe adding a callback of some kind that the artist can call at a specific time?

capture buffer time

Add a small time buffer to when the image capture occurs and the next round of rendering.

Why? Some of my current work is producing fully black or white images because the initialization and rendering of the next frame is occurring while the browser is still trying to download the image. Probably runs out of memory or something?

Bracketing comparison

Having the ability to set the viewer in a "bracketing mode" which would allow the hash pairs (selectable? all?) to be bracketed by a given range. This way, on each generation you could preview what things look like to either side of a given set of features or parameters at once without needing to adjust sliders manually.

An artist on ArtBlocks developed this in their own local test environment...

image

generate contact sheet

Add an option to the automation panel to create a contact sheet HTML file, which would present all of the generated images along with their features in a simple table.

escape key to cancel modals

I find myself pressed "Escape" a lot when I no longer want the modal I've clicked... key should trigger close modal

Add a "external_url" variable to the URL of the app to load the `URL` directly

For example:
https://owenmoore.github.io/token-art-tools/?url=https://mywebsite.com/myproject

This would be helpful to simply load in an external resources (for review, sharing, etc.) in an easy to explore way. Might want to consider adding an optional seed hash as the starting point as well.

Helpful for doing reviews, sharing / exploring via an external URL, doing reviews with AB, etc.

Support non-canvas works

Screenshot doesn't work if someone is drawing to a div without a canvas (vanilla JS), using an ID in the provider may allow screenshot if whatever the artist targets.

Features crash is undefined

Put checks to make sure the values are Int, Float, or String. If anything else, do not display them.

Ideally put some kind of error message indicating which one (using the key only)

question about setup canvas

I cannot figure out what this means: 'Your index.html file must display your work within a single canvas tag for all features to work.'

Can you help?
Do I make something like

The examples I find show running createCanvas and then using parent to attach the canvas to a div.
let cnv = createCanvas(100, 100);
cnv.parent('myContainer');

But this is not working for me.

thank you

improve "features" documentation

Make improvements to the README and in-application documentation with regards to how to set up a "features" script within a project. There should be two main methods:

Including it in the body of the HTML file as such:

<html>
<head>
... stuff
</head>
<body>
    <script src="features.js"></script>
    <script>
        features = calculateFeatures(tokenData);
    </script>
    <script src="sketch.js"></script>
</body>

Or, including it in the script JS file itself (to be removed later when deploying)...

import calculateFeatures from './features'
features = calculateFeatures(tokenData)

The second method would require the features script to export the function to make it accessible...

export default calculateFeatures

enter hash string manually

Having a field to enter a hash string, which would appropriately set all of the slider values and display the work, would be handy if you want to return to a previously saved hash.

Audio Recording

Would be nice if audio could be recorded easily from generator URLs (ArtBlocks). Probably not too difficult, might be more appropriate as a standalone tool for the project, but worth investigating if generalized solution works or not.

params in url

In the preview window, the URL params are not respected if the application itself uses the params (ex: modifying quality via ?quality=1) because the app is using them to implement the hash URLs. Might be a way to pass them through?

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.