summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--colors.html5
-rw-r--r--css/sally.css14
-rw-r--r--index.html9
-rw-r--r--js/app.js23
-rw-r--r--js/blit.js51
-rw-r--r--js/clipboard.js1
-rw-r--r--js/color.js16
-rw-r--r--js/draw.js128
-rw-r--r--js/lex.js22
-rw-r--r--js/matrix.js73
-rw-r--r--js/tool.js42
-rw-r--r--js/ui/brush.js28
-rw-r--r--js/ui/canvas.js24
-rw-r--r--js/ui/controls.js120
-rw-r--r--js/ui/keys.js8
-rw-r--r--js/ui/palette.js2
-rw-r--r--js/ui/selection.js148
-rw-r--r--js/util.js9
18 files changed, 572 insertions, 151 deletions
diff --git a/colors.html b/colors.html
index 7ae4a60..f063e09 100644
--- a/colors.html
+++ b/colors.html
@@ -16,9 +16,9 @@
<script>
// var color_hue_order = ("black dark-blue purple dark-red red orange " +
-// "yellow lime green dark-cyan cyan blue magenta dark-gray light-gray white").split(" ");
+// "yellow lime green teal cyan blue magenta dark-gray light-gray white").split(" ");
-var color_mat_order = ("dark-red red orange yellow lime cyan dark-cyan blue dark-blue purple magenta dark-red black").split(" ")
+var color_mat_order = ("dark-red red orange yellow lime cyan teal blue dark-blue purple magenta dark-red black").split(" ")
function color_mat (i) { return colors[color_mat_order[ mod(i,color_mat_order.length) ]] }
@@ -83,6 +83,7 @@ var canvas = new Matrix (72, 35, function(x,y){
lerp_color(lex, start_color, end_color, t, xx, yy)
}
+ lex.opacity = 1
lex.build()
return lex
})
diff --git a/css/sally.css b/css/sally.css
index 5d57693..515442a 100644
--- a/css/sally.css
+++ b/css/sally.css
@@ -60,3 +60,17 @@ body { transition: 0.1s linear; }
textarea { font-size:12pt; width: 45%; height: 300px; background: #333; color: #0f0; border: 0; font-family: 'FixedsysExcelsior301Regular'; outline: 0; border: 1px solid #333; background:#010;}
#import_rapper { display: none; }
#cursor_input { position: absolute; top: 0; right: 0; width:30px; opacity: 0; }
+.selector_el {
+ border: 1px dashed #fff !important;
+ padding-top: 1px;
+ position:absolute;
+ top:-999px;left:-999px;
+ pointer-events: none;
+}
+.selector_el.dragging {
+ color: #0f0;
+}
+.selector_el.creating div {
+ display: none;
+}
+
diff --git a/index.html b/index.html
index bd9c1bd..2cdb580 100644
--- a/index.html
+++ b/index.html
@@ -14,6 +14,9 @@
<span id="square_el" class="tool">square</span><br>
<span id="circle_el" class="tool">circle</span><br>
<span id="text_el" class="tool">text</span><br>
+ <span id="select_el" class="tool">select</span><br>
+ <span id="fill_el" class="tool">fill</span><br>
+ <br>
<span id="clear_el" class="tool">clear</span><br>
<span id="grid_el" class="tool">grid</span><br>
<br>
@@ -51,14 +54,14 @@
</div>
-
<input type="text" id="cursor_input">
</body>
<script type="text/javascript-shader" id="demo_shader">
lex.bg = hue((x+y*y+t/10)/20)
lex.fg = (x+y)%16
- lex.char = (y%2) ? ":" : "%"
+ lex.char = (y%2) ? ":" : "%"
+ lex.opacity = 1
</script>
<script src="js/util.js"></script>
<script src="js/color.js"></script>
@@ -66,6 +69,7 @@
<script src="js/lex.js"></script>
<script src="js/matrix.js"></script>
+<script src="js/blit.js"></script>
<script src="js/tool.js"></script>
<script src="js/shader.js"></script>
<script src="js/draw.js"></script>
@@ -75,5 +79,6 @@
<script src="js/ui/keys.js"></script>
<script src="js/ui/controls.js"></script>
<script src="js/ui/palette.js"></script>
+<script src="js/ui/selection.js"></script>
<script src="js/app.js"></script>
diff --git a/js/app.js b/js/app.js
index fd375cf..ab2c1ab 100644
--- a/js/app.js
+++ b/js/app.js
@@ -1,7 +1,9 @@
var dragging = false
-var drawing = true
+var drawing = false
var erasing = false
+var selecting = false
+var filling = false
var focused
var canvas, tools, palette, controls, brush, mode, current_tool, current_canvas
@@ -25,6 +27,8 @@ function build () {
brush.bg = colors.red
brush.generate()
brush.build()
+
+ controls.grid.use()
}
function bind () {
canvas.bind()
@@ -33,9 +37,14 @@ function bind () {
controls.bind()
keys.bind()
- window.addEventListener('mouseup', function(){
+ window.addEventListener('mouseup', function(e){
dragging = erasing = false
- if (current_tool.name != 'shader' && current_tool.name != 'load' && current_tool.name != 'save') { cursor_input.focus() }
+ if (current_tool.name != 'shader' && current_tool.name != 'load' && current_tool.name != 'save') {
+ cursor_input.focus()
+ }
+ if (selecting) {
+ selection.up(e)
+ }
});
window.addEventListener('mousedown', function(e){
@@ -49,12 +58,4 @@ function bind () {
})
}
-
-function int_key (f) {
- return function (key, keyCode) {
- var n = parseInt(key)
- ! isNaN(n) && f(n)
- }
-}
-
init()
diff --git a/js/blit.js b/js/blit.js
new file mode 100644
index 0000000..8683f22
--- /dev/null
+++ b/js/blit.js
@@ -0,0 +1,51 @@
+var blit = (function(){
+ var blit = {}
+ blit.and = blit.atop = function(A, B, x, y){
+ x = x || 0 ; y = y || 0
+ B.forEach(function(lex, u, v){
+ var cell = A.getCell(u+x, v+y)
+ if (cell && lex.opacity > 0) {
+ cell.clone(lex)
+ }
+ })
+ }
+ blit.or = blit.under = function(A, B, x, y){
+ x = x || 0 ; y = y || 0
+ B.forEach(function(lex, u, v){
+ var cell = A.getCell(u+x, v+y)
+ if (cell && cell.opacity == 0) {
+ cell.clone(lex)
+ }
+ })
+ }
+ // copy the region of A beginning at x,y into B
+ blit.copy_from = function(A, B, x, y){
+ x = x || 0 ; y = y || 0
+ B.forEach(function(lex, u, v){
+ var cell = A.getCell(u+x, v+y)
+ if (cell) {
+ lex.clone(cell)
+ }
+ })
+ }
+ blit.copy_to = function(A, B, x, y){
+ x = x || 0 ; y = y || 0
+ B.forEach(function(lex, u, v){
+ var cell = A.getCell(u+x, v+y)
+ if (cell) {
+ cell.clone(lex)
+ }
+ })
+ }
+ blit.invert = function(A, B, x, y){
+ x = x || 0 ; y = y || 0
+ B.forEach(function(lex, u, v){
+ var cell = A.getCell(u+x, v+y)
+ if (cell && lex.opacity > 0) {
+ cell.fg = get_inverse(cell.fg)
+ cell.bg = get_inverse(cell.bg)
+ }
+ })
+ }
+ return blit
+})()
diff --git a/js/clipboard.js b/js/clipboard.js
index 0788284..da326ff 100644
--- a/js/clipboard.js
+++ b/js/clipboard.js
@@ -66,6 +66,7 @@ var clipboard = (function () {
if (! lex) return
lex.char = line[x]
lex.fg = brush.bg
+ lex.opacity = 1
lex.build()
}
})
diff --git a/js/color.js b/js/color.js
index 8f51518..5328095 100644
--- a/js/color.js
+++ b/js/color.js
@@ -1,25 +1,29 @@
var color_names = ("white black dark-blue green red dark-red purple orange " +
- "yellow lime dark-cyan cyan blue magenta dark-gray light-gray").split(" ");
-var all_color_hue_order = ("dark-red red orange " +
- "yellow lime green dark-cyan cyan blue dark-blue purple magenta black dark-gray light-gray white").split(" ");
-var color_hue_order = "dark-red red orange yellow lime cyan dark-cyan blue dark-blue purple magenta".split(" ");
+ "yellow lime teal cyan blue magenta dark-gray light-gray").split(" ");
+var all_color_hue_order = "dark-red red orange yellow lime green teal cyan blue dark-blue purple magenta black dark-gray light-gray white".split(" ");
+var all_color_inv_order = "cyan teal blue dark-blue purple magenta dark-red red orange yellow lime green white light-gray dark-gray black".split(" ");
+var color_hue_order = "dark-red red orange yellow lime cyan teal blue dark-blue purple magenta".split(" ");
+var color_inv_order = "cyan teal blue dark-blue purple magenta dark-red red orange yellow lime green".split(" ");
var gray_names = ("black dark-gray light-gray white").split(" ")
var fire_names = ("black dark-red red orange yellow white cyan").split(" ")
var red_names = ("black dark-red red").split(" ")
var yellow_names = ("black orange yellow white").split(" ")
-var green_names = ("dark-cyan green lime").split(" ")
+var green_names = ("teal green lime").split(" ")
var blue_names = ("black dark-blue blue").split(" ")
var purple_names = ("dark-blue purple magenta red").split(" ")
-var dark_gray_names = ("black dark-blue dark-cyan dark-gray light-gray white").split(" ")
+var dark_gray_names = ("black dark-blue teal dark-gray light-gray white").split(" ")
var letters = "abcdefghijklmnop";
var colors = {}
color_names.forEach(function(name, i){ colors[name] = i })
+function get_inverse (n) { return colors[all_color_inv_order.indexOf(color_names[n])] }
function all_hue (n) { return colors[all_color_hue_order[mod(n, 16)|0]] }
+function all_inv_hue (n) { return colors[all_color_inv_order[mod(n, 16)|0]] }
function hue (n) { return colors[color_hue_order[mod(n, 11)|0]] }
+function inv_hue (n) { return colors[color_inv_order[mod(n, 11)|0]] }
function gray (n) { return colors[gray_names[mod(n, 4)|0]] }
function fire (n) { return colors[fire_names[mod(n, 7)|0]] }
function red (n) { return colors[red_names[mod(n, 3)|0]] }
diff --git a/js/draw.js b/js/draw.js
index 173a84e..6bf55bd 100644
--- a/js/draw.js
+++ b/js/draw.js
@@ -1,32 +1,106 @@
+var draw = (function(){
-function draw (lex, x, y, erasing) {
- stamp (canvas, brush, x, y, erasing)
-}
+ var last_point = [0,0]
+
+ function down (e, lex, point) {
+ erasing = (e.which == "3" || e.ctrlKey)
+ if (e.shiftKey) {
+ line (lex, last_point, point, erasing)
+ }
+ else {
+ stamp (canvas, brush, point[0], point[1], erasing)
+ }
+ last_point[0] = point[0]
+ last_point[1] = point[1]
+ }
+
+ function move (e, lex, point) {
+ line(lex, last_point, point, erasing)
+ last_point[0] = point[0]
+ last_point[1] = point[1]
+ }
+
+ function point (lex, x, y, erasing) {
+ stamp (canvas, brush, x, y, erasing)
+ }
-function line (lex, a, b, erasing) {
- var len = dist(a[0], a[1], b[0], b[1])
- var bw = 1
- var x, y, i;
- for (var i = 0; i < len; i += bw) {
- x = lerp(i / len, a[0], b[0])
- y = lerp(i / len, a[1], b[1])
- stamp (canvas, brush, x, y, erasing)
- }
-}
+ function line (lex, a, b, erasing) {
+ var len = dist(a[0], a[1], b[0], b[1])
+ var bw = 1
+ var x, y, i;
+ for (var i = 0; i <= len; i += bw) {
+ x = lerp(i / len, a[0], b[0])
+ y = lerp(i / len, a[1], b[1])
+ stamp (canvas, brush, x, y, erasing)
+ }
+ }
-function stamp (canvas, brush, x, y, erasing) {
- hh = brush.w/2|0
- brush.forEach(function(lex, s, t){
- s = round( s + x-hh )
- t = round( t + y-hh )
- if (s >= 0 && s < canvas.w && t >= 0 && t < canvas.h) {
- if (erasing) {
- canvas.aa[t][s].erase(lex)
- }
- else {
- canvas.aa[t][s].clone(lex)
- }
+ function stamp (canvas, brush, x, y, erasing) {
+ hh = brush.w/2|0
+ brush.forEach(function(lex, s, t){
+ s = round( s + x-hh )
+ t = round( t + y-hh )
+ if (lex.opacity > 0 && s >= 0 && s < canvas.w && t >= 0 && t < canvas.h) {
+ if (erasing) {
+ canvas.aa[t][s].erase(lex)
+ }
+ else {
+ canvas.aa[t][s].clone(lex)
+ }
+ }
+ })
+ }
+
+ function fill (lex, x, y) {
+ var q = [ [x,y] ]
+ var target = canvas.aa[y][x].copy()
+ var n, w = 0, e = 0, j = 0
+ var kk = 0
+ // gets into a weird infinite loop if we don't break here.. :\
+ if (target.eq(lex)) { return }
+ LOOP: while (q.length) {
+ n = q.shift()
+ if (canvas.aa[n[1]][n[0]].ne(target)) {
+ continue LOOP
+ }
+ w = e = n[0]
+ j = n[1]
+ WEST: while (w > 0) {
+ if (canvas.aa[j][w-1].eq(target)) {
+ w = w-1
+ }
+ else {
+ break WEST
+ }
+ }
+ EAST: while (e < canvas.w-1) {
+ if (canvas.aa[j][e+1].eq(target)) {
+ e = e+1
+ }
+ else {
+ break EAST
+ }
+ }
+ for (var i = w; i <= e; i++) {
+ canvas.aa[j][i].clone(lex)
+ if (j > 0 && canvas.aa[j-1][i].eq(target)) {
+ q.push([ i, j-1 ])
+ }
+ if (j < canvas.h-1 && canvas.aa[j+1][i].eq(target)) {
+ q.push([ i, j+1 ])
+ }
+ }
}
- })
-}
+ }
+
+ var draw = {}
+ draw.down = down
+ draw.move = move
+ draw.stamp = stamp
+ draw.line = line
+ draw.point = point
+ draw.fill = fill
+ return draw
+
+})()
diff --git a/js/lex.js b/js/lex.js
index 1dc07a0..8c3b0f1 100644
--- a/js/lex.js
+++ b/js/lex.js
@@ -10,12 +10,14 @@ function Lex (x,y) {
this.fg = colors.white
this.bg = colors.black
this.char = " "
+ this.opacity = 1
}
Lex.prototype.build = function(){
this.span.className = this.css()
this.span.innerHTML = this.html()
}
Lex.prototype.css = function(){
+ if (this.opacity == 0) return "fabb"
return "f" + letters[mod(this.fg,16)] + "b" + letters[mod(this.bg,16)]
}
Lex.prototype.html = function(){
@@ -52,23 +54,32 @@ Lex.prototype.clone = function (lex){
this.fg = lex.fg
this.bg = lex.bg
this.char = lex.char
+ this.opacity = lex.opacity
this.build()
}
-Lex.prototype.erase = function (lex){
- if (lex.opacity == 0) return
+Lex.prototype.copy = function () {
+ var lex = new Lex (0,0)
+ lex.clone(this)
+ return lex
+}
+Lex.prototype.erase = function (){
this.fg = colors.white
this.bg = colors.black
this.char = " "
+ this.opacity = 0
this.build()
}
-Lex.prototype.fill = function(fg,bg){
+Lex.prototype.fill = function(fg, bg){
this.fg = fg
this.bg = bg
this.opacity = 1
this.build()
}
Lex.prototype.eq = function(lex){
- return lex && this.fg == lex.fg && this.bg == lex.fg && this.char == lex.char
+ return lex && this.fg == lex.fg && this.bg == lex.bg && this.char == lex.char
+}
+Lex.prototype.ne = function(lex){
+ return ! this.eq(lex)
}
Lex.prototype.clear = function(){
this.bg = 1
@@ -88,9 +99,10 @@ Lex.prototype.focus = function(){
Lex.prototype.blur = function(){
this.span.classList.remove('focused')
focused = null
+ this.onBlur && this.onBlur()
}
Lex.prototype.demolish = function(){
- this.span.parentNode.removeChild(this.span)
+ if (this.span.parentNode) { this.span.parentNode.removeChild(this.span) }
this.span = null
}
Lex.prototype.key = function(char, keyCode) {
diff --git a/js/matrix.js b/js/matrix.js
index 0bb2492..79f3d9f 100644
--- a/js/matrix.js
+++ b/js/matrix.js
@@ -89,7 +89,68 @@ Matrix.prototype.region = function(w,h,x,y) {
return parent.aa[y][x]
})
mat.f = this.f
+ return mat
}
+Matrix.prototype.setCell = function(lex,x,y){
+ this.aa[y] && this.aa[y][x] && this.aa[y][x].clone(lex)
+}
+Matrix.prototype.getCell = function(x,y){
+ if (this.aa[y] && this.aa[y][x]) return this.aa[y][x]
+ else return null
+}
+Matrix.prototype.resize = function(w,h){
+ var div, row, lex
+ var f = this.f, old_h = this.h, old_w = this.w
+ var rapper = this.rapper
+ w = max(w, 1)
+ h = max(h, 1)
+ if (h < old_h) {
+ for (var y = old_h; y > h; y--) {
+ row = this.aa.pop()
+ div = row[0].span.parentNode
+ row.forEach(function(lex, x){
+ lex.demolish()
+ })
+ div.parentNode.removeChild(div)
+ }
+ }
+ else if (h > old_h) {
+ for (var y = old_h; y < h; y++) {
+ div = document.createElement("div")
+ rapper.appendChild( div )
+ this.aa[y] = new Array (w)
+ for (var x = 0; x < w; x++) {
+ lex = this.aa[y][x] = f(x,y)
+ div.appendChild(lex.span)
+ }
+ }
+ }
+
+ if (w < old_w) {
+ this.aa.forEach(function(row, y){
+ while (row.length > w) {
+ lex = row.pop()
+ lex.demolish()
+ }
+ })
+ }
+ else if (w > old_w) {
+ this.aa.forEach(function(row, y){
+ div = row[0].span.parentNode
+ for (var x = row.length; x < w; x++) {
+ lex = row[x] = f(x,y)
+ div.appendChild(lex.span)
+ }
+ })
+ }
+
+ this.w = w
+ this.h = h
+ this.bind && this.bind()
+}
+
+//
+
Matrix.prototype.ascii = function () {
var lines = this.aa.map(function(row, y){
var last, line = ""
@@ -152,15 +213,3 @@ Matrix.prototype.irssi = function(){
}
return '/exec -out printf "' + escaped_txt + '"\n'
}
-Matrix.prototype.expand = function(i){
- var w = this.w = clamp(this.w+i, 1, 9), h = this.h = clamp(this.h+i, 1, 9)
- console.log(w,h)
- controls.width.char = ""+w
- controls.width.build()
- controls.height.char = ""+h
- controls.height.build()
- this.rebuild()
-}
-Matrix.prototype.contract = function(i){
- this.expand(-i)
-}
diff --git a/js/tool.js b/js/tool.js
index b0bc536..190f29f 100644
--- a/js/tool.js
+++ b/js/tool.js
@@ -1,18 +1,24 @@
-function Tool (span) {
- this.lex = new Lex (span)
- this.name = span.innerHTML
- this.span = span
-}
-Tool.prototype.use = function(){}
-Tool.prototype.focus = function(){
- // focused && focused.blur()
- current_tool && current_tool.blur()
- current_tool = this
- this.span.classList.add('focused')
- this.use()
- if (this.name != 'shader') { cursor_input.focus() }
-}
-Tool.prototype.blur = function(){
- current_tool = null
- this.span.classList.remove('focused')
-}
+var Tool = Model({
+ init: function (span) {
+ this.el = span
+ this.lex = new Lex (span)
+ this.name = span.innerHTML
+ this.span = span
+ },
+ use: function(){},
+ focus: function(){
+ // focused && focused.blur()
+ current_tool && current_tool.blur()
+ current_tool = this
+ this.span.classList.add('focused')
+ this.use()
+ if (this.name != 'shader') { cursor_input.focus() }
+ },
+ blur: function(){
+ current_tool = null
+ this.span.classList.remove('focused')
+ }
+})
+
+var Checkbox = Tool.extend({
+})
diff --git a/js/ui/brush.js b/js/ui/brush.js
index a055a97..50f6e07 100644
--- a/js/ui/brush.js
+++ b/js/ui/brush.js
@@ -7,20 +7,6 @@ var brush = (function(){
})
brush.modified = false
-
- brush.bind = function(){
- brush.forEach(function(lex, x, y){
- if (lex.bound) return
- lex.bound = true
-
- lex.span.addEventListener('mousedown', function(e){
- e.preventDefault()
- dragging = true
- // lex.fill(lex.fg, lex.bg)
- })
-
- })
- }
brush.bind = function(){
@@ -70,8 +56,22 @@ var brush = (function(){
})
}
+ brush.expand = function(i){
+ var w = this.w = clamp(this.w+i, 1, 9), h = this.h = clamp(this.h+i, 1, 9)
+ controls.width.char = ""+w
+ controls.width.build()
+ controls.height.char = ""+h
+ controls.height.build()
+ this.rebuild()
+ }
+ brush.contract = function(i){
+ this.expand(-i)
+ }
+
+ brush.char = " "
brush.fg = 0
brush.bg = 1
+ brush.opacity = 1
return brush
diff --git a/js/ui/canvas.js b/js/ui/canvas.js
index 4b595a5..206cbee 100644
--- a/js/ui/canvas.js
+++ b/js/ui/canvas.js
@@ -1,4 +1,4 @@
-var canvas = (function(){
+var canvas = current_canvas = (function(){
var cols = 80
var rows = 24
@@ -11,8 +11,6 @@ var canvas = (function(){
exports.bind = function(){
- var last_point = [0,0]
-
exports.forEach(function(lex, x, y){
if (lex.bound) return
@@ -26,19 +24,23 @@ var canvas = (function(){
dragging = true
current_canvas = canvas
if (drawing) {
- erasing = (e.which == "3" || e.ctrlKey)
- draw(lex, x, y, erasing)
- last_point[0] = x
- last_point[1] = y
+ draw.down(e, lex, point)
+ }
+ else if (selecting) {
+ selection.down(e, lex, point)
+ }
+ else if (filling) {
+ draw.fill(brush, x, y)
}
lex.focus()
})
- lex.span.addEventListener("mousemove", function(){
+ lex.span.addEventListener("mousemove", function(e){
if (! dragging) return
if (drawing) {
- line(lex, last_point, point, erasing)
- last_point[0] = x
- last_point[1] = y
+ draw.move(e, lex, point)
+ }
+ else if (selecting) {
+ selection.move(e, lex, point)
}
lex.focus()
})
diff --git a/js/ui/controls.js b/js/ui/controls.js
index d575725..81403db 100644
--- a/js/ui/controls.js
+++ b/js/ui/controls.js
@@ -2,12 +2,13 @@ var controls = (function(){
var controls = {}
-
controls.circle = new Tool (circle_el)
controls.circle.use = function(){
brush.generate = controls.circle.generate
brush.generate()
drawing = true
+ filling = false
+ selection.hide()
brush.modified = false
}
controls.circle.generate = function(){
@@ -28,80 +29,100 @@ var controls = (function(){
controls.square.use = function(){
brush.generate = controls.square.generate
brush.generate()
- drawing = true
brush.modified = false
+ drawing = true
+ filling = false
+ selection.hide()
}
controls.square.generate = function(){
var fg = brush.fg, bg = brush.bg
brush.fill(fg,bg)
}
-
-
+
controls.text = new Tool (text_el)
controls.text.use = function(){
brush.generate = controls.text.generate
brush.generate()
drawing = false
+ filling = false
+ selection.hide()
}
controls.text.generate = function(){
}
-
+ controls.select = new Tool (select_el)
+ controls.select.use = function(){
+ drawing = false
+ filling = false
+ selection.show()
+ }
+
+ controls.fill = new Tool (fill_el)
+ controls.fill.use = function(){
+ drawing = false
+ filling = true
+ selection.hide()
+ }
+
controls.clear = new Tool (clear_el)
controls.clear.use = function(){
canvas.clear()
}
-
controls.grid = new Tool (grid_el)
controls.grid.use = function(){
document.body.classList.toggle('grid')
}
-
-
- controls.shader = new Tool (shader_el)
- controls.shader.use = function(){
- shader_textarea.style.display = "block"
- // setTimeout(function(){ shader_textarea.focus() })
- shader_textarea.focus()
+ controls.grid.show = function(){
+ document.body.classList.add('grid')
}
- controls.shader.blur = function(){
- Tool.prototype.blur.call(this)
- shader_textarea.style.display = "none"
+ controls.grid.hide = function(){
+ document.body.classList.remove('grid')
}
+
+ ClipboardTool = Tool.extend({
+ blur: function(){
+ this.__blur()
+ clipboard.hide()
+ }
+ })
+ ShaderTool = Tool.extend({
+ use: function(){
+ shader_textarea.style.display = "block"
+ shader_textarea.focus()
+ },
+ blur: function(){
+ this.__blur()
+ shader_textarea.style.display = "none"
+ }
+ })
+
+ controls.shader = new ShaderTool (shader_el)
+
shader_textarea.value = demo_shader.innerHTML
shader_textarea.addEventListener("input", function(){
var fn = shader.build(shader_textarea.value)
fn && shader.run(canvas)
})
- controls.save = new Tool (save_el)
+ controls.save = new ClipboardTool (save_el)
controls.save.use = function(){
clipboard.show()
clipboard.export_mode()
}
- controls.save.blur = function(){
- Tool.prototype.blur.call(this)
- clipboard.hide()
- }
- controls.load = new Tool (load_el)
+ controls.load = new ClipboardTool (load_el)
controls.load.use = function(){
clipboard.show()
clipboard.import_mode()
}
- controls.load.blur = function(){
- Tool.prototype.blur.call(this)
- clipboard.hide()
- }
controls.animate = new Tool (animate_checkbox)
controls.animate.use = function(){
var state = shader.toggle()
- if (state) animate_checkbox.innerHTML = "x animate"
- else animate_checkbox.innerHTML = "_ animate"
+ if (state) this.el.innerHTML = "x animate"
+ else this.el.innerHTML = "_ animate"
}
-
controls.width = new Lex (width_el)
controls.height = new Lex (height_el)
controls.canvas_width = new Lex (canvas_width_el)
@@ -110,7 +131,12 @@ var controls = (function(){
// bind
controls.bind = function(){
- [controls.width, controls.height, controls.canvas_width, controls.canvas_height].forEach(function(lex){
+ [
+ controls.width,
+ controls.height,
+ controls.canvas_width,
+ controls.canvas_height
+ ].forEach(function(lex){
lex.span.addEventListener('mousedown', function(e){
lex.focus()
})
@@ -120,6 +146,8 @@ var controls = (function(){
controls.square,
controls.circle,
controls.text,
+ controls.fill,
+ controls.select,
controls.clear,
controls.grid,
controls.shader,
@@ -133,14 +161,14 @@ var controls = (function(){
})
controls.width.key = int_key(function(n, keyCode){
- controls.width.blur()
+ controls.width.blur()
controls.width.char = ""+n
controls.width.build()
brush.w = n
brush.rebuild()
})
controls.height.key = int_key(function(n, keyCode){
- controls.height.blur()
+ controls.height.blur()
controls.height.char = ""+n
controls.height.build()
brush.h = n
@@ -154,22 +182,36 @@ var controls = (function(){
}
controls.canvas_width.char = ""+n
controls.canvas_width.build()
- canvas.w = n
- canvas.rebuild()
- canvas.build()
})
+ controls.canvas_width.onBlur = function(){
+ var w = parseInt(controls.canvas_width.char) || 1
+ controls.canvas_width.char = w+""
+ controls.canvas_width.build()
+ canvas.resize(w, canvas.h)
+ }
+
controls.canvas_height.key = int_key(function(n, keyCode){
controls.canvas_height.read()
- if (controls.canvas_height.char.length == 1) {
+ if (controls.canvas_height.char.length < 3) {
n = parseInt(controls.canvas_height.char) * 10 + n
}
controls.canvas_height.char = ""+n
controls.canvas_height.build()
- canvas.h = n
- canvas.rebuild()
- canvas.build()
})
+ controls.canvas_height.onBlur = function(){
+ var h = parseInt(controls.canvas_height.char) || 1
+ controls.canvas_height.char = h+""
+ controls.canvas_height.build()
+ canvas.resize(canvas.w, h)
+ }
}
+ function int_key (f) {
+ return function (key, keyCode) {
+ var n = parseInt(key)
+ ! isNaN(n) && f(n)
+ }
+ }
+
return controls
})() \ No newline at end of file
diff --git a/js/ui/keys.js b/js/ui/keys.js
index 7711e9d..1915333 100644
--- a/js/ui/keys.js
+++ b/js/ui/keys.js
@@ -5,7 +5,7 @@ var keys = (function(){
keys.bind = function(){
cursor_input.addEventListener('keydown', function(e){
- console.log("keycode:", e.keyCode)
+ // console.log("keycode:", e.keyCode)
switch (e.keyCode) {
case 27: // esc
@@ -69,12 +69,14 @@ var keys = (function(){
var char = cursor_input.value
cursor_input.value = ""
- console.log("input:", char)
+ // console.log("input:", char)
if (focused && char) {
var y = focused.y, x = focused.x
focused.key(char, e.keyCode)
- current_canvas.focusLex(y + direction[0], focused.x + direction[1])
+ if (! ('y' in focused && 'x' in focused) ) { return }
+ // console.log(y, direction[0], x, direction[1])
+ current_canvas.focusLex(y + direction[0], x + direction[1])
}
})
}
diff --git a/js/ui/palette.js b/js/ui/palette.js
index ce8078e..54211fb 100644
--- a/js/ui/palette.js
+++ b/js/ui/palette.js
@@ -2,7 +2,7 @@ var palette = (function(){
var palette = new Matrix (32, 2, function(x,y){
var lex = new Lex (x,y)
- lex.bg = all_hue(x>>1)
+ lex.bg = all_inv_hue(x>>1)
lex.build()
return lex
})
diff --git a/js/ui/selection.js b/js/ui/selection.js
new file mode 100644
index 0000000..cbd15bf
--- /dev/null
+++ b/js/ui/selection.js
@@ -0,0 +1,148 @@
+var selection = (function(){
+
+ var creating = false, moving = false, copying = false
+
+ var selection_canvas = new Matrix (1, 1, function(x,y){
+ var lex = new Lex (x,y)
+ lex.build()
+ return lex
+ })
+
+ var selector_el = document.createElement("div")
+ selector_el.className = "selector_el"
+ selection_canvas.append(selector_el)
+ document.body.appendChild(selector_el)
+
+ // in selection mode..
+ // - we start by clicking the canvas. this positions the selection, and copies
+ // the character
+ // - then we drag down and to the right. this resizes the selection and pushes new
+ // rows and columns. each of these copies the character underneath.
+ // - on mouseup, the selection is locked. then..
+ // - drag the selection to move it -- this "cuts" it and leaves a blank space on the canvas.
+ // - shift-drag the selection to copy it
+
+ var a = [0, 0]
+ var b = [0, 0]
+ var c = [0, 0]
+ var d = [0, 0]
+
+ function reset () {
+ a[0] = a[1] = b[0] = b[1] = 0
+ }
+ function left (a,b) { return min(a[0],b[0]) }
+ function top (a,b) { return min(a[1],b[1]) }
+ function right (a,b) { return max(a[0],b[0]) }
+ function bottom (a,b) { return max(a[1],b[1]) }
+ function width (a,b) { return abs(a[0]-b[0])+1 }
+ function height (a,b) { return abs(a[1]-b[1])+1 }
+ function mag_x (a,b) { return a[0]-b[0] }
+ function mag_y (a,b) { return a[1]-b[1] }
+ function orient (a,b) {
+ var l = left(a,b), m = top(a,b), n = right(a,b), o = bottom(a,b)
+ a[0] = l ; a[1] = m ; b[0] = n ; b[1] = o
+ }
+
+ function contains (a,b,point) {
+ var contains_x = a[0] <= point[0] && point[0] <= b[0]
+ var contains_y = a[1] <= point[1] && point[1] <= b[1]
+ return (contains_x && contains_y)
+ }
+ function reposition (a,b) {
+ var cell = canvas.aa[top(a,b)][left(a,b)].span
+ var cell_left = cell.offsetLeft
+ var cell_top = cell.offsetTop
+ var cell_width = 9
+ var cell_height = 17
+ var w = width(a,b)
+ var h = height(a,b)
+ selector_el.style.top = (cell_top-1) + "px"
+ selector_el.style.left = (cell_left-2) + "px"
+ selector_el.style.width = (cell_width*w+1) + "px"
+ selector_el.style.height = (cell_height*h+1) + "px"
+ }
+ function down (e, lex, point){
+ if ( ! contains(a,b,point) ) {
+ copying = false
+ moving = false
+ creating = true
+ a[0] = point[0]
+ a[1] = point[1]
+ b[0] = point[0]
+ b[1] = point[1]
+ reposition(a,b)
+ selector_el.classList.add("creating")
+ } else {
+ copying = false
+ moving = true
+ creating = false
+ c[0] = point[0]
+ c[1] = point[1]
+ d[0] = point[0]
+ d[1] = point[1]
+ }
+ show()
+ selector_el.classList.remove("dragging")
+ }
+ function move (e, lex, point){
+ if (creating) {
+ b[0] = point[0]
+ b[1] = point[1]
+ reposition(a,b)
+ }
+ else if (moving) {
+ d[0] = point[0]
+ d[1] = point[1]
+ var dx = - clamp( mag_x(c,d), b[0] - canvas.w + 1, a[0] )
+ var dy = - clamp( mag_y(c,d), b[1] - canvas.h + 1, a[1] )
+ reposition( [ a[0] + dx, a[1] + dy ], [ b[0] + dx, b[1] + dy ])
+ }
+ else if (copying) {
+ }
+ }
+ function up (e) {
+ if (creating) {
+ orient(a,b)
+ selection_canvas.resize(width(a,b), height(a,b))
+ blit.copy_from( canvas, selection_canvas, a[0], a[1] )
+ selection_canvas.build()
+ selector_el.classList.remove("creating")
+ }
+ if (moving) {
+ var dx = - clamp( mag_x(c,d), b[0] - canvas.w + 1, a[0] )
+ var dy = - clamp( mag_y(c,d), b[1] - canvas.h + 1, a[1] )
+ a[0] += dx
+ a[1] += dy
+ b[0] += dx
+ b[1] += dy
+ blit.copy_to( canvas, selection_canvas, a[0], a[1] )
+ }
+ if (copying) {
+ }
+ creating = moving = copying = false
+ selector_el.classList.remove("dragging")
+ }
+
+ function show () {
+ selecting = true
+ controls.grid.show()
+ }
+ function hide () {
+ reset()
+ selector_el.style.top = "-9999px"
+ selector_el.style.left = "-9999px"
+ selector_el.style.width = "0px"
+ selector_el.style.height = "0px"
+ selecting = false
+ }
+
+ var selection = {}
+ selection.down = down
+ selection.move = move
+ selection.up = up
+ selection.canvas = selection_canvas
+ selection.show = show
+ selection.hide = hide
+ return selection
+
+})()
diff --git a/js/util.js b/js/util.js
index f76fc8e..2a4f86a 100644
--- a/js/util.js
+++ b/js/util.js
@@ -143,3 +143,12 @@ function elastic (t) {
return ( e * Math.pow( 2, - 10 * t ) * Math.sin( ( t - f / 4 ) * ( 2 * Math.PI ) / f ) + 1 );
}
+Model=function a(b,c,d,e){function f(){var a=this,f={};a.on=function(a,b){(f[a]||
+(f[a]=[])).push(b)},a.trigger=function(a,b){for(var c=f[a],d=0;c&&d<c.length;)c
+[d++](b)},a.off=function(a,b){for(d=f[a]||[];b&&(c=d.indexOf(b))>-1;)d.splice(c
+,1);f[a]=b?d:[]};for(c in b)d=b[c],a[c]=typeof d=="function"?function(){return(
+d=this.apply(a,arguments))===e?a:d}.bind(d):d;a.init&&a.init.apply(a,arguments)
+}return f.extend=function(f){d={};for(c in b)d[c]=b[c];for(c in f)d[c]=f[c],b[c
+]!==e&&(d["__"+c]=b[c]);return a(d)},f},typeof module=="object"&&(module.exports
+=Model); // c-{{{-<
+