Skip to content

Commit

Permalink
CanvasCraftv2.0.0-beta.1.6
Browse files Browse the repository at this point in the history
11 new updates, including the ability to edit presets
  • Loading branch information
Hope41 authored Jul 9, 2024
1 parent a212387 commit 23fda9a
Show file tree
Hide file tree
Showing 6 changed files with 216 additions and 52 deletions.
2 changes: 1 addition & 1 deletion src/file.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

function generateDownloadFile() {
const save = {}
save.version = 'canvasCraft-v2.0.0-beta.5'
save.version = 'canvasCraft-v2.0.0-beta.1.6'
save.codes = codes
save.layers = []

Expand Down
91 changes: 74 additions & 17 deletions src/functions.js
Original file line number Diff line number Diff line change
Expand Up @@ -208,14 +208,13 @@ function syntaxHighlightJavaScriptCode(code) {
const main = code => {
const data = {
multi: /`[\s\S]*?`/,
regex: /\/.+?\/[gim]*/,
comment: /\/\*[\s\S]*?\*\/|\/\/.*/,
string: /".*?"|'.*?'/}
const total = new RegExp('(' + data.multi.source + '|' + data.string.source + '|' + data.comment.source + '|' + data.regex.source + ')')
const total = new RegExp('(' + data.multi.source + '|' + data.string.source + '|' + data.comment.source + ')')

return code.split(total).map((e, i) => i % 2 ? data.multi.test(e) ? e.split(/(\${.*?})/).map(
(e, i) => i % 2 ? loop(e) : span('string', e)).join('') : data.comment.test(e) ? span('comment', e) :
data.regex.test(e) ? span('regex', e) : span('string', e) : loop(e)).join('')
(e, i) => i % 2 ? loop(e) : span('string', e)).join('') :
data.comment.test(e) ? span('comment', e) : span('string', e) : loop(e)).join('')
}

