<!DOCTYPE html>
<html>
<head>
<script>
/// + hi! the p5remix editor is made with tailwindCSS, React and p5js (from @OnChainMonkey, p5js.org)
/// + built by bop.xbt
/// + need help or have questions? DM me: twitter.com/boppleton
</script>
<title>p5remix</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='100' height='100' viewBox='0 0 100 100'><rect width='100' height='100' fill='black'/><rect x='9.5' y='9.5' width='81' height='81' fill='%23ff9900'/></svg>">
<style>
html {
background: #000;
color: #fff;
}
</style>
</head>
<body>
<div id="root" style="height: 100%;">
<div style="margin: 20px">🎨 loading.. 🎨</div>
</div>
<script type="module">
window.init = () => {}
// import p5remix module
import '/content/dc3bf4fe1876252d0af01c3cdc52b2075dda0509dce573bd939deab4e1feef48i0'
// init is called after module is loaded
window.init = async () => {
const button = 'rounded-full shadow px-4 py-1 text-sm hover:bg-cyan-600 active:bg-cyan-700 focus:outline-none focus:ring focus:ring-cyan-500'
const Left = () => {
const ref = useRef()
useEffect(() => {
window.left = ref.current
if (window.startEditor) {
startEditor()
editor.setValue(`//
// welcome to p5remix!
//
let fontFill, fontBorder
let pixelSize = 32;
let grid = [];
function setup() {
createCanvas(windowWidth, windowHeight);
let button1 = createButton('âž• Blank Canvas');
button1.position(5, 5);
button1.mousePressed(() => {
window.parent.postMessage('blankCanvas', '*');
});
initNoiseGrid()
// Ultima Online font (thanks Lord British!), [non-commercial CC license] sourced here (by 'Jack') https://fontstruct.com/fontstructions/show/490665/ultima_online_border
fontFill = loadFont('/content/6f3edaba40b7a69f0d9e3e1b72d71849ba9924972922b3b2640adf7622731d05i0');
fontBorder = loadFont('/content/bee161358965c7b50154c241a4af4dfee886aeb9403b151a3274795950bb154bi0');
}
function windowResized() {
resizeCanvas(windowWidth, windowHeight);
}
function printText(str, x, y, font, size, color) {
textFont(font);
fill(color)
textSize(size);
text(str, width / 2 + x, height / 2 + y);
}
function printRemixText(str, x, y, font, size, color, mul) {
textFont(font);
textSize(size);
const sin1 = sin(millis() * 0.001)
const sin2 = sin(millis() * 0.002 + mul)
const cos1 = cos(millis() * 0.002 + mul)
strokeWeight(abs(sin1 + cos1) * 3 + (mul * 1))
stroke(250 * abs(sin1), 250 * abs(cos1), abs(sin2) * 255, abs(sin2) * 255)
fill(0, 0, 0)
text('remix', width / 2 + x, height / 2 + y + -abs(sin1 * 5));
}
function printLetter(letter, x, y, ran, size) {
textFont(fontFill);
textSize(size);
const sin1 = sin(millis() * 0.001)
const sin2 = sin(millis() * 0.002 * ran)
const cos1 = cos(millis() * 0.004 * ran)
noStroke()
fill(abs(sin2) * 255, abs(sin1) * 255, abs(cos1) * 255)
text(letter, width / 2 + x, height / 2 + y + -abs(sin1 * 5));
}
function drawBrush(x, y, c) {
fill(c);
const t = c === '#ff9900' ? 0.009 : 0.006
const sin1 = sin(-millis() * t)
const cos1 = cos(-millis() * t)
rect(x + sin1 * 20, y + cos1 * 20, 10, 10)
rect(x - sin1 * 20, y + cos1 * 12, 10, 10)
}
function initNoiseGrid() {
noiseGrid = [];
for (let y = 0; y < ceil(height / pixelSize); y++) {
let noiseRow = [];
for (let x = 0; x < ceil(width / pixelSize); x++) {
noiseRow.push(random(1));
}
grid.push(noiseRow);
}
}
function draw() {
if (height < 250 || !mouseIsPressed) clear()
noStroke()
for (let y = 0; y < grid.length; y++) {
for (let x = 0; x < grid[y].length; x++) {
let intensity = noise(grid[y][x]) * 55;
fill(intensity);
rect(x * pixelSize, y * pixelSize, pixelSize, pixelSize);
grid[y][x] += 0.003;
}
}
let wide = windowWidth > windowHeight
let small = windowWidth <= 80
if (small) {
const remixHeight = 8
const remixWidth = wide ? 0 : -23
const remixSize = 14
printRemixText('remix', 8 + remixWidth, remixHeight, fontBorder, remixSize, '#31fc15', 1.2)
printRemixText('remix', 8 + remixWidth, remixHeight, fontBorder, remixSize, '#31fc15', 1.1)
printLetter('r', 8 + remixWidth, remixHeight, 3.5, remixSize)
printLetter('e', 14 + remixWidth, remixHeight, 3.4, remixSize)
printLetter('m', 18 + remixWidth, remixHeight, 3.3, remixSize)
printLetter('i', 29 + remixWidth, remixHeight, 3.2, remixSize)
printLetter('x', 32 + remixWidth, remixHeight, 3.1, remixSize)
printRemixText('remix', 8 + remixWidth, remixHeight, fontBorder, remixSize, '#31fc15', 1)
return
}
const remixHeight = wide ? 16 : (width < 250 ? (width <= 200 ? 30 : -10) : -60)
const remixWidth = wide ? 0 : -36
const remixSize = 40
if (wide) {
printText('p5', -93, 8, 'Arial', 60, '#ed225d')
printText('*', -26, -10, 'Arial', 30, '#ed225d')
} else {
printText('p5', -20, -105 + (width < 250 ? (width <= 200 ? 90 : 50) : 0), 'Arial', 32, '#ed225d')
printText('*', 15, -114 + (width < 250 ? (width <= 200 ? 90 : 50) : 0), 'Arial', 16, '#ed225d')
}
printRemixText('remix', -8 + remixWidth, remixHeight, fontBorder, remixSize, '#31fc15', 1.2)
printRemixText('remix', -8 + remixWidth, remixHeight, fontBorder, remixSize, '#31fc15', 1.1)
printLetter('r', -8 + remixWidth, remixHeight, 3.5, remixSize)
printLetter('e', 9 + remixWidth, remixHeight, 3.4, remixSize)
printLetter('m', 25 + remixWidth, remixHeight, 3.3, remixSize)
printLetter('i', 51 + remixWidth, remixHeight, 3.2, remixSize)
printLetter('x', 65 + remixWidth, remixHeight, 3.1, remixSize)
printRemixText('remix', -8 + remixWidth, remixHeight, fontBorder, remixSize, '#31fc15', 1)
if (mouseIsPressed) {
drawBrush(mouseX, mouseY, '#ff9900');
}
noStroke()
textFont('Arial');
textSize(14);
fill(255, 120, 0, 120)
}
`);
editor.selection.moveCursorTo(0, 0);
}
}, []);
return html`
<div ref=${ref} class="w-full transition-width duration-200 flex flex-col h-full">
<div id="editor" class="w-full h-full"></div>
</div>
`
}
const Right = () => {
const ref = useRef()
useEffect(() => {
window.iframe = ref.current
}, []);
useEffect(() => {
// In the parent window
window.addEventListener('message', function(event) {
// Check if the message type is what you expect
if (event.data && event.data === 'blankCanvas') {
const s = `function setup() {
createCanvas(windowWidth, windowHeight);
background('gray');
fill('#ff9900')
rect(10, 10, 40, 40)
}
function windowResized() {
resizeCanvas(windowWidth, windowHeight);
}
function draw() {
}`
const p5code = '"' + zipString(s) + '"'
changeSrcdoc(p5code)
var htmlContent = `<` + `script>
import("/content/523cbe494d52b1ed6d24180d9066c2fe53f560b00576ee3bf4e2a8d05df9d19fi0")
.then(p5 => p5.remix(${p5code}))
<` + `/script>`;
editor.setValue(s)
editor.selection.moveCursorTo(0, 0);
window.iframe.setAttribute('srcdoc', htmlContent);
}
}, false);
}, [])
return html`
<div class="w-full bg-black">
<iframe class="w-full h-full" ref=${ref}></iframe>
</div>
`
}
function changeSrcdoc(s) {
var htmlContent = `<` + `script>
import("/content/523cbe494d52b1ed6d24180d9066c2fe53f560b00576ee3bf4e2a8d05df9d19fi0")
.then(p5 => p5.remix(${s}))
<` + `/script>`;
if (window.setSizer) {
setSizer(htmlContent.length)
}
buildEditor.setValue(htmlContent)
buildEditor.selection.moveCursorTo(0, 0);
window.iframe.setAttribute('srcdoc', htmlContent);
}
const Header = () => {
const ref = useRef()
const buttonRef = useRef()
const [sizer, setSizer] = useState('? kb')
useEffect(() => {
if (window.startEditor) {
startEditor('buildEditor')
}
window.setSizer = setSizer
}, [setSizer])
const onRun = useCallback((e) => {
if (e) e.stopPropagation()
const p5code = '"' + zipString(window.editor.getValue()) + '"'
changeSrcdoc(p5code)
}, [])
useEffect(() => {
setTimeout(() => {
onRun()
}, 320)
}, []);
const toggleButton = useCallback(() => {
if (left && buttonRef.current) {
left.classList.toggle('w-full');
left.classList.toggle('w-0');
setTimeout(() => {
onRun()
}, 320)
}
}, [])
const toggleBuild = useCallback(() => {
if (left && buttonRef.current) {
ref.current.classList.toggle('h-12');
ref.current.classList.toggle('h-fit');
setTimeout(() => {
onRun()
}, 320)
}
}, [])
return html`
<div ref=${ref}
class="items-center pt-2 transition-height duration-400 bg-neutral-800 h-12 px-2 text-gray-300 flex flex-col w-full border-b-2 border-neutral-700">
<div class="flex w-full">
<button onClick=${toggleButton} ref=${buttonRef}
class="shadow tracking-wide bg-gray-700 ${button} rounded-md">
${'🎨'}
</button>
<div class="px-3">
<button onClick=${onRun} class="bg-green-700 ${button} hover:bg-green-800">
<span class="text-white">✅ Run</span>
</button>
</div>
<div class="ml-auto">
</div>
<button onClick=${toggleBuild} class="bg-cyan-700 ${button}">
🚀 <span class="text-white px-1">Build</span>
</button>
</div>
<div class="w-fit h-full ring-2 rounded-md ring-cyan-500 p-2 px-4 m-4 flex bg-neutral-900">
<div class="h-full p-0 flex flex-col">
<span class="p-2 font-bold shadow">🎒 Compressed Build: <span
class="text-sm">${(sizer / 1000).toFixed(2)} kb</span> <span
class="text-xs px-4 m-2 mt-6 w-fit p-1">Inscribe this code as an HTML file:</span>
</span>
<div id="buildEditor" class="w-full h-24 shadow"></div>
<span class="mt-2 text-xs px-4 mb-2 ring-1 rounded-md ring-yellow-500 w-fit p-1">Make sure it is an HTML file ending with .html</span>
<span class="text-xs px-4 mb-2 ring-1 rounded-md ring-green-500 w-fit p-1">Before inscribing, test it on-chain with this tool: <span
class="font-bold text-lg">ord.io/33633842</span></span>
</div>
</div>
</div>
`
}
const Body = () => {
return html`
<div class="h-full flex">
<${Left}/>
<${Right}/>
</div>
`
}
const App = () => {
return html`
<div class="flex flex-col w-full h-full">
<${Header}/>
<${Body}/>
</div>
`
}
render({
testComponent: {
component: App
}
})
}
</script>
</body>
</html>
Owner
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago