Skip to content

Commit

Permalink
Fix all the broken things [Issue #54] (#56)
Browse files Browse the repository at this point in the history
* Fix all the broken things...

Man! This was so spaghetti'd I'm now Italian...

~ Removed a break from the switch statement in the constructor of CommandExecutor which meant that float values were pushed to the argument list twice (once as a float and then again as a command).

~ In Parser.parse() moved the call to nextToken() out of the else condition so that it is always executed.
  The intended functionality is to call parseExpression() when the argument type is int or float.
  After this change nextToken() was always executed regardless, then parseExpression was executed as well if the expression was an int or float, causing arguments to get skipped resulting in attempts to invoke numbers as if they were commands.

~ Renamed COMMAND_TYPES to ARGUMENT_TYPES but not everywhere causing ReferenceErrors

~ #30 Removed calls to parseInt() and parseFloat() in the CommandExecutor constructor because an argument may be an Expression object. #52 Added them back causing Expression objects to become NaN

~ Missing brace at end of parser.js

~ #50 also removed the calls to drawingBounds.reset() and drawingBounds.move(turtle.x, turtle.y) which obviously broke the autofit-drawing-to-canvas feature

~ The autofit-drawing-to-canvas feature was also broken because someone removed the call to the function ¯\_(ツ)_/¯

* Remove bounding box debug rect()

* Switch statements should have breaks, not bugs 🐜

* Changed variable name back

In a previous commit changed 'str' to 'arg' when arg could be a mix of int-as-string/float-as-string/Expression

#55 Changed this and now it will always be string so 'str' is more appropriate.

* [Bugfix] Can't reselect default drawing

Looks like selecting the 'Default' item in the dropdown used to clear the textarea and the drawing until [this](https://github.com/CodingTrain/Logo/pull/51/files#diff-9f2094443505273ff51ea1d1702e4367L101) commit removed it.
So now the drawing remains unchanged when selecting the default item.
It then resets the camera position and calls goTurtle() to redraw which causes the view to jump off-center.

Instead it should put the default Logo in the textarea and call scaleToFitBoundingBox() to redraw _and_ center the drawing. This commit makes this change.
  • Loading branch information
TheTastefulToastie authored and shiffman committed Nov 13, 2018
1 parent 7d47d27 commit 25bd739
Show file tree
Hide file tree
Showing 7 changed files with 59 additions and 92 deletions.
12 changes: 5 additions & 7 deletions command.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,13 @@ class CommandArg {
this.validator = (str) => {
return /^[-+]?[0-9]*\.?[0-9]*$/.test(str);
}

break;
case ARGUMENT_TYPES.EXPRESSION:
this.validator = (str) => {
let res = /^[-+]?([0-9]+\.?[0-9]?|[0-9]*\.?[0-9]+)(\s[+-/*]{1}\s[-+]?([0-9]+\.?[0-9]?|[0-9]*\.?[0-9]+))*$/.test(str);
return res;
}

break;
}
} else
this.validator = validator;
Expand Down Expand Up @@ -117,16 +117,15 @@ class CommandExecutor {
break;
case ARGUMENT_TYPES.FLOAT:
this.values.push(parseFloat(value));
break;
case ARGUMENT_TYPES.COMMANDS:
this.values.push(
new Parser(value, this.callback).parse()
);
break;

case ARGUMENT_TYPES.EXPRESSION:
//console.log(this.parseExpression(value))
this.values.push(this.parseExpression(value).eval())

this.values.push(this.parseExpression(value).eval());
break;
case ARGUMENT_TYPES.PARAMETERS: // Example
this.values.push(value.split(" "));
break;
Expand All @@ -147,7 +146,6 @@ class CommandExecutor {
e = new Expression(next,new Expression('$',token), right);
} else
return new Expression('$', token);
//console.log(right);
if (right.lvl() > e.lvl()) {
let new_left = new Expression(next, new Expression('$',token), right.left);
e = new Expression(right.type, new_left, right.right);
Expand Down
16 changes: 0 additions & 16 deletions commandList.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,33 +9,25 @@ const commandLookUp = new CommandLookUp();
* and then the function to execute.
*/
commandLookUp.add(

new Command("fd", [new CommandArg("value", ARGUMENT_TYPES.EXPRESSION)], value => {

turtle.forward(value);
})
);

commandLookUp.add(

new Command("bd", [new CommandArg("value", ARGUMENT_TYPES.EXPRESSION)], value => {

turtle.forward(-value);
})
);

commandLookUp.add(

new Command("rt", [new CommandArg("value", ARGUMENT_TYPES.EXPRESSION)], value => {

turtle.right(value);
})
);

commandLookUp.add(

new Command("lt", [new CommandArg("value", ARGUMENT_TYPES.EXPRESSION)], value => {

turtle.right(-value);
})
);
Expand All @@ -55,9 +47,7 @@ commandLookUp.add(
commandLookUp.add(
new Command(
"pensize",

[new CommandArg("size", ARGUMENT_TYPES.EXPRESSION)],

size => {
turtle.strokeWeight = size;
}
Expand All @@ -68,10 +58,8 @@ commandLookUp.add(
new Command(
"setxy",
[

new CommandArg("x", ARGUMENT_TYPES.EXPRESSION),
new CommandArg("y", ARGUMENT_TYPES.EXPRESSION)

],
(x, y) => {
turtle.x = x;
Expand All @@ -81,17 +69,13 @@ commandLookUp.add(
);

commandLookUp.add(

new Command("setx", [new CommandArg("x", ARGUMENT_TYPES.EXPRESSION)], x => {

turtle.x = x;
})
);

commandLookUp.add(

new Command("sety", [new CommandArg("y", ARGUMENT_TYPES.EXPRESSION)], y => {

turtle.y = y;
})
);
Expand Down
4 changes: 2 additions & 2 deletions expression.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ class Expression {

eval() {
if(this.type == '$') {
return parseFloat(this.left);
} else if(this.type == '/') {
return parseFloat(this.left);
} else if(this.type == '/') {
return this.left.eval() / this.right.eval();
} else if(this.type == '*') {
return this.left.eval() * this.right.eval();
Expand Down
12 changes: 4 additions & 8 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -34,22 +34,18 @@
<img src="./assets/img/color.svg" style="width: 30px; height: 30px; padding: 2px;" alt="">
</span>
</div>

<!-- Canvas div -->
<div id="logo-canvas"></div>

<!-- Editor -->
<textarea id="code" cols="40" rows="4" autocomplete="false" spellcheck="false" autofocus></textarea>

<!-- Icon Copyright info -->
<small style="color: white; font-family: 'Montserrat'; padding-top: 10px;">
Icons made by <a href="https://www.flaticon.com/authors/freepik" title="Turtle">Turtle</a> from <a href="https://www.flaticon.com/" title="Flaticon">www.flaticon.com</a> is licensed by <a href="http://creativecommons.org/licenses/by/3.0/" title="Creative Commons BY 3.0" target="_blank">CC 3.0 BY</a>
</small>

<script>
document.querySelector("#code").value = "pu lt 90 fd 100 lt 90 fd 250 rt 90 rt 90 pd fd 500 rt 90 fd 150 rt 90 fd 500 rt 90 fd 150";
</script>


<script src="sketch.js"></script>
</body>

Expand Down
5 changes: 0 additions & 5 deletions parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,26 +91,21 @@ class Parser {
parse() {
let cmdsExecutors = [];
while (this.remainingTokens()) {

let token = this.nextToken();
let cmd = commandLookUp.get(token);;
let args = [];

if (cmd) {
for (let i = 0; i < cmd.argsTemplate.length; i++) {
let startIndex = this.index;
let arg = cmd.argsTemplate[i];

let theArgToken = this.getArgs();
if (arg.validator !== undefined) {
if (!arg.validator(theArgToken))

console.error(`Argument number ${i} (${theArgToken}) is invalid for command ${token}`);
args.push(theArgToken);
}
else {
args.push(theArgToken);
console.warn(`A validator is missing for argument ${theArgToken}`);
}
}
cmdsExecutors.push(new CommandExecutor(cmd, args, this.afterCmdCallback));
Expand Down
99 changes: 47 additions & 52 deletions sketch.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,8 @@ let turtle;
let recentreBtn;
let bgcolorBtn;

let xOffset = 0;
let yOffset = 0;
let startX = 100;
let startY = 100;
let dragStartMousePos = new p5.Vector();
let dragStartCanvasOffset = new p5.Vector();
let allCases;
let bgcolor = "#6040e6";

Expand All @@ -19,8 +17,8 @@ let canvasScrollX = 0;
let canvasScrollY = 0;
let canvasScaleX = 1;
let canvasScaleY = 1;
let drawing_bounds = new BoundingBox();
let drawingPadding = 50; // Padding round the edge of the drawing when autofit
let drawingBounds = new BoundingBox();
let drawingPadding = 100; // Padding round the edge of the drawing when autofit

function preload() {
loadJSON("./assets/tests.json", createTestDataView);
Expand All @@ -34,16 +32,16 @@ function setup() {

angleMode(DEGREES);
background(bgcolor);

canvas.mousePressed(function () {
xOffset = mouseX-startX;
yOffset = mouseY-startY;
dragStartMousePos = new p5.Vector(mouseX, mouseY);
dragStartCanvasOffset = new p5.Vector(canvasScrollX, canvasScrollY);
});

canvas.mouseMoved(function () {
if (mouseIsPressed) {
startX = mouseX-xOffset;
startY = mouseY-yOffset;
canvasScrollX = dragStartCanvasOffset.x + dragStartMousePos.x - mouseX;
canvasScrollY = dragStartCanvasOffset.y + dragStartMousePos.y - mouseY;
goTurtle();
}
});
Expand All @@ -52,9 +50,7 @@ function setup() {
bgcolorBtn = document.querySelector("#bgcolor");

recentreBtn.onclick = function () {
startX = width/2;
startY = height/2;
goTurtle();
scaleToFitBoundingBox(drawingBounds);
}

bgcolorBtn.onclick = function () {
Expand All @@ -65,62 +61,66 @@ function setup() {
let col = `#${r.toString(16)}${g.toString(16)}${b.toString(16)}`;
bgcolor = col;
goTurtle();

console.log(bgcolor);
}

startX = width/2;
startY = height/2;
editor = select("#code");
setDefaultDrawing();
editor.input(goTurtle);
goTurtle();
scaleToFitBoundingBox(drawingBounds); // This also redraws (it has to in order to measure the size of the drawing)
}

function scaleToFitBoundingBox(boundingBox) {
startX = 0;
startY = 0;
goTurtle();

let scale = Math.min((width - drawingPadding) / (boundingBox.width), (height - drawingPadding) / (boundingBox.height));
canvasScaleX = canvasScaleY = scale;
canvasScrollX = (drawing_bounds.x * scale - width * .5);
canvasScrollY = (drawing_bounds.y * scale - height * .5);
canvasScrollX = (drawingBounds.x * scale - width * .5);
canvasScrollY = (drawingBounds.y * scale - height * .5);
goTurtle();
}

function afterCommandExecuted() {
if (turtle.pen) {
drawing_bounds.includePoint(turtle.x, turtle.y);
drawingBounds.includePoint(turtle.x, turtle.y);
}
}

function goTurtle() {
console.log({startX:startX,startY:startY});

turtle = new Turtle(startX / canvasScaleX, startY / canvasScaleY, 0);
turtle = new Turtle(0, 0, 0);
drawingBounds.reset();
drawingBounds.move(turtle.x, turtle.y);
background(bgcolor);


push();
translate(-canvasScrollX, -canvasScrollY);
scale(canvasScaleX, canvasScaleY);

push();
scale(canvasScaleX, canvasScaleY);
turtle.reset();
let code = editor.value();
let parser = new Parser(code, afterCommandExecuted);
let commands = parser.parse();
for (let cmd of commands) {
cmd.execute();
}

pop();

pop();
}

/**
* Writes the Logo code for the default drawing to the textarea
* Called on page load
* Also called when selecting the default item from the #testdata dropdown
*/
function setDefaultDrawing() {
editor.value("pu lt 90 fd 100 lt 90 fd 250 rt 90 rt 90 pd fd 500 rt 90 fd 150 rt 90 fd 500 rt 90 fd 150");
}

function createTestDataView(cases) {
let selector = select("#testdata");
allCases = cases;

selector.option("Logo Default", -1);

Expand All @@ -132,31 +132,26 @@ function createTestDataView(cases) {
selector.changed(function() {
let val = parseInt(selector.value());
if (val < 0) {
turtle.strokeColor = 255;
turtle.dir = 0;
turtle.x = width / 2;
turtle.y = height / 2;
xOffset = 0;
yOffset = 0;
startX = 100;
startY = 100;
canvasScrollX = 0;
canvasScrollY = 0;
canvasScaleX = 1;
canvasScaleY = 1;

goTurtle();
return;
// Use the default drawing
setDefaultDrawing();
} else {
// Use a drawing from tests.json
editor.value(cases[val].code);
}

editor.value(allCases[val].code);

// Reset default parameters for turtle
turtle.strokeColor = 255;
turtle.dir = 0;
turtle.x = width / 2;
turtle.y = height / 2;
turtle.x = 0;
turtle.y = 0;

// Reset default parameters for camera
canvasScrollX = 0;
canvasScrollY = 0;
canvasScaleX = 1;
canvasScaleY = 1;

canvasScrollX = canvasScrollY = 0;
scaleToFitBoundingBox(drawing_bounds);
// Move and scale the drawing to fit on-screen
scaleToFitBoundingBox(drawingBounds);
});
}
3 changes: 1 addition & 2 deletions turtle.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ class Turtle {
}

reset() {
console.log(this.x, this.y, this.dir);
translate(this.x, this.y);
rotate(this.dir);
this.pen = true;
Expand All @@ -35,6 +34,6 @@ class Turtle {

home() {
this.x = this.homeX;
this.y = this.homey;
this.y = this.homeY;
}
}

0 comments on commit 25bd739

Please sign in to comment.