Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Comparing changes

Choose two branches to see what's changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base fork: trethaller/teztura
base: daebdfd31c
...
head fork: trethaller/teztura
compare: 8d4496c503
Checking mergeability… Don't worry, you can still create the pull request.
  • 7 commits
  • 17 files changed
  • 0 commit comments
  • 1 contributor
View
1  out/css/normalize.min.css
@@ -0,0 +1 @@
+/*! normalize.css v1.1.2 | MIT License | git.io/normalize */article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}audio:not([controls]){display:none;height:0}[hidden]{display:none}html{font-size:100%;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}html,button,input,select,textarea{font-family:sans-serif}body{margin:0}a:focus{outline:thin dotted}a:active,a:hover{outline:0}h1{font-size:2em;margin:.67em 0}h2{font-size:1.5em;margin:.83em 0}h3{font-size:1.17em;margin:1em 0}h4{font-size:1em;margin:1.33em 0}h5{font-size:.83em;margin:1.67em 0}h6{font-size:.67em;margin:2.33em 0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}blockquote{margin:1em 40px}dfn{font-style:italic}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}mark{background:#ff0;color:#000}p,pre{margin:1em 0}code,kbd,pre,samp{font-family:monospace,serif;_font-family:'courier new',monospace;font-size:1em}pre{white-space:pre;white-space:pre-wrap;word-wrap:break-word}q{quotes:none}q:before,q:after{content:'';content:none}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}dl,menu,ol,ul{margin:1em 0}dd{margin:0 0 0 40px}menu,ol,ul{padding:0 0 0 40px}nav ul,nav ol{list-style:none;list-style-image:none}img{border:0;-ms-interpolation-mode:bicubic}svg:not(:root){overflow:hidden}figure{margin:0}form{margin:0}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0;white-space:normal;*margin-left:-7px}button,input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}button,input{line-height:normal}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer;*overflow:visible}button[disabled],html input[disabled]{cursor:default}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0;*height:13px;*width:13px}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}textarea{overflow:auto;vertical-align:top}table{border-collapse:collapse;border-spacing:0}
View
BIN  out/img/matcaps/clay_1.0.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  out/img/matcaps/clay_2.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
7 out/index.html
@@ -7,6 +7,7 @@
<link rel="stylesheet" href="css/app.css">
<link rel="stylesheet" href="css/ui-lightness/jquery-ui-1.10.3.custom.min.css">
<script src="js/vendor/jquery-1.10.1.min.js"></script>
+<script src="js/vendor/jquery.mousewheel.js"></script>
<script src="js/vendor/jquery-ui-1.10.3.custom.js"></script>
<script src="js/vendor/underscore-min.js"></script>
<script src="js/vendor/backbone.js"></script>
@@ -22,16 +23,14 @@
</div>
<div id="commands"></div>
<div class="row">
- <div class="document-view span8">
+ <div class="document-view span9">
</div>
- <div id="tools" class="span4">
+ <div id="tools" class="span3">
<div id="palette"></div>
<div class="buttons"></div>
<div class="properties"></div>
</div>
</div>
- <pre id="status-bar">
- </pre>
</div>
<!--[if IE]>
View
70 out/js/teztura-renderers.js
@@ -40,7 +40,7 @@ GammaRenderer = (function() {
properties: properties,
renderLayer: renderLayer
};
-})();
+})();
GradientRenderer = (function() {
properties = {
@@ -66,19 +66,11 @@ GradientRenderer = (function() {
var offset = iy * width;
for(var ix=minX; ix<=maxX; ++ix) {
var fval = fb[offset + ix];
- var lookup = lut[
- Math.round(
- Math.min(511,
- Math.max(0,
- 256.0 * (1.0 + fval)
- )
- )
- )
- ];
+ var lookupIndex = Math.round(Math.min(511,Math.max(0,256.0 * (1.0 + fval)))) * 4;
var off = (offset + ix) << 2;
- imgData[off] = lookup & 0xff;
- imgData[off+1] = (lookup >> 8) & 0xff;
- imgData[off+2] = (lookup >> 16) & 0xff;
+ imgData[off] = lut[lookupIndex];
+ imgData[off+1] = lut[lookupIndex+1];
+ imgData[off+2] = lut[lookupIndex+2];
imgData[off+3] = 0xff;
}
}
@@ -93,7 +85,59 @@ GradientRenderer = (function() {
properties: properties,
renderLayer: renderLayer
};
+})();
+
+MatcapRenderer = (function(){
+ var properties = {
+ gain: 3.0,
+ matcap: null
+ };
+
+ function renderLayer (layer, view, rects) {
+ var width = layer.width;
+ var height = layer.height;
+ var imgData = view.imageData.data;
+ var fb = layer.getBuffer();
+ var dz = 1.0 / (properties.gain);
+ var matcapData = properties.matcap.data;
+ for(var ri in rects) {
+ var r = rects[ri];
+ var minX = r.x;
+ var minY = r.y;
+ var maxX = minX + r.width;
+ var maxY = minY + r.height;
+ for(var iy=minY; iy<=maxY; ++iy) {
+ for(var ix=minX; ix<=maxX; ++ix) {
+ var sx1 = fb[ ((iy + height) % height) * width + ((ix - 1 + width) % width) ];
+ var sx2 = fb[ ((iy + height) % height) * width + ((ix + 1 + width) % width) ];
+ var sy1 = fb[ ((iy - 1 + height) % height) * width + ((ix + width) % width) ];
+ var sy2 = fb[ ((iy + 1 + height) % height) * width + ((ix + width) % width) ];
+ var dx = sx2 - sx1;
+ var dy = sy2 - sy1;
+ var fac = 256.0 / Math.sqrt(dx*dx + dy*dy + dz*dz);
+ var lookupX = Math.round(dx * fac + 255.0);
+ var lookupY = Math.round(-dy * fac + 255.0);
+ var lookup = (lookupY * 512 + lookupX) * 4;
+ var i = (iy * width + ix) << 2;
+ imgData[i] = matcapData[lookup];
+ imgData[i+1] = matcapData[lookup+1];
+ imgData[i+2] = matcapData[lookup+2];
+ imgData[i+3] = 0xff;
+ }
+ }
+ view.context.putImageData(view.imageData, 0, 0, r.x, r.y, r.width+1, r.height+1);
+ }
+ }
+
+ return {
+ description: {
+ name: "Matcap"
+ },
+ properties: properties,
+ renderLayer: renderLayer
+ };
})();
+
NormalRenderer = (function(){
var properties = {
View
123 out/js/teztura.js
@@ -1,4 +1,4 @@
-var BlendModes, Commands, Document, DocumentView, Editor, FlattenBrush, Picker, PropertyPanel, PropertyView, Renderers, RoundBrush, StepBrush, Tools, createCommandsButtons, createPalette, createRenderersButtons, createToolsButtons, editor, loadGradient, refresh, status, toolsProperties, _ref,
+var BlendModes, Commands, Document, DocumentView, Editor, FlattenBrush, Matcaps, Picker, PropertyPanel, PropertyView, Renderers, RoundBrush, StepBrush, Tools, createCommandsButtons, createPalette, createRenderersButtons, createToolsButtons, editor, loadGradient, loadMatcaps, refresh, status, toolsProperties, _ref,
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
@@ -10,6 +10,8 @@ editor = null;
toolsProperties = null;
+Matcaps = [];
+
Commands = [
{
name: "Fill",
@@ -236,17 +238,41 @@ loadGradient = function(name, url) {
ctx = $canvas[0].getContext('2d');
imageObj = new Image();
imageObj.onload = function() {
- var data, imageData;
+ var imageData;
ctx.drawImage(this, 0, 0);
imageData = ctx.getImageData(0, 0, 512, 1);
- data = new Uint32Array(imageData.data.buffer);
return GradientRenderer.properties.gradient = {
- lut: data
+ lut: imageData.data
};
};
return imageObj.src = url;
};
+loadMatcaps = function(defs) {
+ var $canvas, ctx;
+ $canvas = $('<canvas/>').attr({
+ width: 512,
+ height: 512
+ });
+ ctx = $canvas[0].getContext('2d');
+ return defs.forEach(function(matcapDef) {
+ var imageObj;
+ imageObj = new Image();
+ imageObj.onload = function() {
+ var imageData;
+ console.log("Loaded matcap " + matcapDef.name);
+ ctx.drawImage(this, 0, 0);
+ imageData = ctx.getImageData(0, 0, 512, 512);
+ matcapDef.data = imageData.data;
+ Matcaps.push(matcapDef);
+ if (MatcapRenderer.properties.matcap == null) {
+ return MatcapRenderer.properties.matcap = matcapDef;
+ }
+ };
+ return imageObj.src = matcapDef.url;
+ });
+};
+
$(window).keydown(function(e) {
if (e.key === 'Control') {
editor.set('altkeyDown', true);
@@ -271,7 +297,13 @@ $(window).keyup(function(e) {
$(document).ready(function() {
loadGradient('g1', 'img/gradient-1.png');
- Renderers = [GammaRenderer, NormalRenderer, GradientRenderer];
+ loadMatcaps([
+ {
+ name: 'clay2',
+ url: 'img/matcaps/clay_2.jpg'
+ }
+ ]);
+ Renderers = [GammaRenderer, GradientRenderer, NormalRenderer, MatcapRenderer];
Tools = [RoundBrush, Picker, FlattenBrush];
toolsProperties = new PropertyPanel('#tools > .properties');
editor = new Editor();
@@ -303,10 +335,12 @@ DocumentView = (function() {
DocumentView.prototype.offset = new Vec2(0.0, 0.0);
- DocumentView.prototype.scale = 1.0;
+ DocumentView.prototype.scale = 2.0;
+
+ DocumentView.prototype.penPos = new Vec2(0, 0);
function DocumentView($container, doc) {
- var $backCanvas, $canvas, getCanvasCoords, getPenCoords, getPressure, local, penAPI, plugin,
+ var $backCanvas, $canvas, getCanvasCoords, getMouseCoords, getPressure, local, penAPI, plugin, updatePen,
_this = this;
this.doc = doc;
$container.empty();
@@ -330,12 +364,7 @@ DocumentView = (function() {
this.context.mozImageSmoothingEnabled = false;
plugin = document.getElementById('wtPlugin');
penAPI = plugin != null ? plugin.penAPI : null;
- getCanvasCoords = function(e) {
- var v;
- v = getPenCoords(e);
- return _this.screenToCanvas(v);
- };
- getPenCoords = function(e) {
+ getMouseCoords = function(e) {
var v;
v = new Vec2(e.pageX, e.pageY);
/*
@@ -355,6 +384,14 @@ DocumentView = (function() {
}
return 1.0;
};
+ updatePen = function(e) {
+ var pos;
+ pos = getMouseCoords(e);
+ return _this.penPos = _this.penPos.add(pos.sub(_this.penPos).scale(0.6));
+ };
+ getCanvasCoords = function() {
+ return _this.screenToCanvas(_this.penPos);
+ };
local = {};
$backCanvas.mousedown(function(e) {
var coords;
@@ -362,21 +399,21 @@ DocumentView = (function() {
if (e.which === 1) {
_this.drawing = true;
_this.actionDirtyRect = null;
- coords = getCanvasCoords(e);
+ coords = getCanvasCoords();
editor.getToolObject().beginDraw(doc.layer, coords);
doc.beginEdit();
_this.onDraw(coords, getPressure());
}
if (e.which === 2) {
_this.panning = true;
- local.panningStart = getPenCoords(e);
+ local.panningStart = getMouseCoords(e);
return local.offsetStart = _this.offset.clone();
}
});
$container.mouseup(function(e) {
e.preventDefault();
if (e.which === 1) {
- editor.getToolObject().endDraw(getCanvasCoords(e));
+ editor.getToolObject().endDraw(getCanvasCoords());
_this.drawing = false;
if (_this.actionDirtyRect != null) {
doc.afterEdit(_this.actionDirtyRect);
@@ -389,16 +426,23 @@ DocumentView = (function() {
$container.mousemove(function(e) {
var curPos, o;
e.preventDefault();
+ updatePen(e);
if (_this.drawing) {
- _this.onDraw(getCanvasCoords(e), getPressure());
+ _this.onDraw(getCanvasCoords(), getPressure());
}
if (_this.panning) {
- curPos = getPenCoords(e);
+ curPos = getMouseCoords(e);
o = local.offsetStart.add(curPos.sub(local.panningStart));
_this.offset = o;
return _this.rePaint();
}
});
+ $container.mousewheel(function(e, delta, deltaX, deltaY) {
+ var mult;
+ mult = 1.0 + (deltaY * 0.25);
+ _this.scale *= mult;
+ return _this.rePaint();
+ });
}
DocumentView.prototype.screenToCanvas = function(pt) {
@@ -717,11 +761,10 @@ RoundBrush = (function() {
};
properties = [
{
- id: 'stepSize',
- name: "Step size",
- defaultValue: 3,
- range: [1, 10],
- type: 'int'
+ id: 'step',
+ name: "Step %",
+ defaultValue: 10,
+ range: [0, 100]
}, {
id: 'hardness',
name: "Hardness",
@@ -750,9 +793,12 @@ RoundBrush = (function() {
createTool = function(env) {
var func, hardness, hardnessPlus1, sb, size;
sb = new StepBrush();
- sb.stepSize = self.get('stepSize');
- sb.tiling = env.get('tiling');
size = self.get('size');
+ sb.stepSize = Math.round(self.get('step') * size / 100.0);
+ if (sb.stepSize < 1) {
+ sb.stepSize = 1;
+ }
+ sb.tiling = env.get('tiling');
hardness = Math.pow(self.get('hardness'), 2.0) * 8.0;
hardnessPlus1 = hardness + 1.0;
func = genBrushFunc({
@@ -785,26 +831,25 @@ FlattenBrush = (function() {
};
properties = [
{
- id: 'stepSize',
- name: "Step size",
- defaultValue: 3,
- range: [1, 10],
- type: 'int'
+ id: 'step',
+ name: "Step %",
+ defaultValue: 10,
+ range: [0, 100]
}, {
id: 'hardness',
name: "Hardness",
- defaultValue: 0.8,
+ defaultValue: 0.2,
range: [0.0, 1.0]
}, {
id: 'size',
name: "Size",
- defaultValue: 40.0,
+ defaultValue: 30.0,
range: [1.0, 256.0],
type: 'int'
}, {
id: 'intensity',
name: "Intensity",
- defaultValue: 0.2,
+ defaultValue: 0.1,
range: [0.0, 1.0],
power: 2.0
}
@@ -813,9 +858,12 @@ FlattenBrush = (function() {
createTool = function(env) {
var func, hardness, hardnessPlus1, sb, size;
sb = new StepBrush();
- sb.stepSize = self.get('stepSize');
- sb.tiling = env.get('tiling');
size = self.get('size');
+ sb.stepSize = Math.round(self.get('step') * size / 100.0);
+ if (sb.stepSize < 1) {
+ sb.stepSize = 1;
+ }
+ sb.tiling = env.get('tiling');
hardness = Math.pow(self.get('hardness'), 2.0) * 8.0;
hardnessPlus1 = hardness + 1.0;
func = genBrushFunc({
@@ -825,9 +873,10 @@ FlattenBrush = (function() {
blendExp: "var tar = (-normal.x * (rect.x + sx) - normal.y * (rect.y + sy) - det) / normal.z; {dst} = {dst} * (1 - intensity * {src}) + intensity * tar * {src};"
});
sb.drawStep = function(layer, pos, intensity, rect) {
- var det, r;
+ var det, r, rad;
r = new Rect(pos.x - size * 0.5, pos.y - size * 0.5, size, size);
- self.normal = layer.getNormalAt(pos, 4);
+ rad = Math.round(self.get('size') * 0.5 * 0.75);
+ self.normal = layer.getNormalAt(pos, rad);
self.origin = new Vec3(pos.x, pos.y, layer.getAt(pos));
det = -self.normal.x * self.origin.x - self.normal.y * self.origin.y - self.normal.z * self.origin.z;
func(r, layer, intensity * self.get('intensity'), hardness, self.normal, det);
View
117 out/js/vendor/jquery.mousewheel.js
@@ -0,0 +1,117 @@
+/*! Copyright (c) 2013 Brandon Aaron (http://brandonaaron.net)
+ * Licensed under the MIT License (LICENSE.txt).
+ *
+ * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers.
+ * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix.
+ * Thanks to: Seamus Leahy for adding deltaX and deltaY
+ *
+ * Version: 3.1.3
+ *
+ * Requires: 1.2.2+
+ */
+
+(function (factory) {
+ if ( typeof define === 'function' && define.amd ) {
+ // AMD. Register as an anonymous module.
+ define(['jquery'], factory);
+ } else if (typeof exports === 'object') {
+ // Node/CommonJS style for Browserify
+ module.exports = factory;
+ } else {
+ // Browser globals
+ factory(jQuery);
+ }
+}(function ($) {
+
+ var toFix = ['wheel', 'mousewheel', 'DOMMouseScroll', 'MozMousePixelScroll'];
+ var toBind = 'onwheel' in document || document.documentMode >= 9 ? ['wheel'] : ['mousewheel', 'DomMouseScroll', 'MozMousePixelScroll'];
+ var lowestDelta, lowestDeltaXY;
+
+ if ( $.event.fixHooks ) {
+ for ( var i = toFix.length; i; ) {
+ $.event.fixHooks[ toFix[--i] ] = $.event.mouseHooks;
+ }
+ }
+
+ $.event.special.mousewheel = {
+ setup: function() {
+ if ( this.addEventListener ) {
+ for ( var i = toBind.length; i; ) {
+ this.addEventListener( toBind[--i], handler, false );
+ }
+ } else {
+ this.onmousewheel = handler;
+ }
+ },
+
+ teardown: function() {
+ if ( this.removeEventListener ) {
+ for ( var i = toBind.length; i; ) {
+ this.removeEventListener( toBind[--i], handler, false );
+ }
+ } else {
+ this.onmousewheel = null;
+ }
+ }
+ };
+
+ $.fn.extend({
+ mousewheel: function(fn) {
+ return fn ? this.bind("mousewheel", fn) : this.trigger("mousewheel");
+ },
+
+ unmousewheel: function(fn) {
+ return this.unbind("mousewheel", fn);
+ }
+ });
+
+
+ function handler(event) {
+ var orgEvent = event || window.event,
+ args = [].slice.call(arguments, 1),
+ delta = 0,
+ deltaX = 0,
+ deltaY = 0,
+ absDelta = 0,
+ absDeltaXY = 0,
+ fn;
+ event = $.event.fix(orgEvent);
+ event.type = "mousewheel";
+
+ // Old school scrollwheel delta
+ if ( orgEvent.wheelDelta ) { delta = orgEvent.wheelDelta; }
+ if ( orgEvent.detail ) { delta = orgEvent.detail * -1; }
+
+ // New school wheel delta (wheel event)
+ if ( orgEvent.deltaY ) {
+ deltaY = orgEvent.deltaY * -1;
+ delta = deltaY;
+ }
+ if ( orgEvent.deltaX ) {
+ deltaX = orgEvent.deltaX;
+ delta = deltaX * -1;
+ }
+
+ // Webkit
+ if ( orgEvent.wheelDeltaY !== undefined ) { deltaY = orgEvent.wheelDeltaY; }
+ if ( orgEvent.wheelDeltaX !== undefined ) { deltaX = orgEvent.wheelDeltaX * -1; }
+
+ // Look for lowest delta to normalize the delta values
+ absDelta = Math.abs(delta);
+ if ( !lowestDelta || absDelta < lowestDelta ) { lowestDelta = absDelta; }
+ absDeltaXY = Math.max(Math.abs(deltaY), Math.abs(deltaX));
+ if ( !lowestDeltaXY || absDeltaXY < lowestDeltaXY ) { lowestDeltaXY = absDeltaXY; }
+
+ // Get a whole value for the deltas
+ fn = delta > 0 ? 'floor' : 'ceil';
+ delta = Math[fn](delta / lowestDelta);
+ deltaX = Math[fn](deltaX / lowestDeltaXY);
+ deltaY = Math[fn](deltaY / lowestDeltaXY);
+
+ // Add event and delta to the front of the arguments
+ args.unshift(event, delta, deltaX, deltaY);
+
+ return ($.event.dispatch || $.event.handle).apply(this, args);
+ }
+
+}));
View
3  package.json
@@ -25,5 +25,8 @@
"grunt-contrib-sass": "~0.5.0",
"grunt-contrib-watch": "~0.5.2",
"grunt-contrib-connect": "~0.3.0"
+ },
+ "dependencies": {
+ "jquery-mousewheel": "~3.1.3"
}
}
View
BIN  resources/matcaps/clay_1.0.blend
Binary file not shown
View
BIN  resources/matcaps/clay_1.0.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  resources/matcaps/clay_1.0.xcf
Binary file not shown
View
BIN  resources/matcaps/generator2.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
31 src/app.coffee
@@ -3,6 +3,7 @@ Renderers = null
Tools = null
editor = null
toolsProperties = null
+Matcaps = []
Commands = [
{
@@ -69,6 +70,7 @@ Commands = [
# ---
+
class Editor extends Backbone.Model
defaults: ->
doc: null
@@ -179,15 +181,33 @@ loadGradient = (name, url)->
imageObj.onload = ()->
ctx.drawImage(this, 0, 0);
imageData = ctx.getImageData(0,0,512,1)
- data = new Uint32Array(imageData.data.buffer)
GradientRenderer.properties.gradient = {
- lut: data
+ lut: imageData.data
}
imageObj.src = url
+loadMatcaps = (defs)->
+ $canvas = $('<canvas/>').attr {width: 512, height:512}
+ ctx = $canvas[0].getContext('2d')
+ defs.forEach (matcapDef)->
+ imageObj = new Image()
+ imageObj.onload = ()->
+ console.log "Loaded matcap " + matcapDef.name
+ ctx.drawImage(this, 0, 0)
+ imageData = ctx.getImageData(0,0,512,512)
+ matcapDef.data = imageData.data
+ Matcaps.push(matcapDef)
+
+ # Set first by default
+ if not MatcapRenderer.properties.matcap?
+ MatcapRenderer.properties.matcap = matcapDef
+
+ imageObj.src = matcapDef.url
+
# --
+
$(window).keydown (e)->
if e.key is 'Control'
editor.set('altkeyDown', true)
@@ -208,9 +228,14 @@ $(window).keyup (e)->
$(document).ready ()->
loadGradient('g1', 'img/gradient-1.png')
+ loadMatcaps([
+ {name: 'clay2', url: 'img/matcaps/clay_2.jpg'}
+ # {name: 'clay1', url: 'img/matcaps/clay_1.0.png'}
+ ])
+
#loadGradient('g2', 'img/gradient-2.png')
- Renderers = [GammaRenderer, NormalRenderer, GradientRenderer]
+ Renderers = [GammaRenderer, GradientRenderer, NormalRenderer, MatcapRenderer]
Tools = [RoundBrush, Picker, FlattenBrush]
toolsProperties = new PropertyPanel '#tools > .properties'
View
34 src/document-view.coffee
@@ -8,7 +8,8 @@ class DocumentView
backContext: null
doc: null
offset: new Vec2(0.0, 0.0)
- scale: 1.0
+ scale: 2.0
+ penPos: new Vec2(0,0)
constructor: ($container, doc)->
@doc = doc
@@ -27,11 +28,8 @@ class DocumentView
plugin = document.getElementById('wtPlugin')
penAPI = if plugin? then plugin.penAPI else null
- getCanvasCoords = (e)=>
- v = getPenCoords(e)
- return @screenToCanvas(v)
-
- getPenCoords = (e)=>
+
+ getMouseCoords = (e)=>
v = new Vec2(e.pageX, e.pageY)
###
@@ -49,6 +47,13 @@ class DocumentView
return penAPI.pressure
return 1.0
+ updatePen = (e)=>
+ pos = getMouseCoords(e)
+ @penPos = @penPos.add( pos.sub(@penPos).scale(0.6) )
+
+ getCanvasCoords = =>
+ return @screenToCanvas(@penPos)
+
local = {}
$backCanvas.mousedown (e)=>
@@ -57,20 +62,20 @@ class DocumentView
if e.which is 1
@drawing = true
@actionDirtyRect = null
- coords = getCanvasCoords(e)
+ coords = getCanvasCoords()
editor.getToolObject().beginDraw(doc.layer, coords)
doc.beginEdit()
@onDraw(coords, getPressure())
if e.which is 2
@panning = true
- local.panningStart = getPenCoords(e)
+ local.panningStart = getMouseCoords(e)
local.offsetStart = @offset.clone()
$container.mouseup (e)=>
e.preventDefault()
if e.which is 1
- editor.getToolObject().endDraw(getCanvasCoords(e))
+ editor.getToolObject().endDraw(getCanvasCoords())
@drawing = false
if @actionDirtyRect?
doc.afterEdit(@actionDirtyRect)
@@ -80,15 +85,22 @@ class DocumentView
$container.mousemove (e)=>
e.preventDefault()
+ updatePen(e)
+
if @drawing
- @onDraw(getCanvasCoords(e), getPressure())
+ @onDraw(getCanvasCoords(), getPressure())
if @panning
- curPos = getPenCoords(e)
+ curPos = getMouseCoords(e)
o = local.offsetStart.add(curPos.sub(local.panningStart))
@offset = o
@rePaint()
+ $container.mousewheel (e, delta, deltaX, deltaY)=>
+ mult = 1.0 + (deltaY * 0.25)
+ @scale *= mult
+ @rePaint()
+
screenToCanvas: (pt)->
return pt.sub(@offset).scale(1.0/@scale)
View
16 src/renderers/gradient-renderer.js
@@ -23,19 +23,11 @@ GradientRenderer = (function() {
var offset = iy * width;
for(var ix=minX; ix<=maxX; ++ix) {
var fval = fb[offset + ix];
- var lookup = lut[
- Math.round(
- Math.min(511,
- Math.max(0,
- 256.0 * (1.0 + fval)
- )
- )
- )
- ];
+ var lookupIndex = Math.round(Math.min(511,Math.max(0,256.0 * (1.0 + fval)))) * 4;
var off = (offset + ix) << 2;
- imgData[off] = lookup & 0xff;
- imgData[off+1] = (lookup >> 8) & 0xff;
- imgData[off+2] = (lookup >> 16) & 0xff;
+ imgData[off] = lut[lookupIndex];
+ imgData[off+1] = lut[lookupIndex+1];
+ imgData[off+2] = lut[lookupIndex+2];
imgData[off+3] = 0xff;
}
}
View
51 src/renderers/matcap-renderer.js
@@ -0,0 +1,51 @@
+
+MatcapRenderer = (function(){
+ var properties = {
+ gain: 3.0,
+ matcap: null
+ };
+
+ function renderLayer (layer, view, rects) {
+ var width = layer.width;
+ var height = layer.height;
+ var imgData = view.imageData.data;
+ var fb = layer.getBuffer();
+ var dz = 1.0 / (properties.gain);
+ var matcapData = properties.matcap.data;
+ for(var ri in rects) {
+ var r = rects[ri];
+ var minX = r.x;
+ var minY = r.y;
+ var maxX = minX + r.width;
+ var maxY = minY + r.height;
+ for(var iy=minY; iy<=maxY; ++iy) {
+ for(var ix=minX; ix<=maxX; ++ix) {
+ var sx1 = fb[ ((iy + height) % height) * width + ((ix - 1 + width) % width) ];
+ var sx2 = fb[ ((iy + height) % height) * width + ((ix + 1 + width) % width) ];
+ var sy1 = fb[ ((iy - 1 + height) % height) * width + ((ix + width) % width) ];
+ var sy2 = fb[ ((iy + 1 + height) % height) * width + ((ix + width) % width) ];
+ var dx = sx2 - sx1;
+ var dy = sy2 - sy1;
+ var fac = 256.0 / Math.sqrt(dx*dx + dy*dy + dz*dz);
+ var lookupX = Math.round(dx * fac + 255.0);
+ var lookupY = Math.round(-dy * fac + 255.0);
+ var lookup = (lookupY * 512 + lookupX) * 4;
+ var i = (iy * width + ix) << 2;
+ imgData[i] = matcapData[lookup];
+ imgData[i+1] = matcapData[lookup+1];
+ imgData[i+2] = matcapData[lookup+2];
+ imgData[i+3] = 0xff;
+ }
+ }
+ view.context.putImageData(view.imageData, 0, 0, r.x, r.y, r.width+1, r.height+1);
+ }
+ }
+
+ return {
+ description: {
+ name: "Matcap"
+ },
+ properties: properties,
+ renderLayer: renderLayer
+ };
+})();
View
41 src/tools.coffee
@@ -72,11 +72,10 @@ RoundBrush = (()->
name: 'Round'
properties = [
{
- id: 'stepSize'
- name: "Step size"
- defaultValue: 3
- range: [1, 10]
- type: 'int'
+ id: 'step'
+ name: "Step %"
+ defaultValue: 10
+ range: [0, 100]
},
{
id: 'hardness'
@@ -110,9 +109,12 @@ RoundBrush = (()->
createTool = (env)->
sb = new StepBrush()
- sb.stepSize = self.get('stepSize')
- sb.tiling = env.get('tiling')
+
size = self.get('size')
+ sb.stepSize = Math.round(self.get('step') * size / 100.0)
+ if sb.stepSize < 1
+ sb.stepSize = 1
+ sb.tiling = env.get('tiling')
hardness = Math.pow(self.get('hardness'), 2.0) * 8.0;
hardnessPlus1 = hardness + 1.0
@@ -150,29 +152,28 @@ FlattenBrush = (()->
name: 'Flatten'
properties = [
{
- id: 'stepSize'
- name: "Step size"
- defaultValue: 3
- range: [1, 10]
- type: 'int'
+ id: 'step'
+ name: "Step %"
+ defaultValue: 10
+ range: [0, 100]
},
{
id: 'hardness'
name: "Hardness"
- defaultValue: 0.8
+ defaultValue: 0.2
range: [0.0, 1.0]
},
{
id: 'size'
name: "Size"
- defaultValue: 40.0
+ defaultValue: 30.0
range: [1.0, 256.0]
type: 'int'
},
{
id:'intensity'
name: "Intensity"
- defaultValue: 0.2
+ defaultValue: 0.1
range: [0.0, 1.0]
power: 2.0
}
@@ -182,10 +183,13 @@ FlattenBrush = (()->
createTool = (env)->
sb = new StepBrush()
- sb.stepSize = self.get('stepSize')
- sb.tiling = env.get('tiling')
size = self.get('size')
+ sb.stepSize = Math.round(self.get('step') * size / 100.0)
+ if sb.stepSize < 1
+ sb.stepSize = 1
+ sb.tiling = env.get('tiling')
+
hardness = Math.pow(self.get('hardness'), 2.0) * 8.0;
hardnessPlus1 = hardness + 1.0
func = genBrushFunc {
@@ -203,7 +207,8 @@ FlattenBrush = (()->
pos.y - size * 0.5,
size, size)
- self.normal = layer.getNormalAt(pos, 4)
+ rad = Math.round(self.get('size') * 0.5 * 0.75)
+ self.normal = layer.getNormalAt(pos, rad)
self.origin = new Vec3(pos.x, pos.y, layer.getAt(pos))
det = -self.normal.x * self.origin.x - self.normal.y * self.origin.y - self.normal.z * self.origin.z;
func(r, layer, intensity * self.get('intensity'), hardness, self.normal, det)

No commit comments for this range

Something went wrong with that request. Please try again.