diff options
| author | Jules Laplace <jules@okfoc.us> | 2014-08-29 22:34:54 -0400 |
|---|---|---|
| committer | Jules Laplace <jules@okfoc.us> | 2014-08-29 22:34:54 -0400 |
| commit | 01755335859b19756f6d64a2f8a10ae98abceb5f (patch) | |
| tree | d5ba0258769f85fff5512498b04c3c037daecf79 /public/assets/javascripts/ui/editor/LightControl.js | |
| parent | 2235c34e498499b8141e835998b962067583a0ce (diff) | |
| parent | 851ddfd46abb7f944c1a6b7f198b5fd8cabd4c13 (diff) | |
merge
Diffstat (limited to 'public/assets/javascripts/ui/editor/LightControl.js')
| -rw-r--r-- | public/assets/javascripts/ui/editor/LightControl.js | 299 |
1 files changed, 264 insertions, 35 deletions
diff --git a/public/assets/javascripts/ui/editor/LightControl.js b/public/assets/javascripts/ui/editor/LightControl.js index c3e80c2..bd09dc2 100644 --- a/public/assets/javascripts/ui/editor/LightControl.js +++ b/public/assets/javascripts/ui/editor/LightControl.js @@ -1,43 +1,272 @@ var LightControl = View.extend({ - el: ".lightcontrol", - - events: { - "mousedown": "stopPropagation", - }, + el: ".lightcontrol", + + events: { + "mousedown": "stopPropagation", + "click .swatch": "clickSwatch", + "click label": "clickLabel", + "input #shadow-control": "updateShadow", + "mousedown #brightness-control": "beginBrightness", + "input #brightness-control": "updateBrightness", + "input #outline-hue": "updateShadow", + "input #wall-hue": "updateShadow", + }, + + initialize: function(){ + this.colorPicker = new LabColorPicker(this, 180, 180) + this.$el.prepend( this.colorPicker.canvas ) + + this.$swatches = this.$(".swatch") + this.$labels = this.$(".swatch + label") + this.$swatch = { + wall: this.$("#wall-color"), + outline: this.$("#outline-color"), + floor: this.$("#floor-color"), + ceiling: this.$("#ceiling-color"), + } + this.$brightnessControl = this.$("#brightness-control") + }, - toggle: function(state){ + modes: [ "wall", "outline", "floor", "ceiling" ], + + load: function(data){ + this.modes.forEach(function(mode){ + Walls.setColor[mode](data[mode]) + this.$swatch[ mode ].css("background-color", rgb_string(data[mode])) + }.bind(this)) + this.setMode("wall") + }, + + loadDefaults: function(){ + var colors = { + wall: app.defaults.wallColor.slice(), + outline: app.defaults.outlineColor.slice(), + floor: app.defaults.floorColor.slice(), + ceiling: app.defaults.ceilingColor.slice(), + } + this.load(colors) + }, + + toggle: function(state){ this.$el.toggleClass("active", state); + }, + + show: function(){ + this.toggle(true) + }, + + hide: function(){ + this.toggle(false) + }, + + pick: function(rgb, Lab){ + this.labColor = Lab + this.setSwatchColor(this.mode, rgb) + Walls.setColor[ this.mode ](rgb) + }, + + setSwatchColor: function(mode, rgb) { + this.$swatch[ mode ].css("background-color", rgb_string(rgb)) + }, + + initialState: null, + + begin: function(){ + this.initialState = this.serialize() + }, + + serialize: function(){ + return { + mode: this.mode, + rgb: Walls.colors[ this.mode ] + } + }, + + finalize: function(){ + if (! this.initialState) { return } + UndoStack.push({ + type: 'update-colors', + undo: this.initialState, + redo: this.serialize(), + }) + this.initialState = null + }, + + setMode: function (mode) { + var color, brightness + this.mode = mode + this.$swatches.removeClass("selected") + this.$labels.removeClass("selected") + this.$swatch[ mode ].addClass("selected") + color = Walls.colors[ mode ] + + this.$(".swatch.selected").next("label").addClass("selected") + this.labColor = this.colorPicker.load(color) + this.$brightnessControl.val( this.labColor[0] ) + }, + + clickLabel: function(e){ + $(e.currentTarget).prev(".swatch").trigger("click") + }, + clickSwatch: function(e){ + var mode = $(e.currentTarget).data('mode') + this.setMode(mode) + }, + + beginBrightness: function(){ + this.begin() + $(window).one("mouseup", this.finalize.bind(this)) + }, + + updateBrightness: function(){ + this.labColor[0] = parseFloat( this.$brightnessControl.val() ) + var rgb = this.colorPicker.setLab( this.labColor ) + this.pick(rgb, this.labColor) + }, - // toggle the class that makes the cursor a paintbucket - // $("body").removeClass("pastePaper"); - }, - show: function(){ - this.toggle(true) - }, - hide: function(){ - this.toggle(false) - }, +}) -/* - $("#shadow-control").on({ - mousedown: function(){ app.dragging = true }, - change: function(){ - var hex = (~~($(this).int() / 100 * 0xff)).toString(10) - if (hex.length == 1) hex = "0" + hex; - var color = "rgba(" + [hex, hex, hex, "1.0"] + ")" - $(".face").css("border-color", color) - } - }) +var LabColorPicker = function (parent, w, h) { + var base = this + var canvas = this.canvas = document.createElement('canvas') + var ctx = this.ctx = canvas.getContext('2d') + var imageData = ctx.createImageData(w,h) + var data = imageData.data - $("#brightness-control").on({ - mousedown: function(){ app.dragging = true }, - change: function(){ - var hex = (~~($(this).int() / 100 * 0xff)).toString(10) - var color = "rgba(" + [hex, hex, hex, "0.9"] + ")" - $("body,.face").css("background-color", color) - } - }) -*/ +// var cursor = this.cursor = document.createElement("div") +// cursor.className = "colorPickerCursor" -}) + canvas.width = w + canvas.height = h + canvas.className = "colorPicker" + + var ww = w-1 + var hh = h-1 + + var L_range = [0, 110] + var a_range = [-86.185, 98.254] + var b_range = [-107.863, 94.482] + + var rgb = [0,0,0] + + var val = 80 + + this.mouse = new mouse({ + el: canvas, + down: function(e, cursor){ + parent.begin() + cursor.x.a = -cursor.x.a + base.pick(cursor.x.a, cursor.y.a) + }, + drag: function(e, cursor){ + cursor.x.b = -cursor.x.b + base.pick(cursor.x.b, cursor.y.b) + }, + up: function(){ + parent.finalize() + } + }) + + this.setLab = function(Lab) { + val = Lab[0] + this.paint() + var rgb = xyz2rgb(hunterlab2xyz(Lab[0], Lab[1], Lab[2])).map(Math.round) + return rgb + } + this.pick = function(i, j){ + var x = mix( i/ww, a_range[0], a_range[1] ) + var y = mix( j/hh, b_range[0], b_range[1] ) + var rgb = xyz2rgb(hunterlab2xyz(val, x, y)).map(Math.round) + parent.pick( rgb, [val,x,y] ) + } + this.load = function(rgba){ + var Lab = xyz2hunterlab(rgb2xyz(rgba)) + var val = clamp( Lab[0], L_range[0], L_range[1] ) + var x = mix( norm(Lab[1], a_range[0], a_range[1]), 0, ww ) + var y = mix( norm(Lab[2], b_range[0], b_range[1]), 0, hh ) + // move the cursor + this.setLab(Lab) + return Lab + } + this.paint = function() { + val = clamp(val, L_range[0], L_range[1]) + var x, y, t + for (var i = 0; i < w; i++) { + for (var j = 0; j < h; j++) { + x = mix( i/ww, a_range[0], a_range[1] ) + y = mix( j/hh, b_range[0], b_range[1] ) + t = (j*w + i) * 4 + rgb = xyz2rgb(hunterlab2xyz(val, x, y)) + data[t] = Math.round( rgb[0] ) + data[t+1] = Math.round( rgb[1] ) + data[t+2] = Math.round( rgb[2] ) + data[t+3] = 255 + } + } + ctx.putImageData(imageData,0,0) + } + + function hunterlab2xyz (L,a,b) { + var_Y = L / 10 + var_X = a / 17.5 * L / 10 + var_Z = b / 7 * L / 10 + + Y = Math.pow(var_Y, 2) + X = ( var_X + Y ) / 1.02 + Z = -( var_Z - Y ) / 0.847 + xyz = [X,Y,Z] + } + function xyz2rgb(){ + var var_X = xyz[0] / 100 //X from 0 to 95.047 (Observer = 2°, Illuminant = D65) + var var_Y = xyz[1] / 100 //Y from 0 to 100.000 + var var_Z = xyz[2] / 100 //Z from 0 to 108.883 + + var_R = var_X * 3.2406 + var_Y * -1.5372 + var_Z * -0.4986 + var_G = var_X * -0.9689 + var_Y * 1.8758 + var_Z * 0.0415 + var_B = var_X * 0.0557 + var_Y * -0.2040 + var_Z * 1.0570 + + if ( var_R > 0.0031308 ) var_R = 1.055 * Math.pow( var_R, 1 / 2.4 ) - 0.055 + else var_R = 12.92 * var_R + if ( var_G > 0.0031308 ) var_G = 1.055 * Math.pow( var_G, 1 / 2.4 ) - 0.055 + else var_G = 12.92 * var_G + if ( var_B > 0.0031308 ) var_B = 1.055 * Math.pow( var_B, 1 / 2.4 ) - 0.055 + else var_B = 12.92 * var_B + + rgb[0] = clamp(var_R * 255, 0, 255) + rgb[1] = clamp(var_G * 255, 0, 255) + rgb[2] = clamp(var_B * 255, 0, 255) + return rgb + } + function rgb2xyz(RGB){ + var var_R = ( RGB[0] / 255 ) // R from 0 to 255 + var var_G = ( RGB[1] / 255 ) // G from 0 to 255 + var var_B = ( RGB[2] / 255 ) // B from 0 to 255 + + if ( var_R > 0.04045 ) var_R = ( ( var_R + 0.055 ) / 1.055 ) ^ 2.4 + else var_R = var_R / 12.92 + if ( var_G > 0.04045 ) var_G = ( ( var_G + 0.055 ) / 1.055 ) ^ 2.4 + else var_G = var_G / 12.92 + if ( var_B > 0.04045 ) var_B = ( ( var_B + 0.055 ) / 1.055 ) ^ 2.4 + else var_B = var_B / 12.92 + + var_R = var_R * 100 + var_G = var_G * 100 + var_B = var_B * 100 + + //Observer. = 2°, Illuminant = D65 + var x = var_R * 0.4124 + var_G * 0.3576 + var_B * 0.1805 + var y = var_R * 0.2126 + var_G * 0.7152 + var_B * 0.0722 + var z = var_R * 0.0193 + var_G * 0.1192 + var_B * 0.9505 + return [x,y,z] + } + function xyz2hunterlab (XYZ) { + var X = XYZ[0] + var Y = XYZ[1] || 1e-6 // otherwise divide-by-zero error when converting rgb(0,0,0) + var Z = XYZ[2] + var L = 10 * sqrt( Y ) + var a = 17.5 * ( ( ( 1.02 * X ) - Y ) / sqrt( Y ) ) + var b = 7 * ( ( Y - ( 0.847 * Z ) ) / sqrt( Y ) ) + return [L,a,b] + } +} |