const loop = (code, index = 0) => {
Expand All @@ -225,7 +224,7 @@ function syntaxHighlightJavaScriptCode(code) {
{class: 'builtin', regex: /\b(eval|isFinite|isNaN|parseFloat|parseInt|decodeURI|decodeURIComponent|encodeURI|encodeURIComponent|escape|unescape)\b/},
{class: 'function', regex: /\b(\w+\()/, item: /\w+/},
{class: 'variable', regex: /\b(\w+)\b/},
{class: 'operator', regex: /([\/*+<>%=-?:]+)/}
{class: 'operator', regex: /([\/\\*+<>%=?:\{\}\(\)\-]+)/}
]

return code.split(list[index].regex).map((e, i) => i % 2 ? list[index].item ? e.replace(
Expand Down Expand Up @@ -501,7 +500,7 @@ function addNewLayer(insertIndex) {
collapse.textContent = 'Collapse'
hide.textContent = 'Hide'
insert.textContent = 'New Layer'
move.textContent = 'Sink'
move.textContent = 'Drop'
layer.sink = move

name.value = 'Layer ' + layers.length
Expand Down Expand Up @@ -1098,6 +1097,7 @@ function applyInfoToShapePanel(div, update = false) {
div.shape.activeRemix = i
div.shape.activePreset = code.preset
applyInfoToShapePanel(div, true)
div.shape.drawOnShape()
}
popupChoice.appendChild(button)
}
Expand All @@ -1115,12 +1115,12 @@ function applyInfoToShapePanel(div, update = false) {
asDefault.onmousedown = () => {
popup.classList.add('open')

popupText.textContent = 'Set "' + name + '" as Default'
popupText.textContent = 'Set "'+name+'" as Default'
popupChoice.innerHTML = ''

// Confirm text
const confirm = document.createElement('div')
confirm.textContent = 'From now on, all shapes will be given the "' + name + '" template as default.'
confirm.innerHTML = 'From now on, all shapes will be given the <span class=code>'+name +'</span> template by default.'
popupChoice.appendChild(confirm)

// Confirm
Expand Down Expand Up @@ -1148,7 +1148,7 @@ function applyInfoToShapePanel(div, update = false) {

// Function text
const codeName = document.createElement('div')
codeName.innerHTML = '<span style="color:var(--keyword)">function</span> <span style="color:var(--function)">draw</span><span style="color:var(--operator)">(</span><span style="color:var(--variable)">x</span>, <span style="color:var(--variable)">y</span>, <span style="color:var(--variable)">color</span><span style="color:var(--operator)">)</span> <span style="color:var(--operator)">{</span>'
codeName.innerHTML = '<span style="color:var(--keyword)">function</span> <span style="color:var(--function)">draw</span><span style="color:var(--operator)">(</span><span class=param onmouseover=helpChange("pixelX")>x</span>, <span class=param onmouseover=helpChange("pixelY")>y</span>, <span class=param onmouseover=helpChange("pixelColor")>color</span>, <span class=param onmouseover=helpChange("pixelSize")>size</span><span style="color:var(--operator)">)</span> <span style="color:var(--operator)">{</span>'
codeContain.appendChild(codeName)

// Textarea code box
Expand All @@ -1166,12 +1166,14 @@ function applyInfoToShapePanel(div, update = false) {
// Syntax highlight
codePre.innerHTML = syntaxHighlightJavaScriptCode(codeTextarea.value + '\n')

// Set height
codeTextarea.style.height = '3px'
codeTextarea.style.height = (codePre.scrollHeight + 3) + 'px'

// Set background code
div.shape.remixes[div.shape.activeRemix].code = codeTextarea.value
}
codeTextarea.oninput = () => change()
change()

codeTextarea.onscroll = () => {
codePre.scrollTop = codeTextarea.scrollTop
codePre.scrollLeft = codeTextarea.scrollLeft
Expand All @@ -1187,6 +1189,8 @@ function applyInfoToShapePanel(div, update = false) {
ending.innerHTML = '<span style="color:var(--operator)">}</span>'
codeContain.appendChild(ending)

change()

// Error
const error = document.createElement('div')
error.className = 'error'
Expand Down Expand Up @@ -1220,11 +1224,18 @@ function applyInfoToShapePanel(div, update = false) {
ok.style.padding = '0'
ok.style.transitionDuration = '.6s'

// Confirm text
const confirmText = document.createElement('div')
const DIVNAME = 'You are adding this texture to the list of templates. Any shape in CanvasCraft will be able to access it.'
confirmText.textContent = DIVNAME

// Name box
const input = document.createElement('input')
input.style.backgroundColor = '#111'
input.className = 'wide'
input.placeholder = 'Name this template'
let nameExists = {}
let shapesArr = []
input.oninput = () => {
if (input.value.length) {
ok.style.opacity = '1'
Expand All @@ -1234,19 +1245,65 @@ function applyInfoToShapePanel(div, update = false) {
ok.style.opacity = '0'
ok.style.padding = '0'
}

nameExists = {}
for (let i = 0; i < codes.length; i ++) {
const code = codes[i]
if (input.value == code.name) {
nameExists = {name: code.name, idx: i}
break
}
}
if (nameExists.name) {
shapesArr = []
for (let i = 0; i < layers.length; i ++) {
const layer = layers[i].arr
for (let j = 0; j < layer.length; j ++) {
const shape = layer[j]
if (input.value == codes[shape.activePreset].name)
shapesArr.push(shape)
}
}

popupText.textContent = 'Just one minute...'
let shapesWithThisPreset = shapesArr.length
const many = shapesWithThisPreset > 1
confirmText.innerHTML = 'It seems like this preset already exists. You can override the <span class=code>'+nameExists.name+'</span> preset by pressing Confirm, but remember that this cannot be undone. '+(shapesWithThisPreset?'There '+(many?'are':'is')+' currently '+shapesWithThisPreset+' shape'+(many?'s':'')+' that '+(many?'have':'has')+' this preset. By continuing, '+(many?'these shapes':'the shape')+' will be updated with the new code. Do you really want to do this?':'There are no shapes that are currently using this preset.')
}
else {
popupText.textContent = 'Save as a template'
confirmText.innerHTML = DIVNAME
}
}
popupChoice.appendChild(input)

// Confirm text
const div = document.createElement('div')
div.textContent = 'You are adding this texture to the list of templates. Any shape in CanvasCraft will be able to access it.'
popupChoice.appendChild(div)
popupChoice.appendChild(confirmText)

// Confirm button
ok.onmousedown = () => {
if (!input.value.length) return
popup.classList.remove('open')
codes.push({name: input.value, code: codeTextarea.value})

if (nameExists.name) {
const presetToChange = codes[nameExists.idx]
presetToChange.code = codeTextarea.value

// Update all shapes with new preset
for (let i = 0; i < shapesArr.length; i ++) {
const shape = shapesArr[i]
shape.addRemix(presetToChange, nameExists.idx)
shape.drawOnShape()
}
}

else {
codes.push({name: input.value, code: codeTextarea.value})
div.shape.activePreset = codes.length - 1

const activeRemix = div.shape.remixes[div.shape.activeRemix]
activeRemix.name = input.value + ' ' + div.shape.remixes.length + 1
activeRemix.preset = div.shape.activePreset
applyInfoToShapePanel(div, true)
}
}

popupChoice.appendChild(ok)
Expand Down
68 changes: 66 additions & 2 deletions src/help.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
const help = document.getElementById('helpMenu')
const helpButton = document.getElementById('helpButton')

const querySearch = document.getElementById('querySearch')
const quesryResult = document.getElementById('queryResult')

helpButton.onmouseover = () => helpChange('help')

const conversation = {
Expand Down Expand Up @@ -46,14 +49,75 @@ const conversation = {
transform: '*Transform Layer* Move the contents of the layer by a certain amount',
layerUp: '*Move Back* Push the layer back',
layerDown: '*Move Down* Pull the layer forward',
merge: '*Merge Up* Merge this layer with the one above',
merge: '*Merge Up* Merge this layer into the one above',
image: '*Image Mode* This allows you to insert an image from your device. You can switch back at any time',
shapeMode: '*Shape Mode* Go back to the original texture mode. You can switch back at any time',
chooseShapeImage: '*Select Image* Upload to an image from your device to assign it to this shape. If you do not want to upload an image, just switch back to Shape Mode',
opacitySlider: '*Opacity* Control the opacity of this image',
imagexPos: '*X Offset* The x offset of the image in this shape',
imageyPos: '*Y Offset* The y offset of the image in this shape',
imageScale: '*Scale* Control the size of the image'
imageScale: '*Scale* Control the size of the image',
pixelX: '*Pixel X* The x position of the pixel. <span class = code><span style="color:var(--operator)">(</span><span style="color:var(--number)">0</span>, <span style="color:var(--number)">0</span><span style="color:var(--operator)">)</span></span> is the top left of the shape',
pixelY: '*Pixel Y* The y position of the pixel. <span class = code><span style="color:var(--operator)">(</span><span style="color:var(--number)">0</span>, <span style="color:var(--number)">0</span><span style="color:var(--operator)">)</span></span> is the top left of the shape',
pixelColor: '*Shape Colour* Access the RGB colour values of this shape as <span class = code><span style="color:var(--operator)">{</span><span style="color:var(--variable)">r</span>, <span style="color:var(--variable)">g</span>, <span style="color:var(--variable)">b</span><span style="color:var(--operator)">}</span></span>',
pixelSize: '*Size* Access the width and height of this shape as <span class = code><span style="color:var(--operator)">{</span><span style="color:var(--variable)">w</span>, <span style="color:var(--variable)">h</span><span style="color:var(--operator)">}</span></span>',
}

const queries = [
['whatiscanvascraft','<p>CanvasCraft is a free tool designed to help creators create game worlds and images. You can learn more about us by clicking the "About" button on the homepage.</p>'],
['whatarecodetemplatespresets', '<h1>What are code templates?</h1><p>Code templates allow you to store useful code snippets that can be accessed by other shapes. Just press the "Save code as template" button and choose its name!</p>'],
['whatarecoderemixes', '<h1>What are code remixes?</h1><p>Code remixes are ways of storing multiple codes for a single shape. If you want to experiment with new textures without losing your original creation, just select a new template, and CanvasCraft will generate a fresh remix for you. This allows you to experiment with different textures while preserving your previous designs. </p><h2>How it Works</h2><p>&bull; Write some code to create a texture</p><p>&bull; When you\'re happy with how it looks, select a new texture from the <span class=code>Templates</span> list. This will create a new <b>Remix.</b> If you ever want to go back to the old texture that you made, simply select the right one in the <span class=code>Remixes</span> list!</p>'],
['whatlanguageisthecodeinuse', '<h1>What language is the code in?</h1><p>When you\'re creating textures in CanvasCraft, you will be coding in pure JavaScript. You are given the coordinates of each pixel in the shape, the shape\'s base colour, and the width and height of the shape.</p>'],
['howdoiusecanvascraft', '<h1>How do I use CanvasCraft?</h1><p>At the time of writing, CanvasCraft does not support touch-screen devices. For PCs, you can start CanvasCraft by clicking on the big icon on the homepage. The basic help assistant will tell you how to get started. If you need further help, simply hover over something and the assistant will explain it.</p>'],
['howdoiusejavascriptcodetomaketexturesincanvascraftcodebox', '<h1>How do I use JavaScript code to make textures in CanvasCraft?</h1><p>Making a texture is very simple, provided you know a little about code and RGB colours. Here\'s a breakdown of how it works.</p><p>&bull; The first time you create a shape, it will be given the Basic template. A template is a small code texture that you can work from.</p><p>&bull; At the start of the code, it defines four variables. <span class=code>r</span> - the red value - is a number between 0 and 255. The Green and Blue values are stored in the same way. Curiously, the alpha variable <span class=code>a</span> is stored as a number between 0 and 1. We added this feature to CanvasCraft because that\'s how standard JavaScript workds when creating RGB colours.</p><p>&bull; The last part of the code returns a string from the function. What does that mean? To put it into simple words, imagine the code snippet as a machine. You put stuff into the machine, and after doing a few calculations, it spits something back out. When we\'re coding textures in CanvasCraft, we are in essence telling the machine how to process its given information. The parameters of the function (or, the stuff that\'s put into the machine) is <span class=code>x</span>, <span class=code>y</span>, <span class=code>color</span> and <span class=code>size</span>. To learn more about them, search "What are the code arguments?" into the query bar at the top of this page. Back to the machine. So we have all these inputs, and we need to give an output. The output of this function is a standard JavaScript string. This can be in Hexadecimal format, HSL, or - in our instance - RGB.</p><p>&bull; Now we can start coding! Remember, we have the RGB variables defined earlier, so why not try making the colours change based on the coordinates? Paste the following code below the <span class=code>let a = 1</span> line and see what happens: <span class=code>r = r + x * 20</span>. After pressing "Apply Texture," the shape should gradually get redder from left to right. This is a very basic example of how to make textures, but it should be enough to get you started.</p>'],
['whatarethecodeparametersargumentsforboxxycolorsize', '<h1>What are the code arguments?</h1><p>The arguments for the code box function are <span class=code>x</span>, <span class=code>y</span>, <span class=code>color</span> and <span class=code>size</span>. The <span class=code>x</span> and <span class=code>y</span> values represent the positions of a pixel. When you apply the texture, the function will run for <b>every pixel in the shape.</b> This means that each pixel can be given a different colour, based on the arguments provided. The final two arguments <span class=code>color {r, g, b}</span> and <span class=code>size {w, h}</span> are <b>objects.</b></p>']
]

querySearch.oninput = () => {
const queryWords = querySearch.value.split(' ')
quesryResult.innerHTML = queryWords

const arr = []

// Iterate through stored queries
for (let i = 0; i < queries.length; i ++) {
const dic = {name: queries[i][0], score: 0}
const name = dic.name

// Iterate through words of searches query
for (let j = 0; j < queryWords.length; j ++) {
const word = queryWords[j].toLowerCase().replace(/[^a-z]/g,'')
if (name.includes(word)) dic.score += word.length

// If the word doesn't match, find a match inside the word
else {
for (let k = 0; k < word.length; k ++) {
const wordSoFar = word.slice(0, k)
if (name.includes(wordSoFar)) dic.score ++
}
}
}

arr.push(dic)
}

// Get largest score
let score = -1
let chosen = -1
for (let i = 0; i < arr.length; i ++) {
if (arr[i].score > score) {
score = arr[i].score
chosen = i
}
}
if (chosen > -1) {
quesryResult.innerHTML = queries[chosen][1]
const spans = document.getElementsByClassName('code')
for (let i = 0; i < spans.length; i ++) {
const span = spans[i]
span.innerHTML = syntaxHighlightJavaScriptCode(span.textContent)
}
}
}

let createdAShape = false
Expand Down
Loading

0 comments on commit 23fda9a

Please sign in to comment.