Partial completion of basic move functionality, missing deletion of existing structures however
This commit is contained in:
parent
1a7fd31643
commit
24be421d5e
|
@ -37,6 +37,13 @@ ascii.Vector.prototype.add = function(other) {
|
||||||
return new ascii.Vector(this.x + other.x, this.y + other.y);
|
return new ascii.Vector(this.x + other.x, this.y + other.y);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {ascii.Vector}
|
||||||
|
*/
|
||||||
|
ascii.Vector.prototype.clone = function() {
|
||||||
|
return new ascii.Vector(this.x, this.y);
|
||||||
|
};
|
||||||
|
|
||||||
/** @return {number} */
|
/** @return {number} */
|
||||||
ascii.Vector.prototype.length = function() {
|
ascii.Vector.prototype.length = function() {
|
||||||
return Math.sqrt(this.x * this.x + this.y * this.y);
|
return Math.sqrt(this.x * this.x + this.y * this.y);
|
||||||
|
|
|
@ -2,6 +2,29 @@ goog.provide('ascii.StateController');
|
||||||
|
|
||||||
goog.require('ascii.Vector');
|
goog.require('ascii.Vector');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draws a line.
|
||||||
|
*/
|
||||||
|
function drawLine(state, startPosition, endPosition, clockwise) {
|
||||||
|
var hX1 = Math.min(startPosition.x, endPosition.x);
|
||||||
|
var vY1 = Math.min(startPosition.y, endPosition.y);
|
||||||
|
var hX2 = Math.max(startPosition.x, endPosition.x);
|
||||||
|
var vY2 = Math.max(startPosition.y, endPosition.y);
|
||||||
|
|
||||||
|
var hY = clockwise ? startPosition.y : endPosition.y;
|
||||||
|
var vX = clockwise ? endPosition.x : startPosition.x;
|
||||||
|
|
||||||
|
while (hX1++ < hX2) {
|
||||||
|
state.drawSpecial(new ascii.Vector(hX1, hY));
|
||||||
|
}
|
||||||
|
while (vY1++ < vY2) {
|
||||||
|
state.drawSpecial(new ascii.Vector(vX, vY1));
|
||||||
|
}
|
||||||
|
state.drawSpecial(startPosition);
|
||||||
|
state.drawSpecial(endPosition);
|
||||||
|
state.drawSpecial(new ascii.Vector(vX, hY));
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Common interface for different drawing functions, e.g. box, line, etc.
|
* Common interface for different drawing functions, e.g. box, line, etc.
|
||||||
* @interface
|
* @interface
|
||||||
|
@ -22,45 +45,21 @@ DrawFunction.prototype.end = function(position) {};
|
||||||
function DrawBox(state) {
|
function DrawBox(state) {
|
||||||
this.state = state;
|
this.state = state;
|
||||||
/** @type {ascii.Vector} */ this.startPosition = null;
|
/** @type {ascii.Vector} */ this.startPosition = null;
|
||||||
/** @type {ascii.Vector} */ this.endPosition = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DrawBox.prototype.start = function(position) {
|
DrawBox.prototype.start = function(position) {
|
||||||
this.startPosition = position;
|
this.startPosition = position;
|
||||||
this.endPosition = position;
|
|
||||||
this.draw();
|
|
||||||
};
|
};
|
||||||
DrawBox.prototype.move = function(position) {
|
DrawBox.prototype.move = function(position) {
|
||||||
this.endPosition = position;
|
this.endPosition = position;
|
||||||
this.state.clearDraw();
|
this.state.clearDraw();
|
||||||
this.draw();
|
drawLine(this.state, this.startPosition, position, true);
|
||||||
|
drawLine(this.state, this.startPosition, position, false);
|
||||||
};
|
};
|
||||||
DrawBox.prototype.end = function(position) {
|
DrawBox.prototype.end = function(position) {
|
||||||
this.state.commitDraw();
|
this.state.commitDraw();
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Draws the currently dragged out box. */
|
|
||||||
DrawBox.prototype.draw = function() {
|
|
||||||
var x1 = Math.min(this.startPosition.x, this.endPosition.x);
|
|
||||||
var y1 = Math.min(this.startPosition.y, this.endPosition.y);
|
|
||||||
var x2 = Math.max(this.startPosition.x, this.endPosition.x);
|
|
||||||
var y2 = Math.max(this.startPosition.y, this.endPosition.y);
|
|
||||||
|
|
||||||
this.state.drawSpecial(new ascii.Vector(x1, y1));
|
|
||||||
this.state.drawSpecial(new ascii.Vector(x1, y2));
|
|
||||||
this.state.drawSpecial(new ascii.Vector(x2, y1));
|
|
||||||
this.state.drawSpecial(new ascii.Vector(x2, y2));
|
|
||||||
|
|
||||||
|
|
||||||
for (var x = x1 + 1; x < x2; x++) {
|
|
||||||
this.state.drawSpecial(new ascii.Vector(x, y1));
|
|
||||||
this.state.drawSpecial(new ascii.Vector(x, y2));
|
|
||||||
}
|
|
||||||
for (var y = y1 + 1; y < y2; y++) {
|
|
||||||
this.state.drawSpecial(new ascii.Vector(x1, y));
|
|
||||||
this.state.drawSpecial(new ascii.Vector(x2, y));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @constructor
|
* @constructor
|
||||||
|
@ -70,58 +69,27 @@ DrawBox.prototype.draw = function() {
|
||||||
function DrawLine(state) {
|
function DrawLine(state) {
|
||||||
this.state = state;
|
this.state = state;
|
||||||
/** @type {ascii.Vector} */ this.startPosition = null;
|
/** @type {ascii.Vector} */ this.startPosition = null;
|
||||||
/** @type {ascii.Vector} */ this.endPosition = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DrawLine.prototype.start = function(position) {
|
DrawLine.prototype.start = function(position) {
|
||||||
this.startPosition = position;
|
this.startPosition = position;
|
||||||
this.endPosition = position;
|
|
||||||
this.draw();
|
|
||||||
};
|
};
|
||||||
DrawLine.prototype.move = function(position) {
|
DrawLine.prototype.move = function(position) {
|
||||||
this.endPosition = position;
|
|
||||||
this.state.clearDraw();
|
this.state.clearDraw();
|
||||||
this.draw();
|
|
||||||
|
// Try to infer line orientation.
|
||||||
|
var startContext = this.state.getContext(this.startPosition);
|
||||||
|
var endContext = this.state.getContext(position);
|
||||||
|
var clockwise = (startContext.up && startContext.down) ||
|
||||||
|
(endContext.left && endContext.right);
|
||||||
|
|
||||||
|
drawLine(this.state, this.startPosition, position, clockwise);
|
||||||
};
|
};
|
||||||
|
|
||||||
DrawLine.prototype.end = function(position) {
|
DrawLine.prototype.end = function(position) {
|
||||||
this.state.commitDraw();
|
this.state.commitDraw();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Draws the currently dragged out line.
|
|
||||||
*/
|
|
||||||
DrawLine.prototype.draw = function() {
|
|
||||||
var upStart = this.state.isSpecial(
|
|
||||||
this.startPosition.add(new ascii.Vector(0, -1)));
|
|
||||||
var downStart = this.state.isSpecial(
|
|
||||||
this.startPosition.add(new ascii.Vector(0, 1)));
|
|
||||||
var leftEnd = this.state.isSpecial(
|
|
||||||
this.endPosition.add(new ascii.Vector(-1, 0)));
|
|
||||||
var rightEnd = this.state.isSpecial(
|
|
||||||
this.endPosition.add(new ascii.Vector(1, 0)));
|
|
||||||
|
|
||||||
// Look at the start and end contexts to infer line orientation.
|
|
||||||
var isClockwise = (upStart && downStart) || (leftEnd && rightEnd);
|
|
||||||
|
|
||||||
var hX1 = Math.min(this.startPosition.x, this.endPosition.x);
|
|
||||||
var vY1 = Math.min(this.startPosition.y, this.endPosition.y);
|
|
||||||
var hX2 = Math.max(this.startPosition.x, this.endPosition.x);
|
|
||||||
var vY2 = Math.max(this.startPosition.y, this.endPosition.y);
|
|
||||||
|
|
||||||
var hY = isClockwise ? this.startPosition.y : this.endPosition.y;
|
|
||||||
var vX = isClockwise ? this.endPosition.x : this.startPosition.x;
|
|
||||||
|
|
||||||
while (hX1++ < hX2) {
|
|
||||||
this.state.drawSpecial(new ascii.Vector(hX1, hY));
|
|
||||||
}
|
|
||||||
while (vY1++ < vY2) {
|
|
||||||
this.state.drawSpecial(new ascii.Vector(vX, vY1));
|
|
||||||
}
|
|
||||||
this.state.drawSpecial(new ascii.Vector(this.startPosition.x, this.startPosition.y));
|
|
||||||
this.state.drawSpecial(new ascii.Vector(this.endPosition.x, this.endPosition.y));
|
|
||||||
this.state.drawSpecial(new ascii.Vector(vX, hY));
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @constructor
|
* @constructor
|
||||||
* @implements {DrawFunction}
|
* @implements {DrawFunction}
|
||||||
|
@ -143,6 +111,84 @@ DrawFreeform.prototype.move = function(position) {
|
||||||
DrawFreeform.prototype.end = function(position) {
|
DrawFreeform.prototype.end = function(position) {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @implements {DrawFunction}
|
||||||
|
* @param {ascii.State} state
|
||||||
|
*/
|
||||||
|
function DrawMove(state) {
|
||||||
|
this.state = state;
|
||||||
|
this.ends = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawMove.prototype.start = function(position) {
|
||||||
|
var context = this.state.getContext(position);
|
||||||
|
var directions = [
|
||||||
|
new ascii.Vector(1, 0),
|
||||||
|
new ascii.Vector(-1, 0),
|
||||||
|
new ascii.Vector(0, 1),
|
||||||
|
new ascii.Vector(0, -1) ];
|
||||||
|
|
||||||
|
var ends = [];
|
||||||
|
for (var i in directions) {
|
||||||
|
var midPoint = this.followLine(position, directions[i]);
|
||||||
|
// Clockwise is a lie, it is true if we move vertically first.
|
||||||
|
var clockwise = (directions[i].x != 0);
|
||||||
|
// Ignore any directions that didn't go anywhere.
|
||||||
|
if (position.equals(midPoint)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
var midPointContext = this.state.getContext(midPoint);
|
||||||
|
// Special case, a straight line with no turns.
|
||||||
|
if ((midPointContext.left + midPointContext.right +
|
||||||
|
midPointContext.up + midPointContext.down) == 1) {
|
||||||
|
ends.push({position: midPoint, clockwise: clockwise});
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Continue following lines from the midpoint.
|
||||||
|
for (var j in directions) {
|
||||||
|
if (directions[i].add(directions[j]).length() == 0) {
|
||||||
|
// Don't go back on ourselves.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
var end = this.followLine(midPoint, directions[j]);
|
||||||
|
// Ignore any directions that didn't go anywhere.
|
||||||
|
if (midPoint.equals(end)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ends.push({position: end, clockwise: clockwise});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.ends = ends;
|
||||||
|
};
|
||||||
|
|
||||||
|
DrawMove.prototype.move = function(position) {
|
||||||
|
this.state.clearDraw();
|
||||||
|
for (var i in this.ends) {
|
||||||
|
drawLine(this.state, position, this.ends[i].position, this.ends[i].clockwise);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
DrawMove.prototype.end = function(position) {
|
||||||
|
this.state.commitDraw();
|
||||||
|
};
|
||||||
|
|
||||||
|
DrawMove.prototype.followLine = function(startPosition, direction) {
|
||||||
|
var endPosition = startPosition.clone();
|
||||||
|
while (true) {
|
||||||
|
var nextEnd = endPosition.add(direction);
|
||||||
|
if (!this.state.isSpecial(nextEnd)) {
|
||||||
|
return endPosition;
|
||||||
|
}
|
||||||
|
endPosition = nextEnd;
|
||||||
|
var context = this.state.getContext(nextEnd);
|
||||||
|
if (!(context.left && context.right && !context.up && !context.down) &&
|
||||||
|
!(!context.left && !context.right && context.up && context.down)) {
|
||||||
|
return endPosition;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles management of the diagram state. Input events are cleaned in the
|
* Handles management of the diagram state. Input events are cleaned in the
|
||||||
* parent controller and passed down to this class for dealing with drawing.
|
* parent controller and passed down to this class for dealing with drawing.
|
||||||
|
@ -169,6 +215,10 @@ ascii.StateController = function(state) {
|
||||||
$('#erase-button').click(function(e) {
|
$('#erase-button').click(function(e) {
|
||||||
this.drawFunction = new DrawFreeform(state, null);
|
this.drawFunction = new DrawFreeform(state, null);
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
|
|
||||||
|
$('#move-button').click(function(e) {
|
||||||
|
this.drawFunction = new DrawMove(state);
|
||||||
|
}.bind(this));
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -21,6 +21,19 @@ ascii.Cell.prototype.getDrawValue = function() {
|
||||||
return (this.scratchValue != null ? this.scratchValue : this.value);
|
return (this.scratchValue != null ? this.scratchValue : this.value);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The context for a cell, i.e. the status of the cells around it.
|
||||||
|
*
|
||||||
|
* @param {boolean} left, right, up, down
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
ascii.CellContext = function(left, right, up, down) {
|
||||||
|
/** @type {boolean} */ this.left = left;
|
||||||
|
/** @type {boolean} */ this.right = right;
|
||||||
|
/** @type {boolean} */ this.up = up;
|
||||||
|
/** @type {boolean} */ this.down = down;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds the entire state of the diagram as a 2D array of cells.
|
* Holds the entire state of the diagram as a 2D array of cells.
|
||||||
*
|
*
|
||||||
|
@ -118,21 +131,30 @@ ascii.State.prototype.getDrawValue = function(position) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Magic time.
|
// Magic time.
|
||||||
|
var context = this.getContext(position);
|
||||||
|
|
||||||
|
if (context.left && context.right && !context.up && !context.down) {
|
||||||
|
return SPECIAL_LINE_H;
|
||||||
|
}
|
||||||
|
if (!context.left && !context.right && context.up && context.down) {
|
||||||
|
return SPECIAL_LINE_V;
|
||||||
|
}
|
||||||
|
if (context.left && context.right && context.up && context.down) {
|
||||||
|
return SPECIAL_LINE_H;
|
||||||
|
}
|
||||||
|
return SPECIAL_VALUE;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {ascii.Vector} position
|
||||||
|
* @return {ascii.CellContext}
|
||||||
|
*/
|
||||||
|
ascii.State.prototype.getContext = function(position) {
|
||||||
var left = this.isSpecial(position.add(new ascii.Vector(-1, 0)));
|
var left = this.isSpecial(position.add(new ascii.Vector(-1, 0)));
|
||||||
var right = this.isSpecial(position.add(new ascii.Vector(1, 0)));
|
var right = this.isSpecial(position.add(new ascii.Vector(1, 0)));
|
||||||
var up = this.isSpecial(position.add(new ascii.Vector(0, -1)));
|
var up = this.isSpecial(position.add(new ascii.Vector(0, -1)));
|
||||||
var down = this.isSpecial(position.add(new ascii.Vector(0, 1)));
|
var down = this.isSpecial(position.add(new ascii.Vector(0, 1)));
|
||||||
|
return new ascii.CellContext(left, right, up, down);
|
||||||
if (left && right && !up && !down) {
|
|
||||||
return SPECIAL_LINE_H;
|
|
||||||
}
|
|
||||||
if (!left && !right && up && down) {
|
|
||||||
return SPECIAL_LINE_V;
|
|
||||||
}
|
|
||||||
if (left && right && up && down) {
|
|
||||||
return SPECIAL_LINE_H;
|
|
||||||
}
|
|
||||||
return SPECIAL_VALUE;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -39,6 +39,7 @@ button {
|
||||||
<button id="line-button">Line</button>
|
<button id="line-button">Line</button>
|
||||||
<button id="freeform-button">Freeform</button>
|
<button id="freeform-button">Freeform</button>
|
||||||
<button id="erase-button">Erase</button>
|
<button id="erase-button">Erase</button>
|
||||||
|
<button id="move-button">Move</button>
|
||||||
</div>
|
</div>
|
||||||
<canvas id="ascii-canvas"></canvas>
|
<canvas id="ascii-canvas"></canvas>
|
||||||
<script src="jquery-1.9.1.min.js"></script>
|
<script src="jquery-1.9.1.min.js"></script>
|
||||||
|
|
Loading…
Reference in New Issue