From bc2bc02d9b317cdea5003210be0fbaf32c818ba9 Mon Sep 17 00:00:00 2001 From: funny bot Date: Tue, 7 Jul 2026 20:33:13 -0700 Subject: [PATCH 1/8] Add functioning brush resolution --- engine/src/tools/Brush.js | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/engine/src/tools/Brush.js b/engine/src/tools/Brush.js index 50fe2afeb..36048638b 100644 --- a/engine/src/tools/Brush.js +++ b/engine/src/tools/Brush.js @@ -40,6 +40,13 @@ Wick.Tools.Brush = class extends Wick.Tool { this.MIN_PRESSURE = 0.14; + this.TARGET_BRUSH_SIZE = 50; + this.MAX_RESOLUTION_FACTOR = 2; + this.smoothness = 1; + this.resolutionFactor = 1; + this.canvasScaleFactor = 1; // Resolution: Greater or equal to 1 + this.imageScaleFactor = 1; // Resolution: Lesser or equal to 1 + this.croquis = null; this.croquisDOMElement = null; this.croquisBrush = null; @@ -119,6 +126,11 @@ Wick.Tools.Brush = class extends Wick.Tool { this.croquisDOMElement.style.height = '100%'; this.croquisDOMElement.style.display = 'block'; this.croquisDOMElement.style.pointerEvents = 'none'; + + this.croquisDOMElement.querySelectorAll('canvas').forEach(canvasElement => { + canvasElement.style.width = '100%'; + canvasElement.style.height = '100%'; + }); } this._isInProgress = false; @@ -178,10 +190,13 @@ Wick.Tools.Brush = class extends Wick.Tool { clearTimeout(this._croquisStartTimeout); this._isInProgress = true; + this.resolutionFactor = Math.min(this.TARGET_BRUSH_SIZE/this._getRealBrushSize() * this.smoothness, this.MAX_RESOLUTION_FACTOR); + this.canvasScaleFactor = (this.resolutionFactor > 1) ? this.resolutionFactor : 1; + this.imageScaleFactor = (this.resolutionFactor < 1) ? this.resolutionFactor : 1; this._updateCanvasAttributes(); // Update croquis params - this.croquisBrush.setSize(this._getRealBrushSize()); + this.croquisBrush.setSize(this._getRealBrushSize() * this.canvasScaleFactor); this.croquisBrush.setColor(this.getSetting('fillColor').hex); this.croquisBrush.setSpacing(this.BRUSH_POINT_SPACING); this.croquis.setToolStabilizeLevel(this.BRUSH_STABILIZER_LEVEL); @@ -379,10 +394,12 @@ Wick.Tools.Brush = class extends Wick.Tool { } // Update croquis element canvas size - if(this.croquis.getCanvasWidth() !== this.paper.view._element.width || - this.croquis.getCanvasHeight() !== this.paper.view._element.height) { - this.croquis.setCanvasSize(this.paper.view._element.width, this.paper.view._element.height); + if(this.croquis.getCanvasWidth() !== this.paper.view._element.width * this.canvasScaleFactor || + this.croquis.getCanvasHeight() !== this.paper.view._element.height * this.canvasScaleFactor) { + this.croquis.setCanvasSize(this.paper.view._element.width * this.canvasScaleFactor, this.paper.view._element.height * this.canvasScaleFactor); } + this.croquisDOMElement.style.width = '100%'; + this.croquisDOMElement.style.height = '100%'; // Fake brush opacity in croquis by changing the opacity of the croquis canvas this.croquisDOMElement.style.opacity = this.getSetting('fillColor').a; @@ -391,7 +408,7 @@ Wick.Tools.Brush = class extends Wick.Tool { /* Convert a point in Croquis' canvas space to paper.js's canvas space. */ _croquisToPaperPoint (croquisPoint) { var paperPoint = this.paper.view.projectToView(croquisPoint.x, croquisPoint.y); - return paperPoint; + return paperPoint.multiply(this.canvasScaleFactor); } /* Used for calculating the crop amount for potrace. */ @@ -458,8 +475,8 @@ Wick.Tools.Brush = class extends Wick.Tool { // (and crop out empty space using strokeBounds - this massively speeds up potrace) var croppedCanvas = document.createElement("canvas"); var croppedCanvasCtx = croppedCanvas.getContext("2d"); - croppedCanvas.width = strokeBounds.width; - croppedCanvas.height = strokeBounds.height; + croppedCanvas.width = strokeBounds.width * this.imageScaleFactor; + croppedCanvas.height = strokeBounds.height * this.imageScaleFactor; if(strokeBounds.x < 0) strokeBounds.x = 0; if(strokeBounds.y < 0) strokeBounds.y = 0; croppedCanvasCtx.drawImage( @@ -477,6 +494,7 @@ Wick.Tools.Brush = class extends Wick.Tool { potracePath.position.y += this.paper.view.bounds.y; potracePath.position.x += strokeBounds.x / this.paper.view.zoom; potracePath.position.y += strokeBounds.y / this.paper.view.zoom; + potracePath.scale(1 / this.resolutionFactor, this.paper.view.bounds.topLeft); potracePath.remove(); potracePath.closed = true; potracePath.children[0].closed = true; From 7adf7ff61098001f4c43097d7f016e4f4269d69e Mon Sep 17 00:00:00 2001 From: funny bot Date: Tue, 7 Jul 2026 21:09:30 -0700 Subject: [PATCH 2/8] Add brush smoothness slider to inspector --- src/Editor/Panels/Inspector/Inspector.jsx | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/Editor/Panels/Inspector/Inspector.jsx b/src/Editor/Panels/Inspector/Inspector.jsx index 22ecc5436..7481abe08 100644 --- a/src/Editor/Panels/Inspector/Inspector.jsx +++ b/src/Editor/Panels/Inspector/Inspector.jsx @@ -1045,6 +1045,26 @@ class Inspector extends Component { } render() { + if (this.props.project.selection.numObjects === 0 && this.props.project.activeTool.name === 'brush') { + return ( +
+
+ +
+
+ {this.props.project.tools.brush.smoothness = val; window.editor.projectDidChange(); }} + divider={false} + inputProps={{min: 0.01, max: 1, step: 0.01}} + id="inspector-brush-tool-smoothness"/> +
+
+ ); + } let selectionType = this.props.getSelectionType(); return(
From 5a4d4bc21df3bba12bb5300b5860adbe503defbc Mon Sep 17 00:00:00 2001 From: funny bot Date: Wed, 8 Jul 2026 14:17:43 -0700 Subject: [PATCH 3/8] Fix brush stroke getting cut off and offset from browser zoom --- engine/src/tools/Brush.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/engine/src/tools/Brush.js b/engine/src/tools/Brush.js index 36048638b..27305fb86 100644 --- a/engine/src/tools/Brush.js +++ b/engine/src/tools/Brush.js @@ -394,9 +394,10 @@ Wick.Tools.Brush = class extends Wick.Tool { } // Update croquis element canvas size - if(this.croquis.getCanvasWidth() !== this.paper.view._element.width * this.canvasScaleFactor || - this.croquis.getCanvasHeight() !== this.paper.view._element.height * this.canvasScaleFactor) { - this.croquis.setCanvasSize(this.paper.view._element.width * this.canvasScaleFactor, this.paper.view._element.height * this.canvasScaleFactor); + let width = Math.round(this.paper.view._viewSize.width * this.canvasScaleFactor); + let height = Math.round(this.paper.view._viewSize.height * this.canvasScaleFactor); + if(this.croquis.getCanvasWidth() !== width || this.croquis.getCanvasHeight() !== height) { + this.croquis.setCanvasSize(width, height); } this.croquisDOMElement.style.width = '100%'; this.croquisDOMElement.style.height = '100%'; From 28491c7ae08aafba1619df8c63e634abf6ce29c3 Mon Sep 17 00:00:00 2001 From: funny bot Date: Mon, 13 Jul 2026 14:24:21 -0700 Subject: [PATCH 4/8] Add some test sliders for paper.js tolerance and smoothness factor exponent --- engine/src/tools/Brush.js | 5 ++++- src/Editor/Panels/Inspector/Inspector.jsx | 14 ++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/engine/src/tools/Brush.js b/engine/src/tools/Brush.js index 27305fb86..275d042a9 100644 --- a/engine/src/tools/Brush.js +++ b/engine/src/tools/Brush.js @@ -46,6 +46,8 @@ Wick.Tools.Brush = class extends Wick.Tool { this.resolutionFactor = 1; this.canvasScaleFactor = 1; // Resolution: Greater or equal to 1 this.imageScaleFactor = 1; // Resolution: Lesser or equal to 1 + this.testPaperTolerance = 0; + this.testSmoothnessExponent = 2; this.croquis = null; this.croquisDOMElement = null; @@ -190,7 +192,7 @@ Wick.Tools.Brush = class extends Wick.Tool { clearTimeout(this._croquisStartTimeout); this._isInProgress = true; - this.resolutionFactor = Math.min(this.TARGET_BRUSH_SIZE/this._getRealBrushSize() * this.smoothness, this.MAX_RESOLUTION_FACTOR); + this.resolutionFactor = Math.min(this.TARGET_BRUSH_SIZE/this._getRealBrushSize() * Math.pow(this.smoothness, this.testSmoothnessExponent), this.MAX_RESOLUTION_FACTOR); this.canvasScaleFactor = (this.resolutionFactor > 1) ? this.resolutionFactor : 1; this.imageScaleFactor = (this.resolutionFactor < 1) ? this.resolutionFactor : 1; this._updateCanvasAttributes(); @@ -501,6 +503,7 @@ Wick.Tools.Brush = class extends Wick.Tool { potracePath.children[0].closed = true; potracePath.children[0].applyMatrix = true; var result = potracePath.children[0]; + if (this.testPaperTolerance > 0) result.simplify(this.testPaperTolerance); // Do special brush mode action var brushMode = this.getSetting('brushMode'); diff --git a/src/Editor/Panels/Inspector/Inspector.jsx b/src/Editor/Panels/Inspector/Inspector.jsx index 7481abe08..3bcbd1dc5 100644 --- a/src/Editor/Panels/Inspector/Inspector.jsx +++ b/src/Editor/Panels/Inspector/Inspector.jsx @@ -1061,6 +1061,20 @@ class Inspector extends Component { divider={false} inputProps={{min: 0.01, max: 1, step: 0.01}} id="inspector-brush-tool-smoothness"/> + {this.props.project.tools.brush.testPaperTolerance = val; window.editor.projectDidChange(); }} + divider={false} + inputProps={{min: 0, max: 10, step: 0.1}} + id="inspector-brush-tool-paper-js-tolerance"/> + {this.props.project.tools.brush.testSmoothnessExponent = val; window.editor.projectDidChange(); }} + divider={false} + inputProps={{min: 1, max: 8, step: 0.1}} + id="inspector-brush-tool-smoothness-exponent"/>
); From f2847ecc4babfe4f29e4fef2648331a2f437bbd1 Mon Sep 17 00:00:00 2001 From: funny bot Date: Mon, 13 Jul 2026 14:55:19 -0700 Subject: [PATCH 5/8] normalized inspector smoothness slider --- engine/src/tools/Brush.js | 2 +- src/Editor/Panels/Inspector/Inspector.jsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/engine/src/tools/Brush.js b/engine/src/tools/Brush.js index 275d042a9..c4119e014 100644 --- a/engine/src/tools/Brush.js +++ b/engine/src/tools/Brush.js @@ -192,7 +192,7 @@ Wick.Tools.Brush = class extends Wick.Tool { clearTimeout(this._croquisStartTimeout); this._isInProgress = true; - this.resolutionFactor = Math.min(this.TARGET_BRUSH_SIZE/this._getRealBrushSize() * Math.pow(this.smoothness, this.testSmoothnessExponent), this.MAX_RESOLUTION_FACTOR); + this.resolutionFactor = Math.min(this.TARGET_BRUSH_SIZE/this._getRealBrushSize() * Math.pow(1-(1-this.smoothness)*(1-Math.pow(0.05, 1/this.testSmoothnessExponent)), this.testSmoothnessExponent), this.MAX_RESOLUTION_FACTOR); this.canvasScaleFactor = (this.resolutionFactor > 1) ? this.resolutionFactor : 1; this.imageScaleFactor = (this.resolutionFactor < 1) ? this.resolutionFactor : 1; this._updateCanvasAttributes(); diff --git a/src/Editor/Panels/Inspector/Inspector.jsx b/src/Editor/Panels/Inspector/Inspector.jsx index 3bcbd1dc5..ab309946e 100644 --- a/src/Editor/Panels/Inspector/Inspector.jsx +++ b/src/Editor/Panels/Inspector/Inspector.jsx @@ -1059,7 +1059,7 @@ class Inspector extends Component { val={this.props.project.tools.brush.smoothness} onChange={(val) => {this.props.project.tools.brush.smoothness = val; window.editor.projectDidChange(); }} divider={false} - inputProps={{min: 0.01, max: 1, step: 0.01}} + inputProps={{min: 0, max: 1, step: 0.01}} id="inspector-brush-tool-smoothness"/> Date: Mon, 13 Jul 2026 20:11:48 -0700 Subject: [PATCH 6/8] Make brush resolution a setting --- engine/src/ToolSettings.js | 7 ++++ engine/src/tools/Brush.js | 7 ++-- src/Editor/Panels/Inspector/Inspector.jsx | 34 ------------------- .../Toolbox/ToolSettings/ToolSettings.jsx | 14 ++++++++ src/Editor/Util/ToolIcon/ToolIcon.jsx | 2 ++ .../property-icons/brushresolution.svg | 10 ++++++ 6 files changed, 36 insertions(+), 38 deletions(-) create mode 100644 src/resources/inspector-icons/property-icons/brushresolution.svg diff --git a/engine/src/ToolSettings.js b/engine/src/ToolSettings.js index 597344ca0..78c1a84d5 100644 --- a/engine/src/ToolSettings.js +++ b/engine/src/ToolSettings.js @@ -62,6 +62,13 @@ Wick.ToolSettings = class { min: 0, max: 100, step: 1, + }, { + type: "number", + name: 'brushResolution', + default: 1, + min: 0, + max: 1, + step: 0.01, }, { type: "boolean", name: 'pressureEnabled', diff --git a/engine/src/tools/Brush.js b/engine/src/tools/Brush.js index c4119e014..4c598c210 100644 --- a/engine/src/tools/Brush.js +++ b/engine/src/tools/Brush.js @@ -46,8 +46,6 @@ Wick.Tools.Brush = class extends Wick.Tool { this.resolutionFactor = 1; this.canvasScaleFactor = 1; // Resolution: Greater or equal to 1 this.imageScaleFactor = 1; // Resolution: Lesser or equal to 1 - this.testPaperTolerance = 0; - this.testSmoothnessExponent = 2; this.croquis = null; this.croquisDOMElement = null; @@ -192,7 +190,9 @@ Wick.Tools.Brush = class extends Wick.Tool { clearTimeout(this._croquisStartTimeout); this._isInProgress = true; - this.resolutionFactor = Math.min(this.TARGET_BRUSH_SIZE/this._getRealBrushSize() * Math.pow(1-(1-this.smoothness)*(1-Math.pow(0.05, 1/this.testSmoothnessExponent)), this.testSmoothnessExponent), this.MAX_RESOLUTION_FACTOR); + var smoothnessFactor = Math.pow(1 - (1-this.getSetting('brushResolution'))*0.486095733599, 4.5); //1-Math.pow(0.05, 1/4.5), 0.486095733599 + this.resolutionFactor = this.TARGET_BRUSH_SIZE/this._getRealBrushSize() * smoothnessFactor; + this.resolutionFactor = Math.min(Math.max(this.resolutionFactor, smoothnessFactor), this.MAX_RESOLUTION_FACTOR); this.canvasScaleFactor = (this.resolutionFactor > 1) ? this.resolutionFactor : 1; this.imageScaleFactor = (this.resolutionFactor < 1) ? this.resolutionFactor : 1; this._updateCanvasAttributes(); @@ -503,7 +503,6 @@ Wick.Tools.Brush = class extends Wick.Tool { potracePath.children[0].closed = true; potracePath.children[0].applyMatrix = true; var result = potracePath.children[0]; - if (this.testPaperTolerance > 0) result.simplify(this.testPaperTolerance); // Do special brush mode action var brushMode = this.getSetting('brushMode'); diff --git a/src/Editor/Panels/Inspector/Inspector.jsx b/src/Editor/Panels/Inspector/Inspector.jsx index ab309946e..22ecc5436 100644 --- a/src/Editor/Panels/Inspector/Inspector.jsx +++ b/src/Editor/Panels/Inspector/Inspector.jsx @@ -1045,40 +1045,6 @@ class Inspector extends Component { } render() { - if (this.props.project.selection.numObjects === 0 && this.props.project.activeTool.name === 'brush') { - return ( -
-
- -
-
- {this.props.project.tools.brush.smoothness = val; window.editor.projectDidChange(); }} - divider={false} - inputProps={{min: 0, max: 1, step: 0.01}} - id="inspector-brush-tool-smoothness"/> - {this.props.project.tools.brush.testPaperTolerance = val; window.editor.projectDidChange(); }} - divider={false} - inputProps={{min: 0, max: 10, step: 0.1}} - id="inspector-brush-tool-paper-js-tolerance"/> - {this.props.project.tools.brush.testSmoothnessExponent = val; window.editor.projectDidChange(); }} - divider={false} - inputProps={{min: 1, max: 8, step: 0.1}} - id="inspector-brush-tool-smoothness-exponent"/> -
-
- ); - } let selectionType = this.props.getSelectionType(); return(
diff --git a/src/Editor/Panels/Toolbox/ToolSettings/ToolSettings.jsx b/src/Editor/Panels/Toolbox/ToolSettings/ToolSettings.jsx index 96051eb0a..3f36c60a8 100644 --- a/src/Editor/Panels/Toolbox/ToolSettings/ToolSettings.jsx +++ b/src/Editor/Panels/Toolbox/ToolSettings/ToolSettings.jsx @@ -71,6 +71,7 @@ class ToolSettings extends Component {
{this.renderBrushSize()} {this.renderBrushSmoothing()} + {this.renderBrushResolution()} {this.renderEnablePressure()} {this.renderEnableRelativeBrushSize()} {this.renderBrushMode()} @@ -234,6 +235,19 @@ class ToolSettings extends Component { ) } + renderBrushResolution = () => { + return ( + this.setToolSetting('brushResolution', val)} + inputRestrictions={this.props.getToolSettingRestrictions('brushResolution')}/> + ) + } + renderFontSize = () => { return ( + + + + + + + + + From a288b2c41271677aa4d6d94f672f9bcb5ea87040 Mon Sep 17 00:00:00 2001 From: funny bot Date: Mon, 13 Jul 2026 20:14:02 -0700 Subject: [PATCH 7/8] Remove unused smoothness property --- engine/src/tools/Brush.js | 1 - 1 file changed, 1 deletion(-) diff --git a/engine/src/tools/Brush.js b/engine/src/tools/Brush.js index 4c598c210..c48cac8e3 100644 --- a/engine/src/tools/Brush.js +++ b/engine/src/tools/Brush.js @@ -42,7 +42,6 @@ Wick.Tools.Brush = class extends Wick.Tool { this.TARGET_BRUSH_SIZE = 50; this.MAX_RESOLUTION_FACTOR = 2; - this.smoothness = 1; this.resolutionFactor = 1; this.canvasScaleFactor = 1; // Resolution: Greater or equal to 1 this.imageScaleFactor = 1; // Resolution: Lesser or equal to 1 From 0c599e4840e0c9f1cfdfeef3455a1050b576b5a2 Mon Sep 17 00:00:00 2001 From: funny bot Date: Tue, 14 Jul 2026 14:02:19 -0700 Subject: [PATCH 8/8] Modify easing of brush resolution setting --- engine/src/tools/Brush.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/engine/src/tools/Brush.js b/engine/src/tools/Brush.js index c48cac8e3..3fe53c9ac 100644 --- a/engine/src/tools/Brush.js +++ b/engine/src/tools/Brush.js @@ -189,7 +189,8 @@ Wick.Tools.Brush = class extends Wick.Tool { clearTimeout(this._croquisStartTimeout); this._isInProgress = true; - var smoothnessFactor = Math.pow(1 - (1-this.getSetting('brushResolution'))*0.486095733599, 4.5); //1-Math.pow(0.05, 1/4.5), 0.486095733599 + var t = this.getSetting('brushResolution'); + var smoothnessFactor = 0.05 + (Math.pow(t, 5) + 0.1*t*(1-t)) * 0.95; this.resolutionFactor = this.TARGET_BRUSH_SIZE/this._getRealBrushSize() * smoothnessFactor; this.resolutionFactor = Math.min(Math.max(this.resolutionFactor, smoothnessFactor), this.MAX_RESOLUTION_FACTOR); this.canvasScaleFactor = (this.resolutionFactor > 1) ? this.resolutionFactor : 1;